diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 29e1700ce4..f608476a0e 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -41,13 +41,13 @@ pci_get_nth_pci_info(long index, pci_info *outInfo) uint32 -pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size) +pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size) { uint8 bus; int domain; uint32 value; - if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK) + if (sPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) return 0xffffffff; if (sPCI->ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK) @@ -58,12 +58,12 @@ pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint void -pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value) +pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value) { uint8 bus; int domain; - if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK) + if (sPCI->ResolveVirtualBus(virtualBus, &domain, &bus) != B_OK) return; sPCI->WritePciConfig(domain, bus, device, function, offset, size, value); @@ -313,6 +313,8 @@ PCI::PCI() : fRootBus(0) , fDomainCount(0) , fBusEnumeration(false) + , fVirtualBusMap() + , fNextVirtualBus(0) { #if defined(__POWERPC__) || defined(__M68K__) fBusEnumeration = true; @@ -360,31 +362,72 @@ PCI::~PCI() status_t -PCI::AddVirtBus(int domain, uint8 bus, uint8 *virt_bus) +PCI::CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus) { - if (MAX_PCI_DOMAINS != 8) - panic("PCI::AddVirtBus only 8 controllers supported"); - - if (domain > 7) - panic("PCI::AddVirtBus domain %d too large", domain); +#if defined(__INTEL__) - if (bus > 31) - panic("PCI::AddVirtBus bus %d too large", bus); - - *virt_bus = (domain << 5) | bus; + // IA32 doesn't use domains + if (domain) + panic("PCI::CreateVirtualBus domain != 0"); + *virtualBus = bus; return B_OK; + +#else + + if (fNextVirtualBus > 0xff) + panic("PCI::CreateVirtualBus: virtual bus number space exhausted"); + if (unsigned(domain) > 0xff) + panic("PCI::CreateVirtualBus: domain %d too large", domain); + + uint16 value = domain << 8 | bus; + + // XXX iterate through entries 0 to fNextVirtualBus + // XXX and check if value is already present, return + // XXX key if found instead of inserting a new one + + *virtualBus = fNextVirtualBus++; + + dprintf("CreateVirtualBus domain %d, bus %d => virtualBus %d\n", domain, bus, *virtualBus); + + return fVirtualBusMap.Insert(*virtualBus, value); + +#endif } status_t -PCI::GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus) +PCI::ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus) { - // XXX if you modify this, also change pci_info.cpp print_info_basic() !! - *domain = virt_bus >> 5; - *bus = virt_bus & 0x1f; +#if defined(__INTEL__) + + // IA32 doesn't use domains + *bus = virtualBus; + *domain = 0; return B_OK; + +#else + + if (virtualBus >= fNextVirtualBus) + return B_ERROR; + + uint16 value = fVirtualBusMap.Get(virtualBus); + *domain = value >> 8; + *bus = value & 0xff; + return B_OK; + +#endif } + +// used by pci_info.cpp print_info_basic() +void +__pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus) +{ + if (sPCI->ResolveVirtualBus(virtualBus, domain, bus) < B_OK) + panic("ResolveVirtualBus failed"); +} + + status_t PCI::AddController(pci_controller *controller, void *controller_cookie) { @@ -745,16 +788,16 @@ PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uin void PCI::ReadPciBasicInfo(PCIDev *dev) { - uint8 virt_bus; + uint8 virtualBus; - if (AddVirtBus(dev->domain, dev->bus, &virt_bus) != B_OK) { - dprintf("PCI: AddVirtBus failed, domain %u, bus %u\n", dev->domain, dev->bus); + if (CreateVirtualBus(dev->domain, dev->bus, &virtualBus) != B_OK) { + dprintf("PCI: CreateVirtualBus failed, domain %u, bus %u\n", dev->domain, dev->bus); return; } dev->info.vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_vendor_id, 2); dev->info.device_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_device_id, 2); - dev->info.bus = virt_bus; + dev->info.bus = virtualBus; dev->info.device = dev->dev; dev->info.function = dev->func; dev->info.revision = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_revision, 1); diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index 225f702508..189a55db08 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -10,6 +10,10 @@ #include +#ifdef __cplusplus + #include +#endif + #include "pci_controller.h" @@ -77,7 +81,7 @@ class PCI { status_t WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value); - status_t GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus); + status_t ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus); private: @@ -104,7 +108,7 @@ class PCI { domain_data * GetDomainData(int domain); - status_t AddVirtBus(int domain, uint8 bus, uint8 *virt_bus); + status_t CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus); private: PCIBus * fRootBus; @@ -114,6 +118,9 @@ class PCI { domain_data fDomainData[MAX_PCI_DOMAINS]; int fDomainCount; bool fBusEnumeration; + + VectorMap fVirtualBusMap; + int fNextVirtualBus; }; #endif // __cplusplus @@ -128,8 +135,10 @@ void pci_uninit(void); long pci_get_nth_pci_info(long index, pci_info *outInfo); -uint32 pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size); -void pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value); +uint32 pci_read_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size); +void pci_write_config(uint8 virtualBus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value); + +void __pci_resolve_virtual_bus(uint8 virtualBus, int *domain, uint8 *bus); #ifdef __cplusplus } diff --git a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp index bb93e2f539..8ddc588d73 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp @@ -148,10 +148,14 @@ print_capabilities(const pci_info *info) static void print_info_basic(const pci_info *info, bool verbose) { + int domain; + uint8 bus; + + __pci_resolve_virtual_bus(info->bus, &domain, &bus); + TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n", - // XXX this works only as long as PCI manager virtual bus mapping isn't changed: - (info->bus >> 5) /* domain */, (info->bus & 0x1f) /* bus */, - info->bus, info->device, info->function, info->vendor_id, info->device_id, info->revision)); + domain, bus, info->bus /* virtual bus*/, + info->device, info->function, info->vendor_id, info->device_id, info->revision)); TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n", info->class_base, info->class_sub, info->class_api));