sparc32_dma.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * QEMU Sparc32 DMA controller emulation
  3. *
  4. * Copyright (c) 2006 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "sparc32_dma.h"
  26. #include "sun4m.h"
  27. /* debug DMA */
  28. //#define DEBUG_DMA
  29. /*
  30. * This is the DMA controller part of chip STP2000 (Master I/O), also
  31. * produced as NCR89C100. See
  32. * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  33. * and
  34. * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
  35. */
  36. #ifdef DEBUG_DMA
  37. #define DPRINTF(fmt, args...) \
  38. do { printf("DMA: " fmt , ##args); } while (0)
  39. #else
  40. #define DPRINTF(fmt, args...)
  41. #endif
  42. #define DMA_REGS 4
  43. #define DMA_SIZE (4 * sizeof(uint32_t))
  44. /* We need the mask, because one instance of the device is not page
  45. aligned (ledma, start address 0x0010) */
  46. #define DMA_MASK (DMA_SIZE - 1)
  47. #define DMA_VER 0xa0000000
  48. #define DMA_INTR 1
  49. #define DMA_INTREN 0x10
  50. #define DMA_WRITE_MEM 0x100
  51. #define DMA_LOADED 0x04000000
  52. #define DMA_DRAIN_FIFO 0x40
  53. #define DMA_RESET 0x80
  54. typedef struct DMAState DMAState;
  55. struct DMAState {
  56. uint32_t dmaregs[DMA_REGS];
  57. qemu_irq irq;
  58. void *iommu;
  59. qemu_irq dev_reset;
  60. };
  61. /* Note: on sparc, the lance 16 bit bus is swapped */
  62. void ledma_memory_read(void *opaque, target_phys_addr_t addr,
  63. uint8_t *buf, int len, int do_bswap)
  64. {
  65. DMAState *s = opaque;
  66. int i;
  67. DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
  68. s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
  69. addr |= s->dmaregs[3];
  70. if (do_bswap) {
  71. sparc_iommu_memory_read(s->iommu, addr, buf, len);
  72. } else {
  73. addr &= ~1;
  74. len &= ~1;
  75. sparc_iommu_memory_read(s->iommu, addr, buf, len);
  76. for(i = 0; i < len; i += 2) {
  77. bswap16s((uint16_t *)(buf + i));
  78. }
  79. }
  80. }
  81. void ledma_memory_write(void *opaque, target_phys_addr_t addr,
  82. uint8_t *buf, int len, int do_bswap)
  83. {
  84. DMAState *s = opaque;
  85. int l, i;
  86. uint16_t tmp_buf[32];
  87. DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
  88. s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
  89. addr |= s->dmaregs[3];
  90. if (do_bswap) {
  91. sparc_iommu_memory_write(s->iommu, addr, buf, len);
  92. } else {
  93. addr &= ~1;
  94. len &= ~1;
  95. while (len > 0) {
  96. l = len;
  97. if (l > sizeof(tmp_buf))
  98. l = sizeof(tmp_buf);
  99. for(i = 0; i < l; i += 2) {
  100. tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
  101. }
  102. sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
  103. len -= l;
  104. buf += l;
  105. addr += l;
  106. }
  107. }
  108. }
  109. static void dma_set_irq(void *opaque, int irq, int level)
  110. {
  111. DMAState *s = opaque;
  112. if (level) {
  113. DPRINTF("Raise IRQ\n");
  114. s->dmaregs[0] |= DMA_INTR;
  115. qemu_irq_raise(s->irq);
  116. } else {
  117. s->dmaregs[0] &= ~DMA_INTR;
  118. DPRINTF("Lower IRQ\n");
  119. qemu_irq_lower(s->irq);
  120. }
  121. }
  122. void espdma_memory_read(void *opaque, uint8_t *buf, int len)
  123. {
  124. DMAState *s = opaque;
  125. DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
  126. s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
  127. sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
  128. s->dmaregs[0] |= DMA_INTR;
  129. s->dmaregs[1] += len;
  130. }
  131. void espdma_memory_write(void *opaque, uint8_t *buf, int len)
  132. {
  133. DMAState *s = opaque;
  134. DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
  135. s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
  136. sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
  137. s->dmaregs[0] |= DMA_INTR;
  138. s->dmaregs[1] += len;
  139. }
  140. static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
  141. {
  142. DMAState *s = opaque;
  143. uint32_t saddr;
  144. saddr = (addr & DMA_MASK) >> 2;
  145. DPRINTF("read dmareg " TARGET_FMT_plx ": 0x%8.8x\n", addr,
  146. s->dmaregs[saddr]);
  147. return s->dmaregs[saddr];
  148. }
  149. static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  150. {
  151. DMAState *s = opaque;
  152. uint32_t saddr;
  153. saddr = (addr & DMA_MASK) >> 2;
  154. DPRINTF("write dmareg " TARGET_FMT_plx ": 0x%8.8x -> 0x%8.8x\n", addr,
  155. s->dmaregs[saddr], val);
  156. switch (saddr) {
  157. case 0:
  158. if (!(val & DMA_INTREN)) {
  159. DPRINTF("Lower IRQ\n");
  160. qemu_irq_lower(s->irq);
  161. }
  162. if (val & DMA_RESET) {
  163. qemu_irq_raise(s->dev_reset);
  164. qemu_irq_lower(s->dev_reset);
  165. } else if (val & DMA_DRAIN_FIFO) {
  166. val &= ~DMA_DRAIN_FIFO;
  167. } else if (val == 0)
  168. val = DMA_DRAIN_FIFO;
  169. val &= 0x0fffffff;
  170. val |= DMA_VER;
  171. break;
  172. case 1:
  173. s->dmaregs[0] |= DMA_LOADED;
  174. break;
  175. default:
  176. break;
  177. }
  178. s->dmaregs[saddr] = val;
  179. }
  180. static CPUReadMemoryFunc *dma_mem_read[3] = {
  181. NULL,
  182. NULL,
  183. dma_mem_readl,
  184. };
  185. static CPUWriteMemoryFunc *dma_mem_write[3] = {
  186. NULL,
  187. NULL,
  188. dma_mem_writel,
  189. };
  190. static void dma_reset(void *opaque)
  191. {
  192. DMAState *s = opaque;
  193. memset(s->dmaregs, 0, DMA_SIZE);
  194. s->dmaregs[0] = DMA_VER;
  195. }
  196. static void dma_save(QEMUFile *f, void *opaque)
  197. {
  198. DMAState *s = opaque;
  199. unsigned int i;
  200. for (i = 0; i < DMA_REGS; i++)
  201. qemu_put_be32s(f, &s->dmaregs[i]);
  202. }
  203. static int dma_load(QEMUFile *f, void *opaque, int version_id)
  204. {
  205. DMAState *s = opaque;
  206. unsigned int i;
  207. if (version_id != 2)
  208. return -EINVAL;
  209. for (i = 0; i < DMA_REGS; i++)
  210. qemu_get_be32s(f, &s->dmaregs[i]);
  211. return 0;
  212. }
  213. void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq,
  214. void *iommu, qemu_irq **dev_irq, qemu_irq **reset)
  215. {
  216. DMAState *s;
  217. int dma_io_memory;
  218. s = qemu_mallocz(sizeof(DMAState));
  219. s->irq = parent_irq;
  220. s->iommu = iommu;
  221. dma_io_memory = cpu_register_io_memory(0, dma_mem_read, dma_mem_write, s);
  222. cpu_register_physical_memory(daddr, DMA_SIZE, dma_io_memory);
  223. register_savevm("sparc32_dma", daddr, 2, dma_save, dma_load, s);
  224. qemu_register_reset(dma_reset, s);
  225. *dev_irq = qemu_allocate_irqs(dma_set_irq, s, 1);
  226. *reset = &s->dev_reset;
  227. return s;
  228. }