Deleted Added
full compact
usb_controller.c (215802) usb_controller.c (215812)
1/* $FreeBSD: head/sys/dev/usb/controller/usb_controller.c 215802 2010-11-24 19:11:32Z weongyo $ */
1/* $FreeBSD: head/sys/dev/usb/controller/usb_controller.c 215812 2010-11-25 03:30:43Z weongyo $ */
2/*-
3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include "opt_ddb.h"
28
29#include <sys/stdint.h>
30#include <sys/stddef.h>
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/types.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/bus.h>
37#include <sys/linker_set.h>
38#include <sys/module.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/condvar.h>
42#include <sys/sysctl.h>
43#include <sys/sx.h>
44#include <sys/unistd.h>
45#include <sys/callout.h>
46#include <sys/malloc.h>
47#include <sys/priv.h>
48
49#include <dev/usb/usb.h>
50#include <dev/usb/usbdi.h>
51
52#define USB_DEBUG_VAR usb_ctrl_debug
53
54#include <dev/usb/usb_core.h>
55#include <dev/usb/usb_debug.h>
56#include <dev/usb/usb_process.h>
57#include <dev/usb/usb_busdma.h>
58#include <dev/usb/usb_dynamic.h>
59#include <dev/usb/usb_device.h>
60#include <dev/usb/usb_hub.h>
61
62#include <dev/usb/usb_controller.h>
63#include <dev/usb/usb_bus.h>
64#include <dev/usb/usb_pf.h>
65
66/* function prototypes */
67
68static device_probe_t usb_probe;
69static device_attach_t usb_attach;
70static device_detach_t usb_detach;
71
72static void usb_attach_sub(device_t, struct usb_bus *);
73
74/* static variables */
75
76#ifdef USB_DEBUG
77static int usb_ctrl_debug = 0;
78
79SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
80SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
81 "Debug level");
82#endif
83
84static int usb_no_boot_wait = 0;
85TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
86SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
87 "No device enumerate waiting at boot.");
88
89static devclass_t usb_devclass;
90
91static device_method_t usb_methods[] = {
92 DEVMETHOD(device_probe, usb_probe),
93 DEVMETHOD(device_attach, usb_attach),
94 DEVMETHOD(device_detach, usb_detach),
95 DEVMETHOD(device_suspend, bus_generic_suspend),
96 DEVMETHOD(device_resume, bus_generic_resume),
97 DEVMETHOD(device_shutdown, bus_generic_shutdown),
98 {0, 0}
99};
100
101static driver_t usb_driver = {
102 .name = "usbus",
103 .methods = usb_methods,
104 .size = 0,
105};
106
107/* Host Only Drivers */
108DRIVER_MODULE(usbus, ohci, usb_driver, usb_devclass, 0, 0);
109DRIVER_MODULE(usbus, uhci, usb_driver, usb_devclass, 0, 0);
110DRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0);
111DRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0);
112
113/* Device Only Drivers */
114DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
115DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
116DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
117
118/*------------------------------------------------------------------------*
119 * usb_probe
120 *
121 * This function is called from "{ehci,ohci,uhci}_pci_attach()".
122 *------------------------------------------------------------------------*/
123static int
124usb_probe(device_t dev)
125{
126 DPRINTF("\n");
127 return (0);
128}
129
130static void
131usb_root_mount_rel(struct usb_bus *bus)
132{
133 if (bus->bus_roothold != NULL) {
134 DPRINTF("Releasing root mount hold %p\n", bus->bus_roothold);
135 root_mount_rel(bus->bus_roothold);
136 bus->bus_roothold = NULL;
137 }
138}
139
140/*------------------------------------------------------------------------*
141 * usb_attach
142 *------------------------------------------------------------------------*/
143static int
144usb_attach(device_t dev)
145{
146 struct usb_bus *bus = device_get_ivars(dev);
147
148 DPRINTF("\n");
149
150 if (bus == NULL) {
151 device_printf(dev, "USB device has no ivars\n");
152 return (ENXIO);
153 }
154
155 if (usb_no_boot_wait == 0) {
156 /* delay vfs_mountroot until the bus is explored */
157 bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
158 }
159
160 usb_attach_sub(dev, bus);
161
162 return (0); /* return success */
163}
164
165/*------------------------------------------------------------------------*
166 * usb_detach
167 *------------------------------------------------------------------------*/
168static int
169usb_detach(device_t dev)
170{
171 struct usb_bus *bus = device_get_softc(dev);
172
173 DPRINTF("\n");
174
175 if (bus == NULL) {
176 /* was never setup properly */
177 return (0);
178 }
179 /* Stop power watchdog */
180 usb_callout_drain(&bus->power_wdog);
181
182 /* Let the USB explore process detach all devices. */
183 usb_root_mount_rel(bus);
184
185 USB_BUS_LOCK(bus);
186 if (usb_proc_msignal(&bus->explore_proc,
187 &bus->detach_msg[0], &bus->detach_msg[1])) {
188 /* ignore */
189 }
190 /* Wait for detach to complete */
191
192 usb_proc_mwait(&bus->explore_proc,
193 &bus->detach_msg[0], &bus->detach_msg[1]);
194
195 USB_BUS_UNLOCK(bus);
196
197 /* Get rid of USB callback processes */
198
199 usb_proc_free(&bus->giant_callback_proc);
200 usb_proc_free(&bus->non_giant_callback_proc);
201
202 /* Get rid of USB explore process */
203
204 usb_proc_free(&bus->explore_proc);
205
206 /* Get rid of control transfer process */
207
208 usb_proc_free(&bus->control_xfer_proc);
209
2/*-
3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include "opt_ddb.h"
28
29#include <sys/stdint.h>
30#include <sys/stddef.h>
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/types.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/bus.h>
37#include <sys/linker_set.h>
38#include <sys/module.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/condvar.h>
42#include <sys/sysctl.h>
43#include <sys/sx.h>
44#include <sys/unistd.h>
45#include <sys/callout.h>
46#include <sys/malloc.h>
47#include <sys/priv.h>
48
49#include <dev/usb/usb.h>
50#include <dev/usb/usbdi.h>
51
52#define USB_DEBUG_VAR usb_ctrl_debug
53
54#include <dev/usb/usb_core.h>
55#include <dev/usb/usb_debug.h>
56#include <dev/usb/usb_process.h>
57#include <dev/usb/usb_busdma.h>
58#include <dev/usb/usb_dynamic.h>
59#include <dev/usb/usb_device.h>
60#include <dev/usb/usb_hub.h>
61
62#include <dev/usb/usb_controller.h>
63#include <dev/usb/usb_bus.h>
64#include <dev/usb/usb_pf.h>
65
66/* function prototypes */
67
68static device_probe_t usb_probe;
69static device_attach_t usb_attach;
70static device_detach_t usb_detach;
71
72static void usb_attach_sub(device_t, struct usb_bus *);
73
74/* static variables */
75
76#ifdef USB_DEBUG
77static int usb_ctrl_debug = 0;
78
79SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
80SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
81 "Debug level");
82#endif
83
84static int usb_no_boot_wait = 0;
85TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
86SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
87 "No device enumerate waiting at boot.");
88
89static devclass_t usb_devclass;
90
91static device_method_t usb_methods[] = {
92 DEVMETHOD(device_probe, usb_probe),
93 DEVMETHOD(device_attach, usb_attach),
94 DEVMETHOD(device_detach, usb_detach),
95 DEVMETHOD(device_suspend, bus_generic_suspend),
96 DEVMETHOD(device_resume, bus_generic_resume),
97 DEVMETHOD(device_shutdown, bus_generic_shutdown),
98 {0, 0}
99};
100
101static driver_t usb_driver = {
102 .name = "usbus",
103 .methods = usb_methods,
104 .size = 0,
105};
106
107/* Host Only Drivers */
108DRIVER_MODULE(usbus, ohci, usb_driver, usb_devclass, 0, 0);
109DRIVER_MODULE(usbus, uhci, usb_driver, usb_devclass, 0, 0);
110DRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0);
111DRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0);
112
113/* Device Only Drivers */
114DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
115DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
116DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
117
118/*------------------------------------------------------------------------*
119 * usb_probe
120 *
121 * This function is called from "{ehci,ohci,uhci}_pci_attach()".
122 *------------------------------------------------------------------------*/
123static int
124usb_probe(device_t dev)
125{
126 DPRINTF("\n");
127 return (0);
128}
129
130static void
131usb_root_mount_rel(struct usb_bus *bus)
132{
133 if (bus->bus_roothold != NULL) {
134 DPRINTF("Releasing root mount hold %p\n", bus->bus_roothold);
135 root_mount_rel(bus->bus_roothold);
136 bus->bus_roothold = NULL;
137 }
138}
139
140/*------------------------------------------------------------------------*
141 * usb_attach
142 *------------------------------------------------------------------------*/
143static int
144usb_attach(device_t dev)
145{
146 struct usb_bus *bus = device_get_ivars(dev);
147
148 DPRINTF("\n");
149
150 if (bus == NULL) {
151 device_printf(dev, "USB device has no ivars\n");
152 return (ENXIO);
153 }
154
155 if (usb_no_boot_wait == 0) {
156 /* delay vfs_mountroot until the bus is explored */
157 bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
158 }
159
160 usb_attach_sub(dev, bus);
161
162 return (0); /* return success */
163}
164
165/*------------------------------------------------------------------------*
166 * usb_detach
167 *------------------------------------------------------------------------*/
168static int
169usb_detach(device_t dev)
170{
171 struct usb_bus *bus = device_get_softc(dev);
172
173 DPRINTF("\n");
174
175 if (bus == NULL) {
176 /* was never setup properly */
177 return (0);
178 }
179 /* Stop power watchdog */
180 usb_callout_drain(&bus->power_wdog);
181
182 /* Let the USB explore process detach all devices. */
183 usb_root_mount_rel(bus);
184
185 USB_BUS_LOCK(bus);
186 if (usb_proc_msignal(&bus->explore_proc,
187 &bus->detach_msg[0], &bus->detach_msg[1])) {
188 /* ignore */
189 }
190 /* Wait for detach to complete */
191
192 usb_proc_mwait(&bus->explore_proc,
193 &bus->detach_msg[0], &bus->detach_msg[1]);
194
195 USB_BUS_UNLOCK(bus);
196
197 /* Get rid of USB callback processes */
198
199 usb_proc_free(&bus->giant_callback_proc);
200 usb_proc_free(&bus->non_giant_callback_proc);
201
202 /* Get rid of USB explore process */
203
204 usb_proc_free(&bus->explore_proc);
205
206 /* Get rid of control transfer process */
207
208 usb_proc_free(&bus->control_xfer_proc);
209
210 usbpf_detach(bus);
211
210 return (0);
211}
212
213/*------------------------------------------------------------------------*
214 * usb_bus_explore
215 *
216 * This function is used to explore the device tree from the root.
217 *------------------------------------------------------------------------*/
218static void
219usb_bus_explore(struct usb_proc_msg *pm)
220{
221 struct usb_bus *bus;
222 struct usb_device *udev;
223
224 bus = ((struct usb_bus_msg *)pm)->bus;
225 udev = bus->devices[USB_ROOT_HUB_ADDR];
226
227 if (udev && udev->hub) {
228
229 if (bus->do_probe) {
230 bus->do_probe = 0;
231 bus->driver_added_refcount++;
232 }
233 if (bus->driver_added_refcount == 0) {
234 /* avoid zero, hence that is memory default */
235 bus->driver_added_refcount = 1;
236 }
237
238#ifdef DDB
239 /*
240 * The following three lines of code are only here to
241 * recover from DDB:
242 */
243 usb_proc_rewakeup(&bus->control_xfer_proc);
244 usb_proc_rewakeup(&bus->giant_callback_proc);
245 usb_proc_rewakeup(&bus->non_giant_callback_proc);
246#endif
247
248 USB_BUS_UNLOCK(bus);
249
250#if USB_HAVE_POWERD
251 /*
252 * First update the USB power state!
253 */
254 usb_bus_powerd(bus);
255#endif
256 /* Explore the Root USB HUB. */
257 (udev->hub->explore) (udev);
258 USB_BUS_LOCK(bus);
259 }
260 usb_root_mount_rel(bus);
261}
262
263/*------------------------------------------------------------------------*
264 * usb_bus_detach
265 *
266 * This function is used to detach the device tree from the root.
267 *------------------------------------------------------------------------*/
268static void
269usb_bus_detach(struct usb_proc_msg *pm)
270{
271 struct usb_bus *bus;
272 struct usb_device *udev;
273 device_t dev;
274
275 bus = ((struct usb_bus_msg *)pm)->bus;
276 udev = bus->devices[USB_ROOT_HUB_ADDR];
277 dev = bus->bdev;
278 /* clear the softc */
279 device_set_softc(dev, NULL);
280 USB_BUS_UNLOCK(bus);
281
282 /* detach children first */
283 mtx_lock(&Giant);
284 bus_generic_detach(dev);
285 mtx_unlock(&Giant);
286
287 /*
288 * Free USB device and all subdevices, if any.
289 */
290 usb_free_device(udev, 0);
291
292 USB_BUS_LOCK(bus);
293 /* clear bdev variable last */
294 bus->bdev = NULL;
295}
296
297static void
298usb_power_wdog(void *arg)
299{
300 struct usb_bus *bus = arg;
301
302 USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
303
304 usb_callout_reset(&bus->power_wdog,
305 4 * hz, usb_power_wdog, arg);
306
307#ifdef DDB
308 /*
309 * The following line of code is only here to recover from
310 * DDB:
311 */
312 usb_proc_rewakeup(&bus->explore_proc); /* recover from DDB */
313#endif
314
315#if USB_HAVE_POWERD
316 USB_BUS_UNLOCK(bus);
317
318 usb_bus_power_update(bus);
319
320 USB_BUS_LOCK(bus);
321#endif
322}
323
324/*------------------------------------------------------------------------*
325 * usb_bus_attach
326 *
327 * This function attaches USB in context of the explore thread.
328 *------------------------------------------------------------------------*/
329static void
330usb_bus_attach(struct usb_proc_msg *pm)
331{
332 struct usb_bus *bus;
333 struct usb_device *child;
334 device_t dev;
335 usb_error_t err;
336 enum usb_dev_speed speed;
337
338 bus = ((struct usb_bus_msg *)pm)->bus;
339 dev = bus->bdev;
340
341 DPRINTF("\n");
342
343 switch (bus->usbrev) {
344 case USB_REV_1_0:
345 speed = USB_SPEED_FULL;
346 device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n");
347 break;
348
349 case USB_REV_1_1:
350 speed = USB_SPEED_FULL;
351 device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n");
352 break;
353
354 case USB_REV_2_0:
355 speed = USB_SPEED_HIGH;
356 device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n");
357 break;
358
359 case USB_REV_2_5:
360 speed = USB_SPEED_VARIABLE;
361 device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n");
362 break;
363
364 case USB_REV_3_0:
365 speed = USB_SPEED_SUPER;
366 device_printf(bus->bdev, "4.8Gbps Super Speed USB v3.0\n");
367 break;
368
369 default:
370 device_printf(bus->bdev, "Unsupported USB revision\n");
371 usb_root_mount_rel(bus);
372 return;
373 }
374
375 USB_BUS_UNLOCK(bus);
376
377 /* default power_mask value */
378 bus->hw_power_state =
379 USB_HW_POWER_CONTROL |
380 USB_HW_POWER_BULK |
381 USB_HW_POWER_INTERRUPT |
382 USB_HW_POWER_ISOC |
383 USB_HW_POWER_NON_ROOT_HUB;
384
385 /* make sure power is set at least once */
386
387 if (bus->methods->set_hw_power != NULL) {
388 (bus->methods->set_hw_power) (bus);
389 }
390
391 /* Allocate the Root USB device */
392
393 child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
394 speed, USB_MODE_HOST);
395 if (child) {
396 err = usb_probe_and_attach(child,
397 USB_IFACE_INDEX_ANY);
398 if (!err) {
399 if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) ||
400 (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) {
401 err = USB_ERR_NO_ROOT_HUB;
402 }
403 }
404 } else {
405 err = USB_ERR_NOMEM;
406 }
407
408 USB_BUS_LOCK(bus);
409
410 if (err) {
411 device_printf(bus->bdev, "Root HUB problem, error=%s\n",
412 usbd_errstr(err));
413 usb_root_mount_rel(bus);
414 }
415
416 /* set softc - we are ready */
417 device_set_softc(dev, bus);
418
419 /* start watchdog */
420 usb_power_wdog(bus);
421}
422
423/*------------------------------------------------------------------------*
424 * usb_attach_sub
425 *
426 * This function creates a thread which runs the USB attach code.
427 *------------------------------------------------------------------------*/
428static void
429usb_attach_sub(device_t dev, struct usb_bus *bus)
430{
431 const char *pname = device_get_nameunit(dev);
432
433 mtx_lock(&Giant);
434 if (usb_devclass_ptr == NULL)
435 usb_devclass_ptr = devclass_find("usbus");
436 mtx_unlock(&Giant);
437
212 return (0);
213}
214
215/*------------------------------------------------------------------------*
216 * usb_bus_explore
217 *
218 * This function is used to explore the device tree from the root.
219 *------------------------------------------------------------------------*/
220static void
221usb_bus_explore(struct usb_proc_msg *pm)
222{
223 struct usb_bus *bus;
224 struct usb_device *udev;
225
226 bus = ((struct usb_bus_msg *)pm)->bus;
227 udev = bus->devices[USB_ROOT_HUB_ADDR];
228
229 if (udev && udev->hub) {
230
231 if (bus->do_probe) {
232 bus->do_probe = 0;
233 bus->driver_added_refcount++;
234 }
235 if (bus->driver_added_refcount == 0) {
236 /* avoid zero, hence that is memory default */
237 bus->driver_added_refcount = 1;
238 }
239
240#ifdef DDB
241 /*
242 * The following three lines of code are only here to
243 * recover from DDB:
244 */
245 usb_proc_rewakeup(&bus->control_xfer_proc);
246 usb_proc_rewakeup(&bus->giant_callback_proc);
247 usb_proc_rewakeup(&bus->non_giant_callback_proc);
248#endif
249
250 USB_BUS_UNLOCK(bus);
251
252#if USB_HAVE_POWERD
253 /*
254 * First update the USB power state!
255 */
256 usb_bus_powerd(bus);
257#endif
258 /* Explore the Root USB HUB. */
259 (udev->hub->explore) (udev);
260 USB_BUS_LOCK(bus);
261 }
262 usb_root_mount_rel(bus);
263}
264
265/*------------------------------------------------------------------------*
266 * usb_bus_detach
267 *
268 * This function is used to detach the device tree from the root.
269 *------------------------------------------------------------------------*/
270static void
271usb_bus_detach(struct usb_proc_msg *pm)
272{
273 struct usb_bus *bus;
274 struct usb_device *udev;
275 device_t dev;
276
277 bus = ((struct usb_bus_msg *)pm)->bus;
278 udev = bus->devices[USB_ROOT_HUB_ADDR];
279 dev = bus->bdev;
280 /* clear the softc */
281 device_set_softc(dev, NULL);
282 USB_BUS_UNLOCK(bus);
283
284 /* detach children first */
285 mtx_lock(&Giant);
286 bus_generic_detach(dev);
287 mtx_unlock(&Giant);
288
289 /*
290 * Free USB device and all subdevices, if any.
291 */
292 usb_free_device(udev, 0);
293
294 USB_BUS_LOCK(bus);
295 /* clear bdev variable last */
296 bus->bdev = NULL;
297}
298
299static void
300usb_power_wdog(void *arg)
301{
302 struct usb_bus *bus = arg;
303
304 USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
305
306 usb_callout_reset(&bus->power_wdog,
307 4 * hz, usb_power_wdog, arg);
308
309#ifdef DDB
310 /*
311 * The following line of code is only here to recover from
312 * DDB:
313 */
314 usb_proc_rewakeup(&bus->explore_proc); /* recover from DDB */
315#endif
316
317#if USB_HAVE_POWERD
318 USB_BUS_UNLOCK(bus);
319
320 usb_bus_power_update(bus);
321
322 USB_BUS_LOCK(bus);
323#endif
324}
325
326/*------------------------------------------------------------------------*
327 * usb_bus_attach
328 *
329 * This function attaches USB in context of the explore thread.
330 *------------------------------------------------------------------------*/
331static void
332usb_bus_attach(struct usb_proc_msg *pm)
333{
334 struct usb_bus *bus;
335 struct usb_device *child;
336 device_t dev;
337 usb_error_t err;
338 enum usb_dev_speed speed;
339
340 bus = ((struct usb_bus_msg *)pm)->bus;
341 dev = bus->bdev;
342
343 DPRINTF("\n");
344
345 switch (bus->usbrev) {
346 case USB_REV_1_0:
347 speed = USB_SPEED_FULL;
348 device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n");
349 break;
350
351 case USB_REV_1_1:
352 speed = USB_SPEED_FULL;
353 device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n");
354 break;
355
356 case USB_REV_2_0:
357 speed = USB_SPEED_HIGH;
358 device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n");
359 break;
360
361 case USB_REV_2_5:
362 speed = USB_SPEED_VARIABLE;
363 device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n");
364 break;
365
366 case USB_REV_3_0:
367 speed = USB_SPEED_SUPER;
368 device_printf(bus->bdev, "4.8Gbps Super Speed USB v3.0\n");
369 break;
370
371 default:
372 device_printf(bus->bdev, "Unsupported USB revision\n");
373 usb_root_mount_rel(bus);
374 return;
375 }
376
377 USB_BUS_UNLOCK(bus);
378
379 /* default power_mask value */
380 bus->hw_power_state =
381 USB_HW_POWER_CONTROL |
382 USB_HW_POWER_BULK |
383 USB_HW_POWER_INTERRUPT |
384 USB_HW_POWER_ISOC |
385 USB_HW_POWER_NON_ROOT_HUB;
386
387 /* make sure power is set at least once */
388
389 if (bus->methods->set_hw_power != NULL) {
390 (bus->methods->set_hw_power) (bus);
391 }
392
393 /* Allocate the Root USB device */
394
395 child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
396 speed, USB_MODE_HOST);
397 if (child) {
398 err = usb_probe_and_attach(child,
399 USB_IFACE_INDEX_ANY);
400 if (!err) {
401 if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) ||
402 (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) {
403 err = USB_ERR_NO_ROOT_HUB;
404 }
405 }
406 } else {
407 err = USB_ERR_NOMEM;
408 }
409
410 USB_BUS_LOCK(bus);
411
412 if (err) {
413 device_printf(bus->bdev, "Root HUB problem, error=%s\n",
414 usbd_errstr(err));
415 usb_root_mount_rel(bus);
416 }
417
418 /* set softc - we are ready */
419 device_set_softc(dev, bus);
420
421 /* start watchdog */
422 usb_power_wdog(bus);
423}
424
425/*------------------------------------------------------------------------*
426 * usb_attach_sub
427 *
428 * This function creates a thread which runs the USB attach code.
429 *------------------------------------------------------------------------*/
430static void
431usb_attach_sub(device_t dev, struct usb_bus *bus)
432{
433 const char *pname = device_get_nameunit(dev);
434
435 mtx_lock(&Giant);
436 if (usb_devclass_ptr == NULL)
437 usb_devclass_ptr = devclass_find("usbus");
438 mtx_unlock(&Giant);
439
440 usbpf_attach(bus);
441
438 /* Initialise USB process messages */
439 bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
440 bus->explore_msg[0].bus = bus;
441 bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
442 bus->explore_msg[1].bus = bus;
443
444 bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
445 bus->detach_msg[0].bus = bus;
446 bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
447 bus->detach_msg[1].bus = bus;
448
449 bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
450 bus->attach_msg[0].bus = bus;
451 bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
452 bus->attach_msg[1].bus = bus;
453
454 /* Create USB explore and callback processes */
455
456 if (usb_proc_create(&bus->giant_callback_proc,
457 &bus->bus_mtx, pname, USB_PRI_MED)) {
458 printf("WARNING: Creation of USB Giant "
459 "callback process failed.\n");
460 } else if (usb_proc_create(&bus->non_giant_callback_proc,
461 &bus->bus_mtx, pname, USB_PRI_HIGH)) {
462 printf("WARNING: Creation of USB non-Giant "
463 "callback process failed.\n");
464 } else if (usb_proc_create(&bus->explore_proc,
465 &bus->bus_mtx, pname, USB_PRI_MED)) {
466 printf("WARNING: Creation of USB explore "
467 "process failed.\n");
468 } else if (usb_proc_create(&bus->control_xfer_proc,
469 &bus->bus_mtx, pname, USB_PRI_MED)) {
470 printf("WARNING: Creation of USB control transfer "
471 "process failed.\n");
472 } else {
473 /* Get final attach going */
474 USB_BUS_LOCK(bus);
475 if (usb_proc_msignal(&bus->explore_proc,
476 &bus->attach_msg[0], &bus->attach_msg[1])) {
477 /* ignore */
478 }
479 USB_BUS_UNLOCK(bus);
480
481 /* Do initial explore */
482 usb_needs_explore(bus, 1);
483 }
484}
485
486SYSUNINIT(usb_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb_bus_unload, NULL);
487
488/*------------------------------------------------------------------------*
489 * usb_bus_mem_flush_all_cb
490 *------------------------------------------------------------------------*/
491#if USB_HAVE_BUSDMA
492static void
493usb_bus_mem_flush_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
494 struct usb_page *pg, usb_size_t size, usb_size_t align)
495{
496 usb_pc_cpu_flush(pc);
497}
498#endif
499
500/*------------------------------------------------------------------------*
501 * usb_bus_mem_flush_all - factored out code
502 *------------------------------------------------------------------------*/
503#if USB_HAVE_BUSDMA
504void
505usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
506{
507 if (cb) {
508 cb(bus, &usb_bus_mem_flush_all_cb);
509 }
510}
511#endif
512
513/*------------------------------------------------------------------------*
514 * usb_bus_mem_alloc_all_cb
515 *------------------------------------------------------------------------*/
516#if USB_HAVE_BUSDMA
517static void
518usb_bus_mem_alloc_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
519 struct usb_page *pg, usb_size_t size, usb_size_t align)
520{
521 /* need to initialize the page cache */
522 pc->tag_parent = bus->dma_parent_tag;
523
524 if (usb_pc_alloc_mem(pc, pg, size, align)) {
525 bus->alloc_failed = 1;
526 }
527}
528#endif
529
530/*------------------------------------------------------------------------*
531 * usb_bus_mem_alloc_all - factored out code
532 *
533 * Returns:
534 * 0: Success
535 * Else: Failure
536 *------------------------------------------------------------------------*/
537uint8_t
538usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
539 usb_bus_mem_cb_t *cb)
540{
541 bus->alloc_failed = 0;
542
543 mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
544 NULL, MTX_DEF | MTX_RECURSE);
545
546 usb_callout_init_mtx(&bus->power_wdog,
547 &bus->bus_mtx, 0);
548
549 TAILQ_INIT(&bus->intr_q.head);
550
442 /* Initialise USB process messages */
443 bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
444 bus->explore_msg[0].bus = bus;
445 bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
446 bus->explore_msg[1].bus = bus;
447
448 bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
449 bus->detach_msg[0].bus = bus;
450 bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
451 bus->detach_msg[1].bus = bus;
452
453 bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
454 bus->attach_msg[0].bus = bus;
455 bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
456 bus->attach_msg[1].bus = bus;
457
458 /* Create USB explore and callback processes */
459
460 if (usb_proc_create(&bus->giant_callback_proc,
461 &bus->bus_mtx, pname, USB_PRI_MED)) {
462 printf("WARNING: Creation of USB Giant "
463 "callback process failed.\n");
464 } else if (usb_proc_create(&bus->non_giant_callback_proc,
465 &bus->bus_mtx, pname, USB_PRI_HIGH)) {
466 printf("WARNING: Creation of USB non-Giant "
467 "callback process failed.\n");
468 } else if (usb_proc_create(&bus->explore_proc,
469 &bus->bus_mtx, pname, USB_PRI_MED)) {
470 printf("WARNING: Creation of USB explore "
471 "process failed.\n");
472 } else if (usb_proc_create(&bus->control_xfer_proc,
473 &bus->bus_mtx, pname, USB_PRI_MED)) {
474 printf("WARNING: Creation of USB control transfer "
475 "process failed.\n");
476 } else {
477 /* Get final attach going */
478 USB_BUS_LOCK(bus);
479 if (usb_proc_msignal(&bus->explore_proc,
480 &bus->attach_msg[0], &bus->attach_msg[1])) {
481 /* ignore */
482 }
483 USB_BUS_UNLOCK(bus);
484
485 /* Do initial explore */
486 usb_needs_explore(bus, 1);
487 }
488}
489
490SYSUNINIT(usb_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb_bus_unload, NULL);
491
492/*------------------------------------------------------------------------*
493 * usb_bus_mem_flush_all_cb
494 *------------------------------------------------------------------------*/
495#if USB_HAVE_BUSDMA
496static void
497usb_bus_mem_flush_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
498 struct usb_page *pg, usb_size_t size, usb_size_t align)
499{
500 usb_pc_cpu_flush(pc);
501}
502#endif
503
504/*------------------------------------------------------------------------*
505 * usb_bus_mem_flush_all - factored out code
506 *------------------------------------------------------------------------*/
507#if USB_HAVE_BUSDMA
508void
509usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
510{
511 if (cb) {
512 cb(bus, &usb_bus_mem_flush_all_cb);
513 }
514}
515#endif
516
517/*------------------------------------------------------------------------*
518 * usb_bus_mem_alloc_all_cb
519 *------------------------------------------------------------------------*/
520#if USB_HAVE_BUSDMA
521static void
522usb_bus_mem_alloc_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
523 struct usb_page *pg, usb_size_t size, usb_size_t align)
524{
525 /* need to initialize the page cache */
526 pc->tag_parent = bus->dma_parent_tag;
527
528 if (usb_pc_alloc_mem(pc, pg, size, align)) {
529 bus->alloc_failed = 1;
530 }
531}
532#endif
533
534/*------------------------------------------------------------------------*
535 * usb_bus_mem_alloc_all - factored out code
536 *
537 * Returns:
538 * 0: Success
539 * Else: Failure
540 *------------------------------------------------------------------------*/
541uint8_t
542usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
543 usb_bus_mem_cb_t *cb)
544{
545 bus->alloc_failed = 0;
546
547 mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
548 NULL, MTX_DEF | MTX_RECURSE);
549
550 usb_callout_init_mtx(&bus->power_wdog,
551 &bus->bus_mtx, 0);
552
553 TAILQ_INIT(&bus->intr_q.head);
554
551 usbpf_attach(bus);
552
553#if USB_HAVE_BUSDMA
554 usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
555 dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
556#endif
557 if ((bus->devices_max > USB_MAX_DEVICES) ||
558 (bus->devices_max < USB_MIN_DEVICES) ||
559 (bus->devices == NULL)) {
560 DPRINTFN(0, "Devices field has not been "
561 "initialised properly\n");
562 bus->alloc_failed = 1; /* failure */
563 }
564#if USB_HAVE_BUSDMA
565 if (cb) {
566 cb(bus, &usb_bus_mem_alloc_all_cb);
567 }
568#endif
569 if (bus->alloc_failed) {
570 usb_bus_mem_free_all(bus, cb);
571 }
572 return (bus->alloc_failed);
573}
574
575/*------------------------------------------------------------------------*
576 * usb_bus_mem_free_all_cb
577 *------------------------------------------------------------------------*/
578#if USB_HAVE_BUSDMA
579static void
580usb_bus_mem_free_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
581 struct usb_page *pg, usb_size_t size, usb_size_t align)
582{
583 usb_pc_free_mem(pc);
584}
585#endif
586
587/*------------------------------------------------------------------------*
588 * usb_bus_mem_free_all - factored out code
589 *------------------------------------------------------------------------*/
590void
591usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
592{
593#if USB_HAVE_BUSDMA
594 if (cb) {
595 cb(bus, &usb_bus_mem_free_all_cb);
596 }
597 usb_dma_tag_unsetup(bus->dma_parent_tag);
598#endif
599
555#if USB_HAVE_BUSDMA
556 usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
557 dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
558#endif
559 if ((bus->devices_max > USB_MAX_DEVICES) ||
560 (bus->devices_max < USB_MIN_DEVICES) ||
561 (bus->devices == NULL)) {
562 DPRINTFN(0, "Devices field has not been "
563 "initialised properly\n");
564 bus->alloc_failed = 1; /* failure */
565 }
566#if USB_HAVE_BUSDMA
567 if (cb) {
568 cb(bus, &usb_bus_mem_alloc_all_cb);
569 }
570#endif
571 if (bus->alloc_failed) {
572 usb_bus_mem_free_all(bus, cb);
573 }
574 return (bus->alloc_failed);
575}
576
577/*------------------------------------------------------------------------*
578 * usb_bus_mem_free_all_cb
579 *------------------------------------------------------------------------*/
580#if USB_HAVE_BUSDMA
581static void
582usb_bus_mem_free_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
583 struct usb_page *pg, usb_size_t size, usb_size_t align)
584{
585 usb_pc_free_mem(pc);
586}
587#endif
588
589/*------------------------------------------------------------------------*
590 * usb_bus_mem_free_all - factored out code
591 *------------------------------------------------------------------------*/
592void
593usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
594{
595#if USB_HAVE_BUSDMA
596 if (cb) {
597 cb(bus, &usb_bus_mem_free_all_cb);
598 }
599 usb_dma_tag_unsetup(bus->dma_parent_tag);
600#endif
601
600 usbpf_detach(bus);
601
602 mtx_destroy(&bus->bus_mtx);
603}
604
605struct usb_bus *
606usb_bus_find(const char *name)
607{
608 struct usb_bus *ubus;
609 devclass_t dc;
610 device_t *devlist;
611 int devcount, error, i;
612 const char *nameunit;
613
614 dc = devclass_find("usbus");
615 if (dc == NULL)
616 return (NULL);
617 error = devclass_get_devices(dc, &devlist, &devcount);
618 if (error != 0)
619 return (NULL);
620 for (i = 0; i < devcount; i++) {
621 nameunit = device_get_nameunit(devlist[i]);
622 if (!strncmp(name, nameunit, strlen(nameunit))) {
623 ubus = device_get_ivars(devlist[i]);
624 free(devlist, M_TEMP);
625 return (ubus);
626 }
627 }
628 free(devlist, M_TEMP);
629 return (NULL);
630}
602 mtx_destroy(&bus->bus_mtx);
603}
604
605struct usb_bus *
606usb_bus_find(const char *name)
607{
608 struct usb_bus *ubus;
609 devclass_t dc;
610 device_t *devlist;
611 int devcount, error, i;
612 const char *nameunit;
613
614 dc = devclass_find("usbus");
615 if (dc == NULL)
616 return (NULL);
617 error = devclass_get_devices(dc, &devlist, &devcount);
618 if (error != 0)
619 return (NULL);
620 for (i = 0; i < devcount; i++) {
621 nameunit = device_get_nameunit(devlist[i]);
622 if (!strncmp(name, nameunit, strlen(nameunit))) {
623 ubus = device_get_ivars(devlist[i]);
624 free(devlist, M_TEMP);
625 return (ubus);
626 }
627 }
628 free(devlist, M_TEMP);
629 return (NULL);
630}