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