1 #include "qemu/osdep.h" 2 #include "net/net.h" 3 #include "hw/qdev-properties.h" 4 #include "qapi/error.h" 5 #include "hw/pci/pci.h" 6 #include "qapi/qapi-types-block.h" 7 #include "qapi/qapi-types-misc.h" 8 #include "qapi/qmp/qerror.h" 9 #include "qemu/ctype.h" 10 #include "qemu/error-report.h" 11 #include "qapi/qapi-types-migration.h" 12 #include "hw/block/block.h" 13 #include "net/hub.h" 14 #include "qapi/visitor.h" 15 #include "chardev/char.h" 16 #include "qemu/uuid.h" 17 #include "qemu/units.h" 18 #include "qemu/cutils.h" 19 20 void qdev_prop_set_after_realize(DeviceState *dev, const char *name, 21 Error **errp) 22 { 23 if (dev->id) { 24 error_setg(errp, "Attempt to set property '%s' on device '%s' " 25 "(type '%s') after it was realized", name, dev->id, 26 object_get_typename(OBJECT(dev))); 27 } else { 28 error_setg(errp, "Attempt to set property '%s' on anonymous device " 29 "(type '%s') after it was realized", name, 30 object_get_typename(OBJECT(dev))); 31 } 32 } 33 34 void qdev_prop_allow_set_link_before_realize(const Object *obj, 35 const char *name, 36 Object *val, Error **errp) 37 { 38 DeviceState *dev = DEVICE(obj); 39 40 if (dev->realized) { 41 error_setg(errp, "Attempt to set link property '%s' on device '%s' " 42 "(type '%s') after it was realized", 43 name, dev->id, object_get_typename(obj)); 44 } 45 } 46 47 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) 48 { 49 void *ptr = dev; 50 ptr += prop->offset; 51 return ptr; 52 } 53 54 static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, 55 Error **errp) 56 { 57 DeviceState *dev = DEVICE(obj); 58 Property *prop = opaque; 59 int *ptr = qdev_get_prop_ptr(dev, prop); 60 61 visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); 62 } 63 64 static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, 65 Error **errp) 66 { 67 DeviceState *dev = DEVICE(obj); 68 Property *prop = opaque; 69 int *ptr = qdev_get_prop_ptr(dev, prop); 70 71 if (dev->realized) { 72 qdev_prop_set_after_realize(dev, name, errp); 73 return; 74 } 75 76 visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); 77 } 78 79 static void set_default_value_enum(ObjectProperty *op, const Property *prop) 80 { 81 object_property_set_default_str(op, 82 qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); 83 } 84 85 /* Bit */ 86 87 static uint32_t qdev_get_prop_mask(Property *prop) 88 { 89 assert(prop->info == &qdev_prop_bit); 90 return 0x1 << prop->bitnr; 91 } 92 93 static void bit_prop_set(DeviceState *dev, Property *props, bool val) 94 { 95 uint32_t *p = qdev_get_prop_ptr(dev, props); 96 uint32_t mask = qdev_get_prop_mask(props); 97 if (val) { 98 *p |= mask; 99 } else { 100 *p &= ~mask; 101 } 102 } 103 104 static void prop_get_bit(Object *obj, Visitor *v, const char *name, 105 void *opaque, Error **errp) 106 { 107 DeviceState *dev = DEVICE(obj); 108 Property *prop = opaque; 109 uint32_t *p = qdev_get_prop_ptr(dev, prop); 110 bool value = (*p & qdev_get_prop_mask(prop)) != 0; 111 112 visit_type_bool(v, name, &value, errp); 113 } 114 115 static void prop_set_bit(Object *obj, Visitor *v, const char *name, 116 void *opaque, Error **errp) 117 { 118 DeviceState *dev = DEVICE(obj); 119 Property *prop = opaque; 120 bool value; 121 122 if (dev->realized) { 123 qdev_prop_set_after_realize(dev, name, errp); 124 return; 125 } 126 127 if (!visit_type_bool(v, name, &value, errp)) { 128 return; 129 } 130 bit_prop_set(dev, prop, value); 131 } 132 133 static void set_default_value_bool(ObjectProperty *op, const Property *prop) 134 { 135 object_property_set_default_bool(op, prop->defval.u); 136 } 137 138 const PropertyInfo qdev_prop_bit = { 139 .name = "bool", 140 .description = "on/off", 141 .get = prop_get_bit, 142 .set = prop_set_bit, 143 .set_default_value = set_default_value_bool, 144 }; 145 146 /* Bit64 */ 147 148 static uint64_t qdev_get_prop_mask64(Property *prop) 149 { 150 assert(prop->info == &qdev_prop_bit64); 151 return 0x1ull << prop->bitnr; 152 } 153 154 static void bit64_prop_set(DeviceState *dev, Property *props, bool val) 155 { 156 uint64_t *p = qdev_get_prop_ptr(dev, props); 157 uint64_t mask = qdev_get_prop_mask64(props); 158 if (val) { 159 *p |= mask; 160 } else { 161 *p &= ~mask; 162 } 163 } 164 165 static void prop_get_bit64(Object *obj, Visitor *v, const char *name, 166 void *opaque, Error **errp) 167 { 168 DeviceState *dev = DEVICE(obj); 169 Property *prop = opaque; 170 uint64_t *p = qdev_get_prop_ptr(dev, prop); 171 bool value = (*p & qdev_get_prop_mask64(prop)) != 0; 172 173 visit_type_bool(v, name, &value, errp); 174 } 175 176 static void prop_set_bit64(Object *obj, Visitor *v, const char *name, 177 void *opaque, Error **errp) 178 { 179 DeviceState *dev = DEVICE(obj); 180 Property *prop = opaque; 181 bool value; 182 183 if (dev->realized) { 184 qdev_prop_set_after_realize(dev, name, errp); 185 return; 186 } 187 188 if (!visit_type_bool(v, name, &value, errp)) { 189 return; 190 } 191 bit64_prop_set(dev, prop, value); 192 } 193 194 const PropertyInfo qdev_prop_bit64 = { 195 .name = "bool", 196 .description = "on/off", 197 .get = prop_get_bit64, 198 .set = prop_set_bit64, 199 .set_default_value = set_default_value_bool, 200 }; 201 202 /* --- bool --- */ 203 204 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque, 205 Error **errp) 206 { 207 DeviceState *dev = DEVICE(obj); 208 Property *prop = opaque; 209 bool *ptr = qdev_get_prop_ptr(dev, prop); 210 211 visit_type_bool(v, name, ptr, errp); 212 } 213 214 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque, 215 Error **errp) 216 { 217 DeviceState *dev = DEVICE(obj); 218 Property *prop = opaque; 219 bool *ptr = qdev_get_prop_ptr(dev, prop); 220 221 if (dev->realized) { 222 qdev_prop_set_after_realize(dev, name, errp); 223 return; 224 } 225 226 visit_type_bool(v, name, ptr, errp); 227 } 228 229 const PropertyInfo qdev_prop_bool = { 230 .name = "bool", 231 .get = get_bool, 232 .set = set_bool, 233 .set_default_value = set_default_value_bool, 234 }; 235 236 /* --- 8bit integer --- */ 237 238 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 239 Error **errp) 240 { 241 DeviceState *dev = DEVICE(obj); 242 Property *prop = opaque; 243 uint8_t *ptr = qdev_get_prop_ptr(dev, prop); 244 245 visit_type_uint8(v, name, ptr, errp); 246 } 247 248 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 249 Error **errp) 250 { 251 DeviceState *dev = DEVICE(obj); 252 Property *prop = opaque; 253 uint8_t *ptr = qdev_get_prop_ptr(dev, prop); 254 255 if (dev->realized) { 256 qdev_prop_set_after_realize(dev, name, errp); 257 return; 258 } 259 260 visit_type_uint8(v, name, ptr, errp); 261 } 262 263 static void set_default_value_int(ObjectProperty *op, const Property *prop) 264 { 265 object_property_set_default_int(op, prop->defval.i); 266 } 267 268 static void set_default_value_uint(ObjectProperty *op, const Property *prop) 269 { 270 object_property_set_default_uint(op, prop->defval.u); 271 } 272 273 const PropertyInfo qdev_prop_uint8 = { 274 .name = "uint8", 275 .get = get_uint8, 276 .set = set_uint8, 277 .set_default_value = set_default_value_uint, 278 }; 279 280 /* --- 16bit integer --- */ 281 282 static void get_uint16(Object *obj, Visitor *v, const char *name, 283 void *opaque, Error **errp) 284 { 285 DeviceState *dev = DEVICE(obj); 286 Property *prop = opaque; 287 uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 288 289 visit_type_uint16(v, name, ptr, errp); 290 } 291 292 static void set_uint16(Object *obj, Visitor *v, const char *name, 293 void *opaque, Error **errp) 294 { 295 DeviceState *dev = DEVICE(obj); 296 Property *prop = opaque; 297 uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 298 299 if (dev->realized) { 300 qdev_prop_set_after_realize(dev, name, errp); 301 return; 302 } 303 304 visit_type_uint16(v, name, ptr, errp); 305 } 306 307 const PropertyInfo qdev_prop_uint16 = { 308 .name = "uint16", 309 .get = get_uint16, 310 .set = set_uint16, 311 .set_default_value = set_default_value_uint, 312 }; 313 314 /* --- 32bit integer --- */ 315 316 static void get_uint32(Object *obj, Visitor *v, const char *name, 317 void *opaque, Error **errp) 318 { 319 DeviceState *dev = DEVICE(obj); 320 Property *prop = opaque; 321 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 322 323 visit_type_uint32(v, name, ptr, errp); 324 } 325 326 static void set_uint32(Object *obj, Visitor *v, const char *name, 327 void *opaque, Error **errp) 328 { 329 DeviceState *dev = DEVICE(obj); 330 Property *prop = opaque; 331 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 332 333 if (dev->realized) { 334 qdev_prop_set_after_realize(dev, name, errp); 335 return; 336 } 337 338 visit_type_uint32(v, name, ptr, errp); 339 } 340 341 static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque, 342 Error **errp) 343 { 344 DeviceState *dev = DEVICE(obj); 345 Property *prop = opaque; 346 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 347 348 visit_type_int32(v, name, ptr, errp); 349 } 350 351 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque, 352 Error **errp) 353 { 354 DeviceState *dev = DEVICE(obj); 355 Property *prop = opaque; 356 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 357 358 if (dev->realized) { 359 qdev_prop_set_after_realize(dev, name, errp); 360 return; 361 } 362 363 visit_type_int32(v, name, ptr, errp); 364 } 365 366 const PropertyInfo qdev_prop_uint32 = { 367 .name = "uint32", 368 .get = get_uint32, 369 .set = set_uint32, 370 .set_default_value = set_default_value_uint, 371 }; 372 373 const PropertyInfo qdev_prop_int32 = { 374 .name = "int32", 375 .get = get_int32, 376 .set = set_int32, 377 .set_default_value = set_default_value_int, 378 }; 379 380 /* --- 64bit integer --- */ 381 382 static void get_uint64(Object *obj, Visitor *v, const char *name, 383 void *opaque, Error **errp) 384 { 385 DeviceState *dev = DEVICE(obj); 386 Property *prop = opaque; 387 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 388 389 visit_type_uint64(v, name, ptr, errp); 390 } 391 392 static void set_uint64(Object *obj, Visitor *v, const char *name, 393 void *opaque, Error **errp) 394 { 395 DeviceState *dev = DEVICE(obj); 396 Property *prop = opaque; 397 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 398 399 if (dev->realized) { 400 qdev_prop_set_after_realize(dev, name, errp); 401 return; 402 } 403 404 visit_type_uint64(v, name, ptr, errp); 405 } 406 407 static void get_int64(Object *obj, Visitor *v, const char *name, 408 void *opaque, Error **errp) 409 { 410 DeviceState *dev = DEVICE(obj); 411 Property *prop = opaque; 412 int64_t *ptr = qdev_get_prop_ptr(dev, prop); 413 414 visit_type_int64(v, name, ptr, errp); 415 } 416 417 static void set_int64(Object *obj, Visitor *v, const char *name, 418 void *opaque, Error **errp) 419 { 420 DeviceState *dev = DEVICE(obj); 421 Property *prop = opaque; 422 int64_t *ptr = qdev_get_prop_ptr(dev, prop); 423 424 if (dev->realized) { 425 qdev_prop_set_after_realize(dev, name, errp); 426 return; 427 } 428 429 visit_type_int64(v, name, ptr, errp); 430 } 431 432 const PropertyInfo qdev_prop_uint64 = { 433 .name = "uint64", 434 .get = get_uint64, 435 .set = set_uint64, 436 .set_default_value = set_default_value_uint, 437 }; 438 439 const PropertyInfo qdev_prop_int64 = { 440 .name = "int64", 441 .get = get_int64, 442 .set = set_int64, 443 .set_default_value = set_default_value_int, 444 }; 445 446 /* --- string --- */ 447 448 static void release_string(Object *obj, const char *name, void *opaque) 449 { 450 Property *prop = opaque; 451 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop)); 452 } 453 454 static void get_string(Object *obj, Visitor *v, const char *name, 455 void *opaque, Error **errp) 456 { 457 DeviceState *dev = DEVICE(obj); 458 Property *prop = opaque; 459 char **ptr = qdev_get_prop_ptr(dev, prop); 460 461 if (!*ptr) { 462 char *str = (char *)""; 463 visit_type_str(v, name, &str, errp); 464 } else { 465 visit_type_str(v, name, ptr, errp); 466 } 467 } 468 469 static void set_string(Object *obj, Visitor *v, const char *name, 470 void *opaque, Error **errp) 471 { 472 DeviceState *dev = DEVICE(obj); 473 Property *prop = opaque; 474 char **ptr = qdev_get_prop_ptr(dev, prop); 475 char *str; 476 477 if (dev->realized) { 478 qdev_prop_set_after_realize(dev, name, errp); 479 return; 480 } 481 482 if (!visit_type_str(v, name, &str, errp)) { 483 return; 484 } 485 g_free(*ptr); 486 *ptr = str; 487 } 488 489 const PropertyInfo qdev_prop_string = { 490 .name = "str", 491 .release = release_string, 492 .get = get_string, 493 .set = set_string, 494 }; 495 496 /* --- mac address --- */ 497 498 /* 499 * accepted syntax versions: 500 * 01:02:03:04:05:06 501 * 01-02-03-04-05-06 502 */ 503 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, 504 Error **errp) 505 { 506 DeviceState *dev = DEVICE(obj); 507 Property *prop = opaque; 508 MACAddr *mac = qdev_get_prop_ptr(dev, prop); 509 char buffer[2 * 6 + 5 + 1]; 510 char *p = buffer; 511 512 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", 513 mac->a[0], mac->a[1], mac->a[2], 514 mac->a[3], mac->a[4], mac->a[5]); 515 516 visit_type_str(v, name, &p, errp); 517 } 518 519 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, 520 Error **errp) 521 { 522 DeviceState *dev = DEVICE(obj); 523 Property *prop = opaque; 524 MACAddr *mac = qdev_get_prop_ptr(dev, prop); 525 int i, pos; 526 char *str, *p; 527 528 if (dev->realized) { 529 qdev_prop_set_after_realize(dev, name, errp); 530 return; 531 } 532 533 if (!visit_type_str(v, name, &str, errp)) { 534 return; 535 } 536 537 for (i = 0, pos = 0; i < 6; i++, pos += 3) { 538 if (!qemu_isxdigit(str[pos])) { 539 goto inval; 540 } 541 if (!qemu_isxdigit(str[pos+1])) { 542 goto inval; 543 } 544 if (i == 5) { 545 if (str[pos+2] != '\0') { 546 goto inval; 547 } 548 } else { 549 if (str[pos+2] != ':' && str[pos+2] != '-') { 550 goto inval; 551 } 552 } 553 mac->a[i] = strtol(str+pos, &p, 16); 554 } 555 g_free(str); 556 return; 557 558 inval: 559 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 560 g_free(str); 561 } 562 563 const PropertyInfo qdev_prop_macaddr = { 564 .name = "str", 565 .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", 566 .get = get_mac, 567 .set = set_mac, 568 }; 569 570 /* --- Reserved Region --- */ 571 572 /* 573 * Accepted syntax: 574 * <low address>:<high address>:<type> 575 * where low/high addresses are uint64_t in hexadecimal 576 * and type is a non-negative decimal integer 577 */ 578 static void get_reserved_region(Object *obj, Visitor *v, const char *name, 579 void *opaque, Error **errp) 580 { 581 DeviceState *dev = DEVICE(obj); 582 Property *prop = opaque; 583 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); 584 char buffer[64]; 585 char *p = buffer; 586 int rc; 587 588 rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u", 589 rr->low, rr->high, rr->type); 590 assert(rc < sizeof(buffer)); 591 592 visit_type_str(v, name, &p, errp); 593 } 594 595 static void set_reserved_region(Object *obj, Visitor *v, const char *name, 596 void *opaque, Error **errp) 597 { 598 DeviceState *dev = DEVICE(obj); 599 Property *prop = opaque; 600 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); 601 Error *local_err = NULL; 602 const char *endptr; 603 char *str; 604 int ret; 605 606 if (dev->realized) { 607 qdev_prop_set_after_realize(dev, name, errp); 608 return; 609 } 610 611 visit_type_str(v, name, &str, &local_err); 612 if (local_err) { 613 error_propagate(errp, local_err); 614 return; 615 } 616 617 ret = qemu_strtou64(str, &endptr, 16, &rr->low); 618 if (ret) { 619 error_setg(errp, "start address of '%s'" 620 " must be a hexadecimal integer", name); 621 goto out; 622 } 623 if (*endptr != ':') { 624 goto separator_error; 625 } 626 627 ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high); 628 if (ret) { 629 error_setg(errp, "end address of '%s'" 630 " must be a hexadecimal integer", name); 631 goto out; 632 } 633 if (*endptr != ':') { 634 goto separator_error; 635 } 636 637 ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type); 638 if (ret) { 639 error_setg(errp, "type of '%s'" 640 " must be a non-negative decimal integer", name); 641 } 642 goto out; 643 644 separator_error: 645 error_setg(errp, "reserved region fields must be separated with ':'"); 646 out: 647 g_free(str); 648 return; 649 } 650 651 const PropertyInfo qdev_prop_reserved_region = { 652 .name = "reserved_region", 653 .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0", 654 .get = get_reserved_region, 655 .set = set_reserved_region, 656 }; 657 658 /* --- on/off/auto --- */ 659 660 const PropertyInfo qdev_prop_on_off_auto = { 661 .name = "OnOffAuto", 662 .description = "on/off/auto", 663 .enum_table = &OnOffAuto_lookup, 664 .get = get_enum, 665 .set = set_enum, 666 .set_default_value = set_default_value_enum, 667 }; 668 669 /* --- lost tick policy --- */ 670 671 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); 672 673 const PropertyInfo qdev_prop_losttickpolicy = { 674 .name = "LostTickPolicy", 675 .enum_table = &LostTickPolicy_lookup, 676 .get = get_enum, 677 .set = set_enum, 678 .set_default_value = set_default_value_enum, 679 }; 680 681 /* --- Block device error handling policy --- */ 682 683 QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); 684 685 const PropertyInfo qdev_prop_blockdev_on_error = { 686 .name = "BlockdevOnError", 687 .description = "Error handling policy, " 688 "report/ignore/enospc/stop/auto", 689 .enum_table = &BlockdevOnError_lookup, 690 .get = get_enum, 691 .set = set_enum, 692 .set_default_value = set_default_value_enum, 693 }; 694 695 /* --- BIOS CHS translation */ 696 697 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); 698 699 const PropertyInfo qdev_prop_bios_chs_trans = { 700 .name = "BiosAtaTranslation", 701 .description = "Logical CHS translation algorithm, " 702 "auto/none/lba/large/rechs", 703 .enum_table = &BiosAtaTranslation_lookup, 704 .get = get_enum, 705 .set = set_enum, 706 .set_default_value = set_default_value_enum, 707 }; 708 709 /* --- FDC default drive types */ 710 711 const PropertyInfo qdev_prop_fdc_drive_type = { 712 .name = "FdcDriveType", 713 .description = "FDC drive type, " 714 "144/288/120/none/auto", 715 .enum_table = &FloppyDriveType_lookup, 716 .get = get_enum, 717 .set = set_enum, 718 .set_default_value = set_default_value_enum, 719 }; 720 721 /* --- MultiFDCompression --- */ 722 723 const PropertyInfo qdev_prop_multifd_compression = { 724 .name = "MultiFDCompression", 725 .description = "multifd_compression values, " 726 "none/zlib/zstd", 727 .enum_table = &MultiFDCompression_lookup, 728 .get = get_enum, 729 .set = set_enum, 730 .set_default_value = set_default_value_enum, 731 }; 732 733 /* --- pci address --- */ 734 735 /* 736 * bus-local address, i.e. "$slot" or "$slot.$fn" 737 */ 738 static void set_pci_devfn(Object *obj, Visitor *v, const char *name, 739 void *opaque, Error **errp) 740 { 741 DeviceState *dev = DEVICE(obj); 742 Property *prop = opaque; 743 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); 744 unsigned int slot, fn, n; 745 Error *local_err = NULL; 746 char *str; 747 748 if (dev->realized) { 749 qdev_prop_set_after_realize(dev, name, errp); 750 return; 751 } 752 753 if (!visit_type_str(v, name, &str, &local_err)) { 754 error_free(local_err); 755 local_err = NULL; 756 if (!visit_type_int32(v, name, &value, errp)) { 757 return; 758 } 759 if (value < -1 || value > 255) { 760 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 761 name ? name : "null", "pci_devfn"); 762 return; 763 } 764 *ptr = value; 765 return; 766 } 767 768 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { 769 fn = 0; 770 if (sscanf(str, "%x%n", &slot, &n) != 1) { 771 goto invalid; 772 } 773 } 774 if (str[n] != '\0' || fn > 7 || slot > 31) { 775 goto invalid; 776 } 777 *ptr = slot << 3 | fn; 778 g_free(str); 779 return; 780 781 invalid: 782 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 783 g_free(str); 784 } 785 786 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, 787 size_t len) 788 { 789 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 790 791 if (*ptr == -1) { 792 return snprintf(dest, len, "<unset>"); 793 } else { 794 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); 795 } 796 } 797 798 const PropertyInfo qdev_prop_pci_devfn = { 799 .name = "int32", 800 .description = "Slot and optional function number, example: 06.0 or 06", 801 .print = print_pci_devfn, 802 .get = get_int32, 803 .set = set_pci_devfn, 804 .set_default_value = set_default_value_int, 805 }; 806 807 /* --- 32bit unsigned int 'size' type --- */ 808 809 static void get_size32(Object *obj, Visitor *v, const char *name, void *opaque, 810 Error **errp) 811 { 812 DeviceState *dev = DEVICE(obj); 813 Property *prop = opaque; 814 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 815 uint64_t value = *ptr; 816 817 visit_type_size(v, name, &value, errp); 818 } 819 820 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, 821 Error **errp) 822 { 823 DeviceState *dev = DEVICE(obj); 824 Property *prop = opaque; 825 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 826 uint64_t value; 827 828 if (dev->realized) { 829 qdev_prop_set_after_realize(dev, name, errp); 830 return; 831 } 832 833 if (!visit_type_size(v, name, &value, errp)) { 834 return; 835 } 836 837 if (value > UINT32_MAX) { 838 error_setg(errp, 839 "Property %s.%s doesn't take value %" PRIu64 840 " (maximum: %u)", 841 dev->id ? : "", name, value, UINT32_MAX); 842 return; 843 } 844 845 *ptr = value; 846 } 847 848 const PropertyInfo qdev_prop_size32 = { 849 .name = "size", 850 .get = get_size32, 851 .set = set_size32, 852 .set_default_value = set_default_value_uint, 853 }; 854 855 /* --- blocksize --- */ 856 857 /* lower limit is sector size */ 858 #define MIN_BLOCK_SIZE 512 859 #define MIN_BLOCK_SIZE_STR "512 B" 860 /* 861 * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and 862 * matches qcow2 cluster size limit 863 */ 864 #define MAX_BLOCK_SIZE (2 * MiB) 865 #define MAX_BLOCK_SIZE_STR "2 MiB" 866 867 static void set_blocksize(Object *obj, Visitor *v, const char *name, 868 void *opaque, Error **errp) 869 { 870 DeviceState *dev = DEVICE(obj); 871 Property *prop = opaque; 872 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 873 uint64_t value; 874 875 if (dev->realized) { 876 qdev_prop_set_after_realize(dev, name, errp); 877 return; 878 } 879 880 if (!visit_type_size(v, name, &value, errp)) { 881 return; 882 } 883 /* value of 0 means "unset" */ 884 if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) { 885 error_setg(errp, 886 "Property %s.%s doesn't take value %" PRIu64 887 " (minimum: " MIN_BLOCK_SIZE_STR 888 ", maximum: " MAX_BLOCK_SIZE_STR ")", 889 dev->id ? : "", name, value); 890 return; 891 } 892 893 /* We rely on power-of-2 blocksizes for bitmasks */ 894 if ((value & (value - 1)) != 0) { 895 error_setg(errp, 896 "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2", 897 dev->id ?: "", name, (int64_t)value); 898 return; 899 } 900 901 *ptr = value; 902 } 903 904 const PropertyInfo qdev_prop_blocksize = { 905 .name = "size", 906 .description = "A power of two between " MIN_BLOCK_SIZE_STR 907 " and " MAX_BLOCK_SIZE_STR, 908 .get = get_size32, 909 .set = set_blocksize, 910 .set_default_value = set_default_value_uint, 911 }; 912 913 /* --- pci host address --- */ 914 915 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, 916 void *opaque, Error **errp) 917 { 918 DeviceState *dev = DEVICE(obj); 919 Property *prop = opaque; 920 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 921 char buffer[] = "ffff:ff:ff.f"; 922 char *p = buffer; 923 int rc = 0; 924 925 /* 926 * Catch "invalid" device reference from vfio-pci and allow the 927 * default buffer representing the non-existent device to be used. 928 */ 929 if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { 930 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", 931 addr->domain, addr->bus, addr->slot, addr->function); 932 assert(rc == sizeof(buffer) - 1); 933 } 934 935 visit_type_str(v, name, &p, errp); 936 } 937 938 /* 939 * Parse [<domain>:]<bus>:<slot>.<func> 940 * if <domain> is not supplied, it's assumed to be 0. 941 */ 942 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, 943 void *opaque, Error **errp) 944 { 945 DeviceState *dev = DEVICE(obj); 946 Property *prop = opaque; 947 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 948 char *str, *p; 949 char *e; 950 unsigned long val; 951 unsigned long dom = 0, bus = 0; 952 unsigned int slot = 0, func = 0; 953 954 if (dev->realized) { 955 qdev_prop_set_after_realize(dev, name, errp); 956 return; 957 } 958 959 if (!visit_type_str(v, name, &str, errp)) { 960 return; 961 } 962 963 p = str; 964 val = strtoul(p, &e, 16); 965 if (e == p || *e != ':') { 966 goto inval; 967 } 968 bus = val; 969 970 p = e + 1; 971 val = strtoul(p, &e, 16); 972 if (e == p) { 973 goto inval; 974 } 975 if (*e == ':') { 976 dom = bus; 977 bus = val; 978 p = e + 1; 979 val = strtoul(p, &e, 16); 980 if (e == p) { 981 goto inval; 982 } 983 } 984 slot = val; 985 986 if (*e != '.') { 987 goto inval; 988 } 989 p = e + 1; 990 val = strtoul(p, &e, 10); 991 if (e == p) { 992 goto inval; 993 } 994 func = val; 995 996 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { 997 goto inval; 998 } 999 1000 if (*e) { 1001 goto inval; 1002 } 1003 1004 addr->domain = dom; 1005 addr->bus = bus; 1006 addr->slot = slot; 1007 addr->function = func; 1008 1009 g_free(str); 1010 return; 1011 1012 inval: 1013 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 1014 g_free(str); 1015 } 1016 1017 const PropertyInfo qdev_prop_pci_host_devaddr = { 1018 .name = "str", 1019 .description = "Address (bus/device/function) of " 1020 "the host device, example: 04:10.0", 1021 .get = get_pci_host_devaddr, 1022 .set = set_pci_host_devaddr, 1023 }; 1024 1025 /* --- UUID --- */ 1026 1027 static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque, 1028 Error **errp) 1029 { 1030 DeviceState *dev = DEVICE(obj); 1031 Property *prop = opaque; 1032 QemuUUID *uuid = qdev_get_prop_ptr(dev, prop); 1033 char buffer[UUID_FMT_LEN + 1]; 1034 char *p = buffer; 1035 1036 qemu_uuid_unparse(uuid, buffer); 1037 1038 visit_type_str(v, name, &p, errp); 1039 } 1040 1041 #define UUID_VALUE_AUTO "auto" 1042 1043 static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque, 1044 Error **errp) 1045 { 1046 DeviceState *dev = DEVICE(obj); 1047 Property *prop = opaque; 1048 QemuUUID *uuid = qdev_get_prop_ptr(dev, prop); 1049 char *str; 1050 1051 if (dev->realized) { 1052 qdev_prop_set_after_realize(dev, name, errp); 1053 return; 1054 } 1055 1056 if (!visit_type_str(v, name, &str, errp)) { 1057 return; 1058 } 1059 1060 if (!strcmp(str, UUID_VALUE_AUTO)) { 1061 qemu_uuid_generate(uuid); 1062 } else if (qemu_uuid_parse(str, uuid) < 0) { 1063 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 1064 } 1065 g_free(str); 1066 } 1067 1068 static void set_default_uuid_auto(ObjectProperty *op, const Property *prop) 1069 { 1070 object_property_set_default_str(op, UUID_VALUE_AUTO); 1071 } 1072 1073 const PropertyInfo qdev_prop_uuid = { 1074 .name = "str", 1075 .description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO 1076 "\" for random value (default)", 1077 .get = get_uuid, 1078 .set = set_uuid, 1079 .set_default_value = set_default_uuid_auto, 1080 }; 1081 1082 /* --- support for array properties --- */ 1083 1084 /* Used as an opaque for the object properties we add for each 1085 * array element. Note that the struct Property must be first 1086 * in the struct so that a pointer to this works as the opaque 1087 * for the underlying element's property hooks as well as for 1088 * our own release callback. 1089 */ 1090 typedef struct { 1091 struct Property prop; 1092 char *propname; 1093 ObjectPropertyRelease *release; 1094 } ArrayElementProperty; 1095 1096 /* object property release callback for array element properties: 1097 * we call the underlying element's property release hook, and 1098 * then free the memory we allocated when we added the property. 1099 */ 1100 static void array_element_release(Object *obj, const char *name, void *opaque) 1101 { 1102 ArrayElementProperty *p = opaque; 1103 if (p->release) { 1104 p->release(obj, name, opaque); 1105 } 1106 g_free(p->propname); 1107 g_free(p); 1108 } 1109 1110 static void set_prop_arraylen(Object *obj, Visitor *v, const char *name, 1111 void *opaque, Error **errp) 1112 { 1113 /* Setter for the property which defines the length of a 1114 * variable-sized property array. As well as actually setting the 1115 * array-length field in the device struct, we have to create the 1116 * array itself and dynamically add the corresponding properties. 1117 */ 1118 DeviceState *dev = DEVICE(obj); 1119 Property *prop = opaque; 1120 uint32_t *alenptr = qdev_get_prop_ptr(dev, prop); 1121 void **arrayptr = (void *)dev + prop->arrayoffset; 1122 void *eltptr; 1123 const char *arrayname; 1124 int i; 1125 1126 if (dev->realized) { 1127 qdev_prop_set_after_realize(dev, name, errp); 1128 return; 1129 } 1130 if (*alenptr) { 1131 error_setg(errp, "array size property %s may not be set more than once", 1132 name); 1133 return; 1134 } 1135 if (!visit_type_uint32(v, name, alenptr, errp)) { 1136 return; 1137 } 1138 if (!*alenptr) { 1139 return; 1140 } 1141 1142 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix; 1143 * strip it off so we can get the name of the array itself. 1144 */ 1145 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX, 1146 strlen(PROP_ARRAY_LEN_PREFIX)) == 0); 1147 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX); 1148 1149 /* Note that it is the responsibility of the individual device's deinit 1150 * to free the array proper. 1151 */ 1152 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize); 1153 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) { 1154 char *propname = g_strdup_printf("%s[%d]", arrayname, i); 1155 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1); 1156 arrayprop->release = prop->arrayinfo->release; 1157 arrayprop->propname = propname; 1158 arrayprop->prop.info = prop->arrayinfo; 1159 arrayprop->prop.name = propname; 1160 /* This ugly piece of pointer arithmetic sets up the offset so 1161 * that when the underlying get/set hooks call qdev_get_prop_ptr 1162 * they get the right answer despite the array element not actually 1163 * being inside the device struct. 1164 */ 1165 arrayprop->prop.offset = eltptr - (void *)dev; 1166 assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr); 1167 object_property_add(obj, propname, 1168 arrayprop->prop.info->name, 1169 arrayprop->prop.info->get, 1170 arrayprop->prop.info->set, 1171 array_element_release, 1172 arrayprop); 1173 } 1174 } 1175 1176 const PropertyInfo qdev_prop_arraylen = { 1177 .name = "uint32", 1178 .get = get_uint32, 1179 .set = set_prop_arraylen, 1180 .set_default_value = set_default_value_uint, 1181 }; 1182 1183 /* --- public helpers --- */ 1184 1185 static Property *qdev_prop_walk(Property *props, const char *name) 1186 { 1187 if (!props) { 1188 return NULL; 1189 } 1190 while (props->name) { 1191 if (strcmp(props->name, name) == 0) { 1192 return props; 1193 } 1194 props++; 1195 } 1196 return NULL; 1197 } 1198 1199 static Property *qdev_prop_find(DeviceState *dev, const char *name) 1200 { 1201 ObjectClass *class; 1202 Property *prop; 1203 1204 /* device properties */ 1205 class = object_get_class(OBJECT(dev)); 1206 do { 1207 prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name); 1208 if (prop) { 1209 return prop; 1210 } 1211 class = object_class_get_parent(class); 1212 } while (class != object_class_by_name(TYPE_DEVICE)); 1213 1214 return NULL; 1215 } 1216 1217 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, 1218 Property *prop, const char *value) 1219 { 1220 switch (ret) { 1221 case -EEXIST: 1222 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", 1223 object_get_typename(OBJECT(dev)), prop->name, value); 1224 break; 1225 default: 1226 case -EINVAL: 1227 error_setg(errp, QERR_PROPERTY_VALUE_BAD, 1228 object_get_typename(OBJECT(dev)), prop->name, value); 1229 break; 1230 case -ENOENT: 1231 error_setg(errp, "Property '%s.%s' can't find value '%s'", 1232 object_get_typename(OBJECT(dev)), prop->name, value); 1233 break; 1234 case 0: 1235 break; 1236 } 1237 } 1238 1239 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) 1240 { 1241 object_property_set_bool(OBJECT(dev), name, value, &error_abort); 1242 } 1243 1244 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) 1245 { 1246 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1247 } 1248 1249 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 1250 { 1251 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1252 } 1253 1254 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 1255 { 1256 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1257 } 1258 1259 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) 1260 { 1261 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1262 } 1263 1264 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) 1265 { 1266 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1267 } 1268 1269 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) 1270 { 1271 object_property_set_str(OBJECT(dev), name, value, &error_abort); 1272 } 1273 1274 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, 1275 const uint8_t *value) 1276 { 1277 char str[2 * 6 + 5 + 1]; 1278 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", 1279 value[0], value[1], value[2], value[3], value[4], value[5]); 1280 1281 object_property_set_str(OBJECT(dev), name, str, &error_abort); 1282 } 1283 1284 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) 1285 { 1286 Property *prop; 1287 1288 prop = qdev_prop_find(dev, name); 1289 object_property_set_str(OBJECT(dev), name, 1290 qapi_enum_lookup(prop->info->enum_table, value), 1291 &error_abort); 1292 } 1293 1294 static GPtrArray *global_props(void) 1295 { 1296 static GPtrArray *gp; 1297 1298 if (!gp) { 1299 gp = g_ptr_array_new(); 1300 } 1301 1302 return gp; 1303 } 1304 1305 void qdev_prop_register_global(GlobalProperty *prop) 1306 { 1307 g_ptr_array_add(global_props(), prop); 1308 } 1309 1310 const GlobalProperty *qdev_find_global_prop(DeviceState *dev, 1311 const char *name) 1312 { 1313 GPtrArray *props = global_props(); 1314 const GlobalProperty *p; 1315 int i; 1316 1317 for (i = 0; i < props->len; i++) { 1318 p = g_ptr_array_index(props, i); 1319 if (object_dynamic_cast(OBJECT(dev), p->driver) 1320 && !strcmp(p->property, name)) { 1321 return p; 1322 } 1323 } 1324 return NULL; 1325 } 1326 1327 int qdev_prop_check_globals(void) 1328 { 1329 int i, ret = 0; 1330 1331 for (i = 0; i < global_props()->len; i++) { 1332 GlobalProperty *prop; 1333 ObjectClass *oc; 1334 DeviceClass *dc; 1335 1336 prop = g_ptr_array_index(global_props(), i); 1337 if (prop->used) { 1338 continue; 1339 } 1340 oc = object_class_by_name(prop->driver); 1341 oc = object_class_dynamic_cast(oc, TYPE_DEVICE); 1342 if (!oc) { 1343 warn_report("global %s.%s has invalid class name", 1344 prop->driver, prop->property); 1345 ret = 1; 1346 continue; 1347 } 1348 dc = DEVICE_CLASS(oc); 1349 if (!dc->hotpluggable && !prop->used) { 1350 warn_report("global %s.%s=%s not used", 1351 prop->driver, prop->property, prop->value); 1352 ret = 1; 1353 continue; 1354 } 1355 } 1356 return ret; 1357 } 1358 1359 void qdev_prop_set_globals(DeviceState *dev) 1360 { 1361 object_apply_global_props(OBJECT(dev), global_props(), 1362 dev->hotplugged ? NULL : &error_fatal); 1363 } 1364 1365 /* --- 64bit unsigned int 'size' type --- */ 1366 1367 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque, 1368 Error **errp) 1369 { 1370 DeviceState *dev = DEVICE(obj); 1371 Property *prop = opaque; 1372 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 1373 1374 visit_type_size(v, name, ptr, errp); 1375 } 1376 1377 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque, 1378 Error **errp) 1379 { 1380 DeviceState *dev = DEVICE(obj); 1381 Property *prop = opaque; 1382 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 1383 1384 visit_type_size(v, name, ptr, errp); 1385 } 1386 1387 const PropertyInfo qdev_prop_size = { 1388 .name = "size", 1389 .get = get_size, 1390 .set = set_size, 1391 .set_default_value = set_default_value_uint, 1392 }; 1393 1394 /* --- object link property --- */ 1395 1396 static void create_link_property(ObjectClass *oc, Property *prop) 1397 { 1398 object_class_property_add_link(oc, prop->name, prop->link_type, 1399 prop->offset, 1400 qdev_prop_allow_set_link_before_realize, 1401 OBJ_PROP_LINK_STRONG); 1402 } 1403 1404 const PropertyInfo qdev_prop_link = { 1405 .name = "link", 1406 .create = create_link_property, 1407 }; 1408 1409 /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ 1410 1411 const PropertyInfo qdev_prop_off_auto_pcibar = { 1412 .name = "OffAutoPCIBAR", 1413 .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", 1414 .enum_table = &OffAutoPCIBAR_lookup, 1415 .get = get_enum, 1416 .set = set_enum, 1417 .set_default_value = set_default_value_enum, 1418 }; 1419 1420 /* --- PCIELinkSpeed 2_5/5/8/16 -- */ 1421 1422 static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, 1423 void *opaque, Error **errp) 1424 { 1425 DeviceState *dev = DEVICE(obj); 1426 Property *prop = opaque; 1427 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); 1428 int speed; 1429 1430 switch (*p) { 1431 case QEMU_PCI_EXP_LNK_2_5GT: 1432 speed = PCIE_LINK_SPEED_2_5; 1433 break; 1434 case QEMU_PCI_EXP_LNK_5GT: 1435 speed = PCIE_LINK_SPEED_5; 1436 break; 1437 case QEMU_PCI_EXP_LNK_8GT: 1438 speed = PCIE_LINK_SPEED_8; 1439 break; 1440 case QEMU_PCI_EXP_LNK_16GT: 1441 speed = PCIE_LINK_SPEED_16; 1442 break; 1443 default: 1444 /* Unreachable */ 1445 abort(); 1446 } 1447 1448 visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); 1449 } 1450 1451 static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, 1452 void *opaque, Error **errp) 1453 { 1454 DeviceState *dev = DEVICE(obj); 1455 Property *prop = opaque; 1456 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); 1457 int speed; 1458 1459 if (dev->realized) { 1460 qdev_prop_set_after_realize(dev, name, errp); 1461 return; 1462 } 1463 1464 if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table, 1465 errp)) { 1466 return; 1467 } 1468 1469 switch (speed) { 1470 case PCIE_LINK_SPEED_2_5: 1471 *p = QEMU_PCI_EXP_LNK_2_5GT; 1472 break; 1473 case PCIE_LINK_SPEED_5: 1474 *p = QEMU_PCI_EXP_LNK_5GT; 1475 break; 1476 case PCIE_LINK_SPEED_8: 1477 *p = QEMU_PCI_EXP_LNK_8GT; 1478 break; 1479 case PCIE_LINK_SPEED_16: 1480 *p = QEMU_PCI_EXP_LNK_16GT; 1481 break; 1482 default: 1483 /* Unreachable */ 1484 abort(); 1485 } 1486 } 1487 1488 const PropertyInfo qdev_prop_pcie_link_speed = { 1489 .name = "PCIELinkSpeed", 1490 .description = "2_5/5/8/16", 1491 .enum_table = &PCIELinkSpeed_lookup, 1492 .get = get_prop_pcielinkspeed, 1493 .set = set_prop_pcielinkspeed, 1494 .set_default_value = set_default_value_enum, 1495 }; 1496 1497 /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ 1498 1499 static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, 1500 void *opaque, Error **errp) 1501 { 1502 DeviceState *dev = DEVICE(obj); 1503 Property *prop = opaque; 1504 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); 1505 int width; 1506 1507 switch (*p) { 1508 case QEMU_PCI_EXP_LNK_X1: 1509 width = PCIE_LINK_WIDTH_1; 1510 break; 1511 case QEMU_PCI_EXP_LNK_X2: 1512 width = PCIE_LINK_WIDTH_2; 1513 break; 1514 case QEMU_PCI_EXP_LNK_X4: 1515 width = PCIE_LINK_WIDTH_4; 1516 break; 1517 case QEMU_PCI_EXP_LNK_X8: 1518 width = PCIE_LINK_WIDTH_8; 1519 break; 1520 case QEMU_PCI_EXP_LNK_X12: 1521 width = PCIE_LINK_WIDTH_12; 1522 break; 1523 case QEMU_PCI_EXP_LNK_X16: 1524 width = PCIE_LINK_WIDTH_16; 1525 break; 1526 case QEMU_PCI_EXP_LNK_X32: 1527 width = PCIE_LINK_WIDTH_32; 1528 break; 1529 default: 1530 /* Unreachable */ 1531 abort(); 1532 } 1533 1534 visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); 1535 } 1536 1537 static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, 1538 void *opaque, Error **errp) 1539 { 1540 DeviceState *dev = DEVICE(obj); 1541 Property *prop = opaque; 1542 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); 1543 int width; 1544 1545 if (dev->realized) { 1546 qdev_prop_set_after_realize(dev, name, errp); 1547 return; 1548 } 1549 1550 if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table, 1551 errp)) { 1552 return; 1553 } 1554 1555 switch (width) { 1556 case PCIE_LINK_WIDTH_1: 1557 *p = QEMU_PCI_EXP_LNK_X1; 1558 break; 1559 case PCIE_LINK_WIDTH_2: 1560 *p = QEMU_PCI_EXP_LNK_X2; 1561 break; 1562 case PCIE_LINK_WIDTH_4: 1563 *p = QEMU_PCI_EXP_LNK_X4; 1564 break; 1565 case PCIE_LINK_WIDTH_8: 1566 *p = QEMU_PCI_EXP_LNK_X8; 1567 break; 1568 case PCIE_LINK_WIDTH_12: 1569 *p = QEMU_PCI_EXP_LNK_X12; 1570 break; 1571 case PCIE_LINK_WIDTH_16: 1572 *p = QEMU_PCI_EXP_LNK_X16; 1573 break; 1574 case PCIE_LINK_WIDTH_32: 1575 *p = QEMU_PCI_EXP_LNK_X32; 1576 break; 1577 default: 1578 /* Unreachable */ 1579 abort(); 1580 } 1581 } 1582 1583 const PropertyInfo qdev_prop_pcie_link_width = { 1584 .name = "PCIELinkWidth", 1585 .description = "1/2/4/8/12/16/32", 1586 .enum_table = &PCIELinkWidth_lookup, 1587 .get = get_prop_pcielinkwidth, 1588 .set = set_prop_pcielinkwidth, 1589 .set_default_value = set_default_value_enum, 1590 }; 1591