| /* |
| * QEMU IndustryPack emulation |
| * |
| * Copyright (C) 2012 Igalia, S.L. |
| * Author: Alberto Garcia <agarcia@igalia.com> |
| * |
| * This code is licensed under the GNU GPL v2 or (at your option) any |
| * later version. |
| */ |
| |
| #include "ipack.h" |
| |
| IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot) |
| { |
| BusChild *kid; |
| |
| QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) { |
| DeviceState *qdev = kid->child; |
| IPackDevice *ip = IPACK_DEVICE(qdev); |
| if (ip->slot == slot) { |
| return ip; |
| } |
| } |
| return NULL; |
| } |
| |
| void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, |
| DeviceState *parent, |
| const char *name, uint8_t n_slots, |
| qemu_irq_handler handler) |
| { |
| qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name); |
| bus->n_slots = n_slots; |
| bus->set_irq = handler; |
| } |
| |
| static int ipack_device_dev_init(DeviceState *qdev) |
| { |
| IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(qdev)); |
| IPackDevice *dev = IPACK_DEVICE(qdev); |
| IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); |
| |
| if (dev->slot < 0) { |
| dev->slot = bus->free_slot; |
| } |
| if (dev->slot >= bus->n_slots) { |
| return -1; |
| } |
| bus->free_slot = dev->slot + 1; |
| |
| dev->irq = qemu_allocate_irqs(bus->set_irq, dev, 2); |
| |
| return k->init(dev); |
| } |
| |
| static int ipack_device_dev_exit(DeviceState *qdev) |
| { |
| IPackDevice *dev = IPACK_DEVICE(qdev); |
| IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); |
| |
| if (k->exit) { |
| k->exit(dev); |
| } |
| |
| qemu_free_irqs(dev->irq); |
| |
| return 0; |
| } |
| |
| static Property ipack_device_props[] = { |
| DEFINE_PROP_INT32("slot", IPackDevice, slot, -1), |
| DEFINE_PROP_END_OF_LIST() |
| }; |
| |
| static void ipack_device_class_init(ObjectClass *klass, void *data) |
| { |
| DeviceClass *k = DEVICE_CLASS(klass); |
| set_bit(DEVICE_CATEGORY_INPUT, k->categories); |
| k->bus_type = TYPE_IPACK_BUS; |
| k->init = ipack_device_dev_init; |
| k->exit = ipack_device_dev_exit; |
| k->props = ipack_device_props; |
| } |
| |
| const VMStateDescription vmstate_ipack_device = { |
| .name = "ipack_device", |
| .version_id = 1, |
| .minimum_version_id = 1, |
| .minimum_version_id_old = 1, |
| .fields = (VMStateField[]) { |
| VMSTATE_INT32(slot, IPackDevice), |
| VMSTATE_END_OF_LIST() |
| } |
| }; |
| |
| static const TypeInfo ipack_device_info = { |
| .name = TYPE_IPACK_DEVICE, |
| .parent = TYPE_DEVICE, |
| .instance_size = sizeof(IPackDevice), |
| .class_size = sizeof(IPackDeviceClass), |
| .class_init = ipack_device_class_init, |
| .abstract = true, |
| }; |
| |
| static const TypeInfo ipack_bus_info = { |
| .name = TYPE_IPACK_BUS, |
| .parent = TYPE_BUS, |
| .instance_size = sizeof(IPackBus), |
| }; |
| |
| static void ipack_register_types(void) |
| { |
| type_register_static(&ipack_device_info); |
| type_register_static(&ipack_bus_info); |
| } |
| |
| type_init(ipack_register_types) |