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 ch->processing = 0; 279 if ((ch->regs[DBDMA_STATUS] & RUN) && 280 (ch->regs[DBDMA_STATUS] & ACTIVE)) 281 channel_run(ch); 282 } 283 284 static void start_output(DBDMA_channel *ch, int key, uint32_t addr, 285 uint16_t req_count, int is_last) 286 { 287 DBDMA_DPRINTF("start_output\n"); 288 289 /* KEY_REGS, KEY_DEVICE and KEY_STREAM 290 * are not implemented in the mac-io chip 291 */ 292 293 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); 294 if (!addr || key > KEY_STREAM3) { 295 kill_channel(ch); 296 return; 297 } 298 299 ch->io.addr = addr; 300 ch->io.len = req_count; 301 ch->io.is_last = is_last; 302 ch->io.dma_end = dbdma_end; 303 ch->io.is_dma_out = 1; 304 ch->processing = 1; 305 if (ch->rw) { 306 ch->rw(&ch->io); 307 } 308 } 309 310 static void start_input(DBDMA_channel *ch, int key, uint32_t addr, 311 uint16_t req_count, int is_last) 312 { 313 DBDMA_DPRINTF("start_input\n"); 314 315 /* KEY_REGS, KEY_DEVICE and KEY_STREAM 316 * are not implemented in the mac-io chip 317 */ 318 319 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); 320 if (!addr || key > KEY_STREAM3) { 321 kill_channel(ch); 322 return; 323 } 324 325 ch->io.addr = addr; 326 ch->io.len = req_count; 327 ch->io.is_last = is_last; 328 ch->io.dma_end = dbdma_end; 329 ch->io.is_dma_out = 0; 330 ch->processing = 1; 331 if (ch->rw) { 332 ch->rw(&ch->io); 333 } 334 } 335 336 static void load_word(DBDMA_channel *ch, int key, uint32_t addr, 337 uint16_t len) 338 { 339 dbdma_cmd *current = &ch->current; 340 uint32_t val; 341 342 DBDMA_DPRINTF("load_word\n"); 343 344 /* only implements KEY_SYSTEM */ 345 346 if (key != KEY_SYSTEM) { 347 printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key); 348 kill_channel(ch); 349 return; 350 } 351 352 cpu_physical_memory_read(addr, &val, len); 353 354 if (len == 2) 355 val = (val << 16) | (current->cmd_dep & 0x0000ffff); 356 else if (len == 1) 357 val = (val << 24) | (current->cmd_dep & 0x00ffffff); 358 359 current->cmd_dep = val; 360 361 if (conditional_wait(ch)) 362 goto wait; 363 364 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); 365 dbdma_cmdptr_save(ch); 366 ch->regs[DBDMA_STATUS] &= ~FLUSH; 367 368 conditional_interrupt(ch); 369 next(ch); 370 371 wait: 372 DBDMA_kick(dbdma_from_ch(ch)); 373 } 374 375 static void store_word(DBDMA_channel *ch, int key, uint32_t addr, 376 uint16_t len) 377 { 378 dbdma_cmd *current = &ch->current; 379 uint32_t val; 380 381 DBDMA_DPRINTF("store_word\n"); 382 383 /* only implements KEY_SYSTEM */ 384 385 if (key != KEY_SYSTEM) { 386 printf("DBDMA: STORE_WORD, unimplemented key %x\n", key); 387 kill_channel(ch); 388 return; 389 } 390 391 val = current->cmd_dep; 392 if (len == 2) 393 val >>= 16; 394 else if (len == 1) 395 val >>= 24; 396 397 cpu_physical_memory_write(addr, &val, len); 398 399 if (conditional_wait(ch)) 400 goto wait; 401 402 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); 403 dbdma_cmdptr_save(ch); 404 ch->regs[DBDMA_STATUS] &= ~FLUSH; 405 406 conditional_interrupt(ch); 407 next(ch); 408 409 wait: 410 DBDMA_kick(dbdma_from_ch(ch)); 411 } 412 413 static void nop(DBDMA_channel *ch) 414 { 415 dbdma_cmd *current = &ch->current; 416 417 if (conditional_wait(ch)) 418 goto wait; 419 420 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]); 421 dbdma_cmdptr_save(ch); 422 423 conditional_interrupt(ch); 424 conditional_branch(ch); 425 426 wait: 427 DBDMA_kick(dbdma_from_ch(ch)); 428 } 429 430 static void stop(DBDMA_channel *ch) 431 { 432 ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH); 433 434 /* the stop command does not increment command pointer */ 435 } 436 437 static void channel_run(DBDMA_channel *ch) 438 { 439 dbdma_cmd *current = &ch->current; 440 uint16_t cmd, key; 441 uint16_t req_count; 442 uint32_t phy_addr; 443 444 DBDMA_DPRINTF("channel_run\n"); 445 dump_dbdma_cmd(current); 446 447 /* clear WAKE flag at command fetch */ 448 449 ch->regs[DBDMA_STATUS] &= ~WAKE; 450 451 cmd = le16_to_cpu(current->command) & COMMAND_MASK; 452 453 switch (cmd) { 454 case DBDMA_NOP: 455 nop(ch); 456 return; 457 458 case DBDMA_STOP: 459 stop(ch); 460 return; 461 } 462 463 key = le16_to_cpu(current->command) & 0x0700; 464 req_count = le16_to_cpu(current->req_count); 465 phy_addr = le32_to_cpu(current->phy_addr); 466 467 if (key == KEY_STREAM4) { 468 printf("command %x, invalid key 4\n", cmd); 469 kill_channel(ch); 470 return; 471 } 472 473 switch (cmd) { 474 case OUTPUT_MORE: 475 start_output(ch, key, phy_addr, req_count, 0); 476 return; 477 478 case OUTPUT_LAST: 479 start_output(ch, key, phy_addr, req_count, 1); 480 return; 481 482 case INPUT_MORE: 483 start_input(ch, key, phy_addr, req_count, 0); 484 return; 485 486 case INPUT_LAST: 487 start_input(ch, key, phy_addr, req_count, 1); 488 return; 489 } 490 491 if (key < KEY_REGS) { 492 printf("command %x, invalid key %x\n", cmd, key); 493 key = KEY_SYSTEM; 494 } 495 496 /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits 497 * and BRANCH is invalid 498 */ 499 500 req_count = req_count & 0x0007; 501 if (req_count & 0x4) { 502 req_count = 4; 503 phy_addr &= ~3; 504 } else if (req_count & 0x2) { 505 req_count = 2; 506 phy_addr &= ~1; 507 } else 508 req_count = 1; 509 510 switch (cmd) { 511 case LOAD_WORD: 512 load_word(ch, key, phy_addr, req_count); 513 return; 514 515 case STORE_WORD: 516 store_word(ch, key, phy_addr, req_count); 517 return; 518 } 519 } 520 521 static void DBDMA_run(DBDMAState *s) 522 { 523 int channel; 524 525 for (channel = 0; channel < DBDMA_CHANNELS; channel++) { 526 DBDMA_channel *ch = &s->channels[channel]; 527 uint32_t status = ch->regs[DBDMA_STATUS]; 528 if (!ch->processing && (status & RUN) && (status & ACTIVE)) { 529 channel_run(ch); 530 } 531 } 532 } 533 534 static void DBDMA_run_bh(void *opaque) 535 { 536 DBDMAState *s = opaque; 537 538 DBDMA_DPRINTF("DBDMA_run_bh\n"); 539 540 DBDMA_run(s); 541 } 542 543 void DBDMA_kick(DBDMAState *dbdma) 544 { 545 qemu_bh_schedule(dbdma->bh); 546 } 547 548 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, 549 DBDMA_rw rw, DBDMA_flush flush, 550 void *opaque) 551 { 552 DBDMAState *s = dbdma; 553 DBDMA_channel *ch = &s->channels[nchan]; 554 555 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); 556 557 ch->irq = irq; 558 ch->channel = nchan; 559 ch->rw = rw; 560 ch->flush = flush; 561 ch->io.opaque = opaque; 562 ch->io.channel = ch; 563 } 564 565 static void 566 dbdma_control_write(DBDMA_channel *ch) 567 { 568 uint16_t mask, value; 569 uint32_t status; 570 571 mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff; 572 value = ch->regs[DBDMA_CONTROL] & 0xffff; 573 574 value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT); 575 576 status = ch->regs[DBDMA_STATUS]; 577 578 status = (value & mask) | (status & ~mask); 579 580 if (status & WAKE) 581 status |= ACTIVE; 582 if (status & RUN) { 583 status |= ACTIVE; 584 status &= ~DEAD; 585 } 586 if (status & PAUSE) 587 status &= ~ACTIVE; 588 if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) { 589 /* RUN is cleared */ 590 status &= ~(ACTIVE|DEAD); 591 if ((status & FLUSH) && ch->flush) { 592 ch->flush(&ch->io); 593 status &= ~FLUSH; 594 } 595 } 596 597 DBDMA_DPRINTF(" status 0x%08x\n", status); 598 599 ch->regs[DBDMA_STATUS] = status; 600 601 if (status & ACTIVE) { 602 DBDMA_kick(dbdma_from_ch(ch)); 603 } 604 if ((status & FLUSH) && ch->flush) { 605 ch->flush(&ch->io); 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_channel = { 717 .name = "dbdma_channel", 718 .version_id = 0, 719 .minimum_version_id = 0, 720 .minimum_version_id_old = 0, 721 .fields = (VMStateField[]) { 722 VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS), 723 VMSTATE_END_OF_LIST() 724 } 725 }; 726 727 static const VMStateDescription vmstate_dbdma = { 728 .name = "dbdma", 729 .version_id = 2, 730 .minimum_version_id = 2, 731 .minimum_version_id_old = 2, 732 .fields = (VMStateField[]) { 733 VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1, 734 vmstate_dbdma_channel, DBDMA_channel), 735 VMSTATE_END_OF_LIST() 736 } 737 }; 738 739 static void dbdma_reset(void *opaque) 740 { 741 DBDMAState *s = opaque; 742 int i; 743 744 for (i = 0; i < DBDMA_CHANNELS; i++) 745 memset(s->channels[i].regs, 0, DBDMA_SIZE); 746 } 747 748 void* DBDMA_init (MemoryRegion **dbdma_mem) 749 { 750 DBDMAState *s; 751 752 s = g_malloc0(sizeof(DBDMAState)); 753 754 memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000); 755 *dbdma_mem = &s->mem; 756 vmstate_register(NULL, -1, &vmstate_dbdma, s); 757 qemu_register_reset(dbdma_reset, s); 758 759 s->bh = qemu_bh_new(DBDMA_run_bh, s); 760 761 return s; 762 } 763