blob: df958b1f42c1011c1fe583525d8f008a4b3e28a1 [file] [log] [blame]
#include <dri/pci/pci.h>
#include <dri/pci/vendors.h>
#include <io.h>
#include <log.h>
#include <alloc.h>
static uint num_drivers, size_drivers;
static struct pci_device_driver *drivers;
uint pci_config_readd(uchar bus, uchar slot, uchar func, uchar offset)
{
uint address =
(bus << 16) | (slot << 11) | (func << 8) | (offset << 2) | 0x80000000;
outl(PCI_CONFIG_ADDRESS, address);
return inl(PCI_CONFIG_DATA);
}
struct pci_device pci_check_device(uchar bus, uchar slot, uchar func)
{
uint vendor_device = pci_config_readd(bus, slot, func, 0);
ushort vendor = vendor_device & 0xffff;
struct pci_device device;
device.valid = false;
if (vendor != 0xffff)
{
device.valid = true;
device.device_id = vendor_device >> 16;
device.vendor = pci_vendor_by_id(vendor);
// 3rd dword
uint class_subclass = pci_config_readd(bus, slot, func, 2);
device.class = class_subclass >> 24;
device.subclass = (class_subclass >> 16) & 0xff;
device.prog_if = (class_subclass >> 8) & 0xff;
}
return device;
}
struct pci_vendor *pci_vendor_by_id(ushort id)
{
// Find vendor using binary search
uint start = 0, max = pci_num_vendors;
while (true)
{
if (max == start)
// Can't find one
return NULL;
uint guess = (max - start) / 2 + start;
if (pci_vendors[guess].id == id)
return &pci_vendors[guess];
else if (pci_vendors[guess].id > id)
max = guess;
else
start = guess;
}
}
void pci_print_devices()
{
kprintf(INFO "Enumerating PCI devices:\n");
for (int bus = 0; bus < 0xff; bus++)
{
for (int slot = 0; slot < 32; slot++)
{
for (int func = 0; func < 8; func++)
{
struct pci_device dev = pci_check_device(bus, slot, func);
if (dev.valid)
{
kprintf(INFO "%d %d %d --- d:0x%x --- %d:%d:%d --- %s\n", bus,
slot, func, dev.device_id, dev.class, dev.subclass,
dev.prog_if, dev.vendor->name);
}
}
}
}
}
void pci_register_device_driver(struct pci_device_driver driver)
{
if (num_drivers == size_drivers)
{
size_drivers += 8;
drivers = realloc(drivers, sizeof(struct pci_device_driver) * size_drivers);
}
driver.loaded = 0;
drivers[num_drivers++] = driver;
}
void pci_init()
{
num_drivers = 0;
size_drivers = 4;
drivers = malloc(sizeof(struct pci_device_driver) * size_drivers);
}
void pci_load()
{
for (int bus = 0; bus < 0xff; bus++)
{
for (int slot = 0; slot < 32; slot++)
{
for (int func = 0; func < 8; func++)
{
struct pci_device dev = pci_check_device(bus, slot, func);
// Do any drivers support this?
for (uint i = 0; i < num_drivers; i++)
{
if (drivers[i].supports(&dev))
{
drivers[i].loaded++;
drivers[i].dev = dev;
drivers[i].init(dev, bus, slot, func);
}
}
}
}
}
}
void pci_print_drivers()
{
kprintf(INFO "Enumerating PCI device drivers:\n");
for (uint i = 0; i < num_drivers; i++)
{
for (uint j = 0; j < drivers[i].loaded; j++)
{
struct pci_device_driver d = drivers[i];
kprintf(INFO "Driver: %s, vendor: %s\n", d.generic_name, d.dev.vendor->name);
}
}
}