summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 *,