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