subr_bus.c revision 38860
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.4 1998/07/22 08:35:52 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 dev;
262    device_t *list;
263
264    count = 0;
265    for (i = 0; i < dc->maxunit; i++)
266	if (dc->devices[i])
267	    count++;
268
269    list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
270    if (!list)
271	return ENOMEM;
272
273    count = 0;
274    for (i = 0; i < dc->maxunit; i++)
275	if (dc->devices[i]) {
276	    list[count] = dc->devices[i];
277	    count++;
278	}
279
280    *devlistp = list;
281    *devcountp = count;
282
283    return 0;
284}
285
286int
287devclass_get_maxunit(devclass_t dc)
288{
289    return dc->maxunit;
290}
291
292static int
293devclass_alloc_unit(devclass_t dc, int *unitp)
294{
295    int unit = *unitp;
296
297    /*
298     * If we have been given a wired unit number, check for existing
299     * device.
300     */
301    if (unit != -1) {
302	device_t dev;
303	dev = devclass_get_device(dc, unit);
304	if (dev) {
305	    printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit);
306	    unit = -1;
307	}
308    }
309
310    if (unit == -1) {
311	unit = dc->nextunit;
312	dc->nextunit++;
313    } else if (dc->nextunit <= unit)
314	dc->nextunit = unit + 1;
315
316    if (unit >= dc->maxunit) {
317	device_t *newlist;
318	int newsize;
319
320	newsize = (dc->maxunit ? 2 * dc->maxunit
321		   : MINALLOCSIZE / sizeof(device_t));
322	newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT);
323	if (!newlist)
324	    return ENOMEM;
325	bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
326	bzero(newlist + dc->maxunit,
327	      sizeof(device_t) * (newsize - dc->maxunit));
328	if (dc->devices)
329	    free(dc->devices, M_DEVBUF);
330	dc->devices = newlist;
331	dc->maxunit = newsize;
332    }
333
334    *unitp = unit;
335    return 0;
336}
337
338static int
339devclass_add_device(devclass_t dc, device_t dev)
340{
341    int error;
342
343    if (error = devclass_alloc_unit(dc, &dev->unit))
344	return error;
345    dc->devices[dev->unit] = dev;
346    dev->devclass = dc;
347    return 0;
348}
349
350static int
351devclass_delete_device(devclass_t dc, device_t dev)
352{
353    if (dev->devclass != dc
354	|| dc->devices[dev->unit] != dev)
355	panic("devclass_delete_device: inconsistent device class");
356    dc->devices[dev->unit] = NULL;
357    if (dev->flags & DF_WILDCARD)
358	dev->unit = -1;
359    dev->devclass = NULL;
360    while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL)
361	dc->nextunit--;
362    return 0;
363}
364
365static device_t
366make_device(device_t parent, const char *name,
367	    int unit, void *ivars)
368{
369    driver_t *driver;
370    device_t dev;
371    devclass_t dc;
372    int error;
373
374    if (name) {
375	dc = devclass_find_internal(name, TRUE);
376	if (!dc) {
377	    printf("make_device: can't find device class %s\n", name);
378	    return NULL;
379	}
380
381	if (error = devclass_alloc_unit(dc, &unit))
382	    return NULL;
383    } else
384	dc = NULL;
385
386    dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT);
387    if (!dev)
388	return 0;
389
390    dev->parent = parent;
391    TAILQ_INIT(&dev->children);
392    dev->ops = &null_ops;
393    dev->driver = NULL;
394    dev->devclass = dc;
395    dev->unit = unit;
396    dev->desc = NULL;
397    dev->busy = 0;
398    dev->flags = DF_ENABLED;
399    if (unit == -1)
400	dev->flags |= DF_WILDCARD;
401    if (name)
402	dev->flags |= DF_FIXEDCLASS;
403    dev->ivars = ivars;
404    dev->softc = NULL;
405
406    if (dc)
407	dc->devices[unit] = dev;
408
409    dev->state = DS_NOTPRESENT;
410
411    return dev;
412}
413
414static void
415device_print_child(device_t dev, device_t child)
416{
417    printf("%s%d", device_get_name(child), device_get_unit(child));
418    if (device_is_alive(child)) {
419	if (device_get_desc(child))
420	    printf(": <%s>", device_get_desc(child));
421	BUS_PRINT_CHILD(dev, child);
422    } else
423	printf(" not found");
424    printf("\n");
425}
426
427device_t
428device_add_child(device_t dev, const char *name, int unit, void *ivars)
429{
430    device_t child;
431
432    child = make_device(dev, name, unit, ivars);
433
434    TAILQ_INSERT_TAIL(&dev->children, child, link);
435
436    return child;
437}
438
439device_t
440device_add_child_after(device_t dev, device_t place, const char *name,
441		       int unit, void *ivars)
442{
443    device_t child;
444
445    child = make_device(dev, name, unit, ivars);
446
447    if (place) {
448	TAILQ_INSERT_AFTER(&dev->children, place, dev, link);
449    } else {
450	TAILQ_INSERT_HEAD(&dev->children, dev, link);
451    }
452
453    return child;
454}
455
456int
457device_delete_child(device_t dev, device_t child)
458{
459    int error;
460
461    if (error = DEVICE_DETACH(child))
462	return error;
463    if (child->devclass)
464	devclass_delete_device(child->devclass, child);
465    TAILQ_REMOVE(&dev->children, child, link);
466    free(dev, M_DEVBUF);
467
468    return 0;
469}
470
471/*
472 * Find only devices attached to this bus.
473 */
474device_t
475device_find_child(device_t dev, const char *classname, int unit)
476{
477    devclass_t dc;
478    device_t child;
479
480    dc = devclass_find(classname);
481    if (!dc)
482	return NULL;
483
484    child = devclass_get_device(dc, unit);
485    if (child && child->parent == dev)
486	return child;
487    return NULL;
488}
489
490static driver_t *
491first_matching_driver(devclass_t dc, device_t dev)
492{
493    if (dev->devclass)
494	return devclass_find_driver(dc, dev->devclass->name);
495    else
496	return TAILQ_FIRST(&dc->drivers);
497}
498
499static driver_t *
500next_matching_driver(devclass_t dc, device_t dev, driver_t *last)
501{
502    if (dev->devclass) {
503	driver_t *driver;
504	for (driver = TAILQ_NEXT(last, link); driver;
505	     driver = TAILQ_NEXT(driver, link))
506	    if (!strcmp(dev->devclass->name, driver->name))
507		return driver;
508	return NULL;
509    } else
510	return TAILQ_NEXT(last, link);
511}
512
513static int
514device_probe_child(device_t dev, device_t child)
515{
516    devclass_t dc;
517    driver_t *driver;
518    void *softc;
519
520    dc = dev->devclass;
521    if (dc == NULL)
522	panic("device_probe_child: parent device has no devclass");
523
524    if (child->state == DS_ALIVE)
525	return 0;
526
527    for (driver = first_matching_driver(dc, child);
528	 driver;
529	 driver = next_matching_driver(dc, child, driver)) {
530	device_set_driver(child, driver);
531	if (DEVICE_PROBE(child) == 0) {
532	    if (!child->devclass)
533		device_set_devclass(child, driver->name);
534	    child->state = DS_ALIVE;
535	    return 0;
536	}
537    }
538
539    return ENXIO;
540}
541
542device_t
543device_get_parent(device_t dev)
544{
545    return dev->parent;
546}
547
548driver_t *
549device_get_driver(device_t dev)
550{
551    return dev->driver;
552}
553
554devclass_t
555device_get_devclass(device_t dev)
556{
557    return dev->devclass;
558}
559
560const char *
561device_get_name(device_t dev)
562{
563    if (dev->devclass)
564	return devclass_get_name(dev->devclass);
565    return NULL;
566}
567
568int
569device_get_unit(device_t dev)
570{
571    return dev->unit;
572}
573
574const char *
575device_get_desc(device_t dev)
576{
577    return dev->desc;
578}
579
580void
581device_set_desc(device_t dev, const char* desc)
582{
583    dev->desc = desc;
584}
585
586void *
587device_get_softc(device_t dev)
588{
589    return dev->softc;
590}
591
592void *
593device_get_ivars(device_t dev)
594{
595    return dev->ivars;
596}
597
598device_state_t
599device_get_state(device_t dev)
600{
601    return dev->state;
602}
603
604void
605device_enable(device_t dev)
606{
607    dev->flags |= DF_ENABLED;
608}
609
610void
611device_disable(device_t dev)
612{
613    dev->flags &= ~DF_ENABLED;
614}
615
616void
617device_busy(device_t dev)
618{
619    if (dev->state < DS_ATTACHED)
620	panic("device_busy: called for unattached device");
621    if (dev->busy == 0 && dev->parent)
622	device_busy(dev->parent);
623    dev->busy++;
624    dev->state = DS_BUSY;
625}
626
627void
628device_unbusy(device_t dev)
629{
630    if (dev->state != DS_BUSY)
631	panic("device_unbusy: called for non-busy device");
632    dev->busy--;
633    if (dev->busy == 0) {
634	if (dev->parent)
635	    device_unbusy(dev->parent);
636	dev->state = DS_ATTACHED;
637    }
638}
639
640int
641device_is_enabled(device_t dev)
642{
643    return (dev->flags & DF_ENABLED) != 0;
644}
645
646int
647device_is_alive(device_t dev)
648{
649    return dev->state >= DS_ALIVE;
650}
651
652int
653device_set_devclass(device_t dev, const char *classname)
654{
655    devclass_t dc;
656
657    if (dev->devclass) {
658	printf("device_set_devclass: device class already set\n");
659	return EINVAL;
660    }
661
662    dc = devclass_find_internal(classname, TRUE);
663    if (!dc)
664	return ENOMEM;
665
666    return devclass_add_device(dc, dev);
667}
668
669int
670device_set_driver(device_t dev, driver_t *driver)
671{
672    if (dev->state >= DS_ATTACHED)
673	return EBUSY;
674
675    if (dev->driver == driver)
676	return 0;
677
678    if (dev->softc) {
679	free(dev->softc, M_DEVBUF);
680	dev->softc = NULL;
681    }
682    dev->ops = &null_ops;
683    dev->driver = driver;
684    if (driver) {
685	dev->ops = driver->ops;
686	dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT);
687	bzero(dev->softc, driver->softc);
688    }
689    return 0;
690}
691
692int
693device_probe_and_attach(device_t dev)
694{
695    device_t bus = dev->parent;
696    int error;
697
698    if (dev->state >= DS_ALIVE)
699	return 0;
700
701    if (dev->flags & DF_ENABLED) {
702	device_probe_child(bus, dev);
703	device_print_child(bus, dev);
704	if (dev->state == DS_ALIVE) {
705	    error = DEVICE_ATTACH(dev);
706	    if (!error)
707		dev->state = DS_ATTACHED;
708	    else {
709		printf("device_probe_and_attach: %s%d attach returned %d\n",
710		       dev->driver->name, dev->unit, error);
711		device_set_driver(dev, NULL);
712		dev->state = DS_NOTPRESENT;
713	    }
714	}
715    } else
716	printf("%s%d: disabled, not probed.\n",
717	       dev->devclass->name, dev->unit);
718
719    return 0;
720}
721
722int
723device_detach(device_t dev)
724{
725    int error;
726
727    if (dev->state == DS_BUSY)
728	return EBUSY;
729    if (dev->state != DS_ATTACHED)
730	return 0;
731
732    if (error = DEVICE_DETACH(dev))
733	    return error;
734
735    if (!(dev->flags & DF_FIXEDCLASS))
736	devclass_delete_device(dev->devclass, dev);
737
738    dev->state = DS_NOTPRESENT;
739    device_set_driver(dev, NULL);
740
741    return 0;
742}
743
744int
745device_shutdown(device_t dev)
746{
747    if (dev->state < DS_ATTACHED)
748	return 0;
749    return DEVICE_SHUTDOWN(dev);
750}
751
752/*
753 * Access functions for device resources.
754 */
755extern struct config_device devtab[];
756extern int devtab_count;
757
758static int
759resource_match_string(int i, char *resname, char *value)
760{
761	int j;
762	struct resource *res;
763
764	for (j = 0, res = devtab[i].resources;
765	     j < devtab[i].resource_count; j++, res++)
766		if (!strcmp(res->name, resname)
767		    && res->type == RES_STRING
768		    && !strcmp(res->u.stringval, value))
769			return TRUE;
770	return FALSE;
771}
772
773static int
774resource_find(const char *name, int unit, char *resname, struct resource **result)
775{
776	int i, j;
777	struct resource *res;
778
779	/*
780	 * First check specific instances, then generic.
781	 */
782	for (i = 0; i < devtab_count; i++) {
783		if (devtab[i].unit < 0)
784			continue;
785		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
786			res = devtab[i].resources;
787			for (j = 0; j < devtab[i].resource_count; j++, res++)
788				if (!strcmp(res->name, resname)) {
789					*result = res;
790					return 0;
791				}
792		}
793	}
794	for (i = 0; i < devtab_count; i++) {
795		if (devtab[i].unit >= 0)
796			continue;
797		if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
798			res = devtab[i].resources;
799			for (j = 0; j < devtab[i].resource_count; j++, res++)
800				if (!strcmp(res->name, resname)) {
801					*result = res;
802					return 0;
803				}
804		}
805	}
806	return ENOENT;
807}
808
809int
810resource_int_value(const char *name, int unit, char *resname, int *result)
811{
812	int error;
813	struct resource *res;
814	if ((error = resource_find(name, unit, resname, &res)) != 0)
815		return error;
816	if (res->type != RES_INT)
817		return EFTYPE;
818	*result = res->u.intval;
819	return 0;
820}
821
822int
823resource_long_value(const char *name, int unit, char *resname, long *result)
824{
825	int error;
826	struct resource *res;
827	if ((error = resource_find(name, unit, resname, &res)) != 0)
828		return error;
829	if (res->type != RES_LONG)
830		return EFTYPE;
831	*result = res->u.longval;
832	return 0;
833}
834
835int
836resource_string_value(const char *name, int unit, char *resname, char **result)
837{
838	int error;
839	struct resource *res;
840	if ((error = resource_find(name, unit, resname, &res)) != 0)
841		return error;
842	if (res->type != RES_STRING)
843		return EFTYPE;
844	*result = res->u.stringval;
845	return 0;
846}
847
848int
849resource_query_string(int i, char *resname, char *value)
850{
851	if (i < 0)
852		i = 0;
853	else
854		i = i + 1;
855	for (; i < devtab_count; i++)
856		if (resource_match_string(i, resname, value))
857			return i;
858	return -1;
859}
860
861char *
862resource_query_name(int i)
863{
864	return devtab[i].name;
865}
866
867int
868resource_query_unit(int i)
869{
870	return devtab[i].unit;
871}
872
873
874/*
875 * Some useful method implementations to make life easier for bus drivers.
876 */
877int
878bus_generic_attach(device_t dev)
879{
880    device_t child;
881    int error;
882
883    for (child = TAILQ_FIRST(&dev->children);
884	 child; child = TAILQ_NEXT(child, link))
885	device_probe_and_attach(child);
886
887    return 0;
888}
889
890int
891bus_generic_detach(device_t dev)
892{
893    device_t child;
894    int error;
895
896    if (dev->state != DS_ATTACHED)
897	return EBUSY;
898
899    for (child = TAILQ_FIRST(&dev->children);
900	 child; child = TAILQ_NEXT(child, link))
901	DEVICE_DETACH(child);
902
903    return 0;
904}
905
906int
907bus_generic_shutdown(device_t dev)
908{
909    device_t child;
910
911    for (child = TAILQ_FIRST(&dev->children);
912	 child; child = TAILQ_NEXT(child, link))
913	DEVICE_SHUTDOWN(child);
914
915    return 0;
916}
917
918void
919bus_generic_print_child(device_t dev, device_t child)
920{
921}
922
923int
924bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result)
925{
926    return ENOENT;
927}
928
929int
930bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value)
931{
932    return ENOENT;
933}
934
935void *
936bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg)
937{
938    /* Propagate up the bus hierarchy until someone handles it. */
939    if (dev->parent)
940	return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg);
941    else
942	return NULL;
943}
944
945int
946bus_generic_connect_intr(device_t dev, void *ih)
947{
948    /* Propagate up the bus hierarchy until someone handles it. */
949    if (dev->parent)
950	return BUS_CONNECT_INTR(dev->parent, ih);
951    else
952	return EINVAL;
953}
954
955static int root_create_intr(device_t dev, device_t child,
956			    driver_intr_t *intr, void *arg)
957{
958    /*
959     * If an interrupt mapping gets to here something bad has happened.
960     * Should probably panic.
961     */
962    return EINVAL;
963}
964
965static device_method_t root_methods[] = {
966	/* Bus interface */
967	DEVMETHOD(bus_print_child,	bus_generic_print_child),
968	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
969	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
970	DEVMETHOD(bus_create_intr,	root_create_intr),
971
972	{ 0, 0 }
973};
974
975static driver_t root_driver = {
976	"root",
977	root_methods,
978	DRIVER_TYPE_MISC,
979	1,			/* no softc */
980};
981
982device_t root_bus;
983devclass_t root_devclass;
984
985static int
986root_bus_module_handler(module_t mod, modeventtype_t what, void* arg)
987{
988    switch (what) {
989    case MOD_LOAD:
990	devclass_init();
991	compile_methods(&root_driver);
992	root_bus = make_device(NULL, "root", 0, NULL);
993	root_bus->ops = root_driver.ops;
994	root_bus->driver = &root_driver;
995	root_bus->state = DS_ATTACHED;
996	root_devclass = devclass_find("root");
997	return 0;
998    }
999
1000    return 0;
1001}
1002
1003static moduledata_t root_bus_mod = {
1004	"rootbus",
1005	root_bus_module_handler,
1006	0
1007};
1008DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1009
1010void
1011root_bus_configure()
1012{
1013    device_t dev;
1014    int error;
1015
1016    for (dev = TAILQ_FIRST(&root_bus->children); dev;
1017	 dev = TAILQ_NEXT(dev, link)) {
1018	device_probe_and_attach(dev);
1019    }
1020}
1021
1022int
1023driver_module_handler(module_t mod, modeventtype_t what, void* arg)
1024{
1025    struct driver_module_data* data = (struct driver_module_data*) arg;
1026    devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE);
1027    int error;
1028
1029    switch (what) {
1030    case MOD_LOAD:
1031	if (error = devclass_add_driver(bus_devclass,
1032					data->driver))
1033	    return error;
1034	*data->devclass =
1035	    devclass_find_internal(data->driver->name, TRUE);
1036	break;
1037
1038    case MOD_UNLOAD:
1039	if (error = devclass_delete_driver(bus_devclass,
1040					   data->driver))
1041	    return error;
1042	break;
1043    }
1044
1045    if (data->chainevh)
1046	return data->chainevh(mod, what, data->chainarg);
1047    else
1048	return 0;
1049}
1050