blob: 67995a32ddf117ba67d1c96aad904dd874b97256 [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
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200513static void free_string(DeviceState *dev, Property *prop)
514{
Anthony Liguori7267c092011-08-20 22:09:37 -0500515 g_free(*(char **)qdev_get_prop_ptr(dev, prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200516}
517
Gerd Hoffmann59419662009-10-12 17:15:47 +0530518static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
519{
520 char **ptr = qdev_get_prop_ptr(dev, prop);
521 if (!*ptr)
522 return snprintf(dest, len, "<null>");
523 return snprintf(dest, len, "\"%s\"", *ptr);
524}
525
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600526static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100527 const char *name, Error **errp)
528{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600529 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100530 Property *prop = opaque;
531 char **ptr = qdev_get_prop_ptr(dev, prop);
532
533 if (!*ptr) {
534 char *str = (char *)"";
535 visit_type_str(v, &str, name, errp);
536 } else {
537 visit_type_str(v, ptr, name, errp);
538 }
539}
540
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600541static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100542 const char *name, Error **errp)
543{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600544 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100545 Property *prop = opaque;
546 char **ptr = qdev_get_prop_ptr(dev, prop);
547 Error *local_err = NULL;
548 char *str;
549
550 if (dev->state != DEV_STATE_CREATED) {
551 error_set(errp, QERR_PERMISSION_DENIED);
552 return;
553 }
554
555 visit_type_str(v, &str, name, &local_err);
556 if (local_err) {
557 error_propagate(errp, local_err);
558 return;
559 }
560 if (!*str) {
561 g_free(str);
562 str = NULL;
563 }
564 if (*ptr) {
565 g_free(*ptr);
566 }
567 *ptr = str;
568}
569
Gerd Hoffmann59419662009-10-12 17:15:47 +0530570PropertyInfo qdev_prop_string = {
571 .name = "string",
572 .type = PROP_TYPE_STRING,
573 .size = sizeof(char*),
Gerd Hoffmann59419662009-10-12 17:15:47 +0530574 .print = print_string,
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200575 .free = free_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100576 .get = get_string,
577 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530578};
579
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200580/* --- drive --- */
581
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100582static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200583{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200584 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200585
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200586 bs = bdrv_find(str);
587 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100588 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200589 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200590 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200591 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200592 return 0;
593}
594
Markus Armbruster14bafc52010-06-25 08:09:10 +0200595static void free_drive(DeviceState *dev, Property *prop)
596{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200597 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200598
599 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200600 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200601 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200602 }
603}
604
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100605static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200606{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100607 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200608}
609
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100610static void get_pointer(Object *obj, Visitor *v, Property *prop,
611 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100612 const char *name, Error **errp)
613{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600614 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100615 void **ptr = qdev_get_prop_ptr(dev, prop);
616 char *p;
617
618 p = (char *) (*ptr ? print(*ptr) : "");
619 visit_type_str(v, &p, name, errp);
620}
621
622static void set_pointer(Object *obj, Visitor *v, Property *prop,
623 int (*parse)(DeviceState *dev, const char *str, void **ptr),
624 const char *name, Error **errp)
625{
626 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100627 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100628 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100629 char *str;
630 int ret;
631
632 if (dev->state != DEV_STATE_CREATED) {
633 error_set(errp, QERR_PERMISSION_DENIED);
634 return;
635 }
636
637 visit_type_str(v, &str, name, &local_err);
638 if (local_err) {
639 error_propagate(errp, local_err);
640 return;
641 }
642 if (!*str) {
643 g_free(str);
644 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
645 return;
646 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100647 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100648 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
649 g_free(str);
650}
651
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100652static void get_drive(Object *obj, Visitor *v, void *opaque,
653 const char *name, Error **errp)
654{
655 get_pointer(obj, v, opaque, print_drive, name, errp);
656}
657
658static void set_drive(Object *obj, Visitor *v, void *opaque,
659 const char *name, Error **errp)
660{
661 set_pointer(obj, v, opaque, parse_drive, name, errp);
662}
663
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200664PropertyInfo qdev_prop_drive = {
665 .name = "drive",
666 .type = PROP_TYPE_DRIVE,
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200667 .size = sizeof(BlockDriverState *),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100668 .get = get_drive,
669 .set = set_drive,
Markus Armbruster14bafc52010-06-25 08:09:10 +0200670 .free = free_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200671};
672
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200673/* --- character device --- */
674
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100675static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200676{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100677 CharDriverState *chr = qemu_chr_find(str);
678 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100679 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530680 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100681 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530682 return -EEXIST;
683 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100684 *ptr = chr;
685 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200686 return 0;
687}
688
Amit Shaha87f3e82012-01-13 15:29:47 +0530689static void free_chr(DeviceState *dev, Property *prop)
690{
691 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
692
693 if (*ptr) {
694 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
695 }
696}
697
698
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100699static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200700{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100701 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000702
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100703 return chr->label ? chr->label : "";
704}
705
706static void get_chr(Object *obj, Visitor *v, void *opaque,
707 const char *name, Error **errp)
708{
709 get_pointer(obj, v, opaque, print_chr, name, errp);
710}
711
712static void set_chr(Object *obj, Visitor *v, void *opaque,
713 const char *name, Error **errp)
714{
715 set_pointer(obj, v, opaque, parse_chr, name, errp);
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*),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100722 .get = get_chr,
723 .set = set_chr,
Amit Shaha87f3e82012-01-13 15:29:47 +0530724 .free = free_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200725};
726
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200727/* --- netdev device --- */
728
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100729static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200730{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100731 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200732
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100733 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100734 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100735 }
736 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100737 return -EEXIST;
738 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100739 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200740 return 0;
741}
742
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100743static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200744{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100745 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200746
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100747 return netdev->name ? netdev->name : "";
748}
749
750static void get_netdev(Object *obj, Visitor *v, void *opaque,
751 const char *name, Error **errp)
752{
753 get_pointer(obj, v, opaque, print_netdev, name, errp);
754}
755
756static void set_netdev(Object *obj, Visitor *v, void *opaque,
757 const char *name, Error **errp)
758{
759 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200760}
761
762PropertyInfo qdev_prop_netdev = {
763 .name = "netdev",
764 .type = PROP_TYPE_NETDEV,
765 .size = sizeof(VLANClientState*),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100766 .get = get_netdev,
767 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200768};
769
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200770/* --- vlan --- */
771
772static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
773{
774 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
775 int id;
776
777 if (sscanf(str, "%d", &id) != 1)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100778 return -EINVAL;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200779 *ptr = qemu_find_vlan(id, 1);
780 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100781 return -ENOENT;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200782 return 0;
783}
784
785static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
786{
787 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
788
789 if (*ptr) {
790 return snprintf(dest, len, "%d", (*ptr)->id);
791 } else {
792 return snprintf(dest, len, "<null>");
793 }
794}
795
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600796static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100797 const char *name, Error **errp)
798{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600799 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100800 Property *prop = opaque;
801 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
802 int64_t id;
803
804 id = *ptr ? (*ptr)->id : -1;
805 visit_type_int(v, &id, name, errp);
806}
807
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600808static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100809 const char *name, Error **errp)
810{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600811 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100812 Property *prop = opaque;
813 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
814 Error *local_err = NULL;
815 int64_t id;
816 VLANState *vlan;
817
818 if (dev->state != DEV_STATE_CREATED) {
819 error_set(errp, QERR_PERMISSION_DENIED);
820 return;
821 }
822
823 visit_type_int(v, &id, name, &local_err);
824 if (local_err) {
825 error_propagate(errp, local_err);
826 return;
827 }
828 if (id == -1) {
829 *ptr = NULL;
830 return;
831 }
832 vlan = qemu_find_vlan(id, 1);
833 if (!vlan) {
834 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
835 name, prop->info->name);
836 return;
837 }
838 *ptr = vlan;
839}
840
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200841PropertyInfo qdev_prop_vlan = {
842 .name = "vlan",
843 .type = PROP_TYPE_VLAN,
844 .size = sizeof(VLANClientState*),
845 .parse = parse_vlan,
846 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100847 .get = get_vlan,
848 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200849};
850
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200851/* --- pointer --- */
852
Markus Armbruster036f7162010-02-19 11:47:06 +0100853/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200854PropertyInfo qdev_prop_ptr = {
855 .name = "ptr",
856 .type = PROP_TYPE_PTR,
857 .size = sizeof(void*),
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200858};
859
860/* --- mac address --- */
861
862/*
863 * accepted syntax versions:
864 * 01:02:03:04:05:06
865 * 01-02-03-04-05-06
866 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100867static void get_mac(Object *obj, Visitor *v, void *opaque,
868 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200869{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100870 DeviceState *dev = DEVICE(obj);
871 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200872 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100873 char buffer[2 * 6 + 5 + 1];
874 char *p = buffer;
875
876 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
877 mac->a[0], mac->a[1], mac->a[2],
878 mac->a[3], mac->a[4], mac->a[5]);
879
880 visit_type_str(v, &p, name, errp);
881}
882
883static void set_mac(Object *obj, Visitor *v, void *opaque,
884 const char *name, Error **errp)
885{
886 DeviceState *dev = DEVICE(obj);
887 Property *prop = opaque;
888 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
889 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200890 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100891 char *str, *p;
892
893 if (dev->state != DEV_STATE_CREATED) {
894 error_set(errp, QERR_PERMISSION_DENIED);
895 return;
896 }
897
898 visit_type_str(v, &str, name, &local_err);
899 if (local_err) {
900 error_propagate(errp, local_err);
901 return;
902 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200903
904 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000905 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100906 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000907 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100908 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200909 if (i == 5) {
910 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100911 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200912 } else {
913 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100914 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200915 }
916 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200917 }
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100918 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200919
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100920inval:
921 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200922}
923
924PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200925 .name = "macaddr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200926 .type = PROP_TYPE_MACADDR,
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200927 .size = sizeof(MACAddr),
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100928 .get = get_mac,
929 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200930};
931
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100932
933/* --- lost tick policy --- */
934
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100935static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
936 [LOST_TICK_DISCARD] = "discard",
937 [LOST_TICK_DELAY] = "delay",
938 [LOST_TICK_MERGE] = "merge",
939 [LOST_TICK_SLEW] = "slew",
940 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100941};
942
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100943QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100944
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100945static void get_enum(Object *obj, Visitor *v, void *opaque,
946 const char *name, Error **errp)
947{
948 DeviceState *dev = DEVICE(obj);
949 Property *prop = opaque;
950 int *ptr = qdev_get_prop_ptr(dev, prop);
951
952 visit_type_enum(v, ptr, prop->info->enum_table,
953 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100954}
955
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100956static void set_enum(Object *obj, Visitor *v, void *opaque,
957 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100958{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100959 DeviceState *dev = DEVICE(obj);
960 Property *prop = opaque;
961 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100962
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100963 if (dev->state != DEV_STATE_CREATED) {
964 error_set(errp, QERR_PERMISSION_DENIED);
965 return;
966 }
967
968 visit_type_enum(v, ptr, prop->info->enum_table,
969 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100970}
971
972PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100973 .name = "LostTickPolicy",
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100974 .type = PROP_TYPE_LOSTTICKPOLICY,
975 .size = sizeof(LostTickPolicy),
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100976 .enum_table = lost_tick_policy_table,
977 .get = get_enum,
978 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100979};
980
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200981/* --- pci address --- */
982
983/*
984 * bus-local address, i.e. "$slot" or "$slot.$fn"
985 */
986static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
987{
988 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
989 unsigned int slot, fn, n;
990
991 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
992 fn = 0;
993 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100994 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200995 }
996 }
997 if (str[n] != '\0')
Markus Armbruster6bf38812010-02-26 15:50:50 +0100998 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200999 if (fn > 7)
Markus Armbruster6bf38812010-02-26 15:50:50 +01001000 return -EINVAL;
Donald Dutileffe3ce12011-09-21 15:25:11 -04001001 if (slot > 31)
1002 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001003 *ptr = slot << 3 | fn;
1004 return 0;
1005}
1006
1007static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
1008{
1009 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
1010
Blue Swirl73538c32009-08-28 19:12:16 +00001011 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001012 return snprintf(dest, len, "<unset>");
1013 } else {
1014 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
1015 }
1016}
1017
1018PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +01001019 .name = "int32",
1020 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001021 .type = PROP_TYPE_UINT32,
1022 .size = sizeof(uint32_t),
1023 .parse = parse_pci_devfn,
1024 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +01001025 .get = get_int32,
1026 .set = set_int32,
1027 /* FIXME: this should be -1...255, but the address is stored
1028 * into an uint32_t rather than int32_t.
1029 */
1030 .min = 0,
1031 .max = 0xFFFFFFFFULL,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001032};
1033
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001034/* --- public helpers --- */
1035
1036static Property *qdev_prop_walk(Property *props, const char *name)
1037{
1038 if (!props)
1039 return NULL;
1040 while (props->name) {
1041 if (strcmp(props->name, name) == 0)
1042 return props;
1043 props++;
1044 }
1045 return NULL;
1046}
1047
1048static Property *qdev_prop_find(DeviceState *dev, const char *name)
1049{
1050 Property *prop;
1051
1052 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001053 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001054 if (prop)
1055 return prop;
1056
1057 /* bus properties */
1058 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1059 if (prop)
1060 return prop;
1061
1062 return NULL;
1063}
1064
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001065int qdev_prop_exists(DeviceState *dev, const char *name)
1066{
1067 return qdev_prop_find(dev, name) ? true : false;
1068}
1069
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001070void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1071 Property *prop, const char *value)
1072{
1073 switch (ret) {
1074 case -EEXIST:
1075 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001076 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001077 break;
1078 default:
1079 case -EINVAL:
1080 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001081 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001082 break;
1083 case -ENOENT:
1084 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001085 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001086 break;
1087 case 0:
1088 break;
1089 }
1090}
1091
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001092int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1093{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001094 char *legacy_name;
1095 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001096
Paolo Bonzinid8229792012-02-02 09:47:13 +01001097 legacy_name = g_strdup_printf("legacy-%s", name);
1098 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1099 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1100 } else {
1101 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001102 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001103 g_free(legacy_name);
1104
1105 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001106 qerror_report_err(err);
1107 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001108 return -1;
1109 }
1110 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001111}
1112
1113void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
1114{
1115 Property *prop;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001116
1117 prop = qdev_prop_find(dev, name);
1118 if (!prop) {
1119 fprintf(stderr, "%s: property \"%s.%s\" not found\n",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001120 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001121 abort();
1122 }
1123 if (prop->info->type != type) {
1124 fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001125 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001126 abort();
1127 }
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +02001128 qdev_prop_cpy(dev, prop, src);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001129}
1130
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001131void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1132{
1133 qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
1134}
1135
Juan Quintelac7cc1722009-09-29 22:48:25 +02001136void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1137{
1138 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
1139}
1140
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001141void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1142{
1143 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
1144}
1145
1146void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1147{
1148 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
1149}
1150
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001151void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1152{
1153 qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
1154}
1155
Blue Swirl5a053d12009-07-21 11:10:41 +00001156void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1157{
1158 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
1159}
1160
Markus Armbrustercc984672010-06-01 20:32:30 +02001161void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1162{
1163 qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
1164}
1165
Markus Armbruster18846de2010-06-29 16:58:30 +02001166int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001167{
Markus Armbruster18846de2010-06-29 16:58:30 +02001168 int res;
1169
Markus Armbrusterfa879d62011-08-03 15:07:40 +02001170 res = bdrv_attach_dev(value, dev);
Markus Armbruster18846de2010-06-29 16:58:30 +02001171 if (res < 0) {
1172 error_report("Can't attach drive %s to %s.%s: %s",
1173 bdrv_get_device_name(value),
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001174 dev->id ? dev->id : object_get_typename(OBJECT(dev)),
Markus Armbruster18846de2010-06-29 16:58:30 +02001175 name, strerror(-res));
1176 return -1;
1177 }
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001178 qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
Markus Armbruster18846de2010-06-29 16:58:30 +02001179 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001180}
1181
Markus Armbruster18846de2010-06-29 16:58:30 +02001182void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1183{
1184 if (qdev_prop_set_drive(dev, name, value) < 0) {
1185 exit(1);
1186 }
1187}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001188void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1189{
1190 qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
1191}
1192
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001193void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1194{
1195 qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
1196}
1197
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001198void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1199{
1200 qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
1201}
1202
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001203void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1204{
1205 qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
1206}
1207
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001208void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
1209 LostTickPolicy *value)
1210{
1211 qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
1212}
1213
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001214void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1215{
1216 qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
1217}
1218
1219void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1220{
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001221 if (!props)
1222 return;
1223 while (props->name) {
1224 if (props->defval) {
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +02001225 qdev_prop_cpy(dev, props, props->defval);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001226 }
1227 props++;
1228 }
1229}
1230
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001231static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001232
Kevin Wolf25920d62010-03-15 17:01:24 +01001233static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001234{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001235 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001236}
1237
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001238void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001239{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001240 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001241
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001242 for (i = 0; props[i].driver != NULL; i++) {
1243 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001244 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001245}
1246
1247void qdev_prop_set_globals(DeviceState *dev)
1248{
1249 GlobalProperty *prop;
1250
1251 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001252 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001253 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001254 continue;
1255 }
1256 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001257 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001258 }
1259 }
1260}
Kevin Wolf25920d62010-03-15 17:01:24 +01001261
1262static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1263{
1264 GlobalProperty *g;
1265
Anthony Liguori7267c092011-08-20 22:09:37 -05001266 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001267 g->driver = qemu_opt_get(opts, "driver");
1268 g->property = qemu_opt_get(opts, "property");
1269 g->value = qemu_opt_get(opts, "value");
1270 qdev_prop_register_global(g);
1271 return 0;
1272}
1273
1274void qemu_add_globals(void)
1275{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001276 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001277}