diff options
-rw-r--r-- | sys/arch/sparc64/dev/iommureg.h | 160 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/iommuvar.h | 79 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/sbus.c | 931 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/sbusreg.h | 192 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/sbusvar.h | 117 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/upavar.h | 145 |
6 files changed, 1624 insertions, 0 deletions
diff --git a/sys/arch/sparc64/dev/iommureg.h b/sys/arch/sparc64/dev/iommureg.h new file mode 100644 index 00000000000..17341c68969 --- /dev/null +++ b/sys/arch/sparc64/dev/iommureg.h @@ -0,0 +1,160 @@ +/* $NetBSD: iommureg.h,v 1.6 2001/07/20 00:07:13 eeh Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sbusreg.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _SPARC64_DEV_IOMMUREG_H_ +#define _SPARC64_DEV_IOMMUREG_H_ + +/* + * UltraSPARC IOMMU registers, common to both the sbus and PCI + * controllers. + */ + +/* iommmu registers */ +struct iommureg { + u_int64_t iommu_cr; /* IOMMU control register */ + u_int64_t iommu_tsb; /* IOMMU TSB base register */ + u_int64_t iommu_flush; /* IOMMU flush register */ +}; + +/* streaming buffer registers */ +struct iommu_strbuf { + u_int64_t strbuf_ctl; /* streaming buffer control reg */ + u_int64_t strbuf_pgflush; /* streaming buffer page flush */ + u_int64_t strbuf_flushsync;/* streaming buffer flush sync */ +}; + +/* streaming buffer control register */ +#define STRBUF_EN 0x000000000000000001LL +#define STRBUF_D 0x000000000000000002LL + +/* control register bits */ +#define IOMMUCR_TSB1K 0x000000000000000000LL /* Nummber of entries in IOTSB */ +#define IOMMUCR_TSB2K 0x000000000000010000LL +#define IOMMUCR_TSB4K 0x000000000000020000LL +#define IOMMUCR_TSB8K 0x000000000000030000LL +#define IOMMUCR_TSB16K 0x000000000000040000LL +#define IOMMUCR_TSB32K 0x000000000000050000LL +#define IOMMUCR_TSB64K 0x000000000000060000LL +#define IOMMUCR_TSB128K 0x000000000000070000LL +#define IOMMUCR_TSBMASK 0xfffffffffffff8ffffLL /* Mask for above */ +#define IOMMUCR_8KPG 0x000000000000000000LL /* 8K iommu page size */ +#define IOMMUCR_64KPG 0x000000000000000004LL /* 64K iommu page size */ +#define IOMMUCR_DE 0x000000000000000002LL /* Diag enable */ +#define IOMMUCR_EN 0x000000000000000001LL /* Enable IOMMU */ + +/* + * IOMMU stuff + */ +#define IOTTE_V 0x8000000000000000LL /* Entry valid */ +#define IOTTE_64K 0x2000000000000000LL /* 8K or 64K page? */ +#define IOTTE_8K 0x0000000000000000LL +#define IOTTE_STREAM 0x1000000000000000LL /* Is page streamable? */ +#define IOTTE_LOCAL 0x0800000000000000LL /* Accesses to same bus segment? */ +#define IOTTE_PAMASK 0x000001ffffffe000LL /* Let's assume this is correct */ +#define IOTTE_C 0x0000000000000010LL /* Accesses to cacheable space */ +#define IOTTE_W 0x0000000000000002LL /* Writeable */ + +/* + * On sun4u each bus controller has a separate IOMMU. The IOMMU has + * a TSB which must be page aligned and physically contiguous. Mappings + * can be of 8K IOMMU pages or 64K IOMMU pages. We use 8K for compatibility + * with the CPU's MMU. + * + * On sysio, psycho, and psycho+, IOMMU TSBs using 8K pages can map the + * following size segments: + * + * VA size VA base TSB size tsbsize + * -------- -------- --------- ------- + * 8MB ff800000 8K 0 + * 16MB ff000000 16K 1 + * 32MB fe000000 32K 2 + * 64MB fc000000 64K 3 + * 128MB f8000000 128K 4 + * 256MB f0000000 256K 5 + * 512MB e0000000 512K 6 + * 1GB c0000000 1MB 7 + * + * Unfortunately, sabres on UltraSPARC IIi and IIe processors does not use + * this scheme to determine the IOVA base address. Instead, bits 31-29 are + * used to check against the Target Address Space register in the IIi and + * the the IOMMU is used if they hit. God knows what goes on in the IIe. + * + */ + + +#define IOTSB_VEND (0xffffffffffffffffLL<<PGSHIFT) +#define IOTSB_VSTART(sz) (u_int)(IOTSB_VEND << ((sz)+10)) + +#define MAKEIOTTE(pa,w,c,s) (((pa)&IOTTE_PAMASK)|((w)?IOTTE_W:0)|((c)?IOTTE_C:0)|((s)?IOTTE_STREAM:0)|(IOTTE_V|IOTTE_8K)) +#define IOTSBSLOT(va,sz) ((u_int)(((vaddr_t)(va))-(is->is_dvmabase))>>PGSHIFT) + +/* + * interrupt map stuff. this belongs elsewhere. + */ + +#define INTMAP_V 0x080000000LL /* Interrupt valid (enabled) */ +#define INTMAP_TID 0x07c000000LL /* UPA target ID mask */ +#define INTMAP_IGN 0x0000007c0LL /* Interrupt group no (sbus only). */ +#define INTMAP_INO 0x00000003fLL /* Interrupt number */ +#define INTMAP_INR (INTMAP_IGN|INTMAP_INO) +#define INTMAP_SBUSSLOT 0x000000018LL /* SBUS slot # */ +#define INTMAP_PCIBUS 0x000000010LL /* PCI bus number (A or B) */ +#define INTMAP_PCISLOT 0x00000000cLL /* PCI slot # */ +#define INTMAP_PCIINT 0x000000003LL /* PCI interrupt #A,#B,#C,#D */ +#define INTMAP_OBIO 0x000000020LL /* Onboard device */ +#define INTMAP_LSHIFT 11 /* Encode level in vector */ +#define INTLEVENCODE(x) (((x)&0x0f)<<INTMAP_LSHIFT) +#define INTLEV(x) (((x)>>INTMAP_LSHIFT)&0x0f) +#define INTVEC(x) ((x)&INTMAP_INR) +#define INTSLOT(x) (((x)>>3)&0x7) +#define INTPRI(x) ((x)&0x7) +#define INTINO(x) ((x)&INTMAP_INO) + +#define INTPCI_MAXOBINO 0x16 /* maximum OBIO INO value for PCI */ +#define INTPCIOBINOX(x) ((x)&0x1f) /* OBIO ino index (for PCI machines) */ +#define INTPCIINOX(x) (((x)&0x1c)>>2) /* PCI ino index */ + +#endif /* _SPARC64_DEV_IOMMUREG_H_ */ diff --git a/sys/arch/sparc64/dev/iommuvar.h b/sys/arch/sparc64/dev/iommuvar.h new file mode 100644 index 00000000000..07ac5d65bfa --- /dev/null +++ b/sys/arch/sparc64/dev/iommuvar.h @@ -0,0 +1,79 @@ +/* $NetBSD: iommuvar.h,v 1.7 2001/07/20 00:07:13 eeh Exp $ */ + +/* + * Copyright (c) 1999 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SPARC64_DEV_IOMMUVAR_H_ +#define _SPARC64_DEV_IOMMUVAR_H_ + +/* + * per-IOMMU state + */ +struct iommu_state { + paddr_t is_ptsb; /* TSB physical address */ + int64_t *is_tsb; /* TSB virtual address */ + int is_tsbsize; /* 0 = 8K, ... */ + u_int is_dvmabase; + int64_t is_cr; /* IOMMU control regiter value */ + struct extent *is_dvmamap; /* DVMA map for this instance */ + + paddr_t is_flushpa; /* used to flush the SBUS */ + /* Needs to be volatile or egcs optimizes away loads */ + volatile int64_t is_flush; + + /* copies of our parents state, to allow us to be self contained */ + bus_space_tag_t is_bustag; /* our bus tag */ + struct iommureg *is_iommu; /* IOMMU registers */ + struct iommu_strbuf *is_sb; /* streaming buffer */ +}; + +/* interfaces for PCI/SBUS code */ +void iommu_init __P((char *, struct iommu_state *, int, u_int32_t)); +void iommu_reset __P((struct iommu_state *)); +void iommu_enter __P((struct iommu_state *, vaddr_t, int64_t, int)); +void iommu_remove __P((struct iommu_state *, vaddr_t, size_t)); + +int iommu_dvmamap_load __P((bus_dma_tag_t, struct iommu_state *, + bus_dmamap_t, void *, bus_size_t, struct proc *, int)); +void iommu_dvmamap_unload __P((bus_dma_tag_t, struct iommu_state *, + bus_dmamap_t)); +int iommu_dvmamap_load_raw __P((bus_dma_tag_t, struct iommu_state *, + bus_dmamap_t, bus_dma_segment_t *, int, int, bus_size_t)); +void iommu_dvmamap_sync __P((bus_dma_tag_t, struct iommu_state *, + bus_dmamap_t, bus_addr_t, bus_size_t, int)); +int iommu_dvmamem_alloc __P((bus_dma_tag_t, struct iommu_state *, + bus_size_t, bus_size_t, bus_size_t, bus_dma_segment_t *, + int, int *, int)); +void iommu_dvmamem_free __P((bus_dma_tag_t, struct iommu_state *, + bus_dma_segment_t *, int)); +int iommu_dvmamem_map __P((bus_dma_tag_t, struct iommu_state *, + bus_dma_segment_t *, int, size_t, caddr_t *, int)); +void iommu_dvmamem_unmap __P((bus_dma_tag_t, struct iommu_state *, + caddr_t, size_t)); + +#endif /* _SPARC64_DEV_IOMMUVAR_H_ */ diff --git a/sys/arch/sparc64/dev/sbus.c b/sys/arch/sparc64/dev/sbus.c new file mode 100644 index 00000000000..91c98c1d2f1 --- /dev/null +++ b/sys/arch/sparc64/dev/sbus.c @@ -0,0 +1,931 @@ +/* $NetBSD: sbus.c,v 1.43 2001/07/20 00:07:13 eeh Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sbus.c 8.1 (Berkeley) 6/11/93 + */ + +/* + * Copyright (c) 1999 Eduardo Horvath + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +/* + * Sbus stuff. + */ + +#include <sys/param.h> +#include <sys/extent.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> + +#include <machine/bus.h> +#include <sparc64/sparc64/cache.h> +#include <sparc64/dev/iommureg.h> +#include <sparc64/dev/iommuvar.h> +#include <sparc64/dev/sbusreg.h> +#include <dev/sbus/sbusvar.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> +#include <machine/sparc64.h> + +#ifdef DEBUG +#define SDB_DVMA 0x1 +#define SDB_INTR 0x2 +int sbus_debug = 0; +#define DPRINTF(l, s) do { if (sbus_debug & l) printf s; } while (0) +#else +#define DPRINTF(l, s) +#endif + +void sbusreset __P((int)); + +static bus_space_tag_t sbus_alloc_bustag __P((struct sbus_softc *)); +static bus_dma_tag_t sbus_alloc_dmatag __P((struct sbus_softc *)); +static int sbus_get_intr __P((struct sbus_softc *, int, + struct sbus_intr **, int *, int)); +static int sbus_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t, + int, bus_space_handle_t *)); +static int sbus_overtemp __P((void *)); +static int _sbus_bus_map __P(( + bus_space_tag_t, + bus_type_t, + bus_addr_t, /*offset*/ + bus_size_t, /*size*/ + int, /*flags*/ + vaddr_t, /*preferred virtual address */ + bus_space_handle_t *)); +static void *sbus_intr_establish __P(( + bus_space_tag_t, + int, /*Sbus interrupt level*/ + int, /*`device class' priority*/ + int, /*flags*/ + int (*) __P((void *)), /*handler*/ + void *)); /*handler arg*/ + + +/* autoconfiguration driver */ +int sbus_match __P((struct device *, void *, void *)); +void sbus_attach __P((struct device *, struct device *, void *)); + + +struct cfattach sbus_ca = { + sizeof(struct sbus_softc), sbus_match, sbus_attach +}; + +extern struct cfdriver sbus_cd; + +/* + * DVMA routines + */ +int sbus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); +void sbus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); +int sbus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); +void sbus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int)); +int sbus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, + int flags)); +void sbus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs)); +int sbus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags)); +void sbus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva, + size_t size)); + +/* + * Child devices receive the Sbus interrupt level in their attach + * arguments. We translate these to CPU IPLs using the following + * tables. Note: obio bus interrupt levels are identical to the + * processor IPL. + * + * The second set of tables is used when the Sbus interrupt level + * cannot be had from the PROM as an `interrupt' property. We then + * fall back on the `intr' property which contains the CPU IPL. + */ + +/* Translate Sbus interrupt level to processor IPL */ +static int intr_sbus2ipl_4c[] = { + 0, 1, 2, 3, 5, 7, 8, 9 +}; +static int intr_sbus2ipl_4m[] = { + 0, 2, 3, 5, 7, 9, 11, 13 +}; + +/* + * This value is or'ed into the attach args' interrupt level cookie + * if the interrupt level comes from an `intr' property, i.e. it is + * not an Sbus interrupt level. + */ +#define SBUS_INTR_COMPAT 0x80000000 + + +/* + * Print the location of some sbus-attached device (called just + * before attaching that device). If `sbus' is not NULL, the + * device was found but not configured; print the sbus as well. + * Return UNCONF (config_find ignores this if the device was configured). + */ +int +sbus_print(args, busname) + void *args; + const char *busname; +{ + struct sbus_attach_args *sa = args; + int i; + + if (busname) + printf("%s at %s", sa->sa_name, busname); + printf(" slot %ld offset 0x%lx", (long)sa->sa_slot, + (u_long)sa->sa_offset); + for (i = 0; i < sa->sa_nintr; i++) { + struct sbus_intr *sbi = &sa->sa_intr[i]; + + printf(" vector %lx ipl %ld", + (u_long)sbi->sbi_vec, + (long)INTLEV(sbi->sbi_pri)); + } + return (UNCONF); +} + +int +sbus_match(parent, vcf, aux) + struct device *parent; + void *vcf; + void *aux; +{ + struct cfdata *cf = vcf; + struct mainbus_attach_args *ma = aux; + + return (strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0); +} + +/* + * Attach an Sbus. + */ +void +sbus_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct sbus_softc *sc = (struct sbus_softc *)self; + struct mainbus_attach_args *ma = aux; + struct intrhand *ih; + int ipl; + char *name; + int node = ma->ma_node; + + int node0, error; + bus_space_tag_t sbt; + struct sbus_attach_args sa; + + sc->sc_bustag = ma->ma_bustag; + sc->sc_dmatag = ma->ma_dmatag; + sc->sc_sysio = (struct sysioreg*)(u_long)ma->ma_address[0]; /* Use prom mapping for sysio. */ + sc->sc_ign = ma->ma_interrupts[0] & INTMAP_IGN; /* Find interrupt group no */ + + /* Setup interrupt translation tables */ + sc->sc_intr2ipl = CPU_ISSUN4C + ? intr_sbus2ipl_4c + : intr_sbus2ipl_4m; + + /* + * Record clock frequency for synchronous SCSI. + * IS THIS THE CORRECT DEFAULT?? + */ + sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000); + printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq)); + + sbt = sbus_alloc_bustag(sc); + sc->sc_dmatag = sbus_alloc_dmatag(sc); + + /* + * Get the SBus burst transfer size if burst transfers are supported + */ + sc->sc_burst = getpropint(node, "burst-sizes", 0); + + /* + * Collect address translations from the OBP. + */ + error = getprop(node, "ranges", sizeof(struct sbus_range), + &sc->sc_nrange, (void **)&sc->sc_range); + if (error) + panic("%s: error getting ranges property", sc->sc_dev.dv_xname); + + /* initailise the IOMMU */ + + /* punch in our copies */ + sc->sc_is.is_bustag = sc->sc_bustag; + sc->sc_is.is_iommu = &sc->sc_sysio->sys_iommu; + sc->sc_is.is_sb = &sc->sc_sysio->sys_strbuf; + + /* give us a nice name.. */ + name = (char *)malloc(32, M_DEVBUF, M_NOWAIT); + if (name == 0) + panic("couldn't malloc iommu name"); + snprintf(name, 32, "%s dvma", sc->sc_dev.dv_xname); + + iommu_init(name, &sc->sc_is, 0, -1); + + /* Enable the over temp intr */ + ih = (struct intrhand *) + malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT); + ih->ih_map = &sc->sc_sysio->therm_int_map; + ih->ih_clr = NULL; /* &sc->sc_sysio->therm_clr_int; */ + ih->ih_fun = sbus_overtemp; + ipl = 1; + ih->ih_pil = (1<<ipl); + ih->ih_number = INTVEC(*(ih->ih_map)); + intr_establish(ipl, ih); + *(ih->ih_map) |= INTMAP_V; + + /* + * Note: the stupid SBUS IOMMU ignores the high bits of an address, so a + * NULL DMA pointer will be translated by the first page of the IOTSB. + * To avoid bugs we'll alloc and ignore the first entry in the IOTSB. + */ + { + u_long dummy; + + if (extent_alloc_subregion(sc->sc_is.is_dvmamap, + sc->sc_is.is_dvmabase, sc->sc_is.is_dvmabase + NBPG, + NBPG, NBPG, 0, 0, EX_NOWAIT|EX_BOUNDZERO, + (u_long *)&dummy) != 0) + panic("sbus iommu: can't toss first dvma page"); + } + + /* + * Loop through ROM children, fixing any relative addresses + * and then configuring each device. + * `specials' is an array of device names that are treated + * specially: + */ + node0 = firstchild(node); + for (node = node0; node; node = nextsibling(node)) { + char *name = getpropstring(node, "name"); + + if (sbus_setup_attach_args(sc, sbt, sc->sc_dmatag, + node, &sa) != 0) { + printf("sbus_attach: %s: incomplete\n", name); + continue; + } + (void) config_found(&sc->sc_dev, (void *)&sa, sbus_print); + sbus_destroy_attach_args(&sa); + } +} + +int +sbus_setup_attach_args(sc, bustag, dmatag, node, sa) + struct sbus_softc *sc; + bus_space_tag_t bustag; + bus_dma_tag_t dmatag; + int node; + struct sbus_attach_args *sa; +{ + /*struct sbus_reg sbusreg;*/ + /*int base;*/ + int error; + int n; + + bzero(sa, sizeof(struct sbus_attach_args)); + error = getprop(node, "name", 1, &n, (void **)&sa->sa_name); + if (error != 0) + return (error); + sa->sa_name[n] = '\0'; + + sa->sa_bustag = bustag; + sa->sa_dmatag = dmatag; + sa->sa_node = node; + sa->sa_frequency = sc->sc_clockfreq; + + error = getprop(node, "reg", sizeof(struct sbus_reg), + &sa->sa_nreg, (void **)&sa->sa_reg); + if (error != 0) { + char buf[32]; + if (error != ENOENT || + !node_has_property(node, "device_type") || + strcmp(getpropstringA(node, "device_type", buf), + "hierarchical") != 0) + return (error); + } + for (n = 0; n < sa->sa_nreg; n++) { + /* Convert to relative addressing, if necessary */ + u_int32_t base = sa->sa_reg[n].sbr_offset; + if (SBUS_ABS(base)) { + sa->sa_reg[n].sbr_slot = SBUS_ABS_TO_SLOT(base); + sa->sa_reg[n].sbr_offset = SBUS_ABS_TO_OFFSET(base); + } + } + + if ((error = sbus_get_intr(sc, node, &sa->sa_intr, &sa->sa_nintr, + sa->sa_slot)) != 0) + return (error); + + error = getprop(node, "address", sizeof(u_int32_t), + &sa->sa_npromvaddrs, (void **)&sa->sa_promvaddrs); + if (error != 0 && error != ENOENT) + return (error); + + return (0); +} + +void +sbus_destroy_attach_args(sa) + struct sbus_attach_args *sa; +{ + if (sa->sa_name != NULL) + free(sa->sa_name, M_DEVBUF); + + if (sa->sa_nreg != 0) + free(sa->sa_reg, M_DEVBUF); + + if (sa->sa_intr) + free(sa->sa_intr, M_DEVBUF); + + if (sa->sa_promvaddrs) + free((void *)sa->sa_promvaddrs, M_DEVBUF); + + bzero(sa, sizeof(struct sbus_attach_args)); /*DEBUG*/ +} + + +int +_sbus_bus_map(t, btype, offset, size, flags, vaddr, hp) + bus_space_tag_t t; + bus_type_t btype; + bus_addr_t offset; + bus_size_t size; + int flags; + vaddr_t vaddr; + bus_space_handle_t *hp; +{ + struct sbus_softc *sc = t->cookie; + int64_t slot = btype; + int i; + + for (i = 0; i < sc->sc_nrange; i++) { + bus_addr_t paddr; + + if (sc->sc_range[i].cspace != slot) + continue; + + /* We've found the connection to the parent bus */ + paddr = sc->sc_range[i].poffset + offset; + paddr |= ((bus_addr_t)sc->sc_range[i].pspace<<32); + DPRINTF(SDB_DVMA, +("\n_sbus_bus_map: mapping paddr slot %lx offset %lx poffset %lx paddr %lx\n", + (long)slot, (long)offset, (long)sc->sc_range[i].poffset, + (long)paddr)); + return (bus_space_map2(sc->sc_bustag, 0, paddr, + size, flags, vaddr, hp)); + } + + return (EINVAL); +} + +int +sbus_bus_mmap(t, btype, paddr, flags, hp) + bus_space_tag_t t; + bus_type_t btype; + bus_addr_t paddr; + int flags; + bus_space_handle_t *hp; +{ + bus_addr_t offset = paddr; + int slot = btype; + struct sbus_softc *sc = t->cookie; + int i; + + for (i = 0; i < sc->sc_nrange; i++) { + bus_addr_t paddr; + + if (sc->sc_range[i].cspace != slot) + continue; + + paddr = sc->sc_range[i].poffset + offset; + paddr |= ((bus_addr_t)sc->sc_range[i].pspace<<32); + return (bus_space_mmap(sc->sc_bustag, 0, paddr, + flags, hp)); + } + + return (-1); +} + + +/* + * Each attached device calls sbus_establish after it initializes + * its sbusdev portion. + */ +void +sbus_establish(sd, dev) + register struct sbusdev *sd; + register struct device *dev; +{ + register struct sbus_softc *sc; + register struct device *curdev; + + /* + * We have to look for the sbus by name, since it is not necessarily + * our immediate parent (i.e. sun4m /iommu/sbus/espdma/esp) + * We don't just use the device structure of the above-attached + * sbus, since we might (in the future) support multiple sbus's. + */ + for (curdev = dev->dv_parent; ; curdev = curdev->dv_parent) { + if (!curdev || !curdev->dv_xname) + panic("sbus_establish: can't find sbus parent for %s", + sd->sd_dev->dv_xname + ? sd->sd_dev->dv_xname + : "<unknown>" ); + + if (strncmp(curdev->dv_xname, "sbus", 4) == 0) + break; + } + sc = (struct sbus_softc *) curdev; + + sd->sd_dev = dev; + sd->sd_bchain = sc->sc_sbdev; + sc->sc_sbdev = sd; +} + +/* + * Reset the given sbus. + */ +void +sbusreset(sbus) + int sbus; +{ + register struct sbusdev *sd; + struct sbus_softc *sc = sbus_cd.cd_devs[sbus]; + struct device *dev; + + printf("reset %s:", sc->sc_dev.dv_xname); + for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) { + if (sd->sd_reset) { + dev = sd->sd_dev; + (*sd->sd_reset)(dev); + printf(" %s", dev->dv_xname); + } + } + /* Reload iommu regs */ + iommu_reset(&sc->sc_is); +} + +/* + * Handle an overtemp situation. + * + * SPARCs have temperature sensors which generate interrupts + * if the machine's temperature exceeds a certain threshold. + * This handles the interrupt and powers off the machine. + * The same needs to be done to PCI controller drivers. + */ +int +sbus_overtemp(arg) + void *arg; +{ + /* Should try a clean shutdown first */ + printf("DANGER: OVER TEMPERATURE detected\nShutting down...\n"); + delay(20); + boot(RB_POWERDOWN|RB_HALT); + /*NOTREACHED*/ + return (1); +} + +/* + * Get interrupt attributes for an Sbus device. + */ +int +sbus_get_intr(sc, node, ipp, np, slot) + struct sbus_softc *sc; + int node; + struct sbus_intr **ipp; + int *np; + int slot; +{ + int *ipl; + int n, i; + char buf[32]; + + /* + * The `interrupts' property contains the Sbus interrupt level. + */ + ipl = NULL; + if (getprop(node, "interrupts", sizeof(int), np, (void **)&ipl) == 0) { + struct sbus_intr *ip; + int pri; + + /* Default to interrupt level 2 -- otherwise unused */ + pri = INTLEVENCODE(2); + + /* Change format to an `struct sbus_intr' array */ + ip = malloc(*np * sizeof(struct sbus_intr), M_DEVBUF, M_NOWAIT); + if (ip == NULL) + return (ENOMEM); + + /* + * Now things get ugly. We need to take this value which is + * the interrupt vector number and encode the IPL into it + * somehow. Luckily, the interrupt vector has lots of free + * space and we can easily stuff the IPL in there for a while. + */ + getpropstringA(node, "device_type", buf); + if (!buf[0]) + getpropstringA(node, "name", buf); + + for (i = 0; intrmap[i].in_class; i++) + if (strcmp(intrmap[i].in_class, buf) == 0) { + pri = INTLEVENCODE(intrmap[i].in_lev); + break; + } + + /* + * Sbus card devices need the slot number encoded into + * the vector as this is generally not done. + */ + if ((ipl[0] & INTMAP_OBIO) == 0) + pri |= slot << 3; + + for (n = 0; n < *np; n++) { + /* + * We encode vector and priority into sbi_pri so we + * can pass them as a unit. This will go away if + * sbus_establish ever takes an sbus_intr instead + * of an integer level. + * Stuff the real vector in sbi_vec. + */ + + ip[n].sbi_pri = pri|ipl[n]; + ip[n].sbi_vec = ipl[n]; + } + free(ipl, M_DEVBUF); + *ipp = ip; + } + + return (0); +} + + +/* + * Install an interrupt handler for an Sbus device. + */ +void * +sbus_intr_establish(t, pri, level, flags, handler, arg) + bus_space_tag_t t; + int pri; + int level; + int flags; + int (*handler) __P((void *)); + void *arg; +{ + struct sbus_softc *sc = t->cookie; + struct intrhand *ih; + int ipl; + long vec = pri; + + ih = (struct intrhand *) + malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT); + if (ih == NULL) + return (NULL); + + if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) != 0) + ipl = vec; + else if ((vec & SBUS_INTR_COMPAT) != 0) + ipl = vec & ~SBUS_INTR_COMPAT; + else { + /* Decode and remove IPL */ + ipl = INTLEV(vec); + vec = INTVEC(vec); + DPRINTF(SDB_INTR, + ("\nsbus: intr[%ld]%lx: %lx\nHunting for IRQ...\n", + (long)ipl, (long)vec, (u_long)intrlev[vec])); + if ((vec & INTMAP_OBIO) == 0) { + /* We're in an SBUS slot */ + /* Register the map and clear intr registers */ + + int slot = INTSLOT(pri); + + ih->ih_map = &(&sc->sc_sysio->sbus_slot0_int)[slot]; + ih->ih_clr = &sc->sc_sysio->sbus0_clr_int[vec]; +#ifdef DEBUG + if (sbus_debug & SDB_INTR) { + int64_t intrmap = *ih->ih_map; + + printf("SBUS %lx IRQ as %llx in slot %d\n", + (long)vec, (long long)intrmap, slot); + printf("\tmap addr %p clr addr %p\n", + ih->ih_map, ih->ih_clr); + } +#endif + /* Enable the interrupt */ + vec |= INTMAP_V; + /* Insert IGN */ + vec |= sc->sc_ign; + bus_space_write_8(sc->sc_bustag, + (bus_space_handle_t)(u_long)ih->ih_map, 0, vec); + } else { + int64_t *intrptr = &sc->sc_sysio->scsi_int_map; + int64_t intrmap = 0; + int i; + + /* Insert IGN */ + vec |= sc->sc_ign; + for (i = 0; &intrptr[i] <= + (int64_t *)&sc->sc_sysio->reserved_int_map && + INTVEC(intrmap = intrptr[i]) != INTVEC(vec); i++) + ; + if (INTVEC(intrmap) == INTVEC(vec)) { + DPRINTF(SDB_INTR, + ("OBIO %lx IRQ as %lx in slot %d\n", + vec, (long)intrmap, i)); + /* Register the map and clear intr registers */ + ih->ih_map = &intrptr[i]; + intrptr = (int64_t *)&sc->sc_sysio->scsi_clr_int; + ih->ih_clr = &intrptr[i]; + /* Enable the interrupt */ + intrmap |= INTMAP_V; + bus_space_write_8(sc->sc_bustag, + (bus_space_handle_t)(u_long)ih->ih_map, 0, + (u_long)intrmap); + } else + panic("IRQ not found!"); + } + } +#ifdef DEBUG + if (sbus_debug & SDB_INTR) { long i; for (i = 0; i < 400000000; i++); } +#endif + + ih->ih_fun = handler; + ih->ih_arg = arg; + ih->ih_number = vec; + ih->ih_pil = (1<<ipl); + intr_establish(ipl, ih); + return (ih); +} + +static bus_space_tag_t +sbus_alloc_bustag(sc) + struct sbus_softc *sc; +{ + bus_space_tag_t sbt; + + sbt = (bus_space_tag_t) + malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT); + if (sbt == NULL) + return (NULL); + + bzero(sbt, sizeof *sbt); + sbt->cookie = sc; + sbt->parent = sc->sc_bustag; + sbt->type = SBUS_BUS_SPACE; + sbt->sparc_bus_map = _sbus_bus_map; + sbt->sparc_bus_mmap = sbus_bus_mmap; + sbt->sparc_intr_establish = sbus_intr_establish; + return (sbt); +} + + +static bus_dma_tag_t +sbus_alloc_dmatag(sc) + struct sbus_softc *sc; +{ + bus_dma_tag_t sdt, psdt = sc->sc_dmatag; + + sdt = (bus_dma_tag_t) + malloc(sizeof(struct sparc_bus_dma_tag), M_DEVBUF, M_NOWAIT); + if (sdt == NULL) + /* Panic? */ + return (psdt); + + sdt->_cookie = sc; + sdt->_parent = psdt; +#define PCOPY(x) sdt->x = psdt->x + PCOPY(_dmamap_create); + PCOPY(_dmamap_destroy); + sdt->_dmamap_load = sbus_dmamap_load; + PCOPY(_dmamap_load_mbuf); + PCOPY(_dmamap_load_uio); + sdt->_dmamap_load_raw = sbus_dmamap_load_raw; + sdt->_dmamap_unload = sbus_dmamap_unload; + sdt->_dmamap_sync = sbus_dmamap_sync; + sdt->_dmamem_alloc = sbus_dmamem_alloc; + sdt->_dmamem_free = sbus_dmamem_free; + sdt->_dmamem_map = sbus_dmamem_map; + sdt->_dmamem_unmap = sbus_dmamem_unmap; + PCOPY(_dmamem_mmap); +#undef PCOPY + sc->sc_dmatag = sdt; + return (sdt); +} + +int +sbus_dmamap_load(tag, map, buf, buflen, p, flags) + bus_dma_tag_t tag; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + return (iommu_dvmamap_load(tag, &sc->sc_is, map, buf, buflen, p, flags)); +} + +int +sbus_dmamap_load_raw(tag, map, segs, nsegs, size, flags) + bus_dma_tag_t tag; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + return (iommu_dvmamap_load_raw(tag, &sc->sc_is, map, segs, nsegs, flags, size)); +} + +void +sbus_dmamap_unload(tag, map) + bus_dma_tag_t tag; + bus_dmamap_t map; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + iommu_dvmamap_unload(tag, &sc->sc_is, map); +} + +void +sbus_dmamap_sync(tag, map, offset, len, ops) + bus_dma_tag_t tag; + bus_dmamap_t map; + bus_addr_t offset; + bus_size_t len; + int ops; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + if (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) { + /* Flush the CPU then the IOMMU */ + bus_dmamap_sync(tag->_parent, map, offset, len, ops); + iommu_dvmamap_sync(tag, &sc->sc_is, map, offset, len, ops); + } + if (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) { + /* Flush the IOMMU then the CPU */ + iommu_dvmamap_sync(tag, &sc->sc_is, map, offset, len, ops); + bus_dmamap_sync(tag->_parent, map, offset, len, ops); + } +} + +int +sbus_dmamem_alloc(tag, size, alignment, boundary, segs, nsegs, rsegs, flags) + bus_dma_tag_t tag; + bus_size_t size; + bus_size_t alignment; + bus_size_t boundary; + bus_dma_segment_t *segs; + int nsegs; + int *rsegs; + int flags; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + return (iommu_dvmamem_alloc(tag, &sc->sc_is, size, alignment, boundary, + segs, nsegs, rsegs, flags)); +} + +void +sbus_dmamem_free(tag, segs, nsegs) + bus_dma_tag_t tag; + bus_dma_segment_t *segs; + int nsegs; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + iommu_dvmamem_free(tag, &sc->sc_is, segs, nsegs); +} + +int +sbus_dmamem_map(tag, segs, nsegs, size, kvap, flags) + bus_dma_tag_t tag; + bus_dma_segment_t *segs; + int nsegs; + size_t size; + caddr_t *kvap; + int flags; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + return (iommu_dvmamem_map(tag, &sc->sc_is, segs, nsegs, size, kvap, flags)); +} + +void +sbus_dmamem_unmap(tag, kva, size) + bus_dma_tag_t tag; + caddr_t kva; + size_t size; +{ + struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie; + + iommu_dvmamem_unmap(tag, &sc->sc_is, kva, size); +} diff --git a/sys/arch/sparc64/dev/sbusreg.h b/sys/arch/sparc64/dev/sbusreg.h new file mode 100644 index 00000000000..a53429f8f62 --- /dev/null +++ b/sys/arch/sparc64/dev/sbusreg.h @@ -0,0 +1,192 @@ +/* $NetBSD: sbusreg.h,v 1.7 1999/06/07 05:28:03 eeh Exp $ */ + +/* + * Copyright (c) 1996-1999 Eduardo Horvath + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + + +/* + * Sbus device addresses are obtained from the FORTH PROMs. They come + * in `absolute' and `relative' address flavors, so we have to handle both. + * Relative addresses do *not* include the slot number. + */ +#define SBUS_BASE 0xf8000000 +#define SBUS_ADDR(slot, off) (SBUS_BASE + ((slot) << 25) + (off)) +#define SBUS_ABS(a) ((unsigned)(a) >= SBUS_BASE) +#define SBUS_ABS_TO_SLOT(a) (((a) - SBUS_BASE) >> 25) +#define SBUS_ABS_TO_OFFSET(a) (((a) - SBUS_BASE) & 0x1ffffff) + +/* + * Sun4u S-bus definitions. Here's where we deal w/the machine + * dependencies of sysio. + * + * SYSIO implements or is the interface to several things: + * + * o The SBUS interface itself + * o The IOMMU + * o The DVMA units + * o The interrupt controller + * o The counter/timers + * + * Since it has registers to control lots of different things + * as well as several on-board SBUS devices and external SBUS + * slots scattered throughout its address space, it's a pain. + * + * One good point, however, is that all registers are 64-bit. + */ + +struct sysioreg { + struct upareg { + u_int64_t upa_portid; /* UPA port ID register */ /* 1fe.0000.0000 */ + u_int64_t upa_config; /* UPA config register */ /* 1fe.0000.0008 */ + } sys_upa; + + u_int64_t sys_csr; /* SYSIO control/status register */ /* 1fe.0000.0010 */ + u_int64_t pad0; + u_int64_t sys_ecccr; /* ECC control register */ /* 1fe.0000.0020 */ + u_int64_t reserved; /* 1fe.0000.0028 */ + u_int64_t sys_ue_afsr; /* Uncorrectable Error AFSR */ /* 1fe.0000.0030 */ + u_int64_t sys_ue_afar; /* Uncorrectable Error AFAR */ /* 1fe.0000.0038 */ + u_int64_t sys_ce_afsr; /* Correctable Error AFSR */ /* 1fe.0000.0040 */ + u_int64_t sys_ce_afar; /* Correctable Error AFAR */ /* 1fe.0000.0048 */ + + u_int64_t pad1[22]; + + struct perfmon { + u_int64_t pm_cr; /* Performance monitor control reg */ /* 1fe.0000.0100 */ + u_int64_t pm_count; /* Performance monitor counter reg */ /* 1fe.0000.0108 */ + } sys_pm; + + u_int64_t pad2[990]; + + struct sbusreg { + u_int64_t sbus_cr; /* SBUS Control Register */ /* 1fe.0000.2000 */ + u_int64_t reserved; /* 1fe.0000.2008 */ + u_int64_t sbus_afsr; /* SBUS AFSR */ /* 1fe.0000.2010 */ + u_int64_t sbus_afar; /* SBUS AFAR */ /* 1fe.0000.2018 */ + u_int64_t sbus_config0; /* SBUS Slot 0 config register */ /* 1fe.0000.2020 */ + u_int64_t sbus_config1; /* SBUS Slot 1 config register */ /* 1fe.0000.2028 */ + u_int64_t sbus_config2; /* SBUS Slot 2 config register */ /* 1fe.0000.2030 */ + u_int64_t sbus_config3; /* SBUS Slot 3 config register */ /* 1fe.0000.2038 */ + u_int64_t sbus_config13; /* Slot 13 config register <audio> */ /* 1fe.0000.2040 */ + u_int64_t sbus_config14; /* Slot 14 config register <macio> */ /* 1fe.0000.2048 */ + u_int64_t sbus_config15; /* Slot 15 config register <slavio> */ /* 1fe.0000.2050 */ + } sys_sbus; + + u_int64_t pad3[117]; + + struct iommureg sys_iommu; /* 1fe.0000.2400,2410 */ + + u_int64_t pad4[125]; + + struct iommu_strbuf sys_strbuf; /* 1fe.0000.2800-2810 */ + + u_int64_t pad5[125]; + + u_int64_t sbus_slot0_int; /* SBUS slot 0 interrupt map reg */ /* 1fe.0000.2c00 */ + u_int64_t sbus_slot1_int; /* SBUS slot 1 interrupt map reg */ /* 1fe.0000.2c08 */ + u_int64_t sbus_slot2_int; /* SBUS slot 2 interrupt map reg */ /* 1fe.0000.2c10 */ + u_int64_t sbus_slot3_int; /* SBUS slot 3 interrupt map reg */ /* 1fe.0000.2c18 */ + u_int64_t intr_retry; /* interrupt retry timer reg */ /* 1fe.0000.2c20 */ + + u_int64_t pad6[123]; + + u_int64_t scsi_int_map; /* SCSI interrupt map reg */ /* 1fe.0000.3000 */ + u_int64_t ether_int_map; /* ethernet interrupt map reg */ /* 1fe.0000.3008 */ + u_int64_t bpp_int_map; /* parallel interrupt map reg */ /* 1fe.0000.3010 */ + u_int64_t audio_int_map; /* audio interrupt map reg */ /* 1fe.0000.3018 */ + u_int64_t power_int_map; /* power fail interrupt map reg */ /* 1fe.0000.3020 */ + u_int64_t ser_kbd_ms_int_map; /* serial/kbd/mouse interrupt map reg *//* 1fe.0000.3028 */ + u_int64_t fd_int_map; /* floppy interrupt map reg */ /* 1fe.0000.3030 */ + u_int64_t therm_int_map; /* thermal warn interrupt map reg */ /* 1fe.0000.3038 */ + u_int64_t kbd_int_map; /* kbd [unused] interrupt map reg */ /* 1fe.0000.3040 */ + u_int64_t mouse_int_map; /* mouse [unused] interrupt map reg */ /* 1fe.0000.3048 */ + u_int64_t serial_int_map; /* second serial interrupt map reg */ /* 1fe.0000.3050 */ + u_int64_t pad7; + u_int64_t timer0_int_map; /* timer 0 interrupt map reg */ /* 1fe.0000.3060 */ + u_int64_t timer1_int_map; /* timer 1 interrupt map reg */ /* 1fe.0000.3068 */ + u_int64_t ue_int_map; /* UE interrupt map reg */ /* 1fe.0000.3070 */ + u_int64_t ce_int_map; /* CE interrupt map reg */ /* 1fe.0000.3078 */ + u_int64_t sbus_async_int_map; /* SBUS error interrupt map reg */ /* 1fe.0000.3080 */ + u_int64_t pwrmgt_int_map; /* power mgmt wake interrupt map reg */ /* 1fe.0000.3088 */ + u_int64_t upagr_int_map; /* UPA graphics interrupt map reg */ /* 1fe.0000.3090 */ + u_int64_t reserved_int_map; /* reserved interrupt map reg */ /* 1fe.0000.3098 */ + + u_int64_t pad8[108]; + + /* Note: clear interrupt 0 registers are not really used */ + u_int64_t sbus0_clr_int[8]; /* SBUS slot 0 clear int regs 0..7 */ /* 1fe.0000.3400-3438 */ + u_int64_t sbus1_clr_int[8]; /* SBUS slot 1 clear int regs 0..7 */ /* 1fe.0000.3440-3478 */ + u_int64_t sbus2_clr_int[8]; /* SBUS slot 2 clear int regs 0..7 */ /* 1fe.0000.3480-34b8 */ + u_int64_t sbus3_clr_int[8]; /* SBUS slot 3 clear int regs 0..7 */ /* 1fe.0000.34c0-34f8 */ + + u_int64_t pad9[96]; + + u_int64_t scsi_clr_int; /* SCSI clear int reg */ /* 1fe.0000.3800 */ + u_int64_t ether_clr_int; /* ethernet clear int reg */ /* 1fe.0000.3808 */ + u_int64_t bpp_clr_int; /* parallel clear int reg */ /* 1fe.0000.3810 */ + u_int64_t audio_clr_int; /* audio clear int reg */ /* 1fe.0000.3818 */ + u_int64_t power_clr_int; /* power fail clear int reg */ /* 1fe.0000.3820 */ + u_int64_t ser_kb_ms_clr_int; /* serial/kbd/mouse clear int reg */ /* 1fe.0000.3828 */ + u_int64_t fd_clr_int; /* floppy clear int reg */ /* 1fe.0000.3830 */ + u_int64_t therm_clr_int; /* thermal warn clear int reg */ /* 1fe.0000.3838 */ + u_int64_t kbd_clr_int; /* kbd [unused] clear int reg */ /* 1fe.0000.3840 */ + u_int64_t mouse_clr_int; /* mouse [unused] clear int reg */ /* 1fe.0000.3848 */ + u_int64_t serial_clr_int; /* second serial clear int reg */ /* 1fe.0000.3850 */ + u_int64_t pad10; + u_int64_t timer0_clr_int; /* timer 0 clear int reg */ /* 1fe.0000.3860 */ + u_int64_t timer1_clr_int; /* timer 1 clear int reg */ /* 1fe.0000.3868 */ + u_int64_t ue_clr_int; /* UE clear int reg */ /* 1fe.0000.3870 */ + u_int64_t ce_clr_int; /* CE clear int reg */ /* 1fe.0000.3878 */ + u_int64_t sbus_clr_async_int; /* SBUS error clr interrupt reg */ /* 1fe.0000.3880 */ + u_int64_t pwrmgt_clr_int; /* power mgmt wake clr interrupt reg */ /* 1fe.0000.3888 */ + + u_int64_t pad11[110]; + + struct timer_counter { + u_int64_t tc_count; /* timer/counter 0/1 count register */ /* ife.0000.3c00,3c10 */ + u_int64_t tc_limit; /* timer/counter 0/1 limit register */ /* ife.0000.3c08,3c18 */ + } tc[2]; + + u_int64_t pad12[252]; + + u_int64_t sys_svadiag; /* SBUS virtual addr diag reg */ /* 1fe.0000.4400 */ + + u_int64_t pad13[31]; + + u_int64_t iommu_queue_diag[16]; /* IOMMU LRU queue diag */ /* 1fe.0000.4500-457f */ + u_int64_t tlb_tag_diag[16]; /* TLB tag diag */ /* 1fe.0000.4580-45ff */ + u_int64_t tlb_data_diag[32]; /* TLB data RAM diag */ /* 1fe.0000.4600-46ff */ + + u_int64_t pad14[32]; + + u_int64_t sbus_int_diag; /* SBUS int state diag reg */ /* 1fe.0000.4800 */ + u_int64_t obio_int_diag; /* OBIO and misc int state diag reg */ /* 1fe.0000.4808 */ + + u_int64_t pad15[254]; + + u_int64_t strbuf_data_diag[128]; /* streaming buffer data RAM diag */ /* 1fe.0000.5000-53f8 */ + u_int64_t strbuf_error_diag[128]; /* streaming buffer error status diag *//* 1fe.0000.5400-57f8 */ + u_int64_t strbuf_pg_tag_diag[16]; /* streaming buffer page tag diag */ /* 1fe.0000.5800-5878 */ + u_int64_t pad16[16]; + u_int64_t strbuf_ln_tag_diag[16]; /* streaming buffer line tag diag */ /* 1fe.0000.5900-5978 */ +}; diff --git a/sys/arch/sparc64/dev/sbusvar.h b/sys/arch/sparc64/dev/sbusvar.h new file mode 100644 index 00000000000..f51b3541eb5 --- /dev/null +++ b/sys/arch/sparc64/dev/sbusvar.h @@ -0,0 +1,117 @@ +/* $NetBSD: sbusvar.h,v 1.7 1999/06/05 05:30:43 mrg Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sbusvar.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _SBUS_VAR_SPARC64_H_ +#define _SBUS_VAR_SPARC64_H_ + +#include <machine/bus.h> + +#include <sparc64/dev/iommuvar.h> + +/* + * Most devices are configured according to information kept in + * the FORTH PROMs. In particular, we extract the `name', `reg', + * and `address' properties of each device attached to the mainbus; + * other drives may also use this information. The mainbus itself + * (which `is' the CPU, in some sense) gets just the node, with a + * fake name ("mainbus"). + */ + +/* variables per Sbus */ +struct sbus_softc { + struct device sc_dev; /* base device */ + bus_space_tag_t sc_bustag; + bus_dma_tag_t sc_dmatag; + int sc_clockfreq; /* clock frequency (in Hz) */ + struct sbusdev *sc_sbdev; /* list of all children */ + struct sbus_range *sc_range; + int sc_nrange; + int sc_burst; /* burst transfer sizes supported */ + int *sc_intr2ipl; /* Interrupt level translation */ + int *sc_intr_compat;/* `intr' property to sbus compat */ + + struct sysioreg *sc_sysio; /* SBUS control registers */ + int sc_ign; /* Interrupt group number for this sysio */ + struct iommu_state sc_is; /* IOMMU state, see iommureg.h */ +}; + +#endif /* _SBUS_VAR_SPARC64_H_ */ diff --git a/sys/arch/sparc64/dev/upavar.h b/sys/arch/sparc64/dev/upavar.h new file mode 100644 index 00000000000..af5c6012189 --- /dev/null +++ b/sys/arch/sparc64/dev/upavar.h @@ -0,0 +1,145 @@ +/* $NetBSD: upavar.h,v 1.2 2000/01/14 14:33:31 pk Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)upavar.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _UPA_VAR_H +#define _UPA_VAR_H + +/* Device register space description */ +struct upa_reg { + int64_t ur_paddr; + int64_t ur_len; +}; + +/* + * UPA bus variables. + */ +struct upadev { + struct device *ud_dev; /* backpointer to generic */ + struct upadev *ud_bchain; /* forward link in bus chain */ + void (*ud_reset) __P((struct device *)); +}; + +/* variables per Upa */ +struct upa_softc { + struct device uc_dev; /* base device */ + bus_space_tag_t uc_bustag; + bus_dma_tag_t uc_dmatag; + int uc_clockfreq; /* clock frequency (in Hz) */ + struct upadev *uc_sbdev; /* list of all children */ +}; + +/* + * Upa driver attach arguments. + */ +struct upa_attach_args { + bus_space_tag_t ua_bustag; + bus_dma_tag_t ua_dmatag; + char *ua_name; /* PROM node name */ + int ua_node; /* PROM handle */ + struct upa_reg *ua_reg; /* "reg" properties */ + int ua_nreg; + void* *ua_address; /* "address" properties */ + int ua_naddress; + int *ua_interrupts; /* "interrupts" properties */ + int ua_ninterrupts; + int ua_pri; /* priority (IPL) */ +}; + +/* upa_attach() is also used from obio.c */ +void upa_attach __P((struct upa_softc *, char *, int, + const char * const *)); +int upa_print __P((void *, const char *)); + +int upadev_match __P((struct cfdata *, void *)); +void upa_establish __P((struct upadev *, struct device *)); + +int upa_setup_attach_args __P(( + struct upa_softc *, + bus_space_tag_t, + bus_dma_tag_t, + int, /*node*/ + struct upa_attach_args *)); + +#define upa_bus_map(t, bt, a, s, f, v, hp) \ + bus_space_map2(t, bt, a, s, f, v, hp) + +#endif /* _UPA_VAR_H */ |