cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

mac_dbdma.c (25701B)


      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)