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