87 lines
2.2 KiB
C
87 lines
2.2 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));
|
|
|
|
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);
|