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