qemu/hw/misc/macio/mac_dbdma.c
<<
>>
Prefs
   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
  40#include "qemu/osdep.h"
  41#include "hw/irq.h"
  42#include "hw/ppc/mac_dbdma.h"
  43#include "migration/vmstate.h"
  44#include "qemu/main-loop.h"
  45#include "qemu/module.h"
  46#include "qemu/log.h"
  47#include "sysemu/dma.h"
  48
  49/* debug DBDMA */
  50#define DEBUG_DBDMA 0
  51#define DEBUG_DBDMA_CHANMASK ((1ull << DBDMA_CHANNELS) - 1)
  52
  53#define DBDMA_DPRINTF(fmt, ...) do { \
  54    if (DEBUG_DBDMA) { \
  55        printf("DBDMA: " fmt , ## __VA_ARGS__); \
  56    } \
  57} while (0)
  58
  59#define DBDMA_DPRINTFCH(ch, fmt, ...) do { \
  60    if (DEBUG_DBDMA) { \
  61        if ((1ul << (ch)->channel) & DEBUG_DBDMA_CHANMASK) { \
  62            printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \
  63        } \
  64    } \
  65} while (0)
  66
  67/*
  68 */
  69
  70static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
  71{
  72    return container_of(ch, DBDMAState, channels[ch->channel]);
  73}
  74
  75#if DEBUG_DBDMA
  76static void dump_dbdma_cmd(DBDMA_channel *ch, dbdma_cmd *cmd)
  77{
  78    DBDMA_DPRINTFCH(ch, "dbdma_cmd %p\n", cmd);
  79    DBDMA_DPRINTFCH(ch, "    req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
  80    DBDMA_DPRINTFCH(ch, "    command 0x%04x\n", le16_to_cpu(cmd->command));
  81    DBDMA_DPRINTFCH(ch, "    phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
  82    DBDMA_DPRINTFCH(ch, "    cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
  83    DBDMA_DPRINTFCH(ch, "    res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
  84    DBDMA_DPRINTFCH(ch, "    xfer_status 0x%04x\n",
  85                    le16_to_cpu(cmd->xfer_status));
  86}
  87#else
  88static void dump_dbdma_cmd(DBDMA_channel *ch, dbdma_cmd *cmd)
  89{
  90}
  91#endif
  92static void dbdma_cmdptr_load(DBDMA_channel *ch)
  93{
  94    DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_load 0x%08x\n",
  95                    ch->regs[DBDMA_CMDPTR_LO]);
  96    dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
  97                    &ch->current, sizeof(dbdma_cmd));
  98}
  99
 100static void dbdma_cmdptr_save(DBDMA_channel *ch)
 101{
 102    DBDMA_DPRINTFCH(ch, "-> update 0x%08x stat=0x%08x, res=0x%04x\n",
 103                    ch->regs[DBDMA_CMDPTR_LO],
 104                    le16_to_cpu(ch->current.xfer_status),
 105                    le16_to_cpu(ch->current.res_count));
 106    dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
 107                     &ch->current, sizeof(dbdma_cmd));
 108}
 109
 110static void kill_channel(DBDMA_channel *ch)
 111{
 112    DBDMA_DPRINTFCH(ch, "kill_channel\n");
 113
 114    ch->regs[DBDMA_STATUS] |= DEAD;
 115    ch->regs[DBDMA_STATUS] &= ~ACTIVE;
 116
 117    qemu_irq_raise(ch->irq);
 118}
 119
 120static void conditional_interrupt(DBDMA_channel *ch)
 121{
 122    dbdma_cmd *current = &ch->current;
 123    uint16_t intr;
 124    uint16_t sel_mask, sel_value;
 125    uint32_t status;
 126    int cond;
 127
 128    DBDMA_DPRINTFCH(ch, "%s\n", __func__);
 129
 130    intr = le16_to_cpu(current->command) & INTR_MASK;
 131
 132    switch(intr) {
 133    case INTR_NEVER:  /* don't interrupt */
 134        return;
 135    case INTR_ALWAYS: /* always interrupt */
 136        qemu_irq_raise(ch->irq);
 137        DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
 138        return;
 139    }
 140
 141    status = ch->regs[DBDMA_STATUS] & DEVSTAT;
 142
 143    sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
 144    sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
 145
 146    cond = (status & sel_mask) == (sel_value & sel_mask);
 147
 148    switch(intr) {
 149    case INTR_IFSET:  /* intr if condition bit is 1 */
 150        if (cond) {
 151            qemu_irq_raise(ch->irq);
 152            DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
 153        }
 154        return;
 155    case INTR_IFCLR:  /* intr if condition bit is 0 */
 156        if (!cond) {
 157            qemu_irq_raise(ch->irq);
 158            DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
 159        }
 160        return;
 161    }
 162}
 163
 164static int conditional_wait(DBDMA_channel *ch)
 165{
 166    dbdma_cmd *current = &ch->current;
 167    uint16_t wait;
 168    uint16_t sel_mask, sel_value;
 169    uint32_t status;
 170    int cond;
 171    int res = 0;
 172
 173    wait = le16_to_cpu(current->command) & WAIT_MASK;
 174    switch(wait) {
 175    case WAIT_NEVER:  /* don't wait */
 176        return 0;
 177    case WAIT_ALWAYS: /* always wait */
 178        DBDMA_DPRINTFCH(ch, "  [WAIT_ALWAYS]\n");
 179        return 1;
 180    }
 181
 182    status = ch->regs[DBDMA_STATUS] & DEVSTAT;
 183
 184    sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
 185    sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
 186
 187    cond = (status & sel_mask) == (sel_value & sel_mask);
 188
 189    switch(wait) {
 190    case WAIT_IFSET:  /* wait if condition bit is 1 */
 191        if (cond) {
 192            res = 1;
 193        }
 194        DBDMA_DPRINTFCH(ch, "  [WAIT_IFSET=%d]\n", res);
 195        break;
 196    case WAIT_IFCLR:  /* wait if condition bit is 0 */
 197        if (!cond) {
 198            res = 1;
 199        }
 200        DBDMA_DPRINTFCH(ch, "  [WAIT_IFCLR=%d]\n", res);
 201        break;
 202    }
 203    return res;
 204}
 205
 206static void next(DBDMA_channel *ch)
 207{
 208    uint32_t cp;
 209
 210    ch->regs[DBDMA_STATUS] &= ~BT;
 211
 212    cp = ch->regs[DBDMA_CMDPTR_LO];
 213    ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
 214    dbdma_cmdptr_load(ch);
 215}
 216
 217static void branch(DBDMA_channel *ch)
 218{
 219    dbdma_cmd *current = &ch->current;
 220
 221    ch->regs[DBDMA_CMDPTR_LO] = le32_to_cpu(current->cmd_dep);
 222    ch->regs[DBDMA_STATUS] |= BT;
 223    dbdma_cmdptr_load(ch);
 224}
 225
 226static void conditional_branch(DBDMA_channel *ch)
 227{
 228    dbdma_cmd *current = &ch->current;
 229    uint16_t br;
 230    uint16_t sel_mask, sel_value;
 231    uint32_t status;
 232    int cond;
 233
 234    /* check if we must branch */
 235
 236    br = le16_to_cpu(current->command) & BR_MASK;
 237
 238    switch(br) {
 239    case BR_NEVER:  /* don't branch */
 240        next(ch);
 241        return;
 242    case BR_ALWAYS: /* always branch */
 243        DBDMA_DPRINTFCH(ch, "  [BR_ALWAYS]\n");
 244        branch(ch);
 245        return;
 246    }
 247
 248    status = ch->regs[DBDMA_STATUS] & DEVSTAT;
 249
 250    sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
 251    sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
 252
 253    cond = (status & sel_mask) == (sel_value & sel_mask);
 254
 255    switch(br) {
 256    case BR_IFSET:  /* branch if condition bit is 1 */
 257        if (cond) {
 258            DBDMA_DPRINTFCH(ch, "  [BR_IFSET = 1]\n");
 259            branch(ch);
 260        } else {
 261            DBDMA_DPRINTFCH(ch, "  [BR_IFSET = 0]\n");
 262            next(ch);
 263        }
 264        return;
 265    case BR_IFCLR:  /* branch if condition bit is 0 */
 266        if (!cond) {
 267            DBDMA_DPRINTFCH(ch, "  [BR_IFCLR = 1]\n");
 268            branch(ch);
 269        } else {
 270            DBDMA_DPRINTFCH(ch, "  [BR_IFCLR = 0]\n");
 271            next(ch);
 272        }
 273        return;
 274    }
 275}
 276
 277static void channel_run(DBDMA_channel *ch);
 278
 279static void dbdma_end(DBDMA_io *io)
 280{
 281    DBDMA_channel *ch = io->channel;
 282    dbdma_cmd *current = &ch->current;
 283
 284    DBDMA_DPRINTFCH(ch, "%s\n", __func__);
 285
 286    if (conditional_wait(ch))
 287        goto wait;
 288
 289    current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
 290    current->res_count = cpu_to_le16(io->len);
 291    dbdma_cmdptr_save(ch);
 292    if (io->is_last)
 293        ch->regs[DBDMA_STATUS] &= ~FLUSH;
 294
 295    conditional_interrupt(ch);
 296    conditional_branch(ch);
 297
 298wait:
 299    /* Indicate that we're ready for a new DMA round */
 300    ch->io.processing = false;
 301
 302    if ((ch->regs[DBDMA_STATUS] & RUN) &&
 303        (ch->regs[DBDMA_STATUS] & ACTIVE))
 304        channel_run(ch);
 305}
 306
 307static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
 308                        uint16_t req_count, int is_last)
 309{
 310    DBDMA_DPRINTFCH(ch, "start_output\n");
 311
 312    /* KEY_REGS, KEY_DEVICE and KEY_STREAM
 313     * are not implemented in the mac-io chip
 314     */
 315
 316    DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
 317    if (!addr || key > KEY_STREAM3) {
 318        kill_channel(ch);
 319        return;
 320    }
 321
 322    ch->io.addr = addr;
 323    ch->io.len = req_count;
 324    ch->io.is_last = is_last;
 325    ch->io.dma_end = dbdma_end;
 326    ch->io.is_dma_out = 1;
 327    ch->io.processing = true;
 328    if (ch->rw) {
 329        ch->rw(&ch->io);
 330    }
 331}
 332
 333static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
 334                       uint16_t req_count, int is_last)
 335{
 336    DBDMA_DPRINTFCH(ch, "start_input\n");
 337
 338    /* KEY_REGS, KEY_DEVICE and KEY_STREAM
 339     * are not implemented in the mac-io chip
 340     */
 341
 342    DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
 343    if (!addr || key > KEY_STREAM3) {
 344        kill_channel(ch);
 345        return;
 346    }
 347
 348    ch->io.addr = addr;
 349    ch->io.len = req_count;
 350    ch->io.is_last = is_last;
 351    ch->io.dma_end = dbdma_end;
 352    ch->io.is_dma_out = 0;
 353    ch->io.processing = true;
 354    if (ch->rw) {
 355        ch->rw(&ch->io);
 356    }
 357}
 358
 359static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
 360                     uint16_t len)
 361{
 362    dbdma_cmd *current = &ch->current;
 363
 364    DBDMA_DPRINTFCH(ch, "load_word %d bytes, addr=%08x\n", len, addr);
 365
 366    /* only implements KEY_SYSTEM */
 367
 368    if (key != KEY_SYSTEM) {
 369        printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
 370        kill_channel(ch);
 371        return;
 372    }
 373
 374    dma_memory_read(&address_space_memory, addr, &current->cmd_dep, len);
 375
 376    if (conditional_wait(ch))
 377        goto wait;
 378
 379    current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
 380    dbdma_cmdptr_save(ch);
 381    ch->regs[DBDMA_STATUS] &= ~FLUSH;
 382
 383    conditional_interrupt(ch);
 384    next(ch);
 385
 386wait:
 387    DBDMA_kick(dbdma_from_ch(ch));
 388}
 389
 390static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
 391                      uint16_t len)
 392{
 393    dbdma_cmd *current = &ch->current;
 394
 395    DBDMA_DPRINTFCH(ch, "store_word %d bytes, addr=%08x pa=%x\n",
 396                    len, addr, le32_to_cpu(current->cmd_dep));
 397
 398    /* only implements KEY_SYSTEM */
 399
 400    if (key != KEY_SYSTEM) {
 401        printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
 402        kill_channel(ch);
 403        return;
 404    }
 405
 406    dma_memory_write(&address_space_memory, addr, &current->cmd_dep, len);
 407
 408    if (conditional_wait(ch))
 409        goto wait;
 410
 411    current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
 412    dbdma_cmdptr_save(ch);
 413    ch->regs[DBDMA_STATUS] &= ~FLUSH;
 414
 415    conditional_interrupt(ch);
 416    next(ch);
 417
 418wait:
 419    DBDMA_kick(dbdma_from_ch(ch));
 420}
 421
 422static void nop(DBDMA_channel *ch)
 423{
 424    dbdma_cmd *current = &ch->current;
 425
 426    if (conditional_wait(ch))
 427        goto wait;
 428
 429    current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
 430    dbdma_cmdptr_save(ch);
 431
 432    conditional_interrupt(ch);
 433    conditional_branch(ch);
 434
 435wait:
 436    DBDMA_kick(dbdma_from_ch(ch));
 437}
 438
 439static void stop(DBDMA_channel *ch)
 440{
 441    ch->regs[DBDMA_STATUS] &= ~(ACTIVE);
 442
 443    /* the stop command does not increment command pointer */
 444}
 445
 446static void channel_run(DBDMA_channel *ch)
 447{
 448    dbdma_cmd *current = &ch->current;
 449    uint16_t cmd, key;
 450    uint16_t req_count;
 451    uint32_t phy_addr;
 452
 453    DBDMA_DPRINTFCH(ch, "channel_run\n");
 454    dump_dbdma_cmd(ch, current);
 455
 456    /* clear WAKE flag at command fetch */
 457
 458    ch->regs[DBDMA_STATUS] &= ~WAKE;
 459
 460    cmd = le16_to_cpu(current->command) & COMMAND_MASK;
 461
 462    switch (cmd) {
 463    case DBDMA_NOP:
 464        nop(ch);
 465        return;
 466
 467    case DBDMA_STOP:
 468        stop(ch);
 469        return;
 470    }
 471
 472    key = le16_to_cpu(current->command) & 0x0700;
 473    req_count = le16_to_cpu(current->req_count);
 474    phy_addr = le32_to_cpu(current->phy_addr);
 475
 476    if (key == KEY_STREAM4) {
 477        printf("command %x, invalid key 4\n", cmd);
 478        kill_channel(ch);
 479        return;
 480    }
 481
 482    switch (cmd) {
 483    case OUTPUT_MORE:
 484        DBDMA_DPRINTFCH(ch, "* OUTPUT_MORE *\n");
 485        start_output(ch, key, phy_addr, req_count, 0);
 486        return;
 487
 488    case OUTPUT_LAST:
 489        DBDMA_DPRINTFCH(ch, "* OUTPUT_LAST *\n");
 490        start_output(ch, key, phy_addr, req_count, 1);
 491        return;
 492
 493    case INPUT_MORE:
 494        DBDMA_DPRINTFCH(ch, "* INPUT_MORE *\n");
 495        start_input(ch, key, phy_addr, req_count, 0);
 496        return;
 497
 498    case INPUT_LAST:
 499        DBDMA_DPRINTFCH(ch, "* INPUT_LAST *\n");
 500        start_input(ch, key, phy_addr, req_count, 1);
 501        return;
 502    }
 503
 504    if (key < KEY_REGS) {
 505        printf("command %x, invalid key %x\n", cmd, key);
 506        key = KEY_SYSTEM;
 507    }
 508
 509    /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
 510     * and BRANCH is invalid
 511     */
 512
 513    req_count = req_count & 0x0007;
 514    if (req_count & 0x4) {
 515        req_count = 4;
 516        phy_addr &= ~3;
 517    } else if (req_count & 0x2) {
 518        req_count = 2;
 519        phy_addr &= ~1;
 520    } else
 521        req_count = 1;
 522
 523    switch (cmd) {
 524    case LOAD_WORD:
 525        DBDMA_DPRINTFCH(ch, "* LOAD_WORD *\n");
 526        load_word(ch, key, phy_addr, req_count);
 527        return;
 528
 529    case STORE_WORD:
 530        DBDMA_DPRINTFCH(ch, "* STORE_WORD *\n");
 531        store_word(ch, key, phy_addr, req_count);
 532        return;
 533    }
 534}
 535
 536static void DBDMA_run(DBDMAState *s)
 537{
 538    int channel;
 539
 540    for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
 541        DBDMA_channel *ch = &s->channels[channel];
 542        uint32_t status = ch->regs[DBDMA_STATUS];
 543        if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) {
 544            channel_run(ch);
 545        }
 546    }
 547}
 548
 549static void DBDMA_run_bh(void *opaque)
 550{
 551    DBDMAState *s = opaque;
 552
 553    DBDMA_DPRINTF("-> DBDMA_run_bh\n");
 554    DBDMA_run(s);
 555    DBDMA_DPRINTF("<- DBDMA_run_bh\n");
 556}
 557
 558void DBDMA_kick(DBDMAState *dbdma)
 559{
 560    qemu_bh_schedule(dbdma->bh);
 561}
 562
 563void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
 564                            DBDMA_rw rw, DBDMA_flush flush,
 565                            void *opaque)
 566{
 567    DBDMAState *s = dbdma;
 568    DBDMA_channel *ch = &s->channels[nchan];
 569
 570    DBDMA_DPRINTFCH(ch, "DBDMA_register_channel 0x%x\n", nchan);
 571
 572    assert(rw);
 573    assert(flush);
 574
 575    ch->irq = irq;
 576    ch->rw = rw;
 577    ch->flush = flush;
 578    ch->io.opaque = opaque;
 579}
 580
 581static void dbdma_control_write(DBDMA_channel *ch)
 582{
 583    uint16_t mask, value;
 584    uint32_t status;
 585    bool do_flush = false;
 586
 587    mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
 588    value = ch->regs[DBDMA_CONTROL] & 0xffff;
 589
 590    /* This is the status register which we'll update
 591     * appropriately and store back
 592     */
 593    status = ch->regs[DBDMA_STATUS];
 594
 595    /* RUN and PAUSE are bits under SW control only
 596     * FLUSH and WAKE are set by SW and cleared by HW
 597     * DEAD, ACTIVE and BT are only under HW control
 598     *
 599     * We handle ACTIVE separately at the end of the
 600     * logic to ensure all cases are covered.
 601     */
 602
 603    /* Setting RUN will tentatively activate the channel
 604     */
 605    if ((mask & RUN) && (value & RUN)) {
 606        status |= RUN;
 607        DBDMA_DPRINTFCH(ch, " Setting RUN !\n");
 608    }
 609
 610    /* Clearing RUN 1->0 will stop the channel */
 611    if ((mask & RUN) && !(value & RUN)) {
 612        /* This has the side effect of clearing the DEAD bit */
 613        status &= ~(DEAD | RUN);
 614        DBDMA_DPRINTFCH(ch, " Clearing RUN !\n");
 615    }
 616
 617    /* Setting WAKE wakes up an idle channel if it's running
 618     *
 619     * Note: The doc doesn't say so but assume that only works
 620     * on a channel whose RUN bit is set.
 621     *
 622     * We set WAKE in status, it's not terribly useful as it will
 623     * be cleared on the next command fetch but it seems to mimmic
 624     * the HW behaviour and is useful for the way we handle
 625     * ACTIVE further down.
 626     */
 627    if ((mask & WAKE) && (value & WAKE) && (status & RUN)) {
 628        status |= WAKE;
 629        DBDMA_DPRINTFCH(ch, " Setting WAKE !\n");
 630    }
 631
 632    /* PAUSE being set will deactivate (or prevent activation)
 633     * of the channel. We just copy it over for now, ACTIVE will
 634     * be re-evaluated later.
 635     */
 636    if (mask & PAUSE) {
 637        status = (status & ~PAUSE) | (value & PAUSE);
 638        DBDMA_DPRINTFCH(ch, " %sing PAUSE !\n",
 639                        (value & PAUSE) ? "sett" : "clear");
 640    }
 641
 642    /* FLUSH is its own thing */
 643    if ((mask & FLUSH) && (value & FLUSH))  {
 644        DBDMA_DPRINTFCH(ch, " Setting FLUSH !\n");
 645        /* We set flush directly in the status register, we do *NOT*
 646         * set it in "status" so that it gets naturally cleared when
 647         * we update the status register further down. That way it
 648         * will be set only during the HW flush operation so it is
 649         * visible to any completions happening during that time.
 650         */
 651        ch->regs[DBDMA_STATUS] |= FLUSH;
 652        do_flush = true;
 653    }
 654
 655    /* If either RUN or PAUSE is clear, so should ACTIVE be,
 656     * otherwise, ACTIVE will be set if we modified RUN, PAUSE or
 657     * set WAKE. That means that PAUSE was just cleared, RUN was
 658     * just set or WAKE was just set.
 659     */
 660    if ((status & PAUSE) || !(status & RUN)) {
 661        status &= ~ACTIVE;
 662        DBDMA_DPRINTFCH(ch, "  -> ACTIVE down !\n");
 663
 664        /* We stopped processing, we want the underlying HW command
 665         * to complete *before* we clear the ACTIVE bit. Otherwise
 666         * we can get into a situation where the command status will
 667         * have RUN or ACTIVE not set which is going to confuse the
 668         * MacOS driver.
 669         */
 670        do_flush = true;
 671    } else if (mask & (RUN | PAUSE)) {
 672        status |= ACTIVE;
 673        DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
 674    } else if ((mask & WAKE) && (value & WAKE)) {
 675        status |= ACTIVE;
 676        DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
 677    }
 678
 679    DBDMA_DPRINTFCH(ch, " new status=0x%08x\n", status);
 680
 681    /* If we need to flush the underlying HW, do it now, this happens
 682     * both on FLUSH commands and when stopping the channel for safety.
 683     */
 684    if (do_flush && ch->flush) {
 685        ch->flush(&ch->io);
 686    }
 687
 688    /* Finally update the status register image */
 689    ch->regs[DBDMA_STATUS] = status;
 690
 691    /* If active, make sure the BH gets to run */
 692    if (status & ACTIVE) {
 693        DBDMA_kick(dbdma_from_ch(ch));
 694    }
 695}
 696
 697static void dbdma_write(void *opaque, hwaddr addr,
 698                        uint64_t value, unsigned size)
 699{
 700    int channel = addr >> DBDMA_CHANNEL_SHIFT;
 701    DBDMAState *s = opaque;
 702    DBDMA_channel *ch = &s->channels[channel];
 703    int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
 704
 705    DBDMA_DPRINTFCH(ch, "writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
 706                    addr, value);
 707    DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
 708                    (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
 709
 710    /* cmdptr cannot be modified if channel is ACTIVE */
 711
 712    if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
 713        return;
 714    }
 715
 716    ch->regs[reg] = value;
 717
 718    switch(reg) {
 719    case DBDMA_CONTROL:
 720        dbdma_control_write(ch);
 721        break;
 722    case DBDMA_CMDPTR_LO:
 723        /* 16-byte aligned */
 724        ch->regs[DBDMA_CMDPTR_LO] &= ~0xf;
 725        dbdma_cmdptr_load(ch);
 726        break;
 727    case DBDMA_STATUS:
 728    case DBDMA_INTR_SEL:
 729    case DBDMA_BRANCH_SEL:
 730    case DBDMA_WAIT_SEL:
 731        /* nothing to do */
 732        break;
 733    case DBDMA_XFER_MODE:
 734    case DBDMA_CMDPTR_HI:
 735    case DBDMA_DATA2PTR_HI:
 736    case DBDMA_DATA2PTR_LO:
 737    case DBDMA_ADDRESS_HI:
 738    case DBDMA_BRANCH_ADDR_HI:
 739    case DBDMA_RES1:
 740    case DBDMA_RES2:
 741    case DBDMA_RES3:
 742    case DBDMA_RES4:
 743        /* unused */
 744        break;
 745    }
 746}
 747
 748static uint64_t dbdma_read(void *opaque, hwaddr addr,
 749                           unsigned size)
 750{
 751    uint32_t value;
 752    int channel = addr >> DBDMA_CHANNEL_SHIFT;
 753    DBDMAState *s = opaque;
 754    DBDMA_channel *ch = &s->channels[channel];
 755    int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
 756
 757    value = ch->regs[reg];
 758
 759    switch(reg) {
 760    case DBDMA_CONTROL:
 761        value = ch->regs[DBDMA_STATUS];
 762        break;
 763    case DBDMA_STATUS:
 764    case DBDMA_CMDPTR_LO:
 765    case DBDMA_INTR_SEL:
 766    case DBDMA_BRANCH_SEL:
 767    case DBDMA_WAIT_SEL:
 768        /* nothing to do */
 769        break;
 770    case DBDMA_XFER_MODE:
 771    case DBDMA_CMDPTR_HI:
 772    case DBDMA_DATA2PTR_HI:
 773    case DBDMA_DATA2PTR_LO:
 774    case DBDMA_ADDRESS_HI:
 775    case DBDMA_BRANCH_ADDR_HI:
 776        /* unused */
 777        value = 0;
 778        break;
 779    case DBDMA_RES1:
 780    case DBDMA_RES2:
 781    case DBDMA_RES3:
 782    case DBDMA_RES4:
 783        /* reserved */
 784        break;
 785    }
 786
 787    DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
 788    DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
 789                    (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
 790
 791    return value;
 792}
 793
 794static const MemoryRegionOps dbdma_ops = {
 795    .read = dbdma_read,
 796    .write = dbdma_write,
 797    .endianness = DEVICE_LITTLE_ENDIAN,
 798    .valid = {
 799        .min_access_size = 4,
 800        .max_access_size = 4,
 801    },
 802};
 803
 804static const VMStateDescription vmstate_dbdma_io = {
 805    .name = "dbdma_io",
 806    .version_id = 0,
 807    .minimum_version_id = 0,
 808    .fields = (VMStateField[]) {
 809        VMSTATE_UINT64(addr, struct DBDMA_io),
 810        VMSTATE_INT32(len, struct DBDMA_io),
 811        VMSTATE_INT32(is_last, struct DBDMA_io),
 812        VMSTATE_INT32(is_dma_out, struct DBDMA_io),
 813        VMSTATE_BOOL(processing, struct DBDMA_io),
 814        VMSTATE_END_OF_LIST()
 815    }
 816};
 817
 818static const VMStateDescription vmstate_dbdma_cmd = {
 819    .name = "dbdma_cmd",
 820    .version_id = 0,
 821    .minimum_version_id = 0,
 822    .fields = (VMStateField[]) {
 823        VMSTATE_UINT16(req_count, dbdma_cmd),
 824        VMSTATE_UINT16(command, dbdma_cmd),
 825        VMSTATE_UINT32(phy_addr, dbdma_cmd),
 826        VMSTATE_UINT32(cmd_dep, dbdma_cmd),
 827        VMSTATE_UINT16(res_count, dbdma_cmd),
 828        VMSTATE_UINT16(xfer_status, dbdma_cmd),
 829        VMSTATE_END_OF_LIST()
 830    }
 831};
 832
 833static const VMStateDescription vmstate_dbdma_channel = {
 834    .name = "dbdma_channel",
 835    .version_id = 1,
 836    .minimum_version_id = 1,
 837    .fields = (VMStateField[]) {
 838        VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
 839        VMSTATE_STRUCT(io, struct DBDMA_channel, 0, vmstate_dbdma_io, DBDMA_io),
 840        VMSTATE_STRUCT(current, struct DBDMA_channel, 0, vmstate_dbdma_cmd,
 841                       dbdma_cmd),
 842        VMSTATE_END_OF_LIST()
 843    }
 844};
 845
 846static const VMStateDescription vmstate_dbdma = {
 847    .name = "dbdma",
 848    .version_id = 3,
 849    .minimum_version_id = 3,
 850    .fields = (VMStateField[]) {
 851        VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
 852                             vmstate_dbdma_channel, DBDMA_channel),
 853        VMSTATE_END_OF_LIST()
 854    }
 855};
 856
 857static void mac_dbdma_reset(DeviceState *d)
 858{
 859    DBDMAState *s = MAC_DBDMA(d);
 860    int i;
 861
 862    for (i = 0; i < DBDMA_CHANNELS; i++) {
 863        memset(s->channels[i].regs, 0, DBDMA_SIZE);
 864    }
 865}
 866
 867static void dbdma_unassigned_rw(DBDMA_io *io)
 868{
 869    DBDMA_channel *ch = io->channel;
 870    dbdma_cmd *current = &ch->current;
 871    uint16_t cmd;
 872    qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
 873                  __func__, ch->channel);
 874    ch->io.processing = false;
 875
 876    cmd = le16_to_cpu(current->command) & COMMAND_MASK;
 877    if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
 878        cmd == INPUT_MORE || cmd == INPUT_LAST) {
 879        current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
 880        current->res_count = cpu_to_le16(io->len);
 881        dbdma_cmdptr_save(ch);
 882    }
 883}
 884
 885static void dbdma_unassigned_flush(DBDMA_io *io)
 886{
 887    DBDMA_channel *ch = io->channel;
 888    qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
 889                  __func__, ch->channel);
 890}
 891
 892static void mac_dbdma_init(Object *obj)
 893{
 894    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 895    DBDMAState *s = MAC_DBDMA(obj);
 896    int i;
 897
 898    for (i = 0; i < DBDMA_CHANNELS; i++) {
 899        DBDMA_channel *ch = &s->channels[i];
 900
 901        ch->rw = dbdma_unassigned_rw;
 902        ch->flush = dbdma_unassigned_flush;
 903        ch->channel = i;
 904        ch->io.channel = ch;
 905    }
 906
 907    memory_region_init_io(&s->mem, obj, &dbdma_ops, s, "dbdma", 0x1000);
 908    sysbus_init_mmio(sbd, &s->mem);
 909}
 910
 911static void mac_dbdma_realize(DeviceState *dev, Error **errp)
 912{
 913    DBDMAState *s = MAC_DBDMA(dev);
 914
 915    s->bh = qemu_bh_new(DBDMA_run_bh, s);
 916}
 917
 918static void mac_dbdma_class_init(ObjectClass *oc, void *data)
 919{
 920    DeviceClass *dc = DEVICE_CLASS(oc);
 921
 922    dc->realize = mac_dbdma_realize;
 923    dc->reset = mac_dbdma_reset;
 924    dc->vmsd = &vmstate_dbdma;
 925}
 926
 927static const TypeInfo mac_dbdma_type_info = {
 928    .name = TYPE_MAC_DBDMA,
 929    .parent = TYPE_SYS_BUS_DEVICE,
 930    .instance_size = sizeof(DBDMAState),
 931    .instance_init = mac_dbdma_init,
 932    .class_init = mac_dbdma_class_init
 933};
 934
 935static void mac_dbdma_register_types(void)
 936{
 937    type_register_static(&mac_dbdma_type_info);
 938}
 939
 940type_init(mac_dbdma_register_types)
 941