[BACK]Return to subr_autoconf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/subr_autoconf.c between version 1.62 and 1.62.6.1

version 1.62, 2002/02/15 11:18:26 version 1.62.6.1, 2002/03/22 18:29:52
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/kernel.h>  #include <sys/kernel.h>
 #include <sys/errno.h>  #include <sys/errno.h>
 #include <sys/proc.h>  #include <sys/proc.h>
   #include <sys/properties.h>
 #include <machine/limits.h>  #include <machine/limits.h>
   
 #include "opt_userconf.h"  #include "opt_userconf.h"
Line 104  __KERNEL_RCSID(0, "$NetBSD$");
Line 105  __KERNEL_RCSID(0, "$NetBSD$");
  * Autoconfiguration subroutines.   * Autoconfiguration subroutines.
  */   */
   
   static struct device *dev_create(struct device *, ssize_t, int);
   
 /*  /*
  * ioconf.c exports exactly two names: cfdata and cfroots.  All system   * ioconf.c exports exactly two names: cfdata and cfroots.  All system
  * devices and drivers are found via these tables.   * devices and drivers are found via these tables.
Line 122  struct matchinfo {
Line 125  struct matchinfo {
 };  };
   
 static char *number(char *, int);  static char *number(char *, int);
 static void mapply(struct matchinfo *, struct cfdata *);  static void mapply(struct matchinfo *, struct cfdata *, struct device *);
   static void locset(struct device *, struct cfdata *);
   static void locrm(struct device *, struct cfdata *);
   
 struct deferred_config {  struct deferred_config {
         TAILQ_ENTRY(deferred_config) dc_queue;          TAILQ_ENTRY(deferred_config) dc_queue;
Line 146  struct evcntlist allevents = TAILQ_HEAD_
Line 151  struct evcntlist allevents = TAILQ_HEAD_
   
 __volatile int config_pending;          /* semaphore for mountroot */  __volatile int config_pending;          /* semaphore for mountroot */
   
   /* device properties database */
   static propdb_t devpropdb;
   
 /*  /*
  * Configure the system's hardware.   * Configure the system's hardware.
  */   */
Line 157  configure(void)
Line 165  configure(void)
         TAILQ_INIT(&interrupt_config_queue);          TAILQ_INIT(&interrupt_config_queue);
         TAILQ_INIT(&alldevs);          TAILQ_INIT(&alldevs);
   
           devpropdb = propdb_create("devprop");
   
 #ifdef USERCONF  #ifdef USERCONF
         if (boothowto & RB_USERCONF)          if (boothowto & RB_USERCONF)
                 user_config();                  user_config();
Line 186  configure(void)
Line 196  configure(void)
 }  }
   
 /*  /*
    * Set locators as properties on device node.
    */
   static void
   locset(struct device *d, struct cfdata *cf)
   {
           int i;
           int type = PROP_CONST|PROP_INT;
           char buf[32];
   
           for (i=0; cf->cf_locnames[i]; i++) {
                   sprintf(buf, "loc-%s", cf->cf_locnames[i]);
                   dev_setprop(d, buf, &cf->cf_loc[i],
                               sizeof(int), type, (!cold));
           }
   }
   
   /*
    * Remove locator properties from device node.
    */
   static void
   locrm(struct device *d, struct cfdata *cf)
   {
           int i;
           char buf[32];
   
           for (i=0; cf->cf_locnames[i]; i++) {
                   sprintf(buf, "loc-%s", cf->cf_locnames[i]);
                   dev_delprop(d, buf);
           }
   }
   
   /*
  * Apply the matching function and choose the best.  This is used   * Apply the matching function and choose the best.  This is used
  * a few times and we want to keep the code small.   * a few times and we want to keep the code small.
  */   */
 static void  static void
 mapply(struct matchinfo *m, struct cfdata *cf)  mapply(struct matchinfo *m, struct cfdata *cf, struct device *child)
 {  {
         int pri;          int pri;
           void *aux = m->aux;
   
           if ((ssize_t)cf->cf_attach->ca_devsize < 0) {
                   /* New-style device driver */
                   if (!child)
                           panic("mapply: no device for new-style driver\n");
                   locset(child, cf);
                   child->dv_private = aux;
                   aux = child;
           }
         if (m->fn != NULL)          if (m->fn != NULL)
                   /* Someday the submatch function should use properties too. */
                 pri = (*m->fn)(m->parent, cf, m->aux);                  pri = (*m->fn)(m->parent, cf, m->aux);
         else {          else {
                 if (cf->cf_attach->ca_match == NULL) {                  if (cf->cf_attach->ca_match == NULL) {
                         panic("mapply: no match function for '%s' device\n",                          panic("mapply: no match function for '%s' device\n",
                             cf->cf_driver->cd_name);                              cf->cf_driver->cd_name);
                 }                  }
                 pri = (*cf->cf_attach->ca_match)(m->parent, cf, m->aux);                  pri = (*cf->cf_attach->ca_match)(m->parent, cf, aux);
         }          }
         if (pri > m->pri) {          if (pri > m->pri) {
                 m->match = cf;                  m->match = cf;
                 m->pri = pri;                  m->pri = pri;
         }          }
           if (child) {
                   locrm(child, cf);
                   child->dv_private = NULL;
           }
 }  }
   
 /*  /*
Line 221  mapply(struct matchinfo *m, struct cfdat
Line 277  mapply(struct matchinfo *m, struct cfdat
  * can be ignored).   * can be ignored).
  */   */
 struct cfdata *  struct cfdata *
 config_search(cfmatch_t fn, struct device *parent, void *aux)  config_search_ad(cfmatch_t fn, struct device *parent, void *aux,
                    struct device *child)
 {  {
         struct cfdata *cf;          struct cfdata *cf;
         short *p;          short *p;
Line 232  config_search(cfmatch_t fn, struct devic
Line 289  config_search(cfmatch_t fn, struct devic
         m.aux = aux;          m.aux = aux;
         m.match = NULL;          m.match = NULL;
         m.pri = 0;          m.pri = 0;
   
         for (cf = cfdata; cf->cf_driver; cf++) {          for (cf = cfdata; cf->cf_driver; cf++) {
                 /*                  /*
                  * Skip cf if no longer eligible, otherwise scan through                   * Skip cf if no longer eligible, otherwise scan through
Line 241  config_search(cfmatch_t fn, struct devic
Line 299  config_search(cfmatch_t fn, struct devic
                         continue;                          continue;
                 for (p = cf->cf_parents; *p >= 0; p++)                  for (p = cf->cf_parents; *p >= 0; p++)
                         if (parent->dv_cfdata == &cfdata[*p])                          if (parent->dv_cfdata == &cfdata[*p])
                                 mapply(&m, cf);                                  mapply(&m, cf, child);
         }          }
         return (m.match);          return (m.match);
 }  }
Line 251  config_search(cfmatch_t fn, struct devic
Line 309  config_search(cfmatch_t fn, struct devic
  * This is much like config_search, but there is no parent.   * This is much like config_search, but there is no parent.
  */   */
 struct cfdata *  struct cfdata *
 config_rootsearch(cfmatch_t fn, const char *rootname, void *aux)  config_rootsearch_ad(cfmatch_t fn, const char *rootname, void *aux,
                        struct device *root)
 {  {
         struct cfdata *cf;          struct cfdata *cf;
         short *p;          short *p;
Line 270  config_rootsearch(cfmatch_t fn, const ch
Line 329  config_rootsearch(cfmatch_t fn, const ch
         for (p = cfroots; *p >= 0; p++) {          for (p = cfroots; *p >= 0; p++) {
                 cf = &cfdata[*p];                  cf = &cfdata[*p];
                 if (strcmp(cf->cf_driver->cd_name, rootname) == 0)                  if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
                         mapply(&m, cf);                          mapply(&m, cf, root);
         }          }
         return (m.match);          return (m.match);
 }  }
Line 286  static const char *msgs[3] = { "", " not
Line 345  static const char *msgs[3] = { "", " not
  * not configured, call the given `print' function and return 0.   * not configured, call the given `print' function and return 0.
  */   */
 struct device *  struct device *
 config_found_sm(struct device *parent, void *aux, cfprint_t print,  config_found_sad(struct device *parent, void *aux, cfprint_t print,
     cfmatch_t submatch)      cfmatch_t submatch, struct device *d)
 {  {
         struct cfdata *cf;          struct cfdata *cf;
   
         if ((cf = config_search(submatch, parent, aux)) != NULL)          /*
                 return (config_attach(parent, cf, aux, print));           * Creating the dummy device here is really optional.  But
            * it allows old-style bus drivers to attach new-style children.
            */
           if (!d) d = dev_create(ROOT, 0, cold ? M_NOWAIT : M_WAITOK);
           if ((cf = config_search_ad(submatch, parent, aux, d)) != NULL)
                   return (config_attach_ad(parent, cf, aux, print, d));
         if (print)          if (print)
                 printf("%s", msgs[(*print)(aux, parent->dv_xname)]);                  printf("%s", msgs[(*print)(aux, parent->dv_xname)]);
         return (NULL);          return (NULL);
Line 305  struct device *
Line 369  struct device *
 config_rootfound(const char *rootname, void *aux)  config_rootfound(const char *rootname, void *aux)
 {  {
         struct cfdata *cf;          struct cfdata *cf;
           struct device *root;
   
         if ((cf = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)          root = dev_create(ROOT, 0, cold ? M_NOWAIT : M_WAITOK);
                 return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));          if ((cf = config_rootsearch_ad((cfmatch_t)NULL, rootname, aux, root)) != NULL)
                   return (config_attach_ad(ROOT, cf, aux, (cfprint_t)NULL, root));
         printf("root device %s not configured\n", rootname);          printf("root device %s not configured\n", rootname);
         return (NULL);          return (NULL);
 }  }
Line 327  number(char *ep, int n)
Line 393  number(char *ep, int n)
 }  }
   
 /*  /*
    * Allocate an empty device node.  If `parent' is provided then the
    * new node is attached to the tree under `parent'.  If `size'
    * is provided, then the new device node is allocated to be that
    * size.
    */
   static struct device *
   dev_create(struct device *parent, ssize_t size, int wait) {
           struct device * dev;
   
           /* get memory for all device vars */
           if (size == 0)
                   size = sizeof(struct device);
           dev = (struct device *)malloc(size, M_DEVBUF, wait);
           if (!dev)
               panic("dev_create: memory allocation for device failed");
           memset(dev, 0, size);
           TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */
           dev->dv_class = DV_EMPTY;
           if (parent)
                   dev->dv_parent = parent;
           return (dev);
   }
   
   /*
  * Expand the size of the cd_devs array if necessary.   * Expand the size of the cd_devs array if necessary.
  */   */
 void  void
Line 366  config_makeroom(int n, struct cfdriver *
Line 456  config_makeroom(int n, struct cfdriver *
  * Attach a found device.  Allocates memory for device variables.   * Attach a found device.  Allocates memory for device variables.
  */   */
 struct device *  struct device *
 config_attach(struct device *parent, struct cfdata *cf, void *aux,  config_attach_ad(struct device *parent, struct cfdata *cf, void *aux,
         cfprint_t print)          cfprint_t print, struct device *propdev)
 {  {
         struct device *dev;          struct device *dev;
         struct cfdriver *cd;          struct cfdriver *cd;
         struct cfattach *ca;          struct cfattach *ca;
         size_t lname, lunit;          size_t lname, lunit;
           ssize_t softsize;
         const char *xunit;          const char *xunit;
         int myunit;          int myunit;
         char num[10];          char num[10];
   
         cd = cf->cf_driver;          cd = cf->cf_driver;
         ca = cf->cf_attach;          ca = cf->cf_attach;
         if (ca->ca_devsize < sizeof(struct device))          softsize = ca->ca_devsize;
                 panic("config_attach");  
 #ifndef __BROKEN_CONFIG_UNIT_USAGE  #ifndef __BROKEN_CONFIG_UNIT_USAGE
         if (cf->cf_fstate == FSTATE_STAR) {          if (cf->cf_fstate == FSTATE_STAR) {
                 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)                  for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
Line 410  config_attach(struct device *parent, str
Line 501  config_attach(struct device *parent, str
                 panic("config_attach: device name too long");                  panic("config_attach: device name too long");
   
         /* get memory for all device vars */          /* get memory for all device vars */
         dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF,          if (softsize < 0) {
             cold ? M_NOWAIT : M_WAITOK);                  /* New-style device */
         if (!dev)                  if (propdev) {
             panic("config_attach: memory allocation for device softc failed");                          /* Great, we can use the propdev. */
         memset(dev, 0, ca->ca_devsize);                          dev = propdev;
         TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */                  } else {
                           dev = dev_create(parent, 0, cold ? M_NOWAIT : M_WAITOK);
                           if (!dev)
                                   panic("config_attach: memory allocation for device failed");
                   }
                   if (softsize < 0) softsize = -softsize;
                   if (softsize < sizeof(struct device)) panic("config_attach");
                   dev->dv_private = malloc(softsize, M_DEVBUF,
                                            cold ? M_NOWAIT : M_WAITOK);
                   if (!dev->dv_private)
                           panic("config_attach: memory allocation for device softc failed");
                   memset(dev->dv_private, 0, softsize);
                   dev->dv_flags |= DVF_SOFTC;
           } else {
                   dev = (struct device *)malloc(softsize, M_DEVBUF,
                                                 cold ? M_NOWAIT : M_WAITOK);
                   if (!dev)
                           panic("config_attach: memory allocation for device softc failed");
                   memset(dev, 0, softsize);
                   TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */
                   dev->dv_private = dev;          /* Point private to ourself... */
           }
         dev->dv_class = cd->cd_class;          dev->dv_class = cd->cd_class;
         dev->dv_cfdata = cf;          dev->dv_cfdata = cf;
         dev->dv_unit = myunit;          dev->dv_unit = myunit;
         memcpy(dev->dv_xname, cd->cd_name, lname);          memcpy(dev->dv_xname, cd->cd_name, lname);
         memcpy(dev->dv_xname + lname, xunit, lunit);          memcpy(dev->dv_xname + lname, xunit, lunit);
         dev->dv_parent = parent;          dev->dv_parent = parent;
         dev->dv_flags = DVF_ACTIVE;     /* always initially active */          dev->dv_flags |= DVF_ACTIVE;    /* always initially active */
           if (propdev && propdev != dev) {
                   /* Inherit (steal) properties from dummy device */
                   dev_copyprops(propdev, dev, (!cold));
                   dev_delprop(propdev, NULL);
                   /* destroy propdev */
                   config_detach(propdev, 0);
           }
   
         if (parent == ROOT)          if (parent == ROOT)
                 printf("%s (root)", dev->dv_xname);                  printf("%s (root)", dev->dv_xname);
Line 482  config_detach(struct device *dev, int fl
Line 601  config_detach(struct device *dev, int fl
 #endif  #endif
         int rv = 0, i;          int rv = 0, i;
   
           if (dev->dv_class == DV_EMPTY) {
                   /*
                    * The device is a dummy that never fully attached.
                    * Simply remove it from the global list and free it.
                    */
                   TAILQ_REMOVE(&alldevs, dev, dv_list);
                   dev_delprop(dev, NULL);
                   if (dev->dv_flags & DVF_SOFTC)
                           /* Separately allocated softc */
                           free(dev->dv_private, M_DEVBUF);
                   free(dev, M_DEVBUF);
                   return (0);
           }
   
         cf = dev->dv_cfdata;          cf = dev->dv_cfdata;
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
         if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)          if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
Line 489  config_detach(struct device *dev, int fl
Line 622  config_detach(struct device *dev, int fl
 #endif  #endif
         ca = cf->cf_attach;          ca = cf->cf_attach;
         cd = cf->cf_driver;          cd = cf->cf_driver;
   
         /*          /*
          * Ensure the device is deactivated.  If the device doesn't           * Ensure the device is deactivated.  If the device doesn't
          * have an activation entry point, we allow DVF_ACTIVE to           * have an activation entry point, we allow DVF_ACTIVE to
Line 498  config_detach(struct device *dev, int fl
Line 631  config_detach(struct device *dev, int fl
          */           */
         if (ca->ca_activate != NULL)          if (ca->ca_activate != NULL)
                 rv = config_deactivate(dev);                  rv = config_deactivate(dev);
   
         /*          /*
          * Try to detach the device.  If that's not possible, then           * Try to detach the device.  If that's not possible, then
          * we either panic() (for the forced but failed case), or           * we either panic() (for the forced but failed case), or
Line 515  config_detach(struct device *dev, int fl
Line 648  config_detach(struct device *dev, int fl
                         return (rv);                          return (rv);
                 else                  else
                         panic("config_detach: forced detach of %s failed (%d)",                          panic("config_detach: forced detach of %s failed (%d)",
                             dev->dv_xname, rv);                                dev->dv_xname, rv);
         }          }
   
         /*          /*
          * The device has now been successfully detached.           * The device has now been successfully detached.
          */           */
   
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
         /*          /*
          * Sanity: If you're successfully detached, you should have no           * Sanity: If you're successfully detached, you should have no
Line 530  config_detach(struct device *dev, int fl
Line 663  config_detach(struct device *dev, int fl
          * the list.)           * the list.)
          */           */
         for (d = TAILQ_NEXT(dev, dv_list); d != NULL;          for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
             d = TAILQ_NEXT(d, dv_list)) {               d = TAILQ_NEXT(d, dv_list)) {
                 if (d->dv_parent == dev) {                  if (d->dv_parent == dev) {
                         printf("config_detach: detached device %s"                          printf("config_detach: detached device %s"
                             " has children %s\n", dev->dv_xname, d->dv_xname);                                 " has children %s\n", dev->dv_xname, d->dv_xname);
                         panic("config_detach");                          panic("config_detach");
                 }                  }
         }          }
 #endif  #endif
   
         /*          /*
          * Mark cfdata to show that the unit can be reused, if possible.           * Mark cfdata to show that the unit can be reused, if possible.
          */           */
Line 569  config_detach(struct device *dev, int fl
Line 702  config_detach(struct device *dev, int fl
         /*          /*
          * Remove from cfdriver's array, tell the world, and free softc.           * Remove from cfdriver's array, tell the world, and free softc.
          */           */
         cd->cd_devs[dev->dv_unit] = NULL;          if (cd) {
         if ((flags & DETACH_QUIET) == 0)                  cd->cd_devs[dev->dv_unit] = NULL;
                 printf("%s detached\n", dev->dv_xname);                  if ((flags & DETACH_QUIET) == 0)
                           printf("%s detached\n", dev->dv_xname);
           }
           dev_delprop(dev, NULL);
           if (dev->dv_flags & DVF_SOFTC)
                   /* Separately allocated softc */
                   free(dev->dv_private, M_DEVBUF);
         free(dev, M_DEVBUF);          free(dev, M_DEVBUF);
   
         /*          /*
Line 789  evcnt_detach(struct evcnt *ev)
Line 928  evcnt_detach(struct evcnt *ev)
         TAILQ_REMOVE(&allevents, ev, ev_list);          TAILQ_REMOVE(&allevents, ev, ev_list);
 }  }
   
   /*
    * Device property management routines.
    */
   #ifdef DEBUG
   int devprop_debug = 0;
   #endif
   
   /*
    * Create a dummy device you can attach properties to.
    */
   struct device *
   dev_config_create(struct device *parent, int wait)
   {
           struct device *dev;
   
           dev = dev_create(parent, 0, wait ? M_WAITOK : M_NOWAIT);
           return (dev);
   }
   
   
   int
   dev_setprop(struct device *dev, const char *name, void *val,
                           size_t len, int type, int wait)
   {
   #ifdef DEBUG
           if (devprop_debug)
                   printf("dev_setprop(%p, %s, %p %s, %ld, %x, %d)\n",
                          dev, name, val, (PROP_TYPE(type) == PROP_STRING) ?
                          (char *)val : "", len, type, wait);
   #endif
   
           return (prop_set(devpropdb, dev, name, val, len, type, wait));
   }
   
   size_t
   dev_getprop(struct device *dev, const char *name, void *val,
                           size_t len, int *type, int search)
   {
           ssize_t rv;
   
   #ifdef DEBUG
           if (devprop_debug) {
                   printf("dev_getprop(%p, %s, %p, %ld, %p, %d)\n",
                          dev, name, val, len, type, search);
           }
   #endif
           rv = prop_get(devpropdb, dev, name, val, len, type);
           if (rv == -1) {
                   /* Not found -- try md_getprop */
                   rv = dev_mdgetprop(dev->dv_parent, name, val,
                           len, type);
           }
           if ((rv == -1) && search) {
                   if (dev->dv_parent)
                           /* Tail recursion -- there should be no stack growth. */
                           return (dev_getprop(dev->dv_parent, name,
                                               val, len, type, search));
           }
   #ifdef DEBUG
           if (devprop_debug && (rv == -1)) {
                   printf("%s no found\n", name);
           }
   #endif
           return (rv);
   }
   
   int
   dev_delprop(struct device *dev, const char *name)
   {
   
   #ifdef DEBUG_N
           if (devprop_debug)
                   printf("dev_delprop(%p, %s, %x)\n", dev, name);
   #endif
           return (prop_delete(devpropdb, dev, name));
   }
   
   
   int
   dev_copyprops(struct device *src, struct device *dest, int wait)
   {
           return (prop_copy(devpropdb, src, dest, wait));
   }
   
 #ifdef DDB  #ifdef DDB
 void  void
 event_print(int full, void (*pr)(const char *, ...))  event_print(int full, void (*pr)(const char *, ...))

Legend:
Removed from v.1.62  
changed lines
  Added in v.1.62.6.1

CVSweb <webmaster@jp.NetBSD.org>