/*
 * 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);
}

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,
    .minimum_version_id_old = 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)
