]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/usb/bsd_kernel.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / boot / usb / bsd_kernel.c
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2013 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 <bsd_global.h>
28
29 struct usb_process usb_process[USB_PROC_MAX];
30
31 static device_t usb_pci_root;
32
33 /*------------------------------------------------------------------------*
34  * Implementation of mutex API
35  *------------------------------------------------------------------------*/
36
37 struct mtx Giant;
38
39 static void
40 mtx_system_init(void *arg)
41 {
42         mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
43 }
44 SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL);
45
46 void
47 mtx_init(struct mtx *mtx, const char *name, const char *type, int opt)
48 {
49         mtx->owned = 0;
50         mtx->parent = mtx;
51 }
52
53 void
54 mtx_lock(struct mtx *mtx)
55 {
56         mtx = mtx->parent;
57         mtx->owned++;
58 }
59
60 void
61 mtx_unlock(struct mtx *mtx)
62 {
63         mtx = mtx->parent;
64         mtx->owned--;
65 }
66
67 int
68 mtx_owned(struct mtx *mtx)
69 {
70         mtx = mtx->parent;
71         return (mtx->owned != 0);
72 }
73
74 void
75 mtx_destroy(struct mtx *mtx)
76 {
77         /* NOP */
78 }
79
80 /*------------------------------------------------------------------------*
81  * Implementation of shared/exclusive mutex API
82  *------------------------------------------------------------------------*/
83
84 void
85 sx_init_flags(struct sx *sx, const char *name, int flags)
86 {
87         sx->owned = 0;
88 }
89
90 void
91 sx_destroy(struct sx *sx)
92 {
93         /* NOP */
94 }
95
96 void
97 sx_xlock(struct sx *sx)
98 {
99         sx->owned++;
100 }
101
102 void
103 sx_xunlock(struct sx *sx)
104 {
105         sx->owned--;
106 }
107
108 int
109 sx_xlocked(struct sx *sx)
110 {
111         return (sx->owned != 0);
112 }
113
114 /*------------------------------------------------------------------------*
115  * Implementaiton of condition variable API
116  *------------------------------------------------------------------------*/
117
118 void
119 cv_init(struct cv *cv, const char *desc)
120 {
121         cv->sleeping = 0;
122 }
123
124 void
125 cv_destroy(struct cv *cv)
126 {
127         /* NOP */
128 }
129
130 void
131 cv_wait(struct cv *cv, struct mtx *mtx)
132 {
133         cv_timedwait(cv, mtx, -1);
134 }
135
136 int
137 cv_timedwait(struct cv *cv, struct mtx *mtx, int timo)
138 {
139         int start = ticks;
140         int delta;
141
142         if (cv->sleeping)
143                 return (EWOULDBLOCK);   /* not allowed */
144
145         cv->sleeping = 1;
146
147         while (cv->sleeping) {
148                 if (timo >= 0) {
149                         delta = ticks - start;
150                         if (delta >= timo || delta < 0)
151                                 break;
152                 }
153                 mtx_unlock(mtx);
154
155                 usb_idle();
156
157                 mtx_lock(mtx);
158         }
159
160         if (cv->sleeping) {
161                 cv->sleeping = 0;
162                 return (EWOULDBLOCK);   /* not allowed */
163         }
164         return (0);
165 }
166
167 void
168 cv_signal(struct cv *cv)
169 {
170         cv->sleeping = 0;
171 }
172
173 void
174 cv_broadcast(struct cv *cv)
175 {
176         cv->sleeping = 0;
177 }
178
179 /*------------------------------------------------------------------------*
180  * Implementation of callout API
181  *------------------------------------------------------------------------*/
182
183 static void callout_proc_msg(struct usb_proc_msg *);
184
185 volatile int ticks = 0;
186
187 static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout);
188
189 static struct mtx mtx_callout;
190 static struct usb_proc_msg callout_msg[2];
191
192 static void
193 callout_system_init(void *arg)
194 {
195         mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE);
196
197         callout_msg[0].pm_callback = &callout_proc_msg;
198         callout_msg[1].pm_callback = &callout_proc_msg;
199 }
200 SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL);
201
202 static void
203 callout_callback(struct callout *c)
204 {
205         mtx_lock(c->mtx);
206
207         mtx_lock(&mtx_callout);
208         if (c->entry.le_prev != NULL) {
209                 LIST_REMOVE(c, entry);
210                 c->entry.le_prev = NULL;
211         }
212         mtx_unlock(&mtx_callout);
213
214         if (c->func)
215                 (c->func) (c->arg);
216
217         if (!(c->flags & CALLOUT_RETURNUNLOCKED))
218                 mtx_unlock(c->mtx);
219 }
220
221 void
222 callout_process(int timeout)
223 {
224         ticks += timeout;
225         usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]);
226 }
227
228 static void
229 callout_proc_msg(struct usb_proc_msg *pmsg)
230 {
231         struct callout *c;
232         int delta;
233
234 repeat:
235         mtx_lock(&mtx_callout);
236
237         LIST_FOREACH(c, &head_callout, entry) {
238
239                 delta = c->timeout - ticks;
240                 if (delta < 0) {
241                         mtx_unlock(&mtx_callout);
242
243                         callout_callback(c);
244
245                         goto repeat;
246                 }
247         }
248         mtx_unlock(&mtx_callout);
249 }
250
251 void
252 callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
253 {
254         memset(c, 0, sizeof(*c));
255
256         if (mtx == NULL)
257                 mtx = &Giant;
258
259         c->mtx = mtx;
260         c->flags = (flags & CALLOUT_RETURNUNLOCKED);
261 }
262
263 void
264 callout_reset(struct callout *c, int to_ticks,
265     void (*func) (void *), void *arg)
266 {
267         callout_stop(c);
268
269         c->func = func;
270         c->arg = arg;
271         c->timeout = ticks + to_ticks;
272
273         mtx_lock(&mtx_callout);
274         LIST_INSERT_HEAD(&head_callout, c, entry);
275         mtx_unlock(&mtx_callout);
276 }
277
278 void
279 callout_stop(struct callout *c)
280 {
281         mtx_lock(&mtx_callout);
282
283         if (c->entry.le_prev != NULL) {
284                 LIST_REMOVE(c, entry);
285                 c->entry.le_prev = NULL;
286         }
287         mtx_unlock(&mtx_callout);
288
289         c->func = NULL;
290         c->arg = NULL;
291 }
292
293 void
294 callout_drain(struct callout *c)
295 {
296         if (c->mtx == NULL)
297                 return;                 /* not initialised */
298
299         mtx_lock(c->mtx);
300         callout_stop(c);
301         mtx_unlock(c->mtx);
302 }
303
304 int
305 callout_pending(struct callout *c)
306 {
307         int retval;
308
309         mtx_lock(&mtx_callout);
310         retval = (c->entry.le_prev != NULL);
311         mtx_unlock(&mtx_callout);
312
313         return (retval);
314 }
315
316 /*------------------------------------------------------------------------*
317  * Implementation of device API
318  *------------------------------------------------------------------------*/
319
320 static const char unknown_string[] = { "unknown" };
321
322 static TAILQ_HEAD(, module_data) module_head =
323     TAILQ_HEAD_INITIALIZER(module_head);
324
325 static uint8_t
326 devclass_equal(const char *a, const char *b)
327 {
328         char ta, tb;
329
330         if (a == b)
331                 return (1);
332
333         while (1) {
334                 ta = *a;
335                 tb = *b;
336                 if (ta != tb)
337                         return (0);
338                 if (ta == 0)
339                         break;
340                 a++;
341                 b++;
342         }
343         return (1);
344 }
345
346 int
347 bus_generic_resume(device_t dev)
348 {
349         return (0);
350 }
351
352 int
353 bus_generic_shutdown(device_t dev)
354 {
355         return (0);
356 }
357
358 int
359 bus_generic_suspend(device_t dev)
360 {
361         return (0);
362 }
363
364 int
365 bus_generic_print_child(device_t dev, device_t child)
366 {
367         return (0);
368 }
369
370 void
371 bus_generic_driver_added(device_t dev, driver_t *driver)
372 {
373         return;
374 }
375
376 device_t
377 device_get_parent(device_t dev)
378 {
379         return (dev ? dev->dev_parent : NULL);
380 }
381
382 void
383 device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg)
384 {
385         dev->dev_irq_fn = fn;
386         dev->dev_irq_arg = arg;
387 }
388
389 void
390 device_run_interrupts(device_t parent)
391 {
392         device_t child;
393
394         if (parent == NULL)
395                 return;
396
397         TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
398                 if (child->dev_irq_fn != NULL)
399                         (child->dev_irq_fn) (child->dev_irq_arg);
400         }
401 }
402
403 void
404 device_set_ivars(device_t dev, void *ivars)
405 {
406         dev->dev_aux = ivars;
407 }
408
409 void   *
410 device_get_ivars(device_t dev)
411 {
412         return (dev ? dev->dev_aux : NULL);
413 }
414
415 int
416 device_get_unit(device_t dev)
417 {
418         return (dev ? dev->dev_unit : 0);
419 }
420
421 int
422 bus_generic_detach(device_t dev)
423 {
424         device_t child;
425         int error;
426
427         if (!dev->dev_attached)
428                 return (EBUSY);
429
430         TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
431                 if ((error = device_detach(child)) != 0)
432                         return (error);
433         }
434         return (0);
435 }
436
437 const char *
438 device_get_nameunit(device_t dev)
439 {
440         if (dev && dev->dev_nameunit[0])
441                 return (dev->dev_nameunit);
442
443         return (unknown_string);
444 }
445
446 static uint8_t
447 devclass_create(devclass_t *dc_pp)
448 {
449         if (dc_pp == NULL) {
450                 return (1);
451         }
452         if (dc_pp[0] == NULL) {
453                 dc_pp[0] = malloc(sizeof(**(dc_pp)),
454                     M_DEVBUF, M_WAITOK | M_ZERO);
455
456                 if (dc_pp[0] == NULL) {
457                         return (1);
458                 }
459         }
460         return (0);
461 }
462
463 static const struct module_data *
464 devclass_find_create(const char *classname)
465 {
466         const struct module_data *mod;
467
468         TAILQ_FOREACH(mod, &module_head, entry) {
469                 if (devclass_equal(mod->mod_name, classname)) {
470                         if (devclass_create(mod->devclass_pp)) {
471                                 continue;
472                         }
473                         return (mod);
474                 }
475         }
476         return (NULL);
477 }
478
479 static uint8_t
480 devclass_add_device(const struct module_data *mod, device_t dev)
481 {
482         device_t *pp_dev;
483         device_t *end;
484         uint8_t unit;
485
486         pp_dev = mod->devclass_pp[0]->dev_list;
487         end = pp_dev + DEVCLASS_MAXUNIT;
488         unit = 0;
489
490         while (pp_dev != end) {
491                 if (*pp_dev == NULL) {
492                         *pp_dev = dev;
493                         dev->dev_unit = unit;
494                         dev->dev_module = mod;
495                         snprintf(dev->dev_nameunit,
496                             sizeof(dev->dev_nameunit),
497                             "%s%d", device_get_name(dev), unit);
498                         return (0);
499                 }
500                 pp_dev++;
501                 unit++;
502         }
503         DPRINTF("Could not add device to devclass.\n");
504         return (1);
505 }
506
507 static void
508 devclass_delete_device(const struct module_data *mod, device_t dev)
509 {
510         if (mod == NULL) {
511                 return;
512         }
513         mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
514         dev->dev_module = NULL;
515 }
516
517 static device_t
518 make_device(device_t parent, const char *name)
519 {
520         device_t dev = NULL;
521         const struct module_data *mod = NULL;
522
523         if (name) {
524
525                 mod = devclass_find_create(name);
526
527                 if (!mod) {
528
529                         DPRINTF("%s:%d:%s: can't find device "
530                             "class %s\n", __FILE__, __LINE__,
531                             __FUNCTION__, name);
532
533                         goto done;
534                 }
535         }
536         dev = malloc(sizeof(*dev),
537             M_DEVBUF, M_WAITOK | M_ZERO);
538
539         if (dev == NULL)
540                 goto done;
541
542         dev->dev_parent = parent;
543         TAILQ_INIT(&dev->dev_children);
544
545         if (name) {
546                 dev->dev_fixed_class = 1;
547                 if (devclass_add_device(mod, dev)) {
548                         goto error;
549                 }
550         }
551 done:
552         return (dev);
553
554 error:
555         if (dev) {
556                 free(dev, M_DEVBUF);
557         }
558         return (NULL);
559 }
560
561 device_t
562 device_add_child(device_t dev, const char *name, int unit)
563 {
564         device_t child;
565
566         if (unit != -1) {
567                 device_printf(dev, "Unit is not -1\n");
568         }
569         child = make_device(dev, name);
570         if (child == NULL) {
571                 device_printf(dev, "Could not add child '%s'\n", name);
572                 goto done;
573         }
574         if (dev == NULL) {
575                 /* no parent */
576                 goto done;
577         }
578         TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
579 done:
580         return (child);
581 }
582
583 int
584 device_delete_child(device_t dev, device_t child)
585 {
586         int error = 0;
587         device_t grandchild;
588
589         /* remove children first */
590
591         while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
592                 error = device_delete_child(child, grandchild);
593                 if (error) {
594                         device_printf(dev, "Error deleting child!\n");
595                         goto done;
596                 }
597         }
598
599         error = device_detach(child);
600
601         if (error)
602                 goto done;
603
604         devclass_delete_device(child->dev_module, child);
605
606         if (dev != NULL) {
607                 /* remove child from parent */
608                 TAILQ_REMOVE(&dev->dev_children, child, dev_link);
609         }
610         free(child, M_DEVBUF);
611
612 done:
613         return (error);
614 }
615
616 int
617 device_delete_children(device_t dev)
618 {
619         device_t child;
620         int error = 0;
621
622         while ((child = TAILQ_FIRST(&dev->dev_children))) {
623                 error = device_delete_child(dev, child);
624                 if (error) {
625                         device_printf(dev, "Error deleting child!\n");
626                         break;
627                 }
628         }
629         return (error);
630 }
631
632 void
633 device_quiet(device_t dev)
634 {
635         dev->dev_quiet = 1;
636 }
637
638 const char *
639 device_get_desc(device_t dev)
640 {
641         if (dev)
642                 return &(dev->dev_desc[0]);
643         return (unknown_string);
644 }
645
646 static int
647 default_method(void)
648 {
649         /* do nothing */
650         DPRINTF("Default method called\n");
651         return (0);
652 }
653
654 void   *
655 device_get_method(device_t dev, const char *what)
656 {
657         const struct device_method *mtod;
658
659         mtod = dev->dev_module->driver->methods;
660         while (mtod->func != NULL) {
661                 if (devclass_equal(mtod->desc, what)) {
662                         return (mtod->func);
663                 }
664                 mtod++;
665         }
666         return ((void *)&default_method);
667 }
668
669 const char *
670 device_get_name(device_t dev)
671 {
672         if (dev == NULL)
673                 return (unknown_string);
674
675         return (dev->dev_module->driver->name);
676 }
677
678 static int
679 device_allocate_softc(device_t dev)
680 {
681         const struct module_data *mod;
682
683         mod = dev->dev_module;
684
685         if ((dev->dev_softc_alloc == 0) &&
686             (mod->driver->size != 0)) {
687                 dev->dev_sc = malloc(mod->driver->size,
688                     M_DEVBUF, M_WAITOK | M_ZERO);
689
690                 if (dev->dev_sc == NULL)
691                         return (ENOMEM);
692
693                 dev->dev_softc_alloc = 1;
694         }
695         return (0);
696 }
697
698 int
699 device_probe_and_attach(device_t dev)
700 {
701         const struct module_data *mod;
702         const char *bus_name_parent;
703
704         bus_name_parent = device_get_name(device_get_parent(dev));
705
706         if (dev->dev_attached)
707                 return (0);             /* fail-safe */
708
709         if (dev->dev_fixed_class) {
710
711                 mod = dev->dev_module;
712
713                 if (DEVICE_PROBE(dev) <= 0) {
714
715                         if (device_allocate_softc(dev) == 0) {
716
717                                 if (DEVICE_ATTACH(dev) == 0) {
718                                         /* success */
719                                         dev->dev_attached = 1;
720                                         return (0);
721                                 }
722                         }
723                 }
724                 device_detach(dev);
725
726                 goto error;
727         }
728         /*
729          * Else find a module for our device, if any
730          */
731
732         TAILQ_FOREACH(mod, &module_head, entry) {
733                 if (devclass_equal(mod->bus_name, bus_name_parent)) {
734                         if (devclass_create(mod->devclass_pp)) {
735                                 continue;
736                         }
737                         if (devclass_add_device(mod, dev)) {
738                                 continue;
739                         }
740                         if (DEVICE_PROBE(dev) <= 0) {
741
742                                 if (device_allocate_softc(dev) == 0) {
743
744                                         if (DEVICE_ATTACH(dev) == 0) {
745                                                 /* success */
746                                                 dev->dev_attached = 1;
747                                                 return (0);
748                                         }
749                                 }
750                         }
751                         /* else try next driver */
752
753                         device_detach(dev);
754                 }
755         }
756
757 error:
758         return (ENODEV);
759 }
760
761 int
762 device_detach(device_t dev)
763 {
764         const struct module_data *mod = dev->dev_module;
765         int error;
766
767         if (dev->dev_attached) {
768
769                 error = DEVICE_DETACH(dev);
770                 if (error) {
771                         return error;
772                 }
773                 dev->dev_attached = 0;
774         }
775         device_set_softc(dev, NULL);
776
777         if (dev->dev_fixed_class == 0)
778                 devclass_delete_device(mod, dev);
779
780         return (0);
781 }
782
783 void
784 device_set_softc(device_t dev, void *softc)
785 {
786         if (dev->dev_softc_alloc) {
787                 free(dev->dev_sc, M_DEVBUF);
788                 dev->dev_sc = NULL;
789         }
790         dev->dev_sc = softc;
791         dev->dev_softc_alloc = 0;
792 }
793
794 void   *
795 device_get_softc(device_t dev)
796 {
797         if (dev == NULL)
798                 return (NULL);
799
800         return (dev->dev_sc);
801 }
802
803 int
804 device_is_attached(device_t dev)
805 {
806         return (dev->dev_attached);
807 }
808
809 void
810 device_set_desc(device_t dev, const char *desc)
811 {
812         snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
813 }
814
815 void
816 device_set_desc_copy(device_t dev, const char *desc)
817 {
818         device_set_desc(dev, desc);
819 }
820
821 void   *
822 devclass_get_softc(devclass_t dc, int unit)
823 {
824         return (device_get_softc(devclass_get_device(dc, unit)));
825 }
826
827 int
828 devclass_get_maxunit(devclass_t dc)
829 {
830         int max_unit = 0;
831
832         if (dc) {
833                 max_unit = DEVCLASS_MAXUNIT;
834                 while (max_unit--) {
835                         if (dc->dev_list[max_unit]) {
836                                 break;
837                         }
838                 }
839                 max_unit++;
840         }
841         return (max_unit);
842 }
843
844 device_t
845 devclass_get_device(devclass_t dc, int unit)
846 {
847         return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
848             NULL : dc->dev_list[unit]);
849 }
850
851 devclass_t
852 devclass_find(const char *classname)
853 {
854         const struct module_data *mod;
855
856         TAILQ_FOREACH(mod, &module_head, entry) {
857                 if (devclass_equal(mod->mod_name, classname))
858                         return (mod->devclass_pp[0]);
859         }
860         return (NULL);
861 }
862
863 void
864 module_register(void *data)
865 {
866         struct module_data *mdata = data;
867
868         TAILQ_INSERT_TAIL(&module_head, mdata, entry);
869 }
870
871 /*------------------------------------------------------------------------*
872  * System startup
873  *------------------------------------------------------------------------*/
874
875 static void
876 sysinit_run(const void **ppdata)
877 {
878         const struct sysinit *psys;
879
880         while ((psys = *ppdata) != NULL) {
881                 (psys->func) (psys->data);
882                 ppdata++;
883         }
884 }
885
886 /*------------------------------------------------------------------------*
887  * USB process API
888  *------------------------------------------------------------------------*/
889
890 static int usb_do_process(struct usb_process *);
891 static int usb_proc_level = -1;
892 static struct mtx usb_proc_mtx;
893
894 void
895 usb_idle(void)
896 {
897         int old_level = usb_proc_level;
898         int old_giant = Giant.owned;
899         int worked;
900
901         device_run_interrupts(usb_pci_root);
902
903         do {
904                 worked = 0;
905                 Giant.owned = 0;
906
907                 while (++usb_proc_level < USB_PROC_MAX)
908                         worked |= usb_do_process(usb_process + usb_proc_level);
909
910                 usb_proc_level = old_level;
911                 Giant.owned = old_giant;
912
913         } while (worked);
914 }
915
916 void
917 usb_init(void)
918 {
919         sysinit_run(sysinit_data);
920 }
921
922 void
923 usb_uninit(void)
924 {
925         sysinit_run(sysuninit_data);
926 }
927
928 static void
929 usb_process_init_sub(struct usb_process *up)
930 {
931         TAILQ_INIT(&up->up_qhead);
932
933         cv_init(&up->up_cv, "-");
934         cv_init(&up->up_drain, "usbdrain");
935
936         up->up_mtx = &usb_proc_mtx;
937 }
938
939 static void
940 usb_process_init(void *arg)
941 {
942         uint8_t x;
943
944         mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
945
946         for (x = 0; x != USB_PROC_MAX; x++)
947                 usb_process_init_sub(&usb_process[x]);
948
949 }
950 SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
951
952 static int
953 usb_do_process(struct usb_process *up)
954 {
955         struct usb_proc_msg *pm;
956         int worked = 0;
957
958         mtx_lock(&usb_proc_mtx);
959
960 repeat:
961         pm = TAILQ_FIRST(&up->up_qhead);
962
963         if (pm != NULL) {
964
965                 worked = 1;
966
967                 (pm->pm_callback) (pm);
968
969                 if (pm == TAILQ_FIRST(&up->up_qhead)) {
970                         /* nothing changed */
971                         TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
972                         pm->pm_qentry.tqe_prev = NULL;
973                 }
974                 goto repeat;
975         }
976         mtx_unlock(&usb_proc_mtx);
977
978         return (worked);
979 }
980
981 void   *
982 usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
983 {
984         struct usb_proc_msg *pm0 = _pm0;
985         struct usb_proc_msg *pm1 = _pm1;
986         struct usb_proc_msg *pm2;
987         usb_size_t d;
988         uint8_t t;
989
990         t = 0;
991
992         if (pm0->pm_qentry.tqe_prev) {
993                 t |= 1;
994         }
995         if (pm1->pm_qentry.tqe_prev) {
996                 t |= 2;
997         }
998         if (t == 0) {
999                 /*
1000                  * No entries are queued. Queue "pm0" and use the existing
1001                  * message number.
1002                  */
1003                 pm2 = pm0;
1004         } else if (t == 1) {
1005                 /* Check if we need to increment the message number. */
1006                 if (pm0->pm_num == up->up_msg_num) {
1007                         up->up_msg_num++;
1008                 }
1009                 pm2 = pm1;
1010         } else if (t == 2) {
1011                 /* Check if we need to increment the message number. */
1012                 if (pm1->pm_num == up->up_msg_num) {
1013                         up->up_msg_num++;
1014                 }
1015                 pm2 = pm0;
1016         } else if (t == 3) {
1017                 /*
1018                  * Both entries are queued. Re-queue the entry closest to
1019                  * the end.
1020                  */
1021                 d = (pm1->pm_num - pm0->pm_num);
1022
1023                 /* Check sign after subtraction */
1024                 if (d & 0x80000000) {
1025                         pm2 = pm0;
1026                 } else {
1027                         pm2 = pm1;
1028                 }
1029
1030                 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
1031         } else {
1032                 pm2 = NULL;             /* panic - should not happen */
1033         }
1034
1035         /* Put message last on queue */
1036
1037         pm2->pm_num = up->up_msg_num;
1038         TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
1039
1040         return (pm2);
1041 }
1042
1043 /*------------------------------------------------------------------------*
1044  *      usb_proc_is_gone
1045  *
1046  * Return values:
1047  *    0: USB process is running
1048  * Else: USB process is tearing down
1049  *------------------------------------------------------------------------*/
1050 uint8_t
1051 usb_proc_is_gone(struct usb_process *up)
1052 {
1053         return (0);
1054 }
1055
1056 /*------------------------------------------------------------------------*
1057  *      usb_proc_mwait
1058  *
1059  * This function will return when the USB process message pointed to
1060  * by "pm" is no longer on a queue. This function must be called
1061  * having "usb_proc_mtx" locked.
1062  *------------------------------------------------------------------------*/
1063 void
1064 usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
1065 {
1066         struct usb_proc_msg *pm0 = _pm0;
1067         struct usb_proc_msg *pm1 = _pm1;
1068
1069         /* Just remove the messages from the queue. */
1070         if (pm0->pm_qentry.tqe_prev) {
1071                 TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
1072                 pm0->pm_qentry.tqe_prev = NULL;
1073         }
1074         if (pm1->pm_qentry.tqe_prev) {
1075                 TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
1076                 pm1->pm_qentry.tqe_prev = NULL;
1077         }
1078 }
1079
1080 /*------------------------------------------------------------------------*
1081  * SYSTEM attach
1082  *------------------------------------------------------------------------*/
1083
1084 static device_method_t pci_methods[] = {
1085         DEVMETHOD_END
1086 };
1087
1088 static driver_t pci_driver = {
1089         .name = "pci",
1090         .methods = pci_methods,
1091 };
1092
1093 static devclass_t pci_devclass;
1094
1095 DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
1096
1097 static const char *usb_pci_devices[] = {
1098 #ifdef USB_PROBE_LIST
1099         USB_PROBE_LIST
1100 #endif
1101 };
1102
1103 #define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *))
1104
1105 static device_t usb_pci_dev[USB_PCI_USB_MAX];
1106
1107 static void
1108 usb_pci_mod_load(void *arg)
1109 {
1110         uint32_t x;
1111
1112         usb_pci_root = device_add_child(NULL, "pci", -1);
1113         if (usb_pci_root == NULL)
1114                 return;
1115
1116         for (x = 0; x != USB_PCI_USB_MAX; x++) {
1117                 usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1);
1118                 if (usb_pci_dev[x] == NULL)
1119                         continue;
1120                 if (device_probe_and_attach(usb_pci_dev[x])) {
1121                         device_printf(usb_pci_dev[x],
1122                             "WARNING: Probe and attach failed!\n");
1123                 }
1124         }
1125 }
1126 SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
1127
1128 static void
1129 usb_pci_mod_unload(void *arg)
1130 {
1131         uint32_t x;
1132
1133         for (x = 0; x != USB_PCI_USB_MAX; x++) {
1134                 if (usb_pci_dev[x]) {
1135                         device_detach(usb_pci_dev[x]);
1136                         device_delete_child(usb_pci_root, usb_pci_dev[x]);
1137                 }
1138         }
1139         if (usb_pci_root)
1140                 device_delete_child(NULL, usb_pci_root);
1141 }
1142 SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
1143
1144 /*------------------------------------------------------------------------*
1145  * MALLOC API
1146  *------------------------------------------------------------------------*/
1147
1148 #define USB_POOL_ALIGN 8
1149
1150 static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
1151 static uint32_t usb_pool_rem = USB_POOL_SIZE;
1152 static uint32_t usb_pool_entries;
1153
1154 struct malloc_hdr {
1155         TAILQ_ENTRY(malloc_hdr) entry;
1156         uint32_t size;
1157 } __aligned(USB_POOL_ALIGN);
1158
1159 static TAILQ_HEAD(, malloc_hdr) malloc_head =
1160         TAILQ_HEAD_INITIALIZER(malloc_head);
1161
1162 void   *
1163 usb_malloc(unsigned long size)
1164 {
1165         struct malloc_hdr *hdr;
1166
1167         size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
1168         size += sizeof(struct malloc_hdr);
1169
1170         TAILQ_FOREACH(hdr, &malloc_head, entry) {
1171                 if (hdr->size == size)
1172                         break;
1173         }
1174
1175         if (hdr) {
1176                 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1177                     (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1178
1179                 TAILQ_REMOVE(&malloc_head, hdr, entry);
1180                 memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1181                 return (hdr + 1);
1182         }
1183         if (usb_pool_rem >= size) {
1184                 hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
1185                 hdr->size = size;
1186
1187                 usb_pool_rem -= size;
1188                 usb_pool_entries++;
1189
1190                 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1191                     (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1192
1193                 memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1194                 return (hdr + 1);
1195         }
1196         return (NULL);
1197 }
1198
1199 void
1200 usb_free(void *arg)
1201 {
1202         struct malloc_hdr *hdr;
1203
1204         if (arg == NULL)
1205                 return;
1206
1207         hdr = arg;
1208         hdr--;
1209
1210         TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
1211 }
1212
1213 char   *
1214 usb_strdup(const char *str)
1215 {
1216         char *tmp;
1217         int len;
1218
1219         len = 1 + strlen(str);
1220
1221         tmp = usb_malloc(len);
1222         if (tmp == NULL)
1223                 return (NULL);
1224
1225         memcpy(tmp, str, len);
1226         return (tmp);
1227 }