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