Diff for /qemu/hw/qdev.c between versions 1.1.1.3 and 1.1.1.5

version 1.1.1.3, 2018/04/24 18:28:31 version 1.1.1.5, 2018/04/24 18:59:52
Line 31 Line 31
 #include "monitor.h"  #include "monitor.h"
   
 static int qdev_hotplug = 0;  static int qdev_hotplug = 0;
   static bool qdev_hot_added = false;
   static bool qdev_hot_removed = false;
   
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */  /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 static BusState *main_system_bus;  static BusState *main_system_bus;
Line 92  static DeviceState *qdev_create_from_inf Line 94  static DeviceState *qdev_create_from_inf
     if (qdev_hotplug) {      if (qdev_hotplug) {
         assert(bus->allow_hotplug);          assert(bus->allow_hotplug);
         dev->hotplugged = 1;          dev->hotplugged = 1;
           qdev_hot_added = true;
     }      }
     dev->instance_id_alias = -1;      dev->instance_id_alias = -1;
     dev->state = DEV_STATE_CREATED;      dev->state = DEV_STATE_CREATED;
Line 103  static DeviceState *qdev_create_from_inf Line 106  static DeviceState *qdev_create_from_inf
    initialize the actual device emulation.  */     initialize the actual device emulation.  */
 DeviceState *qdev_create(BusState *bus, const char *name)  DeviceState *qdev_create(BusState *bus, const char *name)
 {  {
       DeviceState *dev;
   
       dev = qdev_try_create(bus, name);
       if (!dev) {
           hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
       }
   
       return dev;
   }
   
   DeviceState *qdev_try_create(BusState *bus, const char *name)
   {
     DeviceInfo *info;      DeviceInfo *info;
   
     if (!bus) {      if (!bus) {
         if (!main_system_bus) {          bus = sysbus_get_default();
             main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");  
         }  
         bus = main_system_bus;  
     }      }
   
     info = qdev_find_info(bus->info, name);      info = qdev_find_info(bus->info, name);
     if (!info) {      if (!info) {
         hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);          return NULL;
     }      }
   
     return qdev_create_from_info(bus, info);      return qdev_create_from_info(bus, info);
Line 256  DeviceState *qdev_device_add(QemuOpts *o Line 268  DeviceState *qdev_device_add(QemuOpts *o
     return qdev;      return qdev;
 }  }
   
 static void qdev_reset(void *opaque)  
 {  
     DeviceState *dev = opaque;  
     if (dev->info->reset)  
         dev->info->reset(dev);  
 }  
   
 /* Initialize a device.  Device properties should be set before calling  /* Initialize a device.  Device properties should be set before calling
    this function.  IRQs and MMIO regions should be connected/mapped after     this function.  IRQs and MMIO regions should be connected/mapped after
    calling this function.     calling this function.
Line 278  int qdev_init(DeviceState *dev) Line 283  int qdev_init(DeviceState *dev)
         qdev_free(dev);          qdev_free(dev);
         return rc;          return rc;
     }      }
     qemu_register_reset(qdev_reset, dev);  
     if (dev->info->vmsd) {      if (dev->info->vmsd) {
         vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,          vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
                                        dev->instance_id_alias,                                         dev->instance_id_alias,
Line 304  int qdev_unplug(DeviceState *dev) Line 308  int qdev_unplug(DeviceState *dev)
     }      }
     assert(dev->info->unplug != NULL);      assert(dev->info->unplug != NULL);
   
       qdev_hot_removed = true;
   
     return dev->info->unplug(dev);      return dev->info->unplug(dev);
 }  }
   
   static int qdev_reset_one(DeviceState *dev, void *opaque)
   {
       if (dev->info->reset) {
           dev->info->reset(dev);
       }
   
       return 0;
   }
   
   BusState *sysbus_get_default(void)
   {
       if (!main_system_bus) {
           main_system_bus = qbus_create(&system_bus_info, NULL,
                                         "main-system-bus");
       }
       return main_system_bus;
   }
   
   static int qbus_reset_one(BusState *bus, void *opaque)
   {
       if (bus->info->reset) {
           return bus->info->reset(bus);
       }
       return 0;
   }
   
   void qdev_reset_all(DeviceState *dev)
   {
       qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
   }
   
   void qbus_reset_all_fn(void *opaque)
   {
       BusState *bus = opaque;
       qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
   }
   
 /* can be used as ->unplug() callback for the simple cases */  /* can be used as ->unplug() callback for the simple cases */
 int qdev_simple_unplug_cb(DeviceState *dev)  int qdev_simple_unplug_cb(DeviceState *dev)
 {  {
Line 315  int qdev_simple_unplug_cb(DeviceState *d Line 358  int qdev_simple_unplug_cb(DeviceState *d
     return 0;      return 0;
 }  }
   
 /* Like qdev_init(), but terminate program via hw_error() instead of  
   /* Like qdev_init(), but terminate program via error_report() instead of
    returning an error value.  This is okay during machine creation.     returning an error value.  This is okay during machine creation.
    Don't use for hotplug, because there callers need to recover from     Don't use for hotplug, because there callers need to recover from
    failure.  Exception: if you know the device's init() callback can't     failure.  Exception: if you know the device's init() callback can't
Line 327  void qdev_init_nofail(DeviceState *dev) Line 371  void qdev_init_nofail(DeviceState *dev)
     DeviceInfo *info = dev->info;      DeviceInfo *info = dev->info;
   
     if (qdev_init(dev) < 0) {      if (qdev_init(dev) < 0) {
         error_report("Initialization of device %s failed\n", info->name);          error_report("Initialization of device %s failed", info->name);
         exit(1);          exit(1);
     }      }
 }  }
Line 350  void qdev_free(DeviceState *dev) Line 394  void qdev_free(DeviceState *dev)
         if (dev->opts)          if (dev->opts)
             qemu_opts_del(dev->opts);              qemu_opts_del(dev->opts);
     }      }
     qemu_unregister_reset(qdev_reset, dev);  
     QLIST_REMOVE(dev, sibling);      QLIST_REMOVE(dev, sibling);
     for (prop = dev->info->props; prop && prop->name; prop++) {      for (prop = dev->info->props; prop && prop->name; prop++) {
         if (prop->info->free) {          if (prop->info->free) {
Line 369  void qdev_machine_creation_done(void) Line 412  void qdev_machine_creation_done(void)
     qdev_hotplug = 1;      qdev_hotplug = 1;
 }  }
   
   bool qdev_machine_modified(void)
   {
       return qdev_hot_added || qdev_hot_removed;
   }
   
 /* Get a character (serial) device interface.  */  /* Get a character (serial) device interface.  */
 CharDriverState *qdev_init_chardev(DeviceState *dev)  CharDriverState *qdev_init_chardev(DeviceState *dev)
 {  {
Line 411  void qdev_connect_gpio_out(DeviceState * Line 459  void qdev_connect_gpio_out(DeviceState *
   
 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)  void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
 {  {
     qdev_prop_set_macaddr(dev, "mac", nd->macaddr);      qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
     if (nd->vlan)      if (nd->vlan)
         qdev_prop_set_vlan(dev, "vlan", nd->vlan);          qdev_prop_set_vlan(dev, "vlan", nd->vlan);
     if (nd->netdev)      if (nd->netdev)
Line 420  void qdev_set_nic_properties(DeviceState Line 468  void qdev_set_nic_properties(DeviceState
         qdev_prop_exists(dev, "vectors")) {          qdev_prop_exists(dev, "vectors")) {
         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);          qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
     }      }
       nd->instantiated = 1;
 }  }
   
 static int next_block_unit[IF_COUNT];  BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
   {
       BusState *bus;
   
       QLIST_FOREACH(bus, &dev->child_bus, sibling) {
           if (strcmp(name, bus->name) == 0) {
               return bus;
           }
       }
       return NULL;
   }
   
 /* Get a block device.  This should only be used for single-drive devices  int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the                         qbus_walkerfn *busfn, void *opaque)
    appropriate bus.  */  
 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)  
 {  {
     int unit = next_block_unit[type]++;      DeviceState *dev;
     DriveInfo *dinfo;      int err;
   
       if (busfn) {
           err = busfn(bus, opaque);
           if (err) {
               return err;
           }
       }
   
     dinfo = drive_get(type, 0, unit);      QLIST_FOREACH(dev, &bus->children, sibling) {
     return dinfo ? dinfo->bdrv : NULL;          err = qdev_walk_children(dev, devfn, busfn, opaque);
           if (err < 0) {
               return err;
           }
       }
   
       return 0;
 }  }
   
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)  int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                          qbus_walkerfn *busfn, void *opaque)
 {  {
     BusState *bus;      BusState *bus;
       int err;
   
       if (devfn) {
           err = devfn(dev, opaque);
           if (err) {
               return err;
           }
       }
   
     QLIST_FOREACH(bus, &dev->child_bus, sibling) {      QLIST_FOREACH(bus, &dev->child_bus, sibling) {
         if (strcmp(name, bus->name) == 0) {          err = qbus_walk_children(bus, devfn, busfn, opaque);
             return bus;          if (err < 0) {
               return err;
         }          }
     }      }
     return NULL;  
       return 0;
 }  }
   
 static BusState *qbus_find_recursive(BusState *bus, const char *name,  static BusState *qbus_find_recursive(BusState *bus, const char *name,
Line 476  static BusState *qbus_find_recursive(Bus Line 557  static BusState *qbus_find_recursive(Bus
     return NULL;      return NULL;
 }  }
   
 static DeviceState *qdev_find_recursive(BusState *bus, const char *id)  DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {  {
     DeviceState *dev, *ret;      DeviceState *dev, *ret;
     BusState *child;      BusState *child;
Line 683  void qbus_create_inplace(BusState *bus,  Line 764  void qbus_create_inplace(BusState *bus, 
     if (parent) {      if (parent) {
         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);          QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
         parent->num_child_bus++;          parent->num_child_bus++;
       } else if (bus != main_system_bus) {
           /* TODO: once all bus devices are qdevified,
              only reset handler for main_system_bus should be registered here. */
           qemu_register_reset(qbus_reset_all_fn, bus);
     }      }
   
 }  }
   
 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)  BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
Line 707  void qbus_free(BusState *bus) Line 791  void qbus_free(BusState *bus)
     if (bus->parent) {      if (bus->parent) {
         QLIST_REMOVE(bus, sibling);          QLIST_REMOVE(bus, sibling);
         bus->parent->num_child_bus--;          bus->parent->num_child_bus--;
       } else {
           assert(bus != main_system_bus); /* main_system_bus is never freed */
           qemu_unregister_reset(qbus_reset_all_fn, bus);
     }      }
     qemu_free((void*)bus->name);      qemu_free((void*)bus->name);
     if (bus->qdev_allocated) {      if (bus->qdev_allocated) {
Line 792  int do_device_add(Monitor *mon, const QD Line 879  int do_device_add(Monitor *mon, const QD
 {  {
     QemuOpts *opts;      QemuOpts *opts;
   
     opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);      opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
     if (!opts) {      if (!opts) {
         return -1;          return -1;
     }      }
Line 819  int do_device_del(Monitor *mon, const QD Line 906  int do_device_del(Monitor *mon, const QD
     }      }
     return qdev_unplug(dev);      return qdev_unplug(dev);
 }  }
   
   static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
   {
       int l = 0;
   
       if (dev && dev->parent_bus) {
           char *d;
           l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
           if (dev->parent_bus->info->get_fw_dev_path) {
               d = dev->parent_bus->info->get_fw_dev_path(dev);
               l += snprintf(p + l, size - l, "%s", d);
               qemu_free(d);
           } else {
               l += snprintf(p + l, size - l, "%s", dev->info->name);
           }
       }
       l += snprintf(p + l , size - l, "/");
   
       return l;
   }
   
   char* qdev_get_fw_dev_path(DeviceState *dev)
   {
       char path[128];
       int l;
   
       l = qdev_get_fw_dev_path_helper(dev, path, 128);
   
       path[l-1] = '\0';
   
       return strdup(path);
   }

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.5


unix.superglobalmegacorp.com