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