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