#include #include #include #include #include #include #include #include "pci.h" struct driver *pci_driver = NULL; struct bus_device *pci_bus = NULL; static void init_pci_device(uint32_t device, uint16_t vendid, uint16_t devid, void *arg) { struct device *dev = generic_device_create(); snprintf(dev->dev_name, sizeof dev->dev_name, "%02x:%02x.%u", pci_get_bus(device), pci_get_slot(device), pci_get_func(device)); printk("pci: found device %s (vend:%04x, dev:%04x)", dev->dev_name, vendid, devid); struct pci_device *pci_dev = kmalloc(sizeof *pci_dev, VM_NORMAL); if (!pci_dev) { /* TODO destroy device */ return; } pci_dev->pci_id.pci_vendor_id = vendid; pci_dev->pci_id.pci_device_id = devid; pci_dev->pci_bus = pci_get_bus(device); pci_dev->pci_slot = pci_get_slot(device); pci_dev->pci_func = pci_get_func(device); dev->dev_bus_priv = pci_dev; /* register as a generic device under the PCI driver. if we find a suitable driver for this device, that device will re-register it as theirs. */ device_register(dev, pci_driver, bus_device_base(pci_bus)); struct pci_driver *driver = find_driver_for_pci_device(vendid, devid); if (driver && driver->probe) { driver->probe(driver, dev); } } static kern_status_t pci_bus_scan(struct device *bus) { printk("pci: scanning for devices..."); pci_enumerate_devices(init_pci_device, -1, NULL); return KERN_OK; } static struct bus_device_ops pci_bus_ops = { .scan = pci_bus_scan, }; static kern_status_t online(struct kext *self) { pci_driver = driver_create(self, "pci"); if (!pci_driver) { return KERN_NO_MEMORY; } kern_status_t status = init_pci_driver_cache(); if (status != KERN_OK) { return status; } driver_register(pci_driver); pci_bus = bus_device_create(); struct device *pci_base = bus_device_base(pci_bus); snprintf(pci_base->dev_name, sizeof pci_base->dev_name, "pci"); pci_bus->b_ops = &pci_bus_ops; device_register(pci_base, pci_driver, root_device()); printk("pci: subsystem initialised"); return KERN_OK; } DEFINE_KEXT(PCI_SUBSYSTEM_KEXT_ID, online, NULL, KEXT_NO_DEPENDENCIES);