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