Rewrote mapping of domains and busses into a virtual bus number to

allow arbitrary bus numbers. Disabled domain support for __INTEL__.
This should fix bug #1774


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23944 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2008-02-10 23:39:35 +00:00
parent 3ecd55ed65
commit bc3318b640
3 changed files with 85 additions and 29 deletions

View File

@ -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);

View File

@ -10,6 +10,10 @@
#include <PCI.h>
#ifdef __cplusplus
#include <VectorMap.h>
#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<uint8, uint16> 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
}

View File

@ -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));