From 3b04cdc3ff7ae587663d97378f727afa528c6ac5 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Tue, 27 Jun 2006 21:22:15 +0000 Subject: Fix interrupt mapping. This now seems to work on all machines, even with pci cards that have a pci-pci bridge and lack fcode. tested by many, ok jason@, dlg@ --- sys/arch/sparc64/dev/psycho.c | 63 +++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'sys/arch/sparc64/dev/psycho.c') diff --git a/sys/arch/sparc64/dev/psycho.c b/sys/arch/sparc64/dev/psycho.c index 0f3defc211d..53c24be1878 100644 --- a/sys/arch/sparc64/dev/psycho.c +++ b/sys/arch/sparc64/dev/psycho.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psycho.c,v 1.43 2006/03/19 02:43:38 brad Exp $ */ +/* $OpenBSD: psycho.c,v 1.44 2006/06/27 21:22:14 kettenis Exp $ */ /* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */ /* @@ -1031,40 +1031,37 @@ psycho_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) struct psycho_pbm *pp = pa->pa_pc->cookie; struct psycho_softc *sc = pp->pp_sc; u_int dev; - u_int ino; - ino = *ihp; - - if ((ino & ~INTMAP_PCIINT) == 0) { - /* - * This deserves some documentation. Should anyone - * have anything official looking, please speak up. - */ - if (sc->sc_mode == PSYCHO_MODE_PSYCHO && - pp->pp_id == PSYCHO_PBM_B) - dev = pa->pa_device - 2; - else - dev = pa->pa_device - 1; - - if (ino == 0 || ino > 4) { - u_int32_t intreg; - - intreg = pci_conf_read(pa->pa_pc, pa->pa_tag, - PCI_INTERRUPT_REG); - - ino = PCI_INTERRUPT_PIN(intreg) - 1; - } else - ino -= 1; - - ino &= INTMAP_PCIINT; - - ino |= sc->sc_ign; - ino |= ((pp->pp_id == PSYCHO_PBM_B) ? INTMAP_PCIBUS : 0); - ino |= (dev << 2) & INTMAP_PCISLOT; - - *ihp = ino; + if (*ihp != (pci_intr_handle_t)-1) { + *ihp |= sc->sc_ign; + return (0); } - + + /* + * We didn't find a PROM mapping for this interrupt. Try to + * construct one ourselves based on the swizzled interrupt pin + * and the interrupt mapping for PCI slots documented in the + * UltraSPARC-IIi User's Manual. + */ + + if (pa->pa_intrpin == 0) + return (-1); + + /* + * This deserves some documentation. Should anyone + * have anything official looking, please speak up. + */ + if (sc->sc_mode == PSYCHO_MODE_PSYCHO && + pp->pp_id == PSYCHO_PBM_B) + dev = PCITAG_DEV(pa->pa_intrtag) - 2; + else + dev = PCITAG_DEV(pa->pa_intrtag) - 1; + + *ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT; + *ihp |= ((pp->pp_id == PSYCHO_PBM_B) ? INTMAP_PCIBUS : 0); + *ihp |= (dev << 2) & INTMAP_PCISLOT; + *ihp |= sc->sc_ign; + return (0); } -- cgit v1.2.3