4 * Copyright (c) 2009 CodeSourcery
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "hw/qdev-core.h"
23 #include "qapi/error.h"
25 static NamedGPIOList
*qdev_get_named_gpio_list(DeviceState
*dev
,
30 QLIST_FOREACH(ngl
, &dev
->gpios
, node
) {
31 /* NULL is a valid and matchable name. */
32 if (g_strcmp0(name
, ngl
->name
) == 0) {
37 ngl
= g_malloc0(sizeof(*ngl
));
38 ngl
->name
= g_strdup(name
);
39 QLIST_INSERT_HEAD(&dev
->gpios
, ngl
, node
);
43 void qdev_init_gpio_in_named_with_opaque(DeviceState
*dev
,
44 qemu_irq_handler handler
,
46 const char *name
, int n
)
49 NamedGPIOList
*gpio_list
= qdev_get_named_gpio_list(dev
, name
);
51 assert(gpio_list
->num_out
== 0 || !name
);
52 gpio_list
->in
= qemu_extend_irqs(gpio_list
->in
, gpio_list
->num_in
, handler
,
56 name
= "unnamed-gpio-in";
58 for (i
= gpio_list
->num_in
; i
< gpio_list
->num_in
+ n
; i
++) {
59 gchar
*propname
= g_strdup_printf("%s[%u]", name
, i
);
61 object_property_add_child(OBJECT(dev
), propname
,
62 OBJECT(gpio_list
->in
[i
]));
66 gpio_list
->num_in
+= n
;
69 void qdev_init_gpio_in(DeviceState
*dev
, qemu_irq_handler handler
, int n
)
71 qdev_init_gpio_in_named(dev
, handler
, NULL
, n
);
74 void qdev_init_gpio_out_named(DeviceState
*dev
, qemu_irq
*pins
,
75 const char *name
, int n
)
78 NamedGPIOList
*gpio_list
= qdev_get_named_gpio_list(dev
, name
);
80 assert(gpio_list
->num_in
== 0 || !name
);
83 name
= "unnamed-gpio-out";
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
);
90 object_property_add_link(OBJECT(dev
), propname
, TYPE_IRQ
,
92 object_property_allow_set_link
,
93 OBJ_PROP_LINK_STRONG
);
96 gpio_list
->num_out
+= n
;
99 void qdev_init_gpio_out(DeviceState
*dev
, qemu_irq
*pins
, int n
)
101 qdev_init_gpio_out_named(dev
, pins
, NULL
, n
);
104 qemu_irq
qdev_get_gpio_in_named(DeviceState
*dev
, const char *name
, int n
)
106 NamedGPIOList
*gpio_list
= qdev_get_named_gpio_list(dev
, name
);
108 assert(n
>= 0 && n
< gpio_list
->num_in
);
109 return gpio_list
->in
[n
];
112 qemu_irq
qdev_get_gpio_in(DeviceState
*dev
, int n
)
114 return qdev_get_gpio_in_named(dev
, NULL
, n
);
117 void qdev_connect_gpio_out_named(DeviceState
*dev
, const char *name
, int n
,
120 char *propname
= g_strdup_printf("%s[%d]",
121 name
? name
: "unnamed-gpio-out", n
);
122 if (input_pin
&& !OBJECT(input_pin
)->parent
) {
123 /* We need a name for object_property_set_link to work */
124 object_property_add_child(container_get(qdev_get_machine(),
126 "non-qdev-gpio[*]", OBJECT(input_pin
));
128 object_property_set_link(OBJECT(dev
), propname
,
129 OBJECT(input_pin
), &error_abort
);
133 qemu_irq
qdev_get_gpio_out_connector(DeviceState
*dev
, const char *name
, int n
)
135 g_autofree
char *propname
= g_strdup_printf("%s[%d]",
136 name
? name
: "unnamed-gpio-out", n
);
138 qemu_irq ret
= (qemu_irq
)object_property_get_link(OBJECT(dev
), propname
,
144 /* disconnect a GPIO output, returning the disconnected input (if any) */
146 static qemu_irq
qdev_disconnect_gpio_out_named(DeviceState
*dev
,
147 const char *name
, int n
)
149 char *propname
= g_strdup_printf("%s[%d]",
150 name
? name
: "unnamed-gpio-out", n
);
152 qemu_irq ret
= (qemu_irq
)object_property_get_link(OBJECT(dev
), propname
,
155 object_property_set_link(OBJECT(dev
), propname
, NULL
, NULL
);
161 qemu_irq
qdev_intercept_gpio_out(DeviceState
*dev
, qemu_irq icpt
,
162 const char *name
, int n
)
164 qemu_irq disconnected
= qdev_disconnect_gpio_out_named(dev
, name
, n
);
165 qdev_connect_gpio_out_named(dev
, name
, n
, icpt
);
169 void qdev_connect_gpio_out(DeviceState
*dev
, int n
, qemu_irq input_pin
)
171 qdev_connect_gpio_out_named(dev
, NULL
, n
, input_pin
);
174 void qdev_pass_gpios(DeviceState
*dev
, DeviceState
*container
,
178 NamedGPIOList
*ngl
= qdev_get_named_gpio_list(dev
, name
);
180 for (i
= 0; i
< ngl
->num_in
; i
++) {
181 const char *nm
= ngl
->name
? ngl
->name
: "unnamed-gpio-in";
182 char *propname
= g_strdup_printf("%s[%d]", nm
, i
);
184 object_property_add_alias(OBJECT(container
), propname
,
185 OBJECT(dev
), propname
);
188 for (i
= 0; i
< ngl
->num_out
; i
++) {
189 const char *nm
= ngl
->name
? ngl
->name
: "unnamed-gpio-out";
190 char *propname
= g_strdup_printf("%s[%d]", nm
, i
);
192 object_property_add_alias(OBJECT(container
), propname
,
193 OBJECT(dev
), propname
);
196 QLIST_REMOVE(ngl
, node
);
197 QLIST_INSERT_HEAD(&container
->gpios
, ngl
, node
);