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