xref: /haiku/src/libs/compat/freebsd_network/driver.c (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 #include "sysinit.h"
17 
18 #include <stdlib.h>
19 #include <sys/sockio.h>
20 
21 #include <Drivers.h>
22 #include <ether_driver.h>
23 #include <PCI_x86.h>
24 
25 #include <compat/sys/haiku-module.h>
26 
27 #include <compat/sys/bus.h>
28 #include <compat/sys/mbuf.h>
29 #include <compat/net/ethernet.h>
30 
31 
32 //#define TRACE_DRIVER
33 #ifdef TRACE_DRIVER
34 #	define TRACE(x) dprintf x
35 #else
36 #	define TRACE(x)
37 #endif
38 
39 
40 static struct {
41 	driver_t* driver;
42 	pci_info info;
43 } sProbedDevices[MAX_DEVICES];
44 
45 const char* gDeviceNameList[MAX_DEVICES + 1];
46 struct ifnet* gDevices[MAX_DEVICES];
47 int32 gDeviceCount;
48 
49 
50 static status_t
51 init_root_device(device_t *_root)
52 {
53 	static driver_t sRootDriver = {
54 		"pci",
55 		NULL,
56 		sizeof(struct root_device_softc)
57 	};
58 
59 	device_t root = device_add_child(NULL, NULL, 0);
60 	if (root == NULL)
61 		return B_NO_MEMORY;
62 
63 	root->softc = malloc(sizeof(struct root_device_softc));
64 	if (root->softc == NULL) {
65 		device_delete_child(NULL, root);
66 		return B_NO_MEMORY;
67 	}
68 
69 	bzero(root->softc, sizeof(struct root_device_softc));
70 	root->driver = &sRootDriver;
71 	root->root = root;
72 
73 	if (_root != NULL)
74 		*_root = root;
75 
76 	return B_OK;
77 }
78 
79 
80 static status_t
81 add_child_device(driver_t* driver, device_t root, device_t* _child)
82 {
83 	device_t child = device_add_child_driver(root, driver->name, driver, 0);
84 	if (child == NULL) {
85 		return B_ERROR;
86 	}
87 
88 	if (_child != NULL)
89 		*_child = child;
90 
91 	return B_OK;
92 }
93 
94 
95 static pci_info *
96 get_pci_info(struct device *device)
97 {
98 	return &((struct root_device_softc *)device->softc)->pci_info;
99 }
100 
101 
102 //	#pragma mark - Haiku Driver API
103 
104 
105 status_t
106 _fbsd_init_hardware(driver_t *drivers[])
107 {
108 	status_t status;
109 	int i = 0, p = 0, index = 0;
110 	pci_info* info;
111 	device_t root;
112 
113 	status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci);
114 	if (status != B_OK)
115 		return status;
116 
117 	// if it fails we just don't support x86 specific features (like MSIs)
118 	if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK)
119 		gPCIx86 = NULL;
120 
121 	status = init_root_device(&root);
122 	if (status != B_OK)
123 		return status;
124 
125 	for (p = 0; p <= MAX_DEVICES; p++)
126 		sProbedDevices[i].driver = NULL;
127 	p = 0;
128 
129 	for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK;
130 			i++) {
131 		int best = 0;
132 		driver_t* driver = NULL;
133 
134 		for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) {
135 			int result;
136 			device_t device = NULL;
137 			status = add_child_device(drivers[index], root, &device);
138 			if (status < B_OK)
139 				break;
140 
141 			result = device->methods.probe(device);
142 			if (result >= 0 && (driver == NULL || result > best)) {
143 				TRACE(("%s, found %s at %d (%d)\n", gDriverName,
144 					device_get_desc(device), i, result));
145 				driver = drivers[index];
146 				best = result;
147 			}
148 			device_delete_child(root, device);
149 		}
150 
151 		if (driver == NULL)
152 			continue;
153 
154 		// We've found a driver; now try to reserve the device and store it
155 		if (gPci->reserve_device(info->bus, info->device, info->function,
156 				gDriverName, NULL) != B_OK) {
157 			dprintf("%s: Failed to reserve PCI:%d:%d:%d\n",
158 				gDriverName, info->bus, info->device, info->function);
159 			continue;
160 		}
161 		sProbedDevices[p].driver = driver;
162 		sProbedDevices[p].info = *info;
163 		p++;
164 	}
165 
166 	device_delete_child(NULL, root);
167 
168 	if (p > 0)
169 		return B_OK;
170 
171 	put_module(B_PCI_MODULE_NAME);
172 	if (gPCIx86 != NULL)
173 		put_module(B_PCI_X86_MODULE_NAME);
174 	return B_NOT_SUPPORTED;
175 }
176 
177 
178 status_t
179 _fbsd_init_drivers(driver_t *drivers[])
180 {
181 	status_t status;
182 	int p = 0;
183 	pci_info* info;
184 	device_t root;
185 
186 	status = init_mutexes();
187 	if (status < B_OK)
188 		goto err2;
189 
190 	status = init_mbufs();
191 	if (status < B_OK)
192 		goto err3;
193 
194 	status = init_callout();
195 	if (status < B_OK)
196 		goto err4;
197 
198 	init_bounce_pages();
199 
200 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
201 		status = init_taskqueues();
202 		if (status < B_OK)
203 			goto err5;
204 	}
205 
206 	init_sysinit();
207 
208 	status = init_wlan_stack();
209 	if (status < B_OK)
210 		goto err6;
211 
212 	status = init_root_device(&root);
213 	if (status != B_OK)
214 		goto err7;
215 	info = get_pci_info(root);
216 
217 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
218 		device_t device = NULL;
219 		*info = sProbedDevices[p].info;
220 
221 		status = add_child_device(sProbedDevices[p].driver, root, &device);
222 		if (status != B_OK)
223 			break;
224 
225 		// some drivers expect probe() to be called before attach()
226 		// (i.e. they set driver softc in probe(), etc.)
227 		if (device->methods.probe(device) >= 0
228 				&& device_attach(device) == 0) {
229 			dprintf("%s: init_driver(%p)\n", gDriverName,
230 				sProbedDevices[p].driver);
231 			status = init_root_device(&root);
232 			if (status != B_OK)
233 				break;
234 			info = get_pci_info(root);
235 		} else
236 			device_delete_child(root, device);
237 	}
238 
239 	if (gDeviceCount > 0)
240 		return B_OK;
241 
242 	device_delete_child(NULL, root);
243 
244 	if (status == B_OK)
245 		status = B_ERROR;
246 
247 err7:
248 	uninit_wlan_stack();
249 
250 err6:
251 	uninit_sysinit();
252 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
253 		uninit_taskqueues();
254 err5:
255 	uninit_bounce_pages();
256 	uninit_callout();
257 err4:
258 	uninit_mbufs();
259 err3:
260 	uninit_mutexes();
261 err2:
262 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
263 		gPci->unreserve_device(sProbedDevices[p].info.bus,
264 			sProbedDevices[p].info.device, sProbedDevices[p].info.function,
265 			gDriverName, NULL);
266 	}
267 
268 	put_module(B_PCI_MODULE_NAME);
269 	if (gPCIx86 != NULL)
270 		put_module(B_PCI_X86_MODULE_NAME);
271 
272 	return status;
273 }
274 
275 
276 status_t
277 _fbsd_uninit_drivers(driver_t *drivers[])
278 {
279 	int i, p;
280 
281 	for (i = 0; drivers[i]; i++)
282 		TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i]));
283 
284 	for (i = 0; i < gDeviceCount; i++) {
285 		device_delete_child(NULL, gDevices[i]->root_device);
286 	}
287 
288 	uninit_wlan_stack();
289 	uninit_sysinit();
290 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
291 		uninit_taskqueues();
292 	uninit_bounce_pages();
293 	uninit_callout();
294 	uninit_mbufs();
295 	uninit_mutexes();
296 
297 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
298 		gPci->unreserve_device(sProbedDevices[p].info.bus,
299 			sProbedDevices[p].info.device, sProbedDevices[p].info.function,
300 			gDriverName, NULL);
301 	}
302 
303 	put_module(B_PCI_MODULE_NAME);
304 	if (gPCIx86 != NULL)
305 		put_module(B_PCI_X86_MODULE_NAME);
306 
307 	return B_OK;
308 }
309