diff options
Diffstat (limited to 'sys/arch/alpha/tc')
28 files changed, 1172 insertions, 4623 deletions
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_machdep.h b/sys/arch/alpha/tc/tc_machdep.h deleted file mode 100644 index 3c26c5c8f85..00000000000 --- a/sys/arch/alpha/tc/tc_machdep.h +++ /dev/null @@ -1,95 +0,0 @@ -/* $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 $ */ - -/* - * 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. - */ - -/* - * Machine-specific definitions for TurboChannel support. - * - * This file must typedef the following types: - * - * tc_addr_t TurboChannel bus address - * tc_offset_t TurboChannel bus address difference (offset) - * - * This file must prototype or define the following functions - * or macros (one or more of which may be no-ops): - * - * tc_mb() read/write memory barrier (any CPU<->memory - * reads/writes before must complete before any - * CPU<->memory reads/writes after). - * tc_wmb() write memory barrier (any CPU<->memory writes - * before must complete before any CPU<->memory - * writes after). - * tc_syncbus() sync TC bus; make sure CPU writes are - * propagated across the TurboChannel bus. - * tc_badaddr() return non-zero if the given address is invalid. - * TC_DENSE_TO_SPARSE() - * convert the given physical address in - * TurboChannel dense space to the corresponding - * address in TurboChannel sparse space. - * TC_PHYS_TO_UNCACHED() - * convert the given system memory physical address - * to the physical address of the corresponding - * region that is not cached. - */ - -typedef u_int64_t tc_addr_t; -typedef int32_t tc_offset_t; - -#define tc_mb() alpha_mb() -#define tc_wmb() alpha_wmb() - -/* - * A junk address to read from, to make sure writes are complete. See - * System Programmer's Manual, section 9.3 (p. 9-4), and sacrifice a - * chicken. - */ -#define tc_syncbus() \ - do { \ - volatile u_int32_t no_optimize; \ - no_optimize = \ - *(volatile u_int32_t *)ALPHA_PHYS_TO_K0SEG(0x00000001f0080220); \ - } while (0) - -#define tc_badaddr(tcaddr) \ - badaddr((void *)(tcaddr), sizeof (u_int32_t)) - -#define TC_SPACE_IND 0xffffffffe0000003 -#define TC_SPACE_DENSE 0x0000000000000000 -#define TC_SPACE_DENSE_OFFSET 0x0000000007fffffc -#define TC_SPACE_SPARSE 0x0000000010000000 -#define TC_SPACE_SPARSE_OFFSET 0x000000000ffffff8 - -#define TC_DENSE_TO_SPARSE(addr) \ - (((addr) & TC_SPACE_IND) | TC_SPACE_SPARSE | \ - (((addr) & TC_SPACE_DENSE_OFFSET) << 1)) - -#define TC_PHYS_TO_UNCACHED(addr) \ - (addr) - -bus_space_tag_t tc_bus_mem_init(void *memv);; 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/arch/alpha/tc/tcdsreg.h b/sys/arch/alpha/tc/tcdsreg.h deleted file mode 100644 index 02cfdba2102..00000000000 --- a/sys/arch/alpha/tc/tcdsreg.h +++ /dev/null @@ -1,215 +0,0 @@ -/* $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 $ */ - -/* - * Copyright (c) 1994, 1995 Carnegie-Mellon University. - * All rights reserved. - * - * Authors: 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. - */ - -/* - * Offsets to the SCSI chips - */ -#define TCDS_SCSI0_OFFSET 0x080000 -#define TCDS_SCSI1_OFFSET 0x080100 - -/* - * TCDS register offsets, bit masks. - */ -#define TCDS_CIR 0x040000 /* CIR offset */ - -/* - * TCDS CIR control bits. - */ -#define TCDS_CIR_GPO_0 0x00000001 /* Not used */ -#define TCDS_CIR_GPO_1 0x00000002 /* Not used */ -#define TCDS_CIR_GPO_2 0x00000004 /* Not used */ -#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_3 0x00000080 /* Not used */ -#define TCDS_CIR_SCSI0_DMAENA 0x00000100 /* SCSI 0 DMA enable */ -#define TCDS_CIR_SCSI1_DMAENA 0x00000200 /* SCSI 1 DMA enable */ -#define TCDS_CIR_SCSI0_RESET 0x00000400 /* SCSI 0 reset */ -#define TCDS_CIR_SCSI1_RESET 0x00000800 /* SCSI 1 reset */ -#define TCDS_CIR_SCSI0_DMA_TEST 0x00001000 /* SCSI 0 DMA buf parity test */ -#define TCDS_CIR_SCSI1_DMA_TEST 0x00002000 /* SCSI 1 DMA buf parity test */ -#define TCDS_CIR_DB_PAR 0x00004000 /* DB parity test mode */ -#define TCDS_CIR_TC_PAR 0x00008000 /* TC parity test mode */ -#define TCDS_CIR_ALLCONTROL 0x0000ffff /* all control bits */ - -/* TCDS CIR interrupt bits. */ -#define TCDS_CIR_SCSI0_DREQ 0x00010000 /* SCSI 0 DREQ */ -#define TCDS_CIR_SCSI1_DREQ 0x00020000 /* SCSI 1 DREQ */ -#define TCDS_CIR_SCSI0_INT 0x00040000 /* SCSI 0 interrupt */ -#define TCDS_CIR_SCSI1_INT 0x00080000 /* SCSI 1 interrupt */ -#define TCDS_CIR_SCSI0_PREFETCH 0x00100000 /* SCSI 0 prefetch */ -#define TCDS_CIR_SCSI1_PREFETCH 0x00200000 /* SCSI 1 prefetch */ -#define TCDS_CIR_SCSI0_DMA 0x00400000 /* SCSI 0 DMA error */ -#define TCDS_CIR_SCSI1_DMA 0x00800000 /* SCSI 1 DMA error */ -#define TCDS_CIR_SCSI0_DB 0x01000000 /* SCSI 0 DB parity */ -#define TCDS_CIR_SCSI1_DB 0x02000000 /* SCSI 1 DB parity */ -#define TCDS_CIR_SCSI0_DMAB_PAR 0x04000000 /* SCSI 0 DMA buffer parity */ -#define TCDS_CIR_SCSI1_DMAB_PAR 0x08000000 /* SCSI 1 DMA buffer parity */ -#define TCDS_CIR_SCSI0_DMAR_PAR 0x10000000 /* SCSI 0 DMA read parity */ -#define TCDS_CIR_SCSI1_DMAR_PAR 0x20000000 /* SCSI 1 DMA read parity */ -#define TCDS_CIR_TCIOW_PAR 0x40000000 /* TC I/O write parity */ -#define TCDS_CIR_TCIOA_PAR 0x80000000 /* TC I/O address parity */ -#define TCDS_CIR_ALLINTR 0xffff0000 /* all interrupt bits */ - -#define TCDS_CIR_CLR(c, b) c = ((c | TCDS_CIR_ALLINTR) & ~b) -#define TCDS_CIR_SET(c, b) c = ((c | TCDS_CIR_ALLINTR) | b) - -/* TCDS IMER masks and enables, for interrupts in the CIR. */ -#define TCDS_IMER_SCSI0_MASK 0x04 /* SCSI 0 intr/enable mask */ -#define TCDS_IMER_SCSI1_MASK 0x08 /* SCSI 1 intr/enable mask */ -#define TCDS_IMER_SCSI0_ENB (TCDS_IMER_SCSI0_MASK << 16) -#define TCDS_IMER_SCSI1_ENB (TCDS_IMER_SCSI1_MASK << 16) -#define TCDS_IMER 0x040004 /* IMER offset */ - -#define TCDS_SCSI0_DMA_ADDR 0x041000 /* DMA address */ -#define TCDS_SCSI0_DMA_INTR 0x041004 /* DMA interrupt control */ -#define TCDS_SCSI0_DMA_DUD0 0x041008 /* DMA unaligned data[0] */ -#define TCDS_SCSI0_DMA_DUD1 0x04100c /* DMA unaligned data[1] */ - -#define TCDS_SCSI1_DMA_ADDR 0x041100 /* DMA address */ -#define TCDS_SCSI1_DMA_INTR 0x041104 /* DMA interrupt control */ -#define TCDS_SCSI1_DMA_DUD0 0x041108 /* DMA unaligned data[0] */ -#define TCDS_SCSI1_DMA_DUD1 0x04110c /* DMA unaligned data[1] */ - -#define TCDS_DIC_ADDRMASK 0x03 /* DMA address bits <1:0> */ -#define TCDS_DIC_READ_PREFETCH 0x40 /* DMA read prefetch enable */ -#define TCDS_DIC_WRITE 0x80 /* DMA write */ - -#define TCDS_DUD0_VALID00 0x00000001 /* byte 00 valid mask (zero) */ -#define TCDS_DUD0_VALID01 0x00000002 /* byte 01 valid mask */ -#define TCDS_DUD0_VALID10 0x00000004 /* byte 10 valid mask */ -#define TCDS_DUD0_VALID11 0x00000008 /* byte 11 valid mask */ -#define TCDS_DUD0_VALIDBITS 0x0000000f /* bits that show valid bytes */ - -#define TCDS_DUD1_VALID00 0x01000000 /* byte 00 valid mask */ -#define TCDS_DUD1_VALID01 0x02000000 /* byte 01 valid mask */ -#define TCDS_DUD1_VALID10 0x04000000 /* byte 10 valid mask */ -#define TCDS_DUD1_VALID11 0x08000000 /* byte 11 valid mask (zero) */ -#define TCDS_DUD1_VALIDBITS 0x0f000000 /* bits that show valid bytes */ - -#define TCDS_DUD_BYTE00 0x000000ff /* byte 00 mask */ -#define TCDS_DUD_BYTE01 0x0000ff00 /* byte 01 mask */ -#define TCDS_DUD_BYTE10 0x00ff0000 /* byte 10 mask */ -#define TCDS_DUD_BYTE11 0xff000000 /* byte 11 mask */ - -#if 0 -int tcds_scsi_iserr(struct dma_softc *); -int tcds_scsi_isintr(int, int); -void tcds_dma_disable(int); -void tcds_dma_enable(int); -void tcds_dma_init(struct dma_softc *, int); -void tcds_scsi_disable(int); -void tcds_scsi_enable(int); -void tcds_scsi_reset(int); - -/* - * XXX - * Start of MACH #defines, minimal changes to port to {Net/Open}BSD. - * - * The following register is the SCSI control interrupt register. It - * starts, stops and resets scsi DMA. It takes over the SCSI funtions - * that were handled by the ASIC on the 3min. - */ -#define KN15AA_SYS_SCSI 0x1d0000000 -#define KN15AA_REG_SCSI_CIR (KN15AA_SYS_SCSI + 0x80000) -#define SCSI_CIR_AIOPAR 0x80000000 /* TC IO Address parity error */ -#define SCSI_CIR_WDIOPAR 0x40000000 /* TC IO write data parity error */ -#define SCSI_CIR_DMARPAR1 0x20000000 /* SCSI[1] TC DMA read data parity */ -#define SCSI_CIR_DMARPAR0 0x10000000 /* SCSI[0] TC DMA read data parity */ -#define SCSI_CIR_DMABUFPAR1 0x08000000 /* SCSI[1] DMA buffer parity error */ -#define SCSI_CIR_DMABUFPAR0 0x04000000 /* SCSI[0] DMA buffer parity error */ -#define SCSI_CIR_DBPAR1 0x02000000 /* SCSI[1] DB parity error */ -#define SCSI_CIR_DBPAR0 0x01000000 /* SCSI[0] DB parity error */ -#define SCSI_CIR_DMAERR1 0x00800000 /* SCSI[1] DMA error */ -#define SCSI_CIR_DMAERR0 0x00400000 /* SCSI[0] DMA error */ -#if fmm50 -#define SCSI_CIR_xxx0 0x00200000 /* RESERVED */ -#define SCSI_CIR_xxx1 0x00100000 /* RESERVED */ -#else -#define SCSI_CIR_PREF1 0x00200000 /* 53C94 prefetch interupt */ -#define SCSI_CIR_PREF0 0x00100000 /* 53C94 prefetch interupt */ -#endif -#define SCSI_CIR_53C94_INT1 0x00080000 /* SCSI[1] 53C94 Interupt */ -#define SCSI_CIR_53C94_INT0 0x00040000 /* SCSI[0] 53C94 Interupt */ -#define SCSI_CIR_53C94_DREQ1 0x00020000 /* SCSI[1] 53C94 DREQ */ -#define SCSI_CIR_53C94_DREQ0 0x00010000 /* SCSI[0] 53C94 DREQ */ -#define SCSI_CIR_TC_PAR_TEST 0x00008000 /* TC parity test mode */ -#define SCSI_CIR_DB_PAR_TEST 0x00004000 /* DB parity test mode */ -#define SCSI_CIR_DBUF_PAR_TEST1 0x00002000 /* SCSI[1] DMA buffer parity test */ -#define SCSI_CIR_DBUF_PAR_TEST0 0x00001000 /* SCSI[0] DMA buffer parity test */ -#define SCSI_CIR_RESET1 0x00000800 /* SCSI[1] ~Reset,enable(0)/disable(1) */ -#define SCSI_CIR_RESET0 0x00000400 /* SCSI[0] ~Reset,enable(0)/disable(1) */ -#define SCSI_CIR_DMAENA1 0x00000200 /* SCSI[1] DMA enable */ -#define SCSI_CIR_DMAENA0 0x00000100 /* SCSI[1] DMA enable */ -#define SCSI_CIR_GPI3 0x00000080 /* General purpose input <3> */ -#define SCSI_CIR_GPI2 0x00000040 /* General purpose input <2> */ -#define SCSI_CIR_GPI1 0x00000020 /* General purpose input <1> */ -#define SCSI_CIR_GPI0 0x00000010 /* General purpose input <0> */ -#define SCSI_CIR_TXDIS 0x00000008 /* TXDIS- serial transmit disable */ -#define SCSI_CIR_GPO2 0x00000004 /* General purpose output <2> */ -#define SCSI_CIR_GPO1 0x00000002 /* General purpose output <1> */ -#define SCSI_CIR_GPO0 0x00000001 /* General purpose output <0> */ -#define SCSI_CIR_ERROR (SCSI_CIR_AIOPAR | SCSI_CIR_WDIOPAR | SCSI_CIR_DMARPAR1 | SCSI_CIR_DMARPAR0 | SCSI_CIR_DMABUFPAR1 | SCSI_CIR_DMABUFPAR0 | SCSI_CIR_DBPAR1 |SCSI_CIR_DBPAR0 | SCSI_CIR_DMAERR1 | SCSI_CIR_DMAERR0 ) - -#define KN15AA_REG_SCSI_DMAPTR0 (KN15AA_SYS_SCSI + 0x82000) -#define KN15AA_REG_SCSI_DMAPTR1 (KN15AA_SYS_SCSI + 0x82200) - -#define KN15AA_REG_SCSI_DIC0 (KN15AA_SYS_SCSI + 0x82008) -#define KN15AA_REG_SCSI_DIC1 (KN15AA_SYS_SCSI + 0x82208) -#define SCSI_DIC_DMADIR 0x00000080 /* DMA direction read(0)/write(1) */ -#define SCSI_DIC_PREFENA 0x00000040 /* DMA read prefetch dis(0)/ena(1) */ -#define SCSI_DIC_DMAADDR1 0x00000002 /* DMA address <1> */ -#define SCSI_DIC_DMAADDR0 0x00000001 /* DMA address <0> */ -#define SCSI_DIC_ADDR_MASK (SCSI_DIC_DMAADDR0 |SCSI_DIC_DMAADDR1) - -#define KN15AA_REG_SCSI_94REG0 (KN15AA_SYS_SCSI + 0x100000) -#define KN15AA_REG_SCSI_94REG1 (KN15AA_SYS_SCSI + 0x100200) - -#define KN15AA_REG_SCSI_IMER (KN15AA_SYS_SCSI + 0x80008) - -/* these are the bits that were unalligned at the beginning of the dma */ -#define KN15AA_REG_SCSI_DUDB0 (KN15AA_SYS_SCSI + 0x82010) -#define KN15AA_REG_SCSI_DUDB1 (KN15AA_SYS_SCSI + 0x82210) -# define SCSI_DUDB_MASK01 0x00000001 /* Mask bit for byte[01] */ -# define SCSI_DUDB_MASK10 0x00000002 /* Mask bit for byte[10] */ -# define SCSI_DUDB_MASK11 0x00000004 /* Mask bit for byte[11] */ - -/* these are the bits that were unalligned at the end of the dma */ -#define KN15AA_REG_SCSI_DUDE0 (KN15AA_SYS_SCSI + 0x82018) -#define KN15AA_REG_SCSI_DUDE1 (KN15AA_SYS_SCSI + 0x82218) -# define SCSI_DUDE_MASK00 0x1000000 /* Mask bit for byte[00] */ -# define SCSI_DUDE_MASK01 0x2000000 /* Mask bit for byte[01] */ -# define SCSI_DUDE_MASK10 0x4000000 /* Mask bit for byte[10] */ - -#define SCSI_CIR ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_CIR) -#define SCSI_IMER ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_IMER) - -#endif diff --git a/sys/arch/alpha/tc/tcdsvar.h b/sys/arch/alpha/tc/tcdsvar.h deleted file mode 100644 index 5c73d575a94..00000000000 --- a/sys/arch/alpha/tc/tcdsvar.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $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 $ */ - -/* - * Copyright (c) 1995, 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 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 */ - int (*sc_intrhand)(void *); /* intr. handler */ - void *sc_intrarg; /* intr. handler arg. */ - - /* - * Sets of bits in TCDS CIR and IMER that enable/check - * various things. - */ - u_int32_t sc_resetbits; - u_int32_t sc_intrmaskbits; - u_int32_t sc_intrbits; - u_int32_t sc_dmabits; - u_int32_t sc_errorbits; - - /* - * Pointers 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; -}; - -struct tcdsdev_attach_args { - struct tc_attach_args tcdsda_ta; - struct tcds_slotconfig *tcdsda_sc; - u_int tcdsda_id; - u_int tcdsda_freq; -}; -#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, - int (*)(void *), void *); -void tcds_intr_disestablish(struct device *, void *); -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; |