ivshmem: Implement shm=... with a memory backend
[qemu/kevin.git] / hw / misc / macio / mac_dbdma.c
blob6051f17dbd9412a43f6527782c26082d17c212d9
1 /*
2 * PowerMac descriptor-based DMA emulation
4 * Copyright (c) 2005-2007 Fabrice Bellard
5 * Copyright (c) 2007 Jocelyn Mayer
6 * Copyright (c) 2009 Laurent Vivier
8 * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h
10 * Definitions for using the Apple Descriptor-Based DMA controller
11 * in Power Macintosh computers.
13 * Copyright (C) 1996 Paul Mackerras.
15 * some parts from mol 0.9.71
17 * Descriptor based DMA emulation
19 * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se)
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:
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
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.
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"
45 /* debug DBDMA */
46 //#define DEBUG_DBDMA
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
58 static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
60 return container_of(ch, DBDMAState, channels[ch->channel]);
63 #ifdef DEBUG_DBDMA
64 static void dump_dbdma_cmd(dbdma_cmd *cmd)
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));
74 #else
75 static void dump_dbdma_cmd(dbdma_cmd *cmd)
78 #endif
79 static void dbdma_cmdptr_load(DBDMA_channel *ch)
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));
87 static void dbdma_cmdptr_save(DBDMA_channel *ch)
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));
98 static void kill_channel(DBDMA_channel *ch)
100 DBDMA_DPRINTF("kill_channel\n");
102 ch->regs[DBDMA_STATUS] |= DEAD;
103 ch->regs[DBDMA_STATUS] &= ~ACTIVE;
105 qemu_irq_raise(ch->irq);
108 static void conditional_interrupt(DBDMA_channel *ch)
110 dbdma_cmd *current = &ch->current;
111 uint16_t intr;
112 uint16_t sel_mask, sel_value;
113 uint32_t status;
114 int cond;
116 DBDMA_DPRINTF("%s\n", __func__);
118 intr = le16_to_cpu(current->command) & INTR_MASK;
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;
129 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
131 sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
132 sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
134 cond = (status & sel_mask) == (sel_value & sel_mask);
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__);
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__);
148 return;
152 static int conditional_wait(DBDMA_channel *ch)
154 dbdma_cmd *current = &ch->current;
155 uint16_t wait;
156 uint16_t sel_mask, sel_value;
157 uint32_t status;
158 int cond;
160 DBDMA_DPRINTF("conditional_wait\n");
162 wait = le16_to_cpu(current->command) & WAIT_MASK;
164 switch(wait) {
165 case WAIT_NEVER: /* don't wait */
166 return 0;
167 case WAIT_ALWAYS: /* always wait */
168 return 1;
171 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
173 sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
174 sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
176 cond = (status & sel_mask) == (sel_value & sel_mask);
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;
188 return 0;
191 static void next(DBDMA_channel *ch)
193 uint32_t cp;
195 ch->regs[DBDMA_STATUS] &= ~BT;
197 cp = ch->regs[DBDMA_CMDPTR_LO];
198 ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
199 dbdma_cmdptr_load(ch);
202 static void branch(DBDMA_channel *ch)
204 dbdma_cmd *current = &ch->current;
206 ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
207 ch->regs[DBDMA_STATUS] |= BT;
208 dbdma_cmdptr_load(ch);
211 static void conditional_branch(DBDMA_channel *ch)
213 dbdma_cmd *current = &ch->current;
214 uint16_t br;
215 uint16_t sel_mask, sel_value;
216 uint32_t status;
217 int cond;
219 DBDMA_DPRINTF("conditional_branch\n");
221 /* check if we must branch */
223 br = le16_to_cpu(current->command) & BR_MASK;
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;
234 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
236 sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
237 sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
239 cond = (status & sel_mask) == (sel_value & sel_mask);
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;
257 static void channel_run(DBDMA_channel *ch);
259 static void dbdma_end(DBDMA_io *io)
261 DBDMA_channel *ch = io->channel;
262 dbdma_cmd *current = &ch->current;
264 DBDMA_DPRINTF("%s\n", __func__);
266 if (conditional_wait(ch))
267 goto wait;
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;
275 conditional_interrupt(ch);
276 conditional_branch(ch);
278 wait:
279 /* Indicate that we're ready for a new DMA round */
280 ch->io.processing = false;
282 if ((ch->regs[DBDMA_STATUS] & RUN) &&
283 (ch->regs[DBDMA_STATUS] & ACTIVE))
284 channel_run(ch);
287 static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
288 uint16_t req_count, int is_last)
290 DBDMA_DPRINTF("start_output\n");
292 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
293 * are not implemented in the mac-io chip
296 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
297 if (!addr || key > KEY_STREAM3) {
298 kill_channel(ch);
299 return;
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);
313 static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
314 uint16_t req_count, int is_last)
316 DBDMA_DPRINTF("start_input\n");
318 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
319 * are not implemented in the mac-io chip
322 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
323 if (!addr || key > KEY_STREAM3) {
324 kill_channel(ch);
325 return;
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);
339 static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
340 uint16_t len)
342 dbdma_cmd *current = &ch->current;
343 uint32_t val;
345 DBDMA_DPRINTF("load_word\n");
347 /* only implements KEY_SYSTEM */
349 if (key != KEY_SYSTEM) {
350 printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
351 kill_channel(ch);
352 return;
355 cpu_physical_memory_read(addr, &val, len);
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);
362 current->cmd_dep = val;
364 if (conditional_wait(ch))
365 goto wait;
367 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
368 dbdma_cmdptr_save(ch);
369 ch->regs[DBDMA_STATUS] &= ~FLUSH;
371 conditional_interrupt(ch);
372 next(ch);
374 wait:
375 DBDMA_kick(dbdma_from_ch(ch));
378 static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
379 uint16_t len)
381 dbdma_cmd *current = &ch->current;
382 uint32_t val;
384 DBDMA_DPRINTF("store_word\n");
386 /* only implements KEY_SYSTEM */
388 if (key != KEY_SYSTEM) {
389 printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
390 kill_channel(ch);
391 return;
394 val = current->cmd_dep;
395 if (len == 2)
396 val >>= 16;
397 else if (len == 1)
398 val >>= 24;
400 cpu_physical_memory_write(addr, &val, len);
402 if (conditional_wait(ch))
403 goto wait;
405 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
406 dbdma_cmdptr_save(ch);
407 ch->regs[DBDMA_STATUS] &= ~FLUSH;
409 conditional_interrupt(ch);
410 next(ch);
412 wait:
413 DBDMA_kick(dbdma_from_ch(ch));
416 static void nop(DBDMA_channel *ch)
418 dbdma_cmd *current = &ch->current;
420 if (conditional_wait(ch))
421 goto wait;
423 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
424 dbdma_cmdptr_save(ch);
426 conditional_interrupt(ch);
427 conditional_branch(ch);
429 wait:
430 DBDMA_kick(dbdma_from_ch(ch));
433 static void stop(DBDMA_channel *ch)
435 ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
437 /* the stop command does not increment command pointer */
440 static void channel_run(DBDMA_channel *ch)
442 dbdma_cmd *current = &ch->current;
443 uint16_t cmd, key;
444 uint16_t req_count;
445 uint32_t phy_addr;
447 DBDMA_DPRINTF("channel_run\n");
448 dump_dbdma_cmd(current);
450 /* clear WAKE flag at command fetch */
452 ch->regs[DBDMA_STATUS] &= ~WAKE;
454 cmd = le16_to_cpu(current->command) & COMMAND_MASK;
456 switch (cmd) {
457 case DBDMA_NOP:
458 nop(ch);
459 return;
461 case DBDMA_STOP:
462 stop(ch);
463 return;
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);
470 if (key == KEY_STREAM4) {
471 printf("command %x, invalid key 4\n", cmd);
472 kill_channel(ch);
473 return;
476 switch (cmd) {
477 case OUTPUT_MORE:
478 start_output(ch, key, phy_addr, req_count, 0);
479 return;
481 case OUTPUT_LAST:
482 start_output(ch, key, phy_addr, req_count, 1);
483 return;
485 case INPUT_MORE:
486 start_input(ch, key, phy_addr, req_count, 0);
487 return;
489 case INPUT_LAST:
490 start_input(ch, key, phy_addr, req_count, 1);
491 return;
494 if (key < KEY_REGS) {
495 printf("command %x, invalid key %x\n", cmd, key);
496 key = KEY_SYSTEM;
499 /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
500 * and BRANCH is invalid
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;
513 switch (cmd) {
514 case LOAD_WORD:
515 load_word(ch, key, phy_addr, req_count);
516 return;
518 case STORE_WORD:
519 store_word(ch, key, phy_addr, req_count);
520 return;
524 static void DBDMA_run(DBDMAState *s)
526 int channel;
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);
537 static void DBDMA_run_bh(void *opaque)
539 DBDMAState *s = opaque;
541 DBDMA_DPRINTF("DBDMA_run_bh\n");
543 DBDMA_run(s);
546 void DBDMA_kick(DBDMAState *dbdma)
548 qemu_bh_schedule(dbdma->bh);
551 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
552 DBDMA_rw rw, DBDMA_flush flush,
553 void *opaque)
555 DBDMAState *s = dbdma;
556 DBDMA_channel *ch = &s->channels[nchan];
558 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
560 assert(rw);
561 assert(flush);
563 ch->irq = irq;
564 ch->rw = rw;
565 ch->flush = flush;
566 ch->io.opaque = opaque;
569 static void
570 dbdma_control_write(DBDMA_channel *ch)
572 uint16_t mask, value;
573 uint32_t status;
575 mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
576 value = ch->regs[DBDMA_CONTROL] & 0xffff;
578 value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
580 status = ch->regs[DBDMA_STATUS];
582 status = (value & mask) | (status & ~mask);
584 if (status & WAKE)
585 status |= ACTIVE;
586 if (status & RUN) {
587 status |= ACTIVE;
588 status &= ~DEAD;
590 if (status & PAUSE)
591 status &= ~ACTIVE;
592 if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
593 /* RUN is cleared */
594 status &= ~(ACTIVE|DEAD);
597 if ((status & FLUSH) && ch->flush) {
598 ch->flush(&ch->io);
599 status &= ~FLUSH;
602 DBDMA_DPRINTF(" status 0x%08x\n", status);
604 ch->regs[DBDMA_STATUS] = status;
606 if (status & ACTIVE) {
607 DBDMA_kick(dbdma_from_ch(ch));
611 static void dbdma_write(void *opaque, hwaddr addr,
612 uint64_t value, unsigned size)
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;
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);
624 /* cmdptr cannot be modified if channel is ACTIVE */
626 if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
627 return;
630 ch->regs[reg] = value;
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;
662 static uint64_t dbdma_read(void *opaque, hwaddr addr,
663 unsigned size)
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;
671 value = ch->regs[reg];
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);
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;
705 return value;
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,
718 static const VMStateDescription vmstate_dbdma_io = {
719 .name = "dbdma_io",
720 .version_id = 0,
721 .minimum_version_id = 0,
722 .fields = (VMStateField[]) {
723 VMSTATE_UINT64(addr, struct DBDMA_io),
724 VMSTATE_INT32(len, struct DBDMA_io),
725 VMSTATE_INT32(is_last, struct DBDMA_io),
726 VMSTATE_INT32(is_dma_out, struct DBDMA_io),
727 VMSTATE_BOOL(processing, struct DBDMA_io),
728 VMSTATE_END_OF_LIST()
732 static const VMStateDescription vmstate_dbdma_cmd = {
733 .name = "dbdma_cmd",
734 .version_id = 0,
735 .minimum_version_id = 0,
736 .fields = (VMStateField[]) {
737 VMSTATE_UINT16(req_count, dbdma_cmd),
738 VMSTATE_UINT16(command, dbdma_cmd),
739 VMSTATE_UINT32(phy_addr, dbdma_cmd),
740 VMSTATE_UINT32(cmd_dep, dbdma_cmd),
741 VMSTATE_UINT16(res_count, dbdma_cmd),
742 VMSTATE_UINT16(xfer_status, dbdma_cmd),
743 VMSTATE_END_OF_LIST()
747 static const VMStateDescription vmstate_dbdma_channel = {
748 .name = "dbdma_channel",
749 .version_id = 1,
750 .minimum_version_id = 1,
751 .fields = (VMStateField[]) {
752 VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
753 VMSTATE_STRUCT(io, struct DBDMA_channel, 0, vmstate_dbdma_io, DBDMA_io),
754 VMSTATE_STRUCT(current, struct DBDMA_channel, 0, vmstate_dbdma_cmd,
755 dbdma_cmd),
756 VMSTATE_END_OF_LIST()
760 static const VMStateDescription vmstate_dbdma = {
761 .name = "dbdma",
762 .version_id = 3,
763 .minimum_version_id = 3,
764 .fields = (VMStateField[]) {
765 VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
766 vmstate_dbdma_channel, DBDMA_channel),
767 VMSTATE_END_OF_LIST()
771 static void dbdma_reset(void *opaque)
773 DBDMAState *s = opaque;
774 int i;
776 for (i = 0; i < DBDMA_CHANNELS; i++)
777 memset(s->channels[i].regs, 0, DBDMA_SIZE);
780 static void dbdma_unassigned_rw(DBDMA_io *io)
782 DBDMA_channel *ch = io->channel;
783 qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
784 __func__, ch->channel);
787 static void dbdma_unassigned_flush(DBDMA_io *io)
789 DBDMA_channel *ch = io->channel;
790 qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
791 __func__, ch->channel);
794 void* DBDMA_init (MemoryRegion **dbdma_mem)
796 DBDMAState *s;
797 int i;
799 s = g_malloc0(sizeof(DBDMAState));
801 for (i = 0; i < DBDMA_CHANNELS; i++) {
802 DBDMA_io *io = &s->channels[i].io;
803 DBDMA_channel *ch = &s->channels[i];
804 qemu_iovec_init(&io->iov, 1);
806 ch->rw = dbdma_unassigned_rw;
807 ch->flush = dbdma_unassigned_flush;
808 ch->channel = i;
809 ch->io.channel = ch;
812 memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
813 *dbdma_mem = &s->mem;
814 vmstate_register(NULL, -1, &vmstate_dbdma, s);
815 qemu_register_reset(dbdma_reset, s);
817 s->bh = qemu_bh_new(DBDMA_run_bh, s);
819 return s;