]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/boot/usb/bsd_kernel.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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, driver_filter_t *filter,
384     driver_intr_t *fn, void *arg)
385 {
386         dev->dev_irq_filter = filter;
387         dev->dev_irq_fn = fn;
388         dev->dev_irq_arg = arg;
389 }
390
391 void
392 device_run_interrupts(device_t parent)
393 {
394         device_t child;
395
396         if (parent == NULL)
397                 return;
398
399         TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
400                 int status;
401                 if (child->dev_irq_filter != NULL)
402                         status = child->dev_irq_filter(child->dev_irq_arg);
403                 else
404                         status = FILTER_SCHEDULE_THREAD;
405
406                 if (status == FILTER_SCHEDULE_THREAD) {
407                         if (child->dev_irq_fn != NULL)
408                                 (child->dev_irq_fn) (child->dev_irq_arg);
409                 }
410         }
411 }
412
413 void
414 device_set_ivars(device_t dev, void *ivars)
415 {
416         dev->dev_aux = ivars;
417 }
418
419 void   *
420 device_get_ivars(device_t dev)
421 {
422         return (dev ? dev->dev_aux : NULL);
423 }
424
425 int
426 device_get_unit(device_t dev)
427 {
428         return (dev ? dev->dev_unit : 0);
429 }
430
431 int
432 bus_generic_detach(device_t dev)
433 {
434         device_t child;
435         int error;
436
437         if (!dev->dev_attached)
438                 return (EBUSY);
439
440         TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
441                 if ((error = device_detach(child)) != 0)
442                         return (error);
443         }
444         return (0);
445 }
446
447 const char *
448 device_get_nameunit(device_t dev)
449 {
450         if (dev && dev->dev_nameunit[0])
451                 return (dev->dev_nameunit);
452
453         return (unknown_string);
454 }
455
456 static uint8_t
457 devclass_create(devclass_t *dc_pp)
458 {
459         if (dc_pp == NULL) {
460                 return (1);
461         }
462         if (dc_pp[0] == NULL) {
463                 dc_pp[0] = malloc(sizeof(**(dc_pp)),
464                     M_DEVBUF, M_WAITOK | M_ZERO);
465
466                 if (dc_pp[0] == NULL) {
467                         return (1);
468                 }
469         }
470         return (0);
471 }
472
473 static const struct module_data *
474 devclass_find_create(const char *classname)
475 {
476         const struct module_data *mod;
477
478         TAILQ_FOREACH(mod, &module_head, entry) {
479                 if (devclass_equal(mod->mod_name, classname)) {
480                         if (devclass_create(mod->devclass_pp)) {
481                                 continue;
482                         }
483                         return (mod);
484                 }
485         }
486         return (NULL);
487 }
488
489 static uint8_t
490 devclass_add_device(const struct module_data *mod, device_t dev)
491 {
492         device_t *pp_dev;
493         device_t *end;
494         uint8_t unit;
495
496         pp_dev = mod->devclass_pp[0]->dev_list;
497         end = pp_dev + DEVCLASS_MAXUNIT;
498         unit = 0;
499
500         while (pp_dev != end) {
501                 if (*pp_dev == NULL) {
502                         *pp_dev = dev;
503                         dev->dev_unit = unit;
504                         dev->dev_module = mod;
505                         snprintf(dev->dev_nameunit,
506                             sizeof(dev->dev_nameunit),
507                             "%s%d", device_get_name(dev), unit);
508                         return (0);
509                 }
510                 pp_dev++;
511                 unit++;
512         }
513         DPRINTF("Could not add device to devclass.\n");
514         return (1);
515 }
516
517 static void
518 devclass_delete_device(const struct module_data *mod, device_t dev)
519 {
520         if (mod == NULL) {
521                 return;
522         }
523         mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
524         dev->dev_module = NULL;
525 }
526
527 static device_t
528 make_device(device_t parent, const char *name)
529 {
530         device_t dev = NULL;
531         const struct module_data *mod = NULL;
532
533         if (name) {
534
535                 mod = devclass_find_create(name);
536
537                 if (!mod) {
538
539                         DPRINTF("%s:%d:%s: can't find device "
540                             "class %s\n", __FILE__, __LINE__,
541                             __FUNCTION__, name);
542
543                         goto done;
544                 }
545         }
546         dev = malloc(sizeof(*dev),
547             M_DEVBUF, M_WAITOK | M_ZERO);
548
549         if (dev == NULL)
550                 goto done;
551
552         dev->dev_parent = parent;
553         TAILQ_INIT(&dev->dev_children);
554
555         if (name) {
556                 dev->dev_fixed_class = 1;
557                 if (devclass_add_device(mod, dev)) {
558                         goto error;
559                 }
560         }
561 done:
562         return (dev);
563
564 error:
565         if (dev) {
566                 free(dev, M_DEVBUF);
567         }
568         return (NULL);
569 }
570
571 device_t
572 device_add_child(device_t dev, const char *name, int unit)
573 {
574         device_t child;
575
576         if (unit != -1) {
577                 device_printf(dev, "Unit is not -1\n");
578         }
579         child = make_device(dev, name);
580         if (child == NULL) {
581                 device_printf(dev, "Could not add child '%s'\n", name);
582                 goto done;
583         }
584         if (dev == NULL) {
585                 /* no parent */
586                 goto done;
587         }
588         TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
589 done:
590         return (child);
591 }
592
593 int
594 device_delete_child(device_t dev, device_t child)
595 {
596         int error = 0;
597         device_t grandchild;
598
599         /* remove children first */
600
601         while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
602                 error = device_delete_child(child, grandchild);
603                 if (error) {
604                         device_printf(dev, "Error deleting child!\n");
605                         goto done;
606                 }
607         }
608
609         error = device_detach(child);
610
611         if (error)
612                 goto done;
613
614         devclass_delete_device(child->dev_module, child);
615
616         if (dev != NULL) {
617                 /* remove child from parent */
618                 TAILQ_REMOVE(&dev->dev_children, child, dev_link);
619         }
620         free(child, M_DEVBUF);
621
622 done:
623         return (error);
624 }
625
626 int
627 device_delete_children(device_t dev)
628 {
629         device_t child;
630         int error = 0;
631
632         while ((child = TAILQ_FIRST(&dev->dev_children))) {
633                 error = device_delete_child(dev, child);
634                 if (error) {
635                         device_printf(dev, "Error deleting child!\n");
636                         break;
637                 }
638         }
639         return (error);
640 }
641
642 void
643 device_quiet(device_t dev)
644 {
645         dev->dev_quiet = 1;
646 }
647
648 const char *
649 device_get_desc(device_t dev)
650 {
651         if (dev)
652                 return &(dev->dev_desc[0]);
653         return (unknown_string);
654 }
655
656 static int
657 default_method(void)
658 {
659         /* do nothing */
660         DPRINTF("Default method called\n");
661         return (0);
662 }
663
664 void   *
665 device_get_method(device_t dev, const char *what)
666 {
667         const struct device_method *mtod;
668
669         mtod = dev->dev_module->driver->methods;
670         while (mtod->func != NULL) {
671                 if (devclass_equal(mtod->desc, what)) {
672                         return (mtod->func);
673                 }
674                 mtod++;
675         }
676         return ((void *)&default_method);
677 }
678
679 const char *
680 device_get_name(device_t dev)
681 {
682         if (dev == NULL)
683                 return (unknown_string);
684
685         return (dev->dev_module->driver->name);
686 }
687
688 static int
689 device_allocate_softc(device_t dev)
690 {
691         const struct module_data *mod;
692
693         mod = dev->dev_module;
694
695         if ((dev->dev_softc_alloc == 0) &&
696             (mod->driver->size != 0)) {
697                 dev->dev_sc = malloc(mod->driver->size,
698                     M_DEVBUF, M_WAITOK | M_ZERO);
699
700                 if (dev->dev_sc == NULL)
701                         return (ENOMEM);
702
703                 dev->dev_softc_alloc = 1;
704         }
705         return (0);
706 }
707
708 int
709 device_probe_and_attach(device_t dev)
710 {
711         const struct module_data *mod;
712         const char *bus_name_parent;
713
714         bus_name_parent = device_get_name(device_get_parent(dev));
715
716         if (dev->dev_attached)
717                 return (0);             /* fail-safe */
718
719         if (dev->dev_fixed_class) {
720
721                 mod = dev->dev_module;
722
723                 if (DEVICE_PROBE(dev) <= 0) {
724
725                         if (device_allocate_softc(dev) == 0) {
726
727                                 if (DEVICE_ATTACH(dev) == 0) {
728                                         /* success */
729                                         dev->dev_attached = 1;
730                                         return (0);
731                                 }
732                         }
733                 }
734                 device_detach(dev);
735
736                 goto error;
737         }
738         /*
739          * Else find a module for our device, if any
740          */
741
742         TAILQ_FOREACH(mod, &module_head, entry) {
743                 if (devclass_equal(mod->bus_name, bus_name_parent)) {
744                         if (devclass_create(mod->devclass_pp)) {
745                                 continue;
746                         }
747                         if (devclass_add_device(mod, dev)) {
748                                 continue;
749                         }
750                         if (DEVICE_PROBE(dev) <= 0) {
751
752                                 if (device_allocate_softc(dev) == 0) {
753
754                                         if (DEVICE_ATTACH(dev) == 0) {
755                                                 /* success */
756                                                 dev->dev_attached = 1;
757                                                 return (0);
758                                         }
759                                 }
760                         }
761                         /* else try next driver */
762
763                         device_detach(dev);
764                 }
765         }
766
767 error:
768         return (ENODEV);
769 }
770
771 int
772 device_detach(device_t dev)
773 {
774         const struct module_data *mod = dev->dev_module;
775         int error;
776
777         if (dev->dev_attached) {
778
779                 error = DEVICE_DETACH(dev);
780                 if (error) {
781                         return error;
782                 }
783                 dev->dev_attached = 0;
784         }
785         device_set_softc(dev, NULL);
786
787         if (dev->dev_fixed_class == 0)
788                 devclass_delete_device(mod, dev);
789
790         return (0);
791 }
792
793 void
794 device_set_softc(device_t dev, void *softc)
795 {
796         if (dev->dev_softc_alloc) {
797                 free(dev->dev_sc, M_DEVBUF);
798                 dev->dev_sc = NULL;
799         }
800         dev->dev_sc = softc;
801         dev->dev_softc_alloc = 0;
802 }
803
804 void   *
805 device_get_softc(device_t dev)
806 {
807         if (dev == NULL)
808                 return (NULL);
809
810         return (dev->dev_sc);
811 }
812
813 int
814 device_is_attached(device_t dev)
815 {
816         return (dev->dev_attached);
817 }
818
819 void
820 device_set_desc(device_t dev, const char *desc)
821 {
822         snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
823 }
824
825 void
826 device_set_desc_copy(device_t dev, const char *desc)
827 {
828         device_set_desc(dev, desc);
829 }
830
831 void   *
832 devclass_get_softc(devclass_t dc, int unit)
833 {
834         return (device_get_softc(devclass_get_device(dc, unit)));
835 }
836
837 int
838 devclass_get_maxunit(devclass_t dc)
839 {
840         int max_unit = 0;
841
842         if (dc) {
843                 max_unit = DEVCLASS_MAXUNIT;
844                 while (max_unit--) {
845                         if (dc->dev_list[max_unit]) {
846                                 break;
847                         }
848                 }
849                 max_unit++;
850         }
851         return (max_unit);
852 }
853
854 device_t
855 devclass_get_device(devclass_t dc, int unit)
856 {
857         return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
858             NULL : dc->dev_list[unit]);
859 }
860
861 devclass_t
862 devclass_find(const char *classname)
863 {
864         const struct module_data *mod;
865
866         TAILQ_FOREACH(mod, &module_head, entry) {
867                 if (devclass_equal(mod->mod_name, classname))
868                         return (mod->devclass_pp[0]);
869         }
870         return (NULL);
871 }
872
873 void
874 module_register(void *data)
875 {
876         struct module_data *mdata = data;
877
878         TAILQ_INSERT_TAIL(&module_head, mdata, entry);
879 }
880
881 /*------------------------------------------------------------------------*
882  * System startup
883  *------------------------------------------------------------------------*/
884
885 static void
886 sysinit_run(const void **ppdata)
887 {
888         const struct sysinit *psys;
889
890         while ((psys = *ppdata) != NULL) {
891                 (psys->func) (psys->data);
892                 ppdata++;
893         }
894 }
895
896 /*------------------------------------------------------------------------*
897  * USB process API
898  *------------------------------------------------------------------------*/
899
900 static int usb_do_process(struct usb_process *);
901 static int usb_proc_level = -1;
902 static struct mtx usb_proc_mtx;
903
904 void
905 usb_idle(void)
906 {
907         int old_level = usb_proc_level;
908         int old_giant = Giant.owned;
909         int worked;
910
911         device_run_interrupts(usb_pci_root);
912
913         do {
914                 worked = 0;
915                 Giant.owned = 0;
916
917                 while (++usb_proc_level < USB_PROC_MAX)
918                         worked |= usb_do_process(usb_process + usb_proc_level);
919
920                 usb_proc_level = old_level;
921                 Giant.owned = old_giant;
922
923         } while (worked);
924 }
925
926 void
927 usb_init(void)
928 {
929         sysinit_run(sysinit_data);
930 }
931
932 void
933 usb_uninit(void)
934 {
935         sysinit_run(sysuninit_data);
936 }
937
938 static void
939 usb_process_init_sub(struct usb_process *up)
940 {
941         TAILQ_INIT(&up->up_qhead);
942
943         cv_init(&up->up_cv, "-");
944         cv_init(&up->up_drain, "usbdrain");
945
946         up->up_mtx = &usb_proc_mtx;
947 }
948
949 static void
950 usb_process_init(void *arg)
951 {
952         uint8_t x;
953
954         mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
955
956         for (x = 0; x != USB_PROC_MAX; x++)
957                 usb_process_init_sub(&usb_process[x]);
958
959 }
960 SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
961
962 static int
963 usb_do_process(struct usb_process *up)
964 {
965         struct usb_proc_msg *pm;
966         int worked = 0;
967
968         mtx_lock(&usb_proc_mtx);
969
970 repeat:
971         pm = TAILQ_FIRST(&up->up_qhead);
972
973         if (pm != NULL) {
974
975                 worked = 1;
976
977                 (pm->pm_callback) (pm);
978
979                 if (pm == TAILQ_FIRST(&up->up_qhead)) {
980                         /* nothing changed */
981                         TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
982                         pm->pm_qentry.tqe_prev = NULL;
983                 }
984                 goto repeat;
985         }
986         mtx_unlock(&usb_proc_mtx);
987
988         return (worked);
989 }
990
991 void   *
992 usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
993 {
994         struct usb_proc_msg *pm0 = _pm0;
995         struct usb_proc_msg *pm1 = _pm1;
996         struct usb_proc_msg *pm2;
997         usb_size_t d;
998         uint8_t t;
999
1000         t = 0;
1001
1002         if (pm0->pm_qentry.tqe_prev) {
1003                 t |= 1;
1004         }
1005         if (pm1->pm_qentry.tqe_prev) {
1006                 t |= 2;
1007         }
1008         if (t == 0) {
1009                 /*
1010                  * No entries are queued. Queue "pm0" and use the existing
1011                  * message number.
1012                  */
1013                 pm2 = pm0;
1014         } else if (t == 1) {
1015                 /* Check if we need to increment the message number. */
1016                 if (pm0->pm_num == up->up_msg_num) {
1017                         up->up_msg_num++;
1018                 }
1019                 pm2 = pm1;
1020         } else if (t == 2) {
1021                 /* Check if we need to increment the message number. */
1022                 if (pm1->pm_num == up->up_msg_num) {
1023                         up->up_msg_num++;
1024                 }
1025                 pm2 = pm0;
1026         } else if (t == 3) {
1027                 /*
1028                  * Both entries are queued. Re-queue the entry closest to
1029                  * the end.
1030                  */
1031                 d = (pm1->pm_num - pm0->pm_num);
1032
1033                 /* Check sign after subtraction */
1034                 if (d & 0x80000000) {
1035                         pm2 = pm0;
1036                 } else {
1037                         pm2 = pm1;
1038                 }
1039
1040                 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
1041         } else {
1042                 pm2 = NULL;             /* panic - should not happen */
1043         }
1044
1045         /* Put message last on queue */
1046
1047         pm2->pm_num = up->up_msg_num;
1048         TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
1049
1050         return (pm2);
1051 }
1052
1053 /*------------------------------------------------------------------------*
1054  *      usb_proc_is_gone
1055  *
1056  * Return values:
1057  *    0: USB process is running
1058  * Else: USB process is tearing down
1059  *------------------------------------------------------------------------*/
1060 uint8_t
1061 usb_proc_is_gone(struct usb_process *up)
1062 {
1063         return (0);
1064 }
1065
1066 /*------------------------------------------------------------------------*
1067  *      usb_proc_mwait
1068  *
1069  * This function will return when the USB process message pointed to
1070  * by "pm" is no longer on a queue. This function must be called
1071  * having "usb_proc_mtx" locked.
1072  *------------------------------------------------------------------------*/
1073 void
1074 usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
1075 {
1076         struct usb_proc_msg *pm0 = _pm0;
1077         struct usb_proc_msg *pm1 = _pm1;
1078
1079         /* Just remove the messages from the queue. */
1080         if (pm0->pm_qentry.tqe_prev) {
1081                 TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
1082                 pm0->pm_qentry.tqe_prev = NULL;
1083         }
1084         if (pm1->pm_qentry.tqe_prev) {
1085                 TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
1086                 pm1->pm_qentry.tqe_prev = NULL;
1087         }
1088 }
1089
1090 /*------------------------------------------------------------------------*
1091  * SYSTEM attach
1092  *------------------------------------------------------------------------*/
1093
1094 static device_method_t pci_methods[] = {
1095         DEVMETHOD_END
1096 };
1097
1098 static driver_t pci_driver = {
1099         .name = "pci",
1100         .methods = pci_methods,
1101 };
1102
1103 static devclass_t pci_devclass;
1104
1105 DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
1106
1107 static const char *usb_pci_devices[] = {
1108 #ifdef USB_PROBE_LIST
1109         USB_PROBE_LIST
1110 #endif
1111 };
1112
1113 #define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *))
1114
1115 static device_t usb_pci_dev[USB_PCI_USB_MAX];
1116
1117 static void
1118 usb_pci_mod_load(void *arg)
1119 {
1120         uint32_t x;
1121
1122         usb_pci_root = device_add_child(NULL, "pci", -1);
1123         if (usb_pci_root == NULL)
1124                 return;
1125
1126         for (x = 0; x != USB_PCI_USB_MAX; x++) {
1127                 usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1);
1128                 if (usb_pci_dev[x] == NULL)
1129                         continue;
1130                 if (device_probe_and_attach(usb_pci_dev[x])) {
1131                         device_printf(usb_pci_dev[x],
1132                             "WARNING: Probe and attach failed!\n");
1133                 }
1134         }
1135 }
1136 SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
1137
1138 static void
1139 usb_pci_mod_unload(void *arg)
1140 {
1141         uint32_t x;
1142
1143         for (x = 0; x != USB_PCI_USB_MAX; x++) {
1144                 if (usb_pci_dev[x]) {
1145                         device_detach(usb_pci_dev[x]);
1146                         device_delete_child(usb_pci_root, usb_pci_dev[x]);
1147                 }
1148         }
1149         if (usb_pci_root)
1150                 device_delete_child(NULL, usb_pci_root);
1151 }
1152 SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
1153
1154 /*------------------------------------------------------------------------*
1155  * MALLOC API
1156  *------------------------------------------------------------------------*/
1157
1158 #define USB_POOL_ALIGN 8
1159
1160 static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
1161 static uint32_t usb_pool_rem = USB_POOL_SIZE;
1162 static uint32_t usb_pool_entries;
1163
1164 struct malloc_hdr {
1165         TAILQ_ENTRY(malloc_hdr) entry;
1166         uint32_t size;
1167 } __aligned(USB_POOL_ALIGN);
1168
1169 static TAILQ_HEAD(, malloc_hdr) malloc_head =
1170         TAILQ_HEAD_INITIALIZER(malloc_head);
1171
1172 void   *
1173 usb_malloc(unsigned long size)
1174 {
1175         struct malloc_hdr *hdr;
1176
1177         size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
1178         size += sizeof(struct malloc_hdr);
1179
1180         TAILQ_FOREACH(hdr, &malloc_head, entry) {
1181                 if (hdr->size == size)
1182                         break;
1183         }
1184
1185         if (hdr) {
1186                 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1187                     (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1188
1189                 TAILQ_REMOVE(&malloc_head, hdr, entry);
1190                 memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1191                 return (hdr + 1);
1192         }
1193         if (usb_pool_rem >= size) {
1194                 hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
1195                 hdr->size = size;
1196
1197                 usb_pool_rem -= size;
1198                 usb_pool_entries++;
1199
1200                 printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1201                     (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1202
1203                 memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1204                 return (hdr + 1);
1205         }
1206         return (NULL);
1207 }
1208
1209 void
1210 usb_free(void *arg)
1211 {
1212         struct malloc_hdr *hdr;
1213
1214         if (arg == NULL)
1215                 return;
1216
1217         hdr = arg;
1218         hdr--;
1219
1220         TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
1221 }
1222
1223 char   *
1224 usb_strdup(const char *str)
1225 {
1226         char *tmp;
1227         int len;
1228
1229         len = 1 + strlen(str);
1230
1231         tmp = usb_malloc(len);
1232         if (tmp == NULL)
1233                 return (NULL);
1234
1235         memcpy(tmp, str, len);
1236         return (tmp);
1237 }