]> Git Repo - qemu.git/blob - hw/qdev-properties-system.c
PPC: Fix dma interrupt
[qemu.git] / hw / qdev-properties-system.c
1 /*
2  * qdev property parsing and global properties
3  * (parts specific for qemu-system-*)
4  *
5  * This file is based on code from hw/qdev-properties.c from
6  * commit 074a86fccd185616469dfcdc0e157f438aebba18,
7  * Copyright (c) Gerd Hoffmann <[email protected]> and other contributors.
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12
13 #include "net/net.h"
14 #include "qdev.h"
15 #include "qapi/qmp/qerror.h"
16 #include "sysemu/blockdev.h"
17 #include "hw/block-common.h"
18 #include "net/hub.h"
19 #include "qapi/visitor.h"
20 #include "char/char.h"
21
22 static void get_pointer(Object *obj, Visitor *v, Property *prop,
23                         const char *(*print)(void *ptr),
24                         const char *name, Error **errp)
25 {
26     DeviceState *dev = DEVICE(obj);
27     void **ptr = qdev_get_prop_ptr(dev, prop);
28     char *p;
29
30     p = (char *) (*ptr ? print(*ptr) : "");
31     visit_type_str(v, &p, name, errp);
32 }
33
34 static void set_pointer(Object *obj, Visitor *v, Property *prop,
35                         int (*parse)(DeviceState *dev, const char *str,
36                                      void **ptr),
37                         const char *name, Error **errp)
38 {
39     DeviceState *dev = DEVICE(obj);
40     Error *local_err = NULL;
41     void **ptr = qdev_get_prop_ptr(dev, prop);
42     char *str;
43     int ret;
44
45     if (dev->realized) {
46         error_set(errp, QERR_PERMISSION_DENIED);
47         return;
48     }
49
50     visit_type_str(v, &str, name, &local_err);
51     if (local_err) {
52         error_propagate(errp, local_err);
53         return;
54     }
55     if (!*str) {
56         g_free(str);
57         *ptr = NULL;
58         return;
59     }
60     ret = parse(dev, str, ptr);
61     error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
62     g_free(str);
63 }
64
65 /* --- drive --- */
66
67 static int parse_drive(DeviceState *dev, const char *str, void **ptr)
68 {
69     BlockDriverState *bs;
70
71     bs = bdrv_find(str);
72     if (bs == NULL) {
73         return -ENOENT;
74     }
75     if (bdrv_attach_dev(bs, dev) < 0) {
76         return -EEXIST;
77     }
78     *ptr = bs;
79     return 0;
80 }
81
82 static void release_drive(Object *obj, const char *name, void *opaque)
83 {
84     DeviceState *dev = DEVICE(obj);
85     Property *prop = opaque;
86     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
87
88     if (*ptr) {
89         bdrv_detach_dev(*ptr, dev);
90         blockdev_auto_del(*ptr);
91     }
92 }
93
94 static const char *print_drive(void *ptr)
95 {
96     return bdrv_get_device_name(ptr);
97 }
98
99 static void get_drive(Object *obj, Visitor *v, void *opaque,
100                       const char *name, Error **errp)
101 {
102     get_pointer(obj, v, opaque, print_drive, name, errp);
103 }
104
105 static void set_drive(Object *obj, Visitor *v, void *opaque,
106                       const char *name, Error **errp)
107 {
108     set_pointer(obj, v, opaque, parse_drive, name, errp);
109 }
110
111 PropertyInfo qdev_prop_drive = {
112     .name  = "drive",
113     .get   = get_drive,
114     .set   = set_drive,
115     .release = release_drive,
116 };
117
118 /* --- character device --- */
119
120 static int parse_chr(DeviceState *dev, const char *str, void **ptr)
121 {
122     CharDriverState *chr = qemu_chr_find(str);
123     if (chr == NULL) {
124         return -ENOENT;
125     }
126     if (chr->avail_connections < 1) {
127         return -EEXIST;
128     }
129     *ptr = chr;
130     --chr->avail_connections;
131     return 0;
132 }
133
134 static void release_chr(Object *obj, const char *name, void *opaque)
135 {
136     DeviceState *dev = DEVICE(obj);
137     Property *prop = opaque;
138     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
139
140     if (*ptr) {
141         qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
142     }
143 }
144
145
146 static const char *print_chr(void *ptr)
147 {
148     CharDriverState *chr = ptr;
149
150     return chr->label ? chr->label : "";
151 }
152
153 static void get_chr(Object *obj, Visitor *v, void *opaque,
154                     const char *name, Error **errp)
155 {
156     get_pointer(obj, v, opaque, print_chr, name, errp);
157 }
158
159 static void set_chr(Object *obj, Visitor *v, void *opaque,
160                     const char *name, Error **errp)
161 {
162     set_pointer(obj, v, opaque, parse_chr, name, errp);
163 }
164
165 PropertyInfo qdev_prop_chr = {
166     .name  = "chr",
167     .get   = get_chr,
168     .set   = set_chr,
169     .release = release_chr,
170 };
171
172 /* --- netdev device --- */
173
174 static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
175 {
176     NICPeers *peers_ptr = (NICPeers *)ptr;
177     NICConf *conf = container_of(peers_ptr, NICConf, peers);
178     NetClientState **ncs = peers_ptr->ncs;
179     NetClientState *peers[MAX_QUEUE_NUM];
180     int queues, i = 0;
181     int ret;
182
183     queues = qemu_find_net_clients_except(str, peers,
184                                           NET_CLIENT_OPTIONS_KIND_NIC,
185                                           MAX_QUEUE_NUM);
186     if (queues == 0) {
187         ret = -ENOENT;
188         goto err;
189     }
190
191     if (queues > MAX_QUEUE_NUM) {
192         ret = -E2BIG;
193         goto err;
194     }
195
196     for (i = 0; i < queues; i++) {
197         if (peers[i] == NULL) {
198             ret = -ENOENT;
199             goto err;
200         }
201
202         if (peers[i]->peer) {
203             ret = -EEXIST;
204             goto err;
205         }
206
207         ncs[i] = peers[i];
208         ncs[i]->queue_index = i;
209     }
210
211     conf->queues = queues;
212
213     return 0;
214
215 err:
216     return ret;
217 }
218
219 static const char *print_netdev(void *ptr)
220 {
221     NetClientState *netdev = ptr;
222
223     return netdev->name ? netdev->name : "";
224 }
225
226 static void get_netdev(Object *obj, Visitor *v, void *opaque,
227                        const char *name, Error **errp)
228 {
229     get_pointer(obj, v, opaque, print_netdev, name, errp);
230 }
231
232 static void set_netdev(Object *obj, Visitor *v, void *opaque,
233                        const char *name, Error **errp)
234 {
235     set_pointer(obj, v, opaque, parse_netdev, name, errp);
236 }
237
238 PropertyInfo qdev_prop_netdev = {
239     .name  = "netdev",
240     .get   = get_netdev,
241     .set   = set_netdev,
242 };
243
244 /* --- vlan --- */
245
246 static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
247 {
248     NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
249
250     if (*ptr) {
251         int id;
252         if (!net_hub_id_for_client(*ptr, &id)) {
253             return snprintf(dest, len, "%d", id);
254         }
255     }
256
257     return snprintf(dest, len, "<null>");
258 }
259
260 static void get_vlan(Object *obj, Visitor *v, void *opaque,
261                      const char *name, Error **errp)
262 {
263     DeviceState *dev = DEVICE(obj);
264     Property *prop = opaque;
265     NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
266     int32_t id = -1;
267
268     if (*ptr) {
269         int hub_id;
270         if (!net_hub_id_for_client(*ptr, &hub_id)) {
271             id = hub_id;
272         }
273     }
274
275     visit_type_int32(v, &id, name, errp);
276 }
277
278 static void set_vlan(Object *obj, Visitor *v, void *opaque,
279                      const char *name, Error **errp)
280 {
281     DeviceState *dev = DEVICE(obj);
282     Property *prop = opaque;
283     NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
284     NetClientState **ptr = &peers_ptr->ncs[0];
285     Error *local_err = NULL;
286     int32_t id;
287     NetClientState *hubport;
288
289     if (dev->realized) {
290         error_set(errp, QERR_PERMISSION_DENIED);
291         return;
292     }
293
294     visit_type_int32(v, &id, name, &local_err);
295     if (local_err) {
296         error_propagate(errp, local_err);
297         return;
298     }
299     if (id == -1) {
300         *ptr = NULL;
301         return;
302     }
303
304     hubport = net_hub_port_find(id);
305     if (!hubport) {
306         error_set(errp, QERR_INVALID_PARAMETER_VALUE,
307                   name, prop->info->name);
308         return;
309     }
310     *ptr = hubport;
311 }
312
313 PropertyInfo qdev_prop_vlan = {
314     .name  = "vlan",
315     .print = print_vlan,
316     .get   = get_vlan,
317     .set   = set_vlan,
318 };
319
320 int qdev_prop_set_drive(DeviceState *dev, const char *name,
321                         BlockDriverState *value)
322 {
323     Error *errp = NULL;
324     const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
325     object_property_set_str(OBJECT(dev), bdrv_name,
326                             name, &errp);
327     if (errp) {
328         qerror_report_err(errp);
329         error_free(errp);
330         return -1;
331     }
332     return 0;
333 }
334
335 void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
336                                 BlockDriverState *value)
337 {
338     if (qdev_prop_set_drive(dev, name, value) < 0) {
339         exit(1);
340     }
341 }
342 void qdev_prop_set_chr(DeviceState *dev, const char *name,
343                        CharDriverState *value)
344 {
345     Error *errp = NULL;
346     assert(!value || value->label);
347     object_property_set_str(OBJECT(dev),
348                             value ? value->label : "", name, &errp);
349     assert_no_error(errp);
350 }
351
352 void qdev_prop_set_netdev(DeviceState *dev, const char *name,
353                           NetClientState *value)
354 {
355     Error *errp = NULL;
356     assert(!value || value->name);
357     object_property_set_str(OBJECT(dev),
358                             value ? value->name : "", name, &errp);
359     assert_no_error(errp);
360 }
361
362 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
363 {
364     qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
365     if (nd->netdev) {
366         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
367     }
368     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
369         object_property_find(OBJECT(dev), "vectors", NULL)) {
370         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
371     }
372     nd->instantiated = 1;
373 }
374
375 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
376 {
377     GlobalProperty *g;
378
379     g = g_malloc0(sizeof(*g));
380     g->driver   = qemu_opt_get(opts, "driver");
381     g->property = qemu_opt_get(opts, "property");
382     g->value    = qemu_opt_get(opts, "value");
383     qdev_prop_register_global(g);
384     return 0;
385 }
386
387 void qemu_add_globals(void)
388 {
389     qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
390 }
This page took 0.045238 seconds and 4 git commands to generate.