Commit 1d893440 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.11-20170927' into staging



ppc patch queue 2017-09-27

Contains
 * a number of Mac machine type fixes
 * a number of embedded machine type fixes (preliminary to adding the
   Sam460ex board)
 * a important fix for handling of migration with KVM PR
 * assorted other minor fixes and cleanups

# gpg: Signature made Wed 27 Sep 2017 08:40:48 BST
# gpg:                using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.11-20170927: (26 commits)
  macio: use object link between MACIO_IDE and MAC_DBDMA object
  macio: pass channel into MACIOIDEState via qdev property
  mac_dbdma: remove DBDMA_init() function
  mac_dbdma: QOMify
  mac_dbdma: remove unused IO fields from DBDMAState
  spapr: fix the value of SDR1 in kvmppc_put_books_sregs()
  ppc/pnv: check for OPAL firmware file presence
  ppc: remove all unused CPU definitions
  ppc: remove unused CPU definitions
  spapr_pci: make index property mandatory
  macio: convert pmac_ide_ops from old_mmio
  ppc/pnv: Improve macro parenthesization
  spapr: introduce helpers to migrate HPT chunks and the end marker
  ppc/kvm: generalize the use of kvmppc_get_htab_fd()
  ppc/kvm: change kvmppc_get_htab_fd() to return -errno on error
  ppc: Fix OpenPIC model
  ppc/ide/macio: Add missing registers
  ppc/mac: More rework of the DBDMA emulation
  ppc/mac: Advertise a high clock frequency for NewWorld Macs
  ppc: QOMify g3beige machine
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents cfe4cade e451b85f
Loading
Loading
Loading
Loading
+111 −95
Original line number Diff line number Diff line
@@ -255,114 +255,100 @@ static void pmac_ide_flush(DBDMA_io *io)
}

/* PowerMac IDE memory IO */
static void pmac_ide_writeb (void *opaque,
                             hwaddr addr, uint32_t val)
static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size)
{
    MACIOIDEState *d = opaque;
    uint64_t retval = 0xffffffff;
    int reg = addr >> 4;

    addr = (addr & 0xFFF) >> 4;
    switch (addr) {
    case 1 ... 7:
        ide_ioport_write(&d->bus, addr, val);
        break;
    case 8:
    case 22:
        ide_cmd_write(&d->bus, 0, val);
        break;
    default:
        break;
    switch (reg) {
    case 0x0:
        if (size == 2) {
            retval = ide_data_readw(&d->bus, 0);
        } else if (size == 4) {
            retval = ide_data_readl(&d->bus, 0);
        }
        break;
    case 0x1 ... 0x7:
        if (size == 1) {
            retval = ide_ioport_read(&d->bus, reg);
        }

static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
{
    uint8_t retval;
    MACIOIDEState *d = opaque;

    addr = (addr & 0xFFF) >> 4;
    switch (addr) {
    case 1 ... 7:
        retval = ide_ioport_read(&d->bus, addr);
        break;
    case 8:
    case 22:
    case 0x8:
    case 0x16:
        if (size == 1) {
            retval = ide_status_read(&d->bus, 0);
        }
        break;
    default:
        retval = 0xFF;
    case 0x20:
        if (size == 4) {
            retval = d->timing_reg;
        }
        break;
    case 0x30:
        /* This is an interrupt state register that only exists
         * in the KeyLargo and later variants. Bit 0x8000_0000
         * latches the DMA interrupt and has to be written to
         * clear. Bit 0x4000_0000 is an image of the disk
         * interrupt. MacOS X relies on this and will hang if
         * we don't provide at least the disk interrupt
         */
        if (size == 4) {
            retval = d->irq_reg;
        }
        break;
    }

    return retval;
}

static void pmac_ide_writew (void *opaque,
                             hwaddr addr, uint32_t val)

static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val,
                           unsigned size)
{
    MACIOIDEState *d = opaque;
    int reg = addr >> 4;

    addr = (addr & 0xFFF) >> 4;
    val = bswap16(val);
    if (addr == 0) {
    switch (reg) {
    case 0x0:
        if (size == 2) {
            ide_data_writew(&d->bus, 0, val);
        } else if (size == 4) {
            ide_data_writel(&d->bus, 0, val);
        }
        break;
    case 0x1 ... 0x7:
        if (size == 1) {
            ide_ioport_write(&d->bus, reg, val);
        }

static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
{
    uint16_t retval;
    MACIOIDEState *d = opaque;

    addr = (addr & 0xFFF) >> 4;
    if (addr == 0) {
        retval = ide_data_readw(&d->bus, 0);
    } else {
        retval = 0xFFFF;
        break;
    case 0x8:
    case 0x16:
        if (size == 1) {
            ide_cmd_write(&d->bus, 0, val);
        }
    retval = bswap16(retval);
    return retval;
        break;
    case 0x20:
        if (size == 4) {
            d->timing_reg = val;
        }

static void pmac_ide_writel (void *opaque,
                             hwaddr addr, uint32_t val)
{
    MACIOIDEState *d = opaque;

    addr = (addr & 0xFFF) >> 4;
    val = bswap32(val);
    if (addr == 0) {
        ide_data_writel(&d->bus, 0, val);
        break;
    case 0x30:
        if (size == 4) {
            if (val & 0x80000000u) {
                d->irq_reg &= 0x7fffffff;
            }
        }

static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
{
    uint32_t retval;
    MACIOIDEState *d = opaque;

    addr = (addr & 0xFFF) >> 4;
    if (addr == 0) {
        retval = ide_data_readl(&d->bus, 0);
    } else {
        retval = 0xFFFFFFFF;
        break;
    }
    retval = bswap32(retval);
    return retval;
}

static const MemoryRegionOps pmac_ide_ops = {
    .old_mmio = {
        .write = {
            pmac_ide_writeb,
            pmac_ide_writew,
            pmac_ide_writel,
        },
        .read = {
            pmac_ide_readb,
            pmac_ide_readw,
            pmac_ide_readl,
        },
    },
    .endianness = DEVICE_NATIVE_ENDIAN,
    .read = pmac_ide_read,
    .write = pmac_ide_write,
    .valid.min_access_size = 1,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static const VMStateDescription vmstate_pmac = {
@@ -426,13 +412,32 @@ static void macio_ide_realizefn(DeviceState *dev, Error **errp)
{
    MACIOIDEState *s = MACIO_IDE(dev);

    ide_init2(&s->bus, s->irq);
    ide_init2(&s->bus, s->ide_irq);

    /* Register DMA callbacks */
    s->dma.ops = &dbdma_ops;
    s->bus.dma = &s->dma;
}

static void pmac_ide_irq(void *opaque, int n, int level)
{
    MACIOIDEState *s = opaque;
    uint32_t mask = 0x80000000u >> n;

    /* We need to reflect the IRQ state in the irq register */
    if (level) {
        s->irq_reg |= mask;
    } else {
        s->irq_reg &= ~mask;
    }

    if (n) {
        qemu_set_irq(s->real_ide_irq, level);
    } else {
        qemu_set_irq(s->real_dma_irq, level);
    }
}

static void macio_ide_initfn(Object *obj)
{
    SysBusDevice *d = SYS_BUS_DEVICE(obj);
@@ -441,16 +446,28 @@ static void macio_ide_initfn(Object *obj)
    ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
    memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
    sysbus_init_mmio(d, &s->mem);
    sysbus_init_irq(d, &s->irq);
    sysbus_init_irq(d, &s->dma_irq);
    sysbus_init_irq(d, &s->real_ide_irq);
    sysbus_init_irq(d, &s->real_dma_irq);
    s->dma_irq = qemu_allocate_irq(pmac_ide_irq, s, 0);
    s->ide_irq = qemu_allocate_irq(pmac_ide_irq, s, 1);

    object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
                             (Object **) &s->dbdma,
                             qdev_prop_allow_set_link_before_realize, 0, NULL);
}

static Property macio_ide_properties[] = {
    DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0),
    DEFINE_PROP_END_OF_LIST(),
};

static void macio_ide_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = macio_ide_realizefn;
    dc->reset = macio_ide_reset;
    dc->props = macio_ide_properties;
    dc->vmsd = &vmstate_pmac;
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
@@ -480,10 +497,9 @@ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
    }
}

void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
void macio_ide_register_dma(MACIOIDEState *s)
{
    s->dbdma = dbdma;
    DBDMA_register_channel(dbdma, channel, s->dma_irq,
    DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq,
                           pmac_ide_transfer, pmac_ide_flush, s);
}

+35 −0
Original line number Diff line number Diff line
@@ -92,6 +92,16 @@ static int get_current_cpu(void);
#define RAVEN_MAX_TMR      OPENPIC_MAX_TMR
#define RAVEN_MAX_IPI      OPENPIC_MAX_IPI

/* KeyLargo */
#define KEYLARGO_MAX_CPU  4
#define KEYLARGO_MAX_EXT  64
#define KEYLARGO_MAX_IPI  4
#define KEYLARGO_MAX_IRQ  (64 + KEYLARGO_MAX_IPI)
#define KEYLARGO_MAX_TMR  0
#define KEYLARGO_IPI_IRQ  (KEYLARGO_MAX_EXT) /* First IPI IRQ */
/* Timers don't exist but this makes the code happy... */
#define KEYLARGO_TMR_IRQ  (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)

/* Interrupt definitions */
#define RAVEN_FE_IRQ     (RAVEN_MAX_EXT)     /* Internal functional IRQ */
#define RAVEN_ERR_IRQ    (RAVEN_MAX_EXT + 1) /* Error IRQ */
@@ -120,6 +130,7 @@ static FslMpicInfo fsl_mpic_42 = {
#define VID_REVISION_1_3   3

#define VIR_GENERIC      0x00000000 /* Generic Vendor ID */
#define VIR_MPIC2A       0x00004614 /* IBM MPIC-2A */

#define GCR_RESET        0x80000000
#define GCR_MODE_PASS    0x00000000
@@ -329,6 +340,8 @@ typedef struct OpenPICState {
    uint32_t nb_cpus;
    /* Timer registers */
    OpenPICTimer timers[OPENPIC_MAX_TMR];
    uint32_t max_tmr;

    /* Shared MSI registers */
    OpenPICMSI msi[MAX_MSI];
    uint32_t max_irq;
@@ -1715,6 +1728,28 @@ static void openpic_realize(DeviceState *dev, Error **errp)
            return;
        }

        map_list(opp, list_le, &list_count);
        break;

    case OPENPIC_MODEL_KEYLARGO:
        opp->nb_irqs = KEYLARGO_MAX_EXT;
        opp->vid = VID_REVISION_1_2;
        opp->vir = VIR_GENERIC;
        opp->vector_mask = 0xFF;
        opp->tfrr_reset = 4160000;
        opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
        opp->idr_reset = 0;
        opp->max_irq = KEYLARGO_MAX_IRQ;
        opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
        opp->irq_tim0 = KEYLARGO_TMR_IRQ;
        opp->brr1 = -1;
        opp->mpic_mode_mask = GCR_MODE_MIXED;

        if (opp->nb_cpus != 1) {
            error_setg(errp, "Only UP supported today");
            return;
        }

        map_list(opp, list_le, &list_count);
        break;
    }
+176 −66
Original line number Diff line number Diff line
@@ -96,9 +96,8 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)

static void dbdma_cmdptr_save(DBDMA_channel *ch)
{
    DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n",
                    ch->regs[DBDMA_CMDPTR_LO]);
    DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n",
    DBDMA_DPRINTFCH(ch, "-> update 0x%08x stat=0x%08x, res=0x%04x\n",
                    ch->regs[DBDMA_CMDPTR_LO],
                    le16_to_cpu(ch->current.xfer_status),
                    le16_to_cpu(ch->current.res_count));
    dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
@@ -166,15 +165,14 @@ static int conditional_wait(DBDMA_channel *ch)
    uint16_t sel_mask, sel_value;
    uint32_t status;
    int cond;

    DBDMA_DPRINTFCH(ch, "conditional_wait\n");
    int res = 0;

    wait = le16_to_cpu(current->command) & WAIT_MASK;

    switch(wait) {
    case WAIT_NEVER:  /* don't wait */
        return 0;
    case WAIT_ALWAYS: /* always wait */
        DBDMA_DPRINTFCH(ch, "  [WAIT_ALWAYS]\n");
        return 1;
    }

@@ -187,15 +185,19 @@ static int conditional_wait(DBDMA_channel *ch)

    switch(wait) {
    case WAIT_IFSET:  /* wait if condition bit is 1 */
        if (cond)
            return 1;
        return 0;
        if (cond) {
            res = 1;
        }
        DBDMA_DPRINTFCH(ch, "  [WAIT_IFSET=%d]\n", res);
        break;
    case WAIT_IFCLR:  /* wait if condition bit is 0 */
        if (!cond)
            return 1;
        return 0;
        if (!cond) {
            res = 1;
        }
    return 0;
        DBDMA_DPRINTFCH(ch, "  [WAIT_IFCLR=%d]\n", res);
        break;
    }
    return res;
}

static void next(DBDMA_channel *ch)
@@ -226,8 +228,6 @@ static void conditional_branch(DBDMA_channel *ch)
    uint32_t status;
    int cond;

    DBDMA_DPRINTFCH(ch, "conditional_branch\n");

    /* check if we must branch */

    br = le16_to_cpu(current->command) & BR_MASK;
@@ -237,6 +237,7 @@ static void conditional_branch(DBDMA_channel *ch)
        next(ch);
        return;
    case BR_ALWAYS: /* always branch */
        DBDMA_DPRINTFCH(ch, "  [BR_ALWAYS]\n");
        branch(ch);
        return;
    }
@@ -250,16 +251,22 @@ static void conditional_branch(DBDMA_channel *ch)

    switch(br) {
    case BR_IFSET:  /* branch if condition bit is 1 */
        if (cond)
        if (cond) {
            DBDMA_DPRINTFCH(ch, "  [BR_IFSET = 1]\n");
            branch(ch);
        else
        } else {
            DBDMA_DPRINTFCH(ch, "  [BR_IFSET = 0]\n");
            next(ch);
        }
        return;
    case BR_IFCLR:  /* branch if condition bit is 0 */
        if (!cond)
        if (!cond) {
            DBDMA_DPRINTFCH(ch, "  [BR_IFCLR = 1]\n");
            branch(ch);
        else
        } else {
            DBDMA_DPRINTFCH(ch, "  [BR_IFCLR = 0]\n");
            next(ch);
        }
        return;
    }
}
@@ -428,7 +435,7 @@ wait:

static void stop(DBDMA_channel *ch)
{
    ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
    ch->regs[DBDMA_STATUS] &= ~(ACTIVE);

    /* the stop command does not increment command pointer */
}
@@ -471,18 +478,22 @@ static void channel_run(DBDMA_channel *ch)

    switch (cmd) {
    case OUTPUT_MORE:
        DBDMA_DPRINTFCH(ch, "* OUTPUT_MORE *\n");
        start_output(ch, key, phy_addr, req_count, 0);
        return;

    case OUTPUT_LAST:
        DBDMA_DPRINTFCH(ch, "* OUTPUT_LAST *\n");
        start_output(ch, key, phy_addr, req_count, 1);
        return;

    case INPUT_MORE:
        DBDMA_DPRINTFCH(ch, "* INPUT_MORE *\n");
        start_input(ch, key, phy_addr, req_count, 0);
        return;

    case INPUT_LAST:
        DBDMA_DPRINTFCH(ch, "* INPUT_LAST *\n");
        start_input(ch, key, phy_addr, req_count, 1);
        return;
    }
@@ -508,10 +519,12 @@ static void channel_run(DBDMA_channel *ch)

    switch (cmd) {
    case LOAD_WORD:
        DBDMA_DPRINTFCH(ch, "* LOAD_WORD *\n");
        load_word(ch, key, phy_addr, req_count);
        return;

    case STORE_WORD:
        DBDMA_DPRINTFCH(ch, "* STORE_WORD *\n");
        store_word(ch, key, phy_addr, req_count);
        return;
    }
@@ -562,43 +575,117 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
    ch->io.opaque = opaque;
}

static void
dbdma_control_write(DBDMA_channel *ch)
static void dbdma_control_write(DBDMA_channel *ch)
{
    uint16_t mask, value;
    uint32_t status;
    bool do_flush = false;

    mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
    value = ch->regs[DBDMA_CONTROL] & 0xffff;

    value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);

    /* This is the status register which we'll update
     * appropriately and store back
     */
    status = ch->regs[DBDMA_STATUS];

    status = (value & mask) | (status & ~mask);
    /* RUN and PAUSE are bits under SW control only
     * FLUSH and WAKE are set by SW and cleared by HW
     * DEAD, ACTIVE and BT are only under HW control
     *
     * We handle ACTIVE separately at the end of the
     * logic to ensure all cases are covered.
     */

    /* Setting RUN will tentatively activate the channel
     */
    if ((mask & RUN) && (value & RUN)) {
        status |= RUN;
        DBDMA_DPRINTFCH(ch, " Setting RUN !\n");
    }

    if (status & WAKE)
        status |= ACTIVE;
    if (status & RUN) {
        status |= ACTIVE;
        status &= ~DEAD;
    /* Clearing RUN 1->0 will stop the channel */
    if ((mask & RUN) && !(value & RUN)) {
        /* This has the side effect of clearing the DEAD bit */
        status &= ~(DEAD | RUN);
        DBDMA_DPRINTFCH(ch, " Clearing RUN !\n");
    }

    /* Setting WAKE wakes up an idle channel if it's running
     *
     * Note: The doc doesn't say so but assume that only works
     * on a channel whose RUN bit is set.
     *
     * We set WAKE in status, it's not terribly useful as it will
     * be cleared on the next command fetch but it seems to mimmic
     * the HW behaviour and is useful for the way we handle
     * ACTIVE further down.
     */
    if ((mask & WAKE) && (value & WAKE) && (status & RUN)) {
        status |= WAKE;
        DBDMA_DPRINTFCH(ch, " Setting WAKE !\n");
    }
    if (status & PAUSE)

    /* PAUSE being set will deactivate (or prevent activation)
     * of the channel. We just copy it over for now, ACTIVE will
     * be re-evaluated later.
     */
    if (mask & PAUSE) {
        status = (status & ~PAUSE) | (value & PAUSE);
        DBDMA_DPRINTFCH(ch, " %sing PAUSE !\n",
                        (value & PAUSE) ? "sett" : "clear");
    }

    /* FLUSH is its own thing */
    if ((mask & FLUSH) && (value & FLUSH))  {
        DBDMA_DPRINTFCH(ch, " Setting FLUSH !\n");
        /* We set flush directly in the status register, we do *NOT*
         * set it in "status" so that it gets naturally cleared when
         * we update the status register further down. That way it
         * will be set only during the HW flush operation so it is
         * visible to any completions happening during that time.
         */
        ch->regs[DBDMA_STATUS] |= FLUSH;
        do_flush = true;
    }

    /* If either RUN or PAUSE is clear, so should ACTIVE be,
     * otherwise, ACTIVE will be set if we modified RUN, PAUSE or
     * set WAKE. That means that PAUSE was just cleared, RUN was
     * just set or WAKE was just set.
     */
    if ((status & PAUSE) || !(status & RUN)) {
        status &= ~ACTIVE;
    if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
        /* RUN is cleared */
        status &= ~(ACTIVE|DEAD);
        DBDMA_DPRINTFCH(ch, "  -> ACTIVE down !\n");

        /* We stopped processing, we want the underlying HW command
         * to complete *before* we clear the ACTIVE bit. Otherwise
         * we can get into a situation where the command status will
         * have RUN or ACTIVE not set which is going to confuse the
         * MacOS driver.
         */
        do_flush = true;
    } else if (mask & (RUN | PAUSE)) {
        status |= ACTIVE;
        DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
    } else if ((mask & WAKE) && (value & WAKE)) {
        status |= ACTIVE;
        DBDMA_DPRINTFCH(ch, " -> ACTIVE up !\n");
    }

    if ((status & FLUSH) && ch->flush) {
    DBDMA_DPRINTFCH(ch, " new status=0x%08x\n", status);

    /* If we need to flush the underlying HW, do it now, this happens
     * both on FLUSH commands and when stopping the channel for safety.
     */
    if (do_flush && ch->flush) {
        ch->flush(&ch->io);
        status &= ~FLUSH;
    }

    DBDMA_DPRINTFCH(ch, "    status 0x%08x\n", status);

    /* Finally update the status register image */
    ch->regs[DBDMA_STATUS] = status;

    /* If active, make sure the BH gets to run */
    if (status & ACTIVE) {
        DBDMA_kick(dbdma_from_ch(ch));
    }
@@ -666,13 +753,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,

    value = ch->regs[reg];

    DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
    DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
                    (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);

    switch(reg) {
    case DBDMA_CONTROL:
        value = 0;
        value = ch->regs[DBDMA_STATUS];
        break;
    case DBDMA_STATUS:
    case DBDMA_CMDPTR_LO:
@@ -698,6 +781,10 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
        break;
    }

    DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
    DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
                    (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);

    return value;
}

@@ -764,51 +851,49 @@ static const VMStateDescription vmstate_dbdma = {
    }
};

static void dbdma_reset(void *opaque)
static void mac_dbdma_reset(DeviceState *d)
{
    DBDMAState *s = opaque;
    DBDMAState *s = MAC_DBDMA(d);
    int i;

    for (i = 0; i < DBDMA_CHANNELS; i++)
    for (i = 0; i < DBDMA_CHANNELS; i++) {
        memset(s->channels[i].regs, 0, DBDMA_SIZE);
    }

static void dbdma_unassigned_rw(DBDMA_io *io)
{
    DBDMA_channel *ch = io->channel;
    qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
                  __func__, ch->channel);
    ch->io.processing = false;
}

static void dbdma_unassigned_flush(DBDMA_io *io)
static void dbdma_unassigned_rw(DBDMA_io *io)
{
    DBDMA_channel *ch = io->channel;
    dbdma_cmd *current = &ch->current;
    uint16_t cmd;
    qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
                  __func__, ch->channel);
    ch->io.processing = false;

    cmd = le16_to_cpu(current->command) & COMMAND_MASK;
    if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
        cmd == INPUT_MORE || cmd == INPUT_LAST) {
        current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH);
        current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
        current->res_count = cpu_to_le16(io->len);
        dbdma_cmdptr_save(ch);
    }
}

void* DBDMA_init (MemoryRegion **dbdma_mem)
static void dbdma_unassigned_flush(DBDMA_io *io)
{
    DBDMAState *s;
    int i;
    DBDMA_channel *ch = io->channel;
    qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
                  __func__, ch->channel);
}

    s = g_malloc0(sizeof(DBDMAState));
static void mac_dbdma_init(Object *obj)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    DBDMAState *s = MAC_DBDMA(obj);
    int i;

    for (i = 0; i < DBDMA_CHANNELS; i++) {
        DBDMA_io *io = &s->channels[i].io;
        DBDMA_channel *ch = &s->channels[i];
        qemu_iovec_init(&io->iov, 1);

        ch->rw = dbdma_unassigned_rw;
        ch->flush = dbdma_unassigned_flush;
@@ -816,12 +901,37 @@ void* DBDMA_init (MemoryRegion **dbdma_mem)
        ch->io.channel = ch;
    }

    memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
    *dbdma_mem = &s->mem;
    vmstate_register(NULL, -1, &vmstate_dbdma, s);
    qemu_register_reset(dbdma_reset, s);
    memory_region_init_io(&s->mem, obj, &dbdma_ops, s, "dbdma", 0x1000);
    sysbus_init_mmio(sbd, &s->mem);
}

static void mac_dbdma_realize(DeviceState *dev, Error **errp)
{
    DBDMAState *s = MAC_DBDMA(dev);

    s->bh = qemu_bh_new(DBDMA_run_bh, s);
}

    return s;
static void mac_dbdma_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = mac_dbdma_realize;
    dc->reset = mac_dbdma_reset;
    dc->vmsd = &vmstate_dbdma;
}

static const TypeInfo mac_dbdma_type_info = {
    .name = TYPE_MAC_DBDMA,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(DBDMAState),
    .instance_init = mac_dbdma_init,
    .class_init = mac_dbdma_class_init
};

static void mac_dbdma_register_types(void)
{
    type_register_static(&mac_dbdma_type_info);
}

type_init(mac_dbdma_register_types)
+16 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ typedef struct MacIOState

    MemoryRegion bar;
    CUDAState cuda;
    void *dbdma;
    DBDMAState *dbdma;
    MemoryRegion *pic_mem;
    MemoryRegion *escc_mem;
    uint64_t frequency;
@@ -127,10 +127,15 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
    MacIOState *s = MACIO(d);
    SysBusDevice *sysbus_dev;
    Error *err = NULL;
    MemoryRegion *dbdma_mem;

    s->dbdma = DBDMA_init(&dbdma_mem);
    memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
    object_property_set_bool(OBJECT(s->dbdma), true, "realized", &err);
    if (err) {
        error_propagate(errp, err);
        return;
    }
    sysbus_dev = SYS_BUS_DEVICE(s->dbdma);
    memory_region_add_subregion(&s->bar, 0x08000,
                                sysbus_mmio_get_region(sysbus_dev, 0));

    object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
    if (err) {
@@ -154,7 +159,10 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
    sysbus_dev = SYS_BUS_DEVICE(ide);
    sysbus_connect_irq(sysbus_dev, 0, irq0);
    sysbus_connect_irq(sysbus_dev, 1, irq1);
    macio_ide_register_dma(ide, s->dbdma, dmaid);
    qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid);
    object_property_set_link(OBJECT(ide), OBJECT(s->dbdma), "dbdma", errp);
    macio_ide_register_dma(ide);

    object_property_set_bool(OBJECT(ide), true, "realized", errp);
}

@@ -334,6 +342,9 @@ static void macio_instance_init(Object *obj)
    object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
    qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
    object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);

    s->dbdma = MAC_DBDMA(object_new(TYPE_MAC_DBDMA));
    object_property_add_child(obj, "dbdma", OBJECT(s->dbdma), NULL);
}

static const VMStateDescription vmstate_macio_oldworld = {
+7 −3
Original line number Diff line number Diff line
@@ -131,8 +131,10 @@ typedef struct MACIOIDEState {
    /*< private >*/
    SysBusDevice parent_obj;
    /*< public >*/

    qemu_irq irq;
    uint32_t channel;
    qemu_irq real_ide_irq;
    qemu_irq real_dma_irq;
    qemu_irq ide_irq;
    qemu_irq dma_irq;

    MemoryRegion mem;
@@ -140,10 +142,12 @@ typedef struct MACIOIDEState {
    IDEDMA dma;
    void *dbdma;
    bool dma_active;
    uint32_t timing_reg;
    uint32_t irq_reg;
} MACIOIDEState;

void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel);
void macio_ide_register_dma(MACIOIDEState *ide);

void macio_init(PCIDevice *dev,
                MemoryRegion *pic_mem,
Loading