f173d57a4c
Allocate each IRQ individually on array allocations. This prepares for QOMification of IRQs, where pointers to individual IRQs may be taken and handed around for usage as QOM Links. The g_renew() scheme used here is too fragile and would break all existing links should an IRQ list be extended. We now have to pass the IRQ count to qemu_free_irqs(). We have so few call sites however, so this change is reasonably trivial. Cc: agarcia@igalia.com Cc: mst@redhat.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Alberto Garcia <agarcia@igalia.com> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> Signed-off-by: Andreas Färber <afaerber@suse.de>
120 lines
3.0 KiB
C
120 lines
3.0 KiB
C
/*
|
|
* QEMU IndustryPack emulation
|
|
*
|
|
* Copyright (C) 2012 Igalia, S.L.
|
|
* Author: Alberto Garcia <agarcia@igalia.com>
|
|
*
|
|
* This code is licensed under the GNU GPL v2 or (at your option) any
|
|
* later version.
|
|
*/
|
|
|
|
#include "hw/ipack/ipack.h"
|
|
|
|
IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
|
|
{
|
|
BusChild *kid;
|
|
|
|
QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
|
|
DeviceState *qdev = kid->child;
|
|
IPackDevice *ip = IPACK_DEVICE(qdev);
|
|
if (ip->slot == slot) {
|
|
return ip;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
|
|
DeviceState *parent,
|
|
const char *name, uint8_t n_slots,
|
|
qemu_irq_handler handler)
|
|
{
|
|
qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name);
|
|
bus->n_slots = n_slots;
|
|
bus->set_irq = handler;
|
|
}
|
|
|
|
static void ipack_device_realize(DeviceState *dev, Error **errp)
|
|
{
|
|
IPackDevice *idev = IPACK_DEVICE(dev);
|
|
IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev));
|
|
IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
|
|
|
|
if (idev->slot < 0) {
|
|
idev->slot = bus->free_slot;
|
|
}
|
|
if (idev->slot >= bus->n_slots) {
|
|
error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots);
|
|
return;
|
|
}
|
|
bus->free_slot = idev->slot + 1;
|
|
|
|
idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2);
|
|
|
|
k->realize(dev, errp);
|
|
}
|
|
|
|
static void ipack_device_unrealize(DeviceState *dev, Error **errp)
|
|
{
|
|
IPackDevice *idev = IPACK_DEVICE(dev);
|
|
IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
|
|
Error *err = NULL;
|
|
|
|
if (k->unrealize) {
|
|
k->unrealize(dev, &err);
|
|
error_propagate(errp, err);
|
|
return;
|
|
}
|
|
|
|
qemu_free_irqs(idev->irq, 2);
|
|
}
|
|
|
|
static Property ipack_device_props[] = {
|
|
DEFINE_PROP_INT32("slot", IPackDevice, slot, -1),
|
|
DEFINE_PROP_END_OF_LIST()
|
|
};
|
|
|
|
static void ipack_device_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
DeviceClass *k = DEVICE_CLASS(klass);
|
|
|
|
set_bit(DEVICE_CATEGORY_INPUT, k->categories);
|
|
k->bus_type = TYPE_IPACK_BUS;
|
|
k->realize = ipack_device_realize;
|
|
k->unrealize = ipack_device_unrealize;
|
|
k->props = ipack_device_props;
|
|
}
|
|
|
|
const VMStateDescription vmstate_ipack_device = {
|
|
.name = "ipack_device",
|
|
.version_id = 1,
|
|
.minimum_version_id = 1,
|
|
.fields = (VMStateField[]) {
|
|
VMSTATE_INT32(slot, IPackDevice),
|
|
VMSTATE_END_OF_LIST()
|
|
}
|
|
};
|
|
|
|
static const TypeInfo ipack_device_info = {
|
|
.name = TYPE_IPACK_DEVICE,
|
|
.parent = TYPE_DEVICE,
|
|
.instance_size = sizeof(IPackDevice),
|
|
.class_size = sizeof(IPackDeviceClass),
|
|
.class_init = ipack_device_class_init,
|
|
.abstract = true,
|
|
};
|
|
|
|
static const TypeInfo ipack_bus_info = {
|
|
.name = TYPE_IPACK_BUS,
|
|
.parent = TYPE_BUS,
|
|
.instance_size = sizeof(IPackBus),
|
|
};
|
|
|
|
static void ipack_register_types(void)
|
|
{
|
|
type_register_static(&ipack_device_info);
|
|
type_register_static(&ipack_bus_info);
|
|
}
|
|
|
|
type_init(ipack_register_types)
|