diff options
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/i86pc/io/pci/pci_boot.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/usr/src/uts/i86pc/io/pci/pci_boot.c b/usr/src/uts/i86pc/io/pci/pci_boot.c index 869c89d68c..57a70cbaa3 100644 --- a/usr/src/uts/i86pc/io/pci/pci_boot.c +++ b/usr/src/uts/i86pc/io/pci/pci_boot.c @@ -83,6 +83,85 @@ extern int pci_slot_names_prop(int, char *, int); /* set non-zero to force PCI peer-bus renumbering */ int pci_bus_always_renumber = 0; +/* get the subordinate bus # for a root/peer bus */ +static int +pci_root_subbus(int bus, uchar_t *subbus) +{ + ACPI_HANDLE hdl; + ACPI_BUFFER rb; + ACPI_RESOURCE *rp; + int rv; + + if (pci_bus_res[bus].dip == NULL) { + /* non-used bus # */ + return (AE_ERROR); + } + if (acpica_find_pciobj(pci_bus_res[bus].dip, &hdl) != AE_OK) { + cmn_err(CE_WARN, "!No ACPI obj for bus%d, ACPI OFF?\n", bus); + return (AE_ERROR); + } + + rb.Length = ACPI_ALLOCATE_BUFFER; + if (AcpiGetCurrentResources(hdl, &rb) != AE_OK) { + cmn_err(CE_WARN, "!_CRS failed on pci%d\n", bus); + return (AE_ERROR); + } + + rv = AE_ERROR; + + for (rp = rb.Pointer; rp->Type != ACPI_RESOURCE_TYPE_END_TAG; + rp = ACPI_NEXT_RESOURCE(rp)) { + + switch (rp->Type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: + if (rp->Data.Address.ResourceType + != ACPI_BUS_NUMBER_RANGE) + continue; + *subbus = (uchar_t)rp->Data.Address16.Maximum; + dcmn_err(CE_NOTE, "Address16,subbus=%d\n", *subbus); + break; + case ACPI_RESOURCE_TYPE_ADDRESS32: + if (rp->Data.Address.ResourceType + != ACPI_BUS_NUMBER_RANGE) + continue; + *subbus = (uchar_t)rp->Data.Address32.Maximum; + dcmn_err(CE_NOTE, "Address32,subbus=%d\n", *subbus); + break; + case ACPI_RESOURCE_TYPE_ADDRESS64: + if (rp->Data.Address.ResourceType + != ACPI_BUS_NUMBER_RANGE) + continue; + *subbus = (uchar_t)rp->Data.Address64.Maximum; + dcmn_err(CE_NOTE, "Address64,subbus=%d\n", *subbus); + break; + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + if (rp->Data.Address.ResourceType + != ACPI_BUS_NUMBER_RANGE) + continue; + *subbus = (uchar_t)rp->Data.ExtAddress64.Maximum; + dcmn_err(CE_NOTE, "ExtAdr64,subbus=%d\n", *subbus); + break; + default: + dcmn_err(CE_NOTE, "rp->Type=%d\n", rp->Type); + continue; + } + + /* found the bus-range resource */ + dcmn_err(CE_NOTE, "pci%d, subbus=%d\n", bus, *subbus); + rv = AE_OK; + + /* This breaks out of the resource scanning loop */ + break; + } + + AcpiOsFree(rb.Pointer); + if (rv != AE_OK) + cmn_err(CE_NOTE, "!No bus-range resource for pci%d\n", bus); + + return (rv); + +} + /* * Enumerate all PCI devices */ @@ -126,11 +205,6 @@ pci_setup_tree() add_bus_slot_names_prop(i); } - /* add bus-range property for root/peer bus nodes */ - for (i = 0; i <= pci_bios_nbus; i++) { - if (pci_bus_res[i].par_bus == (uchar_t)-1) - add_bus_range_prop(i); - } } /* @@ -277,6 +351,16 @@ pci_reprogram(void) */ pci_renumber_root_busses(); + /* add bus-range property for root/peer bus nodes */ + for (i = 0; i <= pci_bios_nbus; i++) { + if (pci_bus_res[i].par_bus == (uchar_t)-1) { + uchar_t subbus; + if (pci_root_subbus(i, &subbus) == AE_OK) + pci_bus_res[i].sub_bus = subbus; + add_bus_range_prop(i); + } + } + if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "pci-reprog", &onoff) == DDI_SUCCESS) { if (strcmp(onoff, "off") == 0) { |