summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-05-03 21:23:05 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-05-03 21:23:05 +0000
commit444cf09812c53e424a7a660801091456e94aeaa0 (patch)
tree6235fdb8b6a09b6eba7f9a6c8839abfedeaaca64
parent85fcad227f1983194b01453d5855f1093bfb187f (diff)
On the UltraBook the PROM privides two interrupts for its ccb(4)'s. Handle
this case by choosing the interrupt that corresponds to the PCI function. Makes the second PCMCIA slot work.
-rw-r--r--sys/arch/sparc64/dev/pci_machdep.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/sys/arch/sparc64/dev/pci_machdep.c b/sys/arch/sparc64/dev/pci_machdep.c
index 0066ec2b73e..08ef6504b91 100644
--- a/sys/arch/sparc64/dev/pci_machdep.c
+++ b/sys/arch/sparc64/dev/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.36 2008/03/24 21:24:30 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.37 2009/05/03 21:23:04 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.22 2001/07/20 00:07:13 eeh Exp $ */
/*
@@ -344,38 +344,47 @@ pci_intr_map(pa, ihp)
pci_intr_handle_t *ihp;
{
pcitag_t tag = pa->pa_tag;
- int interrupts;
+ int interrupts[4], ninterrupts;
int len, node = PCITAG_NODE(tag);
char devtype[30];
len = OF_getproplen(node, "interrupts");
- if (len < 0 || len < sizeof(interrupts)) {
+ if (len < 0 || len < sizeof(interrupts[0])) {
DPRINTF(SPDB_INTMAP,
("pci_intr_map: interrupts len %d too small\n", len));
return (ENODEV);
}
- if (OF_getprop(node, "interrupts", (void *)&interrupts,
- sizeof(interrupts)) != len) {
+ if (OF_getprop(node, "interrupts", interrupts,
+ sizeof(interrupts)) != len) {
DPRINTF(SPDB_INTMAP,
("pci_intr_map: could not read interrupts\n"));
return (ENODEV);
}
- if (OF_mapintr(node, &interrupts, sizeof(interrupts),
- sizeof(interrupts)) < 0) {
- interrupts = -1;
+ /*
+ * If we have multiple interrupts for a device, choose the one
+ * that corresponds to the PCI function. This makes the
+ * second PC Card slot on the UltraBook get the right interrupt.
+ */
+ ninterrupts = len / sizeof(interrupts[0]);
+ if (PCITAG_FUN(pa->pa_tag) < ninterrupts)
+ interrupts[0] = interrupts[PCITAG_FUN(pa->pa_tag)];
+
+ if (OF_mapintr(node, &interrupts[0], sizeof(interrupts[0]),
+ sizeof(interrupts)) < 0) {
+ interrupts[0] = -1;
}
/* Try to find an IPL for this type of device. */
if (OF_getprop(node, "device_type", &devtype, sizeof(devtype)) > 0) {
for (len = 0; intrmap[len].in_class; len++)
if (strcmp(intrmap[len].in_class, devtype) == 0) {
- interrupts |= INTLEVENCODE(intrmap[len].in_lev);
+ interrupts[0] |= INTLEVENCODE(intrmap[len].in_lev);
break;
}
}
/* XXXX -- we use the ino. What if there is a valid IGN? */
- *ihp = interrupts;
+ *ihp = interrupts[0];
if (pa->pa_pc->intr_map)
return ((*pa->pa_pc->intr_map)(pa, ihp));