qdev-properties.c 28.9 KB
Newer Older
P
Peter Maydell 已提交
1
#include "qemu/osdep.h"
P
Paolo Bonzini 已提交
2
#include "net/net.h"
3
#include "hw/qdev.h"
4
#include "qapi/qmp/qerror.h"
5
#include "qemu/error-report.h"
6
#include "sysemu/block-backend.h"
P
Paolo Bonzini 已提交
7
#include "hw/block/block.h"
8
#include "net/hub.h"
9
#include "qapi/visitor.h"
10
#include "sysemu/char.h"
G
Gerd Hoffmann 已提交
11

12 13 14 15 16 17 18 19 20 21 22 23 24 25
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
                                  Error **errp)
{
    if (dev->id) {
        error_setg(errp, "Attempt to set property '%s' on device '%s' "
                   "(type '%s') after it was realized", name, dev->id,
                   object_get_typename(OBJECT(dev)));
    } else {
        error_setg(errp, "Attempt to set property '%s' on anonymous device "
                   "(type '%s') after it was realized", name,
                   object_get_typename(OBJECT(dev)));
    }
}

26 27 28 29 30 31 32 33 34 35 36 37
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
                                             Object *val, Error **errp)
{
    DeviceState *dev = DEVICE(obj);

    if (dev->realized) {
        error_setg(errp, "Attempt to set link property '%s' on device '%s' "
                   "(type '%s') after it was realized",
                   name, dev->id, object_get_typename(obj));
    }
}

G
Gerd Hoffmann 已提交
38 39 40 41 42 43 44
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

45 46
static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
47 48 49 50 51
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int *ptr = qdev_get_prop_ptr(dev, prop);

52
    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
53 54
}

55 56
static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
57 58 59 60 61
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int *ptr = qdev_get_prop_ptr(dev, prop);

62
    if (dev->realized) {
63
        qdev_prop_set_after_realize(dev, name, errp);
64 65 66
        return;
    }

67
    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
68 69 70 71
}

/* Bit */

M
Michael S. Tsirkin 已提交
72 73
static uint32_t qdev_get_prop_mask(Property *prop)
{
74
    assert(prop->info == &qdev_prop_bit);
M
Michael S. Tsirkin 已提交
75 76 77 78 79 80 81
    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);
E
Eduardo Habkost 已提交
82
    if (val) {
83
        *p |= mask;
E
Eduardo Habkost 已提交
84
    } else {
M
Michael S. Tsirkin 已提交
85
        *p &= ~mask;
E
Eduardo Habkost 已提交
86
    }
M
Michael S. Tsirkin 已提交
87 88
}

89 90
static void prop_get_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
91
{
92
    DeviceState *dev = DEVICE(obj);
93 94 95 96
    Property *prop = opaque;
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

97
    visit_type_bool(v, name, &value, errp);
98 99
}

100 101
static void prop_set_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
102
{
103
    DeviceState *dev = DEVICE(obj);
104 105 106 107
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

108
    if (dev->realized) {
109
        qdev_prop_set_after_realize(dev, name, errp);
110 111 112
        return;
    }

113
    visit_type_bool(v, name, &value, &local_err);
114 115 116 117 118 119 120
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit_prop_set(dev, prop, value);
}

M
Michael S. Tsirkin 已提交
121
PropertyInfo qdev_prop_bit = {
122
    .name  = "bool",
123
    .description = "on/off",
124 125
    .get   = prop_get_bit,
    .set   = prop_set_bit,
M
Michael S. Tsirkin 已提交
126 127
};

G
Gerd Hoffmann 已提交
128 129 130 131
/* Bit64 */

static uint64_t qdev_get_prop_mask64(Property *prop)
{
C
Cornelia Huck 已提交
132
    assert(prop->info == &qdev_prop_bit64);
G
Gonglei 已提交
133
    return 0x1ull << prop->bitnr;
G
Gerd Hoffmann 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146
}

static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint64_t *p = qdev_get_prop_ptr(dev, props);
    uint64_t mask = qdev_get_prop_mask64(props);
    if (val) {
        *p |= mask;
    } else {
        *p &= ~mask;
    }
}

147 148
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
149 150 151 152 153 154
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

155
    visit_type_bool(v, name, &value, errp);
G
Gerd Hoffmann 已提交
156 157
}

158 159
static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
160 161 162 163 164 165 166 167 168 169 170
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

171
    visit_type_bool(v, name, &value, &local_err);
G
Gerd Hoffmann 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit64_prop_set(dev, prop, value);
}

PropertyInfo qdev_prop_bit64 = {
    .name  = "bool",
    .description = "on/off",
    .get   = prop_get_bit64,
    .set   = prop_set_bit64,
};

186 187
/* --- bool --- */

188 189
static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
190 191 192 193 194
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

195
    visit_type_bool(v, name, ptr, errp);
196 197
}

198 199
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
200 201 202 203 204 205 206 207 208 209
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

210
    visit_type_bool(v, name, ptr, errp);
211 212 213
}

PropertyInfo qdev_prop_bool = {
214
    .name  = "bool",
215 216 217 218
    .get   = get_bool,
    .set   = set_bool,
};

J
Juan Quintela 已提交
219 220
/* --- 8bit integer --- */

221 222
static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
223
{
224
    DeviceState *dev = DEVICE(obj);
225
    Property *prop = opaque;
226
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
227

228
    visit_type_uint8(v, name, ptr, errp);
229 230
}

231 232
static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
233
{
234
    DeviceState *dev = DEVICE(obj);
235
    Property *prop = opaque;
236
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
237

238
    if (dev->realized) {
239
        qdev_prop_set_after_realize(dev, name, errp);
240 241 242
        return;
    }

243
    visit_type_uint8(v, name, ptr, errp);
244 245
}

J
Juan Quintela 已提交
246 247
PropertyInfo qdev_prop_uint8 = {
    .name  = "uint8",
248 249
    .get   = get_uint8,
    .set   = set_uint8,
J
Juan Quintela 已提交
250 251
};

G
Gerd Hoffmann 已提交
252 253
/* --- 16bit integer --- */

254 255
static void get_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
256
{
257
    DeviceState *dev = DEVICE(obj);
258
    Property *prop = opaque;
259
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
260

261
    visit_type_uint16(v, name, ptr, errp);
262 263
}

264 265
static void set_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
266
{
267
    DeviceState *dev = DEVICE(obj);
268
    Property *prop = opaque;
269
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
270

271
    if (dev->realized) {
272
        qdev_prop_set_after_realize(dev, name, errp);
273 274 275
        return;
    }

276
    visit_type_uint16(v, name, ptr, errp);
277 278
}

G
Gerd Hoffmann 已提交
279 280
PropertyInfo qdev_prop_uint16 = {
    .name  = "uint16",
281 282
    .get   = get_uint16,
    .set   = set_uint16,
G
Gerd Hoffmann 已提交
283 284 285 286
};

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

287 288
static void get_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
289 290 291
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
292
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
293

294
    visit_type_uint32(v, name, ptr, errp);
295 296
}

297 298
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
299 300 301
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
302
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
303

304
    if (dev->realized) {
305
        qdev_prop_set_after_realize(dev, name, errp);
306 307 308
        return;
    }

309
    visit_type_uint32(v, name, ptr, errp);
310 311
}

312 313
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
314
{
315
    DeviceState *dev = DEVICE(obj);
316 317 318
    Property *prop = opaque;
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);

319
    visit_type_int32(v, name, ptr, errp);
320 321
}

322 323
static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
324
{
325
    DeviceState *dev = DEVICE(obj);
326
    Property *prop = opaque;
327
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
328

329
    if (dev->realized) {
330
        qdev_prop_set_after_realize(dev, name, errp);
331 332 333
        return;
    }

334
    visit_type_int32(v, name, ptr, errp);
335 336
}

G
Gerd Hoffmann 已提交
337 338
PropertyInfo qdev_prop_uint32 = {
    .name  = "uint32",
339 340
    .get   = get_uint32,
    .set   = set_uint32,
G
Gerd Hoffmann 已提交
341 342
};

343 344
PropertyInfo qdev_prop_int32 = {
    .name  = "int32",
345 346
    .get   = get_int32,
    .set   = set_int32,
347 348
};

B
Blue Swirl 已提交
349 350
/* --- 64bit integer --- */

351 352
static void get_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
353
{
354
    DeviceState *dev = DEVICE(obj);
355
    Property *prop = opaque;
356
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
357

358
    visit_type_uint64(v, name, ptr, errp);
359 360
}

361 362
static void set_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
363
{
364
    DeviceState *dev = DEVICE(obj);
365
    Property *prop = opaque;
366
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
367

368
    if (dev->realized) {
369
        qdev_prop_set_after_realize(dev, name, errp);
370 371 372
        return;
    }

373
    visit_type_uint64(v, name, ptr, errp);
374 375
}

B
Blue Swirl 已提交
376 377
PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
378 379
    .get   = get_uint64,
    .set   = set_uint64,
B
Blue Swirl 已提交
380 381
};

G
Gerd Hoffmann 已提交
382 383
/* --- string --- */

P
Paolo Bonzini 已提交
384
static void release_string(Object *obj, const char *name, void *opaque)
385
{
P
Paolo Bonzini 已提交
386 387
    Property *prop = opaque;
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
388 389
}

390 391
static void get_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
392
{
393
    DeviceState *dev = DEVICE(obj);
394 395 396 397 398
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);

    if (!*ptr) {
        char *str = (char *)"";
399
        visit_type_str(v, name, &str, errp);
400
    } else {
401
        visit_type_str(v, name, ptr, errp);
402 403 404
    }
}

405 406
static void set_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
407
{
408
    DeviceState *dev = DEVICE(obj);
409 410 411 412 413
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str;

414
    if (dev->realized) {
415
        qdev_prop_set_after_realize(dev, name, errp);
416 417 418
        return;
    }

419
    visit_type_str(v, name, &str, &local_err);
420 421 422 423
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
424
    g_free(*ptr);
425 426 427
    *ptr = str;
}

G
Gerd Hoffmann 已提交
428
PropertyInfo qdev_prop_string = {
429
    .name  = "str",
P
Paolo Bonzini 已提交
430
    .release = release_string,
431 432
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
433 434
};

G
Gerd Hoffmann 已提交
435 436
/* --- pointer --- */

437
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
G
Gerd Hoffmann 已提交
438 439 440 441 442 443 444 445 446 447 448
PropertyInfo qdev_prop_ptr = {
    .name  = "ptr",
};

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

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
449 450
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
451
{
452 453
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
454
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
455 456 457 458 459 460 461
    char buffer[2 * 6 + 5 + 1];
    char *p = buffer;

    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
             mac->a[0], mac->a[1], mac->a[2],
             mac->a[3], mac->a[4], mac->a[5]);

462
    visit_type_str(v, name, &p, errp);
463 464
}

465 466
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
467 468 469 470 471
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
472
    int i, pos;
473 474
    char *str, *p;

475
    if (dev->realized) {
476
        qdev_prop_set_after_realize(dev, name, errp);
477 478 479
        return;
    }

480
    visit_type_str(v, name, &str, &local_err);
481 482 483 484
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
485 486

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
E
Eduardo Habkost 已提交
487
        if (!qemu_isxdigit(str[pos])) {
488
            goto inval;
E
Eduardo Habkost 已提交
489 490
        }
        if (!qemu_isxdigit(str[pos+1])) {
491
            goto inval;
E
Eduardo Habkost 已提交
492
        }
G
Gerd Hoffmann 已提交
493
        if (i == 5) {
E
Eduardo Habkost 已提交
494
            if (str[pos+2] != '\0') {
495
                goto inval;
E
Eduardo Habkost 已提交
496
            }
G
Gerd Hoffmann 已提交
497
        } else {
E
Eduardo Habkost 已提交
498
            if (str[pos+2] != ':' && str[pos+2] != '-') {
499
                goto inval;
E
Eduardo Habkost 已提交
500
            }
G
Gerd Hoffmann 已提交
501 502
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
503
    }
D
dunrong huang 已提交
504
    g_free(str);
505
    return;
G
Gerd Hoffmann 已提交
506

507 508
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
509
    g_free(str);
G
Gerd Hoffmann 已提交
510 511 512
}

PropertyInfo qdev_prop_macaddr = {
513
    .name  = "str",
514
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
515 516
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
517 518
};

519 520
/* --- lost tick policy --- */

521 522
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

523
PropertyInfo qdev_prop_losttickpolicy = {
524
    .name  = "LostTickPolicy",
525
    .enum_table  = LostTickPolicy_lookup,
526 527
    .get   = get_enum,
    .set   = set_enum,
528 529
};

530 531
/* --- BIOS CHS translation */

532
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
533 534

PropertyInfo qdev_prop_bios_chs_trans = {
535
    .name = "BiosAtaTranslation",
536 537
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
538
    .enum_table = BiosAtaTranslation_lookup,
539 540 541 542
    .get = get_enum,
    .set = set_enum,
};

J
John Snow 已提交
543 544 545 546 547 548 549 550 551 552 553
/* --- FDC default drive types */

PropertyInfo qdev_prop_fdc_drive_type = {
    .name = "FdcDriveType",
    .description = "FDC drive type, "
                   "144/288/120/none/auto",
    .enum_table = FloppyDriveType_lookup,
    .get = get_enum,
    .set = set_enum
};

554 555 556 557 558
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
559 560
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
561
{
562 563
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
564
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
565
    unsigned int slot, fn, n;
566
    Error *local_err = NULL;
D
dunrong huang 已提交
567
    char *str;
568

569
    if (dev->realized) {
570
        qdev_prop_set_after_realize(dev, name, errp);
571 572 573
        return;
    }

574
    visit_type_str(v, name, &str, &local_err);
575
    if (local_err) {
576
        error_free(local_err);
577
        local_err = NULL;
578
        visit_type_int32(v, name, &value, &local_err);
579 580 581
        if (local_err) {
            error_propagate(errp, local_err);
        } else if (value < -1 || value > 255) {
582 583
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                       name ? name : "null", "pci_devfn");
584 585 586 587
        } else {
            *ptr = value;
        }
        return;
588
    }
589 590 591 592

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
593
            goto invalid;
594 595
        }
    }
596 597 598
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
599
    *ptr = slot << 3 | fn;
D
dunrong huang 已提交
600
    g_free(str);
601 602 603 604
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
605
    g_free(str);
606 607
}

E
Eduardo Habkost 已提交
608 609
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
610
{
611
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
612

B
Blue Swirl 已提交
613
    if (*ptr == -1) {
614 615 616 617 618 619 620
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

PropertyInfo qdev_prop_pci_devfn = {
621
    .name  = "int32",
622
    .description = "Slot and optional function number, example: 06.0 or 06",
623
    .print = print_pci_devfn,
624
    .get   = get_int32,
625
    .set   = set_pci_devfn,
626 627
};

628 629
/* --- blocksize --- */

630 631
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
632 633 634
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
635
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
636
    Error *local_err = NULL;
637 638
    const int64_t min = 512;
    const int64_t max = 32768;
639

640
    if (dev->realized) {
641
        qdev_prop_set_after_realize(dev, name, errp);
642 643 644
        return;
    }

645
    visit_type_uint16(v, name, &value, &local_err);
646 647 648 649
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
650 651
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
652 653
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
654 655 656 657 658
        return;
    }

    /* We rely on power-of-2 blocksizes for bitmasks */
    if ((value & (value - 1)) != 0) {
659 660 661
        error_setg(errp,
                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
                  dev->id ?: "", name, (int64_t)value);
662 663 664 665 666 667 668
        return;
    }

    *ptr = value;
}

PropertyInfo qdev_prop_blocksize = {
669
    .name  = "uint16",
670
    .description = "A power of two between 512 and 32768",
671
    .get   = get_uint16,
672 673 674
    .set   = set_blocksize,
};

675 676
/* --- pci host address --- */

677 678
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
679 680 681 682 683 684 685 686 687 688 689 690
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
    char buffer[] = "xxxx:xx:xx.x";
    char *p = buffer;
    int rc = 0;

    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
                  addr->domain, addr->bus, addr->slot, addr->function);
    assert(rc == sizeof(buffer) - 1);

691
    visit_type_str(v, name, &p, errp);
692 693 694 695 696 697
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
698 699
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
700 701 702 703 704 705 706 707 708 709 710
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str, *p;
    char *e;
    unsigned long val;
    unsigned long dom = 0, bus = 0;
    unsigned int slot = 0, func = 0;

711
    if (dev->realized) {
712
        qdev_prop_set_after_realize(dev, name, errp);
713 714 715
        return;
    }

716
    visit_type_str(v, name, &str, &local_err);
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    p = str;
    val = strtoul(p, &e, 16);
    if (e == p || *e != ':') {
        goto inval;
    }
    bus = val;

    p = e + 1;
    val = strtoul(p, &e, 16);
    if (e == p) {
        goto inval;
    }
    if (*e == ':') {
        dom = bus;
        bus = val;
        p = e + 1;
        val = strtoul(p, &e, 16);
        if (e == p) {
            goto inval;
        }
    }
    slot = val;

    if (*e != '.') {
        goto inval;
    }
    p = e + 1;
    val = strtoul(p, &e, 10);
    if (e == p) {
        goto inval;
    }
    func = val;

    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
        goto inval;
    }

    if (*e) {
        goto inval;
    }

    addr->domain = dom;
    addr->bus = bus;
    addr->slot = slot;
    addr->function = func;

    g_free(str);
    return;

inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
    g_free(str);
}

PropertyInfo qdev_prop_pci_host_devaddr = {
777
    .name = "str",
778 779
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
780 781 782 783
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
/* --- support for array properties --- */

/* Used as an opaque for the object properties we add for each
 * array element. Note that the struct Property must be first
 * in the struct so that a pointer to this works as the opaque
 * for the underlying element's property hooks as well as for
 * our own release callback.
 */
typedef struct {
    struct Property prop;
    char *propname;
    ObjectPropertyRelease *release;
} ArrayElementProperty;

/* object property release callback for array element properties:
 * we call the underlying element's property release hook, and
 * then free the memory we allocated when we added the property.
 */
static void array_element_release(Object *obj, const char *name, void *opaque)
{
    ArrayElementProperty *p = opaque;
    if (p->release) {
        p->release(obj, name, opaque);
    }
    g_free(p->propname);
    g_free(p);
}

812 813
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
814 815 816 817 818 819 820 821 822 823
{
    /* Setter for the property which defines the length of a
     * variable-sized property array. As well as actually setting the
     * array-length field in the device struct, we have to create the
     * array itself and dynamically add the corresponding properties.
     */
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
    void **arrayptr = (void *)dev + prop->arrayoffset;
824
    Error *local_err = NULL;
825 826 827 828 829
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
830
        qdev_prop_set_after_realize(dev, name, errp);
831 832 833 834 835 836 837
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
838
    visit_type_uint32(v, name, alenptr, &local_err);
839 840
    if (local_err) {
        error_propagate(errp, local_err);
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
        return;
    }
    if (!*alenptr) {
        return;
    }

    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
     * strip it off so we can get the name of the array itself.
     */
    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

    /* Note that it is the responsibility of the individual device's deinit
     * to free the array proper.
     */
    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
        arrayprop->release = prop->arrayinfo->release;
        arrayprop->propname = propname;
        arrayprop->prop.info = prop->arrayinfo;
        arrayprop->prop.name = propname;
        /* This ugly piece of pointer arithmetic sets up the offset so
         * that when the underlying get/set hooks call qdev_get_prop_ptr
         * they get the right answer despite the array element not actually
         * being inside the device struct.
         */
        arrayprop->prop.offset = eltptr - (void *)dev;
        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
        object_property_add(obj, propname,
                            arrayprop->prop.info->name,
                            arrayprop->prop.info->get,
                            arrayprop->prop.info->set,
                            array_element_release,
877 878 879
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
880 881 882 883 884 885 886 887 888 889 890
            return;
        }
    }
}

PropertyInfo qdev_prop_arraylen = {
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
};

G
Gerd Hoffmann 已提交
891 892 893 894
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
895
    if (!props) {
G
Gerd Hoffmann 已提交
896
        return NULL;
E
Eduardo Habkost 已提交
897
    }
G
Gerd Hoffmann 已提交
898
    while (props->name) {
E
Eduardo Habkost 已提交
899
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
900
            return props;
E
Eduardo Habkost 已提交
901
        }
G
Gerd Hoffmann 已提交
902 903 904 905 906 907 908
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
909
    ObjectClass *class;
G
Gerd Hoffmann 已提交
910 911 912
    Property *prop;

    /* device properties */
913 914 915 916 917 918 919 920
    class = object_get_class(OBJECT(dev));
    do {
        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
        if (prop) {
            return prop;
        }
        class = object_class_get_parent(class);
    } while (class != object_class_by_name(TYPE_DEVICE));
G
Gerd Hoffmann 已提交
921 922 923 924

    return NULL;
}

925 926 927 928 929
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                    Property *prop, const char *value)
{
    switch (ret) {
    case -EEXIST:
930
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
931
                  object_get_typename(OBJECT(dev)), prop->name, value);
932 933 934
        break;
    default:
    case -EINVAL:
935 936
        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
                   object_get_typename(OBJECT(dev)), prop->name, value);
937 938
        break;
    case -ENOENT:
939
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
940
                  object_get_typename(OBJECT(dev)), prop->name, value);
941 942 943 944 945 946
        break;
    case 0:
        break;
    }
}

947 948
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
949
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
950 951
}

J
Juan Quintela 已提交
952 953
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
954
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
955 956
}

G
Gerd Hoffmann 已提交
957 958
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
959
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
960 961 962 963
}

void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
{
964
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
965 966
}

967 968
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
969
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
970 971
}

B
Blue Swirl 已提交
972 973
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
974
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
975 976
}

977
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
978
{
979
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
980 981
}

G
Gerd Hoffmann 已提交
982 983
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
{
P
Paolo Bonzini 已提交
984 985 986 987
    char str[2 * 6 + 5 + 1];
    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
             value[0], value[1], value[2], value[3], value[4], value[5]);

988
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
989 990
}

P
Paolo Bonzini 已提交
991
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
992
{
P
Paolo Bonzini 已提交
993 994 995 996
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
997
                            name, &error_abort);
998 999
}

G
Gerd Hoffmann 已提交
1000 1001
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1002 1003 1004 1005 1006 1007 1008
    Property *prop;
    void **ptr;

    prop = qdev_prop_find(dev, name);
    assert(prop && prop->info == &qdev_prop_ptr);
    ptr = qdev_get_prop_ptr(dev, prop);
    *ptr = value;
G
Gerd Hoffmann 已提交
1009 1010
}

E
Eduardo Habkost 已提交
1011 1012
static QTAILQ_HEAD(, GlobalProperty) global_props =
        QTAILQ_HEAD_INITIALIZER(global_props);
1013

1014
void qdev_prop_register_global(GlobalProperty *prop)
1015
{
1016
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
1017 1018
}

1019
void qdev_prop_register_global_list(GlobalProperty *props)
1020
{
1021
    int i;
1022

1023 1024
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1025
    }
1026 1027
}

1028
int qdev_prop_check_globals(void)
1029 1030 1031 1032 1033
{
    GlobalProperty *prop;
    int ret = 0;

    QTAILQ_FOREACH(prop, &global_props, next) {
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
        ObjectClass *oc;
        DeviceClass *dc;
        if (prop->used) {
            continue;
        }
        if (!prop->user_provided) {
            continue;
        }
        oc = object_class_by_name(prop->driver);
        oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
        if (!oc) {
            error_report("Warning: global %s.%s has invalid class name",
                       prop->driver, prop->property);
            ret = 1;
            continue;
        }
        dc = DEVICE_CLASS(oc);
        if (!dc->hotpluggable && !prop->used) {
            error_report("Warning: global %s.%s=%s not used",
                       prop->driver, prop->property, prop->value);
            ret = 1;
1055 1056 1057 1058 1059 1060
            continue;
        }
    }
    return ret;
}

1061 1062
static void qdev_prop_set_globals_for_type(DeviceState *dev,
                                const char *typename)
1063 1064 1065 1066 1067 1068 1069 1070 1071
{
    GlobalProperty *prop;

    QTAILQ_FOREACH(prop, &global_props, next) {
        Error *err = NULL;

        if (strcmp(typename, prop->driver) != 0) {
            continue;
        }
1072
        prop->used = true;
P
Paolo Bonzini 已提交
1073
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1074
        if (err != NULL) {
1075
            assert(prop->user_provided);
1076 1077
            error_reportf_err(err, "Warning: global %s.%s=%s ignored: ",
                              prop->driver, prop->property, prop->value);
1078 1079 1080 1081 1082
            return;
        }
    }
}

1083
void qdev_prop_set_globals(DeviceState *dev)
1084
{
1085 1086 1087
    ObjectClass *class = object_get_class(OBJECT(dev));

    do {
1088
        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1089 1090
        class = object_class_get_parent(class);
    } while (class);
1091
}
1092 1093 1094

/* --- 64bit unsigned int 'size' type --- */

1095 1096
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1097 1098 1099 1100 1101
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1102
    visit_type_size(v, name, ptr, errp);
1103 1104
}

1105 1106
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1107 1108 1109 1110 1111
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1112
    visit_type_size(v, name, ptr, errp);
1113 1114 1115 1116 1117 1118 1119
}

PropertyInfo qdev_prop_size = {
    .name  = "size",
    .get = get_size,
    .set = set_size,
};