diff options
-rw-r--r-- | sys/arch/sparc64/dev/pci_machdep.c | 11 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/psycho.c | 72 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/psychovar.h | 8 | ||||
-rw-r--r-- | sys/arch/sparc64/include/pci_machdep.h | 4 |
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 *, |