xref: /haiku/src/libs/compat/freebsd_network/driver.c (revision c9ad965c81b08802fed0827fd1dd16f45297928a)
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_hard_clock();
153 	if (status < B_OK)
154 		goto err1;
155 
156 	status = init_mutexes();
157 	if (status < B_OK)
158 		goto err2;
159 
160 	status = init_mbufs();
161 	if (status < B_OK)
162 		goto err3;
163 
164 	init_bounce_pages();
165 
166 	status = init_condition_variables();
167 	if (status < B_OK)
168 		goto err4;
169 
170 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
171 		status = init_taskqueues();
172 		if (status < B_OK)
173 			goto err5;
174 	}
175 
176 	status = init_wlan_stack();
177 	if (status < B_OK)
178 		goto err6;
179 
180 	while (gDeviceCount < MAX_DEVICES) {
181 		device_t root, device;
182 		bool found = false;
183 		pci_info *info;
184 
185 		status = init_root_device(driver, &root, &device);
186 		if (status < B_OK)
187 			break;
188 
189 		info = get_pci_info(root);
190 
191 		for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) {
192 			if (device->methods.probe(device) < 0)
193 				continue;
194 
195 			if (device_attach(device) == 0)
196 				found = true;
197 
198 			i++;
199 			break;
200 		}
201 
202 		if (!found) {
203 			device_delete_child(NULL, root);
204 			break;
205 		}
206 	}
207 
208 	if (gDeviceCount > 0)
209 		return B_OK;
210 
211 	if (status == B_OK)
212 		status = B_ERROR;
213 
214 	uninit_wlan_stack();
215 
216 err6:
217 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
218 		uninit_taskqueues();
219 err5:
220 	uninit_condition_variables();
221 err4:
222 	uninit_mbufs();
223 err3:
224 	uninit_mutexes();
225 err2:
226 	uninit_hard_clock();
227 err1:
228 	put_module(B_PCI_MODULE_NAME);
229 	return status;
230 }
231 
232 
233 void
234 _fbsd_uninit_driver(driver_t *driver)
235 {
236 	int i;
237 
238 	TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver));
239 
240 	for (i = 0; i < gDeviceCount; i++) {
241 		device_delete_child(NULL, gDevices[i]->root_device);
242 	}
243 
244 	uninit_wlan_stack();
245 	uninit_condition_variables();
246 	uninit_bounce_pages();
247 	uninit_mbufs();
248 	if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
249 		uninit_taskqueues();
250 	uninit_mutexes();
251 
252 	put_module(B_PCI_MODULE_NAME);
253 }
254