xref: /haiku/src/libs/compat/freebsd_network/driver.c (revision 60a6f1d5d7a8715cd3897dd0b626f2e4a64984a8)
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 
184 	status = init_mutexes();
185 	if (status < B_OK)
186 		goto err2;
187 
188 	status = init_mbufs();
189 	if (status < B_OK)
190 		goto err3;
191 
192 	status = init_callout();
193 	if (status < B_OK)
194 		goto err4;
195 
196 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
197 		status = init_taskqueues();
198 		if (status < B_OK)
199 			goto err5;
200 	}
201 
202 	init_sysinit();
203 
204 	status = init_wlan_stack();
205 	if (status < B_OK)
206 		goto err6;
207 
208 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
209 		pci_info* info;
210 		device_t root, device = NULL;
211 		status = init_root_device(&root);
212 		if (status != B_OK)
213 			break;
214 
215 		info = get_pci_info(root);
216 		*info = sProbedDevices[p].info;
217 
218 		status = add_child_device(sProbedDevices[p].driver, root, &device);
219 		if (status != B_OK)
220 			break;
221 
222 		// some drivers expect probe() to be called before attach()
223 		// (i.e. they set driver softc in probe(), etc.)
224 		if (device->methods.probe(device) >= 0
225 				&& device_attach(device) == 0) {
226 			dprintf("%s: init_driver(%p)\n", gDriverName,
227 				sProbedDevices[p].driver);
228 		} else
229 			device_delete_child(NULL, root);
230 	}
231 
232 	if (gDeviceCount > 0)
233 		return B_OK;
234 
235 	if (status == B_OK)
236 		status = B_ERROR;
237 
238 err7:
239 	uninit_wlan_stack();
240 err6:
241 	uninit_sysinit();
242 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
243 		uninit_taskqueues();
244 err5:
245 	uninit_callout();
246 err4:
247 	uninit_mbufs();
248 err3:
249 	uninit_mutexes();
250 err2:
251 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
252 		gPci->unreserve_device(sProbedDevices[p].info.bus,
253 			sProbedDevices[p].info.device, sProbedDevices[p].info.function,
254 			gDriverName, NULL);
255 	}
256 
257 	put_module(B_PCI_MODULE_NAME);
258 	if (gPCIx86 != NULL)
259 		put_module(B_PCI_X86_MODULE_NAME);
260 
261 	return status;
262 }
263 
264 
265 status_t
266 _fbsd_uninit_drivers(driver_t *drivers[])
267 {
268 	int i, p;
269 
270 	for (i = 0; drivers[i]; i++)
271 		TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i]));
272 
273 	for (i = 0; i < gDeviceCount; i++) {
274 		device_delete_child(NULL, gDevices[i]->root_device);
275 	}
276 
277 	uninit_wlan_stack();
278 	uninit_sysinit();
279 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
280 		uninit_taskqueues();
281 	uninit_callout();
282 	uninit_mbufs();
283 	uninit_mutexes();
284 
285 	for (p = 0; sProbedDevices[p].driver != NULL; p++) {
286 		gPci->unreserve_device(sProbedDevices[p].info.bus,
287 			sProbedDevices[p].info.device, sProbedDevices[p].info.function,
288 			gDriverName, NULL);
289 	}
290 
291 	put_module(B_PCI_MODULE_NAME);
292 	if (gPCIx86 != NULL)
293 		put_module(B_PCI_X86_MODULE_NAME);
294 
295 	return B_OK;
296 }
297