new PCI bus scanning & configuration code as C++ class

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4856 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-09-29 18:58:51 +00:00
parent b1393f0002
commit 9b4ce42bf2
2 changed files with 249 additions and 0 deletions
+189
View File
@@ -0,0 +1,189 @@
#include <KernelExport.h>
#include <PCI.h>
#include "util/kernel_cpp.h"
#include "pci_priv.h"
#include "pci.h"
static PCI *pcidb;
void
pci_init(void)
{
pcidb = new PCI;
}
void
pci_uninit(void)
{
delete pcidb;
}
long
pci_get_nth_pci_info(long index, pci_info *outInfo)
{
return pcidb->GetNthPciInfo(index, outInfo);
}
PCI::PCI()
{
fRootBus.parent = 0;
fRootBus.bus = 0;
fRootBus.child = 0;
DiscoverBus(&fRootBus);
}
PCI::~PCI()
{
}
status_t
PCI::GetNthPciInfo(long index, pci_info *outInfo)
{
long curindex = 0;
return GetNthPciInfo(&fRootBus, &curindex, index, outInfo);
}
status_t
PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo)
{
// maps tree structure to linear indexed view
PCIDev *dev = bus->child;
while (dev) {
if (*curindex == wantindex) {
*outInfo = dev->info;
return B_OK;
}
*curindex += 1;
if (dev->child && B_OK == GetNthPciInfo(dev->child, curindex, wantindex, outInfo))
return B_OK;
dev = dev->next;
}
return B_ERROR;
}
void
PCI::DiscoverBus(PCIBus *bus)
{
dprintf("PCI: DiscoverBus, bus %u\n", bus->bus);
for (int dev = 0; dev < gMaxBusDevices; dev++) {
uint16 vendor_id = pci_read_config(bus->bus, dev, 0, PCI_vendor_id, 2);
if (vendor_id == 0xffff)
continue;
uint8 type = pci_read_config(bus->bus, dev, 0, PCI_header_type, 1);
int nfunc = (type & PCI_multifunction) ? 8 : 1;
for (int func = 0; func < nfunc; func++)
DiscoverDevice(bus, dev, func);
}
}
void
PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func)
{
dprintf("PCI: DiscoverDevice, bus %u, dev %u, func %u\n", bus->bus, dev, func);
uint16 device_id = pci_read_config(bus->bus, dev, func, PCI_device_id, 2);
if (device_id == 0xffff)
return;
PCIDev *newdev = CreateDevice(bus, dev, func);
uint8 base_class = pci_read_config(bus->bus, dev, func, PCI_class_base, 1);
uint8 sub_class = pci_read_config(bus->bus, dev, func, PCI_class_sub, 1);
if (base_class == PCI_bridge && sub_class == PCI_pci) {
uint8 secondary_bus = pci_read_config(bus->bus, dev, func, PCI_secondary_bus, 1);
PCIBus *newbus = CreateBus(newdev, secondary_bus);
DiscoverBus(newbus);
}
}
PCIBus *
PCI::CreateBus(PCIDev *parent, uint8 bus)
{
PCIBus *newbus = new PCIBus;
newbus->parent = parent;
newbus->bus = bus;
newbus->child = 0;
// append
parent->child = newbus;
return newbus;
}
PCIDev *
PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func)
{
dprintf("PCI: CreateDevice, bus %u, dev %u, func %u:\n", parent->bus, dev, func);
PCIDev *newdev = new PCIDev;
newdev->next = 0;
newdev->parent = parent;
newdev->child = 0;
newdev->bus = parent->bus;
newdev->dev = dev;
newdev->func = func;
ReadPciBasicInfo(newdev);
dprintf("PCI: vendor 0x%04x, device 0x%04x, class_base 0x%02x, class_sub 0x%02x\n",
newdev->info.vendor_id, newdev->info.device_id, newdev->info.class_base, newdev->info.class_sub);
// append
if (parent->child == 0) {
parent->child = newdev;
} else {
PCIDev *sub = parent->child;
while (sub->next)
sub = sub->next;
sub->next = newdev;
}
return newdev;
}
void
PCI::ReadPciBasicInfo(PCIDev *dev)
{
dev->info.vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_vendor_id, 2);
dev->info.device_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_device_id, 2);
dev->info.bus = dev->bus;
dev->info.device = dev->dev;
dev->info.function = dev->func;
dev->info.revision = pci_read_config(dev->bus, dev->dev, dev->func, PCI_revision, 1);
dev->info.class_api = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_api, 1);
dev->info.class_sub = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_sub, 1);
dev->info.class_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_base, 1);
dev->info.line_size = pci_read_config(dev->bus, dev->dev, dev->func, PCI_line_size, 1);
dev->info.latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_latency, 1);
dev->info.header_type = pci_read_config(dev->bus, dev->dev, dev->func, PCI_header_type, 1);
dev->info.header_type &= PCI_header_type_mask; // this masks off the multifunction bit
dev->info.bist = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bist, 1);
dev->info.reserved = 0;
}
void
PCI::ReadPciHeaderInfo(PCIDev *dev)
{
switch (dev->info.header_type) {
case 0:
break;
case 1:
break;
default:
dprintf("PCI: Header type unknown (%d)\n", dev->info.header_type);
break;
}
}
+60
View File
@@ -0,0 +1,60 @@
#ifdef __cplusplus
extern "C" {
#endif
void pci_init(void);
void pci_uninit(void);
long pci_get_nth_pci_info(long index, pci_info *outInfo);
#ifdef __cplusplus
struct PCIBus;
struct PCIDev;
struct PCIBus
{
PCIDev *parent;
uint8 bus;
PCIDev *child;
};
struct PCIDev
{
PCIDev *next;
PCIBus *parent;
PCIBus *child;
uint8 bus;
uint8 dev;
uint8 func;
pci_info info;
};
class PCI
{
public:
PCI();
~PCI();
status_t GetNthPciInfo(long index, pci_info *outInfo);
private:
void DiscoverBus(PCIBus *bus);
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func);
PCIDev *CreateDevice(PCIBus *parent, uint8 dev, uint8 func);
PCIBus *CreateBus(PCIDev *parent, uint8 bus);
status_t GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo);
void ReadPciBasicInfo(PCIDev *dev);
void ReadPciHeaderInfo(PCIDev *dev);
private:
PCIBus fRootBus;
};
#endif // __cplusplus
#ifdef __cplusplus
}
#endif