do not test reserved config bits
[qemu] / hw / ide.c
index d2220ba..cf9a9a7 100644 (file)
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -296,8 +296,11 @@ typedef struct IDEState {
     int cylinders, heads, sectors;
     int64_t nb_sectors;
     int mult_sectors;
+    int identify_set;
+    uint16_t identify_data[256];
+    SetIRQFunc *set_irq;
+    void *irq_opaque;
     int irq;
-    openpic_t *openpic;
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
@@ -332,6 +335,7 @@ typedef struct IDEState {
     uint8_t *data_ptr;
     uint8_t *data_end;
     uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+    QEMUTimer *sector_write_timer; /* only used for win2k instal hack */
 } IDEState;
 
 #define BM_STATUS_DMAING 0x01
@@ -341,6 +345,18 @@ typedef struct IDEState {
 #define BM_CMD_START     0x01
 #define BM_CMD_READ      0x08
 
+#define IDE_TYPE_PIIX3   0
+#define IDE_TYPE_CMD646  1
+
+/* CMD646 specific */
+#define MRDMODE                0x71
+#define   MRDMODE_INTR_CH0     0x04
+#define   MRDMODE_INTR_CH1     0x08
+#define   MRDMODE_BLK_CH0      0x10
+#define   MRDMODE_BLK_CH1      0x20
+#define UDIDETCR0      0x73
+#define UDIDETCR1      0x7B
+
 typedef int IDEDMAFunc(IDEState *s, 
                        target_phys_addr_t phys_addr, 
                        int transfer_size1);
@@ -349,6 +365,8 @@ typedef struct BMDMAState {
     uint8_t cmd;
     uint8_t status;
     uint32_t addr;
+
+    struct PCIIDEState *pci_dev;
     /* current transfer state */
     IDEState *ide_if;
     IDEDMAFunc *dma_cb;
@@ -358,6 +376,7 @@ typedef struct PCIIDEState {
     PCIDevice dev;
     IDEState ide_if[4];
     BMDMAState bmdma[2];
+    int type; /* see IDE_TYPE_xxx */
 } PCIIDEState;
 
 static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
@@ -397,6 +416,11 @@ static void ide_identify(IDEState *s)
     unsigned int oldsize;
     char buf[20];
 
+    if (s->identify_set) {
+       memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
+       return;
+    }
+
     memset(s->io_buffer, 0, 512);
     p = (uint16_t *)s->io_buffer;
     put_le16(p + 0, 0x0040);
@@ -416,10 +440,10 @@ static void ide_identify(IDEState *s)
     put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
 #endif
     put_le16(p + 48, 1); /* dword I/O */
-    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
+    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
     put_le16(p + 51, 0x200); /* PIO transfer cycle */
     put_le16(p + 52, 0x200); /* DMA transfer cycle */
-    put_le16(p + 53, 1 | 1 << 2); /* words 54-58,88 are valid */
+    put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */
     put_le16(p + 54, s->cylinders);
     put_le16(p + 55, s->heads);
     put_le16(p + 56, s->sectors);
@@ -430,15 +454,24 @@ static void ide_identify(IDEState *s)
         put_le16(p + 59, 0x100 | s->mult_sectors);
     put_le16(p + 60, s->nb_sectors);
     put_le16(p + 61, s->nb_sectors >> 16);
-    put_le16(p + 80, (1 << 1) | (1 << 2));
+    put_le16(p + 63, 0x07); /* mdma0-2 supported */
+    put_le16(p + 65, 120);
+    put_le16(p + 66, 120);
+    put_le16(p + 67, 120);
+    put_le16(p + 68, 120);
+    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
+    put_le16(p + 81, 0x16); /* conforms to ata5 */
     put_le16(p + 82, (1 << 14));
     put_le16(p + 83, (1 << 14));
     put_le16(p + 84, (1 << 14));
     put_le16(p + 85, (1 << 14));
     put_le16(p + 86, 0);
     put_le16(p + 87, (1 << 14));
-    put_le16(p + 88, 0x1f | (1 << 13));
-    put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000);
+    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
+    put_le16(p + 93, 1 | (1 << 14) | 0x2000);
+
+    memcpy(s->identify_data, p, sizeof(s->identify_data));
+    s->identify_set = 1;
 }
 
 static void ide_atapi_identify(IDEState *s)
@@ -446,6 +479,11 @@ static void ide_atapi_identify(IDEState *s)
     uint16_t *p;
     char buf[20];
 
+    if (s->identify_set) {
+       memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
+       return;
+    }
+
     memset(s->io_buffer, 0, 512);
     p = (uint16_t *)s->io_buffer;
     /* Removable CDROM, 50us response, 12 byte packets */
@@ -466,11 +504,14 @@ static void ide_atapi_identify(IDEState *s)
     put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
     put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
     put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
-    
+
     put_le16(p + 71, 30); /* in ns */
     put_le16(p + 72, 30); /* in ns */
 
     put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
+
+    memcpy(s->identify_data, p, sizeof(s->identify_data));
+    s->identify_set = 1;
 }
 
 static void ide_set_signature(IDEState *s)
@@ -501,17 +542,10 @@ static inline void ide_set_irq(IDEState *s)
 {
     BMDMAState *bm = s->bmdma;
     if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
-        if (bm)
+        if (bm) {
             bm->status |= BM_STATUS_INT;
-#ifdef TARGET_PPC
-        if (s->openpic) 
-            openpic_set_irq(s->openpic, s->irq, 1);
-        else 
-#endif
-        if (s->irq == 16)
-            pci_set_irq(s->pci_dev, 0, 1);
-        else
-            pic_set_irq(s->irq, 1);
+        }
+        s->set_irq(s->irq_opaque, s->irq, 1);
     }
 }
 
@@ -645,6 +679,12 @@ static void ide_sector_read_dma(IDEState *s)
     ide_dma_start(s, ide_read_dma_cb);
 }
 
+static void ide_sector_write_timer_cb(void *opaque)
+{
+    IDEState *s = opaque;
+    ide_set_irq(s);
+}
+
 static void ide_sector_write(IDEState *s)
 {
     int64_t sector_num;
@@ -670,7 +710,22 @@ static void ide_sector_write(IDEState *s)
         ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
     }
     ide_set_sector(s, sector_num + n);
-    ide_set_irq(s);
+    
+#ifdef TARGET_I386
+    if (win2k_install_hack) {
+        /* It seems there is a bug in the Windows 2000 installer HDD
+           IDE driver which fills the disk with empty logs when the
+           IDE write IRQ comes too early. This hack tries to correct
+           that at the expense of slower write performances. Use this
+           option _only_ to install Windows 2000. You must disable it
+           for normal use. */
+        qemu_mod_timer(s->sector_write_timer, 
+                       qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
+    } else 
+#endif
+    {
+        ide_set_irq(s);
+    }
 }
 
 static int ide_write_dma_cb(IDEState *s, 
@@ -792,7 +847,8 @@ static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
     case 2352:
         /* sync bytes */
         buf[0] = 0x00;
-        memset(buf + 1, 0xff, 11);
+        memset(buf + 1, 0xff, 10);
+        buf[11] = 0x00;
         buf += 12;
         /* MSF */
         lba_to_msf(buf, lba);
@@ -920,6 +976,9 @@ static int ide_atapi_cmd_read_dma_cb(IDEState *s,
     
     transfer_size = transfer_size1;
     while (transfer_size > 0) {
+#ifdef DEBUG_IDE_ATAPI
+        printf("transfer_size: %d phys_addr=%08x\n", transfer_size, phys_addr);
+#endif
         if (s->packet_transfer_size <= 0)
             break;
         len = s->cd_sector_size - s->io_buffer_index;
@@ -997,9 +1056,8 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)
         *q++ = 0; /* reserved */
         if (msf) {
             *q++ = 0; /* reserved */
-            *q++ = 0; /* minute */
-            *q++ = 2; /* second */
-            *q++ = 0; /* frame */
+            lba_to_msf(q, 0);
+            q += 3;
         } else {
             /* sector 0 */
             cpu_to_ube32(q, 0);
@@ -1084,10 +1142,16 @@ static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf,
     *q++ = 0; /* min */
     *q++ = 0; /* sec */
     *q++ = 0; /* frame */
-    *q++ = 0; 
-    *q++ = 0; 
-    *q++ = 0; 
-    *q++ = 0; 
+    if (msf) {
+        *q++ = 0; 
+        lba_to_msf(q, 0);
+        q += 3;
+    } else {
+        *q++ = 0; 
+        *q++ = 0; 
+        *q++ = 0; 
+        *q++ = 0; 
+    }
 
     len = q - buf;
     cpu_to_ube16(buf, len - 2);
@@ -1561,19 +1625,43 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             /* XXX: valid for CDROM ? */
             switch(s->feature) {
             case 0x02: /* write cache enable */
-            case 0x03: /* set transfer mode */
             case 0x82: /* write cache disable */
             case 0xaa: /* read look-ahead enable */
             case 0x55: /* read look-ahead disable */
                 s->status = READY_STAT | SEEK_STAT;
                 ide_set_irq(s);
                 break;
+            case 0x03: { /* set transfer mode */
+               uint8_t val = s->nsector & 0x07;
+
+               switch (s->nsector >> 3) {
+                   case 0x00: /* pio default */
+                   case 0x01: /* pio mode */
+                       put_le16(s->identify_data + 63,0x07);
+                       put_le16(s->identify_data + 88,0x3f);
+                       break;
+                   case 0x04: /* mdma mode */
+                       put_le16(s->identify_data + 63,0x07 | (1 << (val + 8)));
+                       put_le16(s->identify_data + 88,0x3f);
+                       break;
+                   case 0x08: /* udma mode */
+                       put_le16(s->identify_data + 63,0x07);
+                       put_le16(s->identify_data + 88,0x3f | (1 << (val + 8)));
+                       break;
+                   default:
+                       goto abort_cmd;
+               }
+                s->status = READY_STAT | SEEK_STAT;
+                ide_set_irq(s);
+                break;
+           }
             default:
                 goto abort_cmd;
             }
             break;
        case WIN_STANDBYNOW1:
         case WIN_IDLEIMMEDIATE:
+        case WIN_FLUSH_CACHE:
            s->status = READY_STAT;
             ide_set_irq(s);
             break;
@@ -1581,7 +1669,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         case WIN_PIDENTIFY:
             if (s->is_cdrom) {
                 ide_atapi_identify(s);
-                s->status = READY_STAT;
+                s->status = READY_STAT | SEEK_STAT;
                 ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
             } else {
                 ide_abort_command(s);
@@ -1675,15 +1763,7 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
             ret = 0;
         else
             ret = s->status;
-#ifdef TARGET_PPC
-        if (s->openpic) 
-            openpic_set_irq(s->openpic, s->irq, 0);
-        else 
-#endif
-        if (s->irq == 16)
-            pci_set_irq(s->pci_dev, 0, 0);
-        else
-            pic_set_irq(s->irq, 0);
+        s->set_irq(s->irq_opaque, s->irq, 0);
         break;
     }
 #ifdef DEBUG_IDE
@@ -1876,8 +1956,9 @@ static int guess_disk_lchs(IDEState *s,
     return -1;
 }
 
-static void ide_init2(IDEState *ide_state, int irq,
-                      BlockDriverState *hd0, BlockDriverState *hd1)
+static void ide_init2(IDEState *ide_state,
+                      BlockDriverState *hd0, BlockDriverState *hd1,
+                      SetIRQFunc *set_irq, void *irq_opaque, int irq)
 {
     IDEState *s;
     static int drive_serial = 1;
@@ -1938,7 +2019,11 @@ static void ide_init2(IDEState *ide_state, int irq,
             }
         }
         s->drive_serial = drive_serial++;
+        s->set_irq = set_irq;
+        s->irq_opaque = irq_opaque;
         s->irq = irq;
+        s->sector_write_timer = qemu_new_timer(vm_clock, 
+                                               ide_sector_write_timer_cb, s);
         ide_reset(s);
     }
 }
@@ -1971,13 +2056,15 @@ void isa_ide_init(int iobase, int iobase2, int irq,
     if (!ide_state)
         return;
     
-    ide_init2(ide_state, irq, hd0, hd1);
+    ide_init2(ide_state, hd0, hd1, pic_set_irq_new, isa_pic, irq);
     ide_init_ioport(ide_state, iobase, iobase2);
 }
 
 /***********************************************************/
 /* PCI IDE definitions */
 
+static void cmd646_update_irq(PCIIDEState *d);
+
 static void ide_map(PCIDevice *pci_dev, int region_num, 
                     uint32_t addr, uint32_t size, int type)
 {
@@ -2058,17 +2145,6 @@ static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb)
     }
 }
 
-static uint32_t bmdma_cmd_readb(void *opaque, uint32_t addr)
-{
-    BMDMAState *bm = opaque;
-    uint32_t val;
-    val = bm->cmd;
-#ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
-#endif
-    return val;
-}
-
 static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     BMDMAState *bm = opaque;
@@ -2088,24 +2164,77 @@ static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-static uint32_t bmdma_status_readb(void *opaque, uint32_t addr)
+static uint32_t bmdma_readb(void *opaque, uint32_t addr)
 {
     BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev;
     uint32_t val;
-    val = bm->status;
+    
+    switch(addr & 3) {
+    case 0: 
+        val = bm->cmd;
+        break;
+    case 1:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            val = pci_dev->dev.config[MRDMODE];
+        } else {
+            val = 0xff;
+        }
+        break;
+    case 2:
+        val = bm->status;
+        break;
+    case 3:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            if (bm == &pci_dev->bmdma[0])
+                val = pci_dev->dev.config[UDIDETCR0];
+            else
+                val = pci_dev->dev.config[UDIDETCR1];
+        } else {
+            val = 0xff;
+        }
+        break;
+    default:
+        val = 0xff;
+        break;
+    }
 #ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
+    printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
 #endif
     return val;
 }
 
-static void bmdma_status_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     BMDMAState *bm = opaque;
+    PCIIDEState *pci_dev;
 #ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
+    printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
-    bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
+    switch(addr & 3) {
+    case 1:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            pci_dev->dev.config[MRDMODE] = 
+                (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
+            cmd646_update_irq(pci_dev);
+        }
+        break;
+    case 2:
+        bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
+        break;
+    case 3:
+        pci_dev = bm->pci_dev;
+        if (pci_dev->type == IDE_TYPE_CMD646) {
+            if (bm == &pci_dev->bmdma[0])
+                pci_dev->dev.config[UDIDETCR0] = val;
+            else
+                pci_dev->dev.config[UDIDETCR1] = val;
+        }
+        break;
+    }
 }
 
 static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
@@ -2138,12 +2267,12 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         BMDMAState *bm = &d->bmdma[i];
         d->ide_if[2 * i].bmdma = bm;
         d->ide_if[2 * i + 1].bmdma = bm;
-        
+        bm->pci_dev = (PCIIDEState *)pci_dev;
+
         register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
-        register_ioport_read(addr, 1, 1, bmdma_cmd_readb, bm);
 
-        register_ioport_write(addr + 2, 1, 1, bmdma_status_writeb, bm);
-        register_ioport_read(addr + 2, 1, 1, bmdma_status_readb, bm);
+        register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
+        register_ioport_read(addr, 4, 1, bmdma_readb, bm);
 
         register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
         register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
@@ -2151,29 +2280,62 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
     }
 }
 
-/* hd_table must contain 4 block drivers */
-void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table)
+/* XXX: call it also when the MRDMODE is changed from the PCI config
+   registers */
+static void cmd646_update_irq(PCIIDEState *d)
+{
+    int pci_level;
+    pci_level = ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH0) &&
+                 !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
+        ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
+         !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
+    pci_set_irq((PCIDevice *)d, 0, pci_level);
+}
+
+/* the PCI irq level is the logical OR of the two channels */
+static void cmd646_set_irq(void *opaque, int channel, int level)
+{
+    PCIIDEState *d = opaque;
+    int irq_mask;
+
+    irq_mask = MRDMODE_INTR_CH0 << channel;
+    if (level)
+        d->dev.config[MRDMODE] |= irq_mask;
+    else
+        d->dev.config[MRDMODE] &= ~irq_mask;
+    cmd646_update_irq(d);
+}
+
+/* CMD646 PCI IDE controller */
+void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
+                         int secondary_ide_enabled)
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
     int i;
 
-    d = (PCIIDEState *)pci_register_device(bus, "IDE", sizeof(PCIIDEState),
+    d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE", 
+                                           sizeof(PCIIDEState),
                                            -1, 
                                            NULL, NULL);
+    d->type = IDE_TYPE_CMD646;
     pci_conf = d->dev.config;
-    pci_conf[0x00] = 0x86; // Intel
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x00; // fake
-    pci_conf[0x03] = 0x01; // fake
+    pci_conf[0x00] = 0x95; // CMD646
+    pci_conf[0x01] = 0x10;
+    pci_conf[0x02] = 0x46;
+    pci_conf[0x03] = 0x06;
+
+    pci_conf[0x08] = 0x07; // IDE controller revision
+    pci_conf[0x09] = 0x8f; 
+
     pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
-    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
-
-    pci_conf[0x2c] = 0x86; // subsys vendor
-    pci_conf[0x2d] = 0x80; // subsys vendor
-    pci_conf[0x2e] = 0x00; // fake
-    pci_conf[0x2f] = 0x01; // fake
+    pci_conf[0x0e] = 0x00; // header_type
+    
+    if (secondary_ide_enabled) {
+        /* XXX: if not enabled, really disable the seconday IDE controller */
+        pci_conf[0x51] = 0x80; /* enable IDE1 */
+    }
 
     pci_register_io_region((PCIDevice *)d, 0, 0x8, 
                            PCI_ADDRESS_SPACE_IO, ide_map);
@@ -2187,11 +2349,13 @@ void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table)
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
     pci_conf[0x3d] = 0x01; // interrupt on pin 1
-
+    
     for(i = 0; i < 4; i++)
         d->ide_if[i].pci_dev = (PCIDevice *)d;
-    ide_init2(&d->ide_if[0], 16, hd_table[0], hd_table[1]);
-    ide_init2(&d->ide_if[2], 16, hd_table[2], hd_table[3]);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
+              cmd646_set_irq, d, 0);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
+              cmd646_set_irq, d, 1);
 }
 
 /* hd_table must contain 4 block drivers */
@@ -2206,11 +2370,14 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
                                            sizeof(PCIIDEState),
                                            ((PCIDevice *)piix3_state)->devfn + 1, 
                                            NULL, NULL);
+    d->type = IDE_TYPE_PIIX3;
+
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0x86; // Intel
     pci_conf[0x01] = 0x80;
     pci_conf[0x02] = 0x10;
     pci_conf[0x03] = 0x70;
+    pci_conf[0x09] = 0x80; // legacy ATA mode
     pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
@@ -2218,8 +2385,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
     pci_register_io_region((PCIDevice *)d, 4, 0x10, 
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]);
-    ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
+              pic_set_irq_new, isa_pic, 14);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
+              pic_set_irq_new, isa_pic, 15);
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 }
@@ -2337,15 +2506,14 @@ static CPUReadMemoryFunc *pmac_ide_read[] = {
 /* PowerMac uses memory mapped registers, not I/O. Return the memory
    I/O index to access the ide. */
 int pmac_ide_init (BlockDriverState **hd_table,
-                   openpic_t *openpic, int irq)
+                   SetIRQFunc *set_irq, void *irq_opaque, int irq)
 {
     IDEState *ide_if;
     int pmac_ide_memory;
 
     ide_if = qemu_mallocz(sizeof(IDEState) * 2);
-    ide_init2(&ide_if[0], irq, hd_table[0], hd_table[1]);
-    ide_if[0].openpic = openpic;
-    ide_if[1].openpic = openpic;
+    ide_init2(&ide_if[0], hd_table[0], hd_table[1],
+              set_irq, irq_opaque, irq);
     
     pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
                                              pmac_ide_write, &ide_if[0]);