subr_bus.c revision 40671
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.7 1998/10/25 17:44:51 phk 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/bus_private.h>
35#include <sys/systm.h>
36
37#include "opt_bus.h"
38
39#ifdef BUS_DEBUG
40#define PDEBUG(a)	(printf(__FUNCTION__ ":%d: ", __LINE__), printf a, printf("\n"))
41#define DEVICENAME(d)	((d)? device_get_name(d): "no device")
42#define DRIVERNAME(d)	((d)? d->name : "no driver")
43#define DEVCLANAME(d)	((d)? d->name : "no devclass")
44
45/* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
46 * prevent syslog from deleting initial spaces
47 */
48#define indentprintf(p)	do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while(0)
49
50static void print_method_list(device_method_t *m, int indent);
51static void print_device_ops(device_ops_t ops, int indent);
52static void print_device_short(device_t dev, int indent);
53static void print_device(device_t dev, int indent);
54void print_device_tree_short(device_t dev, int indent);
55void print_device_tree(device_t dev, int indent);
56static void print_driver_short(driver_t *driver, int indent);
57static void print_driver(driver_t *driver, int indent);
58static void print_driver_list(driver_list_t drivers, int indent);
59static void print_devclass_short(devclass_t dc, int indent);
60static void print_devclass(devclass_t dc, int indent);
61void print_devclass_list_short(void);
62void print_devclass_list(void);
63
64#else
65/* Make the compiler ignore the function calls */
66#define PDEBUG(a)			/* nop */
67#define DEVICENAME(d)			/* nop */
68#define DRIVERNAME(d)			/* nop */
69#define DEVCLANAME(d)			/* nop */
70
71#define print_method_list(m,i)		/* nop */
72#define print_device_ops(o,i)		/* nop */
73#define print_device_short(d,i)		/* nop */
74#define print_device(d,i)		/* nop */
75#define print_device_tree_short(d,i)	/* nop */
76#define print_device_tree(d,i)		/* nop */
77#define print_driver_short(d,i)		/* nop */
78#define print_driver(d,i)		/* nop */
79#define print_driver_list(d,i)		/* nop */
80#define print_devclass_short(d,i)	/* nop */
81#define print_devclass(d,i)		/* nop */
82#define print_devclass_list_short()	/* nop */
83#define print_devclass_list()		/* nop */
84#endif
85
86
87/*
88 * Method table handling
89 */
90static int next_method_offset = 1;
91static int methods_count = 0;
92static int methods_size = 0;
93
94struct method {
95    int offset;
96    char* name;
97};
98
99static struct method *methods = 0;
100
101static void
102register_method(struct device_op_desc *desc)
103{
104    int i;
105    struct method* m;
106
107    for (i = 0; i < methods_count; i++)
108	if (!strcmp(methods[i].name, desc->name)) {
109	    desc->offset = methods[i].offset;
110	    PDEBUG(("methods[%d] has the same name, %s, with offset %d",
111	    		i, desc->name, desc->offset));
112	    return;
113	}
114
115    if (methods_count == methods_size) {
116	struct method* p;
117
118	methods_size += 10;
119	p = (struct method*) malloc(methods_size * sizeof(struct method),
120				     M_DEVBUF, M_NOWAIT);
121	if (!p)
122	    panic("register_method: out of memory");
123	if (methods) {
124	    bcopy(methods, p, methods_count * sizeof(struct method));
125	    free(methods, M_DEVBUF);
126	}
127	methods = p;
128    }
129    m = &methods[methods_count++];
130    m->name = malloc(strlen(desc->name) + 1, M_DEVBUF, M_NOWAIT);
131    if (!m->name)
132	    panic("register_method: out of memory");
133    strcpy(m->name, desc->name);
134    desc->offset = m->offset = next_method_offset++;
135}
136
137static int error_method(void)
138{
139    return ENXIO;
140}
141
142static struct device_ops null_ops = {
143    1,
144    { error_method }
145};
146
147static void
148compile_methods(driver_t *driver)
149{
150    device_ops_t ops;
151    struct device_method *m;
152    int i;
153
154    /*
155     * First register any methods which need it.
156     */
157    for (i = 0, m = driver->methods; m->desc; i++, m++)
158	if (!m->desc->offset)
159	    register_method(m->desc);
160	else
161	    PDEBUG(("offset not equal to zero, method desc %d left as is", i));
162
163    /*
164     * Then allocate the compiled op table.
165     */
166    ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),
167		 M_DEVBUF, M_NOWAIT);
168    if (!ops)
169	panic("compile_methods: out of memory");
170
171    ops->maxoffset = next_method_offset;
172    for (i = 0; i < next_method_offset; i++)
173	ops->methods[i] = error_method;
174    for (i = 0, m = driver->methods; m->desc; i++, m++)
175	ops->methods[m->desc->offset] = m->func;
176    PDEBUG(("%s has %d method%s, wasting %d bytes",
177    		DRIVERNAME(driver), i, (i==1?"":"s"),
178		(next_method_offset-i)*sizeof(devop_t)));
179
180    driver->ops = ops;
181}
182
183/*
184 * Devclass implementation
185 */
186
187static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
188
189static devclass_t
190devclass_find_internal(const char *classname, int create)
191{
192    devclass_t dc;
193
194    PDEBUG(("looking for %s", classname));
195    if (!classname)
196	return NULL;
197
198    for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
199	if (!strcmp(dc->name, classname))
200	    return dc;
201
202    PDEBUG(("%s not found%s", classname, (create? ", creating": "")));
203    if (create) {
204	dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
205		    M_DEVBUF, M_NOWAIT);
206	if (!dc)
207	    return NULL;
208	dc->name = (char*) (dc + 1);
209	strcpy(dc->name, classname);
210	dc->devices = NULL;
211	dc->maxunit = 0;
212	dc->nextunit = 0;
213	TAILQ_INIT(&dc->drivers);
214	TAILQ_INSERT_TAIL(&devclasses, dc, link);
215    }
216
217    return dc;
218}
219
220devclass_t
221devclass_find(const char *classname)
222{
223    return devclass_find_internal(classname, FALSE);
224}
225
226int
227devclass_add_driver(devclass_t dc, driver_t *driver)
228{
229    PDEBUG(("%s", DRIVERNAME(driver)));
230    /*
231     * Compile the drivers methods.
232     */
233    compile_methods(driver);
234
235    /*
236     * Make sure the devclass which the driver is implementing exists.
237     */
238    devclass_find_internal(driver->name, TRUE);
239
240    TAILQ_INSERT_TAIL(&dc->drivers, driver, link);
241
242    return 0;
243}
244
245int
246devclass_delete_driver(devclass_t busclass, driver_t *driver)
247{
248    devclass_t dc = devclass_find(driver->name);
249    device_t dev;
250    int i;
251    int error;
252
253    PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
254
255    if (!dc)
256	return 0;
257
258    /*
259     * Disassociate from any devices.  We iterate through all the
260     * devices in the devclass of the driver and detach any which are
261     * using the driver.
262     */
263    for (i = 0; i < dc->maxunit; i++) {
264	if (dc->devices[i]) {
265	    dev = dc->devices[i];
266	    if (dev->driver == driver) {
267		if (error = device_detach(dev))
268		    return error;
269		device_set_driver(dev, NULL);
270	    }
271	}
272    }
273
274    TAILQ_REMOVE(&busclass->drivers, driver, link);
275    return 0;
276}
277
278driver_t *
279devclass_find_driver(devclass_t dc, const char *classname)
280{
281    driver_t *driver;
282
283    PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
284
285    for (driver = TAILQ_FIRST(&dc->drivers); driver;
286	 driver = TAILQ_NEXT(driver, link)) {
287	if (!strcmp(driver->name, classname))
288	    return driver;
289    }
290
291    PDEBUG(("not found"));
292    return NULL;
293}
294
295const char *
296devclass_get_name(devclass_t dc)
297{
298    return dc->name;
299}
300
301device_t
302devclass_get_device(devclass_t dc, int unit)
303{
304    if (unit < 0 || unit >= dc->maxunit)
305	return NULL;
306    return dc->devices[unit];
307}
308
309void *
310devclass_get_softc(devclass_t dc, int unit)
311{
312    device_t dev;
313
314    if (unit < 0 || unit >= dc->maxunit)
315	return NULL;
316    dev = dc->devices[unit];
317    if (!dev || dev->state < DS_ATTACHED)
318	return NULL;
319    return dev->softc;
320}
321
322int
323devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
324{
325    int i;
326    int count;
327    device_t *list;
328
329    count = 0;
330    for (i = 0; i < dc->maxunit; i++)
331	if (dc->devices[i])
332	    count++;
333
334    list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
335    if (!list)
336	return ENOMEM;
337
338    count = 0;
339    for (i = 0; i < dc->maxunit; i++)
340	if (dc->devices[i]) {
341	    list[count] = dc->devices[i];
342	    count++;
343	}
344
345    *devlistp = list;
346    *devcountp = count;
347
348    return 0;
349}
350
351int
352devclass_get_maxunit(devclass_t dc)
353{
354    return dc->maxunit;
355}
356
357static int
358devclass_alloc_unit(devclass_t dc, int *unitp)
359{
360    int unit = *unitp;
361
362    PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
363
364    /*
365     * If we have been given a wired unit number, check for existing
366     * device.
367     */
368    if (unit != -1) {
369	device_t dev;
370	dev = devclass_get_device(dc, unit);
371	if (dev) {
372	    printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit);
373	    unit = -1;
374	}
375    }
376
377    if (unit == -1) {
378	unit = dc->nextunit;
379	dc->nextunit++;
380    } else if (dc->nextunit <= unit)
381	dc->nextunit = unit + 1;
382
383    if (unit >= dc->maxunit) {
384	device_t *newlist;
385	int newsize;
386
387	newsize = (dc->maxunit ? 2 * dc->maxunit
388		   : MINALLOCSIZE / sizeof(device_t));
389	newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT);
390	if (!newlist)
391	    return ENOMEM;
392	bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
393	bzero(newlist + dc->maxunit,
394	      sizeof(device_t) * (newsize - dc->maxunit));
395	if (dc->devices)
396	    free(dc->devices, M_DEVBUF);
397	dc->devices = newlist;
398	dc->maxunit = newsize;
399    }
400    PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
401
402    *unitp = unit;
403    return 0;
404}
405
406static int
407devclass_add_device(devclass_t dc, device_t dev)
408{
409    int error;
410
411    PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
412
413    if (error = devclass_alloc_unit(dc, &dev->unit))
414	return error;
415    dc->devices[dev->unit] = dev;
416    dev->devclass = dc;
417    return 0;
418}
419
420static int
421devclass_delete_device(devclass_t dc, device_t dev)
422{
423    PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
424
425    if (dev->devclass != dc
426	|| dc->devices[dev->unit] != dev)
427	panic("devclass_delete_device: inconsistent device class");
428    dc->devices[dev->unit] = NULL;
429    if (dev->flags & DF_WILDCARD)
430	dev->unit = -1;
431    dev->devclass = NULL;
432    while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL)
433	dc->nextunit--;
434    return 0;
435}
436
437static device_t
438make_device(device_t parent, const char *name,
439	    int unit, void *ivars)
440{
441    device_t dev;
442    devclass_t dc;
443    int error;
444
445    PDEBUG(("%s at %s as unit %d with%s ivars",
446    	    name, DEVICENAME(parent), unit, (ivars? "":"out")));
447
448    if (name) {
449	dc = devclass_find_internal(name, TRUE);
450	if (!dc) {
451	    printf("make_device: can't find device class %s\n", name);
452	    return NULL;
453	}
454
455	if (error = devclass_alloc_unit(dc, &unit))
456	    return NULL;
457    } else
458	dc = NULL;
459
460    dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT);
461    if (!dev)
462	return 0;
463
464    dev->parent = parent;
465    TAILQ_INIT(&dev->children);
466    dev->ops = &null_ops;
467    dev->driver = NULL;
468    dev->devclass = dc;
469    dev->unit = unit;
470    dev->desc = NULL;
471    dev->busy = 0;
472    dev->flags = DF_ENABLED;
473    if (unit == -1)
474	dev->flags |= DF_WILDCARD;
475    if (name)
476	dev->flags |= DF_FIXEDCLASS;
477    dev->ivars = ivars;
478    dev->softc = NULL;
479
480    if (dc)
481	dc->devices[unit] = dev;
482
483    dev->state = DS_NOTPRESENT;
484
485    return dev;
486}
487
488static void
489device_print_child(device_t dev, device_t child)
490{
491    printf("%s%d", device_get_name(child), device_get_unit(child));
492    if (device_is_alive(child)) {
493	if (device_get_desc(child))
494	    printf(": <%s>", device_get_desc(child));
495	BUS_PRINT_CHILD(dev, child);
496    } else
497	printf(" not found");
498    printf("\n");
499}
500
501device_t
502device_add_child(device_t dev, const char *name, int unit, void *ivars)
503{
504    device_t child;
505
506    PDEBUG(("%s at %s as unit %d with%s ivars",
507    	    name, DEVICENAME(dev), unit, (ivars? "":"out")));
508
509    child = make_device(dev, name, unit, ivars);
510
511    TAILQ_INSERT_TAIL(&dev->children, child, link);
512
513    return child;
514}
515
516device_t
517device_add_child_after(device_t dev, device_t place, const char *name,
518		       int unit, void *ivars)
519{
520    device_t child;
521
522    PDEBUG(("%s at %s after %s as unit %d with%s ivars",
523    	    name, DEVICENAME(dev), DEVICENAME(place), unit, (ivars? "":"out")));
524
525    child = make_device(dev, name, unit, ivars);
526
527    if (place) {
528	TAILQ_INSERT_AFTER(&dev->children, place, dev, link);
529    } else {
530	TAILQ_INSERT_HEAD(&dev->children, dev, link);
531    }
532
533    return child;
534}
535
536int
537device_delete_child(device_t dev, device_t child)
538{
539    int error;
540
541    PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
542
543    if (error = device_detach(child))
544	return error;
545    if (child->devclass)
546	devclass_delete_device(child->devclass, child);
547    TAILQ_REMOVE(&dev->children, child, link);
548    free(dev, M_DEVBUF);
549
550    return 0;
551}
552
553/*
554 * Find only devices attached to this bus.
555 */
556device_t
557device_find_child(device_t dev, const char *classname, int unit)
558{
559    devclass_t dc;
560    device_t child;
561
562    dc = devclass_find(classname);
563    if (!dc)
564	return NULL;
565
566    child = devclass_get_device(dc, unit);
567    if (child && child->parent == dev)
568	return child;
569    return NULL;
570}
571
572static driver_t *
573first_matching_driver(devclass_t dc, device_t dev)
574{
575    if (dev->devclass)
576	return devclass_find_driver(dc, dev->devclass->name);
577    else
578	return TAILQ_FIRST(&dc->drivers);
579}
580
581static driver_t *
582next_matching_driver(devclass_t dc, device_t dev, driver_t *last)
583{
584    if (dev->devclass) {
585	driver_t *driver;
586	for (driver = TAILQ_NEXT(last, link); driver;
587	     driver = TAILQ_NEXT(driver, link))
588	    if (!strcmp(dev->devclass->name, driver->name))
589		return driver;
590	return NULL;
591    } else
592	return TAILQ_NEXT(last, link);
593}
594
595static int
596device_probe_child(device_t dev, device_t child)
597{
598    devclass_t dc;
599    driver_t *driver;
600
601    dc = dev->devclass;
602    if (dc == NULL)
603	panic("device_probe_child: parent device has no devclass");
604
605    if (child->state == DS_ALIVE)
606	return 0;
607
608    for (driver = first_matching_driver(dc, child);
609	 driver;
610	 driver = next_matching_driver(dc, child, driver)) {
611	PDEBUG(("Trying %s", DRIVERNAME(driver)));
612	device_set_driver(child, driver);
613	if (DEVICE_PROBE(child) == 0) {
614	    if (!child->devclass)
615		device_set_devclass(child, driver->name);
616	    child->state = DS_ALIVE;
617	    return 0;
618	}
619    }
620
621    return ENXIO;
622}
623
624device_t
625device_get_parent(device_t dev)
626{
627    return dev->parent;
628}
629
630driver_t *
631device_get_driver(device_t dev)
632{
633    return dev->driver;
634}
635
636devclass_t
637device_get_devclass(device_t dev)
638{
639    return dev->devclass;
640}
641
642const char *
643device_get_name(device_t dev)
644{
645    if (dev->devclass)
646	return devclass_get_name(dev->devclass);
647    return NULL;
648}
649
650int
651device_get_unit(device_t dev)
652{
653    return dev->unit;
654}
655
656const char *
657device_get_desc(device_t dev)
658{
659    return dev->desc;
660}
661
662void
663device_set_desc(device_t dev, const char* desc)
664{
665    dev->desc = desc;
666}
667
668void *
669device_get_softc(device_t dev)
670{
671    return dev->softc;
672}
673
674void *
675device_get_ivars(device_t dev)
676{
677    return dev->ivars;
678}
679
680device_state_t
681device_get_state(device_t dev)
682{
683    return dev->state;
684}
685
686void
687device_enable(device_t dev)
688{
689    dev->flags |= DF_ENABLED;
690}
691
692void
693device_disable(device_t dev)
694{
695    dev->flags &= ~DF_ENABLED;
696}
697
698void
699device_busy(device_t dev)
700{
701    if (dev->state < DS_ATTACHED)
702	panic("device_busy: called for unattached device");
703    if (dev->busy == 0 && dev->parent)
704	device_busy(dev->parent);
705    dev->busy++;
706    dev->state = DS_BUSY;
707}
708
709void
710device_unbusy(device_t dev)
711{
712    if (dev->state != DS_BUSY)
713	panic("device_unbusy: called for non-busy device");
714    dev->busy--;
715    if (dev->busy == 0) {
716	if (dev->parent)
717	    device_unbusy(dev->parent);
718	dev->state = DS_ATTACHED;
719    }
720}
721
722int
723device_is_enabled(device_t dev)
724{
725    return (dev->flags & DF_ENABLED) != 0;
726}
727
728int
729device_is_alive(device_t dev)
730{
731    return dev->state >= DS_ALIVE;
732}
733
734int
735device_set_devclass(device_t dev, const char *classname)
736{
737    devclass_t dc;
738
739    if (dev->devclass) {
740	printf("device_set_devclass: device class already set\n");
741	return EINVAL;
742    }
743
744    dc = devclass_find_internal(classname, TRUE);
745    if (!dc)
746	return ENOMEM;
747
748    return devclass_add_device(dc, dev);
749}
750
751int
752device_set_driver(device_t dev, driver_t *driver)
753{
754    if (dev->state >= DS_ATTACHED)
755	return EBUSY;
756
757    if (dev->driver == driver)
758	return 0;
759
760    if (dev->softc) {
761	free(dev->softc, M_DEVBUF);
762	dev->softc = NULL;
763    }
764    dev->ops = &null_ops;
765    dev->driver = driver;
766    if (driver) {
767	dev->ops = driver->ops;
768	dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT);
769	if (!dev->softc) {
770	    dev->ops = &null_ops;
771	    dev->driver = NULL;
772	    return ENOMEM;
773	}
774	bzero(dev->softc, driver->softc);
775    }
776    return 0;
777}
778
779int
780device_probe_and_attach(device_t dev)
781{
782    device_t bus = dev->parent;
783    int error;
784
785    if (dev->state >= DS_ALIVE)
786	return 0;
787
788    if (dev->flags & DF_ENABLED) {
789	device_probe_child(bus, dev);
790	device_print_child(bus, dev);
791	if (dev->state == DS_ALIVE) {
792	    error = DEVICE_ATTACH(dev);
793	    if (!error)
794		dev->state = DS_ATTACHED;
795	    else {
796		printf("device_probe_and_attach: %s%d attach returned %d\n",
797		       dev->driver->name, dev->unit, error);
798		device_set_driver(dev, NULL);
799		dev->state = DS_NOTPRESENT;
800	    }
801	}
802    } else
803	printf("%s%d: disabled, not probed.\n",
804	       dev->devclass->name, dev->unit);
805
806    return 0;
807}
808
809int
810device_detach(device_t dev)
811{
812    int error;
813
814    PDEBUG(("%s", DEVICENAME(dev)));
815    if (dev->state == DS_BUSY)
816	return EBUSY;
817    if (dev->state != DS_ATTACHED)
818	return 0;
819
820    if (error = DEVICE_DETACH(dev))
821	    return error;
822
823    if (!(dev->flags & DF_FIXEDCLASS))
824	devclass_delete_device(dev->devclass, dev);
825
826    dev->state = DS_NOTPRESENT;
827    device_set_driver(dev, NULL);
828
829    return 0;
830}
831
832int
833device_shutdown(device_t dev)
834{
835    if (dev->state < DS_ATTACHED)
836	return 0;
837    return DEVICE_SHUTDOWN(dev);
838}
839
840/*
841 * Access functions for device resources.
842 */
843extern struct config_device devtab[];
844extern int devtab_count;
845
846static int
847resource_match_string(int i, char *resname, char *value)
848{
849	int j;
850	struct resource *res;
851
852	for (j = 0, res = devtab[i].resources;
853	     j < devtab[i].resource_count; j++, res++)
854		if (!strcmp(res->name, resname)
855		    && res->type == RES_STRING
856		    && !strcmp(res->u.stringval, value))
857			return TRUE;
858	return FALSE;
859}
860
861static int
862resource_find(const char *name, int unit, char *resname, struct resource **result)
863{
864	int i, j;
865	struct resource *res;
866
867	/*
868	 * First check specific instances, then generic.
869	 */
870	for (i = 0; i < devtab_count; i++) {
871		if (devtab[i].unit < 0)
872			continue;
873		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
874			res = devtab[i].resources;
875			for (j = 0; j < devtab[i].resource_count; j++, res++)
876				if (!strcmp(res->name, resname)) {
877					*result = res;
878					return 0;
879				}
880		}
881	}
882	for (i = 0; i < devtab_count; i++) {
883		if (devtab[i].unit >= 0)
884			continue;
885		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
886			res = devtab[i].resources;
887			for (j = 0; j < devtab[i].resource_count; j++, res++)
888				if (!strcmp(res->name, resname)) {
889					*result = res;
890					return 0;
891				}
892		}
893	}
894	return ENOENT;
895}
896
897int
898resource_int_value(const char *name, int unit, char *resname, int *result)
899{
900	int error;
901	struct resource *res;
902	if ((error = resource_find(name, unit, resname, &res)) != 0)
903		return error;
904	if (res->type != RES_INT)
905		return EFTYPE;
906	*result = res->u.intval;
907	return 0;
908}
909
910int
911resource_long_value(const char *name, int unit, char *resname, long *result)
912{
913	int error;
914	struct resource *res;
915	if ((error = resource_find(name, unit, resname, &res)) != 0)
916		return error;
917	if (res->type != RES_LONG)
918		return EFTYPE;
919	*result = res->u.longval;
920	return 0;
921}
922
923int
924resource_string_value(const char *name, int unit, char *resname, char **result)
925{
926	int error;
927	struct resource *res;
928	if ((error = resource_find(name, unit, resname, &res)) != 0)
929		return error;
930	if (res->type != RES_STRING)
931		return EFTYPE;
932	*result = res->u.stringval;
933	return 0;
934}
935
936int
937resource_query_string(int i, char *resname, char *value)
938{
939	if (i < 0)
940		i = 0;
941	else
942		i = i + 1;
943	for (; i < devtab_count; i++)
944		if (resource_match_string(i, resname, value))
945			return i;
946	return -1;
947}
948
949char *
950resource_query_name(int i)
951{
952	return devtab[i].name;
953}
954
955int
956resource_query_unit(int i)
957{
958	return devtab[i].unit;
959}
960
961
962/*
963 * Some useful method implementations to make life easier for bus drivers.
964 */
965int
966bus_generic_attach(device_t dev)
967{
968    device_t child;
969
970    for (child = TAILQ_FIRST(&dev->children);
971	 child; child = TAILQ_NEXT(child, link))
972	device_probe_and_attach(child);
973
974    return 0;
975}
976
977int
978bus_generic_detach(device_t dev)
979{
980    device_t child;
981    int error;
982
983    if (dev->state != DS_ATTACHED)
984	return EBUSY;
985
986    for (child = TAILQ_FIRST(&dev->children);
987	 child; child = TAILQ_NEXT(child, link))
988	if (error = device_detach(child))
989	    return error;
990
991    return 0;
992}
993
994int
995bus_generic_shutdown(device_t dev)
996{
997    device_t child;
998
999    for (child = TAILQ_FIRST(&dev->children);
1000	 child; child = TAILQ_NEXT(child, link))
1001	DEVICE_SHUTDOWN(child);
1002
1003    return 0;
1004}
1005
1006void
1007bus_generic_print_child(device_t dev, device_t child)
1008{
1009}
1010
1011int
1012bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result)
1013{
1014    return ENOENT;
1015}
1016
1017int
1018bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value)
1019{
1020    return ENOENT;
1021}
1022
1023void *
1024bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg)
1025{
1026    /* Propagate up the bus hierarchy until someone handles it. */
1027    if (dev->parent)
1028	return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg);
1029    else
1030	return NULL;
1031}
1032
1033int
1034bus_generic_connect_intr(device_t dev, void *ih)
1035{
1036    /* Propagate up the bus hierarchy until someone handles it. */
1037    if (dev->parent)
1038	return BUS_CONNECT_INTR(dev->parent, ih);
1039    else
1040	return EINVAL;
1041}
1042
1043static int root_create_intr(device_t dev, device_t child,
1044			    driver_intr_t *intr, void *arg)
1045{
1046    /*
1047     * If an interrupt mapping gets to here something bad has happened.
1048     * Should probably panic.
1049     */
1050    return EINVAL;
1051}
1052
1053static device_method_t root_methods[] = {
1054	/* Bus interface */
1055	DEVMETHOD(bus_print_child,	bus_generic_print_child),
1056	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
1057	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
1058	DEVMETHOD(bus_create_intr,	root_create_intr),
1059
1060	{ 0, 0 }
1061};
1062
1063static driver_t root_driver = {
1064	"root",
1065	root_methods,
1066	DRIVER_TYPE_MISC,
1067	1,			/* no softc */
1068};
1069
1070device_t root_bus;
1071devclass_t root_devclass;
1072
1073static int
1074root_bus_module_handler(module_t mod, modeventtype_t what, void* arg)
1075{
1076    switch (what) {
1077    case MOD_LOAD:
1078	compile_methods(&root_driver);
1079	root_bus = make_device(NULL, "root", 0, NULL);
1080	root_bus->desc = "System root bus";
1081	root_bus->ops = root_driver.ops;
1082	root_bus->driver = &root_driver;
1083	root_bus->state = DS_ATTACHED;
1084	root_devclass = devclass_find_internal("root", FALSE);
1085	return 0;
1086    }
1087
1088    return 0;
1089}
1090
1091static moduledata_t root_bus_mod = {
1092	"rootbus",
1093	root_bus_module_handler,
1094	0
1095};
1096DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1097
1098void
1099root_bus_configure()
1100{
1101    device_t dev;
1102
1103    PDEBUG(("."));
1104
1105    for (dev = TAILQ_FIRST(&root_bus->children); dev;
1106	 dev = TAILQ_NEXT(dev, link)) {
1107	device_probe_and_attach(dev);
1108    }
1109}
1110
1111int
1112driver_module_handler(module_t mod, modeventtype_t what, void* arg)
1113{
1114    struct driver_module_data* data = (struct driver_module_data*) arg;
1115    devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE);
1116    int error;
1117
1118    switch (what) {
1119    case MOD_LOAD:
1120    	PDEBUG(("Loading module: driver %s on bus %s",
1121		DRIVERNAME(data->driver), data->busname));
1122	if (error = devclass_add_driver(bus_devclass,
1123					data->driver))
1124	    return error;
1125	*data->devclass =
1126	    devclass_find_internal(data->driver->name, TRUE);
1127	break;
1128
1129    case MOD_UNLOAD:
1130    	PDEBUG(("Unloading module: driver %s from bus %s",
1131		DRIVERNAME(data->driver), data->busname));
1132	if (error = devclass_delete_driver(bus_devclass,
1133					   data->driver))
1134	    return error;
1135	break;
1136    }
1137
1138    if (data->chainevh)
1139	return data->chainevh(mod, what, data->chainarg);
1140    else
1141	return 0;
1142}
1143
1144
1145
1146#ifdef BUS_DEBUG
1147
1148/* the _short versions avoid iteration by not calling anything that prints
1149 * more than oneliners. I love oneliners.
1150 */
1151
1152static void
1153print_method_list(device_method_t *m, int indent)
1154{
1155	int i;
1156
1157	if (!m)
1158		return;
1159
1160	for (i = 0; m->desc; i++, m++)
1161		indentprintf(("method %d: %s, offset=%d\n",
1162			i, m->desc->name, m->desc->offset));
1163}
1164
1165static void
1166print_device_ops(device_ops_t ops, int indent)
1167{
1168	int i;
1169	int count = 0;
1170
1171	if (!ops)
1172		return;
1173
1174	/* we present a list of the methods that are pointing to the
1175	 * error_method, but ignore the 0'th elements; it is always
1176	 * error_method.
1177	 */
1178	for (i = 1; i < ops->maxoffset; i++) {
1179		if (ops->methods[i] == error_method) {
1180			if (count == 0)
1181				indentprintf(("error_method:"));
1182			printf(" %d", i);
1183			count++;
1184		}
1185	}
1186	if (count)
1187		printf("\n");
1188
1189	indentprintf(("(%d method%s, %d valid, %d error_method%s)\n",
1190		ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"),
1191		ops->maxoffset-1-count,
1192		count, (count == 1? "":"'s")));
1193}
1194
1195static void
1196print_device_short(device_t dev, int indent)
1197{
1198	if (!dev)
1199		return;
1200
1201	indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%sivars,%ssoftc,busy=%d\n",
1202		dev->unit, dev->desc,
1203		(dev->parent? "":"no "),
1204		(TAILQ_EMPTY(&dev->children)? "no ":""),
1205		(dev->flags&DF_ENABLED? "enabled,":"disabled,"),
1206		(dev->flags&DF_FIXEDCLASS? "fixed,":""),
1207		(dev->flags&DF_WILDCARD? "wildcard,":""),
1208		(dev->ivars? "":"no "),
1209		(dev->softc? "":"no "),
1210		dev->busy));
1211}
1212
1213static void
1214print_device(device_t dev, int indent)
1215{
1216	if (!dev)
1217		return;
1218
1219	print_device_short(dev, indent);
1220
1221	indentprintf(("Parent:\n"));
1222	print_device_short(dev->parent, indent+1);
1223	indentprintf(("Methods:\n"));
1224	print_device_ops(dev->ops, indent+1);
1225	indentprintf(("Driver:\n"));
1226	print_driver_short(dev->driver, indent+1);
1227	indentprintf(("Devclass:\n"));
1228	print_devclass_short(dev->devclass, indent+1);
1229}
1230
1231void
1232print_device_tree_short(device_t dev, int indent)
1233/* print the device and all its children (indented) */
1234{
1235	device_t child;
1236
1237	if (!dev)
1238		return;
1239
1240	print_device_short(dev, indent);
1241
1242	for (child = TAILQ_FIRST(&dev->children); child;
1243		 child = TAILQ_NEXT(child, link))
1244		print_device_tree_short(child, indent+1);
1245}
1246
1247void
1248print_device_tree(device_t dev, int indent)
1249/* print the device and all its children (indented) */
1250{
1251	device_t child;
1252
1253	if (!dev)
1254		return;
1255
1256	print_device(dev, indent);
1257
1258	for (child = TAILQ_FIRST(&dev->children); child;
1259		 child = TAILQ_NEXT(child, link))
1260		print_device_tree(child, indent+1);
1261}
1262
1263static void
1264print_driver_short(driver_t *driver, int indent)
1265{
1266	if (!driver)
1267		return;
1268
1269	indentprintf(("driver %s: type = %s%s%s%s, softc size = %d\n",
1270		driver->name,
1271		/* yes, I know this looks silly, but going to bed at
1272		 * two o'clock and having to get up at 7:30 again is silly
1273		 * as well. As is sticking your head in a bucket of water.
1274		 */
1275		(driver->type == DRIVER_TYPE_TTY? "tty":""),
1276		(driver->type == DRIVER_TYPE_BIO? "bio":""),
1277		(driver->type == DRIVER_TYPE_NET? "net":""),
1278		(driver->type == DRIVER_TYPE_MISC? "misc":""),
1279		driver->softc));
1280}
1281
1282static void
1283print_driver(driver_t *driver, int indent)
1284{
1285	if (!driver)
1286		return;
1287
1288	print_driver_short(driver, indent);
1289	indentprintf(("Methods:\n"));
1290	print_method_list(driver->methods, indent+1);
1291	indentprintf(("Operations:\n"));
1292	print_device_ops(driver->ops, indent+1);
1293}
1294
1295
1296static void
1297print_driver_list(driver_list_t drivers, int indent)
1298{
1299	driver_t *driver;
1300
1301	for (driver = TAILQ_FIRST(&drivers); driver;
1302	     driver = TAILQ_NEXT(driver, link))
1303		print_driver(driver, indent);
1304}
1305
1306static void
1307print_devclass_short(devclass_t dc, int indent)
1308{
1309	device_t dev;
1310
1311	if ( !dc )
1312		return;
1313
1314	indentprintf(("devclass %s: max units = %d, next unit = %d\n",
1315		dc->name, dc->maxunit, dc->nextunit));
1316}
1317
1318static void
1319print_devclass(devclass_t dc, int indent)
1320{
1321	int i;
1322
1323	if ( !dc )
1324		return;
1325
1326	print_devclass_short(dc, indent);
1327	indentprintf(("Drivers:\n"));
1328	print_driver_list(dc->drivers, indent+1);
1329
1330	indentprintf(("Devices:\n"));
1331	for (i = 0; i < dc->maxunit; i++)
1332		if (dc->devices[i])
1333			print_device(dc->devices[i], indent+1);
1334}
1335
1336void
1337print_devclass_list_short(void)
1338{
1339	devclass_t dc;
1340
1341	printf("Short listing of devclasses, drivers & devices:\n");
1342	for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
1343		print_devclass_short(dc, 0);
1344}
1345
1346void
1347print_devclass_list(void)
1348{
1349	devclass_t dc;
1350
1351	printf("Full listing of devclasses, drivers & devices:\n");
1352	for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
1353		print_devclass(dc, 0);
1354}
1355
1356#endif
1357