summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2008-07-22 18:47:25 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2008-07-22 18:47:25 +0000
commita37a4907ee2cf3856953e907081d786b12052a58 (patch)
tree8acfab3cac061577cd1ab28f920c9144dbda6a42 /sys/arch
parent789f154baaec675b334ee405c5fc0ce00d31604e (diff)
Proper interrupt swizzling for devices behind bridges; matches what SRM
configures when it can. ok kettenis@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/pci/pci_1000a.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/sys/arch/alpha/pci/pci_1000a.c b/sys/arch/alpha/pci/pci_1000a.c
index 8998babe6b8..22115d0c1fa 100644
--- a/sys/arch/alpha/pci/pci_1000a.c
+++ b/sys/arch/alpha/pci/pci_1000a.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_1000a.c,v 1.9 2008/07/22 18:45:50 miod Exp $ */
+/* $OpenBSD: pci_1000a.c,v 1.10 2008/07/22 18:47:24 miod Exp $ */
/* $NetBSD: pci_1000a.c,v 1.14 2001/07/27 00:25:20 thorpej Exp $ */
/*
@@ -147,7 +147,7 @@ dec_1000a_intr_map(pa, ihp)
{
pcitag_t bustag = pa->pa_intrtag;
int buspin = pa->pa_intrpin, line = pa->pa_intrline;
- int imrbit = 0, device;
+ int imrbit = 0, bus, device;
/*
* Get bit number in mystery ICU imr
*/
@@ -162,13 +162,19 @@ dec_1000a_intr_map(pa, ihp)
/* 5 */ { 1, 0, 0, 0 }, /* Corelle */
/* 6 */ { 10, 0, 0, 0 }, /* Corelle */
/* 7 */ IRQNONE,
- /* 8 */ { 1, 0, 0, 0 }, /* isp behind ppb */
+ /* 8 */ IRQNONE, /* see imrmap2[] below */
/* 9 */ IRQNONE,
/* 10 */ IRQNONE,
/* 11 */ IRQSPLIT(2),
/* 12 */ IRQSPLIT(4),
/* 13 */ IRQSPLIT(6),
/* 14 */ IRQSPLIT(8) /* Corelle */
+ }, imrmap2[][4] = {
+ /* 0 */ { 1, 0, 0, 0 }, /* isp */
+ /* 1 */ IRQSPLIT(8),
+ /* 2 */ IRQSPLIT(10),
+ /* 3 */ IRQSPLIT(12),
+ /* 4 */ IRQSPLIT(14)
};
if (buspin == 0) /* No IRQ used. */
@@ -176,7 +182,7 @@ dec_1000a_intr_map(pa, ihp)
if (!(1 <= buspin && buspin <= 4))
goto bad;
- pci_decompose_tag(pa->pa_pc, bustag, NULL, &device, NULL);
+ pci_decompose_tag(pa->pa_pc, bustag, &bus, &device, NULL);
/*
* The console places the interrupt mapping in the "line" value.
@@ -184,10 +190,37 @@ dec_1000a_intr_map(pa, ihp)
*/
if (line >= 0 && line < PCI_NIRQ) {
imrbit = line + 1;
- } else if (0 <= device && device < sizeof imrmap / sizeof imrmap[0]) {
- if (device == 0)
- printf("dec_1000a_intr_map: ?! UNEXPECTED DEV 0\n");
- imrbit = imrmap[device][buspin - 1];
+ } else {
+ if (pa->pa_bridgetag) {
+ buspin = pa->pa_rawintrpin;
+ bus = pa->pa_bus;
+ device = pa->pa_device;
+
+ if (bus == 2) {
+ /*
+ * Devices behind ppb1 (pci bus #2).
+ * Those use fixed per-slot assignments.
+ */
+ if (0 <= device && device <
+ sizeof imrmap2 / sizeof imrmap2[0]) {
+ imrbit = imrmap2[device][buspin - 1];
+ }
+ } else {
+ /*
+ * Devices behind further ppb.
+ * Those reuse ppb configured interrupts.
+ */
+ buspin = PPB_INTERRUPT_SWIZZLE(buspin, device);
+ if (pa->pa_bridgeih[buspin - 1] != 0) {
+ imrbit =
+ IRQ2IMR(pa->pa_bridgeih[buspin - 1]);
+ }
+ }
+ } else {
+ if (0 <= device &&
+ device < sizeof imrmap / sizeof imrmap[0])
+ imrbit = imrmap[device][buspin - 1];
+ }
}
if (imrbit) {