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