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 28 /* debug DMA */ 29 //#define DEBUG_DMA 30 31 /* 32 * This is the DMA controller part of chip STP2000 (Master I/O), also 33 * produced as NCR89C100. See 34 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt 35 * and 36 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt 37 */ 38 39 #ifdef DEBUG_DMA 40 #define DPRINTF(fmt, ...) \ 41 do { printf("DMA: " fmt , ## __VA_ARGS__); } while (0) 42 #else 43 #define DPRINTF(fmt, ...) 44 #endif 45 46 #define DMA_REGS 4 47 #define DMA_SIZE (4 * sizeof(uint32_t)) 48 /* We need the mask, because one instance of the device is not page 49 aligned (ledma, start address 0x0010) */ 50 #define DMA_MASK (DMA_SIZE - 1) 51 52 #define DMA_VER 0xa0000000 53 #define DMA_INTR 1 54 #define DMA_INTREN 0x10 55 #define DMA_WRITE_MEM 0x100 56 #define DMA_LOADED 0x04000000 57 #define DMA_DRAIN_FIFO 0x40 58 #define DMA_RESET 0x80 59 60 typedef struct DMAState DMAState; 61 62 struct DMAState { 63 uint32_t dmaregs[DMA_REGS]; 64 qemu_irq irq; 65 void *iommu; 66 qemu_irq dev_reset; 67 }; 68 69 /* Note: on sparc, the lance 16 bit bus is swapped */ 70 void ledma_memory_read(void *opaque, target_phys_addr_t addr, 71 uint8_t *buf, int len, int do_bswap) 72 { 73 DMAState *s = opaque; 74 int i; 75 76 DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n", 77 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); 78 addr |= s->dmaregs[3]; 79 if (do_bswap) { 80 sparc_iommu_memory_read(s->iommu, addr, buf, len); 81 } else { 82 addr &= ~1; 83 len &= ~1; 84 sparc_iommu_memory_read(s->iommu, addr, buf, len); 85 for(i = 0; i < len; i += 2) { 86 bswap16s((uint16_t *)(buf + i)); 87 } 88 } 89 } 90 91 void ledma_memory_write(void *opaque, target_phys_addr_t addr, 92 uint8_t *buf, int len, int do_bswap) 93 { 94 DMAState *s = opaque; 95 int l, i; 96 uint16_t tmp_buf[32]; 97 98 DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n", 99 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); 100 addr |= s->dmaregs[3]; 101 if (do_bswap) { 102 sparc_iommu_memory_write(s->iommu, addr, buf, len); 103 } else { 104 addr &= ~1; 105 len &= ~1; 106 while (len > 0) { 107 l = len; 108 if (l > sizeof(tmp_buf)) 109 l = sizeof(tmp_buf); 110 for(i = 0; i < l; i += 2) { 111 tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i)); 112 } 113 sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l); 114 len -= l; 115 buf += l; 116 addr += l; 117 } 118 } 119 } 120 121 static void dma_set_irq(void *opaque, int irq, int level) 122 { 123 DMAState *s = opaque; 124 if (level) { 125 DPRINTF("Raise IRQ\n"); 126 s->dmaregs[0] |= DMA_INTR; 127 qemu_irq_raise(s->irq); 128 } else { 129 s->dmaregs[0] &= ~DMA_INTR; 130 DPRINTF("Lower IRQ\n"); 131 qemu_irq_lower(s->irq); 132 } 133 } 134 135 void espdma_memory_read(void *opaque, uint8_t *buf, int len) 136 { 137 DMAState *s = opaque; 138 139 DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n", 140 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); 141 sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len); 142 s->dmaregs[0] |= DMA_INTR; 143 s->dmaregs[1] += len; 144 } 145 146 void espdma_memory_write(void *opaque, uint8_t *buf, int len) 147 { 148 DMAState *s = opaque; 149 150 DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n", 151 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); 152 sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len); 153 s->dmaregs[0] |= DMA_INTR; 154 s->dmaregs[1] += len; 155 } 156 157 static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr) 158 { 159 DMAState *s = opaque; 160 uint32_t saddr; 161 162 saddr = (addr & DMA_MASK) >> 2; 163 DPRINTF("read dmareg " TARGET_FMT_plx ": 0x%8.8x\n", addr, 164 s->dmaregs[saddr]); 165 166 return s->dmaregs[saddr]; 167 } 168 169 static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) 170 { 171 DMAState *s = opaque; 172 uint32_t saddr; 173 174 saddr = (addr & DMA_MASK) >> 2; 175 DPRINTF("write dmareg " TARGET_FMT_plx ": 0x%8.8x -> 0x%8.8x\n", addr, 176 s->dmaregs[saddr], val); 177 switch (saddr) { 178 case 0: 179 if (!(val & DMA_INTREN)) { 180 DPRINTF("Lower IRQ\n"); 181 qemu_irq_lower(s->irq); 182 } 183 if (val & DMA_RESET) { 184 qemu_irq_raise(s->dev_reset); 185 qemu_irq_lower(s->dev_reset); 186 } else if (val & DMA_DRAIN_FIFO) { 187 val &= ~DMA_DRAIN_FIFO; 188 } else if (val == 0) 189 val = DMA_DRAIN_FIFO; 190 val &= 0x0fffffff; 191 val |= DMA_VER; 192 break; 193 case 1: 194 s->dmaregs[0] |= DMA_LOADED; 195 break; 196 default: 197 break; 198 } 199 s->dmaregs[saddr] = val; 200 } 201 202 static CPUReadMemoryFunc *dma_mem_read[3] = { 203 NULL, 204 NULL, 205 dma_mem_readl, 206 }; 207 208 static CPUWriteMemoryFunc *dma_mem_write[3] = { 209 NULL, 210 NULL, 211 dma_mem_writel, 212 }; 213 214 static void dma_reset(void *opaque) 215 { 216 DMAState *s = opaque; 217 218 memset(s->dmaregs, 0, DMA_SIZE); 219 s->dmaregs[0] = DMA_VER; 220 } 221 222 static void dma_save(QEMUFile *f, void *opaque) 223 { 224 DMAState *s = opaque; 225 unsigned int i; 226 227 for (i = 0; i < DMA_REGS; i++) 228 qemu_put_be32s(f, &s->dmaregs[i]); 229 } 230 231 static int dma_load(QEMUFile *f, void *opaque, int version_id) 232 { 233 DMAState *s = opaque; 234 unsigned int i; 235 236 if (version_id != 2) 237 return -EINVAL; 238 for (i = 0; i < DMA_REGS; i++) 239 qemu_get_be32s(f, &s->dmaregs[i]); 240 241 return 0; 242 } 243 244 void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, 245 void *iommu, qemu_irq **dev_irq, qemu_irq **reset) 246 { 247 DMAState *s; 248 int dma_io_memory; 249 250 s = qemu_mallocz(sizeof(DMAState)); 251 252 s->irq = parent_irq; 253 s->iommu = iommu; 254 255 dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s); 256 cpu_register_physical_memory(daddr, DMA_SIZE, dma_io_memory); 257 258 register_savevm("sparc32_dma", daddr, 2, dma_save, dma_load, s); 259 qemu_register_reset(dma_reset, 0, s); 260 *dev_irq = qemu_allocate_irqs(dma_set_irq, s, 1); 261 262 *reset = &s->dev_reset; 263 264 return s; 265 } 266