Message ID | 1350352644-14436-4-git-send-email-imammedo@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Oct 16, 2012 at 03:57:15AM +0200, Igor Mammedov wrote: [...] > @@ -0,0 +1,68 @@ > +#include "qdev.h" > + > +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > +{ > + assert(dev->num_gpio_in == 0); > + dev->num_gpio_in = n; > + dev->gpio_in = qemu_allocate_irqs(handler, dev, n); > +} > + [...] > -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > -{ > - dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, > - dev, n); > - dev->num_gpio_in += n; > -} Oops. It looks like you rebased but kept the old code. I will fix this in the next version.
Igor Mammedov <imammedo@redhat.com> writes: > From: Eduardo Habkost <ehabkost@redhat.com> > > This change should help on two things: > - Allowing DeviceState to be used by *-user; > - Writing qdev unit tests without pulling too many dependencies. > > Note that there are two parts that depend on code compiled only on > qemu-system-*, but are still inside qdev.c: > - vmstate handling > - reset function registration. > > Those two parts will be handled later, by moving that code to > qdev-system.c but keeping weak symbols for *-user. > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > --- > [imammedo: keep qdev_get_child_bus() in hw/qdev.c] > [imammedo: put qdev_set_nic_properties() in hw/qdev-properties-system.c] > --- > hw/Makefile.objs | 1 + > hw/qdev-properties-system.c | 340 ++++++++++++++++++++++++++++++++++++++++++++ > hw/qdev-properties.c | 320 +---------------------------------------- > hw/qdev-properties.h | 1 + > hw/qdev-system.c | 68 +++++++++ > hw/qdev.c | 80 ----------- > 6 files changed, 411 insertions(+), 399 deletions(-) > create mode 100644 hw/qdev-properties-system.c > create mode 100644 hw/qdev-system.c > > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index 854faa9..16f23c0 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -181,6 +181,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o > common-obj-y += bt-hci-csr.o > common-obj-y += msmouse.o ps2.o > common-obj-y += qdev.o qdev-properties.o qdev-monitor.o > +common-obj-y += qdev-system.o qdev-properties-system.o > common-obj-$(CONFIG_BRLAPI) += baum.o > > # xen backend driver support > diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c > new file mode 100644 > index 0000000..e3a21db > --- /dev/null > +++ b/hw/qdev-properties-system.c > @@ -0,0 +1,340 @@ New files should carry copyright/licenses. I don't really understand the split here and the 'system' suffix really doesn't explain it for me. Could you at least add a comment to each of these files explaining what belongs in them? Regards, Anthony Liguori > +#include "net.h" > +#include "qdev.h" > +#include "qerror.h" > +#include "blockdev.h" > +#include "hw/block-common.h" > +#include "net/hub.h" > +#include "qapi/qapi-visit-core.h" > + > +static void get_pointer(Object *obj, Visitor *v, Property *prop, > + const char *(*print)(void *ptr), > + const char *name, Error **errp) > +{ > + DeviceState *dev = DEVICE(obj); > + void **ptr = qdev_get_prop_ptr(dev, prop); > + char *p; > + > + p = (char *) (*ptr ? print(*ptr) : ""); > + visit_type_str(v, &p, name, errp); > +} > + > +static void set_pointer(Object *obj, Visitor *v, Property *prop, > + int (*parse)(DeviceState *dev, const char *str, > + void **ptr), > + const char *name, Error **errp) > +{ > + DeviceState *dev = DEVICE(obj); > + Error *local_err = NULL; > + void **ptr = qdev_get_prop_ptr(dev, prop); > + char *str; > + int ret; > + > + if (dev->state != DEV_STATE_CREATED) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_str(v, &str, name, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + if (!*str) { > + g_free(str); > + *ptr = NULL; > + return; > + } > + ret = parse(dev, str, ptr); > + error_set_from_qdev_prop_error(errp, ret, dev, prop, str); > + g_free(str); > +} > + > +/* --- drive --- */ > + > +static int parse_drive(DeviceState *dev, const char *str, void **ptr) > +{ > + BlockDriverState *bs; > + > + bs = bdrv_find(str); > + if (bs == NULL) > + return -ENOENT; > + if (bdrv_attach_dev(bs, dev) < 0) > + return -EEXIST; > + *ptr = bs; > + return 0; > +} > + > +static void release_drive(Object *obj, const char *name, void *opaque) > +{ > + DeviceState *dev = DEVICE(obj); > + Property *prop = opaque; > + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); > + > + if (*ptr) { > + bdrv_detach_dev(*ptr, dev); > + blockdev_auto_del(*ptr); > + } > +} > + > +static const char *print_drive(void *ptr) > +{ > + return bdrv_get_device_name(ptr); > +} > + > +static void get_drive(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + get_pointer(obj, v, opaque, print_drive, name, errp); > +} > + > +static void set_drive(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + set_pointer(obj, v, opaque, parse_drive, name, errp); > +} > + > +PropertyInfo qdev_prop_drive = { > + .name = "drive", > + .get = get_drive, > + .set = set_drive, > + .release = release_drive, > +}; > + > +/* --- character device --- */ > + > +static int parse_chr(DeviceState *dev, const char *str, void **ptr) > +{ > + CharDriverState *chr = qemu_chr_find(str); > + if (chr == NULL) { > + return -ENOENT; > + } > + if (chr->avail_connections < 1) { > + return -EEXIST; > + } > + *ptr = chr; > + --chr->avail_connections; > + return 0; > +} > + > +static void release_chr(Object *obj, const char *name, void *opaque) > +{ > + DeviceState *dev = DEVICE(obj); > + Property *prop = opaque; > + CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); > + > + if (*ptr) { > + qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); > + } > +} > + > + > +static const char *print_chr(void *ptr) > +{ > + CharDriverState *chr = ptr; > + > + return chr->label ? chr->label : ""; > +} > + > +static void get_chr(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + get_pointer(obj, v, opaque, print_chr, name, errp); > +} > + > +static void set_chr(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + set_pointer(obj, v, opaque, parse_chr, name, errp); > +} > + > +PropertyInfo qdev_prop_chr = { > + .name = "chr", > + .get = get_chr, > + .set = set_chr, > + .release = release_chr, > +}; > + > +/* --- netdev device --- */ > + > +static int parse_netdev(DeviceState *dev, const char *str, void **ptr) > +{ > + NetClientState *netdev = qemu_find_netdev(str); > + > + if (netdev == NULL) { > + return -ENOENT; > + } > + if (netdev->peer) { > + return -EEXIST; > + } > + *ptr = netdev; > + return 0; > +} > + > +static const char *print_netdev(void *ptr) > +{ > + NetClientState *netdev = ptr; > + > + return netdev->name ? netdev->name : ""; > +} > + > +static void get_netdev(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + get_pointer(obj, v, opaque, print_netdev, name, errp); > +} > + > +static void set_netdev(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + set_pointer(obj, v, opaque, parse_netdev, name, errp); > +} > + > +PropertyInfo qdev_prop_netdev = { > + .name = "netdev", > + .get = get_netdev, > + .set = set_netdev, > +}; > + > +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) > +{ > + qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); > + if (nd->netdev) > + qdev_prop_set_netdev(dev, "netdev", nd->netdev); > + if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && > + object_property_find(OBJECT(dev), "vectors", NULL)) { > + qdev_prop_set_uint32(dev, "vectors", nd->nvectors); > + } > + nd->instantiated = 1; > +} > + > +/* --- vlan --- */ > + > +static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) > +{ > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > + > + if (*ptr) { > + int id; > + if (!net_hub_id_for_client(*ptr, &id)) { > + return snprintf(dest, len, "%d", id); > + } > + } > + > + return snprintf(dest, len, "<null>"); > +} > + > +static void get_vlan(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + DeviceState *dev = DEVICE(obj); > + Property *prop = opaque; > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > + int32_t id = -1; > + > + if (*ptr) { > + int hub_id; > + if (!net_hub_id_for_client(*ptr, &hub_id)) { > + id = hub_id; > + } > + } > + > + visit_type_int32(v, &id, name, errp); > +} > + > +static void set_vlan(Object *obj, Visitor *v, void *opaque, > + const char *name, Error **errp) > +{ > + DeviceState *dev = DEVICE(obj); > + Property *prop = opaque; > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > + Error *local_err = NULL; > + int32_t id; > + NetClientState *hubport; > + > + if (dev->state != DEV_STATE_CREATED) { > + error_set(errp, QERR_PERMISSION_DENIED); > + return; > + } > + > + visit_type_int32(v, &id, name, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + if (id == -1) { > + *ptr = NULL; > + return; > + } > + > + hubport = net_hub_port_find(id); > + if (!hubport) { > + error_set(errp, QERR_INVALID_PARAMETER_VALUE, > + name, prop->info->name); > + return; > + } > + *ptr = hubport; > +} > + > +PropertyInfo qdev_prop_vlan = { > + .name = "vlan", > + .print = print_vlan, > + .get = get_vlan, > + .set = set_vlan, > +}; > + > + > +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) > +{ > + Error *errp = NULL; > + const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; > + object_property_set_str(OBJECT(dev), bdrv_name, > + name, &errp); > + if (errp) { > + qerror_report_err(errp); > + error_free(errp); > + return -1; > + } > + return 0; > +} > + > +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) > +{ > + if (qdev_prop_set_drive(dev, name, value) < 0) { > + exit(1); > + } > +} > + > +void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) > +{ > + Error *errp = NULL; > + assert(!value || value->label); > + object_property_set_str(OBJECT(dev), > + value ? value->label : "", name, &errp); > + assert_no_error(errp); > +} > + > +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) > +{ > + Error *errp = NULL; > + assert(!value || value->name); > + object_property_set_str(OBJECT(dev), > + value ? value->name : "", name, &errp); > + assert_no_error(errp); > +} > + > +static int qdev_add_one_global(QemuOpts *opts, void *opaque) > +{ > + GlobalProperty *g; > + > + g = g_malloc0(sizeof(*g)); > + g->driver = qemu_opt_get(opts, "driver"); > + g->property = qemu_opt_get(opts, "property"); > + g->value = qemu_opt_get(opts, "value"); > + qdev_prop_register_global(g); > + return 0; > +} > + > +void qemu_add_globals(void) > +{ > + qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); > +} > diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c > index 81d901c..917d986 100644 > --- a/hw/qdev-properties.c > +++ b/hw/qdev-properties.c > @@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) > return ptr; > } > > -static void get_pointer(Object *obj, Visitor *v, Property *prop, > - const char *(*print)(void *ptr), > - const char *name, Error **errp) > -{ > - DeviceState *dev = DEVICE(obj); > - void **ptr = qdev_get_prop_ptr(dev, prop); > - char *p; > - > - p = (char *) (*ptr ? print(*ptr) : ""); > - visit_type_str(v, &p, name, errp); > -} > - > -static void set_pointer(Object *obj, Visitor *v, Property *prop, > - int (*parse)(DeviceState *dev, const char *str, > - void **ptr), > - const char *name, Error **errp) > -{ > - DeviceState *dev = DEVICE(obj); > - Error *local_err = NULL; > - void **ptr = qdev_get_prop_ptr(dev, prop); > - char *str; > - int ret; > - > - if (dev->state != DEV_STATE_CREATED) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_str(v, &str, name, &local_err); > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - if (!*str) { > - g_free(str); > - *ptr = NULL; > - return; > - } > - ret = parse(dev, str, ptr); > - error_set_from_qdev_prop_error(errp, ret, dev, prop, str); > - g_free(str); > -} > - > static void get_enum(Object *obj, Visitor *v, void *opaque, > const char *name, Error **errp) > { > @@ -476,227 +433,6 @@ PropertyInfo qdev_prop_string = { > .set = set_string, > }; > > -/* --- drive --- */ > - > -static int parse_drive(DeviceState *dev, const char *str, void **ptr) > -{ > - BlockDriverState *bs; > - > - bs = bdrv_find(str); > - if (bs == NULL) > - return -ENOENT; > - if (bdrv_attach_dev(bs, dev) < 0) > - return -EEXIST; > - *ptr = bs; > - return 0; > -} > - > -static void release_drive(Object *obj, const char *name, void *opaque) > -{ > - DeviceState *dev = DEVICE(obj); > - Property *prop = opaque; > - BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); > - > - if (*ptr) { > - bdrv_detach_dev(*ptr, dev); > - blockdev_auto_del(*ptr); > - } > -} > - > -static const char *print_drive(void *ptr) > -{ > - return bdrv_get_device_name(ptr); > -} > - > -static void get_drive(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - get_pointer(obj, v, opaque, print_drive, name, errp); > -} > - > -static void set_drive(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - set_pointer(obj, v, opaque, parse_drive, name, errp); > -} > - > -PropertyInfo qdev_prop_drive = { > - .name = "drive", > - .get = get_drive, > - .set = set_drive, > - .release = release_drive, > -}; > - > -/* --- character device --- */ > - > -static int parse_chr(DeviceState *dev, const char *str, void **ptr) > -{ > - CharDriverState *chr = qemu_chr_find(str); > - if (chr == NULL) { > - return -ENOENT; > - } > - if (chr->avail_connections < 1) { > - return -EEXIST; > - } > - *ptr = chr; > - --chr->avail_connections; > - return 0; > -} > - > -static void release_chr(Object *obj, const char *name, void *opaque) > -{ > - DeviceState *dev = DEVICE(obj); > - Property *prop = opaque; > - CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); > - > - if (*ptr) { > - qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); > - } > -} > - > - > -static const char *print_chr(void *ptr) > -{ > - CharDriverState *chr = ptr; > - > - return chr->label ? chr->label : ""; > -} > - > -static void get_chr(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - get_pointer(obj, v, opaque, print_chr, name, errp); > -} > - > -static void set_chr(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - set_pointer(obj, v, opaque, parse_chr, name, errp); > -} > - > -PropertyInfo qdev_prop_chr = { > - .name = "chr", > - .get = get_chr, > - .set = set_chr, > - .release = release_chr, > -}; > - > -/* --- netdev device --- */ > - > -static int parse_netdev(DeviceState *dev, const char *str, void **ptr) > -{ > - NetClientState *netdev = qemu_find_netdev(str); > - > - if (netdev == NULL) { > - return -ENOENT; > - } > - if (netdev->peer) { > - return -EEXIST; > - } > - *ptr = netdev; > - return 0; > -} > - > -static const char *print_netdev(void *ptr) > -{ > - NetClientState *netdev = ptr; > - > - return netdev->name ? netdev->name : ""; > -} > - > -static void get_netdev(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - get_pointer(obj, v, opaque, print_netdev, name, errp); > -} > - > -static void set_netdev(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - set_pointer(obj, v, opaque, parse_netdev, name, errp); > -} > - > -PropertyInfo qdev_prop_netdev = { > - .name = "netdev", > - .get = get_netdev, > - .set = set_netdev, > -}; > - > -/* --- vlan --- */ > - > -static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) > -{ > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > - > - if (*ptr) { > - int id; > - if (!net_hub_id_for_client(*ptr, &id)) { > - return snprintf(dest, len, "%d", id); > - } > - } > - > - return snprintf(dest, len, "<null>"); > -} > - > -static void get_vlan(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - DeviceState *dev = DEVICE(obj); > - Property *prop = opaque; > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > - int32_t id = -1; > - > - if (*ptr) { > - int hub_id; > - if (!net_hub_id_for_client(*ptr, &hub_id)) { > - id = hub_id; > - } > - } > - > - visit_type_int32(v, &id, name, errp); > -} > - > -static void set_vlan(Object *obj, Visitor *v, void *opaque, > - const char *name, Error **errp) > -{ > - DeviceState *dev = DEVICE(obj); > - Property *prop = opaque; > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > - Error *local_err = NULL; > - int32_t id; > - NetClientState *hubport; > - > - if (dev->state != DEV_STATE_CREATED) { > - error_set(errp, QERR_PERMISSION_DENIED); > - return; > - } > - > - visit_type_int32(v, &id, name, &local_err); > - if (local_err) { > - error_propagate(errp, local_err); > - return; > - } > - if (id == -1) { > - *ptr = NULL; > - return; > - } > - > - hubport = net_hub_port_find(id); > - if (!hubport) { > - error_set(errp, QERR_INVALID_PARAMETER_VALUE, > - name, prop->info->name); > - return; > - } > - *ptr = hubport; > -} > - > -PropertyInfo qdev_prop_vlan = { > - .name = "vlan", > - .print = print_vlan, > - .get = get_vlan, > - .set = set_vlan, > -}; > - > /* --- pointer --- */ > > /* Not a proper property, just for dirty hacks. TODO Remove it! */ > @@ -1158,44 +894,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) > assert_no_error(errp); > } > > -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) > -{ > - Error *errp = NULL; > - const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; > - object_property_set_str(OBJECT(dev), bdrv_name, > - name, &errp); > - if (errp) { > - qerror_report_err(errp); > - error_free(errp); > - return -1; > - } > - return 0; > -} > - > -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) > -{ > - if (qdev_prop_set_drive(dev, name, value) < 0) { > - exit(1); > - } > -} > -void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) > -{ > - Error *errp = NULL; > - assert(!value || value->label); > - object_property_set_str(OBJECT(dev), > - value ? value->label : "", name, &errp); > - assert_no_error(errp); > -} > - > -void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) > -{ > - Error *errp = NULL; > - assert(!value || value->name); > - object_property_set_str(OBJECT(dev), > - value ? value->name : "", name, &errp); > - assert_no_error(errp); > -} > - > void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) > { > Error *errp = NULL; > @@ -1231,7 +929,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) > > static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); > > -static void qdev_prop_register_global(GlobalProperty *prop) > +void qdev_prop_register_global(GlobalProperty *prop) > { > QTAILQ_INSERT_TAIL(&global_props, prop, next); > } > @@ -1263,19 +961,3 @@ void qdev_prop_set_globals(DeviceState *dev) > } while (class); > } > > -static int qdev_add_one_global(QemuOpts *opts, void *opaque) > -{ > - GlobalProperty *g; > - > - g = g_malloc0(sizeof(*g)); > - g->driver = qemu_opt_get(opts, "driver"); > - g->property = qemu_opt_get(opts, "property"); > - g->value = qemu_opt_get(opts, "value"); > - qdev_prop_register_global(g); > - return 0; > -} > - > -void qemu_add_globals(void) > -{ > - qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); > -} > diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h > index 5b046ab..ddcf774 100644 > --- a/hw/qdev-properties.h > +++ b/hw/qdev-properties.h > @@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); > /* FIXME: Remove opaque pointer properties. */ > void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); > > +void qdev_prop_register_global(GlobalProperty *prop); > void qdev_prop_register_global_list(GlobalProperty *props); > void qdev_prop_set_globals(DeviceState *dev); > void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, > diff --git a/hw/qdev-system.c b/hw/qdev-system.c > new file mode 100644 > index 0000000..490821f > --- /dev/null > +++ b/hw/qdev-system.c > @@ -0,0 +1,68 @@ > +#include "qdev.h" > + > +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > +{ > + assert(dev->num_gpio_in == 0); > + dev->num_gpio_in = n; > + dev->gpio_in = qemu_allocate_irqs(handler, dev, n); > +} > + > +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) > +{ > + assert(dev->num_gpio_out == 0); > + dev->num_gpio_out = n; > + dev->gpio_out = pins; > +} > + > +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) > +{ > + assert(n >= 0 && n < dev->num_gpio_in); > + return dev->gpio_in[n]; > +} > + > +void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) > +{ > + assert(n >= 0 && n < dev->num_gpio_out); > + dev->gpio_out[n] = pin; > +} > + > +/* Create a new device. This only initializes the device state structure > + and allows properties to be set. qdev_init should be called to > + initialize the actual device emulation. */ > +DeviceState *qdev_create(BusState *bus, const char *name) > +{ > + DeviceState *dev; > + > + dev = qdev_try_create(bus, name); > + if (!dev) { > + if (bus) { > + hw_error("Unknown device '%s' for bus '%s'\n", name, > + object_get_typename(OBJECT(bus))); > + } else { > + hw_error("Unknown device '%s' for default sysbus\n", name); > + } > + } > + > + return dev; > +} > + > +DeviceState *qdev_try_create(BusState *bus, const char *type) > +{ > + DeviceState *dev; > + > + if (object_class_by_name(type) == NULL) { > + return NULL; > + } > + dev = DEVICE(object_new(type)); > + if (!dev) { > + return NULL; > + } > + > + if (!bus) { > + bus = sysbus_get_default(); > + } > + > + qdev_set_parent_bus(dev, bus); > + > + return dev; > +} > diff --git a/hw/qdev.c b/hw/qdev.c > index 7ddcd24..ee19dd5 100644 > --- a/hw/qdev.c > +++ b/hw/qdev.c > @@ -25,7 +25,6 @@ > inherit from a particular bus (e.g. PCI or I2C) rather than > this API directly. */ > > -#include "net.h" > #include "qdev.h" > #include "sysemu.h" > #include "error.h" > @@ -99,47 +98,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) > bus_add_child(bus, dev); > } > > -/* Create a new device. This only initializes the device state structure > - and allows properties to be set. qdev_init should be called to > - initialize the actual device emulation. */ > -DeviceState *qdev_create(BusState *bus, const char *name) > -{ > - DeviceState *dev; > - > - dev = qdev_try_create(bus, name); > - if (!dev) { > - if (bus) { > - hw_error("Unknown device '%s' for bus '%s'\n", name, > - object_get_typename(OBJECT(bus))); > - } else { > - hw_error("Unknown device '%s' for default sysbus\n", name); > - } > - } > - > - return dev; > -} > - > -DeviceState *qdev_try_create(BusState *bus, const char *type) > -{ > - DeviceState *dev; > - > - if (object_class_by_name(type) == NULL) { > - return NULL; > - } > - dev = DEVICE(object_new(type)); > - if (!dev) { > - return NULL; > - } > - > - if (!bus) { > - bus = sysbus_get_default(); > - } > - > - qdev_set_parent_bus(dev, bus); > - > - return dev; > -} > - > /* Initialize a device. Device properties should be set before calling > this function. IRQs and MMIO regions should be connected/mapped after > calling this function. > @@ -284,44 +242,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev) > return dev->parent_bus; > } > > -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > -{ > - dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, > - dev, n); > - dev->num_gpio_in += n; > -} > - > -void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) > -{ > - assert(dev->num_gpio_out == 0); > - dev->num_gpio_out = n; > - dev->gpio_out = pins; > -} > - > -qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) > -{ > - assert(n >= 0 && n < dev->num_gpio_in); > - return dev->gpio_in[n]; > -} > - > -void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) > -{ > - assert(n >= 0 && n < dev->num_gpio_out); > - dev->gpio_out[n] = pin; > -} > - > -void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) > -{ > - qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); > - if (nd->netdev) > - qdev_prop_set_netdev(dev, "netdev", nd->netdev); > - if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && > - object_property_find(OBJECT(dev), "vectors", NULL)) { > - qdev_prop_set_uint32(dev, "vectors", nd->nvectors); > - } > - nd->instantiated = 1; > -} > - > BusState *qdev_get_child_bus(DeviceState *dev, const char *name) > { > BusState *bus; > -- > 1.7.11.7
On Wed, Oct 17, 2012 at 01:00:55PM -0500, Anthony Liguori wrote: > Igor Mammedov <imammedo@redhat.com> writes: > > > From: Eduardo Habkost <ehabkost@redhat.com> > > > > This change should help on two things: > > - Allowing DeviceState to be used by *-user; > > - Writing qdev unit tests without pulling too many dependencies. > > > > Note that there are two parts that depend on code compiled only on > > qemu-system-*, but are still inside qdev.c: > > - vmstate handling > > - reset function registration. > > > > Those two parts will be handled later, by moving that code to > > qdev-system.c but keeping weak symbols for *-user. > > > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > > --- > > [imammedo: keep qdev_get_child_bus() in hw/qdev.c] > > [imammedo: put qdev_set_nic_properties() in hw/qdev-properties-system.c] > > --- > > hw/Makefile.objs | 1 + > > hw/qdev-properties-system.c | 340 ++++++++++++++++++++++++++++++++++++++++++++ > > hw/qdev-properties.c | 320 +---------------------------------------- > > hw/qdev-properties.h | 1 + > > hw/qdev-system.c | 68 +++++++++ > > hw/qdev.c | 80 ----------- > > 6 files changed, 411 insertions(+), 399 deletions(-) > > create mode 100644 hw/qdev-properties-system.c > > create mode 100644 hw/qdev-system.c > > > > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > > index 854faa9..16f23c0 100644 > > --- a/hw/Makefile.objs > > +++ b/hw/Makefile.objs > > @@ -181,6 +181,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o > > common-obj-y += bt-hci-csr.o > > common-obj-y += msmouse.o ps2.o > > common-obj-y += qdev.o qdev-properties.o qdev-monitor.o > > +common-obj-y += qdev-system.o qdev-properties-system.o > > common-obj-$(CONFIG_BRLAPI) += baum.o > > > > # xen backend driver support > > diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c > > new file mode 100644 > > index 0000000..e3a21db > > --- /dev/null > > +++ b/hw/qdev-properties-system.c > > @@ -0,0 +1,340 @@ > > New files should carry copyright/licenses. Figuring out the copyright of qdev-properties.c (where the qdev-properties-system.c code is coming from) will be fun... I will check the git logs and see what I can find out. BTW, what's supposed to be the license of files that don't have any license information today? > > I don't really understand the split here and the 'system' suffix really > doesn't explain it for me. Could you at least add a comment to each of > these files explaining what belongs in them? "system" here means "Code used only by qemu-system-*" (in other words, not used by *-user, and not part of the qdev core). Do you have other name suggestions? The goal here is to make qdev-core.c/qdev-properties as small as possible (only what's absolutely required for the CPU classes), and put everything else (that's only used by qemu-system-*) into qdev-system.c/qdev-properties-system.c. > > Regards, > > Anthony Liguori > > > +#include "net.h" > > +#include "qdev.h" > > +#include "qerror.h" > > +#include "blockdev.h" > > +#include "hw/block-common.h" > > +#include "net/hub.h" > > +#include "qapi/qapi-visit-core.h" > > + > > +static void get_pointer(Object *obj, Visitor *v, Property *prop, > > + const char *(*print)(void *ptr), > > + const char *name, Error **errp) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + void **ptr = qdev_get_prop_ptr(dev, prop); > > + char *p; > > + > > + p = (char *) (*ptr ? print(*ptr) : ""); > > + visit_type_str(v, &p, name, errp); > > +} > > + > > +static void set_pointer(Object *obj, Visitor *v, Property *prop, > > + int (*parse)(DeviceState *dev, const char *str, > > + void **ptr), > > + const char *name, Error **errp) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + Error *local_err = NULL; > > + void **ptr = qdev_get_prop_ptr(dev, prop); > > + char *str; > > + int ret; > > + > > + if (dev->state != DEV_STATE_CREATED) { > > + error_set(errp, QERR_PERMISSION_DENIED); > > + return; > > + } > > + > > + visit_type_str(v, &str, name, &local_err); > > + if (local_err) { > > + error_propagate(errp, local_err); > > + return; > > + } > > + if (!*str) { > > + g_free(str); > > + *ptr = NULL; > > + return; > > + } > > + ret = parse(dev, str, ptr); > > + error_set_from_qdev_prop_error(errp, ret, dev, prop, str); > > + g_free(str); > > +} > > + > > +/* --- drive --- */ > > + > > +static int parse_drive(DeviceState *dev, const char *str, void **ptr) > > +{ > > + BlockDriverState *bs; > > + > > + bs = bdrv_find(str); > > + if (bs == NULL) > > + return -ENOENT; > > + if (bdrv_attach_dev(bs, dev) < 0) > > + return -EEXIST; > > + *ptr = bs; > > + return 0; > > +} > > + > > +static void release_drive(Object *obj, const char *name, void *opaque) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + Property *prop = opaque; > > + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); > > + > > + if (*ptr) { > > + bdrv_detach_dev(*ptr, dev); > > + blockdev_auto_del(*ptr); > > + } > > +} > > + > > +static const char *print_drive(void *ptr) > > +{ > > + return bdrv_get_device_name(ptr); > > +} > > + > > +static void get_drive(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + get_pointer(obj, v, opaque, print_drive, name, errp); > > +} > > + > > +static void set_drive(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + set_pointer(obj, v, opaque, parse_drive, name, errp); > > +} > > + > > +PropertyInfo qdev_prop_drive = { > > + .name = "drive", > > + .get = get_drive, > > + .set = set_drive, > > + .release = release_drive, > > +}; > > + > > +/* --- character device --- */ > > + > > +static int parse_chr(DeviceState *dev, const char *str, void **ptr) > > +{ > > + CharDriverState *chr = qemu_chr_find(str); > > + if (chr == NULL) { > > + return -ENOENT; > > + } > > + if (chr->avail_connections < 1) { > > + return -EEXIST; > > + } > > + *ptr = chr; > > + --chr->avail_connections; > > + return 0; > > +} > > + > > +static void release_chr(Object *obj, const char *name, void *opaque) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + Property *prop = opaque; > > + CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); > > + > > + if (*ptr) { > > + qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); > > + } > > +} > > + > > + > > +static const char *print_chr(void *ptr) > > +{ > > + CharDriverState *chr = ptr; > > + > > + return chr->label ? chr->label : ""; > > +} > > + > > +static void get_chr(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + get_pointer(obj, v, opaque, print_chr, name, errp); > > +} > > + > > +static void set_chr(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + set_pointer(obj, v, opaque, parse_chr, name, errp); > > +} > > + > > +PropertyInfo qdev_prop_chr = { > > + .name = "chr", > > + .get = get_chr, > > + .set = set_chr, > > + .release = release_chr, > > +}; > > + > > +/* --- netdev device --- */ > > + > > +static int parse_netdev(DeviceState *dev, const char *str, void **ptr) > > +{ > > + NetClientState *netdev = qemu_find_netdev(str); > > + > > + if (netdev == NULL) { > > + return -ENOENT; > > + } > > + if (netdev->peer) { > > + return -EEXIST; > > + } > > + *ptr = netdev; > > + return 0; > > +} > > + > > +static const char *print_netdev(void *ptr) > > +{ > > + NetClientState *netdev = ptr; > > + > > + return netdev->name ? netdev->name : ""; > > +} > > + > > +static void get_netdev(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + get_pointer(obj, v, opaque, print_netdev, name, errp); > > +} > > + > > +static void set_netdev(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + set_pointer(obj, v, opaque, parse_netdev, name, errp); > > +} > > + > > +PropertyInfo qdev_prop_netdev = { > > + .name = "netdev", > > + .get = get_netdev, > > + .set = set_netdev, > > +}; > > + > > +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) > > +{ > > + qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); > > + if (nd->netdev) > > + qdev_prop_set_netdev(dev, "netdev", nd->netdev); > > + if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && > > + object_property_find(OBJECT(dev), "vectors", NULL)) { > > + qdev_prop_set_uint32(dev, "vectors", nd->nvectors); > > + } > > + nd->instantiated = 1; > > +} > > + > > +/* --- vlan --- */ > > + > > +static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) > > +{ > > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > + > > + if (*ptr) { > > + int id; > > + if (!net_hub_id_for_client(*ptr, &id)) { > > + return snprintf(dest, len, "%d", id); > > + } > > + } > > + > > + return snprintf(dest, len, "<null>"); > > +} > > + > > +static void get_vlan(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + Property *prop = opaque; > > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > + int32_t id = -1; > > + > > + if (*ptr) { > > + int hub_id; > > + if (!net_hub_id_for_client(*ptr, &hub_id)) { > > + id = hub_id; > > + } > > + } > > + > > + visit_type_int32(v, &id, name, errp); > > +} > > + > > +static void set_vlan(Object *obj, Visitor *v, void *opaque, > > + const char *name, Error **errp) > > +{ > > + DeviceState *dev = DEVICE(obj); > > + Property *prop = opaque; > > + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > + Error *local_err = NULL; > > + int32_t id; > > + NetClientState *hubport; > > + > > + if (dev->state != DEV_STATE_CREATED) { > > + error_set(errp, QERR_PERMISSION_DENIED); > > + return; > > + } > > + > > + visit_type_int32(v, &id, name, &local_err); > > + if (local_err) { > > + error_propagate(errp, local_err); > > + return; > > + } > > + if (id == -1) { > > + *ptr = NULL; > > + return; > > + } > > + > > + hubport = net_hub_port_find(id); > > + if (!hubport) { > > + error_set(errp, QERR_INVALID_PARAMETER_VALUE, > > + name, prop->info->name); > > + return; > > + } > > + *ptr = hubport; > > +} > > + > > +PropertyInfo qdev_prop_vlan = { > > + .name = "vlan", > > + .print = print_vlan, > > + .get = get_vlan, > > + .set = set_vlan, > > +}; > > + > > + > > +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) > > +{ > > + Error *errp = NULL; > > + const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; > > + object_property_set_str(OBJECT(dev), bdrv_name, > > + name, &errp); > > + if (errp) { > > + qerror_report_err(errp); > > + error_free(errp); > > + return -1; > > + } > > + return 0; > > +} > > + > > +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) > > +{ > > + if (qdev_prop_set_drive(dev, name, value) < 0) { > > + exit(1); > > + } > > +} > > + > > +void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) > > +{ > > + Error *errp = NULL; > > + assert(!value || value->label); > > + object_property_set_str(OBJECT(dev), > > + value ? value->label : "", name, &errp); > > + assert_no_error(errp); > > +} > > + > > +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) > > +{ > > + Error *errp = NULL; > > + assert(!value || value->name); > > + object_property_set_str(OBJECT(dev), > > + value ? value->name : "", name, &errp); > > + assert_no_error(errp); > > +} > > + > > +static int qdev_add_one_global(QemuOpts *opts, void *opaque) > > +{ > > + GlobalProperty *g; > > + > > + g = g_malloc0(sizeof(*g)); > > + g->driver = qemu_opt_get(opts, "driver"); > > + g->property = qemu_opt_get(opts, "property"); > > + g->value = qemu_opt_get(opts, "value"); > > + qdev_prop_register_global(g); > > + return 0; > > +} > > + > > +void qemu_add_globals(void) > > +{ > > + qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); > > +} > > diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c > > index 81d901c..917d986 100644 > > --- a/hw/qdev-properties.c > > +++ b/hw/qdev-properties.c > > @@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) > > return ptr; > > } > > > > -static void get_pointer(Object *obj, Visitor *v, Property *prop, > > - const char *(*print)(void *ptr), > > - const char *name, Error **errp) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - void **ptr = qdev_get_prop_ptr(dev, prop); > > - char *p; > > - > > - p = (char *) (*ptr ? print(*ptr) : ""); > > - visit_type_str(v, &p, name, errp); > > -} > > - > > -static void set_pointer(Object *obj, Visitor *v, Property *prop, > > - int (*parse)(DeviceState *dev, const char *str, > > - void **ptr), > > - const char *name, Error **errp) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - Error *local_err = NULL; > > - void **ptr = qdev_get_prop_ptr(dev, prop); > > - char *str; > > - int ret; > > - > > - if (dev->state != DEV_STATE_CREATED) { > > - error_set(errp, QERR_PERMISSION_DENIED); > > - return; > > - } > > - > > - visit_type_str(v, &str, name, &local_err); > > - if (local_err) { > > - error_propagate(errp, local_err); > > - return; > > - } > > - if (!*str) { > > - g_free(str); > > - *ptr = NULL; > > - return; > > - } > > - ret = parse(dev, str, ptr); > > - error_set_from_qdev_prop_error(errp, ret, dev, prop, str); > > - g_free(str); > > -} > > - > > static void get_enum(Object *obj, Visitor *v, void *opaque, > > const char *name, Error **errp) > > { > > @@ -476,227 +433,6 @@ PropertyInfo qdev_prop_string = { > > .set = set_string, > > }; > > > > -/* --- drive --- */ > > - > > -static int parse_drive(DeviceState *dev, const char *str, void **ptr) > > -{ > > - BlockDriverState *bs; > > - > > - bs = bdrv_find(str); > > - if (bs == NULL) > > - return -ENOENT; > > - if (bdrv_attach_dev(bs, dev) < 0) > > - return -EEXIST; > > - *ptr = bs; > > - return 0; > > -} > > - > > -static void release_drive(Object *obj, const char *name, void *opaque) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - Property *prop = opaque; > > - BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); > > - > > - if (*ptr) { > > - bdrv_detach_dev(*ptr, dev); > > - blockdev_auto_del(*ptr); > > - } > > -} > > - > > -static const char *print_drive(void *ptr) > > -{ > > - return bdrv_get_device_name(ptr); > > -} > > - > > -static void get_drive(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - get_pointer(obj, v, opaque, print_drive, name, errp); > > -} > > - > > -static void set_drive(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - set_pointer(obj, v, opaque, parse_drive, name, errp); > > -} > > - > > -PropertyInfo qdev_prop_drive = { > > - .name = "drive", > > - .get = get_drive, > > - .set = set_drive, > > - .release = release_drive, > > -}; > > - > > -/* --- character device --- */ > > - > > -static int parse_chr(DeviceState *dev, const char *str, void **ptr) > > -{ > > - CharDriverState *chr = qemu_chr_find(str); > > - if (chr == NULL) { > > - return -ENOENT; > > - } > > - if (chr->avail_connections < 1) { > > - return -EEXIST; > > - } > > - *ptr = chr; > > - --chr->avail_connections; > > - return 0; > > -} > > - > > -static void release_chr(Object *obj, const char *name, void *opaque) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - Property *prop = opaque; > > - CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); > > - > > - if (*ptr) { > > - qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); > > - } > > -} > > - > > - > > -static const char *print_chr(void *ptr) > > -{ > > - CharDriverState *chr = ptr; > > - > > - return chr->label ? chr->label : ""; > > -} > > - > > -static void get_chr(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - get_pointer(obj, v, opaque, print_chr, name, errp); > > -} > > - > > -static void set_chr(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - set_pointer(obj, v, opaque, parse_chr, name, errp); > > -} > > - > > -PropertyInfo qdev_prop_chr = { > > - .name = "chr", > > - .get = get_chr, > > - .set = set_chr, > > - .release = release_chr, > > -}; > > - > > -/* --- netdev device --- */ > > - > > -static int parse_netdev(DeviceState *dev, const char *str, void **ptr) > > -{ > > - NetClientState *netdev = qemu_find_netdev(str); > > - > > - if (netdev == NULL) { > > - return -ENOENT; > > - } > > - if (netdev->peer) { > > - return -EEXIST; > > - } > > - *ptr = netdev; > > - return 0; > > -} > > - > > -static const char *print_netdev(void *ptr) > > -{ > > - NetClientState *netdev = ptr; > > - > > - return netdev->name ? netdev->name : ""; > > -} > > - > > -static void get_netdev(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - get_pointer(obj, v, opaque, print_netdev, name, errp); > > -} > > - > > -static void set_netdev(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - set_pointer(obj, v, opaque, parse_netdev, name, errp); > > -} > > - > > -PropertyInfo qdev_prop_netdev = { > > - .name = "netdev", > > - .get = get_netdev, > > - .set = set_netdev, > > -}; > > - > > -/* --- vlan --- */ > > - > > -static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) > > -{ > > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > - > > - if (*ptr) { > > - int id; > > - if (!net_hub_id_for_client(*ptr, &id)) { > > - return snprintf(dest, len, "%d", id); > > - } > > - } > > - > > - return snprintf(dest, len, "<null>"); > > -} > > - > > -static void get_vlan(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - Property *prop = opaque; > > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > - int32_t id = -1; > > - > > - if (*ptr) { > > - int hub_id; > > - if (!net_hub_id_for_client(*ptr, &hub_id)) { > > - id = hub_id; > > - } > > - } > > - > > - visit_type_int32(v, &id, name, errp); > > -} > > - > > -static void set_vlan(Object *obj, Visitor *v, void *opaque, > > - const char *name, Error **errp) > > -{ > > - DeviceState *dev = DEVICE(obj); > > - Property *prop = opaque; > > - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); > > - Error *local_err = NULL; > > - int32_t id; > > - NetClientState *hubport; > > - > > - if (dev->state != DEV_STATE_CREATED) { > > - error_set(errp, QERR_PERMISSION_DENIED); > > - return; > > - } > > - > > - visit_type_int32(v, &id, name, &local_err); > > - if (local_err) { > > - error_propagate(errp, local_err); > > - return; > > - } > > - if (id == -1) { > > - *ptr = NULL; > > - return; > > - } > > - > > - hubport = net_hub_port_find(id); > > - if (!hubport) { > > - error_set(errp, QERR_INVALID_PARAMETER_VALUE, > > - name, prop->info->name); > > - return; > > - } > > - *ptr = hubport; > > -} > > - > > -PropertyInfo qdev_prop_vlan = { > > - .name = "vlan", > > - .print = print_vlan, > > - .get = get_vlan, > > - .set = set_vlan, > > -}; > > - > > /* --- pointer --- */ > > > > /* Not a proper property, just for dirty hacks. TODO Remove it! */ > > @@ -1158,44 +894,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) > > assert_no_error(errp); > > } > > > > -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) > > -{ > > - Error *errp = NULL; > > - const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; > > - object_property_set_str(OBJECT(dev), bdrv_name, > > - name, &errp); > > - if (errp) { > > - qerror_report_err(errp); > > - error_free(errp); > > - return -1; > > - } > > - return 0; > > -} > > - > > -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) > > -{ > > - if (qdev_prop_set_drive(dev, name, value) < 0) { > > - exit(1); > > - } > > -} > > -void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) > > -{ > > - Error *errp = NULL; > > - assert(!value || value->label); > > - object_property_set_str(OBJECT(dev), > > - value ? value->label : "", name, &errp); > > - assert_no_error(errp); > > -} > > - > > -void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) > > -{ > > - Error *errp = NULL; > > - assert(!value || value->name); > > - object_property_set_str(OBJECT(dev), > > - value ? value->name : "", name, &errp); > > - assert_no_error(errp); > > -} > > - > > void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) > > { > > Error *errp = NULL; > > @@ -1231,7 +929,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) > > > > static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); > > > > -static void qdev_prop_register_global(GlobalProperty *prop) > > +void qdev_prop_register_global(GlobalProperty *prop) > > { > > QTAILQ_INSERT_TAIL(&global_props, prop, next); > > } > > @@ -1263,19 +961,3 @@ void qdev_prop_set_globals(DeviceState *dev) > > } while (class); > > } > > > > -static int qdev_add_one_global(QemuOpts *opts, void *opaque) > > -{ > > - GlobalProperty *g; > > - > > - g = g_malloc0(sizeof(*g)); > > - g->driver = qemu_opt_get(opts, "driver"); > > - g->property = qemu_opt_get(opts, "property"); > > - g->value = qemu_opt_get(opts, "value"); > > - qdev_prop_register_global(g); > > - return 0; > > -} > > - > > -void qemu_add_globals(void) > > -{ > > - qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); > > -} > > diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h > > index 5b046ab..ddcf774 100644 > > --- a/hw/qdev-properties.h > > +++ b/hw/qdev-properties.h > > @@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); > > /* FIXME: Remove opaque pointer properties. */ > > void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); > > > > +void qdev_prop_register_global(GlobalProperty *prop); > > void qdev_prop_register_global_list(GlobalProperty *props); > > void qdev_prop_set_globals(DeviceState *dev); > > void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, > > diff --git a/hw/qdev-system.c b/hw/qdev-system.c > > new file mode 100644 > > index 0000000..490821f > > --- /dev/null > > +++ b/hw/qdev-system.c > > @@ -0,0 +1,68 @@ > > +#include "qdev.h" > > + > > +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > > +{ > > + assert(dev->num_gpio_in == 0); > > + dev->num_gpio_in = n; > > + dev->gpio_in = qemu_allocate_irqs(handler, dev, n); > > +} > > + > > +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) > > +{ > > + assert(dev->num_gpio_out == 0); > > + dev->num_gpio_out = n; > > + dev->gpio_out = pins; > > +} > > + > > +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) > > +{ > > + assert(n >= 0 && n < dev->num_gpio_in); > > + return dev->gpio_in[n]; > > +} > > + > > +void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) > > +{ > > + assert(n >= 0 && n < dev->num_gpio_out); > > + dev->gpio_out[n] = pin; > > +} > > + > > +/* Create a new device. This only initializes the device state structure > > + and allows properties to be set. qdev_init should be called to > > + initialize the actual device emulation. */ > > +DeviceState *qdev_create(BusState *bus, const char *name) > > +{ > > + DeviceState *dev; > > + > > + dev = qdev_try_create(bus, name); > > + if (!dev) { > > + if (bus) { > > + hw_error("Unknown device '%s' for bus '%s'\n", name, > > + object_get_typename(OBJECT(bus))); > > + } else { > > + hw_error("Unknown device '%s' for default sysbus\n", name); > > + } > > + } > > + > > + return dev; > > +} > > + > > +DeviceState *qdev_try_create(BusState *bus, const char *type) > > +{ > > + DeviceState *dev; > > + > > + if (object_class_by_name(type) == NULL) { > > + return NULL; > > + } > > + dev = DEVICE(object_new(type)); > > + if (!dev) { > > + return NULL; > > + } > > + > > + if (!bus) { > > + bus = sysbus_get_default(); > > + } > > + > > + qdev_set_parent_bus(dev, bus); > > + > > + return dev; > > +} > > diff --git a/hw/qdev.c b/hw/qdev.c > > index 7ddcd24..ee19dd5 100644 > > --- a/hw/qdev.c > > +++ b/hw/qdev.c > > @@ -25,7 +25,6 @@ > > inherit from a particular bus (e.g. PCI or I2C) rather than > > this API directly. */ > > > > -#include "net.h" > > #include "qdev.h" > > #include "sysemu.h" > > #include "error.h" > > @@ -99,47 +98,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) > > bus_add_child(bus, dev); > > } > > > > -/* Create a new device. This only initializes the device state structure > > - and allows properties to be set. qdev_init should be called to > > - initialize the actual device emulation. */ > > -DeviceState *qdev_create(BusState *bus, const char *name) > > -{ > > - DeviceState *dev; > > - > > - dev = qdev_try_create(bus, name); > > - if (!dev) { > > - if (bus) { > > - hw_error("Unknown device '%s' for bus '%s'\n", name, > > - object_get_typename(OBJECT(bus))); > > - } else { > > - hw_error("Unknown device '%s' for default sysbus\n", name); > > - } > > - } > > - > > - return dev; > > -} > > - > > -DeviceState *qdev_try_create(BusState *bus, const char *type) > > -{ > > - DeviceState *dev; > > - > > - if (object_class_by_name(type) == NULL) { > > - return NULL; > > - } > > - dev = DEVICE(object_new(type)); > > - if (!dev) { > > - return NULL; > > - } > > - > > - if (!bus) { > > - bus = sysbus_get_default(); > > - } > > - > > - qdev_set_parent_bus(dev, bus); > > - > > - return dev; > > -} > > - > > /* Initialize a device. Device properties should be set before calling > > this function. IRQs and MMIO regions should be connected/mapped after > > calling this function. > > @@ -284,44 +242,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev) > > return dev->parent_bus; > > } > > > > -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > > -{ > > - dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, > > - dev, n); > > - dev->num_gpio_in += n; > > -} > > - > > -void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) > > -{ > > - assert(dev->num_gpio_out == 0); > > - dev->num_gpio_out = n; > > - dev->gpio_out = pins; > > -} > > - > > -qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) > > -{ > > - assert(n >= 0 && n < dev->num_gpio_in); > > - return dev->gpio_in[n]; > > -} > > - > > -void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) > > -{ > > - assert(n >= 0 && n < dev->num_gpio_out); > > - dev->gpio_out[n] = pin; > > -} > > - > > -void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) > > -{ > > - qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); > > - if (nd->netdev) > > - qdev_prop_set_netdev(dev, "netdev", nd->netdev); > > - if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && > > - object_property_find(OBJECT(dev), "vectors", NULL)) { > > - qdev_prop_set_uint32(dev, "vectors", nd->nvectors); > > - } > > - nd->instantiated = 1; > > -} > > - > > BusState *qdev_get_child_bus(DeviceState *dev, const char *name) > > { > > BusState *bus; > > -- > > 1.7.11.7 >
Eduardo Habkost <ehabkost@redhat.com> writes: > On Wed, Oct 17, 2012 at 01:00:55PM -0500, Anthony Liguori wrote: [...] >> I don't really understand the split here and the 'system' suffix really >> doesn't explain it for me. Could you at least add a comment to each of >> these files explaining what belongs in them? > > "system" here means "Code used only by qemu-system-*" (in other words, > not used by *-user, and not part of the qdev core). Do you have other > name suggestions? > > The goal here is to make qdev-core.c/qdev-properties as small as > possible (only what's absolutely required for the CPU classes), and put > everything else (that's only used by qemu-system-*) into > qdev-system.c/qdev-properties-system.c. Creates a permanent if minor development burden: where should my property code go? Doubt it's worth the trouble: text data bss dec hex filename 15897 1448 0 17345 43c1 bld/hw/qdev-properties.o In theory, link-time optimizations can drop unused code. Not sure they do in practice.
On Fri, Oct 19, 2012 at 09:31:00AM +0200, Markus Armbruster wrote: > Eduardo Habkost <ehabkost@redhat.com> writes: > > > On Wed, Oct 17, 2012 at 01:00:55PM -0500, Anthony Liguori wrote: > [...] > >> I don't really understand the split here and the 'system' suffix really > >> doesn't explain it for me. Could you at least add a comment to each of > >> these files explaining what belongs in them? > > > > "system" here means "Code used only by qemu-system-*" (in other words, > > not used by *-user, and not part of the qdev core). Do you have other > > name suggestions? > > > > The goal here is to make qdev-core.c/qdev-properties as small as > > possible (only what's absolutely required for the CPU classes), and put > > everything else (that's only used by qemu-system-*) into > > qdev-system.c/qdev-properties-system.c. > > Creates a permanent if minor development burden: where should my > property code go? > > Doubt it's worth the trouble: > > text data bss dec hex filename > 15897 1448 0 17345 43c1 bld/hw/qdev-properties.o > > In theory, link-time optimizations can drop unused code. Not sure they > do in practice. The reason for the split is not just to reduce qdev-core size, but keep qdev dependencies under control (so it becomes feasible to use qdev on *-user). Most of the code moved to qdev-properties-system.c was moved because it depends on other code that we don't include on *-user (like bdrv_get_device_name(), net_hub_port_find(), net_hub_id_for_client(), qemu_find_netdev(), bdrv_get_device_name(), qemu_chr_find()).
diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 854faa9..16f23c0 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -181,6 +181,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o common-obj-y += bt-hci-csr.o common-obj-y += msmouse.o ps2.o common-obj-y += qdev.o qdev-properties.o qdev-monitor.o +common-obj-y += qdev-system.o qdev-properties-system.o common-obj-$(CONFIG_BRLAPI) += baum.o # xen backend driver support diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c new file mode 100644 index 0000000..e3a21db --- /dev/null +++ b/hw/qdev-properties-system.c @@ -0,0 +1,340 @@ +#include "net.h" +#include "qdev.h" +#include "qerror.h" +#include "blockdev.h" +#include "hw/block-common.h" +#include "net/hub.h" +#include "qapi/qapi-visit-core.h" + +static void get_pointer(Object *obj, Visitor *v, Property *prop, + const char *(*print)(void *ptr), + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + void **ptr = qdev_get_prop_ptr(dev, prop); + char *p; + + p = (char *) (*ptr ? print(*ptr) : ""); + visit_type_str(v, &p, name, errp); +} + +static void set_pointer(Object *obj, Visitor *v, Property *prop, + int (*parse)(DeviceState *dev, const char *str, + void **ptr), + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Error *local_err = NULL; + void **ptr = qdev_get_prop_ptr(dev, prop); + char *str; + int ret; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (!*str) { + g_free(str); + *ptr = NULL; + return; + } + ret = parse(dev, str, ptr); + error_set_from_qdev_prop_error(errp, ret, dev, prop, str); + g_free(str); +} + +/* --- drive --- */ + +static int parse_drive(DeviceState *dev, const char *str, void **ptr) +{ + BlockDriverState *bs; + + bs = bdrv_find(str); + if (bs == NULL) + return -ENOENT; + if (bdrv_attach_dev(bs, dev) < 0) + return -EEXIST; + *ptr = bs; + return 0; +} + +static void release_drive(Object *obj, const char *name, void *opaque) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + bdrv_detach_dev(*ptr, dev); + blockdev_auto_del(*ptr); + } +} + +static const char *print_drive(void *ptr) +{ + return bdrv_get_device_name(ptr); +} + +static void get_drive(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_drive, name, errp); +} + +static void set_drive(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_drive, name, errp); +} + +PropertyInfo qdev_prop_drive = { + .name = "drive", + .get = get_drive, + .set = set_drive, + .release = release_drive, +}; + +/* --- character device --- */ + +static int parse_chr(DeviceState *dev, const char *str, void **ptr) +{ + CharDriverState *chr = qemu_chr_find(str); + if (chr == NULL) { + return -ENOENT; + } + if (chr->avail_connections < 1) { + return -EEXIST; + } + *ptr = chr; + --chr->avail_connections; + return 0; +} + +static void release_chr(Object *obj, const char *name, void *opaque) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); + } +} + + +static const char *print_chr(void *ptr) +{ + CharDriverState *chr = ptr; + + return chr->label ? chr->label : ""; +} + +static void get_chr(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_chr, name, errp); +} + +static void set_chr(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_chr, name, errp); +} + +PropertyInfo qdev_prop_chr = { + .name = "chr", + .get = get_chr, + .set = set_chr, + .release = release_chr, +}; + +/* --- netdev device --- */ + +static int parse_netdev(DeviceState *dev, const char *str, void **ptr) +{ + NetClientState *netdev = qemu_find_netdev(str); + + if (netdev == NULL) { + return -ENOENT; + } + if (netdev->peer) { + return -EEXIST; + } + *ptr = netdev; + return 0; +} + +static const char *print_netdev(void *ptr) +{ + NetClientState *netdev = ptr; + + return netdev->name ? netdev->name : ""; +} + +static void get_netdev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + get_pointer(obj, v, opaque, print_netdev, name, errp); +} + +static void set_netdev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + set_pointer(obj, v, opaque, parse_netdev, name, errp); +} + +PropertyInfo qdev_prop_netdev = { + .name = "netdev", + .get = get_netdev, + .set = set_netdev, +}; + +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) +{ + qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); + if (nd->netdev) + qdev_prop_set_netdev(dev, "netdev", nd->netdev); + if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && + object_property_find(OBJECT(dev), "vectors", NULL)) { + qdev_prop_set_uint32(dev, "vectors", nd->nvectors); + } + nd->instantiated = 1; +} + +/* --- vlan --- */ + +static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + int id; + if (!net_hub_id_for_client(*ptr, &id)) { + return snprintf(dest, len, "%d", id); + } + } + + return snprintf(dest, len, "<null>"); +} + +static void get_vlan(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + int32_t id = -1; + + if (*ptr) { + int hub_id; + if (!net_hub_id_for_client(*ptr, &hub_id)) { + id = hub_id; + } + } + + visit_type_int32(v, &id, name, errp); +} + +static void set_vlan(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + NetClientState **ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int32_t id; + NetClientState *hubport; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int32(v, &id, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (id == -1) { + *ptr = NULL; + return; + } + + hubport = net_hub_port_find(id); + if (!hubport) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, + name, prop->info->name); + return; + } + *ptr = hubport; +} + +PropertyInfo qdev_prop_vlan = { + .name = "vlan", + .print = print_vlan, + .get = get_vlan, + .set = set_vlan, +}; + + +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) +{ + Error *errp = NULL; + const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; + object_property_set_str(OBJECT(dev), bdrv_name, + name, &errp); + if (errp) { + qerror_report_err(errp); + error_free(errp); + return -1; + } + return 0; +} + +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) +{ + if (qdev_prop_set_drive(dev, name, value) < 0) { + exit(1); + } +} + +void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) +{ + Error *errp = NULL; + assert(!value || value->label); + object_property_set_str(OBJECT(dev), + value ? value->label : "", name, &errp); + assert_no_error(errp); +} + +void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) +{ + Error *errp = NULL; + assert(!value || value->name); + object_property_set_str(OBJECT(dev), + value ? value->name : "", name, &errp); + assert_no_error(errp); +} + +static int qdev_add_one_global(QemuOpts *opts, void *opaque) +{ + GlobalProperty *g; + + g = g_malloc0(sizeof(*g)); + g->driver = qemu_opt_get(opts, "driver"); + g->property = qemu_opt_get(opts, "property"); + g->value = qemu_opt_get(opts, "value"); + qdev_prop_register_global(g); + return 0; +} + +void qemu_add_globals(void) +{ + qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); +} diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 81d901c..917d986 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -13,49 +13,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) return ptr; } -static void get_pointer(Object *obj, Visitor *v, Property *prop, - const char *(*print)(void *ptr), - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - void **ptr = qdev_get_prop_ptr(dev, prop); - char *p; - - p = (char *) (*ptr ? print(*ptr) : ""); - visit_type_str(v, &p, name, errp); -} - -static void set_pointer(Object *obj, Visitor *v, Property *prop, - int (*parse)(DeviceState *dev, const char *str, - void **ptr), - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Error *local_err = NULL; - void **ptr = qdev_get_prop_ptr(dev, prop); - char *str; - int ret; - - if (dev->state != DEV_STATE_CREATED) { - error_set(errp, QERR_PERMISSION_DENIED); - return; - } - - visit_type_str(v, &str, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - if (!*str) { - g_free(str); - *ptr = NULL; - return; - } - ret = parse(dev, str, ptr); - error_set_from_qdev_prop_error(errp, ret, dev, prop, str); - g_free(str); -} - static void get_enum(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -476,227 +433,6 @@ PropertyInfo qdev_prop_string = { .set = set_string, }; -/* --- drive --- */ - -static int parse_drive(DeviceState *dev, const char *str, void **ptr) -{ - BlockDriverState *bs; - - bs = bdrv_find(str); - if (bs == NULL) - return -ENOENT; - if (bdrv_attach_dev(bs, dev) < 0) - return -EEXIST; - *ptr = bs; - return 0; -} - -static void release_drive(Object *obj, const char *name, void *opaque) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - bdrv_detach_dev(*ptr, dev); - blockdev_auto_del(*ptr); - } -} - -static const char *print_drive(void *ptr) -{ - return bdrv_get_device_name(ptr); -} - -static void get_drive(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_drive, name, errp); -} - -static void set_drive(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_drive, name, errp); -} - -PropertyInfo qdev_prop_drive = { - .name = "drive", - .get = get_drive, - .set = set_drive, - .release = release_drive, -}; - -/* --- character device --- */ - -static int parse_chr(DeviceState *dev, const char *str, void **ptr) -{ - CharDriverState *chr = qemu_chr_find(str); - if (chr == NULL) { - return -ENOENT; - } - if (chr->avail_connections < 1) { - return -EEXIST; - } - *ptr = chr; - --chr->avail_connections; - return 0; -} - -static void release_chr(Object *obj, const char *name, void *opaque) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL); - } -} - - -static const char *print_chr(void *ptr) -{ - CharDriverState *chr = ptr; - - return chr->label ? chr->label : ""; -} - -static void get_chr(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_chr, name, errp); -} - -static void set_chr(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_chr, name, errp); -} - -PropertyInfo qdev_prop_chr = { - .name = "chr", - .get = get_chr, - .set = set_chr, - .release = release_chr, -}; - -/* --- netdev device --- */ - -static int parse_netdev(DeviceState *dev, const char *str, void **ptr) -{ - NetClientState *netdev = qemu_find_netdev(str); - - if (netdev == NULL) { - return -ENOENT; - } - if (netdev->peer) { - return -EEXIST; - } - *ptr = netdev; - return 0; -} - -static const char *print_netdev(void *ptr) -{ - NetClientState *netdev = ptr; - - return netdev->name ? netdev->name : ""; -} - -static void get_netdev(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - get_pointer(obj, v, opaque, print_netdev, name, errp); -} - -static void set_netdev(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - set_pointer(obj, v, opaque, parse_netdev, name, errp); -} - -PropertyInfo qdev_prop_netdev = { - .name = "netdev", - .get = get_netdev, - .set = set_netdev, -}; - -/* --- vlan --- */ - -static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr) { - int id; - if (!net_hub_id_for_client(*ptr, &id)) { - return snprintf(dest, len, "%d", id); - } - } - - return snprintf(dest, len, "<null>"); -} - -static void get_vlan(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - int32_t id = -1; - - if (*ptr) { - int hub_id; - if (!net_hub_id_for_client(*ptr, &hub_id)) { - id = hub_id; - } - } - - visit_type_int32(v, &id, name, errp); -} - -static void set_vlan(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - int32_t id; - NetClientState *hubport; - - if (dev->state != DEV_STATE_CREATED) { - error_set(errp, QERR_PERMISSION_DENIED); - return; - } - - visit_type_int32(v, &id, name, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - if (id == -1) { - *ptr = NULL; - return; - } - - hubport = net_hub_port_find(id); - if (!hubport) { - error_set(errp, QERR_INVALID_PARAMETER_VALUE, - name, prop->info->name); - return; - } - *ptr = hubport; -} - -PropertyInfo qdev_prop_vlan = { - .name = "vlan", - .print = print_vlan, - .get = get_vlan, - .set = set_vlan, -}; - /* --- pointer --- */ /* Not a proper property, just for dirty hacks. TODO Remove it! */ @@ -1158,44 +894,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) assert_no_error(errp); } -int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) -{ - Error *errp = NULL; - const char *bdrv_name = value ? bdrv_get_device_name(value) : ""; - object_property_set_str(OBJECT(dev), bdrv_name, - name, &errp); - if (errp) { - qerror_report_err(errp); - error_free(errp); - return -1; - } - return 0; -} - -void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) -{ - if (qdev_prop_set_drive(dev, name, value) < 0) { - exit(1); - } -} -void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) -{ - Error *errp = NULL; - assert(!value || value->label); - object_property_set_str(OBJECT(dev), - value ? value->label : "", name, &errp); - assert_no_error(errp); -} - -void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value) -{ - Error *errp = NULL; - assert(!value || value->name); - object_property_set_str(OBJECT(dev), - value ? value->name : "", name, &errp); - assert_no_error(errp); -} - void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) { Error *errp = NULL; @@ -1231,7 +929,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); -static void qdev_prop_register_global(GlobalProperty *prop) +void qdev_prop_register_global(GlobalProperty *prop) { QTAILQ_INSERT_TAIL(&global_props, prop, next); } @@ -1263,19 +961,3 @@ void qdev_prop_set_globals(DeviceState *dev) } while (class); } -static int qdev_add_one_global(QemuOpts *opts, void *opaque) -{ - GlobalProperty *g; - - g = g_malloc0(sizeof(*g)); - g->driver = qemu_opt_get(opts, "driver"); - g->property = qemu_opt_get(opts, "property"); - g->value = qemu_opt_get(opts, "value"); - qdev_prop_register_global(g); - return 0; -} - -void qemu_add_globals(void) -{ - qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); -} diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h index 5b046ab..ddcf774 100644 --- a/hw/qdev-properties.h +++ b/hw/qdev-properties.h @@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); /* FIXME: Remove opaque pointer properties. */ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); +void qdev_prop_register_global(GlobalProperty *prop); void qdev_prop_register_global_list(GlobalProperty *props); void qdev_prop_set_globals(DeviceState *dev); void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, diff --git a/hw/qdev-system.c b/hw/qdev-system.c new file mode 100644 index 0000000..490821f --- /dev/null +++ b/hw/qdev-system.c @@ -0,0 +1,68 @@ +#include "qdev.h" + +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) +{ + assert(dev->num_gpio_in == 0); + dev->num_gpio_in = n; + dev->gpio_in = qemu_allocate_irqs(handler, dev, n); +} + +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) +{ + assert(dev->num_gpio_out == 0); + dev->num_gpio_out = n; + dev->gpio_out = pins; +} + +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) +{ + assert(n >= 0 && n < dev->num_gpio_in); + return dev->gpio_in[n]; +} + +void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) +{ + assert(n >= 0 && n < dev->num_gpio_out); + dev->gpio_out[n] = pin; +} + +/* Create a new device. This only initializes the device state structure + and allows properties to be set. qdev_init should be called to + initialize the actual device emulation. */ +DeviceState *qdev_create(BusState *bus, const char *name) +{ + DeviceState *dev; + + dev = qdev_try_create(bus, name); + if (!dev) { + if (bus) { + hw_error("Unknown device '%s' for bus '%s'\n", name, + object_get_typename(OBJECT(bus))); + } else { + hw_error("Unknown device '%s' for default sysbus\n", name); + } + } + + return dev; +} + +DeviceState *qdev_try_create(BusState *bus, const char *type) +{ + DeviceState *dev; + + if (object_class_by_name(type) == NULL) { + return NULL; + } + dev = DEVICE(object_new(type)); + if (!dev) { + return NULL; + } + + if (!bus) { + bus = sysbus_get_default(); + } + + qdev_set_parent_bus(dev, bus); + + return dev; +} diff --git a/hw/qdev.c b/hw/qdev.c index 7ddcd24..ee19dd5 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -25,7 +25,6 @@ inherit from a particular bus (e.g. PCI or I2C) rather than this API directly. */ -#include "net.h" #include "qdev.h" #include "sysemu.h" #include "error.h" @@ -99,47 +98,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) bus_add_child(bus, dev); } -/* Create a new device. This only initializes the device state structure - and allows properties to be set. qdev_init should be called to - initialize the actual device emulation. */ -DeviceState *qdev_create(BusState *bus, const char *name) -{ - DeviceState *dev; - - dev = qdev_try_create(bus, name); - if (!dev) { - if (bus) { - hw_error("Unknown device '%s' for bus '%s'\n", name, - object_get_typename(OBJECT(bus))); - } else { - hw_error("Unknown device '%s' for default sysbus\n", name); - } - } - - return dev; -} - -DeviceState *qdev_try_create(BusState *bus, const char *type) -{ - DeviceState *dev; - - if (object_class_by_name(type) == NULL) { - return NULL; - } - dev = DEVICE(object_new(type)); - if (!dev) { - return NULL; - } - - if (!bus) { - bus = sysbus_get_default(); - } - - qdev_set_parent_bus(dev, bus); - - return dev; -} - /* Initialize a device. Device properties should be set before calling this function. IRQs and MMIO regions should be connected/mapped after calling this function. @@ -284,44 +242,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev) return dev->parent_bus; } -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) -{ - dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler, - dev, n); - dev->num_gpio_in += n; -} - -void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) -{ - assert(dev->num_gpio_out == 0); - dev->num_gpio_out = n; - dev->gpio_out = pins; -} - -qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) -{ - assert(n >= 0 && n < dev->num_gpio_in); - return dev->gpio_in[n]; -} - -void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) -{ - assert(n >= 0 && n < dev->num_gpio_out); - dev->gpio_out[n] = pin; -} - -void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) -{ - qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); - if (nd->netdev) - qdev_prop_set_netdev(dev, "netdev", nd->netdev); - if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - object_property_find(OBJECT(dev), "vectors", NULL)) { - qdev_prop_set_uint32(dev, "vectors", nd->nvectors); - } - nd->instantiated = 1; -} - BusState *qdev_get_child_bus(DeviceState *dev, const char *name) { BusState *bus;