summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenric Jungheim <henric@cvs.openbsd.org>2003-05-16 06:59:13 +0000
committerHenric Jungheim <henric@cvs.openbsd.org>2003-05-16 06:59:13 +0000
commitcf599f158458425ae996473b91afe4d3ee83f2be (patch)
tree19aaec28d5c71cd038595bbeb031d75cfd9ffe47
parente150ffcc509a8e9b5e856394113e2afc39791dd5 (diff)
The sparc64 proms do not map all interrupt vectors. Instead of
trying to use the interrupt pin (or is it that the PCI function?) as the interrupt vector, this computes the vector from the PCI bus, slot, and pin. This will only change mappings on psycho-based machines (*not* sabre, i.e., IIi/e) and only for those vectors reported as nonsense INRs (INO 0-3). This should fix the mapping of non-bridge expansion cards on U60 and E450, and other psycho boxen. U30 seems to do its own thing.
-rw-r--r--sys/arch/sparc64/dev/pci_machdep.c11
-rw-r--r--sys/arch/sparc64/dev/psycho.c72
-rw-r--r--sys/arch/sparc64/dev/psychovar.h8
-rw-r--r--sys/arch/sparc64/include/pci_machdep.h4
4 files changed, 87 insertions, 8 deletions
diff --git a/sys/arch/sparc64/dev/pci_machdep.c b/sys/arch/sparc64/dev/pci_machdep.c
index 8e48222337e..c4c01bd2cbe 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.12 2003/05/10 21:11:14 deraadt Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.13 2003/05/16 06:59:12 henric Exp $ */
/* $NetBSD: pci_machdep.c,v 1.22 2001/07/20 00:07:13 eeh Exp $ */
/*
@@ -415,7 +415,11 @@ pci_intr_map(pa, ihp)
/* XXXX -- we use the ino. What if there is a valid IGN? */
*ihp = interrupts;
- return (0);
+
+ if (pa->pa_pc->intr_map)
+ return ((*pa->pa_pc->intr_map)(pa, ihp));
+ else
+ return (0);
}
const char *
@@ -454,7 +458,8 @@ pci_intr_establish(pc, ih, level, func, arg, what)
void *cookie;
struct psycho_pbm *pp = (struct psycho_pbm *)pc->cookie;
- DPRINTF(SPDB_INTR, ("pci_intr_establish: ih %lu; level %d", (u_long)ih, level));
+ DPRINTF(SPDB_INTR, ("pci_intr_establish: ih %lu; level %d",
+ (u_long)ih, level));
cookie = bus_intr_establish(pp->pp_memt, ih, level, 0, func, arg);
DPRINTF(SPDB_INTR, ("; returning handle %p\n", cookie));
diff --git a/sys/arch/sparc64/dev/psycho.c b/sys/arch/sparc64/dev/psycho.c
index 41fc0647006..b879cba10cf 100644
--- a/sys/arch/sparc64/dev/psycho.c
+++ b/sys/arch/sparc64/dev/psycho.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: psycho.c,v 1.30 2003/03/25 22:10:19 jason Exp $ */
+/* $OpenBSD: psycho.c,v 1.31 2003/05/16 06:59:12 henric Exp $ */
/* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */
/*
@@ -44,6 +44,8 @@
#include <sys/time.h>
#include <sys/reboot.h>
+#include <uvm/uvm_extern.h>
+
#define _SPARC_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/autoconf.h>
@@ -119,6 +121,9 @@ int psycho_dmamem_map(bus_dma_tag_t, bus_dma_tag_t, bus_dma_segment_t *, int, si
void psycho_dmamem_unmap(bus_dma_tag_t, bus_dma_tag_t, caddr_t, size_t);
void psycho_map_psycho(struct psycho_softc *, int, bus_addr_t, bus_size_t,
bus_addr_t, bus_size_t);
+int psycho_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
+void psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
+ struct pcibus_attach_args *pa);
/* base pci_chipset */
extern struct sparc_pci_chipset _sparc_pci_chipset;
@@ -306,7 +311,7 @@ psycho_attach(struct device *parent, struct device *self, void *aux)
}
csr = psycho_psychoreg_read(sc, psy_csr);
- sc->sc_ign = 0x7c0; /* APB IGN is always 0x7c */
+ sc->sc_ign = INTMAP_IGN; /* APB IGN is always 0x1f << 6 = 0x7c */
if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
@@ -534,11 +539,39 @@ psycho_attach(struct device *parent, struct device *self, void *aux)
pba.pba_memt = sc->sc_psycho_this->pp_memt;
pba.pba_pc->bustag = sc->sc_configtag;
pba.pba_pc->bushandle = sc->sc_configaddr;
+ pba.pba_pc->intr_map = psycho_intr_map;
+
+ if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
+ psycho_identify_pbm(sc, pp, &pba);
+ else
+ pp->pp_id = PSYCHO_PBM_UNKNOWN;
config_found(self, &pba, psycho_print);
}
void
+psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
+ struct pcibus_attach_args *pa)
+{
+ vaddr_t pci_va = (vaddr_t)bus_space_vaddr(sc->sc_bustag, sc->sc_pcictl);
+ paddr_t pci_pa;
+
+ if (pmap_extract(pmap_kernel(), pci_va, &pci_pa) == 0)
+ pp->pp_id = PSYCHO_PBM_UNKNOWN;
+ else switch(pci_pa & 0xffff) {
+ case 0x2000:
+ pp->pp_id = PSYCHO_PBM_A;
+ break;
+ case 0x4000:
+ pp->pp_id = PSYCHO_PBM_B;
+ break;
+ default:
+ pp->pp_id = PSYCHO_PBM_UNKNOWN;
+ break;
+ }
+}
+
+void
psycho_map_psycho(struct psycho_softc* sc, int do_map, bus_addr_t reg_addr,
bus_size_t reg_size, bus_addr_t pci_addr, bus_size_t pci_size)
{
@@ -986,6 +1019,41 @@ psycho_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr,
}
/*
+ * Bus-specific interrupt mapping
+ */
+int
+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 ino;
+
+ ino = *ihp;
+
+ if ((ino & ~INTMAP_PCIINT) == 0) {
+ 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 |= ((pa->pa_device - 1) << 2) & INTMAP_PCISLOT;
+
+ *ihp = ino;
+ }
+
+ return (0);
+}
+
+/*
* install an interrupt handler for a PCI device
*/
void *
diff --git a/sys/arch/sparc64/dev/psychovar.h b/sys/arch/sparc64/dev/psychovar.h
index aa632dd65ac..0bae3d40d45 100644
--- a/sys/arch/sparc64/dev/psychovar.h
+++ b/sys/arch/sparc64/dev/psychovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: psychovar.h,v 1.5 2003/02/17 01:29:20 henric Exp $ */
+/* $OpenBSD: psychovar.h,v 1.6 2003/05/16 06:59:12 henric Exp $ */
/* $NetBSD: psychovar.h,v 1.6 2001/07/20 00:07:13 eeh Exp $ */
/*
@@ -52,6 +52,12 @@ struct psycho_pbm {
int pp_nrange;
int pp_nintmap;
+ /* PCI Bus Module A or PCI Bus Module B */
+ int pp_id;
+#define PSYCHO_PBM_UNKNOWN 0
+#define PSYCHO_PBM_A 1
+#define PSYCHO_PBM_B 2
+
/* chipset tag for this instance */
pci_chipset_tag_t pp_pc;
diff --git a/sys/arch/sparc64/include/pci_machdep.h b/sys/arch/sparc64/include/pci_machdep.h
index e4ec48540ac..b121e6c77de 100644
--- a/sys/arch/sparc64/include/pci_machdep.h
+++ b/sys/arch/sparc64/include/pci_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.h,v 1.11 2003/02/17 01:29:20 henric Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.12 2003/05/16 06:59:12 henric Exp $ */
/* $NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */
/*
@@ -74,7 +74,7 @@ struct sparc_pci_chipset {
bus_space_handle_t bushandle;
int rootnode; /* PCI controller */
int curnode; /* Current OFW node */
-
+ int (*intr_map)(struct pci_attach_args *, pci_intr_handle_t *);
};
void pci_attach_hook(struct device *, struct device *,