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