added PIIX3 like IDE controller - PCI irq generation - SETFEATURES IDE command support
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 May 2004 19:10:26 +0000 (19:10 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 May 2004 19:10:26 +0000 (19:10 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@852 c046a42c-6fe2-441c-8c8c-71466251a162

hw/ide.c

index 35a0648..45974ae 100644 (file)
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -297,6 +297,7 @@ typedef struct IDEState {
     int64_t nb_sectors;
     int mult_sectors;
     int irq;
     int64_t nb_sectors;
     int mult_sectors;
     int irq;
+    PCIDevice *pci_dev;
     int drive_serial;
     /* ide regs */
     uint8_t feature;
     int drive_serial;
     /* ide regs */
     uint8_t feature;
@@ -463,7 +464,10 @@ static inline void ide_abort_command(IDEState *s)
 static inline void ide_set_irq(IDEState *s)
 {
     if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
 static inline void ide_set_irq(IDEState *s)
 {
     if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
-        pic_set_irq(s->irq, 1);
+        if (s->irq == 16)
+            pci_set_irq(s->pci_dev, 0, 1);
+        else
+            pic_set_irq(s->irq, 1);
     }
 }
 
     }
 }
 
@@ -1169,7 +1173,22 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             s->status = READY_STAT;
             ide_set_irq(s);
             break;
             s->status = READY_STAT;
             ide_set_irq(s);
             break;
-
+        case WIN_SETFEATURES:
+            if (!s->bs)
+                goto abort_cmd;
+            /* XXX: valid for CDROM ? */
+            switch(s->feature) {
+            case 0x02: /* write cache enable */
+            case 0x82: /* write cache disable */
+            case 0xaa: /* read look-ahead enable */
+            case 0x55: /* read look-ahead disable */
+                s->status = READY_STAT;
+                ide_set_irq(s);
+                break;
+            default:
+                goto abort_cmd;
+            }
+            break;
             /* ATAPI commands */
         case WIN_PIDENTIFY:
             if (s->is_cdrom) {
             /* ATAPI commands */
         case WIN_PIDENTIFY:
             if (s->is_cdrom) {
@@ -1262,7 +1281,10 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
             ret = 0;
         else
             ret = s->status;
             ret = 0;
         else
             ret = s->status;
-        pic_set_irq(s->irq, 0);
+        if (s->irq == 16)
+            pci_set_irq(s->pci_dev, 0, 0);
+        else
+            pic_set_irq(s->irq, 0);
         break;
     }
 #ifdef DEBUG_IDE
         break;
     }
 #ifdef DEBUG_IDE
@@ -1481,20 +1503,8 @@ static void ide_init2(IDEState *ide_state, int irq,
     }
 }
 
     }
 }
 
-/***********************************************************/
-/* ISA IDE definitions */
-
-void isa_ide_init(int iobase, int iobase2, int irq,
-                  BlockDriverState *hd0, BlockDriverState *hd1)
+static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2)
 {
 {
-    IDEState *ide_state;
-
-    ide_state = qemu_mallocz(sizeof(IDEState) * 2);
-    if (!ide_state)
-        return;
-    
-    ide_init2(ide_state, irq, hd0, hd1);
-
     register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state);
     register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state);
     if (iobase2) {
     register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state);
     register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state);
     if (iobase2) {
@@ -1510,6 +1520,22 @@ void isa_ide_init(int iobase, int iobase2, int irq,
 }
 
 /***********************************************************/
 }
 
 /***********************************************************/
+/* ISA IDE definitions */
+
+void isa_ide_init(int iobase, int iobase2, int irq,
+                  BlockDriverState *hd0, BlockDriverState *hd1)
+{
+    IDEState *ide_state;
+
+    ide_state = qemu_mallocz(sizeof(IDEState) * 2);
+    if (!ide_state)
+        return;
+    
+    ide_init2(ide_state, irq, hd0, hd1);
+    ide_init_ioport(ide_state, iobase, iobase2);
+}
+
+/***********************************************************/
 /* PCI IDE definitions */
 
 typedef struct PCIIDEState {
 /* PCI IDE definitions */
 
 typedef struct PCIIDEState {
@@ -1546,7 +1572,8 @@ void pci_ide_init(BlockDriverState **hd_table)
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
-    
+    int i;
+
     d = (PCIIDEState *)pci_register_device("IDE", sizeof(PCIIDEState),
                                            0, -1, 
                                            NULL, NULL);
     d = (PCIIDEState *)pci_register_device("IDE", sizeof(PCIIDEState),
                                            0, -1, 
                                            NULL, NULL);
@@ -1573,6 +1600,38 @@ void pci_ide_init(BlockDriverState **hd_table)
     pci_register_io_region((PCIDevice *)d, 3, 0x4, 
                            PCI_ADDRESS_SPACE_IO, ide_map);
 
     pci_register_io_region((PCIDevice *)d, 3, 0x4, 
                            PCI_ADDRESS_SPACE_IO, ide_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]);
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
+void pci_piix3_ide_init(BlockDriverState **hd_table)
+{
+    PCIIDEState *d;
+    uint8_t *pci_conf;
+    
+    /* register a function 1 of PIIX3 */
+    d = (PCIIDEState *)pci_register_device("PIIX3 IDE", sizeof(PCIIDEState),
+                                           0, ((PCIDevice *)piix3_state)->devfn + 1, 
+                                           NULL, NULL);
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10;
+    pci_conf[0x03] = 0x70;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+    pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+    pci_conf[0x0e] = 0x00; // header_type
+
+    /* XXX: must add BMDMA support to be fully compliant */
+
     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], 14, hd_table[0], hd_table[1]);
     ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]);
+    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 }
 }