Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ a8a358bf

History | View | Annotate | Download (10.1 kB)

1
#include "sysemu.h"
2
#include "qdev.h"
3

    
4
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
5
{
6
    void *ptr = dev;
7
    ptr += prop->offset;
8
    return ptr;
9
}
10

    
11
/* --- 16bit integer --- */
12

    
13
static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
14
{
15
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
16
    const char *fmt;
17

    
18
    /* accept both hex and decimal */
19
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16;
20
    if (sscanf(str, fmt, ptr) != 1)
21
        return -1;
22
    return 0;
23
}
24

    
25
static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
26
{
27
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
28
    return snprintf(dest, len, "%" PRIu16, *ptr);
29
}
30

    
31
PropertyInfo qdev_prop_uint16 = {
32
    .name  = "uint16",
33
    .type  = PROP_TYPE_UINT16,
34
    .size  = sizeof(uint16_t),
35
    .parse = parse_uint16,
36
    .print = print_uint16,
37
};
38

    
39
/* --- 32bit integer --- */
40

    
41
static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
42
{
43
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
44
    const char *fmt;
45

    
46
    /* accept both hex and decimal */
47
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32;
48
    if (sscanf(str, fmt, ptr) != 1)
49
        return -1;
50
    return 0;
51
}
52

    
53
static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
54
{
55
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
56
    return snprintf(dest, len, "%" PRIu32, *ptr);
57
}
58

    
59
PropertyInfo qdev_prop_uint32 = {
60
    .name  = "uint32",
61
    .type  = PROP_TYPE_UINT32,
62
    .size  = sizeof(uint32_t),
63
    .parse = parse_uint32,
64
    .print = print_uint32,
65
};
66

    
67
/* --- 32bit hex value --- */
68

    
69
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
70
{
71
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
72

    
73
    if (sscanf(str, "%" PRIx32, ptr) != 1)
74
        return -1;
75
    return 0;
76
}
77

    
78
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
79
{
80
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
81
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
82
}
83

    
84
PropertyInfo qdev_prop_hex32 = {
85
    .name  = "hex32",
86
    .type  = PROP_TYPE_UINT32,
87
    .size  = sizeof(uint32_t),
88
    .parse = parse_hex32,
89
    .print = print_hex32,
90
};
91

    
92
/* --- 64bit integer --- */
93

    
94
static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
95
{
96
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
97
    const char *fmt;
98

    
99
    /* accept both hex and decimal */
100
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64;
101
    if (sscanf(str, fmt, ptr) != 1)
102
        return -1;
103
    return 0;
104
}
105

    
106
static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
107
{
108
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
109
    return snprintf(dest, len, "%" PRIu64, *ptr);
110
}
111

    
112
PropertyInfo qdev_prop_uint64 = {
113
    .name  = "uint64",
114
    .type  = PROP_TYPE_UINT64,
115
    .size  = sizeof(uint64_t),
116
    .parse = parse_uint64,
117
    .print = print_uint64,
118
};
119

    
120
/* --- 64bit hex value --- */
121

    
122
static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
123
{
124
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
125

    
126
    if (sscanf(str, "%" PRIx64, ptr) != 1)
127
        return -1;
128
    return 0;
129
}
130

    
131
static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
132
{
133
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
134
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
135
}
136

    
137
PropertyInfo qdev_prop_hex64 = {
138
    .name  = "hex64",
139
    .type  = PROP_TYPE_UINT64,
140
    .size  = sizeof(uint64_t),
141
    .parse = parse_hex64,
142
    .print = print_hex64,
143
};
144

    
145
/* --- drive --- */
146

    
147
static int parse_drive(DeviceState *dev, Property *prop, const char *str)
148
{
149
    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
150

    
151
    *ptr = drive_get_by_id(str);
152
    if (*ptr == NULL)
153
        return -1;
154
    return 0;
155
}
156

    
157
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
158
{
159
    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
160
    return snprintf(dest, len, "%s", (*ptr)->id);
161
}
162

    
163
PropertyInfo qdev_prop_drive = {
164
    .name  = "drive",
165
    .type  = PROP_TYPE_DRIVE,
166
    .size  = sizeof(DriveInfo*),
167
    .parse = parse_drive,
168
    .print = print_drive,
169
};
170

    
171
/* --- character device --- */
172

    
173
static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
174
{
175
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
176

    
177
    if (*ptr && (*ptr)->label) {
178
        return snprintf(dest, len, "%s", (*ptr)->label);
179
    } else {
180
        return snprintf(dest, len, "<null>");
181
    }
182
}
183

    
184
PropertyInfo qdev_prop_chr = {
185
    .name  = "chr",
186
    .type  = PROP_TYPE_CHR,
187
    .size  = sizeof(CharDriverState*),
188
    .print = print_chr,
189
};
190

    
191
/* --- pointer --- */
192

    
193
static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
194
{
195
    void **ptr = qdev_get_prop_ptr(dev, prop);
196
    return snprintf(dest, len, "<%p>", *ptr);
197
}
198

    
199
PropertyInfo qdev_prop_ptr = {
200
    .name  = "ptr",
201
    .type  = PROP_TYPE_PTR,
202
    .size  = sizeof(void*),
203
    .print = print_ptr,
204
};
205

    
206
/* --- mac address --- */
207

    
208
/*
209
 * accepted syntax versions:
210
 *   01:02:03:04:05:06
211
 *   01-02-03-04-05-06
212
 */
213
static int parse_mac(DeviceState *dev, Property *prop, const char *str)
214
{
215
    uint8_t *mac = qdev_get_prop_ptr(dev, prop);
216
    int i, pos;
217
    char *p;
218

    
219
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
220
        if (!qemu_isxdigit(str[pos]))
221
            return -1;
222
        if (!qemu_isxdigit(str[pos+1]))
223
            return -1;
224
        if (i == 5 && str[pos+2] != '\0')
225
            return -1;
226
        if (str[pos+2] != ':' && str[pos+2] != '-')
227
            return -1;
228
        mac[i] = strtol(str+pos, &p, 16);
229
    }
230
    return 0;
231
}
232

    
233
static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
234
{
235
    uint8_t *mac = qdev_get_prop_ptr(dev, prop);
236
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
237
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
238
}
239

    
240
PropertyInfo qdev_prop_macaddr = {
241
    .name  = "mac-addr",
242
    .type  = PROP_TYPE_MACADDR,
243
    .size  = 6,
244
    .parse = parse_mac,
245
    .print = print_mac,
246
};
247

    
248
/* --- pci address --- */
249

    
250
/*
251
 * bus-local address, i.e. "$slot" or "$slot.$fn"
252
 */
253
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
254
{
255
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
256
    unsigned int slot, fn, n;
257

    
258
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
259
        fn = 0;
260
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
261
            return -1;
262
        }
263
    }
264
    if (str[n] != '\0')
265
        return -1;
266
    if (fn > 7)
267
        return -1;
268
    *ptr = slot << 3 | fn;
269
    return 0;
270
}
271

    
272
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
273
{
274
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
275

    
276
    if (-1 == *ptr) {
277
        return snprintf(dest, len, "<unset>");
278
    } else {
279
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
280
    }
281
}
282

    
283
PropertyInfo qdev_prop_pci_devfn = {
284
    .name  = "pci-devfn",
285
    .type  = PROP_TYPE_UINT32,
286
    .size  = sizeof(uint32_t),
287
    .parse = parse_pci_devfn,
288
    .print = print_pci_devfn,
289
};
290

    
291
/* --- public helpers --- */
292

    
293
static Property *qdev_prop_walk(Property *props, const char *name)
294
{
295
    if (!props)
296
        return NULL;
297
    while (props->name) {
298
        if (strcmp(props->name, name) == 0)
299
            return props;
300
        props++;
301
    }
302
    return NULL;
303
}
304

    
305
static Property *qdev_prop_find(DeviceState *dev, const char *name)
306
{
307
    Property *prop;
308

    
309
    /* device properties */
310
    prop = qdev_prop_walk(dev->info->props, name);
311
    if (prop)
312
        return prop;
313

    
314
    /* bus properties */
315
    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
316
    if (prop)
317
        return prop;
318

    
319
    return NULL;
320
}
321

    
322
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
323
{
324
    Property *prop;
325

    
326
    prop = qdev_prop_find(dev, name);
327
    if (!prop) {
328
        fprintf(stderr, "property \"%s.%s\" not found\n",
329
                dev->info->name, name);
330
        return -1;
331
    }
332
    if (!prop->info->parse) {
333
        fprintf(stderr, "property \"%s.%s\" has no parser\n",
334
                dev->info->name, name);
335
        return -1;
336
    }
337
    return prop->info->parse(dev, prop, value);
338
}
339

    
340
void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
341
{
342
    Property *prop;
343
    void *dst;
344

    
345
    prop = qdev_prop_find(dev, name);
346
    if (!prop) {
347
        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
348
                __FUNCTION__, dev->info->name, name);
349
        abort();
350
    }
351
    if (prop->info->type != type) {
352
        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
353
                __FUNCTION__, dev->info->name, name);
354
        abort();
355
    }
356
    dst = qdev_get_prop_ptr(dev, prop);
357
    memcpy(dst, src, prop->info->size);
358
}
359

    
360
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
361
{
362
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
363
}
364

    
365
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
366
{
367
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
368
}
369

    
370
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
371
{
372
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
373
}
374

    
375
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
376
{
377
    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
378
}
379

    
380
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
381
{
382
    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
383
}
384

    
385
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
386
{
387
    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
388
}
389

    
390
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
391
{
392
    char *dst;
393

    
394
    if (!props)
395
        return;
396
    while (props->name) {
397
        if (props->defval) {
398
            dst = qdev_get_prop_ptr(dev, props);
399
            memcpy(dst, props->defval, props->info->size);
400
        }
401
        props++;
402
    }
403
}
404

    
405
static CompatProperty *compat_props;
406

    
407
void qdev_prop_register_compat(CompatProperty *props)
408
{
409
    compat_props = props;
410
}
411

    
412
void qdev_prop_set_compat(DeviceState *dev)
413
{
414
    CompatProperty *prop;
415

    
416
    if (!compat_props) {
417
        return;
418
    }
419
    for (prop = compat_props; prop->driver != NULL; prop++) {
420
        if (strcmp(dev->info->name, prop->driver) != 0) {
421
            continue;
422
        }
423
        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
424
            abort();
425
        }
426
    }
427
}