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_kick(DBDMAState *dbdma) 540 { 541 qemu_bh_schedule(dbdma_bh); 542 } 543 544 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, 545 DBDMA_rw rw, DBDMA_flush flush, 546 void *opaque) 547 { 548 DBDMAState *s = dbdma; 549 DBDMA_channel *ch = &s->channels[nchan]; 550 551 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); 552 553 ch->irq = irq; 554 ch->channel = nchan; 555 ch->rw = rw; 556 ch->flush = flush; 557 ch->io.opaque = opaque; 558 ch->io.channel = ch; 559 } 560 561 static void 562 dbdma_control_write(DBDMA_channel *ch) 563 { 564 uint16_t mask, value; 565 uint32_t status; 566 567 mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff; 568 value = ch->regs[DBDMA_CONTROL] & 0xffff; 569 570 value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT); 571 572 status = ch->regs[DBDMA_STATUS]; 573 574 status = (value & mask) | (status & ~mask); 575 576 if (status & WAKE) 577 status |= ACTIVE; 578 if (status & RUN) { 579 status |= ACTIVE; 580 status &= ~DEAD; 581 } 582 if (status & PAUSE) 583 status &= ~ACTIVE; 584 if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) { 585 /* RUN is cleared */ 586 status &= ~(ACTIVE|DEAD); 587 if ((status & FLUSH) && ch->flush) { 588 ch->flush(&ch->io); 589 status &= ~FLUSH; 590 } 591 } 592 593 DBDMA_DPRINTF(" status 0x%08x\n", status); 594 595 ch->regs[DBDMA_STATUS] = status; 596 597 if (status & ACTIVE) 598 qemu_bh_schedule(dbdma_bh); 599 if ((status & FLUSH) && ch->flush) 600 ch->flush(&ch->io); 601 } 602 603 static void dbdma_write(void *opaque, hwaddr addr, 604 uint64_t value, unsigned size) 605 { 606 int channel = addr >> DBDMA_CHANNEL_SHIFT; 607 DBDMAState *s = opaque; 608 DBDMA_channel *ch = &s->channels[channel]; 609 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; 610 611 DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", 612 addr, value); 613 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", 614 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); 615 616 /* cmdptr cannot be modified if channel is ACTIVE */ 617 618 if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) { 619 return; 620 } 621 622 ch->regs[reg] = value; 623 624 switch(reg) { 625 case DBDMA_CONTROL: 626 dbdma_control_write(ch); 627 break; 628 case DBDMA_CMDPTR_LO: 629 /* 16-byte aligned */ 630 ch->regs[DBDMA_CMDPTR_LO] &= ~0xf; 631 dbdma_cmdptr_load(ch); 632 break; 633 case DBDMA_STATUS: 634 case DBDMA_INTR_SEL: 635 case DBDMA_BRANCH_SEL: 636 case DBDMA_WAIT_SEL: 637 /* nothing to do */ 638 break; 639 case DBDMA_XFER_MODE: 640 case DBDMA_CMDPTR_HI: 641 case DBDMA_DATA2PTR_HI: 642 case DBDMA_DATA2PTR_LO: 643 case DBDMA_ADDRESS_HI: 644 case DBDMA_BRANCH_ADDR_HI: 645 case DBDMA_RES1: 646 case DBDMA_RES2: 647 case DBDMA_RES3: 648 case DBDMA_RES4: 649 /* unused */ 650 break; 651 } 652 } 653 654 static uint64_t dbdma_read(void *opaque, hwaddr addr, 655 unsigned size) 656 { 657 uint32_t value; 658 int channel = addr >> DBDMA_CHANNEL_SHIFT; 659 DBDMAState *s = opaque; 660 DBDMA_channel *ch = &s->channels[channel]; 661 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; 662 663 value = ch->regs[reg]; 664 665 DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value); 666 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", 667 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); 668 669 switch(reg) { 670 case DBDMA_CONTROL: 671 value = 0; 672 break; 673 case DBDMA_STATUS: 674 case DBDMA_CMDPTR_LO: 675 case DBDMA_INTR_SEL: 676 case DBDMA_BRANCH_SEL: 677 case DBDMA_WAIT_SEL: 678 /* nothing to do */ 679 break; 680 case DBDMA_XFER_MODE: 681 case DBDMA_CMDPTR_HI: 682 case DBDMA_DATA2PTR_HI: 683 case DBDMA_DATA2PTR_LO: 684 case DBDMA_ADDRESS_HI: 685 case DBDMA_BRANCH_ADDR_HI: 686 /* unused */ 687 value = 0; 688 break; 689 case DBDMA_RES1: 690 case DBDMA_RES2: 691 case DBDMA_RES3: 692 case DBDMA_RES4: 693 /* reserved */ 694 break; 695 } 696 697 return value; 698 } 699 700 static const MemoryRegionOps dbdma_ops = { 701 .read = dbdma_read, 702 .write = dbdma_write, 703 .endianness = DEVICE_LITTLE_ENDIAN, 704 .valid = { 705 .min_access_size = 4, 706 .max_access_size = 4, 707 }, 708 }; 709 710 static const VMStateDescription vmstate_dbdma_channel = { 711 .name = "dbdma_channel", 712 .version_id = 0, 713 .minimum_version_id = 0, 714 .minimum_version_id_old = 0, 715 .fields = (VMStateField[]) { 716 VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS), 717 VMSTATE_END_OF_LIST() 718 } 719 }; 720 721 static const VMStateDescription vmstate_dbdma = { 722 .name = "dbdma", 723 .version_id = 2, 724 .minimum_version_id = 2, 725 .minimum_version_id_old = 2, 726 .fields = (VMStateField[]) { 727 VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1, 728 vmstate_dbdma_channel, DBDMA_channel), 729 VMSTATE_END_OF_LIST() 730 } 731 }; 732 733 static void dbdma_reset(void *opaque) 734 { 735 DBDMAState *s = opaque; 736 int i; 737 738 for (i = 0; i < DBDMA_CHANNELS; i++) 739 memset(s->channels[i].regs, 0, DBDMA_SIZE); 740 } 741 742 void* DBDMA_init (MemoryRegion **dbdma_mem) 743 { 744 DBDMAState *s; 745 746 s = g_malloc0(sizeof(DBDMAState)); 747 748 memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000); 749 *dbdma_mem = &s->mem; 750 vmstate_register(NULL, -1, &vmstate_dbdma, s); 751 qemu_register_reset(dbdma_reset, s); 752 753 dbdma_bh = qemu_bh_new(DBDMA_run_bh, s); 754 755 return s; 756 } 757