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 23 #include <compat/sys/haiku-module.h> 24 25 #include <compat/sys/bus.h> 26 #include <compat/sys/mbuf.h> 27 #include <compat/net/ethernet.h> 28 29 30 //#define TRACE_DRIVER 31 #ifdef TRACE_DRIVER 32 # define TRACE(x) dprintf x 33 #else 34 # define TRACE(x) 35 #endif 36 37 38 const char *gDeviceNameList[MAX_DEVICES + 1]; 39 struct ifnet *gDevices[MAX_DEVICES]; 40 int32 gDeviceCount; 41 42 43 static status_t 44 init_root_device(driver_t *driver, device_t *_root, device_t *_child) 45 { 46 static driver_t sRootDriver = { 47 "pci", 48 NULL, 49 sizeof(struct root_device_softc) 50 }; 51 device_t child; 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 root->driver = &sRootDriver; 64 root->root = root; 65 66 child = device_add_child(root, driver->name, 0); 67 if (child == NULL) { 68 device_delete_child(NULL, root); 69 return B_ERROR; 70 } 71 72 if (_root != NULL) 73 *_root = root; 74 if (_child != NULL) 75 *_child = child; 76 77 return B_OK; 78 } 79 80 81 static pci_info * 82 get_pci_info(struct device *device) 83 { 84 return &((struct root_device_softc *)device->softc)->pci_info; 85 } 86 87 88 // #pragma mark - Haiku Driver API 89 90 91 status_t 92 _fbsd_init_hardware(driver_t *driver) 93 { 94 status_t status = B_ENTRY_NOT_FOUND; 95 device_t child, root; 96 pci_info *info; 97 int i; 98 99 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) 100 return B_ERROR; 101 102 if (init_root_device(driver, &root, &child) != B_OK) { 103 dprintf("%s: creating device failed.\n", gDriverName); 104 put_module(B_PCI_MODULE_NAME); 105 return B_ERROR; 106 } 107 108 TRACE(("%s: init_hardware(%p)\n", gDriverName, driver)); 109 110 if (child->methods.probe == NULL) { 111 dprintf("%s: driver has no device_probe method.\n", gDriverName); 112 device_delete_child(NULL, root); 113 put_module(B_PCI_MODULE_NAME); 114 return B_ERROR; 115 } 116 117 info = get_pci_info(root); 118 119 for (i = 0; gPci->get_nth_pci_info(i, info) == B_OK; i++) { 120 int result; 121 result = child->methods.probe(child); 122 if (result >= 0) { 123 TRACE(("%s, found %s at %d\n", gDriverName, 124 device_get_desc(child), i)); 125 status = B_OK; 126 break; 127 } 128 } 129 130 if (status < B_OK) 131 TRACE(("%s: no hardware found.\n", gDriverName)); 132 133 device_delete_child(NULL, root); 134 put_module(B_PCI_MODULE_NAME); 135 136 return status; 137 } 138 139 140 status_t 141 _fbsd_init_driver(driver_t *driver) 142 { 143 status_t status; 144 int i = 0; 145 146 dprintf("%s: init_driver(%p)\n", gDriverName, driver); 147 148 status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); 149 if (status < B_OK) 150 return status; 151 152 status = init_hard_clock(); 153 if (status < B_OK) 154 goto err1; 155 156 status = init_mutexes(); 157 if (status < B_OK) 158 goto err2; 159 160 status = init_mbufs(); 161 if (status < B_OK) 162 goto err3; 163 164 init_bounce_pages(); 165 166 status = init_condition_variables(); 167 if (status < B_OK) 168 goto err4; 169 170 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 171 status = init_taskqueues(); 172 if (status < B_OK) 173 goto err5; 174 } 175 176 status = init_wlan_stack(); 177 if (status < B_OK) 178 goto err6; 179 180 while (gDeviceCount < MAX_DEVICES) { 181 device_t root, device; 182 bool found = false; 183 pci_info *info; 184 185 status = init_root_device(driver, &root, &device); 186 if (status < B_OK) 187 break; 188 189 info = get_pci_info(root); 190 191 for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) { 192 if (device->methods.probe(device) < 0) 193 continue; 194 195 if (device_attach(device) == 0) 196 found = true; 197 198 i++; 199 break; 200 } 201 202 if (!found) { 203 device_delete_child(NULL, root); 204 break; 205 } 206 } 207 208 if (gDeviceCount > 0) 209 return B_OK; 210 211 if (status == B_OK) 212 status = B_ERROR; 213 214 uninit_wlan_stack(); 215 216 err6: 217 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 218 uninit_taskqueues(); 219 err5: 220 uninit_condition_variables(); 221 err4: 222 uninit_mbufs(); 223 err3: 224 uninit_mutexes(); 225 err2: 226 uninit_hard_clock(); 227 err1: 228 put_module(B_PCI_MODULE_NAME); 229 return status; 230 } 231 232 233 void 234 _fbsd_uninit_driver(driver_t *driver) 235 { 236 int i; 237 238 TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver)); 239 240 for (i = 0; i < gDeviceCount; i++) { 241 device_delete_child(NULL, gDevices[i]->root_device); 242 } 243 244 uninit_wlan_stack(); 245 uninit_condition_variables(); 246 uninit_bounce_pages(); 247 uninit_mbufs(); 248 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 249 uninit_taskqueues(); 250 uninit_mutexes(); 251 252 put_module(B_PCI_MODULE_NAME); 253 } 254