blob: b6d6fcff011431180664a6dc7b761111427639a4 [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
167 *ptr = strtoul(str, &end, 16);
168 if ((*end != '\0') || (end == str)) {
169 return -EINVAL;
170 }
171
172 return 0;
173}
174
175static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
176{
177 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
178 return snprintf(dest, len, "0x%" PRIx8, *ptr);
179}
180
181PropertyInfo qdev_prop_hex8 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100182 .name = "uint8",
183 .legacy_name = "hex8",
Jan Kiszka68356782011-10-07 09:19:52 +0200184 .parse = parse_hex8,
185 .print = print_hex8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100186 .get = get_int8,
187 .set = set_int8,
188 .min = 0,
189 .max = 255,
Jan Kiszka68356782011-10-07 09:19:52 +0200190};
191
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200192/* --- 16bit integer --- */
193
194static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
195{
196 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200197 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200198
199 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200200 *ptr = strtoul(str, &end, 0);
201 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100202 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200203 }
204
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200205 return 0;
206}
207
208static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
209{
210 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
211 return snprintf(dest, len, "%" PRIu16, *ptr);
212}
213
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600214static void get_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100215 const char *name, Error **errp)
216{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600217 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100218 Property *prop = opaque;
219 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
220 int64_t value;
221
222 value = *ptr;
223 visit_type_int(v, &value, name, errp);
224}
225
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600226static void set_int16(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100227 const char *name, Error **errp)
228{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600229 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100230 Property *prop = opaque;
231 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
232 Error *local_err = NULL;
233 int64_t value;
234
235 if (dev->state != DEV_STATE_CREATED) {
236 error_set(errp, QERR_PERMISSION_DENIED);
237 return;
238 }
239
240 visit_type_int(v, &value, name, &local_err);
241 if (local_err) {
242 error_propagate(errp, local_err);
243 return;
244 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100245 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100246 *ptr = value;
247 } else {
248 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
249 dev->id?:"", name, value, prop->info->min,
250 prop->info->max);
251 }
252}
253
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200254PropertyInfo qdev_prop_uint16 = {
255 .name = "uint16",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200256 .parse = parse_uint16,
257 .print = print_uint16,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100258 .get = get_int16,
259 .set = set_int16,
260 .min = 0,
261 .max = 65535,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200262};
263
264/* --- 32bit integer --- */
265
266static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
267{
268 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200269 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200270
271 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200272 *ptr = strtoul(str, &end, 0);
273 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100274 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200275 }
276
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200277 return 0;
278}
279
280static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
281{
282 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
283 return snprintf(dest, len, "%" PRIu32, *ptr);
284}
285
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600286static void get_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100287 const char *name, Error **errp)
288{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600289 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100290 Property *prop = opaque;
291 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
292 int64_t value;
293
294 value = *ptr;
295 visit_type_int(v, &value, name, errp);
296}
297
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600298static void set_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100299 const char *name, Error **errp)
300{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600301 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100302 Property *prop = opaque;
303 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
304 Error *local_err = NULL;
305 int64_t value;
306
307 if (dev->state != DEV_STATE_CREATED) {
308 error_set(errp, QERR_PERMISSION_DENIED);
309 return;
310 }
311
312 visit_type_int(v, &value, name, &local_err);
313 if (local_err) {
314 error_propagate(errp, local_err);
315 return;
316 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100317 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100318 *ptr = value;
319 } else {
320 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
321 dev->id?:"", name, value, prop->info->min,
322 prop->info->max);
323 }
324}
325
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200326PropertyInfo qdev_prop_uint32 = {
327 .name = "uint32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200328 .parse = parse_uint32,
329 .print = print_uint32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100330 .get = get_int32,
331 .set = set_int32,
332 .min = 0,
333 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200334};
335
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200336static int parse_int32(DeviceState *dev, Property *prop, const char *str)
337{
338 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200339 char *end;
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200340
Kevin Wolf449041d2010-06-18 18:27:03 +0200341 *ptr = strtol(str, &end, 10);
342 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100343 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200344 }
345
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200346 return 0;
347}
348
349static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
350{
351 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
352 return snprintf(dest, len, "%" PRId32, *ptr);
353}
354
355PropertyInfo qdev_prop_int32 = {
356 .name = "int32",
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200357 .parse = parse_int32,
358 .print = print_int32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100359 .get = get_int32,
360 .set = set_int32,
361 .min = -0x80000000LL,
362 .max = 0x7FFFFFFFLL,
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200363};
364
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200365/* --- 32bit hex value --- */
366
367static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
368{
369 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200370 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200371
Kevin Wolf449041d2010-06-18 18:27:03 +0200372 *ptr = strtoul(str, &end, 16);
373 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100374 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200375 }
376
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200377 return 0;
378}
379
380static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
381{
382 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
383 return snprintf(dest, len, "0x%" PRIx32, *ptr);
384}
385
386PropertyInfo qdev_prop_hex32 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100387 .name = "uint32",
388 .legacy_name = "hex32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200389 .parse = parse_hex32,
390 .print = print_hex32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100391 .get = get_int32,
392 .set = set_int32,
393 .min = 0,
394 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200395};
396
Blue Swirl5a053d12009-07-21 11:10:41 +0000397/* --- 64bit integer --- */
398
399static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
400{
401 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200402 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000403
404 /* accept both hex and decimal */
Kevin Wolf449041d2010-06-18 18:27:03 +0200405 *ptr = strtoull(str, &end, 0);
406 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100407 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200408 }
409
Blue Swirl5a053d12009-07-21 11:10:41 +0000410 return 0;
411}
412
413static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
414{
415 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
416 return snprintf(dest, len, "%" PRIu64, *ptr);
417}
418
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600419static void get_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100420 const char *name, Error **errp)
421{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600422 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100423 Property *prop = opaque;
424 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
425
426 visit_type_int(v, ptr, name, errp);
427}
428
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600429static void set_int64(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100430 const char *name, Error **errp)
431{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600432 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100433 Property *prop = opaque;
434 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
435
436 if (dev->state != DEV_STATE_CREATED) {
437 error_set(errp, QERR_PERMISSION_DENIED);
438 return;
439 }
440
441 visit_type_int(v, ptr, name, errp);
442}
443
Blue Swirl5a053d12009-07-21 11:10:41 +0000444PropertyInfo qdev_prop_uint64 = {
445 .name = "uint64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000446 .parse = parse_uint64,
447 .print = print_uint64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100448 .get = get_int64,
449 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000450};
451
452/* --- 64bit hex value --- */
453
454static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
455{
456 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200457 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000458
Kevin Wolf449041d2010-06-18 18:27:03 +0200459 *ptr = strtoull(str, &end, 16);
460 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100461 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200462 }
463
Blue Swirl5a053d12009-07-21 11:10:41 +0000464 return 0;
465}
466
467static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
468{
469 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
470 return snprintf(dest, len, "0x%" PRIx64, *ptr);
471}
472
473PropertyInfo qdev_prop_hex64 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100474 .name = "uint64",
475 .legacy_name = "hex64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000476 .parse = parse_hex64,
477 .print = print_hex64,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100478 .get = get_int64,
479 .set = set_int64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000480};
481
Gerd Hoffmann59419662009-10-12 17:15:47 +0530482/* --- string --- */
483
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100484static void release_string(Object *obj, const char *name, void *opaque)
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200485{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100486 Property *prop = opaque;
487 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200488}
489
Gerd Hoffmann59419662009-10-12 17:15:47 +0530490static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
491{
492 char **ptr = qdev_get_prop_ptr(dev, prop);
493 if (!*ptr)
494 return snprintf(dest, len, "<null>");
495 return snprintf(dest, len, "\"%s\"", *ptr);
496}
497
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600498static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100499 const char *name, Error **errp)
500{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600501 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100502 Property *prop = opaque;
503 char **ptr = qdev_get_prop_ptr(dev, prop);
504
505 if (!*ptr) {
506 char *str = (char *)"";
507 visit_type_str(v, &str, name, errp);
508 } else {
509 visit_type_str(v, ptr, name, errp);
510 }
511}
512
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600513static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100514 const char *name, Error **errp)
515{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600516 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100517 Property *prop = opaque;
518 char **ptr = qdev_get_prop_ptr(dev, prop);
519 Error *local_err = NULL;
520 char *str;
521
522 if (dev->state != DEV_STATE_CREATED) {
523 error_set(errp, QERR_PERMISSION_DENIED);
524 return;
525 }
526
527 visit_type_str(v, &str, name, &local_err);
528 if (local_err) {
529 error_propagate(errp, local_err);
530 return;
531 }
532 if (!*str) {
533 g_free(str);
534 str = NULL;
535 }
536 if (*ptr) {
537 g_free(*ptr);
538 }
539 *ptr = str;
540}
541
Gerd Hoffmann59419662009-10-12 17:15:47 +0530542PropertyInfo qdev_prop_string = {
543 .name = "string",
Gerd Hoffmann59419662009-10-12 17:15:47 +0530544 .print = print_string,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100545 .release = release_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100546 .get = get_string,
547 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530548};
549
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200550/* --- drive --- */
551
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100552static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200553{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200554 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200555
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200556 bs = bdrv_find(str);
557 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100558 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200559 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200560 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200561 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200562 return 0;
563}
564
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100565static void release_drive(Object *obj, const char *name, void *opaque)
Markus Armbruster14bafc52010-06-25 08:09:10 +0200566{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100567 DeviceState *dev = DEVICE(obj);
568 Property *prop = opaque;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200569 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200570
571 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200572 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200573 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200574 }
575}
576
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100577static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200578{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100579 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200580}
581
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100582static void get_pointer(Object *obj, Visitor *v, Property *prop,
583 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100584 const char *name, Error **errp)
585{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600586 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100587 void **ptr = qdev_get_prop_ptr(dev, prop);
588 char *p;
589
590 p = (char *) (*ptr ? print(*ptr) : "");
591 visit_type_str(v, &p, name, errp);
592}
593
594static void set_pointer(Object *obj, Visitor *v, Property *prop,
595 int (*parse)(DeviceState *dev, const char *str, void **ptr),
596 const char *name, Error **errp)
597{
598 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100599 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100600 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100601 char *str;
602 int ret;
603
604 if (dev->state != DEV_STATE_CREATED) {
605 error_set(errp, QERR_PERMISSION_DENIED);
606 return;
607 }
608
609 visit_type_str(v, &str, name, &local_err);
610 if (local_err) {
611 error_propagate(errp, local_err);
612 return;
613 }
614 if (!*str) {
615 g_free(str);
616 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
617 return;
618 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100619 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100620 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
621 g_free(str);
622}
623
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100624static void get_drive(Object *obj, Visitor *v, void *opaque,
625 const char *name, Error **errp)
626{
627 get_pointer(obj, v, opaque, print_drive, name, errp);
628}
629
630static void set_drive(Object *obj, Visitor *v, void *opaque,
631 const char *name, Error **errp)
632{
633 set_pointer(obj, v, opaque, parse_drive, name, errp);
634}
635
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200636PropertyInfo qdev_prop_drive = {
637 .name = "drive",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100638 .get = get_drive,
639 .set = set_drive,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100640 .release = release_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200641};
642
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200643/* --- character device --- */
644
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100645static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200646{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100647 CharDriverState *chr = qemu_chr_find(str);
648 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100649 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530650 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100651 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530652 return -EEXIST;
653 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100654 *ptr = chr;
655 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200656 return 0;
657}
658
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100659static void release_chr(Object *obj, const char *name, void *opaque)
Amit Shaha87f3e82012-01-13 15:29:47 +0530660{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100661 DeviceState *dev = DEVICE(obj);
662 Property *prop = opaque;
Amit Shaha87f3e82012-01-13 15:29:47 +0530663 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
664
665 if (*ptr) {
666 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
667 }
668}
669
670
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100671static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200672{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100673 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000674
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100675 return chr->label ? chr->label : "";
676}
677
678static void get_chr(Object *obj, Visitor *v, void *opaque,
679 const char *name, Error **errp)
680{
681 get_pointer(obj, v, opaque, print_chr, name, errp);
682}
683
684static void set_chr(Object *obj, Visitor *v, void *opaque,
685 const char *name, Error **errp)
686{
687 set_pointer(obj, v, opaque, parse_chr, name, errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200688}
689
690PropertyInfo qdev_prop_chr = {
691 .name = "chr",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100692 .get = get_chr,
693 .set = set_chr,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100694 .release = release_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200695};
696
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200697/* --- netdev device --- */
698
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100699static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200700{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100701 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200702
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100703 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100704 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100705 }
706 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100707 return -EEXIST;
708 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100709 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200710 return 0;
711}
712
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100713static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200714{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100715 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200716
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100717 return netdev->name ? netdev->name : "";
718}
719
720static void get_netdev(Object *obj, Visitor *v, void *opaque,
721 const char *name, Error **errp)
722{
723 get_pointer(obj, v, opaque, print_netdev, name, errp);
724}
725
726static void set_netdev(Object *obj, Visitor *v, void *opaque,
727 const char *name, Error **errp)
728{
729 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200730}
731
732PropertyInfo qdev_prop_netdev = {
733 .name = "netdev",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100734 .get = get_netdev,
735 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200736};
737
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200738/* --- vlan --- */
739
740static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
741{
742 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
743 int id;
744
745 if (sscanf(str, "%d", &id) != 1)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100746 return -EINVAL;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200747 *ptr = qemu_find_vlan(id, 1);
748 if (*ptr == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100749 return -ENOENT;
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200750 return 0;
751}
752
753static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
754{
755 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
756
757 if (*ptr) {
758 return snprintf(dest, len, "%d", (*ptr)->id);
759 } else {
760 return snprintf(dest, len, "<null>");
761 }
762}
763
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600764static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100765 const char *name, Error **errp)
766{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600767 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100768 Property *prop = opaque;
769 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
770 int64_t id;
771
772 id = *ptr ? (*ptr)->id : -1;
773 visit_type_int(v, &id, name, errp);
774}
775
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600776static void set_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 Error *local_err = NULL;
783 int64_t id;
784 VLANState *vlan;
785
786 if (dev->state != DEV_STATE_CREATED) {
787 error_set(errp, QERR_PERMISSION_DENIED);
788 return;
789 }
790
791 visit_type_int(v, &id, name, &local_err);
792 if (local_err) {
793 error_propagate(errp, local_err);
794 return;
795 }
796 if (id == -1) {
797 *ptr = NULL;
798 return;
799 }
800 vlan = qemu_find_vlan(id, 1);
801 if (!vlan) {
802 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
803 name, prop->info->name);
804 return;
805 }
806 *ptr = vlan;
807}
808
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200809PropertyInfo qdev_prop_vlan = {
810 .name = "vlan",
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200811 .parse = parse_vlan,
812 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100813 .get = get_vlan,
814 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200815};
816
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200817/* --- pointer --- */
818
Markus Armbruster036f7162010-02-19 11:47:06 +0100819/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200820PropertyInfo qdev_prop_ptr = {
821 .name = "ptr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200822};
823
824/* --- mac address --- */
825
826/*
827 * accepted syntax versions:
828 * 01:02:03:04:05:06
829 * 01-02-03-04-05-06
830 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100831static void get_mac(Object *obj, Visitor *v, void *opaque,
832 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200833{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100834 DeviceState *dev = DEVICE(obj);
835 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200836 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100837 char buffer[2 * 6 + 5 + 1];
838 char *p = buffer;
839
840 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
841 mac->a[0], mac->a[1], mac->a[2],
842 mac->a[3], mac->a[4], mac->a[5]);
843
844 visit_type_str(v, &p, name, errp);
845}
846
847static void set_mac(Object *obj, Visitor *v, void *opaque,
848 const char *name, Error **errp)
849{
850 DeviceState *dev = DEVICE(obj);
851 Property *prop = opaque;
852 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
853 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200854 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100855 char *str, *p;
856
857 if (dev->state != DEV_STATE_CREATED) {
858 error_set(errp, QERR_PERMISSION_DENIED);
859 return;
860 }
861
862 visit_type_str(v, &str, name, &local_err);
863 if (local_err) {
864 error_propagate(errp, local_err);
865 return;
866 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200867
868 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000869 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100870 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000871 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100872 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200873 if (i == 5) {
874 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100875 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200876 } else {
877 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100878 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200879 }
880 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200881 }
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100882 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200883
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100884inval:
885 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200886}
887
888PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200889 .name = "macaddr",
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100890 .get = get_mac,
891 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200892};
893
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100894
895/* --- lost tick policy --- */
896
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100897static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
898 [LOST_TICK_DISCARD] = "discard",
899 [LOST_TICK_DELAY] = "delay",
900 [LOST_TICK_MERGE] = "merge",
901 [LOST_TICK_SLEW] = "slew",
902 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100903};
904
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100905QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100906
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100907static void get_enum(Object *obj, Visitor *v, void *opaque,
908 const char *name, Error **errp)
909{
910 DeviceState *dev = DEVICE(obj);
911 Property *prop = opaque;
912 int *ptr = qdev_get_prop_ptr(dev, prop);
913
914 visit_type_enum(v, ptr, prop->info->enum_table,
915 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100916}
917
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100918static void set_enum(Object *obj, Visitor *v, void *opaque,
919 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100920{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100921 DeviceState *dev = DEVICE(obj);
922 Property *prop = opaque;
923 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100924
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100925 if (dev->state != DEV_STATE_CREATED) {
926 error_set(errp, QERR_PERMISSION_DENIED);
927 return;
928 }
929
930 visit_type_enum(v, ptr, prop->info->enum_table,
931 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100932}
933
934PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100935 .name = "LostTickPolicy",
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100936 .enum_table = lost_tick_policy_table,
937 .get = get_enum,
938 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100939};
940
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200941/* --- pci address --- */
942
943/*
944 * bus-local address, i.e. "$slot" or "$slot.$fn"
945 */
946static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
947{
948 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
949 unsigned int slot, fn, n;
950
951 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
952 fn = 0;
953 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100954 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200955 }
956 }
957 if (str[n] != '\0')
Markus Armbruster6bf38812010-02-26 15:50:50 +0100958 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200959 if (fn > 7)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100960 return -EINVAL;
Donald Dutileffe3ce12011-09-21 15:25:11 -0400961 if (slot > 31)
962 return -EINVAL;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200963 *ptr = slot << 3 | fn;
964 return 0;
965}
966
967static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
968{
969 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
970
Blue Swirl73538c32009-08-28 19:12:16 +0000971 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200972 return snprintf(dest, len, "<unset>");
973 } else {
974 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
975 }
976}
977
978PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +0100979 .name = "int32",
980 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200981 .parse = parse_pci_devfn,
982 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +0100983 .get = get_int32,
984 .set = set_int32,
985 /* FIXME: this should be -1...255, but the address is stored
986 * into an uint32_t rather than int32_t.
987 */
988 .min = 0,
989 .max = 0xFFFFFFFFULL,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200990};
991
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200992/* --- public helpers --- */
993
994static Property *qdev_prop_walk(Property *props, const char *name)
995{
996 if (!props)
997 return NULL;
998 while (props->name) {
999 if (strcmp(props->name, name) == 0)
1000 return props;
1001 props++;
1002 }
1003 return NULL;
1004}
1005
1006static Property *qdev_prop_find(DeviceState *dev, const char *name)
1007{
1008 Property *prop;
1009
1010 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001011 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001012 if (prop)
1013 return prop;
1014
1015 /* bus properties */
1016 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1017 if (prop)
1018 return prop;
1019
1020 return NULL;
1021}
1022
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001023int qdev_prop_exists(DeviceState *dev, const char *name)
1024{
1025 return qdev_prop_find(dev, name) ? true : false;
1026}
1027
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001028void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1029 Property *prop, const char *value)
1030{
1031 switch (ret) {
1032 case -EEXIST:
1033 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001034 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001035 break;
1036 default:
1037 case -EINVAL:
1038 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001039 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001040 break;
1041 case -ENOENT:
1042 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001043 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001044 break;
1045 case 0:
1046 break;
1047 }
1048}
1049
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001050int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1051{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001052 char *legacy_name;
1053 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001054
Paolo Bonzinid8229792012-02-02 09:47:13 +01001055 legacy_name = g_strdup_printf("legacy-%s", name);
1056 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1057 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1058 } else {
1059 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001060 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001061 g_free(legacy_name);
1062
1063 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001064 qerror_report_err(err);
1065 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001066 return -1;
1067 }
1068 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001069}
1070
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001071void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1072{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001073 Error *errp = NULL;
1074 object_property_set_bool(OBJECT(dev), value, name, &errp);
1075 assert(!errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001076}
1077
Juan Quintelac7cc1722009-09-29 22:48:25 +02001078void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1079{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001080 Error *errp = NULL;
1081 object_property_set_int(OBJECT(dev), value, name, &errp);
1082 assert(!errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001083}
1084
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001085void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1086{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001087 Error *errp = NULL;
1088 object_property_set_int(OBJECT(dev), value, name, &errp);
1089 assert(!errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001090}
1091
1092void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1093{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001094 Error *errp = NULL;
1095 object_property_set_int(OBJECT(dev), value, name, &errp);
1096 assert(!errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001097}
1098
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001099void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1100{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001101 Error *errp = NULL;
1102 object_property_set_int(OBJECT(dev), value, name, &errp);
1103 assert(!errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001104}
1105
Blue Swirl5a053d12009-07-21 11:10:41 +00001106void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1107{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001108 Error *errp = NULL;
1109 object_property_set_int(OBJECT(dev), value, name, &errp);
1110 assert(!errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001111}
1112
Markus Armbrustercc984672010-06-01 20:32:30 +02001113void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1114{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001115 Error *errp = NULL;
1116 object_property_set_str(OBJECT(dev), value, name, &errp);
1117 assert(!errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001118}
1119
Markus Armbruster18846de2010-06-29 16:58:30 +02001120int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001121{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001122 Error *errp = NULL;
1123 object_property_set_str(OBJECT(dev), bdrv_get_device_name(value),
1124 name, &errp);
1125 if (errp) {
1126 qerror_report_err(errp);
1127 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001128 return -1;
1129 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001130 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001131}
1132
Markus Armbruster18846de2010-06-29 16:58:30 +02001133void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1134{
1135 if (qdev_prop_set_drive(dev, name, value) < 0) {
1136 exit(1);
1137 }
1138}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001139void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1140{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001141 Error *errp = NULL;
1142 assert(value->label);
1143 object_property_set_str(OBJECT(dev), value->label, name, &errp);
1144 assert(!errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001145}
1146
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001147void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1148{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001149 Error *errp = NULL;
1150 assert(value->name);
1151 object_property_set_str(OBJECT(dev), value->name, name, &errp);
1152 assert(!errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001153}
1154
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001155void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1156{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001157 Error *errp = NULL;
1158 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
1159 assert(!errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001160}
1161
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001162void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1163{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001164 Error *errp = NULL;
1165 char str[2 * 6 + 5 + 1];
1166 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1167 value[0], value[1], value[2], value[3], value[4], value[5]);
1168
1169 object_property_set_str(OBJECT(dev), str, name, &errp);
1170 assert(!errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001171}
1172
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001173void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001174{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001175 Property *prop;
1176 Error *errp = NULL;
1177
1178 prop = qdev_prop_find(dev, name);
1179 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1180 name, &errp);
1181 assert(!errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001182}
1183
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001184void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1185{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001186 Property *prop;
1187 void **ptr;
1188
1189 prop = qdev_prop_find(dev, name);
1190 assert(prop && prop->info == &qdev_prop_ptr);
1191 ptr = qdev_get_prop_ptr(dev, prop);
1192 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001193}
1194
1195void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1196{
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001197 Object *obj = OBJECT(dev);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001198 if (!props)
1199 return;
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001200 for (; props->name; props++) {
1201 Error *errp = NULL;
1202 if (props->qtype == QTYPE_NONE) {
1203 continue;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001204 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001205 if (props->qtype == QTYPE_QBOOL) {
1206 object_property_set_bool(obj, props->defval, props->name, &errp);
1207 } else if (props->info->enum_table) {
1208 object_property_set_str(obj, props->info->enum_table[props->defval],
1209 props->name, &errp);
1210 } else if (props->qtype == QTYPE_QINT) {
1211 object_property_set_int(obj, props->defval, props->name, &errp);
1212 }
1213 assert(!errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001214 }
1215}
1216
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001217static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001218
Kevin Wolf25920d62010-03-15 17:01:24 +01001219static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001220{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001221 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001222}
1223
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001224void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001225{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001226 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001227
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001228 for (i = 0; props[i].driver != NULL; i++) {
1229 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001230 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001231}
1232
1233void qdev_prop_set_globals(DeviceState *dev)
1234{
1235 GlobalProperty *prop;
1236
1237 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001238 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001239 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001240 continue;
1241 }
1242 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001243 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001244 }
1245 }
1246}
Kevin Wolf25920d62010-03-15 17:01:24 +01001247
1248static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1249{
1250 GlobalProperty *g;
1251
Anthony Liguori7267c092011-08-20 22:09:37 -05001252 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001253 g->driver = qemu_opt_get(opts, "driver");
1254 g->property = qemu_opt_get(opts, "property");
1255 g->value = qemu_opt_get(opts, "value");
1256 qdev_prop_register_global(g);
1257 return 0;
1258}
1259
1260void qemu_add_globals(void)
1261{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001262 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001263}