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