blob: b3cd2a8921647c03785806f5666ba9b1cb8be836 [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 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100154 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100155 *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 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100262 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100263 *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 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100336 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100337 *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
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100513static void release_string(Object *obj, const char *name, void *opaque)
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200514{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100515 Property *prop = opaque;
516 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200517}
518
Gerd Hoffmann59419662009-10-12 17:15:47 +0530519static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
520{
521 char **ptr = qdev_get_prop_ptr(dev, prop);
522 if (!*ptr)
523 return snprintf(dest, len, "<null>");
524 return snprintf(dest, len, "\"%s\"", *ptr);
525}
526
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600527static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100528 const char *name, Error **errp)
529{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600530 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100531 Property *prop = opaque;
532 char **ptr = qdev_get_prop_ptr(dev, prop);
533
534 if (!*ptr) {
535 char *str = (char *)"";
536 visit_type_str(v, &str, name, errp);
537 } else {
538 visit_type_str(v, ptr, name, errp);
539 }
540}
541
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600542static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100543 const char *name, Error **errp)
544{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600545 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100546 Property *prop = opaque;
547 char **ptr = qdev_get_prop_ptr(dev, prop);
548 Error *local_err = NULL;
549 char *str;
550
551 if (dev->state != DEV_STATE_CREATED) {
552 error_set(errp, QERR_PERMISSION_DENIED);
553 return;
554 }
555
556 visit_type_str(v, &str, name, &local_err);
557 if (local_err) {
558 error_propagate(errp, local_err);
559 return;
560 }
561 if (!*str) {
562 g_free(str);
563 str = NULL;
564 }
565 if (*ptr) {
566 g_free(*ptr);
567 }
568 *ptr = str;
569}
570
Gerd Hoffmann59419662009-10-12 17:15:47 +0530571PropertyInfo qdev_prop_string = {
572 .name = "string",
573 .type = PROP_TYPE_STRING,
574 .size = sizeof(char*),
Gerd Hoffmann59419662009-10-12 17:15:47 +0530575 .print = print_string,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100576 .release = release_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100577 .get = get_string,
578 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530579};
580
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200581/* --- drive --- */
582
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100583static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200584{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200585 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200586
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200587 bs = bdrv_find(str);
588 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100589 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200590 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200591 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200592 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200593 return 0;
594}
595
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100596static void release_drive(Object *obj, const char *name, void *opaque)
Markus Armbruster14bafc52010-06-25 08:09:10 +0200597{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100598 DeviceState *dev = DEVICE(obj);
599 Property *prop = opaque;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200600 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200601
602 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200603 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200604 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200605 }
606}
607
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100608static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200609{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100610 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200611}
612
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100613static void get_pointer(Object *obj, Visitor *v, Property *prop,
614 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100615 const char *name, Error **errp)
616{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600617 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100618 void **ptr = qdev_get_prop_ptr(dev, prop);
619 char *p;
620
621 p = (char *) (*ptr ? print(*ptr) : "");
622 visit_type_str(v, &p, name, errp);
623}
624
625static void set_pointer(Object *obj, Visitor *v, Property *prop,
626 int (*parse)(DeviceState *dev, const char *str, void **ptr),
627 const char *name, Error **errp)
628{
629 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100630 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100631 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100632 char *str;
633 int ret;
634
635 if (dev->state != DEV_STATE_CREATED) {
636 error_set(errp, QERR_PERMISSION_DENIED);
637 return;
638 }
639
640 visit_type_str(v, &str, name, &local_err);
641 if (local_err) {
642 error_propagate(errp, local_err);
643 return;
644 }
645 if (!*str) {
646 g_free(str);
647 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
648 return;
649 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100650 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100651 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
652 g_free(str);
653}
654
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100655static void get_drive(Object *obj, Visitor *v, void *opaque,
656 const char *name, Error **errp)
657{
658 get_pointer(obj, v, opaque, print_drive, name, errp);
659}
660
661static void set_drive(Object *obj, Visitor *v, void *opaque,
662 const char *name, Error **errp)
663{
664 set_pointer(obj, v, opaque, parse_drive, name, errp);
665}
666
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200667PropertyInfo qdev_prop_drive = {
668 .name = "drive",
669 .type = PROP_TYPE_DRIVE,
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200670 .size = sizeof(BlockDriverState *),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100671 .get = get_drive,
672 .set = set_drive,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100673 .release = release_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200674};
675
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200676/* --- character device --- */
677
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100678static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200679{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100680 CharDriverState *chr = qemu_chr_find(str);
681 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100682 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530683 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100684 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530685 return -EEXIST;
686 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100687 *ptr = chr;
688 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200689 return 0;
690}
691
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100692static void release_chr(Object *obj, const char *name, void *opaque)
Amit Shaha87f3e82012-01-13 15:29:47 +0530693{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100694 DeviceState *dev = DEVICE(obj);
695 Property *prop = opaque;
Amit Shaha87f3e82012-01-13 15:29:47 +0530696 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
697
698 if (*ptr) {
699 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
700 }
701}
702
703
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100704static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200705{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100706 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000707
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100708 return chr->label ? chr->label : "";
709}
710
711static void get_chr(Object *obj, Visitor *v, void *opaque,
712 const char *name, Error **errp)
713{
714 get_pointer(obj, v, opaque, print_chr, name, errp);
715}
716
717static void set_chr(Object *obj, Visitor *v, void *opaque,
718 const char *name, Error **errp)
719{
720 set_pointer(obj, v, opaque, parse_chr, name, errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200721}
722
723PropertyInfo qdev_prop_chr = {
724 .name = "chr",
725 .type = PROP_TYPE_CHR,
726 .size = sizeof(CharDriverState*),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100727 .get = get_chr,
728 .set = set_chr,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100729 .release = release_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200730};
731
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200732/* --- netdev device --- */
733
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100734static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200735{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100736 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200737
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100738 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100739 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100740 }
741 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100742 return -EEXIST;
743 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100744 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200745 return 0;
746}
747
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100748static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200749{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100750 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200751
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100752 return netdev->name ? netdev->name : "";
753}
754
755static void get_netdev(Object *obj, Visitor *v, void *opaque,
756 const char *name, Error **errp)
757{
758 get_pointer(obj, v, opaque, print_netdev, name, errp);
759}
760
761static void set_netdev(Object *obj, Visitor *v, void *opaque,
762 const char *name, Error **errp)
763{
764 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200765}
766
767PropertyInfo qdev_prop_netdev = {
768 .name = "netdev",
769 .type = PROP_TYPE_NETDEV,
770 .size = sizeof(VLANClientState*),
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100771 .get = get_netdev,
772 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200773};
774
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200775/* --- vlan --- */
776
777static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
778{
779 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
780 int id;
781
782 if (sscanf(str, "%d", &id) != 1)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100783 return -EINVAL;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200784 *ptr = qemu_find_vlan(id, 1);
785 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100786 return -ENOENT;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200787 return 0;
788}
789
790static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
791{
792 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
793
794 if (*ptr) {
795 return snprintf(dest, len, "%d", (*ptr)->id);
796 } else {
797 return snprintf(dest, len, "<null>");
798 }
799}
800
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600801static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100802 const char *name, Error **errp)
803{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600804 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100805 Property *prop = opaque;
806 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
807 int64_t id;
808
809 id = *ptr ? (*ptr)->id : -1;
810 visit_type_int(v, &id, name, errp);
811}
812
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600813static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100814 const char *name, Error **errp)
815{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600816 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100817 Property *prop = opaque;
818 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
819 Error *local_err = NULL;
820 int64_t id;
821 VLANState *vlan;
822
823 if (dev->state != DEV_STATE_CREATED) {
824 error_set(errp, QERR_PERMISSION_DENIED);
825 return;
826 }
827
828 visit_type_int(v, &id, name, &local_err);
829 if (local_err) {
830 error_propagate(errp, local_err);
831 return;
832 }
833 if (id == -1) {
834 *ptr = NULL;
835 return;
836 }
837 vlan = qemu_find_vlan(id, 1);
838 if (!vlan) {
839 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
840 name, prop->info->name);
841 return;
842 }
843 *ptr = vlan;
844}
845
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200846PropertyInfo qdev_prop_vlan = {
847 .name = "vlan",
848 .type = PROP_TYPE_VLAN,
849 .size = sizeof(VLANClientState*),
850 .parse = parse_vlan,
851 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100852 .get = get_vlan,
853 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200854};
855
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200856/* --- pointer --- */
857
Markus Armbruster036f7162010-02-19 11:47:06 +0100858/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200859PropertyInfo qdev_prop_ptr = {
860 .name = "ptr",
861 .type = PROP_TYPE_PTR,
862 .size = sizeof(void*),
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200863};
864
865/* --- mac address --- */
866
867/*
868 * accepted syntax versions:
869 * 01:02:03:04:05:06
870 * 01-02-03-04-05-06
871 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100872static void get_mac(Object *obj, Visitor *v, void *opaque,
873 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200874{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100875 DeviceState *dev = DEVICE(obj);
876 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200877 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100878 char buffer[2 * 6 + 5 + 1];
879 char *p = buffer;
880
881 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
882 mac->a[0], mac->a[1], mac->a[2],
883 mac->a[3], mac->a[4], mac->a[5]);
884
885 visit_type_str(v, &p, name, errp);
886}
887
888static void set_mac(Object *obj, Visitor *v, void *opaque,
889 const char *name, Error **errp)
890{
891 DeviceState *dev = DEVICE(obj);
892 Property *prop = opaque;
893 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
894 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200895 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100896 char *str, *p;
897
898 if (dev->state != DEV_STATE_CREATED) {
899 error_set(errp, QERR_PERMISSION_DENIED);
900 return;
901 }
902
903 visit_type_str(v, &str, name, &local_err);
904 if (local_err) {
905 error_propagate(errp, local_err);
906 return;
907 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200908
909 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000910 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100911 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000912 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100913 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200914 if (i == 5) {
915 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100916 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200917 } else {
918 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100919 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200920 }
921 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200922 }
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100923 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200924
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100925inval:
926 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200927}
928
929PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200930 .name = "macaddr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200931 .type = PROP_TYPE_MACADDR,
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200932 .size = sizeof(MACAddr),
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100933 .get = get_mac,
934 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200935};
936
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100937
938/* --- lost tick policy --- */
939
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100940static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
941 [LOST_TICK_DISCARD] = "discard",
942 [LOST_TICK_DELAY] = "delay",
943 [LOST_TICK_MERGE] = "merge",
944 [LOST_TICK_SLEW] = "slew",
945 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100946};
947
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100948QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100949
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100950static void get_enum(Object *obj, Visitor *v, void *opaque,
951 const char *name, Error **errp)
952{
953 DeviceState *dev = DEVICE(obj);
954 Property *prop = opaque;
955 int *ptr = qdev_get_prop_ptr(dev, prop);
956
957 visit_type_enum(v, ptr, prop->info->enum_table,
958 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100959}
960
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100961static void set_enum(Object *obj, Visitor *v, void *opaque,
962 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100963{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100964 DeviceState *dev = DEVICE(obj);
965 Property *prop = opaque;
966 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100967
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100968 if (dev->state != DEV_STATE_CREATED) {
969 error_set(errp, QERR_PERMISSION_DENIED);
970 return;
971 }
972
973 visit_type_enum(v, ptr, prop->info->enum_table,
974 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100975}
976
977PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100978 .name = "LostTickPolicy",
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100979 .type = PROP_TYPE_LOSTTICKPOLICY,
980 .size = sizeof(LostTickPolicy),
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100981 .enum_table = lost_tick_policy_table,
982 .get = get_enum,
983 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100984};
985
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200986/* --- pci address --- */
987
988/*
989 * bus-local address, i.e. "$slot" or "$slot.$fn"
990 */
991static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
992{
993 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
994 unsigned int slot, fn, n;
995
996 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
997 fn = 0;
998 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100999 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001000 }
1001 }
1002 if (str[n] != '\0')
Markus Armbruster6bf38812010-02-26 15:50:50 +01001003 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001004 if (fn > 7)
Markus Armbruster6bf38812010-02-26 15:50:50 +01001005 return -EINVAL;
Donald Dutileffe3ce12011-09-21 15:25:11 -04001006 if (slot > 31)
1007 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001008 *ptr = slot << 3 | fn;
1009 return 0;
1010}
1011
1012static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
1013{
1014 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
1015
Blue Swirl73538c32009-08-28 19:12:16 +00001016 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001017 return snprintf(dest, len, "<unset>");
1018 } else {
1019 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
1020 }
1021}
1022
1023PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +01001024 .name = "int32",
1025 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001026 .type = PROP_TYPE_UINT32,
1027 .size = sizeof(uint32_t),
1028 .parse = parse_pci_devfn,
1029 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +01001030 .get = get_int32,
1031 .set = set_int32,
1032 /* FIXME: this should be -1...255, but the address is stored
1033 * into an uint32_t rather than int32_t.
1034 */
1035 .min = 0,
1036 .max = 0xFFFFFFFFULL,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001037};
1038
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001039/* --- public helpers --- */
1040
1041static Property *qdev_prop_walk(Property *props, const char *name)
1042{
1043 if (!props)
1044 return NULL;
1045 while (props->name) {
1046 if (strcmp(props->name, name) == 0)
1047 return props;
1048 props++;
1049 }
1050 return NULL;
1051}
1052
1053static Property *qdev_prop_find(DeviceState *dev, const char *name)
1054{
1055 Property *prop;
1056
1057 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001058 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001059 if (prop)
1060 return prop;
1061
1062 /* bus properties */
1063 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1064 if (prop)
1065 return prop;
1066
1067 return NULL;
1068}
1069
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001070int qdev_prop_exists(DeviceState *dev, const char *name)
1071{
1072 return qdev_prop_find(dev, name) ? true : false;
1073}
1074
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001075void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1076 Property *prop, const char *value)
1077{
1078 switch (ret) {
1079 case -EEXIST:
1080 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
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 default:
1084 case -EINVAL:
1085 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001086 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001087 break;
1088 case -ENOENT:
1089 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001090 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001091 break;
1092 case 0:
1093 break;
1094 }
1095}
1096
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001097int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1098{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001099 char *legacy_name;
1100 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001101
Paolo Bonzinid8229792012-02-02 09:47:13 +01001102 legacy_name = g_strdup_printf("legacy-%s", name);
1103 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1104 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1105 } else {
1106 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001107 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001108 g_free(legacy_name);
1109
1110 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001111 qerror_report_err(err);
1112 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001113 return -1;
1114 }
1115 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001116}
1117
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001118void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1119{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001120 Error *errp = NULL;
1121 object_property_set_bool(OBJECT(dev), value, name, &errp);
1122 assert(!errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001123}
1124
Juan Quintelac7cc1722009-09-29 22:48:25 +02001125void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1126{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001127 Error *errp = NULL;
1128 object_property_set_int(OBJECT(dev), value, name, &errp);
1129 assert(!errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001130}
1131
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001132void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1133{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001134 Error *errp = NULL;
1135 object_property_set_int(OBJECT(dev), value, name, &errp);
1136 assert(!errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001137}
1138
1139void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1140{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001141 Error *errp = NULL;
1142 object_property_set_int(OBJECT(dev), value, name, &errp);
1143 assert(!errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001144}
1145
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001146void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1147{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001148 Error *errp = NULL;
1149 object_property_set_int(OBJECT(dev), value, name, &errp);
1150 assert(!errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001151}
1152
Blue Swirl5a053d12009-07-21 11:10:41 +00001153void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1154{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001155 Error *errp = NULL;
1156 object_property_set_int(OBJECT(dev), value, name, &errp);
1157 assert(!errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001158}
1159
Markus Armbrustercc984672010-06-01 20:32:30 +02001160void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1161{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001162 Error *errp = NULL;
1163 object_property_set_str(OBJECT(dev), value, name, &errp);
1164 assert(!errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001165}
1166
Markus Armbruster18846de2010-06-29 16:58:30 +02001167int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001168{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001169 Error *errp = NULL;
1170 object_property_set_str(OBJECT(dev), bdrv_get_device_name(value),
1171 name, &errp);
1172 if (errp) {
1173 qerror_report_err(errp);
1174 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001175 return -1;
1176 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001177 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001178}
1179
Markus Armbruster18846de2010-06-29 16:58:30 +02001180void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1181{
1182 if (qdev_prop_set_drive(dev, name, value) < 0) {
1183 exit(1);
1184 }
1185}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001186void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1187{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001188 Error *errp = NULL;
1189 assert(value->label);
1190 object_property_set_str(OBJECT(dev), value->label, name, &errp);
1191 assert(!errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001192}
1193
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001194void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1195{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001196 Error *errp = NULL;
1197 assert(value->name);
1198 object_property_set_str(OBJECT(dev), value->name, name, &errp);
1199 assert(!errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001200}
1201
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001202void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1203{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001204 Error *errp = NULL;
1205 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
1206 assert(!errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001207}
1208
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001209void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1210{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001211 Error *errp = NULL;
1212 char str[2 * 6 + 5 + 1];
1213 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1214 value[0], value[1], value[2], value[3], value[4], value[5]);
1215
1216 object_property_set_str(OBJECT(dev), str, name, &errp);
1217 assert(!errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001218}
1219
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001220void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001221{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001222 Property *prop;
1223 Error *errp = NULL;
1224
1225 prop = qdev_prop_find(dev, name);
1226 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1227 name, &errp);
1228 assert(!errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001229}
1230
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001231void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1232{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001233 Property *prop;
1234 void **ptr;
1235
1236 prop = qdev_prop_find(dev, name);
1237 assert(prop && prop->info == &qdev_prop_ptr);
1238 ptr = qdev_get_prop_ptr(dev, prop);
1239 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001240}
1241
1242void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1243{
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001244 if (!props)
1245 return;
1246 while (props->name) {
1247 if (props->defval) {
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +02001248 qdev_prop_cpy(dev, props, props->defval);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001249 }
1250 props++;
1251 }
1252}
1253
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001254static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001255
Kevin Wolf25920d62010-03-15 17:01:24 +01001256static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001257{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001258 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001259}
1260
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001261void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001262{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001263 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001264
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001265 for (i = 0; props[i].driver != NULL; i++) {
1266 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001267 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001268}
1269
1270void qdev_prop_set_globals(DeviceState *dev)
1271{
1272 GlobalProperty *prop;
1273
1274 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001275 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001276 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001277 continue;
1278 }
1279 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001280 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001281 }
1282 }
1283}
Kevin Wolf25920d62010-03-15 17:01:24 +01001284
1285static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1286{
1287 GlobalProperty *g;
1288
Anthony Liguori7267c092011-08-20 22:09:37 -05001289 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001290 g->driver = qemu_opt_get(opts, "driver");
1291 g->property = qemu_opt_get(opts, "property");
1292 g->value = qemu_opt_get(opts, "value");
1293 qdev_prop_register_global(g);
1294 return 0;
1295}
1296
1297void qemu_add_globals(void)
1298{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001299 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001300}