xref: /haiku/src/libs/compat/freebsd_network/driver.c (revision 8d2bf6953e851d431fc67de1bc970c40afa79e9f)
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(driver_t *driver, device_t *_root, device_t *_child)
46 {
47 	static driver_t sRootDriver = {
48 		"pci",
49 		NULL,
50 		sizeof(struct root_device_softc)
51 	};
52 	device_t child;
53 
54 	device_t root = device_add_child(NULL, NULL, 0);
55 	if (root == NULL)
56 		return B_NO_MEMORY;
57 
58 	root->softc = malloc(sizeof(struct root_device_softc));
59 	if (root->softc == NULL) {
60 		device_delete_child(NULL, root);
61 		return B_NO_MEMORY;
62 	}
63 
64 	bzero(root->softc, sizeof(struct root_device_softc));
65 	root->driver = &sRootDriver;
66 	root->root = root;
67 
68 	child = device_add_child(root, driver->name, 0);
69 	if (child == NULL) {
70 		device_delete_child(NULL, root);
71 		return B_ERROR;
72 	}
73 
74 	if (_root != NULL)
75 		*_root = root;
76 	if (_child != NULL)
77 		*_child = child;
78 
79 	return B_OK;
80 }
81 
82 
83 static pci_info *
84 get_pci_info(struct device *device)
85 {
86 	return &((struct root_device_softc *)device->softc)->pci_info;
87 }
88 
89 
90 //	#pragma mark - Haiku Driver API
91 
92 
93 status_t
94 _fbsd_init_hardware(driver_t *drivers[])
95 {
96 	status_t status = B_ENTRY_NOT_FOUND;
97 	int index;
98 
99 	if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK)
100 		return B_ERROR;
101 
102 	for (index = 0; status != B_OK && drivers[index]; index++) {
103 		device_t child, root;
104 		pci_info *info;
105 		int i;
106 
107 		if (init_root_device(drivers[index], &root, &child) != B_OK) {
108 			dprintf("%s: creating device failed.\n", gDriverName);
109 			put_module(B_PCI_MODULE_NAME);
110 			return B_ERROR;
111 		}
112 
113 		TRACE(("%s: init_hardware(%p)\n", gDriverName, drivers[index]));
114 
115 		if (child->methods.probe == NULL) {
116 			dprintf("%s: driver has no device_probe method.\n", gDriverName);
117 			device_delete_child(NULL, root);
118 			put_module(B_PCI_MODULE_NAME);
119 			return B_ERROR;
120 		}
121 
122 		info = get_pci_info(root);
123 
124 		for (i = 0; gPci->get_nth_pci_info(i, info) == B_OK; i++) {
125 			int result;
126 			result = child->methods.probe(child);
127 			if (result >= 0) {
128 				TRACE(("%s, found %s at %d\n", gDriverName,
129 					device_get_desc(child), i));
130 				status = B_OK;
131 				break;
132 			}
133 		}
134 
135 		device_delete_child(NULL, root);
136 	}
137 
138 	if (status < B_OK)
139 		TRACE(("%s: no hardware found.\n", gDriverName));
140 
141 	put_module(B_PCI_MODULE_NAME);
142 
143 	return status;
144 }
145 
146 
147 status_t
148 _fbsd_init_drivers(driver_t *drivers[])
149 {
150 	status_t status;
151 	int i = 0;
152 	int index = 0;
153 
154 	dprintf("%s: init_driver(%p)\n", gDriverName, drivers[index]);
155 
156 	status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci);
157 	if (status < B_OK)
158 		return status;
159 
160 	// if it fails we just don't support x86 specific features (like MSIs)
161 	if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK)
162 		gPCIx86 = NULL;
163 
164 	status = init_hard_clock();
165 	if (status < B_OK)
166 		goto err1;
167 
168 	status = init_mutexes();
169 	if (status < B_OK)
170 		goto err2;
171 
172 	status = init_mbufs();
173 	if (status < B_OK)
174 		goto err3;
175 
176 	status = init_callout();
177 	if (status < B_OK)
178 		goto err4;
179 
180 	init_bounce_pages();
181 
182 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
183 		status = init_taskqueues();
184 		if (status < B_OK)
185 			goto err5;
186 	}
187 
188 	status = init_wlan_stack();
189 	if (status < B_OK)
190 		goto err6;
191 
192 	while (drivers[index] && gDeviceCount < MAX_DEVICES) {
193 		device_t root, device;
194 		bool found = false;
195 		pci_info *info;
196 
197 		status = init_root_device(drivers[index], &root, &device);
198 		if (status < B_OK)
199 			break;
200 
201 		info = get_pci_info(root);
202 
203 		for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) {
204 			if (device->methods.probe(device) < 0)
205 				continue;
206 
207 			if (device_attach(device) == 0)
208 				found = true;
209 
210 			i++;
211 			break;
212 		}
213 
214 		if (!found) {
215 			device_delete_child(NULL, root);
216 			i = 0;
217 			if (drivers[++index])
218 				dprintf("%s: init_driver(%p)\n", gDriverName, drivers[index]);
219 		}
220 	}
221 
222 	if (gDeviceCount > 0)
223 		return B_OK;
224 
225 	if (status == B_OK)
226 		status = B_ERROR;
227 
228 	uninit_wlan_stack();
229 
230 err6:
231 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
232 		uninit_taskqueues();
233 err5:
234 	uninit_mbufs();
235 err4:
236 	uninit_callout();
237 err3:
238 	uninit_mutexes();
239 err2:
240 	uninit_hard_clock();
241 err1:
242 	put_module(B_PCI_MODULE_NAME);
243 	if (gPCIx86 != NULL)
244 		put_module(B_PCI_X86_MODULE_NAME);
245 
246 	return status;
247 }
248 
249 
250 status_t
251 _fbsd_uninit_drivers(driver_t *drivers[])
252 {
253 	int i;
254 
255 	for (i = 0; drivers[i]; i++)
256 		TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i]));
257 
258 	for (i = 0; i < gDeviceCount; i++) {
259 		device_delete_child(NULL, gDevices[i]->root_device);
260 	}
261 
262 	uninit_wlan_stack();
263 	uninit_bounce_pages();
264 	uninit_mbufs();
265 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
266 		uninit_taskqueues();
267 	uninit_callout();
268 	uninit_mutexes();
269 
270 	put_module(B_PCI_MODULE_NAME);
271 	if (gPCIx86 != NULL)
272 		put_module(B_PCI_X86_MODULE_NAME);
273 
274 	return B_OK;
275 }
276