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"