/* * Copyright 2007, Hugo Santos. All Rights Reserved. * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2004, Marcus Overhagen. All Rights Reserved. * Distributed under the terms of the MIT License. */ /*! Driver functions that adapt the FreeBSD driver to Haiku's driver API. The actual driver functions are exported by the HAIKU_FBSD_DRIVER_GLUE macro, and just call the functions here. */ #include "device.h" #include #include #include #include #include #include #include #include //#define TRACE_DRIVER #ifdef TRACE_DRIVER # define TRACE(x) dprintf x #else # define TRACE(x) #endif const char *gDeviceNameList[MAX_DEVICES + 1]; struct ifnet *gDevices[MAX_DEVICES]; int32 gDeviceCount; static status_t init_root_device(driver_t *driver, device_t *_root, device_t *_child) { static driver_t sRootDriver = { "pci", NULL, sizeof(struct root_device_softc) }; device_t child; device_t root = device_add_child(NULL, NULL, 0); if (root == NULL) return B_NO_MEMORY; root->softc = malloc(sizeof(struct root_device_softc)); if (root->softc == NULL) { device_delete_child(NULL, root); return B_NO_MEMORY; } root->driver = &sRootDriver; root->root = root; child = device_add_child(root, driver->name, 0); if (child == NULL) { device_delete_child(NULL, root); return B_ERROR; } if (_root != NULL) *_root = root; if (_child != NULL) *_child = child; return B_OK; } static pci_info * get_pci_info(struct device *device) { return &((struct root_device_softc *)device->softc)->pci_info; } // #pragma mark - Haiku Driver API status_t _fbsd_init_hardware(driver_t *driver) { status_t status = B_ENTRY_NOT_FOUND; device_t child, root; pci_info *info; int i; if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) return B_ERROR; if (init_root_device(driver, &root, &child) != B_OK) { dprintf("%s: creating device failed.\n", gDriverName); put_module(B_PCI_MODULE_NAME); return B_ERROR; } TRACE(("%s: init_hardware(%p)\n", gDriverName, driver)); if (child->methods.probe == NULL) { dprintf("%s: driver has no device_probe method.\n", gDriverName); device_delete_child(NULL, root); put_module(B_PCI_MODULE_NAME); return B_ERROR; } info = get_pci_info(root); for (i = 0; gPci->get_nth_pci_info(i, info) == B_OK; i++) { int result; result = child->methods.probe(child); if (result >= 0) { TRACE(("%s, found %s at %d\n", gDriverName, device_get_desc(child), i)); status = B_OK; break; } } if (status < B_OK) TRACE(("%s: no hardware found.\n", gDriverName)); device_delete_child(NULL, root); put_module(B_PCI_MODULE_NAME); return status; } status_t _fbsd_init_driver(driver_t *driver) { status_t status; int i = 0; dprintf("%s: init_driver(%p)\n", gDriverName, driver); status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); if (status < B_OK) return status; status = init_mutexes(); if (status < B_OK) goto err1; status = init_mbufs(); if (status < B_OK) goto err2; init_bounce_pages(); status = init_condition_variables(); if (status < B_OK) goto err3; if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { status = init_taskqueues(); if (status < B_OK) goto err4; } status = init_wlan_stack(); if (status < B_OK) goto err5; while (gDeviceCount < MAX_DEVICES) { device_t root, device; bool found = false; pci_info *info; status = init_root_device(driver, &root, &device); if (status < B_OK) break; info = get_pci_info(root); for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) { if (device->methods.probe(device) < 0) continue; if (device_attach(device) == 0) found = true; i++; break; } if (!found) { device_delete_child(NULL, root); break; } } if (gDeviceCount > 0) return B_OK; if (status == B_OK) status = B_ERROR; uninit_wlan_stack(); err5: if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) uninit_taskqueues(); err4: uninit_condition_variables(); err3: uninit_mbufs(); err2: uninit_mutexes(); err1: put_module(B_PCI_MODULE_NAME); return status; } void _fbsd_uninit_driver(driver_t *driver) { int i; TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver)); for (i = 0; i < gDeviceCount; i++) { device_delete_child(NULL, gDevices[i]->root_device); } uninit_wlan_stack(); uninit_condition_variables(); uninit_bounce_pages(); uninit_mbufs(); if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) uninit_taskqueues(); uninit_mutexes(); put_module(B_PCI_MODULE_NAME); }