xref: /haiku/src/libs/compat/freebsd_network/driver.c (revision 14627e087b920676d05d45cec5f28688744e1fdb)
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 
23 #include <compat/sys/haiku-module.h>
24 
25 #include <compat/sys/bus.h>
26 #include <compat/sys/mbuf.h>
27 #include <compat/net/ethernet.h>
28 
29 
30 //#define TRACE_DRIVER
31 #ifdef TRACE_DRIVER
32 #	define TRACE(x) dprintf x
33 #else
34 #	define TRACE(x)
35 #endif
36 
37 
38 const char *gDeviceNameList[MAX_DEVICES + 1];
39 struct ifnet *gDevices[MAX_DEVICES];
40 int32 gDeviceCount;
41 
42 
43 static status_t
44 init_root_device(driver_t *driver, device_t *_root, device_t *_child)
45 {
46 	static driver_t sRootDriver = {
47 		"pci",
48 		NULL,
49 		sizeof(struct root_device_softc)
50 	};
51 	device_t child;
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 	root->driver = &sRootDriver;
64 	root->root = root;
65 
66 	child = device_add_child(root, driver->name, 0);
67 	if (child == NULL) {
68 		device_delete_child(NULL, root);
69 		return B_ERROR;
70 	}
71 
72 	if (_root != NULL)
73 		*_root = root;
74 	if (_child != NULL)
75 		*_child = child;
76 
77 	return B_OK;
78 }
79 
80 
81 static pci_info *
82 get_pci_info(struct device *device)
83 {
84 	return &((struct root_device_softc *)device->softc)->pci_info;
85 }
86 
87 
88 //	#pragma mark - Haiku Driver API
89 
90 
91 status_t
92 _fbsd_init_hardware(driver_t *driver)
93 {
94 	status_t status = B_ENTRY_NOT_FOUND;
95 	device_t child, root;
96 	pci_info *info;
97 	int i;
98 
99 	if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK)
100 		return B_ERROR;
101 
102 	if (init_root_device(driver, &root, &child) != B_OK) {
103 		dprintf("%s: creating device failed.\n", gDriverName);
104 		put_module(B_PCI_MODULE_NAME);
105 		return B_ERROR;
106 	}
107 
108 	TRACE(("%s: init_hardware(%p)\n", gDriverName, driver));
109 
110 	if (child->methods.probe == NULL) {
111 		dprintf("%s: driver has no device_probe method.\n", gDriverName);
112 		device_delete_child(NULL, root);
113 		put_module(B_PCI_MODULE_NAME);
114 		return B_ERROR;
115 	}
116 
117 	info = get_pci_info(root);
118 
119 	for (i = 0; gPci->get_nth_pci_info(i, info) == B_OK; i++) {
120 		int result;
121 		result = child->methods.probe(child);
122 		if (result >= 0) {
123 			TRACE(("%s, found %s at %d\n", gDriverName,
124 				device_get_desc(child), i));
125 			status = B_OK;
126 			break;
127 		}
128 	}
129 
130 	if (status < B_OK)
131 		TRACE(("%s: no hardware found.\n", gDriverName));
132 
133 	device_delete_child(NULL, root);
134 	put_module(B_PCI_MODULE_NAME);
135 
136 	return status;
137 }
138 
139 
140 status_t
141 _fbsd_init_driver(driver_t *driver)
142 {
143 	status_t status;
144 	int i = 0;
145 
146 	dprintf("%s: init_driver(%p)\n", gDriverName, driver);
147 
148 	status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci);
149 	if (status < B_OK)
150 		return status;
151 
152 	status = init_mutexes();
153 	if (status < B_OK)
154 		goto err1;
155 
156 	status = init_mbufs();
157 	if (status < B_OK)
158 		goto err2;
159 
160 	init_bounce_pages();
161 
162 	status = init_condition_variables();
163 	if (status < B_OK)
164 		goto err3;
165 
166 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
167 		status = init_taskqueues();
168 		if (status < B_OK)
169 			goto err4;
170 	}
171 
172 	status = init_wlan_stack();
173 	if (status < B_OK)
174 		goto err5;
175 
176 	while (gDeviceCount < MAX_DEVICES) {
177 		device_t root, device;
178 		bool found = false;
179 		pci_info *info;
180 
181 		status = init_root_device(driver, &root, &device);
182 		if (status < B_OK)
183 			break;
184 
185 		info = get_pci_info(root);
186 
187 		for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) {
188 			if (device->methods.probe(device) < 0)
189 				continue;
190 
191 			if (device_attach(device) == 0)
192 				found = true;
193 
194 			i++;
195 			break;
196 		}
197 
198 		if (!found) {
199 			device_delete_child(NULL, root);
200 			break;
201 		}
202 	}
203 
204 	if (gDeviceCount > 0)
205 		return B_OK;
206 
207 	if (status == B_OK)
208 		status = B_ERROR;
209 
210 	uninit_wlan_stack();
211 
212 err5:
213 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
214 		uninit_taskqueues();
215 err4:
216 	uninit_condition_variables();
217 err3:
218 	uninit_mbufs();
219 err2:
220 	uninit_mutexes();
221 err1:
222 	put_module(B_PCI_MODULE_NAME);
223 	return status;
224 }
225 
226 
227 void
228 _fbsd_uninit_driver(driver_t *driver)
229 {
230 	int i;
231 
232 	TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver));
233 
234 	for (i = 0; i < gDeviceCount; i++) {
235 		device_delete_child(NULL, gDevices[i]->root_device);
236 	}
237 
238 	uninit_wlan_stack();
239 	uninit_condition_variables();
240 	uninit_bounce_pages();
241 	uninit_mbufs();
242 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
243 		uninit_taskqueues();
244 	uninit_mutexes();
245 
246 	put_module(B_PCI_MODULE_NAME);
247 }
248