summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/subr_bus.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-09 14:19:03 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-01-10 09:53:34 +0100
commit75b706fde4cbf82bcd41a1cec319778aa0f8eb2d (patch)
treeea39a351a1f6337b5a5dd6036314693adef5ffe6 /freebsd/sys/kern/subr_bus.c
parentVMSTAT(8): Port to RTEMS (diff)
downloadrtems-libbsd-75b706fde4cbf82bcd41a1cec319778aa0f8eb2d.tar.bz2
Update to FreeBSD head 2016-12-10
Git mirror commit 80c55f08a05ab3b26a73b226ccb56adc3122a55c.
Diffstat (limited to 'freebsd/sys/kern/subr_bus.c')
-rw-r--r--freebsd/sys/kern/subr_bus.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 3eb7d7e9..1175456c 100644
--- a/freebsd/sys/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
@@ -30,6 +30,7 @@
__FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_bus.h>
+#include <rtems/bsd/local/opt_ddb.h>
#include <rtems/bsd/sys/param.h>
#include <sys/conf.h>
@@ -67,6 +68,8 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <vm/vm.h>
+#include <ddb/ddb.h>
+
SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
SYSCTL_ROOT_NODE(OID_AUTO, dev, CTLFLAG_RW, NULL, NULL);
@@ -147,6 +150,9 @@ static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
static void devctl2_init(void);
#endif /* __rtems__ */
+#define DRIVERNAME(d) ((d)? d->name : "no driver")
+#define DEVCLANAME(d) ((d)? d->name : "no devclass")
+
#ifdef BUS_DEBUG
static int bus_debug = 1;
@@ -155,8 +161,6 @@ SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0,
#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
#define DEVICENAME(d) ((d)? device_get_name(d): "no device")
-#define DRIVERNAME(d) ((d)? d->name : "no driver")
-#define DEVCLANAME(d) ((d)? d->name : "no devclass")
/**
* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
@@ -180,8 +184,6 @@ void print_devclass_list(void);
/* Make the compiler ignore the function calls */
#define PDEBUG(a) /* nop */
#define DEVICENAME(d) /* nop */
-#define DRIVERNAME(d) /* nop */
-#define DEVCLANAME(d) /* nop */
#define print_device_short(d,i) /* nop */
#define print_device(d,i) /* nop */
@@ -1981,15 +1983,17 @@ device_delete_child(device_t dev, device_t child)
PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
- /* remove children first */
+ /* detach parent before deleting children, if any */
+ if ((error = device_detach(child)) != 0)
+ return (error);
+
+ /* remove children second */
while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) {
error = device_delete_child(child, grandchild);
if (error)
return (error);
}
- if ((error = device_detach(child)) != 0)
- return (error);
if (child->devclass)
devclass_delete_device(child->devclass, child);
if (child->parent)
@@ -2180,6 +2184,12 @@ device_probe_child(device_t dev, device_t child)
}
/*
+ * Reset DF_QUIET in case this driver doesn't
+ * end up as the best driver.
+ */
+ device_verbose(child);
+
+ /*
* Probes that return BUS_PROBE_NOWILDCARD or lower
* only match on devices whose driver was explicitly
* specified.
@@ -3008,6 +3018,7 @@ device_detach(device_t dev)
if (!(dev->flags & DF_FIXEDCLASS))
devclass_delete_device(dev->devclass, dev);
+ device_verbose(dev);
dev->state = DS_NOTPRESENT;
(void)device_set_driver(dev, NULL);
device_sysctl_fini(dev);
@@ -5396,6 +5407,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
case DEV_SUSPEND:
case DEV_RESUME:
case DEV_SET_DRIVER:
+ case DEV_CLEAR_DRIVER:
case DEV_RESCAN:
case DEV_DELETE:
error = priv_check(td, PRIV_DRIVER);
@@ -5561,6 +5573,25 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = device_probe_and_attach(dev);
break;
}
+ case DEV_CLEAR_DRIVER:
+ if (!(dev->flags & DF_FIXEDCLASS)) {
+ error = 0;
+ break;
+ }
+ if (device_is_attached(dev)) {
+ if (req->dr_flags & DEVF_CLEAR_DRIVER_DETACH)
+ error = device_detach(dev);
+ else
+ error = EBUSY;
+ if (error)
+ break;
+ }
+
+ dev->flags &= ~DF_FIXEDCLASS;
+ dev->flags |= DF_WILDCARD;
+ devclass_delete_device(dev->devclass, dev);
+ error = device_probe_and_attach(dev);
+ break;
case DEV_RESCAN:
if (!device_is_attached(dev)) {
error = ENXIO;
@@ -5604,4 +5635,33 @@ devctl2_init(void)
make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
UID_ROOT, GID_WHEEL, 0600, "devctl2");
}
+
+#ifdef DDB
+DB_SHOW_COMMAND(device, db_show_device)
+{
+ device_t dev;
+
+ if (!have_addr)
+ return;
+
+ dev = (device_t)addr;
+
+ db_printf("name: %s\n", device_get_nameunit(dev));
+ db_printf(" driver: %s\n", DRIVERNAME(dev->driver));
+ db_printf(" class: %s\n", DEVCLANAME(dev->devclass));
+ db_printf(" addr: %p\n", dev);
+ db_printf(" parent: %p\n", dev->parent);
+ db_printf(" softc: %p\n", dev->softc);
+ db_printf(" ivars: %p\n", dev->ivars);
+}
+
+DB_SHOW_ALL_COMMAND(devices, db_show_all_devices)
+{
+ device_t dev;
+
+ TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+ db_show_device((db_expr_t)dev, true, count, modif);
+ }
+}
+#endif
#endif /* __rtems__ */