1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "hw/qdev-core.h"
22#include "hw/irq.h"
23#include "qapi/error.h"
24
25static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
26 const char *name)
27{
28 NamedGPIOList *ngl;
29
30 QLIST_FOREACH(ngl, &dev->gpios, node) {
31
32 if (g_strcmp0(name, ngl->name) == 0) {
33 return ngl;
34 }
35 }
36
37 ngl = g_malloc0(sizeof(*ngl));
38 ngl->name = g_strdup(name);
39 QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
40 return ngl;
41}
42
43void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
44 qemu_irq_handler handler,
45 void *opaque,
46 const char *name, int n)
47{
48 int i;
49 NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
50
51 assert(gpio_list->num_out == 0 || !name);
52 gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
53 opaque, n);
54
55 if (!name) {
56 name = "unnamed-gpio-in";
57 }
58 for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
59 gchar *propname = g_strdup_printf("%s[%u]", name, i);
60
61 object_property_add_child(OBJECT(dev), propname,
62 OBJECT(gpio_list->in[i]));
63 g_free(propname);
64 }
65
66 gpio_list->num_in += n;
67}
68
69void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
70{
71 qdev_init_gpio_in_named(dev, handler, NULL, n);
72}
73
74void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
75 const char *name, int n)
76{
77 int i;
78 NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
79
80 assert(gpio_list->num_in == 0 || !name);
81
82 if (!name) {
83 name = "unnamed-gpio-out";
84 }
85 memset(pins, 0, sizeof(*pins) * n);
86 for (i = 0; i < n; ++i) {
87 gchar *propname = g_strdup_printf("%s[%u]", name,
88 gpio_list->num_out + i);
89
90 object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
91 (Object **)&pins[i],
92 object_property_allow_set_link,
93 OBJ_PROP_LINK_STRONG);
94 g_free(propname);
95 }
96 gpio_list->num_out += n;
97}
98
99void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
100{
101 qdev_init_gpio_out_named(dev, pins, NULL, n);
102}
103
104qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
105{
106 NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
107
108 assert(n >= 0 && n < gpio_list->num_in);
109 return gpio_list->in[n];
110}
111
112qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
113{
114 return qdev_get_gpio_in_named(dev, NULL, n);
115}
116
117void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
118 qemu_irq pin)
119{
120 char *propname = g_strdup_printf("%s[%d]",
121 name ? name : "unnamed-gpio-out", n);
122 if (pin && !OBJECT(pin)->parent) {
123
124 object_property_add_child(container_get(qdev_get_machine(),
125 "/unattached"),
126 "non-qdev-gpio[*]", OBJECT(pin));
127 }
128 object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort);
129 g_free(propname);
130}
131
132qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
133{
134 g_autofree char *propname = g_strdup_printf("%s[%d]",
135 name ? name : "unnamed-gpio-out", n);
136
137 qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
138 NULL);
139
140 return ret;
141}
142
143
144
145static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
146 const char *name, int n)
147{
148 char *propname = g_strdup_printf("%s[%d]",
149 name ? name : "unnamed-gpio-out", n);
150
151 qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
152 NULL);
153 if (ret) {
154 object_property_set_link(OBJECT(dev), propname, NULL, NULL);
155 }
156 g_free(propname);
157 return ret;
158}
159
160qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
161 const char *name, int n)
162{
163 qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n);
164 qdev_connect_gpio_out_named(dev, name, n, icpt);
165 return disconnected;
166}
167
168void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin)
169{
170 qdev_connect_gpio_out_named(dev, NULL, n, pin);
171}
172
173void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
174 const char *name)
175{
176 int i;
177 NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name);
178
179 for (i = 0; i < ngl->num_in; i++) {
180 const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in";
181 char *propname = g_strdup_printf("%s[%d]", nm, i);
182
183 object_property_add_alias(OBJECT(container), propname,
184 OBJECT(dev), propname);
185 g_free(propname);
186 }
187 for (i = 0; i < ngl->num_out; i++) {
188 const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
189 char *propname = g_strdup_printf("%s[%d]", nm, i);
190
191 object_property_add_alias(OBJECT(container), propname,
192 OBJECT(dev), propname);
193 g_free(propname);
194 }
195 QLIST_REMOVE(ngl, node);
196 QLIST_INSERT_HEAD(&container->gpios, ngl, node);
197}
198