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