1*1f9c4cfdSAndreas Färber /* 2*1f9c4cfdSAndreas Färber * QEMU IndustryPack emulation 3*1f9c4cfdSAndreas Färber * 4*1f9c4cfdSAndreas Färber * Copyright (C) 2012 Igalia, S.L. 5*1f9c4cfdSAndreas Färber * Author: Alberto Garcia <agarcia@igalia.com> 6*1f9c4cfdSAndreas Färber * 7*1f9c4cfdSAndreas Färber * This code is licensed under the GNU GPL v2 or (at your option) any 8*1f9c4cfdSAndreas Färber * later version. 9*1f9c4cfdSAndreas Färber */ 10*1f9c4cfdSAndreas Färber 11*1f9c4cfdSAndreas Färber #include "hw/ipack/ipack.h" 12*1f9c4cfdSAndreas Färber 13*1f9c4cfdSAndreas Färber IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot) 14*1f9c4cfdSAndreas Färber { 15*1f9c4cfdSAndreas Färber BusChild *kid; 16*1f9c4cfdSAndreas Färber 17*1f9c4cfdSAndreas Färber QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) { 18*1f9c4cfdSAndreas Färber DeviceState *qdev = kid->child; 19*1f9c4cfdSAndreas Färber IPackDevice *ip = IPACK_DEVICE(qdev); 20*1f9c4cfdSAndreas Färber if (ip->slot == slot) { 21*1f9c4cfdSAndreas Färber return ip; 22*1f9c4cfdSAndreas Färber } 23*1f9c4cfdSAndreas Färber } 24*1f9c4cfdSAndreas Färber return NULL; 25*1f9c4cfdSAndreas Färber } 26*1f9c4cfdSAndreas Färber 27*1f9c4cfdSAndreas Färber void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, 28*1f9c4cfdSAndreas Färber DeviceState *parent, 29*1f9c4cfdSAndreas Färber const char *name, uint8_t n_slots, 30*1f9c4cfdSAndreas Färber qemu_irq_handler handler) 31*1f9c4cfdSAndreas Färber { 32*1f9c4cfdSAndreas Färber qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name); 33*1f9c4cfdSAndreas Färber bus->n_slots = n_slots; 34*1f9c4cfdSAndreas Färber bus->set_irq = handler; 35*1f9c4cfdSAndreas Färber } 36*1f9c4cfdSAndreas Färber 37*1f9c4cfdSAndreas Färber static void ipack_device_realize(DeviceState *dev, Error **errp) 38*1f9c4cfdSAndreas Färber { 39*1f9c4cfdSAndreas Färber IPackDevice *idev = IPACK_DEVICE(dev); 40*1f9c4cfdSAndreas Färber IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev)); 41*1f9c4cfdSAndreas Färber IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); 42*1f9c4cfdSAndreas Färber 43*1f9c4cfdSAndreas Färber if (idev->slot < 0) { 44*1f9c4cfdSAndreas Färber idev->slot = bus->free_slot; 45*1f9c4cfdSAndreas Färber } 46*1f9c4cfdSAndreas Färber if (idev->slot >= bus->n_slots) { 47*1f9c4cfdSAndreas Färber error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots); 48*1f9c4cfdSAndreas Färber return; 49*1f9c4cfdSAndreas Färber } 50*1f9c4cfdSAndreas Färber bus->free_slot = idev->slot + 1; 51*1f9c4cfdSAndreas Färber 52*1f9c4cfdSAndreas Färber idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2); 53*1f9c4cfdSAndreas Färber 54*1f9c4cfdSAndreas Färber k->realize(dev, errp); 55*1f9c4cfdSAndreas Färber } 56*1f9c4cfdSAndreas Färber 57*1f9c4cfdSAndreas Färber static void ipack_device_unrealize(DeviceState *dev, Error **errp) 58*1f9c4cfdSAndreas Färber { 59*1f9c4cfdSAndreas Färber IPackDevice *idev = IPACK_DEVICE(dev); 60*1f9c4cfdSAndreas Färber IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev); 61*1f9c4cfdSAndreas Färber Error *err = NULL; 62*1f9c4cfdSAndreas Färber 63*1f9c4cfdSAndreas Färber if (k->unrealize) { 64*1f9c4cfdSAndreas Färber k->unrealize(dev, &err); 65*1f9c4cfdSAndreas Färber error_propagate(errp, err); 66*1f9c4cfdSAndreas Färber return; 67*1f9c4cfdSAndreas Färber } 68*1f9c4cfdSAndreas Färber 69*1f9c4cfdSAndreas Färber qemu_free_irqs(idev->irq); 70*1f9c4cfdSAndreas Färber } 71*1f9c4cfdSAndreas Färber 72*1f9c4cfdSAndreas Färber static Property ipack_device_props[] = { 73*1f9c4cfdSAndreas Färber DEFINE_PROP_INT32("slot", IPackDevice, slot, -1), 74*1f9c4cfdSAndreas Färber DEFINE_PROP_END_OF_LIST() 75*1f9c4cfdSAndreas Färber }; 76*1f9c4cfdSAndreas Färber 77*1f9c4cfdSAndreas Färber static void ipack_device_class_init(ObjectClass *klass, void *data) 78*1f9c4cfdSAndreas Färber { 79*1f9c4cfdSAndreas Färber DeviceClass *k = DEVICE_CLASS(klass); 80*1f9c4cfdSAndreas Färber 81*1f9c4cfdSAndreas Färber set_bit(DEVICE_CATEGORY_INPUT, k->categories); 82*1f9c4cfdSAndreas Färber k->bus_type = TYPE_IPACK_BUS; 83*1f9c4cfdSAndreas Färber k->realize = ipack_device_realize; 84*1f9c4cfdSAndreas Färber k->unrealize = ipack_device_unrealize; 85*1f9c4cfdSAndreas Färber k->props = ipack_device_props; 86*1f9c4cfdSAndreas Färber } 87*1f9c4cfdSAndreas Färber 88*1f9c4cfdSAndreas Färber const VMStateDescription vmstate_ipack_device = { 89*1f9c4cfdSAndreas Färber .name = "ipack_device", 90*1f9c4cfdSAndreas Färber .version_id = 1, 91*1f9c4cfdSAndreas Färber .minimum_version_id = 1, 92*1f9c4cfdSAndreas Färber .minimum_version_id_old = 1, 93*1f9c4cfdSAndreas Färber .fields = (VMStateField[]) { 94*1f9c4cfdSAndreas Färber VMSTATE_INT32(slot, IPackDevice), 95*1f9c4cfdSAndreas Färber VMSTATE_END_OF_LIST() 96*1f9c4cfdSAndreas Färber } 97*1f9c4cfdSAndreas Färber }; 98*1f9c4cfdSAndreas Färber 99*1f9c4cfdSAndreas Färber static const TypeInfo ipack_device_info = { 100*1f9c4cfdSAndreas Färber .name = TYPE_IPACK_DEVICE, 101*1f9c4cfdSAndreas Färber .parent = TYPE_DEVICE, 102*1f9c4cfdSAndreas Färber .instance_size = sizeof(IPackDevice), 103*1f9c4cfdSAndreas Färber .class_size = sizeof(IPackDeviceClass), 104*1f9c4cfdSAndreas Färber .class_init = ipack_device_class_init, 105*1f9c4cfdSAndreas Färber .abstract = true, 106*1f9c4cfdSAndreas Färber }; 107*1f9c4cfdSAndreas Färber 108*1f9c4cfdSAndreas Färber static const TypeInfo ipack_bus_info = { 109*1f9c4cfdSAndreas Färber .name = TYPE_IPACK_BUS, 110*1f9c4cfdSAndreas Färber .parent = TYPE_BUS, 111*1f9c4cfdSAndreas Färber .instance_size = sizeof(IPackBus), 112*1f9c4cfdSAndreas Färber }; 113*1f9c4cfdSAndreas Färber 114*1f9c4cfdSAndreas Färber static void ipack_register_types(void) 115*1f9c4cfdSAndreas Färber { 116*1f9c4cfdSAndreas Färber type_register_static(&ipack_device_info); 117*1f9c4cfdSAndreas Färber type_register_static(&ipack_bus_info); 118*1f9c4cfdSAndreas Färber } 119*1f9c4cfdSAndreas Färber 120*1f9c4cfdSAndreas Färber type_init(ipack_register_types) 121