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 pci_info* info; 184 device_t root; 185 186 status = init_mutexes(); 187 if (status < B_OK) 188 goto err2; 189 190 status = init_mbufs(); 191 if (status < B_OK) 192 goto err3; 193 194 status = init_callout(); 195 if (status < B_OK) 196 goto err4; 197 198 init_bounce_pages(); 199 200 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 201 status = init_taskqueues(); 202 if (status < B_OK) 203 goto err5; 204 } 205 206 init_sysinit(); 207 208 status = init_wlan_stack(); 209 if (status < B_OK) 210 goto err6; 211 212 status = init_root_device(&root); 213 if (status != B_OK) 214 goto err7; 215 info = get_pci_info(root); 216 217 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 218 device_t device = NULL; 219 *info = sProbedDevices[p].info; 220 221 status = add_child_device(sProbedDevices[p].driver, root, &device); 222 if (status != B_OK) 223 break; 224 225 // some drivers expect probe() to be called before attach() 226 // (i.e. they set driver softc in probe(), etc.) 227 if (device->methods.probe(device) >= 0 228 && device_attach(device) == 0) { 229 dprintf("%s: init_driver(%p)\n", gDriverName, 230 sProbedDevices[p].driver); 231 status = init_root_device(&root); 232 if (status != B_OK) 233 break; 234 info = get_pci_info(root); 235 } else 236 device_delete_child(root, device); 237 } 238 239 if (gDeviceCount > 0) 240 return B_OK; 241 242 device_delete_child(NULL, root); 243 244 if (status == B_OK) 245 status = B_ERROR; 246 247 err7: 248 uninit_wlan_stack(); 249 250 err6: 251 uninit_sysinit(); 252 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 253 uninit_taskqueues(); 254 err5: 255 uninit_bounce_pages(); 256 uninit_callout(); 257 err4: 258 uninit_mbufs(); 259 err3: 260 uninit_mutexes(); 261 err2: 262 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 263 gPci->unreserve_device(sProbedDevices[p].info.bus, 264 sProbedDevices[p].info.device, sProbedDevices[p].info.function, 265 gDriverName, NULL); 266 } 267 268 put_module(B_PCI_MODULE_NAME); 269 if (gPCIx86 != NULL) 270 put_module(B_PCI_X86_MODULE_NAME); 271 272 return status; 273 } 274 275 276 status_t 277 _fbsd_uninit_drivers(driver_t *drivers[]) 278 { 279 int i, p; 280 281 for (i = 0; drivers[i]; i++) 282 TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i])); 283 284 for (i = 0; i < gDeviceCount; i++) { 285 device_delete_child(NULL, gDevices[i]->root_device); 286 } 287 288 uninit_wlan_stack(); 289 uninit_sysinit(); 290 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 291 uninit_taskqueues(); 292 uninit_bounce_pages(); 293 uninit_callout(); 294 uninit_mbufs(); 295 uninit_mutexes(); 296 297 for (p = 0; sProbedDevices[p].driver != NULL; p++) { 298 gPci->unreserve_device(sProbedDevices[p].info.bus, 299 sProbedDevices[p].info.device, sProbedDevices[p].info.function, 300 gDriverName, NULL); 301 } 302 303 put_module(B_PCI_MODULE_NAME); 304 if (gPCIx86 != NULL) 305 put_module(B_PCI_X86_MODULE_NAME); 306 307 return B_OK; 308 } 309