Diff for /src/sys/kern/subr_bus.c between versions 1.4 and 1.5

version 1.4, 2003/11/09 02:22:36 version 1.5, 2003/11/17 00:54:40
Line 37 Line 37
 #ifdef DEVICE_SYSCTLS  #ifdef DEVICE_SYSCTLS
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
 #endif  #endif
   #include <sys/kobj.h>
 #include <sys/bus_private.h>  #include <sys/bus_private.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <machine/bus.h>  #include <machine/bus.h>
Line 56  MALLOC_DEFINE(M_BUS, "bus", "Bus data st Line 57  MALLOC_DEFINE(M_BUS, "bus", "Bus data st
  */   */
 #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while(0)  #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while(0)
   
 static void print_method_list(device_method_t *m, int indent);  
 static void print_device_ops(device_ops_t ops, int indent);  
 static void print_device_short(device_t dev, int indent);  static void print_device_short(device_t dev, int indent);
 static void print_device(device_t dev, int indent);  static void print_device(device_t dev, int indent);
 void print_device_tree_short(device_t dev, int indent);  void print_device_tree_short(device_t dev, int indent);
Line 77  void print_devclass_list(void); Line 76  void print_devclass_list(void);
 #define DRIVERNAME(d)                   /* nop */  #define DRIVERNAME(d)                   /* nop */
 #define DEVCLANAME(d)                   /* nop */  #define DEVCLANAME(d)                   /* nop */
   
 #define print_method_list(m,i)          /* nop */  
 #define print_device_ops(o,i)           /* nop */  
 #define print_device_short(d,i)         /* nop */  #define print_device_short(d,i)         /* nop */
 #define print_device(d,i)               /* nop */  #define print_device(d,i)               /* nop */
 #define print_device_tree_short(d,i)    /* nop */  #define print_device_tree_short(d,i)    /* nop */
Line 97  static void device_register_oids(device_ Line 94  static void device_register_oids(device_
 static void device_unregister_oids(device_t dev);  static void device_unregister_oids(device_t dev);
 #endif  #endif
   
 /*  kobj_method_t null_methods[] = {
  * Method table handling      { 0, 0 }
  */  
 static int error_method(void);  
 static int next_method_offset = 1;  
   
 LIST_HEAD(methodlist, method) methods;  
 struct method {  
     LIST_ENTRY(method) link;    /* linked list of methods */  
     int offset;                 /* offset in method table */  
     int refs;                   /* count of device_op_desc users */  
     devop_t deflt;              /* default implementation */  
     char* name;                 /* unique name of method */  
 };  };
   
 static void  DEFINE_CLASS(null, null_methods, 0);
 register_method(struct device_op_desc *desc)  
 {  
     struct method* m;  
   
     if (desc->method) {  
         desc->method->refs++;  
         return;  
     }  
   
     /*  
      * Make sure that desc->deflt is always valid to simplify dispatch.  
      */  
     if (!desc->deflt)  
         desc->deflt = error_method;  
   
     for (m = LIST_FIRST(&methods); m; m = LIST_NEXT(m, link)) {  
         if (!strcmp(m->name, desc->name)) {  
             desc->offset = m->offset;  
             desc->method = m;  
             m->refs++;  
             PDEBUG(("method %p has the same name, %s, with offset %d",  
                     (void *)m, desc->name, desc->offset));  
             return;  
         }  
     }  
   
     m = (struct method *) malloc(sizeof(struct method)  
                                  + strlen(desc->name) + 1,  
                                  M_BUS, M_NOWAIT);  
     if (!m)  
             panic("register_method: out of memory");  
     bzero(m, sizeof(struct method) + strlen(desc->name) + 1);  
     m->offset = next_method_offset++;  
     m->refs = 1;  
     m->deflt = desc->deflt;  
     m->name = (char*) (m + 1);  
     strcpy(m->name, desc->name);  
     LIST_INSERT_HEAD(&methods, m, link);  
   
     desc->offset = m->offset;  
     desc->method = m;  
 }  
   
 static void  
 unregister_method(struct device_op_desc *desc)  
 {  
     struct method *m = desc->method;  
     m->refs--;  
     if (m->refs == 0) {  
         PDEBUG(("method %s, reached refcount 0", desc->name));  
         LIST_REMOVE(m, link);  
         free(m, M_BUS);  
         desc->method = 0;  
     }  
 }  
   
 static int error_method(void)  
 {  
     return ENXIO;  
 }  
   
 static struct device_ops null_ops = {  
     1,   
     { error_method }  
 };  
   
 static void  
 compile_methods(driver_t *driver)  
 {  
     device_ops_t ops;  
     struct device_method *m;  
     struct method *cm;  
     int i;  
   
     /*  
      * First register any methods which need it.  
      */  
     for (i = 0, m = driver->methods; m->desc; i++, m++)  
         register_method(m->desc);  
   
     /*  
      * Then allocate the compiled op table.  
      */  
     ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),  
                  M_BUS, M_NOWAIT);  
     if (!ops)  
         panic("compile_methods: out of memory");  
     bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t));  
   
     ops->maxoffset = next_method_offset;  
     /* Fill in default methods and then overwrite with driver methods */  
     for (i = 0; i < next_method_offset; i++)  
         ops->methods[i] = error_method;  
     for (cm = LIST_FIRST(&methods); cm; cm = LIST_NEXT(cm, link)) {  
         if (cm->deflt)  
             ops->methods[cm->offset] = cm->deflt;  
     }  
     for (i = 0, m = driver->methods; m->desc; i++, m++)  
         ops->methods[m->desc->offset] = m->func;  
     PDEBUG(("%s has %d method%s, wasting %d bytes",  
                 DRIVERNAME(driver), i, (i==1?"":"s"),  
                 (next_method_offset-i)*sizeof(devop_t)));  
   
     driver->ops = ops;  
 }  
   
 static void  
 free_methods(driver_t *driver)  
 {  
     int i;  
     struct device_method *m;  
   
     /*  
      * Unregister any methods which are no longer used.  
      */  
     for (i = 0, m = driver->methods; m->desc; i++, m++)  
         unregister_method(m->desc);  
   
     /*  
      * Free memory and clean up.  
      */  
     free(driver->ops, M_BUS);  
     driver->ops = 0;  
 }  
   
 /*  /*
  * Devclass implementation   * Devclass implementation
Line 301  devclass_add_driver(devclass_t dc, drive Line 163  devclass_add_driver(devclass_t dc, drive
     bzero(dl, sizeof *dl);      bzero(dl, sizeof *dl);
   
     /*      /*
      * Compile the driver's methods.       * 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.
      */       */
     if (!driver->ops)      kobj_class_compile((kobj_class_t) driver);
         compile_methods(driver);  
   
     /*      /*
      * Make sure the devclass which the driver is implementing exists.       * Make sure the devclass which the driver is implementing exists.
Line 380  devclass_delete_driver(devclass_t buscla Line 244  devclass_delete_driver(devclass_t buscla
   
     driver->refs--;      driver->refs--;
     if (driver->refs == 0)      if (driver->refs == 0)
         free_methods(driver);          kobj_class_free((kobj_class_t) driver);
   
     return 0;      return 0;
 }  }
Line 604  make_device(device_t parent, const char Line 468  make_device(device_t parent, const char
   
     dev->parent = parent;      dev->parent = parent;
     TAILQ_INIT(&dev->children);      TAILQ_INIT(&dev->children);
     dev->ops = &null_ops;      kobj_init((kobj_t) dev, &null_class);
     dev->driver = NULL;      dev->driver = NULL;
     dev->devclass = NULL;      dev->devclass = NULL;
     dev->unit = unit;      dev->unit = unit;
Line 625  make_device(device_t parent, const char Line 489  make_device(device_t parent, const char
   
     dev->state = DS_NOTPRESENT;      dev->state = DS_NOTPRESENT;
   
       kobj_init((kobj_t) dev, &null_class);
   
     return dev;      return dev;
 }  }
   
Line 1125  device_set_driver(device_t dev, driver_t Line 991  device_set_driver(device_t dev, driver_t
         free(dev->softc, M_BUS);          free(dev->softc, M_BUS);
         dev->softc = NULL;          dev->softc = NULL;
     }      }
     dev->ops = &null_ops;      kobj_delete((kobj_t) dev, 0);
     dev->driver = driver;      dev->driver = driver;
     if (driver) {      if (driver) {
         dev->ops = driver->ops;          kobj_init((kobj_t) dev, (kobj_class_t) driver);
         if (!(dev->flags & DF_EXTERNALSOFTC)) {          if (!(dev->flags & DF_EXTERNALSOFTC)) {
             dev->softc = malloc(driver->softc, M_BUS, M_NOWAIT);              dev->softc = malloc(driver->size, M_BUS, M_NOWAIT);
             if (!dev->softc) {              if (!dev->softc) {
                 dev->ops = &null_ops;                  kobj_init((kobj_t) dev, &null_class);
                 dev->driver = NULL;                  dev->driver = NULL;
                 return ENOMEM;                  return ENOMEM;
             }              }
             bzero(dev->softc, driver->softc);              bzero(dev->softc, driver->size);
         }          } else
               kobj_init((kobj_t) dev, &null_class);
     }      }
     return 0;      return 0;
 }  }
Line 2228  root_setup_intr(device_t dev, device_t c Line 2095  root_setup_intr(device_t dev, device_t c
         panic("root_setup_intr");          panic("root_setup_intr");
 }  }
   
 static device_method_t root_methods[] = {  static kobj_method_t root_methods[] = {
         /* Device interface */          /* Device interface */
         DEVMETHOD(device_shutdown,      bus_generic_shutdown),          KOBJMETHOD(device_shutdown,     bus_generic_shutdown),
         DEVMETHOD(device_suspend,       bus_generic_suspend),          KOBJMETHOD(device_suspend,      bus_generic_suspend),
         DEVMETHOD(device_resume,        bus_generic_resume),          KOBJMETHOD(device_resume,       bus_generic_resume),
   
         /* Bus interface */          /* Bus interface */
         DEVMETHOD(bus_print_child,      root_print_child),          KOBJMETHOD(bus_print_child,     root_print_child),
         DEVMETHOD(bus_read_ivar,        bus_generic_read_ivar),          KOBJMETHOD(bus_read_ivar,       bus_generic_read_ivar),
         DEVMETHOD(bus_write_ivar,       bus_generic_write_ivar),          KOBJMETHOD(bus_write_ivar,      bus_generic_write_ivar),
         DEVMETHOD(bus_setup_intr,       root_setup_intr),          KOBJMETHOD(bus_setup_intr,      root_setup_intr),
   
         { 0, 0 }          { 0, 0 }
 };  };
Line 2257  root_bus_module_handler(module_t mod, in Line 2124  root_bus_module_handler(module_t mod, in
 {  {
     switch (what) {      switch (what) {
     case MOD_LOAD:      case MOD_LOAD:
         compile_methods(&root_driver);          kobj_class_compile((kobj_class_t) &root_driver);
         root_bus = make_device(NULL, "root", 0);          root_bus = make_device(NULL, "root", 0);
         root_bus->desc = "System root bus";          root_bus->desc = "System root bus";
         root_bus->ops = root_driver.ops;          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", FALSE);
Line 2353  driver_module_handler(module_t mod, int Line 2220  driver_module_handler(module_t mod, int
  */   */
   
 static void  static void
 print_method_list(device_method_t *m, int indent)  
 {  
         int i;  
   
         if (!m)  
                 return;  
   
         for (i = 0; m->desc; i++, m++)  
                 indentprintf(("method %d: %s, offset=%d\n",  
                         i, m->desc->name, m->desc->offset));  
 }  
   
 static void  
 print_device_ops(device_ops_t ops, int indent)  
 {  
         int i;  
         int count = 0;  
   
         if (!ops)  
                 return;  
   
         /* we present a list of the methods that are pointing to the  
          * error_method, but ignore the 0'th elements; it is always  
          * error_method.  
          */  
         for (i = 1; i < ops->maxoffset; i++) {  
                 if (ops->methods[i] == error_method) {  
                         if (count == 0)  
                                 indentprintf(("error_method:"));  
                         printf(" %d", i);  
                         count++;  
                 }  
         }  
         if (count)  
                 printf("\n");  
   
         indentprintf(("(%d method%s, %d valid, %d error_method%s)\n",  
                 ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"),  
                 ops->maxoffset-1-count,  
                 count, (count == 1? "":"'s")));  
 }  
   
 static void  
 print_device_short(device_t dev, int indent)  print_device_short(device_t dev, int indent)
 {  {
         if (!dev)          if (!dev)
Line 2424  print_device(device_t dev, int indent) Line 2248  print_device(device_t dev, int indent)
   
         indentprintf(("Parent:\n"));          indentprintf(("Parent:\n"));
         print_device_short(dev->parent, indent+1);          print_device_short(dev->parent, indent+1);
         indentprintf(("Methods:\n"));  
         print_device_ops(dev->ops, indent+1);  
         indentprintf(("Driver:\n"));          indentprintf(("Driver:\n"));
         print_driver_short(dev->driver, indent+1);          print_driver_short(dev->driver, indent+1);
         indentprintf(("Devclass:\n"));          indentprintf(("Devclass:\n"));
Line 2471  print_driver_short(driver_t *driver, int Line 2293  print_driver_short(driver_t *driver, int
                 return;                  return;
   
         indentprintf(("driver %s: softc size = %d\n",          indentprintf(("driver %s: softc size = %d\n",
                 driver->name, driver->softc));                  driver->name, driver->size));
 }  }
   
 static void  static void
Line 2481  print_driver(driver_t *driver, int inden Line 2303  print_driver(driver_t *driver, int inden
                 return;                  return;
   
         print_driver_short(driver, indent);          print_driver_short(driver, indent);
         indentprintf(("Methods:\n"));  
         print_method_list(driver->methods, indent+1);  
         indentprintf(("Operations:\n"));  
         print_device_ops(driver->ops, indent+1);  
 }  }
   
   

Removed from v.1.4  
changed lines
  Added in v.1.5