Home | History | Annotate | Download | only in hw
      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.h"
     30 #include "qdev.h"
     31 #include "sysemu.h"
     32 #include "monitor.h"
     33 
     34 struct DeviceProperty {
     35     const char *name;
     36     DevicePropType type;
     37     union {
     38         uint64_t i;
     39         void *ptr;
     40     } value;
     41     DeviceProperty *next;
     42 };
     43 
     44 struct DeviceType {
     45     DeviceInfo *info;
     46     DeviceType *next;
     47 };
     48 
     49 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
     50 static BusState *main_system_bus;
     51 
     52 static DeviceType *device_type_list;
     53 
     54 /* Register a new device type.  */
     55 void qdev_register(DeviceInfo *info)
     56 {
     57     DeviceType *t;
     58 
     59     assert(info->size >= sizeof(DeviceState));
     60 
     61     t = qemu_mallocz(sizeof(DeviceType));
     62     t->next = device_type_list;
     63     device_type_list = t;
     64     t->info = info;
     65 }
     66 
     67 /* Create a new device.  This only initializes the device state structure
     68    and allows properties to be set.  qdev_init should be called to
     69    initialize the actual device emulation.  */
     70 DeviceState *qdev_create(BusState *bus, const char *name)
     71 {
     72     DeviceType *t;
     73     DeviceState *dev;
     74 
     75     for (t = device_type_list; t; t = t->next) {
     76         if (strcmp(t->info->name, name) == 0) {
     77             break;
     78         }
     79     }
     80     if (!t) {
     81         hw_error("Unknown device '%s'\n", name);
     82     }
     83 
     84     dev = qemu_mallocz(t->info->size);
     85     dev->type = t;
     86 
     87     if (!bus) {
     88         /* ???: This assumes system busses have no additional state.  */
     89         if (!main_system_bus) {
     90             main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
     91                                           NULL, "main-system-bus");
     92         }
     93         bus = main_system_bus;
     94     }
     95     if (t->info->bus_type != bus->type) {
     96         /* TODO: Print bus type names.  */
     97         hw_error("Device '%s' on wrong bus type (%d/%d)", name,
     98                  t->info->bus_type, bus->type);
     99     }
    100     dev->parent_bus = bus;
    101     QLIST_INSERT_HEAD(&bus->children, dev, sibling);
    102     return dev;
    103 }
    104 
    105 /* Initialize a device.  Device properties should be set before calling
    106    this function.  IRQs and MMIO regions should be connected/mapped after
    107    calling this function.  */
    108 void qdev_init(DeviceState *dev)
    109 {
    110     dev->type->info->init(dev, dev->type->info);
    111 }
    112 
    113 /* Unlink device from bus and free the structure.  */
    114 void qdev_free(DeviceState *dev)
    115 {
    116     QLIST_REMOVE(dev, sibling);
    117     qemu_free(dev);
    118 }
    119 
    120 static DeviceProperty *create_prop(DeviceState *dev, const char *name,
    121                                    DevicePropType type)
    122 {
    123     DeviceProperty *prop;
    124 
    125     /* TODO: Check for duplicate properties.  */
    126     prop = qemu_mallocz(sizeof(*prop));
    127     prop->name = qemu_strdup(name);
    128     prop->type = type;
    129     prop->next = dev->props;
    130     dev->props = prop;
    131 
    132     return prop;
    133 }
    134 
    135 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
    136 {
    137     DeviceProperty *prop;
    138 
    139     prop = create_prop(dev, name, PROP_TYPE_INT);
    140     prop->value.i = value;
    141 }
    142 
    143 void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
    144 {
    145     DeviceProperty *prop;
    146 
    147     prop = create_prop(dev, name, PROP_TYPE_DEV);
    148     prop->value.ptr = value;
    149 }
    150 
    151 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
    152 {
    153     DeviceProperty *prop;
    154 
    155     prop = create_prop(dev, name, PROP_TYPE_PTR);
    156     prop->value.ptr = value;
    157 }
    158 
    159 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
    160 {
    161     assert(!dev->nd);
    162     dev->nd = nd;
    163 }
    164 
    165 
    166 /* Get a character (serial) device interface.  */
    167 CharDriverState *qdev_init_chardev(DeviceState *dev)
    168 {
    169     static int next_serial;
    170     static int next_virtconsole;
    171     /* FIXME: This is a nasty hack that needs to go away.  */
    172     if (strncmp(dev->type->info->name, "virtio", 6) == 0) {
    173         return virtcon_hds[next_virtconsole++];
    174     } else {
    175         return serial_hds[next_serial++];
    176     }
    177 }
    178 
    179 BusState *qdev_get_parent_bus(DeviceState *dev)
    180 {
    181     return dev->parent_bus;
    182 }
    183 
    184 static DeviceProperty *find_prop(DeviceState *dev, const char *name,
    185                                  DevicePropType type)
    186 {
    187     DeviceProperty *prop;
    188 
    189     for (prop = dev->props; prop; prop = prop->next) {
    190         if (strcmp(prop->name, name) == 0) {
    191             assert (prop->type == type);
    192             return prop;
    193         }
    194     }
    195     return NULL;
    196 }
    197 
    198 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
    199 {
    200     DeviceProperty *prop;
    201 
    202     prop = find_prop(dev, name, PROP_TYPE_INT);
    203     if (!prop) {
    204         return def;
    205     }
    206 
    207     return prop->value.i;
    208 }
    209 
    210 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
    211 {
    212     DeviceProperty *prop;
    213 
    214     prop = find_prop(dev, name, PROP_TYPE_PTR);
    215     assert(prop);
    216     return prop->value.ptr;
    217 }
    218 
    219 DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
    220 {
    221     DeviceProperty *prop;
    222 
    223     prop = find_prop(dev, name, PROP_TYPE_DEV);
    224     if (!prop) {
    225         return NULL;
    226     }
    227     return prop->value.ptr;
    228 }
    229 
    230 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
    231 {
    232     assert(dev->num_gpio_in == 0);
    233     dev->num_gpio_in = n;
    234     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
    235 }
    236 
    237 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
    238 {
    239     assert(dev->num_gpio_out == 0);
    240     dev->num_gpio_out = n;
    241     dev->gpio_out = pins;
    242 }
    243 
    244 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
    245 {
    246     assert(n >= 0 && n < dev->num_gpio_in);
    247     return dev->gpio_in[n];
    248 }
    249 
    250 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
    251 {
    252     assert(n >= 0 && n < dev->num_gpio_out);
    253     dev->gpio_out[n] = pin;
    254 }
    255 
    256 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
    257                                       NetCanReceive *can_receive,
    258                                       NetReceive *receive,
    259                                       NetReceiveIOV *receive_iov,
    260                                       NetCleanup *cleanup,
    261                                       void *opaque)
    262 {
    263     NICInfo *nd = dev->nd;
    264     assert(nd);
    265     return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
    266                                 receive, receive_iov, cleanup, opaque);
    267 }
    268 
    269 
    270 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
    271 {
    272     memcpy(macaddr, dev->nd->macaddr, 6);
    273 }
    274 
    275 static int next_block_unit[IF_COUNT];
    276 
    277 /* Get a block device.  This should only be used for single-drive devices
    278    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
    279    appropriate bus.  */
    280 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
    281 {
    282     int unit = next_block_unit[type]++;
    283     int index;
    284 
    285     index = drive_get_index(type, 0, unit);
    286     if (index == -1) {
    287         return NULL;
    288     }
    289     return drives_table[index].bdrv;
    290 }
    291 
    292 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
    293 {
    294     BusState *bus;
    295 
    296     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
    297         if (strcmp(name, bus->name) == 0) {
    298             return bus;
    299         }
    300     }
    301     return NULL;
    302 }
    303 
    304 static int next_scsi_bus;
    305 
    306 /* Create a scsi bus, and attach devices to it.  */
    307 /* TODO: Actually create a scsi bus for hotplug to use.  */
    308 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
    309 {
    310    int bus = next_scsi_bus++;
    311    int unit;
    312    int index;
    313 
    314    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
    315        index = drive_get_index(IF_SCSI, bus, unit);
    316        if (index == -1) {
    317            continue;
    318        }
    319        attach(host, drives_table[index].bdrv, unit);
    320    }
    321 }
    322 
    323 BusState *qbus_create(BusType type, size_t size,
    324                       DeviceState *parent, const char *name)
    325 {
    326     BusState *bus;
    327 
    328     bus = qemu_mallocz(size);
    329     bus->type = type;
    330     bus->parent = parent;
    331     bus->name = qemu_strdup(name);
    332     QLIST_INIT(&bus->children);
    333     if (parent) {
    334         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
    335     }
    336     return bus;
    337 }
    338 
    339 static const char *bus_type_names[] = {
    340     [ BUS_TYPE_SYSTEM ] = "System",
    341     [ BUS_TYPE_PCI ]    = "PCI",
    342     [ BUS_TYPE_SCSI ]   = "SCSI",
    343     [ BUS_TYPE_I2C ]    = "I2C",
    344     [ BUS_TYPE_SSI ]    = "SSI",
    345 };
    346 
    347 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
    348 static void qbus_print(Monitor *mon, BusState *bus, int indent);
    349 
    350 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
    351 {
    352     DeviceProperty *prop;
    353     BusState *child;
    354     qdev_printf("dev: %s\n", dev->type->info->name);
    355     indent += 2;
    356     if (dev->num_gpio_in) {
    357         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
    358     }
    359     if (dev->num_gpio_out) {
    360         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
    361     }
    362     for (prop = dev->props; prop; prop = prop->next) {
    363         switch (prop->type) {
    364         case PROP_TYPE_INT:
    365             qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
    366                         prop->value.i);
    367             break;
    368         case PROP_TYPE_PTR:
    369             qdev_printf("prop-ptr %s\n", prop->name);
    370             break;
    371         case PROP_TYPE_DEV:
    372             qdev_printf("prop-dev %s %s\n", prop->name,
    373                         ((DeviceState *)prop->value.ptr)->type->info->name);
    374             break;
    375         default:
    376             qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
    377             break;
    378         }
    379     }
    380     switch (dev->parent_bus->type) {
    381     case BUS_TYPE_SYSTEM:
    382         sysbus_dev_print(mon, dev, indent);
    383         break;
    384     default:
    385         break;
    386     }
    387     QLIST_FOREACH(child, &dev->child_bus, sibling) {
    388         qbus_print(mon, child, indent);
    389     }
    390 }
    391 
    392 static void qbus_print(Monitor *mon, BusState *bus, int indent)
    393 {
    394     struct DeviceState *dev;
    395 
    396     qdev_printf("bus: %s\n", bus->name);
    397     indent += 2;
    398     qdev_printf("type %s\n", bus_type_names[bus->type]);
    399     QLIST_FOREACH(dev, &bus->children, sibling) {
    400         qdev_print(mon, dev, indent);
    401     }
    402 }
    403 #undef qdev_printf
    404 
    405 void do_info_qtree(Monitor *mon)
    406 {
    407     if (main_system_bus)
    408         qbus_print(mon, main_system_bus, 0);
    409 }
    410