xref: /qemu/hw/ipack/ipack.c (revision d6454270)
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"
16*d6454270SMarkus Armbruster #include "migration/vmstate.h"
171f9c4cfdSAndreas Färber 
181f9c4cfdSAndreas Färber IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
191f9c4cfdSAndreas Färber {
201f9c4cfdSAndreas Färber     BusChild *kid;
211f9c4cfdSAndreas Färber 
221f9c4cfdSAndreas Färber     QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
231f9c4cfdSAndreas Färber         DeviceState *qdev = kid->child;
241f9c4cfdSAndreas Färber         IPackDevice *ip = IPACK_DEVICE(qdev);
251f9c4cfdSAndreas Färber         if (ip->slot == slot) {
261f9c4cfdSAndreas Färber             return ip;
271f9c4cfdSAndreas Färber         }
281f9c4cfdSAndreas Färber     }
291f9c4cfdSAndreas Färber     return NULL;
301f9c4cfdSAndreas Färber }
311f9c4cfdSAndreas Färber 
321f9c4cfdSAndreas Färber void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
331f9c4cfdSAndreas Färber                            DeviceState *parent,
341f9c4cfdSAndreas Färber                            const char *name, uint8_t n_slots,
351f9c4cfdSAndreas Färber                            qemu_irq_handler handler)
361f9c4cfdSAndreas Färber {
371f9c4cfdSAndreas Färber     qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name);
381f9c4cfdSAndreas Färber     bus->n_slots = n_slots;
391f9c4cfdSAndreas Färber     bus->set_irq = handler;
401f9c4cfdSAndreas Färber }
411f9c4cfdSAndreas Färber 
421f9c4cfdSAndreas Färber static void ipack_device_realize(DeviceState *dev, Error **errp)
431f9c4cfdSAndreas Färber {
441f9c4cfdSAndreas Färber     IPackDevice *idev = IPACK_DEVICE(dev);
451f9c4cfdSAndreas Färber     IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev));
461f9c4cfdSAndreas Färber     IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
471f9c4cfdSAndreas Färber 
481f9c4cfdSAndreas Färber     if (idev->slot < 0) {
491f9c4cfdSAndreas Färber         idev->slot = bus->free_slot;
501f9c4cfdSAndreas Färber     }
511f9c4cfdSAndreas Färber     if (idev->slot >= bus->n_slots) {
521f9c4cfdSAndreas Färber         error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots);
531f9c4cfdSAndreas Färber         return;
541f9c4cfdSAndreas Färber     }
551f9c4cfdSAndreas Färber     bus->free_slot = idev->slot + 1;
561f9c4cfdSAndreas Färber 
571f9c4cfdSAndreas Färber     idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2);
581f9c4cfdSAndreas Färber 
591f9c4cfdSAndreas Färber     k->realize(dev, errp);
601f9c4cfdSAndreas Färber }
611f9c4cfdSAndreas Färber 
621f9c4cfdSAndreas Färber static void ipack_device_unrealize(DeviceState *dev, Error **errp)
631f9c4cfdSAndreas Färber {
641f9c4cfdSAndreas Färber     IPackDevice *idev = IPACK_DEVICE(dev);
651f9c4cfdSAndreas Färber     IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
661f9c4cfdSAndreas Färber     Error *err = NULL;
671f9c4cfdSAndreas Färber 
681f9c4cfdSAndreas Färber     if (k->unrealize) {
691f9c4cfdSAndreas Färber         k->unrealize(dev, &err);
701f9c4cfdSAndreas Färber         error_propagate(errp, err);
711f9c4cfdSAndreas Färber         return;
721f9c4cfdSAndreas Färber     }
731f9c4cfdSAndreas Färber 
74f173d57aSPeter Crosthwaite     qemu_free_irqs(idev->irq, 2);
751f9c4cfdSAndreas Färber }
761f9c4cfdSAndreas Färber 
771f9c4cfdSAndreas Färber static Property ipack_device_props[] = {
781f9c4cfdSAndreas Färber     DEFINE_PROP_INT32("slot", IPackDevice, slot, -1),
791f9c4cfdSAndreas Färber     DEFINE_PROP_END_OF_LIST()
801f9c4cfdSAndreas Färber };
811f9c4cfdSAndreas Färber 
821f9c4cfdSAndreas Färber static void ipack_device_class_init(ObjectClass *klass, void *data)
831f9c4cfdSAndreas Färber {
841f9c4cfdSAndreas Färber     DeviceClass *k = DEVICE_CLASS(klass);
851f9c4cfdSAndreas Färber 
861f9c4cfdSAndreas Färber     set_bit(DEVICE_CATEGORY_INPUT, k->categories);
871f9c4cfdSAndreas Färber     k->bus_type = TYPE_IPACK_BUS;
881f9c4cfdSAndreas Färber     k->realize = ipack_device_realize;
891f9c4cfdSAndreas Färber     k->unrealize = ipack_device_unrealize;
901f9c4cfdSAndreas Färber     k->props = ipack_device_props;
911f9c4cfdSAndreas Färber }
921f9c4cfdSAndreas Färber 
931f9c4cfdSAndreas Färber const VMStateDescription vmstate_ipack_device = {
941f9c4cfdSAndreas Färber     .name = "ipack_device",
951f9c4cfdSAndreas Färber     .version_id = 1,
961f9c4cfdSAndreas Färber     .minimum_version_id = 1,
971f9c4cfdSAndreas Färber     .fields = (VMStateField[]) {
981f9c4cfdSAndreas Färber         VMSTATE_INT32(slot, IPackDevice),
991f9c4cfdSAndreas Färber         VMSTATE_END_OF_LIST()
1001f9c4cfdSAndreas Färber     }
1011f9c4cfdSAndreas Färber };
1021f9c4cfdSAndreas Färber 
1031f9c4cfdSAndreas Färber static const TypeInfo ipack_device_info = {
1041f9c4cfdSAndreas Färber     .name          = TYPE_IPACK_DEVICE,
1051f9c4cfdSAndreas Färber     .parent        = TYPE_DEVICE,
1061f9c4cfdSAndreas Färber     .instance_size = sizeof(IPackDevice),
1071f9c4cfdSAndreas Färber     .class_size    = sizeof(IPackDeviceClass),
1081f9c4cfdSAndreas Färber     .class_init    = ipack_device_class_init,
1091f9c4cfdSAndreas Färber     .abstract      = true,
1101f9c4cfdSAndreas Färber };
1111f9c4cfdSAndreas Färber 
1121f9c4cfdSAndreas Färber static const TypeInfo ipack_bus_info = {
1131f9c4cfdSAndreas Färber     .name = TYPE_IPACK_BUS,
1141f9c4cfdSAndreas Färber     .parent = TYPE_BUS,
1151f9c4cfdSAndreas Färber     .instance_size = sizeof(IPackBus),
1161f9c4cfdSAndreas Färber };
1171f9c4cfdSAndreas Färber 
1181f9c4cfdSAndreas Färber static void ipack_register_types(void)
1191f9c4cfdSAndreas Färber {
1201f9c4cfdSAndreas Färber     type_register_static(&ipack_device_info);
1211f9c4cfdSAndreas Färber     type_register_static(&ipack_bus_info);
1221f9c4cfdSAndreas Färber }
1231f9c4cfdSAndreas Färber 
1241f9c4cfdSAndreas Färber type_init(ipack_register_types)
125