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