// Must be in same directory as driver files. (Uses __DIR__) // Throws if stack has no driver for the PC's hardware. #define PCIV_PCNET 0x1022 #define PCID_PCNET 0x2000 #define PCIV_E1000 0x8086 #define PCID_82545EM 0x100F #define PCIV_VIRTIO 0x1AF4 #define PCID_VIRTIO_NET 0x1000 U0 NetDriverInclude(U8 *driver) { U8 *filename = MStrPrint(__DIR__ "/%s", driver); ExeFile(filename); Free(filename); } class CNetDriver:CQueue { U16 vendor_id; U16 device_id; U8 *filename; // relative to Drivers/ folder, not absolute }; CQueue *net_drivers = CAlloc(sizeof(CQueue)); QueueInit(net_drivers); U0 NetDriverRegister(U16 vendor_id=NULL, U16 device_id=NULL, U8 *filename) { CNetDriver *driver; if (!vendor_id && !device_id) return; driver = CAlloc(sizeof(CNetDriver)); driver->vendor_id = vendor_id; driver->device_id = device_id; driver->filename = StrNew(filename); QueueInsertRev(driver, net_drivers); } U0 NetDriverInit() { Bool found = FALSE; CNetDriver *net_driver; CPCIDev *net_pci; // register NIC PCI details with driver (file)name NetDriverRegister(PCIV_VIRTIO, PCID_VIRTIO_NET, "VirtIONet"); NetDriverRegister(PCIV_E1000, PCID_82545EM, "E1000"); NetDriverRegister(PCIV_PCNET, PCID_PCNET, "PCNet"); // iterate registered drivers until match is found, if any found net_driver = net_drivers->next; while (net_driver != net_drivers) { net_pci = PCIDevFind(,, net_driver->vendor_id, net_driver->device_id); if (net_pci) { found = TRUE; NetDriverInclude(net_driver->filename); break; } net_driver = net_driver->next; } if (!found) { ClassRep(net_pci); throw('NODRIVER'); } } NetDriverInit;