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 voidDEFINE_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