xref: /qemu/hw/ipack/ipack.c (revision 8913d05d)
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