blob: 5e19ec8be3c08d110ff8226284c97f26cb9a3ab8 [file] [log] [blame]
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001#include "net.h"
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02002#include "qdev.h"
Markus Armbruster9f59b562010-03-22 10:29:00 +01003#include "qerror.h"
Blue Swirl24463332010-08-24 15:22:24 +00004#include "blockdev.h"
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02005
6void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
7{
8 void *ptr = dev;
9 ptr += prop->offset;
10 return ptr;
11}
12
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020013static uint32_t qdev_get_prop_mask(Property *prop)
14{
15 assert(prop->info->type == PROP_TYPE_BIT);
16 return 0x1 << prop->bitnr;
17}
18
19static void bit_prop_set(DeviceState *dev, Property *props, bool val)
20{
21 uint32_t *p = qdev_get_prop_ptr(dev, props);
22 uint32_t mask = qdev_get_prop_mask(props);
23 if (val)
Michael S. Tsirkindbd48322010-01-12 21:16:59 +020024 *p |= mask;
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020025 else
26 *p &= ~mask;
27}
28
29static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
30{
31 if (props->info->type == PROP_TYPE_BIT) {
32 bool *defval = src;
33 bit_prop_set(dev, props, *defval);
34 } else {
35 char *dst = qdev_get_prop_ptr(dev, props);
36 memcpy(dst, src, props->info->size);
37 }
38}
39
40/* Bit */
41static int parse_bit(DeviceState *dev, Property *prop, const char *str)
42{
Jan Kiszkac455d172012-01-21 14:43:07 +010043 if (!strcasecmp(str, "on"))
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020044 bit_prop_set(dev, prop, true);
Jan Kiszkac455d172012-01-21 14:43:07 +010045 else if (!strcasecmp(str, "off"))
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020046 bit_prop_set(dev, prop, false);
47 else
Markus Armbruster6bf38812010-02-26 15:50:50 +010048 return -EINVAL;
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020049 return 0;
50}
51
52static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
53{
David 'Digit' Turner5a5e3d52011-01-10 23:11:40 +010054 uint32_t *p = qdev_get_prop_ptr(dev, prop);
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020055 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
56}
57
Anthony Liguori57c9faf2012-01-30 08:55:55 -060058static void get_bit(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010059 const char *name, Error **errp)
60{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060061 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010062 Property *prop = opaque;
63 uint32_t *p = qdev_get_prop_ptr(dev, prop);
64 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
65
66 visit_type_bool(v, &value, name, errp);
67}
68
Anthony Liguori57c9faf2012-01-30 08:55:55 -060069static void set_bit(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010070 const char *name, Error **errp)
71{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060072 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010073 Property *prop = opaque;
74 Error *local_err = NULL;
75 bool value;
76
77 if (dev->state != DEV_STATE_CREATED) {
78 error_set(errp, QERR_PERMISSION_DENIED);
79 return;
80 }
81
82 visit_type_bool(v, &value, name, &local_err);
83 if (local_err) {
84 error_propagate(errp, local_err);
85 return;
86 }
87 bit_prop_set(dev, prop, value);
88}
89
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020090PropertyInfo qdev_prop_bit = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +010091 .name = "boolean",
92 .legacy_name = "on/off",
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020093 .type = PROP_TYPE_BIT,
94 .size = sizeof(uint32_t),
95 .parse = parse_bit,
96 .print = print_bit,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010097 .get = get_bit,
98 .set = set_bit,
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020099};
100
Juan Quintelac7cc1722009-09-29 22:48:25 +0200101/* --- 8bit integer --- */
102
103static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
104{
105 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200106 char *end;
Juan Quintelac7cc1722009-09-29 22:48:25 +0200107
108 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200109 *ptr = strtoul(str, &end, 0);
110 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100111 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200112 }
113
Juan Quintelac7cc1722009-09-29 22:48:25 +0200114 return 0;
115}
116
117static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
118{
119 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
120 return snprintf(dest, len, "%" PRIu8, *ptr);
121}
122
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600123static void get_int8(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100124 const char *name, Error **errp)
125{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600126 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100127 Property *prop = opaque;
128 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
129 int64_t value;
130
131 value = *ptr;
132 visit_type_int(v, &value, name, errp);
133}
134
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600135static void set_int8(Object *obj, Visitor *v, void *opaque,
136 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100137{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600138 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100139 Property *prop = opaque;
140 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
141 Error *local_err = NULL;
142 int64_t value;
143
144 if (dev->state != DEV_STATE_CREATED) {
145 error_set(errp, QERR_PERMISSION_DENIED);
146 return;
147 }
148
149 visit_type_int(v, &value, name, &local_err);
150 if (local_err) {
151 error_propagate(errp, local_err);
152 return;
153 }
154 if (value > prop->info->min && value <= prop->info->max) {
155 *ptr = value;
156 } else {
157 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
158 dev->id?:"", name, value, prop->info->min,
159 prop->info->max);
160 }
161}
162
Juan Quintelac7cc1722009-09-29 22:48:25 +0200163PropertyInfo qdev_prop_uint8 = {
164 .name = "uint8",
165 .type = PROP_TYPE_UINT8,
166 .size = sizeof(uint8_t),
167 .parse = parse_uint8,
168 .print = print_uint8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100169 .get = get_int8,
170 .set = set_int8,
171 .min = 0,
172 .max = 255,
Juan Quintelac7cc1722009-09-29 22:48:25 +0200173};
174
Jan Kiszka68356782011-10-07 09:19:52 +0200175/* --- 8bit hex value --- */
176
177static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
178{
179 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
180 char *end;
181
182 *ptr = strtoul(str, &end, 16);
183 if ((*end != '\0') || (end == str)) {
184 return -EINVAL;
185 }
186
187 return 0;
188}
189
190static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
191{
192 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
193 return snprintf(dest, len, "0x%" PRIx8, *ptr);
194}
195
196PropertyInfo qdev_prop_hex8 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100197 .name = "uint8",
198 .legacy_name = "hex8",
Jan Kiszka68356782011-10-07 09:19:52 +0200199 .type = PROP_TYPE_UINT8,
200 .size = sizeof(uint8_t),
201 .parse = parse_hex8,
202 .print = print_hex8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100203 .get = get_int8,
204 .set = set_int8,
205 .min = 0,
206 .max = 255,
Jan Kiszka68356782011-10-07 09:19:52 +0200207};
208
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200209/* --- 16bit integer --- */
210
211static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
212{
213 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200214 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200215
216 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200217 *ptr = strtoul(str, &end, 0);
218 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100219 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200220 }
221
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200222 return 0;
223}
224
225static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
226{
227 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
228 return snprintf(dest, len, "%" PRIu16, *ptr);
229}
230
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600231static void get_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100232 const char *name, Error **errp)
233{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600234 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100235 Property *prop = opaque;
236 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
237 int64_t value;
238
239 value = *ptr;
240 visit_type_int(v, &value, name, errp);
241}
242
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600243static void set_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100244 const char *name, Error **errp)
245{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600246 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100247 Property *prop = opaque;
248 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
249 Error *local_err = NULL;
250 int64_t value;
251
252 if (dev->state != DEV_STATE_CREATED) {
253 error_set(errp, QERR_PERMISSION_DENIED);
254 return;
255 }
256
257 visit_type_int(v, &value, name, &local_err);
258 if (local_err) {
259 error_propagate(errp, local_err);
260 return;
261 }
262 if (value > prop->info->min && value <= prop->info->max) {
263 *ptr = value;
264 } else {
265 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
266 dev->id?:"", name, value, prop->info->min,
267 prop->info->max);
268 }
269}
270
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200271PropertyInfo qdev_prop_uint16 = {
272 .name = "uint16",
273 .type = PROP_TYPE_UINT16,
274 .size = sizeof(uint16_t),
275 .parse = parse_uint16,
276 .print = print_uint16,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100277 .get = get_int16,
278 .set = set_int16,
279 .min = 0,
280 .max = 65535,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200281};
282
283/* --- 32bit integer --- */
284
285static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
286{
287 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200288 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200289
290 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200291 *ptr = strtoul(str, &end, 0);
292 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100293 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200294 }
295
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200296 return 0;
297}
298
299static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
300{
301 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
302 return snprintf(dest, len, "%" PRIu32, *ptr);
303}
304
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600305static void get_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100306 const char *name, Error **errp)
307{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600308 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100309 Property *prop = opaque;
310 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
311 int64_t value;
312
313 value = *ptr;
314 visit_type_int(v, &value, name, errp);
315}
316
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600317static void set_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100318 const char *name, Error **errp)
319{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600320 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100321 Property *prop = opaque;
322 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
323 Error *local_err = NULL;
324 int64_t value;
325
326 if (dev->state != DEV_STATE_CREATED) {
327 error_set(errp, QERR_PERMISSION_DENIED);
328 return;
329 }
330
331 visit_type_int(v, &value, name, &local_err);
332 if (local_err) {
333 error_propagate(errp, local_err);
334 return;
335 }
336 if (value > prop->info->min && value <= prop->info->max) {
337 *ptr = value;
338 } else {
339 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
340 dev->id?:"", name, value, prop->info->min,
341 prop->info->max);
342 }
343}
344
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200345PropertyInfo qdev_prop_uint32 = {
346 .name = "uint32",
347 .type = PROP_TYPE_UINT32,
348 .size = sizeof(uint32_t),
349 .parse = parse_uint32,
350 .print = print_uint32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100351 .get = get_int32,
352 .set = set_int32,
353 .min = 0,
354 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200355};
356
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200357static int parse_int32(DeviceState *dev, Property *prop, const char *str)
358{
359 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200360 char *end;
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200361
Kevin Wolf449041d2010-06-18 18:27:03 +0200362 *ptr = strtol(str, &end, 10);
363 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100364 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200365 }
366
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200367 return 0;
368}
369
370static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
371{
372 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
373 return snprintf(dest, len, "%" PRId32, *ptr);
374}
375
376PropertyInfo qdev_prop_int32 = {
377 .name = "int32",
378 .type = PROP_TYPE_INT32,
379 .size = sizeof(int32_t),
380 .parse = parse_int32,
381 .print = print_int32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100382 .get = get_int32,
383 .set = set_int32,
384 .min = -0x80000000LL,
385 .max = 0x7FFFFFFFLL,
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200386};
387
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200388/* --- 32bit hex value --- */
389
390static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
391{
392 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200393 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200394
Kevin Wolf449041d2010-06-18 18:27:03 +0200395 *ptr = strtoul(str, &end, 16);
396 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100397 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200398 }
399
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200400 return 0;
401}
402
403static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
404{
405 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
406 return snprintf(dest, len, "0x%" PRIx32, *ptr);
407}
408
409PropertyInfo qdev_prop_hex32 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100410 .name = "uint32",
411 .legacy_name = "hex32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200412 .type = PROP_TYPE_UINT32,
413 .size = sizeof(uint32_t),
414 .parse = parse_hex32,
415 .print = print_hex32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100416 .get = get_int32,
417 .set = set_int32,
418 .min = 0,
419 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200420};
421
Blue Swirl5a053d12009-07-21 11:10:41 +0000422/* --- 64bit integer --- */
423
424static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
425{
426 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200427 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000428
429 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200430 *ptr = strtoull(str, &end, 0);
431 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100432 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200433 }
434
Blue Swirl5a053d12009-07-21 11:10:41 +0000435 return 0;
436}
437
438static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
439{
440 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
441 return snprintf(dest, len, "%" PRIu64, *ptr);
442}
443
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600444static void get_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100445 const char *name, Error **errp)
446{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600447 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100448 Property *prop = opaque;
449 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
450
451 visit_type_int(v, ptr, name, errp);
452}
453
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600454static void set_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100455 const char *name, Error **errp)
456{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600457 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100458 Property *prop = opaque;
459 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
460
461 if (dev->state != DEV_STATE_CREATED) {
462 error_set(errp, QERR_PERMISSION_DENIED);
463 return;
464 }
465
466 visit_type_int(v, ptr, name, errp);
467}
468
Blue Swirl5a053d12009-07-21 11:10:41 +0000469PropertyInfo qdev_prop_uint64 = {
470 .name = "uint64",
471 .type = PROP_TYPE_UINT64,
472 .size = sizeof(uint64_t),
473 .parse = parse_uint64,
474 .print = print_uint64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100475 .get = get_int64,
476 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000477};
478
479/* --- 64bit hex value --- */
480
481static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
482{
483 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200484 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000485
Kevin Wolf449041d2010-06-18 18:27:03 +0200486 *ptr = strtoull(str, &end, 16);
487 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100488 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200489 }
490
Blue Swirl5a053d12009-07-21 11:10:41 +0000491 return 0;
492}
493
494static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
495{
496 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
497 return snprintf(dest, len, "0x%" PRIx64, *ptr);
498}
499
500PropertyInfo qdev_prop_hex64 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100501 .name = "uint64",
502 .legacy_name = "hex64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000503 .type = PROP_TYPE_UINT64,
504 .size = sizeof(uint64_t),
505 .parse = parse_hex64,
506 .print = print_hex64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100507 .get = get_int64,
508 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000509};
510
Gerd Hoffmann59419662009-10-12 17:15:47 +0530511/* --- string --- */
512
513static int parse_string(DeviceState *dev, Property *prop, const char *str)
514{
515 char **ptr = qdev_get_prop_ptr(dev, prop);
516
517 if (*ptr)
Anthony Liguori7267c092011-08-20 22:09:37 -0500518 g_free(*ptr);
519 *ptr = g_strdup(str);
Gerd Hoffmann59419662009-10-12 17:15:47 +0530520 return 0;
521}
522
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200523static void free_string(DeviceState *dev, Property *prop)
524{
Anthony Liguori7267c092011-08-20 22:09:37 -0500525 g_free(*(char **)qdev_get_prop_ptr(dev, prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200526}
527
Gerd Hoffmann59419662009-10-12 17:15:47 +0530528static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
529{
530 char **ptr = qdev_get_prop_ptr(dev, prop);
531 if (!*ptr)
532 return snprintf(dest, len, "<null>");
533 return snprintf(dest, len, "\"%s\"", *ptr);
534}
535
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600536static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100537 const char *name, Error **errp)
538{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600539 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100540 Property *prop = opaque;
541 char **ptr = qdev_get_prop_ptr(dev, prop);
542
543 if (!*ptr) {
544 char *str = (char *)"";
545 visit_type_str(v, &str, name, errp);
546 } else {
547 visit_type_str(v, ptr, name, errp);
548 }
549}
550
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600551static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100552 const char *name, Error **errp)
553{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600554 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100555 Property *prop = opaque;
556 char **ptr = qdev_get_prop_ptr(dev, prop);
557 Error *local_err = NULL;
558 char *str;
559
560 if (dev->state != DEV_STATE_CREATED) {
561 error_set(errp, QERR_PERMISSION_DENIED);
562 return;
563 }
564
565 visit_type_str(v, &str, name, &local_err);
566 if (local_err) {
567 error_propagate(errp, local_err);
568 return;
569 }
570 if (!*str) {
571 g_free(str);
572 str = NULL;
573 }
574 if (*ptr) {
575 g_free(*ptr);
576 }
577 *ptr = str;
578}
579
Gerd Hoffmann59419662009-10-12 17:15:47 +0530580PropertyInfo qdev_prop_string = {
581 .name = "string",
582 .type = PROP_TYPE_STRING,
583 .size = sizeof(char*),
584 .parse = parse_string,
585 .print = print_string,
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200586 .free = free_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100587 .get = get_string,
588 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530589};
590
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200591/* --- drive --- */
592
593static int parse_drive(DeviceState *dev, Property *prop, const char *str)
594{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200595 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
596 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200597
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200598 bs = bdrv_find(str);
599 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100600 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200601 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200602 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200603 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200604 return 0;
605}
606
Markus Armbruster14bafc52010-06-25 08:09:10 +0200607static void free_drive(DeviceState *dev, Property *prop)
608{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200609 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200610
611 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200612 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200613 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200614 }
615}
616
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200617static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
618{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200619 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
620 return snprintf(dest, len, "%s",
621 *ptr ? bdrv_get_device_name(*ptr) : "<null>");
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200622}
623
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600624static void get_generic(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100625 const char *name, Error **errp)
626{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600627 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100628 Property *prop = opaque;
629 void **ptr = qdev_get_prop_ptr(dev, prop);
630 char buffer[1024];
631 char *p = buffer;
632
633 buffer[0] = 0;
634 if (*ptr) {
635 prop->info->print(dev, prop, buffer, sizeof(buffer));
636 }
637 visit_type_str(v, &p, name, errp);
638}
639
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600640static void set_generic(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100641 const char *name, Error **errp)
642{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600643 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100644 Property *prop = opaque;
645 Error *local_err = NULL;
646 char *str;
647 int ret;
648
649 if (dev->state != DEV_STATE_CREATED) {
650 error_set(errp, QERR_PERMISSION_DENIED);
651 return;
652 }
653
654 visit_type_str(v, &str, name, &local_err);
655 if (local_err) {
656 error_propagate(errp, local_err);
657 return;
658 }
659 if (!*str) {
660 g_free(str);
661 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
662 return;
663 }
664 ret = prop->info->parse(dev, prop, str);
665 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
666 g_free(str);
667}
668
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200669PropertyInfo qdev_prop_drive = {
670 .name = "drive",
671 .type = PROP_TYPE_DRIVE,
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200672 .size = sizeof(BlockDriverState *),
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200673 .parse = parse_drive,
674 .print = print_drive,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100675 .get = get_generic,
676 .set = set_generic,
Markus Armbruster14bafc52010-06-25 08:09:10 +0200677 .free = free_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200678};
679
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200680/* --- character device --- */
681
Gerd Hoffmann06113712009-09-10 10:58:53 +0200682static int parse_chr(DeviceState *dev, Property *prop, const char *str)
683{
684 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
685
686 *ptr = qemu_chr_find(str);
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530687 if (*ptr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100688 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530689 }
Kusanagi Kouichid5b27162011-04-26 19:19:26 +0900690 if ((*ptr)->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530691 return -EEXIST;
692 }
Kusanagi Kouichid5b27162011-04-26 19:19:26 +0900693 --(*ptr)->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200694 return 0;
695}
696
Amit Shaha87f3e82012-01-13 15:29:47 +0530697static void free_chr(DeviceState *dev, Property *prop)
698{
699 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
700
701 if (*ptr) {
702 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
703 }
704}
705
706
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200707static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
708{
709 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Blue Swirlbc19fca2009-08-13 16:26:52 +0000710
711 if (*ptr && (*ptr)->label) {
712 return snprintf(dest, len, "%s", (*ptr)->label);
713 } else {
714 return snprintf(dest, len, "<null>");
715 }
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200716}
717
718PropertyInfo qdev_prop_chr = {
719 .name = "chr",
720 .type = PROP_TYPE_CHR,
721 .size = sizeof(CharDriverState*),
Gerd Hoffmann06113712009-09-10 10:58:53 +0200722 .parse = parse_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200723 .print = print_chr,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100724 .get = get_generic,
725 .set = set_generic,
Amit Shaha87f3e82012-01-13 15:29:47 +0530726 .free = free_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200727};
728
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200729/* --- netdev device --- */
730
731static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
732{
733 VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
734
735 *ptr = qemu_find_netdev(str);
736 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100737 return -ENOENT;
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100738 if ((*ptr)->peer) {
739 return -EEXIST;
740 }
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200741 return 0;
742}
743
744static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
745{
746 VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
747
748 if (*ptr && (*ptr)->name) {
749 return snprintf(dest, len, "%s", (*ptr)->name);
750 } else {
751 return snprintf(dest, len, "<null>");
752 }
753}
754
755PropertyInfo qdev_prop_netdev = {
756 .name = "netdev",
757 .type = PROP_TYPE_NETDEV,
758 .size = sizeof(VLANClientState*),
759 .parse = parse_netdev,
760 .print = print_netdev,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100761 .get = get_generic,
762 .set = set_generic,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200763};
764
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200765/* --- vlan --- */
766
767static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
768{
769 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
770 int id;
771
772 if (sscanf(str, "%d", &id) != 1)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100773 return -EINVAL;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200774 *ptr = qemu_find_vlan(id, 1);
775 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100776 return -ENOENT;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200777 return 0;
778}
779
780static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
781{
782 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
783
784 if (*ptr) {
785 return snprintf(dest, len, "%d", (*ptr)->id);
786 } else {
787 return snprintf(dest, len, "<null>");
788 }
789}
790
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600791static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100792 const char *name, Error **errp)
793{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600794 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100795 Property *prop = opaque;
796 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
797 int64_t id;
798
799 id = *ptr ? (*ptr)->id : -1;
800 visit_type_int(v, &id, name, errp);
801}
802
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600803static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100804 const char *name, Error **errp)
805{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600806 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100807 Property *prop = opaque;
808 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
809 Error *local_err = NULL;
810 int64_t id;
811 VLANState *vlan;
812
813 if (dev->state != DEV_STATE_CREATED) {
814 error_set(errp, QERR_PERMISSION_DENIED);
815 return;
816 }
817
818 visit_type_int(v, &id, name, &local_err);
819 if (local_err) {
820 error_propagate(errp, local_err);
821 return;
822 }
823 if (id == -1) {
824 *ptr = NULL;
825 return;
826 }
827 vlan = qemu_find_vlan(id, 1);
828 if (!vlan) {
829 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
830 name, prop->info->name);
831 return;
832 }
833 *ptr = vlan;
834}
835
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200836PropertyInfo qdev_prop_vlan = {
837 .name = "vlan",
838 .type = PROP_TYPE_VLAN,
839 .size = sizeof(VLANClientState*),
840 .parse = parse_vlan,
841 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100842 .get = get_vlan,
843 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200844};
845
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200846/* --- pointer --- */
847
Markus Armbruster036f7162010-02-19 11:47:06 +0100848/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200849PropertyInfo qdev_prop_ptr = {
850 .name = "ptr",
851 .type = PROP_TYPE_PTR,
852 .size = sizeof(void*),
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200853};
854
855/* --- mac address --- */
856
857/*
858 * accepted syntax versions:
859 * 01:02:03:04:05:06
860 * 01-02-03-04-05-06
861 */
862static int parse_mac(DeviceState *dev, Property *prop, const char *str)
863{
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200864 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200865 int i, pos;
866 char *p;
867
868 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000869 if (!qemu_isxdigit(str[pos]))
Markus Armbruster6bf38812010-02-26 15:50:50 +0100870 return -EINVAL;
Christoph Egger88e150a2009-07-17 17:48:02 +0000871 if (!qemu_isxdigit(str[pos+1]))
Markus Armbruster6bf38812010-02-26 15:50:50 +0100872 return -EINVAL;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200873 if (i == 5) {
874 if (str[pos+2] != '\0')
Markus Armbruster6bf38812010-02-26 15:50:50 +0100875 return -EINVAL;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200876 } else {
877 if (str[pos+2] != ':' && str[pos+2] != '-')
Markus Armbruster6bf38812010-02-26 15:50:50 +0100878 return -EINVAL;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200879 }
880 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200881 }
882 return 0;
883}
884
885static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
886{
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200887 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
888
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200889 return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200890 mac->a[0], mac->a[1], mac->a[2],
891 mac->a[3], mac->a[4], mac->a[5]);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200892}
893
894PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200895 .name = "macaddr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200896 .type = PROP_TYPE_MACADDR,
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200897 .size = sizeof(MACAddr),
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200898 .parse = parse_mac,
899 .print = print_mac,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100900 .get = get_generic,
901 .set = set_generic,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200902};
903
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100904
905/* --- lost tick policy --- */
906
907static const struct {
908 const char *name;
909 LostTickPolicy code;
910} lost_tick_policy_table[] = {
911 { .name = "discard", .code = LOST_TICK_DISCARD },
912 { .name = "delay", .code = LOST_TICK_DELAY },
913 { .name = "merge", .code = LOST_TICK_MERGE },
914 { .name = "slew", .code = LOST_TICK_SLEW },
915};
916
917static int parse_lost_tick_policy(DeviceState *dev, Property *prop,
918 const char *str)
919{
920 LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
921 int i;
922
923 for (i = 0; i < ARRAY_SIZE(lost_tick_policy_table); i++) {
924 if (!strcasecmp(str, lost_tick_policy_table[i].name)) {
925 *ptr = lost_tick_policy_table[i].code;
926 break;
927 }
928 }
929 if (i == ARRAY_SIZE(lost_tick_policy_table)) {
930 return -EINVAL;
931 }
932 return 0;
933}
934
935static int print_lost_tick_policy(DeviceState *dev, Property *prop, char *dest,
936 size_t len)
937{
938 LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
939
940 return snprintf(dest, len, "%s", lost_tick_policy_table[*ptr].name);
941}
942
943PropertyInfo qdev_prop_losttickpolicy = {
944 .name = "lost_tick_policy",
945 .type = PROP_TYPE_LOSTTICKPOLICY,
946 .size = sizeof(LostTickPolicy),
947 .parse = parse_lost_tick_policy,
948 .print = print_lost_tick_policy,
949 .get = get_generic,
950 .set = set_generic,
951};
952
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200953/* --- pci address --- */
954
955/*
956 * bus-local address, i.e. "$slot" or "$slot.$fn"
957 */
958static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
959{
960 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
961 unsigned int slot, fn, n;
962
963 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
964 fn = 0;
965 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100966 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200967 }
968 }
969 if (str[n] != '\0')
Markus Armbruster6bf38812010-02-26 15:50:50 +0100970 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200971 if (fn > 7)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100972 return -EINVAL;
Donald Dutileffe3ce12011-09-21 15:25:11 -0400973 if (slot > 31)
974 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200975 *ptr = slot << 3 | fn;
976 return 0;
977}
978
979static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
980{
981 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
982
Blue Swirl73538c32009-08-28 19:12:16 +0000983 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200984 return snprintf(dest, len, "<unset>");
985 } else {
986 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
987 }
988}
989
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600990static void get_pci_devfn(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100991 const char *name, Error **errp)
992{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600993 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100994 Property *prop = opaque;
995 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
996 char buffer[32];
997 char *p = buffer;
998
999 buffer[0] = 0;
1000 if (*ptr != -1) {
1001 snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7);
1002 }
1003 visit_type_str(v, &p, name, errp);
1004}
1005
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001006PropertyInfo qdev_prop_pci_devfn = {
1007 .name = "pci-devfn",
1008 .type = PROP_TYPE_UINT32,
1009 .size = sizeof(uint32_t),
1010 .parse = parse_pci_devfn,
1011 .print = print_pci_devfn,
Paolo Bonzini80e555c2011-12-18 17:05:09 +01001012 .get = get_pci_devfn,
1013 .set = set_generic,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001014};
1015
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001016/* --- public helpers --- */
1017
1018static Property *qdev_prop_walk(Property *props, const char *name)
1019{
1020 if (!props)
1021 return NULL;
1022 while (props->name) {
1023 if (strcmp(props->name, name) == 0)
1024 return props;
1025 props++;
1026 }
1027 return NULL;
1028}
1029
1030static Property *qdev_prop_find(DeviceState *dev, const char *name)
1031{
1032 Property *prop;
1033
1034 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001035 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001036 if (prop)
1037 return prop;
1038
1039 /* bus properties */
1040 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1041 if (prop)
1042 return prop;
1043
1044 return NULL;
1045}
1046
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001047int qdev_prop_exists(DeviceState *dev, const char *name)
1048{
1049 return qdev_prop_find(dev, name) ? true : false;
1050}
1051
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001052void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1053 Property *prop, const char *value)
1054{
1055 switch (ret) {
1056 case -EEXIST:
1057 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001058 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001059 break;
1060 default:
1061 case -EINVAL:
1062 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001063 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001064 break;
1065 case -ENOENT:
1066 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001067 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001068 break;
1069 case 0:
1070 break;
1071 }
1072}
1073
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001074int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1075{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001076 char *legacy_name;
1077 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001078
Paolo Bonzinid8229792012-02-02 09:47:13 +01001079 legacy_name = g_strdup_printf("legacy-%s", name);
1080 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1081 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1082 } else {
1083 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001084 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001085 g_free(legacy_name);
1086
1087 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001088 qerror_report_err(err);
1089 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001090 return -1;
1091 }
1092 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001093}
1094
1095void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
1096{
1097 Property *prop;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001098
1099 prop = qdev_prop_find(dev, name);
1100 if (!prop) {
1101 fprintf(stderr, "%s: property \"%s.%s\" not found\n",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001102 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001103 abort();
1104 }
1105 if (prop->info->type != type) {
1106 fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001107 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001108 abort();
1109 }
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +02001110 qdev_prop_cpy(dev, prop, src);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001111}
1112
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001113void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1114{
1115 qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
1116}
1117
Juan Quintelac7cc1722009-09-29 22:48:25 +02001118void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1119{
1120 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
1121}
1122
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001123void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1124{
1125 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
1126}
1127
1128void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1129{
1130 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
1131}
1132
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001133void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1134{
1135 qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
1136}
1137
Blue Swirl5a053d12009-07-21 11:10:41 +00001138void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1139{
1140 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
1141}
1142
Markus Armbrustercc984672010-06-01 20:32:30 +02001143void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1144{
1145 qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
1146}
1147
Markus Armbruster18846de2010-06-29 16:58:30 +02001148int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001149{
Markus Armbruster18846de2010-06-29 16:58:30 +02001150 int res;
1151
Markus Armbrusterfa879d62011-08-03 15:07:40 +02001152 res = bdrv_attach_dev(value, dev);
Markus Armbruster18846de2010-06-29 16:58:30 +02001153 if (res < 0) {
1154 error_report("Can't attach drive %s to %s.%s: %s",
1155 bdrv_get_device_name(value),
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001156 dev->id ? dev->id : object_get_typename(OBJECT(dev)),
Markus Armbruster18846de2010-06-29 16:58:30 +02001157 name, strerror(-res));
1158 return -1;
1159 }
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001160 qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
Markus Armbruster18846de2010-06-29 16:58:30 +02001161 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001162}
1163
Markus Armbruster18846de2010-06-29 16:58:30 +02001164void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1165{
1166 if (qdev_prop_set_drive(dev, name, value) < 0) {
1167 exit(1);
1168 }
1169}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001170void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1171{
1172 qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
1173}
1174
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001175void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1176{
1177 qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
1178}
1179
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001180void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1181{
1182 qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
1183}
1184
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001185void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1186{
1187 qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
1188}
1189
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001190void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
1191 LostTickPolicy *value)
1192{
1193 qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
1194}
1195
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001196void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1197{
1198 qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
1199}
1200
1201void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1202{
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001203 if (!props)
1204 return;
1205 while (props->name) {
1206 if (props->defval) {
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +02001207 qdev_prop_cpy(dev, props, props->defval);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001208 }
1209 props++;
1210 }
1211}
1212
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001213static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001214
Kevin Wolf25920d62010-03-15 17:01:24 +01001215static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001216{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001217 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001218}
1219
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001220void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001221{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001222 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001223
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001224 for (i = 0; props[i].driver != NULL; i++) {
1225 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001226 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001227}
1228
1229void qdev_prop_set_globals(DeviceState *dev)
1230{
1231 GlobalProperty *prop;
1232
1233 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001234 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001235 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001236 continue;
1237 }
1238 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001239 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001240 }
1241 }
1242}
Kevin Wolf25920d62010-03-15 17:01:24 +01001243
1244static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1245{
1246 GlobalProperty *g;
1247
Anthony Liguori7267c092011-08-20 22:09:37 -05001248 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001249 g->driver = qemu_opt_get(opts, "driver");
1250 g->property = qemu_opt_get(opts, "property");
1251 g->value = qemu_opt_get(opts, "value");
1252 qdev_prop_register_global(g);
1253 return 0;
1254}
1255
1256void qemu_add_globals(void)
1257{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001258 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001259}