2
0

qdev-properties.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  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 "hw/block/block.h"
  12. #include "net/hub.h"
  13. #include "qapi/visitor.h"
  14. #include "chardev/char.h"
  15. #include "qemu/uuid.h"
  16. void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
  17. Error **errp)
  18. {
  19. if (dev->id) {
  20. error_setg(errp, "Attempt to set property '%s' on device '%s' "
  21. "(type '%s') after it was realized", name, dev->id,
  22. object_get_typename(OBJECT(dev)));
  23. } else {
  24. error_setg(errp, "Attempt to set property '%s' on anonymous device "
  25. "(type '%s') after it was realized", name,
  26. object_get_typename(OBJECT(dev)));
  27. }
  28. }
  29. void qdev_prop_allow_set_link_before_realize(const Object *obj,
  30. const char *name,
  31. Object *val, Error **errp)
  32. {
  33. DeviceState *dev = DEVICE(obj);
  34. if (dev->realized) {
  35. error_setg(errp, "Attempt to set link property '%s' on device '%s' "
  36. "(type '%s') after it was realized",
  37. name, dev->id, object_get_typename(obj));
  38. }
  39. }
  40. void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
  41. {
  42. void *ptr = dev;
  43. ptr += prop->offset;
  44. return ptr;
  45. }
  46. static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
  47. Error **errp)
  48. {
  49. DeviceState *dev = DEVICE(obj);
  50. Property *prop = opaque;
  51. int *ptr = qdev_get_prop_ptr(dev, prop);
  52. visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
  53. }
  54. static void set_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. if (dev->realized) {
  61. qdev_prop_set_after_realize(dev, name, errp);
  62. return;
  63. }
  64. visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
  65. }
  66. static void set_default_value_enum(Object *obj, const Property *prop)
  67. {
  68. object_property_set_str(obj,
  69. qapi_enum_lookup(prop->info->enum_table,
  70. prop->defval.i),
  71. prop->name, &error_abort);
  72. }
  73. /* Bit */
  74. static uint32_t qdev_get_prop_mask(Property *prop)
  75. {
  76. assert(prop->info == &qdev_prop_bit);
  77. return 0x1 << prop->bitnr;
  78. }
  79. static void bit_prop_set(DeviceState *dev, Property *props, bool val)
  80. {
  81. uint32_t *p = qdev_get_prop_ptr(dev, props);
  82. uint32_t mask = qdev_get_prop_mask(props);
  83. if (val) {
  84. *p |= mask;
  85. } else {
  86. *p &= ~mask;
  87. }
  88. }
  89. static void prop_get_bit(Object *obj, Visitor *v, const char *name,
  90. void *opaque, Error **errp)
  91. {
  92. DeviceState *dev = DEVICE(obj);
  93. Property *prop = opaque;
  94. uint32_t *p = qdev_get_prop_ptr(dev, prop);
  95. bool value = (*p & qdev_get_prop_mask(prop)) != 0;
  96. visit_type_bool(v, name, &value, errp);
  97. }
  98. static void prop_set_bit(Object *obj, Visitor *v, const char *name,
  99. void *opaque, Error **errp)
  100. {
  101. DeviceState *dev = DEVICE(obj);
  102. Property *prop = opaque;
  103. Error *local_err = NULL;
  104. bool value;
  105. if (dev->realized) {
  106. qdev_prop_set_after_realize(dev, name, errp);
  107. return;
  108. }
  109. visit_type_bool(v, name, &value, &local_err);
  110. if (local_err) {
  111. error_propagate(errp, local_err);
  112. return;
  113. }
  114. bit_prop_set(dev, prop, value);
  115. }
  116. static void set_default_value_bool(Object *obj, const Property *prop)
  117. {
  118. object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
  119. }
  120. const PropertyInfo qdev_prop_bit = {
  121. .name = "bool",
  122. .description = "on/off",
  123. .get = prop_get_bit,
  124. .set = prop_set_bit,
  125. .set_default_value = set_default_value_bool,
  126. };
  127. /* Bit64 */
  128. static uint64_t qdev_get_prop_mask64(Property *prop)
  129. {
  130. assert(prop->info == &qdev_prop_bit64);
  131. return 0x1ull << prop->bitnr;
  132. }
  133. static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
  134. {
  135. uint64_t *p = qdev_get_prop_ptr(dev, props);
  136. uint64_t mask = qdev_get_prop_mask64(props);
  137. if (val) {
  138. *p |= mask;
  139. } else {
  140. *p &= ~mask;
  141. }
  142. }
  143. static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
  144. void *opaque, Error **errp)
  145. {
  146. DeviceState *dev = DEVICE(obj);
  147. Property *prop = opaque;
  148. uint64_t *p = qdev_get_prop_ptr(dev, prop);
  149. bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
  150. visit_type_bool(v, name, &value, errp);
  151. }
  152. static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
  153. void *opaque, Error **errp)
  154. {
  155. DeviceState *dev = DEVICE(obj);
  156. Property *prop = opaque;
  157. Error *local_err = NULL;
  158. bool value;
  159. if (dev->realized) {
  160. qdev_prop_set_after_realize(dev, name, errp);
  161. return;
  162. }
  163. visit_type_bool(v, name, &value, &local_err);
  164. if (local_err) {
  165. error_propagate(errp, local_err);
  166. return;
  167. }
  168. bit64_prop_set(dev, prop, value);
  169. }
  170. const PropertyInfo qdev_prop_bit64 = {
  171. .name = "bool",
  172. .description = "on/off",
  173. .get = prop_get_bit64,
  174. .set = prop_set_bit64,
  175. .set_default_value = set_default_value_bool,
  176. };
  177. /* --- bool --- */
  178. static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
  179. Error **errp)
  180. {
  181. DeviceState *dev = DEVICE(obj);
  182. Property *prop = opaque;
  183. bool *ptr = qdev_get_prop_ptr(dev, prop);
  184. visit_type_bool(v, name, ptr, errp);
  185. }
  186. static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
  187. Error **errp)
  188. {
  189. DeviceState *dev = DEVICE(obj);
  190. Property *prop = opaque;
  191. bool *ptr = qdev_get_prop_ptr(dev, prop);
  192. if (dev->realized) {
  193. qdev_prop_set_after_realize(dev, name, errp);
  194. return;
  195. }
  196. visit_type_bool(v, name, ptr, errp);
  197. }
  198. const PropertyInfo qdev_prop_bool = {
  199. .name = "bool",
  200. .get = get_bool,
  201. .set = set_bool,
  202. .set_default_value = set_default_value_bool,
  203. };
  204. /* --- 8bit integer --- */
  205. static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  206. Error **errp)
  207. {
  208. DeviceState *dev = DEVICE(obj);
  209. Property *prop = opaque;
  210. uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
  211. visit_type_uint8(v, name, ptr, errp);
  212. }
  213. static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  214. Error **errp)
  215. {
  216. DeviceState *dev = DEVICE(obj);
  217. Property *prop = opaque;
  218. uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
  219. if (dev->realized) {
  220. qdev_prop_set_after_realize(dev, name, errp);
  221. return;
  222. }
  223. visit_type_uint8(v, name, ptr, errp);
  224. }
  225. static void set_default_value_int(Object *obj, const Property *prop)
  226. {
  227. object_property_set_int(obj, prop->defval.i, prop->name, &error_abort);
  228. }
  229. static void set_default_value_uint(Object *obj, const Property *prop)
  230. {
  231. object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
  232. }
  233. const PropertyInfo qdev_prop_uint8 = {
  234. .name = "uint8",
  235. .get = get_uint8,
  236. .set = set_uint8,
  237. .set_default_value = set_default_value_uint,
  238. };
  239. /* --- 16bit integer --- */
  240. static void get_uint16(Object *obj, Visitor *v, const char *name,
  241. void *opaque, Error **errp)
  242. {
  243. DeviceState *dev = DEVICE(obj);
  244. Property *prop = opaque;
  245. uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
  246. visit_type_uint16(v, name, ptr, errp);
  247. }
  248. static void set_uint16(Object *obj, Visitor *v, const char *name,
  249. void *opaque, Error **errp)
  250. {
  251. DeviceState *dev = DEVICE(obj);
  252. Property *prop = opaque;
  253. uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
  254. if (dev->realized) {
  255. qdev_prop_set_after_realize(dev, name, errp);
  256. return;
  257. }
  258. visit_type_uint16(v, name, ptr, errp);
  259. }
  260. const PropertyInfo qdev_prop_uint16 = {
  261. .name = "uint16",
  262. .get = get_uint16,
  263. .set = set_uint16,
  264. .set_default_value = set_default_value_uint,
  265. };
  266. /* --- 32bit integer --- */
  267. static void get_uint32(Object *obj, Visitor *v, const char *name,
  268. void *opaque, Error **errp)
  269. {
  270. DeviceState *dev = DEVICE(obj);
  271. Property *prop = opaque;
  272. uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  273. visit_type_uint32(v, name, ptr, errp);
  274. }
  275. static void set_uint32(Object *obj, Visitor *v, const char *name,
  276. void *opaque, Error **errp)
  277. {
  278. DeviceState *dev = DEVICE(obj);
  279. Property *prop = opaque;
  280. uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  281. if (dev->realized) {
  282. qdev_prop_set_after_realize(dev, name, errp);
  283. return;
  284. }
  285. visit_type_uint32(v, name, ptr, errp);
  286. }
  287. static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
  288. Error **errp)
  289. {
  290. DeviceState *dev = DEVICE(obj);
  291. Property *prop = opaque;
  292. int32_t *ptr = qdev_get_prop_ptr(dev, prop);
  293. visit_type_int32(v, name, ptr, errp);
  294. }
  295. static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
  296. Error **errp)
  297. {
  298. DeviceState *dev = DEVICE(obj);
  299. Property *prop = opaque;
  300. int32_t *ptr = qdev_get_prop_ptr(dev, prop);
  301. if (dev->realized) {
  302. qdev_prop_set_after_realize(dev, name, errp);
  303. return;
  304. }
  305. visit_type_int32(v, name, ptr, errp);
  306. }
  307. const PropertyInfo qdev_prop_uint32 = {
  308. .name = "uint32",
  309. .get = get_uint32,
  310. .set = set_uint32,
  311. .set_default_value = set_default_value_uint,
  312. };
  313. const PropertyInfo qdev_prop_int32 = {
  314. .name = "int32",
  315. .get = get_int32,
  316. .set = set_int32,
  317. .set_default_value = set_default_value_int,
  318. };
  319. /* --- 64bit integer --- */
  320. static void get_uint64(Object *obj, Visitor *v, const char *name,
  321. void *opaque, Error **errp)
  322. {
  323. DeviceState *dev = DEVICE(obj);
  324. Property *prop = opaque;
  325. uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
  326. visit_type_uint64(v, name, ptr, errp);
  327. }
  328. static void set_uint64(Object *obj, Visitor *v, const char *name,
  329. void *opaque, Error **errp)
  330. {
  331. DeviceState *dev = DEVICE(obj);
  332. Property *prop = opaque;
  333. uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
  334. if (dev->realized) {
  335. qdev_prop_set_after_realize(dev, name, errp);
  336. return;
  337. }
  338. visit_type_uint64(v, name, ptr, errp);
  339. }
  340. static void get_int64(Object *obj, Visitor *v, const char *name,
  341. void *opaque, Error **errp)
  342. {
  343. DeviceState *dev = DEVICE(obj);
  344. Property *prop = opaque;
  345. int64_t *ptr = qdev_get_prop_ptr(dev, prop);
  346. visit_type_int64(v, name, ptr, errp);
  347. }
  348. static void set_int64(Object *obj, Visitor *v, const char *name,
  349. void *opaque, Error **errp)
  350. {
  351. DeviceState *dev = DEVICE(obj);
  352. Property *prop = opaque;
  353. int64_t *ptr = qdev_get_prop_ptr(dev, prop);
  354. if (dev->realized) {
  355. qdev_prop_set_after_realize(dev, name, errp);
  356. return;
  357. }
  358. visit_type_int64(v, name, ptr, errp);
  359. }
  360. const PropertyInfo qdev_prop_uint64 = {
  361. .name = "uint64",
  362. .get = get_uint64,
  363. .set = set_uint64,
  364. .set_default_value = set_default_value_uint,
  365. };
  366. const PropertyInfo qdev_prop_int64 = {
  367. .name = "int64",
  368. .get = get_int64,
  369. .set = set_int64,
  370. .set_default_value = set_default_value_int,
  371. };
  372. /* --- string --- */
  373. static void release_string(Object *obj, const char *name, void *opaque)
  374. {
  375. Property *prop = opaque;
  376. g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
  377. }
  378. static void get_string(Object *obj, Visitor *v, const char *name,
  379. void *opaque, Error **errp)
  380. {
  381. DeviceState *dev = DEVICE(obj);
  382. Property *prop = opaque;
  383. char **ptr = qdev_get_prop_ptr(dev, prop);
  384. if (!*ptr) {
  385. char *str = (char *)"";
  386. visit_type_str(v, name, &str, errp);
  387. } else {
  388. visit_type_str(v, name, ptr, errp);
  389. }
  390. }
  391. static void set_string(Object *obj, Visitor *v, const char *name,
  392. void *opaque, Error **errp)
  393. {
  394. DeviceState *dev = DEVICE(obj);
  395. Property *prop = opaque;
  396. char **ptr = qdev_get_prop_ptr(dev, prop);
  397. Error *local_err = NULL;
  398. char *str;
  399. if (dev->realized) {
  400. qdev_prop_set_after_realize(dev, name, errp);
  401. return;
  402. }
  403. visit_type_str(v, name, &str, &local_err);
  404. if (local_err) {
  405. error_propagate(errp, local_err);
  406. return;
  407. }
  408. g_free(*ptr);
  409. *ptr = str;
  410. }
  411. const PropertyInfo qdev_prop_string = {
  412. .name = "str",
  413. .release = release_string,
  414. .get = get_string,
  415. .set = set_string,
  416. };
  417. /* --- pointer --- */
  418. /* Not a proper property, just for dirty hacks. TODO Remove it! */
  419. const PropertyInfo qdev_prop_ptr = {
  420. .name = "ptr",
  421. };
  422. /* --- mac address --- */
  423. /*
  424. * accepted syntax versions:
  425. * 01:02:03:04:05:06
  426. * 01-02-03-04-05-06
  427. */
  428. static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
  429. Error **errp)
  430. {
  431. DeviceState *dev = DEVICE(obj);
  432. Property *prop = opaque;
  433. MACAddr *mac = qdev_get_prop_ptr(dev, prop);
  434. char buffer[2 * 6 + 5 + 1];
  435. char *p = buffer;
  436. snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
  437. mac->a[0], mac->a[1], mac->a[2],
  438. mac->a[3], mac->a[4], mac->a[5]);
  439. visit_type_str(v, name, &p, errp);
  440. }
  441. static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
  442. Error **errp)
  443. {
  444. DeviceState *dev = DEVICE(obj);
  445. Property *prop = opaque;
  446. MACAddr *mac = qdev_get_prop_ptr(dev, prop);
  447. Error *local_err = NULL;
  448. int i, pos;
  449. char *str, *p;
  450. if (dev->realized) {
  451. qdev_prop_set_after_realize(dev, name, errp);
  452. return;
  453. }
  454. visit_type_str(v, name, &str, &local_err);
  455. if (local_err) {
  456. error_propagate(errp, local_err);
  457. return;
  458. }
  459. for (i = 0, pos = 0; i < 6; i++, pos += 3) {
  460. if (!qemu_isxdigit(str[pos])) {
  461. goto inval;
  462. }
  463. if (!qemu_isxdigit(str[pos+1])) {
  464. goto inval;
  465. }
  466. if (i == 5) {
  467. if (str[pos+2] != '\0') {
  468. goto inval;
  469. }
  470. } else {
  471. if (str[pos+2] != ':' && str[pos+2] != '-') {
  472. goto inval;
  473. }
  474. }
  475. mac->a[i] = strtol(str+pos, &p, 16);
  476. }
  477. g_free(str);
  478. return;
  479. inval:
  480. error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
  481. g_free(str);
  482. }
  483. const PropertyInfo qdev_prop_macaddr = {
  484. .name = "str",
  485. .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
  486. .get = get_mac,
  487. .set = set_mac,
  488. };
  489. /* --- on/off/auto --- */
  490. const PropertyInfo qdev_prop_on_off_auto = {
  491. .name = "OnOffAuto",
  492. .description = "on/off/auto",
  493. .enum_table = &OnOffAuto_lookup,
  494. .get = get_enum,
  495. .set = set_enum,
  496. .set_default_value = set_default_value_enum,
  497. };
  498. /* --- lost tick policy --- */
  499. QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
  500. const PropertyInfo qdev_prop_losttickpolicy = {
  501. .name = "LostTickPolicy",
  502. .enum_table = &LostTickPolicy_lookup,
  503. .get = get_enum,
  504. .set = set_enum,
  505. .set_default_value = set_default_value_enum,
  506. };
  507. /* --- Block device error handling policy --- */
  508. QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
  509. const PropertyInfo qdev_prop_blockdev_on_error = {
  510. .name = "BlockdevOnError",
  511. .description = "Error handling policy, "
  512. "report/ignore/enospc/stop/auto",
  513. .enum_table = &BlockdevOnError_lookup,
  514. .get = get_enum,
  515. .set = set_enum,
  516. .set_default_value = set_default_value_enum,
  517. };
  518. /* --- BIOS CHS translation */
  519. QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
  520. const PropertyInfo qdev_prop_bios_chs_trans = {
  521. .name = "BiosAtaTranslation",
  522. .description = "Logical CHS translation algorithm, "
  523. "auto/none/lba/large/rechs",
  524. .enum_table = &BiosAtaTranslation_lookup,
  525. .get = get_enum,
  526. .set = set_enum,
  527. .set_default_value = set_default_value_enum,
  528. };
  529. /* --- FDC default drive types */
  530. const PropertyInfo qdev_prop_fdc_drive_type = {
  531. .name = "FdcDriveType",
  532. .description = "FDC drive type, "
  533. "144/288/120/none/auto",
  534. .enum_table = &FloppyDriveType_lookup,
  535. .get = get_enum,
  536. .set = set_enum,
  537. .set_default_value = set_default_value_enum,
  538. };
  539. /* --- pci address --- */
  540. /*
  541. * bus-local address, i.e. "$slot" or "$slot.$fn"
  542. */
  543. static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
  544. void *opaque, Error **errp)
  545. {
  546. DeviceState *dev = DEVICE(obj);
  547. Property *prop = opaque;
  548. int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
  549. unsigned int slot, fn, n;
  550. Error *local_err = NULL;
  551. char *str;
  552. if (dev->realized) {
  553. qdev_prop_set_after_realize(dev, name, errp);
  554. return;
  555. }
  556. visit_type_str(v, name, &str, &local_err);
  557. if (local_err) {
  558. error_free(local_err);
  559. local_err = NULL;
  560. visit_type_int32(v, name, &value, &local_err);
  561. if (local_err) {
  562. error_propagate(errp, local_err);
  563. } else if (value < -1 || value > 255) {
  564. error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
  565. name ? name : "null", "pci_devfn");
  566. } else {
  567. *ptr = value;
  568. }
  569. return;
  570. }
  571. if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
  572. fn = 0;
  573. if (sscanf(str, "%x%n", &slot, &n) != 1) {
  574. goto invalid;
  575. }
  576. }
  577. if (str[n] != '\0' || fn > 7 || slot > 31) {
  578. goto invalid;
  579. }
  580. *ptr = slot << 3 | fn;
  581. g_free(str);
  582. return;
  583. invalid:
  584. error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
  585. g_free(str);
  586. }
  587. static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
  588. size_t len)
  589. {
  590. int32_t *ptr = qdev_get_prop_ptr(dev, prop);
  591. if (*ptr == -1) {
  592. return snprintf(dest, len, "<unset>");
  593. } else {
  594. return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
  595. }
  596. }
  597. const PropertyInfo qdev_prop_pci_devfn = {
  598. .name = "int32",
  599. .description = "Slot and optional function number, example: 06.0 or 06",
  600. .print = print_pci_devfn,
  601. .get = get_int32,
  602. .set = set_pci_devfn,
  603. .set_default_value = set_default_value_int,
  604. };
  605. /* --- blocksize --- */
  606. static void set_blocksize(Object *obj, Visitor *v, const char *name,
  607. void *opaque, Error **errp)
  608. {
  609. DeviceState *dev = DEVICE(obj);
  610. Property *prop = opaque;
  611. uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
  612. Error *local_err = NULL;
  613. const int64_t min = 512;
  614. const int64_t max = 32768;
  615. if (dev->realized) {
  616. qdev_prop_set_after_realize(dev, name, errp);
  617. return;
  618. }
  619. visit_type_uint16(v, name, &value, &local_err);
  620. if (local_err) {
  621. error_propagate(errp, local_err);
  622. return;
  623. }
  624. /* value of 0 means "unset" */
  625. if (value && (value < min || value > max)) {
  626. error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
  627. dev->id ? : "", name, (int64_t)value, min, max);
  628. return;
  629. }
  630. /* We rely on power-of-2 blocksizes for bitmasks */
  631. if ((value & (value - 1)) != 0) {
  632. error_setg(errp,
  633. "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
  634. dev->id ?: "", name, (int64_t)value);
  635. return;
  636. }
  637. *ptr = value;
  638. }
  639. const PropertyInfo qdev_prop_blocksize = {
  640. .name = "uint16",
  641. .description = "A power of two between 512 and 32768",
  642. .get = get_uint16,
  643. .set = set_blocksize,
  644. .set_default_value = set_default_value_uint,
  645. };
  646. /* --- pci host address --- */
  647. static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
  648. void *opaque, Error **errp)
  649. {
  650. DeviceState *dev = DEVICE(obj);
  651. Property *prop = opaque;
  652. PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
  653. char buffer[] = "ffff:ff:ff.f";
  654. char *p = buffer;
  655. int rc = 0;
  656. /*
  657. * Catch "invalid" device reference from vfio-pci and allow the
  658. * default buffer representing the non-existent device to be used.
  659. */
  660. if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
  661. rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
  662. addr->domain, addr->bus, addr->slot, addr->function);
  663. assert(rc == sizeof(buffer) - 1);
  664. }
  665. visit_type_str(v, name, &p, errp);
  666. }
  667. /*
  668. * Parse [<domain>:]<bus>:<slot>.<func>
  669. * if <domain> is not supplied, it's assumed to be 0.
  670. */
  671. static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
  672. void *opaque, Error **errp)
  673. {
  674. DeviceState *dev = DEVICE(obj);
  675. Property *prop = opaque;
  676. PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
  677. Error *local_err = NULL;
  678. char *str, *p;
  679. char *e;
  680. unsigned long val;
  681. unsigned long dom = 0, bus = 0;
  682. unsigned int slot = 0, func = 0;
  683. if (dev->realized) {
  684. qdev_prop_set_after_realize(dev, name, errp);
  685. return;
  686. }
  687. visit_type_str(v, name, &str, &local_err);
  688. if (local_err) {
  689. error_propagate(errp, local_err);
  690. return;
  691. }
  692. p = str;
  693. val = strtoul(p, &e, 16);
  694. if (e == p || *e != ':') {
  695. goto inval;
  696. }
  697. bus = val;
  698. p = e + 1;
  699. val = strtoul(p, &e, 16);
  700. if (e == p) {
  701. goto inval;
  702. }
  703. if (*e == ':') {
  704. dom = bus;
  705. bus = val;
  706. p = e + 1;
  707. val = strtoul(p, &e, 16);
  708. if (e == p) {
  709. goto inval;
  710. }
  711. }
  712. slot = val;
  713. if (*e != '.') {
  714. goto inval;
  715. }
  716. p = e + 1;
  717. val = strtoul(p, &e, 10);
  718. if (e == p) {
  719. goto inval;
  720. }
  721. func = val;
  722. if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
  723. goto inval;
  724. }
  725. if (*e) {
  726. goto inval;
  727. }
  728. addr->domain = dom;
  729. addr->bus = bus;
  730. addr->slot = slot;
  731. addr->function = func;
  732. g_free(str);
  733. return;
  734. inval:
  735. error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
  736. g_free(str);
  737. }
  738. const PropertyInfo qdev_prop_pci_host_devaddr = {
  739. .name = "str",
  740. .description = "Address (bus/device/function) of "
  741. "the host device, example: 04:10.0",
  742. .get = get_pci_host_devaddr,
  743. .set = set_pci_host_devaddr,
  744. };
  745. /* --- UUID --- */
  746. static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
  747. Error **errp)
  748. {
  749. DeviceState *dev = DEVICE(obj);
  750. Property *prop = opaque;
  751. QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
  752. char buffer[UUID_FMT_LEN + 1];
  753. char *p = buffer;
  754. qemu_uuid_unparse(uuid, buffer);
  755. visit_type_str(v, name, &p, errp);
  756. }
  757. #define UUID_VALUE_AUTO "auto"
  758. static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
  759. Error **errp)
  760. {
  761. DeviceState *dev = DEVICE(obj);
  762. Property *prop = opaque;
  763. QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
  764. Error *local_err = NULL;
  765. char *str;
  766. if (dev->realized) {
  767. qdev_prop_set_after_realize(dev, name, errp);
  768. return;
  769. }
  770. visit_type_str(v, name, &str, &local_err);
  771. if (local_err) {
  772. error_propagate(errp, local_err);
  773. return;
  774. }
  775. if (!strcmp(str, UUID_VALUE_AUTO)) {
  776. qemu_uuid_generate(uuid);
  777. } else if (qemu_uuid_parse(str, uuid) < 0) {
  778. error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
  779. }
  780. g_free(str);
  781. }
  782. static void set_default_uuid_auto(Object *obj, const Property *prop)
  783. {
  784. object_property_set_str(obj, UUID_VALUE_AUTO, prop->name, &error_abort);
  785. }
  786. const PropertyInfo qdev_prop_uuid = {
  787. .name = "str",
  788. .description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO
  789. "\" for random value (default)",
  790. .get = get_uuid,
  791. .set = set_uuid,
  792. .set_default_value = set_default_uuid_auto,
  793. };
  794. /* --- support for array properties --- */
  795. /* Used as an opaque for the object properties we add for each
  796. * array element. Note that the struct Property must be first
  797. * in the struct so that a pointer to this works as the opaque
  798. * for the underlying element's property hooks as well as for
  799. * our own release callback.
  800. */
  801. typedef struct {
  802. struct Property prop;
  803. char *propname;
  804. ObjectPropertyRelease *release;
  805. } ArrayElementProperty;
  806. /* object property release callback for array element properties:
  807. * we call the underlying element's property release hook, and
  808. * then free the memory we allocated when we added the property.
  809. */
  810. static void array_element_release(Object *obj, const char *name, void *opaque)
  811. {
  812. ArrayElementProperty *p = opaque;
  813. if (p->release) {
  814. p->release(obj, name, opaque);
  815. }
  816. g_free(p->propname);
  817. g_free(p);
  818. }
  819. static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
  820. void *opaque, Error **errp)
  821. {
  822. /* Setter for the property which defines the length of a
  823. * variable-sized property array. As well as actually setting the
  824. * array-length field in the device struct, we have to create the
  825. * array itself and dynamically add the corresponding properties.
  826. */
  827. DeviceState *dev = DEVICE(obj);
  828. Property *prop = opaque;
  829. uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
  830. void **arrayptr = (void *)dev + prop->arrayoffset;
  831. Error *local_err = NULL;
  832. void *eltptr;
  833. const char *arrayname;
  834. int i;
  835. if (dev->realized) {
  836. qdev_prop_set_after_realize(dev, name, errp);
  837. return;
  838. }
  839. if (*alenptr) {
  840. error_setg(errp, "array size property %s may not be set more than once",
  841. name);
  842. return;
  843. }
  844. visit_type_uint32(v, name, alenptr, &local_err);
  845. if (local_err) {
  846. error_propagate(errp, local_err);
  847. return;
  848. }
  849. if (!*alenptr) {
  850. return;
  851. }
  852. /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
  853. * strip it off so we can get the name of the array itself.
  854. */
  855. assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
  856. strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
  857. arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
  858. /* Note that it is the responsibility of the individual device's deinit
  859. * to free the array proper.
  860. */
  861. *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
  862. for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
  863. char *propname = g_strdup_printf("%s[%d]", arrayname, i);
  864. ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
  865. arrayprop->release = prop->arrayinfo->release;
  866. arrayprop->propname = propname;
  867. arrayprop->prop.info = prop->arrayinfo;
  868. arrayprop->prop.name = propname;
  869. /* This ugly piece of pointer arithmetic sets up the offset so
  870. * that when the underlying get/set hooks call qdev_get_prop_ptr
  871. * they get the right answer despite the array element not actually
  872. * being inside the device struct.
  873. */
  874. arrayprop->prop.offset = eltptr - (void *)dev;
  875. assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
  876. object_property_add(obj, propname,
  877. arrayprop->prop.info->name,
  878. arrayprop->prop.info->get,
  879. arrayprop->prop.info->set,
  880. array_element_release,
  881. arrayprop, &local_err);
  882. if (local_err) {
  883. error_propagate(errp, local_err);
  884. return;
  885. }
  886. }
  887. }
  888. const PropertyInfo qdev_prop_arraylen = {
  889. .name = "uint32",
  890. .get = get_uint32,
  891. .set = set_prop_arraylen,
  892. .set_default_value = set_default_value_uint,
  893. };
  894. /* --- public helpers --- */
  895. static Property *qdev_prop_walk(Property *props, const char *name)
  896. {
  897. if (!props) {
  898. return NULL;
  899. }
  900. while (props->name) {
  901. if (strcmp(props->name, name) == 0) {
  902. return props;
  903. }
  904. props++;
  905. }
  906. return NULL;
  907. }
  908. static Property *qdev_prop_find(DeviceState *dev, const char *name)
  909. {
  910. ObjectClass *class;
  911. Property *prop;
  912. /* device properties */
  913. class = object_get_class(OBJECT(dev));
  914. do {
  915. prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
  916. if (prop) {
  917. return prop;
  918. }
  919. class = object_class_get_parent(class);
  920. } while (class != object_class_by_name(TYPE_DEVICE));
  921. return NULL;
  922. }
  923. void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
  924. Property *prop, const char *value)
  925. {
  926. switch (ret) {
  927. case -EEXIST:
  928. error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
  929. object_get_typename(OBJECT(dev)), prop->name, value);
  930. break;
  931. default:
  932. case -EINVAL:
  933. error_setg(errp, QERR_PROPERTY_VALUE_BAD,
  934. object_get_typename(OBJECT(dev)), prop->name, value);
  935. break;
  936. case -ENOENT:
  937. error_setg(errp, "Property '%s.%s' can't find value '%s'",
  938. object_get_typename(OBJECT(dev)), prop->name, value);
  939. break;
  940. case 0:
  941. break;
  942. }
  943. }
  944. void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
  945. {
  946. object_property_set_bool(OBJECT(dev), value, name, &error_abort);
  947. }
  948. void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
  949. {
  950. object_property_set_int(OBJECT(dev), value, name, &error_abort);
  951. }
  952. void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
  953. {
  954. object_property_set_int(OBJECT(dev), value, name, &error_abort);
  955. }
  956. void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
  957. {
  958. object_property_set_int(OBJECT(dev), value, name, &error_abort);
  959. }
  960. void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
  961. {
  962. object_property_set_int(OBJECT(dev), value, name, &error_abort);
  963. }
  964. void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
  965. {
  966. object_property_set_int(OBJECT(dev), value, name, &error_abort);
  967. }
  968. void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
  969. {
  970. object_property_set_str(OBJECT(dev), value, name, &error_abort);
  971. }
  972. void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
  973. const uint8_t *value)
  974. {
  975. char str[2 * 6 + 5 + 1];
  976. snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
  977. value[0], value[1], value[2], value[3], value[4], value[5]);
  978. object_property_set_str(OBJECT(dev), str, name, &error_abort);
  979. }
  980. void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
  981. {
  982. Property *prop;
  983. prop = qdev_prop_find(dev, name);
  984. object_property_set_str(OBJECT(dev),
  985. qapi_enum_lookup(prop->info->enum_table, value),
  986. name, &error_abort);
  987. }
  988. void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
  989. {
  990. Property *prop;
  991. void **ptr;
  992. prop = qdev_prop_find(dev, name);
  993. assert(prop && prop->info == &qdev_prop_ptr);
  994. ptr = qdev_get_prop_ptr(dev, prop);
  995. *ptr = value;
  996. }
  997. static GPtrArray *global_props(void)
  998. {
  999. static GPtrArray *gp;
  1000. if (!gp) {
  1001. gp = g_ptr_array_new();
  1002. }
  1003. return gp;
  1004. }
  1005. void qdev_prop_register_global(GlobalProperty *prop)
  1006. {
  1007. g_ptr_array_add(global_props(), prop);
  1008. }
  1009. int qdev_prop_check_globals(void)
  1010. {
  1011. int i, ret = 0;
  1012. for (i = 0; i < global_props()->len; i++) {
  1013. GlobalProperty *prop;
  1014. ObjectClass *oc;
  1015. DeviceClass *dc;
  1016. prop = g_ptr_array_index(global_props(), i);
  1017. if (prop->used) {
  1018. continue;
  1019. }
  1020. oc = object_class_by_name(prop->driver);
  1021. oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
  1022. if (!oc) {
  1023. warn_report("global %s.%s has invalid class name",
  1024. prop->driver, prop->property);
  1025. ret = 1;
  1026. continue;
  1027. }
  1028. dc = DEVICE_CLASS(oc);
  1029. if (!dc->hotpluggable && !prop->used) {
  1030. warn_report("global %s.%s=%s not used",
  1031. prop->driver, prop->property, prop->value);
  1032. ret = 1;
  1033. continue;
  1034. }
  1035. }
  1036. return ret;
  1037. }
  1038. void qdev_prop_set_globals(DeviceState *dev)
  1039. {
  1040. object_apply_global_props(OBJECT(dev), global_props(),
  1041. dev->hotplugged ? NULL : &error_fatal);
  1042. }
  1043. /* --- 64bit unsigned int 'size' type --- */
  1044. static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
  1045. Error **errp)
  1046. {
  1047. DeviceState *dev = DEVICE(obj);
  1048. Property *prop = opaque;
  1049. uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
  1050. visit_type_size(v, name, ptr, errp);
  1051. }
  1052. static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
  1053. Error **errp)
  1054. {
  1055. DeviceState *dev = DEVICE(obj);
  1056. Property *prop = opaque;
  1057. uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
  1058. visit_type_size(v, name, ptr, errp);
  1059. }
  1060. const PropertyInfo qdev_prop_size = {
  1061. .name = "size",
  1062. .get = get_size,
  1063. .set = set_size,
  1064. .set_default_value = set_default_value_uint,
  1065. };
  1066. /* --- object link property --- */
  1067. static void create_link_property(Object *obj, Property *prop, Error **errp)
  1068. {
  1069. Object **child = qdev_get_prop_ptr(DEVICE(obj), prop);
  1070. object_property_add_link(obj, prop->name, prop->link_type,
  1071. child,
  1072. qdev_prop_allow_set_link_before_realize,
  1073. OBJ_PROP_LINK_STRONG,
  1074. errp);
  1075. }
  1076. const PropertyInfo qdev_prop_link = {
  1077. .name = "link",
  1078. .create = create_link_property,
  1079. };
  1080. /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
  1081. const PropertyInfo qdev_prop_off_auto_pcibar = {
  1082. .name = "OffAutoPCIBAR",
  1083. .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
  1084. .enum_table = &OffAutoPCIBAR_lookup,
  1085. .get = get_enum,
  1086. .set = set_enum,
  1087. .set_default_value = set_default_value_enum,
  1088. };
  1089. /* --- PCIELinkSpeed 2_5/5/8/16 -- */
  1090. static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
  1091. void *opaque, Error **errp)
  1092. {
  1093. DeviceState *dev = DEVICE(obj);
  1094. Property *prop = opaque;
  1095. PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
  1096. int speed;
  1097. switch (*p) {
  1098. case QEMU_PCI_EXP_LNK_2_5GT:
  1099. speed = PCIE_LINK_SPEED_2_5;
  1100. break;
  1101. case QEMU_PCI_EXP_LNK_5GT:
  1102. speed = PCIE_LINK_SPEED_5;
  1103. break;
  1104. case QEMU_PCI_EXP_LNK_8GT:
  1105. speed = PCIE_LINK_SPEED_8;
  1106. break;
  1107. case QEMU_PCI_EXP_LNK_16GT:
  1108. speed = PCIE_LINK_SPEED_16;
  1109. break;
  1110. default:
  1111. /* Unreachable */
  1112. abort();
  1113. }
  1114. visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
  1115. }
  1116. static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
  1117. void *opaque, Error **errp)
  1118. {
  1119. DeviceState *dev = DEVICE(obj);
  1120. Property *prop = opaque;
  1121. PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
  1122. int speed;
  1123. Error *local_err = NULL;
  1124. if (dev->realized) {
  1125. qdev_prop_set_after_realize(dev, name, errp);
  1126. return;
  1127. }
  1128. visit_type_enum(v, prop->name, &speed, prop->info->enum_table, &local_err);
  1129. if (local_err) {
  1130. error_propagate(errp, local_err);
  1131. return;
  1132. }
  1133. switch (speed) {
  1134. case PCIE_LINK_SPEED_2_5:
  1135. *p = QEMU_PCI_EXP_LNK_2_5GT;
  1136. break;
  1137. case PCIE_LINK_SPEED_5:
  1138. *p = QEMU_PCI_EXP_LNK_5GT;
  1139. break;
  1140. case PCIE_LINK_SPEED_8:
  1141. *p = QEMU_PCI_EXP_LNK_8GT;
  1142. break;
  1143. case PCIE_LINK_SPEED_16:
  1144. *p = QEMU_PCI_EXP_LNK_16GT;
  1145. break;
  1146. default:
  1147. /* Unreachable */
  1148. abort();
  1149. }
  1150. }
  1151. const PropertyInfo qdev_prop_pcie_link_speed = {
  1152. .name = "PCIELinkSpeed",
  1153. .description = "2_5/5/8/16",
  1154. .enum_table = &PCIELinkSpeed_lookup,
  1155. .get = get_prop_pcielinkspeed,
  1156. .set = set_prop_pcielinkspeed,
  1157. .set_default_value = set_default_value_enum,
  1158. };
  1159. /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
  1160. static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
  1161. void *opaque, Error **errp)
  1162. {
  1163. DeviceState *dev = DEVICE(obj);
  1164. Property *prop = opaque;
  1165. PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
  1166. int width;
  1167. switch (*p) {
  1168. case QEMU_PCI_EXP_LNK_X1:
  1169. width = PCIE_LINK_WIDTH_1;
  1170. break;
  1171. case QEMU_PCI_EXP_LNK_X2:
  1172. width = PCIE_LINK_WIDTH_2;
  1173. break;
  1174. case QEMU_PCI_EXP_LNK_X4:
  1175. width = PCIE_LINK_WIDTH_4;
  1176. break;
  1177. case QEMU_PCI_EXP_LNK_X8:
  1178. width = PCIE_LINK_WIDTH_8;
  1179. break;
  1180. case QEMU_PCI_EXP_LNK_X12:
  1181. width = PCIE_LINK_WIDTH_12;
  1182. break;
  1183. case QEMU_PCI_EXP_LNK_X16:
  1184. width = PCIE_LINK_WIDTH_16;
  1185. break;
  1186. case QEMU_PCI_EXP_LNK_X32:
  1187. width = PCIE_LINK_WIDTH_32;
  1188. break;
  1189. default:
  1190. /* Unreachable */
  1191. abort();
  1192. }
  1193. visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
  1194. }
  1195. static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
  1196. void *opaque, Error **errp)
  1197. {
  1198. DeviceState *dev = DEVICE(obj);
  1199. Property *prop = opaque;
  1200. PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
  1201. int width;
  1202. Error *local_err = NULL;
  1203. if (dev->realized) {
  1204. qdev_prop_set_after_realize(dev, name, errp);
  1205. return;
  1206. }
  1207. visit_type_enum(v, prop->name, &width, prop->info->enum_table, &local_err);
  1208. if (local_err) {
  1209. error_propagate(errp, local_err);
  1210. return;
  1211. }
  1212. switch (width) {
  1213. case PCIE_LINK_WIDTH_1:
  1214. *p = QEMU_PCI_EXP_LNK_X1;
  1215. break;
  1216. case PCIE_LINK_WIDTH_2:
  1217. *p = QEMU_PCI_EXP_LNK_X2;
  1218. break;
  1219. case PCIE_LINK_WIDTH_4:
  1220. *p = QEMU_PCI_EXP_LNK_X4;
  1221. break;
  1222. case PCIE_LINK_WIDTH_8:
  1223. *p = QEMU_PCI_EXP_LNK_X8;
  1224. break;
  1225. case PCIE_LINK_WIDTH_12:
  1226. *p = QEMU_PCI_EXP_LNK_X12;
  1227. break;
  1228. case PCIE_LINK_WIDTH_16:
  1229. *p = QEMU_PCI_EXP_LNK_X16;
  1230. break;
  1231. case PCIE_LINK_WIDTH_32:
  1232. *p = QEMU_PCI_EXP_LNK_X32;
  1233. break;
  1234. default:
  1235. /* Unreachable */
  1236. abort();
  1237. }
  1238. }
  1239. const PropertyInfo qdev_prop_pcie_link_width = {
  1240. .name = "PCIELinkWidth",
  1241. .description = "1/2/4/8/12/16/32",
  1242. .enum_table = &PCIELinkWidth_lookup,
  1243. .get = get_prop_pcielinkwidth,
  1244. .set = set_prop_pcielinkwidth,
  1245. .set_default_value = set_default_value_enum,
  1246. };