Signed-off-by: Jan Kiszka<jan.kis...@siemens.com>
---
hw/irq.c | 38 +++++++++++++++++++++++++++++---------
hw/irq.h | 22 +++++++++++++++-------
2 files changed, 44 insertions(+), 16 deletions(-)
diff --git a/hw/irq.c b/hw/irq.c
index 7703f62..db2cce6 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -26,19 +26,27 @@
struct IRQState {
qemu_irq_handler handler;
+ qemu_irq_fb_handler feedback_handler;
void *opaque;
int n;
};
-void qemu_set_irq(qemu_irq irq, int level)
+int qemu_set_irq(qemu_irq irq, int level)
{
- if (!irq)
- return;
-
- irq->handler(irq->opaque, irq->n, level);
+ if (!irq) {
+ return 0;
+ }
+ if (irq->feedback_handler) {
+ return irq->feedback_handler(irq->opaque, irq->n, level);
+ } else {
+ irq->handler(irq->opaque, irq->n, level);
+ return QEMU_IRQ_DELIVERED;
+ }
}
-qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+static qemu_irq *allocate_irqs(qemu_irq_handler handler,
+ qemu_irq_fb_handler feedback_handler,
+ void *opaque, int n)
{
qemu_irq *s;
struct IRQState *p;
@@ -48,6 +56,7 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void
*opaque, int n)
p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
for (i = 0; i< n; i++) {
p->handler = handler;
+ p->feedback_handler = feedback_handler;
p->opaque = opaque;
p->n = i;
s[i] = p;
@@ -56,22 +65,33 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void
*opaque, int n)
return s;
}
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+ return allocate_irqs(handler, NULL, opaque, n);
+}
+
+qemu_irq *qemu_allocate_feedback_irqs(qemu_irq_fb_handler handler,
+ void *opaque, int n)
+{
+ return allocate_irqs(NULL, handler, opaque, n);
+}
+
void qemu_free_irqs(qemu_irq *s)
{
qemu_free(s[0]);
qemu_free(s);
}
-static void qemu_notirq(void *opaque, int line, int level)
+static int qemu_notirq(void *opaque, int line, int level)
{
struct IRQState *irq = opaque;
- irq->handler(irq->opaque, irq->n, !level);
+ return qemu_set_irq(irq, !level);
}
qemu_irq qemu_irq_invert(qemu_irq irq)
{
/* The default state for IRQs is low, so raise the output now. */
qemu_irq_raise(irq);
- return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+ return allocate_irqs(NULL, qemu_notirq, irq, 1)[0];
}
diff --git a/hw/irq.h b/hw/irq.h
index 5daae44..eee03e6 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,15 +3,18 @@
/* Generic IRQ/GPIO pin infrastructure. */
-/* FIXME: Rmove one of these. */
+#define QEMU_IRQ_DELIVERED 0
+#define QEMU_IRQ_COALESCED (-1)
+#define QEMU_IRQ_MASKED (-2)
+
typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
-typedef void SetIRQFunc(void *opaque, int irq_num, int level);
+typedef int (*qemu_irq_fb_handler)(void *opaque, int n, int level);
-void qemu_set_irq(qemu_irq irq, int level);
+int qemu_set_irq(qemu_irq irq, int level);
-static inline void qemu_irq_raise(qemu_irq irq)
+static inline int qemu_irq_raise(qemu_irq irq)
{
- qemu_set_irq(irq, 1);
+ return qemu_set_irq(irq, 1);
}
static inline void qemu_irq_lower(qemu_irq irq)
@@ -19,14 +22,19 @@ static inline void qemu_irq_lower(qemu_irq irq)
qemu_set_irq(irq, 0);
}
-static inline void qemu_irq_pulse(qemu_irq irq)
+static inline int qemu_irq_pulse(qemu_irq irq)
{
- qemu_set_irq(irq, 1);
+ int ret;
+
+ ret = qemu_set_irq(irq, 1);
qemu_set_irq(irq, 0);
+ return ret;
}
/* Returns an array of N IRQs. */
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+qemu_irq *qemu_allocate_feedback_irqs(qemu_irq_fb_handler handler,
+ void *opaque, int n);
void qemu_free_irqs(qemu_irq *s);
/* Returns a new IRQ with opposite polarity. */
--
1.6.0.2