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