• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Dynamic device configuration and creation.
3  *
4  *  Copyright (c) 2009 CodeSourcery
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19  */
20 
21 /* The theory here is that it should be possible to create a machine without
22    knowledge of specific devices.  Historically board init routines have
23    passed a bunch of arguments to each device, requiring the board know
24    exactly which device it is dealing with.  This file provides an abstract
25    API for device configuration and initialization.  Devices will generally
26    inherit from a particular bus (e.g. PCI or I2C) rather than
27    this API directly.  */
28 
29 #include "net/net.h"
30 #include "hw/qdev.h"
31 #include "sysemu/sysemu.h"
32 #include "monitor/monitor.h"
33 #include "sysemu/blockdev.h"
34 
35 struct DeviceProperty {
36     const char *name;
37     DevicePropType type;
38     union {
39         uint64_t i;
40         void *ptr;
41     } value;
42     DeviceProperty *next;
43 };
44 
45 struct DeviceType {
46     DeviceInfo *info;
47     DeviceType *next;
48 };
49 
50 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
51 static BusState *main_system_bus;
52 
53 static DeviceType *device_type_list;
54 
55 /* Register a new device type.  */
qdev_register(DeviceInfo * info)56 void qdev_register(DeviceInfo *info)
57 {
58     DeviceType *t;
59 
60     assert(info->size >= sizeof(DeviceState));
61 
62     t = g_malloc0(sizeof(DeviceType));
63     t->next = device_type_list;
64     device_type_list = t;
65     t->info = info;
66 }
67 
68 /* Create a new device.  This only initializes the device state structure
69    and allows properties to be set.  qdev_init should be called to
70    initialize the actual device emulation.  */
qdev_create(BusState * bus,const char * name)71 DeviceState *qdev_create(BusState *bus, const char *name)
72 {
73     DeviceType *t;
74     DeviceState *dev;
75 
76     for (t = device_type_list; t; t = t->next) {
77         if (strcmp(t->info->name, name) == 0) {
78             break;
79         }
80     }
81     if (!t) {
82         hw_error("Unknown device '%s'\n", name);
83     }
84 
85     dev = g_malloc0(t->info->size);
86     dev->type = t;
87 
88     if (!bus) {
89         /* ???: This assumes system busses have no additional state.  */
90         if (!main_system_bus) {
91             main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
92                                           NULL, "main-system-bus");
93         }
94         bus = main_system_bus;
95     }
96     if (t->info->bus_type != bus->type) {
97         /* TODO: Print bus type names.  */
98         hw_error("Device '%s' on wrong bus type (%d/%d)", name,
99                  t->info->bus_type, bus->type);
100     }
101     dev->parent_bus = bus;
102     QLIST_INSERT_HEAD(&bus->children, dev, sibling);
103     return dev;
104 }
105 
qdev_device_help(QemuOpts * opts)106 int qdev_device_help(QemuOpts *opts)
107 {
108 #ifdef CONFIG_ANDROID  /* Not ready yet, will remove when we properly integrate upstream qdev */
109     return 0;
110 #else
111     const char *driver;
112     DeviceInfo *info;
113     Property *prop;
114 
115     driver = qemu_opt_get(opts, "driver");
116     if (driver && !strcmp(driver, "?")) {
117         for (info = device_info_list; info != NULL; info = info->next) {
118             if (info->no_user) {
119                 continue;       /* not available, don't show */
120             }
121             qdev_print_devinfo(info);
122         }
123         return 1;
124     }
125 
126     if (!qemu_opt_get(opts, "?")) {
127         return 0;
128     }
129 
130     info = qdev_find_info(NULL, driver);
131     if (!info) {
132         return 0;
133     }
134 
135     for (prop = info->props; prop && prop->name; prop++) {
136         /*
137          * TODO Properties without a parser are just for dirty hacks.
138          * qdev_prop_ptr is the only such PropertyInfo.  It's marked
139          * for removal.  This conditional should be removed along with
140          * it.
141          */
142         if (!prop->info->parse) {
143             continue;           /* no way to set it, don't show */
144         }
145         error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
146     }
147     return 1;
148 #endif
149 }
150 
qdev_device_add(QemuOpts * opts)151 DeviceState *qdev_device_add(QemuOpts *opts)
152 {
153 #ifdef CONFIG_ANDROID  /* Not ready yet */
154     return NULL;
155 #else
156     const char *driver, *path, *id;
157     DeviceInfo *info;
158     DeviceState *qdev;
159     BusState *bus;
160 
161     driver = qemu_opt_get(opts, "driver");
162     if (!driver) {
163         qerror_report(QERR_MISSING_PARAMETER, "driver");
164         return NULL;
165     }
166 
167     /* find driver */
168     info = qdev_find_info(NULL, driver);
169     if (!info || info->no_user) {
170         qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
171         error_printf_unless_qmp("Try with argument '?' for a list.\n");
172         return NULL;
173     }
174 
175     /* find bus */
176     path = qemu_opt_get(opts, "bus");
177     if (path != NULL) {
178         bus = qbus_find(path);
179         if (!bus) {
180             return NULL;
181         }
182         if (bus->info != info->bus_info) {
183             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
184                            driver, bus->info->name);
185             return NULL;
186         }
187     } else {
188         bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
189         if (!bus) {
190             qerror_report(QERR_NO_BUS_FOR_DEVICE,
191                            info->name, info->bus_info->name);
192             return NULL;
193         }
194     }
195     if (qdev_hotplug && !bus->allow_hotplug) {
196         qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
197         return NULL;
198     }
199 
200     /* create device, set properties */
201     qdev = qdev_create_from_info(bus, info);
202     id = qemu_opts_id(opts);
203     if (id) {
204         qdev->id = id;
205     }
206     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
207         qdev_free(qdev);
208         return NULL;
209     }
210     if (qdev_init(qdev) < 0) {
211         qerror_report(QERR_DEVICE_INIT_FAILED, driver);
212         return NULL;
213     }
214     qdev->opts = opts;
215     return qdev;
216 #endif
217 }
218 
219 /* Initialize a device.  Device properties should be set before calling
220    this function.  IRQs and MMIO regions should be connected/mapped after
221    calling this function.  */
qdev_init(DeviceState * dev)222 void qdev_init(DeviceState *dev)
223 {
224     dev->type->info->init(dev, dev->type->info);
225 }
226 
227 /* Unlink device from bus and free the structure.  */
qdev_free(DeviceState * dev)228 void qdev_free(DeviceState *dev)
229 {
230     QLIST_REMOVE(dev, sibling);
231     g_free(dev);
232 }
233 
create_prop(DeviceState * dev,const char * name,DevicePropType type)234 static DeviceProperty *create_prop(DeviceState *dev, const char *name,
235                                    DevicePropType type)
236 {
237     DeviceProperty *prop;
238 
239     /* TODO: Check for duplicate properties.  */
240     prop = g_malloc0(sizeof(*prop));
241     prop->name = g_strdup(name);
242     prop->type = type;
243     prop->next = dev->props;
244     dev->props = prop;
245 
246     return prop;
247 }
248 
qdev_set_prop_int(DeviceState * dev,const char * name,uint64_t value)249 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
250 {
251     DeviceProperty *prop;
252 
253     prop = create_prop(dev, name, PROP_TYPE_INT);
254     prop->value.i = value;
255 }
256 
qdev_set_prop_dev(DeviceState * dev,const char * name,DeviceState * value)257 void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
258 {
259     DeviceProperty *prop;
260 
261     prop = create_prop(dev, name, PROP_TYPE_DEV);
262     prop->value.ptr = value;
263 }
264 
qdev_set_prop_ptr(DeviceState * dev,const char * name,void * value)265 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
266 {
267     DeviceProperty *prop;
268 
269     prop = create_prop(dev, name, PROP_TYPE_PTR);
270     prop->value.ptr = value;
271 }
272 
qdev_set_netdev(DeviceState * dev,NICInfo * nd)273 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
274 {
275     assert(!dev->nd);
276     dev->nd = nd;
277 }
278 
279 
280 /* Get a character (serial) device interface.  */
qdev_init_chardev(DeviceState * dev)281 CharDriverState *qdev_init_chardev(DeviceState *dev)
282 {
283     static int next_serial;
284     static int next_virtconsole;
285     /* FIXME: This is a nasty hack that needs to go away.  */
286     if (strncmp(dev->type->info->name, "virtio", 6) == 0) {
287         return virtcon_hds[next_virtconsole++];
288     } else {
289         return serial_hds[next_serial++];
290     }
291 }
292 
qdev_get_parent_bus(DeviceState * dev)293 BusState *qdev_get_parent_bus(DeviceState *dev)
294 {
295     return dev->parent_bus;
296 }
297 
find_prop(DeviceState * dev,const char * name,DevicePropType type)298 static DeviceProperty *find_prop(DeviceState *dev, const char *name,
299                                  DevicePropType type)
300 {
301     DeviceProperty *prop;
302 
303     for (prop = dev->props; prop; prop = prop->next) {
304         if (strcmp(prop->name, name) == 0) {
305             assert (prop->type == type);
306             return prop;
307         }
308     }
309     return NULL;
310 }
311 
qdev_get_prop_int(DeviceState * dev,const char * name,uint64_t def)312 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
313 {
314     DeviceProperty *prop;
315 
316     prop = find_prop(dev, name, PROP_TYPE_INT);
317     if (!prop) {
318         return def;
319     }
320 
321     return prop->value.i;
322 }
323 
qdev_get_prop_ptr(DeviceState * dev,const char * name)324 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
325 {
326     DeviceProperty *prop;
327 
328     prop = find_prop(dev, name, PROP_TYPE_PTR);
329     assert(prop);
330     return prop->value.ptr;
331 }
332 
qdev_get_prop_dev(DeviceState * dev,const char * name)333 DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
334 {
335     DeviceProperty *prop;
336 
337     prop = find_prop(dev, name, PROP_TYPE_DEV);
338     if (!prop) {
339         return NULL;
340     }
341     return prop->value.ptr;
342 }
343 
qdev_init_gpio_in(DeviceState * dev,qemu_irq_handler handler,int n)344 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
345 {
346     assert(dev->num_gpio_in == 0);
347     dev->num_gpio_in = n;
348     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
349 }
350 
qdev_init_gpio_out(DeviceState * dev,qemu_irq * pins,int n)351 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
352 {
353     assert(dev->num_gpio_out == 0);
354     dev->num_gpio_out = n;
355     dev->gpio_out = pins;
356 }
357 
qdev_get_gpio_in(DeviceState * dev,int n)358 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
359 {
360     assert(n >= 0 && n < dev->num_gpio_in);
361     return dev->gpio_in[n];
362 }
363 
qdev_connect_gpio_out(DeviceState * dev,int n,qemu_irq pin)364 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
365 {
366     assert(n >= 0 && n < dev->num_gpio_out);
367     dev->gpio_out[n] = pin;
368 }
369 
qdev_get_vlan_client(DeviceState * dev,NetCanReceive * can_receive,NetReceive * receive,NetReceiveIOV * receive_iov,NetCleanup * cleanup,void * opaque)370 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
371                                       NetCanReceive *can_receive,
372                                       NetReceive *receive,
373                                       NetReceiveIOV *receive_iov,
374                                       NetCleanup *cleanup,
375                                       void *opaque)
376 {
377     NICInfo *nd = dev->nd;
378     assert(nd);
379     return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
380                                 receive, receive_iov, cleanup, opaque);
381 }
382 
383 
qdev_get_macaddr(DeviceState * dev,uint8_t * macaddr)384 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
385 {
386     memcpy(macaddr, dev->nd->macaddr, 6);
387 }
388 
389 static int next_block_unit[IF_COUNT];
390 
391 /* Get a block device.  This should only be used for single-drive devices
392    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
393    appropriate bus.  */
qdev_init_bdrv(DeviceState * dev,BlockInterfaceType type)394 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
395 {
396     int unit = next_block_unit[type]++;
397     DriveInfo* info;
398 
399     info = drive_get(type, 0, unit);
400     if (info == NULL) {
401         return NULL;
402     }
403     return info->bdrv;
404 }
405 
qdev_get_child_bus(DeviceState * dev,const char * name)406 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
407 {
408     BusState *bus;
409 
410     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
411         if (strcmp(name, bus->name) == 0) {
412             return bus;
413         }
414     }
415     return NULL;
416 }
417 
418 static int next_scsi_bus;
419 
420 /* Create a scsi bus, and attach devices to it.  */
421 /* TODO: Actually create a scsi bus for hotplug to use.  */
scsi_bus_new(DeviceState * host,SCSIAttachFn attach)422 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
423 {
424    int bus = next_scsi_bus++;
425    int unit;
426    DriveInfo* info;
427 
428    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
429        info = drive_get(IF_SCSI, bus, unit);
430        if (info == NULL) {
431            continue;
432        }
433        attach(host, info->bdrv, unit);
434    }
435 }
436 
qbus_create(BusType type,size_t size,DeviceState * parent,const char * name)437 BusState *qbus_create(BusType type, size_t size,
438                       DeviceState *parent, const char *name)
439 {
440     BusState *bus;
441 
442     bus = g_malloc0(size);
443     bus->type = type;
444     bus->parent = parent;
445     bus->name = g_strdup(name);
446     QLIST_INIT(&bus->children);
447     if (parent) {
448         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
449     }
450     return bus;
451 }
452 
453 static const char *bus_type_names[] = {
454     [ BUS_TYPE_SYSTEM ] = "System",
455     [ BUS_TYPE_PCI ]    = "PCI",
456     [ BUS_TYPE_SCSI ]   = "SCSI",
457     [ BUS_TYPE_I2C ]    = "I2C",
458     [ BUS_TYPE_SSI ]    = "SSI",
459 };
460 
461 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
462 static void qbus_print(Monitor *mon, BusState *bus, int indent);
463 
qdev_print(Monitor * mon,DeviceState * dev,int indent)464 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
465 {
466     DeviceProperty *prop;
467     BusState *child;
468     qdev_printf("dev: %s\n", dev->type->info->name);
469     indent += 2;
470     if (dev->num_gpio_in) {
471         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
472     }
473     if (dev->num_gpio_out) {
474         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
475     }
476     for (prop = dev->props; prop; prop = prop->next) {
477         switch (prop->type) {
478         case PROP_TYPE_INT:
479             qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
480                         prop->value.i);
481             break;
482         case PROP_TYPE_PTR:
483             qdev_printf("prop-ptr %s\n", prop->name);
484             break;
485         case PROP_TYPE_DEV:
486             qdev_printf("prop-dev %s %s\n", prop->name,
487                         ((DeviceState *)prop->value.ptr)->type->info->name);
488             break;
489         default:
490             qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
491             break;
492         }
493     }
494     switch (dev->parent_bus->type) {
495     case BUS_TYPE_SYSTEM:
496         sysbus_dev_print(mon, dev, indent);
497         break;
498     default:
499         break;
500     }
501     QLIST_FOREACH(child, &dev->child_bus, sibling) {
502         qbus_print(mon, child, indent);
503     }
504 }
505 
qbus_print(Monitor * mon,BusState * bus,int indent)506 static void qbus_print(Monitor *mon, BusState *bus, int indent)
507 {
508     struct DeviceState *dev;
509 
510     qdev_printf("bus: %s\n", bus->name);
511     indent += 2;
512     qdev_printf("type %s\n", bus_type_names[bus->type]);
513     QLIST_FOREACH(dev, &bus->children, sibling) {
514         qdev_print(mon, dev, indent);
515     }
516 }
517 #undef qdev_printf
518 
do_info_qtree(Monitor * mon)519 void do_info_qtree(Monitor *mon)
520 {
521     if (main_system_bus)
522         qbus_print(mon, main_system_bus, 0);
523 }
524 
qdev_get_dev_path(DeviceState * dev)525 char *qdev_get_dev_path(DeviceState *dev)
526 {
527     // TODO(digit): Implement this properly.
528     return NULL;
529 }
530 
531