1 /* 2 * Copyright 2007, Hugo Santos. All Rights Reserved. 3 * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. 4 * Copyright 2004, Marcus Overhagen. All Rights Reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 /*! Driver functions that adapt the FreeBSD driver to Haiku's driver API. 10 The actual driver functions are exported by the HAIKU_FBSD_DRIVER_GLUE 11 macro, and just call the functions here. 12 */ 13 14 15 #include "device.h" 16 #include "sysinit.h" 17 18 #include <stdlib.h> 19 #include <sys/sockio.h> 20 21 #include <Drivers.h> 22 #include <ether_driver.h> 23 #include <PCI_x86.h> 24 25 #include <compat/sys/haiku-module.h> 26 27 #include <compat/sys/bus.h> 28 #include <compat/sys/mbuf.h> 29 #include <compat/net/ethernet.h> 30 31 32 //#define TRACE_DRIVER 33 #ifdef TRACE_DRIVER 34 # define TRACE(x) dprintf x 35 #else 36 # define TRACE(x) 37 #endif 38 39 40 static struct { 41 driver_t* driver; 42 pci_info info; 43 } sProbedDevices[MAX_DEVICES]; 44 45 const char* gDeviceNameList[MAX_DEVICES + 1]; 46 struct ifnet* gDevices[MAX_DEVICES]; 47 int32 gDeviceCount; 48 49 50 static status_t 51 init_root_device(device_t *_root) 52 { 53 static driver_t sRootDriver = { 54 "pci", 55 NULL, 56 sizeof(struct root_device_softc) 57 }; 58 59 device_t root = device_add_child(NULL, NULL, 0); 60 if (root == NULL) 61 return B_NO_MEMORY; 62 63 root->softc = malloc(sizeof(struct root_device_softc)); 64 if (root->softc == NULL) { 65 device_delete_child(NULL, root); 66 return B_NO_MEMORY; 67 } 68 69 bzero(root->softc, sizeof(struct root_device_softc)); 70 root->driver = &sRootDriver; 71 root->root = root; 72 73 if (_root != NULL) 74 *_root = root; 75 76 return B_OK; 77 } 78 79 80 static status_t 81 add_child_device(driver_t* driver, device_t root, device_t* _child) 82 { 83 device_t child = device_add_child_driver(root, driver->name, driver, 0); 84 if (child == NULL) { 85 return B_ERROR; 86 } 87 88 if (_child != NULL) 89 *_child = child; 90 91 return B_OK; 92 } 93 94 95 static pci_info * 96 get_pci_info(struct device *device) 97 { 98 return &((struct root_device_softc *)device->softc)->pci_info; 99 } 100 101 102 // #pragma mark - Haiku Driver API 103 104 105 status_t 106 _fbsd_init_hardware(driver_t *drivers[]) 107 { 108 status_t status; 109 int i = 0, p = 0, index = 0; 110 pci_info* info; 111 device_t root; 112 113 status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); 114 if (status != B_OK) 115 return status; 116 117 // if it fails we just don't support x86 specific features (like MSIs) 118 if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK) 119 gPCIx86 = NULL; 120 121 status = init_root_device(&root); 122 if (status != B_OK) 123 return status; 124 125 for (p = 0; p <= MAX_DEVICES; p++) 126 sProbedDevices[i].driver = NULL; 127 p = 0; 128 129 for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK; 130 i++) { 131 int best = 0; 132 driver_t* driver = NULL; 133 134 for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) { 135 int result; 136 device_t device = NULL; 137 status = add_child_device(drivers[index], root, &device); 138 if (status < B_OK) 139 break; 140 141 result = device->methods.probe(device); 142 if (result >= 0 && (driver == NULL || result > best)) { 143 TRACE(("%s, found %s at %d (%d)\n", gDriverName, 144 device_get_desc(device), i, result)); 145 driver = drivers[index]; 146 best = result; 147 } 148 device_delete_child(root, device); 149 } 150 151 if (driver == NULL) 152 continue; 153 154 // We've found a driver; now try to reserve the device and store it 155 if (gPci->reserve_device(info->bus, info->device, info->function, 156 gDriverName, NULL) != B_OK) { 157 dprintf("%s: Failed to reserve PCI:%d:%d:%d\n", 158 gDriverName, info->bus, info->device, info->function); 159 continue; 160 } 161 sProbedDevices[p].driver = driver; 162 sProbedDevices[p].info = *info; 163 p++; 164 } 165 166 device_delete_child(NULL, root); 167 168 if (p > 0) 169 return B_OK; 170 171 put_module(B_PCI_MODULE_NAME); 172 if (gPCIx86 != NULL) 173 put_module(B_PCI_X86_MODULE_NAME); 174 return B_NOT_SUPPORTED; 175 } 176 177 178 status_t 179 _fbsd_init_drivers(driver_t *drivers[]) 180 { 181 status_t status; 182 int p = 0; 183 184 status = init_mutexes(); 185 if (status < B_OK) 186 goto err2; 187 188 status = init_mbufs(); 189 if (status < B_OK) 190 goto err3; 191 192 status = init_callout(); 193 if (status < B_OK) 194 goto err4; 195 196 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 197 status = init_taskqueues(); 198 if (status < B_OK) 199 goto err5; 200 } 201 202 init_sysinit(); 203 204 status = init_wlan_stack(); 205 if (status < B_OK) 206 goto err6; 207 208 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 209 pci_info* info; 210 device_t root, device = NULL; 211 status = init_root_device(&root); 212 if (status != B_OK) 213 break; 214 215 info = get_pci_info(root); 216 *info = sProbedDevices[p].info; 217 218 status = add_child_device(sProbedDevices[p].driver, root, &device); 219 if (status != B_OK) 220 break; 221 222 // some drivers expect probe() to be called before attach() 223 // (i.e. they set driver softc in probe(), etc.) 224 if (device->methods.probe(device) >= 0 225 && device_attach(device) == 0) { 226 dprintf("%s: init_driver(%p)\n", gDriverName, 227 sProbedDevices[p].driver); 228 } else 229 device_delete_child(NULL, root); 230 } 231 232 if (gDeviceCount > 0) 233 return B_OK; 234 235 if (status == B_OK) 236 status = B_ERROR; 237 238 err7: 239 uninit_wlan_stack(); 240 err6: 241 uninit_sysinit(); 242 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 243 uninit_taskqueues(); 244 err5: 245 uninit_callout(); 246 err4: 247 uninit_mbufs(); 248 err3: 249 uninit_mutexes(); 250 err2: 251 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 252 gPci->unreserve_device(sProbedDevices[p].info.bus, 253 sProbedDevices[p].info.device, sProbedDevices[p].info.function, 254 gDriverName, NULL); 255 } 256 257 put_module(B_PCI_MODULE_NAME); 258 if (gPCIx86 != NULL) 259 put_module(B_PCI_X86_MODULE_NAME); 260 261 return status; 262 } 263 264 265 status_t 266 _fbsd_uninit_drivers(driver_t *drivers[]) 267 { 268 int i, p; 269 270 for (i = 0; drivers[i]; i++) 271 TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i])); 272 273 for (i = 0; i < gDeviceCount; i++) { 274 device_delete_child(NULL, gDevices[i]->root_device); 275 } 276 277 uninit_wlan_stack(); 278 uninit_sysinit(); 279 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 280 uninit_taskqueues(); 281 uninit_callout(); 282 uninit_mbufs(); 283 uninit_mutexes(); 284 285 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 286 gPci->unreserve_device(sProbedDevices[p].info.bus, 287 sProbedDevices[p].info.device, sProbedDevices[p].info.function, 288 gDriverName, NULL); 289 } 290 291 put_module(B_PCI_MODULE_NAME); 292 if (gPCIx86 != NULL) 293 put_module(B_PCI_X86_MODULE_NAME); 294 295 return B_OK; 296 } 297