PERFORCE change 123211 for review

Maxim Zhuravlev thioretic at FreeBSD.org
Mon Jul 9 16:44:30 UTC 2007


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

Change 123211 by thioretic at thioretic on 2007/07/09 16:43:44

	TODO: softc, device_set_driver semantics, some functional 
	drivers	related (i.e. parents' manipulation (add/remove))
	stuff and some cleanups.

Affected files ...

.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#10 edit

Differences ...

==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#10 (text+ko) ====

@@ -140,7 +140,8 @@
 	/*
 	 * Details of this device.
 	 */
-	/*driver_t*/ drv_compat_t	driver;	/**< current driver to be probed/attached/...*/
+	/*driver_t*/ pdrv_compat	*driver;	/**< current driver to be probed/attached/...*/
+	int driver_level;
 	//driver_list_t drivers[DRV_LEVELS];
 	pdrv_compat_list_t drivers[DRV_LEVELS];
 	int drv_compat_flags;
@@ -355,7 +356,7 @@
 	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");		/*TODO*/
+	    "device drivers names");		/**TODO*/
 	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
 	    OID_AUTO, "%location", CTLFLAG_RD,
 	    dev, DEVICE_SYSCTL_LOCATION, device_sysctl_handler, "A",
@@ -923,7 +924,12 @@
 	drvc->flags = flags;
 	return (1);
 }
-
+/**
+ * @internal
+ * @brief Checks driver and returns corresponding driver
+ *
+ * @param flags	drv_compat flags
+ */
 static int
 drv_compat_flags2idx (uint32_t flags){
 	switch (flags & DR_ALLEVELS){
@@ -935,6 +941,15 @@
 	}
 }
 
+drv_compat_isfilter (driver_t *driver){
+	uint32_t flags;
+	int level;
+
+	drv_compat_get_flags (driver, &flags);
+	level = drv_compat_flags2idx (flags);
+	return((level>DR_LOWEST & level<DR_TOPMOST) ? TRUE : FALSE);
+}
+
 /**
  * device control multiplexing entries
  */
@@ -1106,24 +1121,26 @@
  * End of compatibility layer implementaion
  */
 
-int 
-is_device_driver (device_t dev, driver_t *driver){ /*TODO*/
+/**
+ * @internal
+ * @brief Checks, whether the driver is in device's stack
+ *
+ * @param dev	device, to check
+ * @param driver	driver, to be checked
+ */
+static int 
+is_device_driver (device_t dev, driver_t *driver){
 	int level;
 	uint32_t flags;
-	//driverlink_t dl;
 	pdrv_compat* pdrvl;
+
 	if (!drv_compat_get_flags(driver, &flags))
 		/*todo what?*/;
-
-	switch ((flags)&(DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)) {
-		case DR_LOWEST: level=DRV_LOWEST; break;
-		case DR_LOWER: level=DRV_LOWER; break;
-		case DR_MIDDLE: level=DRV_MIDDLE; break;
-		case DR_UPPER: level=DRV_UPPER; break;
-		case DR_TOPMOST: level=DRV_TOPMOST; break;
-	}
+	level = drv_compat_flags2idx (flags);
+	
 	TAILQ_FOREACH(pdrvl,&((dev->drivers)[level]),link){
-		if (pdrvl->pdriver->driver==driver) return(TRUE);
+		if (pdrvl->pdriver->driver == driver) 
+			return(TRUE);
 	}
 	return(FALSE);
 }
@@ -1153,9 +1170,9 @@
  */
 static devclass_t
 devclass_find_internal(const char *classname, const char *parentname,
-		       int create, int filter)
+		       int create, int filter)	/**TODO*/
 {
-	devclass_t dc;
+	devclass_t dc, dcp;
 
 	PDEBUG(("looking for %s", classname));
 	if (!classname)
@@ -1190,13 +1207,19 @@
 	 * device_probe_child() if a device exists for which there is no
 	 * suitable driver.
 	 */
-	if (parentname && dc && !dc->parent &&
-	    strcmp(classname, parentname) != 0) {
-		dc->parent = devclass_find_internal(parentname, 0, FALSE, FALSE);
+	if (!parentname)
+		return (dc);
+	
+	dcp = devclass_find_internal(parentname, 0, FALSE, FALSE)
+	
+	if (dc && !dc->parent &&
+	    strcmp(classname, parentname) != 0 &&
+	    !filter) {
+		dc->parent = dcp;
 	}
 
 	if (filter) {
-		TAILQ_INSERT_TAIL(&(dc->parent->filters), &dc, link);
+		TAILQ_INSERT_TAIL(&(dcp->filters), &dc, link);
 	}
 
 	return (dc);
@@ -1242,11 +1265,13 @@
  * @param driver	the driver to register
  */
 int
-devclass_add_driver(devclass_t dc, driver_t *driver)
+devclass_add_driver(devclass_t dc, driver_t *driver)	/*TODO*/
 {
 	driverlink_t dl;
 	int i;
 	uint32_t flags;
+	int isfilter;
+	drv_compat_t drvc;
 
 	PDEBUG(("%s", DRIVERNAME(driver)));
 
@@ -1254,22 +1279,26 @@
 	if (!dl)
 		return (ENOMEM);
 
+	isfilter = drv_compat_isfilter (driver); 
 	/*
 	 * Compile the driver's methods. Also increase the reference count
 	 * so that the class doesn't get freed when the last instance
 	 * goes. This means we can safely use static methods and avoids a
 	 * double-free in devclass_delete_driver.
 	 */
-	kobj_class_compile((kobj_class_t) driver);
+	//kobj_class_compile((kobj_class_t) driver);
+	
+	drvc = drv_compat_find_driver (driver);
+	drvc->topology_ops = kobj_create (drvc->driver, M_BUS, M_NOWAIT|M_ZERO);
 
 	/*
 	 * Make sure the devclass which the driver is implementing exists.
 	 */
-	if (!drv_compat_get_flags (driver, &flags)){
-		/*todo what???*/;
-	}
 
-	devclass_find_internal(driver->name, 0, TRUE, FALSE);
+	if (isfilter)
+		devclass_find_internal(driver->name, dc->name, TRUE, TRUE);
+	else
+		devclass_find_internal(driver->name, 0, TRUE, FALSE);
 
 	dl->driver = driver;
 	TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
@@ -1278,9 +1307,14 @@
 	/*
 	 * Call BUS_DRIVER_ADDED for any existing busses in this class.
 	 */
-	for (i = 0; i < dc->maxunit; i++)
-		if (dc->devices[i])
-			BUS_DRIVER_ADDED(dc->devices[i], driver);
+	if (!isfilter){
+		for (i = 0; i < dc->maxunit; i++)
+			if (dc->devices[i])
+				BUS_DRIVER_ADDED(dc->devices[i], driver);
+	}
+	else {
+		devclass_filter2devices(dc, driver);
+	}
 
 	bus_data_generation_update();
 	return (0);
@@ -1308,6 +1342,7 @@
 	device_t dev;
 	int i;
 	int error;
+	drv_compat_t drvc;
 
 	PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
 
@@ -1342,8 +1377,10 @@
 		if (dc->devices[i]) {
 			dev = dc->devices[i];
 			if (/*dev->driver == driver*/ 
-			is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) &&
+			is_device_driver(dev, driver) && 
+			!TAILQ_EMPTY(&(dev->parents)) &&
 			(TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) {
+				device_set_driver(dev, driver);
 				if ((error = device_detach(dev)) != 0)
 					return (error);
 				device_set_driver(dev, NULL);
@@ -1356,8 +1393,11 @@
 
 	/* XXX: kobj_mtx */
 	driver->refs--;
-	if (driver->refs == 0)
-		kobj_class_free((kobj_class_t) driver);
+	if (driver->refs == 0){
+		drvc = drv_compat_find_driver (driver);
+		//kobj_class_free((kobj_class_t) driver);
+		kobj_delete (drvc->topology_ops, M_BUS);
+	}
 
 	bus_data_generation_update();
 	return (0);
@@ -1770,9 +1810,10 @@
  * @retval ENOMEM	memory allocation failure
  */
 static int
-devclass_add_device(devclass_t dc, device_t dev)
+devclass_add_device(devclass_t dc, device_t dev)	/*TODO*/
 {
 	int buflen, error;
+	drv_compat_t drvc;
 
 	PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
 
@@ -1792,6 +1833,8 @@
 	dev->devclass = dc;
 	snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
 
+	devclass_device2filters (dc, dev);
+	
 	return (0);
 }
 
@@ -1808,7 +1851,7 @@
  * @retval 0		success
  */
 static int
-devclass_delete_device(devclass_t dc, device_t dev)
+devclass_delete_device(devclass_t dc, device_t dev)	/*TODO*/
 {
 	if (!dc || !dev)
 		return (0);
@@ -1827,6 +1870,46 @@
 	return (0);
 }
 
+static int
+filter_probe_and_attach (device_t dev, driver_t *driver){
+	drv_compat_t drvc;
+	int level;
+
+	device_set_driver (dev, dl->driver);
+	if (DEVICE_PROBE(dev)<=0){
+		drvc = dev->driver;
+		level = drv_compat_flags2idx(drvc->flags);
+		TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
+	}
+	device_set_driver (dev, NULL);
+}
+
+static void
+devclass_device2filters (devclass_t dc, device_t dev){
+	pdevclass *pdc;
+	driver_t *drv;
+	driverlink_t dl;
+
+	if (TAILQ_EMPTY(&(dc->filters))) return ();
+	TAILQ_FOREACH (pdc, &(dc->filters), link){
+		if (TAILQ_EMPTY(&(pdc->driver_ptr->drivers))) 
+			continue;
+		TAILQ_FOREACH(dl, &(pdc->driver_ptr->drivers), link){
+			filter_probe_and_attach (dev, dl->driver);
+		}
+	}
+}
+
+static void
+devclass_filter2devices (devclass_t dc, driver_t *filter){
+	int i;
+
+	for (i=0, i<=dc->maxunit; i++){
+		if ((dc->devices[i]) && 
+		   ((dc->devices[i])->state == DS_ALIVE))
+			filter_probe_and_attach (dv->devices[i], filter);
+	}
+}
 /**
  * @internal
  * @brief Make a new device and add it as a child of @p parent
@@ -2747,13 +2830,31 @@
  * @retval ENOMEM	a memory allocation failure occurred
  */
 int
-device_set_driver(device_t dev, driver_t *driver)
+device_set_driver(device_t dev, driver_t *driver) /*TODO*/
 {
-	drv_compat_t drvc;
+	drv_compat_t drvc; 
+	pdrv_compat *drvctmp;
+	uint32_t flags;
+	int level;
 
 	if (dev->state >= DS_ATTACHED)
 		return (EBUSY);
+	
+	drvc = drv_compat_find_driver (driver);
+
+	TAILQ_FOREACH(drvctmp, &(dev->drivers[level]), link){
+		if (drvctmp->pdriver == drvc)
+			break;
+	}
+
+	if (!drvctmp){
+		
+	}
 
+	dev->driver = drvctmp;
+	dev->driver_level = level;
+
+	/*
 	if (dev->driver == driver)
 		return (0);
 
@@ -2761,13 +2862,7 @@
 		free(dev->softc, M_BUS_SC);
 		dev->softc = NULL;
 	}
-	//kobj_delete((kobj_t) dev, 0);
-	dev->driver = drvc = drv_compat_find_driver (driver);
 	if (driver) {
-		if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO)))
-			/*todo what??*/;
-		dev->driver = drvc;
-		//kobj_init((kobj_t) dev, (kobj_class_t) driver);
 		if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) {
 			dev->softc = malloc(driver->size, M_BUS_SC,
 			    M_NOWAIT | M_ZERO);
@@ -2778,8 +2873,6 @@
 				return (ENOMEM);
 			}
 		}
-	} /*else {
-		kobj_init((kobj_t) dev, &null_class);
 	}*/
 
 	bus_data_generation_update();
@@ -2889,7 +2982,7 @@
 		dev->devclass = devclass_find (DRIVERNAME(drvc->driver));
 		level = drv_compat_flags2idx(drvc->flags);
 		TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
-		driver = NULL;
+		dev->driver = NULL;
 	}
 	dev->state = DS_ATTACHED;
 	devadded(dev);
@@ -4273,8 +4366,6 @@
 
 	dmd = (struct driver_module_data *)arg;
 	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) {
@@ -4282,27 +4373,17 @@
 		if (dmd->dmd_chainevh)
 			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
 
-		//driver = 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));
 		if (!parse_parent_name(dmd->dmd_busname, &parents))
 			break;
-		isfilter = drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST);
+		isfilter = drv_compat_isfilter (driver);
 		while (parents[count]){
-			if (isfilter){
-			/* if is a filter driver */
-				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++;
-			}
-			else{
-				error &= devclass_add_driver(parents[count], driver);
-			}
+			parent_devclass = devclass_find_internal(parents[count], 0, TRUE, FALSE);
+			error &= devclass_add_driver (parent_devclass, driver);
+			count++;
 		}
 		free(parents);
 		if (error)
@@ -4330,7 +4411,7 @@
 			dev = make_device (root_bus, DRIVERNAME(driver), -1/*, driver*/);
 			device_set_driver(dev, driver);
 			/*if (!hasclass)*/
-			device_set_devclass(child, dl->driver->name);
+			device_set_devclass(dev, driver->name);
 
 			/* Fetch any flags for the device before probing.
 			resource_int_value(dl->driver->name, child->unit,


More information about the p4-projects mailing list