qdev-properties.c 18.4 KB
Newer Older
G
Gerd Hoffmann 已提交
1
#include "net.h"
G
Gerd Hoffmann 已提交
2
#include "qdev.h"
3
#include "qerror.h"
G
Gerd Hoffmann 已提交
4 5 6 7 8 9 10 11

void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

M
Michael S. Tsirkin 已提交
12 13 14 15 16 17 18 19 20 21 22
static uint32_t qdev_get_prop_mask(Property *prop)
{
    assert(prop->info->type == PROP_TYPE_BIT);
    return 0x1 << prop->bitnr;
}

static void bit_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint32_t *p = qdev_get_prop_ptr(dev, props);
    uint32_t mask = qdev_get_prop_mask(props);
    if (val)
23
        *p |= mask;
M
Michael S. Tsirkin 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    else
        *p &= ~mask;
}

static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
{
    if (props->info->type == PROP_TYPE_BIT) {
        bool *defval = src;
        bit_prop_set(dev, props, *defval);
    } else {
        char *dst = qdev_get_prop_ptr(dev, props);
        memcpy(dst, src, props->info->size);
    }
}

/* Bit */
static int parse_bit(DeviceState *dev, Property *prop, const char *str)
{
    if (!strncasecmp(str, "on", 2))
        bit_prop_set(dev, prop, true);
    else if (!strncasecmp(str, "off", 3))
        bit_prop_set(dev, prop, false);
    else
47
        return -EINVAL;
M
Michael S. Tsirkin 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    return 0;
}

static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint8_t *p = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
}

PropertyInfo qdev_prop_bit = {
    .name  = "on/off",
    .type  = PROP_TYPE_BIT,
    .size  = sizeof(uint32_t),
    .parse = parse_bit,
    .print = print_bit,
};

J
Juan Quintela 已提交
65 66 67 68 69
/* --- 8bit integer --- */

static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
{
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
70
    char *end;
J
Juan Quintela 已提交
71 72

    /* accept both hex and decimal */
73 74
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
75
        return -EINVAL;
76 77
    }

J
Juan Quintela 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    return 0;
}

static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu8, *ptr);
}

PropertyInfo qdev_prop_uint8 = {
    .name  = "uint8",
    .type  = PROP_TYPE_UINT8,
    .size  = sizeof(uint8_t),
    .parse = parse_uint8,
    .print = print_uint8,
};

G
Gerd Hoffmann 已提交
95 96 97 98 99
/* --- 16bit integer --- */

static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
{
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
100
    char *end;
G
Gerd Hoffmann 已提交
101 102

    /* accept both hex and decimal */
103 104
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
105
        return -EINVAL;
106 107
    }

G
Gerd Hoffmann 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    return 0;
}

static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu16, *ptr);
}

PropertyInfo qdev_prop_uint16 = {
    .name  = "uint16",
    .type  = PROP_TYPE_UINT16,
    .size  = sizeof(uint16_t),
    .parse = parse_uint16,
    .print = print_uint16,
};

/* --- 32bit integer --- */

static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
130
    char *end;
G
Gerd Hoffmann 已提交
131 132

    /* accept both hex and decimal */
133 134
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
135
        return -EINVAL;
136 137
    }

G
Gerd Hoffmann 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
    return 0;
}

static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu32, *ptr);
}

PropertyInfo qdev_prop_uint32 = {
    .name  = "uint32",
    .type  = PROP_TYPE_UINT32,
    .size  = sizeof(uint32_t),
    .parse = parse_uint32,
    .print = print_uint32,
};

155 156 157
static int parse_int32(DeviceState *dev, Property *prop, const char *str)
{
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
158
    char *end;
159

160 161
    *ptr = strtol(str, &end, 10);
    if ((*end != '\0') || (end == str)) {
162
        return -EINVAL;
163 164
    }

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    return 0;
}

static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRId32, *ptr);
}

PropertyInfo qdev_prop_int32 = {
    .name  = "int32",
    .type  = PROP_TYPE_INT32,
    .size  = sizeof(int32_t),
    .parse = parse_int32,
    .print = print_int32,
};

G
Gerd Hoffmann 已提交
182 183 184 185 186
/* --- 32bit hex value --- */

static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
187
    char *end;
G
Gerd Hoffmann 已提交
188

189 190
    *ptr = strtoul(str, &end, 16);
    if ((*end != '\0') || (end == str)) {
191
        return -EINVAL;
192 193
    }

G
Gerd Hoffmann 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    return 0;
}

static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
}

PropertyInfo qdev_prop_hex32 = {
    .name  = "hex32",
    .type  = PROP_TYPE_UINT32,
    .size  = sizeof(uint32_t),
    .parse = parse_hex32,
    .print = print_hex32,
};

B
Blue Swirl 已提交
211 212 213 214 215
/* --- 64bit integer --- */

static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
216
    char *end;
B
Blue Swirl 已提交
217 218

    /* accept both hex and decimal */
219 220
    *ptr = strtoull(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
221
        return -EINVAL;
222 223
    }

B
Blue Swirl 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
    return 0;
}

static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu64, *ptr);
}

PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
    .type  = PROP_TYPE_UINT64,
    .size  = sizeof(uint64_t),
    .parse = parse_uint64,
    .print = print_uint64,
};

/* --- 64bit hex value --- */

static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
246
    char *end;
B
Blue Swirl 已提交
247

248 249
    *ptr = strtoull(str, &end, 16);
    if ((*end != '\0') || (end == str)) {
250
        return -EINVAL;
251 252
    }

B
Blue Swirl 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    return 0;
}

static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
}

PropertyInfo qdev_prop_hex64 = {
    .name  = "hex64",
    .type  = PROP_TYPE_UINT64,
    .size  = sizeof(uint64_t),
    .parse = parse_hex64,
    .print = print_hex64,
};

G
Gerd Hoffmann 已提交
270 271 272 273 274 275 276 277 278 279 280 281
/* --- string --- */

static int parse_string(DeviceState *dev, Property *prop, const char *str)
{
    char **ptr = qdev_get_prop_ptr(dev, prop);

    if (*ptr)
        qemu_free(*ptr);
    *ptr = qemu_strdup(str);
    return 0;
}

282 283 284 285 286
static void free_string(DeviceState *dev, Property *prop)
{
    qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
}

G
Gerd Hoffmann 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    char **ptr = qdev_get_prop_ptr(dev, prop);
    if (!*ptr)
        return snprintf(dest, len, "<null>");
    return snprintf(dest, len, "\"%s\"", *ptr);
}

PropertyInfo qdev_prop_string = {
    .name  = "string",
    .type  = PROP_TYPE_STRING,
    .size  = sizeof(char*),
    .parse = parse_string,
    .print = print_string,
301
    .free  = free_string,
G
Gerd Hoffmann 已提交
302 303
};

G
Gerd Hoffmann 已提交
304 305 306 307
/* --- drive --- */

static int parse_drive(DeviceState *dev, Property *prop, const char *str)
{
308 309
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
    BlockDriverState *bs;
G
Gerd Hoffmann 已提交
310

311 312
    bs = bdrv_find(str);
    if (bs == NULL)
313
        return -ENOENT;
314 315
    if (bdrv_attach(bs, dev) < 0)
        return -EEXIST;
316
    *ptr = bs;
G
Gerd Hoffmann 已提交
317 318 319
    return 0;
}

320 321
static void free_drive(DeviceState *dev, Property *prop)
{
322
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
323 324

    if (*ptr) {
325
        bdrv_detach(*ptr, dev);
326
        blockdev_auto_del(*ptr);
327 328 329
    }
}

G
Gerd Hoffmann 已提交
330 331
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
{
332 333 334
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%s",
                    *ptr ? bdrv_get_device_name(*ptr) : "<null>");
G
Gerd Hoffmann 已提交
335 336 337 338 339
}

PropertyInfo qdev_prop_drive = {
    .name  = "drive",
    .type  = PROP_TYPE_DRIVE,
340
    .size  = sizeof(BlockDriverState *),
G
Gerd Hoffmann 已提交
341 342
    .parse = parse_drive,
    .print = print_drive,
343
    .free  = free_drive,
G
Gerd Hoffmann 已提交
344 345
};

346 347
/* --- character device --- */

348 349 350 351 352 353
static int parse_chr(DeviceState *dev, Property *prop, const char *str)
{
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);

    *ptr = qemu_chr_find(str);
    if (*ptr == NULL)
354
        return -ENOENT;
355 356 357
    return 0;
}

358 359 360
static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
B
Blue Swirl 已提交
361 362 363 364 365 366

    if (*ptr && (*ptr)->label) {
        return snprintf(dest, len, "%s", (*ptr)->label);
    } else {
        return snprintf(dest, len, "<null>");
    }
367 368 369 370 371 372
}

PropertyInfo qdev_prop_chr = {
    .name  = "chr",
    .type  = PROP_TYPE_CHR,
    .size  = sizeof(CharDriverState*),
373
    .parse = parse_chr,
374 375 376
    .print = print_chr,
};

G
Gerd Hoffmann 已提交
377 378 379 380 381 382 383 384
/* --- netdev device --- */

static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
{
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);

    *ptr = qemu_find_netdev(str);
    if (*ptr == NULL)
385
        return -ENOENT;
386 387 388
    if ((*ptr)->peer) {
        return -EEXIST;
    }
G
Gerd Hoffmann 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
    return 0;
}

static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);

    if (*ptr && (*ptr)->name) {
        return snprintf(dest, len, "%s", (*ptr)->name);
    } else {
        return snprintf(dest, len, "<null>");
    }
}

PropertyInfo qdev_prop_netdev = {
    .name  = "netdev",
    .type  = PROP_TYPE_NETDEV,
    .size  = sizeof(VLANClientState*),
    .parse = parse_netdev,
    .print = print_netdev,
};

G
Gerd Hoffmann 已提交
411 412 413 414 415 416 417 418
/* --- vlan --- */

static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
{
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
    int id;

    if (sscanf(str, "%d", &id) != 1)
419
        return -EINVAL;
G
Gerd Hoffmann 已提交
420 421
    *ptr = qemu_find_vlan(id, 1);
    if (*ptr == NULL)
422
        return -ENOENT;
G
Gerd Hoffmann 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
    return 0;
}

static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);

    if (*ptr) {
        return snprintf(dest, len, "%d", (*ptr)->id);
    } else {
        return snprintf(dest, len, "<null>");
    }
}

PropertyInfo qdev_prop_vlan = {
    .name  = "vlan",
    .type  = PROP_TYPE_VLAN,
    .size  = sizeof(VLANClientState*),
    .parse = parse_vlan,
    .print = print_vlan,
};

G
Gerd Hoffmann 已提交
445 446
/* --- pointer --- */

447
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
G
Gerd Hoffmann 已提交
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
PropertyInfo qdev_prop_ptr = {
    .name  = "ptr",
    .type  = PROP_TYPE_PTR,
    .size  = sizeof(void*),
};

/* --- mac address --- */

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
static int parse_mac(DeviceState *dev, Property *prop, const char *str)
{
G
Gerd Hoffmann 已提交
463
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
G
Gerd Hoffmann 已提交
464 465 466 467
    int i, pos;
    char *p;

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
C
Christoph Egger 已提交
468
        if (!qemu_isxdigit(str[pos]))
469
            return -EINVAL;
C
Christoph Egger 已提交
470
        if (!qemu_isxdigit(str[pos+1]))
471
            return -EINVAL;
G
Gerd Hoffmann 已提交
472 473
        if (i == 5) {
            if (str[pos+2] != '\0')
474
                return -EINVAL;
G
Gerd Hoffmann 已提交
475 476
        } else {
            if (str[pos+2] != ':' && str[pos+2] != '-')
477
                return -EINVAL;
G
Gerd Hoffmann 已提交
478 479
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
480 481 482 483 484 485
    }
    return 0;
}

static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
{
G
Gerd Hoffmann 已提交
486 487
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);

G
Gerd Hoffmann 已提交
488
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
G
Gerd Hoffmann 已提交
489 490
                    mac->a[0], mac->a[1], mac->a[2],
                    mac->a[3], mac->a[4], mac->a[5]);
G
Gerd Hoffmann 已提交
491 492 493
}

PropertyInfo qdev_prop_macaddr = {
G
Gerd Hoffmann 已提交
494
    .name  = "macaddr",
G
Gerd Hoffmann 已提交
495
    .type  = PROP_TYPE_MACADDR,
G
Gerd Hoffmann 已提交
496
    .size  = sizeof(MACAddr),
G
Gerd Hoffmann 已提交
497 498 499 500
    .parse = parse_mac,
    .print = print_mac,
};

501 502 503 504 505 506 507 508 509 510 511 512 513
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    unsigned int slot, fn, n;

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
514
            return -EINVAL;
515 516 517
        }
    }
    if (str[n] != '\0')
518
        return -EINVAL;
519
    if (fn > 7)
520
        return -EINVAL;
521 522 523 524 525 526 527 528
    *ptr = slot << 3 | fn;
    return 0;
}

static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);

B
Blue Swirl 已提交
529
    if (*ptr == -1) {
530 531 532 533 534 535 536 537 538 539 540 541 542 543
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

PropertyInfo qdev_prop_pci_devfn = {
    .name  = "pci-devfn",
    .type  = PROP_TYPE_UINT32,
    .size  = sizeof(uint32_t),
    .parse = parse_pci_devfn,
    .print = print_pci_devfn,
};

G
Gerd Hoffmann 已提交
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
    if (!props)
        return NULL;
    while (props->name) {
        if (strcmp(props->name, name) == 0)
            return props;
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
    Property *prop;

    /* device properties */
    prop = qdev_prop_walk(dev->info->props, name);
    if (prop)
        return prop;

    /* bus properties */
    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
    if (prop)
        return prop;

    return NULL;
}

G
Gerd Hoffmann 已提交
575 576 577 578 579
int qdev_prop_exists(DeviceState *dev, const char *name)
{
    return qdev_prop_find(dev, name) ? true : false;
}

G
Gerd Hoffmann 已提交
580 581 582
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
{
    Property *prop;
583
    int ret;
G
Gerd Hoffmann 已提交
584 585

    prop = qdev_prop_find(dev, name);
586 587 588 589 590 591 592
    /*
     * TODO Properties without a parse method are just for dirty
     * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
     * marked for removal.  The test !prop->info->parse should be
     * removed along with it.
     */
    if (!prop || !prop->info->parse) {
593
        qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name);
G
Gerd Hoffmann 已提交
594 595
        return -1;
    }
596 597 598
    ret = prop->info->parse(dev, prop, value);
    if (ret < 0) {
        switch (ret) {
599
        case -EEXIST:
600 601
            qerror_report(QERR_PROPERTY_VALUE_IN_USE,
                          dev->info->name, name, value);
602
            break;
603 604
        default:
        case -EINVAL:
605 606
            qerror_report(QERR_PROPERTY_VALUE_BAD,
                          dev->info->name, name, value);
607 608
            break;
        case -ENOENT:
609 610
            qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND,
                          dev->info->name, name, value);
611 612
            break;
        }
613 614 615
        return -1;
    }
    return 0;
G
Gerd Hoffmann 已提交
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
}

void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
{
    Property *prop;

    prop = qdev_prop_find(dev, name);
    if (!prop) {
        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
                __FUNCTION__, dev->info->name, name);
        abort();
    }
    if (prop->info->type != type) {
        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
                __FUNCTION__, dev->info->name, name);
        abort();
    }
M
Michael S. Tsirkin 已提交
633
    qdev_prop_cpy(dev, prop, src);
G
Gerd Hoffmann 已提交
634 635
}

636 637 638 639 640
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
}

J
Juan Quintela 已提交
641 642 643 644 645
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
}

G
Gerd Hoffmann 已提交
646 647 648 649 650 651 652 653 654 655
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
}

void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
}

656 657 658 659 660
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
}

B
Blue Swirl 已提交
661 662 663 664 665
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
}

666 667 668 669 670
void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
}

671
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
G
Gerd Hoffmann 已提交
672
{
673 674 675 676 677 678 679 680 681 682
    int res;

    res = bdrv_attach(value, dev);
    if (res < 0) {
        error_report("Can't attach drive %s to %s.%s: %s",
                     bdrv_get_device_name(value),
                     dev->id ? dev->id : dev->info->name,
                     name, strerror(-res));
        return -1;
    }
G
Gerd Hoffmann 已提交
683
    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
684
    return 0;
G
Gerd Hoffmann 已提交
685 686
}

687 688 689 690 691 692
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
{
    if (qdev_prop_set_drive(dev, name, value) < 0) {
        exit(1);
    }
}
693 694 695 696 697
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
}

G
Gerd Hoffmann 已提交
698 699 700 701 702
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
}

G
Gerd Hoffmann 已提交
703 704 705 706 707
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
}

G
Gerd Hoffmann 已提交
708 709 710 711 712
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
{
    qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
}

G
Gerd Hoffmann 已提交
713 714 715 716 717 718 719 720 721 722 723
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
}

void qdev_prop_set_defaults(DeviceState *dev, Property *props)
{
    if (!props)
        return;
    while (props->name) {
        if (props->defval) {
M
Michael S. Tsirkin 已提交
724
            qdev_prop_cpy(dev, props, props->defval);
G
Gerd Hoffmann 已提交
725 726 727 728 729
        }
        props++;
    }
}

730
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
731

732
static void qdev_prop_register_global(GlobalProperty *prop)
733
{
734
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
735 736
}

737
void qdev_prop_register_global_list(GlobalProperty *props)
738
{
739
    int i;
740

741 742
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
743
    }
744 745 746 747 748 749 750
}

void qdev_prop_set_globals(DeviceState *dev)
{
    GlobalProperty *prop;

    QTAILQ_FOREACH(prop, &global_props, next) {
751 752
        if (strcmp(dev->info->name, prop->driver) != 0 &&
            strcmp(dev->info->bus_info->name, prop->driver) != 0) {
753 754 755
            continue;
        }
        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
756
            exit(1);
757 758 759
        }
    }
}
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776

static int qdev_add_one_global(QemuOpts *opts, void *opaque)
{
    GlobalProperty *g;

    g = qemu_mallocz(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_global_opts, qdev_add_one_global, NULL, 0);
}