diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2002-05-02 22:56:08 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2002-05-02 22:56:08 +0000 |
commit | f69ff2bae348f49f6e5fccbf1594b839e98792ef (patch) | |
tree | 984c07207f03eebcb847988db98df196a848c27e /sys | |
parent | d7aff648af7518e317842f78e06a3d197eca9629 (diff) |
Big TURBOchannel support catchup from NetBSD, part 1.
A few local changes and tweaks remain.
This bring DEC 3000 machines back in the game, but framebuffers are still
not supported at the moment.
Thanks to ericj@ and nate@ for supplying me a DEC 3000 for testing.
Diffstat (limited to 'sys')
58 files changed, 3782 insertions, 4544 deletions
diff --git a/sys/arch/alpha/alpha/dec_3000_300.c b/sys/arch/alpha/alpha/dec_3000_300.c index e223ee20dc5..b600615230d 100644 --- a/sys/arch/alpha/alpha/dec_3000_300.c +++ b/sys/arch/alpha/alpha/dec_3000_300.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dec_3000_300.c,v 1.9 2002/03/14 01:26:26 millert Exp $ */ +/* $OpenBSD: dec_3000_300.c,v 1.10 2002/05/02 22:56:06 miod Exp $ */ /* $NetBSD: dec_3000_300.c,v 1.30 2000/05/22 20:13:32 thorpej Exp $ */ /* @@ -44,7 +44,7 @@ #include <machine/cpuconf.h> #include <dev/tc/tcvar.h> -#include <alpha/tc/tcdsvar.h> +#include <dev/tc/tcdsvar.h> #include <alpha/tc/tc_3000_300.h> #ifndef NEW_SCC_DRIVER #include <alpha/tc/sccvar.h> @@ -213,7 +213,7 @@ dec_3000_300_device_register(dev, aux) if (parent != (struct device *)tcdsdev) return; - if (ta->tcdsda_slot != b->channel) + if (ta->tcdsda_chip != b->channel) return; scsidev = dev; diff --git a/sys/arch/alpha/alpha/dec_3000_500.c b/sys/arch/alpha/alpha/dec_3000_500.c index 06236b957d3..210dcb03e8e 100644 --- a/sys/arch/alpha/alpha/dec_3000_500.c +++ b/sys/arch/alpha/alpha/dec_3000_500.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dec_3000_500.c,v 1.9 2002/03/14 01:26:26 millert Exp $ */ +/* $OpenBSD: dec_3000_500.c,v 1.10 2002/05/02 22:56:06 miod Exp $ */ /* $NetBSD: dec_3000_500.c,v 1.29 2000/05/22 20:13:32 thorpej Exp $ */ /* @@ -43,7 +43,7 @@ #include <machine/cpuconf.h> #include <dev/tc/tcvar.h> -#include <alpha/tc/tcdsvar.h> +#include <dev/tc/tcdsvar.h> #include <alpha/tc/tc_3000_500.h> #ifndef NEW_SCC_DRIVER #include <alpha/tc/sccvar.h> @@ -232,7 +232,7 @@ dec_3000_500_device_register(dev, aux) if (parent != (struct device *)tcdsdev) return; - if (ta->tcdsda_slot != b->channel) + if (ta->tcdsda_chip != b->channel) return; scsidev = dev; diff --git a/sys/arch/alpha/conf/GENERIC b/sys/arch/alpha/conf/GENERIC index e6ed538b0be..0554e38ec4d 100644 --- a/sys/arch/alpha/conf/GENERIC +++ b/sys/arch/alpha/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.105 2002/04/26 20:13:11 matthieu Exp $ +# $OpenBSD: GENERIC,v 1.106 2002/05/02 22:56:06 miod Exp $ # $NetBSD: GENERIC,v 1.31 1996/12/03 17:25:29 cgd Exp $ machine alpha @@ -82,24 +82,24 @@ ugen* at uhub? port ? configuration ? # USB Generic driver # EV6 Tsunami Core Logic tsc* at mainbus0 -# TurboChannel host bus adapter support +# TURBOchannel host bus adapter support tcasic* at mainbus0 -# TurboChannel bus support +# TURBOchannel bus support tc* at tcasic? -# TurboChannel devices +# TURBOchannel devices ioasic* at tc? slot ? offset ? mcclock* at ioasic? offset ? le* at ioasic? offset ? scc0 at ioasic? offset ? scc1 at ioasic? offset ? -tcds0 at tc? slot ? offset ? -asc0 at tcds? slot ? -asc1 at tcds? slot ? +tcds* at tc? slot ? offset ? +asc* at tcds? chip ? scsibus* at asc? -cfb* at tc? slot ? offset ? -sfb* at tc? slot ? offset ? +asc* at tc? slot ? offset ? +#cfb* at tc? slot ? offset ? +#sfb* at tc? slot ? offset ? le* at tc? slot ? offset ? fta* at tc? slot ? offset ? # DEC DEFTA FDDI cards @@ -298,8 +298,8 @@ audio* at uaudio? # Workstation Console attachments #wsdisplay* at cfb? -wsdisplay* at vga? #wsdisplay* at sfb? +#wsdisplay* at vga? wsdisplay* at tga? wskbd* at pckbd? wsmouse* at pms? diff --git a/sys/arch/alpha/conf/RAMDISK b/sys/arch/alpha/conf/RAMDISK index 231d1c8a513..45fb5915704 100644 --- a/sys/arch/alpha/conf/RAMDISK +++ b/sys/arch/alpha/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.56 2002/04/28 20:55:14 pvalchev Exp $ +# $OpenBSD: RAMDISK,v 1.57 2002/05/02 22:56:06 miod Exp $ # $NetBSD: RAMDISK,v 1.9 1996/12/03 17:25:33 cgd Exp $ machine alpha # architecture, used by config; REQUIRED @@ -137,9 +137,7 @@ sd* at scsibus? target ? lun ? # SCSI disk drives #st* at scsibus? target ? lun ? # SCSI tape drives # Workstation Console attachments -#wsdisplay* at cfb? wsdisplay* at vga? -#wsdisplay* at sfb? wsdisplay* at tga? wskbd* at pckbd? diff --git a/sys/arch/alpha/conf/RAMDISKB b/sys/arch/alpha/conf/RAMDISKB index d32a646f415..93e37dcd853 100644 --- a/sys/arch/alpha/conf/RAMDISKB +++ b/sys/arch/alpha/conf/RAMDISKB @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISKB,v 1.19 2002/04/28 20:55:14 pvalchev Exp $ +# $OpenBSD: RAMDISKB,v 1.20 2002/05/02 22:56:06 miod Exp $ # $NetBSD: RAMDISK,v 1.9 1996/12/03 17:25:33 cgd Exp $ machine alpha # architecture, used by config; REQUIRED @@ -138,9 +138,7 @@ sd* at scsibus? target ? lun ? # SCSI disk drives #st* at scsibus? target ? lun ? # SCSI tape drives # Workstation Console attachments -#wsdisplay* at cfb? wsdisplay* at vga? -#wsdisplay* at sfb? wsdisplay* at tga? wskbd* at pckbd? diff --git a/sys/arch/alpha/conf/RAMDISKBIG b/sys/arch/alpha/conf/RAMDISKBIG index fc4d1cba8c2..c77a5faddfe 100644 --- a/sys/arch/alpha/conf/RAMDISKBIG +++ b/sys/arch/alpha/conf/RAMDISKBIG @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISKBIG,v 1.25 2002/04/28 20:55:14 pvalchev Exp $ +# $OpenBSD: RAMDISKBIG,v 1.26 2002/05/02 22:56:06 miod Exp $ # $NetBSD: GENERIC,v 1.31 1996/12/03 17:25:29 cgd Exp $ # # Generic Alpha kernel. Enough to get booted, etc., but not much more. @@ -102,12 +102,12 @@ mcclock* at ioasic? offset ? le* at ioasic? offset ? scc0 at ioasic? offset ? scc1 at ioasic? offset ? -tcds0 at tc? slot ? offset ? -asc0 at tcds? slot ? -asc1 at tcds? slot ? +tcds* at tc? slot ? offset ? +asc* at tcds? chip ? +asc* at tc? slot ? offset ? scsibus* at asc? -cfb* at tc? slot ? offset ? -sfb* at tc? slot ? offset ? +#cfb* at tc? slot ? offset ? +#sfb* at tc? slot ? offset ? le* at tc? slot ? offset ? fta* at tc? slot ? offset ? # DEC DEFTA FDDI cards diff --git a/sys/arch/alpha/conf/files.alpha b/sys/arch/alpha/conf/files.alpha index 5249e2ecadd..8d6c26e4f3c 100644 --- a/sys/arch/alpha/conf/files.alpha +++ b/sys/arch/alpha/conf/files.alpha @@ -1,4 +1,4 @@ -# $OpenBSD: files.alpha,v 1.57 2002/04/28 20:55:14 pvalchev Exp $ +# $OpenBSD: files.alpha,v 1.58 2002/05/02 22:56:06 miod Exp $ # $NetBSD: files.alpha,v 1.32 1996/11/25 04:03:21 cgd Exp $ # # alpha-specific configuration info @@ -60,55 +60,50 @@ include "dev/wsfont/files.wsfont" include "dev/wscons/files.wscons" # -# TurboChannel Devices +# Bus-independent support for DEC devices +# +include "dev/dec/files.dec" + +# +# TURBOchannel Devices # include "dev/tc/files.tc" +# TC attachment is MD +attach tc at tcbus + device tcasic: tcbus attach tcasic at mainbus file arch/alpha/tc/tcasic.c tcasic file arch/alpha/tc/tc_bus_mem.c tcasic +file arch/alpha/tc/tc_dma.c tcasic +file arch/alpha/tc/tc_dma_3000_300.c tcasic & dec_3000_300 +file arch/alpha/tc/tc_dma_3000_500.c tcasic & dec_3000_500 +file arch/alpha/tc/tc_sgmap.c tcasic & dec_3000_500 file arch/alpha/tc/tc_3000_500.c tcasic & dec_3000_500 file arch/alpha/tc/tc_3000_300.c tcasic & dec_3000_300 -# the TurboChannel IOCTL ASIC -device ioasic { offset = -1 } -attach ioasic at tc +# the TURBOchannel IOCTL ASIC +# IOASIC device and attachment defined in sys/dev/tc/files.tc file arch/alpha/tc/ioasic.c ioasic -# Color Frame buffer +# PMAG-B CX device cfb: wsemuldisplaydev, wsrasteremulops attach cfb at tc -file arch/alpha/tc/cfb.c cfb +file arch/alpha/tc/cfb.c cfb needs-flag -# Smart Frame buffer +# PMAGB-B HX or CXT device sfb: wsemuldisplaydev, wsrasteremulops attach sfb at tc -file arch/alpha/tc/sfb.c sfb +file arch/alpha/tc/sfb.c sfb needs-flag # 8530 UARTs device scc attach scc at ioasic file arch/alpha/tc/scc.c scc needs-count -# the TCDS ASIC -device tcds { slot = -1 } -attach tcds at tc -file arch/alpha/tc/tcds.c tcds needs-count - -# 53C[F]90 SCSI -device asc: scsi -attach asc at tcds -file arch/alpha/tc/asc.c asc needs-count -file arch/alpha/tc/tcds_dma.c asc - -# Baseboard Lance ethernet. -attach le at ioasic with le_ioasic -attach le at tc with le_tc -file dev/tc/if_le_dec.c (le_ioasic | le_tc) -file dev/tc/if_le_ioasic.c le_ioasic needs-flag #for le_iomem -file dev/tc/if_le_tc.c le_tc +# TC and baseboard ioasic Lance ethernet are in files.tc # # ISA Bus support diff --git a/sys/arch/alpha/tc/tc_machdep.h b/sys/arch/alpha/include/tc_machdep.h index 3c26c5c8f85..c286497698a 100644 --- a/sys/arch/alpha/tc/tc_machdep.h +++ b/sys/arch/alpha/include/tc_machdep.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_machdep.h,v 1.5 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: tc_machdep.h,v 1.3 1996/10/22 21:34:22 cgd Exp $ */ +/* $OpenBSD: tc_machdep.h,v 1.3 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_machdep.h,v 1.4 2000/06/01 00:04:50 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -92,4 +92,22 @@ typedef int32_t tc_offset_t; #define TC_PHYS_TO_UNCACHED(addr) \ (addr) -bus_space_tag_t tc_bus_mem_init(void *memv);; +/* + * These functions are private, and may not be called by + * machine-independent code. + */ +bus_space_tag_t tc_bus_mem_init(void *memv); +void tc_dma_init(void); + +/* + * Address of scatter/gather SRAM on the 3000/500-series. + * + * There is room for 32K entries, yielding 256M of sgva space. + * The page table is readable in both dense and sparse space. + * The page table is writable only in sparse space. + * + * In sparse space, the 32-bit PTEs are followed by 32-bits + * of pad. + */ +#define TC_SGSRAM_DENSE 0x0000001c2800000UL +#define TC_SGSRAM_SPARSE 0x0000001d5000000UL diff --git a/sys/arch/alpha/tc/asc.c b/sys/arch/alpha/tc/asc.c deleted file mode 100644 index 5b8b4418d8c..00000000000 --- a/sys/arch/alpha/tc/asc.c +++ /dev/null @@ -1,2175 +0,0 @@ -/* $OpenBSD: asc.c,v 1.3 2002/03/14 01:26:27 millert Exp $ */ -/* $NetBSD: esp.c,v 1.26 1996/12/05 01:39:40 cgd Exp $ */ - -#ifdef __sparc__ -#define SPARC_DRIVER -#endif - -/* - * Copyright (c) 1996 Charles M. Hannum. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Charles M. Hannum. - * 4. 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. - */ - -/* - * Copyright (c) 1994 Peter Galbavy - * Copyright (c) 1995 Paul Kranenburg - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Peter Galbavy - * 4. 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. - */ - -/* - * Based on aic6360 by Jarle Greipsland - * - * Acknowledgements: Many of the algorithms used in this driver are - * inspired by the work of Julian Elischer (julian@tfs.com) and - * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/device.h> -#include <sys/buf.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/queue.h> - -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> -#include <scsi/scsi_message.h> - -#include <machine/cpu.h> -#ifdef SPARC_DRIVER -#include <machine/autoconf.h> -#include <sparc/dev/sbusvar.h> -#include <sparc/dev/dmareg.h> -#include <sparc/dev/dmavar.h> -#include <sparc/dev/espreg.h> -#include <sparc/dev/espvar.h> -#else -#include <machine/autoconf.h> /* badaddr() prototype */ -#include <dev/tc/tcvar.h> -#include <alpha/tc/tcdsvar.h> -#include <alpha/tc/ascreg.h> -#include <alpha/tc/ascvar.h> -#endif - -int esp_debug = 0; /*ESP_SHOWPHASE|ESP_SHOWMISC|ESP_SHOWTRAC|ESP_SHOWCMDS;*/ - -/*static*/ void espattach(struct device *, struct device *, - void *); -/*static*/ int espprint(void *, const char *); -#ifdef __BROKEN_INDIRECT_CONFIG -/*static*/ int espmatch(struct device *, void *, void *); -#else -/*static*/ int espmatch(struct device *, struct cfdata *, - void *); -#endif -/*static*/ u_int esp_adapter_info(struct esp_softc *); -/*static*/ void espreadregs(struct esp_softc *); -/*static*/ void esp_select(struct esp_softc *, struct esp_ecb *); -/*static*/ int esp_reselect(struct esp_softc *, int); -/*static*/ void esp_scsi_reset(struct esp_softc *); -/*static*/ void esp_reset(struct esp_softc *); -/*static*/ void espinit(struct esp_softc *, int); -/*static*/ int esp_scsi_cmd(struct scsi_xfer *); -/*static*/ int esp_poll(struct esp_softc *, struct scsi_xfer *, - int); -/*static*/ void esp_sched(struct esp_softc *); -/*static*/ void esp_done(struct esp_softc *, struct esp_ecb *); -/*static*/ void esp_msgin(struct esp_softc *); -/*static*/ void esp_msgout(struct esp_softc *); -/*static*/ int espintr(struct esp_softc *); -/*static*/ void esp_timeout(void *arg); -/*static*/ void esp_abort(struct esp_softc *, struct esp_ecb *); -/*static*/ void esp_dequeue(struct esp_softc *, struct esp_ecb *); -void esp_sense(struct esp_softc *, struct esp_ecb *); -void esp_free_ecb(struct esp_softc *, struct esp_ecb *, int); -struct esp_ecb *esp_get_ecb(struct esp_softc *, int); -static inline int esp_stp2cpb(struct esp_softc *, int); -static inline int esp_cpb2stp(struct esp_softc *, int); -static inline void esp_setsync(struct esp_softc *, struct esp_tinfo *); - -/* Linkup to the rest of the kernel */ -struct cfattach asc_ca = { - sizeof(struct esp_softc), espmatch, espattach -}; - -struct cfdriver asc_cd = { - NULL, "asc", DV_DULL -}; - -struct scsi_adapter esp_switch = { - esp_scsi_cmd, - minphys, /* no max at this level; handled by DMA code */ - NULL, - NULL, -}; - -struct scsi_device esp_dev = { - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ -}; - -/* - * XXX should go when new generic scsiprint finds its way here - */ -int -espprint(aux, name) - void *aux; - const char *name; -{ - if (name != NULL) - printf("scsibus at %s", name); - return UNCONF; -} - -int -#ifdef __BROKEN_INDIRECT_CONFIG -espmatch(parent, vcf, aux) -#else -espmatch(parent, cf, aux) -#endif - struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *vcf; -#else - struct cfdata *cf; -#endif - void *aux; -{ -#ifdef SPARC_DRIVER -#ifdef __BROKEN_INDIRECT_CONFIG - struct cfdata *cf = vcf; -#endif - register struct confargs *ca = aux; - register struct romaux *ra = &ca->ca_ra; - - if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) - return (0); - if (ca->ca_bustype == BUS_SBUS) - return (1); - ra->ra_len = NBPG; - return (probeget(ra->ra_vaddr, 1) != -1); -#else - struct tcdsdev_attach_args *tcdsdev = aux; - - if (strncmp(tcdsdev->tcdsda_modname, "PMAZ-AA ", TC_ROM_LLEN)) - return (0); - return (!tc_badaddr(tcdsdev->tcdsda_addr)); -#endif -} - -/* - * Attach this instance, and then all the sub-devices - */ -void -espattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ -#ifdef SPARC_DRIVER - register struct confargs *ca = aux; -#else - register struct tcdsdev_attach_args *tcdsdev = aux; -#endif - struct esp_softc *sc = (void *)self; -#ifdef SPARC_DRIVER - struct bootpath *bp; - int dmachild = strncmp(parent->dv_xname, "dma", 3) == 0; -#endif - -#ifdef SPARC_DRIVER - /* - * Make sure things are sane. I don't know if this is ever - * necessary, but it seem to be in all of Torek's code. - */ - if (ca->ca_ra.ra_nintr != 1) { - printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr); - return; - } - - sc->sc_pri = ca->ca_ra.ra_intr[0].int_pri; - printf(" pri %d", sc->sc_pri); - - /* - * Map my registers in, if they aren't already in virtual - * address space. - */ - if (ca->ca_ra.ra_vaddr) - sc->sc_reg = (volatile u_char *) ca->ca_ra.ra_vaddr; - else { - sc->sc_reg = (volatile u_char *) - mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len, ca->ca_bustype); - } -#else - sc->sc_reg = (volatile u_int32_t *)tcdsdev->tcdsda_addr; - sc->sc_cookie = tcdsdev->tcdsda_cookie; - sc->sc_dma = tcdsdev->tcdsda_sc; - - printf(": address %p", sc->sc_reg); - tcds_intr_establish(parent, sc->sc_cookie, TC_IPL_BIO, - (int (*)(void *))espintr, sc); -#endif - -#ifdef SPARC_DRIVER - /* Other settings */ - sc->sc_node = ca->ca_ra.ra_node; - if (ca->ca_bustype == BUS_SBUS) { - sc->sc_id = getpropint(sc->sc_node, "initiator-id", 7); - sc->sc_freq = getpropint(sc->sc_node, "clock-frequency", -1); - } else { - sc->sc_id = 7; - sc->sc_freq = 24000000; - } - if (sc->sc_freq < 0) - sc->sc_freq = ((struct sbus_softc *) - sc->sc_dev.dv_parent)->sc_clockfreq; -#else - if (parent->dv_cfdata->cf_driver == &tcds_cd) { - sc->sc_id = tcdsdev->tcdsda_id; - sc->sc_freq = tcdsdev->tcdsda_freq; - } else { - /* XXX */ - sc->sc_id = 7; - sc->sc_freq = 24000000; - } -#endif - - /* gimme Mhz */ - sc->sc_freq /= 1000000; - -#ifdef SPARC_DRIVER - if (dmachild) { - sc->sc_dma = (struct dma_softc *)parent; - sc->sc_dma->sc_esp = sc; - } else { - /* - * find the DMA by poking around the dma device structures - * - * What happens here is that if the dma driver has not been - * configured, then this returns a NULL pointer. Then when the - * dma actually gets configured, it does the opposing test, and - * if the sc->sc_esp field in it's softc is NULL, then tries to - * find the matching esp driver. - * - */ - sc->sc_dma = (struct dma_softc *) - getdevunit("dma", sc->sc_dev.dv_unit); - - /* - * and a back pointer to us, for DMA - */ - if (sc->sc_dma) - sc->sc_dma->sc_esp = sc; - else - panic("espattach: no dma found"); - } -#else - sc->sc_dma->sc_esp = sc; /* XXX */ -#endif - - /* - * It is necessary to try to load the 2nd config register here, - * to find out what rev the esp chip is, else the esp_reset - * will not set up the defaults correctly. - */ - sc->sc_cfg1 = sc->sc_id | ESPCFG1_PARENB; -#ifdef SPARC_DRIVER - sc->sc_cfg2 = ESPCFG2_SCSI2 | ESPCFG2_RPE; - sc->sc_cfg3 = ESPCFG3_CDB; - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); - - if ((ESP_READ_REG(sc, ESP_CFG2) & ~ESPCFG2_RSVD) != (ESPCFG2_SCSI2 | ESPCFG2_RPE)) { - printf(": ESP100"); - sc->sc_rev = ESP100; - } else { - sc->sc_cfg2 = ESPCFG2_SCSI2; - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); - sc->sc_cfg3 = 0; - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - sc->sc_cfg3 = (ESPCFG3_CDB | ESPCFG3_FCLK); - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - if (ESP_READ_REG(sc, ESP_CFG3) != (ESPCFG3_CDB | ESPCFG3_FCLK)) { - printf(": ESP100A"); - sc->sc_rev = ESP100A; - } else { - /* ESPCFG2_FE enables > 64K transfers */ - sc->sc_cfg2 |= ESPCFG2_FE; - sc->sc_cfg3 = 0; - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - printf(": ESP200"); - sc->sc_rev = ESP200; - } - } -#else - sc->sc_cfg2 = ESPCFG2_SCSI2; - sc->sc_cfg3 = 0x4; /* Save residual byte. XXX??? */ - printf(": NCR53C94"); - sc->sc_rev = NCR53C94; -#endif - - /* - * This is the value used to start sync negotiations - * Note that the ESP register "SYNCTP" is programmed - * in "clocks per byte", and has a minimum value of 4. - * The SCSI period used in negotiation is one-fourth - * of the time (in nanoseconds) needed to transfer one byte. - * Since the chip's clock is given in MHz, we have the following - * formula: 4 * period = (1000 / freq) * 4 - */ - sc->sc_minsync = 1000 / sc->sc_freq; - -#ifdef SPARC_DRIVER - /* - * Alas, we must now modify the value a bit, because it's - * only valid when can switch on FASTCLK and FASTSCSI bits - * in config register 3... - */ - switch (sc->sc_rev) { - case ESP100: - sc->sc_maxxfer = 64 * 1024; - sc->sc_minsync = 0; /* No synch on old chip? */ - break; - case ESP100A: - sc->sc_maxxfer = 64 * 1024; - sc->sc_minsync = esp_cpb2stp(sc, 5); /* Min clocks/byte is 5 */ - break; - case ESP200: - sc->sc_maxxfer = 16 * 1024 * 1024; - /* XXX - do actually set FAST* bits */ - } -#else - sc->sc_maxxfer = 64 * 1024; -#endif - - sc->sc_ccf = FREQTOCCF(sc->sc_freq); - - /* The value *must not* be == 1. Make it 2 */ - if (sc->sc_ccf == 1) - sc->sc_ccf = 2; - - /* - * The recommended timeout is 250ms. This register is loaded - * with a value calculated as follows, from the docs: - * - * (timout period) x (CLK frequency) - * reg = ------------------------------------- - * 8192 x (Clock Conversion Factor) - * - * Since CCF has a linear relation to CLK, this generally computes - * to the constant of 153. - */ - sc->sc_timeout = ((250 * 1000) * sc->sc_freq) / (8192 * sc->sc_ccf); - - /* CCF register only has 3 bits; 0 is actually 8 */ - sc->sc_ccf &= 7; - - /* Reset state & bus */ - sc->sc_state = 0; - espinit(sc, 1); - - printf(" %dMhz, target %d\n", sc->sc_freq, sc->sc_id); - -#ifdef SPARC_DRIVER - /* add me to the sbus structures */ - sc->sc_sd.sd_reset = (void *) esp_reset; -#if defined(SUN4C) || defined(SUN4M) - if (ca->ca_bustype == BUS_SBUS) { - if (dmachild) - sbus_establish(&sc->sc_sd, sc->sc_dev.dv_parent); - else - sbus_establish(&sc->sc_sd, &sc->sc_dev); - } -#endif /* SUN4C || SUN4M */ -#endif - -#ifdef SPARC_DRIVER - /* and the interuppts */ - sc->sc_ih.ih_fun = (void *) espintr; - sc->sc_ih.ih_arg = sc; - intr_establish(sc->sc_pri, &sc->sc_ih); - evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); -#endif - - /* - * fill in the prototype scsi_link. - */ - /* sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; */ - sc->sc_link.adapter_softc = sc; - sc->sc_link.adapter_target = sc->sc_id; - sc->sc_link.adapter = &esp_switch; - sc->sc_link.device = &esp_dev; - sc->sc_link.openings = 2; - - /* - * If the boot path is "esp" at the moment and it's me, then - * walk our pointer to the sub-device, ready for the config - * below. - */ -#ifdef SPARC_DRIVER - bp = ca->ca_ra.ra_bp; - switch (ca->ca_bustype) { - case BUS_SBUS: - if (bp != NULL && strcmp(bp->name, "esp") == 0 && - SAME_ESP(sc, bp, ca)) - bootpath_store(1, bp + 1); - break; - default: - if (bp != NULL && strcmp(bp->name, "esp") == 0 && - bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit) - bootpath_store(1, bp + 1); - break; - } -#endif - - /* - * Now try to attach all the sub-devices - */ - config_found(self, &sc->sc_link, /* scsiprint */ espprint); /* XXX */ - -#ifdef SPARC_DRIVER - bootpath_store(1, NULL); -#endif -} - -/* - * This is the generic esp reset function. It does not reset the SCSI bus, - * only this controllers, but kills any on-going commands, and also stops - * and resets the DMA. - * - * After reset, registers are loaded with the defaults from the attach - * routine above. - */ -void -esp_reset(sc) - struct esp_softc *sc; -{ - - /* reset DMA first */ - DMA_RESET(sc->sc_dma); - - /* reset SCSI chip */ - ESPCMD(sc, ESPCMD_RSTCHIP); - ESPCMD(sc, ESPCMD_NOP); - DELAY(500); - - /* do these backwards, and fall through */ - switch (sc->sc_rev) { -#ifndef SPARC_DRIVER - case NCR53C94: -#endif - case ESP200: - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - case ESP100A: - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); - case ESP100: - ESP_WRITE_REG(sc, ESP_CFG1, sc->sc_cfg1); - ESP_WRITE_REG(sc, ESP_CCF, sc->sc_ccf); - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_TIMEOUT, sc->sc_timeout); - break; - default: - printf("%s: unknown revision code, assuming ESP100\n", - sc->sc_dev.dv_xname); - ESP_WRITE_REG(sc, ESP_CFG1, sc->sc_cfg1); - ESP_WRITE_REG(sc, ESP_CCF, sc->sc_ccf); - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_TIMEOUT, sc->sc_timeout); - } -} - -/* - * Reset the SCSI bus, but not the chip - */ -void -esp_scsi_reset(sc) - struct esp_softc *sc; -{ -#ifdef SPARC_DRIVER - /* stop DMA first, as the chip will return to Bus Free phase */ - DMACSR(sc->sc_dma) &= ~D_EN_DMA; -#else - /* - * XXX STOP DMA FIRST - */ -#endif - - printf("esp: resetting SCSI bus\n"); - ESPCMD(sc, ESPCMD_RSTSCSI); -} - -/* - * Initialize esp state machine - */ -void -espinit(sc, doreset) - struct esp_softc *sc; - int doreset; -{ - struct esp_ecb *ecb; - int r; - - ESP_TRACE(("[ESPINIT(%d)] ", doreset)); - - if (sc->sc_state == 0) { - /* First time through; initialize. */ - TAILQ_INIT(&sc->ready_list); - TAILQ_INIT(&sc->nexus_list); - TAILQ_INIT(&sc->free_list); - sc->sc_nexus = NULL; - ecb = sc->sc_ecb; - bzero(ecb, sizeof(sc->sc_ecb)); - for (r = 0; r < sizeof(sc->sc_ecb) / sizeof(*ecb); r++) { - TAILQ_INSERT_TAIL(&sc->free_list, ecb, chain); - ecb++; - } - bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo)); - } else { - /* Cancel any active commands. */ - sc->sc_state = ESP_CLEANING; - if ((ecb = sc->sc_nexus) != NULL) { - ecb->xs->error = XS_DRIVER_STUFFUP; - timeout_del(&ecb->xs->stimeout); - esp_done(sc, ecb); - } - while ((ecb = sc->nexus_list.tqh_first) != NULL) { - ecb->xs->error = XS_DRIVER_STUFFUP; - timeout_del(&ecb->xs->stimeout); - esp_done(sc, ecb); - } - } - - /* - * reset the chip to a known state - */ - esp_reset(sc); - - sc->sc_phase = sc->sc_prevphase = INVALID_PHASE; - for (r = 0; r < 8; r++) { - struct esp_tinfo *ti = &sc->sc_tinfo[r]; -/* XXX - config flags per target: low bits: no reselect; high bits: no synch */ - int fl = sc->sc_dev.dv_cfdata->cf_flags; - - ti->flags = ((sc->sc_minsync && !(fl & (1<<(r+8)))) - ? T_NEGOTIATE : 0) | - ((fl & (1<<r)) ? T_RSELECTOFF : 0) | - T_NEED_TO_RESET; - ti->period = sc->sc_minsync; - ti->offset = 0; - } - - if (doreset) { - sc->sc_state = ESP_SBR; - ESPCMD(sc, ESPCMD_RSTSCSI); - } else { - sc->sc_state = ESP_IDLE; - } -} - -/* - * Read the ESP registers, and save their contents for later use. - * ESP_STAT, ESP_STEP & ESP_INTR are mostly zeroed out when reading - * ESP_INTR - so make sure it is the last read. - * - * I think that (from reading the docs) most bits in these registers - * only make sense when he DMA CSR has an interrupt showing. Call only - * if an interrupt is pending. - */ -void -espreadregs(sc) - struct esp_softc *sc; -{ - - sc->sc_espstat = ESP_READ_REG(sc, ESP_STAT); - /* Only the stepo bits are of interest */ - sc->sc_espstep = ESP_READ_REG(sc, ESP_STEP) & ESPSTEP_MASK; - sc->sc_espintr = ESP_READ_REG(sc, ESP_INTR); -#ifndef SPARC_DRIVER - /* Clear the TCDS interrupt bit. */ - (void)tcds_scsi_isintr(sc->sc_dma, 1); -#endif - - /* - * Determine the SCSI bus phase, return either a real SCSI bus phase - * or some pseudo phase we use to detect certain exceptions. - */ - - sc->sc_phase = (sc->sc_espintr & ESPINTR_DIS) - ? /* Disconnected */ BUSFREE_PHASE - : sc->sc_espstat & ESPSTAT_PHASE; - - ESP_MISC(("regs[intr=%02x,stat=%02x,step=%02x] ", - sc->sc_espintr, sc->sc_espstat, sc->sc_espstep)); -} - -/* - * Convert chip register Clock Per Byte value to Synchronous Transfer Period. - */ -static inline int -esp_cpb2stp(sc, cpb) - struct esp_softc *sc; - int cpb; -{ - return ((250 * cpb) / sc->sc_freq); -} - -/* - * Convert Synchronous Transfer Period to chip register Clock Per Byte value. - */ -static inline int -esp_stp2cpb(sc, period) - struct esp_softc *sc; - int period; -{ - int v; - v = (sc->sc_freq * period) / 250; - if (esp_cpb2stp(sc, v) < period) - /* Correct round-down error */ - v++; - return v; -} - -static inline void -esp_setsync(sc, ti) - struct esp_softc *sc; - struct esp_tinfo *ti; -{ - - if (ti->flags & T_SYNCMODE) { - ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset); - ESP_WRITE_REG(sc, ESP_SYNCTP, esp_stp2cpb(sc, ti->period)); - } else { - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_SYNCTP, 0); - } -} - -/* - * Send a command to a target, set the driver state to ESP_SELECTING - * and let the caller take care of the rest. - * - * Keeping this as a function allows me to say that this may be done - * by DMA instead of programmed I/O soon. - */ -void -esp_select(sc, ecb) - struct esp_softc *sc; - struct esp_ecb *ecb; -{ - struct scsi_link *sc_link = ecb->xs->sc_link; - int target = sc_link->target; - struct esp_tinfo *ti = &sc->sc_tinfo[target]; - u_char *cmd; - int clen; - - ESP_TRACE(("[esp_select(t%d,l%d,cmd:%x)] ", sc_link->target, sc_link->lun, ecb->cmd.opcode)); - - /* new state ESP_SELECTING */ - sc->sc_state = ESP_SELECTING; - - ESPCMD(sc, ESPCMD_FLUSH); - - /* - * The docs say the target register is never reset, and I - * can't think of a better place to set it - */ - ESP_WRITE_REG(sc, ESP_SELID, target); - esp_setsync(sc, ti); - - /* - * Who am I. This is where we tell the target that we are - * happy for it to disconnect etc. - */ - ESP_WRITE_REG(sc, ESP_FIFO, - MSG_IDENTIFY(sc_link->lun, (ti->flags & T_RSELECTOFF)?0:1)); - - if (ti->flags & T_NEGOTIATE) { - /* Arbitrate, select and stop after IDENTIFY message */ - ESPCMD(sc, ESPCMD_SELATNS); - return; - } - - /* Now the command into the FIFO */ - cmd = (u_char *)&ecb->cmd; - clen = ecb->clen; - while (clen--) - ESP_WRITE_REG(sc, ESP_FIFO, *cmd++); - - /* And get the targets attention */ - ESPCMD(sc, ESPCMD_SELATN); -} - -void -esp_free_ecb(sc, ecb, flags) - struct esp_softc *sc; - struct esp_ecb *ecb; - int flags; -{ - int s; - - s = splbio(); - - ecb->flags = 0; - TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (ecb->chain.tqe_next == 0) - wakeup(&sc->free_list); - - splx(s); -} - -struct esp_ecb * -esp_get_ecb(sc, flags) - struct esp_softc *sc; - int flags; -{ - struct esp_ecb *ecb; - int s; - - s = splbio(); - - while ((ecb = sc->free_list.tqh_first) == NULL && - (flags & SCSI_NOSLEEP) == 0) - tsleep(&sc->free_list, PRIBIO, "especb", 0); - if (ecb) { - TAILQ_REMOVE(&sc->free_list, ecb, chain); - ecb->flags |= ECB_ALLOC; - } - - splx(s); - return ecb; -} - -/* - * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS - */ - -/* - * Start a SCSI-command - * This function is called by the higher level SCSI-driver to queue/run - * SCSI-commands. - */ -int -esp_scsi_cmd(xs) - struct scsi_xfer *xs; -{ - struct scsi_link *sc_link = xs->sc_link; - struct esp_softc *sc = sc_link->adapter_softc; - struct esp_ecb *ecb; - int s, flags; - - ESP_TRACE(("[esp_scsi_cmd] ")); - ESP_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, - sc_link->target)); - - flags = xs->flags; - if ((ecb = esp_get_ecb(sc, flags)) == NULL) { - xs->error = XS_DRIVER_STUFFUP; - return TRY_AGAIN_LATER; - } - - /* Initialize ecb */ - ecb->xs = xs; - ecb->timeout = xs->timeout; - timeout_set(&ecb->xs->stimeout, esp_timeout, ecb); - - if (xs->flags & SCSI_RESET) { - ecb->flags |= ECB_RESET; - ecb->clen = 0; - ecb->dleft = 0; - } else { - bcopy(xs->cmd, &ecb->cmd, xs->cmdlen); - ecb->clen = xs->cmdlen; - ecb->daddr = xs->data; - ecb->dleft = xs->datalen; - } - ecb->stat = 0; - - s = splbio(); - - TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain); - if (sc->sc_state == ESP_IDLE) - esp_sched(sc); - - splx(s); - - if ((flags & SCSI_POLL) == 0) - return SUCCESSFULLY_QUEUED; - - /* Not allowed to use interrupts, use polling instead */ - if (esp_poll(sc, xs, ecb->timeout)) { - esp_timeout(ecb); - if (esp_poll(sc, xs, ecb->timeout)) - esp_timeout(ecb); - } - return COMPLETE; -} - -/* - * Used when interrupt driven I/O isn't allowed, e.g. during boot. - */ -int -esp_poll(sc, xs, count) - struct esp_softc *sc; - struct scsi_xfer *xs; - int count; -{ - - ESP_TRACE(("[esp_poll] ")); - while (count) { - if (DMA_ISINTR(sc->sc_dma)) { - espintr(sc); - } -#if alternatively - if (ESP_READ_REG(sc, ESP_STAT) & ESPSTAT_INT) - espintr(sc); -#endif - if ((xs->flags & ITSDONE) != 0) - return 0; - if (sc->sc_state == ESP_IDLE) { - ESP_TRACE(("[esp_poll: rescheduling] ")); - esp_sched(sc); - } - DELAY(1000); - count--; - } - return 1; -} - - -/* - * LOW LEVEL SCSI UTILITIES - */ - -/* - * Schedule a scsi operation. This has now been pulled out of the interrupt - * handler so that we may call it from esp_scsi_cmd and esp_done. This may - * save us an unecessary interrupt just to get things going. Should only be - * called when state == ESP_IDLE and at bio pl. - */ -void -esp_sched(sc) - struct esp_softc *sc; -{ - struct esp_ecb *ecb; - struct scsi_link *sc_link; - struct esp_tinfo *ti; - - ESP_TRACE(("[esp_sched] ")); - if (sc->sc_state != ESP_IDLE) - panic("esp_sched: not IDLE (state=%d)", sc->sc_state); - - /* - * Find first ecb in ready queue that is for a target/lunit - * combinations that is not busy. - */ - for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) { - sc_link = ecb->xs->sc_link; - ti = &sc->sc_tinfo[sc_link->target]; - if ((ti->lubusy & (1 << sc_link->lun)) == 0) { - TAILQ_REMOVE(&sc->ready_list, ecb, chain); - sc->sc_nexus = ecb; - esp_select(sc, ecb); - break; - } else - ESP_MISC(("%d:%d busy\n", - sc_link->target, sc_link->lun)); - } -} - -void -esp_sense(sc, ecb) - struct esp_softc *sc; - struct esp_ecb *ecb; -{ - struct scsi_xfer *xs = ecb->xs; - struct scsi_link *sc_link = xs->sc_link; - struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target]; - struct scsi_sense *ss = (void *)&ecb->cmd; - - ESP_MISC(("requesting sense ")); - /* Next, setup a request sense command block */ - bzero(ss, sizeof(*ss)); - ss->opcode = REQUEST_SENSE; - ss->byte2 = sc_link->lun << 5; - ss->length = sizeof(struct scsi_sense_data); - ecb->clen = sizeof(*ss); - ecb->daddr = (char *)&xs->sense; - ecb->dleft = sizeof(struct scsi_sense_data); - ecb->flags |= ECB_SENSE; - ti->senses++; - if (ecb->flags & ECB_NEXUS) - ti->lubusy &= ~(1 << sc_link->lun); - if (ecb == sc->sc_nexus) { - esp_select(sc, ecb); - } else { - esp_dequeue(sc, ecb); - TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain); - if (sc->sc_state == ESP_IDLE) - esp_sched(sc); - } -} - -/* - * POST PROCESSING OF SCSI_CMD (usually current) - */ -void -esp_done(sc, ecb) - struct esp_softc *sc; - struct esp_ecb *ecb; -{ - struct scsi_xfer *xs = ecb->xs; - struct scsi_link *sc_link = xs->sc_link; - struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target]; - - ESP_TRACE(("[esp_done(error:%x)] ", xs->error)); - - /* - * Now, if we've come here with no error code, i.e. we've kept the - * initial XS_NOERROR, and the status code signals that we should - * check sense, we'll need to set up a request sense cmd block and - * push the command back into the ready queue *before* any other - * commands for this target/lunit, else we lose the sense info. - * We don't support chk sense conditions for the request sense cmd. - */ - if (xs->error == XS_NOERROR) { - if ((ecb->flags & ECB_ABORT) != 0) { - xs->error = XS_DRIVER_STUFFUP; - } else if ((ecb->flags & ECB_SENSE) != 0) { - xs->error = XS_SENSE; - } else if ((ecb->stat & ST_MASK) == SCSI_CHECK) { - /* First, save the return values */ - xs->resid = ecb->dleft; - xs->status = ecb->stat; - esp_sense(sc, ecb); - return; - } else { - xs->resid = ecb->dleft; - } - } - - xs->flags |= ITSDONE; - -#ifdef ESP_DEBUG - if (esp_debug & ESP_SHOWMISC) { - if (xs->resid != 0) - printf("resid=%lu ", xs->resid); - if (xs->error == XS_SENSE) - printf("sense=0x%02x\n", xs->sense.error_code); - else - printf("error=%d\n", xs->error); - } -#endif - - /* - * Remove the ECB from whatever queue it's on. - */ - if (ecb->flags & ECB_NEXUS) - ti->lubusy &= ~(1 << sc_link->lun); - if (ecb == sc->sc_nexus) { - sc->sc_nexus = NULL; - sc->sc_state = ESP_IDLE; - esp_sched(sc); - } else - esp_dequeue(sc, ecb); - - esp_free_ecb(sc, ecb, xs->flags); - ti->cmds++; - scsi_done(xs); -} - -void -esp_dequeue(sc, ecb) - struct esp_softc *sc; - struct esp_ecb *ecb; -{ - - if (ecb->flags & ECB_NEXUS) { - TAILQ_REMOVE(&sc->nexus_list, ecb, chain); - } else { - TAILQ_REMOVE(&sc->ready_list, ecb, chain); - } -} - -/* - * INTERRUPT/PROTOCOL ENGINE - */ - -/* - * Schedule an outgoing message by prioritizing it, and asserting - * attention on the bus. We can only do this when we are the initiator - * else there will be an illegal command interrupt. - */ -#define esp_sched_msgout(m) \ - do { \ - ESP_MISC(("esp_sched_msgout %d ", m)); \ - ESPCMD(sc, ESPCMD_SETATN); \ - sc->sc_flags |= ESP_ATN; \ - sc->sc_msgpriq |= (m); \ - } while (0) - -int -esp_reselect(sc, message) - struct esp_softc *sc; - int message; -{ - u_char selid, target, lun; - struct esp_ecb *ecb; - struct scsi_link *sc_link; - struct esp_tinfo *ti; - - /* - * The SCSI chip made a snapshot of the data bus while the reselection - * was being negotiated. This enables us to determine which target did - * the reselect. - */ - selid = sc->sc_selid & ~(1 << sc->sc_id); - if (selid & (selid - 1)) { - printf("%s: reselect with invalid selid %02x; sending DEVICE RESET\n", - sc->sc_dev.dv_xname, selid); - goto reset; - } - - /* - * Search wait queue for disconnected cmd - * The list should be short, so I haven't bothered with - * any more sophisticated structures than a simple - * singly linked list. - */ - target = ffs(selid) - 1; - lun = message & 0x07; - for (ecb = sc->nexus_list.tqh_first; ecb != NULL; - ecb = ecb->chain.tqe_next) { - sc_link = ecb->xs->sc_link; - if (sc_link->target == target && sc_link->lun == lun) - break; - } - if (ecb == NULL) { - printf("%s: reselect from target %d lun %d with no nexus; sending ABORT\n", - sc->sc_dev.dv_xname, target, lun); - goto abort; - } - - /* Make this nexus active again. */ - TAILQ_REMOVE(&sc->nexus_list, ecb, chain); - sc->sc_state = ESP_CONNECTED; - sc->sc_nexus = ecb; - ti = &sc->sc_tinfo[target]; - ti->lubusy |= (1 << lun); - esp_setsync(sc, ti); - - if (ecb->flags & ECB_RESET) - esp_sched_msgout(SEND_DEV_RESET); - else if (ecb->flags & ECB_ABORT) - esp_sched_msgout(SEND_ABORT); - - /* Do an implicit RESTORE POINTERS. */ - sc->sc_dp = ecb->daddr; - sc->sc_dleft = ecb->dleft; - - return (0); - -reset: - esp_sched_msgout(SEND_DEV_RESET); - return (1); - -abort: - esp_sched_msgout(SEND_ABORT); - return (1); -} - -#define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80) -#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) -#define ISEXTMSG(m) ((m) == 1) - -/* - * Get an incoming message as initiator. - * - * The SCSI bus must already be in MESSAGE_IN_PHASE and there is a - * byte in the FIFO - */ -void -esp_msgin(sc) - register struct esp_softc *sc; -{ - register int v; - - ESP_TRACE(("[esp_msgin(curmsglen:%ld)] ", (long)sc->sc_imlen)); - - if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) == 0) { - printf("%s: msgin: no msg byte available\n", - sc->sc_dev.dv_xname); - return; - } - - /* - * Prepare for a new message. A message should (according - * to the SCSI standard) be transmitted in one single - * MESSAGE_IN_PHASE. If we have been in some other phase, - * then this is a new message. - */ - if (sc->sc_prevphase != MESSAGE_IN_PHASE) { - sc->sc_flags &= ~ESP_DROP_MSGI; - sc->sc_imlen = 0; - } - - v = ESP_READ_REG(sc, ESP_FIFO); - ESP_MISC(("<msgbyte:0x%02x>", v)); - -#if 0 - if (sc->sc_state == ESP_RESELECTED && sc->sc_imlen == 0) { - /* - * Which target is reselecting us? (The ID bit really) - */ - sc->sc_selid = v; - ESP_MISC(("selid=0x%2x ", sc->sc_selid)); - return; - } -#endif - - sc->sc_imess[sc->sc_imlen] = v; - - /* - * If we're going to reject the message, don't bother storing - * the incoming bytes. But still, we need to ACK them. - */ - - if ((sc->sc_flags & ESP_DROP_MSGI)) { - ESPCMD(sc, ESPCMD_MSGOK); - printf("<dropping msg byte %x>", - sc->sc_imess[sc->sc_imlen]); - return; - } - - if (sc->sc_imlen >= ESP_MAX_MSG_LEN) { - esp_sched_msgout(SEND_REJECT); - sc->sc_flags |= ESP_DROP_MSGI; - } else { - sc->sc_imlen++; - /* - * This testing is suboptimal, but most - * messages will be of the one byte variety, so - * it should not effect performance - * significantly. - */ - if (sc->sc_imlen == 1 && IS1BYTEMSG(sc->sc_imess[0])) - goto gotit; - if (sc->sc_imlen == 2 && IS2BYTEMSG(sc->sc_imess[0])) - goto gotit; - if (sc->sc_imlen >= 3 && ISEXTMSG(sc->sc_imess[0]) && - sc->sc_imlen == sc->sc_imess[1] + 2) - goto gotit; - } - /* Ack what we have so far */ - ESPCMD(sc, ESPCMD_MSGOK); - return; - -gotit: - ESP_MSGS(("gotmsg(%x)", sc->sc_imess[0])); - /* - * Now we should have a complete message (1 byte, 2 byte - * and moderately long extended messages). We only handle - * extended messages which total length is shorter than - * ESP_MAX_MSG_LEN. Longer messages will be amputated. - */ - switch (sc->sc_state) { - struct esp_ecb *ecb; - struct esp_tinfo *ti; - - case ESP_CONNECTED: - ecb = sc->sc_nexus; - ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; - - switch (sc->sc_imess[0]) { - case MSG_CMDCOMPLETE: - ESP_MSGS(("cmdcomplete ")); - if (sc->sc_dleft < 0) { - struct scsi_link *sc_link = ecb->xs->sc_link; - printf("%s: %ld extra bytes from %d:%d\n", - sc->sc_dev.dv_xname, -(long)sc->sc_dleft, - sc_link->target, sc_link->lun); - sc->sc_dleft = 0; - } - ecb->xs->resid = ecb->dleft = sc->sc_dleft; - sc->sc_state = ESP_CMDCOMPLETE; - break; - - case MSG_MESSAGE_REJECT: - if (esp_debug & ESP_SHOWMSGS) - printf("%s: our msg rejected by target\n", - sc->sc_dev.dv_xname); - switch (sc->sc_msgout) { - case SEND_SDTR: - sc->sc_flags &= ~ESP_SYNCHNEGO; - ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE); - esp_setsync(sc, ti); - break; - case SEND_INIT_DET_ERR: - goto abort; - } - break; - - case MSG_NOOP: - ESP_MSGS(("noop ")); - break; - - case MSG_DISCONNECT: - ESP_MSGS(("disconnect ")); - ti->dconns++; - sc->sc_state = ESP_DISCONNECT; - if ((ecb->xs->sc_link->quirks & SDEV_AUTOSAVE) == 0) - break; - /*FALLTHROUGH*/ - - case MSG_SAVEDATAPOINTER: - ESP_MSGS(("save datapointer ")); - ecb->daddr = sc->sc_dp; - ecb->dleft = sc->sc_dleft; - break; - - case MSG_RESTOREPOINTERS: - ESP_MSGS(("restore datapointer ")); - sc->sc_dp = ecb->daddr; - sc->sc_dleft = ecb->dleft; - break; - - case MSG_EXTENDED: - ESP_MSGS(("extended(%x) ", sc->sc_imess[2])); - switch (sc->sc_imess[2]) { - case MSG_EXT_SDTR: - ESP_MSGS(("SDTR period %d, offset %d ", - sc->sc_imess[3], sc->sc_imess[4])); - if (sc->sc_imess[1] != 3) - goto reject; - ti->period = sc->sc_imess[3]; - ti->offset = sc->sc_imess[4]; - ti->flags &= ~T_NEGOTIATE; - if (sc->sc_minsync == 0 || - ti->offset == 0 || - ti->period > 124) { - printf("%s:%d: async\n", "esp", - ecb->xs->sc_link->target); - if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { - /* target initiated negotiation */ - ti->offset = 0; - ti->flags &= ~T_SYNCMODE; - esp_sched_msgout(SEND_SDTR); - } else { - /* we are async */ - ti->flags &= ~T_SYNCMODE; - } - } else { - int r = 250/ti->period; - int s = (100*250)/ti->period - 100*r; - int p; - - p = esp_stp2cpb(sc, ti->period); - ti->period = esp_cpb2stp(sc, p); -#ifdef ESP_DEBUG - sc_print_addr(ecb->xs->sc_link); - printf("max sync rate %d.%02dMb/s\n", - r, s); -#endif - if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { - /* target initiated negotiation */ - if (ti->period < sc->sc_minsync) - ti->period = sc->sc_minsync; - if (ti->offset > 15) - ti->offset = 15; - ti->flags &= ~T_SYNCMODE; - esp_sched_msgout(SEND_SDTR); - } else { - /* we are sync */ - ti->flags |= T_SYNCMODE; - } - } - sc->sc_flags &= ~ESP_SYNCHNEGO; - esp_setsync(sc, ti); - break; - - default: - printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n", - sc->sc_dev.dv_xname); - goto reject; - } - break; - - default: - ESP_MSGS(("ident ")); - printf("%s: unrecognized MESSAGE; sending REJECT\n", - sc->sc_dev.dv_xname); - reject: - esp_sched_msgout(SEND_REJECT); - break; - } - break; - - case ESP_RESELECTED: - if (!MSG_ISIDENTIFY(sc->sc_imess[0])) { - printf("%s: reselect without IDENTIFY; sending DEVICE RESET\n", - sc->sc_dev.dv_xname); - goto reset; - } - - (void) esp_reselect(sc, sc->sc_imess[0]); - break; - - default: - printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n", - sc->sc_dev.dv_xname); - reset: - esp_sched_msgout(SEND_DEV_RESET); - break; - - abort: - esp_sched_msgout(SEND_ABORT); - break; - } - - /* Ack last message byte */ - ESPCMD(sc, ESPCMD_MSGOK); - - /* Done, reset message pointer. */ - sc->sc_flags &= ~ESP_DROP_MSGI; - sc->sc_imlen = 0; -} - - -/* - * Send the highest priority, scheduled message - */ -void -esp_msgout(sc) - register struct esp_softc *sc; -{ - struct esp_tinfo *ti; - struct esp_ecb *ecb; - size_t size; - - ESP_TRACE(("[esp_msgout(priq:%x, prevphase:%x)]", sc->sc_msgpriq, sc->sc_prevphase)); - - if (sc->sc_flags & ESP_ATN) { - if (sc->sc_prevphase != MESSAGE_OUT_PHASE) { - new: - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - sc->sc_msgoutq = 0; - sc->sc_omlen = 0; - } - } else { - if (sc->sc_prevphase == MESSAGE_OUT_PHASE) { - esp_sched_msgout(sc->sc_msgoutq); - goto new; - } else { - printf("esp at line %d: unexpected MESSAGE OUT phase\n", __LINE__); - } - } - - if (sc->sc_omlen == 0) { - /* Pick up highest priority message */ - sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq; - sc->sc_msgoutq |= sc->sc_msgout; - sc->sc_msgpriq &= ~sc->sc_msgout; - sc->sc_omlen = 1; /* "Default" message len */ - switch (sc->sc_msgout) { - case SEND_SDTR: - ecb = sc->sc_nexus; - ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; - sc->sc_omess[0] = MSG_EXTENDED; - sc->sc_omess[1] = 3; - sc->sc_omess[2] = MSG_EXT_SDTR; - sc->sc_omess[3] = ti->period; - sc->sc_omess[4] = ti->offset; - sc->sc_omlen = 5; - if ((sc->sc_flags & ESP_SYNCHNEGO) == 0) { - ti->flags |= T_SYNCMODE; - esp_setsync(sc, ti); - } - break; - case SEND_IDENTIFY: - if (sc->sc_state != ESP_CONNECTED) { - printf("esp at line %d: no nexus\n", __LINE__); - } - ecb = sc->sc_nexus; - sc->sc_omess[0] = MSG_IDENTIFY(ecb->xs->sc_link->lun,0); - break; - case SEND_DEV_RESET: - sc->sc_flags |= ESP_ABORTING; - sc->sc_omess[0] = MSG_BUS_DEV_RESET; - ecb = sc->sc_nexus; - ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; - ti->flags &= ~T_SYNCMODE; - ti->flags |= T_NEGOTIATE; - break; - case SEND_PARITY_ERROR: - sc->sc_omess[0] = MSG_PARITY_ERROR; - break; - case SEND_ABORT: - sc->sc_flags |= ESP_ABORTING; - sc->sc_omess[0] = MSG_ABORT; - break; - case SEND_INIT_DET_ERR: - sc->sc_omess[0] = MSG_INITIATOR_DET_ERR; - break; - case SEND_REJECT: - sc->sc_omess[0] = MSG_MESSAGE_REJECT; - break; - default: - ESPCMD(sc, ESPCMD_RSTATN); - sc->sc_flags &= ~ESP_ATN; - sc->sc_omess[0] = MSG_NOOP; - break; - } - sc->sc_omp = sc->sc_omess; - } - -#if 1 - /* (re)send the message */ - size = min(sc->sc_omlen, sc->sc_maxxfer); - DMA_SETUP(sc->sc_dma, &sc->sc_omp, &sc->sc_omlen, 0, &size); - /* Program the SCSI counter */ - ESP_WRITE_REG(sc, ESP_TCL, size); - ESP_WRITE_REG(sc, ESP_TCM, size >> 8); - if (sc->sc_cfg2 & ESPCFG2_FE) { - ESP_WRITE_REG(sc, ESP_TCH, size >> 16); - } - /* load the count in */ - ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA); - ESPCMD(sc, ESPCMD_TRANS|ESPCMD_DMA); - DMA_GO(sc->sc_dma); -#else - { int i; - for (i = 0; i < sc->sc_omlen; i++) - ESP_WRITE_REG(sc, FIFO, sc->sc_omess[i]); - ESPCMD(sc, ESPCMD_TRANS); - sc->sc_omlen = 0; - } -#endif -} - -/* - * This is the most critical part of the driver, and has to know - * how to deal with *all* error conditions and phases from the SCSI - * bus. If there are no errors and the DMA was active, then call the - * DMA pseudo-interrupt handler. If this returns 1, then that was it - * and we can return from here without further processing. - * - * Most of this needs verifying. - */ -int -espintr(sc) - register struct esp_softc *sc; -{ - register struct esp_ecb *ecb; - register struct scsi_link *sc_link; - struct esp_tinfo *ti; - int loop; - size_t size; - - ESP_TRACE(("[espintr]")); - - /* - * I have made some (maybe seriously flawed) assumptions here, - * but basic testing (uncomment the printf() below), show that - * certainly something happens when this loop is here. - * - * The idea is that many of the SCSI operations take very little - * time, and going away and getting interrupted is too high an - * overhead to pay. For example, selecting, sending a message - * and command and then doing some work can be done in one "pass". - * - * The DELAY is not variable because I do not understand that the - * DELAY loop should be fixed-time regardless of CPU speed, but - * I am *assuming* that the faster SCSI processors get things done - * quicker (sending a command byte etc), and so there is no - * need to be too slow. - * - * This is a heuristic. It is 2 when at 20Mhz, 2 at 25Mhz and 1 - * at 40Mhz. This needs testing. - */ - for (loop = 0; 1;loop++, DELAY(50/sc->sc_freq)) { - /* a feeling of deja-vu */ - if (!DMA_ISINTR(sc->sc_dma)) - return (loop != 0); -#if 0 - if (loop) - printf("*"); -#endif - - /* and what do the registers say... */ - espreadregs(sc); - - sc->sc_intrcnt.ev_count++; - - /* - * At the moment, only a SCSI Bus Reset or Illegal - * Command are classed as errors. A disconnect is a - * valid condition, and we let the code check is the - * "ESP_BUSFREE_OK" flag was set before declaring it - * and error. - * - * Also, the status register tells us about "Gross - * Errors" and "Parity errors". Only the Gross Error - * is really bad, and the parity errors are dealt - * with later - * - * TODO - * If there are too many parity error, go to slow - * cable mode ? - */ - - /* SCSI Reset */ - if (sc->sc_espintr & ESPINTR_SBR) { - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - if (sc->sc_state != ESP_SBR) { - printf("%s: SCSI bus reset\n", - sc->sc_dev.dv_xname); - espinit(sc, 0); /* Restart everything */ - return 1; - } -#if 0 - /*XXX*/ printf("<expected bus reset: " - "[intr %x, stat %x, step %d]>\n", - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); -#endif - if (sc->sc_nexus) - panic("%s: nexus in reset state", - sc->sc_dev.dv_xname); - goto sched; - } - - ecb = sc->sc_nexus; - -#define ESPINTR_ERR (ESPINTR_SBR|ESPINTR_ILL) - if (sc->sc_espintr & ESPINTR_ERR || - sc->sc_espstat & ESPSTAT_GE) { - - if (sc->sc_espstat & ESPSTAT_GE) { - /* no target ? */ - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - if (sc->sc_state == ESP_CONNECTED || - sc->sc_state == ESP_SELECTING) { - ecb->xs->error = XS_DRIVER_STUFFUP; - esp_done(sc, ecb); - } - return 1; - } - - if (sc->sc_espintr & ESPINTR_ILL) { - /* illegal command, out of sync ? */ - printf("%s: illegal command: 0x%x (state %d, phase %x, prevphase %x)\n", - sc->sc_dev.dv_xname, sc->sc_lastcmd, - sc->sc_state, sc->sc_phase, - sc->sc_prevphase); - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - espinit(sc, 0); /* Restart everything */ - return 1; - } - } - - /* - * Call if DMA is active. - * - * If DMA_INTR returns true, then maybe go 'round the loop - * again in case there is no more DMA queued, but a phase - * change is expected. - */ - if (DMA_ISACTIVE(sc->sc_dma)) { - int r = DMA_INTR(sc->sc_dma); - if (r == -1) { - printf("%s: DMA error; resetting\n", - sc->sc_dev.dv_xname); - espinit(sc, 1); - } - /* If DMA active here, then go back to work... */ - if (DMA_ISACTIVE(sc->sc_dma)) - return 1; - - if (sc->sc_dleft == 0 && - (sc->sc_espstat & ESPSTAT_TC) == 0) - printf("%s: !TC [intr %x, stat %x, step %d]" - " prevphase %x, resid %lx\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, - sc->sc_espstat, - sc->sc_espstep, - sc->sc_prevphase, - ecb?ecb->dleft:-1); - } - -#if 0 /* Unreliable on some ESP revisions? */ - if ((sc->sc_espstat & ESPSTAT_INT) == 0) { - printf("%s: spurious interrupt\n", sc->sc_dev.dv_xname); - return 1; - } -#endif - - /* - * check for less serious errors - */ - if (sc->sc_espstat & ESPSTAT_PE) { - printf("%s: SCSI bus parity error\n", - sc->sc_dev.dv_xname); - if (sc->sc_prevphase == MESSAGE_IN_PHASE) - esp_sched_msgout(SEND_PARITY_ERROR); - else - esp_sched_msgout(SEND_INIT_DET_ERR); - } - - if (sc->sc_espintr & ESPINTR_DIS) { - ESP_MISC(("<DISC [intr %x, stat %x, step %d]>", - sc->sc_espintr,sc->sc_espstat,sc->sc_espstep)); - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - /* - * This command must (apparently) be issued within - * 250mS of a disconnect. So here you are... - */ - ESPCMD(sc, ESPCMD_ENSEL); - switch (sc->sc_state) { - case ESP_RESELECTED: - goto sched; - - case ESP_SELECTING: - ecb->xs->error = XS_SELTIMEOUT; - goto finish; - - case ESP_CONNECTED: - if ((sc->sc_flags & ESP_SYNCHNEGO)) { -#ifdef ESP_DEBUG - if (ecb) - sc_print_addr(ecb->xs->sc_link); - printf("sync nego not completed!\n"); -#endif - ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; - sc->sc_flags &= ~ESP_SYNCHNEGO; - ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE); - } - - /* it may be OK to disconnect */ - if ((sc->sc_flags & ESP_ABORTING) == 0) { - /* - * Section 5.1.1 of the SCSI 2 spec - * suggests issuing a REQUEST SENSE - * following an unexpected disconnect. - * Some devices go into a contingent - * allegiance condition when - * disconnecting, and this is necessary - * to clean up their state. - */ - printf("%s: unexpected disconnect; ", - sc->sc_dev.dv_xname); - if (ecb->flags & ECB_SENSE) { - printf("resetting\n"); - goto reset; - } - printf("sending REQUEST SENSE\n"); - esp_sense(sc, ecb); - goto out; - } - - ecb->xs->error = XS_DRIVER_STUFFUP; - goto finish; - - case ESP_DISCONNECT: - TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain); - sc->sc_nexus = NULL; - goto sched; - - case ESP_CMDCOMPLETE: - goto finish; - } - } - - switch (sc->sc_state) { - - case ESP_SBR: - printf("%s: waiting for SCSI Bus Reset to happen\n", - sc->sc_dev.dv_xname); - return 1; - - case ESP_RESELECTED: - /* - * we must be continuing a message ? - */ - if (sc->sc_phase != MESSAGE_IN_PHASE) { - printf("%s: target didn't identify\n", - sc->sc_dev.dv_xname); - espinit(sc, 1); - return 1; - } -printf("<<RESELECT CONT'd>>"); -#if XXXX - esp_msgin(sc); - if (sc->sc_state != ESP_CONNECTED) { - /* IDENTIFY fail?! */ - printf("%s: identify failed\n", - sc->sc_dev.dv_xname); - espinit(sc, 1); - return 1; - } -#endif - break; - - case ESP_IDLE: -if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]"); - case ESP_SELECTING: - sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0; - sc->sc_flags = 0; - - if (sc->sc_espintr & ESPINTR_RESEL) { - /* - * If we're trying to select a - * target ourselves, push our command - * back into the ready list. - */ - if (sc->sc_state == ESP_SELECTING) { - ESP_MISC(("backoff selector ")); - sc_link = sc->sc_nexus->xs->sc_link; - ti = &sc->sc_tinfo[sc_link->target]; - TAILQ_INSERT_HEAD(&sc->ready_list, - sc->sc_nexus, chain); - ecb = sc->sc_nexus = NULL; - } - sc->sc_state = ESP_RESELECTED; - if (sc->sc_phase != MESSAGE_IN_PHASE) { - /* - * Things are seriously fucked up. - * Pull the brakes, i.e. reset - */ - printf("%s: target didn't identify\n", - sc->sc_dev.dv_xname); - espinit(sc, 1); - return 1; - } - if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) { - printf("%s: RESELECT: %d bytes in FIFO!\n", - sc->sc_dev.dv_xname, - ESP_READ_REG(sc, ESP_FFLAG) & - ESPFIFO_FF); - espinit(sc, 1); - return 1; - } - sc->sc_selid = ESP_READ_REG(sc, ESP_FIFO); - ESP_MISC(("selid=0x%2x ", sc->sc_selid)); - esp_msgin(sc); /* Handle identify message */ - if (sc->sc_state != ESP_CONNECTED) { - /* IDENTIFY fail?! */ - printf("%s: identify failed\n", - sc->sc_dev.dv_xname); - espinit(sc, 1); - return 1; - } - continue; /* ie. next phase expected soon */ - } - -#define ESPINTR_DONE (ESPINTR_FC|ESPINTR_BS) - if ((sc->sc_espintr & ESPINTR_DONE) == ESPINTR_DONE) { - ecb = sc->sc_nexus; - if (!ecb) - panic("esp: not nexus at sc->sc_nexus"); - - sc_link = ecb->xs->sc_link; - ti = &sc->sc_tinfo[sc_link->target]; - - switch (sc->sc_espstep) { - case 0: - printf("%s: select timeout/no disconnect\n", - sc->sc_dev.dv_xname); - ecb->xs->error = XS_SELTIMEOUT; - goto finish; - case 1: - if ((ti->flags & T_NEGOTIATE) == 0) { - printf("%s: step 1 & !NEG\n", - sc->sc_dev.dv_xname); - goto reset; - } - if (sc->sc_phase != MESSAGE_OUT_PHASE) { - printf("%s: !MSGOUT\n", - sc->sc_dev.dv_xname); - goto reset; - } - /* Start negotiating */ - ti->period = sc->sc_minsync; - ti->offset = 15; - sc->sc_flags |= ESP_SYNCHNEGO; - esp_sched_msgout(SEND_SDTR); - break; - case 3: - /* - * Grr, this is supposed to mean - * "target left command phase - * prematurely". It seems to happen - * regularly when sync mode is on. - * Look at FIFO to see if command - * went out. - * (Timing problems?) - */ - if ((ESP_READ_REG(sc, ESP_FFLAG)&ESPFIFO_FF) == 0) { - /* Hope for the best.. */ - break; - } - printf("(%s:%d:%d): selection failed;" - " %d left in FIFO " - "[intr %x, stat %x, step %d]\n", - sc->sc_dev.dv_xname, - sc_link->target, - sc_link->lun, - ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - ESPCMD(sc, ESPCMD_FLUSH); - esp_sched_msgout(SEND_ABORT); - return 1; - case 2: - /* Select stuck at Command Phase */ - ESPCMD(sc, ESPCMD_FLUSH); - case 4: - /* So far, everything went fine */ - break; - } -#if 0 - if (ecb->xs->flags & SCSI_RESET) - esp_sched_msgout(SEND_DEV_RESET); - else if (ti->flags & T_NEGOTIATE) - esp_sched_msgout( - SEND_IDENTIFY | SEND_SDTR); - else - esp_sched_msgout(SEND_IDENTIFY); -#endif - - ecb->flags |= ECB_NEXUS; - ti->lubusy |= (1 << sc_link->lun); - - sc->sc_prevphase = INVALID_PHASE; /* ?? */ - /* Do an implicit RESTORE POINTERS. */ - sc->sc_dp = ecb->daddr; - sc->sc_dleft = ecb->dleft; - - /* On our first connection, schedule a timeout. */ - if ((ecb->xs->flags & SCSI_POLL) == 0) - timeout_add(&ecb->xs->stimeout, - (ecb->timeout * hz) / 1000); - - sc->sc_state = ESP_CONNECTED; - break; - } else { - printf("%s: unexpected status after select" - ": [intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - goto reset; - } - if (sc->sc_state == ESP_IDLE) { - printf("%s: stray interrupt\n", sc->sc_dev.dv_xname); - return 0; - } - break; - - case ESP_CONNECTED: - if (sc->sc_flags & ESP_ICCS) { - u_char msg; - - sc->sc_flags &= ~ESP_ICCS; - - if (!(sc->sc_espintr & ESPINTR_DONE)) { - printf("%s: ICCS: " - ": [intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - } - if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) { - int i = (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) - 2; - while (i--) - (void) ESP_READ_REG(sc, ESP_FIFO); - } - ecb->stat = ESP_READ_REG(sc, ESP_FIFO); - msg = ESP_READ_REG(sc, ESP_FIFO); - ESP_PHASE(("<stat:(%x,%x)>", ecb->stat, msg)); - if (msg == MSG_CMDCOMPLETE) { - ecb->xs->resid = ecb->dleft = sc->sc_dleft; - sc->sc_state = ESP_CMDCOMPLETE; - } else - printf("%s: STATUS_PHASE: msg %d\n", - sc->sc_dev.dv_xname, msg); - ESPCMD(sc, ESPCMD_MSGOK); - continue; /* ie. wait for disconnect */ - } - break; - default: - panic("%s: invalid state: %d", - sc->sc_dev.dv_xname, - sc->sc_state); - } - - /* - * Driver is now in state ESP_CONNECTED, i.e. we - * have a current command working the SCSI bus. - */ - if (sc->sc_state != ESP_CONNECTED || ecb == NULL) { - panic("esp no nexus"); - } - - switch (sc->sc_phase) { - case MESSAGE_OUT_PHASE: - ESP_PHASE(("MESSAGE_OUT_PHASE ")); - esp_msgout(sc); - sc->sc_prevphase = MESSAGE_OUT_PHASE; - break; - case MESSAGE_IN_PHASE: - ESP_PHASE(("MESSAGE_IN_PHASE ")); - if (sc->sc_espintr & ESPINTR_BS) { - ESPCMD(sc, ESPCMD_FLUSH); - sc->sc_flags |= ESP_WAITI; - ESPCMD(sc, ESPCMD_TRANS); - } else if (sc->sc_espintr & ESPINTR_FC) { - if ((sc->sc_flags & ESP_WAITI) == 0) { - printf("%s: MSGIN: unexpected FC bit: " - "[intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - } - sc->sc_flags &= ~ESP_WAITI; - esp_msgin(sc); - } else { - printf("%s: MSGIN: weird bits: " - "[intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - } - sc->sc_prevphase = MESSAGE_IN_PHASE; - break; - case COMMAND_PHASE: { - /* well, this means send the command again */ - u_char *cmd = (u_char *)&ecb->cmd; - int i; - - ESP_PHASE(("COMMAND_PHASE 0x%02x (%d) ", - ecb->cmd.opcode, ecb->clen)); - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - /* Now the command into the FIFO */ - for (i = 0; i < ecb->clen; i++) - ESP_WRITE_REG(sc, ESP_FIFO, *cmd++); - ESPCMD(sc, ESPCMD_TRANS); - sc->sc_prevphase = COMMAND_PHASE; - } - break; - case DATA_OUT_PHASE: - ESP_PHASE(("DATA_OUT_PHASE [%ld] ",(long)sc->sc_dleft)); - ESPCMD(sc, ESPCMD_FLUSH); - size = min(sc->sc_dleft, sc->sc_maxxfer); - DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, - 0, &size); - sc->sc_prevphase = DATA_OUT_PHASE; - goto setup_xfer; - case DATA_IN_PHASE: - ESP_PHASE(("DATA_IN_PHASE ")); - if (sc->sc_rev == ESP100) - ESPCMD(sc, ESPCMD_FLUSH); - size = min(sc->sc_dleft, sc->sc_maxxfer); - DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, - 1, &size); - sc->sc_prevphase = DATA_IN_PHASE; - setup_xfer: - /* Program the SCSI counter */ - ESP_WRITE_REG(sc, ESP_TCL, size); - ESP_WRITE_REG(sc, ESP_TCM, size >> 8); - if (sc->sc_cfg2 & ESPCFG2_FE) { - ESP_WRITE_REG(sc, ESP_TCH, size >> 16); - } - /* load the count in */ - ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA); - - /* - * Note that if `size' is 0, we've already transceived - * all the bytes we want but we're still in DATA PHASE. - * Apparently, the device needs padding. Also, a - * transfer size of 0 means "maximum" to the chip - * DMA logic. - */ - ESPCMD(sc, - (size==0?ESPCMD_TRPAD:ESPCMD_TRANS)|ESPCMD_DMA); - DMA_GO(sc->sc_dma); - return 1; - case STATUS_PHASE: - ESP_PHASE(("STATUS_PHASE ")); - sc->sc_flags |= ESP_ICCS; - ESPCMD(sc, ESPCMD_ICCS); - sc->sc_prevphase = STATUS_PHASE; - break; - case INVALID_PHASE: - break; - default: - printf("%s: unexpected bus phase; resetting\n", - sc->sc_dev.dv_xname); - goto reset; - } - } - panic("esp: should not get here.."); - -reset: - espinit(sc, 1); - return 1; - -finish: - timeout_del(&ecb->xs->stimeout); - esp_done(sc, ecb); - goto out; - -sched: - sc->sc_state = ESP_IDLE; - esp_sched(sc); - goto out; - -out: - return 1; -} - -void -esp_abort(sc, ecb) - struct esp_softc *sc; - struct esp_ecb *ecb; -{ - - /* 2 secs for the abort */ - ecb->timeout = ESP_ABORT_TIMEOUT; - ecb->flags |= ECB_ABORT; - - if (ecb == sc->sc_nexus) { - /* - * If we're still selecting, the message will be scheduled - * after selection is complete. - */ - if (sc->sc_state == ESP_CONNECTED) - esp_sched_msgout(SEND_ABORT); - - /* - * Reschedule timeout. First, cancel a queued timeout (if any) - * in case someone decides to call esp_abort() from elsewhere. - */ - timeout_add(&ecb->xs->stimeout, (ecb->timeout * hz) / 1000); - } else { - esp_dequeue(sc, ecb); - TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain); - if (sc->sc_state == ESP_IDLE) - esp_sched(sc); - } -} - -void -esp_timeout(arg) - void *arg; -{ - struct esp_ecb *ecb = arg; - struct scsi_xfer *xs = ecb->xs; - struct scsi_link *sc_link = xs->sc_link; - struct esp_softc *sc = sc_link->adapter_softc; - int s; - - sc_print_addr(sc_link); - printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], " - "<state %d, nexus %p, phase(c %x, p %x), resid %lx, msg(q %x,o %x) %s>", - sc->sc_dev.dv_xname, - ecb, ecb->flags, ecb->dleft, ecb->stat, - sc->sc_state, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase, - (long)sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout, - DMA_ISACTIVE(sc->sc_dma) ? "DMA active" : ""); -#if ESP_DEBUG > 0 - printf("TRACE: %s.", ecb->trace); -#endif - - s = splbio(); - - if (ecb->flags & ECB_ABORT) { - /* abort timed out */ - printf(" AGAIN\n"); - espinit(sc, 1); - } else { - /* abort the operation that has timed out */ - printf("\n"); - xs->error = XS_TIMEOUT; - esp_abort(sc, ecb); - } - - splx(s); -} diff --git a/sys/arch/alpha/tc/ascreg.h b/sys/arch/alpha/tc/ascreg.h deleted file mode 100644 index 3ed0088e759..00000000000 --- a/sys/arch/alpha/tc/ascreg.h +++ /dev/null @@ -1,149 +0,0 @@ -/* $OpenBSD: ascreg.h,v 1.1 2000/07/05 21:50:38 ericj Exp $ */ -/* $NetBSD: espreg.h,v 1.3 1996/09/09 18:10:37 cgd Exp $ */ - -/* - * Copyright (c) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Peter Galbavy. - * 4. 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. - */ - -/* - * Register addresses, relative to some base address - */ - -#define ESP_TCL 0x00 /* RW - Transfer Count Low */ -#define ESP_TCM 0x01 /* RW - Transfer Count Mid */ -#define ESP_TCH 0x0e /* RW - Transfer Count High */ - /* NOT on 53C90 */ - -#define ESP_FIFO 0x02 /* RW - FIFO data */ - -#define ESP_CMD 0x03 /* RW - Command (2 deep) */ -#define ESPCMD_DMA 0x80 /* DMA Bit */ -#define ESPCMD_NOP 0x00 /* No Operation */ -#define ESPCMD_FLUSH 0x01 /* Flush FIFO */ -#define ESPCMD_RSTCHIP 0x02 /* Reset Chip */ -#define ESPCMD_RSTSCSI 0x03 /* Reset SCSI Bus */ -#define ESPCMD_RESEL 0x40 /* Reselect Sequence */ -#define ESPCMD_SELNATN 0x41 /* Select without ATN */ -#define ESPCMD_SELATN 0x42 /* Select with ATN */ -#define ESPCMD_SELATNS 0x43 /* Select with ATN & Stop */ -#define ESPCMD_ENSEL 0x44 /* Enable (Re)Selection */ -#define ESPCMD_DISSEL 0x45 /* Disable (Re)Selection */ -#define ESPCMD_SELATN3 0x46 /* Select with ATN3 */ -#define ESPCMD_RESEL3 0x47 /* Reselect3 Sequence */ -#define ESPCMD_SNDMSG 0x20 /* Send Message */ -#define ESPCMD_SNDSTAT 0x21 /* Send Status */ -#define ESPCMD_SNDDATA 0x22 /* Send Data */ -#define ESPCMD_DISCSEQ 0x23 /* Disconnect Sequence */ -#define ESPCMD_TERMSEQ 0x24 /* Terminate Sequence */ -#define ESPCMD_TCCS 0x25 /* Target Command Comp Seq */ -#define ESPCMD_DISC 0x27 /* Disconnect */ -#define ESPCMD_RECMSG 0x28 /* Receive Message */ -#define ESPCMD_RECCMD 0x29 /* Receive Command */ -#define ESPCMD_RECDATA 0x2a /* Receive Data */ -#define ESPCMD_RECCSEQ 0x2b /* Receive Command Sequence*/ -#define ESPCMD_ABORT 0x04 /* Target Abort DMA */ -#define ESPCMD_TRANS 0x10 /* Transfer Information */ -#define ESPCMD_ICCS 0x11 /* Initiator Cmd Comp Seq */ -#define ESPCMD_MSGOK 0x12 /* Message Accepted */ -#define ESPCMD_TRPAD 0x18 /* Transfer Pad */ -#define ESPCMD_SETATN 0x1a /* Set ATN */ -#define ESPCMD_RSTATN 0x1b /* Reset ATN */ - -#define ESP_STAT 0x04 /* RO - Status */ -#define ESPSTAT_INT 0x80 /* Interrupt */ -#define ESPSTAT_GE 0x40 /* Gross Error */ -#define ESPSTAT_PE 0x20 /* Parity Error */ -#define ESPSTAT_TC 0x10 /* Terminal Count */ -#define ESPSTAT_VGC 0x08 /* Valid Group Code */ -#define ESPSTAT_PHASE 0x07 /* Phase bits */ - -#define ESP_SELID 0x04 /* WO - Select/Reselect Bus ID */ - -#define ESP_INTR 0x05 /* RO - Interrupt */ -#define ESPINTR_SBR 0x80 /* SCSI Bus Reset */ -#define ESPINTR_ILL 0x40 /* Illegal Command */ -#define ESPINTR_DIS 0x20 /* Disconnect */ -#define ESPINTR_BS 0x10 /* Bus Service */ -#define ESPINTR_FC 0x08 /* Function Complete */ -#define ESPINTR_RESEL 0x04 /* Reselected */ -#define ESPINTR_SELATN 0x02 /* Select with ATN */ -#define ESPINTR_SEL 0x01 /* Selected */ - -#define ESP_TIMEOUT 0x05 /* WO - Select/Reselect Timeout */ - -#define ESP_STEP 0x06 /* RO - Sequence Step */ -#define ESPSTEP_MASK 0x07 /* the last 3 bits */ -#define ESPSTEP_DONE 0x04 /* command went out */ - -#define ESP_SYNCTP 0x06 /* WO - Synch Transfer Period */ - /* Default 5 (53C9X) */ - -#define ESP_FFLAG 0x07 /* RO - FIFO Flags */ -#define ESPFIFO_SS 0xe0 /* Sequence Step (Dup) */ -#define ESPFIFO_FF 0x1f /* Bytes in FIFO */ - -#define ESP_SYNCOFF 0x07 /* WO - Synch Offset */ - /* 0 = ASYNC */ - /* 1 - 15 = SYNC bytes */ - -#define ESP_CFG1 0x08 /* RW - Configuration #1 */ -#define ESPCFG1_SLOW 0x80 /* Slow Cable Mode */ -#define ESPCFG1_SRR 0x40 /* SCSI Reset Rep Int Dis */ -#define ESPCFG1_PTEST 0x20 /* Parity Test Mod */ -#define ESPCFG1_PARENB 0x10 /* Enable Parity Check */ -#define ESPCFG1_CTEST 0x08 /* Enable Chip Test */ -#define ESPCFG1_BUSID 0x07 /* Bus ID */ - -#define ESP_CCF 0x09 /* WO - Clock Conversion Factor */ - /* 0 = 35.01 - 40Mhz */ - /* NEVER SET TO 1 */ - /* 2 = 10Mhz */ - /* 3 = 10.01 - 15Mhz */ - /* 4 = 15.01 - 20Mhz */ - /* 5 = 20.01 - 25Mhz */ - /* 6 = 25.01 - 30Mhz */ - /* 7 = 30.01 - 35Mhz */ - -#define ESP_TEST 0x0a /* WO - Test (Chip Test Only) */ - -#define ESP_CFG2 0x0b /* RW - Configuration #2 */ -#define ESPCFG2_RSVD 0xa0 /* reserved */ -#define ESPCFG2_FE 0x40 /* Features Enable */ -#define ESPCFG2_DREQ 0x10 /* DREQ High Impedance */ -#define ESPCFG2_SCSI2 0x08 /* SCSI-2 Enable */ -#define ESPCFG2_BPA 0x04 /* Target Bad Parity Abort */ -#define ESPCFG2_RPE 0x02 /* Register Parity Error */ -#define ESPCFG2_DPE 0x01 /* DMA Parity Error */ - -/* Config #3 only on 53C9X */ -#define ESP_CFG3 0x0c /* RW - Configuration #3 */ -#define ESPCFG3_RSVD 0xe0 /* reserved */ -#define ESPCFG3_IDM 0x10 /* ID Message Res Check */ -#define ESPCFG3_QTE 0x08 /* Queue Tag Enable */ -#define ESPCFG3_CDB 0x04 /* CDB 10-bytes OK */ -#define ESPCFG3_FSCSI 0x02 /* Fast SCSI */ -#define ESPCFG3_FCLK 0x01 /* Fast Clock (>25Mhz) */ diff --git a/sys/arch/alpha/tc/ascvar.h b/sys/arch/alpha/tc/ascvar.h deleted file mode 100644 index 7d6b140f7a4..00000000000 --- a/sys/arch/alpha/tc/ascvar.h +++ /dev/null @@ -1,339 +0,0 @@ -/* $OpenBSD: ascvar.h,v 1.2 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: espvar.h,v 1.12 1996/11/24 04:21:30 cgd Exp $ */ - -#if defined(__sparc__) && !defined(SPARC_DRIVER) -#define SPARC_DRIVER -#endif - -/* - * Copyright (c) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Peter Galbavy. - * 4. 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. - */ - -#define ESP_DEBUG 0 - -#define ESP_ABORT_TIMEOUT 2000 /* time to wait for abort */ - -#define FREQTOCCF(freq) (((freq + 4) / 5)) - -/* esp revisions */ -#define ESP100 0x01 -#define ESP100A 0x02 -#define ESP200 0x03 -#define NCR53C94 0x04 - -/* - * ECB. Holds additional information for each SCSI command Comments: We - * need a separate scsi command block because we may need to overwrite it - * with a request sense command. Basicly, we refrain from fiddling with - * the scsi_xfer struct (except do the expected updating of return values). - * We'll generally update: xs->{flags,resid,error,sense,status} and - * occasionally xs->retries. - */ -struct esp_ecb { - TAILQ_ENTRY(esp_ecb) chain; - struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ - int flags; -#define ECB_ALLOC 0x01 -#define ECB_NEXUS 0x02 -#define ECB_SENSE 0x04 -#define ECB_ABORT 0x40 -#define ECB_RESET 0x80 - int timeout; - - struct scsi_generic cmd; /* SCSI command block */ - int clen; - char *daddr; /* Saved data pointer */ - int dleft; /* Residue */ - u_char stat; /* SCSI status byte */ - -#if ESP_DEBUG > 0 - char trace[1000]; -#endif -}; -#if ESP_DEBUG > 0 -#define ECB_TRACE(ecb, msg, a, b) do { \ - const char *f = "[" msg "]"; \ - int n = strlen((ecb)->trace); \ - if (n < (sizeof((ecb)->trace)-100)) \ - sprintf((ecb)->trace + n, f, a, b); \ -} while(0) -#else -#define ECB_TRACE(ecb, msg, a, b) -#endif - -/* - * Some info about each (possible) target on the SCSI bus. This should - * probably have been a "per target+lunit" structure, but we'll leave it at - * this for now. Is there a way to reliably hook it up to sc->fordriver?? - */ -struct esp_tinfo { - int cmds; /* #commands processed */ - int dconns; /* #disconnects */ - int touts; /* #timeouts */ - int perrs; /* #parity errors */ - int senses; /* #request sense commands sent */ - ushort lubusy; /* What local units/subr. are busy? */ - u_char flags; -#define T_NEED_TO_RESET 0x01 /* Should send a BUS_DEV_RESET */ -#define T_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */ -#define T_BUSY 0x04 /* Target is busy, i.e. cmd in progress */ -#define T_SYNCMODE 0x08 /* sync mode has been negotiated */ -#define T_SYNCHOFF 0x10 /* .. */ -#define T_RSELECTOFF 0x20 /* .. */ - u_char period; /* Period suggestion */ - u_char offset; /* Offset suggestion */ -} tinfo_t; - -/* Register a linenumber (for debugging) */ -#define LOGLINE(p) - -#define ESP_SHOWECBS 0x01 -#define ESP_SHOWINTS 0x02 -#define ESP_SHOWCMDS 0x04 -#define ESP_SHOWMISC 0x08 -#define ESP_SHOWTRAC 0x10 -#define ESP_SHOWSTART 0x20 -#define ESP_SHOWPHASE 0x40 -#define ESP_SHOWDMA 0x80 -#define ESP_SHOWCCMDS 0x100 -#define ESP_SHOWMSGS 0x200 - -#ifdef ESP_DEBUG -extern int esp_debug; -#define ESP_ECBS(str) do {if (esp_debug & ESP_SHOWECBS) printf str;} while (0) -#define ESP_MISC(str) do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0) -#define ESP_INTS(str) do {if (esp_debug & ESP_SHOWINTS) printf str;} while (0) -#define ESP_TRACE(str) do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0) -#define ESP_CMDS(str) do {if (esp_debug & ESP_SHOWCMDS) printf str;} while (0) -#define ESP_START(str) do {if (esp_debug & ESP_SHOWSTART) printf str;}while (0) -#define ESP_PHASE(str) do {if (esp_debug & ESP_SHOWPHASE) printf str;}while (0) -#define ESP_DMA(str) do {if (esp_debug & ESP_SHOWDMA) printf str;}while (0) -#define ESP_MSGS(str) do {if (esp_debug & ESP_SHOWMSGS) printf str;}while (0) -#else -#define ESP_ECBS(str) -#define ESP_MISC(str) -#define ESP_INTS(str) -#define ESP_TRACE(str) -#define ESP_CMDS(str) -#define ESP_START(str) -#define ESP_PHASE(str) -#define ESP_DMA(str) -#define ESP_MSGS(str) -#endif - -#define ESP_MAX_MSG_LEN 8 - -struct esp_softc { - struct device sc_dev; /* us as a device */ -#ifdef SPARC_DRIVER - struct sbusdev sc_sd; /* sbus device */ - struct intrhand sc_ih; /* intr handler */ -#endif - struct evcnt sc_intrcnt; /* intr count */ - struct scsi_link sc_link; /* scsi lint struct */ -#ifdef SPARC_DRIVER - volatile u_char *sc_reg; /* the registers */ - struct dma_softc *sc_dma; /* pointer to my dma */ -#else - volatile u_int32_t *sc_reg; /* the registers */ - struct tcds_slotconfig *sc_dma; /* DMA/slot info lives here. */ - void *sc_cookie; /* intr. handling cookie */ -#endif - - /* register defaults */ - u_char sc_cfg1; /* Config 1 */ - u_char sc_cfg2; /* Config 2, not ESP100 */ - u_char sc_cfg3; /* Config 3, only ESP200 */ - u_char sc_ccf; /* Clock Conversion */ - u_char sc_timeout; - - /* register copies, see espreadregs() */ - u_char sc_espintr; - u_char sc_espstat; - u_char sc_espstep; - u_char sc_espfflags; - - /* Lists of command blocks */ - TAILQ_HEAD(ecb_list, esp_ecb) free_list, - ready_list, - nexus_list; - - struct esp_ecb *sc_nexus; /* current command */ - struct esp_ecb sc_ecb[3*8]; /* three per target */ - struct esp_tinfo sc_tinfo[8]; - - /* Data about the current nexus (updated for every cmd switch) */ - caddr_t sc_dp; /* Current data pointer */ - ssize_t sc_dleft; /* Data left to transfer */ - - /* Adapter state */ - int sc_phase; /* Copy of what bus phase we are in */ - int sc_prevphase; /* Copy of what bus phase we were in */ - u_char sc_state; /* State applicable to the adapter */ - u_char sc_flags; - u_char sc_selid; - u_char sc_lastcmd; - - /* Message stuff */ - u_char sc_msgpriq; /* One or more messages to send (encoded) */ - u_char sc_msgout; /* What message is on its way out? */ - u_char sc_msgoutq; /* What messages have been sent so far? */ - u_char sc_omess[ESP_MAX_MSG_LEN]; - caddr_t sc_omp; /* Message pointer (for multibyte messages) */ - size_t sc_omlen; - u_char sc_imess[ESP_MAX_MSG_LEN + 1]; - caddr_t sc_imp; /* Message pointer (for multibyte messages) */ - size_t sc_imlen; - - /* hardware/openprom stuff */ - int sc_node; /* PROM node ID */ - int sc_freq; /* Freq in HZ */ -#ifdef SPARC_DRIVER - int sc_pri; /* SBUS priority */ -#endif - int sc_id; /* our scsi id */ - int sc_rev; /* esp revision */ - int sc_minsync; /* minimum sync period / 4 */ - int sc_maxxfer; /* maximum transfer size */ -}; - -/* values for sc_state */ -#define ESP_IDLE 1 /* waiting for something to do */ -#define ESP_SELECTING 2 /* SCSI command is arbiting */ -#define ESP_RESELECTED 3 /* Has been reselected */ -#define ESP_CONNECTED 4 /* Actively using the SCSI bus */ -#define ESP_DISCONNECT 5 /* MSG_DISCONNECT received */ -#define ESP_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */ -#define ESP_CLEANING 7 -#define ESP_SBR 8 /* Expect a SCSI RST because we commanded it */ - -/* values for sc_flags */ -#define ESP_DROP_MSGI 0x01 /* Discard all msgs (parity err detected) */ -#define ESP_ABORTING 0x02 /* Bailing out */ -#define ESP_DOINGDMA 0x04 /* The FIFO data path is active! */ -#define ESP_SYNCHNEGO 0x08 /* Synch negotiation in progress. */ -#define ESP_ICCS 0x10 /* Expect status phase results */ -#define ESP_WAITI 0x20 /* Waiting for non-DMA data to arrive */ -#define ESP_ATN 0x40 /* ATN asserted */ - -/* values for sc_msgout */ -#define SEND_DEV_RESET 0x01 -#define SEND_PARITY_ERROR 0x02 -#define SEND_INIT_DET_ERR 0x04 -#define SEND_REJECT 0x08 -#define SEND_IDENTIFY 0x10 -#define SEND_ABORT 0x20 -#define SEND_SDTR 0x40 -#define SEND_WDTR 0x80 - -/* SCSI Status codes */ -#define ST_MASK 0x3e /* bit 0,6,7 is reserved */ - -/* phase bits */ -#define IOI 0x01 -#define CDI 0x02 -#define MSGI 0x04 - -/* Information transfer phases */ -#define DATA_OUT_PHASE (0) -#define DATA_IN_PHASE (IOI) -#define COMMAND_PHASE (CDI) -#define STATUS_PHASE (CDI|IOI) -#define MESSAGE_OUT_PHASE (MSGI|CDI) -#define MESSAGE_IN_PHASE (MSGI|CDI|IOI) - -#define PHASE_MASK (MSGI|CDI|IOI) - -/* Some pseudo phases for getphase()*/ -#define BUSFREE_PHASE 0x100 /* Re/Selection no longer valid */ -#define INVALID_PHASE 0x101 /* Re/Selection valid, but no REQ yet */ -#define PSEUDO_PHASE 0x100 /* "pseudo" bit */ - -/* - * Macros to read and write the chip's registers. - */ -#ifdef SPARC_DRIVER -#define ESP_READ_REG(sc, reg) \ - ((sc)->sc_reg[(reg) * 4]) -#define ESP_WRITE_REG(sc, reg, val) \ - do { \ - u_char v = (val); \ - (sc)->sc_reg[(reg) * 4] = v; \ - } while (0) -#else /* ! SPARC_DRIVER */ -#if 1 -static __inline u_char ESP_READ_REG(struct esp_softc *, int); - -static __inline u_char -ESP_READ_REG(sc, reg) - struct esp_softc *sc; - int reg; -{ - u_char v; - - v = sc->sc_reg[reg * 2] & 0xff; - alpha_mb(); - return v; -} -#else -#define ESP_READ_REG(sc, reg) \ - ((u_char)((sc)->sc_reg[(reg) * 2] & 0xff)) -#endif -#define ESP_WRITE_REG(sc, reg, val) \ - do { \ - u_char v = (val); \ - (sc)->sc_reg[(reg) * 2] = v; \ - alpha_mb(); \ - } while (0) -#endif /* SPARC_DRIVER */ - -#ifdef ESP_DEBUG -#define ESPCMD(sc, cmd) do { \ - if (esp_debug & ESP_SHOWCCMDS) \ - printf("<cmd:0x%x>", (unsigned)cmd); \ - sc->sc_lastcmd = cmd; \ - ESP_WRITE_REG(sc, ESP_CMD, cmd); \ -} while (0) -#else -#define ESPCMD(sc, cmd) ESP_WRITE_REG(sc, ESP_CMD, cmd) -#endif - -#define SAME_ESP(sc, bp, ca) \ - ((bp->val[0] == ca->ca_slot && bp->val[1] == ca->ca_offset) || \ - (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)) - -#ifndef SPARC_DRIVER -/* DMA macros for ESP */ -#define DMA_ISINTR(sc) tcds_dma_isintr(sc) -#define DMA_RESET(sc) tcds_dma_reset(sc) -#define DMA_INTR(sc) tcds_dma_intr(sc) -#define DMA_SETUP(sc, addr, len, datain, dmasize) \ - tcds_dma_setup(sc, addr, len, datain, dmasize) -#define DMA_GO(sc) tcds_dma_go(sc) -#define DMA_ISACTIVE(sc) tcds_dma_isactive(sc) -#endif diff --git a/sys/arch/alpha/tc/ioasic.c b/sys/arch/alpha/tc/ioasic.c index d95660442b6..a66b8eaf010 100644 --- a/sys/arch/alpha/tc/ioasic.c +++ b/sys/arch/alpha/tc/ioasic.c @@ -1,5 +1,42 @@ -/* $OpenBSD: ioasic.c,v 1.8 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: ioasic.c,v 1.10 1996/12/05 01:39:41 cgd Exp $ */ +/* $OpenBSD: ioasic.c,v 1.9 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: ioasic.c,v 1.34 2000/07/18 06:10:06 thorpej Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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) 1994, 1995, 1996 Carnegie-Mellon University. @@ -32,33 +69,21 @@ #include <sys/kernel.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/malloc.h> #include <machine/autoconf.h> +#include <machine/bus.h> #include <machine/pte.h> #include <machine/rpb.h> -#ifndef EVCNT_COUNTERS #include <machine/intrcnt.h> -#endif #include <dev/tc/tcvar.h> -#include <alpha/tc/ioasicreg.h> +#include <dev/tc/ioasicreg.h> #include <dev/tc/ioasicvar.h> -struct ioasic_softc { - struct device sc_dv; - - tc_addr_t sc_base; - void *sc_cookie; -}; - /* Definition of the driver for autoconfig. */ -#ifdef __BROKEN_INDIRECT_CONFIG int ioasicmatch(struct device *, void *, void *); -#else -int ioasicmatch(struct device *, struct cfdata *, void *); -#endif void ioasicattach(struct device *, struct device *, void *); -int ioasicprint(void *, const char *); struct cfattach ioasic_ca = { sizeof(struct ioasic_softc), ioasicmatch, ioasicattach, @@ -82,24 +107,26 @@ int ioasic_intrnull(void *); #define IOASIC_NCOOKIES 4 -struct ioasic_dev { - char *iad_modname; - tc_offset_t iad_offset; - void *iad_cookie; - u_int32_t iad_intrbits; -} ioasic_devs[] = { - /* XXX lance name */ - { "lance", 0x000c0000, C(IOASIC_DEV_LANCE), IOASIC_INTR_LANCE, }, - { "z8530 ", 0x00100000, C(IOASIC_DEV_SCC0), IOASIC_INTR_SCC_0, }, - { "z8530 ", 0x00180000, C(IOASIC_DEV_SCC1), IOASIC_INTR_SCC_1, }, - { "TOY_RTC ", 0x00200000, C(IOASIC_DEV_BOGUS), 0, }, - { "AMD79c30", 0x00240000, C(IOASIC_DEV_ISDN), IOASIC_INTR_ISDN, }, +struct ioasic_dev ioasic_devs[] = { + { "PMAD-BA ", IOASIC_SLOT_3_START, C(IOASIC_DEV_LANCE), + IOASIC_INTR_LANCE, }, + { "z8530 ", IOASIC_SLOT_4_START, C(IOASIC_DEV_SCC0), + IOASIC_INTR_SCC_0, }, + { "z8530 ", IOASIC_SLOT_6_START, C(IOASIC_DEV_SCC1), + IOASIC_INTR_SCC_1, }, + { "TOY_RTC ", IOASIC_SLOT_8_START, C(IOASIC_DEV_BOGUS), + 0, }, + { "AMD79c30", IOASIC_SLOT_9_START, C(IOASIC_DEV_ISDN), + IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD, }, }; int ioasic_ndevs = sizeof(ioasic_devs) / sizeof(ioasic_devs[0]); struct ioasicintr { int (*iai_func)(void *); void *iai_arg; +#ifdef EVCNT_COUNTERS + struct evcnt iai_evcnt; +#endif } ioasicintrs[IOASIC_NCOOKIES]; tc_addr_t ioasic_base; /* XXX XXX XXX */ @@ -107,17 +134,10 @@ tc_addr_t ioasic_base; /* XXX XXX XXX */ /* There can be only one. */ int ioasicfound; -extern int cputype; - int ioasicmatch(parent, cfdata, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *cfdata; -#else - struct cfdata *cfdata; -#endif - void *aux; + void *cfdata, *aux; { struct tc_attach_args *ta = aux; @@ -142,20 +162,30 @@ ioasicattach(parent, self, aux) { struct ioasic_softc *sc = (struct ioasic_softc *)self; struct tc_attach_args *ta = aux; - struct ioasicdev_attach_args ioasicdev; - u_long i; +#ifdef DEC_3000_300 + u_long ssr; +#endif + u_long i, imsk; + const struct evcnt *pevcnt; + char *cp; ioasicfound = 1; - sc->sc_base = ta->ta_addr; - ioasic_base = sc->sc_base; /* XXX XXX XXX */ - sc->sc_cookie = ta->ta_cookie; + sc->sc_bst = ta->ta_memt; + if (bus_space_map(ta->ta_memt, ta->ta_addr, + 0x400000, 0, &sc->sc_bsh)) { + printf("%s: unable to map device\n", sc->sc_dv.dv_xname); + return; + } + sc->sc_dmat = ta->ta_dmat; + + ioasic_base = sc->sc_base = ta->ta_addr; /* XXX XXX XXX */ #ifdef DEC_3000_300 if (cputype == ST_DEC_3000_300) { - *(volatile u_int *)IOASIC_REG_CSR(sc->sc_base) |= - IOASIC_CSR_FASTMODE; - tc_mb(); + ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); + ssr |= IOASIC_CSR_FASTMODE; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); printf(": slow mode\n"); } else #endif @@ -165,57 +195,34 @@ ioasicattach(parent, self, aux) * Turn off all device interrupt bits. * (This does _not_ include 3000/300 TC option slot bits. */ + imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); for (i = 0; i < ioasic_ndevs; i++) - *(volatile u_int32_t *)IOASIC_REG_IMSK(ioasic_base) &= - ~ioasic_devs[i].iad_intrbits; - tc_mb(); + imsk &= ~ioasic_devs[i].iad_intrbits; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); /* * Set up interrupt handlers. */ + pevcnt = tc_intr_evcnt(parent, ta->ta_cookie); for (i = 0; i < IOASIC_NCOOKIES; i++) { ioasicintrs[i].iai_func = ioasic_intrnull; ioasicintrs[i].iai_arg = (void *)i; + + cp = malloc(12, M_DEVBUF, M_NOWAIT); + if (cp == NULL) + panic("ioasicattach"); + sprintf(cp, "slot %lu", i); +#ifdef EVCNT_COUNTERS + evcnt_attach_dynamic(&ioasicintrs[i].iai_evcnt, + EVCNT_TYPE_INTR, pevcnt, self->dv_xname, cp); +#endif } - tc_intr_establish(parent, sc->sc_cookie, TC_IPL_NONE, ioasic_intr, sc); + tc_intr_establish(parent, ta->ta_cookie, TC_IPL_NONE, ioasic_intr, sc); - /* + /* * Try to configure each device. */ - for (i = 0; i < ioasic_ndevs; i++) { - strncpy(ioasicdev.iada_modname, ioasic_devs[i].iad_modname, - TC_ROM_LLEN); - ioasicdev.iada_modname[TC_ROM_LLEN] = '\0'; - ioasicdev.iada_offset = ioasic_devs[i].iad_offset; - ioasicdev.iada_addr = sc->sc_base + ioasic_devs[i].iad_offset; - ioasicdev.iada_cookie = ioasic_devs[i].iad_cookie; - - /* Tell the autoconfig machinery we've found the hardware. */ - config_found(self, &ioasicdev, ioasicprint); - } -} - -int -ioasicprint(aux, pnp) - void *aux; - const char *pnp; -{ - struct ioasicdev_attach_args *d = aux; - - if (pnp) - printf("%s at %s", d->iada_modname, pnp); - printf(" offset 0x%lx", (long)d->iada_offset); - return (UNCONF); -} - -int -ioasic_submatch(match, d) - struct cfdata *match; - struct ioasicdev_attach_args *d; -{ - - return ((match->ioasiccf_offset == d->iada_offset) || - (match->ioasiccf_offset == IOASIC_OFFSET_UNKNOWN)); + ioasic_attach_devs(sc, ioasic_devs, ioasic_ndevs); } void @@ -225,7 +232,8 @@ ioasic_intr_establish(ioa, cookie, level, func, arg) tc_intrlevel_t level; int (*func)(void *); { - u_long dev, i; + struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0]; + u_long dev, i, imsk; dev = (u_long)cookie; #ifdef DIAGNOSTIC @@ -233,7 +241,7 @@ ioasic_intr_establish(ioa, cookie, level, func, arg) #endif if (ioasicintrs[dev].iai_func != ioasic_intrnull) - panic("ioasic_intr_establish: cookie %d twice", dev); + panic("ioasic_intr_establish: cookie %lu twice", dev); ioasicintrs[dev].iai_func = func; ioasicintrs[dev].iai_arg = arg; @@ -244,9 +252,10 @@ ioasic_intr_establish(ioa, cookie, level, func, arg) break; if (i == ioasic_ndevs) panic("ioasic_intr_establish: invalid cookie."); - *(volatile u_int32_t *)IOASIC_REG_IMSK(ioasic_base) |= - ioasic_devs[i].iad_intrbits; - tc_mb(); + + imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); + imsk |= ioasic_devs[i].iad_intrbits; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); } void @@ -254,7 +263,8 @@ ioasic_intr_disestablish(ioa, cookie) struct device *ioa; void *cookie; { - u_long dev, i; + struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0]; + u_long dev, i, imsk; dev = (u_long)cookie; #ifdef DIAGNOSTIC @@ -262,7 +272,7 @@ ioasic_intr_disestablish(ioa, cookie) #endif if (ioasicintrs[dev].iai_func == ioasic_intrnull) - panic("ioasic_intr_disestablish: cookie %d missing intr", dev); + panic("ioasic_intr_disestablish: cookie %lu missing intr", dev); /* Enable interrupts for the device. */ for (i = 0; i < ioasic_ndevs; i++) @@ -270,9 +280,10 @@ ioasic_intr_disestablish(ioa, cookie) break; if (i == ioasic_ndevs) panic("ioasic_intr_disestablish: invalid cookie."); - *(volatile u_int32_t *)IOASIC_REG_IMSK(ioasic_base) &= - ~ioasic_devs[i].iad_intrbits; - tc_mb(); + + imsk = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK); + imsk &= ~ioasic_devs[i].iad_intrbits; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_IMSK, imsk); ioasicintrs[dev].iai_func = ioasic_intrnull; ioasicintrs[dev].iai_arg = (void *)dev; @@ -288,8 +299,7 @@ ioasic_intrnull(val) } /* - * asic_intr -- - * ASIC interrupt handler. + * ASIC interrupt handler. */ int ioasic_intr(val) @@ -298,66 +308,44 @@ ioasic_intr(val) register struct ioasic_softc *sc = val; register int ifound; int gifound; - u_int32_t sir; - volatile u_int32_t *sirp; - - sirp = (volatile u_int32_t *)IOASIC_REG_INTR(sc->sc_base); + u_int32_t sir, osir; gifound = 0; do { ifound = 0; tc_syncbus(); - sir = *sirp; + osir = sir = + bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR); #ifdef EVCNT_COUNTERS - /* No interrupt counting via evcnt counters */ - XXX BREAK HERE XXX -#else /* !EVCNT_COUNTERS */ +#define INCRINTRCNT(slot) ioasicintrs[slot].iai_evcnt.ev_count++ +#else #define INCRINTRCNT(slot) intrcnt[INTRCNT_IOASIC + slot]++ -#endif /* EVCNT_COUNTERS */ +#endif /* XXX DUPLICATION OF INTERRUPT BIT INFORMATION... */ -#define CHECKINTR(slot, bits) \ - if (sir & bits) { \ +#define CHECKINTR(slot, bits, clear) \ + if (sir & (bits)) { \ ifound = 1; \ INCRINTRCNT(slot); \ (*ioasicintrs[slot].iai_func) \ (ioasicintrs[slot].iai_arg); \ + if (clear) \ + sir &= ~(bits); \ } - CHECKINTR(IOASIC_DEV_SCC0, IOASIC_INTR_SCC_0); - CHECKINTR(IOASIC_DEV_SCC1, IOASIC_INTR_SCC_1); - CHECKINTR(IOASIC_DEV_LANCE, IOASIC_INTR_LANCE); - CHECKINTR(IOASIC_DEV_ISDN, IOASIC_INTR_ISDN); + CHECKINTR(IOASIC_DEV_SCC0, IOASIC_INTR_SCC_0, 0); + CHECKINTR(IOASIC_DEV_SCC1, IOASIC_INTR_SCC_1, 0); + CHECKINTR(IOASIC_DEV_LANCE, IOASIC_INTR_LANCE, 0); + CHECKINTR(IOASIC_DEV_ISDN, IOASIC_INTR_ISDN_TXLOAD | + IOASIC_INTR_ISDN_RXLOAD | IOASIC_INTR_ISDN_OVRUN, 1); + + if (sir != osir) + bus_space_write_4(sc->sc_bst, sc->sc_bsh, + IOASIC_INTR, sir); gifound |= ifound; } while (ifound); return (gifound); } - -/* XXX */ -char * -ioasic_lance_ether_address() -{ - - return (u_char *)IOASIC_SYS_ETHER_ADDRESS(ioasic_base); -} - -void -ioasic_lance_dma_setup(v) - void *v; -{ - volatile u_int32_t *ldp; - tc_addr_t tca; - - tca = (tc_addr_t)v; - - ldp = (volatile u_int *)IOASIC_REG_LANCE_DMAPTR(ioasic_base); - *ldp = ((tca << 3) & ~(tc_addr_t)0x1f) | ((tca >> 29) & 0x1f); - tc_wmb(); - - *(volatile u_int32_t *)IOASIC_REG_CSR(ioasic_base) |= - IOASIC_CSR_DMAEN_LANCE; - tc_mb(); -} diff --git a/sys/arch/alpha/tc/ioasicreg.h b/sys/arch/alpha/tc/ioasicreg.h deleted file mode 100644 index 2c09ef47776..00000000000 --- a/sys/arch/alpha/tc/ioasicreg.h +++ /dev/null @@ -1,227 +0,0 @@ -/* $OpenBSD: ioasicreg.h,v 1.3 1996/10/30 22:41:09 niklas Exp $ */ -/* $NetBSD: ioasicreg.h,v 1.1 1995/12/20 00:43:22 cgd Exp $ */ - -/* - * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and - * its documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * The Mach Operating System project at Carnegie-Mellon University, - * Ralph Campbell and Rick Macklem. - * - * 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. - * - * @(#)asic.h 8.1 (Berkeley) 6/10/93 - */ - -/* - * Slot definitions - */ - -#define IOASIC_SLOT_0_START 0x000000 -#define IOASIC_SLOT_1_START 0x040000 -#define IOASIC_SLOT_2_START 0x080000 -#define IOASIC_SLOT_3_START 0x0c0000 -#define IOASIC_SLOT_4_START 0x100000 -#define IOASIC_SLOT_5_START 0x140000 -#define IOASIC_SLOT_6_START 0x180000 -#define IOASIC_SLOT_7_START 0x1c0000 -#define IOASIC_SLOT_8_START 0x200000 -#define IOASIC_SLOT_9_START 0x240000 -#define IOASIC_SLOT_10_START 0x280000 -#define IOASIC_SLOT_11_START 0x2c0000 -#define IOASIC_SLOT_12_START 0x300000 -#define IOASIC_SLOT_13_START 0x340000 -#define IOASIC_SLOT_14_START 0x380000 -#define IOASIC_SLOT_15_START 0x3c0000 -#define IOASIC_SLOTS_END 0x3fffff - -/* - * Register offsets (slot 1) - */ - -#define IOASIC_SCSI_DMAPTR IOASIC_SLOT_1_START+0x000 -#define IOASIC_SCSI_NEXTPTR IOASIC_SLOT_1_START+0x010 -#define IOASIC_LANCE_DMAPTR IOASIC_SLOT_1_START+0x020 -#define IOASIC_SCC_T1_DMAPTR IOASIC_SLOT_1_START+0x030 -#define IOASIC_SCC_R1_DMAPTR IOASIC_SLOT_1_START+0x040 -#define IOASIC_SCC_T2_DMAPTR IOASIC_SLOT_1_START+0x050 -#define IOASIC_SCC_R2_DMAPTR IOASIC_SLOT_1_START+0x060 -#define IOASIC_FLOPPY_DMAPTR IOASIC_SLOT_1_START+0x070 -#define IOASIC_ISDN_X_DMAPTR IOASIC_SLOT_1_START+0x080 -#define IOASIC_ISDN_X_NEXTPTR IOASIC_SLOT_1_START+0x090 -#define IOASIC_ISDN_R_DMAPTR IOASIC_SLOT_1_START+0x0a0 -#define IOASIC_ISDN_R_NEXTPTR IOASIC_SLOT_1_START+0x0b0 -#define IOASIC_BUFF0 IOASIC_SLOT_1_START+0x0c0 -#define IOASIC_BUFF1 IOASIC_SLOT_1_START+0x0d0 -#define IOASIC_BUFF2 IOASIC_SLOT_1_START+0x0e0 -#define IOASIC_BUFF3 IOASIC_SLOT_1_START+0x0f0 -#define IOASIC_CSR IOASIC_SLOT_1_START+0x100 -#define IOASIC_INTR IOASIC_SLOT_1_START+0x110 -#define IOASIC_IMSK IOASIC_SLOT_1_START+0x120 -#define IOASIC_CURADDR IOASIC_SLOT_1_START+0x130 -#define IOASIC_ISDN_X_DATA IOASIC_SLOT_1_START+0x140 -#define IOASIC_ISDN_R_DATA IOASIC_SLOT_1_START+0x150 -#define IOASIC_LANCE_DECODE IOASIC_SLOT_1_START+0x160 -#define IOASIC_SCSI_DECODE IOASIC_SLOT_1_START+0x170 -#define IOASIC_SCC0_DECODE IOASIC_SLOT_1_START+0x180 -#define IOASIC_SCC1_DECODE IOASIC_SLOT_1_START+0x190 -#define IOASIC_FLOPPY_DECODE IOASIC_SLOT_1_START+0x1a0 -#define IOASIC_SCSI_SCR IOASIC_SLOT_1_START+0x1b0 -#define IOASIC_SCSI_SDR0 IOASIC_SLOT_1_START+0x1c0 -#define IOASIC_SCSI_SDR1 IOASIC_SLOT_1_START+0x1d0 - -/* System Status and control Register (SSR). */ -#define IOASIC_CSR_DMAEN_T1 0x80000000 /* rw */ -#define IOASIC_CSR_DMAEN_R1 0x40000000 /* rw */ -#define IOASIC_CSR_DMAEN_T2 0x20000000 /* rw */ -#define IOASIC_CSR_DMAEN_R2 0x10000000 /* rw */ -#define IOASIC_CSR_FASTMODE 0x08000000 /* rw */ -#define IOASIC_CSR_xxx 0x07800000 /* unused/reserved */ -#define IOASIC_CSR_FLOPPY_DIR 0x00400000 /* rw */ -#define IOASIC_CSR_DMAEN_FLOPPY 0x00200000 /* rw */ -#define IOASIC_CSR_DMAEN_ISDN_T 0x00100000 /* rw */ -#define IOASIC_CSR_DMAEN_ISDN_R 0x00080000 /* rw */ -#define IOASIC_CSR_SCSI_DIR 0x00040000 /* rw */ -#define IOASIC_CSR_DMAEN_SCSI 0x00020000 /* rw */ -#define IOASIC_CSR_DMAEN_LANCE 0x00010000 /* rw */ -/* low 16 bits are rw gp outputs */ - -/* System Interrupt Register (and Interrupt Mask Register). */ -#define IOASIC_INTR_T1_PAGE_END 0x80000000 /* rz */ -#define IOASIC_INTR_T1_READ_E 0x40000000 /* rz */ -#define IOASIC_INTR_R1_HALF_PAGE 0x20000000 /* rz */ -#define IOASIC_INTR_R1_DMA_OVRUN 0x10000000 /* rz */ -#define IOASIC_INTR_T2_PAGE_END 0x08000000 /* rz */ -#define IOASIC_INTR_T2_READ_E 0x04000000 /* rz */ -#define IOASIC_INTR_R2_HALF_PAGE 0x02000000 /* rz */ -#define IOASIC_INTR_R2_DMA_OVRUN 0x01000000 /* rz */ -#define IOASIC_INTR_FLOPPY_DMA_E 0x00800000 /* rz */ -#define IOASIC_INTR_ISDN_PTR_LOAD 0x00400000 /* rz */ -#define IOASIC_INTR_ISDN_OVRUN 0x00200000 /* rz */ -#define IOASIC_INTR_ISDN_READ_E 0x00100000 /* rz */ -#define IOASIC_INTR_SCSI_PTR_LOAD 0x00080000 /* rz */ -#define IOASIC_INTR_SCSI_OVRUN 0x00040000 /* rz */ -#define IOASIC_INTR_SCSI_READ_E 0x00020000 /* rz */ -#define IOASIC_INTR_LANCE_READ_E 0x00010000 /* rz */ -#define IOASIC_INTR_ISDN 0x00002000 /* ro */ -#define IOASIC_INTR_SEC_CON 0x00000200 /* ro */ -#define IOASIC_INTR_LANCE 0x00000100 /* ro */ -#define IOASIC_INTR_SCC_1 0x00000080 /* ro */ -#define IOASIC_INTR_SCC_0 0x00000040 /* ro */ -#define IOASIC_INTR_ALT_CON 0x00000008 /* ro - 3000/500 */ -#define IOASIC_INTR_300_OPT1 IOASIC_INTR_ALT_CON /* ro - 3000/300 */ -#define IOASIC_INTR_300_OPT0 0x00000004 /* ro - 3000/300 */ - -/* DMA pointer registers (SCSI, Comm, ...) */ - -#define IOASIC_DMAPTR_MASK 0xffffffe0 -#define IOASIC_DMAPTR_SHIFT 5 -#define IOASIC_DMAPTR_SET(reg,val) \ - (reg) = (((val)<<IOASIC_DMAPTR_SHIFT)&IOASIC_DMAPTR_MASK) -#define IOASIC_DMAPTR_GET(reg,val) \ - (val) = (((reg)&IOASIC_DMAPTR_MASK)>>IOASIC_DMAPTR_SHIFT) -#define IOASIC_DMA_ADDR(p) (((unsigned)p) << (5-2)) - -/* For the LANCE DMA pointer register initialization the above suffices */ - -/* More SCSI DMA registers */ - -#define IOASIC_SCR_STATUS 0x00000004 -#define IOASIC_SCR_WORD 0x00000003 - -/* Various Decode registers */ - -#define IOASIC_DECODE_HW_ADDRESS 0x000003f0 -#define IOASIC_DECODE_CHIP_SELECT 0x0000000f - -/* - * Asic register addresses at offset from base. - */ -#define IOASIC_REG_SCSI_DMAPTR(base) ((base) + IOASIC_SCSI_DMAPTR) -#define IOASIC_REG_SCSI_DMANPTR(base) ((base) + IOASIC_SCSI_NEXTPTR) -#define IOASIC_REG_LANCE_DMAPTR(base) ((base) + IOASIC_LANCE_DMAPTR) -#define IOASIC_REG_SCC_T1_DMAPTR(base) ((base) + IOASIC_SCC_T1_DMAPTR) -#define IOASIC_REG_SCC_R1_DMAPTR(base) ((base) + IOASIC_SCC_R1_DMAPTR) -#define IOASIC_REG_SCC_T2_DMAPTR(base) ((base) + IOASIC_SCC_T2_DMAPTR) -#define IOASIC_REG_SCC_R2_DMAPTR(base) ((base) + IOASIC_SCC_R2_DMAPTR) -#define IOASIC_REG_FLOPPY_DMAPTR(base) ((base) + IOASIC_FLOPPY_DMAPTR) -#define IOASIC_REG_ISDN_X_DMAPTR(base) ((base) + IOASIC_ISDN_X_DMAPTR) -#define IOASIC_REG_ISDN_X_NEXTPTR(base) ((base) + IOASIC_ISDN_X_NEXTPTR) -#define IOASIC_REG_ISDN_R_DMAPTR(base) ((base) + IOASIC_ISDN_R_DMAPTR) -#define IOASIC_REG_ISDN_R_NEXTPTR(base) ((base) + IOASIC_ISDN_R_NEXTPTR) -#define IOASIC_REG_BUFF0(base) ((base) + IOASIC_BUFF0) -#define IOASIC_REG_BUFF1(base) ((base) + IOASIC_BUFF1) -#define IOASIC_REG_BUFF2(base) ((base) + IOASIC_BUFF2) -#define IOASIC_REG_BUFF3(base) ((base) + IOASIC_BUFF3) -#define IOASIC_REG_CSR(base) ((base) + IOASIC_CSR) -#define IOASIC_REG_INTR(base) ((base) + IOASIC_INTR) -#define IOASIC_REG_IMSK(base) ((base) + IOASIC_IMSK) -#define IOASIC_REG_CURADDR(base) ((base) + IOASIC_CURADDR) -#define IOASIC_REG_ISDN_X_DATA(base) ((base) + IOASIC_ISDN_X_DATA) -#define IOASIC_REG_ISDN_R_DATA(base) ((base) + IOASIC_ISDN_R_DATA) -#define IOASIC_REG_LANCE_DECODE(base) ((base) + IOASIC_LANCE_DECODE) -#define IOASIC_REG_SCSI_DECODE(base) ((base) + IOASIC_SCSI_DECODE) -#define IOASIC_REG_SCC0_DECODE(base) ((base) + IOASIC_SCC0_DECODE) -#define IOASIC_REG_SCC1_DECODE(base) ((base) + IOASIC_SCC1_DECODE) -#define IOASIC_REG_FLOPPY_DECODE(base) ((base) + IOASIC_FLOPPY_DECODE) -#define IOASIC_REG_SCSI_SCR(base) ((base) + IOASIC_SCSI_SCR) -#define IOASIC_REG_SCSI_SDR0(base) ((base) + IOASIC_SCSI_SDR0) -#define IOASIC_REG_SCSI_SDR1(base) ((base) + IOASIC_SCSI_SDR1) - -/* - * And slot assignments. - */ -#define IOASIC_SYS_ETHER_ADDRESS(base) ((base) + IOASIC_SLOT_2_START) -#define IOASIC_SYS_LANCE(base) ((base) + IOASIC_SLOT_3_START) diff --git a/sys/arch/alpha/tc/mcclock_ioasic.c b/sys/arch/alpha/tc/mcclock_ioasic.c index 2709092949d..da7e8e7a4f6 100644 --- a/sys/arch/alpha/tc/mcclock_ioasic.c +++ b/sys/arch/alpha/tc/mcclock_ioasic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mcclock_ioasic.c,v 1.5 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: mcclock_ioasic.c,v 1.3 1996/12/05 01:39:42 cgd Exp $ */ +/* $OpenBSD: mcclock_ioasic.c,v 1.6 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: mcclock_ioasic.c,v 1.9 2000/07/04 02:37:51 nisimura Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -33,10 +33,9 @@ #include <sys/systm.h> #include <sys/device.h> -#include <alpha/alpha/clockvar.h> -#include <alpha/alpha/mcclockvar.h> +#include <dev/dec/clockvar.h> +#include <dev/dec/mcclockvar.h> #include <dev/ic/mc146818reg.h> -#include <dev/tc/tcreg.h> #include <dev/tc/tcvar.h> #include <dev/tc/ioasicvar.h> /* XXX */ @@ -51,11 +50,7 @@ struct mcclock_ioasic_softc { struct mcclock_ioasic_clockdatum *sc_dp; }; -#ifdef __BROKEN_INDIRECT_CONFIG int mcclock_ioasic_match(struct device *, void *, void *); -#else -int mcclock_ioasic_match(struct device *, struct cfdata *, void *); -#endif void mcclock_ioasic_attach(struct device *, struct device *, void *); struct cfattach mcclock_ioasic_ca = { @@ -73,12 +68,7 @@ const struct mcclock_busfns mcclock_ioasic_busfns = { int mcclock_ioasic_match(parent, match, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *match; -#else - struct cfdata *match; -#endif - void *aux; + void *match, *aux; { struct ioasicdev_attach_args *d = aux; diff --git a/sys/arch/alpha/tc/scc.c b/sys/arch/alpha/tc/scc.c index bfba120fca3..b1734b53296 100644 --- a/sys/arch/alpha/tc/scc.c +++ b/sys/arch/alpha/tc/scc.c @@ -1,5 +1,5 @@ -/* $OpenBSD: scc.c,v 1.14 2002/03/15 01:20:04 millert Exp $ */ -/* $NetBSD: scc.c,v 1.28 1996/12/05 01:39:43 cgd Exp $ */ +/* $OpenBSD: scc.c,v 1.15 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: scc.c,v 1.58 2002/03/17 19:40:27 atatat Exp $ */ /* * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University @@ -11,7 +11,7 @@ * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * @@ -64,9 +64,6 @@ * @(#)scc.c 8.2 (Berkeley) 11/30/93 */ -#include "scc.h" - -#if NSCC > 0 /* * Intel 82530 dual usart chip driver. Supports the serial port(s) on the * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard @@ -81,7 +78,6 @@ #include <sys/tty.h> #include <sys/proc.h> #include <sys/buf.h> -#include <sys/conf.h> #include <sys/file.h> #include <sys/uio.h> #include <sys/kernel.h> @@ -94,42 +90,27 @@ #include <alpha/tc/sccreg.h> #include <alpha/tc/sccvar.h> -#include <machine/autoconf.h> /* For the badaddr() proto */ #include <machine/rpb.h> +#include <machine/conf.h> #include <dev/tc/tcvar.h> -#include <alpha/tc/ioasicreg.h> +#include <dev/tc/ioasicreg.h> #include <dev/tc/ioasicvar.h> #undef SCCDEV #define SCCDEV 15 /* XXX */ -/* - * rcons glass-tty console (as used on pmax) needs lk-201 ASCII input - * support from the tty drivers. This is ugly and broken and won't - * compile on Alphas. - */ +#define raster_console() 1 /* Treat test for cn_screen as true */ +#define CONSOLE_ON_UNIT(unit) 0 /* No raster console on Alphas */ #define NSCCLINE (NSCC*2) #define SCCUNIT(dev) (minor(dev) >> 1) #define SCCLINE(dev) (minor(dev) & 0x1) -/* QVSS-compatible in-kernel X input event parser, pointer tracker */ -void (*sccDivertXInput)(int cc); /* X windows keyboard input routine */ -void (*sccMouseEvent)(int); /* X windows mouse motion event routine */ -void (*sccMouseButtons)(int); /* X windows mouse buttons event routine */ #ifdef DEBUG int debugChar; #endif -struct pdma { - void *p_addr; - char *p_mem; - char *p_end; - int p_arg; - void (*p_fcn)(struct tty *tp); -}; - struct scc_softc { struct device sc_dv; struct pdma scc_pdma[2]; @@ -192,11 +173,7 @@ struct speedtab sccspeedtab[] = { #endif /* Definition of the driver for autoconfig. */ -#ifdef __BROKEN_INDIRECT_CONFIG int sccmatch(struct device *, void *, void *); -#else -int sccmatch(struct device *, struct cfdata *, void *); -#endif void sccattach(struct device *, struct device *, void *); struct cfattach scc_ca = { @@ -209,104 +186,46 @@ struct cfdriver scc_cd = { cdev_decl(scc); +int sccGetc(dev_t); +void sccPutc(dev_t, int); +void sccPollc(dev_t, int); +int sccparam(struct tty *, struct termios *); +void sccstart(struct tty *); + +int sccmctl(struct scc_softc *, int, int, int); int cold_sccparam(struct tty *, struct termios *, - struct scc_softc *sc); -int sccGetc(dev_t); -void sccPollc(dev_t, int); -void sccPutc(dev_t, int); -int sccintr(void *); -int sccmctl(dev_t, int, int); -int sccparam(struct tty *, struct termios *); -void sccreset(struct scc_softc *); -void sccstart(struct tty *); -void scc_alphaintr(int); -void scc_modem_intr(dev_t); + struct scc_softc *sc, int line); + #ifdef SCC_DEBUG -void scc_rr(char *, scc_regmap_t *); +void rr(char *, scc_regmap_t *); #endif +void scc_modem_intr(dev_t); +void sccreset(struct scc_softc *); + +int sccintr(void *); +void scc_alphaintr(int); /* * console variables, for using serial console while still cold and * autoconfig has not attached the scc device. */ scc_regmap_t *scc_cons_addr = 0; -static struct scc_softc coldcons_softc; -static struct consdev scccons = { +struct consdev scccons = { NULL, NULL, sccGetc, sccPutc, sccPollc, NULL, NODEV, 0 }; -void scc_consinit(dev_t dev, scc_regmap_t *sccaddr); -void scc_oconsinit(struct scc_softc *, dev_t); - - -/* - * Set up a given unit as a serial console device. - * We need console output when cold, and before any device is configured. - * Should be callable when cold, to reset the chip and set parameters - * for a remote (serial) console or kgdb line. - * XXX - * As most DECstations only bring out one rs-232 lead from an SCC - * to the bulkhead, and use the other for mouse and keyboard, we - * only allow one unit per SCC to be console. - */ -void -scc_consinit(dev, sccaddr) - dev_t dev; - scc_regmap_t *sccaddr; -{ - struct scc_softc *sc; - struct termios cterm; - struct tty ctty; - int s; - - /* Save address in case we're cold. */ - if (cold && scc_cons_addr == 0) { - scc_cons_addr = sccaddr; - sc = &coldcons_softc; - coldcons_softc.scc_pdma[0].p_addr = sccaddr; - coldcons_softc.scc_pdma[1].p_addr = sccaddr; - } else { - /* being called from sccattach() to reset console */ - sc = scc_cd.cd_devs[SCCUNIT(dev)]; - } - - /* Reset chip. */ - sccreset(sc); - /* XXX make sure sccreset() called only once for this chip? */ - - /* set console-line parameters */ - s = spltty(); - ctty.t_dev = dev; - scccons.cn_dev = dev; - cterm.c_cflag = CS8; - cterm.c_ospeed = cterm.c_ispeed = 9600; - (void) cold_sccparam(&ctty, &cterm, sc); - *cn_tab = scccons; - DELAY(1000); - splx(s); -} /* * Test to see if device is present. * Return true if found. */ int -#ifdef __BROKEN_INDIRECT_CONFIG -sccmatch(parent, cfdata, aux) -#else -sccmatch(parent, cf, aux) -#endif +sccmatch(parent, vcf, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *cfdata; -#else - struct cfdata *cf; -#endif - void *aux; + void *vcf, *aux; { -#ifdef __BROKEN_INDIRECT_CONFIG - struct cfdata *cf = cfdata; -#endif + extern struct cfdriver ioasic_cd; /* XXX */ struct ioasicdev_attach_args *d = aux; + struct cfdata *cf = vcf; void *sccaddr; if (parent->dv_cfdata->cf_driver != &ioasic_cd) { @@ -321,8 +240,12 @@ sccmatch(parent, cf, aux) (strncmp(d->iada_modname, "scc", TC_ROM_LLEN)!= 0)) return (0); - /* XXX MATCH CFLOC */ - if (cf->cf_unit >= NSCC) + /* + * Check user-specified offset against the ioasic offset. + * Allow it to be wildcarded. + */ + if (cf->cf_loc[0] != -1 && + cf->cf_loc[0] != d->iada_offset) return (0); /* Get the address, and check it for validity. */ @@ -345,18 +268,18 @@ scc_alphaintr(onoff) int onoff; { if (onoff) { - *(volatile u_int *)IOASIC_REG_IMSK(ioasic_base) |= + *(volatile u_int *)(ioasic_base + IOASIC_IMSK) |= IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0; #if !defined(DEC_3000_300) && defined(SCC_DMA) - *(volatile u_int *)IOASIC_REG_CSR(ioasic_base) |= + *(volatile u_int *)(ioasic_base + IOASIC_CSR) |= IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 | IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2; #endif } else { - *(volatile u_int *)IOASIC_REG_IMSK(ioasic_base) &= + *(volatile u_int *)(ioasic_base + IOASIC_IMSK) &= ~(IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0); #if !defined(DEC_3000_300) && defined(SCC_DMA) - *(volatile u_int *)IOASIC_REG_CSR(ioasic_base) &= + *(volatile u_int *)(ioasic_base + IOASIC_CSR) &= ~(IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 | IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2); #endif @@ -379,7 +302,9 @@ sccattach(parent, self, aux) struct termios cterm; struct tty ctty; int s; - extern int cputype; + int unit; + + unit = sc->sc_dv.dv_unit; /* Get the address, and check it for validity. */ sccaddr = (void *)d->iada_addr; @@ -395,15 +320,9 @@ sccattach(parent, self, aux) * For a remote console, wait a while for previous output to * complete. */ -#ifdef TK_NOTYET - if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 && - SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) - DELAY(10000); -#else if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) || (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) DELAY(10000); -#endif pdp = &sc->scc_pdma[0]; /* init pseudo DMA structures */ @@ -413,12 +332,12 @@ sccattach(parent, self, aux) if (cntr == 0) tty_attach(tp); pdp->p_arg = (long)tp; - pdp->p_fcn = (void (*)(struct tty*))0; + pdp->p_fcn = (void (*)__P((struct tty*)))0; tp->t_dev = (dev_t)((sc->sc_dv.dv_unit << 1) | cntr); pdp++; } /* What's the warning here? Defaulting to softCAR on line 2? */ - sc->scc_softCAR = 0x2; /* XXX */ + sc->scc_softCAR = sc->sc_dv.dv_cfdata->cf_flags | 0x2; /* XXX */ /* reset chip, initialize register-copies in softc */ sccreset(sc); @@ -426,50 +345,14 @@ sccattach(parent, self, aux) /* * Special handling for consoles. */ - if (0 /* cn_tab.cn_screen */) { - if (1 /* cn_tab.cn_kbdgetc == sccGetc */) { - if (sc->sc_dv.dv_unit == 1) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); - cterm.c_cflag = CS8; - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); - DELAY(10000); -#ifdef notyet - /* - * For some reason doing this hangs the 3min - * during booting. Fortunately the keyboard - * works ok without it. - */ - KBDReset(ctty.t_dev, sccPutc); -#endif - DELAY(10000); - splx(s); - } else if (sc->sc_dv.dv_unit == 0) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); - cterm.c_cflag = CS8 | PARENB | PARODD; - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); -#ifdef TK_NOTYET - DELAY(10000); - MouseInit(ctty.t_dev, sccPutc, sccGetc); - DELAY(10000); -#endif - splx(s); - } - } - } else if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) { + if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) { s = spltty(); - ctty.t_dev = makedev(SCCDEV, - sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT); cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8; cterm.c_ospeed = cterm.c_ispeed = 9600; - (void) sccparam(&ctty, &cterm); + (void) cold_sccparam(&ctty, &cterm, sc, + SCCLINE((sc->sc_dv.dv_unit == 0) ? + SCCCOMM2_PORT : SCCCOMM3_PORT)); DELAY(1000); -#ifdef TK_NOTYET - cn_tab.cn_disabled = 0; -#endif splx(s); } @@ -479,10 +362,12 @@ sccattach(parent, self, aux) */ if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) || (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) { + if (alpha_donot_kludge_scc) + printf("\nSWITCHING TO SERIAL CONSOLE!\n"); cn_tab = &scccons; cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2); - printf(": console\n"); + printf("%s console\n", alpha_donot_kludge_scc ? "\n***" : ":"); /* wire carrier for console. */ sc->scc_softCAR |= SCCLINE(cn_tab->cn_dev); @@ -566,6 +451,7 @@ sccopen(dev, flag, mode, p) register struct tty *tp; register int unit, line; int s, error = 0; + int firstopen = 0; unit = SCCUNIT(dev); if (unit >= scc_cd.cd_ndevs) @@ -586,8 +472,8 @@ sccopen(dev, flag, mode, p) tp->t_param = sccparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_WOPEN; ttychars(tp); + firstopen = 1; #ifndef PORTSELECTOR if (tp->t_ispeed == 0) { #endif @@ -605,19 +491,23 @@ sccopen(dev, flag, mode, p) ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) return (EBUSY); - (void) sccmctl(dev, DML_DTR, DMSET); + (void) sccmctl(sc, SCCLINE(dev), DML_DTR, DMSET); s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) { tp->t_state |= TS_WOPEN; - if ((error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, - ttopen, 0)) != 0) + error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, + ttopen, 0); + tp->t_state &= ~TS_WOPEN; + if (error != 0) break; } splx(s); if (error) return (error); - return ((*linesw[tp->t_line].l_open)(dev, tp)); + error = (*linesw[tp->t_line].l_open)(dev, tp); + + return (error); } /*ARGSUSED*/ @@ -640,7 +530,7 @@ sccclose(dev, flag, mode, p) (*linesw[tp->t_line].l_close)(tp, flag); if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || !(tp->t_state & TS_ISOPEN)) - (void) sccmctl(dev, 0, DMSET); + (void) sccmctl(sc, line, 0, DMSET); return (ttyclose(tp)); } @@ -722,27 +612,27 @@ sccioctl(dev, cmd, data, flag, p) break; case TIOCSDTR: - (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); + (void) sccmctl(sc, line, DML_DTR|DML_RTS, DMBIS); break; case TIOCCDTR: - (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); + (void) sccmctl(sc, line, DML_DTR|DML_RTS, DMBIC); break; case TIOCMSET: - (void) sccmctl(dev, *(int *)data, DMSET); + (void) sccmctl(sc, line, *(int *)data, DMSET); break; case TIOCMBIS: - (void) sccmctl(dev, *(int *)data, DMBIS); + (void) sccmctl(sc, line, *(int *)data, DMBIS); break; case TIOCMBIC: - (void) sccmctl(dev, *(int *)data, DMBIC); + (void) sccmctl(sc, line, *(int *)data, DMBIC); break; case TIOCMGET: - *(int *)data = sccmctl(dev, 0, DMGET); + *(int *)data = sccmctl(sc, line, 0, DMGET); break; default: @@ -765,7 +655,7 @@ sccparam(tp, t) /* Extract the softc and call cold_sccparam to do all the work. */ sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)]; - return cold_sccparam(tp, t, sc); + return cold_sccparam(tp, t, sc, SCCLINE(tp->t_dev)); } @@ -773,13 +663,13 @@ sccparam(tp, t) * Do what sccparam() (t_param entry point) does, but callable when cold. */ int -cold_sccparam(tp, t, sc) +cold_sccparam(tp, t, sc, line) register struct tty *tp; register struct termios *t; register struct scc_softc *sc; + register int line; { register scc_regmap_t *regs; - register int line; register u_char value, wvalue; register int cflag = t->c_cflag; int ospeed; @@ -798,27 +688,15 @@ cold_sccparam(tp, t, sc) /* * Handle console specially. */ -#ifdef HAVE_RCONS - if (cn_tab->cn_getc == LKgetc) { - if (minor(tp->t_dev) == SCCKBD_PORT) { - cflag = CS8; - ospeed = ttspeedtab(4800, sccspeedtab); - } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { - cflag = CS8 | PARENB | PARODD; - ospeed = ttspeedtab(4800, sccspeedtab); - } - } else if (tp->t_dev == cn_tab->cn_dev) -#endif /*HAVE_RCONS*/ { cflag = CS8; ospeed = ttspeedtab(9600, sccspeedtab); } if (ospeed == 0) { - (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ + (void) sccmctl(sc, line, 0, DMSET); /* hang up line */ return (0); } - line = SCCLINE(tp->t_dev); regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; /* @@ -903,12 +781,10 @@ cold_sccparam(tp, t, sc) value = sc->scc_wreg[line].wr14; SCC_WRITE_REG(regs, line, SCC_WR14, value); -#ifdef alpha - if (SCCUNIT(tp->t_dev) == 1) { + if (sc->sc_dv.dv_unit == 1) { /* On unit one, on the flamingo, modem control is floating! */ value = ZSWR15_BREAK_IE; } else -#endif { value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE; } @@ -927,9 +803,7 @@ cold_sccparam(tp, t, sc) SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); tc_mb(); -#ifdef alpha scc_alphaintr(1); /* XXX XXX XXX */ -#endif /*alpha*/ return (0); } @@ -981,10 +855,7 @@ sccintr(xxxsc) (caddr_t) tp->t_outq.c_cf); dp->p_end = dp->p_mem = tp->t_outq.c_cf; } - if (tp->t_line) - (*linesw[tp->t_line].l_start)(tp); - else - sccstart(tp); + (*linesw[tp->t_line].l_start)(tp); if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { SCC_READ_REG(regs, chan, SCC_RR15, cc); cc &= ~ZSWR15_TXUEOM_IE; @@ -1015,39 +886,6 @@ sccintr(xxxsc) } } - /* - * Keyboard needs special treatment. - */ - if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) /* && cn_tab.cn_screen */) { -#ifdef KADB - if (cc == LK_DO) { - spl0(); - kdbpanic(); - return 0; /* XXX */ - } -#endif -#ifdef DEBUG - debugChar = cc; -#endif - if (sccDivertXInput) { - (*sccDivertXInput)(cc); - continue; - } -#ifdef TK_NOTYET - if ((cc = kbdMapChar(cc)) < 0) - continue; -#endif - /* - * Now for mousey - */ - } else if (tp == scctty(makedev(SCCDEV, SCCMOUSE_PORT)) && - sccMouseButtons) { -#ifdef HAVE_RCONS - /*XXX*/ - mouseInput(cc); -#endif - continue; - } if (!(tp->t_state & TS_ISOPEN)) { wakeup((caddr_t)&tp->t_rawq); #ifdef PORTSELECTOR @@ -1100,7 +938,7 @@ sccstart(tp) if (tp->t_outq.c_cc == 0) goto out; /* handle console specially */ - if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) /* && cn_tab.cn_screen */) { + if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) && raster_console()) { while (tp->t_outq.c_cc > 0) { cc = getc(&tp->t_outq) & 0x7f; cnputc(cc); @@ -1174,18 +1012,15 @@ sccstop(tp, flag) } int -sccmctl(dev, bits, how) - dev_t dev; - int bits, how; +sccmctl(sc, line, bits, how) + struct scc_softc *sc; + int line, bits, how; { - register struct scc_softc *sc; register scc_regmap_t *regs; - register int line, mbits; + register int mbits; register u_char value; int s; - sc = scc_cd.cd_devs[SCCUNIT(dev)]; - line = SCCLINE(dev); regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; s = spltty(); /* @@ -1217,7 +1052,7 @@ sccmctl(dev, bits, how) break; case DMGET: - splx(s); + (void) splx(s); return (mbits); } if (line == SCC_CHANNEL_B) { @@ -1230,7 +1065,7 @@ sccmctl(dev, bits, how) } if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line))) sc->scc_tty[line]->t_state |= TS_CARR_ON; - splx(s); + (void) splx(s); return (mbits); } @@ -1262,20 +1097,17 @@ scc_modem_intr(dev) car = value & ZSRR0_DCD; } - /* - * The pmax driver follows carrier-detect. The Alpha does not. - * XXX Why doesn't the Alpha driver follow carrier-detect? - * (in the Alpha driver, this is an "#ifdef notdef"). - * Is it related to console handling? - */ -#ifdef notdef - if (car) { - /* carrier present */ - if (!(tp->t_state & TS_CARR_ON)) - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - } else if (tp->t_state & TS_CARR_ON) - (void)(*linesw[tp->t_line].l_modem)(tp, 0); + /* Break on serial console drops into the debugger */ + if ((value & ZSRR0_BREAK) && CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) { +#ifdef DDB + splx(s); /* spl0()? */ + Debugger(); + return; +#else + /* XXX maybe fall back to PROM? */ #endif + } + splx(s); } @@ -1302,9 +1134,7 @@ sccGetc(dev) if (!regs) return (0); - s = splhigh(); - for (;;) { SCC_READ_REG(regs, line, SCC_RR0, value); if (value & ZSRR0_RX_READY) { @@ -1340,7 +1170,6 @@ sccPutc(dev, c) int s; s = splhigh(); - line = SCCLINE(dev); if (cold && scc_cons_addr) { regs = scc_cons_addr; @@ -1382,7 +1211,7 @@ sccPollc(dev, on) #ifdef SCC_DEBUG void -scc_rr(msg, regs) +rr(msg, regs) char *msg; scc_regmap_t *regs; { @@ -1416,4 +1245,3 @@ scc_rr(msg, regs) r0, r1, r2, r10, r15); } #endif /* SCC_DEBUG */ -#endif /* NSCC */ diff --git a/sys/arch/alpha/tc/sccreg.h b/sys/arch/alpha/tc/sccreg.h index f51a1083921..137a255ff53 100644 --- a/sys/arch/alpha/tc/sccreg.h +++ b/sys/arch/alpha/tc/sccreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sccreg.h,v 1.3 1996/10/30 22:41:12 niklas Exp $ */ -/* $NetBSD: sccreg.h,v 1.2 1995/04/11 03:41:10 mycroft Exp $ */ +/* $OpenBSD: sccreg.h,v 1.4 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: sccreg.h,v 1.3 1997/04/06 22:30:30 cgd Exp $ */ /* * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University diff --git a/sys/arch/alpha/tc/sccvar.h b/sys/arch/alpha/tc/sccvar.h index b1fae134466..8f24120645a 100644 --- a/sys/arch/alpha/tc/sccvar.h +++ b/sys/arch/alpha/tc/sccvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sccvar.h,v 1.4 1997/01/24 19:58:16 niklas Exp $ */ -/* $NetBSD: sccvar.h,v 1.4 1996/11/16 00:40:14 cgd Exp $ */ +/* $OpenBSD: sccvar.h,v 1.5 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: sccvar.h,v 1.7 2001/08/26 16:39:56 simonb Exp $ */ /* * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University @@ -100,6 +100,15 @@ typedef struct { #define scc_set_datum(d, v) \ do { (d) = (volatile unsigned int)(v) << 8; alpha_mb(); DELAY(5); } while (0) +/* From <pmax/dev/pdma.h>. */ +struct pdma { + void *p_addr; + char *p_mem; + char *p_end; + int p_arg; + void (*p_fcn)(struct tty *tp); +}; + /* * Minor device numbers for scc. Weird because B channel comes first and * the A channels are wired for keyboard/mouse and the B channels for the @@ -109,3 +118,5 @@ typedef struct { #define SCCMOUSE_PORT 0x1 #define SCCCOMM3_PORT 0x2 #define SCCKBD_PORT 0x3 + +int alpha_donot_kludge_scc; diff --git a/sys/arch/alpha/tc/tc_3000_300.c b/sys/arch/alpha/tc/tc_3000_300.c index 81341c2842c..fabab7d55c5 100644 --- a/sys/arch/alpha/tc/tc_3000_300.c +++ b/sys/arch/alpha/tc/tc_3000_300.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_300.c,v 1.8 2002/03/14 03:15:51 millert Exp $ */ -/* $NetBSD: tc_3000_300.c,v 1.12 1996/10/13 03:00:37 christos Exp $ */ +/* $OpenBSD: tc_3000_300.c,v 1.9 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_3000_300.c,v 1.26 2001/07/27 00:25:21 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -31,23 +31,23 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/malloc.h> #include <machine/autoconf.h> #include <machine/pte.h> -#ifndef EVCNT_COUNTERS #include <machine/intrcnt.h> -#endif #include <dev/tc/tcvar.h> +#include <dev/tc/ioasicreg.h> #include <alpha/tc/tc_conf.h> #include <alpha/tc/tc_3000_300.h> -#include <alpha/tc/ioasicreg.h> -void tc_3000_300_intr_setup(void); -void tc_3000_300_intr_establish(struct device *, void *, - tc_intrlevel_t, int (*)(void *), void *); -void tc_3000_300_intr_disestablish(struct device *, void *); -void tc_3000_300_iointr(void *, unsigned long); +#include "wsdisplay.h" +#include "sfb.h" + +#if NSFB > 0 +extern int sfb_cnattach(tc_addr_t); +#endif int tc_3000_300_intrnull(void *); @@ -65,17 +65,19 @@ int tc_3000_300_intrnull(void *); struct tc_slotdesc tc_3000_300_slots[] = { { KV(0x100000000), C(TC_3000_300_DEV_OPT0), }, /* 0 - opt slot 0 */ { KV(0x120000000), C(TC_3000_300_DEV_OPT1), }, /* 1 - opt slot 1 */ - { KV(0x180000000), C(TC_3000_300_DEV_BOGUS), }, /* 2 - TCDS ASIC */ - { KV(0x1a0000000), C(TC_3000_300_DEV_BOGUS), }, /* 3 - IOCTL ASIC */ - { KV(0x1c0000000), C(TC_3000_300_DEV_CXTURBO), }, /* 4 - CXTurbo */ + { KV(0x140000000), C(TC_3000_300_DEV_BOGUS), }, /* 2 - unused */ + { KV(0x160000000), C(TC_3000_300_DEV_BOGUS), }, /* 3 - unused */ + { KV(0x180000000), C(TC_3000_300_DEV_BOGUS), }, /* 4 - TCDS ASIC */ + { KV(0x1a0000000), C(TC_3000_300_DEV_BOGUS), }, /* 5 - IOCTL ASIC */ + { KV(0x1c0000000), C(TC_3000_300_DEV_BOGUS), }, /* 6 - CXTurbo */ }; int tc_3000_300_nslots = sizeof(tc_3000_300_slots) / sizeof(tc_3000_300_slots[0]); struct tc_builtin tc_3000_300_builtins[] = { - { "PMAGB-BA", 4, 0x02000000, C(TC_3000_300_DEV_CXTURBO), }, - { "FLAMG-IO", 3, 0x00000000, C(TC_3000_300_DEV_IOASIC), }, - { "PMAZ-DS ", 2, 0x00000000, C(TC_3000_300_DEV_TCDS), }, + { "PMAGB-BA", 6, 0x02000000, C(TC_3000_300_DEV_CXTURBO), }, + { "FLAMG-IO", 5, 0x00000000, C(TC_3000_300_DEV_IOASIC), }, + { "PMAZ-DS ", 4, 0x00000000, C(TC_3000_300_DEV_TCDS), }, }; int tc_3000_300_nbuiltins = sizeof(tc_3000_300_builtins) / sizeof(tc_3000_300_builtins[0]); @@ -83,18 +85,20 @@ int tc_3000_300_nbuiltins = struct tcintr { int (*tci_func)(void *); void *tci_arg; + struct evcnt tci_evcnt; } tc_3000_300_intr[TC_3000_300_NCOOKIES]; void tc_3000_300_intr_setup() { volatile u_int32_t *imskp; + char *cp; u_long i; /* * Disable all interrupts that we can (can't disable builtins). */ - imskp = (volatile u_int32_t *)IOASIC_REG_IMSK(DEC_3000_300_IOASIC_ADDR); + imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); *imskp &= ~(IOASIC_INTR_300_OPT0 | IOASIC_INTR_300_OPT1); /* @@ -103,9 +107,32 @@ tc_3000_300_intr_setup() for (i = 0; i < TC_3000_300_NCOOKIES; i++) { tc_3000_300_intr[i].tci_func = tc_3000_300_intrnull; tc_3000_300_intr[i].tci_arg = (void *)i; + + cp = malloc(12, M_DEVBUF, M_NOWAIT); + if (cp == NULL) + panic("tc_3000_300_intr_setup"); + sprintf(cp, "slot %lu", i); +#ifdef EVCNT_COUNTERS + evcnt_attach_dynamic(&tc_3000_300_intr[i].tci_evcnt, + EVCNT_TYPE_INTR, NULL, "tc", cp); +#endif } } +const struct evcnt * +tc_3000_300_intr_evcnt(tcadev, cookie) + struct device *tcadev; + void *cookie; +{ + u_long dev = (u_long)cookie; + +#ifdef DIAGNOSTIC + /* XXX bounds-check cookie. */ +#endif + + return (&tc_3000_300_intr[dev].tci_evcnt); +} + void tc_3000_300_intr_establish(tcadev, cookie, level, func, arg) struct device *tcadev; @@ -121,12 +148,12 @@ tc_3000_300_intr_establish(tcadev, cookie, level, func, arg) #endif if (tc_3000_300_intr[dev].tci_func != tc_3000_300_intrnull) - panic("tc_3000_300_intr_establish: cookie %d twice", dev); + panic("tc_3000_300_intr_establish: cookie %lu twice", dev); tc_3000_300_intr[dev].tci_func = func; tc_3000_300_intr[dev].tci_arg = arg; - imskp = (volatile u_int32_t *)IOASIC_REG_IMSK(DEC_3000_300_IOASIC_ADDR); + imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); switch (dev) { case TC_3000_300_DEV_OPT0: *imskp |= IOASIC_INTR_300_OPT0; @@ -153,10 +180,10 @@ tc_3000_300_intr_disestablish(tcadev, cookie) #endif if (tc_3000_300_intr[dev].tci_func == tc_3000_300_intrnull) - panic("tc_3000_300_intr_disestablish: cookie %d bad intr", + panic("tc_3000_300_intr_disestablish: cookie %lu bad intr", dev); - imskp = (volatile u_int32_t *)IOASIC_REG_IMSK(DEC_3000_300_IOASIC_ADDR); + imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); switch (dev) { case TC_3000_300_DEV_OPT0: *imskp &= ~IOASIC_INTR_300_OPT0; @@ -183,8 +210,8 @@ tc_3000_300_intrnull(val) } void -tc_3000_300_iointr(framep, vec) - void *framep; +tc_3000_300_iointr(arg, vec) + void *arg; unsigned long vec; { u_int32_t tcir, ioasicir, ioasicimr; @@ -207,9 +234,9 @@ tc_3000_300_iointr(framep, vec) /* find out what interrupts/errors occurred */ tcir = *(volatile u_int32_t *)TC_3000_300_IR; ioasicir = *(volatile u_int32_t *) - IOASIC_REG_INTR(DEC_3000_300_IOASIC_ADDR); + (DEC_3000_300_IOASIC_ADDR + IOASIC_INTR); ioasicimr = *(volatile u_int32_t *) - IOASIC_REG_IMSK(DEC_3000_300_IOASIC_ADDR); + (DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); tc_mb(); /* Ignore interrupts that aren't enabled out. */ @@ -223,11 +250,10 @@ tc_3000_300_iointr(framep, vec) ifound = 0; #ifdef EVCNT_COUNTERS - /* No interrupt counting via evcnt counters */ - XXX BREAK HERE XXX -#else /* !EVCNT_COUNTERS */ +#define INCRINTRCNT(slot) tc_3000_300_intr[slot].tci_evcnt.ev_count++ +#else #define INCRINTRCNT(slot) intrcnt[INTRCNT_KN16 + slot]++ -#endif /* EVCNT_COUNTERS */ +#endif #define CHECKINTR(slot, flag) \ if (flag) { \ @@ -264,3 +290,34 @@ tc_3000_300_iointr(framep, vec) #endif } while (ifound); } + +#if NWSDISPLAY > 0 +/* + * tc_3000_300_fb_cnattach -- + * Attempt to map the CTB output device to a slot and attach the + * framebuffer as the output side of the console. + */ +int +tc_3000_300_fb_cnattach(turbo_slot) + u_int64_t turbo_slot; +{ + u_int32_t output_slot; + + output_slot = turbo_slot & 0xffffffff; + + if (output_slot >= tc_3000_300_nslots) { + return EINVAL; + } + + if (output_slot == 0) { +#if NSFB > 0 + sfb_cnattach(KV(0x1c0000000) + 0x02000000); + return 0; +#else + return ENXIO; +#endif + } + + return tc_fb_cnattach(tc_3000_300_slots[output_slot-1].tcs_addr); +} +#endif /* NWSDISPLAY */ diff --git a/sys/arch/alpha/tc/tc_3000_300.h b/sys/arch/alpha/tc/tc_3000_300.h index 475eefad00b..b91f26b087f 100644 --- a/sys/arch/alpha/tc/tc_3000_300.h +++ b/sys/arch/alpha/tc/tc_3000_300.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_300.h,v 1.4 1996/10/30 22:41:17 niklas Exp $ */ -/* $NetBSD: tc_3000_300.h,v 1.2 1995/12/20 00:43:28 cgd Exp $ */ +/* $OpenBSD: tc_3000_300.h,v 1.5 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_3000_300.h,v 1.4 1998/10/22 01:03:09 briggs Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -60,3 +60,5 @@ #define TC_3000_300_DEV_BOGUS -1 #define TC_3000_300_NCOOKIES 5 + +extern int tc_3000_300_fb_cnattach(u_int64_t); diff --git a/sys/arch/alpha/tc/tc_3000_500.c b/sys/arch/alpha/tc/tc_3000_500.c index 79c987a8b27..a1e03986559 100644 --- a/sys/arch/alpha/tc/tc_3000_500.c +++ b/sys/arch/alpha/tc/tc_3000_500.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_500.c,v 1.9 2002/03/14 03:15:51 millert Exp $ */ -/* $NetBSD: tc_3000_500.c,v 1.12 1996/11/15 23:59:00 cgd Exp $ */ +/* $OpenBSD: tc_3000_500.c,v 1.10 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_3000_500.c,v 1.24 2001/07/27 00:25:21 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -31,17 +31,24 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/malloc.h> #include <machine/autoconf.h> #include <machine/pte.h> -#ifndef EVCNT_COUNTERS +#include <machine/rpb.h> #include <machine/intrcnt.h> -#endif #include <dev/tc/tcvar.h> #include <alpha/tc/tc_conf.h> #include <alpha/tc/tc_3000_500.h> +#include "wsdisplay.h" +#include "sfb.h" + +#if NSFB > 0 +extern int sfb_cnattach(tc_addr_t); +#endif + void tc_3000_500_intr_setup(void); void tc_3000_500_intr_establish(struct device *, void *, tc_intrlevel_t, int (*)(void *), void *); @@ -49,6 +56,7 @@ void tc_3000_500_intr_disestablish(struct device *, void *); void tc_3000_500_iointr(void *, unsigned long); int tc_3000_500_intrnull(void *); +int tc_3000_500_fb_cnattach(u_int64_t); #define C(x) ((void *)(u_long)x) #define KV(x) (ALPHA_PHYS_TO_K0SEG(x)) @@ -96,6 +104,7 @@ u_int32_t tc_3000_500_intrbits[TC_3000_500_NCOOKIES] = { struct tcintr { int (*tci_func)(void *); void *tci_arg; + struct evcnt tci_evcnt; } tc_3000_500_intr[TC_3000_500_NCOOKIES]; u_int32_t tc_3000_500_imask; /* intrs we want to ignore; mirrors IMR. */ @@ -103,6 +112,7 @@ u_int32_t tc_3000_500_imask; /* intrs we want to ignore; mirrors IMR. */ void tc_3000_500_intr_setup() { + char *cp; u_long i; /* @@ -121,9 +131,32 @@ tc_3000_500_intr_setup() for (i = 0; i < TC_3000_500_NCOOKIES; i++) { tc_3000_500_intr[i].tci_func = tc_3000_500_intrnull; tc_3000_500_intr[i].tci_arg = (void *)i; + + cp = malloc(12, M_DEVBUF, M_NOWAIT); + if (cp == NULL) + panic("tc_3000_500_intr_setup"); + sprintf(cp, "slot %lu", i); +#ifdef EVCNT_COUNTERS + evcnt_attach_dynamic(&tc_3000_500_intr[i].tci_evcnt, + EVCNT_TYPE_INTR, NULL, "tc", cp); +#endif } } +const struct evcnt * +tc_3000_500_intr_evcnt(tcadev, cookie) + struct device *tcadev; + void *cookie; +{ + u_long dev = (u_long)cookie; + +#ifdef DIAGNOSTIC + /* XXX bounds-check cookie. */ +#endif + + return (&tc_3000_500_intr[dev].tci_evcnt); +} + void tc_3000_500_intr_establish(tcadev, cookie, level, func, arg) struct device *tcadev; @@ -138,7 +171,7 @@ tc_3000_500_intr_establish(tcadev, cookie, level, func, arg) #endif if (tc_3000_500_intr[dev].tci_func != tc_3000_500_intrnull) - panic("tc_3000_500_intr_establish: cookie %d twice", dev); + panic("tc_3000_500_intr_establish: cookie %lu twice", dev); tc_3000_500_intr[dev].tci_func = func; tc_3000_500_intr[dev].tci_arg = arg; @@ -160,7 +193,7 @@ tc_3000_500_intr_disestablish(tcadev, cookie) #endif if (tc_3000_500_intr[dev].tci_func == tc_3000_500_intrnull) - panic("tc_3000_500_intr_disestablish: cookie %d bad intr", + panic("tc_3000_500_intr_disestablish: cookie %lu bad intr", dev); tc_3000_500_imask |= tc_3000_500_intrbits[dev]; @@ -181,8 +214,8 @@ tc_3000_500_intrnull(val) } void -tc_3000_500_iointr(framep, vec) - void *framep; +tc_3000_500_iointr(arg, vec) + void *arg; unsigned long vec; { u_int32_t ir; @@ -209,11 +242,10 @@ tc_3000_500_iointr(framep, vec) ifound = 0; #ifdef EVCNT_COUNTERS - /* No interrupt counting via evcnt counters */ - XXX BREAK HERE XXX -#else /* !EVCNT_COUNTERS */ +#define INCRINTRCNT(slot) tc_3000_500_intr[slot].tci_evcnt.ev_count++ +#else #define INCRINTRCNT(slot) intrcnt[INTRCNT_KN15 + slot]++ -#endif /* EVCNT_COUNTERS */ +#endif #define CHECKINTR(slot) \ if (ir & tc_3000_500_intrbits[slot]) { \ @@ -257,6 +289,47 @@ tc_3000_500_iointr(framep, vec) } while (ifound); } +#if NWSDISPLAY > 0 +/* + * tc_3000_500_fb_cnattach -- + * Attempt to map the CTB output device to a slot and attach the + * framebuffer as the output side of the console. + */ +int +tc_3000_500_fb_cnattach(turbo_slot) + u_int64_t turbo_slot; +{ + u_int32_t output_slot; + + output_slot = turbo_slot & 0xffffffff; + + if (output_slot >= tc_3000_500_nslots) { + return EINVAL; + } + + if (hwrpb->rpb_variation & SV_GRAPHICS) { + if (output_slot == 0) { +#if NSFB > 0 + sfb_cnattach(KV(0x1e0000000) + 0x02000000); + return 0; +#else + return ENXIO; +#endif + } + } else { + /* + * Slots 0-2 in the tc_3000_500_slots array are only + * on the 500 models that also have the CXTurbo + * (500/800/900) and a total of 6 TC slots. For the + * 400/600/700, slots 0-2 are in table locations 3-5, so + * offset the CTB slot by 3 to get the address in our table. + */ + output_slot += 3; + } + return tc_fb_cnattach(tc_3000_500_slots[output_slot-1].tcs_addr); +} +#endif /* NWSDISPLAY */ + #if 0 /* * tc_3000_500_ioslot -- diff --git a/sys/arch/alpha/tc/tc_3000_500.h b/sys/arch/alpha/tc/tc_3000_500.h index b9249b9a857..b1c6dbe7c36 100644 --- a/sys/arch/alpha/tc/tc_3000_500.h +++ b/sys/arch/alpha/tc/tc_3000_500.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_500.h,v 1.4 1996/10/30 22:41:19 niklas Exp $ */ -/* $NetBSD: tc_3000_500.h,v 1.2 1995/12/20 00:43:31 cgd Exp $ */ +/* $OpenBSD: tc_3000_500.h,v 1.5 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_3000_500.h,v 1.4 1998/10/22 01:03:09 briggs Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -104,3 +104,5 @@ #define TC_3000_500_DEV_BOGUS -1 #define TC_3000_500_NCOOKIES 9 + +extern int tc_3000_500_fb_cnattach(u_int64_t); diff --git a/sys/arch/alpha/tc/tc_bus_mem.c b/sys/arch/alpha/tc/tc_bus_mem.c index 951990eaf44..759c9e4a295 100644 --- a/sys/arch/alpha/tc/tc_bus_mem.c +++ b/sys/arch/alpha/tc/tc_bus_mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_bus_mem.c,v 1.12 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: tc_bus_mem.c,v 1.13 1996/12/02 22:19:34 cgd Exp $ */ +/* $OpenBSD: tc_bus_mem.c,v 1.13 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_bus_mem.c,v 1.25 2001/09/04 05:31:28 thorpej Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -37,11 +37,14 @@ #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> + #include <uvm/uvm_extern.h> #include <machine/bus.h> #include <dev/tc/tcvar.h> +#define __C(A,B) __CONCAT(A,B) + /* mapping/unmapping */ int tc_mem_map(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *); @@ -136,32 +139,16 @@ void tc_mem_set_region_8(void *, bus_space_handle_t, bus_size_t, u_int64_t, bus_size_t); /* copy */ -void tc_mem_copy_1(void *, bus_space_handle_t, +void tc_mem_copy_region_1(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); -void tc_mem_copy_2(void *, bus_space_handle_t, +void tc_mem_copy_region_2(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); -void tc_mem_copy_4(void *, bus_space_handle_t, +void tc_mem_copy_region_4(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); -void tc_mem_copy_8(void *, bus_space_handle_t, +void tc_mem_copy_region_8(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); -/* read multiple raw */ -void tc_mem_read_raw_multi_2(void *, bus_space_handle_t, - bus_size_t, u_int8_t *, bus_size_t); -void tc_mem_read_raw_multi_4(void *, bus_space_handle_t, - bus_size_t, u_int8_t *, bus_size_t); -void tc_mem_read_raw_multi_8(void *, bus_space_handle_t, - bus_size_t, u_int8_t *, bus_size_t); - -/* write multiple raw */ -void tc_mem_write_raw_multi_2(void *, bus_space_handle_t, - bus_size_t, const u_int8_t *, bus_size_t); -void tc_mem_write_raw_multi_4(void *, bus_space_handle_t, - bus_size_t, const u_int8_t *, bus_size_t); -void tc_mem_write_raw_multi_8(void *, bus_space_handle_t, - bus_size_t, const u_int8_t *, bus_size_t); - -static struct alpha_bus_space tc_mem_space = { +struct alpha_bus_space tc_mem_space = { /* cookie */ NULL, @@ -226,20 +213,10 @@ static struct alpha_bus_space tc_mem_space = { tc_mem_set_region_8, /* copy */ - tc_mem_copy_1, - tc_mem_copy_2, - tc_mem_copy_4, - tc_mem_copy_8, - - /* write multiple raw */ - tc_mem_read_raw_multi_2, - tc_mem_read_raw_multi_4, - tc_mem_read_raw_multi_8, - - /* write multiple raw*/ - tc_mem_write_raw_multi_2, - tc_mem_write_raw_multi_4, - tc_mem_write_raw_multi_8, + tc_mem_copy_region_1, + tc_mem_copy_region_2, + tc_mem_copy_region_4, + tc_mem_copy_region_8, }; bus_space_tag_t @@ -252,6 +229,7 @@ tc_bus_mem_init(memv) return (h); } +/* ARGSUSED */ int tc_mem_map(v, memaddr, memsize, cacheable, memhp) void *v; @@ -270,6 +248,7 @@ tc_mem_map(v, memaddr, memsize, cacheable, memhp) return (0); } +/* ARGSUSED */ void tc_mem_unmap(v, memh, memsize) void *v; @@ -300,11 +279,11 @@ tc_mem_subregion(v, memh, offset, size, nmemh) } int -tc_mem_alloc(v, rstart, rend, size, align, boundary, cacheable, addrp, bshp) +tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp) void *v; bus_addr_t rstart, rend, *addrp; bus_size_t size, align, boundary; - int cacheable; + int flags; bus_space_handle_t *bshp; { @@ -331,9 +310,9 @@ tc_mem_barrier(v, h, o, l, f) int f; { - if ((f & BUS_BARRIER_READ) != 0) + if ((f & BUS_SPACE_BARRIER_READ) != 0) alpha_mb(); - else if ((f & BUS_BARRIER_WRITE) != 0) + else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) alpha_wmb(); } @@ -408,7 +387,7 @@ tc_mem_read_8(v, memh, off) #define tc_mem_read_multi_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ +__C(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -416,8 +395,8 @@ __abs_c(tc_mem_read_multi_,BYTES)(v, h, o, a, c) \ { \ \ while (c-- > 0) { \ - tc_mem_barrier(v, h, o, sizeof *a, BUS_BARRIER_READ); \ - *a++ = __abs_c(tc_mem_read_,BYTES)(v, h, o); \ + tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \ + *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ } \ } tc_mem_read_multi_N(1,u_int8_t) @@ -427,7 +406,7 @@ tc_mem_read_multi_N(8,u_int64_t) #define tc_mem_read_region_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ +__C(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -435,7 +414,7 @@ __abs_c(tc_mem_read_region_,BYTES)(v, h, o, a, c) \ { \ \ while (c-- > 0) { \ - *a++ = __abs_c(tc_mem_read_,BYTES)(v, h, o); \ + *a++ = __C(tc_mem_read_,BYTES)(v, h, o); \ o += sizeof *a; \ } \ } @@ -541,7 +520,7 @@ tc_mem_write_8(v, memh, off, val) #define tc_mem_write_multi_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ +__C(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -549,8 +528,8 @@ __abs_c(tc_mem_write_multi_,BYTES)(v, h, o, a, c) \ { \ \ while (c-- > 0) { \ - __abs_c(tc_mem_write_,BYTES)(v, h, o, *a++); \ - tc_mem_barrier(v, h, o, sizeof *a, BUS_BARRIER_WRITE); \ + __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ + tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \ } \ } tc_mem_write_multi_N(1,u_int8_t) @@ -560,7 +539,7 @@ tc_mem_write_multi_N(8,u_int64_t) #define tc_mem_write_region_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ +__C(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -568,7 +547,7 @@ __abs_c(tc_mem_write_region_,BYTES)(v, h, o, a, c) \ { \ \ while (c-- > 0) { \ - __abs_c(tc_mem_write_,BYTES)(v, h, o, *a++); \ + __C(tc_mem_write_,BYTES)(v, h, o, *a++); \ o += sizeof *a; \ } \ } @@ -579,7 +558,7 @@ tc_mem_write_region_N(8,u_int64_t) #define tc_mem_set_multi_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ +__C(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -587,8 +566,8 @@ __abs_c(tc_mem_set_multi_,BYTES)(v, h, o, val, c) \ { \ \ while (c-- > 0) { \ - __abs_c(tc_mem_write_,BYTES)(v, h, o, val); \ - tc_mem_barrier(v, h, o, sizeof val, BUS_BARRIER_WRITE); \ + __C(tc_mem_write_,BYTES)(v, h, o, val); \ + tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \ } \ } tc_mem_set_multi_N(1,u_int8_t) @@ -598,7 +577,7 @@ tc_mem_set_multi_N(8,u_int64_t) #define tc_mem_set_region_N(BYTES,TYPE) \ void \ -__abs_c(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ +__C(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ void *v; \ bus_space_handle_t h; \ bus_size_t o, c; \ @@ -606,7 +585,7 @@ __abs_c(tc_mem_set_region_,BYTES)(v, h, o, val, c) \ { \ \ while (c-- > 0) { \ - __abs_c(tc_mem_write_,BYTES)(v, h, o, val); \ + __C(tc_mem_write_,BYTES)(v, h, o, val); \ o += sizeof val; \ } \ } @@ -615,84 +594,33 @@ tc_mem_set_region_N(2,u_int16_t) tc_mem_set_region_N(4,u_int32_t) tc_mem_set_region_N(8,u_int64_t) -#define tc_mem_copy_N(BYTES) \ +#define tc_mem_copy_region_N(BYTES) \ void \ -__abs_c(tc_mem_copy_,BYTES)(v, h1, o1, h2, o2, c) \ +__C(tc_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c) \ void *v; \ bus_space_handle_t h1, h2; \ bus_size_t o1, o2, c; \ { \ - bus_size_t i, o; \ + bus_size_t o; \ \ if ((h1 & TC_SPACE_SPARSE) != 0 && \ (h2 & TC_SPACE_SPARSE) != 0) { \ - bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \ + bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \ return; \ } \ \ - /* Circumvent a common case of overlapping problems */ \ - if (h1 == h2 && o2 > o1) \ - for (i = 0, o = (c - 1) * BYTES; i < c; i++, o -= BYTES)\ - __abs_c(tc_mem_write_,BYTES)(v, h2, o2 + o, \ - __abs_c(tc_mem_read_,BYTES)(v, h1, o1 + o));\ + if (h1 + o1 >= h2 + o2) \ + /* src after dest: copy forward */ \ + for (o = 0; c > 0; c--, o += BYTES) \ + __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ + __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ else \ - for (i = 0, o = 0; i < c; i++, o += BYTES) \ - __abs_c(tc_mem_write_,BYTES)(v, h2, o2 + o, \ - __abs_c(tc_mem_read_,BYTES)(v, h1, o1 + o));\ -} -tc_mem_copy_N(1) -tc_mem_copy_N(2) -tc_mem_copy_N(4) -tc_mem_copy_N(8) - -#define tc_mem_read_raw_multi_N(BYTES,TYPE) \ -void \ -__abs_c(tc_mem_read_raw_multi_,BYTES)(v, h, o, a, c) \ - void *v; \ - bus_space_handle_t h; \ - bus_size_t o, c; \ - u_int8_t *a; \ -{ \ - TYPE temp; \ - int i; \ - \ - while (c > 0) { \ - tc_mem_barrier(v, h, o, BYTES, BUS_BARRIER_READ); \ - temp = __abs_c(tc_mem_read_,BYTES)(v, h, o); \ - for (i = 0; i < BYTES; i++) { \ - *a++ = temp & 0xff; \ - temp >>= 8; \ - } \ - c -= BYTES; \ - } \ -} -tc_mem_read_raw_multi_N(2,u_int16_t) -tc_mem_read_raw_multi_N(4,u_int32_t) -tc_mem_read_raw_multi_N(8,u_int64_t) - -#define tc_mem_write_raw_multi_N(BYTES,TYPE) \ -void \ -__abs_c(tc_mem_write_raw_multi_,BYTES)(v, h, o, a, c) \ - void *v; \ - bus_space_handle_t h; \ - bus_size_t o, c; \ - const u_int8_t *a; \ -{ \ - TYPE temp; \ - int i; \ - \ - while (c > 0) { \ - temp = 0; \ - for (i = BYTES - 1; i >= 0; i--) { \ - temp <<= 8; \ - temp |= *(a + i); \ - } \ - __abs_c(tc_mem_write_,BYTES)(v, h, o, temp); \ - tc_mem_barrier(v, h, o, BYTES, BUS_BARRIER_WRITE); \ - c -= BYTES; \ - a += BYTES; \ - } \ + /* dest after src: copy backwards */ \ + for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \ + __C(tc_mem_write_,BYTES)(v, h2, o2 + o, \ + __C(tc_mem_read_,BYTES)(v, h1, o1 + o)); \ } -tc_mem_write_raw_multi_N(2,u_int16_t) -tc_mem_write_raw_multi_N(4,u_int32_t) -tc_mem_write_raw_multi_N(8,u_int64_t) +tc_mem_copy_region_N(1) +tc_mem_copy_region_N(2) +tc_mem_copy_region_N(4) +tc_mem_copy_region_N(8) diff --git a/sys/arch/alpha/tc/tc_conf.h b/sys/arch/alpha/tc/tc_conf.h index a1c30c00cb2..ec70762c9f9 100644 --- a/sys/arch/alpha/tc/tc_conf.h +++ b/sys/arch/alpha/tc/tc_conf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_conf.h,v 1.6 2002/03/14 03:15:51 millert Exp $ */ -/* $NetBSD: tc_conf.h,v 1.3 1996/11/15 23:59:01 cgd Exp $ */ +/* $OpenBSD: tc_conf.h,v 1.7 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_conf.h,v 1.10 2000/06/04 19:14:29 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -33,9 +33,13 @@ */ #ifdef DEC_3000_500 +#include <alpha/tc/tc_dma_3000_500.h> + extern void tc_3000_500_intr_setup(void); extern void tc_3000_500_iointr(void *, unsigned long); +extern const struct evcnt * + tc_3000_500_intr_evcnt(struct device *, void *); extern void tc_3000_500_intr_establish(struct device *, void *, tc_intrlevel_t, int (*)(void *), void *); extern void tc_3000_500_intr_disestablish(struct device *, void *); @@ -49,9 +53,13 @@ extern struct tc_builtin tc_3000_500_nographics_builtins[]; #endif /* DEC_3000_500 */ #ifdef DEC_3000_300 +#include <alpha/tc/tc_dma_3000_300.h> + extern void tc_3000_300_intr_setup(void); extern void tc_3000_300_iointr(void *, unsigned long); +extern const struct evcnt * + tc_3000_300_intr_evcnt(struct device *, void *); extern void tc_3000_300_intr_establish(struct device *, void *, tc_intrlevel_t, int (*)(void *), void *); extern void tc_3000_300_intr_disestablish(struct device *, void *); @@ -61,3 +69,6 @@ extern struct tc_slotdesc tc_3000_300_slots[]; extern int tc_3000_300_nbuiltins; extern struct tc_builtin tc_3000_300_builtins[]; #endif /* DEC_3000_300 */ + +extern int tc_fb_cnattach(tc_addr_t); + diff --git a/sys/arch/alpha/tc/tc_dma.c b/sys/arch/alpha/tc/tc_dma.c new file mode 100644 index 00000000000..5de443eaaa5 --- /dev/null +++ b/sys/arch/alpha/tc/tc_dma.c @@ -0,0 +1,83 @@ +/* $OpenBSD: tc_dma.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_dma.c,v 1.10 2001/07/19 06:40:02 thorpej Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#define _ALPHA_BUS_DMA_PRIVATE + +#include <sys/param.h> +#include <sys/device.h> + +#include <machine/bus.h> + +#include <dev/tc/tcvar.h> + +struct alpha_bus_dma_tag tc_dmat_direct = { + NULL, /* _cookie */ + 0, /* _wbase */ + 0, /* _wsize */ + NULL, /* _next_window */ + 0, /* _boundary */ + NULL, /* _sgmap */ + NULL, /* _get_tag */ + _bus_dmamap_create, + _bus_dmamap_destroy, + _bus_dmamap_load_direct, + _bus_dmamap_load_mbuf_direct, + _bus_dmamap_load_uio_direct, + _bus_dmamap_load_raw_direct, + _bus_dmamap_unload, + _bus_dmamap_sync, + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap, +}; + +void +tc_dma_init() +{ + + /* XXX XXX BEGIN XXX XXX */ + { /* XXX */ + extern paddr_t alpha_XXX_dmamap_or; /* XXX */ + alpha_XXX_dmamap_or = 0; /* XXX */ + } /* XXX */ + /* XXX XXX END XXX XXX */ +} diff --git a/sys/arch/alpha/tc/tc_dma_3000_300.c b/sys/arch/alpha/tc/tc_dma_3000_300.c new file mode 100644 index 00000000000..e010cacf141 --- /dev/null +++ b/sys/arch/alpha/tc/tc_dma_3000_300.c @@ -0,0 +1,58 @@ +/* $OpenBSD: tc_dma_3000_300.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_dma_3000_300.c,v 1.3 1997/09/02 13:20:29 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#include <sys/param.h> + +#include <machine/bus.h> + +#include <alpha/tc/tc_dma_3000_300.h> + +/* + * Return the DMA tag for the given slot. + */ +bus_dma_tag_t +tc_dma_get_tag_3000_300(slot) + int slot; +{ + extern struct alpha_bus_dma_tag tc_dmat_direct; + + /* Pelicans don't have SGMAPs. */ + return (&tc_dmat_direct); +} diff --git a/sys/arch/alpha/tc/tc_dma_3000_300.h b/sys/arch/alpha/tc/tc_dma_3000_300.h new file mode 100644 index 00000000000..34050ec5fc3 --- /dev/null +++ b/sys/arch/alpha/tc/tc_dma_3000_300.h @@ -0,0 +1,41 @@ +/* $OpenBSD: tc_dma_3000_300.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_dma_3000_300.h,v 1.2 1997/06/07 00:02:17 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +bus_dma_tag_t tc_dma_get_tag_3000_300(int); diff --git a/sys/arch/alpha/tc/tc_dma_3000_500.c b/sys/arch/alpha/tc/tc_dma_3000_500.c new file mode 100644 index 00000000000..49732d62ec9 --- /dev/null +++ b/sys/arch/alpha/tc/tc_dma_3000_500.c @@ -0,0 +1,247 @@ +/* $OpenBSD: tc_dma_3000_500.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_dma_3000_500.c,v 1.13 2001/07/19 06:40:03 thorpej Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#define _ALPHA_BUS_DMA_PRIVATE + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +#include <dev/tc/tcvar.h> +#include <alpha/tc/tc_sgmap.h> +#include <alpha/tc/tc_dma_3000_500.h> + +struct alpha_bus_dma_tag tc_dmat_sgmap = { + NULL, /* _cookie */ + 0, /* _wbase */ + 0, /* _wsize */ + NULL, /* _next_window */ + 0, /* _boundary */ + NULL, /* _sgmap */ + NULL, /* _get_tag */ + tc_bus_dmamap_create_sgmap, + tc_bus_dmamap_destroy_sgmap, + tc_bus_dmamap_load_sgmap, + tc_bus_dmamap_load_mbuf_sgmap, + tc_bus_dmamap_load_uio_sgmap, + tc_bus_dmamap_load_raw_sgmap, + tc_bus_dmamap_unload_sgmap, + _bus_dmamap_sync, + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap, +}; + +struct tc_dma_slot_info { + struct alpha_sgmap tdsi_sgmap; /* sgmap for slot */ + struct alpha_bus_dma_tag tdsi_dmat; /* dma tag for slot */ +}; +struct tc_dma_slot_info *tc_dma_slot_info; + +void +tc_dma_init_3000_500(nslots) + int nslots; +{ + extern struct alpha_bus_dma_tag tc_dmat_direct; + size_t sisize; + int i; + + /* Allocate per-slot DMA info. */ + sisize = nslots * sizeof(struct tc_dma_slot_info); + tc_dma_slot_info = malloc(sisize, M_DEVBUF, M_NOWAIT); + if (tc_dma_slot_info == NULL) + panic("tc_dma_init: can't allocate per-slot DMA info"); + memset(tc_dma_slot_info, 0, sisize); + + /* Default all slots to direct-mapped. */ + for (i = 0; i < nslots; i++) + memcpy(&tc_dma_slot_info[i].tdsi_dmat, &tc_dmat_direct, + sizeof(tc_dma_slot_info[i].tdsi_dmat)); +} + +/* + * Return the DMA tag for the given slot. + */ +bus_dma_tag_t +tc_dma_get_tag_3000_500(slot) + int slot; +{ + + return (&tc_dma_slot_info[slot].tdsi_dmat); +} + +/* + * Create a TurboChannel SGMAP-mapped DMA map. + */ +int +tc_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary, + flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + bus_dmamap_t map; + int error; + + error = _bus_dmamap_create(t, size, nsegments, maxsegsz, + boundary, flags, dmamp); + if (error) + return (error); + + map = *dmamp; + + /* XXX BUS_DMA_ALLOCNOW */ + + return (error); +} + +/* + * Destroy a TurboChannel SGMAP-mapped DMA map. + */ +void +tc_bus_dmamap_destroy_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + KASSERT(map->dm_mapsize == 0); + + _bus_dmamap_destroy(t, map); +} + +/* + * Load a TurboChannel SGMAP-mapped DMA map with a linear buffer. + */ +int +tc_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + struct tc_dma_slot_info *tdsi = t->_cookie; + + return (tc_sgmap_load(t, map, buf, buflen, p, flags, + &tdsi->tdsi_sgmap)); +} + +/* + * Load a TurboChannel SGMAP-mapped DMA map with an mbuf chain. + */ +int +tc_bus_dmamap_load_mbuf_sgmap(t, map, m, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m; + int flags; +{ + struct tc_dma_slot_info *tdsi = t->_cookie; + + return (tc_sgmap_load_mbuf(t, map, m, flags, &tdsi->tdsi_sgmap)); +} + +/* + * Load a TurboChannel SGMAP-mapped DMA map with a uio. + */ +int +tc_bus_dmamap_load_uio_sgmap(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + struct tc_dma_slot_info *tdsi = t->_cookie; + + return (tc_sgmap_load_uio(t, map, uio, flags, &tdsi->tdsi_sgmap)); +} + +/* + * Load a TurboChannel SGMAP-mapped DMA map with raw memory. + */ +int +tc_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + struct tc_dma_slot_info *tdsi = t->_cookie; + + return (tc_sgmap_load_raw(t, map, segs, nsegs, size, flags, + &tdsi->tdsi_sgmap)); +} + +/* + * Unload a TurboChannel SGMAP-mapped DMA map. + */ +void +tc_bus_dmamap_unload_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + struct tc_dma_slot_info *tdsi = t->_cookie; + + /* + * Invalidate any SGMAP page table entries used by this + * mapping. + */ + tc_sgmap_unload(t, map, &tdsi->tdsi_sgmap); + + /* + * Do the generic bits of the unload. + */ + _bus_dmamap_unload(t, map); +} diff --git a/sys/arch/alpha/tc/tc_dma_3000_500.h b/sys/arch/alpha/tc/tc_dma_3000_500.h new file mode 100644 index 00000000000..de52194fc69 --- /dev/null +++ b/sys/arch/alpha/tc/tc_dma_3000_500.h @@ -0,0 +1,55 @@ +/* $OpenBSD: tc_dma_3000_500.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_dma_3000_500.h,v 1.2 1997/06/07 00:02:19 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +void tc_dma_init_3000_500(int); +bus_dma_tag_t tc_dma_get_tag_3000_500(int); + +int tc_bus_dmamap_create_sgmap(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void tc_bus_dmamap_destroy_sgmap(bus_dma_tag_t, bus_dmamap_t); +int tc_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int tc_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int tc_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int tc_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void tc_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t); diff --git a/sys/arch/alpha/tc/tc_sgmap.c b/sys/arch/alpha/tc/tc_sgmap.c new file mode 100644 index 00000000000..71bc8f2bab0 --- /dev/null +++ b/sys/arch/alpha/tc/tc_sgmap.c @@ -0,0 +1,55 @@ +/* $OpenBSD: tc_sgmap.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_sgmap.c,v 1.5 2001/07/19 06:40:03 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/proc.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +#include <alpha/tc/tc_sgmap.h> + +#include <alpha/dev/sgmap_typedep.c> diff --git a/sys/arch/alpha/tc/tc_sgmap.h b/sys/arch/alpha/tc/tc_sgmap.h new file mode 100644 index 00000000000..39392db3870 --- /dev/null +++ b/sys/arch/alpha/tc/tc_sgmap.h @@ -0,0 +1,60 @@ +/* $OpenBSD: tc_sgmap.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc_sgmap.h,v 1.2 1997/06/07 00:02:20 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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. + */ + +#define SGMAP_TYPE tc_sgmap +#define SGMAP_PTE_TYPE u_int32_t +#define SGMAP_PTE_SPACING 2 + +/* + * A TurboChannel SGMAP page table entry looks like this: + * + * 31 23 22 21 20 4 3 0 + * | Discarded | V | F | P | Page address | UNP | + * + * The page address is bits <29:13> of the physical address of the + * page. The V bit is set if the PTE holds a valid mapping. + * The F (funny) bit forces a parity error. The P bit is a + * hardware-generated parity bit. + */ +#define SGPTE_PGADDR_SHIFT 9 +#define SGPTE_VALID 0x00800000 + +#include <alpha/dev/sgmapvar.h> +#include <alpha/dev/sgmap_typedep.h> diff --git a/sys/arch/alpha/tc/tcasic.c b/sys/arch/alpha/tc/tcasic.c index fe63afca03f..7ea036a533f 100644 --- a/sys/arch/alpha/tc/tcasic.c +++ b/sys/arch/alpha/tc/tcasic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tcasic.c,v 1.9 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: tcasic.c,v 1.14 1996/12/05 01:39:45 cgd Exp $ */ +/* $OpenBSD: tcasic.c,v 1.10 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tcasic.c,v 1.36 2001/08/23 01:16:52 nisimura Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -34,16 +34,13 @@ #include <machine/autoconf.h> #include <machine/rpb.h> +#include <machine/cpu.h> #include <dev/tc/tcvar.h> #include <alpha/tc/tc_conf.h> /* Definition of the driver for autoconfig. */ -#ifdef __BROKEN_INDIRECT_CONFIG int tcasicmatch(struct device *, void *, void *); -#else -int tcasicmatch(struct device *, struct cfdata *, void *); -#endif void tcasicattach(struct device *, struct device *, void *); struct cfattach tcasic_ca = { @@ -54,9 +51,8 @@ struct cfdriver tcasic_cd = { NULL, "tcasic", DV_DULL, }; -int tcasicprint(void *, const char *); -extern int cputype; +int tcasicprint(void *, const char *); /* There can be only one. */ int tcasicfound; @@ -64,12 +60,7 @@ int tcasicfound; int tcasicmatch(parent, cfdata, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *cfdata; -#else - struct cfdata *cfdata; -#endif - void *aux; + void *cfdata, *aux; { struct mainbus_attach_args *ma = aux; @@ -107,7 +98,6 @@ tcasicattach(parent, self, aux) intr_setup = tc_3000_500_intr_setup; iointr = tc_3000_500_iointr; - tba.tba_busname = "tc"; tba.tba_speed = TC_SPEED_25_MHZ; tba.tba_nslots = tc_3000_500_nslots; tba.tba_slots = tc_3000_500_slots; @@ -118,8 +108,13 @@ tcasicattach(parent, self, aux) tba.tba_nbuiltins = tc_3000_500_nographics_nbuiltins; tba.tba_builtins = tc_3000_500_nographics_builtins; } + tba.tba_intr_evcnt = tc_3000_500_intr_evcnt; tba.tba_intr_establish = tc_3000_500_intr_establish; tba.tba_intr_disestablish = tc_3000_500_intr_disestablish; + tba.tba_get_dma_tag = tc_dma_get_tag_3000_500; + + /* Do 3000/500-specific DMA setup now. */ + tc_dma_init_3000_500(tc_3000_500_nslots); break; #endif /* DEC_3000_500 */ @@ -129,14 +124,15 @@ tcasicattach(parent, self, aux) intr_setup = tc_3000_300_intr_setup; iointr = tc_3000_300_iointr; - tba.tba_busname = "tc"; tba.tba_speed = TC_SPEED_12_5_MHZ; tba.tba_nslots = tc_3000_300_nslots; tba.tba_slots = tc_3000_300_slots; tba.tba_nbuiltins = tc_3000_300_nbuiltins; tba.tba_builtins = tc_3000_300_builtins; + tba.tba_intr_evcnt = tc_3000_300_intr_evcnt; tba.tba_intr_establish = tc_3000_300_intr_establish; tba.tba_intr_disestablish = tc_3000_300_intr_disestablish; + tba.tba_get_dma_tag = tc_dma_get_tag_3000_300; break; #endif /* DEC_3000_300 */ @@ -144,14 +140,10 @@ tcasicattach(parent, self, aux) panic("tcasicattach: bad cputype"); } + tba.tba_busname = "tc"; tba.tba_memt = tc_bus_mem_init(NULL); - - /* XXX XXX BEGIN XXX XXX */ - { /* XXX */ - extern vm_offset_t alpha_XXX_dmamap_or; /* XXX */ - alpha_XXX_dmamap_or = 0; /* XXX */ - } /* XXX */ - /* XXX XXX END XXX XXX */ + + tc_dma_init(); (*intr_setup)(); set_iointr(iointr); @@ -170,3 +162,82 @@ tcasicprint(aux, pnp) printf("tc at %s", pnp); return (UNCONF); } + +#include "wsdisplay.h" + +#if NWSDISPLAY > 0 + +#include "sfb.h" +#include "sfbp.h" +#include "cfb.h" +#include "mfb.h" +#include "tfb.h" +#include "px.h" +#include "pxg.h" + +extern void sfb_cnattach(tc_addr_t); +extern void sfbp_cnattach(tc_addr_t); +extern void cfb_cnattach(tc_addr_t); +extern void mfb_cnattach(tc_addr_t); +extern void tfb_cnattach(tc_addr_t); +extern void px_cnattach(tc_addr_t); +extern void pxg_cnattach(tc_addr_t); +extern int tc_checkslot(tc_addr_t, char *); + +struct cnboards { + const char *cb_tcname; + void (*cb_cnattach)(tc_addr_t); +} static const cnboards[] = { +#if NSFB > 0 + { "PMAGB-BA", sfb_cnattach }, +#endif +#if NSFBP > 0 + { "PMAGD ", sfbp_cnattach }, +#endif +#if NCFB > 0 + { "PMAG-BA ", cfb_cnattach }, +#endif +#if NMFB > 0 + { "PMAG-AA ", mfb_cnattach }, +#endif +#if NTFB > 0 + { "PMAG-JA ", tfb_cnattach }, +#endif +#if NPX > 0 + { "PMAG-CA ", px_cnattach }, +#endif +#if NPXG > 0 + { "PMAG-DA ", pxg_cnattach }, + { "PMAG-FA ", pxg_cnattach }, + { "PMAG-FB ", pxg_cnattach }, + { "PMAGB-FA", pxg_cnattach }, + { "PMAGB-FB", pxg_cnattach }, +#endif +}; + +/* + * tc_fb_cnattach -- + * Attempt to attach the appropriate display driver to the + * output console. + */ +int +tc_fb_cnattach(tcaddr) + tc_addr_t tcaddr; +{ + char tcname[TC_ROM_LLEN]; + int i; + + if (tc_badaddr(tcaddr) || (tc_checkslot(tcaddr, tcname) == 0)) + return (EINVAL); + + for (i = 0; i < sizeof(cnboards) / sizeof(cnboards[0]); i++) + if (strncmp(tcname, cnboards[i].cb_tcname, TC_ROM_LLEN) == 0) + break; + + if (i == sizeof(cnboards) / sizeof(cnboards[0])) + return (ENXIO); + + (cnboards[i].cb_cnattach)(tcaddr); + return (0); +} +#endif /* if NWSDISPLAY > 0 */ diff --git a/sys/arch/alpha/tc/tcds.c b/sys/arch/alpha/tc/tcds.c deleted file mode 100644 index 1f3f2f815cd..00000000000 --- a/sys/arch/alpha/tc/tcds.c +++ /dev/null @@ -1,424 +0,0 @@ -/* $OpenBSD: tcds.c,v 1.9 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: tcds.c,v 1.16 1996/12/05 01:39:45 cgd Exp $ */ - -/* - * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. - * All rights reserved. - * - * Author: Keith Bostic, Chris G. Demetriou - * - * Permission to use, copy, modify and distribute this software and - * its documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/device.h> - -#include <machine/pte.h> -#include <machine/rpb.h> -#ifndef EVCNT_COUNTERS -#include <machine/intrcnt.h> -#endif - -#include <dev/tc/tcreg.h> -#include <dev/tc/tcvar.h> -#include <alpha/tc/tcdsreg.h> -#include <alpha/tc/tcdsvar.h> - -struct tcds_softc { - struct device sc_dv; - tc_addr_t sc_base; - void *sc_cookie; - - volatile u_int32_t *sc_cir; - volatile u_int32_t *sc_imer; - - struct tcds_slotconfig sc_slots[2]; -}; - -/* Definition of the driver for autoconfig. */ -#ifdef __BROKEN_INDIRECT_CONFIG -int tcdsmatch(struct device *, void *, void *); -#else -int tcdsmatch(struct device *, struct cfdata *, void *); -#endif -void tcdsattach(struct device *, struct device *, void *); -int tcdsprint(void *, const char *); - -struct cfattach tcds_ca = { - sizeof(struct tcds_softc), tcdsmatch, tcdsattach, -}; - -struct cfdriver tcds_cd = { - NULL, "tcds", DV_DULL, -}; - -/*static*/ int tcds_intr(void *); -/*static*/ int tcds_intrnull(void *); - -int -tcdsmatch(parent, cfdata, aux) - struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *cfdata; -#else - struct cfdata *cfdata; -#endif - void *aux; -{ - struct tc_attach_args *ta = aux; - extern int cputype; - - /* Make sure that we're looking for this type of device. */ - if (strncmp("PMAZ-DS ", ta->ta_modname, TC_ROM_LLEN)) - return (0); - /* PMAZ-FS? */ - - /* Check that it can actually exist. */ - if ((cputype != ST_DEC_3000_500) && (cputype != ST_DEC_3000_300)) - panic("tcdsmatch: how did we get here?"); - - return (1); -} - -void -tcdsattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct tcds_softc *sc = (struct tcds_softc *)self; - struct tc_attach_args *ta = aux; - struct tcdsdev_attach_args tcdsdev; - struct tcds_slotconfig *slotc; - int i; - extern int cputype; - - printf("\n"); - - sc->sc_base = ta->ta_addr; - sc->sc_cookie = ta->ta_cookie; - - sc->sc_cir = TCDS_REG(sc->sc_base, TCDS_CIR); - sc->sc_imer = TCDS_REG(sc->sc_base, TCDS_IMER); - - tc_intr_establish(parent, sc->sc_cookie, TC_IPL_BIO, tcds_intr, sc); - - /* - * XXX - * IMER apparently has some random (or, not so random, but still - * not useful) bits set in it when the system boots. Clear it. - */ - *sc->sc_imer = 0; - alpha_mb(); - - /* XXX Initial contents of CIR? */ - - /* - * Set up the per-slot defintions for later use. - */ - - /* fill in common information first */ - for (i = 0; i < 2; i++) { - slotc = &sc->sc_slots[i]; - - bzero(slotc, sizeof *slotc); /* clear everything */ - - slotc->sc_slot = i; - slotc->sc_tcds = sc; - slotc->sc_esp = NULL; - slotc->sc_intrhand = tcds_intrnull; - slotc->sc_intrarg = (void *)(long)i; - } - - /* information for slot 0 */ - slotc = &sc->sc_slots[0]; - slotc->sc_resetbits = TCDS_CIR_SCSI0_RESET; - slotc->sc_intrmaskbits = - TCDS_IMER_SCSI0_MASK | TCDS_IMER_SCSI0_ENB; - slotc->sc_intrbits = TCDS_CIR_SCSI0_INT; - slotc->sc_dmabits = TCDS_CIR_SCSI0_DMAENA; - slotc->sc_errorbits = 0; /* XXX */ - slotc->sc_sda = TCDS_REG(sc->sc_base, TCDS_SCSI0_DMA_ADDR); - slotc->sc_dic = TCDS_REG(sc->sc_base, TCDS_SCSI0_DMA_INTR); - slotc->sc_dud0 = TCDS_REG(sc->sc_base, TCDS_SCSI0_DMA_DUD0); - slotc->sc_dud1 = TCDS_REG(sc->sc_base, TCDS_SCSI0_DMA_DUD1); - - /* information for slot 1 */ - slotc = &sc->sc_slots[1]; - slotc->sc_resetbits = TCDS_CIR_SCSI1_RESET; - slotc->sc_intrmaskbits = - TCDS_IMER_SCSI1_MASK | TCDS_IMER_SCSI1_ENB; - slotc->sc_intrbits = TCDS_CIR_SCSI1_INT; - slotc->sc_dmabits = TCDS_CIR_SCSI1_DMAENA; - slotc->sc_errorbits = 0; /* XXX */ - slotc->sc_sda = TCDS_REG(sc->sc_base, TCDS_SCSI1_DMA_ADDR); - slotc->sc_dic = TCDS_REG(sc->sc_base, TCDS_SCSI1_DMA_INTR); - slotc->sc_dud0 = TCDS_REG(sc->sc_base, TCDS_SCSI1_DMA_DUD0); - slotc->sc_dud1 = TCDS_REG(sc->sc_base, TCDS_SCSI1_DMA_DUD1); - - /* find the hardware attached to the TCDS ASIC */ - strncpy(tcdsdev.tcdsda_modname, "PMAZ-AA ", TC_ROM_LLEN); - tcdsdev.tcdsda_slot = 0; - tcdsdev.tcdsda_offset = 0; - tcdsdev.tcdsda_addr = (tc_addr_t) - TC_DENSE_TO_SPARSE(sc->sc_base + TCDS_SCSI0_OFFSET); - tcdsdev.tcdsda_cookie = (void *)(long)0; - tcdsdev.tcdsda_sc = &sc->sc_slots[0]; - tcdsdev.tcdsda_id = 7; /* XXX */ - tcdsdev.tcdsda_freq = 25000000; /* XXX */ - - tcds_scsi_reset(tcdsdev.tcdsda_sc); - - config_found(self, &tcdsdev, tcdsprint); - - /* the second SCSI chip isn't present on the 3000/300 series. */ - if (cputype != ST_DEC_3000_300) { - strncpy(tcdsdev.tcdsda_modname, "PMAZ-AA ", - TC_ROM_LLEN); - tcdsdev.tcdsda_slot = 1; - tcdsdev.tcdsda_offset = 0; - tcdsdev.tcdsda_addr = (tc_addr_t) - TC_DENSE_TO_SPARSE(sc->sc_base + TCDS_SCSI1_OFFSET); - tcdsdev.tcdsda_cookie = (void *)(long)1; - tcdsdev.tcdsda_sc = &sc->sc_slots[1]; - tcdsdev.tcdsda_id = 7; /* XXX */ - tcdsdev.tcdsda_freq = 25000000; /* XXX */ - - tcds_scsi_reset(tcdsdev.tcdsda_sc); - - config_found(self, &tcdsdev, tcdsprint); - } -} - -int -tcdsprint(aux, pnp) - void *aux; - const char *pnp; -{ - struct tc_attach_args *ta = aux; - - if (pnp) - printf("%s at %s", ta->ta_modname, pnp); - printf(" slot %d", ta->ta_slot); - return (UNCONF); -} - -void -tcds_intr_establish(tcds, cookie, level, func, arg) - struct device *tcds; - void *cookie, *arg; - tc_intrlevel_t level; - int (*func)(void *); -{ - struct tcds_softc *sc = (struct tcds_softc *)tcds; - u_long slot; - - slot = (u_long)cookie; -#ifdef DIAGNOSTIC - /* XXX check cookie. */ -#endif - - if (sc->sc_slots[slot].sc_intrhand != tcds_intrnull) - panic("tcds_intr_establish: cookie %d twice", slot); - - sc->sc_slots[slot].sc_intrhand = func; - sc->sc_slots[slot].sc_intrarg = arg; - tcds_scsi_reset(&sc->sc_slots[slot]); -} - -void -tcds_intr_disestablish(tcds, cookie) - struct device *tcds; - void *cookie; -{ - struct tcds_softc *sc = (struct tcds_softc *)tcds; - u_long slot; - - slot = (u_long)cookie; -#ifdef DIAGNOSTIC - /* XXX check cookie. */ -#endif - - if (sc->sc_slots[slot].sc_intrhand == tcds_intrnull) - panic("tcds_intr_disestablish: cookie %d missing intr", - slot); - - sc->sc_slots[slot].sc_intrhand = tcds_intrnull; - sc->sc_slots[slot].sc_intrarg = (void *)slot; - - tcds_dma_enable(&sc->sc_slots[slot], 0); - tcds_scsi_enable(&sc->sc_slots[slot], 0); -} - -int -tcds_intrnull(val) - void *val; -{ - - panic("tcds_intrnull: uncaught TCDS intr for cookie %ld", - (u_long)val); -} - -void -tcds_scsi_reset(sc) - struct tcds_slotconfig *sc; -{ - - tcds_dma_enable(sc, 0); - tcds_scsi_enable(sc, 0); - - TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_resetbits); - alpha_mb(); - DELAY(1); - TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_resetbits); - alpha_mb(); - - tcds_scsi_enable(sc, 1); - tcds_dma_enable(sc, 1); -} - -void -tcds_scsi_enable(sc, on) - struct tcds_slotconfig *sc; - int on; -{ - - if (on) - *sc->sc_tcds->sc_imer |= sc->sc_intrmaskbits; - else - *sc->sc_tcds->sc_imer &= ~sc->sc_intrmaskbits; - alpha_mb(); -} - -void -tcds_dma_enable(sc, on) - struct tcds_slotconfig *sc; - int on; -{ - - /* XXX Clear/set IOSLOT/PBS bits. */ - if (on) - TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_dmabits); - else - TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_dmabits); - alpha_mb(); -} - -int -tcds_scsi_isintr(sc, clear) - struct tcds_slotconfig *sc; - int clear; -{ - - if ((*sc->sc_tcds->sc_cir & sc->sc_intrbits) != 0) { - if (clear) { - TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_intrbits); - alpha_mb(); - } - return (1); - } else - return (0); -} - -int -tcds_scsi_iserr(sc) - struct tcds_slotconfig *sc; -{ - - return ((*sc->sc_tcds->sc_cir & sc->sc_errorbits) != 0); -} - -int -tcds_intr(val) - void *val; -{ - struct tcds_softc *sc; - u_int32_t ir; - - sc = val; - - /* - * XXX - * Copy and clear (gag!) the interrupts. - */ - ir = *sc->sc_cir; - alpha_mb(); - TCDS_CIR_CLR(*sc->sc_cir, TCDS_CIR_ALLINTR); - alpha_mb(); - tc_syncbus(); - alpha_mb(); - -#ifdef EVCNT_COUNTERS - /* No interrupt counting via evcnt counters */ - XXX BREAK HERE XXX -#else -#define INCRINTRCNT(slot) intrcnt[INTRCNT_TCDS + slot]++ -#endif - -#define CHECKINTR(slot) \ - if (ir & sc->sc_slots[slot].sc_intrbits) { \ - INCRINTRCNT(slot); \ - (void)(*sc->sc_slots[slot].sc_intrhand) \ - (sc->sc_slots[slot].sc_intrarg); \ - } - CHECKINTR(0); - CHECKINTR(1); -#undef CHECKINTR - -#ifdef DIAGNOSTIC - /* - * Interrupts not currently handled, but would like to know if they - * occur. - * - * XXX - * Don't know if we have to set the interrupt mask and enable bits - * in the IMER to allow some of them to happen? - */ -#define PRINTINTR(msg, bits) \ - if (ir & bits) \ - printf(msg); - PRINTINTR("SCSI0 DREQ interrupt.\n", TCDS_CIR_SCSI0_DREQ); - PRINTINTR("SCSI1 DREQ interrupt.\n", TCDS_CIR_SCSI1_DREQ); - PRINTINTR("SCSI0 prefetch interrupt.\n", TCDS_CIR_SCSI0_PREFETCH); - PRINTINTR("SCSI1 prefetch interrupt.\n", TCDS_CIR_SCSI1_PREFETCH); - PRINTINTR("SCSI0 DMA error.\n", TCDS_CIR_SCSI0_DMA); - PRINTINTR("SCSI1 DMA error.\n", TCDS_CIR_SCSI1_DMA); - PRINTINTR("SCSI0 DB parity error.\n", TCDS_CIR_SCSI0_DB); - PRINTINTR("SCSI1 DB parity error.\n", TCDS_CIR_SCSI1_DB); - PRINTINTR("SCSI0 DMA buffer parity error.\n", TCDS_CIR_SCSI0_DMAB_PAR); - PRINTINTR("SCSI1 DMA buffer parity error.\n", TCDS_CIR_SCSI1_DMAB_PAR); - PRINTINTR("SCSI0 DMA read parity error.\n", TCDS_CIR_SCSI0_DMAR_PAR); - PRINTINTR("SCSI1 DMA read parity error.\n", TCDS_CIR_SCSI1_DMAR_PAR); - PRINTINTR("TC write parity error.\n", TCDS_CIR_TCIOW_PAR); - PRINTINTR("TC I/O address parity error.\n", TCDS_CIR_TCIOA_PAR); -#undef PRINTINTR -#endif - - /* - * XXX - * The MACH source had this, with the comment: - * This is wrong, but machine keeps dying. - */ - DELAY(1); - - return (1); -} diff --git a/sys/arch/alpha/tc/tcds_dma.c b/sys/arch/alpha/tc/tcds_dma.c deleted file mode 100644 index 9453aeab1d3..00000000000 --- a/sys/arch/alpha/tc/tcds_dma.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $OpenBSD: tcds_dma.c,v 1.7 2000/11/08 16:01:26 art Exp $ */ -/* $NetBSD: tcds_dma.c,v 1.15 1996/12/04 22:35:08 mycroft Exp $ */ - -/* - * Copyright (c) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Peter Galbavy. - * 4. 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. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/device.h> -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/proc.h> -#include <sys/user.h> - -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> - -#include <dev/tc/tcvar.h> -#include <alpha/tc/tcdsreg.h> -#include <alpha/tc/tcdsvar.h> -#include <alpha/tc/ascreg.h> -#include <alpha/tc/ascvar.h> - -void -tcds_dma_reset(sc) - struct tcds_slotconfig *sc; -{ - /* TCDS SCSI disable/reset/enable. */ - tcds_scsi_reset(sc); /* XXX */ - - sc->sc_active = 0; /* and of course we aren't */ -} - -int -tcds_dma_isintr(sc) - struct tcds_slotconfig *sc; -{ - int x; - - x = tcds_scsi_isintr(sc, 1); - - /* XXX */ - return x; -} - -/* - * Pseudo (chained) interrupt from the esp driver to kick the - * current running DMA transfer. I am replying on espintr() to - * pickup and clean errors for now - * - * return 1 if it was a DMA continue. - */ -int -tcds_dma_intr(sc) - struct tcds_slotconfig *sc; -{ - u_int32_t dud; - int trans = 0, resid = 0; - u_int32_t *addr, dudmask; - u_char tcl, tcm, tch; - - ESP_DMA(("tcds_dma %d: intr", sc->sc_slot)); - - if (tcds_scsi_iserr(sc)) - return (0); - - /* This is an "assertion" :) */ - if (sc->sc_active == 0) - panic("dmaintr: DMA wasn't active"); - - /* DMA has stopped */ - tcds_dma_enable(sc, 0); - sc->sc_active = 0; - - if (sc->sc_dmasize == 0) { - /* A "Transfer Pad" operation completed */ - tcl = ESP_READ_REG(sc->sc_esp, ESP_TCL); - tcm = ESP_READ_REG(sc->sc_esp, ESP_TCM); - ESP_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n", - tcl | (tcm << 8), tcl, tcm)); - return 0; - } - - if (!sc->sc_iswrite && - (resid = (ESP_READ_REG(sc->sc_esp, ESP_FFLAG) & ESPFIFO_FF)) != 0) { - ESPCMD(sc->sc_esp, ESPCMD_FLUSH); - DELAY(1); - } - - resid += (tcl = ESP_READ_REG(sc->sc_esp, ESP_TCL)); - resid += (tcm = ESP_READ_REG(sc->sc_esp, ESP_TCM)) << 8; - if (sc->sc_esp->sc_rev == ESP200) - resid += (tch = ESP_READ_REG(sc->sc_esp, ESP_TCH)) << 16; - else - tch = 0; - - if (resid == 0 && (sc->sc_esp->sc_rev <= ESP100A) && - (sc->sc_esp->sc_espstat & ESPSTAT_TC) == 0) - resid = 65536; - - trans = sc->sc_dmasize - resid; - if (trans < 0) { /* transferred < 0 ? */ - printf("tcds_dma %d: xfer (%d) > req (%ld)\n", - sc->sc_slot, trans, sc->sc_dmasize); - trans = sc->sc_dmasize; - } - - ESP_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", - tcl, tcm, tch, trans, resid)); - - /* - * Clean up unaligned DMAs into main memory. - */ - if (sc->sc_iswrite) { - /* Handle unaligned starting address, length. */ - dud = *sc->sc_dud0; - if ((dud & TCDS_DUD0_VALIDBITS) != 0) { - addr = (u_int32_t *) - ((vm_offset_t)sc->sc_dmaaddr & ~0x3); - dudmask = 0; - if (dud & TCDS_DUD0_VALID00) - panic("tcds_dma: dud0 byte 0 valid"); - if (dud & TCDS_DUD0_VALID01) - dudmask |= TCDS_DUD_BYTE01; - if (dud & TCDS_DUD0_VALID10) - dudmask |= TCDS_DUD_BYTE10; -#ifdef DIAGNOSTIC - if (dud & TCDS_DUD0_VALID11) - dudmask |= TCDS_DUD_BYTE11; -#endif - ESP_DMA(("dud0 at 0x%p dudmask 0x%x\n", - addr, dudmask)); - addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr); - *addr = (*addr & ~dudmask) | (dud & dudmask); - } - dud = *sc->sc_dud1; - if ((dud & TCDS_DUD1_VALIDBITS) != 0) { - - addr = (u_int32_t *) - ((vm_offset_t)*sc->sc_sda << 2); - dudmask = 0; - if (dud & TCDS_DUD1_VALID00) - dudmask |= TCDS_DUD_BYTE00; - if (dud & TCDS_DUD1_VALID01) - dudmask |= TCDS_DUD_BYTE01; - if (dud & TCDS_DUD1_VALID10) - dudmask |= TCDS_DUD_BYTE10; -#ifdef DIAGNOSTIC - if (dud & TCDS_DUD1_VALID11) - panic("tcds_dma: dud1 byte 3 valid"); -#endif - ESP_DMA(("dud1 at 0x%p dudmask 0x%x\n", - addr, dudmask)); - addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr); - *addr = (*addr & ~dudmask) | (dud & dudmask); - } - /* XXX deal with saved residual byte? */ - } - - *sc->sc_dmalen -= trans; - *sc->sc_dmaaddr += trans; - -#if 0 /* this is not normal operation just yet */ - if (*sc->sc_dmalen == 0 || - sc->sc_esp->sc_phase != sc->sc_esp->sc_prevphase) - return 0; - - /* and again */ - dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, sc->sc_iswrite); - return 1; -#endif - return 0; -} - -#define DMAMAX(a) (0x02000 - ((a) & 0x1fff)) - -/* - * start a dma transfer or keep it going - */ -int -tcds_dma_setup(sc, addr, len, datain, dmasize) - struct tcds_slotconfig *sc; - caddr_t *addr; - size_t *len, *dmasize; - int datain; /* DMA into main memory */ -{ - u_int32_t dic; - size_t size; - - sc->sc_dmaaddr = addr; - sc->sc_dmalen = len; - sc->sc_iswrite = datain; - - ESP_DMA(("tcds_dma %d: start %ld@%p,%d\n", sc->sc_slot, *sc->sc_dmalen, *sc->sc_dmaaddr, sc->sc_iswrite)); - - /* - * the rules say we cannot transfer more than the limit - * of this DMA chip (64k) and we cannot cross a 8k boundary. - */ - - size = min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); - *dmasize = sc->sc_dmasize = size; - - ESP_DMA(("dma_start: dmasize = %ld\n", sc->sc_dmasize)); - - /* Load address, set/clear unaligned transfer and read/write bits. */ - /* XXX PICK AN ADDRESS TYPE, AND STICK TO IT! */ - if ((u_long)*addr > VM_MIN_KERNEL_ADDRESS) { - *sc->sc_sda = vtophys((u_long)*addr) >> 2; - } else { - *sc->sc_sda = ALPHA_K0SEG_TO_PHYS((u_long)*addr) >> 2; - } - alpha_mb(); - dic = *sc->sc_dic; - dic &= ~TCDS_DIC_ADDRMASK; - dic |= (vm_offset_t)*addr & TCDS_DIC_ADDRMASK; - if (datain) - dic |= TCDS_DIC_WRITE; - else - dic &= ~TCDS_DIC_WRITE; - *sc->sc_dic = dic; - alpha_mb(); - - return (0); -} - -void -tcds_dma_go(sc) - struct tcds_slotconfig *sc; -{ - - /* mark unit as DMA-active */ - sc->sc_active = 1; - - /* Start DMA */ - tcds_dma_enable(sc, 1); -} - -int -tcds_dma_isactive(sc) - struct tcds_slotconfig *sc; -{ - - return (sc->sc_active); -} diff --git a/sys/dev/dec/clockvar.h b/sys/dev/dec/clockvar.h new file mode 100644 index 00000000000..b314d74fe45 --- /dev/null +++ b/sys/dev/dec/clockvar.h @@ -0,0 +1,63 @@ +/* $OpenBSD: clockvar.h,v 1.1 2002/05/02 22:56:02 miod Exp $ */ +/* $NetBSD: clockvar.h,v 1.4 1997/06/22 08:02:18 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Definitions for cpu-independent clock handling for the alpha and pmax. + */ + +/* + * clocktime structure: + * + * structure passed to TOY clocks when setting them. broken out this + * way, so that the time_t -> field conversion can be shared. + */ +struct clocktime { + int year; /* year - 1900 */ + int mon; /* month (1 - 12) */ + int day; /* day (1 - 31) */ + int hour; /* hour (0 - 23) */ + int min; /* minute (0 - 59) */ + int sec; /* second (0 - 59) */ + int dow; /* day of week (0 - 6; 0 = Sunday) */ +}; + +/* + * clockfns structure: + * + * function switch used by chip-independent clock code, to access + * chip-dependent routines. + */ +struct clockfns { + void (*cf_init)(struct device *); + void (*cf_get)(struct device *, time_t, struct clocktime *); + void (*cf_set)(struct device *, struct clocktime *); +}; + +void clockattach(struct device *, const struct clockfns *); diff --git a/sys/dev/dec/files.dec b/sys/dev/dec/files.dec new file mode 100644 index 00000000000..16b94890e61 --- /dev/null +++ b/sys/dev/dec/files.dec @@ -0,0 +1,13 @@ +# $OpenBSD: files.dec,v 1.1 2002/05/02 22:56:02 miod Exp $ +# $NetBSD: files.dec,v 1.7 2002/03/13 15:18:22 ad Exp $ +# +# Config file and device description for machine-independent +# code for devices for Digital Equipment Corp. systems. +# Included by ports that need it. + +# Attribute for DEC lance padded-DMA copy functions. Lance attachments +# which need it should specify the le_de_subr attribute. +define le_dec_subr + +# DMA copy functions. Lance attachments qhich Decices +file dev/dec/if_le_dec.c le_dec_subr diff --git a/sys/dev/tc/if_le_dec.c b/sys/dev/dec/if_le_dec.c index 68a96fbeb6f..67e1720f20c 100644 --- a/sys/dev/tc/if_le_dec.c +++ b/sys/dev/dec/if_le_dec.c @@ -1,7 +1,8 @@ -/* $OpenBSD: if_le_dec.c,v 1.5 2002/03/14 01:27:03 millert Exp $ */ -/* $NetBSD: if_le_dec.c,v 1.3 1996/10/13 01:38:38 christos Exp $ */ +/* $OpenBSD: if_le_dec.c,v 1.1 2002/05/02 22:56:02 miod Exp $ */ +/* $NetBSD: if_le_dec.c,v 1.12 2001/11/13 12:49:45 lukem Exp $ */ /*- + * Copyright (c) 1997 Jonathan Stone. All rights reserved. * Copyright (c) 1995 Charles M. Hannum. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -40,8 +41,6 @@ * @(#)if_le.c 8.2 (Berkeley) 11/16/93 */ -#include "bpfilter.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> @@ -63,13 +62,15 @@ #include <dev/tc/if_levar.h> #include <dev/tc/tcvar.h> +#include <machine/bus.h> + /* access LANCE registers */ void le_dec_writereg(volatile u_short *regptr, u_short val); #define LERDWR(cntl, src, dst) { (dst) = (src); tc_mb(); } #define LEWREG(src, dst) le_dec_writereg(&(dst), (src)) -hide void le_dec_wrcsr(struct am7990_softc *, u_int16_t, u_int16_t); -hide u_int16_t le_dec_rdcsr(struct am7990_softc *, u_int16_t); +void le_dec_wrcsr(struct am7990_softc *, u_int16_t, u_int16_t); +u_int16_t le_dec_rdcsr(struct am7990_softc *, u_int16_t); void dec_le_common_attach(sc, eap) @@ -97,7 +98,7 @@ dec_le_common_attach(sc, eap) am7990_config(sc); } -hide void +void le_dec_wrcsr(sc, port, val) struct am7990_softc *sc; u_int16_t port, val; @@ -108,7 +109,7 @@ le_dec_wrcsr(sc, port, val) LERDWR(port, val, ler1->ler1_rdp); } -hide u_int16_t +u_int16_t le_dec_rdcsr(sc, port) struct am7990_softc *sc; u_int16_t port; @@ -152,7 +153,7 @@ le_dec_writereg(regptr, val) * 3 ways: * - contiguous (for the 3max and turbochannel option card) * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) - * spaces (for the pmax) + * spaces (for the pmax, vax 3400, and ioasic LANCE descriptors) * - gap16, which means 16bytes interspersed with 16byte spaces * for buffers which must begin on a 32byte boundary (for 3min, maxine, * and alpha) diff --git a/sys/dev/dec/mcclockvar.h b/sys/dev/dec/mcclockvar.h new file mode 100644 index 00000000000..c12584c6bdb --- /dev/null +++ b/sys/dev/dec/mcclockvar.h @@ -0,0 +1,42 @@ +/* $OpenBSD: mcclockvar.h,v 1.1 2002/05/02 22:56:02 miod Exp $ */ +/* $NetBSD: mcclockvar.h,v 1.4 1997/06/22 08:02:19 jonathan Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +struct mcclock_softc { + struct device sc_dev; + const struct mcclock_busfns *sc_busfns; +}; + +struct mcclock_busfns { + void (*mc_bf_write)(struct mcclock_softc *, u_int, u_int); + u_int (*mc_bf_read)(struct mcclock_softc *, u_int); +}; + +void mcclock_attach(struct mcclock_softc *, + const struct mcclock_busfns *); diff --git a/sys/dev/tc/asc.c b/sys/dev/tc/asc.c new file mode 100644 index 00000000000..b9fd2d5e692 --- /dev/null +++ b/sys/dev/tc/asc.c @@ -0,0 +1,127 @@ +/* $OpenBSD: asc.c,v 1.21 2002/05/02 22:56:06 miod Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Peter Galbavy. + * 4. 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <dev/ic/ncr53c9xreg.h> +#include <dev/ic/ncr53c9xvar.h> +#include <dev/tc/ascvar.h> + +struct cfdriver asc_cd = { + NULL, "asc", DV_DULL, +}; + +struct scsi_adapter asc_switch = { + ncr53c9x_scsi_cmd, + minphys, /* no max at this level; handled by DMA code */ + NULL, + NULL, +}; + +struct scsi_device asc_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default `done' routine */ +}; + +/* + * Glue functions + */ +u_char +asc_read_reg(sc, reg) + struct ncr53c9x_softc *sc; + int reg; +{ + struct asc_softc *asc = (struct asc_softc *)sc; + u_char v; + + v = bus_space_read_4(asc->sc_bst, asc->sc_bsh, + reg * sizeof(u_int32_t)) & 0xff; + + return (v); +} + +void +asc_write_reg(sc, reg, val) + struct ncr53c9x_softc *sc; + int reg; + u_char val; +{ + struct asc_softc *asc = (struct asc_softc *)sc; + + bus_space_write_4(asc->sc_bst, asc->sc_bsh, + reg * sizeof(u_int32_t), val); +} + diff --git a/sys/dev/tc/asc_tc.c b/sys/dev/tc/asc_tc.c new file mode 100644 index 00000000000..df417243dba --- /dev/null +++ b/sys/dev/tc/asc_tc.c @@ -0,0 +1,330 @@ +/* $OpenBSD: asc_tc.c,v 1.6 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: asc_tc.c,v 1.19 2001/11/15 09:48:19 lukem Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <scsi/scsi_message.h> + +#include <machine/bus.h> + +#include <dev/ic/ncr53c9xreg.h> +#include <dev/ic/ncr53c9xvar.h> +#include <dev/tc/ascvar.h> + +#include <dev/tc/tcvar.h> + +struct asc_tc_softc { + struct asc_softc asc; + + /* XXX XXX XXX */ + caddr_t sc_base, sc_bounce, sc_target; +}; + +int asc_tc_match(struct device *, void *, void *); +void asc_tc_attach(struct device *, struct device *, void *); + +struct cfattach asc_tc_ca = { + sizeof(struct asc_tc_softc), asc_tc_match, asc_tc_attach +}; + +extern struct scsi_adapter asc_switch; +extern struct scsi_device asc_dev; + +int asc_dma_isintr(struct ncr53c9x_softc *); +void asc_tc_reset(struct ncr53c9x_softc *); +int asc_tc_intr(struct ncr53c9x_softc *); +int asc_tc_setup(struct ncr53c9x_softc *, caddr_t *, + size_t *, int, size_t *); +void asc_tc_go(struct ncr53c9x_softc *); +void asc_tc_stop(struct ncr53c9x_softc *); +int asc_dma_isactive(struct ncr53c9x_softc *); +void asc_clear_latched_intr(struct ncr53c9x_softc *); + +struct ncr53c9x_glue asc_tc_glue = { + asc_read_reg, + asc_write_reg, + asc_dma_isintr, + asc_tc_reset, + asc_tc_intr, + asc_tc_setup, + asc_tc_go, + asc_tc_stop, + asc_dma_isactive, + asc_clear_latched_intr, +}; + +/* + * Parameters specific to PMAZ-A TC option card. + */ +#define PMAZ_OFFSET_53C94 0x0 /* from module base */ +#define PMAZ_OFFSET_DMAR 0x40000 /* DMA Address Register */ +#define PMAZ_OFFSET_RAM 0x80000 /* 128KB SRAM buffer */ +#define PMAZ_OFFSET_ROM 0xc0000 /* diagnostic ROM */ + +#define PMAZ_RAM_SIZE 0x20000 /* 128k (32k*32) */ +#define PER_TGT_DMA_SIZE ((PMAZ_RAM_SIZE/7) & ~(sizeof(int)-1)) + +#define PMAZ_DMAR_WRITE 0x80000000 /* DMA direction bit */ +#define PMAZ_DMAR_MASK 0x1ffff /* 17 bits, 128k */ +#define PMAZ_DMA_ADDR(x) ((unsigned long)(x) & PMAZ_DMAR_MASK) + +int +asc_tc_match(parent, cfdata, aux) + struct device *parent; + void *cfdata, *aux; +{ + struct tc_attach_args *d = aux; + + if (strncmp("PMAZ-AA ", d->ta_modname, TC_ROM_LLEN)) + return (0); + + return (1); +} + +void +asc_tc_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct tc_attach_args *ta = aux; + struct asc_tc_softc *asc = (struct asc_tc_softc *)self; + struct ncr53c9x_softc *sc = &asc->asc.sc_ncr53c9x; + + /* + * Set up glue for MI code early; we use some of it here. + */ + sc->sc_glue = &asc_tc_glue; + asc->asc.sc_bst = ta->ta_memt; + asc->asc.sc_dmat = ta->ta_dmat; + if (bus_space_map(asc->asc.sc_bst, ta->ta_addr, + PMAZ_OFFSET_RAM + PMAZ_RAM_SIZE, 0, &asc->asc.sc_bsh)) { + printf("%s: unable to map device\n", sc->sc_dev.dv_xname); + return; + } + asc->sc_base = (caddr_t)ta->ta_addr; /* XXX XXX XXX */ + + tc_intr_establish(parent, ta->ta_cookie, IPL_BIO, ncr53c9x_intr, sc); + + sc->sc_id = 7; + sc->sc_freq = (ta->ta_busspeed) ? 25000000 : 12500000; + + /* gimme Mhz */ + sc->sc_freq /= 1000000; + + /* + * XXX More of this should be in ncr53c9x_attach(), but + * XXX should we really poke around the chip that much in + * XXX the MI code? Think about this more... + */ + + /* + * Set up static configuration info. + */ + sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; + sc->sc_cfg2 = NCRCFG2_SCSI2; + sc->sc_cfg3 = 0; + sc->sc_rev = NCR_VARIANT_NCR53C94; + + /* + * XXX minsync and maxxfer _should_ be set up in MI code, + * XXX but it appears to have some dependency on what sort + * XXX of DMA we're hooked up to, etc. + */ + + /* + * This is the value used to start sync negotiations + * Note that the NCR register "SYNCTP" is programmed + * in "clocks per byte", and has a minimum value of 4. + * The SCSI period used in negotiation is one-fourth + * of the time (in nanoseconds) needed to transfer one byte. + * Since the chip's clock is given in MHz, we have the following + * formula: 4 * period = (1000 / freq) * 4 + */ + sc->sc_minsync = (1000 / sc->sc_freq) * 5 / 4; + + sc->sc_maxxfer = 64 * 1024; + + /* Do the common parts of attachment. */ + ncr53c9x_attach(sc, &asc_switch, &asc_dev); +} + +void +asc_tc_reset(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + + asc->asc.sc_flags &= ~(ASC_DMAACTIVE|ASC_MAPLOADED); +} + +int +asc_tc_intr(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + int trans, resid; + + resid = 0; + if ((asc->asc.sc_flags & ASC_ISPULLUP) == 0 && + (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { + NCR_DMA(("asc_tc_intr: empty FIFO of %d ", resid)); + DELAY(1); + } + + resid += NCR_READ_REG(sc, NCR_TCL); + resid += NCR_READ_REG(sc, NCR_TCM) << 8; + + trans = asc->asc.sc_dmasize - resid; + + if (asc->asc.sc_flags & ASC_ISPULLUP) + memcpy(asc->sc_target, asc->sc_bounce, trans); + *asc->asc.sc_dmalen -= trans; + *asc->asc.sc_dmaaddr += trans; + asc->asc.sc_flags &= ~(ASC_DMAACTIVE|ASC_MAPLOADED); + + return (0); +} + +int +asc_tc_setup(sc, addr, len, datain, dmasize) + struct ncr53c9x_softc *sc; + caddr_t *addr; + size_t *len; + int datain; + size_t *dmasize; +{ + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + u_int32_t tc_dmar; + size_t size; + + asc->asc.sc_dmaaddr = addr; + asc->asc.sc_dmalen = len; + asc->asc.sc_flags = (datain) ? ASC_ISPULLUP : 0; + + NCR_DMA(("asc_tc_setup: start %ld@%p, %s\n", (long)*asc->asc.sc_dmalen, + *asc->asc.sc_dmaaddr, datain ? "IN" : "OUT")); + + size = *dmasize; + if (size > PER_TGT_DMA_SIZE) + size = PER_TGT_DMA_SIZE; + *dmasize = asc->asc.sc_dmasize = size; + + NCR_DMA(("asc_tc_setup: dmasize = %ld\n", (long)asc->asc.sc_dmasize)); + + asc->sc_bounce = asc->sc_base + PMAZ_OFFSET_RAM; + asc->sc_bounce += PER_TGT_DMA_SIZE * + sc->sc_nexus->xs->sc_link->target; + asc->sc_target = *addr; + + if ((asc->asc.sc_flags & ASC_ISPULLUP) == 0) + memcpy(asc->sc_bounce, asc->sc_target, size); + +#if 1 + if (asc->asc.sc_flags & ASC_ISPULLUP) + tc_dmar = PMAZ_DMA_ADDR(asc->sc_bounce); + else + tc_dmar = PMAZ_DMAR_WRITE | PMAZ_DMA_ADDR(asc->sc_bounce); + bus_space_write_4(asc->asc.sc_bst, asc->asc.sc_bsh, PMAZ_OFFSET_DMAR, + tc_dmar); + asc->asc.sc_flags |= ASC_MAPLOADED|ASC_DMAACTIVE; +#endif + return (0); +} + +void +asc_tc_go(sc) + struct ncr53c9x_softc *sc; +{ +#if 0 + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + u_int32_t tc_dmar; + + if (asc->asc.sc_flags & ASC_ISPULLUP) + tc_dmar = PMAZ_DMA_ADDR(asc->sc_bounce); + else + tc_dmar = PMAZ_DMAR_WRITE | PMAZ_DMA_ADDR(asc->sc_bounce); + bus_space_write_4(asc->asc.sc_bst, asc->asc.sc_bsh, PMAZ_OFFSET_DMAR, + tc_dmar); + asc->asc.sc_flags |= ASC_DMAACTIVE; +#endif +} + +/* NEVER CALLED BY MI 53C9x ENGINE INDEED */ +void +asc_tc_stop(sc) + struct ncr53c9x_softc *sc; +{ +#if 0 + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + + if (asc->asc.sc_flags & ASC_ISPULLUP) + memcpy(asc->sc_target, asc->sc_bounce, asc->sc_dmasize); + asc->asc.sc_flags &= ~ASC_DMAACTIVE; +#endif +} + +/* + * Glue functions. + */ +int +asc_dma_isintr(sc) + struct ncr53c9x_softc *sc; +{ + return !!(NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT); +} + +int +asc_dma_isactive(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tc_softc *asc = (struct asc_tc_softc *)sc; + + return !!(asc->asc.sc_flags & ASC_DMAACTIVE); +} + +void +asc_clear_latched_intr(sc) + struct ncr53c9x_softc *sc; +{ +} diff --git a/sys/dev/tc/asc_tcds.c b/sys/dev/tc/asc_tcds.c new file mode 100644 index 00000000000..aecbef78109 --- /dev/null +++ b/sys/dev/tc/asc_tcds.c @@ -0,0 +1,495 @@ +/* $OpenBSD: asc_tcds.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: asc_tcds.c,v 1.5 2001/11/15 09:48:19 lukem Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Peter Galbavy. + * 4. 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <dev/ic/ncr53c9xreg.h> +#include <dev/ic/ncr53c9xvar.h> +#include <dev/tc/ascvar.h> + +#include <machine/bus.h> + +#include <dev/tc/tcvar.h> +#include <dev/tc/tcdsreg.h> +#include <dev/tc/tcdsvar.h> + +struct asc_tcds_softc { + struct asc_softc asc; + + struct tcds_slotconfig *sc_tcds; +}; + +int asc_tcds_match (struct device *, void *, void *); +void asc_tcds_attach(struct device *, struct device *, void *); + +/* Linkup to the rest of the kernel */ +struct cfattach asc_tcds_ca = { + sizeof(struct asc_tcds_softc), asc_tcds_match, asc_tcds_attach +}; + +/* + * Functions and the switch for the MI code. + */ +int tcds_dma_isintr(struct ncr53c9x_softc *); +void tcds_dma_reset(struct ncr53c9x_softc *); +int tcds_dma_intr(struct ncr53c9x_softc *); +int tcds_dma_setup(struct ncr53c9x_softc *, caddr_t *, + size_t *, int, size_t *); +void tcds_dma_go(struct ncr53c9x_softc *); +void tcds_dma_stop(struct ncr53c9x_softc *); +int tcds_dma_isactive(struct ncr53c9x_softc *); +void tcds_clear_latched_intr(struct ncr53c9x_softc *); + +struct ncr53c9x_glue asc_tcds_glue = { + asc_read_reg, + asc_write_reg, + tcds_dma_isintr, + tcds_dma_reset, + tcds_dma_intr, + tcds_dma_setup, + tcds_dma_go, + tcds_dma_stop, + tcds_dma_isactive, + tcds_clear_latched_intr, +}; + +extern struct scsi_adapter asc_switch; +extern struct scsi_device asc_dev; + +int +asc_tcds_match(parent, cf, aux) + struct device *parent; + void *cf, *aux; +{ + + /* We always exist. */ + return 1; +} + +#define DMAMAX(a) (NBPG - ((a) & (NBPG - 1))) + +/* + * Attach this instance, and then all the sub-devices + */ +void +asc_tcds_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct tcdsdev_attach_args *tcdsdev = aux; + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)self; + struct ncr53c9x_softc *sc = &asc->asc.sc_ncr53c9x; + int error; + + /* + * Set up glue for MI code early; we use some of it here. + */ + sc->sc_glue = &asc_tcds_glue; + + asc->asc.sc_bst = tcdsdev->tcdsda_bst; + asc->asc.sc_bsh = tcdsdev->tcdsda_bsh; + asc->sc_tcds = tcdsdev->tcdsda_sc; + + /* + * The TCDS ASIC cannot DMA across 8k boundaries, and this + * driver is written such that each DMA segment gets a new + * call to tcds_dma_setup(). Thus, the DMA map only needs + * to support 8k transfers. + */ + asc->asc.sc_dmat = tcdsdev->tcdsda_dmat; + if ((error = bus_dmamap_create(asc->asc.sc_dmat, NBPG, 1, NBPG, + NBPG, BUS_DMA_NOWAIT, &asc->asc.sc_dmamap)) < 0) { + printf("failed to create dma map, error = %d\n", error); + } + + sc->sc_id = tcdsdev->tcdsda_id; + sc->sc_freq = tcdsdev->tcdsda_freq; + + /* gimme Mhz */ + sc->sc_freq /= 1000000; + + tcds_intr_establish(parent, tcdsdev->tcdsda_chip, ncr53c9x_intr, sc); + + /* + * XXX More of this should be in ncr53c9x_attach(), but + * XXX should we really poke around the chip that much in + * XXX the MI code? Think about this more... + */ + + /* + * Set up static configuration info. + */ + sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; + sc->sc_cfg2 = NCRCFG2_SCSI2; + sc->sc_cfg3 = NCRCFG3_CDB; + if (sc->sc_freq > 25) + sc->sc_cfg3 |= NCRF9XCFG3_FCLK; + sc->sc_rev = tcdsdev->tcdsda_variant; + if (tcdsdev->tcdsda_fast) { + sc->sc_features |= NCR_F_FASTSCSI; + sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; + } + + /* + * XXX minsync and maxxfer _should_ be set up in MI code, + * XXX but it appears to have some dependency on what sort + * XXX of DMA we're hooked up to, etc. + */ + + /* + * This is the value used to start sync negotiations + * Note that the NCR register "SYNCTP" is programmed + * in "clocks per byte", and has a minimum value of 4. + * The SCSI period used in negotiation is one-fourth + * of the time (in nanoseconds) needed to transfer one byte. + * Since the chip's clock is given in MHz, we have the following + * formula: 4 * period = (1000 / freq) * 4 + */ + sc->sc_minsync = (1000 / sc->sc_freq) * tcdsdev->tcdsda_period / 4; + + sc->sc_maxxfer = 64 * 1024; + + /* Do the common parts of attachment. */ + ncr53c9x_attach(sc, &asc_switch, &asc_dev); +} + +void +tcds_dma_reset(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + + /* TCDS SCSI disable/reset/enable. */ + tcds_scsi_reset(asc->sc_tcds); /* XXX */ + + if (asc->asc.sc_flags & ASC_MAPLOADED) + bus_dmamap_unload(asc->asc.sc_dmat, asc->asc.sc_dmamap); + asc->asc.sc_flags &= ~(ASC_DMAACTIVE|ASC_MAPLOADED); +} + +/* + * start a dma transfer or keep it going + */ +int +tcds_dma_setup(sc, addr, len, ispullup, dmasize) + struct ncr53c9x_softc *sc; + caddr_t *addr; + size_t *len, *dmasize; + int ispullup; /* DMA into main memory */ +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + struct tcds_slotconfig *tcds = asc->sc_tcds; + size_t size; + u_int32_t dic; + + NCR_DMA(("tcds_dma %d: start %d@%p,%s\n", tcds->sc_slot, + (int)*asc->asc.sc_dmalen, *asc->asc.sc_dmaaddr, + (ispullup) ? "IN" : "OUT")); + + /* + * the rules say we cannot transfer more than the limit + * of this DMA chip (64k) and we cannot cross a 8k boundary. + */ + size = min(*dmasize, DMAMAX((size_t)*addr)); + asc->asc.sc_dmaaddr = addr; + asc->asc.sc_dmalen = len; + asc->asc.sc_flags = (ispullup) ? ASC_ISPULLUP : 0; + *dmasize = asc->asc.sc_dmasize = size; + + NCR_DMA(("dma_start: dmasize = %d\n", (int)size)); + + if (size == 0) + return 0; + + if (bus_dmamap_load(asc->asc.sc_dmat, asc->asc.sc_dmamap, *addr, size, + NULL, BUS_DMA_NOWAIT | (ispullup ? BUS_DMA_READ : BUS_DMA_WRITE))) { + /* + * XXX Should return an error, here, but the upper-layer + * XXX doesn't check the return value! + */ + panic("tcds_dma_setup: dmamap load failed"); + } + + /* synchronize dmamap contents with memory image */ + bus_dmamap_sync(asc->asc.sc_dmat, asc->asc.sc_dmamap, 0, size, + (ispullup) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + + /* load address, set/clear unaligned transfer and read/write bits. */ + bus_space_write_4(tcds->sc_bst, tcds->sc_bsh, tcds->sc_sda, + asc->asc.sc_dmamap->dm_segs[0].ds_addr >> 2); + dic = bus_space_read_4(tcds->sc_bst, tcds->sc_bsh, tcds->sc_dic); + dic &= ~TCDS_DIC_ADDRMASK; + dic |= asc->asc.sc_dmamap->dm_segs[0].ds_addr & TCDS_DIC_ADDRMASK; + if (ispullup) + dic |= TCDS_DIC_WRITE; + else + dic &= ~TCDS_DIC_WRITE; + bus_space_write_4(tcds->sc_bst, tcds->sc_bsh, tcds->sc_dic, dic); + + asc->asc.sc_flags |= ASC_MAPLOADED; + return 0; +} + +void +tcds_dma_go(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + + /* mark unit as DMA-active */ + asc->asc.sc_flags |= ASC_DMAACTIVE; + + /* start DMA */ + tcds_dma_enable(asc->sc_tcds, 1); +} + +void +tcds_dma_stop(sc) + struct ncr53c9x_softc *sc; +{ +#if 0 + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; +#endif + + /* + * XXX STOP DMA HERE! + */ +} + +/* + * Pseudo (chained) interrupt from the asc driver to kick the + * current running DMA transfer. Called from ncr53c9x_intr() + * for now. + * + * return 1 if it was a DMA continue. + */ +int +tcds_dma_intr(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + struct tcds_slotconfig *tcds = asc->sc_tcds; + int trans, resid; + u_int32_t tcl, tcm; + u_int32_t dud, dudmask, *addr; + bus_addr_t pa; + + NCR_DMA(("tcds_dma %d: intr", tcds->sc_slot)); + + if (tcds_scsi_iserr(tcds)) + return 0; + + /* This is an "assertion" :) */ + if ((asc->asc.sc_flags & ASC_DMAACTIVE) == 0) + panic("tcds_dma_intr: DMA wasn't active"); + + /* DMA has stopped */ + tcds_dma_enable(tcds, 0); + asc->asc.sc_flags &= ~ASC_DMAACTIVE; + + if (asc->asc.sc_dmasize == 0) { + /* A "Transfer Pad" operation completed */ + tcl = NCR_READ_REG(sc, NCR_TCL); + tcm = NCR_READ_REG(sc, NCR_TCM); + NCR_DMA(("dma_intr: discarded %d bytes (tcl=%d, tcm=%d)\n", + tcl | (tcm << 8), tcl, tcm)); + return 0; + } + + resid = 0; + if ((asc->asc.sc_flags & ASC_ISPULLUP) == 0 && + (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { + NCR_DMA(("dma_intr: empty esp FIFO of %d ", resid)); + DELAY(1); + } + + resid += (tcl = NCR_READ_REG(sc, NCR_TCL)); + resid += (tcm = NCR_READ_REG(sc, NCR_TCM)) << 8; + + trans = asc->asc.sc_dmasize - resid; + if (trans < 0) { /* transferred < 0 ? */ + printf("tcds_dma %d: xfer (%d) > req (%d)\n", + tcds->sc_slot, trans, (int)asc->asc.sc_dmasize); + trans = asc->asc.sc_dmasize; + } + + NCR_DMA(("dma_intr: tcl=%d, tcm=%d; trans=%d, resid=%d\n", + tcl, tcm, trans, resid)); + + *asc->asc.sc_dmalen -= trans; + *asc->asc.sc_dmaaddr += trans; + + bus_dmamap_sync(asc->asc.sc_dmat, asc->asc.sc_dmamap, + 0, asc->asc.sc_dmamap->dm_mapsize, + (asc->asc.sc_flags & ASC_ISPULLUP) + ? BUS_DMASYNC_POSTREAD + : BUS_DMASYNC_POSTWRITE); + + /* + * Clean up unaligned DMAs into main memory. + */ + if (asc->asc.sc_flags & ASC_ISPULLUP) { + /* Handle unaligned starting address, length. */ + dud = bus_space_read_4(tcds->sc_bst, + tcds->sc_bsh, tcds->sc_dud0); + if ((dud & TCDS_DUD0_VALIDBITS) != 0) { + addr = (u_int32_t *) + ((paddr_t)*asc->asc.sc_dmaaddr & ~0x3); + dudmask = 0; + if (dud & TCDS_DUD0_VALID00) + panic("tcds_dma: dud0 byte 0 valid"); + if (dud & TCDS_DUD0_VALID01) + dudmask |= TCDS_DUD_BYTE01; + if (dud & TCDS_DUD0_VALID10) + dudmask |= TCDS_DUD_BYTE10; +#ifdef DIAGNOSTIC + if (dud & TCDS_DUD0_VALID11) + dudmask |= TCDS_DUD_BYTE11; +#endif + NCR_DMA(("dud0 at 0x%p dudmask 0x%x\n", + addr, dudmask)); + *addr = (*addr & ~dudmask) | (dud & dudmask); + } + dud = bus_space_read_4(tcds->sc_bst, + tcds->sc_bsh, tcds->sc_dud1); + if ((dud & TCDS_DUD1_VALIDBITS) != 0) { + pa = bus_space_read_4(tcds->sc_bst, tcds->sc_bsh, + tcds->sc_sda) << 2; + dudmask = 0; + if (dud & TCDS_DUD1_VALID00) + dudmask |= TCDS_DUD_BYTE00; + if (dud & TCDS_DUD1_VALID01) + dudmask |= TCDS_DUD_BYTE01; + if (dud & TCDS_DUD1_VALID10) + dudmask |= TCDS_DUD_BYTE10; +#ifdef DIAGNOSTIC + if (dud & TCDS_DUD1_VALID11) + panic("tcds_dma: dud1 byte 3 valid"); +#endif + NCR_DMA(("dud1 at 0x%lx dudmask 0x%x\n", + pa, dudmask)); + /* XXX Fix TC_PHYS_TO_UNCACHED() */ +#if defined(__alpha__) + addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG(pa); +#elif defined(__mips__) + addr = (u_int32_t *)MIPS_PHYS_TO_KSEG1(pa); +#else +#error TURBOchannel only exists on DECs, folks... +#endif + *addr = (*addr & ~dudmask) | (dud & dudmask); + } + /* XXX deal with saved residual byte? */ + } + + bus_dmamap_unload(asc->asc.sc_dmat, asc->asc.sc_dmamap); + asc->asc.sc_flags &= ~ASC_MAPLOADED; + + return 0; +} + +/* + * Glue functions. + */ +int +tcds_dma_isintr(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + int x; + + x = tcds_scsi_isintr(asc->sc_tcds, 1); + + /* XXX */ + return x; +} + +int +tcds_dma_isactive(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + + return !!(asc->asc.sc_flags & ASC_DMAACTIVE); +} + +void +tcds_clear_latched_intr(sc) + struct ncr53c9x_softc *sc; +{ + struct asc_tcds_softc *asc = (struct asc_tcds_softc *)sc; + + /* Clear the TCDS interrupt bit. */ + (void)tcds_scsi_isintr(asc->sc_tcds, 1); +} diff --git a/sys/dev/tc/ascvar.h b/sys/dev/tc/ascvar.h new file mode 100644 index 00000000000..f69e770dc5d --- /dev/null +++ b/sys/dev/tc/ascvar.h @@ -0,0 +1,24 @@ +/* $OpenBSD: ascvar.h,v 1.9 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: ascvar.h,v 1.7 2000/10/31 15:16:26 simonb Exp $ */ + +/* + * State kept for each active SCSI host interface (53C94). + */ + +struct asc_softc { + struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ + bus_space_tag_t sc_bst; /* bus space tag */ + bus_space_handle_t sc_bsh; /* ASC register handle */ + bus_dma_tag_t sc_dmat; /* bus dma tag */ + bus_dmamap_t sc_dmamap; /* bus dmamap */ + caddr_t *sc_dmaaddr; + size_t *sc_dmalen; + size_t sc_dmasize; + unsigned sc_flags; +#define ASC_ISPULLUP 0x01 +#define ASC_DMAACTIVE 0x02 +#define ASC_MAPLOADED 0x04 +}; + +u_char asc_read_reg(struct ncr53c9x_softc *, int); +void asc_write_reg(struct ncr53c9x_softc *, int, u_char); diff --git a/sys/dev/tc/devlist2h.awk b/sys/dev/tc/devlist2h.awk index 9164d87ac26..bf189844e04 100644 --- a/sys/dev/tc/devlist2h.awk +++ b/sys/dev/tc/devlist2h.awk @@ -1,5 +1,5 @@ #! /usr/bin/awk -f -# $OpenBSD: devlist2h.awk,v 1.3 1996/12/08 01:03:03 niklas Exp $ +# $OpenBSD: devlist2h.awk,v 1.4 2002/05/02 22:56:06 miod Exp $ # $NetBSD: devlist2h.awk,v 1.3 1996/06/05 18:32:19 cgd Exp $ # # Copyright (c) 1995, 1996 Christopher G. Demetriou @@ -39,6 +39,7 @@ NR == 1 { VERSION = $0 gsub("\\$", "", VERSION) + printf("/*\t\$OpenBSD\$\t*/\n\n") > dfile printf("/*\n") > dfile printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ > dfile @@ -47,6 +48,7 @@ NR == 1 { printf(" *\t%s\n", VERSION) > dfile printf(" */\n") > dfile + printf("/*\t\$OpenBSD\$\t*/\n\n") > hfile printf("/*\n") > hfile printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ > hfile diff --git a/sys/dev/tc/files.tc b/sys/dev/tc/files.tc index 38490a44ab8..5c8b0895d6e 100644 --- a/sys/dev/tc/files.tc +++ b/sys/dev/tc/files.tc @@ -1,21 +1,42 @@ -# $OpenBSD: files.tc,v 1.5 1996/05/26 00:27:52 deraadt Exp $ -# $NetBSD: files.tc,v 1.5 1996/05/20 00:45:02 thorpej Exp $ +# $OpenBSD: files.tc,v 1.6 2002/05/02 22:56:06 miod Exp $ +# $NetBSD: files.tc,v 1.26 2001/11/28 10:21:24 lukem Exp $ # -# Config.new file and device description for machine-independent -# TurboChannel code. Included by ports that need it. +# Config file and device description for machine-independent +# TURBOchannel code. Included by ports that need it. device tc {[slot = -1], [offset = -1]} -attach tc at tcbus +#attach tc at tcbus file dev/tc/tc.c tc needs-flag -# device defined in sys/conf/files -# attach le at ioasic with le_ioasic -# attach le at tc with le_tc -# file dev/tc/if_le_dec.c (le_ioasic | le_tc) -# file dev/tc/if_le_ioasic.c le_ioasic needs-flag # for le_iomem -# file dev/tc/if_le_tc.c le_tc +# IOCTL ASIC +device ioasic { offset = -1 } +attach ioasic at tc +file dev/tc/ioasic_subr.c ioasic -# DEC DEFTA TC FDDI Controller +# LANCE attachments. +# lance device defined in sys/conf/files +# le_dec_subr attribute defined in sys/dev/dec/files.dec + +attach le at ioasic with le_ioasic: le_dec_subr +file dev/tc/if_le_ioasic.c le_ioasic + +attach le at tc with le_tc: le_dec_subr +file dev/tc/if_le_tc.c le_tc + +# DEFTA FDDI controller device fta: pdq, fddi, ifnet attach fta at tc file dev/tc/if_fta.c fta + +# TCDS dual channel SCSI +device tcds { chip = -1 } +attach tcds at tc +file dev/tc/tcds.c tcds + +# 53C[F]90 PMAZ single channel SCSI +device asc: ncr53c9x, scsi +file dev/tc/asc.c asc +attach asc at tc with asc_tc +file dev/tc/asc_tc.c asc_tc +attach asc at tcds with asc_tcds +file dev/tc/asc_tcds.c asc_tcds diff --git a/sys/dev/tc/if_le_ioasic.c b/sys/dev/tc/if_le_ioasic.c index 2ff91977d17..9eab3788dc2 100644 --- a/sys/dev/tc/if_le_ioasic.c +++ b/sys/dev/tc/if_le_ioasic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_le_ioasic.c,v 1.10 2002/03/14 01:27:03 millert Exp $ */ -/* $NetBSD: if_le_ioasic.c,v 1.2 1996/05/07 02:24:56 thorpej Exp $ */ +/* $OpenBSD: if_le_ioasic.c,v 1.11 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: if_le_ioasic.c,v 1.18 2001/11/13 06:26:10 lukem Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -42,8 +42,6 @@ #include <net/if.h> #include <net/if_media.h> -#include <uvm/uvm_extern.h> - #ifdef INET #include <netinet/in.h> #include <netinet/if_ether.h> @@ -54,26 +52,35 @@ #include <dev/tc/if_levar.h> #include <dev/tc/tcvar.h> +#include <dev/tc/ioasicreg.h> #include <dev/tc/ioasicvar.h> -int le_ioasic_match(struct device *, void *, void *); -void le_ioasic_attach(struct device *, struct device *, void *); +struct le_ioasic_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + struct lereg1 *sc_r1; /* LANCE registers */ + /* XXX must match with le_softc of if_levar.h XXX */ -hide void le_ioasic_copytobuf_gap2(struct am7990_softc *, void *, - int, int); -hide void le_ioasic_copyfrombuf_gap2(struct am7990_softc *, void *, - int, int); + bus_dma_tag_t sc_dmat; /* bus dma tag */ + bus_dmamap_t sc_dmamap; /* bus dmamap */ +}; -hide void le_ioasic_copytobuf_gap16(struct am7990_softc *, void *, - int, int); -hide void le_ioasic_copyfrombuf_gap16(struct am7990_softc *, void *, - int, int); -hide void le_ioasic_zerobuf_gap16(struct am7990_softc *, int, int); +int le_ioasic_match(struct device *, void *, void *); +void le_ioasic_attach(struct device *, struct device *, void *); struct cfattach le_ioasic_ca = { sizeof(struct le_softc), le_ioasic_match, le_ioasic_attach }; +void le_ioasic_copytobuf_gap2(struct am7990_softc *, void *, + int, int); +void le_ioasic_copyfrombuf_gap2(struct am7990_softc *, void *, + int, int); +void le_ioasic_copytobuf_gap16(struct am7990_softc *, void *, + int, int); +void le_ioasic_copyfrombuf_gap16(struct am7990_softc *, void *, + int, int); +void le_ioasic_zerobuf_gap16(struct am7990_softc *, int, int); + int le_ioasic_match(parent, match, aux) struct device *parent; @@ -81,67 +88,92 @@ le_ioasic_match(parent, match, aux) { struct ioasicdev_attach_args *d = aux; - if (!ioasic_submatch(match, aux)) - return (0); - if (strncmp("lance", d->iada_modname, TC_ROM_LLEN)) - return (0); + if (strncmp("PMAD-BA ", d->iada_modname, TC_ROM_LLEN) != 0) + return 0; - return (1); + return 1; } -#define LE_IOASIC_MEMSIZE (128*1024) -#define LE_IOASIC_MEMALIGN (128*1024) +/* IOASIC LANCE DMA needs 128KB boundary aligned 128KB chunk */ +#define LE_IOASIC_MEMSIZE (128*1024) +#define LE_IOASIC_MEMALIGN (128*1024) + void le_ioasic_attach(parent, self, aux) struct device *parent, *self; void *aux; { + struct le_ioasic_softc *sc = (void *)self; struct ioasicdev_attach_args *d = aux; - struct le_softc *lesc = (void *)self; - struct am7990_softc *sc = &lesc->sc_am7990; + struct am7990_softc *le = &sc->sc_am7990; + bus_space_tag_t ioasic_bst; + bus_space_handle_t ioasic_bsh; + bus_dma_tag_t dmat; + bus_dma_segment_t seg; + tc_addr_t tca; + u_int32_t ssr; + int rseg; caddr_t le_iomem; - struct pglist pglist; - struct vm_page *pg; - vaddr_t va; - vsize_t size; + ioasic_bst = ((struct ioasic_softc *)parent)->sc_bst; + ioasic_bsh = ((struct ioasic_softc *)parent)->sc_bsh; + dmat = sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat; /* - * XXX - this vm juggling is so wrong. use bus_dma instead! + * Allocate a DMA area for the chip. */ - size = round_page(LE_IOASIC_MEMSIZE); - if (uvm_pglistalloc(size, 0, 0, LE_IOASIC_MEMALIGN, 0, &pglist, 1, 0) || - uvm_map(kernel_map, &va, size, NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE, - UVM_ADV_RANDOM, 0))) - panic("aha_init: could not allocate mailbox"); - - le_iomem = (caddr_t)va; - for (pg = TAILQ_FIRST(&pglist); pg != NULL;pg = TAILQ_NEXT(pg, pageq)) { - pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), - VM_PROT_READ|VM_PROT_WRITE); - va += PAGE_SIZE; + if (bus_dmamem_alloc(dmat, LE_IOASIC_MEMSIZE, LE_IOASIC_MEMALIGN, + 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + printf("can't allocate DMA area for LANCE\n"); + return; + } + if (bus_dmamem_map(dmat, &seg, rseg, LE_IOASIC_MEMSIZE, + &le_iomem, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { + printf("can't map DMA area for LANCE\n"); + bus_dmamem_free(dmat, &seg, rseg); + return; } - pmap_update(pmap_kernel()); /* - * XXXEND + * Create and load the DMA map for the DMA area. */ + if (bus_dmamap_create(dmat, LE_IOASIC_MEMSIZE, 1, + LE_IOASIC_MEMSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) { + printf("can't create DMA map\n"); + goto bad; + } + if (bus_dmamap_load(dmat, sc->sc_dmamap, + le_iomem, LE_IOASIC_MEMSIZE, NULL, BUS_DMA_NOWAIT)) { + printf("can't load DMA map\n"); + goto bad; + } + /* + * Bind 128KB buffer with IOASIC DMA. + */ + tca = IOASIC_DMA_ADDR(sc->sc_dmamap->dm_segs[0].ds_addr); + bus_space_write_4(ioasic_bst, ioasic_bsh, IOASIC_LANCE_DMAPTR, tca); + ssr = bus_space_read_4(ioasic_bst, ioasic_bsh, IOASIC_CSR); + ssr |= IOASIC_CSR_DMAEN_LANCE; + bus_space_write_4(ioasic_bst, ioasic_bsh, IOASIC_CSR, ssr); - lesc->sc_r1 = (struct lereg1 *) + sc->sc_r1 = (struct lereg1 *) TC_DENSE_TO_SPARSE(TC_PHYS_TO_UNCACHED(d->iada_addr)); - sc->sc_mem = (void *)TC_PHYS_TO_UNCACHED(le_iomem); - - sc->sc_copytodesc = le_ioasic_copytobuf_gap2; - sc->sc_copyfromdesc = le_ioasic_copyfrombuf_gap2; - sc->sc_copytobuf = le_ioasic_copytobuf_gap16; - sc->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16; - sc->sc_zerobuf = le_ioasic_zerobuf_gap16; + le->sc_mem = (void *)TC_PHYS_TO_UNCACHED(le_iomem); + le->sc_copytodesc = le_ioasic_copytobuf_gap2; + le->sc_copyfromdesc = le_ioasic_copyfrombuf_gap2; + le->sc_copytobuf = le_ioasic_copytobuf_gap16; + le->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16; + le->sc_zerobuf = le_ioasic_zerobuf_gap16; - ioasic_lance_dma_setup(le_iomem); /* XXX more thought */ - - dec_le_common_attach(sc, ioasic_lance_ether_address()); + dec_le_common_attach(&sc->sc_am7990, + (u_char *)((struct ioasic_softc *)parent)->sc_base + + IOASIC_SLOT_2_START); ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET, am7990_intr, sc); + return; + + bad: + bus_dmamem_unmap(dmat, le_iomem, LE_IOASIC_MEMSIZE); + bus_dmamem_free(dmat, &seg, rseg); } /* @@ -161,11 +193,11 @@ le_ioasic_copytobuf_gap2(sc, fromv, boff, len) struct am7990_softc *sc; void *fromv; int boff; - register int len; + int len; { volatile caddr_t buf = sc->sc_mem; - register caddr_t from = fromv; - register volatile u_int16_t *bptr; + caddr_t from = fromv; + volatile u_int16_t *bptr; if (boff & 0x1) { /* handle unaligned first byte */ @@ -192,9 +224,9 @@ le_ioasic_copyfrombuf_gap2(sc, tov, boff, len) int boff, len; { volatile caddr_t buf = sc->sc_mem; - register caddr_t to = tov; - register volatile u_int16_t *bptr; - register u_int16_t tmp; + caddr_t to = tov; + volatile u_int16_t *bptr; + u_int16_t tmp; if (boff & 0x1) { /* handle unaligned first byte */ @@ -226,24 +258,84 @@ le_ioasic_copytobuf_gap16(sc, fromv, boff, len) struct am7990_softc *sc; void *fromv; int boff; - register int len; + int len; { volatile caddr_t buf = sc->sc_mem; - register caddr_t from = fromv; - register caddr_t bptr; - register int xfer; + caddr_t from = fromv; + caddr_t bptr; bptr = buf + ((boff << 1) & ~0x1f); boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { + + /* + * Dispose of boff so destination of subsequent copies is + * 16-byte aligned. + */ + if (boff) { + int xfer; + xfer = min(len, 16 - boff); bcopy(from, bptr + boff, xfer); from += xfer; bptr += 32; - boff = 0; len -= xfer; - xfer = min(len, 16); } + + /* Destination of copies is now 16-byte aligned. */ + if (len >= 16) + switch ((u_long)from & (sizeof(u_int32_t) -1)) { + case 2: + /* Ethernet headers make this the dominant case. */ + do { + u_int32_t *dst = (u_int32_t*)bptr; + u_int16_t t0; + u_int32_t t1, t2, t3, t4; + + /* read from odd-16-bit-aligned, cached src */ + t0 = *(u_int16_t*)from; + t1 = *(u_int32_t*)(from+2); + t2 = *(u_int32_t*)(from+6); + t3 = *(u_int32_t*)(from+10); + t4 = *(u_int16_t*)(from+14); + + /* DMA buffer is uncached on mips */ + dst[0] = t0 | (t1 << 16); + dst[1] = (t1 >> 16) | (t2 << 16); + dst[2] = (t2 >> 16) | (t3 << 16); + dst[3] = (t3 >> 16) | (t4 << 16); + + from += 16; + bptr += 32; + len -= 16; + } while (len >= 16); + break; + + case 0: + do { + u_int32_t *src = (u_int32_t*)from; + u_int32_t *dst = (u_int32_t*)bptr; + u_int32_t t0, t1, t2, t3; + + t0 = src[0]; t1 = src[1]; t2 = src[2]; t3 = src[3]; + dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; + + from += 16; + bptr += 32; + len -= 16; + } while (len >= 16); + break; + + default: + /* Does odd-aligned case ever happen? */ + do { + bcopy(from, bptr, 16); + from += 16; + bptr += 32; + len -= 16; + } while (len >= 16); + break; + } + if (len) + bcopy(from, bptr, len); } void @@ -253,21 +345,73 @@ le_ioasic_copyfrombuf_gap16(sc, tov, boff, len) int boff, len; { volatile caddr_t buf = sc->sc_mem; - register caddr_t to = tov; - register caddr_t bptr; - register int xfer; + caddr_t to = tov; + caddr_t bptr; bptr = buf + ((boff << 1) & ~0x1f); boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - bcopy(bptr + boff, to, xfer); + + /* Dispose of boff. source of copy is subsequently 16-byte aligned. */ + if (boff) { + int xfer; + xfer = min(len, 16 - boff); + bcopy(bptr+boff, to, xfer); to += xfer; bptr += 32; - boff = 0; len -= xfer; - xfer = min(len, 16); } + if (len >= 16) + switch ((u_long)to & (sizeof(u_int32_t) -1)) { + case 2: + /* + * to is aligned to an odd 16-bit boundary. Ethernet headers + * make this the dominant case (98% or more). + */ + do { + u_int32_t *src = (u_int32_t*)bptr; + u_int32_t t0, t1, t2, t3; + + /* read from uncached aligned DMA buf */ + t0 = src[0]; t1 = src[1]; t2 = src[2]; t3 = src[3]; + + /* write to odd-16-bit-word aligned dst */ + *(u_int16_t *) (to+0) = (u_short) t0; + *(u_int32_t *) (to+2) = (t0 >> 16) | (t1 << 16); + *(u_int32_t *) (to+6) = (t1 >> 16) | (t2 << 16); + *(u_int32_t *) (to+10) = (t2 >> 16) | (t3 << 16); + *(u_int16_t *) (to+14) = (t3 >> 16); + bptr += 32; + to += 16; + len -= 16; + } while (len > 16); + break; + case 0: + /* 32-bit aligned aligned copy. Rare. */ + do { + u_int32_t *src = (u_int32_t*)bptr; + u_int32_t *dst = (u_int32_t*)to; + u_int32_t t0, t1, t2, t3; + + t0 = src[0]; t1 = src[1]; t2 = src[2]; t3 = src[3]; + dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; + to += 16; + bptr += 32; + len -= 16; + } while (len > 16); + break; + + /* XXX Does odd-byte-aligned case ever happen? */ + default: + do { + bcopy(bptr, to, 16); + to += 16; + bptr += 32; + len -= 16; + } while (len > 16); + break; + } + if (len) + bcopy(bptr, to, len); } void @@ -276,8 +420,8 @@ le_ioasic_zerobuf_gap16(sc, boff, len) int boff, len; { volatile caddr_t buf = sc->sc_mem; - register caddr_t bptr; - register int xfer; + caddr_t bptr; + int xfer; bptr = buf + ((boff << 1) & ~0x1f); boff &= 0xf; diff --git a/sys/dev/tc/if_le_tc.c b/sys/dev/tc/if_le_tc.c index 704449b4ef8..deb0c87ac63 100644 --- a/sys/dev/tc/if_le_tc.c +++ b/sys/dev/tc/if_le_tc.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_le_tc.c,v 1.5 2002/03/14 01:27:03 millert Exp $ */ -/* $NetBSD: if_le_tc.c,v 1.2 1996/05/07 02:24:57 thorpej Exp $ */ +/* $OpenBSD: if_le_tc.c,v 1.6 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: if_le_tc.c,v 1.12 2001/11/13 06:26:10 lukem Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -71,8 +71,7 @@ le_tc_match(parent, match, aux) { struct tc_attach_args *d = aux; - if (strncmp("PMAD-AA ", d->ta_modname, TC_ROM_LLEN) && - strncmp("PMAD-BA ", d->ta_modname, TC_ROM_LLEN)) + if (strncmp("PMAD-AA ", d->ta_modname, TC_ROM_LLEN) != 0) return (0); return (1); @@ -83,8 +82,8 @@ le_tc_attach(parent, self, aux) struct device *parent, *self; void *aux; { - register struct le_softc *lesc = (void *)self; - register struct am7990_softc *sc = &lesc->sc_am7990; + struct le_softc *lesc = (void *)self; + struct am7990_softc *sc = &lesc->sc_am7990; struct tc_attach_args *d = aux; /* @@ -106,7 +105,8 @@ le_tc_attach(parent, self, aux) * so DMA setup is not required. */ - dec_le_common_attach(sc, (u_char *)(d->ta_addr + LE_OFFSET_ROM + 2)); + dec_le_common_attach(&lesc->sc_am7990, + (u_char *)(d->ta_addr + LE_OFFSET_ROM + 2)); tc_intr_establish(parent, d->ta_cookie, TC_IPL_NET, am7990_intr, sc); } diff --git a/sys/dev/tc/if_levar.h b/sys/dev/tc/if_levar.h index 25843885576..1efab40ebee 100644 --- a/sys/dev/tc/if_levar.h +++ b/sys/dev/tc/if_levar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if_levar.h,v 1.5 2002/03/14 01:27:03 millert Exp $ */ -/* $NetBSD: if_levar.h,v 1.3 1996/05/07 02:24:58 thorpej Exp $ */ +/* $OpenBSD: if_levar.h,v 1.6 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: if_levar.h,v 1.4 1997/03/15 18:12:07 is Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -57,7 +57,7 @@ struct lereg1 { * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, - * arpcom.ac_if, which the routing code uses to locate the interface. + * ethercom.ec_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct le_softc { diff --git a/sys/dev/tc/ioasic_subr.c b/sys/dev/tc/ioasic_subr.c new file mode 100644 index 00000000000..bb3a4364da8 --- /dev/null +++ b/sys/dev/tc/ioasic_subr.c @@ -0,0 +1,86 @@ +/* $OpenBSD: ioasic_subr.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: ioasic_subr.c,v 1.3 2001/11/13 06:26:10 lukem Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Keith Bostic, Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <dev/tc/tcvar.h> +#include <dev/tc/ioasicvar.h> + +int ioasicprint(void *, const char *); + +int +ioasicprint(aux, pnp) + void *aux; + const char *pnp; +{ + struct ioasicdev_attach_args *d = aux; + + if (pnp) + printf("%s at %s", d->iada_modname, pnp); + printf(" offset 0x%lx", (long)d->iada_offset); + return (UNCONF); +} + +int +ioasic_submatch(vcf, d) + void *vcf; + struct ioasicdev_attach_args *d; +{ + struct cfdata *match = vcf; + + return ((match->ioasiccf_offset == d->iada_offset) || + (match->ioasiccf_offset == IOASIC_OFFSET_UNKNOWN)); +} + +void +ioasic_attach_devs(sc, ioasic_devs, ioasic_ndevs) + struct ioasic_softc *sc; + struct ioasic_dev *ioasic_devs; + int ioasic_ndevs; +{ + struct ioasicdev_attach_args idev; + int i; + + /* + * Try to configure each device. + */ + for (i = 0; i < ioasic_ndevs; i++) { + strncpy(idev.iada_modname, ioasic_devs[i].iad_modname, + TC_ROM_LLEN); + idev.iada_modname[TC_ROM_LLEN] = '\0'; + idev.iada_offset = ioasic_devs[i].iad_offset; + idev.iada_addr = sc->sc_base + ioasic_devs[i].iad_offset; + idev.iada_cookie = ioasic_devs[i].iad_cookie; + + /* Tell the autoconfig machinery we've found the hardware. */ + config_found(&sc->sc_dv, &idev, ioasicprint); + } +} diff --git a/sys/dev/tc/ioasicreg.h b/sys/dev/tc/ioasicreg.h new file mode 100644 index 00000000000..067c15a79ab --- /dev/null +++ b/sys/dev/tc/ioasicreg.h @@ -0,0 +1,204 @@ +/* $OpenBSD: ioasicreg.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: ioasicreg.h,v 1.6 2000/07/17 02:18:17 thorpej Exp $ */ + +/* + * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University, + * Ralph Campbell and Rick Macklem. + * + * 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. + * + * @(#)asic.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Slot definitions + */ + +#define IOASIC_SLOT_0_START 0x000000 +#define IOASIC_SLOT_1_START 0x040000 +#define IOASIC_SLOT_2_START 0x080000 +#define IOASIC_SLOT_3_START 0x0c0000 +#define IOASIC_SLOT_4_START 0x100000 +#define IOASIC_SLOT_5_START 0x140000 +#define IOASIC_SLOT_6_START 0x180000 +#define IOASIC_SLOT_7_START 0x1c0000 +#define IOASIC_SLOT_8_START 0x200000 +#define IOASIC_SLOT_9_START 0x240000 +#define IOASIC_SLOT_10_START 0x280000 +#define IOASIC_SLOT_11_START 0x2c0000 +#define IOASIC_SLOT_12_START 0x300000 +#define IOASIC_SLOT_13_START 0x340000 +#define IOASIC_SLOT_14_START 0x380000 +#define IOASIC_SLOT_15_START 0x3c0000 +#define IOASIC_SLOTS_END 0x3fffff + +/* + * Register offsets (slot 1) + */ + +#define IOASIC_SCSI_DMAPTR IOASIC_SLOT_1_START+0x000 +#define IOASIC_SCSI_NEXTPTR IOASIC_SLOT_1_START+0x010 +#define IOASIC_LANCE_DMAPTR IOASIC_SLOT_1_START+0x020 +#define IOASIC_SCC_T1_DMAPTR IOASIC_SLOT_1_START+0x030 +#define IOASIC_SCC_R1_DMAPTR IOASIC_SLOT_1_START+0x040 +#define IOASIC_SCC_T2_DMAPTR IOASIC_SLOT_1_START+0x050 +#define IOASIC_SCC_R2_DMAPTR IOASIC_SLOT_1_START+0x060 +#define IOASIC_FLOPPY_DMAPTR IOASIC_SLOT_1_START+0x070 +#define IOASIC_ISDN_X_DMAPTR IOASIC_SLOT_1_START+0x080 +#define IOASIC_ISDN_X_NEXTPTR IOASIC_SLOT_1_START+0x090 +#define IOASIC_ISDN_R_DMAPTR IOASIC_SLOT_1_START+0x0a0 +#define IOASIC_ISDN_R_NEXTPTR IOASIC_SLOT_1_START+0x0b0 +#define IOASIC_BUFF0 IOASIC_SLOT_1_START+0x0c0 +#define IOASIC_BUFF1 IOASIC_SLOT_1_START+0x0d0 +#define IOASIC_BUFF2 IOASIC_SLOT_1_START+0x0e0 +#define IOASIC_BUFF3 IOASIC_SLOT_1_START+0x0f0 +#define IOASIC_CSR IOASIC_SLOT_1_START+0x100 +#define IOASIC_INTR IOASIC_SLOT_1_START+0x110 +#define IOASIC_IMSK IOASIC_SLOT_1_START+0x120 +#define IOASIC_CURADDR IOASIC_SLOT_1_START+0x130 +#define IOASIC_ISDN_X_DATA IOASIC_SLOT_1_START+0x140 +#define IOASIC_ISDN_R_DATA IOASIC_SLOT_1_START+0x150 +#define IOASIC_LANCE_DECODE IOASIC_SLOT_1_START+0x160 +#define IOASIC_SCSI_DECODE IOASIC_SLOT_1_START+0x170 +#define IOASIC_SCC0_DECODE IOASIC_SLOT_1_START+0x180 +#define IOASIC_SCC1_DECODE IOASIC_SLOT_1_START+0x190 +#define IOASIC_FLOPPY_DECODE IOASIC_SLOT_1_START+0x1a0 +#define IOASIC_SCSI_SCR IOASIC_SLOT_1_START+0x1b0 +#define IOASIC_SCSI_SDR0 IOASIC_SLOT_1_START+0x1c0 +#define IOASIC_SCSI_SDR1 IOASIC_SLOT_1_START+0x1d0 +#define IOASIC_CTR IOASIC_SLOT_1_START+0x1e0 /*3max+/3000*/ + +/* System Status and control Register (SSR). */ +#define IOASIC_CSR_DMAEN_T1 0x80000000 /* rw */ +#define IOASIC_CSR_DMAEN_R1 0x40000000 /* rw */ +#define IOASIC_CSR_DMAEN_T2 0x20000000 /* rw */ +#define IOASIC_CSR_DMAEN_R2 0x10000000 /* rw */ +#define IOASIC_CSR_FASTMODE 0x08000000 /* rw - 3000 */ +#define IOASIC_CSR_xxx 0x07800000 /* reserved - 3000 */ +#define IOASIC_CSR_DS_xxx 0x0f800000 /* reserved - DS */ +#define IOASIC_CSR_FLOPPY_DIR 0x00400000 /* rw - maxine */ +#define IOASIC_CSR_DMAEN_FLOPPY 0x00200000 /* rw - maxine */ +#define IOASIC_CSR_DMAEN_ISDN_T 0x00100000 /* rw */ +#define IOASIC_CSR_DMAEN_ISDN_R 0x00080000 /* rw */ +#define IOASIC_CSR_SCSI_DIR 0x00040000 /* rw - DS */ +#define IOASIC_CSR_DMAEN_SCSI 0x00020000 /* rw - DS */ +#define IOASIC_CSR_DMAEN_LANCE 0x00010000 /* rw - DS */ +/* low 16 bits are rw gp outputs */ +#define IOASIC_CSR_DIAGDN 0x00008000 /* rw */ +#define IOASIC_CSR_TXDIS_2 0x00004000 /* rw - 3min,3max+ */ +#define IOASIC_CSR_TXDIS_1 0x00002000 /* rw - 3min,3max+ */ +#define IOASIC_CSR_ISDN_ENABLE 0x00001000 /* rw - 3000/maxine */ +#define IOASIC_CSR_SCC_ENABLE 0x00000800 /* rw */ +#define IOASIC_CSR_RTC_ENABLE 0x00000400 /* rw */ +#define IOASIC_CSR_SCSI_ENABLE 0x00000200 /* rw - DS */ +#define IOASIC_CSR_LANCE_ENABLE 0x00000100 /* rw */ + +/* System Interrupt Register (and Interrupt Mask Register). */ +#define IOASIC_INTR_T1_PAGE_END 0x80000000 /* rz */ +#define IOASIC_INTR_T1_READ_E 0x40000000 /* rz */ +#define IOASIC_INTR_R1_HALF_PAGE 0x20000000 /* rz */ +#define IOASIC_INTR_R1_DMA_OVRUN 0x10000000 /* rz */ +#define IOASIC_INTR_T2_PAGE_END 0x08000000 /* rz */ +#define IOASIC_INTR_T2_READ_E 0x04000000 /* rz */ +#define IOASIC_INTR_R2_HALF_PAGE 0x02000000 /* rz */ +#define IOASIC_INTR_R2_DMA_OVRUN 0x01000000 /* rz */ +#define IOASIC_INTR_FLOPPY_DMA_E 0x00800000 /* rz - maxine */ +#define IOASIC_INTR_ISDN_TXLOAD 0x00400000 /* rz - 3000/maxine */ +#define IOASIC_INTR_ISDN_RXLOAD 0x00200000 /* rz - 3000/maxine */ +#define IOASIC_INTR_ISDN_OVRUN 0x00100000 /* rz - 3000/maxine */ +#define IOASIC_INTR_SCSI_PTR_LOAD 0x00080000 /* rz - DS */ +#define IOASIC_INTR_SCSI_OVRUN 0x00040000 /* rz - DS */ +#define IOASIC_INTR_SCSI_READ_E 0x00020000 /* rz - DS */ +#define IOASIC_INTR_LANCE_READ_E 0x00010000 /* rz - DS */ + +/* low 16 bits are model-dependent; see also model specific *.h */ +#define IOASIC_INTR_NVR_JUMPER 0x00004000 /* ro */ +#define IOASIC_INTR_ISDN 0x00002000 /* ro - 3000 */ +#define IOASIC_INTR_NRMOD_JUMPER 0x00000400 /* ro */ +#define IOASIC_INTR_SEC_CON 0x00000200 /* ro */ +#define IOASIC_INTR_SCSI 0x00000200 /* ro - DS */ +#define IOASIC_INTR_LANCE 0x00000100 /* ro */ +#define IOASIC_INTR_SCC_1 0x00000080 /* ro */ +#define IOASIC_INTR_SCC_0 0x00000040 /* ro */ +#define IOASIC_INTR_ALT_CON 0x00000008 /* ro - 3000/500 */ +#define IOASIC_INTR_300_OPT1 0x00000008 /* ro - 3000/300 */ +#define IOASIC_INTR_300_OPT0 0x00000004 /* ro - 3000/300 */ + +/* DMA pointer registers (SCSI, Comm, ...) */ + +#define IOASIC_DMA_ADDR(p) \ + ((((p) << 3) & ~0x1f) | (((p) >> 29) & 0x1f)) +#define IOASIC_DMA_BLOCKSIZE 0x1000 + +/* For the LANCE DMA pointer register initialization the above suffices */ + +/* More SCSI DMA registers */ + +#define IOASIC_SCR_STATUS 0x00000004 +#define IOASIC_SCR_WORD 0x00000003 + +/* Various Decode registers */ + +#define IOASIC_DECODE_HW_ADDRESS 0x000003f0 +#define IOASIC_DECODE_CHIP_SELECT 0x0000000f + +/* + * And slot assignments. + */ +#define IOASIC_SYS_ETHER_ADDRESS(base) ((base) + IOASIC_SLOT_2_START) +#define IOASIC_SYS_LANCE(base) ((base) + IOASIC_SLOT_3_START) diff --git a/sys/dev/tc/ioasicvar.h b/sys/dev/tc/ioasicvar.h index fe00a3fe465..09b95ac8414 100644 --- a/sys/dev/tc/ioasicvar.h +++ b/sys/dev/tc/ioasicvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ioasicvar.h,v 1.5 2002/03/14 03:16:08 millert Exp $ */ -/* $NetBSD: ioasicvar.h,v 1.2 1996/03/17 21:37:45 jonathan Exp $ */ +/* $OpenBSD: ioasicvar.h,v 1.6 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: ioasicvar.h,v 1.14 2000/10/17 09:45:49 nisimura Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -28,11 +28,16 @@ * rights to redistribute these changes. */ -/* - * IOASIC subdevice attachment information. - */ +#ifndef _DEV_TC_IOASICVAR_H_ +#define _DEV_TC_IOASICVAR_H_ + +struct ioasic_dev { + char *iad_modname; + tc_offset_t iad_offset; + void *iad_cookie; + u_int32_t iad_intrbits; +}; -/* Attachment arguments. */ struct ioasicdev_attach_args { char iada_modname[TC_ROM_LLEN]; tc_offset_t iada_offset; @@ -45,30 +50,28 @@ struct ioasicdev_attach_args { #define IOASIC_OFFSET_UNKNOWN -1 -/* - * The IOASIC (bus) cfdriver, so that subdevices can more - * easily tell what bus they're on. - */ -extern struct cfdriver ioasic_cd; +struct ioasic_softc { + struct device sc_dv; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + bus_dma_tag_t sc_dmat; + + tc_addr_t sc_base; /* XXX offset XXX */ +}; +extern struct cfdriver ioasic_cd; /* * XXX Some drivers need direct access to IOASIC registers. */ extern tc_addr_t ioasic_base; - -/* - * Interrupt establishment/disestablishment functions - */ -void ioasic_intr_establish(struct device *, void *, tc_intrlevel_t, - int (*)(void *), void *); +const struct evcnt *ioasic_intr_evcnt(struct device *, void *); +void ioasic_intr_establish(struct device *, void *, + int, int (*)(void *), void *); void ioasic_intr_disestablish(struct device *, void *); +int ioasic_submatch(void *, struct ioasicdev_attach_args *); +void ioasic_attach_devs(struct ioasic_softc *, + struct ioasic_dev *, int); - -/* - * Miscellaneous helper functions. - */ -int ioasic_submatch(struct cfdata *, struct ioasicdev_attach_args *); -char *ioasic_lance_ether_address(void); -void ioasic_lance_dma_setup(void *); +#endif /* _DEV_TC_IOASICVAR_ */ diff --git a/sys/dev/tc/tc.c b/sys/dev/tc/tc.c index 63a132da7a3..d11a1375ba9 100644 --- a/sys/dev/tc/tc.c +++ b/sys/dev/tc/tc.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc.c,v 1.11 2002/03/14 03:16:08 millert Exp $ */ -/* $NetBSD: tc.c,v 1.20 1996/10/22 21:37:29 cgd Exp $ */ +/* $OpenBSD: tc.c,v 1.12 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tc.c,v 1.29 2001/11/13 06:26:10 lukem Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -36,19 +36,6 @@ #include <dev/tc/tcvar.h> #include <dev/tc/tcdevs.h> -#include <machine/autoconf.h> /* for the proto of badaddr() */ - -struct tc_softc { - struct device sc_dv; - - int sc_speed; - int sc_nslots; - struct tc_slotdesc *sc_slots; - - void (*sc_intr_establish)(struct device *, void *, - tc_intrlevel_t, int (*)(void *), void *); - void (*sc_intr_disestablish)(struct device *, void *); -}; /* Definition of the driver for autoconfig. */ int tcmatch(struct device *, void *, void *); @@ -68,13 +55,12 @@ int tc_checkslot(tc_addr_t, char *); void tc_devinfo(const char *, char *); int -tcmatch(parent, cfdata, aux) +tcmatch(parent, vcf, aux) struct device *parent; - void *cfdata; - void *aux; + void *vcf, *aux; { - struct cfdata *cf = cfdata; struct tcbus_attach_args *tba = aux; + struct cfdata *cf = vcf; if (strcmp(tba->tba_busname, cf->cf_driver->cd_name)) return (0); @@ -105,8 +91,10 @@ tcattach(parent, self, aux) sc->sc_speed = tba->tba_speed; sc->sc_nslots = tba->tba_nslots; sc->sc_slots = tba->tba_slots; + sc->sc_intr_evcnt = tba->tba_intr_evcnt; sc->sc_intr_establish = tba->tba_intr_establish; sc->sc_intr_disestablish = tba->tba_intr_disestablish; + sc->sc_get_dma_tag = tba->tba_get_dma_tag; /* * Try to configure each built-in device @@ -131,9 +119,8 @@ tcattach(parent, self, aux) * Set up the device attachment information. */ strncpy(ta.ta_modname, builtin->tcb_modname, TC_ROM_LLEN); -#ifdef __alpha__ /* XXX */ ta.ta_memt = tba->tba_memt; -#endif + ta.ta_dmat = (*sc->sc_get_dma_tag)(builtin->tcb_slot); ta.ta_modname[TC_ROM_LLEN] = '\0'; ta.ta_slot = builtin->tcb_slot; ta.ta_offset = builtin->tcb_offset; @@ -174,6 +161,8 @@ tcattach(parent, self, aux) /* * Set up the rest of the attachment information. */ + ta.ta_memt = tba->tba_memt; + ta.ta_dmat = (*sc->sc_get_dma_tag)(i); ta.ta_slot = i; ta.ta_offset = 0; ta.ta_addr = tcaddr; @@ -209,12 +198,12 @@ tcprint(aux, pnp) } int -tcsubmatch(parent, match, aux) +tcsubmatch(parent, vcf, aux) struct device *parent; - void *match, *aux; + void *vcf, *aux; { - struct cfdata *cf = match; struct tc_attach_args *d = aux; + struct cfdata *cf = vcf; if ((cf->tccf_slot != TCCF_SLOT_UNKNOWN) && (cf->tccf_slot != d->ta_slot)) @@ -223,7 +212,7 @@ tcsubmatch(parent, match, aux) (cf->tccf_offset != d->ta_offset)) return 0; - return ((*cf->cf_attach->ca_match)(parent, match, aux)); + return ((*cf->cf_attach->ca_match)(parent, cf, aux)); } @@ -273,17 +262,24 @@ tc_checkslot(slotbase, namep) return (0); } +const struct evcnt * +tc_intr_evcnt(struct device *dev, void *cookie) +{ + struct tc_softc *sc = tc_cd.cd_devs[0]; + + return ((*sc->sc_intr_evcnt)(dev, cookie)); +} + void tc_intr_establish(dev, cookie, level, handler, arg) struct device *dev; void *cookie, *arg; - tc_intrlevel_t level; + int level; int (*handler)(void *); { - struct tc_softc *sc = (struct tc_softc *)dev; + struct tc_softc *sc = tc_cd.cd_devs[0]; - (*sc->sc_intr_establish)(sc->sc_dv.dv_parent, cookie, level, - handler, arg); + (*sc->sc_intr_establish)(dev, cookie, level, handler, arg); } void @@ -291,9 +287,9 @@ tc_intr_disestablish(dev, cookie) struct device *dev; void *cookie; { - struct tc_softc *sc = (struct tc_softc *)dev; + struct tc_softc *sc = tc_cd.cd_devs[0]; - (*sc->sc_intr_disestablish)(sc->sc_dv.dv_parent, cookie); + (*sc->sc_intr_disestablish)(dev, cookie); } #ifdef TCVERBOSE diff --git a/sys/dev/tc/tcdevs b/sys/dev/tc/tcdevs index cdf9662c160..0f6558ee15a 100644 --- a/sys/dev/tc/tcdevs +++ b/sys/dev/tc/tcdevs @@ -1,5 +1,5 @@ -$OpenBSD: tcdevs,v 1.5 1998/06/23 23:26:18 deraadt Exp $ -/* $NetBSD: tcdevs,v 1.6 1996/08/26 23:39:34 cgd Exp $ */ +$OpenBSD: tcdevs,v 1.6 2002/05/02 22:56:06 miod Exp $ +/* $NetBSD: tcdevs,v 1.17 2000/12/17 13:56:05 ad Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou @@ -32,21 +32,26 @@ $OpenBSD: tcdevs,v 1.5 1998/06/23 23:26:18 deraadt Exp $ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -+device AV01B-AA lofi DecAudio LoFi audio/isdn +device AV01B-AA lofi DecAudio \"LoFi\" audio/isdn +device AV300-AA ??? Video capture option card device DGLTA-FA otto DGLTA ATM device FORE_ATM fa Fore TCA-100 ATM device KZTSA-AA tza TZA FWD SCSI -device OTTO otto DEC SRC OTTO ATM +device OTTO otto DEC SRC \"OTTO\" ATM device PMAD-AA le LANCE Ethernet -device PMAF-AA fza DEFZA FDDI -device PMAF-F fta DEFTA FDDI +device PMAF-AA fza DEC FDDIcontroller 700 (DEFZA; fiber optic) +device PMAF-FA fta DEFTA FDDI device PMAG-AA mfb Monochrome Frame Buffer device PMAG-BA cfb Color Frame Buffer -device PMAG-CA ga 2D Graphics -device PMAG-DA gq 3D Graphics (LM) +device PMAG-CA px 2D Graphics (PX 2DA) +device PMAG-DA pxg 3D Graphics (PXG LM-3DA) +device PMAG-FA pxg 3D Graphics (PXG HE-3DA) +device PMAG-FB pxg 3D Graphics (PXG HE+3DA) +device PMAGB-FA pxg 3D Graphics (PXG HE+3DA) +device PMAGB-FB pxg 3D Graphics (PXG HE+3DA) # the following entry may be incorrect device PMAG-DV xcfb Maxine Color Frame Buffer -device PMAG-FA gq 3D Graphics (HE) +device PMAG-JA ??? 24-plane True Color Frame Buffer (TX) device PMAGB-BA sfb Smart Frame Buffer device PMAGD sfbp Smart Frame Buffer Plus, unknown bpp device PMAGD-AA sfbp Smart Frame Buffer Plus, 8bpp @@ -55,6 +60,25 @@ device PMAZ-AA asc 53c94 SCSI device PMAZ-DS tcds 53c94 TCDS SCSI (baseboard) device PMAZ-FS tcds 53c94 TCDS Fast SCSI (baseboard) device PMAZB-AA tcds 53c94 TCDS SCSI option card +device PMAZB-AB tcds 53c94 TCDS SCSI option card device PMAZC-AA tcds 53c94 TCDS Fast SCSI option card +device PMTNV-AA ??? Non-volatile RAM option card device T1D4PKT ds DECWRL Turbochannel T1 device T3PKT tt DECWRL Turbochannel T3 +device PMAT-AA tra DEC TurboChannel Token Ring Controller +device PMABV-AA vba VME Adapter +device PMAP-AA ??? Prestoserve +device KWS_TD ??? Kubota Denali + +# the following entries are unconfirmed +#device PMAD-AB le LANCE Ethernet +#device PMAF-CA fza DEC FDDIcontroller 700C (DEFZA; copper) +#device PMAG-DB ??? 8-plane 3D Grahpics (PXG) +#device PMAG-AB ??? Monochrome Graphics Adapter (MX) +#device PMAG-JB ??? 24-plane True Color Frame Buffer (TX) +#device PMAGB-BB ??? 8-plane Color/Grayscale 2D SFB (HX) +#device PMAGB-BC ??? 8-plane Color/Grayscale 2D SFB (HX) +#define PMAGB-BD ??? 8-plane Color/Grayscale 2D SFB (HX) +#define PMAGB-BE ??? 8-plane Color/Grayscale 2D SFB (HX) +#device PMAGB-JB ??? 24-plane True Color Frame Buffer (TX) +#device PMAZ-AB asc 53c94 SCSI diff --git a/sys/dev/tc/tcdevs.h b/sys/dev/tc/tcdevs.h index eaa29b985ea..9d4329fcb56 100644 --- a/sys/dev/tc/tcdevs.h +++ b/sys/dev/tc/tcdevs.h @@ -1,10 +1,12 @@ +/* $OpenBSD: tcdevs.h,v 1.6 2002/05/02 22:56:06 miod Exp $ */ + /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * OpenBSD: tcdevs,v 1.5 1998/06/23 23:26:18 deraadt Exp + * OpenBSD */ -/* $NetBSD: tcdevs,v 1.6 1996/08/26 23:39:34 cgd Exp $ */ +/* $NetBSD: tcdevs,v 1.17 2000/12/17 13:56:05 ad Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou @@ -37,6 +39,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define TC_DEVICE_AV01B_AA "lofi" +#define TC_DESCRIPTION_AV01B_AA "DecAudio \"LoFi\" audio/isdn" + +#define TC_DEVICE_AV300_AA "???" +#define TC_DESCRIPTION_AV300_AA "Video capture option card" + #define TC_DEVICE_DGLTA_FA "otto" #define TC_DESCRIPTION_DGLTA_FA "DGLTA ATM" @@ -47,16 +55,16 @@ #define TC_DESCRIPTION_KZTSA_AA "TZA FWD SCSI" #define TC_DEVICE_OTTO "otto" -#define TC_DESCRIPTION_OTTO "DEC SRC OTTO ATM" +#define TC_DESCRIPTION_OTTO "DEC SRC \"OTTO\" ATM" #define TC_DEVICE_PMAD_AA "le" #define TC_DESCRIPTION_PMAD_AA "LANCE Ethernet" #define TC_DEVICE_PMAF_AA "fza" -#define TC_DESCRIPTION_PMAF_AA "DEFZA FDDI" +#define TC_DESCRIPTION_PMAF_AA "DEC FDDIcontroller 700 (DEFZA; fiber optic)" -#define TC_DEVICE_PMAF_F "fta" -#define TC_DESCRIPTION_PMAF_F "DEFTA FDDI" +#define TC_DEVICE_PMAF_FA "fta" +#define TC_DESCRIPTION_PMAF_FA "DEFTA FDDI" #define TC_DEVICE_PMAG_AA "mfb" #define TC_DESCRIPTION_PMAG_AA "Monochrome Frame Buffer" @@ -64,17 +72,29 @@ #define TC_DEVICE_PMAG_BA "cfb" #define TC_DESCRIPTION_PMAG_BA "Color Frame Buffer" -#define TC_DEVICE_PMAG_CA "ga" -#define TC_DESCRIPTION_PMAG_CA "2D Graphics" +#define TC_DEVICE_PMAG_CA "px" +#define TC_DESCRIPTION_PMAG_CA "2D Graphics (PX 2DA)" + +#define TC_DEVICE_PMAG_DA "pxg" +#define TC_DESCRIPTION_PMAG_DA "3D Graphics (PXG LM-3DA)" + +#define TC_DEVICE_PMAG_FA "pxg" +#define TC_DESCRIPTION_PMAG_FA "3D Graphics (PXG HE-3DA)" + +#define TC_DEVICE_PMAG_FB "pxg" +#define TC_DESCRIPTION_PMAG_FB "3D Graphics (PXG HE+3DA)" + +#define TC_DEVICE_PMAGB_FA "pxg" +#define TC_DESCRIPTION_PMAGB_FA "3D Graphics (PXG HE+3DA)" -#define TC_DEVICE_PMAG_DA "gq" -#define TC_DESCRIPTION_PMAG_DA "3D Graphics (LM)" +#define TC_DEVICE_PMAGB_FB "pxg" +#define TC_DESCRIPTION_PMAGB_FB "3D Graphics (PXG HE+3DA)" #define TC_DEVICE_PMAG_DV "xcfb" #define TC_DESCRIPTION_PMAG_DV "Maxine Color Frame Buffer" -#define TC_DEVICE_PMAG_FA "gq" -#define TC_DESCRIPTION_PMAG_FA "3D Graphics (HE)" +#define TC_DEVICE_PMAG_JA "???" +#define TC_DESCRIPTION_PMAG_JA "24-plane True Color Frame Buffer (TX)" #define TC_DEVICE_PMAGB_BA "sfb" #define TC_DESCRIPTION_PMAGB_BA "Smart Frame Buffer" @@ -100,11 +120,29 @@ #define TC_DEVICE_PMAZB_AA "tcds" #define TC_DESCRIPTION_PMAZB_AA "53c94 TCDS SCSI option card" +#define TC_DEVICE_PMAZB_AB "tcds" +#define TC_DESCRIPTION_PMAZB_AB "53c94 TCDS SCSI option card" + #define TC_DEVICE_PMAZC_AA "tcds" #define TC_DESCRIPTION_PMAZC_AA "53c94 TCDS Fast SCSI option card" +#define TC_DEVICE_PMTNV_AA "???" +#define TC_DESCRIPTION_PMTNV_AA "Non-volatile RAM option card" + #define TC_DEVICE_T1D4PKT "ds" #define TC_DESCRIPTION_T1D4PKT "DECWRL Turbochannel T1" #define TC_DEVICE_T3PKT "tt" #define TC_DESCRIPTION_T3PKT "DECWRL Turbochannel T3" + +#define TC_DEVICE_PMAT_AA "tra" +#define TC_DESCRIPTION_PMAT_AA "DEC TurboChannel Token Ring Controller" + +#define TC_DEVICE_PMABV_AA "vba" +#define TC_DESCRIPTION_PMABV_AA "VME Adapter" + +#define TC_DEVICE_PMAP_AA "???" +#define TC_DESCRIPTION_PMAP_AA "Prestoserve" + +#define TC_DEVICE_KWS_TD "???" +#define TC_DESCRIPTION_KWS_TD "Kubota Denali" diff --git a/sys/dev/tc/tcdevs_data.h b/sys/dev/tc/tcdevs_data.h index 26bd3621093..c16f2ea9a9f 100644 --- a/sys/dev/tc/tcdevs_data.h +++ b/sys/dev/tc/tcdevs_data.h @@ -1,10 +1,12 @@ +/* $OpenBSD: tcdevs_data.h,v 1.6 2002/05/02 22:56:06 miod Exp $ */ + /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * OpenBSD: tcdevs,v 1.5 1998/06/23 23:26:18 deraadt Exp + * OpenBSD */ -/* $NetBSD: tcdevs,v 1.6 1996/08/26 23:39:34 cgd Exp $ */ +/* $NetBSD: tcdevs,v 1.17 2000/12/17 13:56:05 ad Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou @@ -39,6 +41,16 @@ struct tc_knowndev tc_knowndevs[] = { { + "AV01B-AA", + TC_DEVICE_AV01B_AA, + TC_DESCRIPTION_AV01B_AA, + }, + { + "AV300-AA", + TC_DEVICE_AV300_AA, + TC_DESCRIPTION_AV300_AA, + }, + { "DGLTA-FA", TC_DEVICE_DGLTA_FA, TC_DESCRIPTION_DGLTA_FA, @@ -69,9 +81,9 @@ struct tc_knowndev tc_knowndevs[] = { TC_DESCRIPTION_PMAF_AA, }, { - "PMAF-F ", - TC_DEVICE_PMAF_F, - TC_DESCRIPTION_PMAF_F, + "PMAF-FA ", + TC_DEVICE_PMAF_FA, + TC_DESCRIPTION_PMAF_FA, }, { "PMAG-AA ", @@ -94,14 +106,34 @@ struct tc_knowndev tc_knowndevs[] = { TC_DESCRIPTION_PMAG_DA, }, { + "PMAG-FA ", + TC_DEVICE_PMAG_FA, + TC_DESCRIPTION_PMAG_FA, + }, + { + "PMAG-FB ", + TC_DEVICE_PMAG_FB, + TC_DESCRIPTION_PMAG_FB, + }, + { + "PMAGB-FA", + TC_DEVICE_PMAGB_FA, + TC_DESCRIPTION_PMAGB_FA, + }, + { + "PMAGB-FB", + TC_DEVICE_PMAGB_FB, + TC_DESCRIPTION_PMAGB_FB, + }, + { "PMAG-DV ", TC_DEVICE_PMAG_DV, TC_DESCRIPTION_PMAG_DV, }, { - "PMAG-FA ", - TC_DEVICE_PMAG_FA, - TC_DESCRIPTION_PMAG_FA, + "PMAG-JA ", + TC_DEVICE_PMAG_JA, + TC_DESCRIPTION_PMAG_JA, }, { "PMAGB-BA", @@ -144,11 +176,21 @@ struct tc_knowndev tc_knowndevs[] = { TC_DESCRIPTION_PMAZB_AA, }, { + "PMAZB-AB", + TC_DEVICE_PMAZB_AB, + TC_DESCRIPTION_PMAZB_AB, + }, + { "PMAZC-AA", TC_DEVICE_PMAZC_AA, TC_DESCRIPTION_PMAZC_AA, }, { + "PMTNV-AA", + TC_DEVICE_PMTNV_AA, + TC_DESCRIPTION_PMTNV_AA, + }, + { "T1D4PKT ", TC_DEVICE_T1D4PKT, TC_DESCRIPTION_T1D4PKT, @@ -158,5 +200,25 @@ struct tc_knowndev tc_knowndevs[] = { TC_DEVICE_T3PKT, TC_DESCRIPTION_T3PKT, }, + { + "PMAT-AA ", + TC_DEVICE_PMAT_AA, + TC_DESCRIPTION_PMAT_AA, + }, + { + "PMABV-AA", + TC_DEVICE_PMABV_AA, + TC_DESCRIPTION_PMABV_AA, + }, + { + "PMAP-AA ", + TC_DEVICE_PMAP_AA, + TC_DESCRIPTION_PMAP_AA, + }, + { + "KWS_TD ", + TC_DEVICE_KWS_TD, + TC_DESCRIPTION_KWS_TD, + }, { NULL, NULL, NULL, } }; diff --git a/sys/dev/tc/tcds.c b/sys/dev/tc/tcds.c new file mode 100644 index 00000000000..a69e5c7805f --- /dev/null +++ b/sys/dev/tc/tcds.c @@ -0,0 +1,602 @@ +/* $OpenBSD: tcds.c,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tcds.c,v 1.3 2001/11/13 06:26:10 lukem Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Keith Bostic, Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#ifdef __alpha__ +#include <machine/rpb.h> +#endif /* __alpha__ */ + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <dev/ic/ncr53c9xvar.h> + +#include <machine/bus.h> + +#ifndef EVCNT_COUNTERS +#include <machine/intrcnt.h> +#endif + +#include <dev/tc/tcvar.h> +#include <dev/tc/tcdsreg.h> +#include <dev/tc/tcdsvar.h> + +struct tcds_softc { + struct device sc_dv; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + bus_dma_tag_t sc_dmat; + void *sc_cookie; + int sc_flags; + struct tcds_slotconfig sc_slots[2]; +}; + +/* sc_flags */ +#define TCDSF_BASEBOARD 0x01 /* baseboard on DEC 3000 */ +#define TCDSF_FASTSCSI 0x02 /* supports Fast SCSI */ + +/* Definition of the driver for autoconfig. */ +int tcdsmatch(struct device *, void *, void *); +void tcdsattach(struct device *, struct device *, void *); +int tcdsprint(void *, const char *); +int tcdssubmatch(struct device *, void *, void *); + +struct cfattach tcds_ca = { + sizeof(struct tcds_softc), tcdsmatch, tcdsattach, +}; + +struct cfdriver tcds_cd = { + NULL, "tcds", DV_DULL, +}; + +/*static*/ int tcds_intr(void *); +/*static*/ int tcds_intrnull(void *); + +struct tcds_device { + const char *td_name; + int td_flags; +} tcds_devices[] = { +#ifdef __alpha__ + { "PMAZ-DS ", TCDSF_BASEBOARD }, + { "PMAZ-FS ", TCDSF_BASEBOARD|TCDSF_FASTSCSI }, +#endif /* __alpha__ */ + { "PMAZB-AA", 0 }, + { "PMAZC-AA", TCDSF_FASTSCSI }, + { NULL, 0 }, +}; + +struct tcds_device *tcds_lookup(const char *); +void tcds_params(struct tcds_softc *, int, int *, int *); + +struct tcds_device * +tcds_lookup(modname) + const char *modname; +{ + struct tcds_device *td; + + for (td = tcds_devices; td->td_name != NULL; td++) + if (strncmp(td->td_name, modname, TC_ROM_LLEN) == 0) + return (td); + + return (NULL); +} + +int +tcdsmatch(parent, cfdata, aux) + struct device *parent; + void *cfdata, *aux; +{ + struct tc_attach_args *ta = aux; + + return (tcds_lookup(ta->ta_modname) != NULL); +} + +void +tcdsattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct tcds_softc *sc = (struct tcds_softc *)self; + struct tc_attach_args *ta = aux; + struct tcdsdev_attach_args tcdsdev; + struct tcds_slotconfig *slotc; + struct tcds_device *td; + bus_space_handle_t sbsh[2]; + int i, gpi2; + const struct evcnt *pevcnt; + + td = tcds_lookup(ta->ta_modname); + if (td == NULL) + panic("\ntcdsattach: impossible"); + + printf(": TurboChannel Dual SCSI"); + if (td->td_flags & TCDSF_BASEBOARD) + printf(" (baseboard)"); + printf("\n"); + + sc->sc_flags = td->td_flags; + + sc->sc_bst = ta->ta_memt; + sc->sc_dmat = ta->ta_dmat; + + /* + * Map the device. + */ + if (bus_space_map(sc->sc_bst, ta->ta_addr, + (TCDS_SCSI1_OFFSET + 0x100), 0, &sc->sc_bsh)) { + printf("%s: unable to map device\n", sc->sc_dv.dv_xname); + return; + } + + /* + * Now, slice off two subregions for the individual NCR SCSI chips. + */ + if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, TCDS_SCSI0_OFFSET, + 0x100, &sbsh[0]) || + bus_space_subregion(sc->sc_bst, sc->sc_bsh, TCDS_SCSI1_OFFSET, + 0x100, &sbsh[1])) { + printf("%s: unable to subregion SCSI chip space\n", + sc->sc_dv.dv_xname); + return; + } + + sc->sc_cookie = ta->ta_cookie; + + pevcnt = tc_intr_evcnt(parent, sc->sc_cookie); + tc_intr_establish(parent, sc->sc_cookie, TC_IPL_BIO, tcds_intr, sc); + + /* + * XXX + * IMER apparently has some random (or, not so random, but still + * not useful) bits set in it when the system boots. Clear it. + */ + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER, 0); + + /* XXX Initial contents of CIR? */ + + /* + * Remember if GPI2 is set in the CIR; we'll need it later. + */ + gpi2 = (bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR) & + TCDS_CIR_GPI_2) != 0; + + /* + * Set up the per-slot defintions for later use. + */ + + /* fill in common information first */ + for (i = 0; i < 2; i++) { + char *cp; + + slotc = &sc->sc_slots[i]; + bzero(slotc, sizeof *slotc); /* clear everything */ + + cp = slotc->sc_name; + snprintf(cp, sizeof(slotc->sc_name), "chip %d", i); +#ifdef EVCNT_COUNTERS + evcnt_attach_dynamic(&slotc->sc_evcnt, EVCNT_TYPE_INTR, + pevcnt, sc->sc_dv.dv_xname, cp); +#endif + + slotc->sc_slot = i; + slotc->sc_bst = sc->sc_bst; + slotc->sc_bsh = sc->sc_bsh; + slotc->sc_intrhand = tcds_intrnull; + slotc->sc_intrarg = (void *)(long)i; + } + + /* information for slot 0 */ + slotc = &sc->sc_slots[0]; + slotc->sc_resetbits = TCDS_CIR_SCSI0_RESET; + slotc->sc_intrmaskbits = + TCDS_IMER_SCSI0_MASK | TCDS_IMER_SCSI0_ENB; + slotc->sc_intrbits = TCDS_CIR_SCSI0_INT; + slotc->sc_dmabits = TCDS_CIR_SCSI0_DMAENA; + slotc->sc_errorbits = 0; /* XXX */ + slotc->sc_sda = TCDS_SCSI0_DMA_ADDR; + slotc->sc_dic = TCDS_SCSI0_DMA_INTR; + slotc->sc_dud0 = TCDS_SCSI0_DMA_DUD0; + slotc->sc_dud1 = TCDS_SCSI0_DMA_DUD1; + + /* information for slot 1 */ + slotc = &sc->sc_slots[1]; + slotc->sc_resetbits = TCDS_CIR_SCSI1_RESET; + slotc->sc_intrmaskbits = + TCDS_IMER_SCSI1_MASK | TCDS_IMER_SCSI1_ENB; + slotc->sc_intrbits = TCDS_CIR_SCSI1_INT; + slotc->sc_dmabits = TCDS_CIR_SCSI1_DMAENA; + slotc->sc_errorbits = 0; /* XXX */ + slotc->sc_sda = TCDS_SCSI1_DMA_ADDR; + slotc->sc_dic = TCDS_SCSI1_DMA_INTR; + slotc->sc_dud0 = TCDS_SCSI1_DMA_DUD0; + slotc->sc_dud1 = TCDS_SCSI1_DMA_DUD1; + + /* find the hardware attached to the TCDS ASIC */ + for (i = 0; i < 2; i++) { + tcds_params(sc, i, &tcdsdev.tcdsda_id, + &tcdsdev.tcdsda_fast); + + tcdsdev.tcdsda_bst = sc->sc_bst; + tcdsdev.tcdsda_bsh = sbsh[i]; + tcdsdev.tcdsda_dmat = sc->sc_dmat; + tcdsdev.tcdsda_chip = i; + tcdsdev.tcdsda_sc = &sc->sc_slots[i]; + /* + * Determine the chip frequency. TCDSF_FASTSCSI will be set + * for TC option cards. For baseboard chips, GPI2 is set, for a + * 25MHz clock, else a 40MHz clock. + */ + if ((sc->sc_flags & TCDSF_BASEBOARD && gpi2 == 0) || + sc->sc_flags & TCDSF_FASTSCSI) { + tcdsdev.tcdsda_freq = 40000000; + tcdsdev.tcdsda_period = tcdsdev.tcdsda_fast ? 4 : 8; + } else { + tcdsdev.tcdsda_freq = 25000000; + tcdsdev.tcdsda_period = 5; + } + if (sc->sc_flags & TCDSF_BASEBOARD) + tcdsdev.tcdsda_variant = NCR_VARIANT_NCR53C94; + else + tcdsdev.tcdsda_variant = NCR_VARIANT_NCR53C96; + + tcds_scsi_reset(tcdsdev.tcdsda_sc); + + config_found_sm(self, &tcdsdev, tcdsprint, tcdssubmatch); +#ifdef __alpha__ + /* + * The second SCSI chip isn't present on the baseboard TCDS + * on the DEC Alpha 3000/300 series. + */ + if (sc->sc_flags & TCDSF_BASEBOARD && + cputype == ST_DEC_3000_300) + break; +#endif /* __alpha__ */ + } +} + +int +tcdssubmatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct tcdsdev_attach_args *tcdsdev = aux; + struct cfdata *cf = vcf; + + if (cf->cf_loc[0] != -1 && + cf->cf_loc[0] != tcdsdev->tcdsda_chip) + return (0); + + return ((*cf->cf_attach->ca_match)(parent, vcf, aux)); +} + +int +tcdsprint(aux, pnp) + void *aux; + const char *pnp; +{ + struct tcdsdev_attach_args *tcdsdev = aux; + + /* Only ASCs can attach to TCDSs; easy. */ + if (pnp) + printf("asc at %s", pnp); + + printf(" chip %d", tcdsdev->tcdsda_chip); + + return (UNCONF); +} + +void +tcds_intr_establish(tcds, slot, func, arg) + struct device *tcds; + int slot; + int (*func)(void *); + void *arg; +{ + struct tcds_softc *sc = (struct tcds_softc *)tcds; + + if (sc->sc_slots[slot].sc_intrhand != tcds_intrnull) + panic("tcds_intr_establish: chip %d twice", slot); + + sc->sc_slots[slot].sc_intrhand = func; + sc->sc_slots[slot].sc_intrarg = arg; + tcds_scsi_reset(&sc->sc_slots[slot]); +} + +void +tcds_intr_disestablish(tcds, slot) + struct device *tcds; + int slot; +{ + struct tcds_softc *sc = (struct tcds_softc *)tcds; + + if (sc->sc_slots[slot].sc_intrhand == tcds_intrnull) + panic("tcds_intr_disestablish: chip %d missing intr", + slot); + + sc->sc_slots[slot].sc_intrhand = tcds_intrnull; + sc->sc_slots[slot].sc_intrarg = (void *)(u_long)slot; + + tcds_dma_enable(&sc->sc_slots[slot], 0); + tcds_scsi_enable(&sc->sc_slots[slot], 0); +} + +int +tcds_intrnull(val) + void *val; +{ + + panic("tcds_intrnull: uncaught TCDS intr for chip %lu\n", + (u_long)val); +} + +void +tcds_scsi_reset(sc) + struct tcds_slotconfig *sc; +{ + u_int32_t cir; + + tcds_dma_enable(sc, 0); + tcds_scsi_enable(sc, 0); + + cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + TCDS_CIR_CLR(cir, sc->sc_resetbits); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); + + DELAY(1); + + cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + TCDS_CIR_SET(cir, sc->sc_resetbits); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); + + tcds_scsi_enable(sc, 1); + tcds_dma_enable(sc, 1); +} + +void +tcds_scsi_enable(sc, on) + struct tcds_slotconfig *sc; + int on; +{ + u_int32_t imer; + + imer = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER); + + if (on) + imer |= sc->sc_intrmaskbits; + else + imer &= ~sc->sc_intrmaskbits; + + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER, imer); +} + +void +tcds_dma_enable(sc, on) + struct tcds_slotconfig *sc; + int on; +{ + u_int32_t cir; + + cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + + /* XXX Clear/set IOSLOT/PBS bits. */ + if (on) + TCDS_CIR_SET(cir, sc->sc_dmabits); + else + TCDS_CIR_CLR(cir, sc->sc_dmabits); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); +} + +int +tcds_scsi_isintr(sc, clear) + struct tcds_slotconfig *sc; + int clear; +{ + u_int32_t cir; + + cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + + if ((cir & sc->sc_intrbits) != 0) { + if (clear) { + TCDS_CIR_CLR(cir, sc->sc_intrbits); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, + cir); + } + return (1); + } else + return (0); +} + +int +tcds_scsi_iserr(sc) + struct tcds_slotconfig *sc; +{ + u_int32_t cir; + + cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + return ((cir & sc->sc_errorbits) != 0); +} + +int +tcds_intr(arg) + void *arg; +{ + struct tcds_softc *sc = arg; + u_int32_t ir, ir0; + + /* + * XXX + * Copy and clear (gag!) the interrupts. + */ + ir = ir0 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); + TCDS_CIR_CLR(ir0, TCDS_CIR_ALLINTR); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, ir0); + tc_syncbus(); + +#ifdef EVCNT_COUNTERS +#define INCRINTRCNT(slot) sc->sc_slots[slot].sc_evcnt.ev_count++ +#else +#define INCRINTRCNT(slot) intrcnt[INTRCNT_TCDS + slot]++ +#endif + +#define CHECKINTR(slot) \ + if (ir & sc->sc_slots[slot].sc_intrbits) { \ + INCRINTRCNT(slot); \ + (void)(*sc->sc_slots[slot].sc_intrhand) \ + (sc->sc_slots[slot].sc_intrarg); \ + } + CHECKINTR(0); + CHECKINTR(1); +#undef CHECKINTR + +#ifdef DIAGNOSTIC + /* + * Interrupts not currently handled, but would like to know if they + * occur. + * + * XXX + * Don't know if we have to set the interrupt mask and enable bits + * in the IMER to allow some of them to happen? + */ +#define PRINTINTR(msg, bits) \ + if (ir & bits) \ + printf("%s: %s", sc->sc_dv.dv_xname, msg); + PRINTINTR("SCSI0 DREQ interrupt.\n", TCDS_CIR_SCSI0_DREQ); + PRINTINTR("SCSI1 DREQ interrupt.\n", TCDS_CIR_SCSI1_DREQ); + PRINTINTR("SCSI0 prefetch interrupt.\n", TCDS_CIR_SCSI0_PREFETCH); + PRINTINTR("SCSI1 prefetch interrupt.\n", TCDS_CIR_SCSI1_PREFETCH); + PRINTINTR("SCSI0 DMA error.\n", TCDS_CIR_SCSI0_DMA); + PRINTINTR("SCSI1 DMA error.\n", TCDS_CIR_SCSI1_DMA); + PRINTINTR("SCSI0 DB parity error.\n", TCDS_CIR_SCSI0_DB); + PRINTINTR("SCSI1 DB parity error.\n", TCDS_CIR_SCSI1_DB); + PRINTINTR("SCSI0 DMA buffer parity error.\n", TCDS_CIR_SCSI0_DMAB_PAR); + PRINTINTR("SCSI1 DMA buffer parity error.\n", TCDS_CIR_SCSI1_DMAB_PAR); + PRINTINTR("SCSI0 DMA read parity error.\n", TCDS_CIR_SCSI0_DMAR_PAR); + PRINTINTR("SCSI1 DMA read parity error.\n", TCDS_CIR_SCSI1_DMAR_PAR); + PRINTINTR("TC write parity error.\n", TCDS_CIR_TCIOW_PAR); + PRINTINTR("TC I/O address parity error.\n", TCDS_CIR_TCIOA_PAR); +#undef PRINTINTR +#endif + + /* + * XXX + * The MACH source had this, with the comment: + * This is wrong, but machine keeps dying. + */ + DELAY(1); + + return (1); +} + +void +tcds_params(sc, chip, idp, fastp) + struct tcds_softc *sc; + int chip, *idp, *fastp; +{ + int id, fast; + u_int32_t ids; + +#ifdef __alpha__ + if (sc->sc_flags & TCDSF_BASEBOARD) { + extern u_int8_t dec_3000_scsiid[], dec_3000_scsifast[]; + + id = dec_3000_scsiid[chip]; + fast = dec_3000_scsifast[chip]; + } else +#endif /* __alpha__ */ + { + /* + * SCSI IDs are stored in the EEPROM, along with whether or + * not the device is "fast". Chip 0 is the high nibble, + * chip 1 the low nibble. + */ + ids = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_EEPROM_IDS); + if (chip == 0) + ids >>= 4; + + id = ids & 0x7; + fast = ids & 0x8; + } + + if (id < 0 || id > 7) { + printf("%s: WARNING: bad SCSI ID %d for chip %d, using 7\n", + sc->sc_dv.dv_xname, id, chip); + id = 7; + } + + if (fast) + printf("%s: fast mode set for chip %d\n", + sc->sc_dv.dv_xname, chip); + + *idp = id; + *fastp = fast; +} diff --git a/sys/arch/alpha/tc/tcdsreg.h b/sys/dev/tc/tcdsreg.h index 02cfdba2102..974f913a7d1 100644 --- a/sys/arch/alpha/tc/tcdsreg.h +++ b/sys/dev/tc/tcdsreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tcdsreg.h,v 1.4 2002/03/14 01:26:28 millert Exp $ */ -/* $NetBSD: tcdsreg.h,v 1.2 1996/07/09 00:55:42 cgd Exp $ */ +/* $OpenBSD: tcdsreg.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tcdsreg.h,v 1.1 2000/07/04 02:22:20 nisimura Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -37,6 +37,9 @@ /* * TCDS register offsets, bit masks. */ +#define TCDS_EEPROM 0x000000 /* EEPROM offset */ +#define TCDS_EEPROM_IDS 0x000008 /* SCSI IDs offset in EEPROM */ + #define TCDS_CIR 0x040000 /* CIR offset */ /* @@ -48,7 +51,7 @@ #define TCDS_CIR_STD 0x00000008 /* Serial transmit disable */ #define TCDS_CIR_GPI_0 0x00000010 /* Not used */ #define TCDS_CIR_GPI_1 0x00000020 /* Not used */ -#define TCDS_CIR_GPI_2 0x00000040 /* Not used */ +#define TCDS_CIR_GPI_2 0x00000040 /* 1 = 25MHz, 0 = 40MHz */ #define TCDS_CIR_GPI_3 0x00000080 /* Not used */ #define TCDS_CIR_SCSI0_DMAENA 0x00000100 /* SCSI 0 DMA enable */ #define TCDS_CIR_SCSI1_DMAENA 0x00000200 /* SCSI 1 DMA enable */ @@ -132,7 +135,7 @@ void tcds_scsi_reset(int); /* * XXX - * Start of MACH #defines, minimal changes to port to {Net/Open}BSD. + * Start of MACH #defines, minimal changes to port to NetBSD. * * The following register is the SCSI control interrupt register. It * starts, stops and resets scsi DMA. It takes over the SCSI funtions diff --git a/sys/arch/alpha/tc/tcdsvar.h b/sys/dev/tc/tcdsvar.h index 5c73d575a94..e1470188d10 100644 --- a/sys/arch/alpha/tc/tcdsvar.h +++ b/sys/dev/tc/tcdsvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tcdsvar.h,v 1.8 2002/03/15 01:20:04 millert Exp $ */ -/* $NetBSD: tcdsvar.h,v 1.5 1996/11/13 21:13:38 cgd Exp $ */ +/* $OpenBSD: tcdsvar.h,v 1.1 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tcdsvar.h,v 1.2 2001/08/22 05:00:27 nisimura Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -33,10 +33,14 @@ struct tcds_slotconfig { * Bookkeeping information */ int sc_slot; - struct tcds_softc *sc_tcds; /* to frob TCDS regs */ - struct esp_softc *sc_esp; /* to frob child's regs */ + + bus_space_tag_t sc_bst; /* to frob TCDS regs */ + bus_space_handle_t sc_bsh; + int (*sc_intrhand)(void *); /* intr. handler */ void *sc_intrarg; /* intr. handler arg. */ + struct evcnt sc_evcnt; /* intr. count */ + char sc_name[8]; /* ev_name */ /* * Sets of bits in TCDS CIR and IMER that enable/check @@ -49,64 +53,35 @@ struct tcds_slotconfig { u_int32_t sc_errorbits; /* - * Pointers to slot-specific DMA resources. + * Offsets to slot-specific DMA resources. */ - volatile u_int32_t *sc_sda; - volatile u_int32_t *sc_dic; - volatile u_int32_t *sc_dud0; - volatile u_int32_t *sc_dud1; - - /* - * DMA bookkeeping information. - */ - int sc_active; /* DMA active ? */ - int sc_iswrite; /* DMA into main memory? */ - size_t sc_dmasize; - caddr_t *sc_dmaaddr; - size_t *sc_dmalen; + bus_size_t sc_sda; + bus_size_t sc_dic; + bus_size_t sc_dud0; + bus_size_t sc_dud1; }; struct tcdsdev_attach_args { - struct tc_attach_args tcdsda_ta; - struct tcds_slotconfig *tcdsda_sc; - u_int tcdsda_id; - u_int tcdsda_freq; + bus_space_tag_t tcdsda_bst; /* bus space tag */ + bus_space_handle_t tcdsda_bsh; /* bus space handle */ + bus_dma_tag_t tcdsda_dmat; /* bus dma tag */ + struct tcds_slotconfig *tcdsda_sc; /* slot configuration */ + int tcdsda_chip; /* chip number */ + int tcdsda_id; /* SCSI ID */ + u_int tcdsda_freq; /* chip frequency */ + int tcdsda_period; /* min. sync period */ + int tcdsda_variant; /* NCR chip variant */ + int tcdsda_fast; /* chip does Fast mode */ }; -#define tcdsda_modname tcdsda_ta.ta_modname -#define tcdsda_slot tcdsda_ta.ta_slot -#define tcdsda_offset tcdsda_ta.ta_offset -#define tcdsda_addr tcdsda_ta.ta_addr -#define tcdsda_cookie tcdsda_ta.ta_cookie - -#define TCDS_REG(base, off) \ - (volatile u_int32_t *)TC_DENSE_TO_SPARSE((base) + (off)) /* * TCDS functions. */ -void tcds_intr_establish(struct device *, void *, tc_intrlevel_t, +void tcds_intr_establish(struct device *, int, int (*)(void *), void *); -void tcds_intr_disestablish(struct device *, void *); +void tcds_intr_disestablish(struct device *, int); void tcds_dma_enable(struct tcds_slotconfig *, int); void tcds_scsi_enable(struct tcds_slotconfig *, int); int tcds_scsi_iserr(struct tcds_slotconfig *); int tcds_scsi_isintr(struct tcds_slotconfig *, int); void tcds_scsi_reset(struct tcds_slotconfig *); -int tcds_scsi_iserr(struct tcds_slotconfig *); - -/* - * TCDS DMA functions (used the the 53c94 driver) - */ -int tcds_dma_isintr(struct tcds_slotconfig *); -void tcds_dma_reset(struct tcds_slotconfig *); -int tcds_dma_intr(struct tcds_slotconfig *); -int tcds_dma_setup(struct tcds_slotconfig *, caddr_t *, size_t *, - int, size_t *); -void tcds_dma_go(struct tcds_slotconfig *); -int tcds_dma_isactive(struct tcds_slotconfig *); - -/* - * The TCDS (bus) cfdriver, so that subdevices can more - * easily tell what bus they're on. - */ -extern struct cfdriver tcds_cd; diff --git a/sys/dev/tc/tcreg.h b/sys/dev/tc/tcreg.h index 7cfe4de700f..115c749953d 100644 --- a/sys/dev/tc/tcreg.h +++ b/sys/dev/tc/tcreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcreg.h,v 1.2 1997/11/07 08:07:52 niklas Exp $ */ +/* $OpenBSD: tcreg.h,v 1.3 2002/05/02 22:56:06 miod Exp $ */ /* $NetBSD: tcreg.h,v 1.1 1995/12/20 00:48:36 cgd Exp $ */ /* diff --git a/sys/dev/tc/tcvar.h b/sys/dev/tc/tcvar.h index 9725a823a6d..4c563692a76 100644 --- a/sys/dev/tc/tcvar.h +++ b/sys/dev/tc/tcvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tcvar.h,v 1.9 2002/03/14 03:16:08 millert Exp $ */ -/* $NetBSD: tcvar.h,v 1.7 1996/10/22 21:37:31 cgd Exp $ */ +/* $OpenBSD: tcvar.h,v 1.10 2002/05/02 22:56:06 miod Exp $ */ +/* $NetBSD: tcvar.h,v 1.17 2000/06/04 19:15:15 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -32,7 +32,7 @@ #define __DEV_TC_TCVAR_H__ /* - * Definitions for TurboChannel autoconfiguration. + * Definitions for TURBOchannel autoconfiguration. */ #include <machine/bus.h> @@ -41,23 +41,16 @@ /* * Machine-dependent definitions. */ -#if !defined(__alpha__) -ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE. -#endif -#ifdef __alpha__ -#include <alpha/tc/tc_machdep.h> -#endif +#include <machine/tc_machdep.h> /* - * In the long run, the following block will go completely away - * (i.e. both parts of the #if, including the #include, etc.). - * For now, the MI TC code still uses the old definitions provided - * by the pmax port, and not the new definitions provided by the - * alpha port. + * In the long run, the following block will go completely away. + * For now, the MI TC code still uses the old TC_IPL_ names + * and not the new IPL_ names. */ -#ifdef __alpha__ +#if 1 /* - * On the alpha, map the new definitions to the old. + * Map the new definitions to the old. */ #include <machine/intr.h> @@ -68,17 +61,28 @@ ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE. #define TC_IPL_NET IPL_NET #define TC_IPL_TTY IPL_TTY #define TC_IPL_CLOCK IPL_CLOCK +#endif /* 1 */ -#endif +struct tc_softc { + struct device sc_dv; + + int sc_speed; + int sc_nslots; + struct tc_slotdesc *sc_slots; + + const struct evcnt *(*sc_intr_evcnt)(struct device *, void *); + void (*sc_intr_establish)(struct device *, void *, + int, int (*)(void *), void *); + void (*sc_intr_disestablish)(struct device *, void *); + bus_dma_tag_t (*sc_get_dma_tag)(int); +}; /* - * Arguments used to attach TurboChannel busses. + * Arguments used to attach TURBOchannel busses. */ struct tcbus_attach_args { char *tba_busname; /* XXX should be common */ -#ifdef __alpha__ /* XXX */ bus_space_tag_t tba_memt; -#endif /* Bus information */ u_int tba_speed; /* see TC_SPEED_* below */ @@ -89,18 +93,19 @@ struct tcbus_attach_args { /* TC bus resource management; XXX will move elsewhere eventually. */ + const struct evcnt *(*tba_intr_evcnt)(struct device *, void *); void (*tba_intr_establish)(struct device *, void *, - tc_intrlevel_t, int (*)(void *), void *); + int, int (*)(void *), void *); void (*tba_intr_disestablish)(struct device *, void *); + bus_dma_tag_t (*tba_get_dma_tag)(int); }; /* - * Arguments used to attach TurboChannel devices. + * Arguments used to attach TURBOchannel devices. */ struct tc_attach_args { -#ifdef __alpha__ /* XXX */ bus_space_tag_t ta_memt; -#endif + bus_dma_tag_t ta_dmat; char ta_modname[TC_ROM_LLEN+1]; u_int ta_slot; @@ -111,8 +116,8 @@ struct tc_attach_args { }; /* - * Description of TurboChannel slots, provided by machine-dependent - * code to the TurboChannel bus driver. + * Description of TURBOchannel slots, provided by machine-dependent + * code to the TURBOchannel bus driver. */ struct tc_slotdesc { tc_addr_t tcs_addr; @@ -121,8 +126,8 @@ struct tc_slotdesc { }; /* - * Description of built-in TurboChannel devices, provided by - * machine-dependent code to the TurboChannel bus driver. + * Description of built-in TURBOchannel devices, provided by + * machine-dependent code to the TURBOchannel bus driver. */ struct tc_builtin { char *tcb_modname; @@ -134,12 +139,16 @@ struct tc_builtin { /* * Interrupt establishment functions. */ -void tc_intr_establish(struct device *, void *, tc_intrlevel_t, - int (*)(void *), void *); +int tc_checkslot(tc_addr_t, char *); +void tc_devinfo(const char *, char *); +void tcattach(struct device *, struct device *, void *); +const struct evcnt *tc_intr_evcnt(struct device *, void *); +void tc_intr_establish(struct device *, void *, int, int (*)(void *), + void *); void tc_intr_disestablish(struct device *, void *); /* - * Easy to remember names for TurboChannel device locators. + * Easy to remember names for TURBOchannel device locators. */ #define tccf_slot cf_loc[0] /* slot */ #define tccf_offset cf_loc[1] /* offset */ @@ -153,10 +162,4 @@ void tc_intr_disestablish(struct device *, void *); #define TC_SPEED_12_5_MHZ 0 /* 12.5MHz TC bus */ #define TC_SPEED_25_MHZ 1 /* 25MHz TC bus */ -/* - * The TurboChannel bus cfdriver, so that subdevices can more - * easily tell what bus they're on. - */ -extern struct cfdriver tc_cd; - #endif /* __DEV_TC_TCVAR_H__ */ |