PERFORCE change 123130 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Sun Jul 8 14:35:40 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123130
Change 123130 by thioretic at thioretic on 2007/07/08 14:34:58
Some rethinking of api (eg. no initto in make_device);
Some logic stuff.
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl/TODO#10 edit
.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#8 edit
Differences ...
==== //depot/projects/soc2007/thioretic_gidl/TODO#10 (text+ko) ====
@@ -105,4 +105,22 @@
# 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.
- + # 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:
+ #
+ # driver_handler: make_dev() & attach_all_parents() & DEVICE_PROBE
+ # DEVICE_PROBE: driver_probe
+ # driver_probe: parents = get_all_parents()
+ # FOR_EACH (parent, parents){
+ # if (DEVICE_INFO (parent) == bad)
+ # detach_parent(parent)
+ # }
+ #
+ # here driver_handler & DEVICE_PROBE reside in subr_bus
+ # driver_probe resides in driver
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#8 (text+ko) ====
@@ -93,6 +93,7 @@
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(pdevice_list, pdevice) pdevice_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;
@@ -133,8 +134,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_list_t parents;
- device_list_t children; /**< list of child devices */
+ /*device_list_t*/ pdevice_list_t parents;
+ /*device_list_t*/ pdevice_list_t children; /**< list of child devices */
/*
* Details of this device.
@@ -163,11 +164,18 @@
u_char pad;
void *ivars; /**< instance variables */
void *softc; /**< current driver's variables */
+ u_long refs;
struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */
struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */
};
+struct pdevice {
+ device_t device_ptr;
+ TAILQ(pdevice) link;
+};
+
+
static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
@@ -1335,7 +1343,7 @@
dev = dc->devices[i];
if (/*dev->driver == driver*/
is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) &&
- (TAILQ_FIRST(&(dev->parent->devclass))) == busclass) {
+ (TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) {
if ((error = device_detach(dev)) != 0)
return (error);
device_set_driver(dev, NULL);
@@ -1411,7 +1419,7 @@
dev = dc->devices[i];
if (/*dev->driver == driver*/
is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents) &&
- (TAILQ_FIRST(&(dev->parent)))->devclass == busclass) {
+ (TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) {
if ((error = device_quiesce(dev)) != 0)
return (error);
}
@@ -1832,12 +1840,13 @@
* @returns the new device
*/
static device_t
-make_device(device_t parent, const char *name, int unit, driver_t *initto) /*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;
+ pdevice *pd;
PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
@@ -1856,26 +1865,30 @@
if (!dev)
return (NULL);
TAILQ_INIT(&(dev->parents));
- TAILQ_INSERT_TAIL(&(dev->parents), *parent, link)
+ pd = malloc(sizeof(struct pdevice), M_BUS, M_NOWAIT|M_ZERO);
+ pd->device_ptr = parent;
+ TAILQ_INSERT_TAIL(&(dev->parents), pd, 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]));
- if (initto){
+ /*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));
+ /* 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{
+ else{*/
dev->devclass = NULL;
dev->state = DS_NOTPRESENT;
- }
+ /*}*/
+
+ dev->refs = 0;
dev->unit = unit;
dev->nameunit = NULL;
dev->desc = NULL;
@@ -1965,19 +1978,22 @@
device_t
device_add_child_ordered(device_t dev, int order, const char *name, int unit)
{
- device_t child;
- device_t place;
+ /*device_t*/ pdevice *child;
+ /*device_t*/ pdevice *place;
PDEBUG(("%s at %s with order %d as unit %d",
name, DEVICENAME(dev), order, unit));
- child = make_device(dev, name, unit, NULL);
- if (child == NULL)
- return (child);
+ child = malloc (sizeof(pdevice), M_BUS, M_NOWAIT|M_ZERO);
+ child->device_ptr = make_device(dev, name, unit/*, NULL*/);
+ if (child->device_ptr == NULL){
+ free (child);
+ return (NULL);
+ }
child->order = order;
TAILQ_FOREACH(place, &dev->children, link) {
- if (place->order > order)
+ if (place->device_ptr->order > order)
break;
}
@@ -1994,6 +2010,7 @@
*/
TAILQ_INSERT_TAIL(&dev->children, child, link);
}
+ child->device_ptr->refs++;
bus_data_generation_update();
return (child);
@@ -2013,39 +2030,54 @@
* @retval non-zero a unit error code describing the error
*/
int
-device_delete_child(device_t dev, device_t child)
+device_delete_child(device_t dev, device_t child) /*TODO*/
{
int error;
- device_t grandchild;
+ /*device_t*/ pdevice *grandchild;
+ pdevice *pd;
PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
-
+
+ child->refs--;
+ if (child->refs) goto deletefromparent;
/* remove children first */
while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
- error = device_delete_child(child, grandchild);
+ error = device_delete_child(child, grandchild->device_ptr);
if (error)
return (error);
+ free (grandchild);
}
if ((error = device_detach(child)) != 0)
return (error);
if (child->devclass)
devclass_delete_device(child->devclass, child);
- TAILQ_REMOVE(&dev->children, child, link);
+deletefromparent:
+ TAILQ_FOREACH_SAFE(pd, &dev->children, link){
+ if (pd->device_ptr == child){
+ TAILQ_REMOVE(&dev->children, child, link);
+ free (pd);
+ break;
+ }
+ }
+
+ if (child->refs)
+ return (0);
+
TAILQ_REMOVE(&bus_data_devices, child, devlink);
kobj_delete((kobj_t) child, M_BUS);
-
+
bus_data_generation_update();
return (0);
}
static int
is_device_parent (device_t dev, device_t child){
- device_t dc;
+ pdevice *dc;
TAILQ_FOREACH (dc, &(child->parents), link){
- if (dc == dev) return (1);
+ if (dc->device_ptr == dev) return (TRUE);
}
- return (0);
+ return (FALSE);
}
/**
@@ -2263,8 +2295,11 @@
device_t
device_get_parent(device_t dev) /*TODO*/
{
- if (!TAILQ_EMPTY(&(dev->parents)))
- return (TAILQ_FIRST(&(dev->parents)));
+ pdevice *pd;
+ if (!TAILQ_EMPTY(&(dev->parents))){
+ pd = TAILQ_FIRST(&(dev->parents));
+ return (pd->device_ptr);
+ }
return (NULL);
}
@@ -2288,7 +2323,7 @@
device_get_children(device_t dev, device_t **devlistp, int *devcountp)
{
int count;
- device_t child;
+ /*device_t*/ pdevice *child;
device_t *list;
count = 0;
@@ -2302,7 +2337,7 @@
count = 0;
TAILQ_FOREACH(child, &dev->children, link) {
- list[count] = child;
+ list[count] = child->device_ptr;
count++;
}
@@ -2584,12 +2619,12 @@
void
device_busy(device_t dev)
{
- device_t parent;
+ pdevice *parent;
if (dev->state < DS_ATTACHED)
panic("device_busy: called for unattached device");
if (dev->busy == 0 && !TAILQ_EMPTY(&(dev->parents))){
TAILQ_FOREACH (parent, &(dev->parents), link){
- device_busy(parent);
+ device_busy(parent->device_ptr);
}
}
dev->busy++;
@@ -2602,6 +2637,7 @@
void
device_unbusy(device_t dev)
{
+ pdevice *parent;
if (dev->state != DS_BUSY)
panic("device_unbusy: called for non-busy device %s",
device_get_nameunit(dev));
@@ -2609,7 +2645,7 @@
if (dev->busy == 0) {
if (/*dev->parent*/!TAILQ_EMPTY(&(dev->parents))){
TAILQ_FOREACH (parent, &(dev->parents), link){
- device_unbusy(parent);
+ device_unbusy(parent->device_ptr);
}
}
//device_unbusy(dev->parent);
@@ -2713,6 +2749,8 @@
int
device_set_driver(device_t dev, driver_t *driver)
{
+ drv_compat_t drvc;
+
if (dev->state >= DS_ATTACHED)
return (EBUSY);
@@ -2723,23 +2761,26 @@
free(dev->softc, M_BUS_SC);
dev->softc = NULL;
}
- kobj_delete((kobj_t) dev, 0);
- dev->driver = driver;
+ //kobj_delete((kobj_t) dev, 0);
+ dev->driver = drvc = drv_compat_find_driver (driver);
if (driver) {
- kobj_init((kobj_t) dev, (kobj_class_t) 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);
if (!dev->softc) {
- kobj_delete((kobj_t) dev, 0);
- kobj_init((kobj_t) dev, &null_class);
+ //kobj_delete((kobj_t) dev, 0);
+ //kobj_init((kobj_t) dev, &null_class);
dev->driver = NULL;
return (ENOMEM);
}
}
- } else {
+ } /*else {
kobj_init((kobj_t) dev, &null_class);
- }
+ }*/
bus_data_generation_update();
return (0);
@@ -2824,12 +2865,13 @@
device_attach(device_t dev)
{
int error;
- device_t parent;
+ pdevice *pd;
+ drv_compat_t drvc;
device_sysctl_init(dev);
if (!device_is_quiet(dev)){
- TAILQ_FOREACH (parent, &(dev->parents), link){
- device_print_child(parent, dev);
+ TAILQ_FOREACH (pd, &(dev->parents), link){
+ device_print_child(pd->device_ptr, dev);
}
}
if ((error = DEVICE_ATTACH(dev)) != 0) {
@@ -2842,6 +2884,12 @@
device_sysctl_fini(dev);
dev->state = DS_NOTPRESENT;
return (error);
+ } 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);
+ driver = NULL;
}
dev->state = DS_ATTACHED;
devadded(dev);
@@ -2868,7 +2916,7 @@
device_detach(device_t dev)
{
int error;
- device_t parent;
+ pdevice *pd;
GIANT_REQUIRED;
@@ -2882,9 +2930,9 @@
return (error);
devremoved(dev);
device_printf(dev, "detached\n");
- if (!TAILQ_EMPTY(&(dev->parent))){
- TAILQ_FOREACH (parent, &(dev->parents), link){
- BUS_CHILD_DETACHED(parent, dev);
+ if (!TAILQ_EMPTY(&(dev->parents))){
+ TAILQ_FOREACH (pd, &(dev->parents), link){
+ BUS_CHILD_DETACHED(pd->device_ptr, dev);
}
}
@@ -3338,10 +3386,10 @@
int
bus_generic_attach(device_t dev)
{
- device_t child;
+ /*device_t*/ pdevice *child;
TAILQ_FOREACH(child, &dev->children, link) {
- device_probe_and_attach(child);
+ device_probe_and_attach(child->device_ptr);
}
return (0);
@@ -4112,7 +4160,7 @@
case MOD_LOAD:
TAILQ_INIT(&bus_data_devices);
kobj_class_compile((kobj_class_t) &root_driver);
- root_bus = make_device(NULL, "root", 0, NULL);
+ 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;
@@ -4221,6 +4269,7 @@
kobj_class_t driver;
char* parents[];
int count=0, isfilter;
+ device_t dev;
dmd = (struct driver_module_data *)arg;
drv_intnl = dmd->dmd_driver;
@@ -4278,7 +4327,17 @@
}
if(drv_intnl->flags & DR_REQDEV){ /*restrict to DR_LOWEST? */
- make_device (root_bus, DRIVERNAME(driver), -1, driver);
+ dev = make_device (root_bus, DRIVERNAME(driver), -1/*, driver*/);
+ device_set_driver(dev, driver);
+ /*if (!hasclass)*/
+ device_set_devclass(child, dl->driver->name);
+
+ /* Fetch any flags for the device before probing.
+ resource_int_value(dl->driver->name, child->unit,
+ "flags", &child->devflags);
+ */
+
+ result = DEVICE_PROBE(dev);
/* todo: set all parents for device
* parents are all devices (alive) in parent
* devclasses
More information about the p4-projects
mailing list