blob: c39dbb481f206129cd65453f665f5b9ae63ebd2b [file] [log] [blame]
Alberto Garcia9c16fa72013-01-11 18:25:29 +01001/*
2 * QEMU IndustryPack emulation
3 *
4 * Copyright (C) 2012 Igalia, S.L.
Alberto Garciab996aed2016-02-23 10:44:25 +02005 * Author: Alberto Garcia <berto@igalia.com>
Alberto Garcia9c16fa72013-01-11 18:25:29 +01006 *
7 * This code is licensed under the GNU GPL v2 or (at your option) any
8 * later version.
9 */
10
Peter Maydell04308912016-01-26 18:17:30 +000011#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010012#include "qapi/error.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020013#include "qemu/module.h"
Andreas Färber1f9c4cf2013-08-02 00:48:40 +020014#include "hw/ipack/ipack.h"
Markus Armbruster64552b62019-08-12 07:23:42 +020015#include "hw/irq.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +020016#include "hw/qdev-properties.h"
Markus Armbrusterd6454272019-08-12 07:23:45 +020017#include "migration/vmstate.h"
Alberto Garcia9c16fa72013-01-11 18:25:29 +010018
19IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
20{
21 BusChild *kid;
22
23 QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
24 DeviceState *qdev = kid->child;
25 IPackDevice *ip = IPACK_DEVICE(qdev);
26 if (ip->slot == slot) {
27 return ip;
28 }
29 }
30 return NULL;
31}
32
Peter Maydell43417c02021-09-23 13:11:49 +010033void ipack_bus_init(IPackBus *bus, size_t bus_size,
34 DeviceState *parent,
35 uint8_t n_slots,
36 qemu_irq_handler handler)
Alberto Garcia9c16fa72013-01-11 18:25:29 +010037{
Peter Maydelld637e1d2021-09-23 13:11:51 +010038 qbus_init(bus, bus_size, TYPE_IPACK_BUS, parent, NULL);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010039 bus->n_slots = n_slots;
40 bus->set_irq = handler;
41}
42
Andreas Färber5c570902013-08-01 18:45:02 +020043static void ipack_device_realize(DeviceState *dev, Error **errp)
Alberto Garcia9c16fa72013-01-11 18:25:29 +010044{
Andreas Färber5c570902013-08-01 18:45:02 +020045 IPackDevice *idev = IPACK_DEVICE(dev);
46 IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(dev));
Alberto Garcia9c16fa72013-01-11 18:25:29 +010047 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
48
Andreas Färber5c570902013-08-01 18:45:02 +020049 if (idev->slot < 0) {
50 idev->slot = bus->free_slot;
Alberto Garcia9c16fa72013-01-11 18:25:29 +010051 }
Andreas Färber5c570902013-08-01 18:45:02 +020052 if (idev->slot >= bus->n_slots) {
53 error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots);
54 return;
Alberto Garcia9c16fa72013-01-11 18:25:29 +010055 }
Andreas Färber5c570902013-08-01 18:45:02 +020056 bus->free_slot = idev->slot + 1;
Alberto Garcia9c16fa72013-01-11 18:25:29 +010057
Andreas Färber5c570902013-08-01 18:45:02 +020058 idev->irq = qemu_allocate_irqs(bus->set_irq, idev, 2);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010059
Andreas Färber5c570902013-08-01 18:45:02 +020060 k->realize(dev, errp);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010061}
62
Markus Armbrusterb69c3c22020-05-05 17:29:24 +020063static void ipack_device_unrealize(DeviceState *dev)
Alberto Garcia9c16fa72013-01-11 18:25:29 +010064{
Andreas Färber5c570902013-08-01 18:45:02 +020065 IPackDevice *idev = IPACK_DEVICE(dev);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010066 IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
67
Andreas Färber5c570902013-08-01 18:45:02 +020068 if (k->unrealize) {
Markus Armbrusterb69c3c22020-05-05 17:29:24 +020069 k->unrealize(dev);
Andreas Färber5c570902013-08-01 18:45:02 +020070 return;
Alberto Garcia9c16fa72013-01-11 18:25:29 +010071 }
72
Peter Crosthwaitef173d572014-06-18 00:56:31 -070073 qemu_free_irqs(idev->irq, 2);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010074}
75
76static Property ipack_device_props[] = {
77 DEFINE_PROP_INT32("slot", IPackDevice, slot, -1),
78 DEFINE_PROP_END_OF_LIST()
79};
80
81static void ipack_device_class_init(ObjectClass *klass, void *data)
82{
83 DeviceClass *k = DEVICE_CLASS(klass);
Andreas Färber5c570902013-08-01 18:45:02 +020084
Marcel Apfelbaum125ee0e2013-07-29 17:17:45 +030085 set_bit(DEVICE_CATEGORY_INPUT, k->categories);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010086 k->bus_type = TYPE_IPACK_BUS;
Andreas Färber5c570902013-08-01 18:45:02 +020087 k->realize = ipack_device_realize;
88 k->unrealize = ipack_device_unrealize;
Marc-André Lureau4f67d302020-01-10 19:30:32 +040089 device_class_set_props(k, ipack_device_props);
Alberto Garcia9c16fa72013-01-11 18:25:29 +010090}
91
92const VMStateDescription vmstate_ipack_device = {
93 .name = "ipack_device",
94 .version_id = 1,
95 .minimum_version_id = 1,
Richard Henderson8913d052023-12-21 14:16:16 +110096 .fields = (const VMStateField[]) {
Alberto Garcia9c16fa72013-01-11 18:25:29 +010097 VMSTATE_INT32(slot, IPackDevice),
98 VMSTATE_END_OF_LIST()
99 }
100};
101
102static const TypeInfo ipack_device_info = {
103 .name = TYPE_IPACK_DEVICE,
104 .parent = TYPE_DEVICE,
105 .instance_size = sizeof(IPackDevice),
106 .class_size = sizeof(IPackDeviceClass),
107 .class_init = ipack_device_class_init,
108 .abstract = true,
109};
110
111static const TypeInfo ipack_bus_info = {
112 .name = TYPE_IPACK_BUS,
113 .parent = TYPE_BUS,
114 .instance_size = sizeof(IPackBus),
115};
116
117static void ipack_register_types(void)
118{
119 type_register_static(&ipack_device_info);
120 type_register_static(&ipack_bus_info);
121}
122
123type_init(ipack_register_types)