qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Update i440FX/PIIX3 emulation


From: Michael Hanselmann
Subject: [Qemu-devel] [PATCH] Update i440FX/PIIX3 emulation
Date: Thu, 25 Oct 2007 00:42:22 +0200
User-agent: Mutt/1.5.16 (2007-06-09)

The patch below updates the i440FX/PIIX3 emulation. It does:
- Add links to all datasheets containing the specifications
- Combine initialization functions for the PIIX, PIIX3 and PIIX4 chips
- Break apart long lists of magic values and name them
- Set more registers to their default values from the specs

Signed-off-by: Michael Hanselmann <address@hidden>

---
This does not yet remove the workaround introduced by Igor Lvovsky's
patch. However, I'm working on that since it, despite my earlier mail,
seems to help with my ACPI shutdown problem.

Greets,
Michael

Index: hw/piix_pci.c
===================================================================
RCS file: /sources/qemu/qemu/hw/piix_pci.c,v
retrieving revision 1.12
diff -u -p -r1.12 piix_pci.c
--- hw/piix_pci.c       20 Oct 2007 20:36:52 -0000      1.12
+++ hw/piix_pci.c       24 Oct 2007 22:39:41 -0000
@@ -22,12 +22,37 @@
  * THE SOFTWARE.
  */
 
+/*
+ * Datasheets:
+ * - 82371FB (PIIX) and 82371SB (PIIX3) PCI ISA IDE Xcelerator
+ *   http://www.intel.com/design/intarch/datashts/290550.htm
+ * - 82371AB PCI-TO-ISA/IDE Xcelerator (PIIX4)
+ *   http://www.intel.com/design/intarch/datashts/290562.htm
+ * - 82371SB (PIIX3) PCIset Specification Update
+ *   http://www.intel.com/design/chipsets/specupdt/297658.htm
+ * - 82371EB (PIIX4E) Specification Update
+ *   http://developer.intel.com/design/chipsets/specupdt/290635.htm
+ * - 82371AB PIIX4, 82371EB PIIX4E and 82371MB PIIX4M Specification Update
+ *   http://www.intel.com/design/chipsets/specupdt/297738.htm
+ * - 440FX PCIset - 82441FX PCI and Memory Controller (PMC) and 82442FX Data
+ *   Bus Accelerator (DBX) Datasheet
+ *   http://developer.intel.com/design/chipsets/datashts/290549.htm
+ * - 440FX PCIset 82441FX (PMC) and 82442FX (DBX) Specification Update
+ *   http://developer.intel.com/design/chipsets/specupdt/297654.htm
+ */
+
 #include "vl.h"
 typedef uint32_t pci_addr_t;
 #include "pci_host.h"
 
 typedef PCIHostState I440FXState;
 
+enum PCIChip {
+    PIIX,
+    PIIX3,
+    PIIX4
+};
+
 static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
 {
     I440FXState *s = opaque;
@@ -178,16 +203,52 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_
     d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
                             NULL, i440fx_write_config);
 
-    d->config[0x00] = 0x86; // vendor_id
+    /* Vendor Identification */
+    d->config[0x00] = 0x86; /* Intel */
     d->config[0x01] = 0x80;
-    d->config[0x02] = 0x37; // device_id
+
+    /* Device Identification */
+    d->config[0x02] = 0x37;
     d->config[0x03] = 0x12;
-    d->config[0x08] = 0x02; // revision
+
+    /* PCI Command Register */
+    d->config[0x04] = 0x06;
+    d->config[0x05] = 0x00;
+
+    /* PCI Status Register */
+    d->config[0x06] = 0x00; /* Default would be 0x80, but we don't support
+                               fast back-to-back transactions as described
+                               in the 440FX datasheet. */
+    d->config[0x07] = 0x02;
+
+    /* Revision Identification */
+    d->config[0x08] = 0x02;
+
+    /* Class Code */
     d->config[0x0a] = 0x00; // class_sub = host2pci
     d->config[0x0b] = 0x06; // class_base = PCI_bridge
-    d->config[0x0e] = 0x00; // header_type
 
-    d->config[0x72] = 0x02; /* SMRAM */
+    /* Header Type */
+    d->config[0x0e] = 0x00;
+
+    /* PMC Configuration */
+    d->config[0x50] = 0x02;
+    d->config[0x51] = 0x00;
+
+    /* DBX Buffer Control */
+    d->config[0x53] = 0x80;
+
+    /* DRAM Control */
+    d->config[0x57] = 0x01;
+
+    /* DRAM Timing */
+    d->config[0x58] = 0x10;
+
+    /* CPU Latency Timer */
+    d->config[0x71] = 0x10;
+
+    /* System Management RAM Control */
+    d->config[0x72] = 0x02;
 
     register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
     *pi440fx_state = d;
@@ -208,7 +269,7 @@ static void piix3_set_irq(qemu_irq *pic,
 {
     int i, pic_irq, pic_level;
 
-    piix3_dev->config[0x60 + irq_num] &= ~0x80;   // enable bit
+    piix3_dev->config[0x60 + irq_num] &= ~0x80;
     pci_irq_levels[irq_num] = level;
 
     /* now we change the pic irq level according to the piix irq mappings */
@@ -226,160 +287,195 @@ static void piix3_set_irq(qemu_irq *pic,
     }
 }
 
-static void piix3_reset(PCIDevice *d)
+static void piix_save(QEMUFile* f, void *opaque)
 {
-    uint8_t *pci_conf = d->config;
+    PCIDevice *d = opaque;
+    pci_device_save(d, f);
+}
 
-    pci_conf[0x04] = 0x07; // master, memory and I/O
-    pci_conf[0x05] = 0x00;
-    pci_conf[0x06] = 0x00;
-    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
-    pci_conf[0x4c] = 0x4d;
-    pci_conf[0x4e] = 0x03;
-    pci_conf[0x4f] = 0x00;
-    pci_conf[0x60] = 0x80;
-    pci_conf[0x69] = 0x02;
-    pci_conf[0x70] = 0x80;
-    pci_conf[0x76] = 0x0c;
-    pci_conf[0x77] = 0x0c;
-    pci_conf[0x78] = 0x02;
-    pci_conf[0x79] = 0x00;
-    pci_conf[0x80] = 0x00;
-    pci_conf[0x82] = 0x00;
-    pci_conf[0xa0] = 0x08;
-    pci_conf[0xa2] = 0x00;
-    pci_conf[0xa3] = 0x00;
-    pci_conf[0xa4] = 0x00;
-    pci_conf[0xa5] = 0x00;
-    pci_conf[0xa6] = 0x00;
-    pci_conf[0xa7] = 0x00;
-    pci_conf[0xa8] = 0x0f;
-    pci_conf[0xaa] = 0x00;
-    pci_conf[0xab] = 0x00;
-    pci_conf[0xac] = 0x00;
-    pci_conf[0xae] = 0x00;
+static int piix_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIDevice *d = opaque;
+    if (version_id != 2)
+        return -EINVAL;
+    return pci_device_load(d, f);
 }
 
-static void piix4_reset(PCIDevice *d)
+/*
+ * The PIIX, PIIX3 and PIIX4 chips share many registers. Thus the two previous
+ * initialization functions were collapsed into this single one.
+ */
+static void piix_generic_init(PCIDevice *d, const enum PCIChip chip)
 {
     uint8_t *pci_conf = d->config;
 
-    pci_conf[0x04] = 0x07; // master, memory and I/O
+    /* Vendor Identification */
+    pci_conf[0x00] = 0x86; /* Intel */
+    pci_conf[0x01] = 0x80;
+
+    /* Device Identification */
+    if (chip == PIIX) {
+        pci_conf[0x02] = 0x2E; /* 82371FB PIIX PCI-to-ISA bridge */
+        pci_conf[0x03] = 0x12;
+    } else if (chip == PIIX3) {
+        pci_conf[0x02] = 0x00; /* 82371SB PIIX3 PCI-to-ISA bridge */
+        pci_conf[0x03] = 0x70;
+    } else if (chip == PIIX4) {
+        pci_conf[0x02] = 0x10; /* 82371AB/EB/MB PIIX4 PCI-to-ISA bridge */
+        pci_conf[0x03] = 0x71;
+    }
+
+    /* PCI Command */
+    pci_conf[0x04] = 0x07; /* master, memory and I/O */
     pci_conf[0x05] = 0x00;
-    pci_conf[0x06] = 0x00;
-    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+
+    /* PCI Device Status */
+    if (chip == PIIX || chip == PIIX3) {
+        pci_conf[0x06] = 0x00;
+        pci_conf[0x07] = 0x02;
+    } else if (chip == PIIX4) {
+        pci_conf[0x06] = 0x00; /* Default would be 0x80, but we don't support
+                                  fast back-to-back transactions as described
+                                  in the PIIX4 datasheet. */
+        pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
+    }
+
+    /* Revision Identification */
+    if (chip == PIIX) {
+        /* Step A1 */
+        pci_conf[0x08] = 0x02;
+    } else if (chip == PIIX3 || chip == PIIX4) {
+        pci_conf[0x08] = 0x00;
+    }
+
+    /* Class Code */
+    pci_conf[0x0a] = 0x01; /* class_sub = PCI_ISA */
+    pci_conf[0x0b] = 0x06; /* class_base = PCI_bridge */
+
+    /* Header Type */
+    pci_conf[0x0e] = 0x80; /* PCI_multifunction, generic */
+
+    /* ISA I/O Recovery Timer */
     pci_conf[0x4c] = 0x4d;
+
+    /* X-Bus Chip Select */
     pci_conf[0x4e] = 0x03;
     pci_conf[0x4f] = 0x00;
-    pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
-    pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
-    pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
-    pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+
+    /* PCI IRQ Route Control */
+    if (chip == PIIX || chip == PIIX3) {
+        pci_conf[0x60] = 0x80;
+    } else if (chip == PIIX4) {
+        pci_conf[0x60] = 0x0a; /* PCI A -> IRQ 10 */
+        pci_conf[0x61] = 0x0a; /* PCI B -> IRQ 10 */
+        pci_conf[0x62] = 0x0b; /* PCI C -> IRQ 11 */
+        pci_conf[0x63] = 0x0b; /* PCI D -> IRQ 11 */
+    }
+
+    if (chip == PIIX4) {
+        /* Serial IRQ Control */
+        pci_conf[0x64] = 0x10;
+    }
+
+    /* Top of Memory */
     pci_conf[0x69] = 0x02;
-    pci_conf[0x70] = 0x80;
+
+    if (chip == PIIX || chip == PIIX3) {
+        /* Motherboard IRQ Route Control 0 */
+        pci_conf[0x70] = 0x80;
+    }
+
+    if (chip == PIIX) {
+        /* Motherboard IRQ Route Control 1 */
+        pci_conf[0x71] = 0x80;
+    }
+
+    /* Motherboard Device DMA Control */
+    /* Disable DMA */
     pci_conf[0x76] = 0x0c;
     pci_conf[0x77] = 0x0c;
-    pci_conf[0x78] = 0x02;
-    pci_conf[0x79] = 0x00;
+
+    if (chip == PIIX || chip == PIIX3) {
+        /* Programmable Chip Select Control */
+        pci_conf[0x78] = 0x02;
+        pci_conf[0x79] = 0x00;
+    }
+
+    /* APIC Base Address Relocation */
     pci_conf[0x80] = 0x00;
-    pci_conf[0x82] = 0x00;
-    pci_conf[0xa0] = 0x08;
-    pci_conf[0xa2] = 0x00;
-    pci_conf[0xa3] = 0x00;
-    pci_conf[0xa4] = 0x00;
-    pci_conf[0xa5] = 0x00;
-    pci_conf[0xa6] = 0x00;
-    pci_conf[0xa7] = 0x00;
-    pci_conf[0xa8] = 0x0f;
-    pci_conf[0xaa] = 0x00;
-    pci_conf[0xab] = 0x00;
-    pci_conf[0xac] = 0x00;
-    pci_conf[0xae] = 0x00;
-}
 
-static void piix_save(QEMUFile* f, void *opaque)
-{
-    PCIDevice *d = opaque;
-    pci_device_save(d, f);
-}
+    if (chip == PIIX3) {
+        /* Deterministic Latency Control */
+        pci_conf[0x82] = 0x00;
+    }
 
-static int piix_load(QEMUFile* f, void *opaque, int version_id)
-{
-    PCIDevice *d = opaque;
-    if (version_id != 2)
-        return -EINVAL;
-    return pci_device_load(d, f);
+    if (chip == PIIX || chip == PIIX3) {
+        /* SMI Control */
+        pci_conf[0xa0] = 0x08;
+
+        /* SMI Enable */
+        pci_conf[0xa2] = 0x00;
+        pci_conf[0xa3] = 0x00;
+
+        /* System Event Enable */
+        pci_conf[0xa4] = 0x00;
+        pci_conf[0xa5] = 0x00;
+        pci_conf[0xa6] = 0x00;
+        pci_conf[0xa7] = 0x00;
+
+        /* Fast Off Timer */
+        pci_conf[0xa8] = 0x0f;
+
+        /* SMI Request */
+        pci_conf[0xaa] = 0x00;
+        pci_conf[0xab] = 0x00;
+
+        /* Clock Scale STPCLK# Low Timer */
+        pci_conf[0xac] = 0x00;
+
+        /* Clock Scale STPCLK# High Timer */
+        pci_conf[0xae] = 0x00;
+    }
 }
 
 int piix_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
-    uint8_t *pci_conf;
 
     d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
-                                    devfn, NULL, NULL);
+                            devfn, NULL, NULL);
     register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
+    piix_generic_init(d, PIIX);
 
     piix3_dev = d;
-    pci_conf = d->config;
-
-    pci_conf[0x00] = 0x86; // Intel
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
-    pci_conf[0x03] = 0x12;
-    pci_conf[0x08] = 0x02; // Step A1
-    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
-    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
-    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
 
-    piix3_reset(d);
     return d->devfn;
 }
 
 int piix3_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
-    uint8_t *pci_conf;
 
     d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    devfn, NULL, NULL);
+                            devfn, NULL, NULL);
     register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
+    piix_generic_init(d, PIIX3);
 
     piix3_dev = d;
-    pci_conf = d->config;
 
-    pci_conf[0x00] = 0x86; // Intel
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
-    pci_conf[0x03] = 0x70;
-    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
-    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
-    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
-
-    piix3_reset(d);
     return d->devfn;
 }
 
 int piix4_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
-    uint8_t *pci_conf;
 
     d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
-                                    devfn, NULL, NULL);
+                            devfn, NULL, NULL);
     register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+    piix_generic_init(d, PIIX4);
 
     piix4_dev = d;
-    pci_conf = d->config;
-
-    pci_conf[0x00] = 0x86; // Intel
-    pci_conf[0x01] = 0x80;
-    pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
-    pci_conf[0x03] = 0x71;
-    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
-    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
-    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
 
-    piix4_reset(d);
     return d->devfn;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]