Diff for /qemu/hw/qdev.c between versions 1.1.1.6 and 1.1.1.7

version 1.1.1.6, 2018/04/24 19:27:28 version 1.1.1.7, 2018/04/24 19:47:15
Line 28 Line 28
 #include "net.h"  #include "net.h"
 #include "qdev.h"  #include "qdev.h"
 #include "sysemu.h"  #include "sysemu.h"
 #include "monitor.h"  #include "error.h"
   
 static int qdev_hotplug = 0;  int qdev_hotplug = 0;
 static bool qdev_hot_added = false;  static bool qdev_hot_added = false;
 static bool qdev_hot_removed = false;  static bool qdev_hot_removed = false;
   
Line 38  static bool qdev_hot_removed = false; Line 38  static bool qdev_hot_removed = false;
 static BusState *main_system_bus;  static BusState *main_system_bus;
 static void main_system_bus_create(void);  static void main_system_bus_create(void);
   
 DeviceInfo *device_info_list;  
   
 static BusState *qbus_find_recursive(BusState *bus, const char *name,  
                                      const BusInfo *info);  
 static BusState *qbus_find(const char *path);  
   
 /* Register a new device type.  */  /* Register a new device type.  */
 void qdev_register(DeviceInfo *info)  const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
   {
       DeviceClass *dc = DEVICE_GET_CLASS(dev);
       return dc->vmsd;
   }
   
   BusInfo *qdev_get_bus_info(DeviceState *dev)
 {  {
     assert(info->size >= sizeof(DeviceState));      DeviceClass *dc = DEVICE_GET_CLASS(dev);
     assert(!info->next);      return dc->bus_info;
   }
   
     info->next = device_info_list;  Property *qdev_get_props(DeviceState *dev)
     device_info_list = info;  {
       DeviceClass *dc = DEVICE_GET_CLASS(dev);
       return dc->props;
 }  }
   
 static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)  const char *qdev_fw_name(DeviceState *dev)
 {  {
     DeviceInfo *info;      DeviceClass *dc = DEVICE_GET_CLASS(dev);
   
     /* first check device names */      if (dc->fw_name) {
     for (info = device_info_list; info != NULL; info = info->next) {          return dc->fw_name;
         if (bus_info && info->bus_info != bus_info)  
             continue;  
         if (strcmp(info->name, name) != 0)  
             continue;  
         return info;  
     }      }
   
     /* failing that check the aliases */      return object_get_typename(OBJECT(dev));
     for (info = device_info_list; info != NULL; info = info->next) {  
         if (bus_info && info->bus_info != bus_info)  
             continue;  
         if (!info->alias)  
             continue;  
         if (strcmp(info->alias, name) != 0)  
             continue;  
         return info;  
     }  
     return NULL;  
 }  }
   
 static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)  bool qdev_exists(const char *name)
 {  {
     DeviceState *dev;      return !!object_class_by_name(name);
   }
   
   static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                        Error **errp);
   
   void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
   {
       Property *prop;
   
     assert(bus->info == info->bus_info);  
     dev = g_malloc0(info->size);  
     dev->info = info;  
     dev->parent_bus = bus;  
     qdev_prop_set_defaults(dev, dev->info->props);  
     qdev_prop_set_defaults(dev, dev->parent_bus->info->props);  
     qdev_prop_set_globals(dev);  
     QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);  
     if (qdev_hotplug) {      if (qdev_hotplug) {
         assert(bus->allow_hotplug);          assert(bus->allow_hotplug);
         dev->hotplugged = 1;  
         qdev_hot_added = true;  
     }      }
     dev->instance_id_alias = -1;  
     dev->state = DEV_STATE_CREATED;      dev->parent_bus = bus;
     return dev;      QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
   
       for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
           qdev_property_add_legacy(dev, prop, NULL);
           qdev_property_add_static(dev, prop, NULL);
       }
       qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
 }  }
   
 /* Create a new device.  This only initializes the device state structure  /* Create a new device.  This only initializes the device state structure
Line 122  DeviceState *qdev_create(BusState *bus,  Line 114  DeviceState *qdev_create(BusState *bus, 
     return dev;      return dev;
 }  }
   
 DeviceState *qdev_try_create(BusState *bus, const char *name)  DeviceState *qdev_try_create(BusState *bus, const char *type)
 {  {
     DeviceInfo *info;      DeviceState *dev;
   
     if (!bus) {  
         bus = sysbus_get_default();  
     }  
   
     info = qdev_find_info(bus->info, name);      if (object_class_by_name(type) == NULL) {
     if (!info) {  
         return NULL;          return NULL;
     }      }
       dev = DEVICE(object_new(type));
     return qdev_create_from_info(bus, info);      if (!dev) {
 }  
   
 static void qdev_print_devinfo(DeviceInfo *info)  
 {  
     error_printf("name \"%s\", bus %s",  
                  info->name, info->bus_info->name);  
     if (info->alias) {  
         error_printf(", alias \"%s\"", info->alias);  
     }  
     if (info->desc) {  
         error_printf(", desc \"%s\"", info->desc);  
     }  
     if (info->no_user) {  
         error_printf(", no-user");  
     }  
     error_printf("\n");  
 }  
   
 static int set_property(const char *name, const char *value, void *opaque)  
 {  
     DeviceState *dev = opaque;  
   
     if (strcmp(name, "driver") == 0)  
         return 0;  
     if (strcmp(name, "bus") == 0)  
         return 0;  
   
     if (qdev_prop_parse(dev, name, value) == -1) {  
         return -1;  
     }  
     return 0;  
 }  
   
 int qdev_device_help(QemuOpts *opts)  
 {  
     const char *driver;  
     DeviceInfo *info;  
     Property *prop;  
   
     driver = qemu_opt_get(opts, "driver");  
     if (driver && !strcmp(driver, "?")) {  
         for (info = device_info_list; info != NULL; info = info->next) {  
             if (info->no_user) {  
                 continue;       /* not available, don't show */  
             }  
             qdev_print_devinfo(info);  
         }  
         return 1;  
     }  
   
     if (!driver || !qemu_opt_get(opts, "?")) {  
         return 0;  
     }  
   
     info = qdev_find_info(NULL, driver);  
     if (!info) {  
         return 0;  
     }  
   
     for (prop = info->props; prop && prop->name; prop++) {  
         /*  
          * TODO Properties without a parser are just for dirty hacks.  
          * qdev_prop_ptr is the only such PropertyInfo.  It's marked  
          * for removal.  This conditional should be removed along with  
          * it.  
          */  
         if (!prop->info->parse) {  
             continue;           /* no way to set it, don't show */  
         }  
         error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);  
     }  
     for (prop = info->bus_info->props; prop && prop->name; prop++) {  
         if (!prop->info->parse) {  
             continue;           /* no way to set it, don't show */  
         }  
         error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);  
     }  
     return 1;  
 }  
   
 DeviceState *qdev_device_add(QemuOpts *opts)  
 {  
     const char *driver, *path, *id;  
     DeviceInfo *info;  
     DeviceState *qdev;  
     BusState *bus;  
   
     driver = qemu_opt_get(opts, "driver");  
     if (!driver) {  
         qerror_report(QERR_MISSING_PARAMETER, "driver");  
         return NULL;          return NULL;
     }      }
   
     /* find driver */      if (!bus) {
     info = qdev_find_info(NULL, driver);          bus = sysbus_get_default();
     if (!info || info->no_user) {  
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");  
         error_printf_unless_qmp("Try with argument '?' for a list.\n");  
         return NULL;  
     }      }
   
     /* find bus */      qdev_set_parent_bus(dev, bus);
     path = qemu_opt_get(opts, "bus");      qdev_prop_set_globals(dev);
     if (path != NULL) {  
         bus = qbus_find(path);  
         if (!bus) {  
             return NULL;  
         }  
         if (bus->info != info->bus_info) {  
             qerror_report(QERR_BAD_BUS_FOR_DEVICE,  
                            driver, bus->info->name);  
             return NULL;  
         }  
     } else {  
         bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);  
         if (!bus) {  
             qerror_report(QERR_NO_BUS_FOR_DEVICE,  
                            info->name, info->bus_info->name);  
             return NULL;  
         }  
     }  
     if (qdev_hotplug && !bus->allow_hotplug) {  
         qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);  
         return NULL;  
     }  
   
     /* create device, set properties */      return dev;
     qdev = qdev_create_from_info(bus, info);  
     id = qemu_opts_id(opts);  
     if (id) {  
         qdev->id = id;  
     }  
     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {  
         qdev_free(qdev);  
         return NULL;  
     }  
     if (qdev_init(qdev) < 0) {  
         qerror_report(QERR_DEVICE_INIT_FAILED, driver);  
         return NULL;  
     }  
     qdev->opts = opts;  
     return qdev;  
 }  }
   
 /* Initialize a device.  Device properties should be set before calling  /* Initialize a device.  Device properties should be set before calling
Line 287  DeviceState *qdev_device_add(QemuOpts *o Line 143  DeviceState *qdev_device_add(QemuOpts *o
    Return 0 on success.  */     Return 0 on success.  */
 int qdev_init(DeviceState *dev)  int qdev_init(DeviceState *dev)
 {  {
       DeviceClass *dc = DEVICE_GET_CLASS(dev);
     int rc;      int rc;
   
     assert(dev->state == DEV_STATE_CREATED);      assert(dev->state == DEV_STATE_CREATED);
     rc = dev->info->init(dev, dev->info);  
       rc = dc->init(dev);
     if (rc < 0) {      if (rc < 0) {
           object_unparent(OBJECT(dev));
         qdev_free(dev);          qdev_free(dev);
         return rc;          return rc;
     }      }
     if (dev->info->vmsd) {  
         vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,      if (!OBJECT(dev)->parent) {
           static int unattached_count = 0;
           gchar *name = g_strdup_printf("device[%d]", unattached_count++);
   
           object_property_add_child(container_get(qdev_get_machine(),
                                                   "/unattached"),
                                     name, OBJECT(dev), NULL);
           g_free(name);
       }
   
       if (qdev_get_vmsd(dev)) {
           vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
                                        dev->instance_id_alias,                                         dev->instance_id_alias,
                                        dev->alias_required_for_version);                                         dev->alias_required_for_version);
     }      }
     dev->state = DEV_STATE_INITIALIZED;      dev->state = DEV_STATE_INITIALIZED;
     if (dev->hotplugged && dev->info->reset) {      if (dev->hotplugged) {
         dev->info->reset(dev);          device_reset(dev);
     }      }
     return 0;      return 0;
 }  }
Line 315  void qdev_set_legacy_instance_id(DeviceS Line 185  void qdev_set_legacy_instance_id(DeviceS
     dev->alias_required_for_version = required_for_version;      dev->alias_required_for_version = required_for_version;
 }  }
   
 int qdev_unplug(DeviceState *dev)  void qdev_unplug(DeviceState *dev, Error **errp)
 {  {
       DeviceClass *dc = DEVICE_GET_CLASS(dev);
   
     if (!dev->parent_bus->allow_hotplug) {      if (!dev->parent_bus->allow_hotplug) {
         qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);          error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
         return -1;          return;
     }      }
     assert(dev->info->unplug != NULL);      assert(dc->unplug != NULL);
   
     qdev_hot_removed = true;      qdev_hot_removed = true;
   
     return dev->info->unplug(dev);      if (dc->unplug(dev) < 0) {
           error_set(errp, QERR_UNDEFINED_ERROR);
           return;
       }
 }  }
   
 static int qdev_reset_one(DeviceState *dev, void *opaque)  static int qdev_reset_one(DeviceState *dev, void *opaque)
 {  {
     if (dev->info->reset) {      device_reset(dev);
         dev->info->reset(dev);  
     }  
   
     return 0;      return 0;
 }  }
Line 368  void qbus_reset_all_fn(void *opaque) Line 241  void qbus_reset_all_fn(void *opaque)
 int qdev_simple_unplug_cb(DeviceState *dev)  int qdev_simple_unplug_cb(DeviceState *dev)
 {  {
     /* just zap it */      /* just zap it */
       object_unparent(OBJECT(dev));
     qdev_free(dev);      qdev_free(dev);
     return 0;      return 0;
 }  }
Line 382  int qdev_simple_unplug_cb(DeviceState *d Line 256  int qdev_simple_unplug_cb(DeviceState *d
    way is somewhat unclean, and best avoided.  */     way is somewhat unclean, and best avoided.  */
 void qdev_init_nofail(DeviceState *dev)  void qdev_init_nofail(DeviceState *dev)
 {  {
     DeviceInfo *info = dev->info;  
   
     if (qdev_init(dev) < 0) {      if (qdev_init(dev) < 0) {
         error_report("Initialization of device %s failed", info->name);          error_report("Initialization of device %s failed",
                        object_get_typename(OBJECT(dev)));
         exit(1);          exit(1);
     }      }
 }  }
Line 393  void qdev_init_nofail(DeviceState *dev) Line 266  void qdev_init_nofail(DeviceState *dev)
 /* Unlink device from bus and free the structure.  */  /* Unlink device from bus and free the structure.  */
 void qdev_free(DeviceState *dev)  void qdev_free(DeviceState *dev)
 {  {
     BusState *bus;      object_delete(OBJECT(dev));
     Property *prop;  
   
     if (dev->state == DEV_STATE_INITIALIZED) {  
         while (dev->num_child_bus) {  
             bus = QLIST_FIRST(&dev->child_bus);  
             qbus_free(bus);  
         }  
         if (dev->info->vmsd)  
             vmstate_unregister(dev, dev->info->vmsd, dev);  
         if (dev->info->exit)  
             dev->info->exit(dev);  
         if (dev->opts)  
             qemu_opts_del(dev->opts);  
     }  
     QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);  
     for (prop = dev->info->props; prop && prop->name; prop++) {  
         if (prop->info->free) {  
             prop->info->free(dev, prop);  
         }  
     }  
     g_free(dev);  
 }  }
   
 void qdev_machine_creation_done(void)  void qdev_machine_creation_done(void)
Line 431  bool qdev_machine_modified(void) Line 283  bool qdev_machine_modified(void)
     return qdev_hot_added || qdev_hot_removed;      return qdev_hot_added || qdev_hot_removed;
 }  }
   
 /* Get a character (serial) device interface.  */  
 CharDriverState *qdev_init_chardev(DeviceState *dev)  
 {  
     static int next_serial;  
   
     /* FIXME: This function needs to go away: use chardev properties!  */  
     return serial_hds[next_serial++];  
 }  
   
 BusState *qdev_get_parent_bus(DeviceState *dev)  BusState *qdev_get_parent_bus(DeviceState *dev)
 {  {
     return dev->parent_bus;      return dev->parent_bus;
Line 543  int qdev_walk_children(DeviceState *dev, Line 386  int qdev_walk_children(DeviceState *dev,
     return 0;      return 0;
 }  }
   
 static BusState *qbus_find_recursive(BusState *bus, const char *name,  
                                      const BusInfo *info)  
 {  
     DeviceState *dev;  
     BusState *child, *ret;  
     int match = 1;  
   
     if (name && (strcmp(bus->name, name) != 0)) {  
         match = 0;  
     }  
     if (info && (bus->info != info)) {  
         match = 0;  
     }  
     if (match) {  
         return bus;  
     }  
   
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         QLIST_FOREACH(child, &dev->child_bus, sibling) {  
             ret = qbus_find_recursive(child, name, info);  
             if (ret) {  
                 return ret;  
             }  
         }  
     }  
     return NULL;  
 }  
   
 DeviceState *qdev_find_recursive(BusState *bus, const char *id)  DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {  {
     DeviceState *dev, *ret;      DeviceState *dev, *ret;
Line 589  DeviceState *qdev_find_recursive(BusStat Line 404  DeviceState *qdev_find_recursive(BusStat
     return NULL;      return NULL;
 }  }
   
 static void qbus_list_bus(DeviceState *dev)  
 {  
     BusState *child;  
     const char *sep = " ";  
   
     error_printf("child busses at \"%s\":",  
                  dev->id ? dev->id : dev->info->name);  
     QLIST_FOREACH(child, &dev->child_bus, sibling) {  
         error_printf("%s\"%s\"", sep, child->name);  
         sep = ", ";  
     }  
     error_printf("\n");  
 }  
   
 static void qbus_list_dev(BusState *bus)  
 {  
     DeviceState *dev;  
     const char *sep = " ";  
   
     error_printf("devices at \"%s\":", bus->name);  
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         error_printf("%s\"%s\"", sep, dev->info->name);  
         if (dev->id)  
             error_printf("/\"%s\"", dev->id);  
         sep = ", ";  
     }  
     error_printf("\n");  
 }  
   
 static BusState *qbus_find_bus(DeviceState *dev, char *elem)  
 {  
     BusState *child;  
   
     QLIST_FOREACH(child, &dev->child_bus, sibling) {  
         if (strcmp(child->name, elem) == 0) {  
             return child;  
         }  
     }  
     return NULL;  
 }  
   
 static DeviceState *qbus_find_dev(BusState *bus, char *elem)  
 {  
     DeviceState *dev;  
   
     /*  
      * try to match in order:  
      *   (1) instance id, if present  
      *   (2) driver name  
      *   (3) driver alias, if present  
      */  
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         if (dev->id  &&  strcmp(dev->id, elem) == 0) {  
             return dev;  
         }  
     }  
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         if (strcmp(dev->info->name, elem) == 0) {  
             return dev;  
         }  
     }  
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {  
             return dev;  
         }  
     }  
     return NULL;  
 }  
   
 static BusState *qbus_find(const char *path)  
 {  
     DeviceState *dev;  
     BusState *bus;  
     char elem[128];  
     int pos, len;  
   
     /* find start element */  
     if (path[0] == '/') {  
         bus = main_system_bus;  
         pos = 0;  
     } else {  
         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {  
             assert(!path[0]);  
             elem[0] = len = 0;  
         }  
         bus = qbus_find_recursive(main_system_bus, elem, NULL);  
         if (!bus) {  
             qerror_report(QERR_BUS_NOT_FOUND, elem);  
             return NULL;  
         }  
         pos = len;  
     }  
   
     for (;;) {  
         assert(path[pos] == '/' || !path[pos]);  
         while (path[pos] == '/') {  
             pos++;  
         }  
         if (path[pos] == '\0') {  
             return bus;  
         }  
   
         /* find device */  
         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {  
             assert(0);  
             elem[0] = len = 0;  
         }  
         pos += len;  
         dev = qbus_find_dev(bus, elem);  
         if (!dev) {  
             qerror_report(QERR_DEVICE_NOT_FOUND, elem);  
             if (!monitor_cur_is_qmp()) {  
                 qbus_list_dev(bus);  
             }  
             return NULL;  
         }  
   
         assert(path[pos] == '/' || !path[pos]);  
         while (path[pos] == '/') {  
             pos++;  
         }  
         if (path[pos] == '\0') {  
             /* last specified element is a device.  If it has exactly  
              * one child bus accept it nevertheless */  
             switch (dev->num_child_bus) {  
             case 0:  
                 qerror_report(QERR_DEVICE_NO_BUS, elem);  
                 return NULL;  
             case 1:  
                 return QLIST_FIRST(&dev->child_bus);  
             default:  
                 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);  
                 if (!monitor_cur_is_qmp()) {  
                     qbus_list_bus(dev);  
                 }  
                 return NULL;  
             }  
         }  
   
         /* find bus */  
         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {  
             assert(0);  
             elem[0] = len = 0;  
         }  
         pos += len;  
         bus = qbus_find_bus(dev, elem);  
         if (!bus) {  
             qerror_report(QERR_BUS_NOT_FOUND, elem);  
             if (!monitor_cur_is_qmp()) {  
                 qbus_list_bus(dev);  
             }  
             return NULL;  
         }  
     }  
 }  
   
 void qbus_create_inplace(BusState *bus, BusInfo *info,  void qbus_create_inplace(BusState *bus, BusInfo *info,
                          DeviceState *parent, const char *name)                           DeviceState *parent, const char *name)
 {  {
Line 825  void qbus_free(BusState *bus) Line 484  void qbus_free(BusState *bus)
     }      }
 }  }
   
 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)  static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
 static void qbus_print(Monitor *mon, BusState *bus, int indent);  
   
 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,  
                              const char *prefix, int indent)  
 {  {
     char buf[64];      int l = 0;
   
     if (!props)      if (dev && dev->parent_bus) {
         return;          char *d;
     while (props->name) {          l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
         /*          if (dev->parent_bus->info->get_fw_dev_path) {
          * TODO Properties without a print method are just for dirty              d = dev->parent_bus->info->get_fw_dev_path(dev);
          * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's              l += snprintf(p + l, size - l, "%s", d);
          * marked for removal.  The test props->info->print should be              g_free(d);
          * removed along with it.          } else {
          */              l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
         if (props->info->print) {  
             props->info->print(dev, props, buf, sizeof(buf));  
             qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);  
         }          }
         props++;  
     }      }
 }      l += snprintf(p + l , size - l, "/");
   
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)      return l;
 {  
     BusState *child;  
     qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,  
                 dev->id ? dev->id : "");  
     indent += 2;  
     if (dev->num_gpio_in) {  
         qdev_printf("gpio-in %d\n", dev->num_gpio_in);  
     }  
     if (dev->num_gpio_out) {  
         qdev_printf("gpio-out %d\n", dev->num_gpio_out);  
     }  
     qdev_print_props(mon, dev, dev->info->props, "dev", indent);  
     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);  
     if (dev->parent_bus->info->print_dev)  
         dev->parent_bus->info->print_dev(mon, dev, indent);  
     QLIST_FOREACH(child, &dev->child_bus, sibling) {  
         qbus_print(mon, child, indent);  
     }  
 }  }
   
 static void qbus_print(Monitor *mon, BusState *bus, int indent)  char* qdev_get_fw_dev_path(DeviceState *dev)
 {  {
     struct DeviceState *dev;      char path[128];
       int l;
   
     qdev_printf("bus: %s\n", bus->name);      l = qdev_get_fw_dev_path_helper(dev, path, 128);
     indent += 2;  
     qdev_printf("type %s\n", bus->info->name);      path[l-1] = '\0';
     QTAILQ_FOREACH(dev, &bus->children, sibling) {  
         qdev_print(mon, dev, indent);      return strdup(path);
     }  
 }  }
 #undef qdev_printf  
   
 void do_info_qtree(Monitor *mon)  static char *qdev_get_type(Object *obj, Error **errp)
 {  {
     if (main_system_bus)      return g_strdup(object_get_typename(obj));
         qbus_print(mon, main_system_bus, 0);  
 }  }
   
 void do_info_qdm(Monitor *mon)  /**
    * Legacy property handling
    */
   
   static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
                                        const char *name, Error **errp)
 {  {
     DeviceInfo *info;      DeviceState *dev = DEVICE(obj);
       Property *prop = opaque;
   
     for (info = device_info_list; info != NULL; info = info->next) {      char buffer[1024];
         qdev_print_devinfo(info);      char *ptr = buffer;
     }  
       prop->info->print(dev, prop, buffer, sizeof(buffer));
       visit_type_str(v, &ptr, name, errp);
 }  }
   
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)  static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
                                        const char *name, Error **errp)
 {  {
     QemuOpts *opts;      DeviceState *dev = DEVICE(obj);
       Property *prop = opaque;
       Error *local_err = NULL;
       char *ptr = NULL;
       int ret;
   
     opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);      if (dev->state != DEV_STATE_CREATED) {
     if (!opts) {          error_set(errp, QERR_PERMISSION_DENIED);
         return -1;          return;
     }      }
     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {  
         qemu_opts_del(opts);      visit_type_str(v, &ptr, name, &local_err);
         return 0;      if (local_err) {
           error_propagate(errp, local_err);
           return;
     }      }
     if (!qdev_device_add(opts)) {  
         qemu_opts_del(opts);      ret = prop->info->parse(dev, prop, ptr);
         return -1;      error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
       g_free(ptr);
   }
   
   /**
    * @qdev_add_legacy_property - adds a legacy property
    *
    * Do not use this is new code!  Properties added through this interface will
    * be given names and types in the "legacy" namespace.
    *
    * Legacy properties are string versions of other OOM properties.  The format
    * of the string depends on the property type.
    */
   void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                 Error **errp)
   {
       gchar *name, *type;
   
       /* Register pointer properties as legacy properties */
       if (!prop->info->print && !prop->info->parse &&
           (prop->info->set || prop->info->get)) {
           return;
     }      }
     return 0;  
       name = g_strdup_printf("legacy-%s", prop->name);
       type = g_strdup_printf("legacy<%s>",
                              prop->info->legacy_name ?: prop->info->name);
   
       object_property_add(OBJECT(dev), name, type,
                           prop->info->print ? qdev_get_legacy_property : prop->info->get,
                           prop->info->parse ? qdev_set_legacy_property : prop->info->set,
                           NULL,
                           prop, errp);
   
       g_free(type);
       g_free(name);
   }
   
   /**
    * @qdev_property_add_static - add a @Property to a device.
    *
    * Static properties access data in a struct.  The actual type of the
    * property and the field depends on the property type.
    */
   void qdev_property_add_static(DeviceState *dev, Property *prop,
                                 Error **errp)
   {
       /*
        * TODO qdev_prop_ptr does not have getters or setters.  It must
        * go now that it can be replaced with links.  The test should be
        * removed along with it: all static properties are read/write.
        */
       if (!prop->info->get && !prop->info->set) {
           return;
       }
   
       object_property_add(OBJECT(dev), prop->name, prop->info->name,
                           prop->info->get, prop->info->set,
                           prop->info->release,
                           prop, errp);
 }  }
   
 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)  static void device_initfn(Object *obj)
 {  {
     const char *id = qdict_get_str(qdict, "id");      DeviceState *dev = DEVICE(obj);
     DeviceState *dev;      Property *prop;
   
       if (qdev_hotplug) {
           dev->hotplugged = 1;
           qdev_hot_added = true;
       }
   
       dev->instance_id_alias = -1;
       dev->state = DEV_STATE_CREATED;
   
     dev = qdev_find_recursive(main_system_bus, id);      for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
     if (NULL == dev) {          qdev_property_add_legacy(dev, prop, NULL);
         qerror_report(QERR_DEVICE_NOT_FOUND, id);          qdev_property_add_static(dev, prop, NULL);
         return -1;  
     }      }
     return qdev_unplug(dev);  
       object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
       qdev_prop_set_defaults(dev, qdev_get_props(dev));
 }  }
   
 static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)  /* Unlink device from bus and free the structure.  */
   static void device_finalize(Object *obj)
 {  {
     int l = 0;      DeviceState *dev = DEVICE(obj);
       BusState *bus;
       DeviceClass *dc = DEVICE_GET_CLASS(dev);
   
     if (dev && dev->parent_bus) {      if (dev->state == DEV_STATE_INITIALIZED) {
         char *d;          while (dev->num_child_bus) {
         l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);              bus = QLIST_FIRST(&dev->child_bus);
         if (dev->parent_bus->info->get_fw_dev_path) {              qbus_free(bus);
             d = dev->parent_bus->info->get_fw_dev_path(dev);          }
             l += snprintf(p + l, size - l, "%s", d);          if (qdev_get_vmsd(dev)) {
             g_free(d);              vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
         } else {          }
             l += snprintf(p + l, size - l, "%s", dev->info->name);          if (dc->exit) {
               dc->exit(dev);
           }
           if (dev->opts) {
               qemu_opts_del(dev->opts);
         }          }
     }      }
     l += snprintf(p + l , size - l, "/");      QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
   }
   
     return l;  void device_reset(DeviceState *dev)
   {
       DeviceClass *klass = DEVICE_GET_CLASS(dev);
   
       if (klass->reset) {
           klass->reset(dev);
       }
 }  }
   
 char* qdev_get_fw_dev_path(DeviceState *dev)  Object *qdev_get_machine(void)
 {  {
     char path[128];      static Object *dev;
     int l;  
   
     l = qdev_get_fw_dev_path_helper(dev, path, 128);      if (dev == NULL) {
           dev = container_get(object_get_root(), "/machine");
       }
   
     path[l-1] = '\0';      return dev;
   }
   
     return strdup(path);  static TypeInfo device_type_info = {
       .name = TYPE_DEVICE,
       .parent = TYPE_OBJECT,
       .instance_size = sizeof(DeviceState),
       .instance_init = device_initfn,
       .instance_finalize = device_finalize,
       .abstract = true,
       .class_size = sizeof(DeviceClass),
   };
   
   static void qdev_register_types(void)
   {
       type_register_static(&device_type_info);
 }  }
   
   type_init(qdev_register_types)

Removed from v.1.1.1.6  
changed lines
  Added in v.1.1.1.7


unix.superglobalmegacorp.com