In order to progress further with sun4u in QEMU, it has become necessary to introduce PCI bridges similar to a real Ultra 5. This is because several OSs make assumptions about the PCI topology, and without the PCI bridge in place will either crash or fail to map memory regions correctly.
This first patchset fixes up PCI bridges so that we can now enumerate them correctly. As an idea as to where I'm going with this, if you also take the WIP QEMU branch at https://github.com/mcayland/qemu/tree/sparc64-pcibridge then the output of show-devs looks like this:
Welcome to OpenBIOS v1.1 built on Jun 11 2017 06:57 Type 'help' for detailed information
0 > show-devs ffe1bf40 / ffe1c118 /aliases ffe1c240 /openprom (BootROM) ffe26b58 /openprom/client-services ffe1c4f8 /options ffe1c5d8 /chosen ffe1c718 /builtin ffe1c840 /builtin/console ffe26620 /packages ffe28648 /packages/cmdline ffe28898 /packages/disk-label ffe2c8e0 /packages/deblocker ffe2cef8 /packages/grubfs-files ffe2d308 /packages/sun-parts ffe2d720 /packages/elf-loader ffe2b218 /memory@0,0 (memory) ffe2b378 /virtual-memory ffe2d880 /pci@1fe,0 (pci) ffe2e1b0 /pci@1fe,0/pci@1 (pci) ffe2e8c8 /pci@1fe,0/pci@1,1 (pci) ffe2efb0 /pci@1fe,0/pci@1,1/ebus@1 ffe2f7f0 /pci@1fe,0/pci@1,1/ebus@1/eeprom@0 ffe2f968 /pci@1fe,0/pci@1,1/ebus@1/fdthree@0 (block) ffe2feb8 /pci@1fe,0/pci@1,1/ebus@1/su@0 (serial) ffe30248 /pci@1fe,0/pci@1,1/ebus@1/kb_ps2@0 (serial) ffe305b8 /pci@1fe,0/pci@1,1/QEMU,VGA@2 (display) ffe31c30 /pci@1fe,0/pci@1,1/pci-ata@3 (pci-ide) ffe32188 /pci@1fe,0/pci@1,1/pci-ata@3/ide0@4000 (ide) ffe32468 /pci@1fe,0/pci@1,1/pci-ata@3/ide1@4100 (ide) ffe32700 /pci@1fe,0/pci@1,1/pci-ata@3/ide1@4100/cdrom@0 (block) ffe32d88 /pci@1fe,0/NE2000@2 (network) ffe33490 /SUNW,UltraSPARC-IIi (cpu) ok
Note I have several more SPARC64-related fixes queued, however as this patchset is starting to get quite unwieldy it makes sense to split this part off separately.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (8): pci: add temporary bus-range property to PCI bridge devices pci: include PCI bus id in ob_pci_decode_unit() pci: create new ob_pci_bridge_node based upon ob_pci_bus_node pci: rename ob_pci_map_in() to ob_pci_bus_map_in() pci: implement ob_pci_bridge_map_in() for PCI-PCI bridge nodes pci: configure base and limit registers during PCI bridge configuration pci: split PCI bus interrupt maps from PCI host bridge interrupt maps pci: allow ob_pci_bus_set_interrupt_map() to take a callback function
drivers/pci.c | 186 ++++++++++++++++++++++++++++++++++++++++++++------------- drivers/pci.h | 5 ++ 2 files changed, 150 insertions(+), 41 deletions(-)
This enables the bridge (and also any children) to determine their bus number during the secondary PCI bus scan.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index d56a40e..f8d18c4 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1262,6 +1262,8 @@ static void ob_configure_pci_bridge(pci_addr addr, unsigned long *io_base, int primary_bus, pci_config_t *config) { + phandle_t ph; + config->primary_bus = primary_bus; pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
@@ -1274,6 +1276,11 @@ static void ob_configure_pci_bridge(pci_addr addr, PCI_DPRINTF("scanning new pci bus %u under bridge %s\n", config->secondary_bus, config->path);
+ /* Temporarily add bus-range property to allow the secondary bus to + determine its bus num */ + ph = find_dev(config->path); + set_int_property(ph, "bus-range", *bus_num); + /* make pci bridge parent device, prepare for recursion */
ob_scan_pci_bus(bus_num, mem_base, io_base,
Instead of hard-coding the bus id to 0, grab the bus id from the first word of the "bus-range" property. In particular this allows us to correctly navigate the DT when trying to access a node with a unit id.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index f8d18c4..2a59a75 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -181,7 +181,7 @@ ob_pci_decode_unit(int *idx) ucell hi, mid, lo; const char *arg = pop_fstr_copy(); int dev, fn, reg, ss, n, p, t; - int bus = 0; /* no information */ + int bus, len; char *ptr;
PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx); @@ -273,6 +273,8 @@ ob_pci_decode_unit(int *idx) } free((char*)arg);
+ bus = get_int_property(get_cur_dev(), "bus-range", &len); + hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg;
PUSH(lo);
These two types of node will need to have slightly differing behaviours moving forwards.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 2a59a75..a442695 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -49,6 +49,7 @@ /* DECLARE data structures for the nodes. */
DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) ); +DECLARE_UNNAMED_NODE( ob_pci_bridge_node, INSTALL_OPEN, 2*sizeof(int) ); DECLARE_UNNAMED_NODE( ob_pci_simple_node, 0, 2*sizeof(int) ); DECLARE_UNNAMED_NODE( ob_pci_empty_node, 0, 2*sizeof(int) );
@@ -400,6 +401,15 @@ NODE_METHODS(ob_pci_bus_node) = { { "pci-map-in", ob_pci_map_in }, };
+NODE_METHODS(ob_pci_bridge_node) = { + { NULL, ob_pci_initialize }, + { "open", ob_pci_open }, + { "close", ob_pci_close }, + { "decode-unit", ob_pci_decode_unit }, + { "encode-unit", ob_pci_encode_unit }, + { "pci-map-in", ob_pci_map_in }, +}; + NODE_METHODS(ob_pci_simple_node) = { { "open", ob_pci_open }, { "close", ob_pci_close }, @@ -1405,7 +1415,7 @@ static void ob_configure_pci_device(const char* parent_path, switch (class) { case PCI_BASE_CLASS_BRIDGE: if (subclass != PCI_SUBCLASS_BRIDGE_HOST) { - REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle); + REGISTER_NAMED_NODE_PHANDLE(ob_pci_bridge_node, config.path, phandle); } break; default:
This is in preparation for separating out the behaviour between host bridges and PCI bridges.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index a442695..07eca8a 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -353,7 +353,7 @@ ob_pci_encode_unit(int *idx) /* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */
static void -ob_pci_map_in(int *idx) +ob_pci_bus_map_in(int *idx) { phys_addr_t phys; uint32_t ba; @@ -398,7 +398,7 @@ NODE_METHODS(ob_pci_bus_node) = { { "close", ob_pci_close }, { "decode-unit", ob_pci_decode_unit }, { "encode-unit", ob_pci_encode_unit }, - { "pci-map-in", ob_pci_map_in }, + { "pci-map-in", ob_pci_bus_map_in }, };
NODE_METHODS(ob_pci_bridge_node) = { @@ -407,7 +407,7 @@ NODE_METHODS(ob_pci_bridge_node) = { { "close", ob_pci_close }, { "decode-unit", ob_pci_decode_unit }, { "encode-unit", ob_pci_encode_unit }, - { "pci-map-in", ob_pci_map_in }, + { "pci-map-in", ob_pci_bus_map_in }, };
NODE_METHODS(ob_pci_simple_node) = {
As indicated by the IEEE-1275 PCI bindings, PCI-PCI bridges should call call the map-in method of the parent.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 07eca8a..e203aa4 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -401,13 +401,22 @@ NODE_METHODS(ob_pci_bus_node) = { { "pci-map-in", ob_pci_bus_map_in }, };
+/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ + +static void +ob_pci_bridge_map_in(int *idx) +{ + /* As per the IEEE-1275 PCI specification, chain up to the parent */ + call_parent_method("pci-map-in"); +} + NODE_METHODS(ob_pci_bridge_node) = { { NULL, ob_pci_initialize }, { "open", ob_pci_open }, { "close", ob_pci_close }, { "decode-unit", ob_pci_decode_unit }, { "encode-unit", ob_pci_encode_unit }, - { "pci-map-in", ob_pci_bus_map_in }, + { "pci-map-in", ob_pci_bridge_map_in }, };
NODE_METHODS(ob_pci_simple_node) = {
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@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
This is to allow us to generate interrupt maps for any PCI bus, not just the PCI host bridge.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index eafec32..7f652a8 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1551,21 +1551,17 @@ static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigne #define SUN4U_INTERRUPT(dev, irq_pin) \ ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
-static void ob_pci_host_set_interrupt_map(phandle_t host) +static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) { - phandle_t dnode = 0, pci_childnode = 0; - u32 props[128], intno; - int i, ncells, len; - u32 *val, addr; - char *reg; - #if defined(CONFIG_PPC) - phandle_t target_node; + /* Set the host bridge interrupt map, returning the phandle + of the interrupt controller */ + phandle_t dnode, target_node; char *path, buf[256];
/* Oldworld macs do interrupt maps differently */ if (!is_newworld()) - return; + return 0;
PCI_DPRINTF("setting up interrupt map for host %x\n", host); dnode = dt_iterate_type(0, "open-pic"); @@ -1612,16 +1608,29 @@ static void ob_pci_host_set_interrupt_map(phandle_t host)
target_node = find_dev(path); set_int_property(target_node, "interrupt-parent", dnode); + + return dnode; } -#else - /* PCI host bridge is the default interrupt controller */ - dnode = host; #endif
+ return host; +} + +static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode) +{ /* Set interrupt-map for PCI devices with an interrupt pin present */ - ncells = 0; + phandle_t pci_childnode = 0; + u32 props[128], intno; + int i, ncells = 0, len; + u32 *val, addr; + char *reg; + + /* If no destination node specified, do nothing */ + if (dnode == 0) { + return; + }
- PUSH(host); + PUSH(pcibus); fword("child"); pci_childnode = POP(); while (pci_childnode) { @@ -1660,13 +1669,13 @@ static void ob_pci_host_set_interrupt_map(phandle_t host) fword("peer"); pci_childnode = POP(); } - set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0])); + set_property(pcibus, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
props[0] = 0x0000f800; props[1] = 0x0; props[2] = 0x0; props[3] = 0x7; - set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); + set_property(pcibus, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); }
int ob_pci_init(void) @@ -1676,7 +1685,7 @@ int ob_pci_init(void) unsigned long mem_base, io_base;
pci_config_t config = {}; /* host bridge */ - phandle_t phandle_host = 0; + phandle_t phandle_host = 0, intc;
PCI_DPRINTF("Initializing PCI host bridge...\n");
@@ -1728,7 +1737,8 @@ int ob_pci_init(void) ob_pci_set_available(phandle_host, mem_base, io_base);
/* configure the host bridge interrupt map */ - ob_pci_host_set_interrupt_map(phandle_host); + intc = ob_pci_host_set_interrupt_map(phandle_host); + ob_pci_bus_set_interrupt_map(phandle_host, intc);
device_end();
This serves 2 purposes: firstly it means that each PCI bridge can set its own custom interrupt-map and interrupt-mask if required, and secondly the interrupt properties can be split into per-architecure sections.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 69 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 23 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 7f652a8..ac7a249 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -1547,13 +1547,9 @@ static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigne set_property(host, "available", (char *)props, ncells * sizeof(props[0])); }
-/* Convert device/irq pin to interrupt property */ -#define SUN4U_INTERRUPT(dev, irq_pin) \ - ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f) - +#if defined(CONFIG_PPC) static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) { -#if defined(CONFIG_PPC) /* Set the host bridge interrupt map, returning the phandle of the interrupt controller */ phandle_t dnode, target_node; @@ -1611,12 +1607,53 @@ static phandle_t ob_pci_host_set_interrupt_map(phandle_t host)
return dnode; } -#endif
return host; }
-static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode) +static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno) +{ + *ncells += pci_encode_phys_addr(props + *ncells, 0, 0, addr, 0, 0); + props[(*ncells)++] = intno; + props[(*ncells)++] = dnode; + props[(*ncells)++] = arch->irqs[((intno - 1) + (addr >> 11)) & 3]; + props[(*ncells)++] = 1; +} + +#elif defined(CONFIG_SPARC64) + +/* Convert device/irq pin to interrupt property */ +#define SUN4U_INTERRUPT(dev, irq_pin) \ + ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f) + +static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) +{ + return host; +} + +static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno) +{ + *ncells += pci_encode_phys_addr(props + *ncells, 0, 0, addr, 0, 0); + props[(*ncells)++] = intno; + props[(*ncells)++] = dnode; + props[(*ncells)++] = SUN4U_INTERRUPT(addr, intno); +} + +#else + +static phandle_t ob_pci_host_set_interrupt_map(phandle_t host) +{ + return host; +} + +static void ob_pci_host_bus_interrupt(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno) +{ + return; +} +#endif + +static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode, + void (*func)(ucell dnode, u32 *props, int *ncells, u32 addr, u32 intno)) { /* Set interrupt-map for PCI devices with an interrupt pin present */ phandle_t pci_childnode = 0; @@ -1645,21 +1682,7 @@ static void ob_pci_bus_set_interrupt_map(phandle_t pcibus, phandle_t dnode)
/* Device address is in 1st 32-bit word of encoded PCI address for config space */ if ((addr & PCI_RANGE_TYPE_MASK) == PCI_RANGE_CONFIG) { -#if defined(CONFIG_SPARC64) - ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = intno; - props[ncells++] = dnode; - props[ncells++] = SUN4U_INTERRUPT(addr, intno); -#elif defined(CONFIG_PPC) - ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); - props[ncells++] = intno; - props[ncells++] = dnode; - props[ncells++] = arch->irqs[((intno - 1) + (addr >> 11)) & 3]; - props[ncells++] = 1; -#else - /* Keep compiler quiet */ - dnode = dnode; -#endif + (*func)(dnode, props, &ncells, addr, intno); } } } @@ -1738,7 +1761,7 @@ int ob_pci_init(void)
/* configure the host bridge interrupt map */ intc = ob_pci_host_set_interrupt_map(phandle_host); - ob_pci_bus_set_interrupt_map(phandle_host, intc); + ob_pci_bus_set_interrupt_map(phandle_host, intc, ob_pci_host_bus_interrupt);
device_end();
On 11/06/17 11:00, Mark Cave-Ayland wrote:
In order to progress further with sun4u in QEMU, it has become necessary to introduce PCI bridges similar to a real Ultra 5. This is because several OSs make assumptions about the PCI topology, and without the PCI bridge in place will either crash or fail to map memory regions correctly.
This first patchset fixes up PCI bridges so that we can now enumerate them correctly. As an idea as to where I'm going with this, if you also take the WIP QEMU branch at https://github.com/mcayland/qemu/tree/sparc64-pcibridge then the output of show-devs looks like this:
Welcome to OpenBIOS v1.1 built on Jun 11 2017 06:57 Type 'help' for detailed information
0 > show-devs ffe1bf40 / ffe1c118 /aliases ffe1c240 /openprom (BootROM) ffe26b58 /openprom/client-services ffe1c4f8 /options ffe1c5d8 /chosen ffe1c718 /builtin ffe1c840 /builtin/console ffe26620 /packages ffe28648 /packages/cmdline ffe28898 /packages/disk-label ffe2c8e0 /packages/deblocker ffe2cef8 /packages/grubfs-files ffe2d308 /packages/sun-parts ffe2d720 /packages/elf-loader ffe2b218 /memory@0,0 (memory) ffe2b378 /virtual-memory ffe2d880 /pci@1fe,0 (pci) ffe2e1b0 /pci@1fe,0/pci@1 (pci) ffe2e8c8 /pci@1fe,0/pci@1,1 (pci) ffe2efb0 /pci@1fe,0/pci@1,1/ebus@1 ffe2f7f0 /pci@1fe,0/pci@1,1/ebus@1/eeprom@0 ffe2f968 /pci@1fe,0/pci@1,1/ebus@1/fdthree@0 (block) ffe2feb8 /pci@1fe,0/pci@1,1/ebus@1/su@0 (serial) ffe30248 /pci@1fe,0/pci@1,1/ebus@1/kb_ps2@0 (serial) ffe305b8 /pci@1fe,0/pci@1,1/QEMU,VGA@2 (display) ffe31c30 /pci@1fe,0/pci@1,1/pci-ata@3 (pci-ide) ffe32188 /pci@1fe,0/pci@1,1/pci-ata@3/ide0@4000 (ide) ffe32468 /pci@1fe,0/pci@1,1/pci-ata@3/ide1@4100 (ide) ffe32700 /pci@1fe,0/pci@1,1/pci-ata@3/ide1@4100/cdrom@0 (block) ffe32d88 /pci@1fe,0/NE2000@2 (network) ffe33490 /SUNW,UltraSPARC-IIi (cpu) ok
Note I have several more SPARC64-related fixes queued, however as this patchset is starting to get quite unwieldy it makes sense to split this part off separately.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (8): pci: add temporary bus-range property to PCI bridge devices pci: include PCI bus id in ob_pci_decode_unit() pci: create new ob_pci_bridge_node based upon ob_pci_bus_node pci: rename ob_pci_map_in() to ob_pci_bus_map_in() pci: implement ob_pci_bridge_map_in() for PCI-PCI bridge nodes pci: configure base and limit registers during PCI bridge configuration pci: split PCI bus interrupt maps from PCI host bridge interrupt maps pci: allow ob_pci_bus_set_interrupt_map() to take a callback function
drivers/pci.c | 186 ++++++++++++++++++++++++++++++++++++++++++++------------- drivers/pci.h | 5 ++ 2 files changed, 150 insertions(+), 41 deletions(-)
I've applied this to master since it is the foundation for further WIP patchsets that I have, plus it's fairly safe since before this patchset PCI bridges weren't working correctly at all which is why QEMU machines running OpenBIOS have avoided them ;)
ATB,
Mark.