subr_bus.c revision 40648
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.6 1998/10/03 08:55:29 dfr 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/*
38 * Method table handling
39 */
40
41static int next_method_offset = 1;
42static int methods_count = 0;
43static int methods_size = 0;
44
45struct method {
46    int offset;
47    char* name;
48};
49
50static struct method *methods = 0;
51
52static void
53register_method(struct device_op_desc *desc)
54{
55    int i;
56    struct method* m;
57
58    for (i = 0; i < methods_count; i++)
59	if (!strcmp(methods[i].name, desc->name)) {
60	    desc->offset = methods[i].offset;
61	    return;
62	}
63
64    if (methods_count == methods_size) {
65	struct method* p;
66
67	methods_size += 10;
68	p = (struct method*) malloc(methods_size * sizeof(struct method),
69				     M_DEVBUF, M_NOWAIT);
70	if (!p)
71	    panic("register_method: out of memory");
72	if (methods) {
73	    bcopy(methods, p, methods_count * sizeof(struct method));
74	    free(methods, M_DEVBUF);
75	}
76	methods = p;
77    }
78    m = &methods[methods_count++];
79    m->name = malloc(strlen(desc->name) + 1, M_DEVBUF, M_NOWAIT);
80    if (!m->name)
81	    panic("register_method: out of memory");
82    strcpy(m->name, desc->name);
83    desc->offset = m->offset = next_method_offset++;
84}
85
86static int error_method(void)
87{
88    return ENXIO;
89}
90
91static struct device_ops null_ops = {
92    1,
93    { error_method }
94};
95
96static void
97compile_methods(driver_t *driver)
98{
99    device_ops_t ops;
100    struct device_method *m;
101    int i;
102
103    /*
104     * First register any methods which need it.
105     */
106    for (i = 0, m = driver->methods; m->desc; i++, m++)
107	if (!m->desc->offset)
108	    register_method(m->desc);
109
110    /*
111     * Then allocate the compiled op table.
112     */
113    ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),
114		 M_DEVBUF, M_NOWAIT);
115    if (!ops)
116	panic("compile_methods: out of memory");
117    ops->maxoffset = next_method_offset;
118    for (i = 0; i < next_method_offset; i++)
119	ops->methods[i] = error_method;
120    for (i = 0, m = driver->methods; m->desc; i++, m++)
121	ops->methods[m->desc->offset] = m->func;
122    driver->ops = ops;
123}
124
125/*
126 * Devclass implementation
127 */
128
129static devclass_list_t devclasses;
130
131static void
132devclass_init(void)
133{
134    TAILQ_INIT(&devclasses);
135}
136
137static devclass_t
138devclass_find_internal(const char *classname, int create)
139{
140    devclass_t dc;
141
142    for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
143	if (!strcmp(dc->name, classname))
144	    return dc;
145
146    if (create) {
147	dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
148		    M_DEVBUF, M_NOWAIT);
149	if (!dc)
150	    return NULL;
151	dc->name = (char*) (dc + 1);
152	strcpy(dc->name, classname);
153	dc->devices = NULL;
154	dc->maxunit = 0;
155	dc->nextunit = 0;
156	TAILQ_INIT(&dc->drivers);
157	TAILQ_INSERT_TAIL(&devclasses, dc, link);
158    }
159
160    return dc;
161}
162
163devclass_t
164devclass_find(const char *classname)
165{
166    return devclass_find_internal(classname, FALSE);
167}
168
169int
170devclass_add_driver(devclass_t dc, driver_t *driver)
171{
172    /*
173     * Compile the drivers methods.
174     */
175    compile_methods(driver);
176
177    /*
178     * Make sure the devclass which the driver is implementing exists.
179     */
180    devclass_find_internal(driver->name, TRUE);
181
182    TAILQ_INSERT_TAIL(&dc->drivers, driver, link);
183
184    return 0;
185}
186
187int
188devclass_delete_driver(devclass_t dc, driver_t *driver)
189{
190    device_t bus;
191    device_t dev;
192    int i;
193    int error;
194
195    /*
196     * Disassociate from any devices.  We iterate through all the
197     * devices attached to any bus in this class.
198     */
199    for (i = 0; i < dc->maxunit; i++) {
200	if (dc->devices[i]) {
201	    bus = dc->devices[i]->parent;
202	    for (dev = TAILQ_FIRST(&bus->children); dev;
203		 dev = TAILQ_NEXT(dev, link))
204		if (dev->driver == driver) {
205		    if (error = device_detach(dev))
206			return error;
207		    device_set_driver(dev, NULL);
208		}
209	}
210    }
211
212    TAILQ_REMOVE(&dc->drivers, driver, link);
213    return 0;
214}
215
216driver_t *
217devclass_find_driver(devclass_t dc, const char *classname)
218{
219    driver_t *driver;
220
221    for (driver = TAILQ_FIRST(&dc->drivers); driver;
222	 driver = TAILQ_NEXT(driver, link))
223	if (!strcmp(driver->name, classname))
224	    return driver;
225
226    return NULL;
227}
228
229const char *
230devclass_get_name(devclass_t dc)
231{
232    return dc->name;
233}
234
235device_t
236devclass_get_device(devclass_t dc, int unit)
237{
238    if (unit < 0 || unit >= dc->maxunit)
239	return NULL;
240    return dc->devices[unit];
241}
242
243void *
244devclass_get_softc(devclass_t dc, int unit)
245{
246    device_t dev;
247
248    if (unit < 0 || unit >= dc->maxunit)
249	return NULL;
250    dev = dc->devices[unit];
251    if (!dev || dev->state < DS_ATTACHED)
252	return NULL;
253    return dev->softc;
254}
255
256int
257devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
258{
259    int i;
260    int count;
261    device_t *list;
262
263    count = 0;
264    for (i = 0; i < dc->maxunit; i++)
265	if (dc->devices[i])
266	    count++;
267
268    list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
269    if (!list)
270	return ENOMEM;
271
272    count = 0;
273    for (i = 0; i < dc->maxunit; i++)
274	if (dc->devices[i]) {
275	    list[count] = dc->devices[i];
276	    count++;
277	}
278
279    *devlistp = list;
280    *devcountp = count;
281
282    return 0;
283}
284
285int
286devclass_get_maxunit(devclass_t dc)
287{
288    return dc->maxunit;
289}
290
291static int
292devclass_alloc_unit(devclass_t dc, int *unitp)
293{
294    int unit = *unitp;
295
296    /*
297     * If we have been given a wired unit number, check for existing
298     * device.
299     */
300    if (unit != -1) {
301	device_t dev;
302	dev = devclass_get_device(dc, unit);
303	if (dev) {
304	    printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit);
305	    unit = -1;
306	}
307    }
308
309    if (unit == -1) {
310	unit = dc->nextunit;
311	dc->nextunit++;
312    } else if (dc->nextunit <= unit)
313	dc->nextunit = unit + 1;
314
315    if (unit >= dc->maxunit) {
316	device_t *newlist;
317	int newsize;
318
319	newsize = (dc->maxunit ? 2 * dc->maxunit
320		   : MINALLOCSIZE / sizeof(device_t));
321	newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT);
322	if (!newlist)
323	    return ENOMEM;
324	bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
325	bzero(newlist + dc->maxunit,
326	      sizeof(device_t) * (newsize - dc->maxunit));
327	if (dc->devices)
328	    free(dc->devices, M_DEVBUF);
329	dc->devices = newlist;
330	dc->maxunit = newsize;
331    }
332
333    *unitp = unit;
334    return 0;
335}
336
337static int
338devclass_add_device(devclass_t dc, device_t dev)
339{
340    int error;
341
342    if (error = devclass_alloc_unit(dc, &dev->unit))
343	return error;
344    dc->devices[dev->unit] = dev;
345    dev->devclass = dc;
346    return 0;
347}
348
349static int
350devclass_delete_device(devclass_t dc, device_t dev)
351{
352    if (dev->devclass != dc
353	|| dc->devices[dev->unit] != dev)
354	panic("devclass_delete_device: inconsistent device class");
355    dc->devices[dev->unit] = NULL;
356    if (dev->flags & DF_WILDCARD)
357	dev->unit = -1;
358    dev->devclass = NULL;
359    while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL)
360	dc->nextunit--;
361    return 0;
362}
363
364static device_t
365make_device(device_t parent, const char *name,
366	    int unit, void *ivars)
367{
368    device_t dev;
369    devclass_t dc;
370    int error;
371
372    if (name) {
373	dc = devclass_find_internal(name, TRUE);
374	if (!dc) {
375	    printf("make_device: can't find device class %s\n", name);
376	    return NULL;
377	}
378
379	if (error = devclass_alloc_unit(dc, &unit))
380	    return NULL;
381    } else
382	dc = NULL;
383
384    dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT);
385    if (!dev)
386	return 0;
387
388    dev->parent = parent;
389    TAILQ_INIT(&dev->children);
390    dev->ops = &null_ops;
391    dev->driver = NULL;
392    dev->devclass = dc;
393    dev->unit = unit;
394    dev->desc = NULL;
395    dev->busy = 0;
396    dev->flags = DF_ENABLED;
397    if (unit == -1)
398	dev->flags |= DF_WILDCARD;
399    if (name)
400	dev->flags |= DF_FIXEDCLASS;
401    dev->ivars = ivars;
402    dev->softc = NULL;
403
404    if (dc)
405	dc->devices[unit] = dev;
406
407    dev->state = DS_NOTPRESENT;
408
409    return dev;
410}
411
412static void
413device_print_child(device_t dev, device_t child)
414{
415    printf("%s%d", device_get_name(child), device_get_unit(child));
416    if (device_is_alive(child)) {
417	if (device_get_desc(child))
418	    printf(": <%s>", device_get_desc(child));
419	BUS_PRINT_CHILD(dev, child);
420    } else
421	printf(" not found");
422    printf("\n");
423}
424
425device_t
426device_add_child(device_t dev, const char *name, int unit, void *ivars)
427{
428    device_t child;
429
430    child = make_device(dev, name, unit, ivars);
431
432    TAILQ_INSERT_TAIL(&dev->children, child, link);
433
434    return child;
435}
436
437device_t
438device_add_child_after(device_t dev, device_t place, const char *name,
439		       int unit, void *ivars)
440{
441    device_t child;
442
443    child = make_device(dev, name, unit, ivars);
444
445    if (place) {
446	TAILQ_INSERT_AFTER(&dev->children, place, dev, link);
447    } else {
448	TAILQ_INSERT_HEAD(&dev->children, dev, link);
449    }
450
451    return child;
452}
453
454int
455device_delete_child(device_t dev, device_t child)
456{
457    int error;
458
459    if (error = device_detach(child))
460	return error;
461    if (child->devclass)
462	devclass_delete_device(child->devclass, child);
463    TAILQ_REMOVE(&dev->children, child, link);
464    free(dev, M_DEVBUF);
465
466    return 0;
467}
468
469/*
470 * Find only devices attached to this bus.
471 */
472device_t
473device_find_child(device_t dev, const char *classname, int unit)
474{
475    devclass_t dc;
476    device_t child;
477
478    dc = devclass_find(classname);
479    if (!dc)
480	return NULL;
481
482    child = devclass_get_device(dc, unit);
483    if (child && child->parent == dev)
484	return child;
485    return NULL;
486}
487
488static driver_t *
489first_matching_driver(devclass_t dc, device_t dev)
490{
491    if (dev->devclass)
492	return devclass_find_driver(dc, dev->devclass->name);
493    else
494	return TAILQ_FIRST(&dc->drivers);
495}
496
497static driver_t *
498next_matching_driver(devclass_t dc, device_t dev, driver_t *last)
499{
500    if (dev->devclass) {
501	driver_t *driver;
502	for (driver = TAILQ_NEXT(last, link); driver;
503	     driver = TAILQ_NEXT(driver, link))
504	    if (!strcmp(dev->devclass->name, driver->name))
505		return driver;
506	return NULL;
507    } else
508	return TAILQ_NEXT(last, link);
509}
510
511static int
512device_probe_child(device_t dev, device_t child)
513{
514    devclass_t dc;
515    driver_t *driver;
516
517    dc = dev->devclass;
518    if (dc == NULL)
519	panic("device_probe_child: parent device has no devclass");
520
521    if (child->state == DS_ALIVE)
522	return 0;
523
524    for (driver = first_matching_driver(dc, child);
525	 driver;
526	 driver = next_matching_driver(dc, child, driver)) {
527	device_set_driver(child, driver);
528	if (DEVICE_PROBE(child) == 0) {
529	    if (!child->devclass)
530		device_set_devclass(child, driver->name);
531	    child->state = DS_ALIVE;
532	    return 0;
533	}
534    }
535
536    return ENXIO;
537}
538
539device_t
540device_get_parent(device_t dev)
541{
542    return dev->parent;
543}
544
545driver_t *
546device_get_driver(device_t dev)
547{
548    return dev->driver;
549}
550
551devclass_t
552device_get_devclass(device_t dev)
553{
554    return dev->devclass;
555}
556
557const char *
558device_get_name(device_t dev)
559{
560    if (dev->devclass)
561	return devclass_get_name(dev->devclass);
562    return NULL;
563}
564
565int
566device_get_unit(device_t dev)
567{
568    return dev->unit;
569}
570
571const char *
572device_get_desc(device_t dev)
573{
574    return dev->desc;
575}
576
577void
578device_set_desc(device_t dev, const char* desc)
579{
580    dev->desc = desc;
581}
582
583void *
584device_get_softc(device_t dev)
585{
586    return dev->softc;
587}
588
589void *
590device_get_ivars(device_t dev)
591{
592    return dev->ivars;
593}
594
595device_state_t
596device_get_state(device_t dev)
597{
598    return dev->state;
599}
600
601void
602device_enable(device_t dev)
603{
604    dev->flags |= DF_ENABLED;
605}
606
607void
608device_disable(device_t dev)
609{
610    dev->flags &= ~DF_ENABLED;
611}
612
613void
614device_busy(device_t dev)
615{
616    if (dev->state < DS_ATTACHED)
617	panic("device_busy: called for unattached device");
618    if (dev->busy == 0 && dev->parent)
619	device_busy(dev->parent);
620    dev->busy++;
621    dev->state = DS_BUSY;
622}
623
624void
625device_unbusy(device_t dev)
626{
627    if (dev->state != DS_BUSY)
628	panic("device_unbusy: called for non-busy device");
629    dev->busy--;
630    if (dev->busy == 0) {
631	if (dev->parent)
632	    device_unbusy(dev->parent);
633	dev->state = DS_ATTACHED;
634    }
635}
636
637int
638device_is_enabled(device_t dev)
639{
640    return (dev->flags & DF_ENABLED) != 0;
641}
642
643int
644device_is_alive(device_t dev)
645{
646    return dev->state >= DS_ALIVE;
647}
648
649int
650device_set_devclass(device_t dev, const char *classname)
651{
652    devclass_t dc;
653
654    if (dev->devclass) {
655	printf("device_set_devclass: device class already set\n");
656	return EINVAL;
657    }
658
659    dc = devclass_find_internal(classname, TRUE);
660    if (!dc)
661	return ENOMEM;
662
663    return devclass_add_device(dc, dev);
664}
665
666int
667device_set_driver(device_t dev, driver_t *driver)
668{
669    if (dev->state >= DS_ATTACHED)
670	return EBUSY;
671
672    if (dev->driver == driver)
673	return 0;
674
675    if (dev->softc) {
676	free(dev->softc, M_DEVBUF);
677	dev->softc = NULL;
678    }
679    dev->ops = &null_ops;
680    dev->driver = driver;
681    if (driver) {
682	dev->ops = driver->ops;
683	dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT);
684	bzero(dev->softc, driver->softc);
685    }
686    return 0;
687}
688
689int
690device_probe_and_attach(device_t dev)
691{
692    device_t bus = dev->parent;
693    int error;
694
695    if (dev->state >= DS_ALIVE)
696	return 0;
697
698    if (dev->flags & DF_ENABLED) {
699	device_probe_child(bus, dev);
700	device_print_child(bus, dev);
701	if (dev->state == DS_ALIVE) {
702	    error = DEVICE_ATTACH(dev);
703	    if (!error)
704		dev->state = DS_ATTACHED;
705	    else {
706		printf("device_probe_and_attach: %s%d attach returned %d\n",
707		       dev->driver->name, dev->unit, error);
708		device_set_driver(dev, NULL);
709		dev->state = DS_NOTPRESENT;
710	    }
711	}
712    } else
713	printf("%s%d: disabled, not probed.\n",
714	       dev->devclass->name, dev->unit);
715
716    return 0;
717}
718
719int
720device_detach(device_t dev)
721{
722    int error;
723
724    if (dev->state == DS_BUSY)
725	return EBUSY;
726    if (dev->state != DS_ATTACHED)
727	return 0;
728
729    if (error = DEVICE_DETACH(dev))
730	    return error;
731
732    if (!(dev->flags & DF_FIXEDCLASS))
733	devclass_delete_device(dev->devclass, dev);
734
735    dev->state = DS_NOTPRESENT;
736    device_set_driver(dev, NULL);
737
738    return 0;
739}
740
741int
742device_shutdown(device_t dev)
743{
744    if (dev->state < DS_ATTACHED)
745	return 0;
746    return DEVICE_SHUTDOWN(dev);
747}
748
749/*
750 * Access functions for device resources.
751 */
752extern struct config_device devtab[];
753extern int devtab_count;
754
755static int
756resource_match_string(int i, char *resname, char *value)
757{
758	int j;
759	struct resource *res;
760
761	for (j = 0, res = devtab[i].resources;
762	     j < devtab[i].resource_count; j++, res++)
763		if (!strcmp(res->name, resname)
764		    && res->type == RES_STRING
765		    && !strcmp(res->u.stringval, value))
766			return TRUE;
767	return FALSE;
768}
769
770static int
771resource_find(const char *name, int unit, char *resname, struct resource **result)
772{
773	int i, j;
774	struct resource *res;
775
776	/*
777	 * First check specific instances, then generic.
778	 */
779	for (i = 0; i < devtab_count; i++) {
780		if (devtab[i].unit < 0)
781			continue;
782		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
783			res = devtab[i].resources;
784			for (j = 0; j < devtab[i].resource_count; j++, res++)
785				if (!strcmp(res->name, resname)) {
786					*result = res;
787					return 0;
788				}
789		}
790	}
791	for (i = 0; i < devtab_count; i++) {
792		if (devtab[i].unit >= 0)
793			continue;
794		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
795			res = devtab[i].resources;
796			for (j = 0; j < devtab[i].resource_count; j++, res++)
797				if (!strcmp(res->name, resname)) {
798					*result = res;
799					return 0;
800				}
801		}
802	}
803	return ENOENT;
804}
805
806int
807resource_int_value(const char *name, int unit, char *resname, int *result)
808{
809	int error;
810	struct resource *res;
811	if ((error = resource_find(name, unit, resname, &res)) != 0)
812		return error;
813	if (res->type != RES_INT)
814		return EFTYPE;
815	*result = res->u.intval;
816	return 0;
817}
818
819int
820resource_long_value(const char *name, int unit, char *resname, long *result)
821{
822	int error;
823	struct resource *res;
824	if ((error = resource_find(name, unit, resname, &res)) != 0)
825		return error;
826	if (res->type != RES_LONG)
827		return EFTYPE;
828	*result = res->u.longval;
829	return 0;
830}
831
832int
833resource_string_value(const char *name, int unit, char *resname, char **result)
834{
835	int error;
836	struct resource *res;
837	if ((error = resource_find(name, unit, resname, &res)) != 0)
838		return error;
839	if (res->type != RES_STRING)
840		return EFTYPE;
841	*result = res->u.stringval;
842	return 0;
843}
844
845int
846resource_query_string(int i, char *resname, char *value)
847{
848	if (i < 0)
849		i = 0;
850	else
851		i = i + 1;
852	for (; i < devtab_count; i++)
853		if (resource_match_string(i, resname, value))
854			return i;
855	return -1;
856}
857
858char *
859resource_query_name(int i)
860{
861	return devtab[i].name;
862}
863
864int
865resource_query_unit(int i)
866{
867	return devtab[i].unit;
868}
869
870
871/*
872 * Some useful method implementations to make life easier for bus drivers.
873 */
874int
875bus_generic_attach(device_t dev)
876{
877    device_t child;
878
879    for (child = TAILQ_FIRST(&dev->children);
880	 child; child = TAILQ_NEXT(child, link))
881	device_probe_and_attach(child);
882
883    return 0;
884}
885
886int
887bus_generic_detach(device_t dev)
888{
889    device_t child;
890
891    if (dev->state != DS_ATTACHED)
892	return EBUSY;
893
894    for (child = TAILQ_FIRST(&dev->children);
895	 child; child = TAILQ_NEXT(child, link))
896	device_detach(child);
897
898    return 0;
899}
900
901int
902bus_generic_shutdown(device_t dev)
903{
904    device_t child;
905
906    for (child = TAILQ_FIRST(&dev->children);
907	 child; child = TAILQ_NEXT(child, link))
908	DEVICE_SHUTDOWN(child);
909
910    return 0;
911}
912
913void
914bus_generic_print_child(device_t dev, device_t child)
915{
916}
917
918int
919bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result)
920{
921    return ENOENT;
922}
923
924int
925bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value)
926{
927    return ENOENT;
928}
929
930void *
931bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg)
932{
933    /* Propagate up the bus hierarchy until someone handles it. */
934    if (dev->parent)
935	return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg);
936    else
937	return NULL;
938}
939
940int
941bus_generic_connect_intr(device_t dev, void *ih)
942{
943    /* Propagate up the bus hierarchy until someone handles it. */
944    if (dev->parent)
945	return BUS_CONNECT_INTR(dev->parent, ih);
946    else
947	return EINVAL;
948}
949
950static int root_create_intr(device_t dev, device_t child,
951			    driver_intr_t *intr, void *arg)
952{
953    /*
954     * If an interrupt mapping gets to here something bad has happened.
955     * Should probably panic.
956     */
957    return EINVAL;
958}
959
960static device_method_t root_methods[] = {
961	/* Bus interface */
962	DEVMETHOD(bus_print_child,	bus_generic_print_child),
963	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
964	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
965	DEVMETHOD(bus_create_intr,	root_create_intr),
966
967	{ 0, 0 }
968};
969
970static driver_t root_driver = {
971	"root",
972	root_methods,
973	DRIVER_TYPE_MISC,
974	1,			/* no softc */
975};
976
977device_t root_bus;
978devclass_t root_devclass;
979
980static int
981root_bus_module_handler(module_t mod, modeventtype_t what, void* arg)
982{
983    switch (what) {
984    case MOD_LOAD:
985	devclass_init();
986	compile_methods(&root_driver);
987	root_bus = make_device(NULL, "root", 0, NULL);
988	root_bus->ops = root_driver.ops;
989	root_bus->driver = &root_driver;
990	root_bus->state = DS_ATTACHED;
991	root_devclass = devclass_find("root");
992	return 0;
993    }
994
995    return 0;
996}
997
998static moduledata_t root_bus_mod = {
999	"rootbus",
1000	root_bus_module_handler,
1001	0
1002};
1003DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1004
1005void
1006root_bus_configure()
1007{
1008    device_t dev;
1009
1010    for (dev = TAILQ_FIRST(&root_bus->children); dev;
1011	 dev = TAILQ_NEXT(dev, link)) {
1012	device_probe_and_attach(dev);
1013    }
1014}
1015
1016int
1017driver_module_handler(module_t mod, modeventtype_t what, void* arg)
1018{
1019    struct driver_module_data* data = (struct driver_module_data*) arg;
1020    devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE);
1021    int error;
1022
1023    switch (what) {
1024    case MOD_LOAD:
1025	if (error = devclass_add_driver(bus_devclass,
1026					data->driver))
1027	    return error;
1028	*data->devclass =
1029	    devclass_find_internal(data->driver->name, TRUE);
1030	break;
1031
1032    case MOD_UNLOAD:
1033	if (error = devclass_delete_driver(bus_devclass,
1034					   data->driver))
1035	    return error;
1036	break;
1037    }
1038
1039    if (data->chainevh)
1040	return data->chainevh(mod, what, data->chainarg);
1041    else
1042	return 0;
1043}
1044