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