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