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