blob: 0deb3780090bb6fb184fb8b0ea775611dc5d2d8a [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);
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +0100616 *ptr = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100617 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 */
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100946static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
947 const char *name, Error **errp)
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200948{
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100949 DeviceState *dev = DEVICE(obj);
950 Property *prop = opaque;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200951 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
952 unsigned int slot, fn, n;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100953 Error *local_err = NULL;
954 char *str = (char *)"";
955
956 if (dev->state != DEV_STATE_CREATED) {
957 error_set(errp, QERR_PERMISSION_DENIED);
958 return;
959 }
960
961 visit_type_str(v, &str, name, &local_err);
962 if (local_err) {
963 return set_int32(obj, v, opaque, name, errp);
964 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200965
966 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
967 fn = 0;
968 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100969 goto invalid;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200970 }
971 }
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100972 if (str[n] != '\0' || fn > 7 || slot > 31) {
973 goto invalid;
974 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200975 *ptr = slot << 3 | fn;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100976 return;
977
978invalid:
979 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200980}
981
982static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
983{
984 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
985
Blue Swirl73538c32009-08-28 19:12:16 +0000986 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200987 return snprintf(dest, len, "<unset>");
988 } else {
989 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
990 }
991}
992
993PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +0100994 .name = "int32",
995 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200996 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +0100997 .get = get_int32,
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100998 .set = set_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +0100999 /* FIXME: this should be -1...255, but the address is stored
1000 * into an uint32_t rather than int32_t.
1001 */
1002 .min = 0,
1003 .max = 0xFFFFFFFFULL,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +02001004};
1005
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001006/* --- public helpers --- */
1007
1008static Property *qdev_prop_walk(Property *props, const char *name)
1009{
1010 if (!props)
1011 return NULL;
1012 while (props->name) {
1013 if (strcmp(props->name, name) == 0)
1014 return props;
1015 props++;
1016 }
1017 return NULL;
1018}
1019
1020static Property *qdev_prop_find(DeviceState *dev, const char *name)
1021{
1022 Property *prop;
1023
1024 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001025 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001026 if (prop)
1027 return prop;
1028
1029 /* bus properties */
1030 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1031 if (prop)
1032 return prop;
1033
1034 return NULL;
1035}
1036
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +02001037int qdev_prop_exists(DeviceState *dev, const char *name)
1038{
1039 return qdev_prop_find(dev, name) ? true : false;
1040}
1041
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001042void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1043 Property *prop, const char *value)
1044{
1045 switch (ret) {
1046 case -EEXIST:
1047 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001048 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001049 break;
1050 default:
1051 case -EINVAL:
1052 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001053 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001054 break;
1055 case -ENOENT:
1056 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001057 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001058 break;
1059 case 0:
1060 break;
1061 }
1062}
1063
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001064int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1065{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001066 char *legacy_name;
1067 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001068
Paolo Bonzinid8229792012-02-02 09:47:13 +01001069 legacy_name = g_strdup_printf("legacy-%s", name);
1070 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1071 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1072 } else {
1073 object_property_set_str(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001074 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001075 g_free(legacy_name);
1076
1077 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001078 qerror_report_err(err);
1079 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001080 return -1;
1081 }
1082 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001083}
1084
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001085void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1086{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001087 Error *errp = NULL;
1088 object_property_set_bool(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001089 assert_no_error(errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001090}
1091
Juan Quintelac7cc1722009-09-29 22:48:25 +02001092void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1093{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001094 Error *errp = NULL;
1095 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001096 assert_no_error(errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001097}
1098
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001099void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1100{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001101 Error *errp = NULL;
1102 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001103 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001104}
1105
1106void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1107{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001108 Error *errp = NULL;
1109 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001110 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001111}
1112
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001113void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1114{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001115 Error *errp = NULL;
1116 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001117 assert_no_error(errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001118}
1119
Blue Swirl5a053d12009-07-21 11:10:41 +00001120void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1121{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001122 Error *errp = NULL;
1123 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001124 assert_no_error(errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001125}
1126
Markus Armbrustercc984672010-06-01 20:32:30 +02001127void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1128{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001129 Error *errp = NULL;
1130 object_property_set_str(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001131 assert_no_error(errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001132}
1133
Markus Armbruster18846de2010-06-29 16:58:30 +02001134int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001135{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001136 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001137 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1138 object_property_set_str(OBJECT(dev), bdrv_name,
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001139 name, &errp);
1140 if (errp) {
1141 qerror_report_err(errp);
1142 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001143 return -1;
1144 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001145 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001146}
1147
Markus Armbruster18846de2010-06-29 16:58:30 +02001148void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1149{
1150 if (qdev_prop_set_drive(dev, name, value) < 0) {
1151 exit(1);
1152 }
1153}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001154void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1155{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001156 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001157 assert(!value || value->label);
1158 object_property_set_str(OBJECT(dev),
1159 value ? value->label : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001160 assert_no_error(errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001161}
1162
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001163void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1164{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001165 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001166 assert(!value || value->name);
1167 object_property_set_str(OBJECT(dev),
1168 value ? value->name : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001169 assert_no_error(errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001170}
1171
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001172void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1173{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001174 Error *errp = NULL;
1175 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001176 assert_no_error(errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001177}
1178
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001179void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1180{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001181 Error *errp = NULL;
1182 char str[2 * 6 + 5 + 1];
1183 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1184 value[0], value[1], value[2], value[3], value[4], value[5]);
1185
1186 object_property_set_str(OBJECT(dev), str, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001187 assert_no_error(errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001188}
1189
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001190void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001191{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001192 Property *prop;
1193 Error *errp = NULL;
1194
1195 prop = qdev_prop_find(dev, name);
1196 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1197 name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001198 assert_no_error(errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001199}
1200
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001201void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1202{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001203 Property *prop;
1204 void **ptr;
1205
1206 prop = qdev_prop_find(dev, name);
1207 assert(prop && prop->info == &qdev_prop_ptr);
1208 ptr = qdev_get_prop_ptr(dev, prop);
1209 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001210}
1211
1212void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1213{
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001214 Object *obj = OBJECT(dev);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001215 if (!props)
1216 return;
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001217 for (; props->name; props++) {
1218 Error *errp = NULL;
1219 if (props->qtype == QTYPE_NONE) {
1220 continue;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001221 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001222 if (props->qtype == QTYPE_QBOOL) {
1223 object_property_set_bool(obj, props->defval, props->name, &errp);
1224 } else if (props->info->enum_table) {
1225 object_property_set_str(obj, props->info->enum_table[props->defval],
1226 props->name, &errp);
1227 } else if (props->qtype == QTYPE_QINT) {
1228 object_property_set_int(obj, props->defval, props->name, &errp);
1229 }
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001230 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001231 }
1232}
1233
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001234static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001235
Kevin Wolf25920d62010-03-15 17:01:24 +01001236static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001237{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001238 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001239}
1240
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001241void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001242{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001243 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001244
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001245 for (i = 0; props[i].driver != NULL; i++) {
1246 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001247 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001248}
1249
1250void qdev_prop_set_globals(DeviceState *dev)
1251{
1252 GlobalProperty *prop;
1253
1254 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001255 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001256 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001257 continue;
1258 }
1259 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001260 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001261 }
1262 }
1263}
Kevin Wolf25920d62010-03-15 17:01:24 +01001264
1265static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1266{
1267 GlobalProperty *g;
1268
Anthony Liguori7267c092011-08-20 22:09:37 -05001269 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001270 g->driver = qemu_opt_get(opts, "driver");
1271 g->property = qemu_opt_get(opts, "property");
1272 g->value = qemu_opt_get(opts, "value");
1273 qdev_prop_register_global(g);
1274 return 0;
1275}
1276
1277void qemu_add_globals(void)
1278{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001279 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001280}