Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Feb 2004 18:20:24 +0100
From:      des@des.no (Dag-Erling =?iso-8859-1?q?Sm=F8rgrav?=)
To:        arch@freebsd.org
Subject:   'sysctl dev', round two
Message-ID:  <xzp8yiophgn.fsf@dwp.des.no>

next in thread | raw e-mail | index | archive | help
--=-=-=
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

New patch attached; it should be considerably cleaner than the
previous one.  A couple of surprises, though:

 - unattached devices still aren't picked up, which they should if
   they have a device_t.  For instance, I don't see a sysctl entry for
   the following:

none0@pci0:31:3:        class=3D0x0c0500 card=3D0x24c21458 chip=3D0x24c3808=
6 rev=3D0x02 hdr=3D0x00
    vendor   =3D 'Intel Corporation'
    device   =3D '82801DB/DBM (ICH4/M) SMBus Controller'
    class    =3D serial bus
    subclass =3D SMBus

 - USB devices don't seem to report their location or pnpinfo.

DES
--=20
Dag-Erling Sm=F8rgrav - des@des.no


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=dev.diff

Index: sys/kern/subr_bus.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_bus.c,v
retrieving revision 1.140
diff -u -r1.140 subr_bus.c
--- sys/kern/subr_bus.c	24 Feb 2004 19:31:30 -0000	1.140
+++ sys/kern/subr_bus.c	27 Feb 2004 16:53:57 -0000
@@ -56,6 +56,7 @@
 #include <vm/uma.h>
 
 SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
+SYSCTL_NODE(, OID_AUTO, dev, CTLFLAG_RW, NULL, NULL);
 
 /*
  * Used to attach drivers to devclasses.
@@ -123,6 +124,9 @@
 	u_char	pad;
 	void	*ivars;
 	void	*softc;
+
+	struct sysctl_ctx_list sysctl_ctx;
+	struct sysctl_oid *sysctl_tree;
 };
 
 struct device_op_desc {
@@ -185,6 +189,106 @@
 #endif
 
 /*
+ * dev sysctl tree
+ */
+
+enum {
+	DEVICE_SYSCTL_CLASS,
+	DEVICE_SYSCTL_DESC,
+	DEVICE_SYSCTL_DRIVER,
+	DEVICE_SYSCTL_LOCATION,
+	DEVICE_SYSCTL_PNPINFO,
+};
+
+static int
+device_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+	device_t dev = (device_t)arg1;
+	const char *value;
+	char *buf;
+	int error;
+
+	buf = NULL;
+	switch (arg2) {
+	case DEVICE_SYSCTL_CLASS:
+		value = dev->devclass ? dev->devclass->name : NULL;
+		break;
+	case DEVICE_SYSCTL_DESC:
+		value = dev->desc;
+		break;
+	case DEVICE_SYSCTL_DRIVER:
+		value = dev->driver ? dev->driver->name : NULL;
+		break;
+	case DEVICE_SYSCTL_LOCATION:
+		value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
+		bus_child_location_str(dev, buf, 1024);
+		break;
+	case DEVICE_SYSCTL_PNPINFO:
+		value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
+		bus_child_pnpinfo_str(dev, buf, 1024);
+		break;
+	default:
+		return (EINVAL);
+	}
+	if (value == NULL)
+		value = "?";
+	error = SYSCTL_OUT(req, value, strlen(value));
+	if (buf != NULL)
+		free(buf, M_BUS);
+	return (error);
+}
+
+static void
+device_sysctl_init(device_t dev)
+{
+	struct sysctl_oid_list *parent_node;
+
+	if (dev->parent) {
+		if (dev->parent->sysctl_tree == NULL)
+			device_sysctl_init(dev->parent);
+		parent_node = SYSCTL_CHILDREN(dev->parent->sysctl_tree);
+	} else {
+		parent_node = SYSCTL_STATIC_CHILDREN(_dev);
+	}
+	if (dev->sysctl_tree != NULL) {
+		sysctl_move_oid(dev->sysctl_tree, parent_node);
+		return;
+	}
+	sysctl_ctx_init(&dev->sysctl_ctx);
+	dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx, parent_node,
+	    OID_AUTO, dev->nameunit, CTLFLAG_RD, 0, "");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%class", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_CLASS, device_sysctl_handler, "A",
+	    "device class name");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%desc", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_DESC, device_sysctl_handler, "A",
+	    "device description");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%driver", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_DRIVER, device_sysctl_handler, "A",
+	    "device driver name");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%location", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_LOCATION, device_sysctl_handler, "A",
+	    "device location relative to parent");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%pnpinfo", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_PNPINFO, device_sysctl_handler, "A",
+	    "device identification");
+}
+
+static void
+device_sysctl_fini(device_t dev)
+{
+	if (dev->sysctl_tree == NULL)
+		return;
+	sysctl_ctx_free(&dev->sysctl_ctx);
+	dev->sysctl_tree = NULL;
+}
+
+/*
  * /dev/devctl implementation
  */
 
@@ -886,6 +990,7 @@
 	dc->devices[dev->unit] = dev;
 	dev->devclass = dc;
 	snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
+	device_sysctl_init(dev);
 
 	return (0);
 }
@@ -900,6 +1005,7 @@
 
 	if (dev->devclass != dc || dc->devices[dev->unit] != dev)
 		panic("devclass_delete_device: inconsistent device class");
+	device_sysctl_fini(dev);
 	dc->devices[dev->unit] = NULL;
 	if (dev->flags & DF_WILDCARD)
 		dev->unit = -1;
@@ -956,9 +1062,7 @@
 	}
 	dev->ivars = NULL;
 	dev->softc = NULL;
-
 	dev->state = DS_NOTPRESENT;
-
 	TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
 	bus_data_generation_update();
 
@@ -1043,6 +1147,7 @@
 	TAILQ_REMOVE(&dev->children, child, link);
 	TAILQ_REMOVE(&bus_data_devices, child, devlink);
 	device_set_desc(child, NULL);
+	device_sysctl_fini(dev);
 	kobj_delete((kobj_t) child, M_BUS);
 
 	bus_data_generation_update();
@@ -1254,6 +1359,18 @@
 device_get_flags(device_t dev)
 {
 	return (dev->devflags);
+}
+
+struct sysctl_ctx_list *
+device_get_sysctl_ctx(device_t dev)
+{
+	return (&dev->sysctl_ctx);
+}
+
+struct sysctl_oid *
+device_get_sysctl_tree(device_t dev)
+{
+	return (dev->sysctl_tree);
 }
 
 int
Index: sys/sys/bus.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/bus.h,v
retrieving revision 1.57
diff -u -r1.57 bus.h
--- sys/sys/bus.h	24 Oct 2003 22:41:54 -0000	1.57
+++ sys/sys/bus.h	27 Feb 2004 15:44:30 -0000
@@ -335,6 +335,8 @@
 void	*device_get_softc(device_t dev);
 device_state_t	device_get_state(device_t dev);
 int	device_get_unit(device_t dev);
+struct sysctl_ctx_list *device_get_sysctl_ctx(device_t dev);
+struct sysctl_oid *device_get_sysctl_tree(device_t dev);
 int	device_is_alive(device_t dev);	/* did probe succeed? */
 int	device_is_attached(device_t dev);	/* did attach succeed? */
 int	device_is_enabled(device_t dev);

--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?xzp8yiophgn.fsf>