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: releng/5.1/sys/kern/subr_bus.c 114293 2003-04-30 12:57:40Z markm $
27 */
28
29 #include "opt_bus.h"
30
31 #include <sys/param.h>
32 #include <sys/conf.h>
33 #include <sys/filio.h>
34 #include <sys/lock.h>
35 #include <sys/kernel.h>
36 #include <sys/kobj.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40 #include <sys/poll.h>
41 #include <sys/proc.h>
42 #include <sys/condvar.h>
43 #include <sys/queue.h>
44 #include <machine/bus.h>
45 #include <sys/rman.h>
46 #include <sys/selinfo.h>
47 #include <sys/signalvar.h>
48 #include <sys/sysctl.h>
49 #include <sys/systm.h>
50 #include <sys/uio.h>
51 #include <sys/bus.h>
52
53 #include <machine/stdarg.h>
54
55 #include <vm/uma.h>
56
57 SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
58
59 /*
60 * Used to attach drivers to devclasses.
61 */
62 typedef struct driverlink *driverlink_t;
63 struct driverlink {
64 driver_t *driver;
65 TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */
66 };
67
68 /*
69 * Forward declarations
70 */
71 typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
72 typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
73 typedef TAILQ_HEAD(device_list, device) device_list_t;
74
75 struct devclass {
76 TAILQ_ENTRY(devclass) link;
77 driver_list_t drivers; /* bus devclasses store drivers for bus */
78 char *name;
79 device_t *devices; /* array of devices indexed by unit */
80 int maxunit; /* size of devices array */
81 };
82
83 /*
84 * Implementation of device.
85 */
86 struct device {
87 /*
88 * A device is a kernel object. The first field must be the
89 * current ops table for the object.
90 */
91 KOBJ_FIELDS;
92
93 /*
94 * Device hierarchy.
95 */
96 TAILQ_ENTRY(device) link; /* list of devices in parent */
97 TAILQ_ENTRY(device) devlink; /* global device list membership */
98 device_t parent;
99 device_list_t children; /* list of subordinate devices */
100
101 /*
102 * Details of this device.
103 */
104 driver_t *driver;
105 devclass_t devclass; /* device class which we are in */
106 int unit;
107 char* nameunit; /* name+unit e.g. foodev0 */
108 char* desc; /* driver specific description */
109 int busy; /* count of calls to device_busy() */
110 device_state_t state;
111 u_int32_t devflags; /* api level flags for device_get_flags() */
112 u_short flags;
113 #define DF_ENABLED 1 /* device should be probed/attached */
114 #define DF_FIXEDCLASS 2 /* devclass specified at create time */
115 #define DF_WILDCARD 4 /* unit was originally wildcard */
116 #define DF_DESCMALLOCED 8 /* description was malloced */
117 #define DF_QUIET 16 /* don't print verbose attach message */
118 #define DF_DONENOMATCH 32 /* don't execute DEVICE_NOMATCH again */
119 #define DF_EXTERNALSOFTC 64 /* softc not allocated by us */
120 u_char order; /* order from device_add_child_ordered() */
121 u_char pad;
122 void *ivars;
123 void *softc;
124 };
125
126 struct device_op_desc {
127 unsigned int offset; /* offset in driver ops */
128 struct method* method; /* internal method implementation */
129 devop_t deflt; /* default implementation */
130 const char* name; /* unique name (for registration) */
131 };
132
133 static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
134
135 #ifdef BUS_DEBUG
136
137 static int bus_debug = 1;
138 TUNABLE_INT("bus.debug", &bus_debug);
139 SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RW, &bus_debug, 0,
140 "Debug bus code");
141
142 #define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
143 #define DEVICENAME(d) ((d)? device_get_name(d): "no device")
144 #define DRIVERNAME(d) ((d)? d->name : "no driver")
145 #define DEVCLANAME(d) ((d)? d->name : "no devclass")
146
147 /* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
148 * prevent syslog from deleting initial spaces
149 */
150 #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while (0)
151
152 static void print_device_short(device_t dev, int indent);
153 static void print_device(device_t dev, int indent);
154 void print_device_tree_short(device_t dev, int indent);
155 void print_device_tree(device_t dev, int indent);
156 static void print_driver_short(driver_t *driver, int indent);
157 static void print_driver(driver_t *driver, int indent);
158 static void print_driver_list(driver_list_t drivers, int indent);
159 static void print_devclass_short(devclass_t dc, int indent);
160 static void print_devclass(devclass_t dc, int indent);
161 void print_devclass_list_short(void);
162 void print_devclass_list(void);
163
164 #else
165 /* Make the compiler ignore the function calls */
166 #define PDEBUG(a) /* nop */
167 #define DEVICENAME(d) /* nop */
168 #define DRIVERNAME(d) /* nop */
169 #define DEVCLANAME(d) /* nop */
170
171 #define print_device_short(d,i) /* nop */
172 #define print_device(d,i) /* nop */
173 #define print_device_tree_short(d,i) /* nop */
174 #define print_device_tree(d,i) /* nop */
175 #define print_driver_short(d,i) /* nop */
176 #define print_driver(d,i) /* nop */
177 #define print_driver_list(d,i) /* nop */
178 #define print_devclass_short(d,i) /* nop */
179 #define print_devclass(d,i) /* nop */
180 #define print_devclass_list_short() /* nop */
181 #define print_devclass_list() /* nop */
182 #endif
183
184 /*
185 * /dev/devctl implementation
186 */
187
188 /*
189 * This design allows only one reader for /dev/devctl. This is not desirable
190 * in the long run, but will get a lot of hair out of this implementation.
191 * Maybe we should make this device a clonable device.
192 *
193 * Also note: we specifically do not attach a device to the device_t tree
194 * to avoid potential chicken and egg problems. One could argue that all
195 * of this belongs to the root node. One could also further argue that the
196 * sysctl interface that we have not might more properly be an ioctl
197 * interface, but at this stage of the game, I'm not inclined to rock that
198 * boat.
199 *
200 * I'm also not sure that the SIGIO support is done correctly or not, as
201 * I copied it from a driver that had SIGIO support that likely hasn't been
202 * tested since 3.4 or 2.2.8!
203 */
204
205 static int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS);
206 static int devctl_disable = 0;
207 TUNABLE_INT("hw.bus.devctl_disable", &devctl_disable);
208 SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable,
209 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_devctl_disable,
210 "I", "devctl disable");
211
212 static d_open_t devopen;
213 static d_close_t devclose;
214 static d_read_t devread;
215 static d_ioctl_t devioctl;
216 static d_poll_t devpoll;
217
218 #define CDEV_MAJOR 173
219 static struct cdevsw dev_cdevsw = {
220 .d_open = devopen,
221 .d_close = devclose,
222 .d_read = devread,
223 .d_ioctl = devioctl,
224 .d_poll = devpoll,
225 .d_name = "devctl",
226 .d_maj = CDEV_MAJOR,
227 };
228
229 struct dev_event_info
230 {
231 char *dei_data;
232 TAILQ_ENTRY(dev_event_info) dei_link;
233 };
234
235 TAILQ_HEAD(devq, dev_event_info);
236
237 static struct dev_softc
238 {
239 int inuse;
240 int nonblock;
241 struct mtx mtx;
242 struct cv cv;
243 struct selinfo sel;
244 struct devq devq;
245 struct proc *async_proc;
246 } devsoftc;
247
248 static dev_t devctl_dev;
249
250 static void
251 devinit(void)
252 {
253 devctl_dev = make_dev(&dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
254 "devctl");
255 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
256 cv_init(&devsoftc.cv, "dev cv");
257 TAILQ_INIT(&devsoftc.devq);
258 }
259
260 static int
261 devopen(dev_t dev, int oflags, int devtype, d_thread_t *td)
262 {
263 if (devsoftc.inuse)
264 return (EBUSY);
265 /* move to init */
266 devsoftc.inuse = 1;
267 devsoftc.nonblock = 0;
268 devsoftc.async_proc = NULL;
269 return (0);
270 }
271
272 static int
273 devclose(dev_t dev, int fflag, int devtype, d_thread_t *td)
274 {
275 devsoftc.inuse = 0;
276 mtx_lock(&devsoftc.mtx);
277 cv_broadcast(&devsoftc.cv);
278 mtx_unlock(&devsoftc.mtx);
279
280 return (0);
281 }
282
283 /*
284 * The read channel for this device is used to report changes to
285 * userland in realtime. We are required to free the data as well as
286 * the n1 object because we allocate them separately. Also note that
287 * we return one record at a time. If you try to read this device a
288 * character at a time, you will loose the rest of the data. Listening
289 * programs are expected to cope.
290 */
291 static int
292 devread(dev_t dev, struct uio *uio, int ioflag)
293 {
294 struct dev_event_info *n1;
295 int rv;
296
297 mtx_lock(&devsoftc.mtx);
298 while (TAILQ_EMPTY(&devsoftc.devq)) {
299 if (devsoftc.nonblock) {
300 mtx_unlock(&devsoftc.mtx);
301 return (EAGAIN);
302 }
303 rv = cv_wait_sig(&devsoftc.cv, &devsoftc.mtx);
304 if (rv) {
305 /*
306 * Need to translate ERESTART to EINTR here? -- jake
307 */
308 mtx_unlock(&devsoftc.mtx);
309 return (rv);
310 }
311 }
312 n1 = TAILQ_FIRST(&devsoftc.devq);
313 TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
314 mtx_unlock(&devsoftc.mtx);
315 rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
316 free(n1->dei_data, M_BUS);
317 free(n1, M_BUS);
318 return (rv);
319 }
320
321 static int
322 devioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td)
323 {
324 switch (cmd) {
325
326 case FIONBIO:
327 if (*(int*)data)
328 devsoftc.nonblock = 1;
329 else
330 devsoftc.nonblock = 0;
331 return (0);
332 case FIOASYNC:
333 if (*(int*)data)
334 devsoftc.async_proc = td->td_proc;
335 else
336 devsoftc.async_proc = NULL;
337 return (0);
338
339 /* (un)Support for other fcntl() calls. */
340 case FIOCLEX:
341 case FIONCLEX:
342 case FIONREAD:
343 case FIOSETOWN:
344 case FIOGETOWN:
345 default:
346 break;
347 }
348 return (ENOTTY);
349 }
350
351 static int
352 devpoll(dev_t dev, int events, d_thread_t *td)
353 {
354 int revents = 0;
355
356 mtx_lock(&devsoftc.mtx);
357 if (events & (POLLIN | POLLRDNORM)) {
358 if (!TAILQ_EMPTY(&devsoftc.devq))
359 revents = events & (POLLIN | POLLRDNORM);
360 else
361 selrecord(td, &devsoftc.sel);
362 }
363 mtx_unlock(&devsoftc.mtx);
364
365 return (revents);
366 }
367
368 /*
369 * Common routine that tries to make sending messages as easy as possible.
370 * We allocate memory for the data, copy strings into that, but do not
371 * free it unless there's an error. The dequeue part of the driver should
372 * free the data. We don't send data when the device is disabled. We do
373 * send data, even when we have no listeners, because we wish to avoid
374 * races relating to startup and restart of listening applications.
375 */
376 static void
377 devaddq(const char *type, const char *what, device_t dev)
378 {
379 struct dev_event_info *n1 = NULL;
380 struct proc *p;
381 char *data = NULL;
382 char *loc;
383 const char *parstr;
384
385 if (devctl_disable)
386 return;
387 n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
388 if (n1 == NULL)
389 goto bad;
390 data = malloc(1024, M_BUS, M_NOWAIT);
391 if (data == NULL)
392 goto bad;
393 loc = malloc(1024, M_BUS, M_NOWAIT);
394 if (loc == NULL)
395 goto bad;
396 *loc = '\0';
397 bus_child_location_str(dev, loc, 1024);
398 if (device_get_parent(dev) == NULL)
399 parstr = "."; /* Or '/' ? */
400 else
401 parstr = device_get_nameunit(device_get_parent(dev));
402 snprintf(data, 1024, "%s%s at %s on %s\n", type, what, loc, parstr);
403 free(loc, M_BUS);
404 n1->dei_data = data;
405 mtx_lock(&devsoftc.mtx);
406 TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
407 cv_broadcast(&devsoftc.cv);
408 mtx_unlock(&devsoftc.mtx);
409 selwakeup(&devsoftc.sel);
410 p = devsoftc.async_proc;
411 if (p != NULL) {
412 PROC_LOCK(p);
413 psignal(p, SIGIO);
414 PROC_UNLOCK(p);
415 }
416 return;
417 bad:;
418 free(data, M_BUS);
419 free(n1, M_BUS);
420 return;
421 }
422
423 /*
424 * A device was added to the tree. We are called just after it successfully
425 * attaches (that is, probe and attach success for this device). No call
426 * is made if a device is merely parented into the tree. See devnomatch
427 * if probe fails. If attach fails, no notification is sent (but maybe
428 * we should have a different message for this).
429 */
430 static void
431 devadded(device_t dev)
432 {
433 devaddq("+", device_get_nameunit(dev), dev);
434 }
435
436 /*
437 * A device was removed from the tree. We are called just before this
438 * happens.
439 */
440 static void
441 devremoved(device_t dev)
442 {
443 devaddq("-", device_get_nameunit(dev), dev);
444 }
445
446 /*
447 * Called when there's no match for this device. This is only called
448 * the first time that no match happens, so we don't keep getitng this
449 * message. Should that prove to be undesirable, we can change it.
450 * This is called when all drivers that can attach to a given bus
451 * decline to accept this device. Other errrors may not be detected.
452 */
453 static void
454 devnomatch(device_t dev)
455 {
456 char *pnp = NULL;
457
458 pnp = malloc(1024, M_BUS, M_NOWAIT);
459 if (pnp == NULL)
460 return;
461 *pnp = '\0';
462 bus_child_pnpinfo_str(dev, pnp, 1024);
463 devaddq("?", pnp, dev);
464 free(pnp, M_BUS);
465 return;
466 }
467
468 static int
469 sysctl_devctl_disable(SYSCTL_HANDLER_ARGS)
470 {
471 struct dev_event_info *n1;
472 int dis, error;
473
474 dis = devctl_disable;
475 error = sysctl_handle_int(oidp, &dis, 0, req);
476 if (error || !req->newptr)
477 return (error);
478 mtx_lock(&devsoftc.mtx);
479 devctl_disable = dis;
480 if (dis) {
481 while (!TAILQ_EMPTY(&devsoftc.devq)) {
482 n1 = TAILQ_FIRST(&devsoftc.devq);
483 TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
484 free(n1->dei_data, M_BUS);
485 free(n1, M_BUS);
486 }
487 }
488 mtx_unlock(&devsoftc.mtx);
489 return (0);
490 }
491
492 /* End of /dev/devctl code */
493
494 TAILQ_HEAD(,device) bus_data_devices;
495 static int bus_data_generation = 1;
496
497 kobj_method_t null_methods[] = {
498 { 0, 0 }
499 };
500
501 DEFINE_CLASS(null, null_methods, 0);
502
503 /*
504 * Devclass implementation
505 */
506
507 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
508
509 static devclass_t
510 devclass_find_internal(const char *classname, int create)
511 {
512 devclass_t dc;
513
514 PDEBUG(("looking for %s", classname));
515 if (!classname)
516 return (NULL);
517
518 TAILQ_FOREACH(dc, &devclasses, link) {
519 if (!strcmp(dc->name, classname))
520 return (dc);
521 }
522
523 PDEBUG(("%s not found%s", classname, (create? ", creating": "")));
524 if (create) {
525 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
526 M_BUS, M_NOWAIT|M_ZERO);
527 if (!dc)
528 return (NULL);
529 dc->name = (char*) (dc + 1);
530 strcpy(dc->name, classname);
531 TAILQ_INIT(&dc->drivers);
532 TAILQ_INSERT_TAIL(&devclasses, dc, link);
533
534 bus_data_generation_update();
535 }
536
537 return (dc);
538 }
539
540 devclass_t
541 devclass_create(const char *classname)
542 {
543 return (devclass_find_internal(classname, TRUE));
544 }
545
546 devclass_t
547 devclass_find(const char *classname)
548 {
549 return (devclass_find_internal(classname, FALSE));
550 }
551
552 int
553 devclass_add_driver(devclass_t dc, driver_t *driver)
554 {
555 driverlink_t dl;
556 int i;
557
558 PDEBUG(("%s", DRIVERNAME(driver)));
559
560 dl = malloc(sizeof *dl, M_BUS, M_NOWAIT|M_ZERO);
561 if (!dl)
562 return (ENOMEM);
563
564 /*
565 * Compile the driver's methods. Also increase the reference count
566 * so that the class doesn't get freed when the last instance
567 * goes. This means we can safely use static methods and avoids a
568 * double-free in devclass_delete_driver.
569 */
570 kobj_class_compile((kobj_class_t) driver);
571
572 /*
573 * Make sure the devclass which the driver is implementing exists.
574 */
575 devclass_find_internal(driver->name, TRUE);
576
577 dl->driver = driver;
578 TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
579 driver->refs++;
580
581 /*
582 * Call BUS_DRIVER_ADDED for any existing busses in this class.
583 */
584 for (i = 0; i < dc->maxunit; i++)
585 if (dc->devices[i])
586 BUS_DRIVER_ADDED(dc->devices[i], driver);
587
588 bus_data_generation_update();
589 return (0);
590 }
591
592 int
593 devclass_delete_driver(devclass_t busclass, driver_t *driver)
594 {
595 devclass_t dc = devclass_find(driver->name);
596 driverlink_t dl;
597 device_t dev;
598 int i;
599 int error;
600
601 PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
602
603 if (!dc)
604 return (0);
605
606 /*
607 * Find the link structure in the bus' list of drivers.
608 */
609 TAILQ_FOREACH(dl, &busclass->drivers, link) {
610 if (dl->driver == driver)
611 break;
612 }
613
614 if (!dl) {
615 PDEBUG(("%s not found in %s list", driver->name,
616 busclass->name));
617 return (ENOENT);
618 }
619
620 /*
621 * Disassociate from any devices. We iterate through all the
622 * devices in the devclass of the driver and detach any which are
623 * using the driver and which have a parent in the devclass which
624 * we are deleting from.
625 *
626 * Note that since a driver can be in multiple devclasses, we
627 * should not detach devices which are not children of devices in
628 * the affected devclass.
629 */
630 for (i = 0; i < dc->maxunit; i++) {
631 if (dc->devices[i]) {
632 dev = dc->devices[i];
633 if (dev->driver == driver && dev->parent &&
634 dev->parent->devclass == busclass) {
635 if ((error = device_detach(dev)) != 0)
636 return (error);
637 device_set_driver(dev, NULL);
638 }
639 }
640 }
641
642 TAILQ_REMOVE(&busclass->drivers, dl, link);
643 free(dl, M_BUS);
644
645 driver->refs--;
646 if (driver->refs == 0)
647 kobj_class_free((kobj_class_t) driver);
648
649 bus_data_generation_update();
650 return (0);
651 }
652
653 static driverlink_t
654 devclass_find_driver_internal(devclass_t dc, const char *classname)
655 {
656 driverlink_t dl;
657
658 PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
659
660 TAILQ_FOREACH(dl, &dc->drivers, link) {
661 if (!strcmp(dl->driver->name, classname))
662 return (dl);
663 }
664
665 PDEBUG(("not found"));
666 return (NULL);
667 }
668
669 driver_t *
670 devclass_find_driver(devclass_t dc, const char *classname)
671 {
672 driverlink_t dl;
673
674 dl = devclass_find_driver_internal(dc, classname);
675 if (dl)
676 return (dl->driver);
677 return (NULL);
678 }
679
680 const char *
681 devclass_get_name(devclass_t dc)
682 {
683 return (dc->name);
684 }
685
686 device_t
687 devclass_get_device(devclass_t dc, int unit)
688 {
689 if (dc == NULL || unit < 0 || unit >= dc->maxunit)
690 return (NULL);
691 return (dc->devices[unit]);
692 }
693
694 void *
695 devclass_get_softc(devclass_t dc, int unit)
696 {
697 device_t dev;
698
699 dev = devclass_get_device(dc, unit);
700 if (!dev)
701 return (NULL);
702
703 return (device_get_softc(dev));
704 }
705
706 int
707 devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
708 {
709 int i;
710 int count;
711 device_t *list;
712
713 count = 0;
714 for (i = 0; i < dc->maxunit; i++)
715 if (dc->devices[i])
716 count++;
717
718 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
719 if (!list)
720 return (ENOMEM);
721
722 count = 0;
723 for (i = 0; i < dc->maxunit; i++) {
724 if (dc->devices[i]) {
725 list[count] = dc->devices[i];
726 count++;
727 }
728 }
729
730 *devlistp = list;
731 *devcountp = count;
732
733 return (0);
734 }
735
736 int
737 devclass_get_maxunit(devclass_t dc)
738 {
739 return (dc->maxunit);
740 }
741
742 int
743 devclass_find_free_unit(devclass_t dc, int unit)
744 {
745 if (dc == NULL)
746 return (unit);
747 while (unit < dc->maxunit && dc->devices[unit] != NULL)
748 unit++;
749 return (unit);
750 }
751
752 static int
753 devclass_alloc_unit(devclass_t dc, int *unitp)
754 {
755 int unit = *unitp;
756
757 PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
758
759 /* If we were given a wired unit number, check for existing device */
760 /* XXX imp XXX */
761 if (unit != -1) {
762 if (unit >= 0 && unit < dc->maxunit &&
763 dc->devices[unit] != NULL) {
764 if (bootverbose)
765 printf("%s: %s%d already exists; skipping it\n",
766 dc->name, dc->name, *unitp);
767 return (EEXIST);
768 }
769 } else {
770 /* Unwired device, find the next available slot for it */
771 unit = 0;
772 while (unit < dc->maxunit && dc->devices[unit] != NULL)
773 unit++;
774 }
775
776 /*
777 * We've selected a unit beyond the length of the table, so let's
778 * extend the table to make room for all units up to and including
779 * this one.
780 */
781 if (unit >= dc->maxunit) {
782 device_t *newlist;
783 int newsize;
784
785 newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t));
786 newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT);
787 if (!newlist)
788 return (ENOMEM);
789 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
790 bzero(newlist + dc->maxunit,
791 sizeof(device_t) * (newsize - dc->maxunit));
792 if (dc->devices)
793 free(dc->devices, M_BUS);
794 dc->devices = newlist;
795 dc->maxunit = newsize;
796 }
797 PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
798
799 *unitp = unit;
800 return (0);
801 }
802
803 static int
804 devclass_add_device(devclass_t dc, device_t dev)
805 {
806 int buflen, error;
807
808 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
809
810 buflen = snprintf(NULL, 0, "%s%d$", dc->name, dev->unit);
811 if (buflen < 0)
812 return (ENOMEM);
813 dev->nameunit = malloc(buflen, M_BUS, M_NOWAIT|M_ZERO);
814 if (!dev->nameunit)
815 return (ENOMEM);
816
817 if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
818 free(dev->nameunit, M_BUS);
819 dev->nameunit = NULL;
820 return (error);
821 }
822 dc->devices[dev->unit] = dev;
823 dev->devclass = dc;
824 snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
825
826 return (0);
827 }
828
829 static int
830 devclass_delete_device(devclass_t dc, device_t dev)
831 {
832 if (!dc || !dev)
833 return (0);
834
835 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
836
837 if (dev->devclass != dc || dc->devices[dev->unit] != dev)
838 panic("devclass_delete_device: inconsistent device class");
839 dc->devices[dev->unit] = NULL;
840 if (dev->flags & DF_WILDCARD)
841 dev->unit = -1;
842 dev->devclass = NULL;
843 free(dev->nameunit, M_BUS);
844 dev->nameunit = NULL;
845
846 return (0);
847 }
848
849 static device_t
850 make_device(device_t parent, const char *name, int unit)
851 {
852 device_t dev;
853 devclass_t dc;
854
855 PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
856
857 if (name) {
858 dc = devclass_find_internal(name, TRUE);
859 if (!dc) {
860 printf("make_device: can't find device class %s\n",
861 name);
862 return (NULL);
863 }
864 } else {
865 dc = NULL;
866 }
867
868 dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT|M_ZERO);
869 if (!dev)
870 return (NULL);
871
872 dev->parent = parent;
873 TAILQ_INIT(&dev->children);
874 kobj_init((kobj_t) dev, &null_class);
875 dev->driver = NULL;
876 dev->devclass = NULL;
877 dev->unit = unit;
878 dev->nameunit = NULL;
879 dev->desc = NULL;
880 dev->busy = 0;
881 dev->devflags = 0;
882 dev->flags = DF_ENABLED;
883 dev->order = 0;
884 if (unit == -1)
885 dev->flags |= DF_WILDCARD;
886 if (name) {
887 dev->flags |= DF_FIXEDCLASS;
888 if (devclass_add_device(dc, dev)) {
889 kobj_delete((kobj_t) dev, M_BUS);
890 return (NULL);
891 }
892 }
893 dev->ivars = NULL;
894 dev->softc = NULL;
895
896 dev->state = DS_NOTPRESENT;
897
898 TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
899 bus_data_generation_update();
900
901 return (dev);
902 }
903
904 static int
905 device_print_child(device_t dev, device_t child)
906 {
907 int retval = 0;
908
909 if (device_is_alive(child))
910 retval += BUS_PRINT_CHILD(dev, child);
911 else
912 retval += device_printf(child, " not found\n");
913
914 return (retval);
915 }
916
917 device_t
918 device_add_child(device_t dev, const char *name, int unit)
919 {
920 return (device_add_child_ordered(dev, 0, name, unit));
921 }
922
923 device_t
924 device_add_child_ordered(device_t dev, int order, const char *name, int unit)
925 {
926 device_t child;
927 device_t place;
928
929 PDEBUG(("%s at %s with order %d as unit %d",
930 name, DEVICENAME(dev), order, unit));
931
932 child = make_device(dev, name, unit);
933 if (child == NULL)
934 return (child);
935 child->order = order;
936
937 TAILQ_FOREACH(place, &dev->children, link) {
938 if (place->order > order)
939 break;
940 }
941
942 if (place) {
943 /*
944 * The device 'place' is the first device whose order is
945 * greater than the new child.
946 */
947 TAILQ_INSERT_BEFORE(place, child, link);
948 } else {
949 /*
950 * The new child's order is greater or equal to the order of
951 * any existing device. Add the child to the tail of the list.
952 */
953 TAILQ_INSERT_TAIL(&dev->children, child, link);
954 }
955
956 bus_data_generation_update();
957 return (child);
958 }
959
960 int
961 device_delete_child(device_t dev, device_t child)
962 {
963 int error;
964 device_t grandchild;
965
966 PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
967
968 /* remove children first */
969 while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
970 error = device_delete_child(child, grandchild);
971 if (error)
972 return (error);
973 }
974
975 if ((error = device_detach(child)) != 0)
976 return (error);
977 if (child->devclass)
978 devclass_delete_device(child->devclass, child);
979 TAILQ_REMOVE(&dev->children, child, link);
980 TAILQ_REMOVE(&bus_data_devices, child, devlink);
981 device_set_desc(child, NULL);
982 kobj_delete((kobj_t) child, M_BUS);
983
984 bus_data_generation_update();
985 return (0);
986 }
987
988 /*
989 * Find only devices attached to this bus.
990 */
991 device_t
992 device_find_child(device_t dev, const char *classname, int unit)
993 {
994 devclass_t dc;
995 device_t child;
996
997 dc = devclass_find(classname);
998 if (!dc)
999 return (NULL);
1000
1001 child = devclass_get_device(dc, unit);
1002 if (child && child->parent == dev)
1003 return (child);
1004 return (NULL);
1005 }
1006
1007 static driverlink_t
1008 first_matching_driver(devclass_t dc, device_t dev)
1009 {
1010 if (dev->devclass)
1011 return (devclass_find_driver_internal(dc, dev->devclass->name));
1012 return (TAILQ_FIRST(&dc->drivers));
1013 }
1014
1015 static driverlink_t
1016 next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
1017 {
1018 if (dev->devclass) {
1019 driverlink_t dl;
1020 for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
1021 if (!strcmp(dev->devclass->name, dl->driver->name))
1022 return (dl);
1023 return (NULL);
1024 }
1025 return (TAILQ_NEXT(last, link));
1026 }
1027
1028 static int
1029 device_probe_child(device_t dev, device_t child)
1030 {
1031 devclass_t dc;
1032 driverlink_t best = 0;
1033 driverlink_t dl;
1034 int result, pri = 0;
1035 int hasclass = (child->devclass != 0);
1036
1037 dc = dev->devclass;
1038 if (!dc)
1039 panic("device_probe_child: parent device has no devclass");
1040
1041 if (child->state == DS_ALIVE)
1042 return (0);
1043
1044 for (dl = first_matching_driver(dc, child);
1045 dl;
1046 dl = next_matching_driver(dc, child, dl)) {
1047 PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
1048 device_set_driver(child, dl->driver);
1049 if (!hasclass)
1050 device_set_devclass(child, dl->driver->name);
1051 result = DEVICE_PROBE(child);
1052 if (!hasclass)
1053 device_set_devclass(child, 0);
1054
1055 /*
1056 * If the driver returns SUCCESS, there can be no higher match
1057 * for this device.
1058 */
1059 if (result == 0) {
1060 best = dl;
1061 pri = 0;
1062 break;
1063 }
1064
1065 /*
1066 * The driver returned an error so it certainly doesn't match.
1067 */
1068 if (result > 0) {
1069 device_set_driver(child, 0);
1070 continue;
1071 }
1072
1073 /*
1074 * A priority lower than SUCCESS, remember the best matching
1075 * driver. Initialise the value of pri for the first match.
1076 */
1077 if (best == 0 || result > pri) {
1078 best = dl;
1079 pri = result;
1080 continue;
1081 }
1082 }
1083
1084 /*
1085 * If we found a driver, change state and initialise the devclass.
1086 */
1087 if (best) {
1088 if (!child->devclass)
1089 device_set_devclass(child, best->driver->name);
1090 device_set_driver(child, best->driver);
1091 if (pri < 0) {
1092 /*
1093 * A bit bogus. Call the probe method again to make
1094 * sure that we have the right description.
1095 */
1096 DEVICE_PROBE(child);
1097 }
1098 child->state = DS_ALIVE;
1099
1100 bus_data_generation_update();
1101 return (0);
1102 }
1103
1104 return (ENXIO);
1105 }
1106
1107 device_t
1108 device_get_parent(device_t dev)
1109 {
1110 return (dev->parent);
1111 }
1112
1113 int
1114 device_get_children(device_t dev, device_t **devlistp, int *devcountp)
1115 {
1116 int count;
1117 device_t child;
1118 device_t *list;
1119
1120 count = 0;
1121 TAILQ_FOREACH(child, &dev->children, link) {
1122 count++;
1123 }
1124
1125 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
1126 if (!list)
1127 return (ENOMEM);
1128
1129 count = 0;
1130 TAILQ_FOREACH(child, &dev->children, link) {
1131 list[count] = child;
1132 count++;
1133 }
1134
1135 *devlistp = list;
1136 *devcountp = count;
1137
1138 return (0);
1139 }
1140
1141 driver_t *
1142 device_get_driver(device_t dev)
1143 {
1144 return (dev->driver);
1145 }
1146
1147 devclass_t
1148 device_get_devclass(device_t dev)
1149 {
1150 return (dev->devclass);
1151 }
1152
1153 const char *
1154 device_get_name(device_t dev)
1155 {
1156 if (dev != NULL && dev->devclass)
1157 return (devclass_get_name(dev->devclass));
1158 return (NULL);
1159 }
1160
1161 const char *
1162 device_get_nameunit(device_t dev)
1163 {
1164 return (dev->nameunit);
1165 }
1166
1167 int
1168 device_get_unit(device_t dev)
1169 {
1170 return (dev->unit);
1171 }
1172
1173 const char *
1174 device_get_desc(device_t dev)
1175 {
1176 return (dev->desc);
1177 }
1178
1179 u_int32_t
1180 device_get_flags(device_t dev)
1181 {
1182 return (dev->devflags);
1183 }
1184
1185 int
1186 device_print_prettyname(device_t dev)
1187 {
1188 const char *name = device_get_name(dev);
1189
1190 if (name == 0)
1191 return (printf("unknown: "));
1192 return (printf("%s%d: ", name, device_get_unit(dev)));
1193 }
1194
1195 int
1196 device_printf(device_t dev, const char * fmt, ...)
1197 {
1198 va_list ap;
1199 int retval;
1200
1201 retval = device_print_prettyname(dev);
1202 va_start(ap, fmt);
1203 retval += vprintf(fmt, ap);
1204 va_end(ap);
1205 return (retval);
1206 }
1207
1208 static void
1209 device_set_desc_internal(device_t dev, const char* desc, int copy)
1210 {
1211 if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
1212 free(dev->desc, M_BUS);
1213 dev->flags &= ~DF_DESCMALLOCED;
1214 dev->desc = NULL;
1215 }
1216
1217 if (copy && desc) {
1218 dev->desc = malloc(strlen(desc) + 1, M_BUS, M_NOWAIT);
1219 if (dev->desc) {
1220 strcpy(dev->desc, desc);
1221 dev->flags |= DF_DESCMALLOCED;
1222 }
1223 } else {
1224 /* Avoid a -Wcast-qual warning */
1225 dev->desc = (char *)(uintptr_t) desc;
1226 }
1227
1228 bus_data_generation_update();
1229 }
1230
1231 void
1232 device_set_desc(device_t dev, const char* desc)
1233 {
1234 device_set_desc_internal(dev, desc, FALSE);
1235 }
1236
1237 void
1238 device_set_desc_copy(device_t dev, const char* desc)
1239 {
1240 device_set_desc_internal(dev, desc, TRUE);
1241 }
1242
1243 void
1244 device_set_flags(device_t dev, u_int32_t flags)
1245 {
1246 dev->devflags = flags;
1247 }
1248
1249 void *
1250 device_get_softc(device_t dev)
1251 {
1252 return (dev->softc);
1253 }
1254
1255 void
1256 device_set_softc(device_t dev, void *softc)
1257 {
1258 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
1259 free(dev->softc, M_BUS);
1260 dev->softc = softc;
1261 if (dev->softc)
1262 dev->flags |= DF_EXTERNALSOFTC;
1263 else
1264 dev->flags &= ~DF_EXTERNALSOFTC;
1265 }
1266
1267 void *
1268 device_get_ivars(device_t dev)
1269 {
1270
1271 KASSERT(dev != NULL, ("device_get_ivars(NULL, ...)"));
1272 return (dev->ivars);
1273 }
1274
1275 void
1276 device_set_ivars(device_t dev, void * ivars)
1277 {
1278
1279 KASSERT(dev != NULL, ("device_set_ivars(NULL, ...)"));
1280 dev->ivars = ivars;
1281 }
1282
1283 device_state_t
1284 device_get_state(device_t dev)
1285 {
1286 return (dev->state);
1287 }
1288
1289 void
1290 device_enable(device_t dev)
1291 {
1292 dev->flags |= DF_ENABLED;
1293 }
1294
1295 void
1296 device_disable(device_t dev)
1297 {
1298 dev->flags &= ~DF_ENABLED;
1299 }
1300
1301 void
1302 device_busy(device_t dev)
1303 {
1304 if (dev->state < DS_ATTACHED)
1305 panic("device_busy: called for unattached device");
1306 if (dev->busy == 0 && dev->parent)
1307 device_busy(dev->parent);
1308 dev->busy++;
1309 dev->state = DS_BUSY;
1310 }
1311
1312 void
1313 device_unbusy(device_t dev)
1314 {
1315 if (dev->state != DS_BUSY)
1316 panic("device_unbusy: called for non-busy device");
1317 dev->busy--;
1318 if (dev->busy == 0) {
1319 if (dev->parent)
1320 device_unbusy(dev->parent);
1321 dev->state = DS_ATTACHED;
1322 }
1323 }
1324
1325 void
1326 device_quiet(device_t dev)
1327 {
1328 dev->flags |= DF_QUIET;
1329 }
1330
1331 void
1332 device_verbose(device_t dev)
1333 {
1334 dev->flags &= ~DF_QUIET;
1335 }
1336
1337 int
1338 device_is_quiet(device_t dev)
1339 {
1340 return ((dev->flags & DF_QUIET) != 0);
1341 }
1342
1343 int
1344 device_is_enabled(device_t dev)
1345 {
1346 return ((dev->flags & DF_ENABLED) != 0);
1347 }
1348
1349 int
1350 device_is_alive(device_t dev)
1351 {
1352 return (dev->state >= DS_ALIVE);
1353 }
1354
1355 int
1356 device_is_attached(device_t dev)
1357 {
1358 return (dev->state >= DS_ATTACHED);
1359 }
1360
1361 int
1362 device_set_devclass(device_t dev, const char *classname)
1363 {
1364 devclass_t dc;
1365 int error;
1366
1367 if (!classname) {
1368 if (dev->devclass)
1369 devclass_delete_device(dev->devclass, dev);
1370 return (0);
1371 }
1372
1373 if (dev->devclass) {
1374 printf("device_set_devclass: device class already set\n");
1375 return (EINVAL);
1376 }
1377
1378 dc = devclass_find_internal(classname, TRUE);
1379 if (!dc)
1380 return (ENOMEM);
1381
1382 error = devclass_add_device(dc, dev);
1383
1384 bus_data_generation_update();
1385 return (error);
1386 }
1387
1388 int
1389 device_set_driver(device_t dev, driver_t *driver)
1390 {
1391 if (dev->state >= DS_ATTACHED)
1392 return (EBUSY);
1393
1394 if (dev->driver == driver)
1395 return (0);
1396
1397 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
1398 free(dev->softc, M_BUS);
1399 dev->softc = NULL;
1400 }
1401 kobj_delete((kobj_t) dev, 0);
1402 dev->driver = driver;
1403 if (driver) {
1404 kobj_init((kobj_t) dev, (kobj_class_t) driver);
1405 if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) {
1406 dev->softc = malloc(driver->size, M_BUS,
1407 M_NOWAIT | M_ZERO);
1408 if (!dev->softc) {
1409 kobj_delete((kobj_t) dev, 0);
1410 kobj_init((kobj_t) dev, &null_class);
1411 dev->driver = NULL;
1412 return (ENOMEM);
1413 }
1414 }
1415 } else {
1416 kobj_init((kobj_t) dev, &null_class);
1417 }
1418
1419 bus_data_generation_update();
1420 return (0);
1421 }
1422
1423 int
1424 device_probe_and_attach(device_t dev)
1425 {
1426 device_t bus = dev->parent;
1427 int error = 0;
1428 int hasclass = (dev->devclass != 0);
1429
1430 if (dev->state >= DS_ALIVE)
1431 return (0);
1432
1433 if (dev->flags & DF_ENABLED) {
1434 error = device_probe_child(bus, dev);
1435 if (!error) {
1436 if (!device_is_quiet(dev))
1437 device_print_child(bus, dev);
1438 error = DEVICE_ATTACH(dev);
1439 if (!error) {
1440 dev->state = DS_ATTACHED;
1441 devadded(dev);
1442 } else {
1443 printf("device_probe_and_attach: %s%d attach returned %d\n",
1444 dev->driver->name, dev->unit, error);
1445 /* Unset the class; set in device_probe_child */
1446 if (!hasclass)
1447 device_set_devclass(dev, 0);
1448 device_set_driver(dev, NULL);
1449 dev->state = DS_NOTPRESENT;
1450 }
1451 } else {
1452 if (!(dev->flags & DF_DONENOMATCH)) {
1453 BUS_PROBE_NOMATCH(bus, dev);
1454 devnomatch(dev);
1455 dev->flags |= DF_DONENOMATCH;
1456 }
1457 }
1458 } else {
1459 if (bootverbose) {
1460 device_print_prettyname(dev);
1461 printf("not probed (disabled)\n");
1462 }
1463 }
1464
1465 return (error);
1466 }
1467
1468 int
1469 device_detach(device_t dev)
1470 {
1471 int error;
1472
1473 PDEBUG(("%s", DEVICENAME(dev)));
1474 if (dev->state == DS_BUSY)
1475 return (EBUSY);
1476 if (dev->state != DS_ATTACHED)
1477 return (0);
1478
1479 if ((error = DEVICE_DETACH(dev)) != 0)
1480 return (error);
1481 devremoved(dev);
1482 device_printf(dev, "detached\n");
1483 if (dev->parent)
1484 BUS_CHILD_DETACHED(dev->parent, dev);
1485
1486 if (!(dev->flags & DF_FIXEDCLASS))
1487 devclass_delete_device(dev->devclass, dev);
1488
1489 dev->state = DS_NOTPRESENT;
1490 device_set_driver(dev, NULL);
1491
1492 return (0);
1493 }
1494
1495 int
1496 device_shutdown(device_t dev)
1497 {
1498 if (dev->state < DS_ATTACHED)
1499 return (0);
1500 return (DEVICE_SHUTDOWN(dev));
1501 }
1502
1503 int
1504 device_set_unit(device_t dev, int unit)
1505 {
1506 devclass_t dc;
1507 int err;
1508
1509 dc = device_get_devclass(dev);
1510 if (unit < dc->maxunit && dc->devices[unit])
1511 return (EBUSY);
1512 err = devclass_delete_device(dc, dev);
1513 if (err)
1514 return (err);
1515 dev->unit = unit;
1516 err = devclass_add_device(dc, dev);
1517 if (err)
1518 return (err);
1519
1520 bus_data_generation_update();
1521 return (0);
1522 }
1523
1524 /*======================================*/
1525 /*
1526 * Some useful method implementations to make life easier for bus drivers.
1527 */
1528
1529 void
1530 resource_list_init(struct resource_list *rl)
1531 {
1532 SLIST_INIT(rl);
1533 }
1534
1535 void
1536 resource_list_free(struct resource_list *rl)
1537 {
1538 struct resource_list_entry *rle;
1539
1540 while ((rle = SLIST_FIRST(rl)) != NULL) {
1541 if (rle->res)
1542 panic("resource_list_free: resource entry is busy");
1543 SLIST_REMOVE_HEAD(rl, link);
1544 free(rle, M_BUS);
1545 }
1546 }
1547
1548 int
1549 resource_list_add_next(struct resource_list *rl, int type, u_long start,
1550 u_long end, u_long count)
1551 {
1552 int rid;
1553
1554 rid = 0;
1555 while (resource_list_find(rl, type, rid) != NULL)
1556 rid++;
1557 resource_list_add(rl, type, rid, start, end, count);
1558 return (rid);
1559 }
1560
1561 void
1562 resource_list_add(struct resource_list *rl, int type, int rid,
1563 u_long start, u_long end, u_long count)
1564 {
1565 struct resource_list_entry *rle;
1566
1567 rle = resource_list_find(rl, type, rid);
1568 if (!rle) {
1569 rle = malloc(sizeof(struct resource_list_entry), M_BUS,
1570 M_NOWAIT);
1571 if (!rle)
1572 panic("resource_list_add: can't record entry");
1573 SLIST_INSERT_HEAD(rl, rle, link);
1574 rle->type = type;
1575 rle->rid = rid;
1576 rle->res = NULL;
1577 }
1578
1579 if (rle->res)
1580 panic("resource_list_add: resource entry is busy");
1581
1582 rle->start = start;
1583 rle->end = end;
1584 rle->count = count;
1585 }
1586
1587 struct resource_list_entry *
1588 resource_list_find(struct resource_list *rl, int type, int rid)
1589 {
1590 struct resource_list_entry *rle;
1591
1592 SLIST_FOREACH(rle, rl, link) {
1593 if (rle->type == type && rle->rid == rid)
1594 return (rle);
1595 }
1596 return (NULL);
1597 }
1598
1599 void
1600 resource_list_delete(struct resource_list *rl, int type, int rid)
1601 {
1602 struct resource_list_entry *rle = resource_list_find(rl, type, rid);
1603
1604 if (rle) {
1605 if (rle->res != NULL)
1606 panic("resource_list_delete: resource has not been released");
1607 SLIST_REMOVE(rl, rle, resource_list_entry, link);
1608 free(rle, M_BUS);
1609 }
1610 }
1611
1612 struct resource *
1613 resource_list_alloc(struct resource_list *rl, device_t bus, device_t child,
1614 int type, int *rid, u_long start, u_long end, u_long count, u_int flags)
1615 {
1616 struct resource_list_entry *rle = 0;
1617 int passthrough = (device_get_parent(child) != bus);
1618 int isdefault = (start == 0UL && end == ~0UL);
1619
1620 if (passthrough) {
1621 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
1622 type, rid, start, end, count, flags));
1623 }
1624
1625 rle = resource_list_find(rl, type, *rid);
1626
1627 if (!rle)
1628 return (NULL); /* no resource of that type/rid */
1629
1630 if (rle->res)
1631 panic("resource_list_alloc: resource entry is busy");
1632
1633 if (isdefault) {
1634 start = rle->start;
1635 count = ulmax(count, rle->count);
1636 end = ulmax(rle->end, start + count - 1);
1637 }
1638
1639 rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
1640 type, rid, start, end, count, flags);
1641
1642 /*
1643 * Record the new range.
1644 */
1645 if (rle->res) {
1646 rle->start = rman_get_start(rle->res);
1647 rle->end = rman_get_end(rle->res);
1648 rle->count = count;
1649 }
1650
1651 return (rle->res);
1652 }
1653
1654 int
1655 resource_list_release(struct resource_list *rl, device_t bus, device_t child,
1656 int type, int rid, struct resource *res)
1657 {
1658 struct resource_list_entry *rle = 0;
1659 int passthrough = (device_get_parent(child) != bus);
1660 int error;
1661
1662 if (passthrough) {
1663 return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
1664 type, rid, res));
1665 }
1666
1667 rle = resource_list_find(rl, type, rid);
1668
1669 if (!rle)
1670 panic("resource_list_release: can't find resource");
1671 if (!rle->res)
1672 panic("resource_list_release: resource entry is not busy");
1673
1674 error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
1675 type, rid, res);
1676 if (error)
1677 return (error);
1678
1679 rle->res = NULL;
1680 return (0);
1681 }
1682
1683 int
1684 resource_list_print_type(struct resource_list *rl, const char *name, int type,
1685 const char *format)
1686 {
1687 struct resource_list_entry *rle;
1688 int printed, retval;
1689
1690 printed = 0;
1691 retval = 0;
1692 /* Yes, this is kinda cheating */
1693 SLIST_FOREACH(rle, rl, link) {
1694 if (rle->type == type) {
1695 if (printed == 0)
1696 retval += printf(" %s ", name);
1697 else
1698 retval += printf(",");
1699 printed++;
1700 retval += printf(format, rle->start);
1701 if (rle->count > 1) {
1702 retval += printf("-");
1703 retval += printf(format, rle->start +
1704 rle->count - 1);
1705 }
1706 }
1707 }
1708 return (retval);
1709 }
1710
1711 /*
1712 * Call DEVICE_IDENTIFY for each driver.
1713 */
1714 int
1715 bus_generic_probe(device_t dev)
1716 {
1717 devclass_t dc = dev->devclass;
1718 driverlink_t dl;
1719
1720 TAILQ_FOREACH(dl, &dc->drivers, link) {
1721 DEVICE_IDENTIFY(dl->driver, dev);
1722 }
1723
1724 return (0);
1725 }
1726
1727 int
1728 bus_generic_attach(device_t dev)
1729 {
1730 device_t child;
1731
1732 TAILQ_FOREACH(child, &dev->children, link) {
1733 device_probe_and_attach(child);
1734 }
1735
1736 return (0);
1737 }
1738
1739 int
1740 bus_generic_detach(device_t dev)
1741 {
1742 device_t child;
1743 int error;
1744
1745 if (dev->state != DS_ATTACHED)
1746 return (EBUSY);
1747
1748 TAILQ_FOREACH(child, &dev->children, link) {
1749 if ((error = device_detach(child)) != 0)
1750 return (error);
1751 }
1752
1753 return (0);
1754 }
1755
1756 int
1757 bus_generic_shutdown(device_t dev)
1758 {
1759 device_t child;
1760
1761 TAILQ_FOREACH(child, &dev->children, link) {
1762 device_shutdown(child);
1763 }
1764
1765 return (0);
1766 }
1767
1768 int
1769 bus_generic_suspend(device_t dev)
1770 {
1771 int error;
1772 device_t child, child2;
1773
1774 TAILQ_FOREACH(child, &dev->children, link) {
1775 error = DEVICE_SUSPEND(child);
1776 if (error) {
1777 for (child2 = TAILQ_FIRST(&dev->children);
1778 child2 && child2 != child;
1779 child2 = TAILQ_NEXT(child2, link))
1780 DEVICE_RESUME(child2);
1781 return (error);
1782 }
1783 }
1784 return (0);
1785 }
1786
1787 int
1788 bus_generic_resume(device_t dev)
1789 {
1790 device_t child;
1791
1792 TAILQ_FOREACH(child, &dev->children, link) {
1793 DEVICE_RESUME(child);
1794 /* if resume fails, there's nothing we can usefully do... */
1795 }
1796 return (0);
1797 }
1798
1799 int
1800 bus_print_child_header (device_t dev, device_t child)
1801 {
1802 int retval = 0;
1803
1804 if (device_get_desc(child)) {
1805 retval += device_printf(child, "<%s>", device_get_desc(child));
1806 } else {
1807 retval += printf("%s", device_get_nameunit(child));
1808 }
1809
1810 return (retval);
1811 }
1812
1813 int
1814 bus_print_child_footer (device_t dev, device_t child)
1815 {
1816 return (printf(" on %s\n", device_get_nameunit(dev)));
1817 }
1818
1819 int
1820 bus_generic_print_child(device_t dev, device_t child)
1821 {
1822 int retval = 0;
1823
1824 retval += bus_print_child_header(dev, child);
1825 retval += bus_print_child_footer(dev, child);
1826
1827 return (retval);
1828 }
1829
1830 int
1831 bus_generic_read_ivar(device_t dev, device_t child, int index,
1832 uintptr_t * result)
1833 {
1834 return (ENOENT);
1835 }
1836
1837 int
1838 bus_generic_write_ivar(device_t dev, device_t child, int index,
1839 uintptr_t value)
1840 {
1841 return (ENOENT);
1842 }
1843
1844 struct resource_list *
1845 bus_generic_get_resource_list (device_t dev, device_t child)
1846 {
1847 return (NULL);
1848 }
1849
1850 void
1851 bus_generic_driver_added(device_t dev, driver_t *driver)
1852 {
1853 device_t child;
1854
1855 DEVICE_IDENTIFY(driver, dev);
1856 TAILQ_FOREACH(child, &dev->children, link) {
1857 if (child->state == DS_NOTPRESENT)
1858 device_probe_and_attach(child);
1859 }
1860 }
1861
1862 int
1863 bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
1864 int flags, driver_intr_t *intr, void *arg, void **cookiep)
1865 {
1866 /* Propagate up the bus hierarchy until someone handles it. */
1867 if (dev->parent)
1868 return (BUS_SETUP_INTR(dev->parent, child, irq, flags,
1869 intr, arg, cookiep));
1870 return (EINVAL);
1871 }
1872
1873 int
1874 bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
1875 void *cookie)
1876 {
1877 /* Propagate up the bus hierarchy until someone handles it. */
1878 if (dev->parent)
1879 return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie));
1880 return (EINVAL);
1881 }
1882
1883 struct resource *
1884 bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
1885 u_long start, u_long end, u_long count, u_int flags)
1886 {
1887 /* Propagate up the bus hierarchy until someone handles it. */
1888 if (dev->parent)
1889 return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid,
1890 start, end, count, flags));
1891 return (NULL);
1892 }
1893
1894 int
1895 bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
1896 struct resource *r)
1897 {
1898 /* Propagate up the bus hierarchy until someone handles it. */
1899 if (dev->parent)
1900 return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid,
1901 r));
1902 return (EINVAL);
1903 }
1904
1905 int
1906 bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
1907 struct resource *r)
1908 {
1909 /* Propagate up the bus hierarchy until someone handles it. */
1910 if (dev->parent)
1911 return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid,
1912 r));
1913 return (EINVAL);
1914 }
1915
1916 int
1917 bus_generic_deactivate_resource(device_t dev, device_t child, int type,
1918 int rid, struct resource *r)
1919 {
1920 /* Propagate up the bus hierarchy until someone handles it. */
1921 if (dev->parent)
1922 return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid,
1923 r));
1924 return (EINVAL);
1925 }
1926
1927 int
1928 bus_generic_rl_get_resource (device_t dev, device_t child, int type, int rid,
1929 u_long *startp, u_long *countp)
1930 {
1931 struct resource_list * rl = NULL;
1932 struct resource_list_entry * rle = NULL;
1933
1934 rl = BUS_GET_RESOURCE_LIST(dev, child);
1935 if (!rl)
1936 return (EINVAL);
1937
1938 rle = resource_list_find(rl, type, rid);
1939 if (!rle)
1940 return (ENOENT);
1941
1942 if (startp)
1943 *startp = rle->start;
1944 if (countp)
1945 *countp = rle->count;
1946
1947 return (0);
1948 }
1949
1950 int
1951 bus_generic_rl_set_resource (device_t dev, device_t child, int type, int rid,
1952 u_long start, u_long count)
1953 {
1954 struct resource_list * rl = NULL;
1955
1956 rl = BUS_GET_RESOURCE_LIST(dev, child);
1957 if (!rl)
1958 return (EINVAL);
1959
1960 resource_list_add(rl, type, rid, start, (start + count - 1), count);
1961
1962 return (0);
1963 }
1964
1965 void
1966 bus_generic_rl_delete_resource (device_t dev, device_t child, int type, int rid)
1967 {
1968 struct resource_list * rl = NULL;
1969
1970 rl = BUS_GET_RESOURCE_LIST(dev, child);
1971 if (!rl)
1972 return;
1973
1974 resource_list_delete(rl, type, rid);
1975
1976 return;
1977 }
1978
1979 int
1980 bus_generic_rl_release_resource (device_t dev, device_t child, int type,
1981 int rid, struct resource *r)
1982 {
1983 struct resource_list * rl = NULL;
1984
1985 rl = BUS_GET_RESOURCE_LIST(dev, child);
1986 if (!rl)
1987 return (EINVAL);
1988
1989 return (resource_list_release(rl, dev, child, type, rid, r));
1990 }
1991
1992 struct resource *
1993 bus_generic_rl_alloc_resource (device_t dev, device_t child, int type,
1994 int *rid, u_long start, u_long end, u_long count, u_int flags)
1995 {
1996 struct resource_list * rl = NULL;
1997
1998 rl = BUS_GET_RESOURCE_LIST(dev, child);
1999 if (!rl)
2000 return (NULL);
2001
2002 return (resource_list_alloc(rl, dev, child, type, rid,
2003 start, end, count, flags));
2004 }
2005
2006 int
2007 bus_generic_child_present(device_t bus, device_t child)
2008 {
2009 return (BUS_CHILD_PRESENT(device_get_parent(bus), bus));
2010 }
2011
2012 /*
2013 * Some convenience functions to make it easier for drivers to use the
2014 * resource-management functions. All these really do is hide the
2015 * indirection through the parent's method table, making for slightly
2016 * less-wordy code. In the future, it might make sense for this code
2017 * to maintain some sort of a list of resources allocated by each device.
2018 */
2019 struct resource *
2020 bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
2021 u_long count, u_int flags)
2022 {
2023 if (dev->parent == 0)
2024 return (0);
2025 return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
2026 count, flags));
2027 }
2028
2029 int
2030 bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
2031 {
2032 if (dev->parent == 0)
2033 return (EINVAL);
2034 return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
2035 }
2036
2037 int
2038 bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
2039 {
2040 if (dev->parent == 0)
2041 return (EINVAL);
2042 return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
2043 }
2044
2045 int
2046 bus_release_resource(device_t dev, int type, int rid, struct resource *r)
2047 {
2048 if (dev->parent == 0)
2049 return (EINVAL);
2050 return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
2051 }
2052
2053 int
2054 bus_setup_intr(device_t dev, struct resource *r, int flags,
2055 driver_intr_t handler, void *arg, void **cookiep)
2056 {
2057 if (dev->parent == 0)
2058 return (EINVAL);
2059 return (BUS_SETUP_INTR(dev->parent, dev, r, flags,
2060 handler, arg, cookiep));
2061 }
2062
2063 int
2064 bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
2065 {
2066 if (dev->parent == 0)
2067 return (EINVAL);
2068 return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
2069 }
2070
2071 int
2072 bus_set_resource(device_t dev, int type, int rid,
2073 u_long start, u_long count)
2074 {
2075 return (BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid,
2076 start, count));
2077 }
2078
2079 int
2080 bus_get_resource(device_t dev, int type, int rid,
2081 u_long *startp, u_long *countp)
2082 {
2083 return (BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2084 startp, countp));
2085 }
2086
2087 u_long
2088 bus_get_resource_start(device_t dev, int type, int rid)
2089 {
2090 u_long start, count;
2091 int error;
2092
2093 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2094 &start, &count);
2095 if (error)
2096 return (0);
2097 return (start);
2098 }
2099
2100 u_long
2101 bus_get_resource_count(device_t dev, int type, int rid)
2102 {
2103 u_long start, count;
2104 int error;
2105
2106 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2107 &start, &count);
2108 if (error)
2109 return (0);
2110 return (count);
2111 }
2112
2113 void
2114 bus_delete_resource(device_t dev, int type, int rid)
2115 {
2116 BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid);
2117 }
2118
2119 int
2120 bus_child_present(device_t child)
2121 {
2122 return (BUS_CHILD_PRESENT(device_get_parent(child), child));
2123 }
2124
2125 int
2126 bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen)
2127 {
2128 device_t parent;
2129
2130 parent = device_get_parent(child);
2131 if (parent == NULL) {
2132 *buf = '\0';
2133 return (0);
2134 }
2135 return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen));
2136 }
2137
2138 int
2139 bus_child_location_str(device_t child, char *buf, size_t buflen)
2140 {
2141 device_t parent;
2142
2143 parent = device_get_parent(child);
2144 if (parent == NULL) {
2145 *buf = '\0';
2146 return (0);
2147 }
2148 return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen));
2149 }
2150
2151 static int
2152 root_print_child(device_t dev, device_t child)
2153 {
2154 int retval = 0;
2155
2156 retval += bus_print_child_header(dev, child);
2157 retval += printf("\n");
2158
2159 return (retval);
2160 }
2161
2162 static int
2163 root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
2164 void **cookiep)
2165 {
2166 /*
2167 * If an interrupt mapping gets to here something bad has happened.
2168 */
2169 panic("root_setup_intr");
2170 }
2171
2172 /*
2173 * If we get here, assume that the device is permanant and really is
2174 * present in the system. Removable bus drivers are expected to intercept
2175 * this call long before it gets here. We return -1 so that drivers that
2176 * really care can check vs -1 or some ERRNO returned higher in the food
2177 * chain.
2178 */
2179 static int
2180 root_child_present(device_t dev, device_t child)
2181 {
2182 return (-1);
2183 }
2184
2185 static kobj_method_t root_methods[] = {
2186 /* Device interface */
2187 KOBJMETHOD(device_shutdown, bus_generic_shutdown),
2188 KOBJMETHOD(device_suspend, bus_generic_suspend),
2189 KOBJMETHOD(device_resume, bus_generic_resume),
2190
2191 /* Bus interface */
2192 KOBJMETHOD(bus_print_child, root_print_child),
2193 KOBJMETHOD(bus_read_ivar, bus_generic_read_ivar),
2194 KOBJMETHOD(bus_write_ivar, bus_generic_write_ivar),
2195 KOBJMETHOD(bus_setup_intr, root_setup_intr),
2196 KOBJMETHOD(bus_child_present, root_child_present),
2197
2198 { 0, 0 }
2199 };
2200
2201 static driver_t root_driver = {
2202 "root",
2203 root_methods,
2204 1, /* no softc */
2205 };
2206
2207 device_t root_bus;
2208 devclass_t root_devclass;
2209
2210 static int
2211 root_bus_module_handler(module_t mod, int what, void* arg)
2212 {
2213 switch (what) {
2214 case MOD_LOAD:
2215 TAILQ_INIT(&bus_data_devices);
2216 kobj_class_compile((kobj_class_t) &root_driver);
2217 root_bus = make_device(NULL, "root", 0);
2218 root_bus->desc = "System root bus";
2219 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
2220 root_bus->driver = &root_driver;
2221 root_bus->state = DS_ATTACHED;
2222 root_devclass = devclass_find_internal("root", FALSE);
2223 devinit();
2224 return (0);
2225
2226 case MOD_SHUTDOWN:
2227 device_shutdown(root_bus);
2228 return (0);
2229 }
2230
2231 return (0);
2232 }
2233
2234 static moduledata_t root_bus_mod = {
2235 "rootbus",
2236 root_bus_module_handler,
2237 0
2238 };
2239 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
2240
2241 void
2242 root_bus_configure(void)
2243 {
2244 device_t dev;
2245
2246 PDEBUG(("."));
2247
2248 TAILQ_FOREACH(dev, &root_bus->children, link) {
2249 device_probe_and_attach(dev);
2250 }
2251 }
2252
2253 int
2254 driver_module_handler(module_t mod, int what, void *arg)
2255 {
2256 int error, i;
2257 struct driver_module_data *dmd;
2258 devclass_t bus_devclass;
2259
2260 dmd = (struct driver_module_data *)arg;
2261 bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE);
2262 error = 0;
2263
2264 switch (what) {
2265 case MOD_LOAD:
2266 if (dmd->dmd_chainevh)
2267 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2268
2269 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
2270 PDEBUG(("Loading module: driver %s on bus %s",
2271 DRIVERNAME(dmd->dmd_drivers[i]), dmd->dmd_busname));
2272 error = devclass_add_driver(bus_devclass,
2273 dmd->dmd_drivers[i]);
2274 }
2275 if (error)
2276 break;
2277
2278 /*
2279 * The drivers loaded in this way are assumed to all
2280 * implement the same devclass.
2281 */
2282 *dmd->dmd_devclass =
2283 devclass_find_internal(dmd->dmd_drivers[0]->name, TRUE);
2284 break;
2285
2286 case MOD_UNLOAD:
2287 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
2288 PDEBUG(("Unloading module: driver %s from bus %s",
2289 DRIVERNAME(dmd->dmd_drivers[i]),
2290 dmd->dmd_busname));
2291 error = devclass_delete_driver(bus_devclass,
2292 dmd->dmd_drivers[i]);
2293 }
2294
2295 if (!error && dmd->dmd_chainevh)
2296 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2297 break;
2298 }
2299
2300 return (error);
2301 }
2302
2303 #ifdef BUS_DEBUG
2304
2305 /* the _short versions avoid iteration by not calling anything that prints
2306 * more than oneliners. I love oneliners.
2307 */
2308
2309 static void
2310 print_device_short(device_t dev, int indent)
2311 {
2312 if (!dev)
2313 return;
2314
2315 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n",
2316 dev->unit, dev->desc,
2317 (dev->parent? "":"no "),
2318 (TAILQ_EMPTY(&dev->children)? "no ":""),
2319 (dev->flags&DF_ENABLED? "enabled,":"disabled,"),
2320 (dev->flags&DF_FIXEDCLASS? "fixed,":""),
2321 (dev->flags&DF_WILDCARD? "wildcard,":""),
2322 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
2323 (dev->ivars? "":"no "),
2324 (dev->softc? "":"no "),
2325 dev->busy));
2326 }
2327
2328 static void
2329 print_device(device_t dev, int indent)
2330 {
2331 if (!dev)
2332 return;
2333
2334 print_device_short(dev, indent);
2335
2336 indentprintf(("Parent:\n"));
2337 print_device_short(dev->parent, indent+1);
2338 indentprintf(("Driver:\n"));
2339 print_driver_short(dev->driver, indent+1);
2340 indentprintf(("Devclass:\n"));
2341 print_devclass_short(dev->devclass, indent+1);
2342 }
2343
2344 void
2345 print_device_tree_short(device_t dev, int indent)
2346 /* print the device and all its children (indented) */
2347 {
2348 device_t child;
2349
2350 if (!dev)
2351 return;
2352
2353 print_device_short(dev, indent);
2354
2355 TAILQ_FOREACH(child, &dev->children, link) {
2356 print_device_tree_short(child, indent+1);
2357 }
2358 }
2359
2360 void
2361 print_device_tree(device_t dev, int indent)
2362 /* print the device and all its children (indented) */
2363 {
2364 device_t child;
2365
2366 if (!dev)
2367 return;
2368
2369 print_device(dev, indent);
2370
2371 TAILQ_FOREACH(child, &dev->children, link) {
2372 print_device_tree(child, indent+1);
2373 }
2374 }
2375
2376 static void
2377 print_driver_short(driver_t *driver, int indent)
2378 {
2379 if (!driver)
2380 return;
2381
2382 indentprintf(("driver %s: softc size = %zd\n",
2383 driver->name, driver->size));
2384 }
2385
2386 static void
2387 print_driver(driver_t *driver, int indent)
2388 {
2389 if (!driver)
2390 return;
2391
2392 print_driver_short(driver, indent);
2393 }
2394
2395
2396 static void
2397 print_driver_list(driver_list_t drivers, int indent)
2398 {
2399 driverlink_t driver;
2400
2401 TAILQ_FOREACH(driver, &drivers, link) {
2402 print_driver(driver->driver, indent);
2403 }
2404 }
2405
2406 static void
2407 print_devclass_short(devclass_t dc, int indent)
2408 {
2409 if ( !dc )
2410 return;
2411
2412 indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit));
2413 }
2414
2415 static void
2416 print_devclass(devclass_t dc, int indent)
2417 {
2418 int i;
2419
2420 if ( !dc )
2421 return;
2422
2423 print_devclass_short(dc, indent);
2424 indentprintf(("Drivers:\n"));
2425 print_driver_list(dc->drivers, indent+1);
2426
2427 indentprintf(("Devices:\n"));
2428 for (i = 0; i < dc->maxunit; i++)
2429 if (dc->devices[i])
2430 print_device(dc->devices[i], indent+1);
2431 }
2432
2433 void
2434 print_devclass_list_short(void)
2435 {
2436 devclass_t dc;
2437
2438 printf("Short listing of devclasses, drivers & devices:\n");
2439 TAILQ_FOREACH(dc, &devclasses, link) {
2440 print_devclass_short(dc, 0);
2441 }
2442 }
2443
2444 void
2445 print_devclass_list(void)
2446 {
2447 devclass_t dc;
2448
2449 printf("Full listing of devclasses, drivers & devices:\n");
2450 TAILQ_FOREACH(dc, &devclasses, link) {
2451 print_devclass(dc, 0);
2452 }
2453 }
2454
2455 #endif
2456
2457 /*
2458 * User-space access to the device tree.
2459 *
2460 * We implement a small set of nodes:
2461 *
2462 * hw.bus Single integer read method to obtain the
2463 * current generation count.
2464 * hw.bus.devices Reads the entire device tree in flat space.
2465 * hw.bus.rman Resource manager interface
2466 *
2467 * We might like to add the ability to scan devclasses and/or drivers to
2468 * determine what else is currently loaded/available.
2469 */
2470
2471 static int
2472 sysctl_bus(SYSCTL_HANDLER_ARGS)
2473 {
2474 struct u_businfo ubus;
2475
2476 ubus.ub_version = BUS_USER_VERSION;
2477 ubus.ub_generation = bus_data_generation;
2478
2479 return (SYSCTL_OUT(req, &ubus, sizeof(ubus)));
2480 }
2481 SYSCTL_NODE(_hw_bus, OID_AUTO, info, CTLFLAG_RW, sysctl_bus,
2482 "bus-related data");
2483
2484 static int
2485 sysctl_devices(SYSCTL_HANDLER_ARGS)
2486 {
2487 int *name = (int *)arg1;
2488 u_int namelen = arg2;
2489 int index;
2490 struct device *dev;
2491 struct u_device udev; /* XXX this is a bit big */
2492 int error;
2493
2494 if (namelen != 2)
2495 return (EINVAL);
2496
2497 if (bus_data_generation_check(name[0]))
2498 return (EINVAL);
2499
2500 index = name[1];
2501
2502 /*
2503 * Scan the list of devices, looking for the requested index.
2504 */
2505 TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
2506 if (index-- == 0)
2507 break;
2508 }
2509 if (dev == NULL)
2510 return (ENOENT);
2511
2512 /*
2513 * Populate the return array.
2514 */
2515 udev.dv_handle = (uintptr_t)dev;
2516 udev.dv_parent = (uintptr_t)dev->parent;
2517 if (dev->nameunit == NULL)
2518 udev.dv_name[0] = '\0';
2519 else
2520 strlcpy(udev.dv_name, dev->nameunit, sizeof(udev.dv_name));
2521
2522 if (dev->desc == NULL)
2523 udev.dv_desc[0] = '\0';
2524 else
2525 strlcpy(udev.dv_desc, dev->desc, sizeof(udev.dv_desc));
2526 if (dev->driver == NULL || dev->driver->name == NULL)
2527 udev.dv_drivername[0] = '\0';
2528 else
2529 strlcpy(udev.dv_drivername, dev->driver->name,
2530 sizeof(udev.dv_drivername));
2531 udev.dv_pnpinfo[0] = '\0';
2532 udev.dv_location[0] = '\0';
2533 bus_child_pnpinfo_str(dev, udev.dv_pnpinfo, sizeof(udev.dv_pnpinfo));
2534 bus_child_location_str(dev, udev.dv_location, sizeof(udev.dv_location));
2535 udev.dv_devflags = dev->devflags;
2536 udev.dv_flags = dev->flags;
2537 udev.dv_state = dev->state;
2538 error = SYSCTL_OUT(req, &udev, sizeof(udev));
2539 return (error);
2540 }
2541
2542 SYSCTL_NODE(_hw_bus, OID_AUTO, devices, CTLFLAG_RD, sysctl_devices,
2543 "system device tree");
2544
2545 /*
2546 * Sysctl interface for scanning the resource lists.
2547 *
2548 * We take two input parameters; the index into the list of resource
2549 * managers, and the resource offset into the list.
2550 */
2551 static int
2552 sysctl_rman(SYSCTL_HANDLER_ARGS)
2553 {
2554 int *name = (int *)arg1;
2555 u_int namelen = arg2;
2556 int rman_idx, res_idx;
2557 struct rman *rm;
2558 struct resource *res;
2559 struct u_rman urm;
2560 struct u_resource ures;
2561 int error;
2562
2563 if (namelen != 3)
2564 return (EINVAL);
2565
2566 if (bus_data_generation_check(name[0]))
2567 return (EINVAL);
2568 rman_idx = name[1];
2569 res_idx = name[2];
2570
2571 /*
2572 * Find the indexed resource manager
2573 */
2574 TAILQ_FOREACH(rm, &rman_head, rm_link) {
2575 if (rman_idx-- == 0)
2576 break;
2577 }
2578 if (rm == NULL)
2579 return (ENOENT);
2580
2581 /*
2582 * If the resource index is -1, we want details on the
2583 * resource manager.
2584 */
2585 if (res_idx == -1) {
2586 urm.rm_handle = (uintptr_t)rm;
2587 strlcpy(urm.rm_descr, rm->rm_descr, RM_TEXTLEN);
2588 urm.rm_start = rm->rm_start;
2589 urm.rm_size = rm->rm_end - rm->rm_start + 1;
2590 urm.rm_type = rm->rm_type;
2591
2592 error = SYSCTL_OUT(req, &urm, sizeof(urm));
2593 return (error);
2594 }
2595
2596 /*
2597 * Find the indexed resource and return it.
2598 */
2599 TAILQ_FOREACH(res, &rm->rm_list, r_link) {
2600 if (res_idx-- == 0) {
2601 ures.r_handle = (uintptr_t)res;
2602 ures.r_parent = (uintptr_t)res->r_rm;
2603 ures.r_device = (uintptr_t)res->r_dev;
2604 if (res->r_dev != NULL) {
2605 if (device_get_name(res->r_dev) != NULL) {
2606 snprintf(ures.r_devname, RM_TEXTLEN,
2607 "%s%d",
2608 device_get_name(res->r_dev),
2609 device_get_unit(res->r_dev));
2610 } else {
2611 strlcpy(ures.r_devname, "nomatch",
2612 RM_TEXTLEN);
2613 }
2614 } else {
2615 ures.r_devname[0] = '\0';
2616 }
2617 ures.r_start = res->r_start;
2618 ures.r_size = res->r_end - res->r_start + 1;
2619 ures.r_flags = res->r_flags;
2620
2621 error = SYSCTL_OUT(req, &ures, sizeof(ures));
2622 return (error);
2623 }
2624 }
2625 return (ENOENT);
2626 }
2627
2628 SYSCTL_NODE(_hw_bus, OID_AUTO, rman, CTLFLAG_RD, sysctl_rman,
2629 "kernel resource manager");
2630
2631 int
2632 bus_data_generation_check(int generation)
2633 {
2634 if (generation != bus_data_generation)
2635 return (1);
2636
2637 /* XXX generate optimised lists here? */
2638 return (0);
2639 }
2640
2641 void
2642 bus_data_generation_update(void)
2643 {
2644 bus_data_generation++;
2645 }
Cache object: 467a04229d6112ab2d63cb7e1a72934c
|