hw/core/irq.c: Use upstream version.
Change-Id: I628d463245995db72be21f08b3c38680c58e2070
diff --git a/arch_init.c b/arch_init.c
index cfd0fad..07edec9 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -29,6 +29,7 @@
#include <sys/mman.h>
#endif
#include "config.h"
+#include "hw/irq.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
#include "sysemu/arch_init.h"
diff --git a/hw/core/irq.c b/hw/core/irq.c
index c43fe48..03c8cb3 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -38,30 +38,59 @@
irq->handler(irq->opaque, irq->n, level);
}
-qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
+ void *opaque, int n)
{
qemu_irq *s;
struct IRQState *p;
int i;
- s = (qemu_irq *)g_malloc0(sizeof(qemu_irq) * n);
- p = (struct IRQState *)g_malloc0(sizeof(struct IRQState) * n);
- for (i = 0; i < n; i++) {
- p->handler = handler;
- p->opaque = opaque;
- p->n = i;
+ if (!old) {
+ n_old = 0;
+ }
+ s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
+ p = old ? g_renew(struct IRQState, s[0], n + n_old) :
+ g_new(struct IRQState, n);
+ for (i = 0; i < n + n_old; i++) {
+ if (i >= n_old) {
+ p->handler = handler;
+ p->opaque = opaque;
+ p->n = i;
+ }
s[i] = p;
p++;
}
return s;
}
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+ return qemu_extend_irqs(NULL, 0, handler, opaque, n);
+}
+
+qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
+{
+ struct IRQState *irq;
+
+ irq = g_new(struct IRQState, 1);
+ irq->handler = handler;
+ irq->opaque = opaque;
+ irq->n = n;
+
+ return irq;
+}
+
void qemu_free_irqs(qemu_irq *s)
{
g_free(s[0]);
g_free(s);
}
+void qemu_free_irq(qemu_irq irq)
+{
+ g_free(irq);
+}
+
static void qemu_notirq(void *opaque, int line, int level)
{
struct IRQState *irq = opaque;
@@ -75,3 +104,49 @@
qemu_irq_raise(irq);
return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
}
+
+static void qemu_splitirq(void *opaque, int line, int level)
+{
+ struct IRQState **irq = opaque;
+ irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
+ irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
+}
+
+qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
+{
+ qemu_irq *s = g_malloc0(2 * sizeof(qemu_irq));
+ s[0] = irq1;
+ s[1] = irq2;
+ return qemu_allocate_irqs(qemu_splitirq, s, 1)[0];
+}
+
+static void proxy_irq_handler(void *opaque, int n, int level)
+{
+ qemu_irq **target = opaque;
+
+ if (*target) {
+ qemu_set_irq((*target)[n], level);
+ }
+}
+
+qemu_irq *qemu_irq_proxy(qemu_irq **target, int n)
+{
+ return qemu_allocate_irqs(proxy_irq_handler, target, n);
+}
+
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
+{
+ int i;
+ qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n);
+ for (i = 0; i < n; i++) {
+ *old_irqs[i] = *gpio_in[i];
+ gpio_in[i]->handler = handler;
+ gpio_in[i]->opaque = old_irqs;
+ }
+}
+
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n)
+{
+ qemu_irq *old_irqs = *gpio_out;
+ *gpio_out = qemu_allocate_irqs(handler, old_irqs, n);
+}
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index e77ed8a..533935c 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -23,6 +23,7 @@
*/
#include "hw/hw.h"
#include "hw/i386/pc.h"
+#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "monitor/monitor.h"
#include "hw/android/goldfish/device.h"
@@ -61,7 +62,7 @@
qemu_irq parent_irq;
void *irq_request_opaque;
/* IOAPIC callback support */
- SetIRQFunc *alt_irq_func;
+ qemu_irq_handler alt_irq_func;
void *alt_irq_opaque;
};
@@ -563,7 +564,7 @@
return qemu_allocate_irqs(i8259_set_irq, s, GFD_MAX_IRQ);
}
-void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
+void pic_set_alt_irq_func(PicState2 *s, qemu_irq_handler alt_irq_func,
void *alt_irq_opaque)
{
s->alt_irq_func = alt_irq_func;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 80ab1f4..eef15f7 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -38,7 +38,7 @@
pci_map_irq_fn map_irq;
uint32_t config_reg; /* XXX: suppress */
/* low level pic */
- SetIRQFunc *low_set_irq;
+ qemu_irq_handler low_set_irq;
qemu_irq *irq_opaque;
PCIDevice *devices[256];
PCIDevice *parent_dev;
diff --git a/include/hw/android/goldfish/device.h b/include/hw/android/goldfish/device.h
index 40b614e..a62e810 100644
--- a/include/hw/android/goldfish/device.h
+++ b/include/hw/android/goldfish/device.h
@@ -14,6 +14,7 @@
#include "config.h"
#include "exec/cpu-common.h"
+#include "hw/irq.h"
struct goldfish_device {
struct goldfish_device *next;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 4d0e4c6..196bf51 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -4,6 +4,7 @@
#include "cpu.h"
#include "qemu-common.h"
#include "exec/hwaddr.h"
+#include "hw/irq.h"
/* PC-style peripherals (also used by other machines). */
@@ -34,7 +35,7 @@
void pic_set_irq(int irq, int level);
void pic_set_irq_new(void *opaque, int irq, int level);
qemu_irq *i8259_init(qemu_irq parent_irq);
-void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
+void pic_set_alt_irq_func(PicState2 *s, qemu_irq_handler alt_irq_func,
void *alt_irq_opaque);
int pic_read_irq(PicState2 *s);
void pic_update_irq(PicState2 *s);
diff --git a/include/hw/irq.h b/include/hw/irq.h
index 5daae44..d08bc02 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -3,9 +3,9 @@
/* Generic IRQ/GPIO pin infrastructure. */
-/* FIXME: Rmove one of these. */
+typedef struct IRQState *qemu_irq;
+
typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
-typedef void SetIRQFunc(void *opaque, int irq_num, int level);
void qemu_set_irq(qemu_irq irq, int level);
@@ -25,11 +25,40 @@
qemu_set_irq(irq, 0);
}
-/* Returns an array of N IRQs. */
+/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
+ * opaque data.
+ */
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+
+/*
+ * Allocates a single IRQ. The irq is assigned with a handler, an opaque
+ * data and the interrupt number.
+ */
+qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
+
+/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
+ * preserved. New IRQs are assigned the argument handler and opaque data.
+ */
+qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
+ void *opaque, int n);
+
void qemu_free_irqs(qemu_irq *s);
+void qemu_free_irq(qemu_irq irq);
/* Returns a new IRQ with opposite polarity. */
qemu_irq qemu_irq_invert(qemu_irq irq);
+/* Returns a new IRQ which feeds into both the passed IRQs */
+qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
+
+/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
+ * may be set later.
+ */
+qemu_irq *qemu_irq_proxy(qemu_irq **target, int n);
+
+/* For internal use in qtest. Similar to qemu_irq_split, but operating
+ on an existing vector of qemu_irq. */
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n);
+
#endif
diff --git a/qemu-char.c b/qemu-char.c
index 73ba896..e9463d4 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -30,6 +30,7 @@
#include "qemu/timer.h"
#include "sysemu/char.h"
#include "block/block.h"
+#include "hw/irq.h"
#include "hw/msmouse.h"
#include "qapi/qmp/types.h"