blob: 553b0d19b108d86fb68ced12a0c6dda3534eace0 [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 */
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020030
31static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
32{
David 'Digit' Turner5a5e3d52011-01-10 23:11:40 +010033 uint32_t *p = qdev_get_prop_ptr(dev, prop);
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020034 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
35}
36
Anthony Liguori57c9faf2012-01-30 08:55:55 -060037static void get_bit(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010038 const char *name, Error **errp)
39{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060040 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010041 Property *prop = opaque;
42 uint32_t *p = qdev_get_prop_ptr(dev, prop);
43 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
44
45 visit_type_bool(v, &value, name, errp);
46}
47
Anthony Liguori57c9faf2012-01-30 08:55:55 -060048static void set_bit(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010049 const char *name, Error **errp)
50{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060051 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010052 Property *prop = opaque;
53 Error *local_err = NULL;
54 bool value;
55
56 if (dev->state != DEV_STATE_CREATED) {
57 error_set(errp, QERR_PERMISSION_DENIED);
58 return;
59 }
60
61 visit_type_bool(v, &value, name, &local_err);
62 if (local_err) {
63 error_propagate(errp, local_err);
64 return;
65 }
66 bit_prop_set(dev, prop, value);
67}
68
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020069PropertyInfo qdev_prop_bit = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +010070 .name = "boolean",
71 .legacy_name = "on/off",
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020072 .print = print_bit,
Paolo Bonzini80e555c2011-12-18 17:05:09 +010073 .get = get_bit,
74 .set = set_bit,
Michael S. Tsirkind2364ee2010-01-10 13:52:41 +020075};
76
Juan Quintelac7cc1722009-09-29 22:48:25 +020077/* --- 8bit integer --- */
78
Michael Rothc08fb2a2012-02-22 12:26:37 -060079static void get_uint8(Object *obj, Visitor *v, void *opaque,
80 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +010081{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060082 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010083 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -060084 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010085
Michael Rothc08fb2a2012-02-22 12:26:37 -060086 visit_type_uint8(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010087}
88
Michael Rothc08fb2a2012-02-22 12:26:37 -060089static void set_uint8(Object *obj, Visitor *v, void *opaque,
90 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +010091{
Anthony Liguori57c9faf2012-01-30 08:55:55 -060092 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010093 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -060094 uint8_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010095 Error *local_err = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +010096
97 if (dev->state != DEV_STATE_CREATED) {
98 error_set(errp, QERR_PERMISSION_DENIED);
99 return;
100 }
101
Michael Rothc08fb2a2012-02-22 12:26:37 -0600102 visit_type_uint8(v, &value, name, &local_err);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100103 if (local_err) {
104 error_propagate(errp, local_err);
105 return;
106 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100107 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100108 *ptr = value;
109 } else {
110 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600111 dev->id?:"", name, (int64_t)value, prop->info->min,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100112 prop->info->max);
113 }
114}
115
Juan Quintelac7cc1722009-09-29 22:48:25 +0200116PropertyInfo qdev_prop_uint8 = {
117 .name = "uint8",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600118 .get = get_uint8,
119 .set = set_uint8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100120 .min = 0,
121 .max = 255,
Juan Quintelac7cc1722009-09-29 22:48:25 +0200122};
123
Jan Kiszka68356782011-10-07 09:19:52 +0200124/* --- 8bit hex value --- */
125
126static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
127{
128 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
129 char *end;
130
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100131 if (str[0] != '0' || str[1] != 'x') {
132 return -EINVAL;
133 }
134
Jan Kiszka68356782011-10-07 09:19:52 +0200135 *ptr = strtoul(str, &end, 16);
136 if ((*end != '\0') || (end == str)) {
137 return -EINVAL;
138 }
139
140 return 0;
141}
142
143static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
144{
145 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
146 return snprintf(dest, len, "0x%" PRIx8, *ptr);
147}
148
149PropertyInfo qdev_prop_hex8 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100150 .name = "uint8",
151 .legacy_name = "hex8",
Jan Kiszka68356782011-10-07 09:19:52 +0200152 .parse = parse_hex8,
153 .print = print_hex8,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600154 .get = get_uint8,
155 .set = set_uint8,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100156 .min = 0,
157 .max = 255,
Jan Kiszka68356782011-10-07 09:19:52 +0200158};
159
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200160/* --- 16bit integer --- */
161
Michael Rothc08fb2a2012-02-22 12:26:37 -0600162static void get_uint16(Object *obj, Visitor *v, void *opaque,
163 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100164{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600165 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100166 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600167 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100168
Michael Rothc08fb2a2012-02-22 12:26:37 -0600169 visit_type_uint16(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100170}
171
Michael Rothc08fb2a2012-02-22 12:26:37 -0600172static void set_uint16(Object *obj, Visitor *v, void *opaque,
173 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100174{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600175 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100176 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600177 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100178 Error *local_err = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100179
180 if (dev->state != DEV_STATE_CREATED) {
181 error_set(errp, QERR_PERMISSION_DENIED);
182 return;
183 }
184
Michael Rothc08fb2a2012-02-22 12:26:37 -0600185 visit_type_uint16(v, &value, name, &local_err);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100186 if (local_err) {
187 error_propagate(errp, local_err);
188 return;
189 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100190 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100191 *ptr = value;
192 } else {
193 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600194 dev->id?:"", name, (int64_t)value, prop->info->min,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100195 prop->info->max);
196 }
197}
198
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200199PropertyInfo qdev_prop_uint16 = {
200 .name = "uint16",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600201 .get = get_uint16,
202 .set = set_uint16,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100203 .min = 0,
204 .max = 65535,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200205};
206
207/* --- 32bit integer --- */
208
Michael Rothc08fb2a2012-02-22 12:26:37 -0600209static void get_uint32(Object *obj, Visitor *v, void *opaque,
210 const char *name, Error **errp)
211{
212 DeviceState *dev = DEVICE(obj);
213 Property *prop = opaque;
214 uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
215
216 value = *ptr;
217 visit_type_uint32(v, &value, name, errp);
218}
219
220static void set_uint32(Object *obj, Visitor *v, void *opaque,
221 const char *name, Error **errp)
222{
223 DeviceState *dev = DEVICE(obj);
224 Property *prop = opaque;
225 uint32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
226 Error *local_err = NULL;
227
228 if (dev->state != DEV_STATE_CREATED) {
229 error_set(errp, QERR_PERMISSION_DENIED);
230 return;
231 }
232
233 visit_type_uint32(v, &value, name, &local_err);
234 if (local_err) {
235 error_propagate(errp, local_err);
236 return;
237 }
238 if (value >= prop->info->min && value <= prop->info->max) {
239 *ptr = value;
240 } else {
241 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
242 dev->id?:"", name, (int64_t)value, prop->info->min,
243 prop->info->max);
244 }
245}
246
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600247static void get_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100248 const char *name, Error **errp)
249{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600250 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100251 Property *prop = opaque;
252 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100253
Michael Rothc08fb2a2012-02-22 12:26:37 -0600254 visit_type_int32(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100255}
256
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600257static void set_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100258 const char *name, Error **errp)
259{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600260 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100261 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600262 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100263 Error *local_err = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100264
265 if (dev->state != DEV_STATE_CREATED) {
266 error_set(errp, QERR_PERMISSION_DENIED);
267 return;
268 }
269
Michael Rothc08fb2a2012-02-22 12:26:37 -0600270 visit_type_int32(v, &value, name, &local_err);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100271 if (local_err) {
272 error_propagate(errp, local_err);
273 return;
274 }
Paolo Bonzini6350b092012-02-02 16:19:21 +0100275 if (value >= prop->info->min && value <= prop->info->max) {
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100276 *ptr = value;
277 } else {
278 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600279 dev->id?:"", name, (int64_t)value, prop->info->min,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100280 prop->info->max);
281 }
282}
283
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200284PropertyInfo qdev_prop_uint32 = {
285 .name = "uint32",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600286 .get = get_uint32,
287 .set = set_uint32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100288 .min = 0,
289 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200290};
291
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200292PropertyInfo qdev_prop_int32 = {
293 .name = "int32",
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100294 .get = get_int32,
295 .set = set_int32,
296 .min = -0x80000000LL,
297 .max = 0x7FFFFFFFLL,
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200298};
299
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200300/* --- 32bit hex value --- */
301
302static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
303{
304 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200305 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200306
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100307 if (str[0] != '0' || str[1] != 'x') {
308 return -EINVAL;
309 }
310
Kevin Wolf449041d2010-06-18 18:27:03 +0200311 *ptr = strtoul(str, &end, 16);
312 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100313 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200314 }
315
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200316 return 0;
317}
318
319static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
320{
321 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
322 return snprintf(dest, len, "0x%" PRIx32, *ptr);
323}
324
325PropertyInfo qdev_prop_hex32 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100326 .name = "uint32",
327 .legacy_name = "hex32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200328 .parse = parse_hex32,
329 .print = print_hex32,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600330 .get = get_uint32,
331 .set = set_uint32,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100332 .min = 0,
333 .max = 0xFFFFFFFFULL,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200334};
335
Blue Swirl5a053d12009-07-21 11:10:41 +0000336/* --- 64bit integer --- */
337
Michael Rothc08fb2a2012-02-22 12:26:37 -0600338static void get_uint64(Object *obj, Visitor *v, void *opaque,
339 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100340{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600341 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100342 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600343 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100344
Michael Rothc08fb2a2012-02-22 12:26:37 -0600345 visit_type_uint64(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100346}
347
Michael Rothc08fb2a2012-02-22 12:26:37 -0600348static void set_uint64(Object *obj, Visitor *v, void *opaque,
349 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100350{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600351 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100352 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600353 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100354
355 if (dev->state != DEV_STATE_CREATED) {
356 error_set(errp, QERR_PERMISSION_DENIED);
357 return;
358 }
359
Michael Rothc08fb2a2012-02-22 12:26:37 -0600360 visit_type_uint64(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100361}
362
Blue Swirl5a053d12009-07-21 11:10:41 +0000363PropertyInfo qdev_prop_uint64 = {
364 .name = "uint64",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600365 .get = get_uint64,
366 .set = set_uint64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000367};
368
369/* --- 64bit hex value --- */
370
371static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
372{
373 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200374 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000375
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100376 if (str[0] != '0' || str[1] != 'x') {
377 return -EINVAL;
378 }
379
Kevin Wolf449041d2010-06-18 18:27:03 +0200380 *ptr = strtoull(str, &end, 16);
381 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100382 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200383 }
384
Blue Swirl5a053d12009-07-21 11:10:41 +0000385 return 0;
386}
387
388static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
389{
390 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
391 return snprintf(dest, len, "0x%" PRIx64, *ptr);
392}
393
394PropertyInfo qdev_prop_hex64 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100395 .name = "uint64",
396 .legacy_name = "hex64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000397 .parse = parse_hex64,
398 .print = print_hex64,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600399 .get = get_uint64,
400 .set = set_uint64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000401};
402
Gerd Hoffmann59419662009-10-12 17:15:47 +0530403/* --- string --- */
404
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100405static void release_string(Object *obj, const char *name, void *opaque)
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200406{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100407 Property *prop = opaque;
408 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200409}
410
Gerd Hoffmann59419662009-10-12 17:15:47 +0530411static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
412{
413 char **ptr = qdev_get_prop_ptr(dev, prop);
414 if (!*ptr)
415 return snprintf(dest, len, "<null>");
416 return snprintf(dest, len, "\"%s\"", *ptr);
417}
418
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600419static void get_string(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 char **ptr = qdev_get_prop_ptr(dev, prop);
425
426 if (!*ptr) {
427 char *str = (char *)"";
428 visit_type_str(v, &str, name, errp);
429 } else {
430 visit_type_str(v, ptr, name, errp);
431 }
432}
433
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600434static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100435 const char *name, Error **errp)
436{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600437 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100438 Property *prop = opaque;
439 char **ptr = qdev_get_prop_ptr(dev, prop);
440 Error *local_err = NULL;
441 char *str;
442
443 if (dev->state != DEV_STATE_CREATED) {
444 error_set(errp, QERR_PERMISSION_DENIED);
445 return;
446 }
447
448 visit_type_str(v, &str, name, &local_err);
449 if (local_err) {
450 error_propagate(errp, local_err);
451 return;
452 }
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100453 if (*ptr) {
454 g_free(*ptr);
455 }
456 *ptr = str;
457}
458
Gerd Hoffmann59419662009-10-12 17:15:47 +0530459PropertyInfo qdev_prop_string = {
460 .name = "string",
Gerd Hoffmann59419662009-10-12 17:15:47 +0530461 .print = print_string,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100462 .release = release_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100463 .get = get_string,
464 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530465};
466
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200467/* --- drive --- */
468
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100469static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200470{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200471 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200472
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200473 bs = bdrv_find(str);
474 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100475 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200476 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200477 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200478 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200479 return 0;
480}
481
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100482static void release_drive(Object *obj, const char *name, void *opaque)
Markus Armbruster14bafc52010-06-25 08:09:10 +0200483{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100484 DeviceState *dev = DEVICE(obj);
485 Property *prop = opaque;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200486 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200487
488 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200489 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200490 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200491 }
492}
493
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100494static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200495{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100496 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200497}
498
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100499static void get_pointer(Object *obj, Visitor *v, Property *prop,
500 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100501 const char *name, Error **errp)
502{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600503 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100504 void **ptr = qdev_get_prop_ptr(dev, prop);
505 char *p;
506
507 p = (char *) (*ptr ? print(*ptr) : "");
508 visit_type_str(v, &p, name, errp);
509}
510
511static void set_pointer(Object *obj, Visitor *v, Property *prop,
512 int (*parse)(DeviceState *dev, const char *str, void **ptr),
513 const char *name, Error **errp)
514{
515 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100516 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100517 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100518 char *str;
519 int ret;
520
521 if (dev->state != DEV_STATE_CREATED) {
522 error_set(errp, QERR_PERMISSION_DENIED);
523 return;
524 }
525
526 visit_type_str(v, &str, name, &local_err);
527 if (local_err) {
528 error_propagate(errp, local_err);
529 return;
530 }
531 if (!*str) {
532 g_free(str);
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +0100533 *ptr = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100534 return;
535 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100536 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100537 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
538 g_free(str);
539}
540
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100541static void get_drive(Object *obj, Visitor *v, void *opaque,
542 const char *name, Error **errp)
543{
544 get_pointer(obj, v, opaque, print_drive, name, errp);
545}
546
547static void set_drive(Object *obj, Visitor *v, void *opaque,
548 const char *name, Error **errp)
549{
550 set_pointer(obj, v, opaque, parse_drive, name, errp);
551}
552
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200553PropertyInfo qdev_prop_drive = {
554 .name = "drive",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100555 .get = get_drive,
556 .set = set_drive,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100557 .release = release_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200558};
559
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200560/* --- character device --- */
561
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100562static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200563{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100564 CharDriverState *chr = qemu_chr_find(str);
565 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100566 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530567 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100568 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530569 return -EEXIST;
570 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100571 *ptr = chr;
572 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200573 return 0;
574}
575
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100576static void release_chr(Object *obj, const char *name, void *opaque)
Amit Shaha87f3e82012-01-13 15:29:47 +0530577{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100578 DeviceState *dev = DEVICE(obj);
579 Property *prop = opaque;
Amit Shaha87f3e82012-01-13 15:29:47 +0530580 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
581
582 if (*ptr) {
583 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
584 }
585}
586
587
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100588static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200589{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100590 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000591
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100592 return chr->label ? chr->label : "";
593}
594
595static void get_chr(Object *obj, Visitor *v, void *opaque,
596 const char *name, Error **errp)
597{
598 get_pointer(obj, v, opaque, print_chr, name, errp);
599}
600
601static void set_chr(Object *obj, Visitor *v, void *opaque,
602 const char *name, Error **errp)
603{
604 set_pointer(obj, v, opaque, parse_chr, name, errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200605}
606
607PropertyInfo qdev_prop_chr = {
608 .name = "chr",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100609 .get = get_chr,
610 .set = set_chr,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100611 .release = release_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200612};
613
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200614/* --- netdev device --- */
615
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100616static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200617{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100618 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200619
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100620 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100621 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100622 }
623 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100624 return -EEXIST;
625 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100626 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200627 return 0;
628}
629
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100630static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200631{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100632 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200633
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100634 return netdev->name ? netdev->name : "";
635}
636
637static void get_netdev(Object *obj, Visitor *v, void *opaque,
638 const char *name, Error **errp)
639{
640 get_pointer(obj, v, opaque, print_netdev, name, errp);
641}
642
643static void set_netdev(Object *obj, Visitor *v, void *opaque,
644 const char *name, Error **errp)
645{
646 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200647}
648
649PropertyInfo qdev_prop_netdev = {
650 .name = "netdev",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100651 .get = get_netdev,
652 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200653};
654
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200655/* --- vlan --- */
656
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200657static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
658{
659 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
660
661 if (*ptr) {
662 return snprintf(dest, len, "%d", (*ptr)->id);
663 } else {
664 return snprintf(dest, len, "<null>");
665 }
666}
667
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600668static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100669 const char *name, Error **errp)
670{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600671 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100672 Property *prop = opaque;
673 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
674 int64_t id;
675
676 id = *ptr ? (*ptr)->id : -1;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600677 visit_type_int64(v, &id, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100678}
679
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600680static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100681 const char *name, Error **errp)
682{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600683 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100684 Property *prop = opaque;
685 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
686 Error *local_err = NULL;
687 int64_t id;
688 VLANState *vlan;
689
690 if (dev->state != DEV_STATE_CREATED) {
691 error_set(errp, QERR_PERMISSION_DENIED);
692 return;
693 }
694
Michael Rothc08fb2a2012-02-22 12:26:37 -0600695 visit_type_int64(v, &id, name, &local_err);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100696 if (local_err) {
697 error_propagate(errp, local_err);
698 return;
699 }
700 if (id == -1) {
701 *ptr = NULL;
702 return;
703 }
704 vlan = qemu_find_vlan(id, 1);
705 if (!vlan) {
706 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
707 name, prop->info->name);
708 return;
709 }
710 *ptr = vlan;
711}
712
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200713PropertyInfo qdev_prop_vlan = {
714 .name = "vlan",
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200715 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100716 .get = get_vlan,
717 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200718};
719
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200720/* --- pointer --- */
721
Markus Armbruster036f7162010-02-19 11:47:06 +0100722/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200723PropertyInfo qdev_prop_ptr = {
724 .name = "ptr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200725};
726
727/* --- mac address --- */
728
729/*
730 * accepted syntax versions:
731 * 01:02:03:04:05:06
732 * 01-02-03-04-05-06
733 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100734static void get_mac(Object *obj, Visitor *v, void *opaque,
735 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200736{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100737 DeviceState *dev = DEVICE(obj);
738 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200739 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100740 char buffer[2 * 6 + 5 + 1];
741 char *p = buffer;
742
743 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
744 mac->a[0], mac->a[1], mac->a[2],
745 mac->a[3], mac->a[4], mac->a[5]);
746
747 visit_type_str(v, &p, name, errp);
748}
749
750static void set_mac(Object *obj, Visitor *v, void *opaque,
751 const char *name, Error **errp)
752{
753 DeviceState *dev = DEVICE(obj);
754 Property *prop = opaque;
755 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
756 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200757 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100758 char *str, *p;
759
760 if (dev->state != DEV_STATE_CREATED) {
761 error_set(errp, QERR_PERMISSION_DENIED);
762 return;
763 }
764
765 visit_type_str(v, &str, name, &local_err);
766 if (local_err) {
767 error_propagate(errp, local_err);
768 return;
769 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200770
771 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000772 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100773 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000774 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100775 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200776 if (i == 5) {
777 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100778 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200779 } else {
780 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100781 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200782 }
783 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200784 }
dunrong huanga3400462012-05-18 19:14:13 +0800785 g_free(str);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100786 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200787
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100788inval:
789 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
dunrong huanga3400462012-05-18 19:14:13 +0800790 g_free(str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200791}
792
793PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200794 .name = "macaddr",
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100795 .get = get_mac,
796 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200797};
798
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100799
800/* --- lost tick policy --- */
801
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100802static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
803 [LOST_TICK_DISCARD] = "discard",
804 [LOST_TICK_DELAY] = "delay",
805 [LOST_TICK_MERGE] = "merge",
806 [LOST_TICK_SLEW] = "slew",
807 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100808};
809
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100810QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100811
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100812static void get_enum(Object *obj, Visitor *v, void *opaque,
813 const char *name, Error **errp)
814{
815 DeviceState *dev = DEVICE(obj);
816 Property *prop = opaque;
817 int *ptr = qdev_get_prop_ptr(dev, prop);
818
819 visit_type_enum(v, ptr, prop->info->enum_table,
820 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100821}
822
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100823static void set_enum(Object *obj, Visitor *v, void *opaque,
824 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100825{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100826 DeviceState *dev = DEVICE(obj);
827 Property *prop = opaque;
828 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100829
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100830 if (dev->state != DEV_STATE_CREATED) {
831 error_set(errp, QERR_PERMISSION_DENIED);
832 return;
833 }
834
835 visit_type_enum(v, ptr, prop->info->enum_table,
836 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100837}
838
839PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100840 .name = "LostTickPolicy",
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100841 .enum_table = lost_tick_policy_table,
842 .get = get_enum,
843 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100844};
845
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200846/* --- pci address --- */
847
848/*
849 * bus-local address, i.e. "$slot" or "$slot.$fn"
850 */
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100851static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
852 const char *name, Error **errp)
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200853{
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100854 DeviceState *dev = DEVICE(obj);
855 Property *prop = opaque;
Michael Roth09f1bbc2012-03-04 13:38:27 -0600856 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200857 unsigned int slot, fn, n;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100858 Error *local_err = NULL;
dunrong huanga3400462012-05-18 19:14:13 +0800859 char *str;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100860
861 if (dev->state != DEV_STATE_CREATED) {
862 error_set(errp, QERR_PERMISSION_DENIED);
863 return;
864 }
865
866 visit_type_str(v, &str, name, &local_err);
867 if (local_err) {
Stefan Weil5c878002012-04-28 02:32:42 +0000868 error_free(local_err);
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100869 return set_int32(obj, v, opaque, name, errp);
870 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200871
872 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
873 fn = 0;
874 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100875 goto invalid;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200876 }
877 }
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100878 if (str[n] != '\0' || fn > 7 || slot > 31) {
879 goto invalid;
880 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200881 *ptr = slot << 3 | fn;
dunrong huanga3400462012-05-18 19:14:13 +0800882 g_free(str);
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100883 return;
884
885invalid:
886 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
dunrong huanga3400462012-05-18 19:14:13 +0800887 g_free(str);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200888}
889
890static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
891{
Michael Roth09f1bbc2012-03-04 13:38:27 -0600892 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200893
Blue Swirl73538c32009-08-28 19:12:16 +0000894 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200895 return snprintf(dest, len, "<unset>");
896 } else {
897 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
898 }
899}
900
901PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +0100902 .name = "int32",
903 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200904 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +0100905 .get = get_int32,
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100906 .set = set_pci_devfn,
Michael Roth09f1bbc2012-03-04 13:38:27 -0600907 .min = -1,
908 .max = 255,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200909};
910
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000911/* --- blocksize --- */
912
913static void set_blocksize(Object *obj, Visitor *v, void *opaque,
914 const char *name, Error **errp)
915{
916 DeviceState *dev = DEVICE(obj);
917 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600918 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000919 Error *local_err = NULL;
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000920
921 if (dev->state != DEV_STATE_CREATED) {
922 error_set(errp, QERR_PERMISSION_DENIED);
923 return;
924 }
925
Michael Rothc08fb2a2012-02-22 12:26:37 -0600926 visit_type_uint16(v, &value, name, &local_err);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000927 if (local_err) {
928 error_propagate(errp, local_err);
929 return;
930 }
931 if (value < prop->info->min || value > prop->info->max) {
932 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600933 dev->id?:"", name, (int64_t)value, prop->info->min,
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000934 prop->info->max);
935 return;
936 }
937
938 /* We rely on power-of-2 blocksizes for bitmasks */
939 if ((value & (value - 1)) != 0) {
940 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600941 dev->id?:"", name, (int64_t)value);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000942 return;
943 }
944
945 *ptr = value;
946}
947
948PropertyInfo qdev_prop_blocksize = {
949 .name = "blocksize",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600950 .get = get_uint16,
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000951 .set = set_blocksize,
952 .min = 512,
953 .max = 65024,
954};
955
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200956/* --- public helpers --- */
957
958static Property *qdev_prop_walk(Property *props, const char *name)
959{
960 if (!props)
961 return NULL;
962 while (props->name) {
963 if (strcmp(props->name, name) == 0)
964 return props;
965 props++;
966 }
967 return NULL;
968}
969
970static Property *qdev_prop_find(DeviceState *dev, const char *name)
971{
972 Property *prop;
973
974 /* device properties */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600975 prop = qdev_prop_walk(qdev_get_props(dev), name);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200976 if (prop)
977 return prop;
978
979 /* bus properties */
980 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
981 if (prop)
982 return prop;
983
984 return NULL;
985}
986
Gerd Hoffmannd8ed79a2009-10-21 15:25:28 +0200987int qdev_prop_exists(DeviceState *dev, const char *name)
988{
989 return qdev_prop_find(dev, name) ? true : false;
990}
991
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +0100992void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
993 Property *prop, const char *value)
994{
995 switch (ret) {
996 case -EEXIST:
997 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600998 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +0100999 break;
1000 default:
1001 case -EINVAL:
1002 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001003 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001004 break;
1005 case -ENOENT:
1006 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001007 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001008 break;
1009 case 0:
1010 break;
1011 }
1012}
1013
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001014int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1015{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001016 char *legacy_name;
1017 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001018
Paolo Bonzinid8229792012-02-02 09:47:13 +01001019 legacy_name = g_strdup_printf("legacy-%s", name);
1020 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
Paolo Bonzini0c96e282012-02-09 10:12:08 +01001021 object_property_parse(OBJECT(dev), value, legacy_name, &err);
Paolo Bonzinid8229792012-02-02 09:47:13 +01001022 } else {
Paolo Bonzini0c96e282012-02-09 10:12:08 +01001023 object_property_parse(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001024 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001025 g_free(legacy_name);
1026
1027 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001028 qerror_report_err(err);
1029 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001030 return -1;
1031 }
1032 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001033}
1034
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001035void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1036{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001037 Error *errp = NULL;
1038 object_property_set_bool(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001039 assert_no_error(errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001040}
1041
Juan Quintelac7cc1722009-09-29 22:48:25 +02001042void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1043{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001044 Error *errp = NULL;
1045 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001046 assert_no_error(errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001047}
1048
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001049void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1050{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001051 Error *errp = NULL;
1052 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001053 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001054}
1055
1056void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1057{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001058 Error *errp = NULL;
1059 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001060 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001061}
1062
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001063void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1064{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001065 Error *errp = NULL;
1066 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001067 assert_no_error(errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001068}
1069
Blue Swirl5a053d12009-07-21 11:10:41 +00001070void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1071{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001072 Error *errp = NULL;
1073 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001074 assert_no_error(errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001075}
1076
Markus Armbrustercc984672010-06-01 20:32:30 +02001077void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1078{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001079 Error *errp = NULL;
1080 object_property_set_str(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001081 assert_no_error(errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001082}
1083
Markus Armbruster18846de2010-06-29 16:58:30 +02001084int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001085{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001086 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001087 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1088 object_property_set_str(OBJECT(dev), bdrv_name,
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001089 name, &errp);
1090 if (errp) {
1091 qerror_report_err(errp);
1092 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001093 return -1;
1094 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001095 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001096}
1097
Markus Armbruster18846de2010-06-29 16:58:30 +02001098void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1099{
1100 if (qdev_prop_set_drive(dev, name, value) < 0) {
1101 exit(1);
1102 }
1103}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001104void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1105{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001106 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001107 assert(!value || value->label);
1108 object_property_set_str(OBJECT(dev),
1109 value ? value->label : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001110 assert_no_error(errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001111}
1112
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001113void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1114{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001115 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001116 assert(!value || value->name);
1117 object_property_set_str(OBJECT(dev),
1118 value ? value->name : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001119 assert_no_error(errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001120}
1121
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001122void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1123{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001124 Error *errp = NULL;
1125 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001126 assert_no_error(errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001127}
1128
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001129void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1130{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001131 Error *errp = NULL;
1132 char str[2 * 6 + 5 + 1];
1133 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1134 value[0], value[1], value[2], value[3], value[4], value[5]);
1135
1136 object_property_set_str(OBJECT(dev), str, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001137 assert_no_error(errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001138}
1139
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001140void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001141{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001142 Property *prop;
1143 Error *errp = NULL;
1144
1145 prop = qdev_prop_find(dev, name);
1146 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1147 name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001148 assert_no_error(errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001149}
1150
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001151void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1152{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001153 Property *prop;
1154 void **ptr;
1155
1156 prop = qdev_prop_find(dev, name);
1157 assert(prop && prop->info == &qdev_prop_ptr);
1158 ptr = qdev_get_prop_ptr(dev, prop);
1159 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001160}
1161
1162void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1163{
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001164 Object *obj = OBJECT(dev);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001165 if (!props)
1166 return;
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001167 for (; props->name; props++) {
1168 Error *errp = NULL;
1169 if (props->qtype == QTYPE_NONE) {
1170 continue;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001171 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +01001172 if (props->qtype == QTYPE_QBOOL) {
1173 object_property_set_bool(obj, props->defval, props->name, &errp);
1174 } else if (props->info->enum_table) {
1175 object_property_set_str(obj, props->info->enum_table[props->defval],
1176 props->name, &errp);
1177 } else if (props->qtype == QTYPE_QINT) {
1178 object_property_set_int(obj, props->defval, props->name, &errp);
1179 }
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001180 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001181 }
1182}
1183
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001184static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001185
Kevin Wolf25920d62010-03-15 17:01:24 +01001186static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001187{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001188 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001189}
1190
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001191void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001192{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001193 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001194
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001195 for (i = 0; props[i].driver != NULL; i++) {
1196 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001197 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001198}
1199
1200void qdev_prop_set_globals(DeviceState *dev)
1201{
1202 GlobalProperty *prop;
1203
1204 QTAILQ_FOREACH(prop, &global_props, next) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001205 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
Anthony Liguori4be9f0d2011-12-09 10:51:49 -06001206 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001207 continue;
1208 }
1209 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001210 exit(1);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001211 }
1212 }
1213}
Kevin Wolf25920d62010-03-15 17:01:24 +01001214
1215static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1216{
1217 GlobalProperty *g;
1218
Anthony Liguori7267c092011-08-20 22:09:37 -05001219 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001220 g->driver = qemu_opt_get(opts, "driver");
1221 g->property = qemu_opt_get(opts, "property");
1222 g->value = qemu_opt_get(opts, "value");
1223 qdev_prop_register_global(g);
1224 return 0;
1225}
1226
1227void qemu_add_globals(void)
1228{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001229 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001230}