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