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