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