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