Files
mango/kexts/drivers/bus/pci/main.c

93 lines
2.4 KiB
C

#include <socks/kext.h>
#include <socks/vm.h>
#include <socks/device.h>
#include <socks/printk.h>
#include <socks/pci.h>
#include <socks/libc/stdio.h>
#include <arch/ports.h>
#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));
uint8_t c = pci_read_field(device, PCI_REG_CLASS, 1);
uint8_t sc = pci_read_field(device, PCI_REG_SUBCLASS, 1);
printk("pci: found device %s (vend:%04x, dev:%04x, class:%02x, subclass:%02x)",
dev->dev_name, vendid, devid, c, sc);
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_id.pci_class_id = c;
pci_dev->pci_id.pci_subclass_id = sc;
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(&pci_dev->pci_id);
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);