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