[OpenBIOS] [PATCH 6/8] pci: configure base and limit registers during PCI bridge configuration

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Sun Jun 11 12:00:35 CEST 2017


Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
 drivers/pci.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 drivers/pci.h |    5 +++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/pci.c b/drivers/pci.c
index e203aa4..eafec32 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -1283,6 +1283,8 @@ static void ob_configure_pci_bridge(pci_addr addr,
                                     unsigned long *io_base,
                                     int primary_bus, pci_config_t *config)
 {
+    unsigned long old_mem_base, old_io_base;
+    uint16_t cmd;
     phandle_t ph;
 
     config->primary_bus = primary_bus;
@@ -1302,6 +1304,29 @@ static void ob_configure_pci_bridge(pci_addr addr,
     ph = find_dev(config->path);
     set_int_property(ph, "bus-range", *bus_num);
 
+    /* Always expose the legacy ioports on the first PCI bridge. If we
+       must have legacy devices behind a PCI bridge then they must be
+       on the first one discovered to ensure that the ioports will work. */
+    if (*io_base < 0x1000) {
+        *io_base = 0x0;
+    }
+
+    /* Align mem_base up to nearest MB, io_base up to nearest 4K */
+    old_mem_base = (*mem_base + 0xfffff - 1) & ~(0xfffff - 1);
+    *mem_base = old_mem_base;
+    old_io_base = (*io_base + 0xfff - 1) & ~(0xfff - 1);
+    *io_base = old_io_base;
+
+    /* Set the base limit registers */
+    pci_config_write16(addr, PCI_MEMORY_BASE, ((*mem_base >> 16) & ~(0xf)));
+    pci_config_write8(addr, PCI_IO_BASE, ((*io_base >> 8) & ~(0xf)));
+
+    /* Always ensure legacy ioports are accessible during enumeration.
+       Some drivers (e.g. IDE) will attempt ioport access as part of
+       the configuration process, so we allow them during the secondary
+       bus scan and then set the correct IO limit below. */
+    pci_config_write8(addr, PCI_IO_LIMIT, (((*io_base + 0xffff - 1) >> 8) & ~(0xf)));    
+
     /* make pci bridge parent device, prepare for recursion */
 
     ob_scan_pci_bus(bus_num, mem_base, io_base,
@@ -1315,6 +1340,24 @@ static void ob_configure_pci_bridge(pci_addr addr,
             config->path, config->primary_bus, config->secondary_bus,
             config->subordinate_bus);
 
+    /* Align mem_base up to nearest MB, io_base up to nearest 4K */
+    *mem_base = (*mem_base + 0xfffff - 1) & ~(0xfffff - 1);
+    *io_base = (*io_base + 0xfff - 1) & ~(0xfff - 1);
+
+    /* Set the limit registers */
+    pci_config_write16(addr, PCI_MEMORY_LIMIT, (((*mem_base - 1) >> 16) & ~(0xf)));
+    pci_config_write8(addr, PCI_IO_LIMIT, (((*io_base - 1) >> 8) & ~(0xf)));
+
+    /* Disable unused address spaces */
+    cmd = pci_config_read16(addr, PCI_COMMAND);
+    if (*mem_base == old_mem_base) {
+        pci_config_write16(addr, PCI_COMMAND, (cmd & ~PCI_COMMAND_MEMORY));
+    }
+
+    if (*io_base == old_io_base) {
+        pci_config_write16(addr, PCI_COMMAND, (cmd & ~PCI_COMMAND_IO));
+    }
+
     pci_set_bus_range(config);
 }
 
diff --git a/drivers/pci.h b/drivers/pci.h
index d5aa5f8..ea70e8a 100644
--- a/drivers/pci.h
+++ b/drivers/pci.h
@@ -46,6 +46,11 @@
 #define PCI_BASE_ADDR_4		0x20
 #define PCI_BASE_ADDR_5		0x24
 
+#define PCI_IO_BASE		0x1c
+#define PCI_IO_LIMIT		0x1d
+#define PCI_MEMORY_BASE		0x20
+#define PCI_MEMORY_LIMIT	0x22
+
 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c
 #define PCI_SUBSYSTEM_ID        0x2e
 
-- 
1.7.10.4




More information about the OpenBIOS mailing list