The devinfo(3) library provides userspace access to the internal device
[dragonfly.git] / sys / kern / subr_bus.c
CommitLineData
984263bc
MD
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: src/sys/kern/subr_bus.c,v 1.54.2.9 2002/10/10 15:13:32 jhb Exp $
0010e23a 27 * $DragonFly: src/sys/kern/subr_bus.c,v 1.45 2008/09/30 12:20:29 hasso Exp $
984263bc
MD
28 */
29
30#include "opt_bus.h"
31
32#include <sys/param.h>
33#include <sys/queue.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <sys/module.h>
80eff43d 37#include <sys/kobj.h>
984263bc 38#include <sys/bus_private.h>
0010e23a 39#include <sys/sysctl.h>
984263bc 40#include <sys/systm.h>
1f7ab7c9 41#include <sys/bus.h>
984263bc 42#include <sys/rman.h>
1f7ab7c9 43
984263bc
MD
44#include <machine/stdarg.h> /* for device_printf() */
45
dbcd0c9b
MD
46#include <sys/thread2.h>
47
0010e23a
HT
48SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
49
984263bc
MD
50MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
51
52#ifdef BUS_DEBUG
6ea70f76 53#define PDEBUG(a) (kprintf("%s:%d: ", __func__, __LINE__), kprintf a, kprintf("\n"))
984263bc
MD
54#define DEVICENAME(d) ((d)? device_get_name(d): "no device")
55#define DRIVERNAME(d) ((d)? d->name : "no driver")
56#define DEVCLANAME(d) ((d)? d->name : "no devclass")
57
58/* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
59 * prevent syslog from deleting initial spaces
60 */
6ea70f76 61#define indentprintf(p) do { int iJ; kprintf("."); for (iJ=0; iJ<indent; iJ++) kprintf(" "); kprintf p ; } while(0)
984263bc 62
0deb64bd
JS
63static void print_device_short(device_t dev, int indent);
64static void print_device(device_t dev, int indent);
65void print_device_tree_short(device_t dev, int indent);
66void print_device_tree(device_t dev, int indent);
67static void print_driver_short(driver_t *driver, int indent);
68static void print_driver(driver_t *driver, int indent);
69static void print_driver_list(driver_list_t drivers, int indent);
70static void print_devclass_short(devclass_t dc, int indent);
71static void print_devclass(devclass_t dc, int indent);
72void print_devclass_list_short(void);
73void print_devclass_list(void);
984263bc
MD
74
75#else
76/* Make the compiler ignore the function calls */
77#define PDEBUG(a) /* nop */
78#define DEVICENAME(d) /* nop */
79#define DRIVERNAME(d) /* nop */
80#define DEVCLANAME(d) /* nop */
81
984263bc
MD
82#define print_device_short(d,i) /* nop */
83#define print_device(d,i) /* nop */
84#define print_device_tree_short(d,i) /* nop */
85#define print_device_tree(d,i) /* nop */
86#define print_driver_short(d,i) /* nop */
87#define print_driver(d,i) /* nop */
88#define print_driver_list(d,i) /* nop */
89#define print_devclass_short(d,i) /* nop */
90#define print_devclass(d,i) /* nop */
91#define print_devclass_list_short() /* nop */
92#define print_devclass_list() /* nop */
93#endif
94
dbcd0c9b
MD
95static void device_attach_async(device_t dev);
96static void device_attach_thread(void *arg);
97static int device_doattach(device_t dev);
98
99static int do_async_attach = 0;
100static int numasyncthreads;
101TUNABLE_INT("kern.do_async_attach", &do_async_attach);
984263bc 102
0010e23a
HT
103TAILQ_HEAD(,device) bus_data_devices;
104static int bus_data_generation = 1;
105
80eff43d 106kobj_method_t null_methods[] = {
0deb64bd 107 { 0, 0 }
984263bc
MD
108};
109
80eff43d 110DEFINE_CLASS(null, null_methods, 0);
984263bc
MD
111
112/*
113 * Devclass implementation
114 */
115
116static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
117
118static devclass_t
91a0c258
JS
119devclass_find_internal(const char *classname, const char *parentname,
120 int create)
984263bc 121{
0deb64bd 122 devclass_t dc;
984263bc 123
0deb64bd
JS
124 PDEBUG(("looking for %s", classname));
125 if (classname == NULL)
126 return(NULL);
127
128 TAILQ_FOREACH(dc, &devclasses, link)
129 if (!strcmp(dc->name, classname))
91a0c258 130 break;
0deb64bd 131
91a0c258
JS
132 if (create && !dc) {
133 PDEBUG(("creating %s", classname));
77652cad 134 dc = kmalloc(sizeof(struct devclass) + strlen(classname) + 1,
3b284c6a 135 M_BUS, M_INTWAIT | M_ZERO);
0deb64bd 136 if (!dc)
91a0c258
JS
137 return(NULL);
138 dc->parent = NULL;
0deb64bd
JS
139 dc->name = (char*) (dc + 1);
140 strcpy(dc->name, classname);
141 dc->devices = NULL;
142 dc->maxunit = 0;
143 TAILQ_INIT(&dc->drivers);
144 TAILQ_INSERT_TAIL(&devclasses, dc, link);
0010e23a
HT
145
146 bus_data_generation_update();
147
0deb64bd 148 }
91a0c258
JS
149 if (parentname && dc && !dc->parent)
150 dc->parent = devclass_find_internal(parentname, NULL, FALSE);
984263bc 151
0deb64bd 152 return(dc);
984263bc
MD
153}
154
155devclass_t
156devclass_create(const char *classname)
157{
91a0c258 158 return(devclass_find_internal(classname, NULL, TRUE));
984263bc
MD
159}
160
161devclass_t
162devclass_find(const char *classname)
163{
91a0c258 164 return(devclass_find_internal(classname, NULL, FALSE));
984263bc
MD
165}
166
2581072f
MD
167device_t
168devclass_find_unit(const char *classname, int unit)
169{
170 devclass_t dc;
171
172 if ((dc = devclass_find(classname)) != NULL)
173 return(devclass_get_device(dc, unit));
174 return (NULL);
175}
176
984263bc
MD
177int
178devclass_add_driver(devclass_t dc, driver_t *driver)
179{
0deb64bd 180 driverlink_t dl;
39b5d600 181 device_t dev;
0deb64bd 182 int i;
984263bc 183
0deb64bd 184 PDEBUG(("%s", DRIVERNAME(driver)));
984263bc 185
efda3bd0 186 dl = kmalloc(sizeof *dl, M_BUS, M_INTWAIT | M_ZERO);
0deb64bd
JS
187 if (!dl)
188 return(ENOMEM);
984263bc 189
0deb64bd
JS
190 /*
191 * Compile the driver's methods. Also increase the reference count
192 * so that the class doesn't get freed when the last instance
193 * goes. This means we can safely use static methods and avoids a
194 * double-free in devclass_delete_driver.
195 */
b4f5425e 196 kobj_class_instantiate(driver);
984263bc 197
0deb64bd
JS
198 /*
199 * Make sure the devclass which the driver is implementing exists.
200 */
91a0c258 201 devclass_find_internal(driver->name, NULL, TRUE);
984263bc 202
0deb64bd
JS
203 dl->driver = driver;
204 TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
984263bc 205
0deb64bd 206 /*
39b5d600
MD
207 * Call BUS_DRIVER_ADDED for any existing busses in this class,
208 * but only if the bus has already been attached (otherwise we
209 * might probe too early).
210 *
211 * This is what will cause a newly loaded module to be associated
212 * with hardware. bus_generic_driver_added() is typically what ends
213 * up being called.
0deb64bd 214 */
39b5d600
MD
215 for (i = 0; i < dc->maxunit; i++) {
216 if ((dev = dc->devices[i]) != NULL) {
308ea088 217 if (dev->state >= DS_ATTACHED)
39b5d600
MD
218 BUS_DRIVER_ADDED(dev, driver);
219 }
220 }
984263bc 221
0010e23a 222 bus_data_generation_update();
0deb64bd 223 return(0);
984263bc
MD
224}
225
226int
227devclass_delete_driver(devclass_t busclass, driver_t *driver)
228{
0deb64bd
JS
229 devclass_t dc = devclass_find(driver->name);
230 driverlink_t dl;
231 device_t dev;
232 int i;
233 int error;
984263bc 234
0deb64bd 235 PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
984263bc 236
0deb64bd
JS
237 if (!dc)
238 return(0);
984263bc 239
0deb64bd
JS
240 /*
241 * Find the link structure in the bus' list of drivers.
242 */
243 TAILQ_FOREACH(dl, &busclass->drivers, link)
244 if (dl->driver == driver)
245 break;
246
247 if (!dl) {
248 PDEBUG(("%s not found in %s list", driver->name, busclass->name));
249 return(ENOENT);
984263bc 250 }
984263bc 251
0deb64bd
JS
252 /*
253 * Disassociate from any devices. We iterate through all the
254 * devices in the devclass of the driver and detach any which are
255 * using the driver and which have a parent in the devclass which
256 * we are deleting from.
257 *
258 * Note that since a driver can be in multiple devclasses, we
259 * should not detach devices which are not children of devices in
260 * the affected devclass.
261 */
262 for (i = 0; i < dc->maxunit; i++)
263 if (dc->devices[i]) {
264 dev = dc->devices[i];
265 if (dev->driver == driver && dev->parent &&
266 dev->parent->devclass == busclass) {
267 if ((error = device_detach(dev)) != 0)
268 return(error);
269 device_set_driver(dev, NULL);
270 }
271 }
272
273 TAILQ_REMOVE(&busclass->drivers, dl, link);
efda3bd0 274 kfree(dl, M_BUS);
984263bc 275
b4f5425e 276 kobj_class_uninstantiate(driver);
984263bc 277
0010e23a 278 bus_data_generation_update();
0deb64bd 279 return(0);
984263bc
MD
280}
281
282static driverlink_t
283devclass_find_driver_internal(devclass_t dc, const char *classname)
284{
0deb64bd 285 driverlink_t dl;
984263bc 286
0deb64bd 287 PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
984263bc 288
0deb64bd
JS
289 TAILQ_FOREACH(dl, &dc->drivers, link)
290 if (!strcmp(dl->driver->name, classname))
291 return(dl);
984263bc 292
0deb64bd
JS
293 PDEBUG(("not found"));
294 return(NULL);
984263bc
MD
295}
296
91a0c258 297kobj_class_t
984263bc
MD
298devclass_find_driver(devclass_t dc, const char *classname)
299{
0deb64bd 300 driverlink_t dl;
984263bc 301
0deb64bd
JS
302 dl = devclass_find_driver_internal(dc, classname);
303 if (dl)
304 return(dl->driver);
305 else
306 return(NULL);
984263bc
MD
307}
308
309const char *
310devclass_get_name(devclass_t dc)
311{
0deb64bd 312 return(dc->name);
984263bc
MD
313}
314
315device_t
316devclass_get_device(devclass_t dc, int unit)
317{
0deb64bd
JS
318 if (dc == NULL || unit < 0 || unit >= dc->maxunit)
319 return(NULL);
320 return(dc->devices[unit]);
984263bc
MD
321}
322
323void *
324devclass_get_softc(devclass_t dc, int unit)
325{
0deb64bd 326 device_t dev;
984263bc 327
0deb64bd
JS
328 dev = devclass_get_device(dc, unit);
329 if (!dev)
330 return(NULL);
984263bc 331
0deb64bd 332 return(device_get_softc(dev));
984263bc
MD
333}
334
335int
336devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
337{
0deb64bd
JS
338 int i;
339 int count;
340 device_t *list;
984263bc 341
0deb64bd
JS
342 count = 0;
343 for (i = 0; i < dc->maxunit; i++)
344 if (dc->devices[i])
345 count++;
346
efda3bd0 347 list = kmalloc(count * sizeof(device_t), M_TEMP, M_INTWAIT | M_ZERO);
0deb64bd
JS
348 if (list == NULL)
349 return(ENOMEM);
984263bc 350
0deb64bd
JS
351 count = 0;
352 for (i = 0; i < dc->maxunit; i++)
353 if (dc->devices[i]) {
354 list[count] = dc->devices[i];
355 count++;
356 }
984263bc 357
0deb64bd
JS
358 *devlistp = list;
359 *devcountp = count;
360
361 return(0);
984263bc
MD
362}
363
5ebadb2c
HT
364/**
365 * @brief Get a list of drivers in the devclass
366 *
367 * An array containing a list of pointers to all the drivers in the
368 * given devclass is allocated and returned in @p *listp. The number
369 * of drivers in the array is returned in @p *countp. The caller should
370 * free the array using @c free(p, M_TEMP).
371 *
372 * @param dc the devclass to examine
373 * @param listp gives location for array pointer return value
374 * @param countp gives location for number of array elements
375 * return value
376 *
377 * @retval 0 success
378 * @retval ENOMEM the array allocation failed
379 */
380int
381devclass_get_drivers(devclass_t dc, driver_t ***listp, int *countp)
382{
383 driverlink_t dl;
384 driver_t **list;
385 int count;
386
387 count = 0;
388 TAILQ_FOREACH(dl, &dc->drivers, link)
389 count++;
390 list = kmalloc(count * sizeof(driver_t *), M_TEMP, M_NOWAIT);
391 if (list == NULL)
392 return (ENOMEM);
393
394 count = 0;
395 TAILQ_FOREACH(dl, &dc->drivers, link) {
396 list[count] = dl->driver;
397 count++;
398 }
399 *listp = list;
400 *countp = count;
401
402 return (0);
403}
404
7d58d14b
HT
405/**
406 * @brief Get the number of devices in a devclass
407 *
408 * @param dc the devclass to examine
409 */
410int
411devclass_get_count(devclass_t dc)
412{
413 int count, i;
414
415 count = 0;
416 for (i = 0; i < dc->maxunit; i++)
417 if (dc->devices[i])
418 count++;
419 return (count);
420}
421
984263bc
MD
422int
423devclass_get_maxunit(devclass_t dc)
424{
0deb64bd 425 return(dc->maxunit);
984263bc
MD
426}
427
91a0c258
JS
428void
429devclass_set_parent(devclass_t dc, devclass_t pdc)
430{
431 dc->parent = pdc;
432}
433
434devclass_t
435devclass_get_parent(devclass_t dc)
436{
437 return(dc->parent);
438}
439
984263bc
MD
440static int
441devclass_alloc_unit(devclass_t dc, int *unitp)
442{
0deb64bd 443 int unit = *unitp;
984263bc 444
0deb64bd 445 PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
984263bc 446
0deb64bd
JS
447 /* If we have been given a wired unit number, check for existing device */
448 if (unit != -1) {
449 if (unit >= 0 && unit < dc->maxunit &&
450 dc->devices[unit] != NULL) {
451 if (bootverbose)
6ea70f76 452 kprintf("%s-: %s%d exists, using next available unit number\n",
0deb64bd
JS
453 dc->name, dc->name, unit);
454 /* find the next available slot */
455 while (++unit < dc->maxunit && dc->devices[unit] != NULL)
456 ;
457 }
458 } else {
459 /* Unwired device, find the next available slot for it */
460 unit = 0;
461 while (unit < dc->maxunit && dc->devices[unit] != NULL)
462 unit++;
984263bc 463 }
0deb64bd
JS
464
465 /*
466 * We've selected a unit beyond the length of the table, so let's
467 * extend the table to make room for all units up to and including
468 * this one.
469 */
470 if (unit >= dc->maxunit) {
471 device_t *newlist;
472 int newsize;
473
474 newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t));
efda3bd0 475 newlist = kmalloc(sizeof(device_t) * newsize, M_BUS,
3b284c6a 476 M_INTWAIT | M_ZERO);
0deb64bd
JS
477 if (newlist == NULL)
478 return(ENOMEM);
479 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
480 if (dc->devices)
efda3bd0 481 kfree(dc->devices, M_BUS);
0deb64bd
JS
482 dc->devices = newlist;
483 dc->maxunit = newsize;
484 }
485 PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
486
487 *unitp = unit;
488 return(0);
984263bc
MD
489}
490
491static int
492devclass_add_device(devclass_t dc, device_t dev)
493{
0deb64bd 494 int buflen, error;
984263bc 495
0deb64bd 496 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
984263bc 497
0deb64bd 498 buflen = strlen(dc->name) + 5;
efda3bd0 499 dev->nameunit = kmalloc(buflen, M_BUS, M_INTWAIT | M_ZERO);
0deb64bd
JS
500 if (!dev->nameunit)
501 return(ENOMEM);
984263bc 502
0deb64bd 503 if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
efda3bd0 504 kfree(dev->nameunit, M_BUS);
0deb64bd
JS
505 dev->nameunit = NULL;
506 return(error);
507 }
508 dc->devices[dev->unit] = dev;
509 dev->devclass = dc;
f8c7a42d 510 ksnprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
984263bc 511
0deb64bd 512 return(0);
984263bc
MD
513}
514
515static int
516devclass_delete_device(devclass_t dc, device_t dev)
517{
0deb64bd
JS
518 if (!dc || !dev)
519 return(0);
984263bc 520
0deb64bd 521 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
984263bc 522
0deb64bd
JS
523 if (dev->devclass != dc || dc->devices[dev->unit] != dev)
524 panic("devclass_delete_device: inconsistent device class");
525 dc->devices[dev->unit] = NULL;
526 if (dev->flags & DF_WILDCARD)
527 dev->unit = -1;
528 dev->devclass = NULL;
efda3bd0 529 kfree(dev->nameunit, M_BUS);
0deb64bd 530 dev->nameunit = NULL;
984263bc 531
0deb64bd 532 return(0);
984263bc
MD
533}
534
535static device_t
536make_device(device_t parent, const char *name, int unit)
537{
0deb64bd
JS
538 device_t dev;
539 devclass_t dc;
984263bc 540
0deb64bd 541 PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
984263bc 542
0deb64bd 543 if (name != NULL) {
91a0c258 544 dc = devclass_find_internal(name, NULL, TRUE);
0deb64bd 545 if (!dc) {
6ea70f76 546 kprintf("make_device: can't find device class %s\n", name);
0deb64bd
JS
547 return(NULL);
548 }
549 } else
550 dc = NULL;
984263bc 551
efda3bd0 552 dev = kmalloc(sizeof(struct device), M_BUS, M_INTWAIT | M_ZERO);
0deb64bd
JS
553 if (!dev)
554 return(0);
984263bc 555
0deb64bd
JS
556 dev->parent = parent;
557 TAILQ_INIT(&dev->children);
558 kobj_init((kobj_t) dev, &null_class);
559 dev->driver = NULL;
560 dev->devclass = NULL;
561 dev->unit = unit;
562 dev->nameunit = NULL;
563 dev->desc = NULL;
564 dev->busy = 0;
565 dev->devflags = 0;
566 dev->flags = DF_ENABLED;
567 dev->order = 0;
568 if (unit == -1)
569 dev->flags |= DF_WILDCARD;
570 if (name) {
571 dev->flags |= DF_FIXEDCLASS;
572 if (devclass_add_device(dc, dev) != 0) {
573 kobj_delete((kobj_t)dev, M_BUS);
574 return(NULL);
575 }
576 }
577 dev->ivars = NULL;
578 dev->softc = NULL;
984263bc 579
0deb64bd 580 dev->state = DS_NOTPRESENT;
984263bc 581
0010e23a
HT
582 TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
583 bus_data_generation_update();
584
0deb64bd 585 return(dev);
984263bc
MD
586}
587
588static int
589device_print_child(device_t dev, device_t child)
590{
0deb64bd 591 int retval = 0;
984263bc 592
0deb64bd
JS
593 if (device_is_alive(child))
594 retval += BUS_PRINT_CHILD(dev, child);
595 else
596 retval += device_printf(child, " not found\n");
984263bc 597
0deb64bd 598 return(retval);
984263bc
MD
599}
600
601device_t
602device_add_child(device_t dev, const char *name, int unit)
603{
0deb64bd 604 return device_add_child_ordered(dev, 0, name, unit);
984263bc
MD
605}
606
607device_t
608device_add_child_ordered(device_t dev, int order, const char *name, int unit)
609{
0deb64bd
JS
610 device_t child;
611 device_t place;
984263bc 612
0deb64bd
JS
613 PDEBUG(("%s at %s with order %d as unit %d", name, DEVICENAME(dev),
614 order, unit));
984263bc 615
0deb64bd
JS
616 child = make_device(dev, name, unit);
617 if (child == NULL)
618 return child;
619 child->order = order;
984263bc 620
0deb64bd
JS
621 TAILQ_FOREACH(place, &dev->children, link)
622 if (place->order > order)
623 break;
984263bc 624
0deb64bd
JS
625 if (place) {
626 /*
627 * The device 'place' is the first device whose order is
628 * greater than the new child.
629 */
630 TAILQ_INSERT_BEFORE(place, child, link);
631 } else {
632 /*
633 * The new child's order is greater or equal to the order of
634 * any existing device. Add the child to the tail of the list.
635 */
636 TAILQ_INSERT_TAIL(&dev->children, child, link);
637 }
984263bc 638
0010e23a 639 bus_data_generation_update();
0deb64bd 640 return(child);
984263bc
MD
641}
642
643int
644device_delete_child(device_t dev, device_t child)
645{
0deb64bd
JS
646 int error;
647 device_t grandchild;
984263bc 648
0deb64bd 649 PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
984263bc 650
0deb64bd
JS
651 /* remove children first */
652 while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
653 error = device_delete_child(child, grandchild);
654 if (error)
655 return(error);
656 }
984263bc 657
0deb64bd
JS
658 if ((error = device_detach(child)) != 0)
659 return(error);
660 if (child->devclass)
661 devclass_delete_device(child->devclass, child);
662 TAILQ_REMOVE(&dev->children, child, link);
0010e23a 663 TAILQ_REMOVE(&bus_data_devices, child, devlink);
0deb64bd
JS
664 device_set_desc(child, NULL);
665 kobj_delete((kobj_t)child, M_BUS);
984263bc 666
0010e23a 667 bus_data_generation_update();
0deb64bd 668 return(0);
984263bc
MD
669}
670
a2a274f4
HT
671/**
672 * @brief Find a device given a unit number
673 *
674 * This is similar to devclass_get_devices() but only searches for
675 * devices which have @p dev as a parent.
676 *
677 * @param dev the parent device to search
678 * @param unit the unit number to search for. If the unit is -1,
679 * return the first child of @p dev which has name
680 * @p classname (that is, the one with the lowest unit.)
681 *
682 * @returns the device with the given unit number or @c
683 * NULL if there is no such device
984263bc
MD
684 */
685device_t
686device_find_child(device_t dev, const char *classname, int unit)
687{
0deb64bd
JS
688 devclass_t dc;
689 device_t child;
984263bc 690
0deb64bd
JS
691 dc = devclass_find(classname);
692 if (!dc)
693 return(NULL);
984263bc 694
a2a274f4
HT
695 if (unit != -1) {
696 child = devclass_get_device(dc, unit);
697 if (child && child->parent == dev)
698 return (child);
699 } else {
700 for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
701 child = devclass_get_device(dc, unit);
702 if (child && child->parent == dev)
703 return (child);
704 }
705 }
0deb64bd 706 return(NULL);
984263bc
MD
707}
708
709static driverlink_t
710first_matching_driver(devclass_t dc, device_t dev)
711{
0deb64bd
JS
712 if (dev->devclass)
713 return(devclass_find_driver_internal(dc, dev->devclass->name));
714 else
715 return(TAILQ_FIRST(&dc->drivers));
984263bc
MD
716}
717
718static driverlink_t
719next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
720{
0deb64bd
JS
721 if (dev->devclass) {
722 driverlink_t dl;
723 for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
724 if (!strcmp(dev->devclass->name, dl->driver->name))
725 return(dl);
726 return(NULL);
727 } else
728 return(TAILQ_NEXT(last, link));
984263bc
MD
729}
730
731static int
732device_probe_child(device_t dev, device_t child)
733{
0deb64bd
JS
734 devclass_t dc;
735 driverlink_t best = 0;
736 driverlink_t dl;
737 int result, pri = 0;
738 int hasclass = (child->devclass != 0);
739
740 dc = dev->devclass;
741 if (!dc)
742 panic("device_probe_child: parent device has no devclass");
984263bc 743
0deb64bd
JS
744 if (child->state == DS_ALIVE)
745 return(0);
984263bc 746
91a0c258
JS
747 for (; dc; dc = dc->parent) {
748 for (dl = first_matching_driver(dc, child); dl;
749 dl = next_matching_driver(dc, child, dl)) {
750 PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
751 device_set_driver(child, dl->driver);
752 if (!hasclass)
753 device_set_devclass(child, dl->driver->name);
754 result = DEVICE_PROBE(child);
755 if (!hasclass)
756 device_set_devclass(child, 0);
984263bc 757
91a0c258
JS
758 /*
759 * If the driver returns SUCCESS, there can be
760 * no higher match for this device.
761 */
762 if (result == 0) {
763 best = dl;
764 pri = 0;
765 break;
766 }
984263bc 767
91a0c258
JS
768 /*
769 * The driver returned an error so it
770 * certainly doesn't match.
771 */
772 if (result > 0) {
773 device_set_driver(child, 0);
774 continue;
775 }
984263bc 776
91a0c258
JS
777 /*
778 * A priority lower than SUCCESS, remember the
779 * best matching driver. Initialise the value
780 * of pri for the first match.
781 */
782 if (best == 0 || result > pri) {
783 best = dl;
784 pri = result;
785 continue;
786 }
787 }
0deb64bd 788 /*
91a0c258
JS
789 * If we have unambiguous match in this devclass,
790 * don't look in the parent.
791 */
792 if (best && pri == 0)
793 break;
984263bc
MD
794 }
795
796 /*
0deb64bd 797 * If we found a driver, change state and initialise the devclass.
984263bc 798 */
0deb64bd
JS
799 if (best) {
800 if (!child->devclass)
801 device_set_devclass(child, best->driver->name);
802 device_set_driver(child, best->driver);
803 if (pri < 0) {
804 /*
805 * A bit bogus. Call the probe method again to make
806 * sure that we have the right description.
807 */
808 DEVICE_PROBE(child);
809 }
0010e23a
HT
810
811 bus_data_generation_update();
0deb64bd
JS
812 child->state = DS_ALIVE;
813 return(0);
984263bc 814 }
984263bc 815
0deb64bd 816 return(ENXIO);
984263bc
MD
817}
818
819device_t
820device_get_parent(device_t dev)
821{
0deb64bd 822 return dev->parent;
984263bc
MD
823}
824
825int
826device_get_children(device_t dev, device_t **devlistp, int *devcountp)
827{
0deb64bd
JS
828 int count;
829 device_t child;
830 device_t *list;
984263bc 831
0deb64bd
JS
832 count = 0;
833 TAILQ_FOREACH(child, &dev->children, link)
834 count++;
984263bc 835
efda3bd0 836 list = kmalloc(count * sizeof(device_t), M_TEMP, M_INTWAIT | M_ZERO);
0deb64bd
JS
837 if (!list)
838 return(ENOMEM);
984263bc 839
0deb64bd
JS
840 count = 0;
841 TAILQ_FOREACH(child, &dev->children, link) {
842 list[count] = child;
843 count++;
844 }
984263bc 845
0deb64bd
JS
846 *devlistp = list;
847 *devcountp = count;
984263bc 848
0deb64bd 849 return(0);
984263bc
MD
850}
851
852driver_t *
853device_get_driver(device_t dev)
854{
0deb64bd 855 return(dev->driver);
984263bc
MD
856}
857
858devclass_t
859device_get_devclass(device_t dev)
860{
0deb64bd 861 return(dev->devclass);
984263bc
MD
862}
863
864const char *
865device_get_name(device_t dev)
866{
0deb64bd
JS
867 if (dev->devclass)
868 return devclass_get_name(dev->devclass);
869 return(NULL);
984263bc
MD
870}
871
872const char *
873device_get_nameunit(device_t dev)
874{
0deb64bd 875 return(dev->nameunit);
984263bc
MD
876}
877
878int
879device_get_unit(device_t dev)
880{
0deb64bd 881 return(dev->unit);
984263bc
MD
882}
883
884const char *
885device_get_desc(device_t dev)
886{
0deb64bd 887 return(dev->desc);
984263bc
MD
888}
889
0deb64bd 890uint32_t
984263bc
MD
891device_get_flags(device_t dev)
892{
0deb64bd 893 return(dev->devflags);
984263bc
MD
894}
895
896int
897device_print_prettyname(device_t dev)
898{
0deb64bd 899 const char *name = device_get_name(dev);
984263bc 900
0deb64bd 901 if (name == 0)
6ea70f76 902 return kprintf("unknown: ");
0deb64bd 903 else
6ea70f76 904 return kprintf("%s%d: ", name, device_get_unit(dev));
984263bc
MD
905}
906
907int
908device_printf(device_t dev, const char * fmt, ...)
909{
0deb64bd
JS
910 __va_list ap;
911 int retval;
984263bc 912
0deb64bd
JS
913 retval = device_print_prettyname(dev);
914 __va_start(ap, fmt);
379210cb 915 retval += kvprintf(fmt, ap);
0deb64bd
JS
916 __va_end(ap);
917 return retval;
984263bc
MD
918}
919
920static void
921device_set_desc_internal(device_t dev, const char* desc, int copy)
922{
0deb64bd 923 if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
efda3bd0 924 kfree(dev->desc, M_BUS);
0deb64bd
JS
925 dev->flags &= ~DF_DESCMALLOCED;
926 dev->desc = NULL;
984263bc 927 }
0deb64bd
JS
928
929 if (copy && desc) {
efda3bd0 930 dev->desc = kmalloc(strlen(desc) + 1, M_BUS, M_INTWAIT);
0deb64bd
JS
931 if (dev->desc) {
932 strcpy(dev->desc, desc);
933 dev->flags |= DF_DESCMALLOCED;
934 }
0010e23a 935 } else {
0deb64bd
JS
936 /* Avoid a -Wcast-qual warning */
937 dev->desc = (char *)(uintptr_t) desc;
0deb64bd 938 }
0010e23a
HT
939
940 bus_data_generation_update();
984263bc
MD
941}
942
943void
944device_set_desc(device_t dev, const char* desc)
945{
0deb64bd 946 device_set_desc_internal(dev, desc, FALSE);
984263bc
MD
947}
948
949void
950device_set_desc_copy(device_t dev, const char* desc)
951{
0deb64bd 952 device_set_desc_internal(dev, desc, TRUE);
984263bc
MD
953}
954
955void
0deb64bd 956device_set_flags(device_t dev, uint32_t flags)
984263bc 957{
0deb64bd 958 dev->devflags = flags;
984263bc
MD
959}
960
961void *
962device_get_softc(device_t dev)
963{
0deb64bd 964 return dev->softc;
984263bc
MD
965}
966
967void
968device_set_softc(device_t dev, void *softc)
969{
0deb64bd 970 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
efda3bd0 971 kfree(dev->softc, M_BUS);
0deb64bd
JS
972 dev->softc = softc;
973 if (dev->softc)
974 dev->flags |= DF_EXTERNALSOFTC;
975 else
976 dev->flags &= ~DF_EXTERNALSOFTC;
984263bc
MD
977}
978
dbcd0c9b
MD
979void
980device_set_async_attach(device_t dev, int enable)
981{
982 if (enable)
983 dev->flags |= DF_ASYNCPROBE;
984 else
985 dev->flags &= ~DF_ASYNCPROBE;
986}
987
984263bc
MD
988void *
989device_get_ivars(device_t dev)
990{
0deb64bd 991 return dev->ivars;
984263bc
MD
992}
993
994void
995device_set_ivars(device_t dev, void * ivars)
996{
0deb64bd
JS
997 if (!dev)
998 return;
984263bc 999
0deb64bd 1000 dev->ivars = ivars;
984263bc
MD
1001}
1002
1003device_state_t
1004device_get_state(device_t dev)
1005{
0deb64bd 1006 return(dev->state);
984263bc
MD
1007}
1008
1009void
1010device_enable(device_t dev)
1011{
0deb64bd 1012 dev->flags |= DF_ENABLED;
984263bc
MD
1013}
1014
1015void
1016device_disable(device_t dev)
1017{
0deb64bd 1018 dev->flags &= ~DF_ENABLED;
984263bc
MD
1019}
1020
8a8d5d85
MD
1021/*
1022 * YYY cannot block
1023 */
984263bc
MD
1024void
1025device_busy(device_t dev)
1026{
0deb64bd
JS
1027 if (dev->state < DS_ATTACHED)
1028 panic("device_busy: called for unattached device");
1029 if (dev->busy == 0 && dev->parent)
1030 device_busy(dev->parent);
1031 dev->busy++;
1032 dev->state = DS_BUSY;
984263bc
MD
1033}
1034
8a8d5d85
MD
1035/*
1036 * YYY cannot block
1037 */
984263bc
MD
1038void
1039device_unbusy(device_t dev)
1040{
0deb64bd
JS
1041 if (dev->state != DS_BUSY)
1042 panic("device_unbusy: called for non-busy device");
1043 dev->busy--;
1044 if (dev->busy == 0) {
1045 if (dev->parent)
1046 device_unbusy(dev->parent);
1047 dev->state = DS_ATTACHED;
1048 }
984263bc
MD
1049}
1050
1051void
1052device_quiet(device_t dev)
1053{
0deb64bd 1054 dev->flags |= DF_QUIET;
984263bc
MD
1055}
1056
1057void
1058device_verbose(device_t dev)
1059{
0deb64bd 1060 dev->flags &= ~DF_QUIET;
984263bc
MD
1061}
1062
1063int
1064device_is_quiet(device_t dev)
1065{
0deb64bd 1066 return((dev->flags & DF_QUIET) != 0);
984263bc
MD
1067}
1068
1069int
1070device_is_enabled(device_t dev)
1071{
0deb64bd 1072 return((dev->flags & DF_ENABLED) != 0);
984263bc
MD
1073}
1074
1075int
1076device_is_alive(device_t dev)
1077{
0deb64bd 1078 return(dev->state >= DS_ALIVE);
984263bc
MD
1079}
1080
2140e77f
JS
1081int
1082device_is_attached(device_t dev)
1083{
0deb64bd 1084 return(dev->state >= DS_ATTACHED);
2140e77f
JS
1085}
1086
984263bc
MD
1087int
1088device_set_devclass(device_t dev, const char *classname)
1089{
0deb64bd 1090 devclass_t dc;
0010e23a 1091 int error;
984263bc 1092
0deb64bd
JS
1093 if (!classname) {
1094 if (dev->devclass)
1095 devclass_delete_device(dev->devclass, dev);
1096 return(0);
1097 }
984263bc 1098
0deb64bd 1099 if (dev->devclass) {
6ea70f76 1100 kprintf("device_set_devclass: device class already set\n");
0deb64bd
JS
1101 return(EINVAL);
1102 }
984263bc 1103
91a0c258 1104 dc = devclass_find_internal(classname, NULL, TRUE);
0deb64bd
JS
1105 if (!dc)
1106 return(ENOMEM);
984263bc 1107
0010e23a
HT
1108 error = devclass_add_device(dc, dev);
1109
1110 bus_data_generation_update();
1111 return(error);
984263bc
MD
1112}
1113
1114int
1115device_set_driver(device_t dev, driver_t *driver)
1116{
0deb64bd
JS
1117 if (dev->state >= DS_ATTACHED)
1118 return(EBUSY);
984263bc 1119
0deb64bd
JS
1120 if (dev->driver == driver)
1121 return(0);
984263bc 1122
0deb64bd 1123 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
efda3bd0 1124 kfree(dev->softc, M_BUS);
0deb64bd 1125 dev->softc = NULL;
20d25173 1126 }
0deb64bd
JS
1127 kobj_delete((kobj_t) dev, 0);
1128 dev->driver = driver;
1129 if (driver) {
1130 kobj_init((kobj_t) dev, (kobj_class_t) driver);
1131 if (!(dev->flags & DF_EXTERNALSOFTC)) {
efda3bd0 1132 dev->softc = kmalloc(driver->size, M_BUS,
3b284c6a 1133 M_INTWAIT | M_ZERO);
0deb64bd
JS
1134 if (!dev->softc) {
1135 kobj_delete((kobj_t)dev, 0);
1136 kobj_init((kobj_t) dev, &null_class);
1137 dev->driver = NULL;
1138 return(ENOMEM);
1139 }
1140 }
0010e23a 1141 } else {
0deb64bd 1142 kobj_init((kobj_t) dev, &null_class);
0010e23a
HT
1143 }
1144
1145 bus_data_generation_update();
0deb64bd 1146 return(0);
984263bc
MD
1147}
1148
1149int
1150device_probe_and_attach(device_t dev)
1151{
0deb64bd
JS
1152 device_t bus = dev->parent;
1153 int error = 0;
984263bc 1154
0deb64bd
JS
1155 if (dev->state >= DS_ALIVE)
1156 return(0);
1157
1158 if ((dev->flags & DF_ENABLED) == 0) {
1159 if (bootverbose) {
1160 device_print_prettyname(dev);
6ea70f76 1161 kprintf("not probed (disabled)\n");
0deb64bd
JS
1162 }
1163 return(0);
1164 }
984263bc 1165
984263bc 1166 error = device_probe_child(bus, dev);
0deb64bd
JS
1167 if (error) {
1168 if (!(dev->flags & DF_DONENOMATCH)) {
1169 BUS_PROBE_NOMATCH(bus, dev);
1170 dev->flags |= DF_DONENOMATCH;
1171 }
1172 return(error);
1173 }
1b20a98f
MD
1174
1175 /*
1176 * Output the exact device chain prior to the attach in case the
1177 * system locks up during attach, and generate the full info after
1178 * the attach so correct irq and other information is displayed.
1179 */
1180 if (bootverbose && !device_is_quiet(dev)) {
1181 device_t tmp;
1182
6ea70f76 1183 kprintf("%s", device_get_nameunit(dev));
64f6c535 1184 for (tmp = dev->parent; tmp; tmp = tmp->parent)
6ea70f76
SW
1185 kprintf(".%s", device_get_nameunit(tmp));
1186 kprintf("\n");
1b20a98f 1187 }
0deb64bd 1188 if (!device_is_quiet(dev))
984263bc 1189 device_print_child(bus, dev);
dbcd0c9b
MD
1190 if ((dev->flags & DF_ASYNCPROBE) && do_async_attach) {
1191 kprintf("%s: probing asynchronously\n",
1192 device_get_nameunit(dev));
1193 dev->state = DS_INPROGRESS;
1194 device_attach_async(dev);
1195 error = 0;
1196 } else {
1197 error = device_doattach(dev);
1198 }
1199 return(error);
1200}
1201
1202/*
1203 * Device is known to be alive, do the attach asynchronously.
1204 *
1205 * The MP lock is held by all threads.
1206 */
1207static void
1208device_attach_async(device_t dev)
1209{
1210 thread_t td;
1211
1212 atomic_add_int(&numasyncthreads, 1);
1213 lwkt_create(device_attach_thread, dev, &td, NULL,
1214 0, 0, (dev->desc ? dev->desc : "devattach"));
1215}
1216
1217static void
1218device_attach_thread(void *arg)
1219{
1220 device_t dev = arg;
1221
1222 (void)device_doattach(dev);
1223 atomic_subtract_int(&numasyncthreads, 1);
1224 wakeup(&numasyncthreads);
1225}
1226
1227/*
1228 * Device is known to be alive, do the attach (synchronous or asynchronous)
1229 */
1230static int
1231device_doattach(device_t dev)
1232{
1233 device_t bus = dev->parent;
1234 int hasclass = (dev->devclass != 0);
1235 int error;
1236
b99fcb0c 1237 error = DEVICE_ATTACH(dev);
1b20a98f 1238 if (error == 0) {
984263bc 1239 dev->state = DS_ATTACHED;
b99fcb0c
MD
1240 if (bootverbose && !device_is_quiet(dev))
1241 device_print_child(bus, dev);
1b20a98f 1242 } else {
6ea70f76 1243 kprintf("device_probe_and_attach: %s%d attach returned %d\n",
984263bc
MD
1244 dev->driver->name, dev->unit, error);
1245 /* Unset the class that was set in device_probe_child */
1246 if (!hasclass)
0deb64bd 1247 device_set_devclass(dev, 0);
984263bc
MD
1248 device_set_driver(dev, NULL);
1249 dev->state = DS_NOTPRESENT;
984263bc 1250 }
0deb64bd 1251 return(error);
984263bc
MD
1252}
1253
1254int
1255device_detach(device_t dev)
1256{
0deb64bd 1257 int error;
984263bc 1258
0deb64bd
JS
1259 PDEBUG(("%s", DEVICENAME(dev)));
1260 if (dev->state == DS_BUSY)
1261 return(EBUSY);
1262 if (dev->state != DS_ATTACHED)
1263 return(0);
984263bc 1264
0deb64bd
JS
1265 if ((error = DEVICE_DETACH(dev)) != 0)
1266 return(error);
1267 device_printf(dev, "detached\n");
1268 if (dev->parent)
1269 BUS_CHILD_DETACHED(dev->parent, dev);
984263bc 1270
0deb64bd
JS
1271 if (!(dev->flags & DF_FIXEDCLASS))
1272 devclass_delete_device(dev->devclass, dev);
984263bc 1273
0deb64bd
JS
1274 dev->state = DS_NOTPRESENT;
1275 device_set_driver(dev, NULL);
984263bc 1276
0deb64bd 1277 return(0);
984263bc
MD
1278}
1279
1280int
1281device_shutdown(device_t dev)
1282{
0deb64bd
JS
1283 if (dev->state < DS_ATTACHED)
1284 return 0;
bb088466 1285 PDEBUG(("%s", DEVICENAME(dev)));
0deb64bd 1286 return DEVICE_SHUTDOWN(dev);
984263bc
MD
1287}
1288
1289int
1290device_set_unit(device_t dev, int unit)
1291{
0deb64bd
JS
1292 devclass_t dc;
1293 int err;
984263bc 1294
0deb64bd
JS
1295 dc = device_get_devclass(dev);
1296 if (unit < dc->maxunit && dc->devices[unit])
1297 return(EBUSY);
1298 err = devclass_delete_device(dc, dev);
1299 if (err)
1300 return(err);
1301 dev->unit = unit;
1302 err = devclass_add_device(dc, dev);
0010e23a
HT
1303 if (err)
1304 return(err);
984263bc 1305
0010e23a
HT
1306 bus_data_generation_update();
1307 return(0);
984263bc
MD
1308}
1309
984263bc
MD
1310/*======================================*/
1311/*
1312 * Access functions for device resources.
1313 */
1314
1315/* Supplied by config(8) in ioconf.c */
1316extern struct config_device config_devtab[];
1317extern int devtab_count;
1318
1319/* Runtime version */
1320struct config_device *devtab = config_devtab;
1321
1322static int
1323resource_new_name(const char *name, int unit)
1324{
1325 struct config_device *new;
1326
efda3bd0 1327 new = kmalloc((devtab_count + 1) * sizeof(*new), M_TEMP,
3b284c6a 1328 M_INTWAIT | M_ZERO);
984263bc 1329 if (new == NULL)
0deb64bd 1330 return(-1);
984263bc
MD
1331 if (devtab && devtab_count > 0)
1332 bcopy(devtab, new, devtab_count * sizeof(*new));
efda3bd0 1333 new[devtab_count].name = kmalloc(strlen(name) + 1, M_TEMP, M_INTWAIT);
984263bc 1334 if (new[devtab_count].name == NULL) {
efda3bd0 1335 kfree(new, M_TEMP);
0deb64bd 1336 return(-1);
984263bc
MD
1337 }
1338 strcpy(new[devtab_count].name, name);
1339 new[devtab_count].unit = unit;
1340 new[devtab_count].resource_count = 0;
1341 new[devtab_count].resources = NULL;
b1954fd1 1342 if (devtab && devtab != config_devtab)
efda3bd0 1343 kfree(devtab, M_TEMP);
984263bc
MD
1344 devtab = new;
1345 return devtab_count++;
1346}
1347
1348static int
1349resource_new_resname(int j, const char *resname, resource_type type)
1350{
1351 struct config_resource *new;
1352 int i;
1353
1354 i = devtab[j].resource_count;
efda3bd0 1355 new = kmalloc((i + 1) * sizeof(*new), M_TEMP, M_INTWAIT | M_ZERO);
984263bc 1356 if (new == NULL)
0deb64bd 1357 return(-1);
984263bc
MD
1358 if (devtab[j].resources && i > 0)
1359 bcopy(devtab[j].resources, new, i * sizeof(*new));
efda3bd0 1360 new[i].name = kmalloc(strlen(resname) + 1, M_TEMP, M_INTWAIT);
984263bc 1361 if (new[i].name == NULL) {
efda3bd0 1362 kfree(new, M_TEMP);
0deb64bd 1363 return(-1);
984263bc
MD
1364 }
1365 strcpy(new[i].name, resname);
1366 new[i].type = type;
1367 if (devtab[j].resources)
efda3bd0 1368 kfree(devtab[j].resources, M_TEMP);
984263bc
MD
1369 devtab[j].resources = new;
1370 devtab[j].resource_count = i + 1;
0deb64bd 1371 return(i);
984263bc
MD
1372}
1373
1374static int
1375resource_match_string(int i, const char *resname, const char *value)
1376{
1377 int j;
1378 struct config_resource *res;
1379
1380 for (j = 0, res = devtab[i].resources;
1381 j < devtab[i].resource_count; j++, res++)
1382 if (!strcmp(res->name, resname)
1383 && res->type == RES_STRING
1384 && !strcmp(res->u.stringval, value))
0deb64bd
JS
1385 return(j);
1386 return(-1);
984263bc
MD
1387}
1388
1389static int
1390resource_find(const char *name, int unit, const char *resname,
1391 struct config_resource **result)
1392{
1393 int i, j;
1394 struct config_resource *res;
1395
1396 /*
1397 * First check specific instances, then generic.
1398 */
1399 for (i = 0; i < devtab_count; i++) {
1400 if (devtab[i].unit < 0)
1401 continue;
1402 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1403 res = devtab[i].resources;
1404 for (j = 0; j < devtab[i].resource_count; j++, res++)
1405 if (!strcmp(res->name, resname)) {
1406 *result = res;
0deb64bd 1407 return(0);
984263bc
MD
1408 }
1409 }
1410 }
1411 for (i = 0; i < devtab_count; i++) {
1412 if (devtab[i].unit >= 0)
1413 continue;
1414 /* XXX should this `&& devtab[i].unit == unit' be here? */
1415 /* XXX if so, then the generic match does nothing */
1416 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1417 res = devtab[i].resources;
1418 for (j = 0; j < devtab[i].resource_count; j++, res++)
1419 if (!strcmp(res->name, resname)) {
1420 *result = res;
0deb64bd 1421 return(0);
984263bc
MD
1422 }
1423 }
1424 }
0deb64bd 1425 return(ENOENT);
984263bc
MD
1426}
1427
1428int
1429resource_int_value(const char *name, int unit, const char *resname, int *result)
1430{
1431 int error;
1432 struct config_resource *res;
1433
1434 if ((error = resource_find(name, unit, resname, &res)) != 0)
0deb64bd 1435 return(error);
984263bc 1436 if (res->type != RES_INT)
0deb64bd 1437 return(EFTYPE);
984263bc 1438 *result = res->u.intval;
0deb64bd 1439 return(0);
984263bc
MD
1440}
1441
1442int
1443resource_long_value(const char *name, int unit, const char *resname,
1444 long *result)
1445{
1446 int error;
1447 struct config_resource *res;
1448
1449 if ((error = resource_find(name, unit, resname, &res)) != 0)
0deb64bd 1450 return(error);
984263bc 1451 if (res->type != RES_LONG)
0deb64bd 1452 return(EFTYPE);
984263bc 1453 *result = res->u.longval;
0deb64bd 1454 return(0);
984263bc
MD
1455}
1456
1457int
1458resource_string_value(const char *name, int unit, const char *resname,
1459 char **result)
1460{
1461 int error;
1462 struct config_resource *res;
1463
1464 if ((error = resource_find(name, unit, resname, &res)) != 0)
0deb64bd 1465 return(error);
984263bc 1466 if (res->type != RES_STRING)
0deb64bd 1467 return(EFTYPE);
984263bc 1468 *result = res->u.stringval;
0deb64bd 1469 return(0);
984263bc
MD
1470}
1471
1472int
1473resource_query_string(int i, const char *resname, const char *value)
1474{
1475 if (i < 0)
1476 i = 0;
1477 else
1478 i = i + 1;
1479 for (; i < devtab_count; i++)
1480 if (resource_match_string(i, resname, value) >= 0)
0deb64bd
JS
1481 return(i);
1482 return(-1);
984263bc
MD
1483}
1484
1485int
1486resource_locate(int i, const char *resname)
1487{
1488 if (i < 0)
1489 i = 0;
1490 else
1491 i = i + 1;
1492 for (; i < devtab_count; i++)
1493 if (!strcmp(devtab[i].name, resname))
0deb64bd
JS
1494 return(i);
1495 return(-1);
984263bc
MD
1496}
1497
1498int
1499resource_count(void)
1500{
0deb64bd 1501 return(devtab_count);
984263bc
MD
1502}
1503
1504char *
1505resource_query_name(int i)
1506{
0deb64bd 1507 return(devtab[i].name);
984263bc
MD
1508}
1509
1510int
1511resource_query_unit(int i)
1512{
0deb64bd 1513 return(devtab[i].unit);
984263bc
MD
1514}
1515
1516static int
1517resource_create(const char *name, int unit, const char *resname,
1518 resource_type type, struct config_resource **result)
1519{
1520 int i, j;
1521 struct config_resource *res = NULL;
1522
0deb64bd 1523 for (i = 0; i < devtab_count; i++)
984263bc
MD
1524 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
1525 res = devtab[i].resources;
1526 break;
1527 }
984263bc
MD
1528 if (res == NULL) {
1529 i = resource_new_name(name, unit);
1530 if (i < 0)
0deb64bd 1531 return(ENOMEM);
984263bc
MD
1532 res = devtab[i].resources;
1533 }
0deb64bd 1534 for (j = 0; j < devtab[i].resource_count; j++, res++)
984263bc
MD
1535 if (!strcmp(res->name, resname)) {
1536 *result = res;
0deb64bd 1537 return(0);
984263bc 1538 }
984263bc
MD
1539 j = resource_new_resname(i, resname, type);
1540 if (j < 0)
0deb64bd 1541 return(ENOMEM);
984263bc
MD
1542 res = &devtab[i].resources[j];
1543 *result = res;
0deb64bd 1544 return(0);
984263bc
MD
1545}
1546
1547int
1548resource_set_int(const char *name, int unit, const char *resname, int value)
1549{
1550 int error;
1551 struct config_resource *res;
1552
1553 error = resource_create(name, unit, resname, RES_INT, &res);
1554 if (error)
0deb64bd 1555 return(error);
984263bc 1556 if (res->type != RES_INT)
0deb64bd 1557 return(EFTYPE);
984263bc 1558 res->u.intval = value;
0deb64bd 1559 return(0);
984263bc
MD
1560}
1561
1562int
1563resource_set_long(const char *name, int unit, const char *resname, long value)
1564{
1565 int error;
1566 struct config_resource *res;
1567
1568 error = resource_create(name, unit, resname, RES_LONG, &res);
1569 if (error)
0deb64bd 1570 return(error);
984263bc 1571 if (res->type != RES_LONG)
0deb64bd 1572 return(EFTYPE);
984263bc 1573 res->u.longval = value;
0deb64bd 1574 return(0);
984263bc
MD
1575}
1576
1577int
1578resource_set_string(const char *name, int unit, const char *resname,
1579 const char *value)
1580{
1581 int error;
1582 struct config_resource *res;
1583
1584 error = resource_create(name, unit, resname, RES_STRING, &res);
1585 if (error)
0deb64bd 1586 return(error);
984263bc 1587 if (res->type != RES_STRING)
0deb64bd 1588 return(EFTYPE);
984263bc 1589 if (res->u.stringval)
efda3bd0
MD
1590 kfree(res->u.stringval, M_TEMP);
1591 res->u.stringval = kmalloc(strlen(value) + 1, M_TEMP, M_INTWAIT);
984263bc 1592 if (res->u.stringval == NULL)
0deb64bd 1593 return(ENOMEM);
984263bc 1594 strcpy(res->u.stringval, value);
0deb64bd 1595 return(0);
984263bc
MD
1596}
1597
984263bc
MD
1598static void
1599resource_cfgload(void *dummy __unused)
1600{
1601 struct config_resource *res, *cfgres;
1602 int i, j;
1603 int error;
1604 char *name, *resname;
1605 int unit;
1606 resource_type type;
1607 char *stringval;
1608 int config_devtab_count;
1609
1610 config_devtab_count = devtab_count;
1611 devtab = NULL;
1612 devtab_count = 0;
1613
1614 for (i = 0; i < config_devtab_count; i++) {
1615 name = config_devtab[i].name;
1616 unit = config_devtab[i].unit;
1617
1618 for (j = 0; j < config_devtab[i].resource_count; j++) {
1619 cfgres = config_devtab[i].resources;
1620 resname = cfgres[j].name;
1621 type = cfgres[j].type;
1622 error = resource_create(name, unit, resname, type,
1623 &res);
1624 if (error) {
6ea70f76 1625 kprintf("create resource %s%d: error %d\n",
984263bc
MD
1626 name, unit, error);
1627 continue;
1628 }
1629 if (res->type != type) {
6ea70f76 1630 kprintf("type mismatch %s%d: %d != %d\n",
984263bc
MD
1631 name, unit, res->type, type);
1632 continue;
1633 }
1634 switch (type) {
1635 case RES_INT:
1636 res->u.intval = cfgres[j].u.intval;
1637 break;
1638 case RES_LONG:
1639 res->u.longval = cfgres[j].u.longval;
1640 break;
1641 case RES_STRING:
1642 if (res->u.stringval)
efda3bd0 1643 kfree(res->u.stringval, M_TEMP);
984263bc 1644 stringval = cfgres[j].u.stringval;
77652cad 1645 res->u.stringval = kmalloc(strlen(stringval) + 1,
3b284c6a 1646 M_TEMP, M_INTWAIT);
984263bc
MD
1647 if (res->u.stringval == NULL)
1648 break;
1649 strcpy(res->u.stringval, stringval);
1650 break;
1651 default:
fc92d4aa 1652 panic("unknown resource type %d", type);
984263bc
MD
1653 }
1654 }
1655 }
1656}
ba39e2e0 1657SYSINIT(cfgload, SI_BOOT1_POST, SI_ORDER_ANY + 50, resource_cfgload, 0)
984263bc
MD
1658
1659
1660/*======================================*/
1661/*
1662 * Some useful method implementations to make life easier for bus drivers.
1663 */
1664
1665void
1666resource_list_init(struct resource_list *rl)
1667{
1668 SLIST_INIT(rl);
1669}
1670
1671void
1672resource_list_free(struct resource_list *rl)
1673{
0deb64bd 1674 struct resource_list_entry *rle;
984263bc 1675
0deb64bd
JS
1676 while ((rle = SLIST_FIRST(rl)) != NULL) {
1677 if (rle->res)
1678 panic("resource_list_free: resource entry is busy");
1679 SLIST_REMOVE_HEAD(rl, link);
efda3bd0 1680 kfree(rle, M_BUS);
0deb64bd 1681 }
984263bc
MD
1682}
1683
1684void
1685resource_list_add(struct resource_list *rl,
1686 int type, int rid,
1687 u_long start, u_long end, u_long count)
1688{
0deb64bd 1689 struct resource_list_entry *rle;
984263bc 1690
0deb64bd
JS
1691 rle = resource_list_find(rl, type, rid);
1692 if (rle == NULL) {
efda3bd0 1693 rle = kmalloc(sizeof(struct resource_list_entry), M_BUS,
3b284c6a 1694 M_INTWAIT);
0deb64bd
JS
1695 if (!rle)
1696 panic("resource_list_add: can't record entry");
1697 SLIST_INSERT_HEAD(rl, rle, link);
1698 rle->type = type;
1699 rle->rid = rid;
1700 rle->res = NULL;
1701 }
984263bc 1702
0deb64bd
JS
1703 if (rle->res)
1704 panic("resource_list_add: resource entry is busy");
984263bc 1705
0deb64bd
JS
1706 rle->start = start;
1707 rle->end = end;
1708 rle->count = count;
984263bc
MD
1709}
1710
1711struct resource_list_entry*
1712resource_list_find(struct resource_list *rl,
1713 int type, int rid)
1714{
0deb64bd 1715 struct resource_list_entry *rle;
984263bc 1716
0deb64bd
JS
1717 SLIST_FOREACH(rle, rl, link)
1718 if (rle->type == type && rle->rid == rid)
1719 return(rle);
1720 return(NULL);
984263bc
MD
1721}
1722
1723void
1724resource_list_delete(struct resource_list *rl,
1725 int type, int rid)
1726{
0deb64bd 1727 struct resource_list_entry *rle = resource_list_find(rl, type, rid);
984263bc 1728
0deb64bd 1729 if (rle) {
0010e23a
HT
1730 if (rle->res != NULL)
1731 panic("resource_list_delete: resource has not been released");
0deb64bd 1732 SLIST_REMOVE(rl, rle, resource_list_entry, link);
efda3bd0 1733 kfree(rle, M_BUS);
0deb64bd 1734 }
984263bc
MD
1735}
1736
1737struct resource *
1738resource_list_alloc(struct resource_list *rl,
1739 device_t bus, device_t child,
1740 int type, int *rid,
1741 u_long start, u_long end,
1742 u_long count, u_int flags)
1743{
0deb64bd
JS
1744 struct resource_list_entry *rle = 0;
1745 int passthrough = (device_get_parent(child) != bus);
1746 int isdefault = (start == 0UL && end == ~0UL);
984263bc 1747
0deb64bd
JS
1748 if (passthrough) {
1749 return(BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
1750 type, rid,
1751 start, end, count, flags));
1752 }
984263bc 1753
0deb64bd 1754 rle = resource_list_find(rl, type, *rid);
984263bc 1755
0deb64bd
JS
1756 if (!rle)
1757 return(0); /* no resource of that type/rid */
0010e23a 1758
0deb64bd
JS
1759 if (rle->res)
1760 panic("resource_list_alloc: resource entry is busy");
984263bc 1761
0deb64bd
JS
1762 if (isdefault) {
1763 start = rle->start;
1764 count = max(count, rle->count);
1765 end = max(rle->end, start + count - 1);
1766 }
984263bc 1767
0deb64bd
JS
1768 rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
1769 type, rid, start, end, count, flags);
984263bc 1770
0deb64bd
JS
1771 /*
1772 * Record the new range.
1773 */
1774 if (rle->res) {
1775 rle->start = rman_get_start(rle->res);
1776 rle->end = rman_get_end(rle->res);
1777 rle->count = count;
1778 }
984263bc 1779
0deb64bd 1780 return(rle->res);
984263bc
MD
1781}
1782
1783int
1784resource_list_release(struct resource_list *rl,
1785 device_t bus, device_t child,
1786 int type, int rid, struct resource *res)
1787{
0deb64bd
JS
1788 struct resource_list_entry *rle = 0;
1789 int passthrough = (device_get_parent(child) != bus);
1790 int error;
984263bc 1791
0deb64bd
JS
1792 if (passthrough) {
1793 return(BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
1794 type, rid, res));
1795 }
984263bc 1796
0deb64bd 1797 rle = resource_list_find(rl, type, rid);
984263bc 1798
0deb64bd
JS
1799 if (!rle)
1800 panic("resource_list_release: can't find resource");
1801 if (!rle->res)
1802 panic("resource_list_release: resource entry is not busy");
984263bc 1803
0deb64bd
JS
1804 error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
1805 type, rid, res);
1806 if (error)
1807 return(error);
984263bc 1808
0deb64bd
JS
1809 rle->res = NULL;
1810 return(0);
984263bc
MD
1811}
1812
1813int
1814resource_list_print_type(struct resource_list *rl, const char *name, int type,
0deb64bd 1815 const char *format)
984263bc
MD
1816{
1817 struct resource_list_entry *rle;
1818 int printed, retval;
1819
1820 printed = 0;
1821 retval = 0;
1822 /* Yes, this is kinda cheating */
1823 SLIST_FOREACH(rle, rl, link) {
1824 if (rle->type == type) {
1825 if (printed == 0)
6ea70f76 1826 retval += kprintf(" %s ", name);
984263bc 1827 else
6ea70f76 1828 retval += kprintf(",");
984263bc 1829 printed++;
6ea70f76 1830 retval += kprintf(format, rle->start);
984263bc 1831 if (rle->count > 1) {
6ea70f76
SW
1832 retval += kprintf("-");
1833 retval += kprintf(format, rle->start +
984263bc
MD
1834 rle->count - 1);
1835 }
1836 }
1837 }
0deb64bd 1838 return(retval);
984263bc
MD
1839}
1840
39b5d600
MD
1841/*
1842 * Generic driver/device identify functions. These will install a device
1843 * rendezvous point under the parent using the same name as the driver
1844 * name, which will at a later time be probed and attached.
1845 *
1846 * These functions are used when the parent does not 'scan' its bus for
1847 * matching devices, or for the particular devices using these functions,
1848 * or when the device is a pseudo or synthesized device (such as can be
1849 * found under firewire and ppbus).
1850 */
1851int
1852bus_generic_identify(driver_t *driver, device_t parent)
1853{
1854 if (parent->state == DS_ATTACHED)
1855 return (0);
2581072f 1856 BUS_ADD_CHILD(parent, parent, 0, driver->name, -1);
39b5d600
MD
1857 return (0);
1858}
1859
1860int
1861bus_generic_identify_sameunit(driver_t *driver, device_t parent)
1862{
1863 if (parent->state == DS_ATTACHED)
1864 return (0);
2581072f 1865 BUS_ADD_CHILD(parent, parent, 0, driver->name, device_get_unit(parent));
39b5d600
MD
1866 return (0);
1867}
1868
984263bc
MD
1869/*
1870 * Call DEVICE_IDENTIFY for each driver.
1871 */
1872int
1873bus_generic_probe(device_t dev)
1874{
0deb64bd
JS
1875 devclass_t dc = dev->devclass;
1876 driverlink_t dl;
984263bc 1877
39b5d600 1878 TAILQ_FOREACH(dl, &dc->drivers, link) {
0deb64bd 1879 DEVICE_IDENTIFY(dl->driver, dev);
39b5d600 1880 }
984263bc 1881
0deb64bd 1882 return(0);
984263bc
MD
1883}
1884
39b5d600
MD
1885/*
1886 * This is an aweful hack due to the isa bus and autoconf code not
1887 * probing the ISA devices until after everything else has configured.
1888 * The ISA bus did a dummy attach long ago so we have to set it back
1889 * to an earlier state so the probe thinks its the initial probe and
1890 * not a bus rescan.
1891 *
1892 * XXX remove by properly defering the ISA bus scan.
1893 */
1894int
1895bus_generic_probe_hack(device_t dev)
1896{
1897 if (dev->state == DS_ATTACHED) {
1898 dev->state = DS_ALIVE;
1899 bus_generic_probe(dev);
1900 dev->state = DS_ATTACHED;
1901 }
1902 return (0);
1903}
1904
984263bc
MD
1905int
1906bus_generic_attach(device_t dev)
1907{
0deb64bd 1908 device_t child;
984263bc 1909
39b5d600 1910 TAILQ_FOREACH(child, &dev->children, link) {
0deb64bd 1911 device_probe_and_attach(child);
39b5d600 1912 }
984263bc 1913
0deb64bd 1914 return(0);
984263bc
MD
1915}
1916
1917int
1918bus_generic_detach(device_t dev)
1919{
0deb64bd
JS
1920 device_t child;
1921 int error;
984263bc 1922
0deb64bd
JS
1923 if (dev->state != DS_ATTACHED)
1924 return(EBUSY);
984263bc 1925
0deb64bd
JS
1926 TAILQ_FOREACH(child, &dev->children, link)
1927 if ((error = device_detach(child)) != 0)
1928 return(error);
984263bc 1929
0deb64bd 1930 return 0;
984263bc
MD
1931}
1932
1933int
1934bus_generic_shutdown(device_t dev)
1935{
0deb64bd 1936 device_t child;
984263bc 1937
0deb64bd
JS
1938 TAILQ_FOREACH(child, &dev->children, link)
1939 device_shutdown(child);
984263bc 1940
0deb64bd 1941 return(0);
984263bc
MD
1942}
1943
1944int
1945bus_generic_suspend(device_t dev)
1946{
0deb64bd
JS
1947 int error;
1948 device_t child, child2;
984263bc 1949
8d0e5ff2 1950 TAILQ_FOREACH(child, &dev->children, link) {
984263bc
MD
1951 error = DEVICE_SUSPEND(child);
1952 if (error) {
1953 for (child2 = TAILQ_FIRST(&dev->children);
1954 child2 && child2 != child;
1955 child2 = TAILQ_NEXT(child2, link))
1956 DEVICE_RESUME(child2);
0deb64bd 1957 return(error);
984263bc
MD
1958 }
1959 }
0deb64bd 1960 return(0);
984263bc
MD
1961}
1962
1963int
1964bus_generic_resume(device_t dev)
1965{
0deb64bd 1966 device_t child;
984263bc 1967
0deb64bd 1968 TAILQ_FOREACH(child, &dev->children, link)
984263bc
MD
1969 DEVICE_RESUME(child);
1970 /* if resume fails, there's nothing we can usefully do... */
0deb64bd
JS
1971
1972 return(0);
984263bc
MD
1973}
1974
1975int
0deb64bd 1976bus_print_child_header(device_t dev, device_t child)
984263bc 1977{
0deb64bd 1978 int retval = 0;
984263bc 1979
0deb64bd
JS
1980 if (device_get_desc(child))
1981 retval += device_printf(child, "<%s>", device_get_desc(child));
1982 else
6ea70f76 1983 retval += kprintf("%s", device_get_nameunit(child));
b99fcb0c
MD
1984 if (bootverbose) {
1985 if (child->state != DS_ATTACHED)
6ea70f76 1986 kprintf(" [tentative]");
b99fcb0c 1987 else
6ea70f76 1988 kprintf(" [attached!]");
b99fcb0c 1989 }
0deb64bd 1990 return(retval);
984263bc
MD
1991}
1992
1993int
0deb64bd 1994bus_print_child_footer(device_t dev, device_t child)
984263bc 1995{
6ea70f76 1996 return(kprintf(" on %s\n", device_get_nameunit(dev)));
984263bc
MD
1997}
1998
2581072f
MD
1999device_t
2000bus_generic_add_child(device_t dev, device_t child, int order,
2001 const char *name, int unit)
2002{
2003 if (dev->parent)
2004 dev = BUS_ADD_CHILD(dev->parent, child, order, name, unit);
2005 else
2006 dev = device_add_child_ordered(child, order, name, unit);
2007 return(dev);
2008
2009}
2010
984263bc
MD
2011int
2012bus_generic_print_child(device_t dev, device_t child)
2013{
0deb64bd 2014 int retval = 0;
984263bc
MD
2015
2016 retval += bus_print_child_header(dev, child);
2017 retval += bus_print_child_footer(dev, child);
2018
0deb64bd 2019 return(retval);
984263bc
MD
2020}
2021
2022int
2023bus_generic_read_ivar(device_t dev, device_t child, int index,
2024 uintptr_t * result)
2025{
2581072f
MD
2026 int error;
2027
2028 if (dev->parent)
2029 error = BUS_READ_IVAR(dev->parent, child, index, result);
2030 else
2031 error = ENOENT;
2032 return (error);
984263bc
MD
2033}
2034
2035int
2036bus_generic_write_ivar(device_t dev, device_t child, int index,
2037 uintptr_t value)
2038{
2581072f
MD
2039 int error;
2040
2041 if (dev->parent)
2042 error = BUS_WRITE_IVAR(dev->parent, child, index, value);
2043 else
2044 error = ENOENT;
2045 return (error);
984263bc
MD
2046}
2047
04ddb925
MD
2048/*
2049 * Resource list are used for iterations, do not recurse.
2050 */
e126caf1
MD
2051struct resource_list *
2052bus_generic_get_resource_list(device_t dev, device_t child)
2053{
04ddb925 2054 return (NULL);
e126caf1
MD
2055}
2056
984263bc
MD
2057void
2058bus_generic_driver_added(device_t dev, driver_t *driver)
2059{
0deb64bd 2060 device_t child;
984263bc 2061
0deb64bd 2062 DEVICE_IDENTIFY(driver, dev);
39b5d600 2063 TAILQ_FOREACH(child, &dev->children, link) {
0deb64bd
JS
2064 if (child->state == DS_NOTPRESENT)
2065 device_probe_and_attach(child);
39b5d600 2066 }
984263bc
MD
2067}
2068
2069int
2070bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
2071 int flags, driver_intr_t *intr, void *arg,
e9cb6d99 2072 void **cookiep, lwkt_serialize_t serializer)
984263bc
MD
2073{
2074 /* Propagate up the bus hierarchy until someone handles it. */
2075 if (dev->parent)
0deb64bd 2076 return(BUS_SETUP_INTR(dev->parent, child, irq, flags,
e9cb6d99 2077 intr, arg, cookiep, serializer));
984263bc 2078 else
0deb64bd 2079 return(EINVAL);
984263bc
MD
2080}
2081
2082int
2083bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
2084 void *cookie)
2085{
2086 /* Propagate up the bus hierarchy until someone handles it. */
2087 if (dev->parent)
0deb64bd 2088 return(BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie));
984263bc 2089 else
0deb64bd 2090 return(EINVAL);
984263bc
MD
2091}
2092
e9cb6d99 2093int
67a2436e
MD
2094bus_generic_disable_intr(device_t dev, device_t child, void *cookie)
2095{
2096 if (dev->parent)
e9cb6d99
MD
2097 return(BUS_DISABLE_INTR(dev->parent, child, cookie));
2098 else
2099 return(0);
67a2436e
MD
2100}
2101
2102void
2103bus_generic_enable_intr(device_t dev, device_t child, void *cookie)
2104{
2105 if (dev->parent)
2106 BUS_ENABLE_INTR(dev->parent, child, cookie);
2107}
2108
2581072f
MD
2109int
2110bus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig,
2111 enum intr_polarity pol)
2112{
2113 /* Propagate up the bus hierarchy until someone handles it. */
2114 if (dev->parent)
2115 return(BUS_CONFIG_INTR(dev->parent, irq, trig, pol));
2116 else
2117 return(EINVAL);
2118}
2119
984263bc
MD
2120struct resource *
2121bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
2122 u_long start, u_long end, u_long count, u_int flags)
2123{
2124 /* Propagate up the bus hierarchy until someone handles it. */
2125 if (dev->parent)
0deb64bd 2126 return(BUS_ALLOC_RESOURCE(dev->parent, child, type, rid,
984263bc
MD
2127 start, end, count, flags));
2128 else
0deb64bd 2129 return(NULL);
984263bc
MD
2130}
2131
2132int
2133bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
2134 struct resource *r)
2135{
2136 /* Propagate up the bus hierarchy until someone handles it. */
2137 if (dev->parent)
0deb64bd 2138 return(BUS_RELEASE_RESOURCE(dev->parent, child, type, rid, r));
984263bc 2139 else
0deb64bd 2140 return(EINVAL);
984263bc
MD
2141}
2142
2143int
2144bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
2145 struct resource *r)
2146{
2147 /* Propagate up the bus hierarchy until someone handles it. */
2148 if (dev->parent)
0deb64bd 2149 return(BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, r));
984263bc 2150 else
0deb64bd 2151 return(EINVAL);
984263bc
MD
2152}
2153
2154int
2155bus_generic_deactivate_resource(device_t dev, device_t child, int type,
2156 int rid, struct resource *r)
2157{
2158 /* Propagate up the bus hierarchy until someone handles it. */
2159 if (dev->parent)
0deb64bd
JS
2160 return(BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid,
2161 r));
984263bc 2162 else
0deb64bd 2163 return(EINVAL);
984263bc
MD
2164}
2165
e126caf1 2166int
2581072f
MD
2167bus_generic_get_resource(device_t dev, device_t child, int type, int rid,
2168 u_long *startp, u_long *countp)
2169{
2170 int error;
2171
2172 error = ENOENT;
2173 if (dev->parent) {
2174 error = BUS_GET_RESOURCE(dev->parent, child, type, rid,
2175 startp, countp);
2176 }
2177 return (error);
2178}
2179
2180int
2181bus_generic_set_resource(device_t dev, device_t child, int type, int rid,
2182 u_long start, u_long count)
2183{
2184 int error;
2185
2186 error = EINVAL;
2187 if (dev->parent) {
2188 error = BUS_SET_RESOURCE(dev->parent, child, type, rid,
2189 start, count);
2190 }
2191 return (error);
2192}
2193
2194void
2195bus_generic_delete_resource(device_t dev, device_t child, int type, int rid)
e126caf1 2196{
e126caf1 2197 if (dev->parent)
2581072f 2198 BUS_DELETE_RESOURCE(dev, child, type, rid);
e126caf1
MD
2199}
2200
2201int
2202bus_generic_rl_get_resource(device_t dev, device_t child, int type, int rid,
2203 u_long *startp, u_long *countp)
2204{
0deb64bd
JS
2205 struct resource_list *rl = NULL;
2206 struct resource_list_entry *rle = NULL;
e126caf1
MD
2207
2208 rl = BUS_GET_RESOURCE_LIST(dev, child);
2209 if (!rl)
0deb64bd 2210 return(EINVAL);
e126caf1
MD
2211
2212 rle = resource_list_find(rl, type, rid);
2213 if (!rle)
0deb64bd 2214 return(ENOENT);
e126caf1
MD
2215
2216 if (startp)
2217 *startp = rle->start;
2218 if (countp)
2219 *countp = rle->count;
2220
0deb64bd 2221 return(0);
e126caf1
MD
2222}
2223
2224int
2225bus_generic_rl_set_resource(device_t dev, device_t child, int type, int rid,
2226 u_long start, u_long count)
2227{
0deb64bd 2228 struct resource_list *rl = NULL;
e126caf1
MD
2229
2230 rl = BUS_GET_RESOURCE_LIST(dev, child);
2231 if (!rl)
0deb64bd 2232 return(EINVAL);
e126caf1
MD
2233
2234 resource_list_add(rl, type, rid, start, (start + count - 1), count);
2235
0deb64bd 2236 return(0);
e126caf1
MD
2237}
2238
2239void
2240bus_generic_rl_delete_resource(device_t dev, device_t child, int type, int rid)
2241{
0deb64bd 2242 struct resource_list *rl = NULL;
e126caf1
MD
2243
2244 rl = BUS_GET_RESOURCE_LIST(dev, child);
2245 if (!rl)
2246 return;
2247
2248 resource_list_delete(rl, type, rid);
e126caf1
MD
2249}
2250
2251int
2252bus_generic_rl_release_resource(device_t dev, device_t child, int type,
2253 int rid, struct resource *r)
2254{
0deb64bd 2255 struct resource_list *rl = NULL;
e126caf1
MD
2256
2257 rl = BUS_GET_RESOURCE_LIST(dev, child);
2258 if (!rl)
0deb64bd 2259 return(EINVAL);
e126caf1 2260
0deb64bd 2261 return(resource_list_release(rl, dev, child, type, rid, r));
e126caf1
MD
2262}
2263
2264struct resource *
2265bus_generic_rl_alloc_resource(device_t dev, device_t child, int type,
2266 int *rid, u_long start, u_long end, u_long count, u_int flags)
2267{
0deb64bd 2268 struct resource_list *rl = NULL;
e126caf1
MD
2269
2270 rl = BUS_GET_RESOURCE_LIST(dev, child);
2271 if (!rl)
0deb64bd 2272 return(NULL);
e126caf1 2273
0deb64bd 2274 return(resource_list_alloc(rl, dev, child, type, rid,
e126caf1
MD
2275 start, end, count, flags));
2276}
2277
2278int
2279bus_generic_child_present(device_t bus, device_t child)
2280{
0deb64bd 2281 return(BUS_CHILD_PRESENT(device_get_parent(bus), bus));
e126caf1
MD
2282}
2283
2284
984263bc
MD
2285/*
2286 * Some convenience functions to make it easier for drivers to use the
2287 * resource-management functions. All these really do is hide the
2288 * indirection through the parent's method table, making for slightly
2289 * less-wordy code. In the future, it might make sense for this code
2290 * to maintain some sort of a list of resources allocated by each device.
2291 */
43167546
HT
2292int
2293bus_alloc_resources(device_t dev, struct resource_spec *rs,
2294 struct resource **res)
2295{
2296 int i;
2297
2298 for (i = 0; rs[i].type != -1; i++)
2299 res[i] = NULL;
2300 for (i = 0; rs[i].type != -1; i++) {
2301 res[i] = bus_alloc_resource_any(dev,
2302 rs[i].type, &rs[i].rid, rs[i].flags);
2303 if (res[i] == NULL) {
2304 bus_release_resources(dev, rs, res);
2305 return (ENXIO);
2306 }
2307 }
2308 return (0);
2309}
2310
2311void
2312bus_release_resources(device_t dev, const struct resource_spec *rs,
2313 struct resource **res)
2314{
2315 int i;
2316
2317 for (i = 0; rs[i].type != -1; i++)
2318 if (res[i] != NULL) {
2319 bus_release_resource(
2320 dev, rs[i].type, rs[i].rid, res[i]);
2321 res[i] = NULL;
2322 }
2323}
2324
984263bc
MD
2325struct resource *
2326bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
2327 u_long count, u_int flags)
2328{
2329 if (dev->parent == 0)
0deb64bd
JS
2330 return(0);
2331 return(BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
2332 count, flags));
984263bc
MD
2333}
2334
2335int
2336bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
2337{
2338 if (dev->parent == 0)
0deb64bd
JS
2339 return(EINVAL);
2340 return(BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
984263bc
MD
2341}
2342
2343int
2344bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
2345{
2346 if (dev->parent == 0)
0deb64bd
JS
2347 return(EINVAL);
2348 return(BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
984263bc
MD
2349}
2350
2351int
2352bus_release_resource(device_t dev, int type, int rid, struct resource *r)
2353{
2354 if (dev->parent == 0)
0deb64bd
JS
2355 return(EINVAL);
2356 return(BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
984263bc
MD
2357}
2358
2359int
2360bus_setup_intr(device_t dev, struct resource *r, int flags,
e9cb6d99
MD
2361 driver_intr_t handler, void *arg,
2362 void **cookiep, lwkt_serialize_t serializer)
984263bc
MD
2363{
2364 if (dev->parent == 0)
0deb64bd
JS
2365 return(EINVAL);
2366 return(BUS_SETUP_INTR(dev->parent, dev, r, flags, handler, arg,
e9cb6d99 2367 cookiep, serializer));
984263bc
MD
2368}
2369
2370int
2371bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
2372{
2373 if (dev->parent == 0)
0deb64bd
JS
2374 return(EINVAL);
2375 return(BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
984263bc
MD
2376}
2377
67a2436e
MD
2378void
2379bus_enable_intr(device_t dev, void *cookie)
2380{
2381 if (dev->parent)
2382 BUS_ENABLE_INTR(dev->parent, dev, cookie);
2383}
2384
e9cb6d99 2385int
67a2436e
MD
2386bus_disable_intr(device_t dev, void *cookie)
2387{
2388 if (dev->parent)
e9cb6d99
MD
2389 return(BUS_DISABLE_INTR(dev->parent, dev, cookie));
2390 else
2391 return(0);
67a2436e
MD
2392}
2393
984263bc
MD
2394int
2395bus_set_resource(device_t dev, int type, int rid,
2396 u_long start, u_long count)
2397{
0deb64bd
JS
2398 return(BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid,
2399 start, count));
984263bc
MD
2400}
2401
2402int
2403bus_get_resource(device_t dev, int type, int rid,
2404 u_long *startp, u_long *countp)
2405{
0deb64bd
JS
2406 return(BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2407 startp, countp));
984263bc
MD
2408}
2409
2410u_long
2411bus_get_resource_start(device_t dev, int type, int rid)
2412{
2413 u_long start, count;
2414 int error;
2415
2416 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2417 &start, &count);
2418 if (error)
0deb64bd
JS
2419 return(0);
2420 return(start);
984263bc
MD
2421}
2422
2423u_long
2424bus_get_resource_count(device_t dev, int type, int rid)
2425{
2426 u_long start, count;
2427 int error;
2428
2429 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
2430 &start, &count);
2431 if (error)
0deb64bd
JS
2432 return(0);
2433 return(count);
984263bc
MD
2434}
2435
2436void
2437bus_delete_resource(device_t dev, int type, int rid)
2438{
2439 BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid);
2440}
2441
cac6f3da
JS
2442int
2443bus_child_present(device_t child)
2444{
2445 return (BUS_CHILD_PRESENT(device_get_parent(child), child));
2446}
2447
2448int
2449bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen)
2450{
2451 device_t parent;
2452
2453 parent = device_get_parent(child);
2454 if (parent == NULL) {
2455 *buf = '\0';
2456 return (0);
2457 }
2458 return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen));
2459}
2460
2461int
2462bus_child_location_str(device_t child, char *buf, size_t buflen)
2463{
2464 device_t parent;
2465
2466 parent = device_get_parent(child);
2467 if (parent == NULL) {
2468 *buf = '\0';
2469 return (0);
2470 }
2471 return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen));
2472}
2473
984263bc
MD
2474static int
2475root_print_child(device_t dev, device_t child)
2476{
0deb64bd 2477 return(0);
984263bc
MD
2478}
2479
2480static int
2481root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
e9cb6d99 2482 void **cookiep, lwkt_serialize_t serializer)
984263bc
MD
2483{
2484 /*
2485 * If an interrupt mapping gets to here something bad has happened.
2486 */
2487 panic("root_setup_intr");
2488}
2489
e126caf1
MD
2490/*
2491 * If we get here, assume that the device is permanant and really is
2492 * present in the system. Removable bus drivers are expected to intercept
2493 * this call long before it gets here. We return -1 so that drivers that
2494 * really care can check vs -1 or some ERRNO returned higher in the food
2495 * chain.
2496 */
2497static int
2498root_child_present(device_t dev, device_t child)
2499{
0deb64bd 2500 return(-1);
e126caf1
MD
2501}
2502
2503/*
2504 * XXX NOTE! other defaults may be set in bus_if.m
2505 */
80eff43d 2506static kobj_method_t root_methods[] = {
984263bc 2507 /* Device interface */
80eff43d
JR
2508 KOBJMETHOD(device_shutdown, bus_generic_shutdown),
2509 KOBJMETHOD(device_suspend, bus_generic_suspend),
2510 KOBJMETHOD(device_resume, bus_generic_resume),
984263bc
MD
2511
2512 /* Bus interface */
2581072f 2513 KOBJMETHOD(bus_add_child, bus_generic_add_child),
80eff43d
JR
2514 KOBJMETHOD(bus_print_child, root_print_child),
2515 KOBJMETHOD(bus_read_ivar, bus_generic_read_ivar),
2516 KOBJMETHOD(bus_write_ivar, bus_generic_write_ivar),
2517 KOBJMETHOD(bus_setup_intr, root_setup_intr),
e126caf1 2518 KOBJMETHOD(bus_child_present, root_child_present),
984263bc
MD
2519
2520 { 0, 0 }
2521};
2522
2523static driver_t root_driver = {
2524 "root",
2525 root_methods,
2526 1, /* no softc */
2527};
2528
2529device_t root_bus;
2530devclass_t root_devclass;
2531
2532static int
2533root_bus_module_handler(module_t mod, int what, void* arg)
2534{
0deb64bd
JS
2535 switch (what) {
2536 case MOD_LOAD:
0010e23a 2537 TAILQ_INIT(&bus_data_devices);
0deb64bd
JS
2538 root_bus = make_device(NULL, "root", 0);
2539 root_bus->desc = "System root bus";
2540 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
2541 root_bus->driver = &root_driver;
39b5d600 2542 root_bus->state = DS_ALIVE;
91a0c258 2543 root_devclass = devclass_find_internal("root", NULL, FALSE);
0deb64bd
JS
2544 return(0);
2545
2546 case MOD_SHUTDOWN:
2547 device_shutdown(root_bus);
2548 return(0);
2549 default:
2550 return(0);
2551 }
984263bc
MD
2552}
2553
2554static moduledata_t root_bus_mod = {
2555 "rootbus",
2556 root_bus_module_handler,
2557 0
2558};
2559DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
2560
2561void
2562root_bus_configure(void)
2563{
dbcd0c9b 2564 int warncount;
0deb64bd 2565 device_t dev;
984263bc 2566
0deb64bd 2567 PDEBUG(("."));
984263bc 2568
39b5d600
MD
2569 /*
2570 * handle device_identify based device attachments to the root_bus
2571 * (typically nexus).
2572 */
2573 bus_generic_probe(root_bus);
2574
2575 /*
2576 * Probe and attach the devices under root_bus.
2577 */
2578 TAILQ_FOREACH(dev, &root_bus->children, link) {
0deb64bd 2579 device_probe_and_attach(dev);
39b5d600 2580 }
dbcd0c9b
MD
2581
2582 /*
2583 * Wait for all asynchronous attaches to complete. If we don't
2584 * our legacy ISA bus scan could steal device unit numbers or
2585 * even I/O ports.
2586 */
2587 warncount = 10;
2588 if (numasyncthreads)
2589 kprintf("Waiting for async drivers to attach\n");
2590 while (numasyncthreads > 0) {
2591 if (tsleep(&numasyncthreads, 0, "rootbus", hz) == EWOULDBLOCK)
2592 --warncount;
2593 if (warncount == 0) {
2594 kprintf("Warning: Still waiting for %d "
2595 "drivers to attach\n", numasyncthreads);
2596 } else if (warncount == -30) {
2597 kprintf("Giving up on %d drivers\n", numasyncthreads);
2598 break;
2599 }
2600 }
39b5d600 2601 root_bus->state = DS_ATTACHED;
984263bc
MD
2602}
2603
2604int
2605driver_module_handler(module_t mod, int what, void *arg)
2606{
91a0c258 2607 int error;
984263bc
MD
2608 struct driver_module_data *dmd;
2609 devclass_t bus_devclass;
91a0c258
JS
2610 kobj_class_t driver;
2611 const char *parentname;
984263bc
MD
2612
2613 dmd = (struct driver_module_data *)arg;
91a0c258 2614 bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
984263bc
MD
2615 error = 0;
2616
2617 switch (what) {
2618 case MOD_LOAD:
2619 if (dmd->dmd_chainevh)
2620 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2621
91a0c258
JS
2622 driver = dmd->dmd_driver;
2623 PDEBUG(("Loading module: driver %s on bus %s",
2624 DRIVERNAME(driver), dmd->dmd_busname));
984263bc
MD
2625
2626 /*
91a0c258
JS
2627 * If the driver has any base classes, make the
2628 * devclass inherit from the devclass of the driver's
2629 * first base class. This will allow the system to
2630 * search for drivers in both devclasses for children
2631 * of a device using this driver.
984263bc 2632 */
91a0c258
JS
2633 if (driver->baseclasses)
2634 parentname = driver->baseclasses[0]->name;
2635 else
2636 parentname = NULL;
0b9823be 2637 *dmd->dmd_devclass = devclass_find_internal(driver->name,
91a0c258 2638 parentname, TRUE);
0b9823be
SS
2639
2640 error = devclass_add_driver(bus_devclass, driver);
2641 if (error)
2642 break;
984263bc
MD
2643 break;
2644
2645 case MOD_UNLOAD:
91a0c258
JS
2646 PDEBUG(("Unloading module: driver %s from bus %s",
2647 DRIVERNAME(dmd->dmd_driver), dmd->dmd_busname));
2648 error = devclass_delete_driver(bus_devclass, dmd->dmd_driver);
984263bc
MD
2649
2650 if (!error && dmd->dmd_chainevh)
2651 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2652 break;
2653 }
2654
2655 return (error);
2656}
2657
2658#ifdef BUS_DEBUG
2659
0deb64bd
JS
2660/*
2661 * The _short versions avoid iteration by not calling anything that prints
984263bc
MD
2662 * more than oneliners. I love oneliners.
2663 */
2664
984263bc
MD
2665static void
2666print_device_short(device_t dev, int indent)
2667{
2668 if (!dev)
2669 return;
2670
2671 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n",
0deb64bd
JS
2672 dev->unit, dev->desc,
2673 (dev->parent? "":"no "),
2674 (TAILQ_EMPTY(&dev->children)? "no ":""),
2675 (dev->flags&DF_ENABLED? "enabled,":"disabled,"),
2676 (dev->flags&DF_FIXEDCLASS? "fixed,":""),
2677 (dev->flags&DF_WILDCARD? "wildcard,":""),
2678 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
2679 (dev->ivars? "":"no "),
2680 (dev->softc? "":"no "),
2681 dev->busy));
984263bc
MD
2682}
2683
2684static void
2685print_device(device_t dev, int indent)
2686{
2687 if (!dev)
2688 return;
2689
2690 print_device_short(dev, indent);
2691
2692 indentprintf(("Parent:\n"));
2693 print_device_short(dev->parent, indent+1);
984263bc
MD
2694 indentprintf(("Driver:\n"));
2695 print_driver_short(dev->driver, indent+1);
2696 indentprintf(("Devclass:\n"));
2697 print_devclass_short(dev->devclass, indent+1);
2698}
2699
0deb64bd
JS
2700/*
2701 * Print the device and all its children (indented).
2702 */
984263bc
MD
2703void
2704print_device_tree_short(device_t dev, int indent)
984263bc
MD
2705{
2706 device_t child;
2707
2708 if (!dev)
2709 return;
2710
2711 print_device_short(dev, indent);
2712
0deb64bd 2713 TAILQ_FOREACH(child, &dev->children, link)
984263bc
MD
2714 print_device_tree_short(child, indent+1);
2715}
2716
0deb64bd
JS
2717/*
2718 * Print the device and all its children (indented).
2719 */
984263bc
MD
2720void
2721print_device_tree(device_t dev, int indent)
984263bc
MD
2722{
2723 device_t child;
2724
2725 if (!dev)
2726 return;
2727
2728 print_device(dev, indent);
2729
0deb64bd 2730 TAILQ_FOREACH(child, &dev->children, link)
984263bc
MD
2731 print_device_tree(child, indent+1);
2732}
2733
2734static void
2735print_driver_short(driver_t *driver, int indent)
2736{
2737 if (!driver)
2738 return;
2739
2740 indentprintf(("driver %s: softc size = %d\n",
0deb64bd 2741 driver->name, driver->size));
984263bc
MD
2742}
2743
2744static void
2745print_driver(driver_t *driver, int indent)
2746{
2747 if (!driver)
2748 return;
2749
2750 print_driver_short(driver, indent);
984263bc
MD
2751}
2752
2753
2754static void
2755print_driver_list(driver_list_t drivers, int indent)
2756{
2757 driverlink_t driver;
2758
0deb64bd 2759 TAILQ_FOREACH(driver, &drivers, link)
984263bc
MD
2760 print_driver(driver->driver, indent);
2761}
2762
2763static void
2764print_devclass_short(devclass_t dc, int indent)
2765{
0deb64bd 2766 if (!dc)
984263bc
MD
2767 return;
2768
0deb64bd 2769 indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit));
984263bc
MD
2770}
2771
2772static void
2773print_devclass(devclass_t dc, int indent)
2774{
2775 int i;
2776
0deb64bd 2777 if (!dc)
984263bc
MD
2778 return;
2779
2780 print_devclass_short(dc, indent);
2781 indentprintf(("Drivers:\n"));
2782 print_driver_list(dc->drivers, indent+1);
2783
2784 indentprintf(("Devices:\n"));
2785 for (i = 0; i < dc->maxunit; i++)
2786 if (dc->devices[i])
2787 print_device(dc->devices[i], indent+1);
2788}
2789
2790void
2791print_devclass_list_short(void)
2792{
2793 devclass_t dc;
2794
6ea70f76 2795 kprintf("Short listing of devclasses, drivers & devices:\n");
8d0e5ff2 2796 TAILQ_FOREACH(dc, &devclasses, link) {
984263bc 2797 print_devclass_short(dc, 0);
8d0e5ff2 2798 }
984263bc
MD
2799}
2800
2801void
2802print_devclass_list(void)
2803{
2804 devclass_t dc;
2805
6ea70f76 2806 kprintf("Full listing of devclasses, drivers & devices:\n");
8d0e5ff2 2807 TAILQ_FOREACH(dc, &devclasses, link) {
984263bc 2808 print_devclass(dc, 0);
8d0e5ff2 2809 }
984263bc
MD
2810}
2811
2812#endif
e126caf1
MD
2813
2814/*
2815 * Check to see if a device is disabled via a disabled hint.
2816 */
2817int
2818resource_disabled(const char *name, int unit)
2819{
2820 int error, value;
2821
2822 error = resource_int_value(name, unit, "disabled", &value);
2823 if (error)
0deb64bd
JS
2824 return(0);
2825 return(value);
e126caf1 2826}
0010e23a
HT
2827
2828/*
2829 * User-space access to the device tree.
2830 *
2831 * We implement a small set of nodes:
2832 *
2833 * hw.bus Single integer read method to obtain the
2834 * current generation count.
2835 * hw.bus.devices Reads the entire device tree in flat space.
2836 * hw.bus.rman Resource manager interface
2837 *
2838 * We might like to add the ability to scan devclasses and/or drivers to
2839 * determine what else is currently loaded/available.
2840 */
2841
2842static int
2843sysctl_bus(SYSCTL_HANDLER_ARGS)
2844{
2845 struct u_businfo ubus;
2846
2847 ubus.ub_version = BUS_USER_VERSION;
2848 ubus.ub_generation = bus_data_generation;
2849
2850 return (SYSCTL_OUT(req, &ubus, sizeof(ubus)));
2851}
2852SYSCTL_NODE(_hw_bus, OID_AUTO, info, CTLFLAG_RW, sysctl_bus,
2853 "bus-related data");
2854
2855static int
2856sysctl_devices(SYSCTL_HANDLER_ARGS)
2857{
2858 int *name = (int *)arg1;
2859 u_int namelen = arg2;
2860 int index;
2861 struct device *dev;
2862 struct u_device udev; /* XXX this is a bit big */
2863 int error;
2864
2865 if (namelen != 2)
2866 return (EINVAL);
2867
2868 if (bus_data_generation_check(name[0]))
2869 return (EINVAL);
2870
2871 index = name[1];
2872
2873 /*
2874 * Scan the list of devices, looking for the requested index.
2875 */
2876 TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
2877 if (index-- == 0)
2878 break;
2879 }
2880 if (dev == NULL)
2881 return (ENOENT);
2882
2883 /*
2884 * Populate the return array.
2885 */
2886 bzero(&udev, sizeof(udev));
2887 udev.dv_handle = (uintptr_t)dev;
2888 udev.dv_parent = (uintptr_t)dev->parent;
2889 if (dev->nameunit != NULL)
2890 strlcpy(udev.dv_name, dev->nameunit, sizeof(udev.dv_name));
2891 if (dev->desc != NULL)
2892 strlcpy(udev.dv_desc, dev->desc, sizeof(udev.dv_desc));
2893 if (dev->driver != NULL && dev->driver->name != NULL)
2894 strlcpy(udev.dv_drivername, dev->driver->name,
2895 sizeof(udev.dv_drivername));
2896 bus_child_pnpinfo_str(dev, udev.dv_pnpinfo, sizeof(udev.dv_pnpinfo));
2897 bus_child_location_str(dev, udev.dv_location, sizeof(udev.dv_location));
2898 udev.dv_devflags = dev->devflags;
2899 udev.dv_flags = dev->flags;
2900 udev.dv_state = dev->state;
2901 error = SYSCTL_OUT(req, &udev, sizeof(udev));
2902 return (error);
2903}
2904
2905SYSCTL_NODE(_hw_bus, OID_AUTO, devices, CTLFLAG_RD, sysctl_devices,
2906 "system device tree");
2907
2908int
2909bus_data_generation_check(int generation)
2910{
2911 if (generation != bus_data_generation)
2912 return (1);
2913
2914 /* XXX generate optimised lists here? */
2915 return (0);
2916}
2917
2918void
2919bus_data_generation_update(void)
2920{
2921 bus_data_generation++;
2922}