PERFORCE change 122974 for review

Maxim Zhuravlev thioretic at FreeBSD.org
Thu Jul 5 21:15:10 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=122974

Change 122974 by thioretic at thioretic on 2007/07/05 21:14:17

	Devclasses for filter drivers stuff.

Affected files ...

.. //depot/projects/soc2007/thioretic_gidl/TODO#7 edit
.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#6 edit
.. //depot/projects/soc2007/thioretic_gidl/sys/bus.h#4 edit

Differences ...

==== //depot/projects/soc2007/thioretic_gidl/TODO#7 (text+ko) ====

@@ -68,4 +68,22 @@
 		#	attached, but to drv_compat_ctrl_driver, which will demux 
 		#	to stacked drivers.
 		#	dev->drivers are pointers to drv_compat structures that
-		#	represent drivers of interest.+		#	represent drivers of interest.
+	a.1.2 Devclasses
+		SOLUTION: add filters field to devclass
+		# the filter drivers (with DR_LOWEST<level<DR_TOPMOST) use
+		# devclasses quite differently. Actually, they just extend
+		# the functionality of DR_LOWEST driver. So only DR_LOWEST
+		# driver should have an in-tree built devclass, with
+		# pointers to devclasses of filter drivers. I.e.:
+		#
+		# Devclasses tree:
+		#
+		# BUS<-+-+....
+		#	   |
+		#	DR_LOWEST driver_n<-+----+...
+		#						|	 |
+		#					filter0 filter1
+		#
+		# NB: here BUS is also a DR_LOWEST driver in turn with all 
+		# those consequences.
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#6 (text+ko) ====

@@ -84,20 +84,29 @@
 struct pdrv_compat {
 	drv_compat *pdriver;
 	TAILQ_ENTRY(pdrv_compat) link;
-}
+};
+
 /*
  * Forward declarations
  */
 typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
+typedef TAILQ_HEAD(pdevclass_list, pdevclass) pdevclass_list_t;
 typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
 typedef TAILQ_HEAD(device_list, device) device_list_t;
 
 typedef TAILQ_HEAD(drv_compat_list, drv_compat) drv_compat_list_t;
 typedef TAILQ_HEAD(pdrv_compat_list, pdrv_compat) pdrv_compat_list_t;
 
+struct pdevclass{
+	devclass_t devclass_ptr;
+	TAILQ_ENTRY(pdevclass) link;
+};
+
 struct devclass {
 	TAILQ_ENTRY(devclass) link;
 	devclass_t	parent;		/* parent in devclass hierarchy */
+	pdevclass_list_t	filters;	/* these are used to hold information, 
+									used for non-DRV_LOWEST drivers' classes */
 	driver_list_t	drivers;     /* bus devclasses store drivers for bus */
 	char		*name;
 	device_t	*devices;	/* array of devices indexed by unit */
@@ -1124,7 +1133,7 @@
  */
 static devclass_t
 devclass_find_internal(const char *classname, const char *parentname,
-		       int create)
+		       int create, int filter)
 {
 	devclass_t dc;
 
@@ -1147,6 +1156,7 @@
 		dc->name = (char*) (dc + 1);
 		strcpy(dc->name, classname);
 		TAILQ_INIT(&dc->drivers);
+		TAILQ_INIT(&dc->filters);
 		TAILQ_INSERT_TAIL(&devclasses, dc, link);
 
 		bus_data_generation_update();
@@ -1162,7 +1172,11 @@
 	 */
 	if (parentname && dc && !dc->parent &&
 	    strcmp(classname, parentname) != 0) {
-		dc->parent = devclass_find_internal(parentname, 0, FALSE);
+		dc->parent = devclass_find_internal(parentname, 0, FALSE, FALSE);
+	}
+
+	if (filter) {
+		TAILQ_INSERT_TAIL(&(dc->parent->filters), dc, link);
 	}
 
 	return (dc);
@@ -1179,7 +1193,7 @@
 devclass_t
 devclass_create(const char *classname)
 {
-	return (devclass_find_internal(classname, 0, TRUE));
+	return (devclass_find_internal(classname, 0, TRUE, FALSE));
 }
 
 /**
@@ -1193,7 +1207,7 @@
 devclass_t
 devclass_find(const char *classname)
 {
-	return (devclass_find_internal(classname, 0, FALSE));
+	return (devclass_find_internal(classname, 0, FALSE, FALSE));
 }
 
 /**
@@ -1212,6 +1226,7 @@
 {
 	driverlink_t dl;
 	int i;
+	uint32_t flags;
 
 	PDEBUG(("%s", DRIVERNAME(driver)));
 
@@ -1230,7 +1245,11 @@
 	/*
 	 * Make sure the devclass which the driver is implementing exists.
 	 */
-	devclass_find_internal(driver->name, 0, TRUE);
+	if (!drv_compat_get_flags (driver, &flags)){
+		/*todo what???*/
+	}
+
+	devclass_find_internal(driver->name, 0, TRUE, FALSE);
 
 	dl->driver = driver;
 	TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
@@ -1810,7 +1829,7 @@
 	PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
 
 	if (name) {
-		dc = devclass_find_internal(name, 0, TRUE);
+		dc = devclass_find_internal(name, 0, TRUE, FALSE);
 		if (!dc) {
 			printf("make_device: can't find device class %s\n",
 			    name);
@@ -2627,7 +2646,7 @@
 		return (EINVAL);
 	}
 
-	dc = devclass_find_internal(classname, 0, TRUE);
+	dc = devclass_find_internal(classname, 0, TRUE, FALSE);
 	if (!dc)
 		return (ENOMEM);
 
@@ -4043,7 +4062,7 @@
 		kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
 		root_bus->driver = &root_driver;
 		root_bus->state = DS_ATTACHED;
-		root_devclass = devclass_find_internal("root", 0, FALSE);
+		root_devclass = devclass_find_internal("root", 0, FALSE, FALSE);
 		devinit();
 		return (0);
 
@@ -4083,6 +4102,53 @@
 }
 
 /**
+ * @internal
+ * @brief Parses the dmd_busname for filter drivers
+ *
+ * The dmd_busname for filter drivers if represented
+ * by a string of busnames (actually they are names
+ * of DR_LOWEST drivers) delimited by '|' symbol.
+ * 
+ * @param in	a pointer to dmd_busname string
+ * @param out	a pointer to store the address
+ *				of an array of strings, representing
+ *				the devclass names of DR_LOWEST
+ *				drivers.
+ */
+
+static int
+parse_parent_name (char* in, char ***out){	/*TODO*/
+	char* cptr = in, *ptr = in, *newpar;
+	int count = 1, num = 0;
+	
+	if (!in || *in == '\0')
+		return (0);
+	
+	if (!strcmp(in, "*")){
+		/* do we need this?
+		 * if we do, then there must be a way
+		 * to add filter driver to devclasses
+		 * of drivers, not yet added
+		 */
+	}
+	else{
+		while (strchr(ptr, '|')) count++;
+		*out = malloc (sizeof(char*)*(count+1), M_BUS, M_NOWAIT|M_ZERO);
+		count=0;
+		do {
+			while (*ptr!='|' && *ptr!='\0')	num++,	ptr++;
+			newpar = malloc ((num+1)*sizeof(char), M_BUS, M_NOWAIT|M_ZERO);
+			if (!newpar) return(0);
+			strlcpy(newpar, cptr, num+1);
+			(*out)[count++] = newpar;
+			num = 0; cptr = ++ptr;
+		} while (cptr<(in+strlen(in)));
+		(*out)[count]=NULL;
+		return (1);
+	}
+}
+
+/**
  * @brief Module handler for registering device drivers
  *
  * This module handler is used to automatically register device
@@ -4095,12 +4161,16 @@
 {
 	int error;
 	struct driver_module_data *dmd;
-	devclass_t bus_devclass;
+	devclass_t bus_devclass, parent_devclass, filter_devclass;
 	drv_internal_t drv_intnl;
 	kobj_class_t driver;
+	char* parents[];
+	int count=0;
 
 	dmd = (struct driver_module_data *)arg;
-	bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE);
+	drv_intnl = dmd->dmd_driver;
+	if (!(drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)))
+		bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE, FALSE);
 	error = 0;
 
 	switch (what) {
@@ -4109,12 +4179,27 @@
 			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
 
 		//driver = dmd->dmd_driver;
-		drv_intnl = dmd->dmd_driver;
 		drv_compat_add_driver(drv_intnl);
 		driver = drv_intnl->devops;
 		PDEBUG(("Loading module: driver %s on bus %s",
 		    DRIVERNAME(driver), dmd->dmd_busname));
-		error = devclass_add_driver(bus_devclass, driver);
+		if (drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)){
+			/* if is a filter driver */
+			if (!parse_parent_name(dmd->dmd_busname, &parents))
+				break;
+			while (parents[count]){
+				parent_devclass = devclass_find_internal (parents[count],
+					0, TRUE, FALSE);
+				filter_devclass = devclass_find_internal (driver->name,
+					parent[count], TRUE, TRUE);
+				error = devclass_add_driver (filter_devclass, driver);
+				count++;
+			}
+			free(parents);
+		}
+		else{
+			error = devclass_add_driver(bus_devclass, driver);
+		}
 		if (error)
 			break;
 

==== //depot/projects/soc2007/thioretic_gidl/sys/bus.h#4 (text+ko) ====

@@ -498,6 +498,8 @@
 	uint32_t flags;
 };
 
+#define DR_ALLLEVELS (DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)
+
 typedef struct drv_internal *drv_internal_t;
 
 struct driver_module_data {
@@ -513,7 +515,7 @@
 									\
 static struct drv_internal name##_##busname##_intnl {		\
 	(kobj_class_t)	&driver,		\
-	LOWEST							\
+	DR_LOWEST							\
 };									\
 									\
 static struct driver_module_data name##_##busname##_driver_mod = {	\


More information about the p4-projects mailing list