diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-02-09 09:53:32 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-02-22 08:31:24 +0100 |
commit | 768a9ebe188bd0a6172a9a4e64777d21fff7f014 (patch) | |
tree | 54ab3af677bc62835d7d5db7dd3e2f6465205552 /hw | |
parent | b2cd7dee86f27b6307b4bd411133bfb6ebc2be66 (diff) |
qdev: accept both strings and integers for PCI addresses
Visitors allow a limited form of polymorphism. Exploit it to support
setting the non-legacy PCI address property both as a DD.F string
and as an 8-bit integer.
The 8-bit integer form is just too clumsy, it is unlikely that we will
ever drop it.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/qdev-properties.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 7b74dd5beb..0deb378009 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -943,25 +943,40 @@ PropertyInfo qdev_prop_losttickpolicy = { /* * bus-local address, i.e. "$slot" or "$slot.$fn" */ -static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str) +static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; uint32_t *ptr = qdev_get_prop_ptr(dev, prop); unsigned int slot, fn, n; + Error *local_err = NULL; + char *str = (char *)""; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + return set_int32(obj, v, opaque, name, errp); + } if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { fn = 0; if (sscanf(str, "%x%n", &slot, &n) != 1) { - return -EINVAL; + goto invalid; } } - if (str[n] != '\0') - return -EINVAL; - if (fn > 7) - return -EINVAL; - if (slot > 31) - return -EINVAL; + if (str[n] != '\0' || fn > 7 || slot > 31) { + goto invalid; + } *ptr = slot << 3 | fn; - return 0; + return; + +invalid: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); } static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) @@ -978,10 +993,9 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t PropertyInfo qdev_prop_pci_devfn = { .name = "int32", .legacy_name = "pci-devfn", - .parse = parse_pci_devfn, .print = print_pci_devfn, .get = get_int32, - .set = set_int32, + .set = set_pci_devfn, /* FIXME: this should be -1...255, but the address is stored * into an uint32_t rather than int32_t. */ |