1 | /* |
2 | * QEMU Sparc32 DMA controller emulation |
3 | * |
4 | * Copyright (c) 2006 Fabrice Bellard |
5 | * |
6 | * Modifications: |
7 | * 2010-Feb-14 Artyom Tarasenko : reworked irq generation |
8 | * |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | * of this software and associated documentation files (the "Software"), to deal |
11 | * in the Software without restriction, including without limitation the rights |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | * copies of the Software, and to permit persons to whom the Software is |
14 | * furnished to do so, subject to the following conditions: |
15 | * |
16 | * The above copyright notice and this permission notice shall be included in |
17 | * all copies or substantial portions of the Software. |
18 | * |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | * THE SOFTWARE. |
26 | */ |
27 | |
28 | #include "qemu/osdep.h" |
29 | #include "hw/irq.h" |
30 | #include "hw/qdev-properties.h" |
31 | #include "hw/sparc/sparc32_dma.h" |
32 | #include "hw/sparc/sun4m_iommu.h" |
33 | #include "hw/sysbus.h" |
34 | #include "migration/vmstate.h" |
35 | #include "sysemu/dma.h" |
36 | #include "qapi/error.h" |
37 | #include "qemu/module.h" |
38 | #include "trace.h" |
39 | |
40 | /* |
41 | * This is the DMA controller part of chip STP2000 (Master I/O), also |
42 | * produced as NCR89C100. See |
43 | * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt |
44 | * and |
45 | * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt |
46 | */ |
47 | |
48 | #define DMA_SIZE (4 * sizeof(uint32_t)) |
49 | /* We need the mask, because one instance of the device is not page |
50 | aligned (ledma, start address 0x0010) */ |
51 | #define DMA_MASK (DMA_SIZE - 1) |
52 | /* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */ |
53 | #define DMA_ETH_SIZE (8 * sizeof(uint32_t)) |
54 | #define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1) |
55 | |
56 | #define DMA_VER 0xa0000000 |
57 | #define DMA_INTR 1 |
58 | #define DMA_INTREN 0x10 |
59 | #define DMA_WRITE_MEM 0x100 |
60 | #define DMA_EN 0x200 |
61 | #define DMA_LOADED 0x04000000 |
62 | #define DMA_DRAIN_FIFO 0x40 |
63 | #define DMA_RESET 0x80 |
64 | |
65 | /* XXX SCSI and ethernet should have different read-only bit masks */ |
66 | #define DMA_CSR_RO_MASK 0xfe000007 |
67 | |
68 | enum { |
69 | GPIO_RESET = 0, |
70 | GPIO_DMA, |
71 | }; |
72 | |
73 | /* Note: on sparc, the lance 16 bit bus is swapped */ |
74 | void ledma_memory_read(void *opaque, hwaddr addr, |
75 | uint8_t *buf, int len, int do_bswap) |
76 | { |
77 | DMADeviceState *s = opaque; |
78 | IOMMUState *is = (IOMMUState *)s->iommu; |
79 | int i; |
80 | |
81 | addr |= s->dmaregs[3]; |
82 | trace_ledma_memory_read(addr, len); |
83 | if (do_bswap) { |
84 | dma_memory_read(&is->iommu_as, addr, buf, len); |
85 | } else { |
86 | addr &= ~1; |
87 | len &= ~1; |
88 | dma_memory_read(&is->iommu_as, addr, buf, len); |
89 | for(i = 0; i < len; i += 2) { |
90 | bswap16s((uint16_t *)(buf + i)); |
91 | } |
92 | } |
93 | } |
94 | |
95 | void ledma_memory_write(void *opaque, hwaddr addr, |
96 | uint8_t *buf, int len, int do_bswap) |
97 | { |
98 | DMADeviceState *s = opaque; |
99 | IOMMUState *is = (IOMMUState *)s->iommu; |
100 | int l, i; |
101 | uint16_t tmp_buf[32]; |
102 | |
103 | addr |= s->dmaregs[3]; |
104 | trace_ledma_memory_write(addr, len); |
105 | if (do_bswap) { |
106 | dma_memory_write(&is->iommu_as, addr, buf, len); |
107 | } else { |
108 | addr &= ~1; |
109 | len &= ~1; |
110 | while (len > 0) { |
111 | l = len; |
112 | if (l > sizeof(tmp_buf)) |
113 | l = sizeof(tmp_buf); |
114 | for(i = 0; i < l; i += 2) { |
115 | tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i)); |
116 | } |
117 | dma_memory_write(&is->iommu_as, addr, tmp_buf, l); |
118 | len -= l; |
119 | buf += l; |
120 | addr += l; |
121 | } |
122 | } |
123 | } |
124 | |
125 | static void dma_set_irq(void *opaque, int irq, int level) |
126 | { |
127 | DMADeviceState *s = opaque; |
128 | if (level) { |
129 | s->dmaregs[0] |= DMA_INTR; |
130 | if (s->dmaregs[0] & DMA_INTREN) { |
131 | trace_sparc32_dma_set_irq_raise(); |
132 | qemu_irq_raise(s->irq); |
133 | } |
134 | } else { |
135 | if (s->dmaregs[0] & DMA_INTR) { |
136 | s->dmaregs[0] &= ~DMA_INTR; |
137 | if (s->dmaregs[0] & DMA_INTREN) { |
138 | trace_sparc32_dma_set_irq_lower(); |
139 | qemu_irq_lower(s->irq); |
140 | } |
141 | } |
142 | } |
143 | } |
144 | |
145 | void espdma_memory_read(void *opaque, uint8_t *buf, int len) |
146 | { |
147 | DMADeviceState *s = opaque; |
148 | IOMMUState *is = (IOMMUState *)s->iommu; |
149 | |
150 | trace_espdma_memory_read(s->dmaregs[1], len); |
151 | dma_memory_read(&is->iommu_as, s->dmaregs[1], buf, len); |
152 | s->dmaregs[1] += len; |
153 | } |
154 | |
155 | void espdma_memory_write(void *opaque, uint8_t *buf, int len) |
156 | { |
157 | DMADeviceState *s = opaque; |
158 | IOMMUState *is = (IOMMUState *)s->iommu; |
159 | |
160 | trace_espdma_memory_write(s->dmaregs[1], len); |
161 | dma_memory_write(&is->iommu_as, s->dmaregs[1], buf, len); |
162 | s->dmaregs[1] += len; |
163 | } |
164 | |
165 | static uint64_t dma_mem_read(void *opaque, hwaddr addr, |
166 | unsigned size) |
167 | { |
168 | DMADeviceState *s = opaque; |
169 | uint32_t saddr; |
170 | |
171 | saddr = (addr & DMA_MASK) >> 2; |
172 | trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]); |
173 | return s->dmaregs[saddr]; |
174 | } |
175 | |
176 | static void dma_mem_write(void *opaque, hwaddr addr, |
177 | uint64_t val, unsigned size) |
178 | { |
179 | DMADeviceState *s = opaque; |
180 | uint32_t saddr; |
181 | |
182 | saddr = (addr & DMA_MASK) >> 2; |
183 | trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val); |
184 | switch (saddr) { |
185 | case 0: |
186 | if (val & DMA_INTREN) { |
187 | if (s->dmaregs[0] & DMA_INTR) { |
188 | trace_sparc32_dma_set_irq_raise(); |
189 | qemu_irq_raise(s->irq); |
190 | } |
191 | } else { |
192 | if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) { |
193 | trace_sparc32_dma_set_irq_lower(); |
194 | qemu_irq_lower(s->irq); |
195 | } |
196 | } |
197 | if (val & DMA_RESET) { |
198 | qemu_irq_raise(s->gpio[GPIO_RESET]); |
199 | qemu_irq_lower(s->gpio[GPIO_RESET]); |
200 | } else if (val & DMA_DRAIN_FIFO) { |
201 | val &= ~DMA_DRAIN_FIFO; |
202 | } else if (val == 0) |
203 | val = DMA_DRAIN_FIFO; |
204 | |
205 | if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) { |
206 | trace_sparc32_dma_enable_raise(); |
207 | qemu_irq_raise(s->gpio[GPIO_DMA]); |
208 | } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) { |
209 | trace_sparc32_dma_enable_lower(); |
210 | qemu_irq_lower(s->gpio[GPIO_DMA]); |
211 | } |
212 | |
213 | val &= ~DMA_CSR_RO_MASK; |
214 | val |= DMA_VER; |
215 | s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val; |
216 | break; |
217 | case 1: |
218 | s->dmaregs[0] |= DMA_LOADED; |
219 | /* fall through */ |
220 | default: |
221 | s->dmaregs[saddr] = val; |
222 | break; |
223 | } |
224 | } |
225 | |
226 | static const MemoryRegionOps dma_mem_ops = { |
227 | .read = dma_mem_read, |
228 | .write = dma_mem_write, |
229 | .endianness = DEVICE_NATIVE_ENDIAN, |
230 | .valid = { |
231 | .min_access_size = 4, |
232 | .max_access_size = 4, |
233 | }, |
234 | }; |
235 | |
236 | static void sparc32_dma_device_reset(DeviceState *d) |
237 | { |
238 | DMADeviceState *s = SPARC32_DMA_DEVICE(d); |
239 | |
240 | memset(s->dmaregs, 0, DMA_SIZE); |
241 | s->dmaregs[0] = DMA_VER; |
242 | } |
243 | |
244 | static const VMStateDescription vmstate_sparc32_dma_device = { |
245 | .name ="sparc32_dma" , |
246 | .version_id = 2, |
247 | .minimum_version_id = 2, |
248 | .fields = (VMStateField[]) { |
249 | VMSTATE_UINT32_ARRAY(dmaregs, DMADeviceState, DMA_REGS), |
250 | VMSTATE_END_OF_LIST() |
251 | } |
252 | }; |
253 | |
254 | static void sparc32_dma_device_init(Object *obj) |
255 | { |
256 | DeviceState *dev = DEVICE(obj); |
257 | DMADeviceState *s = SPARC32_DMA_DEVICE(obj); |
258 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
259 | |
260 | sysbus_init_irq(sbd, &s->irq); |
261 | |
262 | sysbus_init_mmio(sbd, &s->iomem); |
263 | |
264 | object_property_add_link(OBJECT(dev), "iommu" , TYPE_SUN4M_IOMMU, |
265 | (Object **) &s->iommu, |
266 | qdev_prop_allow_set_link_before_realize, |
267 | 0, NULL); |
268 | |
269 | qdev_init_gpio_in(dev, dma_set_irq, 1); |
270 | qdev_init_gpio_out(dev, s->gpio, 2); |
271 | } |
272 | |
273 | static void sparc32_dma_device_class_init(ObjectClass *klass, void *data) |
274 | { |
275 | DeviceClass *dc = DEVICE_CLASS(klass); |
276 | |
277 | dc->reset = sparc32_dma_device_reset; |
278 | dc->vmsd = &vmstate_sparc32_dma_device; |
279 | } |
280 | |
281 | static const TypeInfo sparc32_dma_device_info = { |
282 | .name = TYPE_SPARC32_DMA_DEVICE, |
283 | .parent = TYPE_SYS_BUS_DEVICE, |
284 | .abstract = true, |
285 | .instance_size = sizeof(DMADeviceState), |
286 | .instance_init = sparc32_dma_device_init, |
287 | .class_init = sparc32_dma_device_class_init, |
288 | }; |
289 | |
290 | static void sparc32_espdma_device_init(Object *obj) |
291 | { |
292 | DMADeviceState *s = SPARC32_DMA_DEVICE(obj); |
293 | |
294 | memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, |
295 | "espdma-mmio" , DMA_SIZE); |
296 | } |
297 | |
298 | static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp) |
299 | { |
300 | DeviceState *d; |
301 | SysBusESPState *sysbus; |
302 | ESPState *esp; |
303 | |
304 | d = qdev_create(NULL, TYPE_ESP); |
305 | object_property_add_child(OBJECT(dev), "esp" , OBJECT(d), errp); |
306 | sysbus = ESP_STATE(d); |
307 | esp = &sysbus->esp; |
308 | esp->dma_memory_read = espdma_memory_read; |
309 | esp->dma_memory_write = espdma_memory_write; |
310 | esp->dma_opaque = SPARC32_DMA_DEVICE(dev); |
311 | sysbus->it_shift = 2; |
312 | esp->dma_enabled = 1; |
313 | qdev_init_nofail(d); |
314 | } |
315 | |
316 | static void sparc32_espdma_device_class_init(ObjectClass *klass, void *data) |
317 | { |
318 | DeviceClass *dc = DEVICE_CLASS(klass); |
319 | |
320 | dc->realize = sparc32_espdma_device_realize; |
321 | } |
322 | |
323 | static const TypeInfo sparc32_espdma_device_info = { |
324 | .name = TYPE_SPARC32_ESPDMA_DEVICE, |
325 | .parent = TYPE_SPARC32_DMA_DEVICE, |
326 | .instance_size = sizeof(ESPDMADeviceState), |
327 | .instance_init = sparc32_espdma_device_init, |
328 | .class_init = sparc32_espdma_device_class_init, |
329 | }; |
330 | |
331 | static void sparc32_ledma_device_init(Object *obj) |
332 | { |
333 | DMADeviceState *s = SPARC32_DMA_DEVICE(obj); |
334 | |
335 | memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, |
336 | "ledma-mmio" , DMA_SIZE); |
337 | } |
338 | |
339 | static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) |
340 | { |
341 | DeviceState *d; |
342 | NICInfo *nd = &nd_table[0]; |
343 | |
344 | qemu_check_nic_model(nd, TYPE_LANCE); |
345 | |
346 | d = qdev_create(NULL, TYPE_LANCE); |
347 | object_property_add_child(OBJECT(dev), "lance" , OBJECT(d), errp); |
348 | qdev_set_nic_properties(d, nd); |
349 | qdev_prop_set_ptr(d, "dma" , dev); |
350 | qdev_init_nofail(d); |
351 | } |
352 | |
353 | static void sparc32_ledma_device_class_init(ObjectClass *klass, void *data) |
354 | { |
355 | DeviceClass *dc = DEVICE_CLASS(klass); |
356 | |
357 | dc->realize = sparc32_ledma_device_realize; |
358 | } |
359 | |
360 | static const TypeInfo sparc32_ledma_device_info = { |
361 | .name = TYPE_SPARC32_LEDMA_DEVICE, |
362 | .parent = TYPE_SPARC32_DMA_DEVICE, |
363 | .instance_size = sizeof(LEDMADeviceState), |
364 | .instance_init = sparc32_ledma_device_init, |
365 | .class_init = sparc32_ledma_device_class_init, |
366 | }; |
367 | |
368 | static void sparc32_dma_realize(DeviceState *dev, Error **errp) |
369 | { |
370 | SPARC32DMAState *s = SPARC32_DMA(dev); |
371 | DeviceState *espdma, *esp, *ledma, *lance; |
372 | SysBusDevice *sbd; |
373 | Object *iommu; |
374 | |
375 | iommu = object_resolve_path_type("" , TYPE_SUN4M_IOMMU, NULL); |
376 | if (!iommu) { |
377 | error_setg(errp, "unable to locate sun4m IOMMU device" ); |
378 | return; |
379 | } |
380 | |
381 | espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE); |
382 | object_property_set_link(OBJECT(espdma), iommu, "iommu" , errp); |
383 | object_property_add_child(OBJECT(s), "espdma" , OBJECT(espdma), errp); |
384 | qdev_init_nofail(espdma); |
385 | |
386 | esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp" )); |
387 | sbd = SYS_BUS_DEVICE(esp); |
388 | sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0)); |
389 | qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0)); |
390 | qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1)); |
391 | |
392 | sbd = SYS_BUS_DEVICE(espdma); |
393 | memory_region_add_subregion(&s->dmamem, 0x0, |
394 | sysbus_mmio_get_region(sbd, 0)); |
395 | |
396 | ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE); |
397 | object_property_set_link(OBJECT(ledma), iommu, "iommu" , errp); |
398 | object_property_add_child(OBJECT(s), "ledma" , OBJECT(ledma), errp); |
399 | qdev_init_nofail(ledma); |
400 | |
401 | lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance" )); |
402 | sbd = SYS_BUS_DEVICE(lance); |
403 | sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0)); |
404 | qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0)); |
405 | |
406 | sbd = SYS_BUS_DEVICE(ledma); |
407 | memory_region_add_subregion(&s->dmamem, 0x10, |
408 | sysbus_mmio_get_region(sbd, 0)); |
409 | |
410 | /* Add ledma alias to handle SunOS 5.7 - Solaris 9 invalid access bug */ |
411 | memory_region_init_alias(&s->ledma_alias, OBJECT(dev), "ledma-alias" , |
412 | sysbus_mmio_get_region(sbd, 0), 0x4, 0x4); |
413 | memory_region_add_subregion(&s->dmamem, 0x20, &s->ledma_alias); |
414 | } |
415 | |
416 | static void sparc32_dma_init(Object *obj) |
417 | { |
418 | SPARC32DMAState *s = SPARC32_DMA(obj); |
419 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
420 | |
421 | memory_region_init(&s->dmamem, OBJECT(s), "dma" , DMA_SIZE + DMA_ETH_SIZE); |
422 | sysbus_init_mmio(sbd, &s->dmamem); |
423 | } |
424 | |
425 | static void sparc32_dma_class_init(ObjectClass *klass, void *data) |
426 | { |
427 | DeviceClass *dc = DEVICE_CLASS(klass); |
428 | |
429 | dc->realize = sparc32_dma_realize; |
430 | } |
431 | |
432 | static const TypeInfo sparc32_dma_info = { |
433 | .name = TYPE_SPARC32_DMA, |
434 | .parent = TYPE_SYS_BUS_DEVICE, |
435 | .instance_size = sizeof(SPARC32DMAState), |
436 | .instance_init = sparc32_dma_init, |
437 | .class_init = sparc32_dma_class_init, |
438 | }; |
439 | |
440 | |
441 | static void sparc32_dma_register_types(void) |
442 | { |
443 | type_register_static(&sparc32_dma_device_info); |
444 | type_register_static(&sparc32_espdma_device_info); |
445 | type_register_static(&sparc32_ledma_device_info); |
446 | type_register_static(&sparc32_dma_info); |
447 | } |
448 | |
449 | type_init(sparc32_dma_register_types) |
450 | |