Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Dec 2007 18:15:27 GMT
From:      Maxim Zhuravlev <thioretic@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 130355 for review
Message-ID:  <200712061815.lB6IFR7D014250@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130355

Change 130355 by thioretic@thioretic on 2007/12/06 18:14:38

	Drivers should be able to specify whether newbus to enqueue incoming io requests
		for possible additional processing (like prioritization) for devices 
		controlled by the driver.

Affected files ...

.. //depot/projects/soc2007/thioretic_gidl2/kern/subr_bus.c#9 edit
.. //depot/projects/soc2007/thioretic_gidl2/kern/subr_busio.c#6 edit

Differences ...

==== //depot/projects/soc2007/thioretic_gidl2/kern/subr_bus.c#9 (text+ko) ====

@@ -1,5250 +1,5251 @@
-/*-
- * Copyright (c) 1997,1998,2003 Doug Rabson
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/subr_bus.c,v 1.184.2.5 2006/12/28 22:13:26 jhb Exp $");
-
-#include "opt_bus.h"
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/filio.h>
-#include <sys/lock.h>
-#include <sys/kernel.h>
-#include <sys/kobj.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/poll.h>
-#include <sys/proc.h>
-#include <sys/condvar.h>
-#include <sys/queue.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <sys/selinfo.h>
-#include <sys/signalvar.h>
-#include <sys/sysctl.h>
-#include <sys/systm.h>
-#include <sys/uio.h>
-#include <sys/bus.h>
-
-#include <machine/stdarg.h>
-
-#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.
- */
-typedef struct driverlink *driverlink_t;
-struct driverlink {
-	kobj_class_t	driver;
-	TAILQ_ENTRY(driverlink) link;	/* list of drivers in devclass */
-};
-
-typedef struct driverinfo* driverinfo_t;
-struct driverinfo {
-	kobj_class_t	driver;	/**< kobj class, implementing driver 
-							& bus interface methods (from outer space)*/
-	kobj_class_t	drvops;	/**< kobj class, implementing driverops 
-							interface methods (from outer space)*/
-	kobj_t	topology_ops;	/**< object of class implemented by driver
-							(deeply internal:))*/
-	kobj_t	functional_ops;	/**< object of class implemented by driverops
-							(deeply internal:))*/
-	uint32_t flags;	/**< driver-specific flags (from outer space)*/
-	TAILQ_ENTRY(driverinfo) link;
-};
-
-typedef struct driverinfolink* driverinfolink_t;
-struct driverinfolink {
-	driverinfo_t pdriver;
-	void *ivars;
-	void *softc;
-#define	DF_EXTERNALSOFTC 1		/* softc not allocated by us */
-	int flags;
-	device_state_t state;
-	TAILQ_ENTRY(driverinfolink) link;
-};
-
-/*
- * Forward declarations
- */
-typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
-typedef TAILQ_HEAD(devclasslink_list, devclasslink) devclasslink_list_t;
-
-typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
-
-typedef TAILQ_HEAD(device_list, device) device_list_t;
-typedef TAILQ_HEAD(devicelink_list, devicelink) devicelink_list_t;
-
-typedef TAILQ_HEAD(driverinfo_list, driverinfo) driverinfo_list_t;
-typedef TAILQ_HEAD(driverinfolink_list, driverinfolink) driverinfolink_list_t;
-
-typedef struct devclasslink* devclasslink_t;
-struct devclasslink{
-	devclass_t devclass_ptr;
-	TAILQ_ENTRY(devclasslink) link;
-};
-
-struct devclass {
-	TAILQ_ENTRY(devclass) link;
-	devclass_t	parent;		/* parent in devclass hierarchy */
-	devclasslink_list_t	filters;	/* these are used to hold information, 
-									used for non-DRL_LOWEST drivers' classes */
-	driver_list_t	drivers;     /* bus devclasses store drivers for bus */
-	char		*name;
-	device_t	*devices;	/* array of devices indexed by unit */
-	int		maxunit;	/* size of devices array */
-
-	struct sysctl_ctx_list sysctl_ctx;
+/*-
+ * Copyright (c) 1997,1998,2003 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/kern/subr_bus.c,v 1.184.2.5 2006/12/28 22:13:26 jhb Exp $");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/filio.h>
+#include <sys/lock.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/condvar.h>
+#include <sys/queue.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/selinfo.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/bus.h>
+
+#include <machine/stdarg.h>
+
+#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.
+ */
+typedef struct driverlink *driverlink_t;
+struct driverlink {
+	kobj_class_t	driver;
+	TAILQ_ENTRY(driverlink) link;	/* list of drivers in devclass */
+};
+
+typedef struct driverinfo* driverinfo_t;
+struct driverinfo {
+	kobj_class_t	driver;	/**< kobj class, implementing driver 
+							& bus interface methods (from outer space)*/
+	kobj_class_t	drvops;	/**< kobj class, implementing driverops 
+							interface methods (from outer space)*/
+	kobj_t	topology_ops;	/**< object of class implemented by driver
+							(deeply internal:))*/
+	kobj_t	functional_ops;	/**< object of class implemented by driverops
+							(deeply internal:))*/
+	uint32_t flags;	/**< driver-specific flags (from outer space)*/
+	TAILQ_ENTRY(driverinfo) link;
+};
+
+typedef struct driverinfolink* driverinfolink_t;
+struct driverinfolink {
+	driverinfo_t pdriver;
+	void *ivars;
+	void *softc;
+#define	DF_EXTERNALSOFTC 1		/* softc not allocated by us */
+	int flags;
+	device_state_t state;
+	TAILQ_ENTRY(driverinfolink) link;
+};
+
+/*
+ * Forward declarations
+ */
+typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
+typedef TAILQ_HEAD(devclasslink_list, devclasslink) devclasslink_list_t;
+
+typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
+
+typedef TAILQ_HEAD(device_list, device) device_list_t;
+typedef TAILQ_HEAD(devicelink_list, devicelink) devicelink_list_t;
+
+typedef TAILQ_HEAD(driverinfo_list, driverinfo) driverinfo_list_t;
+typedef TAILQ_HEAD(driverinfolink_list, driverinfolink) driverinfolink_list_t;
+
+typedef struct devclasslink* devclasslink_t;
+struct devclasslink{
+	devclass_t devclass_ptr;
+	TAILQ_ENTRY(devclasslink) link;
+};
+
+struct devclass {
+	TAILQ_ENTRY(devclass) link;
+	devclass_t	parent;		/* parent in devclass hierarchy */
+	devclasslink_list_t	filters;	/* these are used to hold information, 
+									used for non-DRL_LOWEST drivers' classes */
+	driver_list_t	drivers;     /* bus devclasses store drivers for bus */
+	char		*name;
+	device_t	*devices;	/* array of devices indexed by unit */
+	int		maxunit;	/* size of devices array */
+
+	struct sysctl_ctx_list sysctl_ctx;
 	struct sysctl_oid *sysctl_tree;
 
 #define DC_ATTACHCHILDDEV (1<<0)
-	uint32_t flags;
-};
-
-/**
- * @brief Implementation of device.
- */
-struct device {
-	/*
-	 * A device is a kernel object. The first field must be the
-	 * current ops table for the object.
-	 */
-	KOBJ_FIELDS;	/**< !TRICK: will init it to drv_compat_ctrl_driver
-						which gonna work around stacked drivers*/
-
-	/*
-	 * Device hierarchy.
-	 */
-	TAILQ_ENTRY(device)	link;	/**< list of devices in parent */
-	TAILQ_ENTRY(device)	devlink; /**< global device list membership */
-	devicelink_list_t	parents;
-	devicelink_list_t	children;	/**< list of child devices */
-
-	/*
-	 * Details of this device.
-	 */
-	driverinfolink_t driver;	/**< current driver to be probed/attached/...*/
-	int driver_level;
-	driverinfolink_list_t drivers[DRL_LEVELS];
-	int driverinfo_flags;
-	devclass_t	devclass;	/**< current device class */
-	int		unit;		/**< current unit number */
-	char*		nameunit;	/**< name+unit e.g. foodev0 */
-	char*		desc;		/**< driver specific description */
-	int		busy;		/**< count of calls to device_busy() */
-	device_state_t	state;		/**< current device state  */
-	u_int32_t	devflags;	/**< api level flags for device_get_flags() */
-	u_short		flags;		/**< internal device flags  */
-#define	DF_ENABLED	1		/* device should be probed/attached */
-#define	DF_FIXEDCLASS	2		/* devclass specified at create time */
-#define	DF_WILDCARD	4		/* unit was originally wildcard */
-#define	DF_DESCMALLOCED	8		/* description was malloced */
-#define	DF_QUIET	16		/* don't print verbose attach message */
-#define	DF_DONENOMATCH	32		/* don't execute DEVICE_NOMATCH again */
-#define	DF_REBID	128		/* Can rebid after attach */
-#define DF_PERSISTENT	256		/* Should not delete when refs == 0*/
-	u_char	order;			/**< order from device_add_child_ordered() */
-	u_char	pad;
-	//void	*ivars;			/**< instance variables  */
-	//void	*softc;			/**< current driver's variables  */
-	u_long	refs;
-	int raw;
-
-	struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables  */
-	struct sysctl_oid *sysctl_tree;	/**< state for sysctl variables */
-};
-
-typedef struct devicelink* devicelink_t;
-struct devicelink {
-	device_t device_ptr;
-#define DLF_ANCHOR	1
-	int flags;
-	TAILQ(devicelink) link;
-};
-
-static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
-static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
-
-#ifdef BUS_DEBUG
-
-static int bus_debug = 1;
-TUNABLE_INT("bus.debug", &bus_debug);
-SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RW, &bus_debug, 0,
-    "Debug bus code");
-
-#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
- * prevent syslog from deleting initial spaces
- */
-#define indentprintf(p)	do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while (0)
-
-static void print_device_short(device_t dev, int indent);
-static void print_device(device_t dev, int indent);
-void print_device_tree_short(device_t dev, int indent);
-void print_device_tree(device_t dev, int indent);
-static void print_driver_short(driver_t *driver, int indent);
-static void print_driver(driver_t *driver, int indent);
-static void print_driver_list(driver_list_t drivers, int indent);
-static void print_devclass_short(devclass_t dc, int indent);
-static void print_devclass(devclass_t dc, int indent);
-void print_devclass_list_short(void);
-void print_devclass_list(void);
-
-#else
-/* 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 */
-#define print_device_tree_short(d,i)	/* nop */
-#define print_device_tree(d,i)		/* nop */
-#define print_driver_short(d,i)		/* nop */
-#define print_driver(d,i)		/* nop */
-#define print_driver_list(d,i)		/* nop */
-#define print_devclass_short(d,i)	/* nop */
-#define print_devclass(d,i)		/* nop */
-#define print_devclass_list_short()	/* nop */
-#define print_devclass_list()		/* nop */
-#endif
-
-/*
- * dev sysctl tree
- */
-
-enum {
-	DEVCLASS_SYSCTL_PARENT,
-};
-
-static int
-devclass_sysctl_handler(SYSCTL_HANDLER_ARGS)
-{
-	devclass_t dc = (devclass_t)arg1;
-	const char *value;
-
-	switch (arg2) {
-	case DEVCLASS_SYSCTL_PARENT:
-		value = dc->parent ? dc->parent->name : "";
-		break;
-	default:
-		return (EINVAL);
-	}
-	return (SYSCTL_OUT(req, value, strlen(value)));
-}
-
-static void
-devclass_sysctl_init(devclass_t dc)
-{
-
-	if (dc->sysctl_tree != NULL)
-		return;
-	sysctl_ctx_init(&dc->sysctl_ctx);
-	dc->sysctl_tree = SYSCTL_ADD_NODE(&dc->sysctl_ctx,
-	    SYSCTL_STATIC_CHILDREN(_dev), OID_AUTO, dc->name,
-	    CTLFLAG_RD, 0, "");
-	SYSCTL_ADD_PROC(&dc->sysctl_ctx, SYSCTL_CHILDREN(dc->sysctl_tree),
-	    OID_AUTO, "%parent", CTLFLAG_RD,
-	    dc, DEVCLASS_SYSCTL_PARENT, devclass_sysctl_handler, "A",
-	    "parent class");
-}
-
-enum {
-	DEVICE_SYSCTL_DESC,
-	DEVICE_SYSCTL_DRIVER,
-	DEVICE_SYSCTL_LOCATION,
-	DEVICE_SYSCTL_PNPINFO,
-	DEVICE_SYSCTL_PARENT,
-};
-
-static int
-device_sysctl_handler(SYSCTL_HANDLER_ARGS)
-{
-	device_t dev = (device_t)arg1;
-	const char *value;
-	char *buf;
-	int error;
-	int level;
-	driverinfolink_t dil;
-
-	buf = NULL;
-	switch (arg2) {
-	case DEVICE_SYSCTL_DESC:
-		value = dev->desc ? dev->desc : "";
-		break;
-	case DEVICE_SYSCTL_DRIVER:
-		value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
-		buf[0]='\0';
-		for (level=DRL_LOWEST; level<=DRL_TOPMOST; level++){
-			switch(level){
-				case DRL_LOWEST:	tmpbuf="LOWEST:"; break;
-				case DRL_LOWER:	tmpbuf="LOWER:"; break;
-				case DRL_MIDDLE:	tmpbuf="MIDDLE:"; break;
-				case DRL_UPPER:	tmpbuf="UPPER:"; break;
-				case DRL_TOPMOST:	tmpbuf="TOPMOST:"; break;
-			}
-			if (strlen(tmpbuf)+strlen(buf)>1023) break;
-			TAILQ_FOREACH(dil, &((dev->drivers)[level]), link){
-				if(strlen(dil->pdriver->driver->name)+strlen(buf)>1022)
-					break;
-				strcat(buf,dil->pdriver->driver->name);
-				strcat(buf,",");
-			}
-			buf[strlen(buf)]='\0';
-			strcat(buf,"\n");
-		}
-		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;
-	case DEVICE_SYSCTL_PARENT:
-		value = dev->parent ? dev->parent->nameunit : "";
-		break;
-	default:
-		return (EINVAL);
-	}
-	error = SYSCTL_OUT(req, value, strlen(value));
-	if (buf != NULL)
-		free(buf, M_BUS);
-	return (error);
-}
-
-static void
-device_sysctl_init(device_t dev)
-{
-	devclass_t dc = dev->devclass;
-
-	if (dev->sysctl_tree != NULL)
-		return;
-	devclass_sysctl_init(dc);
-	sysctl_ctx_init(&dev->sysctl_ctx);
-	dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx,
-	    SYSCTL_CHILDREN(dc->sysctl_tree), OID_AUTO,
-	    dev->nameunit + strlen(dc->name),
-	    CTLFLAG_RD, 0, "");
-	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 drivers names");
-	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");
-	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
-	    OID_AUTO, "%parent", CTLFLAG_RD,
-	    dev, DEVICE_SYSCTL_PARENT, device_sysctl_handler, "A",
-	    "parent device");
-}
-
-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
- */
-
-/*
- * This design allows only one reader for /dev/devctl.  This is not desirable
- * in the long run, but will get a lot of hair out of this implementation.
- * Maybe we should make this device a clonable device.
- *
- * Also note: we specifically do not attach a device to the device_t tree
- * to avoid potential chicken and egg problems.  One could argue that all
- * of this belongs to the root node.  One could also further argue that the
- * sysctl interface that we have not might more properly be an ioctl
- * interface, but at this stage of the game, I'm not inclined to rock that
- * boat.
- *
- * I'm also not sure that the SIGIO support is done correctly or not, as
- * I copied it from a driver that had SIGIO support that likely hasn't been
- * tested since 3.4 or 2.2.8!
- */
-
-static int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS);
-static int devctl_disable = 0;
-TUNABLE_INT("hw.bus.devctl_disable", &devctl_disable);
-SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
-    sysctl_devctl_disable, "I", "devctl disable");
-
-static d_open_t		devopen;
-static d_close_t	devclose;
-static d_read_t		devread;
-static d_ioctl_t	devioctl;
-static d_poll_t		devpoll;
-
-static struct cdevsw dev_cdevsw = {
-	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT,
-	.d_open =	devopen,
-	.d_close =	devclose,
-	.d_read =	devread,
-	.d_ioctl =	devioctl,
-	.d_poll =	devpoll,
-	.d_name =	"devctl",
-};
-
-struct dev_event_info
-{
-	char *dei_data;
-	TAILQ_ENTRY(dev_event_info) dei_link;
-};
-
-TAILQ_HEAD(devq, dev_event_info);
-
-static struct dev_softc
-{
-	int	inuse;
-	int	nonblock;
-	struct mtx mtx;
-	struct cv cv;
-	struct selinfo sel;
-	struct devq devq;
-	struct proc *async_proc;
-} devsoftc;
-
-static struct cdev *devctl_dev;
-
-static void
-devinit(void)
-{
-	devctl_dev = make_dev(&dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
-	    "devctl");
-	mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
-	cv_init(&devsoftc.cv, "dev cv");
-	TAILQ_INIT(&devsoftc.devq);
-}
-
-static int
-devopen(struct cdev *dev, int oflags, int devtype, d_thread_t *td)
-{
-	if (devsoftc.inuse)
-		return (EBUSY);
-	/* move to init */
-	devsoftc.inuse = 1;
-	devsoftc.nonblock = 0;
-	devsoftc.async_proc = NULL;
-	return (0);
-}
-
-static int
-devclose(struct cdev *dev, int fflag, int devtype, d_thread_t *td)
-{
-	devsoftc.inuse = 0;
-	mtx_lock(&devsoftc.mtx);
-	cv_broadcast(&devsoftc.cv);
-	mtx_unlock(&devsoftc.mtx);
-
-	return (0);
-}
-
-/*
- * The read channel for this device is used to report changes to
- * userland in realtime.  We are required to free the data as well as
- * the n1 object because we allocate them separately.  Also note that
- * we return one record at a time.  If you try to read this device a
- * character at a time, you will loose the rest of the data.  Listening
- * programs are expected to cope.
- */
-static int
-devread(struct cdev *dev, struct uio *uio, int ioflag)
-{
-	struct dev_event_info *n1;
-	int rv;
-
-	mtx_lock(&devsoftc.mtx);
-	while (TAILQ_EMPTY(&devsoftc.devq)) {
-		if (devsoftc.nonblock) {
-			mtx_unlock(&devsoftc.mtx);
-			return (EAGAIN);
-		}
-		rv = cv_wait_sig(&devsoftc.cv, &devsoftc.mtx);
-		if (rv) {
-			/*
-			 * Need to translate ERESTART to EINTR here? -- jake
-			 */
-			mtx_unlock(&devsoftc.mtx);
-			return (rv);
-		}
-	}
-	n1 = TAILQ_FIRST(&devsoftc.devq);
-	TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
-	mtx_unlock(&devsoftc.mtx);
-	rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
-	free(n1->dei_data, M_BUS);
-	free(n1, M_BUS);
-	return (rv);
-}
-
-static	int
-devioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td)
-{
-	switch (cmd) {
-
-	case FIONBIO:
-		if (*(int*)data)
-			devsoftc.nonblock = 1;
-		else
-			devsoftc.nonblock = 0;
-		return (0);
-	case FIOASYNC:
-		if (*(int*)data)
-			devsoftc.async_proc = td->td_proc;
-		else
-			devsoftc.async_proc = NULL;
-		return (0);
-
-		/* (un)Support for other fcntl() calls. */
-	case FIOCLEX:
-	case FIONCLEX:
-	case FIONREAD:
-	case FIOSETOWN:
-	case FIOGETOWN:
-	default:
-		break;
-	}
-	return (ENOTTY);
-}
-
-static	int
-devpoll(struct cdev *dev, int events, d_thread_t *td)
-{
-	int	revents = 0;
-
-	mtx_lock(&devsoftc.mtx);
-	if (events & (POLLIN | POLLRDNORM)) {
-		if (!TAILQ_EMPTY(&devsoftc.devq))
-			revents = events & (POLLIN | POLLRDNORM);
-		else
-			selrecord(td, &devsoftc.sel);
-	}
-	mtx_unlock(&devsoftc.mtx);
-
-	return (revents);
-}
-
-/**
- * @brief Queue data to be read from the devctl device
- *
- * Generic interface to queue data to the devctl device.  It is
- * assumed that @p data is properly formatted.  It is further assumed
- * that @p data is allocated using the M_BUS malloc type.
- */
-void
-devctl_queue_data(char *data)
-{
-	struct dev_event_info *n1 = NULL;
-	struct proc *p;
-
-	n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
-	if (n1 == NULL)
-		return;
-	n1->dei_data = data;
-	mtx_lock(&devsoftc.mtx);
-	TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
-	cv_broadcast(&devsoftc.cv);
-	mtx_unlock(&devsoftc.mtx);
-	selwakeup(&devsoftc.sel);
-	p = devsoftc.async_proc;
-	if (p != NULL) {
-		PROC_LOCK(p);
-		psignal(p, SIGIO);
-		PROC_UNLOCK(p);
-	}
-}
-
-/**
- * @brief Send a 'notification' to userland, using standard ways
- */
-void
-devctl_notify(const char *system, const char *subsystem, const char *type,
-    const char *data)
-{
-	int len = 0;
-	char *msg;
-
-	if (system == NULL)
-		return;		/* BOGUS!  Must specify system. */
-	if (subsystem == NULL)
-		return;		/* BOGUS!  Must specify subsystem. */
-	if (type == NULL)
-		return;		/* BOGUS!  Must specify type. */
-	len += strlen(" system=") + strlen(system);
-	len += strlen(" subsystem=") + strlen(subsystem);
-	len += strlen(" type=") + strlen(type);
-	/* add in the data message plus newline. */
-	if (data != NULL)
-		len += strlen(data);
-	len += 3;	/* '!', '\n', and NUL */
-	msg = malloc(len, M_BUS, M_NOWAIT);
-	if (msg == NULL)
-		return;		/* Drop it on the floor */
-	if (data != NULL)
-		snprintf(msg, len, "!system=%s subsystem=%s type=%s %s\n",
-		    system, subsystem, type, data);
-	else
-		snprintf(msg, len, "!system=%s subsystem=%s type=%s\n",
-		    system, subsystem, type);
-	devctl_queue_data(msg);
-}
-
-/*
- * Common routine that tries to make sending messages as easy as possible.
- * We allocate memory for the data, copy strings into that, but do not
- * free it unless there's an error.  The dequeue part of the driver should
- * free the data.  We don't send data when the device is disabled.  We do
- * send data, even when we have no listeners, because we wish to avoid
- * races relating to startup and restart of listening applications.
- *
- * devaddq is designed to string together the type of event, with the
- * object of that event, plus the plug and play info and location info
- * for that event.  This is likely most useful for devices, but less
- * useful for other consumers of this interface.  Those should use
- * the devctl_queue_data() interface instead.
- */
-static void
-devaddq(const char *type, const char *what, device_t dev)
-{
-	char *data = NULL;
-	char *loc = NULL;
-	char *pnp = NULL;
-	const char *parstr;
-
-	if (devctl_disable)
-		return;
-	data = malloc(1024, M_BUS, M_NOWAIT);
-	if (data == NULL)
-		goto bad;
-
-	/* get the bus specific location of this device */
-	loc = malloc(1024, M_BUS, M_NOWAIT);
-	if (loc == NULL)
-		goto bad;
-	*loc = '\0';
-	bus_child_location_str(dev, loc, 1024);
-
-	/* Get the bus specific pnp info of this device */
-	pnp = malloc(1024, M_BUS, M_NOWAIT);
-	if (pnp == NULL)
-		goto bad;
-	*pnp = '\0';
-	bus_child_pnpinfo_str(dev, pnp, 1024);
-
-	/* Get the parent of this device, or / if high enough in the tree. */
-	if (device_get_parent(dev) == NULL)
-		parstr = ".";	/* Or '/' ? */
-	else
-		parstr = device_get_nameunit(device_get_parent(dev));
-	/* String it all together. */
-	snprintf(data, 1024, "%s%s at %s %s on %s\n", type, what, loc, pnp,
-	  parstr);
-	free(loc, M_BUS);
-	free(pnp, M_BUS);
-	devctl_queue_data(data);
-	return;
-bad:
-	free(pnp, M_BUS);
-	free(loc, M_BUS);
-	free(data, M_BUS);
-	return;
-}
-
-/*
- * A device was added to the tree.  We are called just after it successfully
- * attaches (that is, probe and attach success for this device).  No call
- * is made if a device is merely parented into the tree.  See devnomatch
- * if probe fails.  If attach fails, no notification is sent (but maybe
- * we should have a different message for this).
- */
-static void
-devadded(device_t dev)
-{
-	char *pnp = NULL;
-	char *tmp = NULL;
-
-	pnp = malloc(1024, M_BUS, M_NOWAIT);
-	if (pnp == NULL)
-		goto fail;
-	tmp = malloc(1024, M_BUS, M_NOWAIT);
-	if (tmp == NULL)
-		goto fail;
-	*pnp = '\0';
-	bus_child_pnpinfo_str(dev, pnp, 1024);
-	snprintf(tmp, 1024, "%s %s", device_get_nameunit(dev), pnp);
-	devaddq("+", tmp, dev);
-fail:
-	if (pnp != NULL)
-		free(pnp, M_BUS);
-	if (tmp != NULL)
-		free(tmp, M_BUS);
-	return;
-}
-
-/*
- * A device was removed from the tree.  We are called just before this
- * happens.
- */
-static void
-devremoved(device_t dev)
-{
-	char *pnp = NULL;
-	char *tmp = NULL;
-
-	pnp = malloc(1024, M_BUS, M_NOWAIT);
-	if (pnp == NULL)
-		goto fail;
-	tmp = malloc(1024, M_BUS, M_NOWAIT);
-	if (tmp == NULL)
-		goto fail;
-	*pnp = '\0';
-	bus_child_pnpinfo_str(dev, pnp, 1024);
-	snprintf(tmp, 1024, "%s %s", device_get_nameunit(dev), pnp);
-	devaddq("-", tmp, dev);
-fail:
-	if (pnp != NULL)
-		free(pnp, M_BUS);
-	if (tmp != NULL)
-		free(tmp, M_BUS);
-	return;
-}
-
-/*
- * Called when there's no match for this device.  This is only called
- * the first time that no match happens, so we don't keep getitng this
- * message.  Should that prove to be undesirable, we can change it.
- * This is called when all drivers that can attach to a given bus
- * decline to accept this device.  Other errrors may not be detected.
- */
-static void
-devnomatch(device_t dev)
-{
-	devaddq("?", "", dev);
-}
-
-static int
-sysctl_devctl_disable(SYSCTL_HANDLER_ARGS)
-{
-	struct dev_event_info *n1;
-	int dis, error;
-
-	dis = devctl_disable;
-	error = sysctl_handle_int(oidp, &dis, 0, req);
-	if (error || !req->newptr)
-		return (error);
-	mtx_lock(&devsoftc.mtx);
-	devctl_disable = dis;
-	if (dis) {
-		while (!TAILQ_EMPTY(&devsoftc.devq)) {
-			n1 = TAILQ_FIRST(&devsoftc.devq);
-			TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
-			free(n1->dei_data, M_BUS);
-			free(n1, M_BUS);
-		}
-	}
-	mtx_unlock(&devsoftc.mtx);
-	return (0);
-}
-
-/* End of /dev/devctl code */
-
-TAILQ_HEAD(,device)	bus_data_devices;
-static int bus_data_generation = 1;
-
-kobj_method_t null_methods[] = {
-	{ 0, 0 }
-};
-
-DEFINE_CLASS(null, null_methods, 0);
-
-/*
- * Driver compatibility layer implementation
- */
-
-static driverinfo_list_t driverinfos = TAILQ_HEAD_INITIALIZER(driverinfos);
-
-/**
- * @internal
- * 
- * Is used, when a driver s used in an API function, 
- * but is not in driverinfos. Eg. may happen, if 
- * device_set_driver is called by a bus with driver, set
- * to kobj_class, which wasn't registered by DRIVER_MODULE(). 
- */
-static drv_internal_t
-driverinfo_create_driver_drv_internal (driver_t *driver){
-	drv_internal_t new_drv;
-
-	new_drv = malloc (sizeof(struct drv_internal), M_TEMP, M_NOWAIT|M_ZERO);
-	if (new_drv){
-		new_drv.devops = driver;
-		new_drv.flags = DR_LOWEST;
-	}
-	return (new_drv);
-}
-/**
- * @internal
- * @brief Find or add driver compatibility settings
- * 
- * If a driver is already present in compatibility layer
- * return it, else, if @p add non-zero, add it.
- * 
- * @param driver	the device class and flags
- * @param add	non-zero to add driver to layer
- */
-static driverinfo_t
-driverinfo_find_internal (drv_internal_t driver, int add) {
-	driverinfo_t di;
-	
-	PDEBUG(("looking for driver %s to compatibility layer", driver->devops->name));
-	if (!driver)
-		return (NULL);
-	
-	TAILQ_FOREACH(di, &driverinfos, link){
-		if (driver->devops == di->driver)
-			break;
-	}
-	
-	if (!di && add){

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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