Diff for /src/sys/kern/subr_bus.c between versions 1.16 and 1.17

version 1.16, 2004/04/01 08:41:24 version 1.17, 2004/04/15 13:31:41
Line 107  DEFINE_CLASS(null, null_methods, 0); Line 107  DEFINE_CLASS(null, null_methods, 0);
 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);  static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
   
 static devclass_t  static devclass_t
devclass_find_internal(const char *classname, int create)devclass_find_internal(const char *classname, const char *parentname,
                        int create)
 {  {
         devclass_t dc;          devclass_t dc;
   
Line 117  devclass_find_internal(const char *class Line 118  devclass_find_internal(const char *class
   
         TAILQ_FOREACH(dc, &devclasses, link)          TAILQ_FOREACH(dc, &devclasses, link)
                 if (!strcmp(dc->name, classname))                  if (!strcmp(dc->name, classname))
                        return(dc);                        break;
   
        PDEBUG(("%s not found%s", classname, (create? ", creating": "")));        if (create && !dc) {
        if (create) {                PDEBUG(("creating %s", classname));
                 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,                  dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
                             M_BUS, M_INTWAIT | M_ZERO);                              M_BUS, M_INTWAIT | M_ZERO);
                 if (!dc)                  if (!dc)
                        return NULL;                        return(NULL);
                 dc->parent = NULL;
                 dc->name = (char*) (dc + 1);                  dc->name = (char*) (dc + 1);
                 strcpy(dc->name, classname);                  strcpy(dc->name, classname);
                 dc->devices = NULL;                  dc->devices = NULL;
Line 132  devclass_find_internal(const char *class Line 134  devclass_find_internal(const char *class
                 TAILQ_INIT(&dc->drivers);                  TAILQ_INIT(&dc->drivers);
                 TAILQ_INSERT_TAIL(&devclasses, dc, link);                  TAILQ_INSERT_TAIL(&devclasses, dc, link);
         }          }
           if (parentname && dc && !dc->parent)
                   dc->parent = devclass_find_internal(parentname, NULL, FALSE);
   
         return(dc);          return(dc);
 }  }
Line 139  devclass_find_internal(const char *class Line 143  devclass_find_internal(const char *class
 devclass_t  devclass_t
 devclass_create(const char *classname)  devclass_create(const char *classname)
 {  {
        return(devclass_find_internal(classname, TRUE));        return(devclass_find_internal(classname, NULL, TRUE));
 }  }
   
 devclass_t  devclass_t
 devclass_find(const char *classname)  devclass_find(const char *classname)
 {  {
        return(devclass_find_internal(classname, FALSE));        return(devclass_find_internal(classname, NULL, FALSE));
 }  }
   
 int  int
Line 171  devclass_add_driver(devclass_t dc, drive Line 175  devclass_add_driver(devclass_t dc, drive
         /*          /*
          * Make sure the devclass which the driver is implementing exists.           * Make sure the devclass which the driver is implementing exists.
          */           */
        devclass_find_internal(driver->name, TRUE);        devclass_find_internal(driver->name, NULL, TRUE);
   
         dl->driver = driver;          dl->driver = driver;
         TAILQ_INSERT_TAIL(&dc->drivers, dl, link);          TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
Line 256  devclass_find_driver_internal(devclass_t Line 260  devclass_find_driver_internal(devclass_t
         return(NULL);          return(NULL);
 }  }
   
driver_t *kobj_class_t
 devclass_find_driver(devclass_t dc, const char *classname)  devclass_find_driver(devclass_t dc, const char *classname)
 {  {
         driverlink_t dl;          driverlink_t dl;
Line 329  devclass_get_maxunit(devclass_t dc) Line 333  devclass_get_maxunit(devclass_t dc)
         return(dc->maxunit);          return(dc->maxunit);
 }  }
   
   void
   devclass_set_parent(devclass_t dc, devclass_t pdc)
   {
           dc->parent = pdc;
   }
   
   devclass_t
   devclass_get_parent(devclass_t dc)
   {
           return(dc->parent);
   }
   
 static int  static int
 devclass_alloc_unit(devclass_t dc, int *unitp)  devclass_alloc_unit(devclass_t dc, int *unitp)
 {  {
Line 441  make_device(device_t parent, const char Line 457  make_device(device_t parent, const char
         PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));          PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
   
         if (name != NULL) {          if (name != NULL) {
                dc = devclass_find_internal(name, TRUE);                dc = devclass_find_internal(name, NULL, TRUE);
                 if (!dc) {                  if (!dc) {
                         printf("make_device: can't find device class %s\n", name);                          printf("make_device: can't find device class %s\n", name);
                         return(NULL);                          return(NULL);
Line 619  device_probe_child(device_t dev, device_ Line 635  device_probe_child(device_t dev, device_
         if (child->state == DS_ALIVE)          if (child->state == DS_ALIVE)
                 return(0);                  return(0);
   
        for (dl = first_matching_driver(dc, child); dl;        for (; dc; dc = dc->parent) {
             dl = next_matching_driver(dc, child, dl)) {                for (dl = first_matching_driver(dc, child); dl;
                PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));                     dl = next_matching_driver(dc, child, dl)) {
                device_set_driver(child, dl->driver);                        PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
                if (!hasclass)                        device_set_driver(child, dl->driver);
                        device_set_devclass(child, dl->driver->name);                        if (!hasclass)
                result = DEVICE_PROBE(child);                                device_set_devclass(child, dl->driver->name);
                if (!hasclass)                        result = DEVICE_PROBE(child);
                        device_set_devclass(child, 0);                        if (!hasclass)
                                 device_set_devclass(child, 0);
   
                /*                        /*
                 * If the driver returns SUCCESS, there can be no higher match                         * If the driver returns SUCCESS, there can be
                 * for this device.                         * no higher match for this device.
                 */                         */
                if (result == 0) {                        if (result == 0) {
                        best = dl;                                best = dl;
                        pri = 0;                                pri = 0;
                        break;                                break;
                }                        }
   
                /*                        /*
                 * The driver returned an error so it certainly doesn't match.                         * The driver returned an error so it
                 */                         * certainly doesn't match.
                if (result > 0) {                         */
                        device_set_driver(child, 0);                        if (result > 0) {
                        continue;                                device_set_driver(child, 0);
                }                                continue;
                         }
   
                           /*
                            * A priority lower than SUCCESS, remember the
                            * best matching driver. Initialise the value
                            * of pri for the first match.
                            */
                           if (best == 0 || result > pri) {
                                   best = dl;
                                   pri = result;
                                   continue;
                           }
                   }
                 /*                  /*
                 * A priority lower than SUCCESS, remember the best matching                 * If we have unambiguous match in this devclass,
                 * driver. Initialise the value of pri for the first match.                 * don't look in the parent.
                 */                 */
                if (best == 0 || result > pri) {                if (best && pri == 0)
                        best = dl;                        break;
                        pri = result; 
                        continue; 
                } 
         }          }
   
         /*          /*
Line 959  device_set_devclass(device_t dev, const Line 985  device_set_devclass(device_t dev, const
                 return(EINVAL);                  return(EINVAL);
         }          }
   
        dc = devclass_find_internal(classname, TRUE);        dc = devclass_find_internal(classname, NULL, TRUE);
         if (!dc)          if (!dc)
                 return(ENOMEM);                  return(ENOMEM);
   
Line 2254  root_bus_module_handler(module_t mod, in Line 2280  root_bus_module_handler(module_t mod, in
                 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);                  kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
                 root_bus->driver = &root_driver;                  root_bus->driver = &root_driver;
                 root_bus->state = DS_ATTACHED;                  root_bus->state = DS_ATTACHED;
                root_devclass = devclass_find_internal("root", FALSE);                root_devclass = devclass_find_internal("root", NULL, FALSE);
                 return(0);                  return(0);
   
         case MOD_SHUTDOWN:          case MOD_SHUTDOWN:
Line 2286  root_bus_configure(void) Line 2312  root_bus_configure(void)
 int  int
 driver_module_handler(module_t mod, int what, void *arg)  driver_module_handler(module_t mod, int what, void *arg)
 {  {
        int error, i;        int error;
         struct driver_module_data *dmd;          struct driver_module_data *dmd;
         devclass_t bus_devclass;          devclass_t bus_devclass;
           kobj_class_t driver;
           const char *parentname;
   
         dmd = (struct driver_module_data *)arg;          dmd = (struct driver_module_data *)arg;
        bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE);        bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
         error = 0;          error = 0;
   
         switch (what) {          switch (what) {
Line 2299  driver_module_handler(module_t mod, int Line 2327  driver_module_handler(module_t mod, int
                 if (dmd->dmd_chainevh)                  if (dmd->dmd_chainevh)
                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);                          error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
   
                for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {                driver = dmd->dmd_driver;
                        PDEBUG(("Loading module: driver %s on bus %s",                PDEBUG(("Loading module: driver %s on bus %s",
                                DRIVERNAME(dmd->dmd_drivers[i]),                         DRIVERNAME(driver), dmd->dmd_busname));
                                dmd->dmd_busname));                error = devclass_add_driver(bus_devclass, driver);
                        error = devclass_add_driver(bus_devclass, 
                                                    dmd->dmd_drivers[i]); 
                } 
                 if (error)                  if (error)
                         break;                          break;
   
                 /*                  /*
                 * The drivers loaded in this way are assumed to all                 * If the driver has any base classes, make the
                 * implement the same devclass.                 * devclass inherit from the devclass of the driver's
                  * first base class. This will allow the system to
                  * search for drivers in both devclasses for children
                  * of a device using this driver.
                  */                   */
                *dmd->dmd_devclass =                if (driver->baseclasses)
                        devclass_find_internal(dmd->dmd_drivers[0]->name,                        parentname = driver->baseclasses[0]->name;
                                               TRUE);                else
                         parentname = NULL;
                 *dmd->dmd_devclass = devclass_find_internal(driver->name,
                                                             parentname, TRUE);
                 break;                  break;
   
         case MOD_UNLOAD:          case MOD_UNLOAD:
                for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {                PDEBUG(("Unloading module: driver %s from bus %s",
                        PDEBUG(("Unloading module: driver %s from bus %s",                        DRIVERNAME(dmd->dmd_driver), dmd->dmd_busname));
                                DRIVERNAME(dmd->dmd_drivers[i]),                 error = devclass_delete_driver(bus_devclass, dmd->dmd_driver);
                                dmd->dmd_busname)); 
                        error = devclass_delete_driver(bus_devclass, 
                                                       dmd->dmd_drivers[i]); 
                } 
   
                 if (!error && dmd->dmd_chainevh)                  if (!error && dmd->dmd_chainevh)
                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);                          error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);

Removed from v.1.16  
changed lines
  Added in v.1.17