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