diff --git a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h index 13f29113f5..5c569de0cf 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -80,6 +80,7 @@ typedef struct { __fbsd_ ## name ## _ ## busname +status_t _fbsd_init_hardware(driver_t *driver[]); status_t _fbsd_init_drivers(driver_t *driver[]); status_t _fbsd_uninit_drivers(driver_t *driver[]); @@ -106,7 +107,9 @@ status_t wlan_close(void*); const char *gDriverName = #publicname; \ int32 api_version = B_CUR_DRIVER_API_VERSION; \ status_t init_hardware() \ - { return B_OK; } \ + { \ + return __haiku_handle_fbsd_drivers_list(_fbsd_init_hardware); \ + } \ status_t init_driver() \ { \ return __haiku_handle_fbsd_drivers_list(_fbsd_init_drivers); \ diff --git a/src/libs/compat/freebsd_network/driver.c b/src/libs/compat/freebsd_network/driver.c index 50d7d4373c..6c625d28a3 100644 --- a/src/libs/compat/freebsd_network/driver.c +++ b/src/libs/compat/freebsd_network/driver.c @@ -37,8 +37,13 @@ #endif -const char *gDeviceNameList[MAX_DEVICES + 1]; -struct ifnet *gDevices[MAX_DEVICES]; +static struct { + driver_t* driver; + pci_info info; +} sProbedDevices[MAX_DEVICES]; + +const char* gDeviceNameList[MAX_DEVICES + 1]; +struct ifnet* gDevices[MAX_DEVICES]; int32 gDeviceCount; @@ -98,22 +103,86 @@ get_pci_info(struct device *device) status_t -_fbsd_init_drivers(driver_t *drivers[]) +_fbsd_init_hardware(driver_t *drivers[]) { status_t status; - int i = 0; - int index = 0; - pci_info *info; + int i = 0, p = 0, index = 0; + pci_info* info; device_t root; status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); - if (status < B_OK) + if (status != B_OK) return status; // if it fails we just don't support x86 specific features (like MSIs) if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK) gPCIx86 = NULL; + status = init_root_device(&root); + if (status != B_OK) + return status; + + for (p = 0; p <= MAX_DEVICES; p++) + sProbedDevices[i].driver = NULL; + p = 0; + + for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK; + i++) { + int best = 0; + driver_t* driver = NULL; + + for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) { + int result; + device_t device = NULL; + status = add_child_device(drivers[index], root, &device); + if (status < B_OK) + break; + + result = device->methods.probe(device); + if (result >= 0 && (driver == NULL || result > best)) { + TRACE(("%s, found %s at %d (%d)\n", gDriverName, + device_get_desc(device), i, result)); + driver = drivers[index]; + best = result; + } + device_delete_child(root, device); + } + + if (driver == NULL) + continue; + + // We've found a driver; now try to reserve the device and store it + if (gPci->reserve_device(info->bus, info->device, info->function, + gDriverName, NULL) != B_OK) { + dprintf("%s: Failed to reserve PCI:%d:%d:%d\n", + gDriverName, info->bus, info->device, info->function); + continue; + } + sProbedDevices[p].driver = driver; + sProbedDevices[p].info = *info; + p++; + } + + device_delete_child(NULL, root); + + if (p > 0) + return B_OK; + + put_module(B_PCI_MODULE_NAME); + if (gPCIx86 != NULL) + put_module(B_PCI_X86_MODULE_NAME); + return B_NOT_SUPPORTED; +} + + +status_t +_fbsd_init_drivers(driver_t *drivers[]) +{ + status_t status; + int p = 0; + pci_info* info; + device_t root; + status = init_mutexes(); if (status < B_OK) goto err2; @@ -143,46 +212,28 @@ _fbsd_init_drivers(driver_t *drivers[]) status = init_root_device(&root); if (status != B_OK) goto err7; + info = get_pci_info(root); - for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK; - i++) { - int best = 0; - driver_t *driver = NULL; + for (p = 0; sProbedDevices[p].driver != NULL; p++) { + device_t device = NULL; + *info = sProbedDevices[p].info; - for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) { - int result; - device_t device; - status = add_child_device(drivers[index], root, &device); - if (status < B_OK) - break; + status = add_child_device(sProbedDevices[p].driver, root, &device); + if (status != B_OK) + break; - result = device->methods.probe(device); - if (result >= 0 && (driver == NULL || result > best)) { - TRACE(("%s, found %s at %d (%d)\n", gDriverName, - device_get_desc(device), i, result)); - driver = drivers[index]; - best = result; - } - device_delete_child(root, device); - } - - if (driver != NULL) { - device_t device; - status = add_child_device(driver, root, &device); + // some drivers expect probe() to be called before attach() + // (i.e. they set driver softc in probe(), etc.) + if (device->methods.probe(device) >= 0 + && device_attach(device) == 0) { + dprintf("%s: init_driver(%p)\n", gDriverName, + sProbedDevices[p].driver); + status = init_root_device(&root); if (status != B_OK) break; - // some drivers expect probe() to be called before attach() - // (i.e. they set driver softc in probe(), etc.) - if (device->methods.probe(device) >= 0 - && device_attach(device) == 0) { - dprintf("%s: init_driver(%p) at %d\n", gDriverName, driver, i); - status = init_root_device(&root); - if (status != B_OK) - break; - info = get_pci_info(root); - } else - device_delete_child(root, device); - } + info = get_pci_info(root); + } else + device_delete_child(root, device); } if (gDeviceCount > 0)