Date: Mon, 9 Jul 2007 16:44:29 GMT From: Maxim Zhuravlev <thioretic@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123211 for review Message-ID: <200707091644.l69GiT3g069018@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123211 Change 123211 by thioretic@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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707091644.l69GiT3g069018>