Provide interrupt mapping information in PCI config registers.

Use system-specific information to program the interrupt line register
with the interrupt mappings, which is what the SRM console does on real
hardware; some operating systems (e.g. NetBSD) use this information
rather than having interrupt mappings tables for every possible system
variation.

Signed-off-by: Jason Thorpe <thorpej@me.com>
Message-Id: <20210603035317.6814-7-thorpej@me.com>
[rth: Use inline not macro; fold -1 -> 0xff map into interface.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/pci.c b/pci.c
index e60af55..351e5aa 100644
--- a/pci.c
+++ b/pci.c
@@ -29,6 +29,7 @@
 #include "protos.h"
 #include "pci.h"
 #include "pci_regs.h"
+#include SYSTEM_H
 
 
 #define PCI_SLOT_MAX		32
@@ -131,7 +132,16 @@
 
   pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
-  /* Map the interrupt.  */
+  /* Map the interrupt and program the IRQ into the line register.
+     Some operating systems rely on the Console providing this information
+     in order to avoid having mapping tables for every possible system
+     variation.  */
+
+  const uint8_t pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
+  const uint8_t slot = PCI_SLOT(bdf);
+  const uint8_t irq = MAP_PCI_INTERRUPT(slot, pin, class_id);
+
+  pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irq);
 }
 
 void
diff --git a/sys-clipper.h b/sys-clipper.h
index 31094ff..7c1fa08 100644
--- a/sys-clipper.h
+++ b/sys-clipper.h
@@ -27,4 +27,21 @@
 #define SYS_VARIATION	(5 << 10)
 #define SYS_REVISION	0
 
+#ifndef __ASSEMBLER__
+
+static inline uint8_t MAP_PCI_INTERRUPT(int slot, int pin, int class_id)
+{
+  uint8_t irq = 0xff; /* no interrupt mapping */
+
+  /* PCI-ISA bridge is hard-wired to IRQ 55 on real hardware, and comes in
+     at a different SCB vector; force the line register to 0xff.
+     Otherwise, see qemu hw/alpha/dp264.c:clipper_pci_map_irq()  */
+  if (class_id != 0x0601 && pin >= 1 && pin <= 4)
+    irq = (slot + 1) * 4 + (pin - 1);
+
+  return irq;
+}
+
+#endif /* ! __ASSEMBLER__ */
+
 #endif