1 /* 2 * Copyright 2007-2010, Axel Dörfler. All rights reserved. 3 * Copyright 2009-2022, Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "device.h" 9 #include "sysinit.h" 10 11 #include <stdlib.h> 12 #include <sys/sockio.h> 13 14 #include <Drivers.h> 15 #include <ether_driver.h> 16 17 #include <compat/sys/haiku-module.h> 18 19 #include <compat/sys/bus.h> 20 #include <compat/sys/mbuf.h> 21 #include <compat/net/ethernet.h> 22 23 #include <dev/usb/usb.h> 24 #include <dev/usb/usbdi.h> 25 #include <dev/usb/usb_device.h> 26 27 28 //#define TRACE_DRIVER 29 #ifdef TRACE_DRIVER 30 # define TRACE(x) dprintf x 31 #else 32 # define TRACE(x) 33 #endif 34 35 36 static struct { 37 driver_t* driver; 38 int bus; 39 struct pci_info pci_info; 40 struct freebsd_usb_device usb_dev; 41 struct usb_attach_arg uaa; 42 } sProbedDevices[MAX_DEVICES]; 43 44 const char* gDeviceNameList[MAX_DEVICES + 1]; 45 struct ifnet* gDevices[MAX_DEVICES]; 46 int32 gDeviceCount; 47 48 49 static status_t 50 init_root_device(device_t *_root, int bus_type) 51 { 52 static driver_t sRootDriverPCI = { 53 "pci", 54 NULL, 55 sizeof(struct root_device_softc), 56 }; 57 static driver_t sRootDriverUSB = { 58 "uhub", 59 NULL, 60 sizeof(struct root_device_softc), 61 }; 62 63 device_t root = device_add_child(NULL, NULL, 0); 64 if (root == NULL) 65 return B_NO_MEMORY; 66 67 root->softc = malloc(sizeof(struct root_device_softc)); 68 if (root->softc == NULL) { 69 device_delete_child(NULL, root); 70 return B_NO_MEMORY; 71 } 72 73 bzero(root->softc, sizeof(struct root_device_softc)); 74 75 if (bus_type == BUS_pci) 76 root->driver = &sRootDriverPCI; 77 else if (bus_type == BUS_uhub) 78 root->driver = &sRootDriverUSB; 79 else 80 panic("unknown bus type"); 81 ((struct root_device_softc*)root->softc)->bus = bus_type; 82 83 root->root = root; 84 85 if (_root != NULL) 86 *_root = root; 87 88 return B_OK; 89 } 90 91 92 static status_t 93 add_child_device(driver_t* driver, device_t root, device_t* _child) 94 { 95 device_t child = device_add_child_driver(root, driver->name, driver, 0); 96 if (child == NULL) 97 return B_ERROR; 98 99 if (_child != NULL) 100 *_child = child; 101 102 return B_OK; 103 } 104 105 106 static void 107 uninit_probed_devices() 108 { 109 for (int p = 0; sProbedDevices[p].bus != BUS_INVALID; p++) { 110 if (sProbedDevices[p].bus == BUS_pci) { 111 gPci->unreserve_device(sProbedDevices[p].pci_info.bus, 112 sProbedDevices[p].pci_info.device, sProbedDevices[p].pci_info.function, 113 gDriverName, NULL); 114 } else if (sProbedDevices->bus == BUS_uhub) { 115 usb_cleanup_device(&sProbedDevices[p].usb_dev); 116 } 117 } 118 } 119 120 121 // #pragma mark - Haiku Driver API 122 123 124 static status_t 125 init_hardware_pci(driver_t* drivers[]) 126 { 127 status_t status; 128 int i = 0; 129 pci_info* info; 130 device_t root; 131 132 int p = 0; 133 while (sProbedDevices[p].bus != BUS_INVALID) 134 p++; 135 136 status = init_pci(); 137 if (status != B_OK) 138 return status; 139 140 status = init_root_device(&root, BUS_pci); 141 if (status != B_OK) 142 return status; 143 144 bool found = false; 145 for (info = get_device_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK; i++) { 146 int best = 0; 147 driver_t* driver = NULL; 148 149 for (int index = 0; drivers[index] != NULL; index++) { 150 int result; 151 device_t device = NULL; 152 status = add_child_device(drivers[index], root, &device); 153 if (status < B_OK) 154 break; 155 156 result = device->methods.probe(device); 157 if (result >= 0 && (driver == NULL || result > best)) { 158 TRACE(("%s, found %s at %d (%d)\n", gDriverName, 159 device_get_desc(device), i, result)); 160 driver = drivers[index]; 161 best = result; 162 } 163 device_delete_child(root, device); 164 } 165 166 if (driver == NULL) 167 continue; 168 169 // We've found a driver; now try to reserve the device and store it 170 if (gPci->reserve_device(info->bus, info->device, info->function, 171 gDriverName, NULL) != B_OK) { 172 dprintf("%s: Failed to reserve PCI:%d:%d:%d\n", 173 gDriverName, info->bus, info->device, info->function); 174 continue; 175 } 176 sProbedDevices[p].bus = BUS_pci; 177 sProbedDevices[p].driver = driver; 178 sProbedDevices[p].pci_info = *info; 179 found = true; 180 p++; 181 } 182 sProbedDevices[p].bus = BUS_INVALID; 183 184 device_delete_child(NULL, root); 185 186 if (found) 187 return B_OK; 188 189 uninit_pci(); 190 return B_NOT_SUPPORTED; 191 } 192 193 194 static status_t 195 init_hardware_uhub(driver_t* drivers[]) 196 { 197 status_t status; 198 device_t root; 199 200 int p = 0; 201 while (sProbedDevices[p].bus != BUS_INVALID) 202 p++; 203 204 status = init_usb(); 205 if (status != B_OK) 206 return status; 207 208 status = init_root_device(&root, BUS_uhub); 209 if (status != B_OK) 210 return status; 211 212 bool found = false; 213 uint32 cookie = 0; 214 struct freebsd_usb_device udev = {}; 215 while ((status = get_next_usb_device(&cookie, &udev)) == B_OK) { 216 int best = 0; 217 driver_t* driver = NULL; 218 219 struct usb_attach_arg uaa; 220 status = get_usb_device_attach_arg(&udev, &uaa); 221 if (status != B_OK) 222 continue; 223 224 for (int index = 0; drivers[index] != NULL; index++) { 225 int result; 226 device_t device = NULL; 227 status = add_child_device(drivers[index], root, &device); 228 if (status < B_OK) 229 break; 230 231 device_set_ivars(device, &uaa); 232 233 result = device->methods.probe(device); 234 if (result >= 0 && (driver == NULL || result > best)) { 235 TRACE(("%s, found %s at %d (%d)\n", gDriverName, 236 device_get_desc(device), i, result)); 237 driver = drivers[index]; 238 best = result; 239 } 240 device_delete_child(root, device); 241 } 242 243 if (driver == NULL) 244 continue; 245 246 sProbedDevices[p].bus = BUS_uhub; 247 sProbedDevices[p].driver = driver; 248 sProbedDevices[p].usb_dev = udev; 249 sProbedDevices[p].uaa = uaa; 250 sProbedDevices[p].uaa.device = &sProbedDevices[p].usb_dev; 251 252 // We just "transferred ownership" of usb_dev to sProbedDevices. 253 memset(&udev, 0, sizeof(udev)); 254 255 found = true; 256 p++; 257 } 258 sProbedDevices[p].bus = BUS_INVALID; 259 260 device_delete_child(NULL, root); 261 usb_cleanup_device(&udev); 262 263 if (found) 264 return B_OK; 265 266 uninit_usb(); 267 return B_NOT_SUPPORTED; 268 } 269 270 271 status_t 272 _fbsd_init_hardware(driver_t* pci_drivers[], driver_t* uhub_drivers[]) 273 { 274 sProbedDevices[0].bus = BUS_INVALID; 275 276 if (pci_drivers != NULL) 277 init_hardware_pci(pci_drivers); 278 279 if (uhub_drivers != NULL) 280 init_hardware_uhub(uhub_drivers); 281 282 return (sProbedDevices[0].bus != BUS_INVALID) ? B_OK : B_NOT_SUPPORTED; 283 } 284 285 286 status_t 287 _fbsd_init_drivers() 288 { 289 status_t status = init_mutexes(); 290 if (status < B_OK) 291 goto err2; 292 293 status = init_mbufs(); 294 if (status < B_OK) 295 goto err3; 296 297 status = init_callout(); 298 if (status < B_OK) 299 goto err4; 300 301 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 302 status = init_taskqueues(); 303 if (status < B_OK) 304 goto err5; 305 } 306 307 init_sysinit(); 308 309 status = init_wlan_stack(); 310 if (status < B_OK) 311 goto err6; 312 313 for (int p = 0; sProbedDevices[p].bus != BUS_INVALID; p++) { 314 device_t root, device = NULL; 315 status = init_root_device(&root, sProbedDevices[p].bus); 316 if (status != B_OK) 317 break; 318 319 if (sProbedDevices[p].bus == BUS_pci) { 320 pci_info* info = get_device_pci_info(root); 321 *info = sProbedDevices[p].pci_info; 322 } else if (sProbedDevices[p].bus == BUS_uhub) { 323 struct root_device_softc* root_softc = (struct root_device_softc*)root->softc; 324 root_softc->usb_dev = &sProbedDevices[p].usb_dev; 325 } 326 327 status = add_child_device(sProbedDevices[p].driver, root, &device); 328 if (status != B_OK) 329 break; 330 331 if (sProbedDevices[p].bus == BUS_uhub) 332 device_set_ivars(device, &sProbedDevices[p].uaa); 333 334 // some drivers expect probe() to be called before attach() 335 // (i.e. they set driver softc in probe(), etc.) 336 if (device->methods.probe(device) >= 0 337 && device_attach(device) == 0) { 338 dprintf("%s: init_driver(%p)\n", gDriverName, 339 sProbedDevices[p].driver); 340 } else 341 device_delete_child(NULL, root); 342 } 343 344 if (gDeviceCount > 0) 345 return B_OK; 346 347 if (status == B_OK) 348 status = B_ERROR; 349 350 err7: 351 uninit_wlan_stack(); 352 err6: 353 uninit_sysinit(); 354 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 355 uninit_taskqueues(); 356 err5: 357 uninit_callout(); 358 err4: 359 uninit_mbufs(); 360 err3: 361 uninit_mutexes(); 362 err2: 363 uninit_probed_devices(); 364 365 uninit_usb(); 366 uninit_pci(); 367 368 return status; 369 } 370 371 372 status_t 373 _fbsd_uninit_drivers() 374 { 375 for (int i = 0; i < gDeviceCount; i++) 376 device_delete_child(NULL, gDevices[i]->root_device); 377 378 uninit_wlan_stack(); 379 uninit_sysinit(); 380 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 381 uninit_taskqueues(); 382 uninit_callout(); 383 uninit_mbufs(); 384 uninit_mutexes(); 385 386 uninit_probed_devices(); 387 388 uninit_usb(); 389 uninit_pci(); 390 391 return B_OK; 392 } 393