PERFORCE change 123400 for review

Maxim Zhuravlev thioretic at FreeBSD.org
Thu Jul 12 19:41:46 UTC 2007


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

Change 123400 by thioretic at thioretic on 2007/07/12 19:41:00

	TODO: bus_generic_* and resource_* stuff , cleanups, including proper 
		naming :) (probably they should go first), locking and IO 
		requests processing stuff.
	DONE: device_set_driver semantics.
	ALSO: my thoughts about drv_compat_ctrl_driver should now be more 
		obvious.

Affected files ...

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

Differences ...

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

@@ -107,10 +107,6 @@
 		# a driver not just process, but also produce and destroy an io request.
 		# Inportant note: from above-said one can see, that since now newbus 
 		# won't be a tree, it will be a graph!
-		# New logic:
-		# probe/attach: the dev->driver is set to drv_compat(driver) to be 
-		# probed and attached.
-		# detach: will detach DRV_LOWEST driver and all filters consequently.
 		# As for functional devices (let's call like this all drivers with 
 		# DR_REQDEV flag set), the following scenario looks reasonable:
 		#
@@ -132,4 +128,11 @@
 		#	device_set_driver_softc().
 		# All these return softc of a specified driver for a device. Old functions
 		# (those without '_driver_') return softc of DRV_LOWEST driver (as expected).
-		+	a.1.5 device_set_driver semantics
+		SOLUTION: add DS_RAW state value && add per-pdrv_compat state
+		FILE(S) AFFECTED: kern/subr_bus.c, sys/bus.h
+		# As now device hosts many drivers, dev->driver should point to currently
+		# probed/attached/.. driver. If driver to be set to is DR_LOWEST not equal
+		# to that already in stack or is NULL, the whole driver configuration is
+		# destroyed. Device won't process any i/o requests till its state is set
+		# to DS_ALIVE (i.e. there is no DS_RAW or other drivers in stack).
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#13 (text+ko) ====

@@ -87,6 +87,7 @@
 	void *softc;
 #define	DF_EXTERNALSOFTC 1		/* softc not allocated by us */
 	int flags;
+	device_state_t state;
 	TAILQ_ENTRY(pdrv_compat) link;
 };
 
@@ -953,133 +954,181 @@
 	return((level>DR_LOWEST & level<DR_TOPMOST) ? TRUE : FALSE);
 }
 
+
 /**
  * device control multiplexing entries
  */
+#define PREFIX drv_compat_ctrl
+
+#define FUNC(retval, prefix, name, ...)	\
+	static retval	\
+	prefix##_##name (__VA_ARGS__)
+
+#define FOR_RAW_DRIVER(func, ...)	\
+	return(func(__VA_ARGS__));
+
+#define FOR_ALL_BUT_RAW_DRIVER (func, memb, ...)	\
+	int level;		\
+	pdrv_compat *pdc;		\
+	for (level = DRV_LOWEST; level <= DRV_TOPMOST; level++){	\
+		if(TAILQ_EMPTY(&(dev->drivers[level])))		\
+			continue;	\
+		TAILQ_FOREACH (pdc, &(dev->drivers[level]), link){	\
+			func(pdc->pdriver->memb, __VA_ARGS__);		\
+		}					\
+	}
+
+
+FUNC(int, PREFIX, probe, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_PROBE, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, identify, driver_t *driver, device_t parent){
+	FOR_RAW_DRIVER(DEVICE_IDENTIFY, dev->driver->pdriver->driver, parent);
+}
+
+FUNC(int, PREFIX, attach, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_ATTACH, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, detach, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_DETACH, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, shutdown, device_t parent){
+	FOR_RAW_DRIVER(DEVICE_SHUTDOWN, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, suspend, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_SUSPEND, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, resume, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_RESUME, dev->driver->pdriver->topology_ops);
+}
+
+FUNC(int, PREFIX, quiesce, device_t dev){
+	FOR_RAW_DRIVER(DEVICE_QUIESCE, dev->driver->pdriver->topology_ops);
+}
 
-static int drv_compat_ctrl_probe (device_t dev);
-static int drv_compat_ctrl_identify (driver_t *driver, device_t parent);
-static int drv_compat_ctrl_attach (device_t dev);
-static int drv_compat_ctrl_detach (device_t dev);
-static int drv_compat_ctrl_shutdown (device_t dev);
-static int drv_compat_ctrl_suspend (device_t dev);
-static int drv_compat_ctrl_resume (device_t dev);
-static int drv_compat_ctrl_quiesce (device_t dev);
-static void* drv_compat_ctrl_info (device_t dev);
+FUNC(void *, PREFIX, info, driver_t *driver, device_t parent){
+	FOR_ALL_BUT_RAW_DRIVER(DEVICE_INFO, topology_ops);
+}
+
 /**
  * bus control multiplexing entries
  */
 static int 
 drv_compat_ctrl_print_child (device_t dev,
-							 device_t child);
+			     device_t child);
 static void 
 drv_compat_ctrl_probe_nomatch (device_t dev,
-							   device_t child);
+			       device_t child);
 static int 
 drv_compat_ctrl_read_ivar (device_t dev,
-						   device_t child,
-			 			   int index,
-						   uintptr_t *result);
+			   device_t child,
+			   int index,
+			   uintptr_t *result);
 static int 
 drv_compat_ctrl_write_ivar (device_t dev,
-						    device_t child,
-							int index,
-							uintptr_t value);
+			    device_t child,
+			    int index,
+			    uintptr_t value);
 static void 
 drv_compat_ctrl_child_detached (device_t dev,
-								device_t child);
+				device_t child);
 static void 
 drv_compat_ctrl_driver_added (device_t dev,
-							  driver_t *driver);
+			      driver_t *driver);
 static device_t 
 drv_compat_ctrl_add_child (device_t dev,
-						   int order,
-						   const char* name,
-						   int unit);
+			   int order,
+			   const char* name,
+			   int unit);
 static struct_resource * 
 drv_compat_ctrl_alloc_resource (device_t dev,
-								device_t child,
-								int type,
-								int *rid,
-								u_long start,
-								u_long end,
-								u_long count,
-								u_int flags);
+				device_t child,
+				int type,
+				int *rid,
+				u_long start,
+				u_long end,
+				u_long count,
+				u_int flags);
 static int 
 drv_compat_ctrl_activate_resource (device_t dev,
-								   device_t child,
-								   int type,
-								   int rid,
-								   struct resource *r);
+				   device_t child,
+				   int type,
+				   int rid,
+				   struct resource *r);
 static int 
 drv_compat_ctrl_deactivate_resource (device_t dev,
-									 device_t child,
-									 int type,
-									 int rid,
-									 struct resource *r);
+				     device_t child,
+				     int type,
+				     int rid,
+				     struct resource *r);
 static int 
 drv_compat_ctrl_release_resource (device_t dev,
-						 		  device_t child,
-								  int type,
-								  int rid,
-								  struct resource *res);
+				  device_t child,
+				  int type,
+				  int rid,
+				  struct resource *res);
 static int 
 drv_compat_ctrl_setup_intr (device_t dev,
-							device_t child,
-							struct resource *irq,
-							int flags,
-							driver_intr_t *intr,
-							void *arg,
-							void **cookiep);
+			    device_t child,
+			    struct resource *irq,
+			    int flags,
+			    driver_intr_t *intr,
+			    void *arg,
+			    void **cookiep);
 static int 
 drv_compat_ctrl_teardown_intr (device_t dev,
-							   device_t child,
-							   struct resource *irq,
-							   void *cookie);
+			       device_t child,
+			       struct resource *irq,
+			       void *cookie);
 static int 
 drv_compat_ctrl_set_resource (device_t dev,
-							  device_t child,
-							  int type,
-							  int rid,
-							  u_long start,
-							  u_long count);
+			      device_t child,
+			      int type,
+			      int rid,
+			      u_long start,
+			      u_long count);
 static int 
 drv_compat_ctrl_get_resource (device_t dev,
-							  device_t child,
-							  int type,
-							  int rid,
-							  u_long *startp,
-							  u_long *countp);
+			      device_t child,
+			      int type,
+			      int rid,
+			      u_long *startp,
+			      u_long *countp);
 static void 
 drv_compat_ctrl_delete_resource (device_t dev,
-								 device_t child,
-								 int type,
-								 int rid);
+				 device_t child,
+				 int type,
+				 int rid);
 static struct resource_list * 
 drv_compat_ctrl_get_resource_list (device_t dev,
-								   device_t child);
+				   device_t child);
 static int 
 drv_compat_ctrl_child_present (device_t dev,
-							   device_t child);
+			       device_t child);
 static int 
 drv_compat_ctrl_child_pnpinfo_str (device_t dev,
-								   device_t child,
-								   char *buf,
-								   size_t buflen);
+				   device_t child,
+				   char *buf,
+				   size_t buflen);
 static int 
-drv_compat_ctrl_child_location_str (device_t dev,
-									device_t child,
-									char *buf,
-									size_t buflen);
+drv_compat_ctrl_child_location_str	(device_t dev,
+					device_t child,
+					char *buf,
+					size_t buflen);
 static int 
-drv_compat_ctrl_config_intr (device_t dev,
-							 int irq,
-							 enum intr_trigger trig,
-							 enum intr_polarity pol);
+drv_compat_ctrl_config_intr	(device_t dev,
+				 int irq,
+				 enum intr_trigger trig,
+				 enum intr_polarity pol);
 static void
-drv_compat_ctrl_hinted_child (device_t dev,
-							  const char *dname,
-							  int dunit);
+drv_compat_ctrl_hinted_child	(device_t dev,
+				 const char *dname,
+				 int dunit);
 
 static device_method_t drv_compat_ctrl_methods[] = {
 	DEVMETHOD(device_probe,		drv_compat_ctrl_probe),
@@ -1889,7 +1938,7 @@
 	drv_compat_t drvc;
 	int level;
 
-	device_set_driver (dev, dl->driver);
+	device_set_driver (dev, drvc->driver);
 	if (DEVICE_PROBE(dev)<=0){
 		drvc = dev->driver;
 		level = drv_compat_flags2idx(drvc->flags);
@@ -2053,7 +2102,7 @@
 }
 
 static int
-device_add_to_dev_list (device_t addwhat, pdevice_list_t *addwhere){
+device_add_to_dev_list (device_t addwhat, pdevice_list_t *addwhere, int incr_refs){
 	pdevice *pd;
 	TAILQ_FOREACH (pd, addwhere, link){
 		if (pd->device_ptr == addwhat)
@@ -2066,7 +2115,8 @@
 
 	pd->device_ptr = addwhat;
 	TAILQ_INSERT_TAIL(addwhere, pd, link);
-	pd->device_ptr->refs++;
+	if (incr_refs)
+		pd->device_ptr->refs++;
 
 	bus_data_generation_update();
 	return (1);
@@ -2079,7 +2129,8 @@
  */
 int 
 device_add_existing_child (device_t dev, device_t child){
-	device_add_to_dev_list (child, &(dev->children));
+	device_add_to_dev_list (child, &(dev->children), TRUE);
+	device_add_to_dev_list (dev, &(child->parents), FALSE);
 }
 /**
  * @brief Add a new parent, which is a device, that already exists
@@ -2088,7 +2139,8 @@
  */
 int
 device_add_existing_parent (device_t dev, device_t parent){
-	device_add_to_dev_list (parent, &(dev->parents));
+	device_add_to_dev_list (parent, &(dev->parents), FALSE);
+	device_add_to_dev_list (dev, &(parent->children), TRUE);
 }
 
 
@@ -2149,6 +2201,8 @@
 	}
 	child->device_ptr->refs++;
 
+	device_add_existing_parent (child->device_ptr, dev);
+
 	bus_data_generation_update();
 	return (child);
 }
@@ -2162,27 +2216,32 @@
 	pdevice *grand;
 	pdevice *pd;
 	pdevice_list_t *list;
+	device_t child, parent;
 
 	PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
 	
+	if (direction==PARENTS)
+		return (destroy_recurse (devtodel, dev, CHILDREN));
+
 	/* remove children first */
-	list = (direction == CHILDREN) ? &devtodel->children : &devtodel->parents;
-	if (--devtodel->refs) goto deleteself;
-	while ( (grand = TAILQ_FIRST(list)) ) {
+	if (devtodel->refs>1) goto deletefromparents;
+	while ( (grand = TAILQ_FIRST(&devtodel->children)) ) {
 		error = destroy_recurse(devtodel, grand->device_ptr, direction);
 		if (error)
 			return (error);
+		TAILQ_REMOVE (&devtodel->children, grand, link)
 		free (grand);
 	}
 
-	if ((error = device_detach(devtodel)) != 0)
+/*!!!*/	if ((error = device_detach(devtodel)) != 0)
 		return (error);
 	if (devtodel->devclass)
 		devclass_delete_device(devtodel->devclass, devtodel);
-deletefromparent:
-	TAILQ_FOREACH_SAFE(pd, list, link){
-		if (pd->device_ptr == devtodel){
-			TAILQ_REMOVE(list, devtodel, link);
+deletefromparents:
+	TAILQ_FOREACH_SAFE(pd, &devtodel->parents, link){
+		if (pd->device_ptr == dev){
+			TAILQ_REMOVE(&devtodel->parents, pd, link);
+			devtodel->refs--;
 			free (pd);
 			break;
 		}
@@ -2205,7 +2264,7 @@
 }
 
 void
-device_add_existing_parent (device_t dev, device_t parent){
+device_delete_existing_parent (device_t dev, device_t parent){
 	destroy_recurse (dev, parent, PARENTS);
 }
 
@@ -2983,6 +3042,25 @@
 	return (error);
 }
 
+static int
+device_destroy_configuration (device_t dev){
+	int level, error;
+	pdrv_compat *pdrvc;
+
+	for (level = DRV_TOPMOST; level>= DRV_LOWEST; level--){
+		if (TAILQ_EMPTY(&(dev->drivers[level])))
+			continue;
+		while(pdrvc = TAILQ_FIRST(&(dev->drivers[level]))){
+			pdrvc->state = DS_RAW;
+			if(error = device_detach(dev))
+				return(error);
+			TAILQ_REMOVE(&(dev->drivers[level]), pdrvc, link);
+			free(pdrvc);
+
+		}
+	}
+}
+
 /**
  * @brief Set the driver of a device
  *
@@ -2994,30 +3072,42 @@
 device_set_driver(device_t dev, driver_t *driver) /*TODO*/
 {
 	drv_compat_t drvc; 
-	pdrv_compat *drvctmp;
+	pdrv_compat *pdrvc;
 	uint32_t flags;
 	int level;
 
 	if (dev->state >= DS_ATTACHED)
 		return (EBUSY);
 	
-	drvc = drv_compat_find_driver (driver);
+	if (driver != NULL){
+		drvc = drv_compat_find_driver (driver);
+
+		drv_compat_get_flags(driver, &flags);
+		level = drv_compat_flags2idx(flags);
 
-	TAILQ_FOREACH(drvctmp, &(dev->drivers[level]), link){
-		if (drvctmp->pdriver == drvc)
-			break;
+		TAILQ_FOREACH(pdrvc, &(dev->drivers[level]), link){
+			if (pdrvc->pdriver == drvc)
+				break;
+		}
+		if (pdrvc){
+			pdrvc->state = DS_RAW;
+			return (0);
+		}
 	}
 
-	if (!drvctmp){
-		
+	if(driver == NULL || level == DRV_LOWEST){
+		if(!device_destroy_configuration(dev))
+			return (EBUSY);
 	}
 
-	dev->driver = drvctmp;
-	dev->driver_level = level;
+	pdrvc = malloc (sizeof(struct pdrv_compat), M_BUS, M_NOWAIT|M_ZERO);
+	pdrvc->pdriver = drvc;
+	pdrvc->state = DS_RAW;
+	
+	TAILQ_INSERT_TAIL (&(dev->drivers[level]), pdrvc);
 
-	/*
-	if (dev->driver == driver)
-		return (0);
+	dev->driver = pdrvc;
+//	dev->driver_level = level;
 
 	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
 		free(dev->softc, M_BUS_SC);
@@ -3030,7 +3120,9 @@
 			if (!dev->softc) {
 				//kobj_delete((kobj_t) dev, 0);
 				//kobj_init((kobj_t) dev, &null_class);
-				dev->driver = NULL;
+				//dev->driver = NULL;
+				TAILQ_REMOVE(&(dev->drivers[level]), pdrvc, link);
+				free (pdrvc);
 				return (ENOMEM);
 			}
 		}
@@ -3141,9 +3233,10 @@
 	} else {
 		drvc = dev->driver;
 		dev->devclass = devclass_find (DRIVERNAME(drvc->driver));
-		level = drv_compat_flags2idx(drvc->flags);
-		TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
-		dev->driver = NULL;
+		//level = drv_compat_flags2idx(drvc->flags);
+		
+		//TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
+		//dev->driver = NULL;
 	}
 	dev->state = DS_ATTACHED;
 	devadded(dev);

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

@@ -47,6 +47,7 @@
  * @brief State of the device.
  */
 typedef enum device_state {
+	DS_RAW,
 	DS_NOTPRESENT,			/**< @brief not probed or probe failed */
 	DS_ALIVE,			/**< @brief probe succeeded */
 	DS_ATTACHED,			/**< @brief attach method called */


More information about the p4-projects mailing list