11f9c4cfdSAndreas Färber /*
21f9c4cfdSAndreas Färber * QEMU IndustryPack emulation
31f9c4cfdSAndreas Färber *
41f9c4cfdSAndreas Färber * Copyright (C) 2012 Igalia, S.L.
5b996aed5SAlberto Garcia * Author: Alberto Garcia <berto@igalia.com>
61f9c4cfdSAndreas Färber *
71f9c4cfdSAndreas Färber * This code is licensed under the GNU GPL v2 or (at your option) any
81f9c4cfdSAndreas Färber * later version.
91f9c4cfdSAndreas Färber */
101f9c4cfdSAndreas Färber
110430891cSPeter Maydell #include "qemu/osdep.h"
12da34e65cSMarkus Armbruster #include "qapi/error.h"
130b8fa32fSMarkus Armbruster #include "qemu/module.h"
141f9c4cfdSAndreas Färber #include "hw/ipack/ipack.h"
1564552b6bSMarkus Armbruster #include "hw/irq.h"
16a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
17d6454270SMarkus Armbruster #include "migration/vmstate.h"
181f9c4cfdSAndreas Färber
ipack_device_find(IPackBus * bus,int32_t slot)191f9c4cfdSAndreas Färber IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
201f9c4cfdSAndreas Färber {
211f9c4cfdSAndreas Färber BusChild *kid;
221f9c4cfdSAndreas Färber
231f9c4cfdSAndreas Färber QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
241f9c4cfdSAndreas Färber DeviceState *qdev = kid->child;
251f9c4cfdSAndreas Färber IPackDevice *ip = IPACK_DEVICE(qdev);
261f9c4cfdSAndreas Färber if (ip->slot == slot) {
271f9c4cfdSAndreas Färber return ip;
281f9c4cfdSAndreas Färber }
291f9c4cfdSAndreas Färber }
301f9c4cfdSAndreas Färber return NULL;
311f9c4cfdSAndreas Färber }
321f9c4cfdSAndreas Färber
ipack_bus_init(IPackBus * bus,size_t bus_size,DeviceState * parent,uint8_t n_slots,qemu_irq_handler handler)3343417c0cSPeter Maydell void ipack_bus_init(IPackBus *bus, size_t bus_size,
341f9c4cfdSAndreas Färber DeviceState *parent,
3543417c0cSPeter Maydell uint8_t n_slots,
361f9c4cfdSAndreas Färber qemu_irq_handler handler)
371f9c4cfdSAndreas Färber {
38d637e1dcSPeter Maydell qbus_init(bus, bus_size, TYPE_IPACK_BUS, parent, NULL);
391f9c4cfdSAndreas Färber bus->n_slots = n_slots;
401f9c4cfdSAndreas Färber bus->set_irq = handler;
411f9c4cfdSAndreas Färber }
421f9c4cfdSAndreas Färber
ipack_device_realize(DeviceState * dev,Error ** errp)431f9c4cfdSAndreas Färber static void ipack_device_realize(DeviceState *dev, Error **errp)
441f9c4cfdSAndreas Färber {
451f9c4cfdSAndreas Färber IPackDevice *idev = IPACK_DEVICE(dev);
461f9c4cfdSAndreas Färber IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev));
471f9c4cfdSAndreas Färber IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
481f9c4cfdSAndreas Färber
491f9c4cfdSAndreas Färber if (idev->slot < 0) {
501f9c4cfdSAndreas Färber idev->slot = bus->free_slot;
511f9c4cfdSAndreas Färber }
521f9c4cfdSAndreas Färber if (idev->slot >= bus->n_slots) {
531f9c4cfdSAndreas Färber error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots);
541f9c4cfdSAndreas Färber return;
551f9c4cfdSAndreas Färber }
561f9c4cfdSAndreas Färber bus->free_slot = idev->slot + 1;
571f9c4cfdSAndreas Färber
581f9c4cfdSAndreas Färber idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2);
591f9c4cfdSAndreas Färber
601f9c4cfdSAndreas Färber k->realize(dev, errp);
611f9c4cfdSAndreas Färber }
621f9c4cfdSAndreas Färber
ipack_device_unrealize(DeviceState * dev)63b69c3c21SMarkus Armbruster static void ipack_device_unrealize(DeviceState *dev)
641f9c4cfdSAndreas Färber {
651f9c4cfdSAndreas Färber IPackDevice *idev = IPACK_DEVICE(dev);
661f9c4cfdSAndreas Färber IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
671f9c4cfdSAndreas Färber
681f9c4cfdSAndreas Färber if (k->unrealize) {
69b69c3c21SMarkus Armbruster k->unrealize(dev);
701f9c4cfdSAndreas Färber return;
711f9c4cfdSAndreas Färber }
721f9c4cfdSAndreas Färber
73f173d57aSPeter Crosthwaite qemu_free_irqs(idev->irq, 2);
741f9c4cfdSAndreas Färber }
751f9c4cfdSAndreas Färber
761f9c4cfdSAndreas Färber static Property ipack_device_props[] = {
771f9c4cfdSAndreas Färber DEFINE_PROP_INT32("slot", IPackDevice, slot, -1),
781f9c4cfdSAndreas Färber DEFINE_PROP_END_OF_LIST()
791f9c4cfdSAndreas Färber };
801f9c4cfdSAndreas Färber
ipack_device_class_init(ObjectClass * klass,void * data)811f9c4cfdSAndreas Färber static void ipack_device_class_init(ObjectClass *klass, void *data)
821f9c4cfdSAndreas Färber {
831f9c4cfdSAndreas Färber DeviceClass *k = DEVICE_CLASS(klass);
841f9c4cfdSAndreas Färber
851f9c4cfdSAndreas Färber set_bit(DEVICE_CATEGORY_INPUT, k->categories);
861f9c4cfdSAndreas Färber k->bus_type = TYPE_IPACK_BUS;
871f9c4cfdSAndreas Färber k->realize = ipack_device_realize;
881f9c4cfdSAndreas Färber k->unrealize = ipack_device_unrealize;
894f67d30bSMarc-André Lureau device_class_set_props(k, ipack_device_props);
901f9c4cfdSAndreas Färber }
911f9c4cfdSAndreas Färber
921f9c4cfdSAndreas Färber const VMStateDescription vmstate_ipack_device = {
931f9c4cfdSAndreas Färber .name = "ipack_device",
941f9c4cfdSAndreas Färber .version_id = 1,
951f9c4cfdSAndreas Färber .minimum_version_id = 1,
96*8913d05dSRichard Henderson .fields = (const VMStateField[]) {
971f9c4cfdSAndreas Färber VMSTATE_INT32(slot, IPackDevice),
981f9c4cfdSAndreas Färber VMSTATE_END_OF_LIST()
991f9c4cfdSAndreas Färber }
1001f9c4cfdSAndreas Färber };
1011f9c4cfdSAndreas Färber
1021f9c4cfdSAndreas Färber static const TypeInfo ipack_device_info = {
1031f9c4cfdSAndreas Färber .name = TYPE_IPACK_DEVICE,
1041f9c4cfdSAndreas Färber .parent = TYPE_DEVICE,
1051f9c4cfdSAndreas Färber .instance_size = sizeof(IPackDevice),
1061f9c4cfdSAndreas Färber .class_size = sizeof(IPackDeviceClass),
1071f9c4cfdSAndreas Färber .class_init = ipack_device_class_init,
1081f9c4cfdSAndreas Färber .abstract = true,
1091f9c4cfdSAndreas Färber };
1101f9c4cfdSAndreas Färber
1111f9c4cfdSAndreas Färber static const TypeInfo ipack_bus_info = {
1121f9c4cfdSAndreas Färber .name = TYPE_IPACK_BUS,
1131f9c4cfdSAndreas Färber .parent = TYPE_BUS,
1141f9c4cfdSAndreas Färber .instance_size = sizeof(IPackBus),
1151f9c4cfdSAndreas Färber };
1161f9c4cfdSAndreas Färber
ipack_register_types(void)1171f9c4cfdSAndreas Färber static void ipack_register_types(void)
1181f9c4cfdSAndreas Färber {
1191f9c4cfdSAndreas Färber type_register_static(&ipack_device_info);
1201f9c4cfdSAndreas Färber type_register_static(&ipack_bus_info);
1211f9c4cfdSAndreas Färber }
1221f9c4cfdSAndreas Färber
1231f9c4cfdSAndreas Färber type_init(ipack_register_types)
124