File:  [Qemu by Fabrice Bellard] / qemu / hw / qdev.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:23:47 2018 UTC (2 years, 6 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0111, qemu0110, HEAD
qemu 0.11.0

    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, see <http://www.gnu.org/licenses/>.
   18:  */
   19: 
   20: /* The theory here is that it should be possible to create a machine without
   21:    knowledge of specific devices.  Historically board init routines have
   22:    passed a bunch of arguments to each device, requiring the board know
   23:    exactly which device it is dealing with.  This file provides an abstract
   24:    API for device configuration and initialization.  Devices will generally
   25:    inherit from a particular bus (e.g. PCI or I2C) rather than
   26:    this API directly.  */
   27: 
   28: #include "net.h"
   29: #include "qdev.h"
   30: #include "sysemu.h"
   31: #include "monitor.h"
   32: 
   33: /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
   34: static BusState *main_system_bus;
   35: 
   36: static DeviceInfo *device_info_list;
   37: 
   38: /* Register a new device type.  */
   39: void qdev_register(DeviceInfo *info)
   40: {
   41:     assert(info->size >= sizeof(DeviceState));
   42:     assert(!info->next);
   43: 
   44:     info->next = device_info_list;
   45:     device_info_list = info;
   46: }
   47: 
   48: static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
   49: {
   50:     DeviceInfo *info;
   51: 
   52:     /* first check device names */
   53:     for (info = device_info_list; info != NULL; info = info->next) {
   54:         if (bus_info && info->bus_info != bus_info)
   55:             continue;
   56:         if (strcmp(info->name, name) != 0)
   57:             continue;
   58:         return info;
   59:     }
   60: 
   61:     /* failing that check the aliases */
   62:     for (info = device_info_list; info != NULL; info = info->next) {
   63:         if (bus_info && info->bus_info != bus_info)
   64:             continue;
   65:         if (!info->alias)
   66:             continue;
   67:         if (strcmp(info->alias, name) != 0)
   68:             continue;
   69:         return info;
   70:     }
   71:     return NULL;
   72: }
   73: 
   74: /* Create a new device.  This only initializes the device state structure
   75:    and allows properties to be set.  qdev_init should be called to
   76:    initialize the actual device emulation.  */
   77: DeviceState *qdev_create(BusState *bus, const char *name)
   78: {
   79:     DeviceInfo *info;
   80:     DeviceState *dev;
   81: 
   82:     if (!bus) {
   83:         if (!main_system_bus) {
   84:             main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
   85:         }
   86:         bus = main_system_bus;
   87:     }
   88: 
   89:     info = qdev_find_info(bus->info, name);
   90:     if (!info) {
   91:         hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
   92:     }
   93: 
   94:     dev = qemu_mallocz(info->size);
   95:     dev->info = info;
   96:     dev->parent_bus = bus;
   97:     qdev_prop_set_defaults(dev, dev->info->props);
   98:     qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
   99:     qdev_prop_set_compat(dev);
  100:     LIST_INSERT_HEAD(&bus->children, dev, sibling);
  101:     return dev;
  102: }
  103: 
  104: /* Initialize a device.  Device properties should be set before calling
  105:    this function.  IRQs and MMIO regions should be connected/mapped after
  106:    calling this function.  */
  107: void qdev_init(DeviceState *dev)
  108: {
  109:     dev->info->init(dev, dev->info);
  110: }
  111: 
  112: /* Unlink device from bus and free the structure.  */
  113: void qdev_free(DeviceState *dev)
  114: {
  115:     LIST_REMOVE(dev, sibling);
  116:     qemu_free(dev->id);
  117:     qemu_free(dev);
  118: }
  119: 
  120: /* Get a character (serial) device interface.  */
  121: CharDriverState *qdev_init_chardev(DeviceState *dev)
  122: {
  123:     static int next_serial;
  124:     static int next_virtconsole;
  125:     /* FIXME: This is a nasty hack that needs to go away.  */
  126:     if (strncmp(dev->info->name, "virtio", 6) == 0) {
  127:         return virtcon_hds[next_virtconsole++];
  128:     } else {
  129:         return serial_hds[next_serial++];
  130:     }
  131: }
  132: 
  133: BusState *qdev_get_parent_bus(DeviceState *dev)
  134: {
  135:     return dev->parent_bus;
  136: }
  137: 
  138: void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
  139: {
  140:     assert(dev->num_gpio_in == 0);
  141:     dev->num_gpio_in = n;
  142:     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
  143: }
  144: 
  145: void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
  146: {
  147:     assert(dev->num_gpio_out == 0);
  148:     dev->num_gpio_out = n;
  149:     dev->gpio_out = pins;
  150: }
  151: 
  152: qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
  153: {
  154:     assert(n >= 0 && n < dev->num_gpio_in);
  155:     return dev->gpio_in[n];
  156: }
  157: 
  158: void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
  159: {
  160:     assert(n >= 0 && n < dev->num_gpio_out);
  161:     dev->gpio_out[n] = pin;
  162: }
  163: 
  164: VLANClientState *qdev_get_vlan_client(DeviceState *dev,
  165:                                       NetCanReceive *can_receive,
  166:                                       NetReceive *receive,
  167:                                       NetReceiveIOV *receive_iov,
  168:                                       NetCleanup *cleanup,
  169:                                       void *opaque)
  170: {
  171:     NICInfo *nd = dev->nd;
  172:     assert(nd);
  173:     nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
  174:                                   receive, receive_iov, cleanup, opaque);
  175:     return nd->vc;
  176: }
  177: 
  178: 
  179: void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
  180: {
  181:     memcpy(macaddr, dev->nd->macaddr, 6);
  182: }
  183: 
  184: static int next_block_unit[IF_COUNT];
  185: 
  186: /* Get a block device.  This should only be used for single-drive devices
  187:    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
  188:    appropriate bus.  */
  189: BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
  190: {
  191:     int unit = next_block_unit[type]++;
  192:     int index;
  193: 
  194:     index = drive_get_index(type, 0, unit);
  195:     if (index == -1) {
  196:         return NULL;
  197:     }
  198:     return drives_table[index].bdrv;
  199: }
  200: 
  201: BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
  202: {
  203:     BusState *bus;
  204: 
  205:     LIST_FOREACH(bus, &dev->child_bus, sibling) {
  206:         if (strcmp(name, bus->name) == 0) {
  207:             return bus;
  208:         }
  209:     }
  210:     return NULL;
  211: }
  212: 
  213: static int next_scsi_bus;
  214: 
  215: /* Create a scsi bus, and attach devices to it.  */
  216: /* TODO: Actually create a scsi bus for hotplug to use.  */
  217: void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
  218: {
  219:    int bus = next_scsi_bus++;
  220:    int unit;
  221:    int index;
  222: 
  223:    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
  224:        index = drive_get_index(IF_SCSI, bus, unit);
  225:        if (index == -1) {
  226:            continue;
  227:        }
  228:        attach(host, drives_table[index].bdrv, unit);
  229:    }
  230: }
  231: 
  232: BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
  233: {
  234:     BusState *bus;
  235: 
  236:     bus = qemu_mallocz(info->size);
  237:     bus->info = info;
  238:     bus->parent = parent;
  239:     bus->name = qemu_strdup(name);
  240:     LIST_INIT(&bus->children);
  241:     if (parent) {
  242:         LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
  243:     }
  244:     return bus;
  245: }
  246: 
  247: #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
  248: static void qbus_print(Monitor *mon, BusState *bus, int indent);
  249: 
  250: static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
  251:                              const char *prefix, int indent)
  252: {
  253:     char buf[64];
  254: 
  255:     if (!props)
  256:         return;
  257:     while (props->name) {
  258:         if (props->info->print) {
  259:             props->info->print(dev, props, buf, sizeof(buf));
  260:             qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
  261:         }
  262:         props++;
  263:     }
  264: }
  265: 
  266: static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
  267: {
  268:     BusState *child;
  269:     qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
  270:                 dev->id ? dev->id : "");
  271:     indent += 2;
  272:     if (dev->num_gpio_in) {
  273:         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
  274:     }
  275:     if (dev->num_gpio_out) {
  276:         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
  277:     }
  278:     qdev_print_props(mon, dev, dev->info->props, "dev", indent);
  279:     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
  280:     if (dev->parent_bus->info->print_dev)
  281:         dev->parent_bus->info->print_dev(mon, dev, indent);
  282:     LIST_FOREACH(child, &dev->child_bus, sibling) {
  283:         qbus_print(mon, child, indent);
  284:     }
  285: }
  286: 
  287: static void qbus_print(Monitor *mon, BusState *bus, int indent)
  288: {
  289:     struct DeviceState *dev;
  290: 
  291:     qdev_printf("bus: %s\n", bus->name);
  292:     indent += 2;
  293:     qdev_printf("type %s\n", bus->info->name);
  294:     LIST_FOREACH(dev, &bus->children, sibling) {
  295:         qdev_print(mon, dev, indent);
  296:     }
  297: }
  298: #undef qdev_printf
  299: 
  300: void do_info_qtree(Monitor *mon)
  301: {
  302:     if (main_system_bus)
  303:         qbus_print(mon, main_system_bus, 0);
  304: }

unix.superglobalmegacorp.com