blob: a4545f796985627f1e3529d57c017c66268f9ad3 [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{
Paolo Bonzinia3d4a1b2012-02-02 22:51:09 +010015 assert(prop->info == &qdev_prop_bit);
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020016 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
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020029/* Bit */
30static int parse_bit(DeviceState *dev, Property *prop, const char *str)
31{
Jan Kiszkac455d172012-01-21 14:43:07 +010032 if (!strcasecmp(str, "on"))
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020033 bit_prop_set(dev, prop, true);
Jan Kiszkac455d172012-01-21 14:43:07 +010034 else if (!strcasecmp(str, "off"))
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020035 bit_prop_set(dev, prop, false);
36 else
Markus Armbruster6bf38812010-02-26 15:50:50 +010037 return -EINVAL;
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020038 return 0;
39}
40
41static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
42{
David 'Digit' Turner5a5e3d52011-01-10 23:11:40 +010043 uint32_t *p = qdev_get_prop_ptr(dev, prop);
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020044 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
45}
46
Anthony Liguori57c9faf2012-01-30 08:55:55 -060047static void get_bit(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010048 const char *name, Error **errp)
49{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060050 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010051 Property *prop = opaque;
52 uint32_t *p = qdev_get_prop_ptr(dev, prop);
53 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
54
55 visit_type_bool(v, &value, name, errp);
56}
57
Anthony Liguori57c9faf2012-01-30 08:55:55 -060058static void set_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 Error *local_err = NULL;
64 bool value;
65
66 if (dev->state != DEV_STATE_CREATED) {
67 error_set(errp, QERR_PERMISSION_DENIED);
68 return;
69 }
70
71 visit_type_bool(v, &value, name, &local_err);
72 if (local_err) {
73 error_propagate(errp, local_err);
74 return;
75 }
76 bit_prop_set(dev, prop, value);
77}
78
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020079PropertyInfo qdev_prop_bit = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +010080 .name = "boolean",
81 .legacy_name = "on/off",
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020082 .parse = parse_bit,
83 .print = print_bit,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010084 .get = get_bit,
85 .set = set_bit,
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020086};
87
Juan Quintelac7cc1722009-09-29 22:48:25 +020088/* --- 8bit integer --- */
89
90static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
91{
92 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +020093 char *end;
Juan Quintelac7cc1722009-09-29 22:48:25 +020094
95 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +020096 *ptr = strtoul(str, &end, 0);
97 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +010098 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +020099 }
100
Juan Quintelac7cc1722009-09-29 22:48:25 +0200101 return 0;
102}
103
104static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
105{
106 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
107 return snprintf(dest, len, "%" PRIu8, *ptr);
108}
109
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600110static void get_int8(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100111 const char *name, Error **errp)
112{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600113 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100114 Property *prop = opaque;
115 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
116 int64_t value;
117
118 value = *ptr;
119 visit_type_int(v, &value, name, errp);
120}
121
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600122static void set_int8(Object *obj, Visitor *v, void *opaque,
123 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100124{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600125 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100126 Property *prop = opaque;
127 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
128 Error *local_err = NULL;
129 int64_t value;
130
131 if (dev->state != DEV_STATE_CREATED) {
132 error_set(errp, QERR_PERMISSION_DENIED);
133 return;
134 }
135
136 visit_type_int(v, &value, name, &local_err);
137 if (local_err) {
138 error_propagate(errp, local_err);
139 return;
140 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100141 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100142 *ptr = value;
143 } else {
144 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
145 dev->id?:"", name, value, prop->info->min,
146 prop->info->max);
147 }
148}
149
Juan Quintelac7cc1722009-09-29 22:48:25 +0200150PropertyInfo qdev_prop_uint8 = {
151 .name = "uint8",
Juan Quintelac7cc1722009-09-29 22:48:25 +0200152 .parse = parse_uint8,
153 .print = print_uint8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100154 .get = get_int8,
155 .set = set_int8,
156 .min = 0,
157 .max = 255,
Juan Quintelac7cc1722009-09-29 22:48:25 +0200158};
159
Jan Kiszka68356782011-10-07 09:19:52 +0200160/* --- 8bit hex value --- */
161
162static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
163{
164 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
165 char *end;
166
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100167 if (str[0] != '0' || str[1] != 'x') {
168 return -EINVAL;
169 }
170
Jan Kiszka68356782011-10-07 09:19:52 +0200171 *ptr = strtoul(str, &end, 16);
172 if ((*end != '\0') || (end == str)) {
173 return -EINVAL;
174 }
175
176 return 0;
177}
178
179static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
180{
181 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
182 return snprintf(dest, len, "0x%" PRIx8, *ptr);
183}
184
185PropertyInfo qdev_prop_hex8 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100186 .name = "uint8",
187 .legacy_name = "hex8",
Jan Kiszka68356782011-10-07 09:19:52 +0200188 .parse = parse_hex8,
189 .print = print_hex8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100190 .get = get_int8,
191 .set = set_int8,
192 .min = 0,
193 .max = 255,
Jan Kiszka68356782011-10-07 09:19:52 +0200194};
195
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200196/* --- 16bit integer --- */
197
198static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
199{
200 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200201 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200202
203 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200204 *ptr = strtoul(str, &end, 0);
205 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100206 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200207 }
208
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200209 return 0;
210}
211
212static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
213{
214 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
215 return snprintf(dest, len, "%" PRIu16, *ptr);
216}
217
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600218static void get_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100219 const char *name, Error **errp)
220{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600221 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100222 Property *prop = opaque;
223 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
224 int64_t value;
225
226 value = *ptr;
227 visit_type_int(v, &value, name, errp);
228}
229
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600230static void set_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100231 const char *name, Error **errp)
232{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600233 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100234 Property *prop = opaque;
235 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
236 Error *local_err = NULL;
237 int64_t value;
238
239 if (dev->state != DEV_STATE_CREATED) {
240 error_set(errp, QERR_PERMISSION_DENIED);
241 return;
242 }
243
244 visit_type_int(v, &value, name, &local_err);
245 if (local_err) {
246 error_propagate(errp, local_err);
247 return;
248 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100249 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100250 *ptr = value;
251 } else {
252 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
253 dev->id?:"", name, value, prop->info->min,
254 prop->info->max);
255 }
256}
257
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200258PropertyInfo qdev_prop_uint16 = {
259 .name = "uint16",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200260 .parse = parse_uint16,
261 .print = print_uint16,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100262 .get = get_int16,
263 .set = set_int16,
264 .min = 0,
265 .max = 65535,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200266};
267
268/* --- 32bit integer --- */
269
270static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
271{
272 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200273 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200274
275 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200276 *ptr = strtoul(str, &end, 0);
277 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100278 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200279 }
280
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200281 return 0;
282}
283
284static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
285{
286 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
287 return snprintf(dest, len, "%" PRIu32, *ptr);
288}
289
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600290static void get_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100291 const char *name, Error **errp)
292{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600293 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100294 Property *prop = opaque;
295 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
296 int64_t value;
297
298 value = *ptr;
299 visit_type_int(v, &value, name, errp);
300}
301
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600302static void set_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100303 const char *name, Error **errp)
304{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600305 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100306 Property *prop = opaque;
307 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
308 Error *local_err = NULL;
309 int64_t value;
310
311 if (dev->state != DEV_STATE_CREATED) {
312 error_set(errp, QERR_PERMISSION_DENIED);
313 return;
314 }
315
316 visit_type_int(v, &value, name, &local_err);
317 if (local_err) {
318 error_propagate(errp, local_err);
319 return;
320 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100321 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100322 *ptr = value;
323 } else {
324 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
325 dev->id?:"", name, value, prop->info->min,
326 prop->info->max);
327 }
328}
329
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200330PropertyInfo qdev_prop_uint32 = {
331 .name = "uint32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200332 .parse = parse_uint32,
333 .print = print_uint32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100334 .get = get_int32,
335 .set = set_int32,
336 .min = 0,
337 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200338};
339
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200340static int parse_int32(DeviceState *dev, Property *prop, const char *str)
341{
342 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200343 char *end;
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200344
Kevin Wolf449041d2010-06-18 18:27:03 +0200345 *ptr = strtol(str, &end, 10);
346 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100347 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200348 }
349
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200350 return 0;
351}
352
353static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
354{
355 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
356 return snprintf(dest, len, "%" PRId32, *ptr);
357}
358
359PropertyInfo qdev_prop_int32 = {
360 .name = "int32",
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200361 .parse = parse_int32,
362 .print = print_int32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100363 .get = get_int32,
364 .set = set_int32,
365 .min = -0x80000000LL,
366 .max = 0x7FFFFFFFLL,
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200367};
368
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200369/* --- 32bit hex value --- */
370
371static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
372{
373 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200374 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200375
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100376 if (str[0] != '0' || str[1] != 'x') {
377 return -EINVAL;
378 }
379
Kevin Wolf449041d2010-06-18 18:27:03 +0200380 *ptr = strtoul(str, &end, 16);
381 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100382 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200383 }
384
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200385 return 0;
386}
387
388static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
389{
390 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
391 return snprintf(dest, len, "0x%" PRIx32, *ptr);
392}
393
394PropertyInfo qdev_prop_hex32 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100395 .name = "uint32",
396 .legacy_name = "hex32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200397 .parse = parse_hex32,
398 .print = print_hex32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100399 .get = get_int32,
400 .set = set_int32,
401 .min = 0,
402 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200403};
404
Blue Swirl5a053d12009-07-21 11:10:41 +0000405/* --- 64bit integer --- */
406
407static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
408{
409 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200410 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000411
412 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200413 *ptr = strtoull(str, &end, 0);
414 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100415 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200416 }
417
Blue Swirl5a053d12009-07-21 11:10:41 +0000418 return 0;
419}
420
421static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
422{
423 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
424 return snprintf(dest, len, "%" PRIu64, *ptr);
425}
426
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600427static void get_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100428 const char *name, Error **errp)
429{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600430 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100431 Property *prop = opaque;
432 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
433
434 visit_type_int(v, ptr, name, errp);
435}
436
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600437static void set_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100438 const char *name, Error **errp)
439{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600440 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100441 Property *prop = opaque;
442 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
443
444 if (dev->state != DEV_STATE_CREATED) {
445 error_set(errp, QERR_PERMISSION_DENIED);
446 return;
447 }
448
449 visit_type_int(v, ptr, name, errp);
450}
451
Blue Swirl5a053d12009-07-21 11:10:41 +0000452PropertyInfo qdev_prop_uint64 = {
453 .name = "uint64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000454 .parse = parse_uint64,
455 .print = print_uint64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100456 .get = get_int64,
457 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000458};
459
460/* --- 64bit hex value --- */
461
462static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
463{
464 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200465 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000466
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100467 if (str[0] != '0' || str[1] != 'x') {
468 return -EINVAL;
469 }
470
Kevin Wolf449041d2010-06-18 18:27:03 +0200471 *ptr = strtoull(str, &end, 16);
472 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100473 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200474 }
475
Blue Swirl5a053d12009-07-21 11:10:41 +0000476 return 0;
477}
478
479static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
480{
481 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
482 return snprintf(dest, len, "0x%" PRIx64, *ptr);
483}
484
485PropertyInfo qdev_prop_hex64 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100486 .name = "uint64",
487 .legacy_name = "hex64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000488 .parse = parse_hex64,
489 .print = print_hex64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100490 .get = get_int64,
491 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000492};
493
Gerd Hoffmann59419662009-10-12 17:15:47 +0530494/* --- string --- */
495
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100496static void release_string(Object *obj, const char *name, void *opaque)
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200497{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100498 Property *prop = opaque;
499 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200500}
501
Gerd Hoffmann59419662009-10-12 17:15:47 +0530502static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
503{
504 char **ptr = qdev_get_prop_ptr(dev, prop);
505 if (!*ptr)
506 return snprintf(dest, len, "<null>");
507 return snprintf(dest, len, "\"%s\"", *ptr);
508}
509
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600510static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100511 const char *name, Error **errp)
512{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600513 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100514 Property *prop = opaque;
515 char **ptr = qdev_get_prop_ptr(dev, prop);
516
517 if (!*ptr) {
518 char *str = (char *)"";
519 visit_type_str(v, &str, name, errp);
520 } else {
521 visit_type_str(v, ptr, name, errp);
522 }
523}
524
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600525static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100526 const char *name, Error **errp)
527{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600528 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100529 Property *prop = opaque;
530 char **ptr = qdev_get_prop_ptr(dev, prop);
531 Error *local_err = NULL;
532 char *str;
533
534 if (dev->state != DEV_STATE_CREATED) {
535 error_set(errp, QERR_PERMISSION_DENIED);
536 return;
537 }
538
539 visit_type_str(v, &str, name, &local_err);
540 if (local_err) {
541 error_propagate(errp, local_err);
542 return;
543 }
544 if (!*str) {
545 g_free(str);
546 str = NULL;
547 }
548 if (*ptr) {
549 g_free(*ptr);
550 }
551 *ptr = str;
552}
553
Gerd Hoffmann59419662009-10-12 17:15:47 +0530554PropertyInfo qdev_prop_string = {
555 .name = "string",
Gerd Hoffmann59419662009-10-12 17:15:47 +0530556 .print = print_string,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100557 .release = release_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100558 .get = get_string,
559 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530560};
561
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200562/* --- drive --- */
563
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100564static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200565{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200566 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200567
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200568 bs = bdrv_find(str);
569 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100570 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200571 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200572 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200573 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200574 return 0;
575}
576
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100577static void release_drive(Object *obj, const char *name, void *opaque)
Markus Armbruster14bafc52010-06-25 08:09:10 +0200578{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100579 DeviceState *dev = DEVICE(obj);
580 Property *prop = opaque;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200581 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200582
583 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200584 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200585 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200586 }
587}
588
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100589static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200590{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100591 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200592}
593
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100594static void get_pointer(Object *obj, Visitor *v, Property *prop,
595 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100596 const char *name, Error **errp)
597{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600598 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100599 void **ptr = qdev_get_prop_ptr(dev, prop);
600 char *p;
601
602 p = (char *) (*ptr ? print(*ptr) : "");
603 visit_type_str(v, &p, name, errp);
604}
605
606static void set_pointer(Object *obj, Visitor *v, Property *prop,
607 int (*parse)(DeviceState *dev, const char *str, void **ptr),
608 const char *name, Error **errp)
609{
610 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100611 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100612 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100613 char *str;
614 int ret;
615
616 if (dev->state != DEV_STATE_CREATED) {
617 error_set(errp, QERR_PERMISSION_DENIED);
618 return;
619 }
620
621 visit_type_str(v, &str, name, &local_err);
622 if (local_err) {
623 error_propagate(errp, local_err);
624 return;
625 }
626 if (!*str) {
627 g_free(str);
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +0100628 *ptr = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100629 return;
630 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100631 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100632 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
633 g_free(str);
634}
635
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100636static void get_drive(Object *obj, Visitor *v, void *opaque,
637 const char *name, Error **errp)
638{
639 get_pointer(obj, v, opaque, print_drive, name, errp);
640}
641
642static void set_drive(Object *obj, Visitor *v, void *opaque,
643 const char *name, Error **errp)
644{
645 set_pointer(obj, v, opaque, parse_drive, name, errp);
646}
647
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200648PropertyInfo qdev_prop_drive = {
649 .name = "drive",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100650 .get = get_drive,
651 .set = set_drive,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100652 .release = release_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200653};
654
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200655/* --- character device --- */
656
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100657static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200658{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100659 CharDriverState *chr = qemu_chr_find(str);
660 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100661 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530662 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100663 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530664 return -EEXIST;
665 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100666 *ptr = chr;
667 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200668 return 0;
669}
670
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100671static void release_chr(Object *obj, const char *name, void *opaque)
Amit Shaha87f3e82012-01-13 15:29:47 +0530672{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100673 DeviceState *dev = DEVICE(obj);
674 Property *prop = opaque;
Amit Shaha87f3e82012-01-13 15:29:47 +0530675 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
676
677 if (*ptr) {
678 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
679 }
680}
681
682
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100683static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200684{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100685 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000686
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100687 return chr->label ? chr->label : "";
688}
689
690static void get_chr(Object *obj, Visitor *v, void *opaque,
691 const char *name, Error **errp)
692{
693 get_pointer(obj, v, opaque, print_chr, name, errp);
694}
695
696static void set_chr(Object *obj, Visitor *v, void *opaque,
697 const char *name, Error **errp)
698{
699 set_pointer(obj, v, opaque, parse_chr, name, errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200700}
701
702PropertyInfo qdev_prop_chr = {
703 .name = "chr",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100704 .get = get_chr,
705 .set = set_chr,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100706 .release = release_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200707};
708
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200709/* --- netdev device --- */
710
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100711static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200712{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100713 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200714
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100715 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100716 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100717 }
718 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100719 return -EEXIST;
720 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100721 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200722 return 0;
723}
724
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100725static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200726{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100727 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200728
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100729 return netdev->name ? netdev->name : "";
730}
731
732static void get_netdev(Object *obj, Visitor *v, void *opaque,
733 const char *name, Error **errp)
734{
735 get_pointer(obj, v, opaque, print_netdev, name, errp);
736}
737
738static void set_netdev(Object *obj, Visitor *v, void *opaque,
739 const char *name, Error **errp)
740{
741 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200742}
743
744PropertyInfo qdev_prop_netdev = {
745 .name = "netdev",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100746 .get = get_netdev,
747 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200748};
749
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200750/* --- vlan --- */
751
752static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
753{
754 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
755 int id;
756
757 if (sscanf(str, "%d", &id) != 1)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100758 return -EINVAL;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200759 *ptr = qemu_find_vlan(id, 1);
760 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100761 return -ENOENT;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200762 return 0;
763}
764
765static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
766{
767 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
768
769 if (*ptr) {
770 return snprintf(dest, len, "%d", (*ptr)->id);
771 } else {
772 return snprintf(dest, len, "<null>");
773 }
774}
775
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600776static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100777 const char *name, Error **errp)
778{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600779 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100780 Property *prop = opaque;
781 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
782 int64_t id;
783
784 id = *ptr ? (*ptr)->id : -1;
785 visit_type_int(v, &id, name, errp);
786}
787
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600788static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100789 const char *name, Error **errp)
790{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600791 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100792 Property *prop = opaque;
793 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
794 Error *local_err = NULL;
795 int64_t id;
796 VLANState *vlan;
797
798 if (dev->state != DEV_STATE_CREATED) {
799 error_set(errp, QERR_PERMISSION_DENIED);
800 return;
801 }
802
803 visit_type_int(v, &id, name, &local_err);
804 if (local_err) {
805 error_propagate(errp, local_err);
806 return;
807 }
808 if (id == -1) {
809 *ptr = NULL;
810 return;
811 }
812 vlan = qemu_find_vlan(id, 1);
813 if (!vlan) {
814 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
815 name, prop->info->name);
816 return;
817 }
818 *ptr = vlan;
819}
820
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200821PropertyInfo qdev_prop_vlan = {
822 .name = "vlan",
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200823 .parse = parse_vlan,
824 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100825 .get = get_vlan,
826 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200827};
828
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200829/* --- pointer --- */
830
Markus Armbruster036f7162010-02-19 11:47:06 +0100831/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200832PropertyInfo qdev_prop_ptr = {
833 .name = "ptr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200834};
835
836/* --- mac address --- */
837
838/*
839 * accepted syntax versions:
840 * 01:02:03:04:05:06
841 * 01-02-03-04-05-06
842 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100843static void get_mac(Object *obj, Visitor *v, void *opaque,
844 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200845{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100846 DeviceState *dev = DEVICE(obj);
847 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200848 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100849 char buffer[2 * 6 + 5 + 1];
850 char *p = buffer;
851
852 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
853 mac->a[0], mac->a[1], mac->a[2],
854 mac->a[3], mac->a[4], mac->a[5]);
855
856 visit_type_str(v, &p, name, errp);
857}
858
859static void set_mac(Object *obj, Visitor *v, void *opaque,
860 const char *name, Error **errp)
861{
862 DeviceState *dev = DEVICE(obj);
863 Property *prop = opaque;
864 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
865 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200866 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100867 char *str, *p;
868
869 if (dev->state != DEV_STATE_CREATED) {
870 error_set(errp, QERR_PERMISSION_DENIED);
871 return;
872 }
873
874 visit_type_str(v, &str, name, &local_err);
875 if (local_err) {
876 error_propagate(errp, local_err);
877 return;
878 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200879
880 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000881 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100882 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000883 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100884 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200885 if (i == 5) {
886 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100887 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200888 } else {
889 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100890 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200891 }
892 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200893 }
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100894 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200895
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100896inval:
897 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200898}
899
900PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200901 .name = "macaddr",
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100902 .get = get_mac,
903 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200904};
905
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100906
907/* --- lost tick policy --- */
908
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100909static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
910 [LOST_TICK_DISCARD] = "discard",
911 [LOST_TICK_DELAY] = "delay",
912 [LOST_TICK_MERGE] = "merge",
913 [LOST_TICK_SLEW] = "slew",
914 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100915};
916
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100917QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100918
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100919static void get_enum(Object *obj, Visitor *v, void *opaque,
920 const char *name, Error **errp)
921{
922 DeviceState *dev = DEVICE(obj);
923 Property *prop = opaque;
924 int *ptr = qdev_get_prop_ptr(dev, prop);
925
926 visit_type_enum(v, ptr, prop->info->enum_table,
927 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100928}
929
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100930static void set_enum(Object *obj, Visitor *v, void *opaque,
931 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100932{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100933 DeviceState *dev = DEVICE(obj);
934 Property *prop = opaque;
935 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100936
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100937 if (dev->state != DEV_STATE_CREATED) {
938 error_set(errp, QERR_PERMISSION_DENIED);
939 return;
940 }
941
942 visit_type_enum(v, ptr, prop->info->enum_table,
943 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100944}
945
946PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100947 .name = "LostTickPolicy",
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100948 .enum_table = lost_tick_policy_table,
949 .get = get_enum,
950 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100951};
952
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200953/* --- pci address --- */
954
955/*
956 * bus-local address, i.e. "$slot" or "$slot.$fn"
957 */
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100958static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
959 const char *name, Error **errp)
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200960{
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100961 DeviceState *dev = DEVICE(obj);
962 Property *prop = opaque;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200963 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
964 unsigned int slot, fn, n;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100965 Error *local_err = NULL;
966 char *str = (char *)"";
967
968 if (dev->state != DEV_STATE_CREATED) {
969 error_set(errp, QERR_PERMISSION_DENIED);
970 return;
971 }
972
973 visit_type_str(v, &str, name, &local_err);
974 if (local_err) {
975 return set_int32(obj, v, opaque, name, errp);
976 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200977
978 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
979 fn = 0;
980 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100981 goto invalid;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200982 }
983 }
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100984 if (str[n] != '\0' || fn > 7 || slot > 31) {
985 goto invalid;
986 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200987 *ptr = slot << 3 | fn;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100988 return;
989
990invalid:
991 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200992}
993
994static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
995{
996 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
997
Blue Swirl73538c32009-08-28 19:12:16 +0000998 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200999 return snprintf(dest, len, "<unset>");
1000 } else {
1001 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
1002 }
1003}
1004
1005PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +01001006 .name = "int32",
1007 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001008 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +01001009 .get = get_int32,
Paolo Bonzini768a9eb2012-02-09 09:53:32 +01001010 .set = set_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +01001011 /* FIXME: this should be -1...255, but the address is stored
1012 * into an uint32_t rather than int32_t.
1013 */
1014 .min = 0,
1015 .max = 0xFFFFFFFFULL,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001016};
1017
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001018/* --- public helpers --- */
1019
1020static Property *qdev_prop_walk(Property *props, const char *name)
1021{
1022 if (!props)
1023 return NULL;
1024 while (props->name) {
1025 if (strcmp(props->name, name) == 0)
1026 return props;
1027 props++;
1028 }
1029 return NULL;
1030}
1031
1032static Property *qdev_prop_find(DeviceState *dev, const char *name)
1033{
1034 Property *prop;
1035
1036 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001037 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001038 if (prop)
1039 return prop;
1040
1041 /* bus properties */
1042 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1043 if (prop)
1044 return prop;
1045
1046 return NULL;
1047}
1048
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001049int qdev_prop_exists(DeviceState *dev, const char *name)
1050{
1051 return qdev_prop_find(dev, name) ? true : false;
1052}
1053
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001054void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1055 Property *prop, const char *value)
1056{
1057 switch (ret) {
1058 case -EEXIST:
1059 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001060 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001061 break;
1062 default:
1063 case -EINVAL:
1064 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001065 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001066 break;
1067 case -ENOENT:
1068 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001069 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001070 break;
1071 case 0:
1072 break;
1073 }
1074}
1075
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001076int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1077{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001078 char *legacy_name;
1079 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001080
Paolo Bonzinid8229792012-02-02 09:47:13 +01001081 legacy_name = g_strdup_printf("legacy-%s", name);
1082 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1083 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1084 } else {
1085 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001086 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001087 g_free(legacy_name);
1088
1089 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001090 qerror_report_err(err);
1091 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001092 return -1;
1093 }
1094 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001095}
1096
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001097void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1098{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001099 Error *errp = NULL;
1100 object_property_set_bool(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001101 assert_no_error(errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001102}
1103
Juan Quintelac7cc1722009-09-29 22:48:25 +02001104void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1105{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001106 Error *errp = NULL;
1107 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001108 assert_no_error(errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001109}
1110
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001111void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1112{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001113 Error *errp = NULL;
1114 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001115 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001116}
1117
1118void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1119{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001120 Error *errp = NULL;
1121 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001122 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001123}
1124
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001125void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1126{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001127 Error *errp = NULL;
1128 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001129 assert_no_error(errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001130}
1131
Blue Swirl5a053d12009-07-21 11:10:41 +00001132void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1133{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001134 Error *errp = NULL;
1135 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001136 assert_no_error(errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001137}
1138
Markus Armbrustercc984672010-06-01 20:32:30 +02001139void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1140{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001141 Error *errp = NULL;
1142 object_property_set_str(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001143 assert_no_error(errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001144}
1145
Markus Armbruster18846de2010-06-29 16:58:30 +02001146int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001147{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001148 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001149 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1150 object_property_set_str(OBJECT(dev), bdrv_name,
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001151 name, &errp);
1152 if (errp) {
1153 qerror_report_err(errp);
1154 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001155 return -1;
1156 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001157 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001158}
1159
Markus Armbruster18846de2010-06-29 16:58:30 +02001160void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1161{
1162 if (qdev_prop_set_drive(dev, name, value) < 0) {
1163 exit(1);
1164 }
1165}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001166void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1167{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001168 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001169 assert(!value || value->label);
1170 object_property_set_str(OBJECT(dev),
1171 value ? value->label : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001172 assert_no_error(errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001173}
1174
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001175void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1176{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001177 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001178 assert(!value || value->name);
1179 object_property_set_str(OBJECT(dev),
1180 value ? value->name : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001181 assert_no_error(errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001182}
1183
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001184void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1185{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001186 Error *errp = NULL;
1187 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001188 assert_no_error(errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001189}
1190
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001191void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1192{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001193 Error *errp = NULL;
1194 char str[2 * 6 + 5 + 1];
1195 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1196 value[0], value[1], value[2], value[3], value[4], value[5]);
1197
1198 object_property_set_str(OBJECT(dev), str, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001199 assert_no_error(errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001200}
1201
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001202void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001203{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001204 Property *prop;
1205 Error *errp = NULL;
1206
1207 prop = qdev_prop_find(dev, name);
1208 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1209 name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001210 assert_no_error(errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001211}
1212
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001213void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1214{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001215 Property *prop;
1216 void **ptr;
1217
1218 prop = qdev_prop_find(dev, name);
1219 assert(prop && prop->info == &qdev_prop_ptr);
1220 ptr = qdev_get_prop_ptr(dev, prop);
1221 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001222}
1223
1224void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1225{
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001226 Object *obj = OBJECT(dev);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001227 if (!props)
1228 return;
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001229 for (; props->name; props++) {
1230 Error *errp = NULL;
1231 if (props->qtype == QTYPE_NONE) {
1232 continue;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001233 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001234 if (props->qtype == QTYPE_QBOOL) {
1235 object_property_set_bool(obj, props->defval, props->name, &errp);
1236 } else if (props->info->enum_table) {
1237 object_property_set_str(obj, props->info->enum_table[props->defval],
1238 props->name, &errp);
1239 } else if (props->qtype == QTYPE_QINT) {
1240 object_property_set_int(obj, props->defval, props->name, &errp);
1241 }
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001242 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001243 }
1244}
1245
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001246static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001247
Kevin Wolf25920d62010-03-15 17:01:24 +01001248static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001249{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001250 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001251}
1252
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001253void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001254{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001255 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001256
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001257 for (i = 0; props[i].driver != NULL; i++) {
1258 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001259 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001260}
1261
1262void qdev_prop_set_globals(DeviceState *dev)
1263{
1264 GlobalProperty *prop;
1265
1266 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001267 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001268 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001269 continue;
1270 }
1271 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001272 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001273 }
1274 }
1275}
Kevin Wolf25920d62010-03-15 17:01:24 +01001276
1277static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1278{
1279 GlobalProperty *g;
1280
Anthony Liguori7267c092011-08-20 22:09:37 -05001281 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001282 g->driver = qemu_opt_get(opts, "driver");
1283 g->property = qemu_opt_get(opts, "property");
1284 g->value = qemu_opt_get(opts, "value");
1285 qdev_prop_register_global(g);
1286 return 0;
1287}
1288
1289void qemu_add_globals(void)
1290{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001291 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001292}