subr_bus.c revision 45720
1/*-
2 * Copyright (c) 1997,1998 Doug Rabson
3 * 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 *	$Id: subr_bus.c,v 1.16 1999/03/29 08:54:20 dfr Exp $
27 */
28
29#include <sys/param.h>
30#include <sys/queue.h>
31#include <sys/malloc.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
34#include <sys/sysctl.h>
35#include <sys/bus_private.h>
36#include <sys/systm.h>
37#include <machine/stdarg.h>	/* for device_printf() */
38
39#include "opt_bus.h"
40
41#ifdef BUS_DEBUG
42#define PDEBUG(a)	(printf(__FUNCTION__ ":%d: ", __LINE__), printf a, printf("\n"))
43#define DEVICENAME(d)	((d)? device_get_name(d): "no device")
44#define DRIVERNAME(d)	((d)? d->name : "no driver")
45#define DEVCLANAME(d)	((d)? d->name : "no devclass")
46
47/* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
48 * prevent syslog from deleting initial spaces
49 */
50#define indentprintf(p)	do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while(0)
51
52static void print_method_list(device_method_t *m, int indent);
53static void print_device_ops(device_ops_t ops, int indent);
54static void print_device_short(device_t dev, int indent);
55static void print_device(device_t dev, int indent);
56void print_device_tree_short(device_t dev, int indent);
57void print_device_tree(device_t dev, int indent);
58static void print_driver_short(driver_t *driver, int indent);
59static void print_driver(driver_t *driver, int indent);
60static void print_driver_list(driver_list_t drivers, int indent);
61static void print_devclass_short(devclass_t dc, int indent);
62static void print_devclass(devclass_t dc, int indent);
63void print_devclass_list_short(void);
64void print_devclass_list(void);
65
66#else
67/* Make the compiler ignore the function calls */
68#define PDEBUG(a)			/* nop */
69#define DEVICENAME(d)			/* nop */
70#define DRIVERNAME(d)			/* nop */
71#define DEVCLANAME(d)			/* nop */
72
73#define print_method_list(m,i)		/* nop */
74#define print_device_ops(o,i)		/* nop */
75#define print_device_short(d,i)		/* nop */
76#define print_device(d,i)		/* nop */
77#define print_device_tree_short(d,i)	/* nop */
78#define print_device_tree(d,i)		/* nop */
79#define print_driver_short(d,i)		/* nop */
80#define print_driver(d,i)		/* nop */
81#define print_driver_list(d,i)		/* nop */
82#define print_devclass_short(d,i)	/* nop */
83#define print_devclass(d,i)		/* nop */
84#define print_devclass_list_short()	/* nop */
85#define print_devclass_list()		/* nop */
86#endif
87
88#ifdef DEVICE_SYSCTLS
89static void device_register_oids(device_t dev);
90static void device_unregister_oids(device_t dev);
91#endif
92
93/*
94 * Method table handling
95 */
96static int next_method_offset = 1;
97
98LIST_HEAD(methodlist, method) methods;
99struct method {
100    LIST_ENTRY(method) link;	/* linked list of methods */
101    int offset;			/* offset in method table */
102    int refs;			/* count of device_op_desc users */
103    char* name;			/* unique name of method */
104};
105
106static void
107register_method(struct device_op_desc *desc)
108{
109    struct method* m;
110
111    if (desc->method) {
112	desc->method->refs++;
113	return;
114    }
115
116    for (m = LIST_FIRST(&methods); m; m = LIST_NEXT(m, link)) {
117	if (!strcmp(m->name, desc->name)) {
118	    desc->offset = m->offset;
119	    desc->method = m;
120	    m->refs++;
121	    PDEBUG(("methods %x has the same name, %s, with offset %d",
122		    m, desc->name, desc->offset));
123	    return;
124	}
125    }
126
127    m = (struct method *) malloc(sizeof(struct method)
128				 + strlen(desc->name) + 1,
129				 M_DEVBUF, M_NOWAIT);
130    if (!m)
131	    panic("register_method: out of memory");
132    bzero(m, sizeof(struct method) + strlen(desc->name) + 1);
133    m->offset = next_method_offset++;
134    m->refs = 1;
135    m->name = (char*) (m + 1);
136    strcpy(m->name, desc->name);
137    LIST_INSERT_HEAD(&methods, m, link);
138
139    desc->offset = m->offset;
140    desc->method = m;
141}
142
143static void
144unregister_method(struct device_op_desc *desc)
145{
146    struct method *m = desc->method;
147    m->refs--;
148    if (m->refs == 0) {
149	LIST_REMOVE(m, link);
150	free(m, M_DEVBUF);
151    }
152    desc->method = 0;
153}
154
155static int error_method(void)
156{
157    return ENXIO;
158}
159
160static struct device_ops null_ops = {
161    1,
162    { error_method }
163};
164
165static void
166compile_methods(driver_t *driver)
167{
168    device_ops_t ops;
169    struct device_method *m;
170    int i;
171
172    /*
173     * First register any methods which need it.
174     */
175    for (i = 0, m = driver->methods; m->desc; i++, m++)
176	register_method(m->desc);
177
178    /*
179     * Then allocate the compiled op table.
180     */
181    ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),
182		 M_DEVBUF, M_NOWAIT);
183    if (!ops)
184	panic("compile_methods: out of memory");
185    bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t));
186
187    ops->maxoffset = next_method_offset;
188    for (i = 0; i < next_method_offset; i++)
189	ops->methods[i] = error_method;
190    for (i = 0, m = driver->methods; m->desc; i++, m++)
191	ops->methods[m->desc->offset] = m->func;
192    PDEBUG(("%s has %d method%s, wasting %d bytes",
193    		DRIVERNAME(driver), i, (i==1?"":"s"),
194		(next_method_offset-i)*sizeof(devop_t)));
195
196    driver->ops = ops;
197}
198
199static void
200free_methods(driver_t *driver)
201{
202    int i;
203    struct device_method *m;
204
205    /*
206     * Unregister any methods which are no longer used.
207     */
208    for (i = 0, m = driver->methods; m->desc; i++, m++)
209	unregister_method(m->desc);
210
211    /*
212     * Free memory and clean up.
213     */
214    free(driver->ops, M_DEVBUF);
215    driver->ops = 0;
216}
217
218/*
219 * Devclass implementation
220 */
221
222static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
223
224static devclass_t
225devclass_find_internal(const char *classname, int create)
226{
227    devclass_t dc;
228
229    PDEBUG(("looking for %s", classname));
230    if (!classname)
231	return NULL;
232
233    for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
234	if (!strcmp(dc->name, classname))
235	    return dc;
236
237    PDEBUG(("%s not found%s", classname, (create? ", creating": "")));
238    if (create) {
239	dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
240		    M_DEVBUF, M_NOWAIT);
241	if (!dc)
242	    return NULL;
243	bzero(dc, sizeof(struct devclass) + strlen(classname) + 1);
244	dc->name = (char*) (dc + 1);
245	strcpy(dc->name, classname);
246	dc->devices = NULL;
247	dc->maxunit = 0;
248	dc->nextunit = 0;
249	TAILQ_INIT(&dc->drivers);
250	TAILQ_INSERT_TAIL(&devclasses, dc, link);
251    }
252
253    return dc;
254}
255
256devclass_t
257devclass_find(const char *classname)
258{
259    return devclass_find_internal(classname, FALSE);
260}
261
262int
263devclass_add_driver(devclass_t dc, driver_t *driver)
264{
265    driverlink_t dl;
266    int i;
267
268    PDEBUG(("%s", DRIVERNAME(driver)));
269
270    dl = malloc(sizeof *dl, M_DEVBUF, M_NOWAIT);
271    if (!dl)
272	return ENOMEM;
273    bzero(dl, sizeof *dl);
274
275    /*
276     * Compile the driver's methods.
277     */
278    if (!driver->ops)
279	compile_methods(driver);
280
281    /*
282     * Make sure the devclass which the driver is implementing exists.
283     */
284    devclass_find_internal(driver->name, TRUE);
285
286    dl->driver = driver;
287    TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
288    driver->refs++;
289
290    /*
291     * Call BUS_DRIVER_ADDED for any existing busses in this class.
292     */
293    for (i = 0; i < dc->maxunit; i++)
294	if (dc->devices[i])
295	    BUS_DRIVER_ADDED(dc->devices[i], driver);
296
297    return 0;
298}
299
300int
301devclass_delete_driver(devclass_t busclass, driver_t *driver)
302{
303    devclass_t dc = devclass_find(driver->name);
304    driverlink_t dl;
305    device_t dev;
306    int i;
307    int error;
308
309    PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
310
311    if (!dc)
312	return 0;
313
314    /*
315     * Find the link structure in the bus' list of drivers.
316     */
317    for (dl = TAILQ_FIRST(&busclass->drivers); dl;
318	 dl = TAILQ_NEXT(dl, link)) {
319	if (dl->driver == driver)
320	    break;
321    }
322
323    if (!dl) {
324	PDEBUG(("%s not found in %s list", driver->name, busclass->name));
325	return ENOENT;
326    }
327
328    /*
329     * Disassociate from any devices.  We iterate through all the
330     * devices in the devclass of the driver and detach any which are
331     * using the driver and which have a parent in the devclass which
332     * we are deleting from.
333     *
334     * Note that since a driver can be in multiple devclasses, we
335     * should not detach devices which are not children of devices in
336     * the affected devclass.
337     */
338    for (i = 0; i < dc->maxunit; i++) {
339	if (dc->devices[i]) {
340	    dev = dc->devices[i];
341	    if (dev->driver == driver
342		&& dev->parent && dev->parent->devclass == busclass) {
343		if ((error = device_detach(dev)) != 0)
344		    return error;
345		device_set_driver(dev, NULL);
346	    }
347	}
348    }
349
350    TAILQ_REMOVE(&busclass->drivers, dl, link);
351    free(dl, M_DEVBUF);
352
353    driver->refs--;
354    if (driver->refs == 0)
355	free_methods(driver);
356
357    return 0;
358}
359
360static driverlink_t
361devclass_find_driver_internal(devclass_t dc, const char *classname)
362{
363    driverlink_t dl;
364
365    PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
366
367    for (dl = TAILQ_FIRST(&dc->drivers); dl; dl = TAILQ_NEXT(dl, link)) {
368	if (!strcmp(dl->driver->name, classname))
369	    return dl;
370    }
371
372    PDEBUG(("not found"));
373    return NULL;
374}
375
376driver_t *
377devclass_find_driver(devclass_t dc, const char *classname)
378{
379    driverlink_t dl;
380
381    dl = devclass_find_driver_internal(dc, classname);
382    if (dl)
383	return dl->driver;
384    else
385	return NULL;
386}
387
388const char *
389devclass_get_name(devclass_t dc)
390{
391    return dc->name;
392}
393
394device_t
395devclass_get_device(devclass_t dc, int unit)
396{
397    if (unit < 0 || unit >= dc->maxunit)
398	return NULL;
399    return dc->devices[unit];
400}
401
402void *
403devclass_get_softc(devclass_t dc, int unit)
404{
405    device_t dev;
406
407    if (unit < 0 || unit >= dc->maxunit)
408	return NULL;
409    dev = dc->devices[unit];
410    if (!dev || dev->state < DS_ATTACHED)
411	return NULL;
412    return dev->softc;
413}
414
415int
416devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
417{
418    int i;
419    int count;
420    device_t *list;
421
422    count = 0;
423    for (i = 0; i < dc->maxunit; i++)
424	if (dc->devices[i])
425	    count++;
426
427    list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
428    if (!list)
429	return ENOMEM;
430    bzero(list, count * sizeof(device_t));
431
432    count = 0;
433    for (i = 0; i < dc->maxunit; i++)
434	if (dc->devices[i]) {
435	    list[count] = dc->devices[i];
436	    count++;
437	}
438
439    *devlistp = list;
440    *devcountp = count;
441
442    return 0;
443}
444
445int
446devclass_get_maxunit(devclass_t dc)
447{
448    return dc->maxunit;
449}
450
451static int
452devclass_alloc_unit(devclass_t dc, int *unitp)
453{
454    int unit = *unitp;
455
456    PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
457
458    /*
459     * If we have been given a wired unit number, check for existing
460     * device.
461     */
462    if (unit != -1) {
463	device_t dev;
464	dev = devclass_get_device(dc, unit);
465	if (dev) {
466	    printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit);
467	    unit = -1;
468	}
469    }
470
471    if (unit == -1) {
472	unit = dc->nextunit;
473	dc->nextunit++;
474    } else if (dc->nextunit <= unit)
475	dc->nextunit = unit + 1;
476
477    if (unit >= dc->maxunit) {
478	device_t *newlist;
479	int newsize;
480
481	newsize = (dc->maxunit ? 2 * dc->maxunit
482		   : MINALLOCSIZE / sizeof(device_t));
483	newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT);
484	if (!newlist)
485	    return ENOMEM;
486	bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
487	bzero(newlist + dc->maxunit,
488	      sizeof(device_t) * (newsize - dc->maxunit));
489	if (dc->devices)
490	    free(dc->devices, M_DEVBUF);
491	dc->devices = newlist;
492	dc->maxunit = newsize;
493    }
494    PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
495
496    *unitp = unit;
497    return 0;
498}
499
500static int
501devclass_add_device(devclass_t dc, device_t dev)
502{
503    int buflen, error;
504
505    PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
506
507    buflen = strlen(dc->name) + 5;
508    dev->nameunit = malloc(buflen, M_DEVBUF, M_NOWAIT);
509    if (!dev->nameunit)
510	return ENOMEM;
511    bzero(dev->nameunit, buflen);
512
513    if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
514	free(dev->nameunit, M_DEVBUF);
515	dev->nameunit = NULL;
516	return error;
517    }
518    dc->devices[dev->unit] = dev;
519    dev->devclass = dc;
520    snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
521
522#ifdef DEVICE_SYSCTLS
523    device_register_oids(dev);
524#endif
525
526    return 0;
527}
528
529static int
530devclass_delete_device(devclass_t dc, device_t dev)
531{
532    if (!dc || !dev)
533	return 0;
534
535    PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
536
537    if (dev->devclass != dc
538	|| dc->devices[dev->unit] != dev)
539	panic("devclass_delete_device: inconsistent device class");
540    dc->devices[dev->unit] = NULL;
541    if (dev->flags & DF_WILDCARD)
542	dev->unit = -1;
543    dev->devclass = NULL;
544    free(dev->nameunit, M_DEVBUF);
545    dev->nameunit = NULL;
546    while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL)
547	dc->nextunit--;
548
549#ifdef DEVICE_SYSCTLS
550    device_unregister_oids(dev);
551#endif
552
553    return 0;
554}
555
556static device_t
557make_device(device_t parent, const char *name,
558	    int unit, void *ivars)
559{
560    device_t dev;
561    devclass_t dc;
562
563    PDEBUG(("%s at %s as unit %d with%s ivars",
564    	    name, DEVICENAME(parent), unit, (ivars? "":"out")));
565
566    if (name) {
567	dc = devclass_find_internal(name, TRUE);
568	if (!dc) {
569	    printf("make_device: can't find device class %s\n", name);
570	    return NULL;
571	}
572    } else
573	dc = NULL;
574
575    dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT);
576    if (!dev)
577	return 0;
578    bzero(dev, sizeof(struct device));
579
580    dev->parent = parent;
581    TAILQ_INIT(&dev->children);
582    dev->ops = &null_ops;
583    dev->driver = NULL;
584    dev->devclass = NULL;
585    dev->unit = unit;
586    dev->nameunit = NULL;
587    dev->desc = NULL;
588    dev->busy = 0;
589    dev->flags = DF_ENABLED;
590    if (unit == -1)
591	dev->flags |= DF_WILDCARD;
592    if (name) {
593	dev->flags |= DF_FIXEDCLASS;
594	devclass_add_device(dc, dev);
595    }
596    dev->ivars = ivars;
597    dev->softc = NULL;
598
599    dev->state = DS_NOTPRESENT;
600
601    return dev;
602}
603
604static void
605device_print_child(device_t dev, device_t child)
606{
607    printf("%s%d", device_get_name(child), device_get_unit(child));
608    if (device_is_alive(child)) {
609	if (device_get_desc(child))
610	    printf(": <%s>", device_get_desc(child));
611	BUS_PRINT_CHILD(dev, child);
612    } else
613	printf(" not found");
614    printf("\n");
615}
616
617device_t
618device_add_child(device_t dev, const char *name, int unit, void *ivars)
619{
620    device_t child;
621
622    PDEBUG(("%s at %s as unit %d with%s ivars",
623    	    name, DEVICENAME(dev), unit, (ivars? "":"out")));
624
625    child = make_device(dev, name, unit, ivars);
626
627    if (child)
628	TAILQ_INSERT_TAIL(&dev->children, child, link);
629    else
630	PDEBUG(("%s failed", name));
631
632    return child;
633}
634
635device_t
636device_add_child_after(device_t dev, device_t place, const char *name,
637		       int unit, void *ivars)
638{
639    device_t child;
640
641    PDEBUG(("%s at %s after %s as unit %d with%s ivars",
642    	    name, DEVICENAME(dev), DEVICENAME(place), unit, (ivars? "":"out")));
643
644    child = make_device(dev, name, unit, ivars);
645
646    if (place) {
647	TAILQ_INSERT_AFTER(&dev->children, place, dev, link);
648    } else {
649	TAILQ_INSERT_HEAD(&dev->children, dev, link);
650    }
651
652    return child;
653}
654
655int
656device_delete_child(device_t dev, device_t child)
657{
658    int error;
659    device_t grandchild;
660
661    PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
662
663    /* remove children first */
664    while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
665        error = device_delete_child(child, grandchild);
666	if (error)
667	    return error;
668    }
669
670    if ((error = device_detach(child)) != 0)
671	return error;
672    if (child->devclass)
673	devclass_delete_device(child->devclass, child);
674    TAILQ_REMOVE(&dev->children, child, link);
675    device_set_desc(child, NULL);
676    free(child, M_DEVBUF);
677
678    return 0;
679}
680
681/*
682 * Find only devices attached to this bus.
683 */
684device_t
685device_find_child(device_t dev, const char *classname, int unit)
686{
687    devclass_t dc;
688    device_t child;
689
690    dc = devclass_find(classname);
691    if (!dc)
692	return NULL;
693
694    child = devclass_get_device(dc, unit);
695    if (child && child->parent == dev)
696	return child;
697    return NULL;
698}
699
700static driverlink_t
701first_matching_driver(devclass_t dc, device_t dev)
702{
703    if (dev->devclass)
704	return devclass_find_driver_internal(dc, dev->devclass->name);
705    else
706	return TAILQ_FIRST(&dc->drivers);
707}
708
709static driverlink_t
710next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
711{
712    if (dev->devclass) {
713	driverlink_t dl;
714	for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
715	    if (!strcmp(dev->devclass->name, dl->driver->name))
716		return dl;
717	return NULL;
718    } else
719	return TAILQ_NEXT(last, link);
720}
721
722static int
723device_probe_child(device_t dev, device_t child)
724{
725    devclass_t dc;
726    driverlink_t dl;
727
728    dc = dev->devclass;
729    if (dc == NULL)
730	panic("device_probe_child: parent device has no devclass");
731
732    if (child->state == DS_ALIVE)
733	return 0;
734
735    for (dl = first_matching_driver(dc, child);
736	 dl;
737	 dl = next_matching_driver(dc, child, dl)) {
738	PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
739	device_set_driver(child, dl->driver);
740	if (DEVICE_PROBE(child) == 0) {
741	    if (!child->devclass)
742		device_set_devclass(child, dl->driver->name);
743	    child->state = DS_ALIVE;
744	    return 0;
745	}
746    }
747
748    return ENXIO;
749}
750
751device_t
752device_get_parent(device_t dev)
753{
754    return dev->parent;
755}
756
757int
758device_get_children(device_t dev, device_t **devlistp, int *devcountp)
759{
760    int count;
761    device_t child;
762    device_t *list;
763
764    count = 0;
765    for (child = TAILQ_FIRST(&dev->children); child;
766	 child = TAILQ_NEXT(child, link))
767	count++;
768
769    list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
770    if (!list)
771	return ENOMEM;
772    bzero(list, count * sizeof(device_t));
773
774    count = 0;
775    for (child = TAILQ_FIRST(&dev->children); child;
776	 child = TAILQ_NEXT(child, link)) {
777	list[count] = child;
778	count++;
779    }
780
781    *devlistp = list;
782    *devcountp = count;
783
784    return 0;
785}
786
787driver_t *
788device_get_driver(device_t dev)
789{
790    return dev->driver;
791}
792
793devclass_t
794device_get_devclass(device_t dev)
795{
796    return dev->devclass;
797}
798
799const char *
800device_get_name(device_t dev)
801{
802    if (dev->devclass)
803	return devclass_get_name(dev->devclass);
804    return NULL;
805}
806
807const char *
808device_get_nameunit(device_t dev)
809{
810    return dev->nameunit;
811}
812
813int
814device_get_unit(device_t dev)
815{
816    return dev->unit;
817}
818
819const char *
820device_get_desc(device_t dev)
821{
822    return dev->desc;
823}
824
825void
826device_print_prettyname(device_t dev)
827{
828	const char *name = device_get_name(dev);
829
830	if (name == 0)
831		name = "(no driver assigned)";
832	printf("%s%d: ", name, device_get_unit(dev));
833}
834
835void
836device_printf(device_t dev, const char * fmt, ...)
837{
838	va_list ap;
839
840	device_print_prettyname(dev);
841	va_start(ap, fmt);
842	vprintf(fmt, ap);
843	va_end(ap);
844}
845
846static void
847device_set_desc_internal(device_t dev, const char* desc, int copy)
848{
849    if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
850	free(dev->desc, M_DEVBUF);
851	dev->flags &= ~DF_DESCMALLOCED;
852	dev->desc = NULL;
853    }
854
855    if (copy && desc) {
856	dev->desc = malloc(strlen(desc) + 1, M_DEVBUF, M_NOWAIT);
857	if (dev->desc) {
858	    strcpy(dev->desc, desc);
859	    dev->flags |= DF_DESCMALLOCED;
860	}
861    } else
862	/* Avoid a -Wcast-qual warning */
863	dev->desc = (char *)(uintptr_t) desc;
864
865#ifdef DEVICE_SYSCTLS
866    {
867	struct sysctl_oid *oid = &dev->oid[1];
868	oid->oid_arg1 = dev->desc ? dev->desc : "";
869	oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
870    }
871#endif
872}
873
874void
875device_set_desc(device_t dev, const char* desc)
876{
877    device_set_desc_internal(dev, desc, FALSE);
878}
879
880void
881device_set_desc_copy(device_t dev, const char* desc)
882{
883    device_set_desc_internal(dev, desc, TRUE);
884}
885
886void *
887device_get_softc(device_t dev)
888{
889    return dev->softc;
890}
891
892void *
893device_get_ivars(device_t dev)
894{
895    return dev->ivars;
896}
897
898device_state_t
899device_get_state(device_t dev)
900{
901    return dev->state;
902}
903
904void
905device_enable(device_t dev)
906{
907    dev->flags |= DF_ENABLED;
908}
909
910void
911device_disable(device_t dev)
912{
913    dev->flags &= ~DF_ENABLED;
914}
915
916void
917device_busy(device_t dev)
918{
919    if (dev->state < DS_ATTACHED)
920	panic("device_busy: called for unattached device");
921    if (dev->busy == 0 && dev->parent)
922	device_busy(dev->parent);
923    dev->busy++;
924    dev->state = DS_BUSY;
925}
926
927void
928device_unbusy(device_t dev)
929{
930    if (dev->state != DS_BUSY)
931	panic("device_unbusy: called for non-busy device");
932    dev->busy--;
933    if (dev->busy == 0) {
934	if (dev->parent)
935	    device_unbusy(dev->parent);
936	dev->state = DS_ATTACHED;
937    }
938}
939
940void
941device_quiet(device_t dev)
942{
943    dev->flags |= DF_QUIET;
944}
945
946void
947device_verbose(device_t dev)
948{
949    dev->flags &= ~DF_QUIET;
950}
951
952int
953device_is_quiet(device_t dev)
954{
955    return (dev->flags & DF_QUIET) != 0;
956}
957
958int
959device_is_enabled(device_t dev)
960{
961    return (dev->flags & DF_ENABLED) != 0;
962}
963
964int
965device_is_alive(device_t dev)
966{
967    return dev->state >= DS_ALIVE;
968}
969
970int
971device_set_devclass(device_t dev, const char *classname)
972{
973    devclass_t dc;
974
975    if (dev->devclass) {
976	printf("device_set_devclass: device class already set\n");
977	return EINVAL;
978    }
979
980    dc = devclass_find_internal(classname, TRUE);
981    if (!dc)
982	return ENOMEM;
983
984    return devclass_add_device(dc, dev);
985}
986
987int
988device_set_driver(device_t dev, driver_t *driver)
989{
990    if (dev->state >= DS_ATTACHED)
991	return EBUSY;
992
993    if (dev->driver == driver)
994	return 0;
995
996    if (dev->softc) {
997	free(dev->softc, M_DEVBUF);
998	dev->softc = NULL;
999    }
1000    dev->ops = &null_ops;
1001    dev->driver = driver;
1002    if (driver) {
1003	dev->ops = driver->ops;
1004	dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT);
1005	if (!dev->softc) {
1006	    dev->ops = &null_ops;
1007	    dev->driver = NULL;
1008	    return ENOMEM;
1009	}
1010	bzero(dev->softc, driver->softc);
1011    }
1012    return 0;
1013}
1014
1015int
1016device_probe_and_attach(device_t dev)
1017{
1018    device_t bus = dev->parent;
1019    int error = 0;
1020
1021    if (dev->state >= DS_ALIVE)
1022	return 0;
1023
1024    if (dev->flags & DF_ENABLED) {
1025	error = device_probe_child(bus, dev);
1026	if (!error) {
1027	    if (!device_is_quiet(dev))
1028		device_print_child(bus, dev);
1029	    error = DEVICE_ATTACH(dev);
1030	    if (!error)
1031		dev->state = DS_ATTACHED;
1032	    else {
1033		printf("device_probe_and_attach: %s%d attach returned %d\n",
1034		       dev->driver->name, dev->unit, error);
1035		device_set_driver(dev, NULL);
1036		dev->state = DS_NOTPRESENT;
1037	    }
1038	}
1039    } else {
1040	    device_print_prettyname(dev);
1041	    printf("not probed (disabled)\n");
1042    }
1043
1044    return error;
1045}
1046
1047int
1048device_detach(device_t dev)
1049{
1050    int error;
1051
1052    PDEBUG(("%s", DEVICENAME(dev)));
1053    if (dev->state == DS_BUSY)
1054	return EBUSY;
1055    if (dev->state != DS_ATTACHED)
1056	return 0;
1057
1058    if ((error = DEVICE_DETACH(dev)) != 0)
1059	return error;
1060    if (dev->parent)
1061	BUS_CHILD_DETACHED(dev->parent, dev);
1062
1063    if (!(dev->flags & DF_FIXEDCLASS))
1064	devclass_delete_device(dev->devclass, dev);
1065
1066    dev->state = DS_NOTPRESENT;
1067    device_set_driver(dev, NULL);
1068
1069    return 0;
1070}
1071
1072int
1073device_shutdown(device_t dev)
1074{
1075    if (dev->state < DS_ATTACHED)
1076	return 0;
1077    return DEVICE_SHUTDOWN(dev);
1078}
1079
1080#ifdef DEVICE_SYSCTLS
1081
1082/*
1083 * Sysctl nodes for devices.
1084 */
1085
1086SYSCTL_NODE(_hw, OID_AUTO, devices, CTLFLAG_RW, 0, "A list of all devices");
1087
1088static int
1089sysctl_handle_children SYSCTL_HANDLER_ARGS
1090{
1091    device_t dev = arg1;
1092    device_t child;
1093    int first = 1, error = 0;
1094
1095    for (child = TAILQ_FIRST(&dev->children); child;
1096	 child = TAILQ_NEXT(child, link)) {
1097	if (child->nameunit) {
1098	    if (!first) {
1099		error = SYSCTL_OUT(req, ",", 1);
1100		if (error) return error;
1101	    } else {
1102		first = 0;
1103	    }
1104	    error = SYSCTL_OUT(req, child->nameunit, strlen(child->nameunit));
1105	    if (error) return error;
1106	}
1107    }
1108
1109    error = SYSCTL_OUT(req, "", 1);
1110
1111    return error;
1112}
1113
1114static int
1115sysctl_handle_state SYSCTL_HANDLER_ARGS
1116{
1117    device_t dev = arg1;
1118
1119    switch (dev->state) {
1120    case DS_NOTPRESENT:
1121	return SYSCTL_OUT(req, "notpresent", sizeof("notpresent"));
1122    case DS_ALIVE:
1123	return SYSCTL_OUT(req, "alive", sizeof("alive"));
1124    case DS_ATTACHED:
1125	return SYSCTL_OUT(req, "attached", sizeof("attached"));
1126    case DS_BUSY:
1127	return SYSCTL_OUT(req, "busy", sizeof("busy"));
1128    }
1129
1130    return 0;
1131}
1132
1133static void
1134device_register_oids(device_t dev)
1135{
1136    struct sysctl_oid* oid;
1137
1138    oid = &dev->oid[0];
1139    bzero(oid, sizeof(*oid));
1140    oid->oid_parent = &sysctl__hw_devices_children;
1141    oid->oid_number = OID_AUTO;
1142    oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW;
1143    oid->oid_arg1 = &dev->oidlist[0];
1144    oid->oid_arg2 = 0;
1145    oid->oid_name = dev->nameunit;
1146    oid->oid_handler = 0;
1147    oid->oid_fmt = "N";
1148    SLIST_INIT(&dev->oidlist[0]);
1149    sysctl_register_oid(oid);
1150
1151    oid = &dev->oid[1];
1152    bzero(oid, sizeof(*oid));
1153    oid->oid_parent = &dev->oidlist[0];
1154    oid->oid_number = OID_AUTO;
1155    oid->oid_kind = CTLTYPE_STRING | CTLFLAG_RD;
1156    oid->oid_arg1 = dev->desc ? dev->desc : "";
1157    oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
1158    oid->oid_name = "desc";
1159    oid->oid_handler = sysctl_handle_string;
1160    oid->oid_fmt = "A";
1161    sysctl_register_oid(oid);
1162
1163    oid = &dev->oid[2];
1164    bzero(oid, sizeof(*oid));
1165    oid->oid_parent = &dev->oidlist[0];
1166    oid->oid_number = OID_AUTO;
1167    oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
1168    oid->oid_arg1 = dev;
1169    oid->oid_arg2 = 0;
1170    oid->oid_name = "children";
1171    oid->oid_handler = sysctl_handle_children;
1172    oid->oid_fmt = "A";
1173    sysctl_register_oid(oid);
1174
1175    oid = &dev->oid[3];
1176    bzero(oid, sizeof(*oid));
1177    oid->oid_parent = &dev->oidlist[0];
1178    oid->oid_number = OID_AUTO;
1179    oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
1180    oid->oid_arg1 = dev;
1181    oid->oid_arg2 = 0;
1182    oid->oid_name = "state";
1183    oid->oid_handler = sysctl_handle_state;
1184    oid->oid_fmt = "A";
1185    sysctl_register_oid(oid);
1186}
1187
1188static void
1189device_unregister_oids(device_t dev)
1190{
1191    sysctl_unregister_oid(&dev->oid[0]);
1192    sysctl_unregister_oid(&dev->oid[1]);
1193    sysctl_unregister_oid(&dev->oid[2]);
1194}
1195
1196#endif
1197
1198/*======================================*/
1199/*
1200 * Access functions for device resources.
1201 */
1202
1203/* Supplied by config(8) in ioconf.c */
1204extern struct config_device config_devtab[];
1205extern int devtab_count;
1206
1207/* Runtime version */
1208struct config_device *devtab = config_devtab;
1209
1210static int
1211resource_new_name(char *name, int unit)
1212{
1213	struct config_device *new;
1214
1215	new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
1216	if (new == NULL)
1217		return -1;
1218	if (devtab && devtab_count > 0)
1219		bcopy(devtab, new, devtab_count * sizeof(*new));
1220	bzero(&new[devtab_count], sizeof(*new));
1221	new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT);
1222	if (new[devtab_count].name == NULL) {
1223		free(new, M_TEMP);
1224		return -1;
1225	}
1226	strcpy(new[devtab_count].name, name);
1227	new[devtab_count].unit = unit;
1228	new[devtab_count].resource_count = 0;
1229	new[devtab_count].resources = NULL;
1230	devtab = new;
1231	return devtab_count++;
1232}
1233
1234static int
1235resource_new_resname(int j, char *resname, resource_type type)
1236{
1237	struct config_resource *new;
1238	int i;
1239
1240	i = devtab[j].resource_count;
1241	new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
1242	if (new == NULL)
1243		return -1;
1244	if (devtab[j].resources && i > 0)
1245		bcopy(devtab[j].resources, new, i * sizeof(*new));
1246	bzero(&new[i], sizeof(*new));
1247	new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT);
1248	if (new[i].name == NULL) {
1249		free(new, M_TEMP);
1250		return -1;
1251	}
1252	strcpy(new[i].name, resname);
1253	new[i].type = type;
1254	if (devtab[j].resources)
1255		free(devtab[j].resources, M_TEMP);
1256	devtab[j].resources = new;
1257	devtab[j].resource_count = i + 1;
1258	return i;
1259}
1260
1261static int
1262resource_match_string(int i, char *resname, char *value)
1263{
1264	int j;
1265	struct config_resource *res;
1266
1267	for (j = 0, res = devtab[i].resources;
1268	     j < devtab[i].resource_count; j++, res++)
1269		if (!strcmp(res->name, resname)
1270		    && res->type == RES_STRING
1271		    && !strcmp(res->u.stringval, value))
1272			return j;
1273	return -1;
1274}
1275
1276static int
1277resource_find(const char *name, int unit, char *resname,
1278	      struct config_resource **result)
1279{
1280	int i, j;
1281	struct config_resource *res;
1282
1283	/*
1284	 * First check specific instances, then generic.
1285	 */
1286	for (i = 0; i < devtab_count; i++) {
1287		if (devtab[i].unit < 0)
1288			continue;
1289		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1290			res = devtab[i].resources;
1291			for (j = 0; j < devtab[i].resource_count; j++, res++)
1292				if (!strcmp(res->name, resname)) {
1293					*result = res;
1294					return 0;
1295				}
1296		}
1297	}
1298	for (i = 0; i < devtab_count; i++) {
1299		if (devtab[i].unit >= 0)
1300			continue;
1301		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1302			res = devtab[i].resources;
1303			for (j = 0; j < devtab[i].resource_count; j++, res++)
1304				if (!strcmp(res->name, resname)) {
1305					*result = res;
1306					return 0;
1307				}
1308		}
1309	}
1310	return ENOENT;
1311}
1312
1313int
1314resource_int_value(const char *name, int unit, char *resname, int *result)
1315{
1316	int error;
1317	struct config_resource *res;
1318
1319	if ((error = resource_find(name, unit, resname, &res)) != 0)
1320		return error;
1321	if (res->type != RES_INT)
1322		return EFTYPE;
1323	*result = res->u.intval;
1324	return 0;
1325}
1326
1327int
1328resource_long_value(const char *name, int unit, char *resname, long *result)
1329{
1330	int error;
1331	struct config_resource *res;
1332
1333	if ((error = resource_find(name, unit, resname, &res)) != 0)
1334		return error;
1335	if (res->type != RES_LONG)
1336		return EFTYPE;
1337	*result = res->u.longval;
1338	return 0;
1339}
1340
1341int
1342resource_string_value(const char *name, int unit, char *resname, char **result)
1343{
1344	int error;
1345	struct config_resource *res;
1346
1347	if ((error = resource_find(name, unit, resname, &res)) != 0)
1348		return error;
1349	if (res->type != RES_STRING)
1350		return EFTYPE;
1351	*result = res->u.stringval;
1352	return 0;
1353}
1354
1355int
1356resource_query_string(int i, char *resname, char *value)
1357{
1358	if (i < 0)
1359		i = 0;
1360	else
1361		i = i + 1;
1362	for (; i < devtab_count; i++)
1363		if (resource_match_string(i, resname, value) >= 0)
1364			return i;
1365	return -1;
1366}
1367
1368int
1369resource_locate(int i, char *resname)
1370{
1371	if (i < 0)
1372		i = 0;
1373	else
1374		i = i + 1;
1375	for (; i < devtab_count; i++)
1376		if (!strcmp(devtab[i].name, resname))
1377			return i;
1378	return -1;
1379}
1380
1381int
1382resource_count(void)
1383{
1384	return devtab_count;
1385}
1386
1387char *
1388resource_query_name(int i)
1389{
1390	return devtab[i].name;
1391}
1392
1393int
1394resource_query_unit(int i)
1395{
1396	return devtab[i].unit;
1397}
1398
1399static int
1400resource_create(char *name, int unit, char *resname, resource_type type,
1401		struct config_resource **result)
1402{
1403	int i, j;
1404	struct config_resource *res = NULL;
1405
1406	for (i = 0; i < devtab_count; i++) {
1407		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1408			res = devtab[i].resources;
1409			break;
1410		}
1411	}
1412	if (res == NULL) {
1413		i = resource_new_name(name, unit);
1414		if (i < 0)
1415			return ENOMEM;
1416		res = devtab[i].resources;
1417	}
1418	for (j = 0; j < devtab[i].resource_count; j++, res++) {
1419		if (!strcmp(res->name, resname)) {
1420			*result = res;
1421			return 0;
1422		}
1423	}
1424	j = resource_new_resname(i, resname, type);
1425	if (j < 0)
1426		return ENOMEM;
1427	res = &devtab[i].resources[j];
1428	*result = res;
1429	return 0;
1430}
1431
1432int
1433resource_set_int(int i, char *resname, int value)
1434{
1435	int error;
1436	struct config_resource *res;
1437
1438printf("resource_set_int\n");
1439	if (i < 0 || i >= devtab_count)
1440		return EINVAL;
1441	error = resource_create(devtab[i].name, devtab[i].unit, resname,
1442				RES_INT, &res);
1443	if (error)
1444		return error;
1445	if (res->type != RES_INT)
1446		return EFTYPE;
1447	res->u.intval = value;
1448	return 0;
1449}
1450
1451int
1452resource_set_long(int i, char *resname, long value)
1453{
1454	int error;
1455	struct config_resource *res;
1456
1457printf("resource_set_long\n");
1458	if (i < 0 || i >= devtab_count)
1459		return EINVAL;
1460	error = resource_create(devtab[i].name, devtab[i].unit, resname,
1461				RES_LONG, &res);
1462	if (error)
1463		return error;
1464	if (res->type != RES_LONG)
1465		return EFTYPE;
1466	res->u.longval = value;
1467	return 0;
1468}
1469
1470int
1471resource_set_string(int i, char *resname, char *value)
1472{
1473	int error;
1474	struct config_resource *res;
1475
1476printf("resource_set_string\n");
1477	if (i < 0 || i >= devtab_count)
1478		return EINVAL;
1479	error = resource_create(devtab[i].name, devtab[i].unit, resname,
1480				RES_STRING, &res);
1481	if (error)
1482		return error;
1483	if (res->type != RES_STRING)
1484		return EFTYPE;
1485	if (res->u.stringval)
1486		free(res->u.stringval, M_TEMP);
1487	res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT);
1488	if (res->u.stringval == NULL)
1489		return ENOMEM;
1490	strcpy(res->u.stringval, value);
1491	return 0;
1492}
1493
1494
1495static void
1496resource_cfgload(void *dummy __unused)
1497{
1498	struct config_resource *res, *cfgres;
1499	int i, j;
1500	int error;
1501	char *name, *resname;
1502	int unit;
1503	resource_type type;
1504	char *stringval;
1505	int config_devtab_count;
1506
1507	config_devtab_count = devtab_count;
1508	devtab = NULL;
1509	devtab_count = 0;
1510
1511	for (i = 0; i < config_devtab_count; i++) {
1512		name = config_devtab[i].name;
1513		unit = config_devtab[i].unit;
1514
1515		for (j = 0; j < config_devtab[i].resource_count; j++) {
1516			cfgres = config_devtab[i].resources;
1517			resname = cfgres[j].name;
1518			type = cfgres[j].type;
1519			error = resource_create(name, unit, resname, type,
1520						&res);
1521			if (error) {
1522				printf("create resource %s%d: error %d\n",
1523					name, unit, error);
1524				continue;
1525			}
1526			if (res->type != type) {
1527				printf("type mismatch %s%d: %d != %d\n",
1528					name, unit, res->type, type);
1529				continue;
1530			}
1531			switch (type) {
1532			case RES_INT:
1533				res->u.intval = cfgres[j].u.intval;
1534				break;
1535			case RES_LONG:
1536				res->u.longval = cfgres[j].u.longval;
1537				break;
1538			case RES_STRING:
1539				if (res->u.stringval)
1540					free(res->u.stringval, M_TEMP);
1541				stringval = cfgres[j].u.stringval;
1542				res->u.stringval = malloc(strlen(stringval) + 1,
1543							  M_TEMP, M_NOWAIT);
1544				if (res->u.stringval == NULL)
1545					break;
1546				strcpy(res->u.stringval, stringval);
1547				break;
1548			default:
1549				panic("unknown resource type %d\n", type);
1550			}
1551		}
1552	}
1553}
1554SYSINIT(cfgload, SI_SUB_KMEM, SI_ORDER_ANY + 50, resource_cfgload, 0)
1555
1556
1557/*======================================*/
1558/*
1559 * Some useful method implementations to make life easier for bus drivers.
1560 */
1561int
1562bus_generic_attach(device_t dev)
1563{
1564    device_t child;
1565
1566    for (child = TAILQ_FIRST(&dev->children);
1567	 child; child = TAILQ_NEXT(child, link))
1568	device_probe_and_attach(child);
1569
1570    return 0;
1571}
1572
1573int
1574bus_generic_detach(device_t dev)
1575{
1576    device_t child;
1577    int error;
1578
1579    if (dev->state != DS_ATTACHED)
1580	return EBUSY;
1581
1582    for (child = TAILQ_FIRST(&dev->children);
1583	 child; child = TAILQ_NEXT(child, link))
1584	if ((error = device_detach(child)) != 0)
1585	    return error;
1586
1587    return 0;
1588}
1589
1590int
1591bus_generic_shutdown(device_t dev)
1592{
1593    device_t child;
1594
1595    for (child = TAILQ_FIRST(&dev->children);
1596	 child; child = TAILQ_NEXT(child, link))
1597	device_shutdown(child);
1598
1599    return 0;
1600}
1601
1602int
1603bus_generic_suspend(device_t dev)
1604{
1605	int		error;
1606	device_t	child, child2;
1607
1608	for (child = TAILQ_FIRST(&dev->children);
1609	     child; child = TAILQ_NEXT(child, link)) {
1610		error = DEVICE_SUSPEND(child);
1611		if (error) {
1612			for (child2 = TAILQ_FIRST(&dev->children);
1613			     child2 && child2 != child;
1614			     child2 = TAILQ_NEXT(child2, link))
1615				DEVICE_RESUME(child2);
1616			return (error);
1617		}
1618	}
1619	return 0;
1620}
1621
1622int
1623bus_generic_resume(device_t dev)
1624{
1625	device_t	child;
1626
1627	for (child = TAILQ_FIRST(&dev->children);
1628	     child; child = TAILQ_NEXT(child, link)) {
1629		DEVICE_RESUME(child);
1630		/* if resume fails, there's nothing we can usefully do... */
1631	}
1632	return 0;
1633}
1634
1635void
1636bus_generic_print_child(device_t dev, device_t child)
1637{
1638	printf(" on %s%d", device_get_name(dev), device_get_unit(dev));
1639}
1640
1641int
1642bus_generic_read_ivar(device_t dev, device_t child, int index,
1643		      uintptr_t * result)
1644{
1645    return ENOENT;
1646}
1647
1648int
1649bus_generic_write_ivar(device_t dev, device_t child, int index,
1650		       uintptr_t value)
1651{
1652    return ENOENT;
1653}
1654
1655void
1656bus_generic_driver_added(device_t dev, driver_t *driver)
1657{
1658    device_t child;
1659
1660    for (child = TAILQ_FIRST(&dev->children);
1661	 child; child = TAILQ_NEXT(child, link))
1662	if (child->state == DS_NOTPRESENT)
1663	    device_probe_and_attach(child);
1664}
1665
1666int
1667bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
1668		       driver_intr_t *intr, void *arg, void **cookiep)
1669{
1670	/* Propagate up the bus hierarchy until someone handles it. */
1671	if (dev->parent)
1672		return (BUS_SETUP_INTR(dev->parent, child, irq, intr, arg,
1673				       cookiep));
1674	else
1675		return (EINVAL);
1676}
1677
1678int
1679bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
1680			  void *cookie)
1681{
1682	/* Propagate up the bus hierarchy until someone handles it. */
1683	if (dev->parent)
1684		return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie));
1685	else
1686		return (EINVAL);
1687}
1688
1689struct resource *
1690bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
1691			   u_long start, u_long end, u_long count, u_int flags)
1692{
1693	/* Propagate up the bus hierarchy until someone handles it. */
1694	if (dev->parent)
1695		return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid,
1696					   start, end, count, flags));
1697	else
1698		return (NULL);
1699}
1700
1701int
1702bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
1703			     struct resource *r)
1704{
1705	/* Propagate up the bus hierarchy until someone handles it. */
1706	if (dev->parent)
1707		return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid,
1708					     r));
1709	else
1710		return (EINVAL);
1711}
1712
1713int
1714bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
1715			      struct resource *r)
1716{
1717	/* Propagate up the bus hierarchy until someone handles it. */
1718	if (dev->parent)
1719		return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid,
1720					      r));
1721	else
1722		return (EINVAL);
1723}
1724
1725int
1726bus_generic_deactivate_resource(device_t dev, device_t child, int type,
1727				int rid, struct resource *r)
1728{
1729	/* Propagate up the bus hierarchy until someone handles it. */
1730	if (dev->parent)
1731		return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid,
1732						r));
1733	else
1734		return (EINVAL);
1735}
1736
1737/*
1738 * Some convenience functions to make it easier for drivers to use the
1739 * resource-management functions.  All these really do is hide the
1740 * indirection through the parent's method table, making for slightly
1741 * less-wordy code.  In the future, it might make sense for this code
1742 * to maintain some sort of a list of resources allocated by each device.
1743 */
1744struct resource *
1745bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
1746		   u_long count, u_int flags)
1747{
1748	if (dev->parent == 0)
1749		return (0);
1750	return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
1751				   count, flags));
1752}
1753
1754int
1755bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
1756{
1757	if (dev->parent == 0)
1758		return (EINVAL);
1759	return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
1760}
1761
1762int
1763bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
1764{
1765	if (dev->parent == 0)
1766		return (EINVAL);
1767	return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
1768}
1769
1770int
1771bus_release_resource(device_t dev, int type, int rid, struct resource *r)
1772{
1773	if (dev->parent == 0)
1774		return (EINVAL);
1775	return (BUS_RELEASE_RESOURCE(dev->parent, dev,
1776				     type, rid, r));
1777}
1778
1779int
1780bus_setup_intr(device_t dev, struct resource *r,
1781	       driver_intr_t handler, void *arg, void **cookiep)
1782{
1783	if (dev->parent == 0)
1784		return (EINVAL);
1785	return (BUS_SETUP_INTR(dev->parent, dev, r, handler, arg, cookiep));
1786}
1787
1788int
1789bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
1790{
1791	if (dev->parent == 0)
1792		return (EINVAL);
1793	return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
1794}
1795
1796static void
1797root_print_child(device_t dev, device_t child)
1798{
1799}
1800
1801static int
1802root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
1803		void **cookiep)
1804{
1805	/*
1806	 * If an interrupt mapping gets to here something bad has happened.
1807	 */
1808	panic("root_setup_intr");
1809}
1810
1811static device_method_t root_methods[] = {
1812	/* Device interface */
1813	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1814	DEVMETHOD(device_suspend,	bus_generic_suspend),
1815	DEVMETHOD(device_resume,	bus_generic_resume),
1816
1817	/* Bus interface */
1818	DEVMETHOD(bus_print_child,	root_print_child),
1819	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
1820	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
1821	DEVMETHOD(bus_setup_intr,	root_setup_intr),
1822
1823	{ 0, 0 }
1824};
1825
1826static driver_t root_driver = {
1827	"root",
1828	root_methods,
1829	DRIVER_TYPE_MISC,
1830	1,			/* no softc */
1831};
1832
1833device_t	root_bus;
1834devclass_t	root_devclass;
1835
1836static int
1837root_bus_module_handler(module_t mod, int what, void* arg)
1838{
1839    switch (what) {
1840    case MOD_LOAD:
1841	compile_methods(&root_driver);
1842	root_bus = make_device(NULL, "root", 0, NULL);
1843	root_bus->desc = "System root bus";
1844	root_bus->ops = root_driver.ops;
1845	root_bus->driver = &root_driver;
1846	root_bus->state = DS_ATTACHED;
1847	root_devclass = devclass_find_internal("root", FALSE);
1848	return 0;
1849
1850    case MOD_SHUTDOWN:
1851	device_shutdown(root_bus);
1852	return 0;
1853    }
1854
1855    return 0;
1856}
1857
1858static moduledata_t root_bus_mod = {
1859	"rootbus",
1860	root_bus_module_handler,
1861	0
1862};
1863DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1864
1865void
1866root_bus_configure(void)
1867{
1868    device_t dev;
1869
1870    PDEBUG(("."));
1871
1872    for (dev = TAILQ_FIRST(&root_bus->children); dev;
1873	 dev = TAILQ_NEXT(dev, link)) {
1874	device_probe_and_attach(dev);
1875    }
1876}
1877
1878int
1879driver_module_handler(module_t mod, int what, void *arg)
1880{
1881	int error, i;
1882	struct driver_module_data *dmd;
1883	devclass_t bus_devclass;
1884
1885	dmd = (struct driver_module_data *)arg;
1886	bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE);
1887	error = 0;
1888
1889	switch (what) {
1890	case MOD_LOAD:
1891		for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
1892			PDEBUG(("Loading module: driver %s on bus %s",
1893				DRIVERNAME(dmd->dmd_drivers[i]),
1894				dmd->dmd_busname));
1895			error = devclass_add_driver(bus_devclass,
1896						    dmd->dmd_drivers[i]);
1897		}
1898		if (error)
1899			break;
1900
1901		/*
1902		 * The drivers loaded in this way are assumed to all
1903		 * implement the same devclass.
1904		 */
1905		*dmd->dmd_devclass =
1906			devclass_find_internal(dmd->dmd_drivers[0]->name,
1907					       TRUE);
1908		break;
1909
1910	case MOD_UNLOAD:
1911		for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
1912			PDEBUG(("Unloading module: driver %s from bus %s",
1913				DRIVERNAME(dmd->dmd_drivers[i]),
1914				dmd->dmd_busname));
1915			error = devclass_delete_driver(bus_devclass,
1916						       dmd->dmd_drivers[i]);
1917		}
1918		break;
1919	}
1920
1921	if (!error && dmd->dmd_chainevh)
1922		error = dmd->dmd_chainevh(mod, what, dmd->dmd_chainarg);
1923	return (error);
1924}
1925
1926#ifdef BUS_DEBUG
1927
1928/* the _short versions avoid iteration by not calling anything that prints
1929 * more than oneliners. I love oneliners.
1930 */
1931
1932static void
1933print_method_list(device_method_t *m, int indent)
1934{
1935	int i;
1936
1937	if (!m)
1938		return;
1939
1940	for (i = 0; m->desc; i++, m++)
1941		indentprintf(("method %d: %s, offset=%d\n",
1942			i, m->desc->name, m->desc->offset));
1943}
1944
1945static void
1946print_device_ops(device_ops_t ops, int indent)
1947{
1948	int i;
1949	int count = 0;
1950
1951	if (!ops)
1952		return;
1953
1954	/* we present a list of the methods that are pointing to the
1955	 * error_method, but ignore the 0'th elements; it is always
1956	 * error_method.
1957	 */
1958	for (i = 1; i < ops->maxoffset; i++) {
1959		if (ops->methods[i] == error_method) {
1960			if (count == 0)
1961				indentprintf(("error_method:"));
1962			printf(" %d", i);
1963			count++;
1964		}
1965	}
1966	if (count)
1967		printf("\n");
1968
1969	indentprintf(("(%d method%s, %d valid, %d error_method%s)\n",
1970		ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"),
1971		ops->maxoffset-1-count,
1972		count, (count == 1? "":"'s")));
1973}
1974
1975static void
1976print_device_short(device_t dev, int indent)
1977{
1978	if (!dev)
1979		return;
1980
1981	indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%sivars,%ssoftc,busy=%d\n",
1982		dev->unit, dev->desc,
1983		(dev->parent? "":"no "),
1984		(TAILQ_EMPTY(&dev->children)? "no ":""),
1985		(dev->flags&DF_ENABLED? "enabled,":"disabled,"),
1986		(dev->flags&DF_FIXEDCLASS? "fixed,":""),
1987		(dev->flags&DF_WILDCARD? "wildcard,":""),
1988		(dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
1989		(dev->ivars? "":"no "),
1990		(dev->softc? "":"no "),
1991		dev->busy));
1992}
1993
1994static void
1995print_device(device_t dev, int indent)
1996{
1997	if (!dev)
1998		return;
1999
2000	print_device_short(dev, indent);
2001
2002	indentprintf(("Parent:\n"));
2003	print_device_short(dev->parent, indent+1);
2004	indentprintf(("Methods:\n"));
2005	print_device_ops(dev->ops, indent+1);
2006	indentprintf(("Driver:\n"));
2007	print_driver_short(dev->driver, indent+1);
2008	indentprintf(("Devclass:\n"));
2009	print_devclass_short(dev->devclass, indent+1);
2010}
2011
2012void
2013print_device_tree_short(device_t dev, int indent)
2014/* print the device and all its children (indented) */
2015{
2016	device_t child;
2017
2018	if (!dev)
2019		return;
2020
2021	print_device_short(dev, indent);
2022
2023	for (child = TAILQ_FIRST(&dev->children); child;
2024		 child = TAILQ_NEXT(child, link))
2025		print_device_tree_short(child, indent+1);
2026}
2027
2028void
2029print_device_tree(device_t dev, int indent)
2030/* print the device and all its children (indented) */
2031{
2032	device_t child;
2033
2034	if (!dev)
2035		return;
2036
2037	print_device(dev, indent);
2038
2039	for (child = TAILQ_FIRST(&dev->children); child;
2040		 child = TAILQ_NEXT(child, link))
2041		print_device_tree(child, indent+1);
2042}
2043
2044static void
2045print_driver_short(driver_t *driver, int indent)
2046{
2047	if (!driver)
2048		return;
2049
2050	indentprintf(("driver %s: type = %s%s%s%s, softc size = %d\n",
2051		driver->name,
2052		/* yes, I know this looks silly, but going to bed at
2053		 * two o'clock and having to get up at 7:30 again is silly
2054		 * as well. As is sticking your head in a bucket of water.
2055		 */
2056		(driver->type == DRIVER_TYPE_TTY? "tty":""),
2057		(driver->type == DRIVER_TYPE_BIO? "bio":""),
2058		(driver->type == DRIVER_TYPE_NET? "net":""),
2059		(driver->type == DRIVER_TYPE_MISC? "misc":""),
2060		driver->softc));
2061}
2062
2063static void
2064print_driver(driver_t *driver, int indent)
2065{
2066	if (!driver)
2067		return;
2068
2069	print_driver_short(driver, indent);
2070	indentprintf(("Methods:\n"));
2071	print_method_list(driver->methods, indent+1);
2072	indentprintf(("Operations:\n"));
2073	print_device_ops(driver->ops, indent+1);
2074}
2075
2076
2077static void
2078print_driver_list(driver_list_t drivers, int indent)
2079{
2080	driver_t *driver;
2081
2082	for (driver = TAILQ_FIRST(&drivers); driver;
2083	     driver = TAILQ_NEXT(driver, link))
2084		print_driver(driver, indent);
2085}
2086
2087static void
2088print_devclass_short(devclass_t dc, int indent)
2089{
2090	if ( !dc )
2091		return;
2092
2093	indentprintf(("devclass %s: max units = %d, next unit = %d\n",
2094		dc->name, dc->maxunit, dc->nextunit));
2095}
2096
2097static void
2098print_devclass(devclass_t dc, int indent)
2099{
2100	int i;
2101
2102	if ( !dc )
2103		return;
2104
2105	print_devclass_short(dc, indent);
2106	indentprintf(("Drivers:\n"));
2107	print_driver_list(dc->drivers, indent+1);
2108
2109	indentprintf(("Devices:\n"));
2110	for (i = 0; i < dc->maxunit; i++)
2111		if (dc->devices[i])
2112			print_device(dc->devices[i], indent+1);
2113}
2114
2115void
2116print_devclass_list_short(void)
2117{
2118	devclass_t dc;
2119
2120	printf("Short listing of devclasses, drivers & devices:\n");
2121	for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
2122		print_devclass_short(dc, 0);
2123}
2124
2125void
2126print_devclass_list(void)
2127{
2128	devclass_t dc;
2129
2130	printf("Full listing of devclasses, drivers & devices:\n");
2131	for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
2132		print_devclass(dc, 0);
2133}
2134
2135#endif
2136