summary refs log tree commit diff stats
path: root/hw/misc/macio
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-07-12 07:58:31 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-07-12 07:58:31 -0500
commit25ca6a1f5a3ee0a1ae670590877ed14f05e28fba (patch)
tree594b8455808884e8f28eee95570b9b0de0c54eb8 /hw/misc/macio
parentc170a23ca0097a95b44fc7cc604018cd3c3b7d44 (diff)
parentf35ea98cd9f75db9286f05bf3dc4b532f4cb5eaa (diff)
downloadfocaccia-qemu-25ca6a1f5a3ee0a1ae670590877ed14f05e28fba.tar.gz
focaccia-qemu-25ca6a1f5a3ee0a1ae670590877ed14f05e28fba.zip
Merge remote-tracking branch 'agraf/ppc-for-upstream' into staging
# By Alexander Graf (16) and others
# Via Alexander Graf
* agraf/ppc-for-upstream: (22 commits)
  PPC: dbdma: Support more multi-issue DMA requests
  PPC: Add timer handler for newworld mac-io
  PPC: dbdma: Support unaligned DMA access
  PPC: dbdma: Wait for DMA until we have data
  PPC: dbdma: Move processing to io
  PPC: dbdma: macio: Add DMA callback
  PPC: dbdma: Move static bh variable to device struct
  PPC: dbdma: Introduce kick function
  PPC: dbdma: Move defines into header file
  PPC: dbdma: Allow new commands in RUN state
  PPC: dbdma: Fix debug print
  PPC: Mac: Add debug prints in macio and dbdma code
  PPC: dbdma: Replace tabs with spaces
  PPC: Macio: Replace tabs with spaces
  PPC: g3beige: Move secondary IDE bus to mac-io
  PPC: Mac: Fix guest exported tbfreq values
  target-ppc: Add POWER8 v1.0 CPU model
  pseries: move interrupt controllers to hw/intc/
  spapr: Respect -bios command line option for SLOF
  spapr: Use named enum for function remove_hpte
  ...

Message-id: 1373562085-29728-1-git-send-email-agraf@suse.de
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/misc/macio')
-rw-r--r--hw/misc/macio/mac_dbdma.c193
-rw-r--r--hw/misc/macio/macio.c126
2 files changed, 137 insertions, 182 deletions
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index a1d7862a66..f47a736182 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -54,122 +54,10 @@
 /*
  */
 
-/*
- * DBDMA control/status registers.  All little-endian.
- */
-
-#define DBDMA_CONTROL         0x00
-#define DBDMA_STATUS          0x01
-#define DBDMA_CMDPTR_HI       0x02
-#define DBDMA_CMDPTR_LO       0x03
-#define DBDMA_INTR_SEL        0x04
-#define DBDMA_BRANCH_SEL      0x05
-#define DBDMA_WAIT_SEL        0x06
-#define DBDMA_XFER_MODE       0x07
-#define DBDMA_DATA2PTR_HI     0x08
-#define DBDMA_DATA2PTR_LO     0x09
-#define DBDMA_RES1            0x0A
-#define DBDMA_ADDRESS_HI      0x0B
-#define DBDMA_BRANCH_ADDR_HI  0x0C
-#define DBDMA_RES2            0x0D
-#define DBDMA_RES3            0x0E
-#define DBDMA_RES4            0x0F
-
-#define DBDMA_REGS            16
-#define DBDMA_SIZE            (DBDMA_REGS * sizeof(uint32_t))
-
-#define DBDMA_CHANNEL_SHIFT   7
-#define DBDMA_CHANNEL_SIZE    (1 << DBDMA_CHANNEL_SHIFT)
-
-#define DBDMA_CHANNELS        (0x1000 >> DBDMA_CHANNEL_SHIFT)
-
-/* Bits in control and status registers */
-
-#define RUN	0x8000
-#define PAUSE	0x4000
-#define FLUSH	0x2000
-#define WAKE	0x1000
-#define DEAD	0x0800
-#define ACTIVE	0x0400
-#define BT	0x0100
-#define DEVSTAT	0x00ff
-
-/*
- * DBDMA command structure.  These fields are all little-endian!
- */
-
-typedef struct dbdma_cmd {
-    uint16_t req_count;	  /* requested byte transfer count */
-    uint16_t command;	  /* command word (has bit-fields) */
-    uint32_t phy_addr;	  /* physical data address */
-    uint32_t cmd_dep;	  /* command-dependent field */
-    uint16_t res_count;	  /* residual count after completion */
-    uint16_t xfer_status; /* transfer status */
-} dbdma_cmd;
-
-/* DBDMA command values in command field */
-
-#define COMMAND_MASK    0xf000
-#define OUTPUT_MORE	0x0000	/* transfer memory data to stream */
-#define OUTPUT_LAST	0x1000	/* ditto followed by end marker */
-#define INPUT_MORE	0x2000	/* transfer stream data to memory */
-#define INPUT_LAST	0x3000	/* ditto, expect end marker */
-#define STORE_WORD	0x4000	/* write word (4 bytes) to device reg */
-#define LOAD_WORD	0x5000	/* read word (4 bytes) from device reg */
-#define DBDMA_NOP	0x6000	/* do nothing */
-#define DBDMA_STOP	0x7000	/* suspend processing */
-
-/* Key values in command field */
-
-#define KEY_MASK        0x0700
-#define KEY_STREAM0	0x0000	/* usual data stream */
-#define KEY_STREAM1	0x0100	/* control/status stream */
-#define KEY_STREAM2	0x0200	/* device-dependent stream */
-#define KEY_STREAM3	0x0300	/* device-dependent stream */
-#define KEY_STREAM4	0x0400	/* reserved */
-#define KEY_REGS	0x0500	/* device register space */
-#define KEY_SYSTEM	0x0600	/* system memory-mapped space */
-#define KEY_DEVICE	0x0700	/* device memory-mapped space */
-
-/* Interrupt control values in command field */
-
-#define INTR_MASK       0x0030
-#define INTR_NEVER	0x0000	/* don't interrupt */
-#define INTR_IFSET	0x0010	/* intr if condition bit is 1 */
-#define INTR_IFCLR	0x0020	/* intr if condition bit is 0 */
-#define INTR_ALWAYS	0x0030	/* always interrupt */
-
-/* Branch control values in command field */
-
-#define BR_MASK         0x000c
-#define BR_NEVER	0x0000	/* don't branch */
-#define BR_IFSET	0x0004	/* branch if condition bit is 1 */
-#define BR_IFCLR	0x0008	/* branch if condition bit is 0 */
-#define BR_ALWAYS	0x000c	/* always branch */
-
-/* Wait control values in command field */
-
-#define WAIT_MASK       0x0003
-#define WAIT_NEVER	0x0000	/* don't wait */
-#define WAIT_IFSET	0x0001	/* wait if condition bit is 1 */
-#define WAIT_IFCLR	0x0002	/* wait if condition bit is 0 */
-#define WAIT_ALWAYS	0x0003	/* always wait */
-
-typedef struct DBDMA_channel {
-    int channel;
-    uint32_t regs[DBDMA_REGS];
-    qemu_irq irq;
-    DBDMA_io io;
-    DBDMA_rw rw;
-    DBDMA_flush flush;
-    dbdma_cmd current;
-    int processing;
-} DBDMA_channel;
-
-typedef struct {
-    MemoryRegion mem;
-    DBDMA_channel channels[DBDMA_CHANNELS];
-} DBDMAState;
+static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
+{
+    return container_of(ch, DBDMAState, channels[ch->channel]);
+}
 
 #ifdef DEBUG_DBDMA
 static void dump_dbdma_cmd(dbdma_cmd *cmd)
@@ -224,7 +112,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
     uint32_t status;
     int cond;
 
-    DBDMA_DPRINTF("conditional_interrupt\n");
+    DBDMA_DPRINTF("%s\n", __func__);
 
     intr = le16_to_cpu(current->command) & INTR_MASK;
 
@@ -233,6 +121,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
         return;
     case INTR_ALWAYS: /* always interrupt */
         qemu_irq_raise(ch->irq);
+        DBDMA_DPRINTF("%s: raise\n", __func__);
         return;
     }
 
@@ -245,12 +134,16 @@ static void conditional_interrupt(DBDMA_channel *ch)
 
     switch(intr) {
     case INTR_IFSET:  /* intr if condition bit is 1 */
-        if (cond)
+        if (cond) {
             qemu_irq_raise(ch->irq);
+            DBDMA_DPRINTF("%s: raise\n", __func__);
+        }
         return;
     case INTR_IFCLR:  /* intr if condition bit is 0 */
-        if (!cond)
+        if (!cond) {
             qemu_irq_raise(ch->irq);
+            DBDMA_DPRINTF("%s: raise\n", __func__);
+        }
         return;
     }
 }
@@ -360,7 +253,6 @@ static void conditional_branch(DBDMA_channel *ch)
     }
 }
 
-static QEMUBH *dbdma_bh;
 static void channel_run(DBDMA_channel *ch);
 
 static void dbdma_end(DBDMA_io *io)
@@ -368,6 +260,8 @@ static void dbdma_end(DBDMA_io *io)
     DBDMA_channel *ch = io->channel;
     dbdma_cmd *current = &ch->current;
 
+    DBDMA_DPRINTF("%s\n", __func__);
+
     if (conditional_wait(ch))
         goto wait;
 
@@ -381,7 +275,9 @@ static void dbdma_end(DBDMA_io *io)
     conditional_branch(ch);
 
 wait:
-    ch->processing = 0;
+    /* Indicate that we're ready for a new DMA round */
+    ch->io.processing = false;
+
     if ((ch->regs[DBDMA_STATUS] & RUN) &&
         (ch->regs[DBDMA_STATUS] & ACTIVE))
         channel_run(ch);
@@ -407,7 +303,7 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
     ch->io.is_last = is_last;
     ch->io.dma_end = dbdma_end;
     ch->io.is_dma_out = 1;
-    ch->processing = 1;
+    ch->io.processing = true;
     if (ch->rw) {
         ch->rw(&ch->io);
     }
@@ -422,6 +318,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
      * are not implemented in the mac-io chip
      */
 
+    DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
     if (!addr || key > KEY_STREAM3) {
         kill_channel(ch);
         return;
@@ -432,7 +329,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
     ch->io.is_last = is_last;
     ch->io.dma_end = dbdma_end;
     ch->io.is_dma_out = 0;
-    ch->processing = 1;
+    ch->io.processing = true;
     if (ch->rw) {
         ch->rw(&ch->io);
     }
@@ -474,7 +371,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
     next(ch);
 
 wait:
-    qemu_bh_schedule(dbdma_bh);
+    DBDMA_kick(dbdma_from_ch(ch));
 }
 
 static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
@@ -512,7 +409,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
     next(ch);
 
 wait:
-    qemu_bh_schedule(dbdma_bh);
+    DBDMA_kick(dbdma_from_ch(ch));
 }
 
 static void nop(DBDMA_channel *ch)
@@ -529,7 +426,7 @@ static void nop(DBDMA_channel *ch)
     conditional_branch(ch);
 
 wait:
-    qemu_bh_schedule(dbdma_bh);
+    DBDMA_kick(dbdma_from_ch(ch));
 }
 
 static void stop(DBDMA_channel *ch)
@@ -558,11 +455,11 @@ static void channel_run(DBDMA_channel *ch)
     switch (cmd) {
     case DBDMA_NOP:
         nop(ch);
-	return;
+        return;
 
     case DBDMA_STOP:
         stop(ch);
-	return;
+        return;
     }
 
     key = le16_to_cpu(current->command) & 0x0700;
@@ -578,19 +475,19 @@ static void channel_run(DBDMA_channel *ch)
     switch (cmd) {
     case OUTPUT_MORE:
         start_output(ch, key, phy_addr, req_count, 0);
-	return;
+        return;
 
     case OUTPUT_LAST:
         start_output(ch, key, phy_addr, req_count, 1);
-	return;
+        return;
 
     case INPUT_MORE:
         start_input(ch, key, phy_addr, req_count, 0);
-	return;
+        return;
 
     case INPUT_LAST:
         start_input(ch, key, phy_addr, req_count, 1);
-	return;
+        return;
     }
 
     if (key < KEY_REGS) {
@@ -615,11 +512,11 @@ static void channel_run(DBDMA_channel *ch)
     switch (cmd) {
     case LOAD_WORD:
         load_word(ch, key, phy_addr, req_count);
-	return;
+        return;
 
     case STORE_WORD:
         store_word(ch, key, phy_addr, req_count);
-	return;
+        return;
     }
 }
 
@@ -630,7 +527,7 @@ static void DBDMA_run(DBDMAState *s)
     for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
         DBDMA_channel *ch = &s->channels[channel];
         uint32_t status = ch->regs[DBDMA_STATUS];
-        if (!ch->processing && (status & RUN) && (status & ACTIVE)) {
+        if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) {
             channel_run(ch);
         }
     }
@@ -645,6 +542,11 @@ static void DBDMA_run_bh(void *opaque)
     DBDMA_run(s);
 }
 
+void DBDMA_kick(DBDMAState *dbdma)
+{
+    qemu_bh_schedule(dbdma->bh);
+}
+
 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
                             DBDMA_rw rw, DBDMA_flush flush,
                             void *opaque)
@@ -698,10 +600,12 @@ dbdma_control_write(DBDMA_channel *ch)
 
     ch->regs[DBDMA_STATUS] = status;
 
-    if (status & ACTIVE)
-        qemu_bh_schedule(dbdma_bh);
-    if ((status & FLUSH) && ch->flush)
+    if (status & ACTIVE) {
+        DBDMA_kick(dbdma_from_ch(ch));
+    }
+    if ((status & FLUSH) && ch->flush) {
         ch->flush(&ch->io);
+    }
 }
 
 static void dbdma_write(void *opaque, hwaddr addr,
@@ -712,15 +616,16 @@ static void dbdma_write(void *opaque, hwaddr addr,
     DBDMA_channel *ch = &s->channels[channel];
     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
 
-    DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
+    DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
+                  addr, value);
     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
 
-    /* cmdptr cannot be modified if channel is RUN or ACTIVE */
+    /* cmdptr cannot be modified if channel is ACTIVE */
 
-    if (reg == DBDMA_CMDPTR_LO &&
-        (ch->regs[DBDMA_STATUS] & (RUN | ACTIVE)))
-	return;
+    if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
+        return;
+    }
 
     ch->regs[reg] = value;
 
@@ -853,7 +758,7 @@ void* DBDMA_init (MemoryRegion **dbdma_mem)
     vmstate_register(NULL, -1, &vmstate_dbdma, s);
     qemu_register_reset(dbdma_reset, s);
 
-    dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
+    s->bh = qemu_bh_new(DBDMA_run_bh, s);
 
     return s;
 }
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 76a1cfba32..c0d0bf7287 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -52,10 +52,10 @@ typedef struct OldWorldMacIOState {
     MacIOState parent_obj;
     /*< public >*/
 
-    qemu_irq irqs[3];
+    qemu_irq irqs[5];
 
     MacIONVRAMState nvram;
-    MACIOIDEState ide;
+    MACIOIDEState ide[2];
 } OldWorldMacIOState;
 
 #define NEWWORLD_MACIO(obj) \
@@ -147,18 +147,32 @@ static int macio_common_initfn(PCIDevice *d)
     return 0;
 }
 
+static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0,
+                            qemu_irq irq1, int dmaid)
+{
+    SysBusDevice *sysbus_dev;
+
+    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);
+    return qdev_init(DEVICE(ide));
+}
+
 static int macio_oldworld_initfn(PCIDevice *d)
 {
     MacIOState *s = MACIO(d);
     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
     SysBusDevice *sysbus_dev;
+    int i;
+    int cur_irq = 0;
     int ret = macio_common_initfn(d);
     if (ret < 0) {
         return ret;
     }
 
     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
-    sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]);
+    sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
 
     ret = qdev_init(DEVICE(&os->nvram));
     if (ret < 0) {
@@ -174,23 +188,39 @@ static int macio_oldworld_initfn(PCIDevice *d)
         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
     }
 
-    sysbus_dev = SYS_BUS_DEVICE(&os->ide);
-    sysbus_connect_irq(sysbus_dev, 0, os->irqs[1]);
-    sysbus_connect_irq(sysbus_dev, 1, os->irqs[2]);
-    macio_ide_register_dma(&os->ide, s->dbdma, 0x16);
-    ret = qdev_init(DEVICE(&os->ide));
-    if (ret < 0) {
-        return ret;
+    /* IDE buses */
+    for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
+        qemu_irq irq0 = os->irqs[cur_irq++];
+        qemu_irq irq1 = os->irqs[cur_irq++];
+
+        ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4));
+        if (ret < 0) {
+            return ret;
+        }
     }
 
     return 0;
 }
 
+static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, int index)
+{
+    gchar *name;
+
+    object_initialize(ide, TYPE_MACIO_IDE);
+    qdev_set_parent_bus(DEVICE(ide), sysbus_get_default());
+    memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000),
+                                &ide->mem);
+    name = g_strdup_printf("ide[%i]", index);
+    object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL);
+    g_free(name);
+}
+
 static void macio_oldworld_init(Object *obj)
 {
     MacIOState *s = MACIO(obj);
     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
     DeviceState *dev;
+    int i;
 
     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
 
@@ -199,48 +229,75 @@ static void macio_oldworld_init(Object *obj)
     qdev_prop_set_uint32(dev, "size", 0x2000);
     qdev_prop_set_uint32(dev, "it_shift", 4);
 
-    object_initialize(&os->ide, TYPE_MACIO_IDE);
-    qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default());
-    memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem);
-    object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL);
+    for (i = 0; i < 2; i++) {
+        macio_init_ide(s, &os->ide[i], i);
+    }
 }
 
+static void timer_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned size)
+{
+}
+
+static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
+{
+    uint32_t value = 0;
+
+    switch (addr) {
+    case 0x38:
+        value = qemu_get_clock_ns(vm_clock);
+        break;
+    case 0x3c:
+        value = qemu_get_clock_ns(vm_clock) >> 32;
+        break;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
 static int macio_newworld_initfn(PCIDevice *d)
 {
     MacIOState *s = MACIO(d);
     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
     SysBusDevice *sysbus_dev;
+    MemoryRegion *timer_memory = g_new(MemoryRegion, 1);
+    int i;
+    int cur_irq = 0;
     int ret = macio_common_initfn(d);
     if (ret < 0) {
         return ret;
     }
 
     sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
-    sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]);
+    sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
 
     if (s->pic_mem) {
         /* OpenPIC */
         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
     }
 
-    sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]);
-    sysbus_connect_irq(sysbus_dev, 0, ns->irqs[1]);
-    sysbus_connect_irq(sysbus_dev, 1, ns->irqs[2]);
-    macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16);
-    ret = qdev_init(DEVICE(&ns->ide[0]));
-    if (ret < 0) {
-        return ret;
-    }
+    /* IDE buses */
+    for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
+        qemu_irq irq0 = ns->irqs[cur_irq++];
+        qemu_irq irq1 = ns->irqs[cur_irq++];
 
-    sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]);
-    sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]);
-    sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]);
-    macio_ide_register_dma(&ns->ide[1], s->dbdma, 0x1a);
-    ret = qdev_init(DEVICE(&ns->ide[1]));
-    if (ret < 0) {
-        return ret;
+        ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4));
+        if (ret < 0) {
+            return ret;
+        }
     }
 
+    /* Timer */
+    memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
+                          0x1000);
+    memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
+
     return 0;
 }
 
@@ -249,18 +306,11 @@ static void macio_newworld_init(Object *obj)
     MacIOState *s = MACIO(obj);
     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
     int i;
-    gchar *name;
 
     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
 
     for (i = 0; i < 2; i++) {
-        object_initialize(&ns->ide[i], TYPE_MACIO_IDE);
-        qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default());
-        memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000),
-                                    &ns->ide[i].mem);
-        name = g_strdup_printf("ide[%i]", i);
-        object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL);
-        g_free(name);
+        macio_init_ide(s, &ns->ide[i], i);
     }
 }