1133855Sssouhlal/* $FreeBSD: releng/10.3/sys/boot/usb/bsd_kernel.c 269921 2014-08-13 08:18:49Z hselasky $ */
2133855Sssouhlal/*-
3133855Sssouhlal * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
4133855Sssouhlal *
5133855Sssouhlal * Redistribution and use in source and binary forms, with or without
6133855Sssouhlal * modification, are permitted provided that the following conditions
7133855Sssouhlal * are met:
8133855Sssouhlal * 1. Redistributions of source code must retain the above copyright
9133855Sssouhlal *    notice, this list of conditions and the following disclaimer.
10133855Sssouhlal * 2. Redistributions in binary form must reproduce the above copyright
11133855Sssouhlal *    notice, this list of conditions and the following disclaimer in the
12133855Sssouhlal *    documentation and/or other materials provided with the distribution.
13133855Sssouhlal *
14133855Sssouhlal * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15133855Sssouhlal * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16133855Sssouhlal * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17133855Sssouhlal * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18133855Sssouhlal * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19133855Sssouhlal * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20133855Sssouhlal * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21133855Sssouhlal * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22133855Sssouhlal * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23133855Sssouhlal * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24133855Sssouhlal * SUCH DAMAGE.
25133855Sssouhlal */
26133855Sssouhlal
27133855Sssouhlal#include <bsd_global.h>
28133855Sssouhlal
29133855Sssouhlalstruct usb_process usb_process[USB_PROC_MAX];
30133855Sssouhlal
31133855Sssouhlalstatic device_t usb_pci_root;
32133855Sssouhlal
33133855Sssouhlal/*------------------------------------------------------------------------*
34133855Sssouhlal * Implementation of mutex API
35133855Sssouhlal *------------------------------------------------------------------------*/
36133855Sssouhlal
37133855Sssouhlalstruct mtx Giant;
38133855Sssouhlal
39133855Sssouhlalstatic void
40133855Sssouhlalmtx_system_init(void *arg)
41133855Sssouhlal{
42133855Sssouhlal	mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
43133855Sssouhlal}
44133855SssouhlalSYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL);
45133855Sssouhlal
46133855Sssouhlalvoid
47133855Sssouhlalmtx_init(struct mtx *mtx, const char *name, const char *type, int opt)
48133855Sssouhlal{
49133855Sssouhlal	mtx->owned = 0;
50133855Sssouhlal	mtx->parent = mtx;
51213383Snwhitehorn}
52133855Sssouhlal
53133855Sssouhlalvoid
54133855Sssouhlalmtx_lock(struct mtx *mtx)
55133855Sssouhlal{
56133855Sssouhlal	mtx = mtx->parent;
57133855Sssouhlal	mtx->owned++;
58133855Sssouhlal}
59133855Sssouhlal
60133855Sssouhlalvoid
61133855Sssouhlalmtx_unlock(struct mtx *mtx)
62133855Sssouhlal{
63133855Sssouhlal	mtx = mtx->parent;
64133855Sssouhlal	mtx->owned--;
65133855Sssouhlal}
66133855Sssouhlal
67133855Sssouhlalint
68190681Snwhitehornmtx_owned(struct mtx *mtx)
69133855Sssouhlal{
70133855Sssouhlal	mtx = mtx->parent;
71133855Sssouhlal	return (mtx->owned != 0);
72213383Snwhitehorn}
73213383Snwhitehorn
74133855Sssouhlalvoid
75213383Snwhitehornmtx_destroy(struct mtx *mtx)
76213383Snwhitehorn{
77213383Snwhitehorn	/* NOP */
78213383Snwhitehorn}
79213383Snwhitehorn
80213383Snwhitehorn/*------------------------------------------------------------------------*
81213383Snwhitehorn * Implementation of shared/exclusive mutex API
82213383Snwhitehorn *------------------------------------------------------------------------*/
83213383Snwhitehorn
84213383Snwhitehornvoid
85217515Sjkimsx_init_flags(struct sx *sx, const char *name, int flags)
86213383Snwhitehorn{
87213383Snwhitehorn	sx->owned = 0;
88133855Sssouhlal}
89133855Sssouhlal
90133855Sssouhlalvoid
91133855Sssouhlalsx_destroy(struct sx *sx)
92133855Sssouhlal{
93133855Sssouhlal	/* NOP */
94133855Sssouhlal}
95133855Sssouhlal
96190681Snwhitehornvoid
97190681Snwhitehornsx_xlock(struct sx *sx)
98133855Sssouhlal{
99133855Sssouhlal	sx->owned++;
100133855Sssouhlal}
101133855Sssouhlal
102133855Sssouhlalvoid
103133855Sssouhlalsx_xunlock(struct sx *sx)
104133855Sssouhlal{
105133855Sssouhlal	sx->owned--;
106133855Sssouhlal}
107133855Sssouhlal
108133855Sssouhlalint
109133855Sssouhlalsx_xlocked(struct sx *sx)
110133855Sssouhlal{
111133855Sssouhlal	return (sx->owned != 0);
112133855Sssouhlal}
113133855Sssouhlal
114183397Sed/*------------------------------------------------------------------------*
115133855Sssouhlal * Implementaiton of condition variable API
116133855Sssouhlal *------------------------------------------------------------------------*/
117133855Sssouhlal
118133855Sssouhlalvoid
119133855Sssouhlalcv_init(struct cv *cv, const char *desc)
120133855Sssouhlal{
121133855Sssouhlal	cv->sleeping = 0;
122133855Sssouhlal}
123190681Snwhitehorn
124133855Sssouhlalvoid
125133855Sssouhlalcv_destroy(struct cv *cv)
126133855Sssouhlal{
127190681Snwhitehorn	/* NOP */
128190681Snwhitehorn}
129190681Snwhitehorn
130190681Snwhitehornvoid
131190681Snwhitehorncv_wait(struct cv *cv, struct mtx *mtx)
132190681Snwhitehorn{
133190681Snwhitehorn	cv_timedwait(cv, mtx, -1);
134190681Snwhitehorn}
135133855Sssouhlal
136183397Sedint
137133855Sssouhlalcv_timedwait(struct cv *cv, struct mtx *mtx, int timo)
138133855Sssouhlal{
139204312Snwhitehorn	int start = ticks;
140133855Sssouhlal	int delta;
141133855Sssouhlal
142133855Sssouhlal	if (cv->sleeping)
143133855Sssouhlal		return (EWOULDBLOCK);	/* not allowed */
144133855Sssouhlal
145133855Sssouhlal	cv->sleeping = 1;
146133855Sssouhlal
147133855Sssouhlal	while (cv->sleeping) {
148133855Sssouhlal		if (timo >= 0) {
149133855Sssouhlal			delta = ticks - start;
150133855Sssouhlal			if (delta >= timo || delta < 0)
151133855Sssouhlal				break;
152204312Snwhitehorn		}
153133855Sssouhlal		mtx_unlock(mtx);
154133855Sssouhlal
155133855Sssouhlal		usb_idle();
156133855Sssouhlal
157133855Sssouhlal		mtx_lock(mtx);
158133855Sssouhlal	}
159133855Sssouhlal
160133855Sssouhlal	if (cv->sleeping) {
161133855Sssouhlal		cv->sleeping = 0;
162133855Sssouhlal		return (EWOULDBLOCK);	/* not allowed */
163133855Sssouhlal	}
164133855Sssouhlal	return (0);
165133855Sssouhlal}
166133855Sssouhlal
167133855Sssouhlalvoid
168133855Sssouhlalcv_signal(struct cv *cv)
169133855Sssouhlal{
170133855Sssouhlal	cv->sleeping = 0;
171133855Sssouhlal}
172133855Sssouhlal
173133855Sssouhlalvoid
174133855Sssouhlalcv_broadcast(struct cv *cv)
175133855Sssouhlal{
176133855Sssouhlal	cv->sleeping = 0;
177201223Srnoland}
178201223Srnoland
179133855Sssouhlal/*------------------------------------------------------------------------*
180213383Snwhitehorn * Implementation of callout API
181213383Snwhitehorn *------------------------------------------------------------------------*/
182271113Snwhitehorn
183271113Snwhitehornstatic void callout_proc_msg(struct usb_proc_msg *);
184271113Snwhitehorn
185271113Snwhitehornvolatile int ticks = 0;
186271113Snwhitehorn
187133855Sssouhlalstatic LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout);
188133855Sssouhlal
189213383Snwhitehornstatic struct mtx mtx_callout;
190213383Snwhitehornstatic struct usb_proc_msg callout_msg[2];
191213383Snwhitehorn
192213383Snwhitehornstatic void
193213383Snwhitehorncallout_system_init(void *arg)
194213383Snwhitehorn{
195213383Snwhitehorn	mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE);
196213383Snwhitehorn
197213383Snwhitehorn	callout_msg[0].pm_callback = &callout_proc_msg;
198213383Snwhitehorn	callout_msg[1].pm_callback = &callout_proc_msg;
199213383Snwhitehorn}
200213383SnwhitehornSYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL);
201213383Snwhitehorn
202213383Snwhitehornstatic void
203213383Snwhitehorncallout_callback(struct callout *c)
204213383Snwhitehorn{
205213383Snwhitehorn	mtx_lock(c->mtx);
206213383Snwhitehorn
207213383Snwhitehorn	mtx_lock(&mtx_callout);
208213383Snwhitehorn	if (c->entry.le_prev != NULL) {
209213383Snwhitehorn		LIST_REMOVE(c, entry);
210213383Snwhitehorn		c->entry.le_prev = NULL;
211213383Snwhitehorn	}
212213383Snwhitehorn	mtx_unlock(&mtx_callout);
213213383Snwhitehorn
214213383Snwhitehorn	if (c->func)
215213383Snwhitehorn		(c->func) (c->arg);
216133855Sssouhlal
217133855Sssouhlal	if (!(c->flags & CALLOUT_RETURNUNLOCKED))
218133855Sssouhlal		mtx_unlock(c->mtx);
219213383Snwhitehorn}
220213383Snwhitehorn
221213383Snwhitehornvoid
222213383Snwhitehorncallout_process(int timeout)
223213383Snwhitehorn{
224213383Snwhitehorn	ticks += timeout;
225271113Snwhitehorn	usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]);
226213383Snwhitehorn}
227213383Snwhitehorn
228213383Snwhitehornstatic void
229213383Snwhitehorncallout_proc_msg(struct usb_proc_msg *pmsg)
230213383Snwhitehorn{
231213383Snwhitehorn	struct callout *c;
232213383Snwhitehorn	int delta;
233213383Snwhitehorn
234213383Snwhitehornrepeat:
235213383Snwhitehorn	mtx_lock(&mtx_callout);
236213383Snwhitehorn
237213383Snwhitehorn	LIST_FOREACH(c, &head_callout, entry) {
238213383Snwhitehorn
239213383Snwhitehorn		delta = c->timeout - ticks;
240213383Snwhitehorn		if (delta < 0) {
241213383Snwhitehorn			mtx_unlock(&mtx_callout);
242213383Snwhitehorn
243213383Snwhitehorn			callout_callback(c);
244213383Snwhitehorn
245213383Snwhitehorn			goto repeat;
246213383Snwhitehorn		}
247213383Snwhitehorn	}
248213383Snwhitehorn	mtx_unlock(&mtx_callout);
249213383Snwhitehorn}
250213383Snwhitehorn
251213383Snwhitehornvoid
252213383Snwhitehorncallout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
253213383Snwhitehorn{
254213383Snwhitehorn	memset(c, 0, sizeof(*c));
255213383Snwhitehorn
256213383Snwhitehorn	if (mtx == NULL)
257213383Snwhitehorn		mtx = &Giant;
258213383Snwhitehorn
259213383Snwhitehorn	c->mtx = mtx;
260213383Snwhitehorn	c->flags = (flags & CALLOUT_RETURNUNLOCKED);
261213383Snwhitehorn}
262213383Snwhitehorn
263213383Snwhitehornvoid
264213383Snwhitehorncallout_reset(struct callout *c, int to_ticks,
265213383Snwhitehorn    void (*func) (void *), void *arg)
266213383Snwhitehorn{
267213383Snwhitehorn	callout_stop(c);
268213383Snwhitehorn
269213383Snwhitehorn	c->func = func;
270213383Snwhitehorn	c->arg = arg;
271213383Snwhitehorn	c->timeout = ticks + to_ticks;
272213383Snwhitehorn
273213383Snwhitehorn	mtx_lock(&mtx_callout);
274213383Snwhitehorn	LIST_INSERT_HEAD(&head_callout, c, entry);
275213383Snwhitehorn	mtx_unlock(&mtx_callout);
276213383Snwhitehorn}
277213383Snwhitehorn
278213383Snwhitehornvoid
279213383Snwhitehorncallout_stop(struct callout *c)
280213383Snwhitehorn{
281213383Snwhitehorn	mtx_lock(&mtx_callout);
282213383Snwhitehorn
283213383Snwhitehorn	if (c->entry.le_prev != NULL) {
284213383Snwhitehorn		LIST_REMOVE(c, entry);
285213383Snwhitehorn		c->entry.le_prev = NULL;
286213383Snwhitehorn	}
287213383Snwhitehorn	mtx_unlock(&mtx_callout);
288213383Snwhitehorn
289213383Snwhitehorn	c->func = NULL;
290213383Snwhitehorn	c->arg = NULL;
291213383Snwhitehorn}
292213383Snwhitehorn
293213383Snwhitehornvoid
294213383Snwhitehorncallout_drain(struct callout *c)
295213383Snwhitehorn{
296213383Snwhitehorn	if (c->mtx == NULL)
297213383Snwhitehorn		return;			/* not initialised */
298213383Snwhitehorn
299213383Snwhitehorn	mtx_lock(c->mtx);
300213383Snwhitehorn	callout_stop(c);
301213383Snwhitehorn	mtx_unlock(c->mtx);
302213383Snwhitehorn}
303213383Snwhitehorn
304213383Snwhitehornint
305213383Snwhitehorncallout_pending(struct callout *c)
306213383Snwhitehorn{
307213383Snwhitehorn	int retval;
308213383Snwhitehorn
309213383Snwhitehorn	mtx_lock(&mtx_callout);
310213383Snwhitehorn	retval = (c->entry.le_prev != NULL);
311213383Snwhitehorn	mtx_unlock(&mtx_callout);
312213383Snwhitehorn
313213383Snwhitehorn	return (retval);
314213383Snwhitehorn}
315213383Snwhitehorn
316213383Snwhitehorn/*------------------------------------------------------------------------*
317213383Snwhitehorn * Implementation of device API
318213383Snwhitehorn *------------------------------------------------------------------------*/
319213383Snwhitehorn
320271113Snwhitehornstatic 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, driver_filter_t *filter,
384    driver_intr_t *fn, void *arg)
385{
386	dev->dev_irq_filter = filter;
387	dev->dev_irq_fn = fn;
388	dev->dev_irq_arg = arg;
389}
390
391void
392device_run_interrupts(device_t parent)
393{
394	device_t child;
395
396	if (parent == NULL)
397		return;
398
399	TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
400		int status;
401		if (child->dev_irq_filter != NULL)
402			status = child->dev_irq_filter(child->dev_irq_arg);
403		else
404			status = FILTER_SCHEDULE_THREAD;
405
406		if (status == FILTER_SCHEDULE_THREAD) {
407			if (child->dev_irq_fn != NULL)
408				(child->dev_irq_fn) (child->dev_irq_arg);
409		}
410	}
411}
412
413void
414device_set_ivars(device_t dev, void *ivars)
415{
416	dev->dev_aux = ivars;
417}
418
419void   *
420device_get_ivars(device_t dev)
421{
422	return (dev ? dev->dev_aux : NULL);
423}
424
425int
426device_get_unit(device_t dev)
427{
428	return (dev ? dev->dev_unit : 0);
429}
430
431int
432bus_generic_detach(device_t dev)
433{
434	device_t child;
435	int error;
436
437	if (!dev->dev_attached)
438		return (EBUSY);
439
440	TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
441		if ((error = device_detach(child)) != 0)
442			return (error);
443	}
444	return (0);
445}
446
447const char *
448device_get_nameunit(device_t dev)
449{
450	if (dev && dev->dev_nameunit[0])
451		return (dev->dev_nameunit);
452
453	return (unknown_string);
454}
455
456static uint8_t
457devclass_create(devclass_t *dc_pp)
458{
459	if (dc_pp == NULL) {
460		return (1);
461	}
462	if (dc_pp[0] == NULL) {
463		dc_pp[0] = malloc(sizeof(**(dc_pp)),
464		    M_DEVBUF, M_WAITOK | M_ZERO);
465
466		if (dc_pp[0] == NULL) {
467			return (1);
468		}
469	}
470	return (0);
471}
472
473static const struct module_data *
474devclass_find_create(const char *classname)
475{
476	const struct module_data *mod;
477
478	TAILQ_FOREACH(mod, &module_head, entry) {
479		if (devclass_equal(mod->mod_name, classname)) {
480			if (devclass_create(mod->devclass_pp)) {
481				continue;
482			}
483			return (mod);
484		}
485	}
486	return (NULL);
487}
488
489static uint8_t
490devclass_add_device(const struct module_data *mod, device_t dev)
491{
492	device_t *pp_dev;
493	device_t *end;
494	uint8_t unit;
495
496	pp_dev = mod->devclass_pp[0]->dev_list;
497	end = pp_dev + DEVCLASS_MAXUNIT;
498	unit = 0;
499
500	while (pp_dev != end) {
501		if (*pp_dev == NULL) {
502			*pp_dev = dev;
503			dev->dev_unit = unit;
504			dev->dev_module = mod;
505			snprintf(dev->dev_nameunit,
506			    sizeof(dev->dev_nameunit),
507			    "%s%d", device_get_name(dev), unit);
508			return (0);
509		}
510		pp_dev++;
511		unit++;
512	}
513	DPRINTF("Could not add device to devclass.\n");
514	return (1);
515}
516
517static void
518devclass_delete_device(const struct module_data *mod, device_t dev)
519{
520	if (mod == NULL) {
521		return;
522	}
523	mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
524	dev->dev_module = NULL;
525}
526
527static device_t
528make_device(device_t parent, const char *name)
529{
530	device_t dev = NULL;
531	const struct module_data *mod = NULL;
532
533	if (name) {
534
535		mod = devclass_find_create(name);
536
537		if (!mod) {
538
539			DPRINTF("%s:%d:%s: can't find device "
540			    "class %s\n", __FILE__, __LINE__,
541			    __FUNCTION__, name);
542
543			goto done;
544		}
545	}
546	dev = malloc(sizeof(*dev),
547	    M_DEVBUF, M_WAITOK | M_ZERO);
548
549	if (dev == NULL)
550		goto done;
551
552	dev->dev_parent = parent;
553	TAILQ_INIT(&dev->dev_children);
554
555	if (name) {
556		dev->dev_fixed_class = 1;
557		if (devclass_add_device(mod, dev)) {
558			goto error;
559		}
560	}
561done:
562	return (dev);
563
564error:
565	if (dev) {
566		free(dev, M_DEVBUF);
567	}
568	return (NULL);
569}
570
571device_t
572device_add_child(device_t dev, const char *name, int unit)
573{
574	device_t child;
575
576	if (unit != -1) {
577		device_printf(dev, "Unit is not -1\n");
578	}
579	child = make_device(dev, name);
580	if (child == NULL) {
581		device_printf(dev, "Could not add child '%s'\n", name);
582		goto done;
583	}
584	if (dev == NULL) {
585		/* no parent */
586		goto done;
587	}
588	TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
589done:
590	return (child);
591}
592
593int
594device_delete_child(device_t dev, device_t child)
595{
596	int error = 0;
597	device_t grandchild;
598
599	/* remove children first */
600
601	while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
602		error = device_delete_child(child, grandchild);
603		if (error) {
604			device_printf(dev, "Error deleting child!\n");
605			goto done;
606		}
607	}
608
609	error = device_detach(child);
610
611	if (error)
612		goto done;
613
614	devclass_delete_device(child->dev_module, child);
615
616	if (dev != NULL) {
617		/* remove child from parent */
618		TAILQ_REMOVE(&dev->dev_children, child, dev_link);
619	}
620	free(child, M_DEVBUF);
621
622done:
623	return (error);
624}
625
626int
627device_delete_children(device_t dev)
628{
629	device_t child;
630	int error = 0;
631
632	while ((child = TAILQ_FIRST(&dev->dev_children))) {
633		error = device_delete_child(dev, child);
634		if (error) {
635			device_printf(dev, "Error deleting child!\n");
636			break;
637		}
638	}
639	return (error);
640}
641
642void
643device_quiet(device_t dev)
644{
645	dev->dev_quiet = 1;
646}
647
648const char *
649device_get_desc(device_t dev)
650{
651	if (dev)
652		return &(dev->dev_desc[0]);
653	return (unknown_string);
654}
655
656static int
657default_method(void)
658{
659	/* do nothing */
660	DPRINTF("Default method called\n");
661	return (0);
662}
663
664void   *
665device_get_method(device_t dev, const char *what)
666{
667	const struct device_method *mtod;
668
669	mtod = dev->dev_module->driver->methods;
670	while (mtod->func != NULL) {
671		if (devclass_equal(mtod->desc, what)) {
672			return (mtod->func);
673		}
674		mtod++;
675	}
676	return ((void *)&default_method);
677}
678
679const char *
680device_get_name(device_t dev)
681{
682	if (dev == NULL)
683		return (unknown_string);
684
685	return (dev->dev_module->driver->name);
686}
687
688static int
689device_allocate_softc(device_t dev)
690{
691	const struct module_data *mod;
692
693	mod = dev->dev_module;
694
695	if ((dev->dev_softc_alloc == 0) &&
696	    (mod->driver->size != 0)) {
697		dev->dev_sc = malloc(mod->driver->size,
698		    M_DEVBUF, M_WAITOK | M_ZERO);
699
700		if (dev->dev_sc == NULL)
701			return (ENOMEM);
702
703		dev->dev_softc_alloc = 1;
704	}
705	return (0);
706}
707
708int
709device_probe_and_attach(device_t dev)
710{
711	const struct module_data *mod;
712	const char *bus_name_parent;
713
714	bus_name_parent = device_get_name(device_get_parent(dev));
715
716	if (dev->dev_attached)
717		return (0);		/* fail-safe */
718
719	if (dev->dev_fixed_class) {
720
721		mod = dev->dev_module;
722
723		if (DEVICE_PROBE(dev) <= 0) {
724
725			if (device_allocate_softc(dev) == 0) {
726
727				if (DEVICE_ATTACH(dev) == 0) {
728					/* success */
729					dev->dev_attached = 1;
730					return (0);
731				}
732			}
733		}
734		device_detach(dev);
735
736		goto error;
737	}
738	/*
739         * Else find a module for our device, if any
740         */
741
742	TAILQ_FOREACH(mod, &module_head, entry) {
743		if (devclass_equal(mod->bus_name, bus_name_parent)) {
744			if (devclass_create(mod->devclass_pp)) {
745				continue;
746			}
747			if (devclass_add_device(mod, dev)) {
748				continue;
749			}
750			if (DEVICE_PROBE(dev) <= 0) {
751
752				if (device_allocate_softc(dev) == 0) {
753
754					if (DEVICE_ATTACH(dev) == 0) {
755						/* success */
756						dev->dev_attached = 1;
757						return (0);
758					}
759				}
760			}
761			/* else try next driver */
762
763			device_detach(dev);
764		}
765	}
766
767error:
768	return (ENODEV);
769}
770
771int
772device_detach(device_t dev)
773{
774	const struct module_data *mod = dev->dev_module;
775	int error;
776
777	if (dev->dev_attached) {
778
779		error = DEVICE_DETACH(dev);
780		if (error) {
781			return error;
782		}
783		dev->dev_attached = 0;
784	}
785	device_set_softc(dev, NULL);
786
787	if (dev->dev_fixed_class == 0)
788		devclass_delete_device(mod, dev);
789
790	return (0);
791}
792
793void
794device_set_softc(device_t dev, void *softc)
795{
796	if (dev->dev_softc_alloc) {
797		free(dev->dev_sc, M_DEVBUF);
798		dev->dev_sc = NULL;
799	}
800	dev->dev_sc = softc;
801	dev->dev_softc_alloc = 0;
802}
803
804void   *
805device_get_softc(device_t dev)
806{
807	if (dev == NULL)
808		return (NULL);
809
810	return (dev->dev_sc);
811}
812
813int
814device_is_attached(device_t dev)
815{
816	return (dev->dev_attached);
817}
818
819void
820device_set_desc(device_t dev, const char *desc)
821{
822	snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
823}
824
825void
826device_set_desc_copy(device_t dev, const char *desc)
827{
828	device_set_desc(dev, desc);
829}
830
831void   *
832devclass_get_softc(devclass_t dc, int unit)
833{
834	return (device_get_softc(devclass_get_device(dc, unit)));
835}
836
837int
838devclass_get_maxunit(devclass_t dc)
839{
840	int max_unit = 0;
841
842	if (dc) {
843		max_unit = DEVCLASS_MAXUNIT;
844		while (max_unit--) {
845			if (dc->dev_list[max_unit]) {
846				break;
847			}
848		}
849		max_unit++;
850	}
851	return (max_unit);
852}
853
854device_t
855devclass_get_device(devclass_t dc, int unit)
856{
857	return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
858	    NULL : dc->dev_list[unit]);
859}
860
861devclass_t
862devclass_find(const char *classname)
863{
864	const struct module_data *mod;
865
866	TAILQ_FOREACH(mod, &module_head, entry) {
867		if (devclass_equal(mod->mod_name, classname))
868			return (mod->devclass_pp[0]);
869	}
870	return (NULL);
871}
872
873void
874module_register(void *data)
875{
876	struct module_data *mdata = data;
877
878	TAILQ_INSERT_TAIL(&module_head, mdata, entry);
879}
880
881/*------------------------------------------------------------------------*
882 * System startup
883 *------------------------------------------------------------------------*/
884
885static void
886sysinit_run(const void **ppdata)
887{
888	const struct sysinit *psys;
889
890	while ((psys = *ppdata) != NULL) {
891		(psys->func) (psys->data);
892		ppdata++;
893	}
894}
895
896/*------------------------------------------------------------------------*
897 * USB process API
898 *------------------------------------------------------------------------*/
899
900static int usb_do_process(struct usb_process *);
901static int usb_proc_level = -1;
902static struct mtx usb_proc_mtx;
903
904void
905usb_idle(void)
906{
907	int old_level = usb_proc_level;
908	int old_giant = Giant.owned;
909	int worked;
910
911	device_run_interrupts(usb_pci_root);
912
913	do {
914		worked = 0;
915		Giant.owned = 0;
916
917		while (++usb_proc_level < USB_PROC_MAX)
918			worked |= usb_do_process(usb_process + usb_proc_level);
919
920		usb_proc_level = old_level;
921		Giant.owned = old_giant;
922
923	} while (worked);
924}
925
926void
927usb_init(void)
928{
929	sysinit_run(sysinit_data);
930}
931
932void
933usb_uninit(void)
934{
935	sysinit_run(sysuninit_data);
936}
937
938static void
939usb_process_init_sub(struct usb_process *up)
940{
941	TAILQ_INIT(&up->up_qhead);
942
943	cv_init(&up->up_cv, "-");
944	cv_init(&up->up_drain, "usbdrain");
945
946	up->up_mtx = &usb_proc_mtx;
947}
948
949static void
950usb_process_init(void *arg)
951{
952	uint8_t x;
953
954	mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
955
956	for (x = 0; x != USB_PROC_MAX; x++)
957		usb_process_init_sub(&usb_process[x]);
958
959}
960SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
961
962static int
963usb_do_process(struct usb_process *up)
964{
965	struct usb_proc_msg *pm;
966	int worked = 0;
967
968	mtx_lock(&usb_proc_mtx);
969
970repeat:
971	pm = TAILQ_FIRST(&up->up_qhead);
972
973	if (pm != NULL) {
974
975		worked = 1;
976
977		(pm->pm_callback) (pm);
978
979		if (pm == TAILQ_FIRST(&up->up_qhead)) {
980			/* nothing changed */
981			TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
982			pm->pm_qentry.tqe_prev = NULL;
983		}
984		goto repeat;
985	}
986	mtx_unlock(&usb_proc_mtx);
987
988	return (worked);
989}
990
991void   *
992usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
993{
994	struct usb_proc_msg *pm0 = _pm0;
995	struct usb_proc_msg *pm1 = _pm1;
996	struct usb_proc_msg *pm2;
997	usb_size_t d;
998	uint8_t t;
999
1000	t = 0;
1001
1002	if (pm0->pm_qentry.tqe_prev) {
1003		t |= 1;
1004	}
1005	if (pm1->pm_qentry.tqe_prev) {
1006		t |= 2;
1007	}
1008	if (t == 0) {
1009		/*
1010		 * No entries are queued. Queue "pm0" and use the existing
1011		 * message number.
1012		 */
1013		pm2 = pm0;
1014	} else if (t == 1) {
1015		/* Check if we need to increment the message number. */
1016		if (pm0->pm_num == up->up_msg_num) {
1017			up->up_msg_num++;
1018		}
1019		pm2 = pm1;
1020	} else if (t == 2) {
1021		/* Check if we need to increment the message number. */
1022		if (pm1->pm_num == up->up_msg_num) {
1023			up->up_msg_num++;
1024		}
1025		pm2 = pm0;
1026	} else if (t == 3) {
1027		/*
1028		 * Both entries are queued. Re-queue the entry closest to
1029		 * the end.
1030		 */
1031		d = (pm1->pm_num - pm0->pm_num);
1032
1033		/* Check sign after subtraction */
1034		if (d & 0x80000000) {
1035			pm2 = pm0;
1036		} else {
1037			pm2 = pm1;
1038		}
1039
1040		TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
1041	} else {
1042		pm2 = NULL;		/* panic - should not happen */
1043	}
1044
1045	/* Put message last on queue */
1046
1047	pm2->pm_num = up->up_msg_num;
1048	TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
1049
1050	return (pm2);
1051}
1052
1053/*------------------------------------------------------------------------*
1054 *	usb_proc_is_gone
1055 *
1056 * Return values:
1057 *    0: USB process is running
1058 * Else: USB process is tearing down
1059 *------------------------------------------------------------------------*/
1060uint8_t
1061usb_proc_is_gone(struct usb_process *up)
1062{
1063	return (0);
1064}
1065
1066/*------------------------------------------------------------------------*
1067 *	usb_proc_mwait
1068 *
1069 * This function will return when the USB process message pointed to
1070 * by "pm" is no longer on a queue. This function must be called
1071 * having "usb_proc_mtx" locked.
1072 *------------------------------------------------------------------------*/
1073void
1074usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
1075{
1076	struct usb_proc_msg *pm0 = _pm0;
1077	struct usb_proc_msg *pm1 = _pm1;
1078
1079	/* Just remove the messages from the queue. */
1080	if (pm0->pm_qentry.tqe_prev) {
1081		TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
1082		pm0->pm_qentry.tqe_prev = NULL;
1083	}
1084	if (pm1->pm_qentry.tqe_prev) {
1085		TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
1086		pm1->pm_qentry.tqe_prev = NULL;
1087	}
1088}
1089
1090/*------------------------------------------------------------------------*
1091 * SYSTEM attach
1092 *------------------------------------------------------------------------*/
1093
1094static device_method_t pci_methods[] = {
1095	DEVMETHOD_END
1096};
1097
1098static driver_t pci_driver = {
1099	.name = "pci",
1100	.methods = pci_methods,
1101};
1102
1103static devclass_t pci_devclass;
1104
1105DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
1106
1107static const char *usb_pci_devices[] = {
1108#ifdef USB_PROBE_LIST
1109	USB_PROBE_LIST
1110#endif
1111};
1112
1113#define	USB_PCI_USB_MAX	(sizeof(usb_pci_devices) / sizeof(void *))
1114
1115static device_t usb_pci_dev[USB_PCI_USB_MAX];
1116
1117static void
1118usb_pci_mod_load(void *arg)
1119{
1120	uint32_t x;
1121
1122	usb_pci_root = device_add_child(NULL, "pci", -1);
1123	if (usb_pci_root == NULL)
1124		return;
1125
1126	for (x = 0; x != USB_PCI_USB_MAX; x++) {
1127		usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1);
1128		if (usb_pci_dev[x] == NULL)
1129			continue;
1130		if (device_probe_and_attach(usb_pci_dev[x])) {
1131			device_printf(usb_pci_dev[x],
1132			    "WARNING: Probe and attach failed!\n");
1133		}
1134	}
1135}
1136SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
1137
1138static void
1139usb_pci_mod_unload(void *arg)
1140{
1141	uint32_t x;
1142
1143	for (x = 0; x != USB_PCI_USB_MAX; x++) {
1144		if (usb_pci_dev[x]) {
1145			device_detach(usb_pci_dev[x]);
1146			device_delete_child(usb_pci_root, usb_pci_dev[x]);
1147		}
1148	}
1149	if (usb_pci_root)
1150		device_delete_child(NULL, usb_pci_root);
1151}
1152SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
1153
1154/*------------------------------------------------------------------------*
1155 * MALLOC API
1156 *------------------------------------------------------------------------*/
1157
1158#define	USB_POOL_ALIGN 8
1159
1160static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
1161static uint32_t usb_pool_rem = USB_POOL_SIZE;
1162static uint32_t usb_pool_entries;
1163
1164struct malloc_hdr {
1165	TAILQ_ENTRY(malloc_hdr) entry;
1166	uint32_t size;
1167} __aligned(USB_POOL_ALIGN);
1168
1169static TAILQ_HEAD(, malloc_hdr) malloc_head =
1170	TAILQ_HEAD_INITIALIZER(malloc_head);
1171
1172void   *
1173usb_malloc(unsigned long size)
1174{
1175	struct malloc_hdr *hdr;
1176
1177	size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
1178	size += sizeof(struct malloc_hdr);
1179
1180	TAILQ_FOREACH(hdr, &malloc_head, entry) {
1181		if (hdr->size == size)
1182			break;
1183	}
1184
1185	if (hdr) {
1186		printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1187		    (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1188
1189		TAILQ_REMOVE(&malloc_head, hdr, entry);
1190		memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1191		return (hdr + 1);
1192	}
1193	if (usb_pool_rem >= size) {
1194		hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
1195		hdr->size = size;
1196
1197		usb_pool_rem -= size;
1198		usb_pool_entries++;
1199
1200		printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
1201		    (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
1202
1203		memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
1204		return (hdr + 1);
1205	}
1206	return (NULL);
1207}
1208
1209void
1210usb_free(void *arg)
1211{
1212	struct malloc_hdr *hdr;
1213
1214	if (arg == NULL)
1215		return;
1216
1217	hdr = arg;
1218	hdr--;
1219
1220	TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
1221}
1222
1223char   *
1224usb_strdup(const char *str)
1225{
1226	char *tmp;
1227	int len;
1228
1229	len = 1 + strlen(str);
1230
1231	tmp = usb_malloc(len);
1232	if (tmp == NULL)
1233		return (NULL);
1234
1235	memcpy(tmp, str, len);
1236	return (tmp);
1237}
1238