xref: /qemu/hw/misc/macio/mac_dbdma.c (revision 7a4e543d)
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 "qemu/osdep.h"
40 #include "hw/hw.h"
41 #include "hw/isa/isa.h"
42 #include "hw/ppc/mac_dbdma.h"
43 #include "qemu/main-loop.h"
44 
45 /* debug DBDMA */
46 //#define DEBUG_DBDMA
47 
48 #ifdef DEBUG_DBDMA
49 #define DBDMA_DPRINTF(fmt, ...)                                 \
50     do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
51 #else
52 #define DBDMA_DPRINTF(fmt, ...)
53 #endif
54 
55 /*
56  */
57 
58 static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
59 {
60     return container_of(ch, DBDMAState, channels[ch->channel]);
61 }
62 
63 #ifdef DEBUG_DBDMA
64 static void dump_dbdma_cmd(dbdma_cmd *cmd)
65 {
66     printf("dbdma_cmd %p\n", cmd);
67     printf("    req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
68     printf("    command 0x%04x\n", le16_to_cpu(cmd->command));
69     printf("    phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
70     printf("    cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
71     printf("    res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
72     printf("    xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status));
73 }
74 #else
75 static void dump_dbdma_cmd(dbdma_cmd *cmd)
76 {
77 }
78 #endif
79 static void dbdma_cmdptr_load(DBDMA_channel *ch)
80 {
81     DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
82                   ch->regs[DBDMA_CMDPTR_LO]);
83     cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
84                              &ch->current, sizeof(dbdma_cmd));
85 }
86 
87 static void dbdma_cmdptr_save(DBDMA_channel *ch)
88 {
89     DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
90                   ch->regs[DBDMA_CMDPTR_LO]);
91     DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
92                   le16_to_cpu(ch->current.xfer_status),
93                   le16_to_cpu(ch->current.res_count));
94     cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
95                               &ch->current, sizeof(dbdma_cmd));
96 }
97 
98 static void kill_channel(DBDMA_channel *ch)
99 {
100     DBDMA_DPRINTF("kill_channel\n");
101 
102     ch->regs[DBDMA_STATUS] |= DEAD;
103     ch->regs[DBDMA_STATUS] &= ~ACTIVE;
104 
105     qemu_irq_raise(ch->irq);
106 }
107 
108 static void conditional_interrupt(DBDMA_channel *ch)
109 {
110     dbdma_cmd *current = &ch->current;
111     uint16_t intr;
112     uint16_t sel_mask, sel_value;
113     uint32_t status;
114     int cond;
115 
116     DBDMA_DPRINTF("%s\n", __func__);
117 
118     intr = le16_to_cpu(current->command) & INTR_MASK;
119 
120     switch(intr) {
121     case INTR_NEVER:  /* don't interrupt */
122         return;
123     case INTR_ALWAYS: /* always interrupt */
124         qemu_irq_raise(ch->irq);
125         DBDMA_DPRINTF("%s: raise\n", __func__);
126         return;
127     }
128 
129     status = ch->regs[DBDMA_STATUS] & DEVSTAT;
130 
131     sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
132     sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
133 
134     cond = (status & sel_mask) == (sel_value & sel_mask);
135 
136     switch(intr) {
137     case INTR_IFSET:  /* intr if condition bit is 1 */
138         if (cond) {
139             qemu_irq_raise(ch->irq);
140             DBDMA_DPRINTF("%s: raise\n", __func__);
141         }
142         return;
143     case INTR_IFCLR:  /* intr if condition bit is 0 */
144         if (!cond) {
145             qemu_irq_raise(ch->irq);
146             DBDMA_DPRINTF("%s: raise\n", __func__);
147         }
148         return;
149     }
150 }
151 
152 static int conditional_wait(DBDMA_channel *ch)
153 {
154     dbdma_cmd *current = &ch->current;
155     uint16_t wait;
156     uint16_t sel_mask, sel_value;
157     uint32_t status;
158     int cond;
159 
160     DBDMA_DPRINTF("conditional_wait\n");
161 
162     wait = le16_to_cpu(current->command) & WAIT_MASK;
163 
164     switch(wait) {
165     case WAIT_NEVER:  /* don't wait */
166         return 0;
167     case WAIT_ALWAYS: /* always wait */
168         return 1;
169     }
170 
171     status = ch->regs[DBDMA_STATUS] & DEVSTAT;
172 
173     sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
174     sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
175 
176     cond = (status & sel_mask) == (sel_value & sel_mask);
177 
178     switch(wait) {
179     case WAIT_IFSET:  /* wait if condition bit is 1 */
180         if (cond)
181             return 1;
182         return 0;
183     case WAIT_IFCLR:  /* wait if condition bit is 0 */
184         if (!cond)
185             return 1;
186         return 0;
187     }
188     return 0;
189 }
190 
191 static void next(DBDMA_channel *ch)
192 {
193     uint32_t cp;
194 
195     ch->regs[DBDMA_STATUS] &= ~BT;
196 
197     cp = ch->regs[DBDMA_CMDPTR_LO];
198     ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
199     dbdma_cmdptr_load(ch);
200 }
201 
202 static void branch(DBDMA_channel *ch)
203 {
204     dbdma_cmd *current = &ch->current;
205 
206     ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
207     ch->regs[DBDMA_STATUS] |= BT;
208     dbdma_cmdptr_load(ch);
209 }
210 
211 static void conditional_branch(DBDMA_channel *ch)
212 {
213     dbdma_cmd *current = &ch->current;
214     uint16_t br;
215     uint16_t sel_mask, sel_value;
216     uint32_t status;
217     int cond;
218 
219     DBDMA_DPRINTF("conditional_branch\n");
220 
221     /* check if we must branch */
222 
223     br = le16_to_cpu(current->command) & BR_MASK;
224 
225     switch(br) {
226     case BR_NEVER:  /* don't branch */
227         next(ch);
228         return;
229     case BR_ALWAYS: /* always branch */
230         branch(ch);
231         return;
232     }
233 
234     status = ch->regs[DBDMA_STATUS] & DEVSTAT;
235 
236     sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
237     sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
238 
239     cond = (status & sel_mask) == (sel_value & sel_mask);
240 
241     switch(br) {
242     case BR_IFSET:  /* branch if condition bit is 1 */
243         if (cond)
244             branch(ch);
245         else
246             next(ch);
247         return;
248     case BR_IFCLR:  /* branch if condition bit is 0 */
249         if (!cond)
250             branch(ch);
251         else
252             next(ch);
253         return;
254     }
255 }
256 
257 static void channel_run(DBDMA_channel *ch);
258 
259 static void dbdma_end(DBDMA_io *io)
260 {
261     DBDMA_channel *ch = io->channel;
262     dbdma_cmd *current = &ch->current;
263 
264     DBDMA_DPRINTF("%s\n", __func__);
265 
266     if (conditional_wait(ch))
267         goto wait;
268 
269     current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
270     current->res_count = cpu_to_le16(io->len);
271     dbdma_cmdptr_save(ch);
272     if (io->is_last)
273         ch->regs[DBDMA_STATUS] &= ~FLUSH;
274 
275     conditional_interrupt(ch);
276     conditional_branch(ch);
277 
278 wait:
279     /* Indicate that we're ready for a new DMA round */
280     ch->io.processing = false;
281 
282     if ((ch->regs[DBDMA_STATUS] & RUN) &&
283         (ch->regs[DBDMA_STATUS] & ACTIVE))
284         channel_run(ch);
285 }
286 
287 static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
288                         uint16_t req_count, int is_last)
289 {
290     DBDMA_DPRINTF("start_output\n");
291 
292     /* KEY_REGS, KEY_DEVICE and KEY_STREAM
293      * are not implemented in the mac-io chip
294      */
295 
296     DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
297     if (!addr || key > KEY_STREAM3) {
298         kill_channel(ch);
299         return;
300     }
301 
302     ch->io.addr = addr;
303     ch->io.len = req_count;
304     ch->io.is_last = is_last;
305     ch->io.dma_end = dbdma_end;
306     ch->io.is_dma_out = 1;
307     ch->io.processing = true;
308     if (ch->rw) {
309         ch->rw(&ch->io);
310     }
311 }
312 
313 static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
314                        uint16_t req_count, int is_last)
315 {
316     DBDMA_DPRINTF("start_input\n");
317 
318     /* KEY_REGS, KEY_DEVICE and KEY_STREAM
319      * are not implemented in the mac-io chip
320      */
321 
322     DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
323     if (!addr || key > KEY_STREAM3) {
324         kill_channel(ch);
325         return;
326     }
327 
328     ch->io.addr = addr;
329     ch->io.len = req_count;
330     ch->io.is_last = is_last;
331     ch->io.dma_end = dbdma_end;
332     ch->io.is_dma_out = 0;
333     ch->io.processing = true;
334     if (ch->rw) {
335         ch->rw(&ch->io);
336     }
337 }
338 
339 static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
340                      uint16_t len)
341 {
342     dbdma_cmd *current = &ch->current;
343     uint32_t val;
344 
345     DBDMA_DPRINTF("load_word\n");
346 
347     /* only implements KEY_SYSTEM */
348 
349     if (key != KEY_SYSTEM) {
350         printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
351         kill_channel(ch);
352         return;
353     }
354 
355     cpu_physical_memory_read(addr, &val, len);
356 
357     if (len == 2)
358         val = (val << 16) | (current->cmd_dep & 0x0000ffff);
359     else if (len == 1)
360         val = (val << 24) | (current->cmd_dep & 0x00ffffff);
361 
362     current->cmd_dep = val;
363 
364     if (conditional_wait(ch))
365         goto wait;
366 
367     current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
368     dbdma_cmdptr_save(ch);
369     ch->regs[DBDMA_STATUS] &= ~FLUSH;
370 
371     conditional_interrupt(ch);
372     next(ch);
373 
374 wait:
375     DBDMA_kick(dbdma_from_ch(ch));
376 }
377 
378 static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
379                       uint16_t len)
380 {
381     dbdma_cmd *current = &ch->current;
382     uint32_t val;
383 
384     DBDMA_DPRINTF("store_word\n");
385 
386     /* only implements KEY_SYSTEM */
387 
388     if (key != KEY_SYSTEM) {
389         printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
390         kill_channel(ch);
391         return;
392     }
393 
394     val = current->cmd_dep;
395     if (len == 2)
396         val >>= 16;
397     else if (len == 1)
398         val >>= 24;
399 
400     cpu_physical_memory_write(addr, &val, len);
401 
402     if (conditional_wait(ch))
403         goto wait;
404 
405     current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
406     dbdma_cmdptr_save(ch);
407     ch->regs[DBDMA_STATUS] &= ~FLUSH;
408 
409     conditional_interrupt(ch);
410     next(ch);
411 
412 wait:
413     DBDMA_kick(dbdma_from_ch(ch));
414 }
415 
416 static void nop(DBDMA_channel *ch)
417 {
418     dbdma_cmd *current = &ch->current;
419 
420     if (conditional_wait(ch))
421         goto wait;
422 
423     current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
424     dbdma_cmdptr_save(ch);
425 
426     conditional_interrupt(ch);
427     conditional_branch(ch);
428 
429 wait:
430     DBDMA_kick(dbdma_from_ch(ch));
431 }
432 
433 static void stop(DBDMA_channel *ch)
434 {
435     ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
436 
437     /* the stop command does not increment command pointer */
438 }
439 
440 static void channel_run(DBDMA_channel *ch)
441 {
442     dbdma_cmd *current = &ch->current;
443     uint16_t cmd, key;
444     uint16_t req_count;
445     uint32_t phy_addr;
446 
447     DBDMA_DPRINTF("channel_run\n");
448     dump_dbdma_cmd(current);
449 
450     /* clear WAKE flag at command fetch */
451 
452     ch->regs[DBDMA_STATUS] &= ~WAKE;
453 
454     cmd = le16_to_cpu(current->command) & COMMAND_MASK;
455 
456     switch (cmd) {
457     case DBDMA_NOP:
458         nop(ch);
459         return;
460 
461     case DBDMA_STOP:
462         stop(ch);
463         return;
464     }
465 
466     key = le16_to_cpu(current->command) & 0x0700;
467     req_count = le16_to_cpu(current->req_count);
468     phy_addr = le32_to_cpu(current->phy_addr);
469 
470     if (key == KEY_STREAM4) {
471         printf("command %x, invalid key 4\n", cmd);
472         kill_channel(ch);
473         return;
474     }
475 
476     switch (cmd) {
477     case OUTPUT_MORE:
478         start_output(ch, key, phy_addr, req_count, 0);
479         return;
480 
481     case OUTPUT_LAST:
482         start_output(ch, key, phy_addr, req_count, 1);
483         return;
484 
485     case INPUT_MORE:
486         start_input(ch, key, phy_addr, req_count, 0);
487         return;
488 
489     case INPUT_LAST:
490         start_input(ch, key, phy_addr, req_count, 1);
491         return;
492     }
493 
494     if (key < KEY_REGS) {
495         printf("command %x, invalid key %x\n", cmd, key);
496         key = KEY_SYSTEM;
497     }
498 
499     /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
500      * and BRANCH is invalid
501      */
502 
503     req_count = req_count & 0x0007;
504     if (req_count & 0x4) {
505         req_count = 4;
506         phy_addr &= ~3;
507     } else if (req_count & 0x2) {
508         req_count = 2;
509         phy_addr &= ~1;
510     } else
511         req_count = 1;
512 
513     switch (cmd) {
514     case LOAD_WORD:
515         load_word(ch, key, phy_addr, req_count);
516         return;
517 
518     case STORE_WORD:
519         store_word(ch, key, phy_addr, req_count);
520         return;
521     }
522 }
523 
524 static void DBDMA_run(DBDMAState *s)
525 {
526     int channel;
527 
528     for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
529         DBDMA_channel *ch = &s->channels[channel];
530         uint32_t status = ch->regs[DBDMA_STATUS];
531         if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) {
532             channel_run(ch);
533         }
534     }
535 }
536 
537 static void DBDMA_run_bh(void *opaque)
538 {
539     DBDMAState *s = opaque;
540 
541     DBDMA_DPRINTF("DBDMA_run_bh\n");
542 
543     DBDMA_run(s);
544 }
545 
546 void DBDMA_kick(DBDMAState *dbdma)
547 {
548     qemu_bh_schedule(dbdma->bh);
549 }
550 
551 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
552                             DBDMA_rw rw, DBDMA_flush flush,
553                             void *opaque)
554 {
555     DBDMAState *s = dbdma;
556     DBDMA_channel *ch = &s->channels[nchan];
557 
558     DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
559 
560     ch->irq = irq;
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     }
594 
595     if ((status & FLUSH) && ch->flush) {
596         ch->flush(&ch->io);
597         status &= ~FLUSH;
598     }
599 
600     DBDMA_DPRINTF("    status 0x%08x\n", status);
601 
602     ch->regs[DBDMA_STATUS] = status;
603 
604     if (status & ACTIVE) {
605         DBDMA_kick(dbdma_from_ch(ch));
606     }
607 }
608 
609 static void dbdma_write(void *opaque, hwaddr addr,
610                         uint64_t value, unsigned size)
611 {
612     int channel = addr >> DBDMA_CHANNEL_SHIFT;
613     DBDMAState *s = opaque;
614     DBDMA_channel *ch = &s->channels[channel];
615     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
616 
617     DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
618                   addr, value);
619     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
620                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
621 
622     /* cmdptr cannot be modified if channel is ACTIVE */
623 
624     if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
625         return;
626     }
627 
628     ch->regs[reg] = value;
629 
630     switch(reg) {
631     case DBDMA_CONTROL:
632         dbdma_control_write(ch);
633         break;
634     case DBDMA_CMDPTR_LO:
635         /* 16-byte aligned */
636         ch->regs[DBDMA_CMDPTR_LO] &= ~0xf;
637         dbdma_cmdptr_load(ch);
638         break;
639     case DBDMA_STATUS:
640     case DBDMA_INTR_SEL:
641     case DBDMA_BRANCH_SEL:
642     case DBDMA_WAIT_SEL:
643         /* nothing to do */
644         break;
645     case DBDMA_XFER_MODE:
646     case DBDMA_CMDPTR_HI:
647     case DBDMA_DATA2PTR_HI:
648     case DBDMA_DATA2PTR_LO:
649     case DBDMA_ADDRESS_HI:
650     case DBDMA_BRANCH_ADDR_HI:
651     case DBDMA_RES1:
652     case DBDMA_RES2:
653     case DBDMA_RES3:
654     case DBDMA_RES4:
655         /* unused */
656         break;
657     }
658 }
659 
660 static uint64_t dbdma_read(void *opaque, hwaddr addr,
661                            unsigned size)
662 {
663     uint32_t value;
664     int channel = addr >> DBDMA_CHANNEL_SHIFT;
665     DBDMAState *s = opaque;
666     DBDMA_channel *ch = &s->channels[channel];
667     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
668 
669     value = ch->regs[reg];
670 
671     DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
672     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
673                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
674 
675     switch(reg) {
676     case DBDMA_CONTROL:
677         value = 0;
678         break;
679     case DBDMA_STATUS:
680     case DBDMA_CMDPTR_LO:
681     case DBDMA_INTR_SEL:
682     case DBDMA_BRANCH_SEL:
683     case DBDMA_WAIT_SEL:
684         /* nothing to do */
685         break;
686     case DBDMA_XFER_MODE:
687     case DBDMA_CMDPTR_HI:
688     case DBDMA_DATA2PTR_HI:
689     case DBDMA_DATA2PTR_LO:
690     case DBDMA_ADDRESS_HI:
691     case DBDMA_BRANCH_ADDR_HI:
692         /* unused */
693         value = 0;
694         break;
695     case DBDMA_RES1:
696     case DBDMA_RES2:
697     case DBDMA_RES3:
698     case DBDMA_RES4:
699         /* reserved */
700         break;
701     }
702 
703     return value;
704 }
705 
706 static const MemoryRegionOps dbdma_ops = {
707     .read = dbdma_read,
708     .write = dbdma_write,
709     .endianness = DEVICE_LITTLE_ENDIAN,
710     .valid = {
711         .min_access_size = 4,
712         .max_access_size = 4,
713     },
714 };
715 
716 static const VMStateDescription vmstate_dbdma_io = {
717     .name = "dbdma_io",
718     .version_id = 0,
719     .minimum_version_id = 0,
720     .fields = (VMStateField[]) {
721         VMSTATE_UINT64(addr, struct DBDMA_io),
722         VMSTATE_INT32(len, struct DBDMA_io),
723         VMSTATE_INT32(is_last, struct DBDMA_io),
724         VMSTATE_INT32(is_dma_out, struct DBDMA_io),
725         VMSTATE_BOOL(processing, struct DBDMA_io),
726         VMSTATE_END_OF_LIST()
727     }
728 };
729 
730 static const VMStateDescription vmstate_dbdma_cmd = {
731     .name = "dbdma_cmd",
732     .version_id = 0,
733     .minimum_version_id = 0,
734     .fields = (VMStateField[]) {
735         VMSTATE_UINT16(req_count, dbdma_cmd),
736         VMSTATE_UINT16(command, dbdma_cmd),
737         VMSTATE_UINT32(phy_addr, dbdma_cmd),
738         VMSTATE_UINT32(cmd_dep, dbdma_cmd),
739         VMSTATE_UINT16(res_count, dbdma_cmd),
740         VMSTATE_UINT16(xfer_status, dbdma_cmd),
741         VMSTATE_END_OF_LIST()
742     }
743 };
744 
745 static const VMStateDescription vmstate_dbdma_channel = {
746     .name = "dbdma_channel",
747     .version_id = 1,
748     .minimum_version_id = 1,
749     .fields = (VMStateField[]) {
750         VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
751         VMSTATE_STRUCT(io, struct DBDMA_channel, 0, vmstate_dbdma_io, DBDMA_io),
752         VMSTATE_STRUCT(current, struct DBDMA_channel, 0, vmstate_dbdma_cmd,
753                        dbdma_cmd),
754         VMSTATE_END_OF_LIST()
755     }
756 };
757 
758 static const VMStateDescription vmstate_dbdma = {
759     .name = "dbdma",
760     .version_id = 3,
761     .minimum_version_id = 3,
762     .fields = (VMStateField[]) {
763         VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
764                              vmstate_dbdma_channel, DBDMA_channel),
765         VMSTATE_END_OF_LIST()
766     }
767 };
768 
769 static void dbdma_reset(void *opaque)
770 {
771     DBDMAState *s = opaque;
772     int i;
773 
774     for (i = 0; i < DBDMA_CHANNELS; i++)
775         memset(s->channels[i].regs, 0, DBDMA_SIZE);
776 }
777 
778 void* DBDMA_init (MemoryRegion **dbdma_mem)
779 {
780     DBDMAState *s;
781     int i;
782 
783     s = g_malloc0(sizeof(DBDMAState));
784 
785     for (i = 0; i < DBDMA_CHANNELS; i++) {
786         DBDMA_io *io = &s->channels[i].io;
787         qemu_iovec_init(&io->iov, 1);
788         s->channels[i].channel = i;
789     }
790 
791     memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
792     *dbdma_mem = &s->mem;
793     vmstate_register(NULL, -1, &vmstate_dbdma, s);
794     qemu_register_reset(dbdma_reset, s);
795 
796     s->bh = qemu_bh_new(DBDMA_run_bh, s);
797 
798     return s;
799 }
800