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