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_mutexes(); 153 if (status < B_OK) 154 goto err1; 155 156 status = init_mbufs(); 157 if (status < B_OK) 158 goto err2; 159 160 init_bounce_pages(); 161 162 status = init_condition_variables(); 163 if (status < B_OK) 164 goto err3; 165 166 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 167 status = init_taskqueues(); 168 if (status < B_OK) 169 goto err4; 170 } 171 172 status = init_wlan_stack(); 173 if (status < B_OK) 174 goto err5; 175 176 while (gDeviceCount < MAX_DEVICES) { 177 device_t root, device; 178 bool found = false; 179 pci_info *info; 180 181 status = init_root_device(driver, &root, &device); 182 if (status < B_OK) 183 break; 184 185 info = get_pci_info(root); 186 187 for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) { 188 if (device->methods.probe(device) < 0) 189 continue; 190 191 if (device_attach(device) == 0) 192 found = true; 193 194 i++; 195 break; 196 } 197 198 if (!found) { 199 device_delete_child(NULL, root); 200 break; 201 } 202 } 203 204 if (gDeviceCount > 0) 205 return B_OK; 206 207 if (status == B_OK) 208 status = B_ERROR; 209 210 uninit_wlan_stack(); 211 212 err5: 213 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 214 uninit_taskqueues(); 215 err4: 216 uninit_condition_variables(); 217 err3: 218 uninit_mbufs(); 219 err2: 220 uninit_mutexes(); 221 err1: 222 put_module(B_PCI_MODULE_NAME); 223 return status; 224 } 225 226 227 void 228 _fbsd_uninit_driver(driver_t *driver) 229 { 230 int i; 231 232 TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver)); 233 234 for (i = 0; i < gDeviceCount; i++) { 235 device_delete_child(NULL, gDevices[i]->root_device); 236 } 237 238 uninit_wlan_stack(); 239 uninit_condition_variables(); 240 uninit_bounce_pages(); 241 uninit_mbufs(); 242 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 243 uninit_taskqueues(); 244 uninit_mutexes(); 245 246 put_module(B_PCI_MODULE_NAME); 247 } 248