Deleted Added
full compact
usb_controller.c (213435) usb_controller.c (215649)
1/* $FreeBSD: head/sys/dev/usb/controller/usb_controller.c 213435 2010-10-04 23:18:05Z hselasky $ */
1/* $FreeBSD: head/sys/dev/usb/controller/usb_controller.c 215649 2010-11-22 01:11:28Z 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>
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>
64
65/* function prototypes */
66
67static device_probe_t usb_probe;
68static device_attach_t usb_attach;
69static device_detach_t usb_detach;
70
71static void usb_attach_sub(device_t, struct usb_bus *);
72
73/* static variables */
74
75#ifdef USB_DEBUG
76static int usb_ctrl_debug = 0;
77
78SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
79SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
80 "Debug level");
81#endif
82
83static int usb_no_boot_wait = 0;
84TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
85SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
86 "No device enumerate waiting at boot.");
87
88static devclass_t usb_devclass;
89
90static device_method_t usb_methods[] = {
91 DEVMETHOD(device_probe, usb_probe),
92 DEVMETHOD(device_attach, usb_attach),
93 DEVMETHOD(device_detach, usb_detach),
94 DEVMETHOD(device_suspend, bus_generic_suspend),
95 DEVMETHOD(device_resume, bus_generic_resume),
96 DEVMETHOD(device_shutdown, bus_generic_shutdown),
97 {0, 0}
98};
99
100static driver_t usb_driver = {
101 .name = "usbus",
102 .methods = usb_methods,
103 .size = 0,
104};
105
106/* Host Only Drivers */
107DRIVER_MODULE(usbus, ohci, usb_driver, usb_devclass, 0, 0);
108DRIVER_MODULE(usbus, uhci, usb_driver, usb_devclass, 0, 0);
109DRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0);
110DRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0);
111
112/* Device Only Drivers */
113DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
114DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
115DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
116
117/*------------------------------------------------------------------------*
118 * usb_probe
119 *
120 * This function is called from "{ehci,ohci,uhci}_pci_attach()".
121 *------------------------------------------------------------------------*/
122static int
123usb_probe(device_t dev)
124{
125 DPRINTF("\n");
126 return (0);
127}
128
129static void
130usb_root_mount_rel(struct usb_bus *bus)
131{
132 if (bus->bus_roothold != NULL) {
133 DPRINTF("Releasing root mount hold %p\n", bus->bus_roothold);
134 root_mount_rel(bus->bus_roothold);
135 bus->bus_roothold = NULL;
136 }
137}
138
139/*------------------------------------------------------------------------*
140 * usb_attach
141 *------------------------------------------------------------------------*/
142static int
143usb_attach(device_t dev)
144{
145 struct usb_bus *bus = device_get_ivars(dev);
146
147 DPRINTF("\n");
148
149 if (bus == NULL) {
150 device_printf(dev, "USB device has no ivars\n");
151 return (ENXIO);
152 }
153
154 if (usb_no_boot_wait == 0) {
155 /* delay vfs_mountroot until the bus is explored */
156 bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
157 }
158
159 usb_attach_sub(dev, bus);
160
161 return (0); /* return success */
162}
163
164/*------------------------------------------------------------------------*
165 * usb_detach
166 *------------------------------------------------------------------------*/
167static int
168usb_detach(device_t dev)
169{
170 struct usb_bus *bus = device_get_softc(dev);
171
172 DPRINTF("\n");
173
174 if (bus == NULL) {
175 /* was never setup properly */
176 return (0);
177 }
178 /* Stop power watchdog */
179 usb_callout_drain(&bus->power_wdog);
180
181 /* Let the USB explore process detach all devices. */
182 usb_root_mount_rel(bus);
183
184 USB_BUS_LOCK(bus);
185 if (usb_proc_msignal(&bus->explore_proc,
186 &bus->detach_msg[0], &bus->detach_msg[1])) {
187 /* ignore */
188 }
189 /* Wait for detach to complete */
190
191 usb_proc_mwait(&bus->explore_proc,
192 &bus->detach_msg[0], &bus->detach_msg[1]);
193
194 USB_BUS_UNLOCK(bus);
195
196 /* Get rid of USB callback processes */
197
198 usb_proc_free(&bus->giant_callback_proc);
199 usb_proc_free(&bus->non_giant_callback_proc);
200
201 /* Get rid of USB explore process */
202
203 usb_proc_free(&bus->explore_proc);
204
205 /* Get rid of control transfer process */
206
207 usb_proc_free(&bus->control_xfer_proc);
208
209 return (0);
210}
211
212/*------------------------------------------------------------------------*
213 * usb_bus_explore
214 *
215 * This function is used to explore the device tree from the root.
216 *------------------------------------------------------------------------*/
217static void
218usb_bus_explore(struct usb_proc_msg *pm)
219{
220 struct usb_bus *bus;
221 struct usb_device *udev;
222
223 bus = ((struct usb_bus_msg *)pm)->bus;
224 udev = bus->devices[USB_ROOT_HUB_ADDR];
225
226 if (udev && udev->hub) {
227
228 if (bus->do_probe) {
229 bus->do_probe = 0;
230 bus->driver_added_refcount++;
231 }
232 if (bus->driver_added_refcount == 0) {
233 /* avoid zero, hence that is memory default */
234 bus->driver_added_refcount = 1;
235 }
236
237#ifdef DDB
238 /*
239 * The following three lines of code are only here to
240 * recover from DDB:
241 */
242 usb_proc_rewakeup(&bus->control_xfer_proc);
243 usb_proc_rewakeup(&bus->giant_callback_proc);
244 usb_proc_rewakeup(&bus->non_giant_callback_proc);
245#endif
246
247 USB_BUS_UNLOCK(bus);
248
249#if USB_HAVE_POWERD
250 /*
251 * First update the USB power state!
252 */
253 usb_bus_powerd(bus);
254#endif
255 /* Explore the Root USB HUB. */
256 (udev->hub->explore) (udev);
257 USB_BUS_LOCK(bus);
258 }
259 usb_root_mount_rel(bus);
260}
261
262/*------------------------------------------------------------------------*
263 * usb_bus_detach
264 *
265 * This function is used to detach the device tree from the root.
266 *------------------------------------------------------------------------*/
267static void
268usb_bus_detach(struct usb_proc_msg *pm)
269{
270 struct usb_bus *bus;
271 struct usb_device *udev;
272 device_t dev;
273
274 bus = ((struct usb_bus_msg *)pm)->bus;
275 udev = bus->devices[USB_ROOT_HUB_ADDR];
276 dev = bus->bdev;
277 /* clear the softc */
278 device_set_softc(dev, NULL);
279 USB_BUS_UNLOCK(bus);
280
281 /* detach children first */
282 mtx_lock(&Giant);
283 bus_generic_detach(dev);
284 mtx_unlock(&Giant);
285
286 /*
287 * Free USB device and all subdevices, if any.
288 */
289 usb_free_device(udev, 0);
290
291 USB_BUS_LOCK(bus);
292 /* clear bdev variable last */
293 bus->bdev = NULL;
294}
295
296static void
297usb_power_wdog(void *arg)
298{
299 struct usb_bus *bus = arg;
300
301 USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
302
303 usb_callout_reset(&bus->power_wdog,
304 4 * hz, usb_power_wdog, arg);
305
306#ifdef DDB
307 /*
308 * The following line of code is only here to recover from
309 * DDB:
310 */
311 usb_proc_rewakeup(&bus->explore_proc); /* recover from DDB */
312#endif
313
314#if USB_HAVE_POWERD
315 USB_BUS_UNLOCK(bus);
316
317 usb_bus_power_update(bus);
318
319 USB_BUS_LOCK(bus);
320#endif
321}
322
323/*------------------------------------------------------------------------*
324 * usb_bus_attach
325 *
326 * This function attaches USB in context of the explore thread.
327 *------------------------------------------------------------------------*/
328static void
329usb_bus_attach(struct usb_proc_msg *pm)
330{
331 struct usb_bus *bus;
332 struct usb_device *child;
333 device_t dev;
334 usb_error_t err;
335 enum usb_dev_speed speed;
336
337 bus = ((struct usb_bus_msg *)pm)->bus;
338 dev = bus->bdev;
339
340 DPRINTF("\n");
341
342 switch (bus->usbrev) {
343 case USB_REV_1_0:
344 speed = USB_SPEED_FULL;
345 device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n");
346 break;
347
348 case USB_REV_1_1:
349 speed = USB_SPEED_FULL;
350 device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n");
351 break;
352
353 case USB_REV_2_0:
354 speed = USB_SPEED_HIGH;
355 device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n");
356 break;
357
358 case USB_REV_2_5:
359 speed = USB_SPEED_VARIABLE;
360 device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n");
361 break;
362
363 case USB_REV_3_0:
364 speed = USB_SPEED_SUPER;
365 device_printf(bus->bdev, "4.8Gbps Super Speed USB v3.0\n");
366 break;
367
368 default:
369 device_printf(bus->bdev, "Unsupported USB revision\n");
370 usb_root_mount_rel(bus);
371 return;
372 }
373
374 USB_BUS_UNLOCK(bus);
375
376 /* default power_mask value */
377 bus->hw_power_state =
378 USB_HW_POWER_CONTROL |
379 USB_HW_POWER_BULK |
380 USB_HW_POWER_INTERRUPT |
381 USB_HW_POWER_ISOC |
382 USB_HW_POWER_NON_ROOT_HUB;
383
384 /* make sure power is set at least once */
385
386 if (bus->methods->set_hw_power != NULL) {
387 (bus->methods->set_hw_power) (bus);
388 }
389
390 /* Allocate the Root USB device */
391
392 child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
393 speed, USB_MODE_HOST);
394 if (child) {
395 err = usb_probe_and_attach(child,
396 USB_IFACE_INDEX_ANY);
397 if (!err) {
398 if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) ||
399 (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) {
400 err = USB_ERR_NO_ROOT_HUB;
401 }
402 }
403 } else {
404 err = USB_ERR_NOMEM;
405 }
406
407 USB_BUS_LOCK(bus);
408
409 if (err) {
410 device_printf(bus->bdev, "Root HUB problem, error=%s\n",
411 usbd_errstr(err));
412 usb_root_mount_rel(bus);
413 }
414
415 /* set softc - we are ready */
416 device_set_softc(dev, bus);
417
418 /* start watchdog */
419 usb_power_wdog(bus);
420}
421
422/*------------------------------------------------------------------------*
423 * usb_attach_sub
424 *
425 * This function creates a thread which runs the USB attach code.
426 *------------------------------------------------------------------------*/
427static void
428usb_attach_sub(device_t dev, struct usb_bus *bus)
429{
430 const char *pname = device_get_nameunit(dev);
431
432 mtx_lock(&Giant);
433 if (usb_devclass_ptr == NULL)
434 usb_devclass_ptr = devclass_find("usbus");
435 mtx_unlock(&Giant);
436
437 /* Initialise USB process messages */
438 bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
439 bus->explore_msg[0].bus = bus;
440 bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore;
441 bus->explore_msg[1].bus = bus;
442
443 bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach;
444 bus->detach_msg[0].bus = bus;
445 bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach;
446 bus->detach_msg[1].bus = bus;
447
448 bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach;
449 bus->attach_msg[0].bus = bus;
450 bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
451 bus->attach_msg[1].bus = bus;
452
453 /* Create USB explore and callback processes */
454
455 if (usb_proc_create(&bus->giant_callback_proc,
456 &bus->bus_mtx, pname, USB_PRI_MED)) {
457 printf("WARNING: Creation of USB Giant "
458 "callback process failed.\n");
459 } else if (usb_proc_create(&bus->non_giant_callback_proc,
460 &bus->bus_mtx, pname, USB_PRI_HIGH)) {
461 printf("WARNING: Creation of USB non-Giant "
462 "callback process failed.\n");
463 } else if (usb_proc_create(&bus->explore_proc,
464 &bus->bus_mtx, pname, USB_PRI_MED)) {
465 printf("WARNING: Creation of USB explore "
466 "process failed.\n");
467 } else if (usb_proc_create(&bus->control_xfer_proc,
468 &bus->bus_mtx, pname, USB_PRI_MED)) {
469 printf("WARNING: Creation of USB control transfer "
470 "process failed.\n");
471 } else {
472 /* Get final attach going */
473 USB_BUS_LOCK(bus);
474 if (usb_proc_msignal(&bus->explore_proc,
475 &bus->attach_msg[0], &bus->attach_msg[1])) {
476 /* ignore */
477 }
478 USB_BUS_UNLOCK(bus);
479
480 /* Do initial explore */
481 usb_needs_explore(bus, 1);
482 }
483}
484
485SYSUNINIT(usb_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb_bus_unload, NULL);
486
487/*------------------------------------------------------------------------*
488 * usb_bus_mem_flush_all_cb
489 *------------------------------------------------------------------------*/
490#if USB_HAVE_BUSDMA
491static void
492usb_bus_mem_flush_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
493 struct usb_page *pg, usb_size_t size, usb_size_t align)
494{
495 usb_pc_cpu_flush(pc);
496}
497#endif
498
499/*------------------------------------------------------------------------*
500 * usb_bus_mem_flush_all - factored out code
501 *------------------------------------------------------------------------*/
502#if USB_HAVE_BUSDMA
503void
504usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
505{
506 if (cb) {
507 cb(bus, &usb_bus_mem_flush_all_cb);
508 }
509}
510#endif
511
512/*------------------------------------------------------------------------*
513 * usb_bus_mem_alloc_all_cb
514 *------------------------------------------------------------------------*/
515#if USB_HAVE_BUSDMA
516static void
517usb_bus_mem_alloc_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
518 struct usb_page *pg, usb_size_t size, usb_size_t align)
519{
520 /* need to initialize the page cache */
521 pc->tag_parent = bus->dma_parent_tag;
522
523 if (usb_pc_alloc_mem(pc, pg, size, align)) {
524 bus->alloc_failed = 1;
525 }
526}
527#endif
528
529/*------------------------------------------------------------------------*
530 * usb_bus_mem_alloc_all - factored out code
531 *
532 * Returns:
533 * 0: Success
534 * Else: Failure
535 *------------------------------------------------------------------------*/
536uint8_t
537usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
538 usb_bus_mem_cb_t *cb)
539{
540 bus->alloc_failed = 0;
541
542 mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
543 NULL, MTX_DEF | MTX_RECURSE);
544
545 usb_callout_init_mtx(&bus->power_wdog,
546 &bus->bus_mtx, 0);
547
548 TAILQ_INIT(&bus->intr_q.head);
549
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 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
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
551 usbpf_attach(bus, &bus->uif);
552
550#if USB_HAVE_BUSDMA
551 usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
552 dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
553#endif
554 if ((bus->devices_max > USB_MAX_DEVICES) ||
555 (bus->devices_max < USB_MIN_DEVICES) ||
556 (bus->devices == NULL)) {
557 DPRINTFN(0, "Devices field has not been "
558 "initialised properly\n");
559 bus->alloc_failed = 1; /* failure */
560 }
561#if USB_HAVE_BUSDMA
562 if (cb) {
563 cb(bus, &usb_bus_mem_alloc_all_cb);
564 }
565#endif
566 if (bus->alloc_failed) {
567 usb_bus_mem_free_all(bus, cb);
568 }
569 return (bus->alloc_failed);
570}
571
572/*------------------------------------------------------------------------*
573 * usb_bus_mem_free_all_cb
574 *------------------------------------------------------------------------*/
575#if USB_HAVE_BUSDMA
576static void
577usb_bus_mem_free_all_cb(struct usb_bus *bus, struct usb_page_cache *pc,
578 struct usb_page *pg, usb_size_t size, usb_size_t align)
579{
580 usb_pc_free_mem(pc);
581}
582#endif
583
584/*------------------------------------------------------------------------*
585 * usb_bus_mem_free_all - factored out code
586 *------------------------------------------------------------------------*/
587void
588usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
589{
590#if USB_HAVE_BUSDMA
591 if (cb) {
592 cb(bus, &usb_bus_mem_free_all_cb);
593 }
594 usb_dma_tag_unsetup(bus->dma_parent_tag);
595#endif
596
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
600 usbpf_detach(bus);
601
597 mtx_destroy(&bus->bus_mtx);
598}
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}