blob: 0b894620c97ad95b458f54b43e35260a8948921f [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;
Paolo Bonzini27712df2012-04-12 15:32:26 +020094 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +010095
96 if (dev->state != DEV_STATE_CREATED) {
97 error_set(errp, QERR_PERMISSION_DENIED);
98 return;
99 }
100
Paolo Bonzini27712df2012-04-12 15:32:26 +0200101 visit_type_uint8(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100102}
103
Juan Quintelac7cc1722009-09-29 22:48:25 +0200104PropertyInfo qdev_prop_uint8 = {
105 .name = "uint8",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600106 .get = get_uint8,
107 .set = set_uint8,
Juan Quintelac7cc1722009-09-29 22:48:25 +0200108};
109
Jan Kiszka68356782011-10-07 09:19:52 +0200110/* --- 8bit hex value --- */
111
112static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
113{
114 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
115 char *end;
116
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100117 if (str[0] != '0' || str[1] != 'x') {
118 return -EINVAL;
119 }
120
Jan Kiszka68356782011-10-07 09:19:52 +0200121 *ptr = strtoul(str, &end, 16);
122 if ((*end != '\0') || (end == str)) {
123 return -EINVAL;
124 }
125
126 return 0;
127}
128
129static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
130{
131 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
132 return snprintf(dest, len, "0x%" PRIx8, *ptr);
133}
134
135PropertyInfo qdev_prop_hex8 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100136 .name = "uint8",
137 .legacy_name = "hex8",
Jan Kiszka68356782011-10-07 09:19:52 +0200138 .parse = parse_hex8,
139 .print = print_hex8,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600140 .get = get_uint8,
141 .set = set_uint8,
Jan Kiszka68356782011-10-07 09:19:52 +0200142};
143
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200144/* --- 16bit integer --- */
145
Michael Rothc08fb2a2012-02-22 12:26:37 -0600146static void get_uint16(Object *obj, Visitor *v, void *opaque,
147 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100148{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600149 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100150 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600151 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100152
Michael Rothc08fb2a2012-02-22 12:26:37 -0600153 visit_type_uint16(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100154}
155
Michael Rothc08fb2a2012-02-22 12:26:37 -0600156static void set_uint16(Object *obj, Visitor *v, void *opaque,
157 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100158{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600159 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100160 Property *prop = opaque;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200161 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100162
163 if (dev->state != DEV_STATE_CREATED) {
164 error_set(errp, QERR_PERMISSION_DENIED);
165 return;
166 }
167
Paolo Bonzini27712df2012-04-12 15:32:26 +0200168 visit_type_uint16(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100169}
170
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200171PropertyInfo qdev_prop_uint16 = {
172 .name = "uint16",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600173 .get = get_uint16,
174 .set = set_uint16,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200175};
176
177/* --- 32bit integer --- */
178
Michael Rothc08fb2a2012-02-22 12:26:37 -0600179static void get_uint32(Object *obj, Visitor *v, void *opaque,
180 const char *name, Error **errp)
181{
182 DeviceState *dev = DEVICE(obj);
183 Property *prop = opaque;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200184 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Michael Rothc08fb2a2012-02-22 12:26:37 -0600185
Paolo Bonzini27712df2012-04-12 15:32:26 +0200186 visit_type_uint32(v, ptr, name, errp);
Michael Rothc08fb2a2012-02-22 12:26:37 -0600187}
188
189static void set_uint32(Object *obj, Visitor *v, void *opaque,
190 const char *name, Error **errp)
191{
192 DeviceState *dev = DEVICE(obj);
193 Property *prop = opaque;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200194 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Michael Rothc08fb2a2012-02-22 12:26:37 -0600195
196 if (dev->state != DEV_STATE_CREATED) {
197 error_set(errp, QERR_PERMISSION_DENIED);
198 return;
199 }
200
Paolo Bonzini27712df2012-04-12 15:32:26 +0200201 visit_type_uint32(v, ptr, name, errp);
Michael Rothc08fb2a2012-02-22 12:26:37 -0600202}
203
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600204static void get_int32(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100205 const char *name, Error **errp)
206{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600207 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100208 Property *prop = opaque;
209 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100210
Michael Rothc08fb2a2012-02-22 12:26:37 -0600211 visit_type_int32(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100212}
213
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600214static void set_int32(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;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200219 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100220
221 if (dev->state != DEV_STATE_CREATED) {
222 error_set(errp, QERR_PERMISSION_DENIED);
223 return;
224 }
225
Paolo Bonzini27712df2012-04-12 15:32:26 +0200226 visit_type_int32(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100227}
228
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200229PropertyInfo qdev_prop_uint32 = {
230 .name = "uint32",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600231 .get = get_uint32,
232 .set = set_uint32,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200233};
234
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200235PropertyInfo qdev_prop_int32 = {
236 .name = "int32",
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100237 .get = get_int32,
238 .set = set_int32,
Gerd Hoffmann316940b2009-09-10 11:43:25 +0200239};
240
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200241/* --- 32bit hex value --- */
242
243static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
244{
245 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200246 char *end;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200247
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100248 if (str[0] != '0' || str[1] != 'x') {
249 return -EINVAL;
250 }
251
Kevin Wolf449041d2010-06-18 18:27:03 +0200252 *ptr = strtoul(str, &end, 16);
253 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100254 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200255 }
256
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200257 return 0;
258}
259
260static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
261{
262 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
263 return snprintf(dest, len, "0x%" PRIx32, *ptr);
264}
265
266PropertyInfo qdev_prop_hex32 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100267 .name = "uint32",
268 .legacy_name = "hex32",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200269 .parse = parse_hex32,
270 .print = print_hex32,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600271 .get = get_uint32,
272 .set = set_uint32,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200273};
274
Blue Swirl5a053d12009-07-21 11:10:41 +0000275/* --- 64bit integer --- */
276
Michael Rothc08fb2a2012-02-22 12:26:37 -0600277static void get_uint64(Object *obj, Visitor *v, void *opaque,
278 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100279{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600280 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100281 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600282 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100283
Michael Rothc08fb2a2012-02-22 12:26:37 -0600284 visit_type_uint64(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100285}
286
Michael Rothc08fb2a2012-02-22 12:26:37 -0600287static void set_uint64(Object *obj, Visitor *v, void *opaque,
288 const char *name, Error **errp)
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100289{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600290 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100291 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600292 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100293
294 if (dev->state != DEV_STATE_CREATED) {
295 error_set(errp, QERR_PERMISSION_DENIED);
296 return;
297 }
298
Michael Rothc08fb2a2012-02-22 12:26:37 -0600299 visit_type_uint64(v, ptr, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100300}
301
Blue Swirl5a053d12009-07-21 11:10:41 +0000302PropertyInfo qdev_prop_uint64 = {
303 .name = "uint64",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600304 .get = get_uint64,
305 .set = set_uint64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000306};
307
308/* --- 64bit hex value --- */
309
310static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
311{
312 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
Kevin Wolf449041d2010-06-18 18:27:03 +0200313 char *end;
Blue Swirl5a053d12009-07-21 11:10:41 +0000314
Paolo Bonzini97aa6e92012-02-09 10:07:38 +0100315 if (str[0] != '0' || str[1] != 'x') {
316 return -EINVAL;
317 }
318
Kevin Wolf449041d2010-06-18 18:27:03 +0200319 *ptr = strtoull(str, &end, 16);
320 if ((*end != '\0') || (end == str)) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100321 return -EINVAL;
Kevin Wolf449041d2010-06-18 18:27:03 +0200322 }
323
Blue Swirl5a053d12009-07-21 11:10:41 +0000324 return 0;
325}
326
327static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
328{
329 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
330 return snprintf(dest, len, "0x%" PRIx64, *ptr);
331}
332
333PropertyInfo qdev_prop_hex64 = {
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100334 .name = "uint64",
335 .legacy_name = "hex64",
Blue Swirl5a053d12009-07-21 11:10:41 +0000336 .parse = parse_hex64,
337 .print = print_hex64,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600338 .get = get_uint64,
339 .set = set_uint64,
Blue Swirl5a053d12009-07-21 11:10:41 +0000340};
341
Gerd Hoffmann59419662009-10-12 17:15:47 +0530342/* --- string --- */
343
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100344static void release_string(Object *obj, const char *name, void *opaque)
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200345{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100346 Property *prop = opaque;
347 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200348}
349
Gerd Hoffmann59419662009-10-12 17:15:47 +0530350static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
351{
352 char **ptr = qdev_get_prop_ptr(dev, prop);
353 if (!*ptr)
354 return snprintf(dest, len, "<null>");
355 return snprintf(dest, len, "\"%s\"", *ptr);
356}
357
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600358static void get_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100359 const char *name, Error **errp)
360{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600361 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100362 Property *prop = opaque;
363 char **ptr = qdev_get_prop_ptr(dev, prop);
364
365 if (!*ptr) {
366 char *str = (char *)"";
367 visit_type_str(v, &str, name, errp);
368 } else {
369 visit_type_str(v, ptr, name, errp);
370 }
371}
372
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600373static void set_string(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100374 const char *name, Error **errp)
375{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600376 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100377 Property *prop = opaque;
378 char **ptr = qdev_get_prop_ptr(dev, prop);
379 Error *local_err = NULL;
380 char *str;
381
382 if (dev->state != DEV_STATE_CREATED) {
383 error_set(errp, QERR_PERMISSION_DENIED);
384 return;
385 }
386
387 visit_type_str(v, &str, name, &local_err);
388 if (local_err) {
389 error_propagate(errp, local_err);
390 return;
391 }
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100392 if (*ptr) {
393 g_free(*ptr);
394 }
395 *ptr = str;
396}
397
Gerd Hoffmann59419662009-10-12 17:15:47 +0530398PropertyInfo qdev_prop_string = {
399 .name = "string",
Gerd Hoffmann59419662009-10-12 17:15:47 +0530400 .print = print_string,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100401 .release = release_string,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100402 .get = get_string,
403 .set = set_string,
Gerd Hoffmann59419662009-10-12 17:15:47 +0530404};
405
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200406/* --- drive --- */
407
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100408static int parse_drive(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200409{
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200410 BlockDriverState *bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200411
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200412 bs = bdrv_find(str);
413 if (bs == NULL)
Markus Armbruster6bf38812010-02-26 15:50:50 +0100414 return -ENOENT;
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200415 if (bdrv_attach_dev(bs, dev) < 0)
Markus Armbruster18846de2010-06-29 16:58:30 +0200416 return -EEXIST;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200417 *ptr = bs;
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200418 return 0;
419}
420
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100421static void release_drive(Object *obj, const char *name, void *opaque)
Markus Armbruster14bafc52010-06-25 08:09:10 +0200422{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100423 DeviceState *dev = DEVICE(obj);
424 Property *prop = opaque;
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200425 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200426
427 if (*ptr) {
Markus Armbrusterfa879d62011-08-03 15:07:40 +0200428 bdrv_detach_dev(*ptr, dev);
Markus Armbrusterf8b6cc02010-05-05 16:36:52 +0200429 blockdev_auto_del(*ptr);
Markus Armbruster14bafc52010-06-25 08:09:10 +0200430 }
431}
432
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100433static const char *print_drive(void *ptr)
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200434{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100435 return bdrv_get_device_name(ptr);
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200436}
437
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100438static void get_pointer(Object *obj, Visitor *v, Property *prop,
439 const char *(*print)(void *ptr),
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100440 const char *name, Error **errp)
441{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600442 DeviceState *dev = DEVICE(obj);
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100443 void **ptr = qdev_get_prop_ptr(dev, prop);
444 char *p;
445
446 p = (char *) (*ptr ? print(*ptr) : "");
447 visit_type_str(v, &p, name, errp);
448}
449
450static void set_pointer(Object *obj, Visitor *v, Property *prop,
451 int (*parse)(DeviceState *dev, const char *str, void **ptr),
452 const char *name, Error **errp)
453{
454 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100455 Error *local_err = NULL;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100456 void **ptr = qdev_get_prop_ptr(dev, prop);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100457 char *str;
458 int ret;
459
460 if (dev->state != DEV_STATE_CREATED) {
461 error_set(errp, QERR_PERMISSION_DENIED);
462 return;
463 }
464
465 visit_type_str(v, &str, name, &local_err);
466 if (local_err) {
467 error_propagate(errp, local_err);
468 return;
469 }
470 if (!*str) {
471 g_free(str);
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +0100472 *ptr = NULL;
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100473 return;
474 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100475 ret = parse(dev, str, ptr);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100476 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
477 g_free(str);
478}
479
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100480static void get_drive(Object *obj, Visitor *v, void *opaque,
481 const char *name, Error **errp)
482{
483 get_pointer(obj, v, opaque, print_drive, name, errp);
484}
485
486static void set_drive(Object *obj, Visitor *v, void *opaque,
487 const char *name, Error **errp)
488{
489 set_pointer(obj, v, opaque, parse_drive, name, errp);
490}
491
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200492PropertyInfo qdev_prop_drive = {
493 .name = "drive",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100494 .get = get_drive,
495 .set = set_drive,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100496 .release = release_drive,
Gerd Hoffmann14b41872009-07-31 12:25:40 +0200497};
498
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200499/* --- character device --- */
500
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100501static int parse_chr(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann06113712009-09-10 10:58:53 +0200502{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100503 CharDriverState *chr = qemu_chr_find(str);
504 if (chr == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100505 return -ENOENT;
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530506 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100507 if (chr->avail_connections < 1) {
Amit Shah2d6c1ef2011-02-10 12:55:20 +0530508 return -EEXIST;
509 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100510 *ptr = chr;
511 --chr->avail_connections;
Gerd Hoffmann06113712009-09-10 10:58:53 +0200512 return 0;
513}
514
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100515static void release_chr(Object *obj, const char *name, void *opaque)
Amit Shaha87f3e82012-01-13 15:29:47 +0530516{
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100517 DeviceState *dev = DEVICE(obj);
518 Property *prop = opaque;
Amit Shaha87f3e82012-01-13 15:29:47 +0530519 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
520
521 if (*ptr) {
522 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
523 }
524}
525
526
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100527static const char *print_chr(void *ptr)
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200528{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100529 CharDriverState *chr = ptr;
Blue Swirlbc19fca2009-08-13 16:26:52 +0000530
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100531 return chr->label ? chr->label : "";
532}
533
534static void get_chr(Object *obj, Visitor *v, void *opaque,
535 const char *name, Error **errp)
536{
537 get_pointer(obj, v, opaque, print_chr, name, errp);
538}
539
540static void set_chr(Object *obj, Visitor *v, void *opaque,
541 const char *name, Error **errp)
542{
543 set_pointer(obj, v, opaque, parse_chr, name, errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200544}
545
546PropertyInfo qdev_prop_chr = {
547 .name = "chr",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100548 .get = get_chr,
549 .set = set_chr,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100550 .release = release_chr,
Gerd Hoffmann313feaa2009-08-03 17:35:18 +0200551};
552
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200553/* --- netdev device --- */
554
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100555static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200556{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100557 VLANClientState *netdev = qemu_find_netdev(str);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200558
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100559 if (netdev == NULL) {
Markus Armbruster6bf38812010-02-26 15:50:50 +0100560 return -ENOENT;
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100561 }
562 if (netdev->peer) {
Markus Armbruster27f3f8a2010-02-26 15:50:51 +0100563 return -EEXIST;
564 }
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100565 *ptr = netdev;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200566 return 0;
567}
568
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100569static const char *print_netdev(void *ptr)
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200570{
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100571 VLANClientState *netdev = ptr;
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200572
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100573 return netdev->name ? netdev->name : "";
574}
575
576static void get_netdev(Object *obj, Visitor *v, void *opaque,
577 const char *name, Error **errp)
578{
579 get_pointer(obj, v, opaque, print_netdev, name, errp);
580}
581
582static void set_netdev(Object *obj, Visitor *v, void *opaque,
583 const char *name, Error **errp)
584{
585 set_pointer(obj, v, opaque, parse_netdev, name, errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200586}
587
588PropertyInfo qdev_prop_netdev = {
589 .name = "netdev",
Paolo Bonzini7b009e52012-02-02 13:01:40 +0100590 .get = get_netdev,
591 .set = set_netdev,
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +0200592};
593
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200594/* --- vlan --- */
595
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200596static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
597{
598 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
599
600 if (*ptr) {
601 return snprintf(dest, len, "%d", (*ptr)->id);
602 } else {
603 return snprintf(dest, len, "<null>");
604 }
605}
606
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600607static void get_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100608 const char *name, Error **errp)
609{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600610 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100611 Property *prop = opaque;
612 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
613 int64_t id;
614
615 id = *ptr ? (*ptr)->id : -1;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600616 visit_type_int64(v, &id, name, errp);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100617}
618
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600619static void set_vlan(Object *obj, Visitor *v, void *opaque,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100620 const char *name, Error **errp)
621{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600622 DeviceState *dev = DEVICE(obj);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100623 Property *prop = opaque;
624 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
625 Error *local_err = NULL;
626 int64_t id;
627 VLANState *vlan;
628
629 if (dev->state != DEV_STATE_CREATED) {
630 error_set(errp, QERR_PERMISSION_DENIED);
631 return;
632 }
633
Michael Rothc08fb2a2012-02-22 12:26:37 -0600634 visit_type_int64(v, &id, name, &local_err);
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100635 if (local_err) {
636 error_propagate(errp, local_err);
637 return;
638 }
639 if (id == -1) {
640 *ptr = NULL;
641 return;
642 }
643 vlan = qemu_find_vlan(id, 1);
644 if (!vlan) {
645 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
646 name, prop->info->name);
647 return;
648 }
649 *ptr = vlan;
650}
651
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200652PropertyInfo qdev_prop_vlan = {
653 .name = "vlan",
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200654 .print = print_vlan,
Paolo Bonzini80e555c2011-12-18 17:05:09 +0100655 .get = get_vlan,
656 .set = set_vlan,
Gerd Hoffmann851bec02009-10-21 15:25:25 +0200657};
658
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200659/* --- pointer --- */
660
Markus Armbruster036f7162010-02-19 11:47:06 +0100661/* Not a proper property, just for dirty hacks. TODO Remove it! */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200662PropertyInfo qdev_prop_ptr = {
663 .name = "ptr",
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200664};
665
666/* --- mac address --- */
667
668/*
669 * accepted syntax versions:
670 * 01:02:03:04:05:06
671 * 01-02-03-04-05-06
672 */
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100673static void get_mac(Object *obj, Visitor *v, void *opaque,
674 const char *name, Error **errp)
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200675{
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100676 DeviceState *dev = DEVICE(obj);
677 Property *prop = opaque;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200678 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100679 char buffer[2 * 6 + 5 + 1];
680 char *p = buffer;
681
682 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
683 mac->a[0], mac->a[1], mac->a[2],
684 mac->a[3], mac->a[4], mac->a[5]);
685
686 visit_type_str(v, &p, name, errp);
687}
688
689static void set_mac(Object *obj, Visitor *v, void *opaque,
690 const char *name, Error **errp)
691{
692 DeviceState *dev = DEVICE(obj);
693 Property *prop = opaque;
694 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
695 Error *local_err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200696 int i, pos;
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100697 char *str, *p;
698
699 if (dev->state != DEV_STATE_CREATED) {
700 error_set(errp, QERR_PERMISSION_DENIED);
701 return;
702 }
703
704 visit_type_str(v, &str, name, &local_err);
705 if (local_err) {
706 error_propagate(errp, local_err);
707 return;
708 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200709
710 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
Christoph Egger88e150a2009-07-17 17:48:02 +0000711 if (!qemu_isxdigit(str[pos]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100712 goto inval;
Christoph Egger88e150a2009-07-17 17:48:02 +0000713 if (!qemu_isxdigit(str[pos+1]))
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100714 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200715 if (i == 5) {
716 if (str[pos+2] != '\0')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100717 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200718 } else {
719 if (str[pos+2] != ':' && str[pos+2] != '-')
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100720 goto inval;
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200721 }
722 mac->a[i] = strtol(str+pos, &p, 16);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200723 }
dunrong huanga3400462012-05-18 19:14:13 +0800724 g_free(str);
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100725 return;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200726
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100727inval:
728 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
dunrong huanga3400462012-05-18 19:14:13 +0800729 g_free(str);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200730}
731
732PropertyInfo qdev_prop_macaddr = {
Gerd Hoffmann1503fff2009-10-21 15:25:23 +0200733 .name = "macaddr",
Paolo Bonzinie39e5d62012-02-02 17:08:47 +0100734 .get = get_mac,
735 .set = set_mac,
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200736};
737
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100738
739/* --- lost tick policy --- */
740
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100741static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
742 [LOST_TICK_DISCARD] = "discard",
743 [LOST_TICK_DELAY] = "delay",
744 [LOST_TICK_MERGE] = "merge",
745 [LOST_TICK_SLEW] = "slew",
746 [LOST_TICK_MAX] = NULL,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100747};
748
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100749QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100750
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100751static void get_enum(Object *obj, Visitor *v, void *opaque,
752 const char *name, Error **errp)
753{
754 DeviceState *dev = DEVICE(obj);
755 Property *prop = opaque;
756 int *ptr = qdev_get_prop_ptr(dev, prop);
757
758 visit_type_enum(v, ptr, prop->info->enum_table,
759 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100760}
761
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100762static void set_enum(Object *obj, Visitor *v, void *opaque,
763 const char *name, Error **errp)
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100764{
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100765 DeviceState *dev = DEVICE(obj);
766 Property *prop = opaque;
767 int *ptr = qdev_get_prop_ptr(dev, prop);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100768
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100769 if (dev->state != DEV_STATE_CREATED) {
770 error_set(errp, QERR_PERMISSION_DENIED);
771 return;
772 }
773
774 visit_type_enum(v, ptr, prop->info->enum_table,
775 prop->info->name, prop->name, errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100776}
777
778PropertyInfo qdev_prop_losttickpolicy = {
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100779 .name = "LostTickPolicy",
Paolo Bonzini1ce05122012-02-02 22:09:44 +0100780 .enum_table = lost_tick_policy_table,
781 .get = get_enum,
782 .set = set_enum,
Jan Kiszka4e4fa392012-01-23 20:15:11 +0100783};
784
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200785/* --- pci address --- */
786
787/*
788 * bus-local address, i.e. "$slot" or "$slot.$fn"
789 */
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100790static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
791 const char *name, Error **errp)
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200792{
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100793 DeviceState *dev = DEVICE(obj);
794 Property *prop = opaque;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200795 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200796 unsigned int slot, fn, n;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100797 Error *local_err = NULL;
dunrong huanga3400462012-05-18 19:14:13 +0800798 char *str;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100799
800 if (dev->state != DEV_STATE_CREATED) {
801 error_set(errp, QERR_PERMISSION_DENIED);
802 return;
803 }
804
805 visit_type_str(v, &str, name, &local_err);
806 if (local_err) {
Stefan Weil5c878002012-04-28 02:32:42 +0000807 error_free(local_err);
Paolo Bonzini27712df2012-04-12 15:32:26 +0200808 local_err = NULL;
809 visit_type_int32(v, &value, name, &local_err);
810 if (local_err) {
811 error_propagate(errp, local_err);
812 } else if (value < -1 || value > 255) {
813 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
814 "pci_devfn");
815 } else {
816 *ptr = value;
817 }
818 return;
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100819 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200820
821 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
822 fn = 0;
823 if (sscanf(str, "%x%n", &slot, &n) != 1) {
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100824 goto invalid;
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200825 }
826 }
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100827 if (str[n] != '\0' || fn > 7 || slot > 31) {
828 goto invalid;
829 }
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200830 *ptr = slot << 3 | fn;
dunrong huanga3400462012-05-18 19:14:13 +0800831 g_free(str);
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100832 return;
833
834invalid:
835 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
dunrong huanga3400462012-05-18 19:14:13 +0800836 g_free(str);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200837}
838
839static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
840{
Michael Roth09f1bbc2012-03-04 13:38:27 -0600841 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200842
Blue Swirl73538c32009-08-28 19:12:16 +0000843 if (*ptr == -1) {
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200844 return snprintf(dest, len, "<unset>");
845 } else {
846 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
847 }
848}
849
850PropertyInfo qdev_prop_pci_devfn = {
Paolo Bonzinib4032982012-02-02 17:12:19 +0100851 .name = "int32",
852 .legacy_name = "pci-devfn",
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200853 .print = print_pci_devfn,
Paolo Bonzinib4032982012-02-02 17:12:19 +0100854 .get = get_int32,
Paolo Bonzini768a9eb2012-02-09 09:53:32 +0100855 .set = set_pci_devfn,
Gerd Hoffmann05cb5fe2009-07-15 13:59:22 +0200856};
857
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000858/* --- blocksize --- */
859
860static void set_blocksize(Object *obj, Visitor *v, void *opaque,
861 const char *name, Error **errp)
862{
863 DeviceState *dev = DEVICE(obj);
864 Property *prop = opaque;
Michael Rothc08fb2a2012-02-22 12:26:37 -0600865 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000866 Error *local_err = NULL;
Paolo Bonzini27712df2012-04-12 15:32:26 +0200867 const int64_t min = 512;
868 const int64_t max = 32768;
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000869
870 if (dev->state != DEV_STATE_CREATED) {
871 error_set(errp, QERR_PERMISSION_DENIED);
872 return;
873 }
874
Michael Rothc08fb2a2012-02-22 12:26:37 -0600875 visit_type_uint16(v, &value, name, &local_err);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000876 if (local_err) {
877 error_propagate(errp, local_err);
878 return;
879 }
Paolo Bonzini27712df2012-04-12 15:32:26 +0200880 if (value < min || value > max) {
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000881 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
Paolo Bonzini27712df2012-04-12 15:32:26 +0200882 dev->id?:"", name, (int64_t)value, min, max);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000883 return;
884 }
885
886 /* We rely on power-of-2 blocksizes for bitmasks */
887 if ((value & (value - 1)) != 0) {
888 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
Michael Rothc08fb2a2012-02-22 12:26:37 -0600889 dev->id?:"", name, (int64_t)value);
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000890 return;
891 }
892
893 *ptr = value;
894}
895
896PropertyInfo qdev_prop_blocksize = {
897 .name = "blocksize",
Michael Rothc08fb2a2012-02-22 12:26:37 -0600898 .get = get_uint16,
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000899 .set = set_blocksize,
Stefan Hajnoczi02fda012012-03-14 15:57:05 +0000900};
901
Anthony PERARD679042f2012-06-21 15:36:23 +0000902/* --- pci host address --- */
903
904static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
905 const char *name, Error **errp)
906{
907 DeviceState *dev = DEVICE(obj);
908 Property *prop = opaque;
909 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
910 char buffer[] = "xxxx:xx:xx.x";
911 char *p = buffer;
912 int rc = 0;
913
914 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
915 addr->domain, addr->bus, addr->slot, addr->function);
916 assert(rc == sizeof(buffer) - 1);
917
918 visit_type_str(v, &p, name, errp);
919}
920
921/*
922 * Parse [<domain>:]<bus>:<slot>.<func>
923 * if <domain> is not supplied, it's assumed to be 0.
924 */
925static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
926 const char *name, Error **errp)
927{
928 DeviceState *dev = DEVICE(obj);
929 Property *prop = opaque;
930 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
931 Error *local_err = NULL;
932 char *str, *p;
933 char *e;
934 unsigned long val;
935 unsigned long dom = 0, bus = 0;
936 unsigned int slot = 0, func = 0;
937
938 if (dev->state != DEV_STATE_CREATED) {
939 error_set(errp, QERR_PERMISSION_DENIED);
940 return;
941 }
942
943 visit_type_str(v, &str, name, &local_err);
944 if (local_err) {
945 error_propagate(errp, local_err);
946 return;
947 }
948
949 p = str;
950 val = strtoul(p, &e, 16);
951 if (e == p || *e != ':') {
952 goto inval;
953 }
954 bus = val;
955
956 p = e + 1;
957 val = strtoul(p, &e, 16);
958 if (e == p) {
959 goto inval;
960 }
961 if (*e == ':') {
962 dom = bus;
963 bus = val;
964 p = e + 1;
965 val = strtoul(p, &e, 16);
966 if (e == p) {
967 goto inval;
968 }
969 }
970 slot = val;
971
972 if (*e != '.') {
973 goto inval;
974 }
975 p = e + 1;
976 val = strtoul(p, &e, 10);
977 if (e == p) {
978 goto inval;
979 }
980 func = val;
981
982 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
983 goto inval;
984 }
985
986 if (*e) {
987 goto inval;
988 }
989
990 addr->domain = dom;
991 addr->bus = bus;
992 addr->slot = slot;
993 addr->function = func;
994
995 g_free(str);
996 return;
997
998inval:
999 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1000 g_free(str);
1001}
1002
1003PropertyInfo qdev_prop_pci_host_devaddr = {
1004 .name = "pci-host-devaddr",
1005 .get = get_pci_host_devaddr,
1006 .set = set_pci_host_devaddr,
1007};
1008
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001009/* --- public helpers --- */
1010
1011static Property *qdev_prop_walk(Property *props, const char *name)
1012{
1013 if (!props)
1014 return NULL;
1015 while (props->name) {
1016 if (strcmp(props->name, name) == 0)
1017 return props;
1018 props++;
1019 }
1020 return NULL;
1021}
1022
1023static Property *qdev_prop_find(DeviceState *dev, const char *name)
1024{
Paolo Bonzinibce54472012-03-28 18:12:47 +02001025 ObjectClass *class;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001026 Property *prop;
1027
1028 /* device properties */
Paolo Bonzinibce54472012-03-28 18:12:47 +02001029 class = object_get_class(OBJECT(dev));
1030 do {
1031 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
1032 if (prop) {
1033 return prop;
1034 }
1035 class = object_class_get_parent(class);
1036 } while (class != object_class_by_name(TYPE_DEVICE));
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001037
1038 return NULL;
1039}
1040
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001041void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1042 Property *prop, const char *value)
1043{
1044 switch (ret) {
1045 case -EEXIST:
1046 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001047 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001048 break;
1049 default:
1050 case -EINVAL:
1051 error_set(errp, QERR_PROPERTY_VALUE_BAD,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001052 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001053 break;
1054 case -ENOENT:
1055 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001056 object_get_typename(OBJECT(dev)), prop->name, value);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001057 break;
1058 case 0:
1059 break;
1060 }
1061}
1062
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001063int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1064{
Paolo Bonzinid8229792012-02-02 09:47:13 +01001065 char *legacy_name;
1066 Error *err = NULL;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001067
Paolo Bonzinid8229792012-02-02 09:47:13 +01001068 legacy_name = g_strdup_printf("legacy-%s", name);
1069 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
Paolo Bonzini0c96e282012-02-09 10:12:08 +01001070 object_property_parse(OBJECT(dev), value, legacy_name, &err);
Paolo Bonzinid8229792012-02-02 09:47:13 +01001071 } else {
Paolo Bonzini0c96e282012-02-09 10:12:08 +01001072 object_property_parse(OBJECT(dev), value, name, &err);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001073 }
Paolo Bonzinid8229792012-02-02 09:47:13 +01001074 g_free(legacy_name);
1075
1076 if (err) {
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001077 qerror_report_err(err);
1078 error_free(err);
Gerd Hoffmann9ef5c4b2009-12-16 14:22:11 +01001079 return -1;
1080 }
1081 return 0;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001082}
1083
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001084void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1085{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001086 Error *errp = NULL;
1087 object_property_set_bool(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001088 assert_no_error(errp);
Isaku Yamahataf4594a32010-06-23 16:15:29 +09001089}
1090
Juan Quintelac7cc1722009-09-29 22:48:25 +02001091void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1092{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001093 Error *errp = NULL;
1094 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001095 assert_no_error(errp);
Juan Quintelac7cc1722009-09-29 22:48:25 +02001096}
1097
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001098void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1099{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001100 Error *errp = NULL;
1101 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001102 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001103}
1104
1105void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1106{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001107 Error *errp = NULL;
1108 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001109 assert_no_error(errp);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001110}
1111
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001112void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1113{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001114 Error *errp = NULL;
1115 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001116 assert_no_error(errp);
Gerd Hoffmann316940b2009-09-10 11:43:25 +02001117}
1118
Blue Swirl5a053d12009-07-21 11:10:41 +00001119void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1120{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001121 Error *errp = NULL;
1122 object_property_set_int(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001123 assert_no_error(errp);
Blue Swirl5a053d12009-07-21 11:10:41 +00001124}
1125
Markus Armbrustercc984672010-06-01 20:32:30 +02001126void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1127{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001128 Error *errp = NULL;
1129 object_property_set_str(OBJECT(dev), value, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001130 assert_no_error(errp);
Markus Armbrustercc984672010-06-01 20:32:30 +02001131}
1132
Markus Armbruster18846de2010-06-29 16:58:30 +02001133int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001134{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001135 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001136 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1137 object_property_set_str(OBJECT(dev), bdrv_name,
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001138 name, &errp);
1139 if (errp) {
1140 qerror_report_err(errp);
1141 error_free(errp);
Markus Armbruster18846de2010-06-29 16:58:30 +02001142 return -1;
1143 }
Markus Armbruster18846de2010-06-29 16:58:30 +02001144 return 0;
Gerd Hoffmann14b41872009-07-31 12:25:40 +02001145}
1146
Markus Armbruster18846de2010-06-29 16:58:30 +02001147void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1148{
1149 if (qdev_prop_set_drive(dev, name, value) < 0) {
1150 exit(1);
1151 }
1152}
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001153void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1154{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001155 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001156 assert(!value || value->label);
1157 object_property_set_str(OBJECT(dev),
1158 value ? value->label : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001159 assert_no_error(errp);
Gerd Hoffmann313feaa2009-08-03 17:35:18 +02001160}
1161
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001162void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1163{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001164 Error *errp = NULL;
Paolo Bonzini0a54a0c2012-02-14 10:19:52 +01001165 assert(!value || value->name);
1166 object_property_set_str(OBJECT(dev),
1167 value ? value->name : "", name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001168 assert_no_error(errp);
Gerd Hoffmann2ef924b2009-10-21 15:25:24 +02001169}
1170
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001171void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1172{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001173 Error *errp = NULL;
1174 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001175 assert_no_error(errp);
Gerd Hoffmann851bec02009-10-21 15:25:25 +02001176}
1177
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001178void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1179{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001180 Error *errp = NULL;
1181 char str[2 * 6 + 5 + 1];
1182 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1183 value[0], value[1], value[2], value[3], value[4], value[5]);
1184
1185 object_property_set_str(OBJECT(dev), str, name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001186 assert_no_error(errp);
Gerd Hoffmann1503fff2009-10-21 15:25:23 +02001187}
1188
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001189void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001190{
Paolo Bonzini9b170e62012-02-02 12:51:44 +01001191 Property *prop;
1192 Error *errp = NULL;
1193
1194 prop = qdev_prop_find(dev, name);
1195 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1196 name, &errp);
Paolo Bonzini59f971d2012-02-14 10:19:53 +01001197 assert_no_error(errp);
Jan Kiszka4e4fa392012-01-23 20:15:11 +01001198}
1199
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001200void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1201{
Paolo Bonzini7a7aae22012-02-02 16:58:31 +01001202 Property *prop;
1203 void **ptr;
1204
1205 prop = qdev_prop_find(dev, name);
1206 assert(prop && prop->info == &qdev_prop_ptr);
1207 ptr = qdev_get_prop_ptr(dev, prop);
1208 *ptr = value;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001209}
1210
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001211static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001212
Kevin Wolf25920d62010-03-15 17:01:24 +01001213static void qdev_prop_register_global(GlobalProperty *prop)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001214{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001215 QTAILQ_INSERT_TAIL(&global_props, prop, next);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001216}
1217
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001218void qdev_prop_register_global_list(GlobalProperty *props)
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001219{
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001220 int i;
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001221
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001222 for (i = 0; props[i].driver != NULL; i++) {
1223 qdev_prop_register_global(props+i);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001224 }
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001225}
1226
1227void qdev_prop_set_globals(DeviceState *dev)
1228{
Paolo Bonzinibce54472012-03-28 18:12:47 +02001229 ObjectClass *class = object_get_class(OBJECT(dev));
Gerd Hoffmann458fb672009-12-08 13:11:33 +01001230
Paolo Bonzinibce54472012-03-28 18:12:47 +02001231 do {
1232 GlobalProperty *prop;
1233 QTAILQ_FOREACH(prop, &global_props, next) {
1234 if (strcmp(object_class_get_name(class), prop->driver) != 0) {
1235 continue;
1236 }
1237 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1238 exit(1);
1239 }
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001240 }
Paolo Bonzinibce54472012-03-28 18:12:47 +02001241 class = object_class_get_parent(class);
1242 } while (class);
Gerd Hoffmannb6b61142009-07-15 13:48:21 +02001243}
Kevin Wolf25920d62010-03-15 17:01:24 +01001244
1245static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1246{
1247 GlobalProperty *g;
1248
Anthony Liguori7267c092011-08-20 22:09:37 -05001249 g = g_malloc0(sizeof(*g));
Kevin Wolf25920d62010-03-15 17:01:24 +01001250 g->driver = qemu_opt_get(opts, "driver");
1251 g->property = qemu_opt_get(opts, "property");
1252 g->value = qemu_opt_get(opts, "value");
1253 qdev_prop_register_global(g);
1254 return 0;
1255}
1256
1257void qemu_add_globals(void)
1258{
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001259 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
Kevin Wolf25920d62010-03-15 17:01:24 +01001260}