Add isa_reserve_irq().

Introduce isa_reserve_irq() which marks an irq reserved and returns
the appropriate qemu_irq entry from the i8259 table.

isa_reserve_irq() is a temporary interface to be used to allocate ISA
IRQs for devices which have not yet been converted to qdev, and for
special cases which are not suited for qdev conversions, such as the
'ferr'.

This patch goes on top of Gerd Hoffmann's which makes isa-bus.c own
the ISA irq table.

[ added isa-bus.o to some targets to fix build failures  -- kraxel ]

Signed-off-by: Jes Sorensen <jes@sgi.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/Makefile.target b/Makefile.target
index 0f8137b..7c5f877 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -261,7 +261,7 @@
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 obj-arm-y += pflash_cfi01.o gumstix.o
-obj-arm-y += zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o
+obj-arm-y += zaurus.o ide.o isa-bus.o serial.o spitz.o tosa.o tc6393xb.o
 obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
 obj-arm-y += omap2.o omap_dss.o soc_dma.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
@@ -275,7 +275,7 @@
 
 obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o
-obj-sh4-y += ide.o
+obj-sh4-y += ide.o isa-bus.o
 
 obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
 obj-m68k-y += m68k-semi.o dummy_m68k.o
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 5516867..d482e04 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -60,10 +60,9 @@
 
 typedef struct CSState {
     QEMUSoundCard card;
-    qemu_irq *pic;
+    qemu_irq pic;
     uint32_t regs[CS_REGS];
     uint8_t dregs[CS_DREGS];
-    int irq;
     int dma;
     int port;
     int shift;
@@ -483,7 +482,7 @@
         case Alternate_Feature_Status:
             if ((s->dregs[iaddr] & PI) && !(val & PI)) {
                 /* XXX: TI CI */
-                qemu_irq_lower (s->pic[s->irq]);
+                qemu_irq_lower (s->pic);
                 s->regs[Status] &= ~INT;
             }
             s->dregs[iaddr] = val;
@@ -503,7 +502,7 @@
 
     case Status:
         if (s->regs[Status] & INT) {
-            qemu_irq_lower (s->pic[s->irq]);
+            qemu_irq_lower (s->pic);
         }
         s->regs[Status] &= ~INT;
         s->dregs[Alternate_Feature_Status] &= ~(PI | CI | TI);
@@ -588,7 +587,7 @@
         s->regs[Status] |= INT;
         s->dregs[Alternate_Feature_Status] |= PI;
         s->transferred = 0;
-        qemu_irq_raise (s->pic[s->irq]);
+        qemu_irq_raise (s->pic);
     }
     else {
         s->transferred += written;
@@ -643,8 +642,7 @@
 
     s = qemu_mallocz (sizeof (*s));
 
-    s->pic = pic;
-    s->irq = conf.irq;
+    s->pic = isa_reserve_irq(conf.irq);
     s->dma = conf.dma;
     s->port = conf.port;
 
diff --git a/hw/ide.c b/hw/ide.c
index 0bde632..28b93f4 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -3610,8 +3610,8 @@
     pci_register_bar((PCIDevice *)d, 4, 0x10,
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], isa_reserve_irq(14));
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], isa_reserve_irq(15));
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
@@ -3650,6 +3650,9 @@
     pci_register_bar((PCIDevice *)d, 4, 0x10,
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
+    /*
+     * These should call isa_reserve_irq() instead when MIPS supports it
+     */
     ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
     ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 90a171d..9561c31 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -76,6 +76,27 @@
     }
 }
 
+/*
+ * isa_reserve_irq() reserves the ISA irq and returns the corresponding
+ * qemu_irq entry for the i8259.
+ *
+ * This function is only for special cases such as the 'ferr', and
+ * temporary use for normal devices until they are converted to qdev.
+ */
+qemu_irq isa_reserve_irq(int isairq)
+{
+    if (isairq < 0 || isairq > 15) {
+        fprintf(stderr, "isa irq %d invalid\n", isairq);
+        exit(1);
+    }
+    if (isabus->assigned & (1 << isairq)) {
+        fprintf(stderr, "isa irq %d already assigned\n", isairq);
+        exit(1);
+    }
+    isabus->assigned |= (1 << isairq);
+    return isabus->irqs[isairq];
+}
+
 void isa_init_irq(ISADevice *dev, qemu_irq *p)
 {
     assert(dev->nirqs < ARRAY_SIZE(dev->irqs));
diff --git a/hw/isa.h b/hw/isa.h
index 1a3bb5b..31853a0 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -27,6 +27,7 @@
 ISABus *isa_bus_new(DeviceState *dev);
 void isa_bus_irqs(qemu_irq *irqs);
 void isa_connect_irq(ISADevice *dev, int devirq, int isairq);
+qemu_irq isa_reserve_irq(int isairq);
 void isa_init_irq(ISADevice *dev, qemu_irq *p);
 void isa_qdev_register(ISADeviceInfo *info);
 ISADevice *isa_create_simple(const char *name, uint32_t iobase, uint32_t iobase2);
diff --git a/hw/pc.c b/hw/pc.c
index abb7356..915e691 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1043,13 +1043,14 @@
 }
 #endif
 
-static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
+static void pc_init_ne2k_isa(NICInfo *nd)
 {
     static int nb_ne2k = 0;
 
     if (nb_ne2k == NE2000_NB_MAX)
         return;
-    isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
+    isa_ne2000_init(ne2000_io[nb_ne2k],
+                    isa_reserve_irq(ne2000_irq[nb_ne2k]), nd);
     nb_ne2k++;
 }
 
@@ -1276,7 +1277,6 @@
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
-    ferr_irq = isa_irq[13];
 
     if (pci_enabled) {
         pci_bus = i440fx_init(&i440fx_state, isa_irq);
@@ -1287,6 +1287,8 @@
     }
     isa_bus_irqs(isa_irq);
 
+    ferr_irq = isa_reserve_irq(13);
+
     /* init basic PC hardware */
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
 
@@ -1311,7 +1313,7 @@
         }
     }
 
-    rtc_state = rtc_init(0x70, isa_irq[8], 2000);
+    rtc_state = rtc_init(0x70, isa_reserve_irq(8), 2000);
 
     qemu_register_boot_set(pc_boot_set, rtc_state);
 
@@ -1321,7 +1323,7 @@
     if (pci_enabled) {
         isa_irq_state->ioapic = ioapic_init();
     }
-    pit = pit_init(0x40, isa_irq[0]);
+    pit = pit_init(0x40, isa_reserve_irq(0));
     pcspk_init(pit);
     if (!no_hpet) {
         hpet_init(isa_irq);
@@ -1329,14 +1331,14 @@
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(serial_io[i], isa_irq[serial_irq[i]], 115200,
+            serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200,
                         serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], isa_irq[parallel_irq[i]],
+            parallel_init(parallel_io[i], isa_reserve_irq(parallel_irq[i]),
                           parallel_hds[i]);
         }
     }
@@ -1347,7 +1349,7 @@
         NICInfo *nd = &nd_table[i];
 
         if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
-            pc_init_ne2k_isa(nd, isa_irq);
+            pc_init_ne2k_isa(nd);
         else
             pci_nic_init(nd, "e1000", NULL);
     }
@@ -1368,7 +1370,8 @@
         pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, isa_irq);
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], isa_irq[ide_irq[i]],
+            isa_ide_init(ide_iobase[i], ide_iobase2[i],
+                         isa_reserve_irq(ide_irq[i]),
 	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
         }
     }
@@ -1398,7 +1401,8 @@
         i2c_bus *smbus;
 
         /* TODO: Populate SPD eeprom data.  */
-        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, isa_irq[9]);
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+                              isa_reserve_irq(9));
         for (i = 0; i < 8; i++) {
             DeviceState *eeprom;
             eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
diff --git a/hw/sb16.c b/hw/sb16.c
index 2506d98..9f7680d 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -56,7 +56,7 @@
 
 typedef struct SB16State {
     QEMUSoundCard card;
-    qemu_irq *pic;
+    qemu_irq pic;
     int irq;
     int dma;
     int hdma;
@@ -190,7 +190,7 @@
 {
     SB16State *s = opaque;
     s->can_write = 1;
-    qemu_irq_raise (s->pic[s->irq]);
+    qemu_irq_raise (s->pic);
 }
 
 #define DMA8_AUTO 1
@@ -598,7 +598,7 @@
         case 0xf3:
             dsp_out_data (s, 0xaa);
             s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
-            qemu_irq_raise (s->pic[s->irq]);
+            qemu_irq_raise (s->pic);
             break;
 
         case 0xf9:
@@ -766,7 +766,7 @@
                 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
                 ticks = (bytes * ticks_per_sec) / freq;
                 if (ticks < ticks_per_sec / 1024) {
-                    qemu_irq_raise (s->pic[s->irq]);
+                    qemu_irq_raise (s->pic);
                 }
                 else {
                     if (s->aux_ts) {
@@ -858,10 +858,10 @@
 
 static void reset (SB16State *s)
 {
-    qemu_irq_lower (s->pic[s->irq]);
+    qemu_irq_lower (s->pic);
     if (s->dma_auto) {
-        qemu_irq_raise (s->pic[s->irq]);
-        qemu_irq_lower (s->pic[s->irq]);
+        qemu_irq_raise (s->pic);
+        qemu_irq_lower (s->pic);
     }
 
     s->mixer_regs[0x82] = 0;
@@ -897,7 +897,7 @@
             if (s->v2x6 == 1) {
                 if (0 && s->highspeed) {
                     s->highspeed = 0;
-                    qemu_irq_lower (s->pic[s->irq]);
+                    qemu_irq_lower (s->pic);
                     control (s, 0);
                 }
                 else {
@@ -1008,7 +1008,7 @@
         if (s->mixer_regs[0x82] & 1) {
             ack = 1;
             s->mixer_regs[0x82] &= 1;
-            qemu_irq_lower (s->pic[s->irq]);
+            qemu_irq_lower (s->pic);
         }
         break;
 
@@ -1017,7 +1017,7 @@
         if (s->mixer_regs[0x82] & 2) {
             ack = 1;
             s->mixer_regs[0x82] &= 2;
-            qemu_irq_lower (s->pic[s->irq]);
+            qemu_irq_lower (s->pic);
         }
         break;
 
@@ -1231,7 +1231,7 @@
 
     if (s->left_till_irq <= 0) {
         s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
-        qemu_irq_raise (s->pic[s->irq]);
+        qemu_irq_raise (s->pic);
         if (0 == s->dma_auto) {
             control (s, 0);
             speaker (s, 0);
@@ -1408,8 +1408,7 @@
     s = qemu_mallocz (sizeof (*s));
 
     s->cmd = -1;
-    s->pic = pic;
-    s->irq = conf.irq;
+    s->pic = isa_reserve_irq(conf.irq);
     s->dma = conf.dma;
     s->hdma = conf.hdma;
     s->port = conf.port;