PERFORCE change 123068 for review

Maxim Zhuravlev thioretic at FreeBSD.org
Sat Jul 7 19:06:19 UTC 2007


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

Change 123068 by thioretic at thioretic on 2007/07/07 19:05:27

	Start to introduce advanced topology stuff.
	Now device has multiple parents, so some dummy
	find & replace. Those for bus_generic_* stuff next time.)

Affected files ...

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

Differences ...

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

@@ -71,6 +71,7 @@
 		#	represent drivers of interest.
 	a.1.2 Devclasses
 		SOLUTION: add filters field to devclass
+		FILE(S) AFFECTED: kern/subr_bus.c
 		# 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
@@ -81,9 +82,27 @@
 		#
 		# BUS<-+-+....
 		#      |
-		#   DR_LOWEST driver_n<-+----+...
-		#			|    |
-		#		    filter0 filter1
+		#  DR_LOWEST driver_n<-+-----+...
+		#                      |     |
+		#                 filter_0 filter_1
 		#
 		# NB: here BUS is also a DR_LOWEST driver in turn with all 
-		# those consequences.+		# those consequences.
+	a.1.3 Topology
+		SOLUTION: add a kinda *REQDEV* flag for driver
+		FILE(S) AFFECTED: kern/subr_bus.c, sys/bus.h
+		# Currently device layout is hardware-driven (i.e. depends on
+		# device - bus relations). But all the fun (the project) is all 
+		# about adding functionality-driven layout to newbus. I.e.
+		# mux / demux depends not so much on hardware topology as on
+		# functionality , provided by a device (i.e whether it is a mouse
+		# or a keyboard or ...). At this point it's obvious, that currently
+		# there are no means, provided by newbus, to build a *device*, not
+		# backed up by a *real* device, into the newbus tree. At same time
+		# it's a good idea to use the built tree for such functional (eg. mux) 
+		# devices. At this point it's obvious, that there should be means to
+		# create a corresponding device on driver add, and init it to the 
+		# driver without any probing. Also a device may have multiple parents
+		# and children. At this point it becomes obvious, that we should let
+		# a driver not just process, but also produce and destroy an io request.
+		
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#7 (text+ko) ====

@@ -82,7 +82,7 @@
 typedef struct drv_compat *drv_compat_t;
 
 struct pdrv_compat {
-	drv_compat *pdriver;
+	drv_compat_t pdriver;
 	TAILQ_ENTRY(pdrv_compat) link;
 };
 
@@ -132,7 +132,8 @@
 	 */
 	TAILQ_ENTRY(device)	link;	/**< list of devices in parent */
 	TAILQ_ENTRY(device)	devlink; /**< global device list membership */
-	device_t	parent;		/**< parent of this device  */
+	//device_t	parent;		/**< parent of this device  */
+	device_list_t	parents;
 	device_list_t	children;	/**< list of child devices */
 
 	/*
@@ -915,6 +916,17 @@
 	return (1);
 }
 
+static int
+drv_compat_flags2idx (uint32_t flags){
+	switch (flags & DR_ALLEVELS){
+		case DR_LOWEST: return (DRV_LOWEST);
+		case DR_LOWER:	return (DRV_LOWER);
+		case DR_MIDDLE: return (DRV_MIDDLE);
+		case DR_UPPER:	return (DRV_UPPER);
+		case DR_TOPMOST:	return (DRV_TOPMOST);
+	}
+}
+
 /**
  * device control multiplexing entries
  */
@@ -1076,7 +1088,7 @@
 	DEVMETHOD(bus_hinted_child,			drv_compat_ctrl_hinted_child)
 };
 
-static	driver_t	drv_compat_ctrl_driver = {
+static	driver_t	drv_compat_ctrl_driver = {	/*TODO*/
 	"drv_compat_ctrl",
 	drv_compat_ctrl_methods,
 	0
@@ -1093,7 +1105,7 @@
 	//driverlink_t dl;
 	pdrv_compat* pdrvl;
 	if (!drv_compat_get_flags(driver, &flags))
-		/*todo what?*/
+		/*todo what?*/;
 
 	switch ((flags)&(DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)) {
 		case DR_LOWEST: level=DRV_LOWEST; break;
@@ -1176,7 +1188,7 @@
 	}
 
 	if (filter) {
-		TAILQ_INSERT_TAIL(&(dc->parent->filters), dc, link);
+		TAILQ_INSERT_TAIL(&(dc->parent->filters), &dc, link);
 	}
 
 	return (dc);
@@ -1246,7 +1258,7 @@
 	 * Make sure the devclass which the driver is implementing exists.
 	 */
 	if (!drv_compat_get_flags (driver, &flags)){
-		/*todo what???*/
+		/*todo what???*/;
 	}
 
 	devclass_find_internal(driver->name, 0, TRUE, FALSE);
@@ -1322,8 +1334,8 @@
 		if (dc->devices[i]) {
 			dev = dc->devices[i];
 			if (/*dev->driver == driver*/ 
-				is_device_driver(dev, driver) && dev->parent &&
-			    dev->parent->devclass == busclass) {
+			is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) &&
+			(TAILQ_FIRST(&(dev->parent->devclass))) == busclass) {
 				if ((error = device_detach(dev)) != 0)
 					return (error);
 				device_set_driver(dev, NULL);
@@ -1398,8 +1410,8 @@
 		if (dc->devices[i]) {
 			dev = dc->devices[i];
 			if (/*dev->driver == driver*/ 
-				is_device_driver(dev, driver) && dev->parent &&
-			    dev->parent->devclass == busclass) {
+			is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents) &&
+			(TAILQ_FIRST(&(dev->parent)))->devclass == busclass) {
 				if ((error = device_quiesce(dev)) != 0)
 					return (error);
 			}
@@ -1820,11 +1832,12 @@
  * @returns the new device
  */
 static device_t
-make_device(device_t parent, const char *name, int unit)	/*TODO*/
+make_device(device_t parent, const char *name, int unit, driver_t *initto)	/*TODO*/
 {
 	device_t dev;
 	devclass_t dc;
 	int level;
+	drv_compat_t drvc;
 
 	PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
 
@@ -1842,14 +1855,27 @@
 	dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT|M_ZERO);
 	if (!dev)
 		return (NULL);
-
-	dev->parent = parent;
-	TAILQ_INIT(&dev->children);
-	kobj_init((kobj_t) dev, &null_class);
+	TAILQ_INIT(&(dev->parents));
+	TAILQ_INSERT_TAIL(&(dev->parents), *parent, link)
+	TAILQ_INIT(&(dev->children));
+	//kobj_init((kobj_t) dev, &null_class);
+	kobj_init((kobj_t) dev, &drv_compat_ctrl_driver)
 	//dev->driver = NULL;
 	for (level=DRV_LOWEST; level<=DRV_TOPMOST; level++)
 		TAILQ_INIT(&((dev->drivers)[level]));
-	dev->devclass = NULL;
+	if (initto){
+		drvc = drv_compat_find_driver (initto);
+		if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO)))
+			/*todo what??*/;
+		dev->devclass = devclass_find (DRIVERNAME(driver));
+		level = drv_compat_flags2idx(drvc->flags);
+		TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
+		dev->state = DS_ALIVE;
+	}
+	else{
+		dev->devclass = NULL;
+		dev->state = DS_NOTPRESENT;
+	}
 	dev->unit = unit;
 	dev->nameunit = NULL;
 	dev->desc = NULL;
@@ -1863,13 +1889,13 @@
 		dev->flags |= DF_FIXEDCLASS;
 		if (devclass_add_device(dc, dev)) {
 			kobj_delete((kobj_t) dev, M_BUS);
+			dev->state = 0;
 			return (NULL);
 		}
 	}
 	dev->ivars = NULL;
 	dev->softc = NULL;
 
-	dev->state = DS_NOTPRESENT;
 
 	TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
 	bus_data_generation_update();
@@ -1945,7 +1971,7 @@
 	PDEBUG(("%s at %s with order %d as unit %d",
 	    name, DEVICENAME(dev), order, unit));
 
-	child = make_device(dev, name, unit);
+	child = make_device(dev, name, unit, NULL);
 	if (child == NULL)
 		return (child);
 	child->order = order;
@@ -2013,6 +2039,15 @@
 	return (0);
 }
 
+static int
+is_device_parent (device_t dev, device_t child){
+	device_t dc;
+	TAILQ_FOREACH (dc, &(child->parents), link){
+		if (dc == dev) return (1);
+	}
+	return (0);
+}
+
 /**
  * @brief Find a device given a unit number
  *
@@ -2039,12 +2074,14 @@
 
 	if (unit != -1) {
 		child = devclass_get_device(dc, unit);
-		if (child && child->parent == dev)
+		if (child && /*child->parent == dev*/
+			is_device_parent(dev, child))
 			return (child);
 	} else {
 		for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
 			child = devclass_get_device(dc, unit);
-			if (child && child->parent == dev)
+			if (child && /*child->parent == dev*/
+				is_device_parent(dev, child))
 				return (child);
 		}
 	}
@@ -2224,9 +2261,11 @@
  * @brief Return the parent of a device
  */
 device_t
-device_get_parent(device_t dev)
+device_get_parent(device_t dev) /*TODO*/
 {
-	return (dev->parent);
+	if (!TAILQ_EMPTY(&(dev->parents)))
+		return (TAILQ_FIRST(&(dev->parents)));
+	return (NULL);
 }
 
 /**
@@ -2545,10 +2584,14 @@
 void
 device_busy(device_t dev)
 {
+	device_t parent;
 	if (dev->state < DS_ATTACHED)
 		panic("device_busy: called for unattached device");
-	if (dev->busy == 0 && dev->parent)
-		device_busy(dev->parent);
+	if (dev->busy == 0 && !TAILQ_EMPTY(&(dev->parents))){
+		TAILQ_FOREACH (parent, &(dev->parents), link){
+			device_busy(parent);
+		}
+	}
 	dev->busy++;
 	dev->state = DS_BUSY;
 }
@@ -2564,8 +2607,12 @@
 		    device_get_nameunit(dev));
 	dev->busy--;
 	if (dev->busy == 0) {
-		if (dev->parent)
-			device_unbusy(dev->parent);
+		if (/*dev->parent*/!TAILQ_EMPTY(&(dev->parents))){
+			TAILQ_FOREACH (parent, &(dev->parents), link){
+				device_unbusy(parent);
+			}
+		}
+		//device_unbusy(dev->parent);
 		dev->state = DS_ATTACHED;
 	}
 }
@@ -2725,7 +2772,7 @@
  * @retval non-zero	some other unix error code
  */
 int
-device_probe_and_attach(device_t dev)
+device_probe_and_attach(device_t dev)	/*TODO*/
 {
 	int error;
 
@@ -2777,10 +2824,14 @@
 device_attach(device_t dev)
 {
 	int error;
+	device_t parent;
 
 	device_sysctl_init(dev);
-	if (!device_is_quiet(dev))
-		device_print_child(dev->parent, dev);
+	if (!device_is_quiet(dev)){
+		TAILQ_FOREACH (parent, &(dev->parents), link){
+			device_print_child(parent, dev);
+		}
+	}
 	if ((error = DEVICE_ATTACH(dev)) != 0) {
 		printf("device_attach: %s%d attach returned %d\n",
 		    dev->driver->name, dev->unit, error);
@@ -2817,6 +2868,7 @@
 device_detach(device_t dev)
 {
 	int error;
+	device_t parent;
 
 	GIANT_REQUIRED;
 
@@ -2830,8 +2882,11 @@
 		return (error);
 	devremoved(dev);
 	device_printf(dev, "detached\n");
-	if (dev->parent)
-		BUS_CHILD_DETACHED(dev->parent, dev);
+	if (!TAILQ_EMPTY(&(dev->parent))){
+		TAILQ_FOREACH (parent, &(dev->parents), link){
+			BUS_CHILD_DETACHED(parent, dev);
+		}
+	}
 
 	if (!(dev->flags & DF_FIXEDCLASS))
 		devclass_delete_device(dev->devclass, dev);
@@ -4057,7 +4112,7 @@
 	case MOD_LOAD:
 		TAILQ_INIT(&bus_data_devices);
 		kobj_class_compile((kobj_class_t) &root_driver);
-		root_bus = make_device(NULL, "root", 0);
+		root_bus = make_device(NULL, "root", 0, NULL);
 		root_bus->desc = "System root bus";
 		kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
 		root_bus->driver = &root_driver;
@@ -4159,13 +4214,13 @@
 int
 driver_module_handler(module_t mod, int what, void *arg)
 {
-	int error;
+	int error=0;
 	struct driver_module_data *dmd;
 	devclass_t bus_devclass, parent_devclass, filter_devclass;
 	drv_internal_t drv_intnl;
 	kobj_class_t driver;
 	char* parents[];
-	int count=0;
+	int count=0, isfilter;
 
 	dmd = (struct driver_module_data *)arg;
 	drv_intnl = dmd->dmd_driver;
@@ -4183,23 +4238,24 @@
 		driver = drv_intnl->devops;
 		PDEBUG(("Loading module: driver %s on bus %s",
 		    DRIVERNAME(driver), dmd->dmd_busname));
-		if (drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)){
+		if (!parse_parent_name(dmd->dmd_busname, &parents))
+			break;
+		isfilter = drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST);
+		while (parents[count]){
+			if (isfilter){
 			/* 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);
+				error &= devclass_add_driver (filter_devclass, driver);
 				count++;
 			}
-			free(parents);
+			else{
+				error &= devclass_add_driver(parents[count], driver);
+			}
 		}
-		else{
-			error = devclass_add_driver(bus_devclass, driver);
-		}
+		free(parents);
 		if (error)
 			break;
 
@@ -4220,6 +4276,15 @@
 			*dmd->dmd_devclass =
 				devclass_find_internal(driver->name, 0, TRUE);
 		}
+
+		if(drv_intnl->flags & DR_REQDEV){ /*restrict to DR_LOWEST? */
+			make_device (root_bus, DRIVERNAME(driver), -1, driver);
+			/* todo: set all parents for device
+			 * parents are all devices (alive) in parent
+			 * devclasses
+			 */
+		}
+
 		break;
 
 	case MOD_UNLOAD:

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

@@ -495,6 +495,7 @@
 #define	DR_MIDDLE	8
 #define DR_UPPER	16
 #define DR_TOPMOST	32
+#define DR_REQDEV	64
 	uint32_t flags;
 };
 


More information about the p4-projects mailing list