xref: /freebsd/sys/kern/subr_bus.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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 
41 static int next_method_offset = 1;
42 static int methods_count = 0;
43 static int methods_size = 0;
44 
45 struct method {
46     int offset;
47     char* name;
48 };
49 
50 static struct method *methods = 0;
51 
52 static void
53 register_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 
86 static int error_method(void)
87 {
88     return ENXIO;
89 }
90 
91 static struct device_ops null_ops = {
92     1,
93     { error_method }
94 };
95 
96 static void
97 compile_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 
129 static devclass_list_t devclasses;
130 
131 static void
132 devclass_init(void)
133 {
134     TAILQ_INIT(&devclasses);
135 }
136 
137 static devclass_t
138 devclass_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 
163 devclass_t
164 devclass_find(const char *classname)
165 {
166     return devclass_find_internal(classname, FALSE);
167 }
168 
169 int
170 devclass_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 
187 int
188 devclass_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 
216 driver_t *
217 devclass_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 
229 const char *
230 devclass_get_name(devclass_t dc)
231 {
232     return dc->name;
233 }
234 
235 device_t
236 devclass_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 
243 void *
244 devclass_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 
256 int
257 devclass_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 
286 int
287 devclass_get_maxunit(devclass_t dc)
288 {
289     return dc->maxunit;
290 }
291 
292 static int
293 devclass_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 
338 static int
339 devclass_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 
350 static int
351 devclass_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 
365 static device_t
366 make_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 
414 static void
415 device_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 
427 device_t
428 device_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 
439 device_t
440 device_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 
456 int
457 device_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  */
474 device_t
475 device_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 
490 static driver_t *
491 first_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 
499 static driver_t *
500 next_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 
513 static int
514 device_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 
542 device_t
543 device_get_parent(device_t dev)
544 {
545     return dev->parent;
546 }
547 
548 driver_t *
549 device_get_driver(device_t dev)
550 {
551     return dev->driver;
552 }
553 
554 devclass_t
555 device_get_devclass(device_t dev)
556 {
557     return dev->devclass;
558 }
559 
560 const char *
561 device_get_name(device_t dev)
562 {
563     if (dev->devclass)
564 	return devclass_get_name(dev->devclass);
565     return NULL;
566 }
567 
568 int
569 device_get_unit(device_t dev)
570 {
571     return dev->unit;
572 }
573 
574 const char *
575 device_get_desc(device_t dev)
576 {
577     return dev->desc;
578 }
579 
580 void
581 device_set_desc(device_t dev, const char* desc)
582 {
583     dev->desc = desc;
584 }
585 
586 void *
587 device_get_softc(device_t dev)
588 {
589     return dev->softc;
590 }
591 
592 void *
593 device_get_ivars(device_t dev)
594 {
595     return dev->ivars;
596 }
597 
598 device_state_t
599 device_get_state(device_t dev)
600 {
601     return dev->state;
602 }
603 
604 void
605 device_enable(device_t dev)
606 {
607     dev->flags |= DF_ENABLED;
608 }
609 
610 void
611 device_disable(device_t dev)
612 {
613     dev->flags &= ~DF_ENABLED;
614 }
615 
616 void
617 device_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 
627 void
628 device_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 
640 int
641 device_is_enabled(device_t dev)
642 {
643     return (dev->flags & DF_ENABLED) != 0;
644 }
645 
646 int
647 device_is_alive(device_t dev)
648 {
649     return dev->state >= DS_ALIVE;
650 }
651 
652 int
653 device_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 
669 int
670 device_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 
692 int
693 device_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 
722 int
723 device_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 
744 int
745 device_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  */
755 extern struct config_device devtab[];
756 extern int devtab_count;
757 
758 static int
759 resource_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 
773 static int
774 resource_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 
809 int
810 resource_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 
822 int
823 resource_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 
835 int
836 resource_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 
848 int
849 resource_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 
861 char *
862 resource_query_name(int i)
863 {
864 	return devtab[i].name;
865 }
866 
867 int
868 resource_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  */
877 int
878 bus_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 
890 int
891 bus_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 
906 int
907 bus_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 
918 void
919 bus_generic_print_child(device_t dev, device_t child)
920 {
921 }
922 
923 int
924 bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result)
925 {
926     return ENOENT;
927 }
928 
929 int
930 bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value)
931 {
932     return ENOENT;
933 }
934 
935 void *
936 bus_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 
945 int
946 bus_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 
955 static 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 
965 static 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 
975 static driver_t root_driver = {
976 	"root",
977 	root_methods,
978 	DRIVER_TYPE_MISC,
979 	1,			/* no softc */
980 };
981 
982 device_t root_bus;
983 devclass_t root_devclass;
984 
985 static int
986 root_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 
1003 static moduledata_t root_bus_mod = {
1004 	"rootbus",
1005 	root_bus_module_handler,
1006 	0
1007 };
1008 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
1009 
1010 void
1011 root_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 
1022 int
1023 driver_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