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