]> git.proxmox.com Git - qemu.git/blob - hw/misc/macio/mac_dbdma.c
Merge git://github.com/hw-claudio/qemu-aarch64-queue into tcg-next
[qemu.git] / hw / misc / macio / mac_dbdma.c
1 /*
2 * PowerMac descriptor-based DMA emulation
3 *
4 * Copyright (c) 2005-2007 Fabrice Bellard
5 * Copyright (c) 2007 Jocelyn Mayer
6 * Copyright (c) 2009 Laurent Vivier
7 *
8 * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h
9 *
10 * Definitions for using the Apple Descriptor-Based DMA controller
11 * in Power Macintosh computers.
12 *
13 * Copyright (C) 1996 Paul Mackerras.
14 *
15 * some parts from mol 0.9.71
16 *
17 * Descriptor based DMA emulation
18 *
19 * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se)
20 *
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 * THE SOFTWARE.
38 */
39 #include "hw/hw.h"
40 #include "hw/isa/isa.h"
41 #include "hw/ppc/mac_dbdma.h"
42 #include "qemu/main-loop.h"
43
44 /* debug DBDMA */
45 //#define DEBUG_DBDMA
46
47 #ifdef DEBUG_DBDMA
48 #define DBDMA_DPRINTF(fmt, ...) \
49 do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
50 #else
51 #define DBDMA_DPRINTF(fmt, ...)
52 #endif
53
54 /*
55 */
56
57 static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
58 {
59 return container_of(ch, DBDMAState, channels[ch->channel]);
60 }
61
62 #ifdef DEBUG_DBDMA
63 static void dump_dbdma_cmd(dbdma_cmd *cmd)
64 {
65 printf("dbdma_cmd %p\n", cmd);
66 printf(" req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
67 printf(" command 0x%04x\n", le16_to_cpu(cmd->command));
68 printf(" phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
69 printf(" cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
70 printf(" res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
71 printf(" xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status));
72 }
73 #else
74 static void dump_dbdma_cmd(dbdma_cmd *cmd)
75 {
76 }
77 #endif
78 static void dbdma_cmdptr_load(DBDMA_channel *ch)
79 {
80 DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
81 ch->regs[DBDMA_CMDPTR_LO]);
82 cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
83 &ch->current, sizeof(dbdma_cmd));
84 }
85
86 static void dbdma_cmdptr_save(DBDMA_channel *ch)
87 {
88 DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
89 ch->regs[DBDMA_CMDPTR_LO]);
90 DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
91 le16_to_cpu(ch->current.xfer_status),
92 le16_to_cpu(ch->current.res_count));
93 cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
94 &ch->current, sizeof(dbdma_cmd));
95 }
96
97 static void kill_channel(DBDMA_channel *ch)
98 {
99 DBDMA_DPRINTF("kill_channel\n");
100
101 ch->regs[DBDMA_STATUS] |= DEAD;
102 ch->regs[DBDMA_STATUS] &= ~ACTIVE;
103
104 qemu_irq_raise(ch->irq);
105 }
106
107 static void conditional_interrupt(DBDMA_channel *ch)
108 {
109 dbdma_cmd *current = &ch->current;
110 uint16_t intr;
111 uint16_t sel_mask, sel_value;
112 uint32_t status;
113 int cond;
114
115 DBDMA_DPRINTF("%s\n", __func__);
116
117 intr = le16_to_cpu(current->command) & INTR_MASK;
118
119 switch(intr) {
120 case INTR_NEVER: /* don't interrupt */
121 return;
122 case INTR_ALWAYS: /* always interrupt */
123 qemu_irq_raise(ch->irq);
124 DBDMA_DPRINTF("%s: raise\n", __func__);
125 return;
126 }
127
128 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
129
130 sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
131 sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
132
133 cond = (status & sel_mask) == (sel_value & sel_mask);
134
135 switch(intr) {
136 case INTR_IFSET: /* intr if condition bit is 1 */
137 if (cond) {
138 qemu_irq_raise(ch->irq);
139 DBDMA_DPRINTF("%s: raise\n", __func__);
140 }
141 return;
142 case INTR_IFCLR: /* intr if condition bit is 0 */
143 if (!cond) {
144 qemu_irq_raise(ch->irq);
145 DBDMA_DPRINTF("%s: raise\n", __func__);
146 }
147 return;
148 }
149 }
150
151 static int conditional_wait(DBDMA_channel *ch)
152 {
153 dbdma_cmd *current = &ch->current;
154 uint16_t wait;
155 uint16_t sel_mask, sel_value;
156 uint32_t status;
157 int cond;
158
159 DBDMA_DPRINTF("conditional_wait\n");
160
161 wait = le16_to_cpu(current->command) & WAIT_MASK;
162
163 switch(wait) {
164 case WAIT_NEVER: /* don't wait */
165 return 0;
166 case WAIT_ALWAYS: /* always wait */
167 return 1;
168 }
169
170 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
171
172 sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
173 sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
174
175 cond = (status & sel_mask) == (sel_value & sel_mask);
176
177 switch(wait) {
178 case WAIT_IFSET: /* wait if condition bit is 1 */
179 if (cond)
180 return 1;
181 return 0;
182 case WAIT_IFCLR: /* wait if condition bit is 0 */
183 if (!cond)
184 return 1;
185 return 0;
186 }
187 return 0;
188 }
189
190 static void next(DBDMA_channel *ch)
191 {
192 uint32_t cp;
193
194 ch->regs[DBDMA_STATUS] &= ~BT;
195
196 cp = ch->regs[DBDMA_CMDPTR_LO];
197 ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
198 dbdma_cmdptr_load(ch);
199 }
200
201 static void branch(DBDMA_channel *ch)
202 {
203 dbdma_cmd *current = &ch->current;
204
205 ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
206 ch->regs[DBDMA_STATUS] |= BT;
207 dbdma_cmdptr_load(ch);
208 }
209
210 static void conditional_branch(DBDMA_channel *ch)
211 {
212 dbdma_cmd *current = &ch->current;
213 uint16_t br;
214 uint16_t sel_mask, sel_value;
215 uint32_t status;
216 int cond;
217
218 DBDMA_DPRINTF("conditional_branch\n");
219
220 /* check if we must branch */
221
222 br = le16_to_cpu(current->command) & BR_MASK;
223
224 switch(br) {
225 case BR_NEVER: /* don't branch */
226 next(ch);
227 return;
228 case BR_ALWAYS: /* always branch */
229 branch(ch);
230 return;
231 }
232
233 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
234
235 sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
236 sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
237
238 cond = (status & sel_mask) == (sel_value & sel_mask);
239
240 switch(br) {
241 case BR_IFSET: /* branch if condition bit is 1 */
242 if (cond)
243 branch(ch);
244 else
245 next(ch);
246 return;
247 case BR_IFCLR: /* branch if condition bit is 0 */
248 if (!cond)
249 branch(ch);
250 else
251 next(ch);
252 return;
253 }
254 }
255
256 static void channel_run(DBDMA_channel *ch);
257
258 static void dbdma_end(DBDMA_io *io)
259 {
260 DBDMA_channel *ch = io->channel;
261 dbdma_cmd *current = &ch->current;
262
263 DBDMA_DPRINTF("%s\n", __func__);
264
265 if (conditional_wait(ch))
266 goto wait;
267
268 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
269 current->res_count = cpu_to_le16(io->len);
270 dbdma_cmdptr_save(ch);
271 if (io->is_last)
272 ch->regs[DBDMA_STATUS] &= ~FLUSH;
273
274 conditional_interrupt(ch);
275 conditional_branch(ch);
276
277 wait:
278 /* Indicate that we're ready for a new DMA round */
279 ch->io.processing = false;
280
281 if ((ch->regs[DBDMA_STATUS] & RUN) &&
282 (ch->regs[DBDMA_STATUS] & ACTIVE))
283 channel_run(ch);
284 }
285
286 static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
287 uint16_t req_count, int is_last)
288 {
289 DBDMA_DPRINTF("start_output\n");
290
291 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
292 * are not implemented in the mac-io chip
293 */
294
295 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
296 if (!addr || key > KEY_STREAM3) {
297 kill_channel(ch);
298 return;
299 }
300
301 ch->io.addr = addr;
302 ch->io.len = req_count;
303 ch->io.is_last = is_last;
304 ch->io.dma_end = dbdma_end;
305 ch->io.is_dma_out = 1;
306 ch->io.processing = true;
307 if (ch->rw) {
308 ch->rw(&ch->io);
309 }
310 }
311
312 static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
313 uint16_t req_count, int is_last)
314 {
315 DBDMA_DPRINTF("start_input\n");
316
317 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
318 * are not implemented in the mac-io chip
319 */
320
321 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
322 if (!addr || key > KEY_STREAM3) {
323 kill_channel(ch);
324 return;
325 }
326
327 ch->io.addr = addr;
328 ch->io.len = req_count;
329 ch->io.is_last = is_last;
330 ch->io.dma_end = dbdma_end;
331 ch->io.is_dma_out = 0;
332 ch->io.processing = true;
333 if (ch->rw) {
334 ch->rw(&ch->io);
335 }
336 }
337
338 static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
339 uint16_t len)
340 {
341 dbdma_cmd *current = &ch->current;
342 uint32_t val;
343
344 DBDMA_DPRINTF("load_word\n");
345
346 /* only implements KEY_SYSTEM */
347
348 if (key != KEY_SYSTEM) {
349 printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
350 kill_channel(ch);
351 return;
352 }
353
354 cpu_physical_memory_read(addr, &val, len);
355
356 if (len == 2)
357 val = (val << 16) | (current->cmd_dep & 0x0000ffff);
358 else if (len == 1)
359 val = (val << 24) | (current->cmd_dep & 0x00ffffff);
360
361 current->cmd_dep = val;
362
363 if (conditional_wait(ch))
364 goto wait;
365
366 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
367 dbdma_cmdptr_save(ch);
368 ch->regs[DBDMA_STATUS] &= ~FLUSH;
369
370 conditional_interrupt(ch);
371 next(ch);
372
373 wait:
374 DBDMA_kick(dbdma_from_ch(ch));
375 }
376
377 static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
378 uint16_t len)
379 {
380 dbdma_cmd *current = &ch->current;
381 uint32_t val;
382
383 DBDMA_DPRINTF("store_word\n");
384
385 /* only implements KEY_SYSTEM */
386
387 if (key != KEY_SYSTEM) {
388 printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
389 kill_channel(ch);
390 return;
391 }
392
393 val = current->cmd_dep;
394 if (len == 2)
395 val >>= 16;
396 else if (len == 1)
397 val >>= 24;
398
399 cpu_physical_memory_write(addr, &val, len);
400
401 if (conditional_wait(ch))
402 goto wait;
403
404 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
405 dbdma_cmdptr_save(ch);
406 ch->regs[DBDMA_STATUS] &= ~FLUSH;
407
408 conditional_interrupt(ch);
409 next(ch);
410
411 wait:
412 DBDMA_kick(dbdma_from_ch(ch));
413 }
414
415 static void nop(DBDMA_channel *ch)
416 {
417 dbdma_cmd *current = &ch->current;
418
419 if (conditional_wait(ch))
420 goto wait;
421
422 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
423 dbdma_cmdptr_save(ch);
424
425 conditional_interrupt(ch);
426 conditional_branch(ch);
427
428 wait:
429 DBDMA_kick(dbdma_from_ch(ch));
430 }
431
432 static void stop(DBDMA_channel *ch)
433 {
434 ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
435
436 /* the stop command does not increment command pointer */
437 }
438
439 static void channel_run(DBDMA_channel *ch)
440 {
441 dbdma_cmd *current = &ch->current;
442 uint16_t cmd, key;
443 uint16_t req_count;
444 uint32_t phy_addr;
445
446 DBDMA_DPRINTF("channel_run\n");
447 dump_dbdma_cmd(current);
448
449 /* clear WAKE flag at command fetch */
450
451 ch->regs[DBDMA_STATUS] &= ~WAKE;
452
453 cmd = le16_to_cpu(current->command) & COMMAND_MASK;
454
455 switch (cmd) {
456 case DBDMA_NOP:
457 nop(ch);
458 return;
459
460 case DBDMA_STOP:
461 stop(ch);
462 return;
463 }
464
465 key = le16_to_cpu(current->command) & 0x0700;
466 req_count = le16_to_cpu(current->req_count);
467 phy_addr = le32_to_cpu(current->phy_addr);
468
469 if (key == KEY_STREAM4) {
470 printf("command %x, invalid key 4\n", cmd);
471 kill_channel(ch);
472 return;
473 }
474
475 switch (cmd) {
476 case OUTPUT_MORE:
477 start_output(ch, key, phy_addr, req_count, 0);
478 return;
479
480 case OUTPUT_LAST:
481 start_output(ch, key, phy_addr, req_count, 1);
482 return;
483
484 case INPUT_MORE:
485 start_input(ch, key, phy_addr, req_count, 0);
486 return;
487
488 case INPUT_LAST:
489 start_input(ch, key, phy_addr, req_count, 1);
490 return;
491 }
492
493 if (key < KEY_REGS) {
494 printf("command %x, invalid key %x\n", cmd, key);
495 key = KEY_SYSTEM;
496 }
497
498 /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
499 * and BRANCH is invalid
500 */
501
502 req_count = req_count & 0x0007;
503 if (req_count & 0x4) {
504 req_count = 4;
505 phy_addr &= ~3;
506 } else if (req_count & 0x2) {
507 req_count = 2;
508 phy_addr &= ~1;
509 } else
510 req_count = 1;
511
512 switch (cmd) {
513 case LOAD_WORD:
514 load_word(ch, key, phy_addr, req_count);
515 return;
516
517 case STORE_WORD:
518 store_word(ch, key, phy_addr, req_count);
519 return;
520 }
521 }
522
523 static void DBDMA_run(DBDMAState *s)
524 {
525 int channel;
526
527 for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
528 DBDMA_channel *ch = &s->channels[channel];
529 uint32_t status = ch->regs[DBDMA_STATUS];
530 if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) {
531 channel_run(ch);
532 }
533 }
534 }
535
536 static void DBDMA_run_bh(void *opaque)
537 {
538 DBDMAState *s = opaque;
539
540 DBDMA_DPRINTF("DBDMA_run_bh\n");
541
542 DBDMA_run(s);
543 }
544
545 void DBDMA_kick(DBDMAState *dbdma)
546 {
547 qemu_bh_schedule(dbdma->bh);
548 }
549
550 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
551 DBDMA_rw rw, DBDMA_flush flush,
552 void *opaque)
553 {
554 DBDMAState *s = dbdma;
555 DBDMA_channel *ch = &s->channels[nchan];
556
557 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
558
559 ch->irq = irq;
560 ch->channel = nchan;
561 ch->rw = rw;
562 ch->flush = flush;
563 ch->io.opaque = opaque;
564 ch->io.channel = ch;
565 }
566
567 static void
568 dbdma_control_write(DBDMA_channel *ch)
569 {
570 uint16_t mask, value;
571 uint32_t status;
572
573 mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
574 value = ch->regs[DBDMA_CONTROL] & 0xffff;
575
576 value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
577
578 status = ch->regs[DBDMA_STATUS];
579
580 status = (value & mask) | (status & ~mask);
581
582 if (status & WAKE)
583 status |= ACTIVE;
584 if (status & RUN) {
585 status |= ACTIVE;
586 status &= ~DEAD;
587 }
588 if (status & PAUSE)
589 status &= ~ACTIVE;
590 if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
591 /* RUN is cleared */
592 status &= ~(ACTIVE|DEAD);
593 if ((status & FLUSH) && ch->flush) {
594 ch->flush(&ch->io);
595 status &= ~FLUSH;
596 }
597 }
598
599 DBDMA_DPRINTF(" status 0x%08x\n", status);
600
601 ch->regs[DBDMA_STATUS] = status;
602
603 if (status & ACTIVE) {
604 DBDMA_kick(dbdma_from_ch(ch));
605 }
606 if ((status & FLUSH) && ch->flush) {
607 ch->flush(&ch->io);
608 }
609 }
610
611 static void dbdma_write(void *opaque, hwaddr addr,
612 uint64_t value, unsigned size)
613 {
614 int channel = addr >> DBDMA_CHANNEL_SHIFT;
615 DBDMAState *s = opaque;
616 DBDMA_channel *ch = &s->channels[channel];
617 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
618
619 DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
620 addr, value);
621 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
622 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
623
624 /* cmdptr cannot be modified if channel is ACTIVE */
625
626 if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
627 return;
628 }
629
630 ch->regs[reg] = value;
631
632 switch(reg) {
633 case DBDMA_CONTROL:
634 dbdma_control_write(ch);
635 break;
636 case DBDMA_CMDPTR_LO:
637 /* 16-byte aligned */
638 ch->regs[DBDMA_CMDPTR_LO] &= ~0xf;
639 dbdma_cmdptr_load(ch);
640 break;
641 case DBDMA_STATUS:
642 case DBDMA_INTR_SEL:
643 case DBDMA_BRANCH_SEL:
644 case DBDMA_WAIT_SEL:
645 /* nothing to do */
646 break;
647 case DBDMA_XFER_MODE:
648 case DBDMA_CMDPTR_HI:
649 case DBDMA_DATA2PTR_HI:
650 case DBDMA_DATA2PTR_LO:
651 case DBDMA_ADDRESS_HI:
652 case DBDMA_BRANCH_ADDR_HI:
653 case DBDMA_RES1:
654 case DBDMA_RES2:
655 case DBDMA_RES3:
656 case DBDMA_RES4:
657 /* unused */
658 break;
659 }
660 }
661
662 static uint64_t dbdma_read(void *opaque, hwaddr addr,
663 unsigned size)
664 {
665 uint32_t value;
666 int channel = addr >> DBDMA_CHANNEL_SHIFT;
667 DBDMAState *s = opaque;
668 DBDMA_channel *ch = &s->channels[channel];
669 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
670
671 value = ch->regs[reg];
672
673 DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
674 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
675 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
676
677 switch(reg) {
678 case DBDMA_CONTROL:
679 value = 0;
680 break;
681 case DBDMA_STATUS:
682 case DBDMA_CMDPTR_LO:
683 case DBDMA_INTR_SEL:
684 case DBDMA_BRANCH_SEL:
685 case DBDMA_WAIT_SEL:
686 /* nothing to do */
687 break;
688 case DBDMA_XFER_MODE:
689 case DBDMA_CMDPTR_HI:
690 case DBDMA_DATA2PTR_HI:
691 case DBDMA_DATA2PTR_LO:
692 case DBDMA_ADDRESS_HI:
693 case DBDMA_BRANCH_ADDR_HI:
694 /* unused */
695 value = 0;
696 break;
697 case DBDMA_RES1:
698 case DBDMA_RES2:
699 case DBDMA_RES3:
700 case DBDMA_RES4:
701 /* reserved */
702 break;
703 }
704
705 return value;
706 }
707
708 static const MemoryRegionOps dbdma_ops = {
709 .read = dbdma_read,
710 .write = dbdma_write,
711 .endianness = DEVICE_LITTLE_ENDIAN,
712 .valid = {
713 .min_access_size = 4,
714 .max_access_size = 4,
715 },
716 };
717
718 static const VMStateDescription vmstate_dbdma_channel = {
719 .name = "dbdma_channel",
720 .version_id = 0,
721 .minimum_version_id = 0,
722 .minimum_version_id_old = 0,
723 .fields = (VMStateField[]) {
724 VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
725 VMSTATE_END_OF_LIST()
726 }
727 };
728
729 static const VMStateDescription vmstate_dbdma = {
730 .name = "dbdma",
731 .version_id = 2,
732 .minimum_version_id = 2,
733 .minimum_version_id_old = 2,
734 .fields = (VMStateField[]) {
735 VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
736 vmstate_dbdma_channel, DBDMA_channel),
737 VMSTATE_END_OF_LIST()
738 }
739 };
740
741 static void dbdma_reset(void *opaque)
742 {
743 DBDMAState *s = opaque;
744 int i;
745
746 for (i = 0; i < DBDMA_CHANNELS; i++)
747 memset(s->channels[i].regs, 0, DBDMA_SIZE);
748 }
749
750 void* DBDMA_init (MemoryRegion **dbdma_mem)
751 {
752 DBDMAState *s;
753
754 s = g_malloc0(sizeof(DBDMAState));
755
756 memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
757 *dbdma_mem = &s->mem;
758 vmstate_register(NULL, -1, &vmstate_dbdma, s);
759 qemu_register_reset(dbdma_reset, s);
760
761 s->bh = qemu_bh_new(DBDMA_run_bh, s);
762
763 return s;
764 }