From c54697119ec9872a51e2947476b67736df08b0f9 Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Wed, 7 Mar 2001 01:57:57 +0000 Subject: Change siop name to ssh, as per mvme68k, to prevent conflict with the other siop driver. Change siop-related defines to ssh-related defines everywhere. --- sys/arch/mvme88k/dev/siop.c | 1941 ---------------------------------- sys/arch/mvme88k/dev/siop_script.out | 175 --- sys/arch/mvme88k/dev/siop_script.ss | 205 ---- sys/arch/mvme88k/dev/siopdma.c | 295 ------ sys/arch/mvme88k/dev/siopreg.h | 336 ------ sys/arch/mvme88k/dev/siopvar.h | 204 ---- sys/arch/mvme88k/dev/ssh.c | 1941 ++++++++++++++++++++++++++++++++++ sys/arch/mvme88k/dev/ssh_script.out | 175 +++ sys/arch/mvme88k/dev/ssh_script.ss | 205 ++++ sys/arch/mvme88k/dev/sshdma.c | 295 ++++++ sys/arch/mvme88k/dev/sshreg.h | 336 ++++++ sys/arch/mvme88k/dev/sshvar.h | 204 ++++ sys/arch/mvme88k/dev/vsvar.h | 6 +- 13 files changed, 3159 insertions(+), 3159 deletions(-) delete mode 100644 sys/arch/mvme88k/dev/siop.c delete mode 100644 sys/arch/mvme88k/dev/siop_script.out delete mode 100644 sys/arch/mvme88k/dev/siop_script.ss delete mode 100644 sys/arch/mvme88k/dev/siopdma.c delete mode 100644 sys/arch/mvme88k/dev/siopreg.h delete mode 100644 sys/arch/mvme88k/dev/siopvar.h create mode 100644 sys/arch/mvme88k/dev/ssh.c create mode 100644 sys/arch/mvme88k/dev/ssh_script.out create mode 100644 sys/arch/mvme88k/dev/ssh_script.ss create mode 100644 sys/arch/mvme88k/dev/sshdma.c create mode 100644 sys/arch/mvme88k/dev/sshreg.h create mode 100644 sys/arch/mvme88k/dev/sshvar.h (limited to 'sys/arch') diff --git a/sys/arch/mvme88k/dev/siop.c b/sys/arch/mvme88k/dev/siop.c deleted file mode 100644 index 7b3c06174c1..00000000000 --- a/sys/arch/mvme88k/dev/siop.c +++ /dev/null @@ -1,1941 +0,0 @@ -/* $OpenBSD: siop.c,v 1.5 2001/02/01 03:38:15 smurph Exp $ */ - -/* - * Copyright (c) 1994 Michael L. Hitch - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson of Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)siop.c 7.5 (Berkeley) 5/4/91 - */ - -/* - * 53C710 scsi adaptor driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(MVME187) -#include -#include -#else -#include -#include -#endif /* MVME187 */ - -#if defined(MVME187) -#include "machine/mmu.h" -#endif /* defined(MVME187) */ - - -extern u_int kvtop(); - -/* - * SCSI delays - * In u-seconds, primarily for state changes on the SPC. - */ -#define SCSI_CMD_WAIT 500000 /* wait per step of 'immediate' cmds */ -#define SCSI_DATA_WAIT 500000 /* wait per data in/out step */ -#define SCSI_INIT_WAIT 500000 /* wait per step (both) during init */ - -void siop_select __P((struct siop_softc *)); -void siopabort __P((struct siop_softc *, siop_regmap_p, char *)); -void sioperror __P((struct siop_softc *, siop_regmap_p, u_char)); -void siopstart __P((struct siop_softc *)); -int siop_checkintr __P((struct siop_softc *, u_char, u_char, u_char, int *)); -void siopreset __P((struct siop_softc *)); -void siopsetdelay __P((int)); -void siop_scsidone __P((struct siop_acb *, int)); -void siop_sched __P((struct siop_softc *)); -int siop_poll __P((struct siop_softc *, struct siop_acb *)); -int siopintr __P((struct siop_softc *)); -void scsi_period_to_siop __P((struct siop_softc *, int)); -void siop_start __P((struct siop_softc *, int, int, u_char *, int, u_char *, int)); -void siop_dump_acb __P((struct siop_acb *)); - -/* 53C710 script */ -const -#if defined(MVME187) -#include -#else -#include -#endif /* MVME187 */ - -u_long scsi_nosync = 0; -int shift_nosync; - -/* default to not inhibit sync negotiation on any drive */ -u_char siop_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0 }; /* initialize, so patchable */ -u_char siop_allow_disc[8] = {3, 3, 3, 3, 3, 3, 3, 3}; -int siop_no_dma = 0; - -int siop_reset_delay = 250; /* delay after reset, in milleseconds */ - -int siop_cmd_wait = SCSI_CMD_WAIT; -int siop_data_wait = SCSI_DATA_WAIT; -int siop_init_wait = SCSI_INIT_WAIT; - -extern struct pmap kernel_pmap_store; -#define pmap_kernel() (&kernel_pmap_store) - -#ifdef DEBUG_SYNC -/* - * sync period transfer lookup - only valid for 66Mhz clock - */ -static struct { - unsigned char p; /* period from sync request message */ - unsigned char r; /* siop_period << 4 | sbcl */ -} sync_tab[] = { - { 60/4, 0<<4 | 1}, - { 76/4, 1<<4 | 1}, - { 92/4, 2<<4 | 1}, - { 92/4, 0<<4 | 2}, - {108/4, 3<<4 | 1}, - {116/4, 1<<4 | 2}, - {120/4, 4<<4 | 1}, - {120/4, 0<<4 | 3}, - {136/4, 5<<4 | 1}, - {140/4, 2<<4 | 2}, - {152/4, 6<<4 | 1}, - {152/4, 1<<4 | 3}, - {164/4, 3<<4 | 2}, - {168/4, 7<<4 | 1}, - {180/4, 2<<4 | 3}, - {184/4, 4<<4 | 2}, - {208/4, 5<<4 | 2}, - {212/4, 3<<4 | 3}, - {232/4, 6<<4 | 2}, - {240/4, 4<<4 | 3}, - {256/4, 7<<4 | 2}, - {272/4, 5<<4 | 3}, - {300/4, 6<<4 | 3}, - {332/4, 7<<4 | 3} -}; -#endif - -#ifdef DEBUG -/* - * 0x01 - full debug - * 0x02 - DMA chaining - * 0x04 - siopintr - * 0x08 - phase mismatch - * 0x10 - - * 0x20 - panic on unhandled exceptions - * 0x100 - disconnect/reselect - */ -int siop_debug = 0; -int siopsync_debug = 0; -int siopdma_hits = 0; -int siopdma_misses = 0; -int siopchain_ints = 0; -int siopstarts = 0; -int siopints = 0; -int siopphmm = 0; -#define SIOP_TRACE_SIZE 128 -#define SIOP_TRACE(a,b,c,d) \ - siop_trbuf[siop_trix] = (a); \ - siop_trbuf[siop_trix+1] = (b); \ - siop_trbuf[siop_trix+2] = (c); \ - siop_trbuf[siop_trix+3] = (d); \ - siop_trix = (siop_trix + 4) & (SIOP_TRACE_SIZE - 1); -u_char siop_trbuf[SIOP_TRACE_SIZE]; -int siop_trix; -void siop_dump __P((struct siop_softc *)); -void siop_dump_trace __P((void)); -#else -#define SIOP_TRACE(a,b,c,d) -#endif - -int kludge_city = 1; - -/* - * dummy routine to debug while loops - */ -void -wdummy(void) -{ - static int wcount; - wcount++; - if (wcount > 400000) { - wcount = 0; - } -} - -/* - * default minphys routine for siop based controllers - */ -void -siop_minphys(bp) - struct buf *bp; -{ - - /* - * No max transfer at this level. - */ - minphys(bp); -} - -/* - * used by specific siop controller - * - */ -int -siop_scsicmd(xs) - struct scsi_xfer *xs; -{ - struct siop_acb *acb; - struct siop_softc *sc; - struct scsi_link *slp; - int flags, s, i; - - slp = xs->sc_link; - sc = slp->adapter_softc; - flags = xs->flags; - xs->error = XS_NOERROR; - - /* XXXX ?? */ - if (flags & SCSI_DATA_UIO) - panic("siop: scsi data uio requested"); - - /* XXXX ?? */ - if (sc->sc_nexus && flags & SCSI_POLL) -/* panic("siop_scsicmd: busy");*/ - printf("siop_scsicmd: busy\n"); - - s = splbio(); - acb = sc->free_list.tqh_first; - if (acb) { - TAILQ_REMOVE(&sc->free_list, acb, chain); - } - splx(s); - - if (acb == NULL) { - xs->error = XS_DRIVER_STUFFUP; - return(TRY_AGAIN_LATER); - } - - acb->flags = ACB_ACTIVE; - acb->xs = xs; - bcopy(xs->cmd, &acb->cmd, xs->cmdlen); - acb->clen = xs->cmdlen; - acb->daddr = xs->data; - acb->dleft = xs->datalen; - -#if defined(MVME187) - /* - * Since the 187 doesn't support cache snooping, we have - * to flush the cache for a write and flush with inval for - * a read, prior to starting the IO. - * We should move this siop_sched() XXX - */ - if (xs->flags & SCSI_DATA_IN) { /* read */ - dma_cachectl((vm_offset_t)xs->data, xs->datalen, - DMA_CACHE_SYNC_INVAL); - } else { /* write */ - dma_cachectl((vm_offset_t)xs->data, xs->datalen, - DMA_CACHE_SYNC); - } -#endif - s = splbio(); - TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain); - - if (sc->sc_nexus == NULL) - siop_sched(sc); - - splx(s); - - if (flags & SCSI_POLL || siop_no_dma) - return(siop_poll(sc, acb)); - return(SUCCESSFULLY_QUEUED); -} - -int -siop_poll(sc, acb) - struct siop_softc *sc; - struct siop_acb *acb; -{ - siop_regmap_p rp = sc->sc_siopp; - struct scsi_xfer *xs = acb->xs; - int i; - int status; - u_char istat; - u_char dstat; - u_char sstat0; - int s; - int to; - - s = splbio(); - to = xs->timeout / 1000; - if (sc->nexus_list.tqh_first) - printf("%s: siop_poll called with disconnected device\n", - sc->sc_dev.dv_xname); - for (;;) { - /* use cmd_wait values? */ - i = 50000; - spl0(); - while (((istat = rp->siop_istat) & - (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) { - if (--i <= 0) { -#ifdef DEBUG - printf ("waiting: tgt %d cmd %02x sbcl %02x dsp %x (+%x) dcmd %x ds %x timeout %d\n", - xs->sc_link->target, acb->cmd.opcode, - rp->siop_sbcl, rp->siop_dsp, - rp->siop_dsp - sc->sc_scriptspa, - *((long *)&rp->siop_dcmd), &acb->ds, acb->xs->timeout); -#endif - i = 50000; - --to; - if (to <= 0) { - siopreset(sc); - return(COMPLETE); - } - } - delay(10); - } - sstat0 = rp->siop_sstat0; - delay(10); - dstat = rp->siop_dstat; - if (siop_checkintr(sc, istat, dstat, sstat0, &status)) { - if (acb != sc->sc_nexus) - printf("%s: siop_poll disconnected device completed\n", - sc->sc_dev.dv_xname); - else if ((sc->sc_flags & SIOP_INTDEFER) == 0) { - sc->sc_flags &= ~SIOP_INTSOFF; - rp->siop_sien = sc->sc_sien; - rp->siop_dien = sc->sc_dien; - } - siop_scsidone(sc->sc_nexus, status); - } - if (xs->flags & ITSDONE) - break; - } - splx(s); - return (COMPLETE); -} - -/* - * start next command that's ready - */ -void -siop_sched(sc) - struct siop_softc *sc; -{ - struct scsi_link *slp; - struct siop_acb *acb; - int stat, i; - -#ifdef DEBUG - if (sc->sc_nexus) { - printf("%s: siop_sched- nexus %x/%d ready %x/%d\n", - sc->sc_dev.dv_xname, sc->sc_nexus, - sc->sc_nexus->xs->sc_link->target, - sc->ready_list.tqh_first, - sc->ready_list.tqh_first->xs->sc_link->target); - return; - } -#endif - for (acb = sc->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) { - slp = acb->xs->sc_link; - i = slp->target; - if(!(sc->sc_tinfo[i].lubusy & (1 << slp->lun))) { - struct siop_tinfo *ti = &sc->sc_tinfo[i]; - - TAILQ_REMOVE(&sc->ready_list, acb, chain); - sc->sc_nexus = acb; - slp = acb->xs->sc_link; - ti = &sc->sc_tinfo[slp->target]; - ti->lubusy |= (1 << slp->lun); - break; - } - } - - if (acb == NULL) { -#ifdef DEBUGXXX - printf("%s: siop_sched didn't find ready command\n", - sc->sc_dev.dv_xname); -#endif - return; - } - - if (acb->xs->flags & SCSI_RESET) - siopreset(sc); - -#if 0 - acb->cmd.bytes[0] |= slp->lun << 5; /* XXXX */ -#endif - ++sc->sc_active; - siop_select(sc); -} - -void -siop_scsidone(acb, stat) - struct siop_acb *acb; - int stat; -{ - struct scsi_xfer *xs = acb->xs; - struct scsi_link *slp = xs->sc_link; - struct siop_softc *sc = slp->adapter_softc; - int s, dosched = 0; - - if (acb == NULL || (xs = acb->xs) == NULL) { -#ifdef DIAGNOSTIC - printf("siop_scsidone: NULL acb or scsi_xfer\n"); -#if defined(DEBUG) && defined(DDB) - Debugger(); -#endif -#endif - return; - } - slp = xs->sc_link; - sc = slp->adapter_softc; - /* - * is this right? - */ - xs->status = stat; - - if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) { - if (stat == SCSI_CHECK) { - struct scsi_sense *ss = (void *)&acb->cmd; - bzero(ss, sizeof(*ss)); - ss->opcode = REQUEST_SENSE; - ss->byte2 = slp->lun << 5; - ss->length = sizeof(struct scsi_sense_data); - acb->clen = sizeof(*ss); - acb->daddr = (char *)&xs->sense; - acb->dleft = sizeof(struct scsi_sense_data); - acb->flags = ACB_ACTIVE | ACB_CHKSENSE; - TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain); - --sc->sc_active; - sc->sc_tinfo[slp->target].lubusy &= - ~(1 << slp->lun); - sc->sc_tinfo[slp->target].senses++; - if (sc->sc_nexus == acb) { - sc->sc_nexus = NULL; - siop_sched(sc); - } - SIOP_TRACE('d','s',0,0) - return; - } - } - if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) { - xs->error = XS_SENSE; - } else { - xs->resid = 0; /* XXXX */ - } -#if whataboutthisone - case SCSI_BUSY: - xs->error = XS_BUSY; - break; -#endif - xs->flags |= ITSDONE; - - /* - * Remove the ACB from whatever queue it's on. We have to do a bit of - * a hack to figure out which queue it's on. Note that it is *not* - * necessary to cdr down the ready queue, but we must cdr down the - * nexus queue and see if it's there, so we can mark the unit as no - * longer busy. This code is sickening, but it works. - */ - if (acb == sc->sc_nexus) { - sc->sc_nexus = NULL; - sc->sc_tinfo[slp->target].lubusy &= ~(1<lun); - if (sc->ready_list.tqh_first) - dosched = 1; /* start next command */ - --sc->sc_active; - SIOP_TRACE('d','a',stat,0) - } else if (sc->ready_list.tqh_last == &acb->chain.tqe_next) { - TAILQ_REMOVE(&sc->ready_list, acb, chain); - SIOP_TRACE('d','r',stat,0) - } else { - register struct siop_acb *acb2; - for (acb2 = sc->nexus_list.tqh_first; acb2; - acb2 = acb2->chain.tqe_next) - if (acb2 == acb) { - TAILQ_REMOVE(&sc->nexus_list, acb, chain); - sc->sc_tinfo[slp->target].lubusy - &= ~(1<lun); - --sc->sc_active; - break; - } - if (acb2) - ; - else if (acb->chain.tqe_next) { - TAILQ_REMOVE(&sc->ready_list, acb, chain); - --sc->sc_active; - } else { - printf("%s: can't find matching acb\n", - sc->sc_dev.dv_xname); -#ifdef DDB -/* Debugger(); */ -#endif - } - SIOP_TRACE('d','n',stat,0); - } - /* Put it on the free list. */ - acb->flags = ACB_FREE; - TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); - - sc->sc_tinfo[slp->target].cmds++; - - scsi_done(xs); - - if (dosched && sc->sc_nexus == NULL) - siop_sched(sc); -} - -void -siopabort(sc, rp, where) - register struct siop_softc *sc; - siop_regmap_p rp; - char *where; -{ - int i; - - printf ("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n", - sc->sc_dev.dv_xname, - where, rp->siop_dstat, rp->siop_sstat0, rp->siop_sbcl); - - if (sc->sc_active > 0) { -#ifdef TODO - SET_SBIC_cmd (rp, SBIC_CMD_ABORT); - WAIT_CIP (rp); - - GET_SBIC_asr (rp, asr); - if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) - { - /* ok, get more drastic.. */ - - SET_SBIC_cmd (rp, SBIC_CMD_RESET); - delay(25); - SBIC_WAIT(rp, SBIC_ASR_INT, 0); - GET_SBIC_csr (rp, csr); /* clears interrupt also */ - - return; - } - - do - { - SBIC_WAIT (rp, SBIC_ASR_INT, 0); - GET_SBIC_csr (rp, csr); - } - while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) - && (csr != SBIC_CSR_CMD_INVALID)); -#endif - - /* lets just hope it worked.. */ -#ifdef fix_this - for (i = 0; i < 2; ++i) { - if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] != - sc->sc_cur) { - printf ("siopabort: cleanup!\n"); - sc->sc_iob[i].sc_xs = NULL; - } - } -#endif /* fix_this */ -/* sc->sc_active = 0; */ - } -} - -void -siopinitialize(sc) - struct siop_softc *sc; -{ - /* - * Need to check that scripts is on a long word boundary - * Also should verify that dev doesn't span non-contiguous - * physical pages. - */ - sc->sc_scriptspa = kvtop(scripts); - - /* - * malloc sc_acb to ensure that DS is on a long word boundary. - */ - - MALLOC(sc->sc_acb, struct siop_acb *, - sizeof(struct siop_acb) * SIOP_NACB, M_DEVBUF, M_NOWAIT); - if (sc->sc_acb == NULL) - panic("siopinitialize: ACB malloc failed!"); - - sc->sc_tcp[1] = 1000 / sc->sc_clock_freq; - sc->sc_tcp[2] = 1500 / sc->sc_clock_freq; - sc->sc_tcp[3] = 2000 / sc->sc_clock_freq; - sc->sc_minsync = sc->sc_tcp[1]; /* in 4ns units */ - if (sc->sc_minsync < 25) - sc->sc_minsync = 25; -#if not_used - if (sc->sc_clock_freq <= 25) - sc->sc_tcp[0] = sc->sc_tcp[1]; - else if (sc->sc_clock_freq <= 37) - sc->sc_tcp[0] = sc->sc_tcp[2]; - else if (sc->sc_clock_freq <= 50) - sc->sc_tcp[0] = sc->sc_tcp[3]; - else - sc->sc_tcp[0] = 3000 / sc->sc_clock_freq; -#endif - - siopreset (sc); -} - -void -siopreset(sc) - struct siop_softc *sc; -{ - siop_regmap_p rp; - u_int i, s; - u_char dummy; - struct siop_acb *acb; - - rp = sc->sc_siopp; - - if (sc->sc_flags & SIOP_ALIVE) - siopabort(sc, rp, "reset"); - - s = splbio(); - - /* - * Reset the chip - * XXX - is this really needed? - */ - rp->siop_istat |= SIOP_ISTAT_ABRT; /* abort current script */ - rp->siop_istat |= SIOP_ISTAT_RST; /* reset chip */ - rp->siop_istat &= ~SIOP_ISTAT_RST; - /* - * Reset SCSI bus (do we really want this?) - */ - rp->siop_sien = 0; - rp->siop_scntl1 |= SIOP_SCNTL1_RST; - delay(25); - rp->siop_scntl1 &= ~SIOP_SCNTL1_RST; - - /* - * Set up various chip parameters - */ - rp->siop_scntl0 = SIOP_ARB_FULL | SIOP_SCNTL0_EPC | SIOP_SCNTL0_EPG; - rp->siop_scntl1 = SIOP_SCNTL1_ESR; - rp->siop_dcntl = sc->sc_dcntl; - rp->siop_dmode = 0x80; /* burst length = 4 */ - rp->siop_sien = 0x00; /* don't enable interrupts yet */ - rp->siop_dien = 0x00; /* don't enable interrupts yet */ - rp->siop_scid = 1 << sc->sc_link.adapter_target; - rp->siop_dwt = 0x00; - rp->siop_ctest0 |= SIOP_CTEST0_BTD | SIOP_CTEST0_EAN; - rp->siop_ctest7 = sc->sc_ctest7; - - /* will need to re-negotiate sync xfers */ - bzero(&sc->sc_sync, sizeof (sc->sc_sync)); - - i = rp->siop_istat; - if (i & SIOP_ISTAT_SIP) - dummy = rp->siop_sstat0; - delay(1); - if (i & SIOP_ISTAT_DIP) - dummy = rp->siop_dstat; - - splx (s); - - delay (siop_reset_delay * 1000); - printf(": version %d target %d\n", rp->siop_ctest8 >> 4, - sc->sc_link.adapter_target); - - if ((sc->sc_flags & SIOP_ALIVE) == 0) { - TAILQ_INIT(&sc->ready_list); - TAILQ_INIT(&sc->nexus_list); - TAILQ_INIT(&sc->free_list); - sc->sc_nexus = NULL; - acb = sc->sc_acb; - bzero(acb, sizeof(struct siop_acb) * SIOP_NACB); - for (i = 0; i < SIOP_NACB; i++) { - - pmap_cache_ctrl(pmap_kernel(), - M88K_TRUNC_PAGE((vm_offset_t)acb), - M88K_ROUND_PAGE((vm_offset_t)acb+sizeof(*acb)), - CACHE_INH); - - TAILQ_INSERT_TAIL(&sc->free_list, acb, chain); - acb++; - } - bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo)); - } else { - if (sc->sc_nexus != NULL) { - sc->sc_nexus->xs->error = XS_DRIVER_STUFFUP; - siop_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]); - } - while (acb = sc->nexus_list.tqh_first) { - acb->xs->error = XS_DRIVER_STUFFUP; - siop_scsidone(acb, acb->stat[0]); - } - } - - sc->sc_flags |= SIOP_ALIVE; - sc->sc_flags &= ~(SIOP_INTDEFER|SIOP_INTSOFF); - /* enable SCSI and DMA interrupts */ - /* XXX turn on SEL interrupt? nivas */ - sc->sc_sien = SIOP_SIEN_M_A | SIOP_SIEN_STO | /*SIOP_SIEN_SEL |*/ SIOP_SIEN_SGE | - SIOP_SIEN_UDC | SIOP_SIEN_RST | SIOP_SIEN_PAR; - sc->sc_dien = SIOP_DIEN_BF | SIOP_DIEN_ABRT | SIOP_DIEN_SIR | - /*SIOP_DIEN_WTD |*/ SIOP_DIEN_IID; - rp->siop_sien = sc->sc_sien; - rp->siop_dien = sc->sc_dien; -} - -/* - * Setup Data Storage for 53C710 and start SCRIPTS processing - */ - -void -siop_start (sc, target, lun, cbuf, clen, buf, len) - struct siop_softc *sc; - int target; - int lun; - u_char *cbuf; - int clen; - u_char *buf; - int len; -{ - siop_regmap_p rp = sc->sc_siopp; - int i; - int nchain; - int count, tcount; - char *addr, *dmaend; - struct siop_acb *acb = sc->sc_nexus; - -#ifdef DEBUG - if (siop_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) { - printf ("ACK! siop was busy: rp %x script %x dsa %x active %d\n", - rp, &scripts, &acb->ds, sc->sc_active); - printf ("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n", - rp->siop_istat, rp->siop_sfbr, rp->siop_lcrc, - rp->siop_sien, rp->siop_dien); -#ifdef DDB - /*Debugger();*/ -#endif - } -#endif - acb->msgout[0] = MSG_IDENTIFY | lun; - if (siop_allow_disc[target] & 2 || - (siop_allow_disc[target] && len == 0)) - acb->msgout[0] = MSG_IDENTIFY_DR | lun; - acb->status = 0; - acb->stat[0] = -1; - acb->msg[0] = -1; - acb->ds.scsi_addr = (0x10000 << target) | (sc->sc_sync[target].sxfer << 8); - acb->ds.idlen = 1; - acb->ds.idbuf = (char *) kvtop(&acb->msgout[0]); - acb->ds.cmdlen = clen; - acb->ds.cmdbuf = (char *) kvtop(cbuf); - acb->ds.stslen = 1; - acb->ds.stsbuf = (char *) kvtop(&acb->stat[0]); - acb->ds.msglen = 1; - acb->ds.msgbuf = (char *) kvtop(&acb->msg[0]); - acb->msg[1] = -1; - acb->ds.msginlen = 1; - acb->ds.extmsglen = 1; - acb->ds.synmsglen = 3; - acb->ds.msginbuf = (char *) kvtop(&acb->msg[1]); - acb->ds.extmsgbuf = (char *) kvtop(&acb->msg[2]); - acb->ds.synmsgbuf = (char *) kvtop(&acb->msg[3]); - bzero(&acb->ds.chain, sizeof (acb->ds.chain)); - - if (sc->sc_sync[target].state == SYNC_START) { - if (siop_inhibit_sync[target]) { - sc->sc_sync[target].state = SYNC_DONE; - sc->sc_sync[target].sbcl = 0; - sc->sc_sync[target].sxfer = 0; -#ifdef DEBUG - if (siopsync_debug) - printf ("Forcing target %d asynchronous\n", target); -#endif - } - else { - acb->msg[2] = -1; - acb->msgout[1] = MSG_EXT_MESSAGE; - acb->msgout[2] = 3; - acb->msgout[3] = MSG_SYNC_REQ; -#ifdef MAXTOR_SYNC_KLUDGE - acb->msgout[4] = 50 / 4; /* ask for ridiculous period */ -#else - acb->msgout[4] = sc->sc_minsync; -#endif - acb->msgout[5] = SIOP_MAX_OFFSET; - acb->ds.idlen = 6; - sc->sc_sync[target].state = SYNC_SENT; -#ifdef DEBUG - if (siopsync_debug) - printf ("Sending sync request to target %d\n", target); -#endif - } - } - -/* - * Build physical DMA addresses for scatter/gather I/O - */ - acb->iob_buf = buf; - acb->iob_len = len; - acb->iob_curbuf = acb->iob_curlen = 0; - nchain = 0; - count = len; - addr = buf; - dmaend = NULL; - while (count > 0) { - acb->ds.chain[nchain].databuf = (char *) kvtop (addr); - if (count < (tcount = NBPG - ((int) addr & PGOFSET))) - tcount = count; - acb->ds.chain[nchain].datalen = tcount; - addr += tcount; - count -= tcount; - if (acb->ds.chain[nchain].databuf == dmaend) { - dmaend += acb->ds.chain[nchain].datalen; - acb->ds.chain[nchain].datalen = 0; - acb->ds.chain[--nchain].datalen += tcount; -#ifdef DEBUG - ++siopdma_hits; -#endif - } - else { - dmaend = acb->ds.chain[nchain].databuf + - acb->ds.chain[nchain].datalen; - acb->ds.chain[nchain].datalen = tcount; -#ifdef DEBUG - if (nchain) /* Don't count miss on first one */ - ++siopdma_misses; -#endif - } - ++nchain; - } -#ifdef DEBUG - if (nchain != 1 && len != 0 && siop_debug & 3) { - printf ("DMA chaining set: %d\n", nchain); - for (i = 0; i < nchain; ++i) { - printf (" [%d] %8x %4x\n", i, acb->ds.chain[i].databuf, - acb->ds.chain[i].datalen); - } - } -#endif - -#if CACHECTL - /* push data cache for all data the 53c710 needs to access */ - dma_cachectl(sc, sizeof (struct siop_softc), DMA_CACHE_SYNC); - dma_cachectl(acb, sizeof (*acb), DMA_CACHE_SYNC); -#endif - dma_cachectl((vm_offset_t)cbuf, clen, DMA_CACHE_SYNC); - -#if defined(MVME187) - /* - * Flushing the buf from data cache is very important for MVME187 - * since the board does not snoop the local bus. - * We have to flush the cache for a write and flush with inval for - * a read. - */ - if (buf != NULL && len != 0) { - if (acb->xs->flags & SCSI_DATA_IN) { /* read */ - dma_cachectl((vm_offset_t)buf, len, - DMA_CACHE_SYNC_INVAL); - } else { /* write */ - dma_cachectl((vm_offset_t)buf, len, DMA_CACHE_SYNC); - } - } -#endif - -#ifdef DEBUG - if (siop_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) { - printf ("ACK! siop was busy at start: rp %x script %x dsa %x active %d\n", - rp, &scripts, &acb->ds, sc->sc_active); -#ifdef DDB - /*Debugger();*/ -#endif - } -#endif - if (sc->nexus_list.tqh_first == NULL) { - if (rp->siop_istat & SIOP_ISTAT_CON) - printf("%s: siop_select while connected?\n", - sc->sc_dev.dv_xname); - rp->siop_temp = 0; - rp->siop_sbcl = sc->sc_sync[target].sbcl; - rp->siop_dsa = kvtop(&acb->ds); - rp->siop_dsp = sc->sc_scriptspa; - SIOP_TRACE('s',1,0,0) - } else { - /* - * SIOP is waiting for a reselect. If it is not - * yet connected to the BUS, signal to change state. - * Else, leave it alone - later on, the reselect interrupt - * will take care of this request. - */ - if ((rp->siop_istat & SIOP_ISTAT_CON) == 0) { - rp->siop_istat = SIOP_ISTAT_SIGP; - SIOP_TRACE('s',2,0,0); - } - else { - SIOP_TRACE('s',3,rp->siop_istat,0); - } - } -#ifdef DEBUG - ++siopstarts; -#endif -} - -/* - * Process a DMA or SCSI interrupt from the 53C710 SIOP - */ - -int -siop_checkintr(sc, istat, dstat, sstat0, status) - struct siop_softc *sc; - u_char istat; - u_char dstat; - u_char sstat0; - int *status; -{ - siop_regmap_p rp = sc->sc_siopp; - struct siop_acb *acb = sc->sc_nexus; - int target = 0; - int dfifo, dbc, sstat1; - int dummy; - - dfifo = rp->siop_dfifo; - dbc = rp->siop_dbc0; - sstat1 = rp->siop_sstat1; - - /* - * Flush DMA and SCSI FIFOs. - */ - rp->siop_ctest8 |= SIOP_CTEST8_CLF; - while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT){ - wdummy(); - } - ; - rp->siop_ctest8 &= ~SIOP_CTEST8_CLF; -#ifdef DEBUG - ++siopints; -#if 0 - if (siop_debug & 0x100) { - DCIAS(&acb->stat[0]); /* XXX */ - printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n", - istat, dstat, sstat0, rp->siop_dsps, rp->siop_sbcl, acb->stat[0], acb->msg[0]); - printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", - acb->msg[0], acb->msg[1], acb->msg[2], - acb->msg[3], acb->msg[4], acb->msg[5]); - } -#endif - if (rp->siop_dsp && (rp->siop_dsp < sc->sc_scriptspa || - rp->siop_dsp >= sc->sc_scriptspa + sizeof(scripts))) { - printf ("%s: dsp not within script dsp %x scripts %x:%x", - sc->sc_dev.dv_xname, rp->siop_dsp, sc->sc_scriptspa, - sc->sc_scriptspa + sizeof(scripts)); - printf(" istat %x dstat %x sstat0 %x\n", - istat, dstat, sstat0); -#ifdef DDB - Debugger(); -#endif - } -#endif - SIOP_TRACE('i',dstat,istat,(istat&SIOP_ISTAT_DIP)?rp->siop_dsps&0xff:sstat0); - if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff00) { - /* Normal completion status, or check condition */ -#ifdef DEBUG - if (rp->siop_dsa != kvtop(&acb->ds)) { - printf ("siop: invalid dsa: %x %x\n", rp->siop_dsa, - kvtop(&acb->ds)); - panic("*** siop DSA invalid ***"); - } -#endif - if (acb == NULL) { - printf("%s: Command complete with no active command?\n", - sc->sc_dev.dv_xname); - return (0); - } - - target = acb->xs->sc_link->target; - if (sc->sc_sync[target].state == SYNC_SENT) { -#ifdef DEBUG - if (siopsync_debug) - printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", - acb->msg[0], acb->msg[1], acb->msg[2], - acb->msg[3], acb->msg[4], acb->msg[5]); -#endif - if (acb->msg[1] == 0xff) - printf ("%s: target %d ignored sync request\n", - sc->sc_dev.dv_xname, target); - else if (acb->msg[1] == MSG_REJECT) - printf ("%s: target %d rejected sync request\n", - sc->sc_dev.dv_xname, target); - sc->sc_sync[target].state = SYNC_DONE; - sc->sc_sync[target].sxfer = 0; - sc->sc_sync[target].sbcl = 0; - if (acb->msg[2] == 3 && - acb->msg[3] == MSG_SYNC_REQ && - acb->msg[5] != 0) { -#ifdef MAXTOR_KLUDGE - /* - * Kludge for my Maxtor XT8580S - * It accepts whatever we request, even - * though it won't work. So we ask for - * a short period than we can handle. If - * the device says it can do it, use 208ns. - * If the device says it can do less than - * 100ns, then we limit it to 100ns. - */ - if (acb->msg[4] && acb->msg[4] < 100 / 4) { -#ifdef DEBUG - printf ("%d: target %d wanted %dns period\n", - sc->sc_dev.dv_xname, target, - acb->msg[4] * 4); -#endif - if (acb->msg[4] == 50 / 4) - acb->msg[4] = 208 / 4; - else - acb->msg[4] = 100 / 4; - } -#endif /* MAXTOR_KLUDGE */ - printf ("%s: target %d now synchronous, period=%dns, offset=%d\n", - sc->sc_dev.dv_xname, target, - acb->msg[4] * 4, acb->msg[5]); - scsi_period_to_siop (sc, target); - } - } -#if CACHECTL - /*cmmu_inval_cache(kvtop(&acb->stat[0]), 1);*/ - dma_cachectl(&acb->stat[0], 1); -#endif - *status = acb->stat[0]; -#ifdef DEBUG - if (rp->siop_sbcl & SIOP_BSY) { - /*printf ("ACK! siop was busy at end: rp %x script %x dsa %x\n", - rp, &scripts, &acb->ds);*/ -#ifdef DDB - /*Debugger();*/ -#endif - } - if (acb->msg[0] != 0x00) - printf("%s: message was not COMMAND COMPLETE: %x\n", - sc->sc_dev.dv_xname, acb->msg[0]); -#endif - if (sc->nexus_list.tqh_first) - rp->siop_dcntl |= SIOP_DCNTL_STD; - return 1; - } - if (sstat0 & SIOP_SSTAT0_M_A) { /* Phase mismatch */ -#ifdef DEBUG - ++siopphmm; - if (acb == NULL) - printf("%s: Phase mismatch with no active command?\n", - sc->sc_dev.dv_xname); -#endif - if (acb->iob_len) { - int adjust; - adjust = ((dfifo - (dbc & 0x7f)) & 0x7f); - if (sstat1 & SIOP_SSTAT1_ORF) - ++adjust; - if (sstat1 & SIOP_SSTAT1_OLF) - ++adjust; - acb->iob_curlen = *((long *)&rp->siop_dcmd) & 0xffffff; - acb->iob_curlen += adjust; - acb->iob_curbuf = *((long *)&rp->siop_dnad) - adjust; -#ifdef DEBUG - if (siop_debug & 0x100) { - int i; - printf ("Phase mismatch: curbuf %x curlen %x dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %x\n", - acb->iob_curbuf, acb->iob_curlen, dfifo, - dbc, sstat1, adjust, rp->siop_sbcl, siopstarts, acb); - if (acb->ds.chain[1].datalen) { - for (i = 0; acb->ds.chain[i].datalen; ++i) - printf("chain[%d] addr %x len %x\n", - i, acb->ds.chain[i].databuf, - acb->ds.chain[i].datalen); - } - } -#endif - -#if 0 - dma_cachectl (acb, sizeof(*acb), DMA_CACHE_SYNC)); -#endif - } -#ifdef DEBUG - SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp); - if (siop_debug & 9) - printf ("Phase mismatch: %x dsp +%x dcmd %x\n", - rp->siop_sbcl, - rp->siop_dsp - sc->sc_scriptspa, - *((long *)&rp->siop_dcmd)); -#endif - if ((rp->siop_sbcl & SIOP_REQ) == 0) { - printf ("Phase mismatch: REQ not asserted! %02x dsp %x\n", - rp->siop_sbcl, rp->siop_dsp); -#ifdef DEBUG - Debugger(); -#endif - } - switch (rp->siop_sbcl & 7) { - case 0: /* data out */ - case 1: /* data in */ - case 2: /* status */ - case 3: /* command */ - case 6: /* message in */ - case 7: /* message out */ - rp->siop_dsp = sc->sc_scriptspa + Ent_switch; - break; - default: - goto bad_phase; - } - return 0; - } - if (sstat0 & SIOP_SSTAT0_STO) { /* Select timed out */ -#ifdef DEBUG - if (acb == NULL) - printf("%s: Select timeout with no active command?\n", - sc->sc_dev.dv_xname); - if (rp->siop_sbcl & SIOP_BSY) { - printf ("ACK! siop was busy at timeout: rp %x script %x dsa %x\n", - rp, &scripts, &acb->ds); - printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n", - rp->siop_sbcl, rp->siop_sdid, istat, dstat, sstat0); - if (!(rp->siop_sbcl & SIOP_BSY)) { - printf ("Yikes, it's not busy now!\n"); -#if 0 - *status = -1; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; -#endif - } -/* rp->siop_dcntl |= SIOP_DCNTL_STD;*/ - return (0); -#ifdef DDB - Debugger(); -#endif - } -#endif - *status = -1; - acb->xs->error = XS_SELTIMEOUT; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; - } - if (acb) - target = acb->xs->sc_link->target; - else - target = 7; - if (sstat0 & SIOP_SSTAT0_UDC) { -#ifdef DEBUG - if (acb == NULL) - printf("%s: Unexpected disconnect with no active command?\n", - sc->sc_dev.dv_xname); - printf ("%s: target %d disconnected unexpectedly\n", - sc->sc_dev.dv_xname, target); -#endif -#if 0 - siopabort (sc, rp, "siopchkintr"); -#endif - *status = STS_BUSY; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; - } - if (dstat & SIOP_DSTAT_SIR && (rp->siop_dsps == 0xff01 || - rp->siop_dsps == 0xff02)) { -#ifdef DEBUG - if (siop_debug & 0x100) - printf ("%s: ID %02x disconnected TEMP %x (+%x) curbuf %x curlen %x buf %x len %x dfifo %x dbc %x sstat1 %x starts %d acb %x\n", - sc->sc_dev.dv_xname, 1 << target, rp->siop_temp, - rp->siop_temp ? rp->siop_temp - sc->sc_scriptspa : 0, - acb->iob_curbuf, acb->iob_curlen, - acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, siopstarts, acb); -#endif - if (acb == NULL) { - printf("%s: Disconnect with no active command?\n", - sc->sc_dev.dv_xname); - return (0); - } - /* - * XXXX need to update iob_curbuf/iob_curlen to reflect - * current data transferred. If device disconnected in - * the middle of a DMA block, they should already be set - * by the phase change interrupt. If the disconnect - * occurs on a DMA block boundary, we have to figure out - * which DMA block it was. - */ - if (acb->iob_len && rp->siop_temp) { - int n = rp->siop_temp - sc->sc_scriptspa; - - if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen) - printf("%s: iob_curbuf/len already set? n %x iob %x/%x chain[0] %x/%x\n", - sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen, - acb->ds.chain[0].databuf, acb->ds.chain[0].datalen); - if (n < Ent_datain) - n = (n - Ent_dataout) / 16; - else - n = (n - Ent_datain) / 16; - if (n <= 0 && n > DMAMAXIO) - printf("TEMP invalid %d\n", n); - else { - acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf; - acb->iob_curlen = acb->ds.chain[n].datalen; - } -#ifdef DEBUG - if (siop_debug & 0x100) { - printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n); - printf(" curbuf %x curlen %x\n", acb->iob_curbuf, - acb->iob_curlen); - } -#endif - } - /* - * If data transfer was interrupted by disconnect, iob_curbuf - * and iob_curlen should reflect the point of interruption. - * Adjust the DMA chain so that the data transfer begins - * at the appropriate place upon reselection. - * XXX This should only be done on save data pointer message? - */ - if (acb->iob_curlen) { - int i, j; - -#ifdef DEBUG - if (siop_debug & 0x100) - printf ("%s: adjusting DMA chain\n", - sc->sc_dev.dv_xname); - if (rp->siop_dsps == 0xff02) - printf ("%s: ID %02x disconnected without Save Data Pointers\n", - sc->sc_dev.dv_xname, 1 << target); -#endif - for (i = 0; i < DMAMAXIO; ++i) { - if (acb->ds.chain[i].datalen == 0) - break; - if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf && - acb->iob_curbuf < (long)(acb->ds.chain[i].databuf + - acb->ds.chain[i].datalen)) - break; - } - if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) - printf("couldn't find saved data pointer\n"); -#ifdef DEBUG - if (siop_debug & 0x100) - printf(" chain[0]: %x/%x -> %x/%x\n", - acb->ds.chain[0].databuf, - acb->ds.chain[0].datalen, - acb->iob_curbuf, - acb->iob_curlen); -#endif - acb->ds.chain[0].databuf = (char *)acb->iob_curbuf; - acb->ds.chain[0].datalen = acb->iob_curlen; - for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) { -#ifdef DEBUG - if (siop_debug & 0x100) - printf(" chain[%d]: %x/%x -> %x/%x\n", j, - acb->ds.chain[j].databuf, - acb->ds.chain[j].datalen, - acb->ds.chain[i].databuf, - acb->ds.chain[i].datalen); -#endif - acb->ds.chain[j].databuf = acb->ds.chain[i].databuf; - acb->ds.chain[j].datalen = acb->ds.chain[i].datalen; - } - if (j < DMAMAXIO) - acb->ds.chain[j].datalen = 0; -#if CACHECTL - dma_cachectl(acb->ds.chain, - sizeof(acb->ds.chain)); -#endif - } - ++sc->sc_tinfo[target].dconns; - /* - * add nexus to waiting list - * clear nexus - * try to start another command for another target/lun - */ - acb->status = sc->sc_flags & SIOP_INTSOFF; - TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain); - sc->sc_nexus = NULL; /* no current device */ - /* start script to wait for reselect */ - if (sc->sc_nexus == NULL) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; -/* XXXX start another command ? */ - if (sc->ready_list.tqh_first) - siop_sched(sc); - return (0); - } - if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff03) { - int reselid = rp->siop_scratch & 0x7f; - int reselun = rp->siop_sfbr & 0x07; - - sc->sc_sstat1 = rp->siop_sbcl; /* XXXX save current SBCL */ -#ifdef DEBUG - if (siop_debug & 0x100) - printf ("%s: target ID %02x reselected dsps %x\n", - sc->sc_dev.dv_xname, reselid, - rp->siop_dsps); - if ((rp->siop_sfbr & 0x80) == 0) - printf("%s: Reselect message in was not identify: %x\n", - sc->sc_dev.dv_xname, rp->siop_sfbr); -#endif - /* - * If we were trying to start a command when the reselect - * occured, need to put it at the head of the ready list, - * mark target/lun unbusy and decrement sc_active count. - */ - if (sc->sc_nexus) { -#ifdef DEBUG - if (siop_debug & 0x100) - printf ("%s: reselect ID %02x w/active\n", - sc->sc_dev.dv_xname, reselid); -#endif - TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain); - sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target].lubusy - &= ~(1 << sc->sc_nexus->xs->sc_link->lun); - --sc->sc_active; - } - /* - * locate acb of reselecting device - * set sc->sc_nexus to acb - */ - for (acb = sc->nexus_list.tqh_first; acb; - acb = acb->chain.tqe_next) { - if (reselid != (acb->ds.scsi_addr >> 16) || - reselun != (acb->msgout[0] & 0x07)) - continue; - TAILQ_REMOVE(&sc->nexus_list, acb, chain); - sc->sc_nexus = acb; - sc->sc_flags |= acb->status; - acb->status = 0; -#if CACHECTL - dma_cachectl(&acb->stat[0], sizeof(acb->stat[0])); -#endif - rp->siop_dsa = kvtop(&acb->ds); - rp->siop_sxfer = sc->sc_sync[acb->xs->sc_link->target].sxfer; - rp->siop_sbcl = sc->sc_sync[acb->xs->sc_link->target].sbcl; - break; - } - if (acb == NULL) { - printf("%s: target ID %02x reselect nexus_list %x\n", - sc->sc_dev.dv_xname, reselid, - sc->nexus_list.tqh_first); - panic("unable to find reselecting device"); - } -#if CACHECTL - dma_cachectl (acb, sizeof(*acb)); -#endif - rp->siop_temp = 0; - rp->siop_dcntl |= SIOP_DCNTL_STD; - return (0); - } - if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff04) { - u_short ctest2 = rp->siop_ctest2; - - /* reselect was interrupted (by Sig_P or select) */ -#ifdef DEBUG - if (siop_debug & 0x100 || - (ctest2 & SIOP_CTEST2_SIGP) == 0) - printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n", - sc->sc_dev.dv_xname, rp->siop_scntl1, - ctest2, rp->siop_sfbr, istat, rp->siop_istat); -#endif - /* XXX assumes it was not select */ - if (sc->sc_nexus == NULL) { - printf("%s: reselect interrupted, sc_nexus == NULL\n", - sc->sc_dev.dv_xname); -#if 0 - siop_dump(sc); -#ifdef DDB - Debugger(); -#endif -#endif - rp->siop_dcntl |= SIOP_DCNTL_STD; - return(0); - } - target = sc->sc_nexus->xs->sc_link->target; - rp->siop_temp = 0; - rp->siop_dsa = kvtop(&sc->sc_nexus->ds); - rp->siop_sxfer = sc->sc_sync[target].sxfer; - rp->siop_sbcl = sc->sc_sync[target].sbcl; - rp->siop_dsp = sc->sc_scriptspa; - return (0); - } - if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff06) { - if (acb == NULL) - printf("%s: Bad message-in with no active command?\n", - sc->sc_dev.dv_xname); - /* Unrecognized message in byte */ -#if CACHECTL - /*cmmu_inval_cache(kvtop(&acb->msg[1]), 1);*/ - dma_cachectl (&acb->msg[1],1); -#endif - printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n", - sc->sc_dev.dv_xname, rp->siop_sfbr, acb->msg[1], rp->siop_sbcl); - /* what should be done here? */ - /*DCIAS(kvtop(&acb->msg[1]));*/ - rp->siop_dsp = sc->sc_scriptspa + Ent_switch; - return (0); - } - if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0a) { - /* Status phase wasn't followed by message in phase? */ - printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n", - sc->sc_dev.dv_xname, rp->siop_sbcl, rp->siop_sbdl); - if (rp->siop_sbcl == 0xa7) { - /* It is now, just continue the script? */ - rp->siop_dcntl |= SIOP_DCNTL_STD; - return (0); - } - - siopreset (sc); - *status = -1; - return 0; /* siopreset has cleaned up */ - } - - if (sstat0 & SIOP_SSTAT0_M_A) { /* Phase mismatch */ - -#ifdef DEBUG - printf("%s: Phase mismatch - expecting %x got %x\n", - sc->sc_dev.dv_xname, rp->siop_dcmd & 0x07, - rp->siop_sstat2 & 0x07); - ++siopphmm; -#endif - if (acb == NULL) { - printf("%s: Phase mismatch with no active command- expecting %x got %x\n", - sc->sc_dev.dv_xname, - *((long *)&rp->siop_dcmd) & 0x07000000, - rp->siop_sstat2 & 0x07); - goto bad_phase; - } - - if (acb->iob_len) { - int adjust; - adjust = ((dfifo - (dbc & 0x7f)) & 0x7f); - if (sstat1 & SIOP_SSTAT1_ORF) - ++adjust; - if (sstat1 & SIOP_SSTAT1_OLF) - ++adjust; - /* XXX what's with this siop_dcmd here? nivas */ - acb->iob_curlen = *((long *)&rp->siop_dcmd) & 0xffffff; - acb->iob_curlen += adjust; - acb->iob_curbuf = *((long *)&rp->siop_dnad) - adjust; -#ifdef DEBUG - if (siop_debug & 0x100) { - int i; - printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n", - acb->iob_curbuf, acb->iob_curlen, dfifo, - dbc, sstat1, adjust, rp->siop_sbcl, siopstarts, acb); - if (acb->ds.chain[1].datalen) { - for (i = 0; acb->ds.chain[i].datalen; ++i) - printf("chain[%d] addr %p len %lx\n", - i, acb->ds.chain[i].databuf, - acb->ds.chain[i].datalen); - } - } -#endif -#if 0 - dma_cachectl(acb, sizeof(*acb), DMA_CACHE_SYNC); -#endif - } -#ifdef DEBUG - SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp); - if (siop_debug & 9) - printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n", - rp->siop_sbcl, - rp->siop_dsp - sc->sc_scriptspa, - *((long *)&rp->siop_dcmd)); -#endif - if ((rp->siop_sbcl & SIOP_REQ) == 0) { - printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n", - rp->siop_sbcl, rp->siop_dsp); -#if defined(DEBUG) && defined(DDB) - Debugger(); -#endif - goto bad_phase; - } -#if XXX - switch (rp->siop_sbcl & 7) -#endif - switch (rp->siop_sstat2 & 7) { - case 0: /* data out */ - case 1: /* data in */ - case 2: /* command */ - case 3: /* status */ - case 6: /* message out */ - case 7: /* message in */ - rp->siop_dsp = sc->sc_scriptspa + Ent_switch; - break; - default: - goto bad_phase; - } - return 0; - } - - if (sstat0 & SIOP_SSTAT0_STO) { /* SCSI bus time out */ - - if (acb == NULL) { - printf("%s: SCSI bus timeout with no active command?\n", - sc->sc_dev.dv_xname); - /*Debugger();*/ - } - - printf ("STO: scripts %x dsp %x dcmd %x dsps %x\n", sc->sc_scriptspa, - rp->siop_dsp, *((long *)&rp->siop_dcmd), rp->siop_dsps); - - if ((istat & SIOP_ISTAT_CON) == 0) { - printf("selection of %x timeout\n", rp->siop_sdid); - } else if ((rp->siop_ctest0 & SIOP_CTEST0_BTD) == 0) { - printf("No SCSI activity for 250ms(ctest0 %x %x dsps %x)\n", - rp->siop_ctest0, - rp->siop_ctest0, - rp->siop_dsps); - } else { - printf("Waited > 250ms for disconnect\n"); - } - -#ifdef DEBUG - printf ("scripts %x dsp %x dcmd %x\n", sc->sc_scriptspa, - rp->siop_dsp, *((long *)&rp->siop_dcmd)); - - printf("msg %x status %x\n", acb->msg[0], acb->stat[0]); - - if (rp->siop_sbcl & SIOP_BSY) { - printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n", - rp, &scripts, &acb->ds); - printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n", - rp->siop_sbcl, rp->siop_sdid, istat, dstat, sstat0); - if (!(rp->siop_sbcl & SIOP_BSY)) { - printf ("Yikes, it's not busy now!\n"); -#if 0 - *status = -1; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; -#endif - } - - /* - * I am not sure if DCNTL_STD can be used to restart. - * The manual discusses this bit only for manual start - * mode and single step mode, which we are not using. - * I will give it a shot... nivas - */ - - if (kludge_city) { - dummy = rp->siop_dsp; - rp->siop_dsp = dummy; - } else { - rp->siop_dcntl |= SIOP_DCNTL_STD; - } - return (0); -#ifdef DDB - Debugger(); -#endif - } -#endif - if (rp->siop_sbcl & SIOP_BSY) { - if (!(rp->siop_sbcl & SIOP_BSY)) { - printf ("Yikes, it's not busy now!\n"); - *status = -1; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; - } - - rp->siop_dcntl |= SIOP_DCNTL_STD; - - return 0; - } - - *status = -1; - if (acb) - acb->xs->error = XS_SELTIMEOUT; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return 1; - } - - if (acb) - target = acb->xs->sc_link->target; - else - target = 7; - - if (sstat0 & SIOP_SSTAT0_UDC) { -#ifdef DEBUG - if (acb == NULL) - printf("%s: Unexpected disconnect with no active command?\n", - sc->sc_dev.dv_xname); - printf ("%s: target %d disconnected unexpectedly\n", - sc->sc_dev.dv_xname, target); -#endif -#if 0 - siopabort (sc, rp, "siopchkintr"); -#endif - *status = STS_BUSY; - if (sc->nexus_list.tqh_first) - rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; - return (acb != NULL); - } - - if (sstat0 == 0 && dstat & SIOP_DSTAT_SIR) { -#if CACHECTL - /*cmmu_inval_cache(kvtop(&acb->stat[0]), 1); */ - /*cmmu_inval_cache(kvtop(&acb->msg[0]), 1); */ - dma_cachectl (&acb->stat[0], 1); - dma_cachectl (&acb->msg[0], 1); -#endif - printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n", - rp->siop_dsps, acb->stat[0], acb->msg[0], acb->msg[1], - rp->siop_sbcl); - siopreset (sc); - *status = -1; - return 0; /* siopreset has cleaned up */ - } - if (sstat0 & SIOP_SSTAT0_SGE) - printf ("SIOP: SCSI Gross Error\n"); - if (sstat0 & SIOP_SSTAT0_PAR) - printf ("SIOP: Parity Error\n"); - - if (dstat & SIOP_DSTAT_IID) { - printf ("SIOP: Illegal instruction detected (dsp %x dcmd %x dsps %x)\n", - rp->siop_dsp, *((long *)&rp->siop_dcmd), - rp->siop_dsps); - - if (*((long *)&rp->siop_dcmd) & 0xf8000000 == 0x48000000) { /* wait disconnect */ - printf("SIOP was executing wait disconnect\n"); - } - } - -bad_phase: -#if XXX - /* - * temporary panic for unhandled conditions - * displays various things about the 53C710 status and registers - * then panics. - * XXXX need to clean this up to print out the info, reset, and continue - */ - printf ("siopchkintr: target %x ds %x\n", target, &acb->ds); - printf ("scripts %x ds %x rp %x dsp %x dcmd %x\n", sc->sc_scriptspa, - kvtop(&acb->ds), kvtop(rp), rp->siop_dsp, - *((long *)&rp->siop_dcmd)); - printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x " - "dsa %x sbcl %x sts %x msg %x %x sfbr %x\n", - istat, dstat, sstat0, rp->siop_dsps, rp->siop_dsa, - rp->siop_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], - rp->siop_sfbr); -#ifdef DEBUG - if (siop_debug & 0x20) - panic("siopchkintr: **** temp ****"); -#ifdef DDB - /* Debugger(); */ -#endif -#endif -#endif /* XXX */ - siopreset (sc); /* hard reset */ - *status = -1; - return 0; /* siopreset cleaned up */ -} - -void -siop_select(sc) - struct siop_softc *sc; -{ - siop_regmap_p rp; - struct siop_acb *acb = sc->sc_nexus; - -#ifdef DEBUG - if (siop_debug & 1) - printf ("%s: select ", sc->sc_dev.dv_xname); -#endif - - rp = sc->sc_siopp; - if (acb->xs->flags & SCSI_POLL || siop_no_dma) { - sc->sc_flags |= SIOP_INTSOFF; - sc->sc_flags &= ~SIOP_INTDEFER; - if ((rp->siop_istat & 0x08) == 0) { - rp->siop_sien = 0; - rp->siop_dien = 0; - } -#if 0 - } else if ((sc->sc_flags & SIOP_INTDEFER) == 0) { - sc->sc_flags &= ~SIOP_INTSOFF; - if ((rp->siop_istat & 0x08) == 0) { - rp->siop_sien = sc->sc_sien; - rp->siop_dien = sc->sc_dien; - } -#endif - } -#ifdef DEBUG - if (siop_debug & 1) - printf ("siop_select: target %x cmd %02x ds %x\n", - acb->xs->sc_link->target, acb->cmd.opcode, - &sc->sc_nexus->ds); -#endif - - siop_start(sc, acb->xs->sc_link->target, acb->xs->sc_link->lun, - (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft); - - return; -} - -/* - * 53C710 interrupt handler - */ - -int -siopintr (sc) - register struct siop_softc *sc; -{ - siop_regmap_p rp; - register u_char istat, dstat, sstat0; - int status; - int s = splbio(); - - istat = sc->sc_istat; - if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) { - /* is this possible? we won't come here if there is not int!!! XXX */ - splx(s); - return; - } - - /* Got a valid interrupt on this device */ - rp = sc->sc_siopp; - dstat = sc->sc_dstat; - sstat0 = sc->sc_sstat0; - if (dstat & SIOP_DSTAT_SIR) - sc->sc_intcode = rp->siop_dsps; /* XXX use sc_intcode instead of dsps */ - - /* Clear the copies in sc */ - sc->sc_istat = 0; - sc->sc_dstat = 0; - sc->sc_sstat0 = 0; - -#ifdef DEBUG - if (siop_debug & 1) - printf ("%s: intr istat %x dstat %x sstat0 %x\n", - sc->sc_dev.dv_xname, istat, dstat, sstat0); - if (!sc->sc_active) { - printf ("%s: spurious interrupt? istat %x dstat %x sstat0 %x status %x\n", - sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus->stat[0]); - } -#endif - -#ifdef DEBUG - if (siop_debug & 5) { -#if CACHECTL - /*cmmu_inval_cache(kvtop(&sc->sc_nexus->stat[0]), - sizeof(sc->sc_nexus->stat[0])); */ - dma_cachectl(&sc->sc_nexus->stat[0], - sizeof(sc->sc_nexus->stat[0])); -#endif - printf ("%s: intr istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n", - sc->sc_dev.dv_xname, istat, dstat, sstat0, - rp->siop_dsps, rp->siop_sbcl, - sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]); - } -#endif - if (sc->sc_flags & SIOP_INTDEFER) { - sc->sc_flags &= ~(SIOP_INTDEFER | SIOP_INTSOFF); - rp->siop_sien = sc->sc_sien; - rp->siop_dien = sc->sc_dien; - } - if (siop_checkintr (sc, istat, dstat, sstat0, &status)) { -#if 1 - if (status == 0xff) - printf ("siopintr: status == 0xff\n"); -#endif - if ((sc->sc_flags & (SIOP_INTSOFF | SIOP_INTDEFER)) != SIOP_INTSOFF) { -#if 0 - if (rp->siop_sbcl & SIOP_BSY) { - printf ("%s: SCSI bus busy at completion", - sc->sc_dev.dv_xname); - printf(" targ %d sbcl %02x sfbr %x lcrc %02x dsp +%x\n", - sc->sc_nexus->xs->sc_link->target, - rp->siop_sbcl, rp->siop_sfbr, rp->siop_lcrc, - rp->siop_dsp - sc->sc_scriptspa); - } -#endif - siop_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]); - } - } - splx(s); -} - -/* - * This is based on the Progressive Peripherals 33Mhz Zeus driver and will - * not be correct for other 53c710 boards. - * XXX fix this - nivas - */ -void -scsi_period_to_siop (sc, target) - struct siop_softc *sc; - int target; -{ - int period, offset, sxfer, sbcl = 0; -#ifdef DEBUG_SYNC - int i; -#endif - - period = sc->sc_nexus->msg[4]; - offset = sc->sc_nexus->msg[5]; -#ifdef DEBUG_SYNC - sxfer = 0; - if (offset <= SIOP_MAX_OFFSET) - sxfer = offset; - for (i = 0; i < sizeof (sync_tab) / 2; ++i) { - if (period <= sync_tab[i].p) { - sxfer |= sync_tab[i].r & 0x70; - sbcl = sync_tab[i].r & 0x03; - break; - } - } - printf ("siop sync old: siop_sxfr %02x, siop_sbcl %02x\n", sxfer, sbcl); -#endif - for (sbcl = 1; sbcl < 4; ++sbcl) { - sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3; - if (sxfer >= 0 && sxfer <= 7) - break; - } - if (sbcl > 3) { - printf("siop_sync: unable to compute sync params for period %dns\n", - period * 4); - /* - * XXX need to pick a value we can do and renegotiate - */ - sxfer = sbcl = 0; - } else { - sxfer = (sxfer << 4) | ((offset <= SIOP_MAX_OFFSET) ? - offset : SIOP_MAX_OFFSET); -#ifdef DEBUG_SYNC - printf("siop sync: params for period %dns: sxfer %x sbcl %x", - period * 4, sxfer, sbcl); - printf(" actual period %dns\n", - sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4)); -#endif - } - sc->sc_sync[target].sxfer = sxfer; - sc->sc_sync[target].sbcl = sbcl; -#ifdef DEBUG_SYNC - printf ("siop sync: siop_sxfr %02x, siop_sbcl %02x\n", sxfer, sbcl); -#endif -} - -#ifdef DEBUG - -#if SIOP_TRACE_SIZE -void -siop_dump_trace() -{ - int i; - - printf("siop trace: next index %d\n", siop_trix); - i = siop_trix; - do { - printf("%3d: '%c' %02x %02x %02x\n", i, siop_trbuf[i], - siop_trbuf[i + 1], siop_trbuf[i + 2], siop_trbuf[i + 3]); - i = (i + 4) & (SIOP_TRACE_SIZE - 1); - } while (i != siop_trix); -} -#endif - -void -siop_dump_acb(acb) - struct siop_acb *acb; -{ - u_char *b = (u_char *) &acb->cmd; - int i; - - printf("acb@%p ", acb); - if (acb->xs == NULL) { - printf("\n"); - return; - } - printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target, - acb->xs->sc_link->lun, acb->flags, acb->clen); - for (i = acb->clen; i; --i) - printf(" %02x", *b++); - printf("\n"); - printf(" xs: %08x data %8x:%04x ", acb->xs, acb->xs->data, - acb->xs->datalen); - printf("va %8x:%04x ", acb->iob_buf, acb->iob_len); - printf("cur %8x:%04x\n", acb->iob_curbuf, acb->iob_curlen); -} - -void -siop_dump(sc) - struct siop_softc *sc; -{ - struct siop_acb *acb; - siop_regmap_p rp = sc->sc_siopp; - int s; - int i; - - s = splbio(); -#if SIOP_TRACE_SIZE - siop_dump_trace(); -#endif - printf("%s@%p regs %p istat %x\n", - sc->sc_dev.dv_xname, sc, rp, rp->siop_istat); - if (acb = sc->free_list.tqh_first) { - printf("Free list:\n"); - while (acb) { - siop_dump_acb(acb); - acb = acb->chain.tqe_next; - } - } - if (acb = sc->ready_list.tqh_first) { - printf("Ready list:\n"); - while (acb) { - siop_dump_acb(acb); - acb = acb->chain.tqe_next; - } - } - if (acb = sc->nexus_list.tqh_first) { - printf("Nexus list:\n"); - while (acb) { - siop_dump_acb(acb); - acb = acb->chain.tqe_next; - } - } - if (sc->sc_nexus) { - printf("Nexus:\n"); - siop_dump_acb(sc->sc_nexus); - } - for (i = 0; i < 8; ++i) { - if (sc->sc_tinfo[i].cmds > 2) { - printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n", - i, sc->sc_tinfo[i].cmds, - sc->sc_tinfo[i].dconns, - sc->sc_tinfo[i].senses, - sc->sc_tinfo[i].lubusy); - } - } - splx(s); -} -#endif diff --git a/sys/arch/mvme88k/dev/siop_script.out b/sys/arch/mvme88k/dev/siop_script.out deleted file mode 100644 index c6a91178fc8..00000000000 --- a/sys/arch/mvme88k/dev/siop_script.out +++ /dev/null @@ -1,175 +0,0 @@ -unsigned long scripts[] = { - 0x47000000, 0x00000118, /* 000 - 0 */ - 0x878b0000, 0x00000030, /* 008 - 8 */ - 0x868a0000, 0x00000168, /* 010 - 16 */ - 0x828a0000, 0x00000170, /* 018 - 24 */ - 0x808a0000, 0x00000180, /* 020 - 32 */ - 0x818a0000, 0x00000288, /* 028 - 40 */ - 0x838a0000, 0x00000390, /* 030 - 48 */ - 0x98080000, 0x0000ff05, /* 038 - 56 */ - 0x1f000024, 0x00000024, /* 040 - 64 */ - 0x808c0001, 0x00000040, /* 048 - 72 */ - 0x808c0004, 0x00000078, /* 050 - 80 */ - 0x808c0002, 0x00000088, /* 058 - 88 */ - 0x808c0007, 0x00000010, /* 060 - 96 */ - 0x808c0003, 0x00000008, /* 068 - 104 */ - 0x98080000, 0x0000ff06, /* 070 - 112 */ - 0x60000040, 0x00000000, /* 078 - 120 */ - 0x60000008, 0x00000000, /* 080 - 128 */ - 0x80880000, 0xffffff78, /* 088 - 136 */ - 0x60000040, 0x00000000, /* 090 - 144 */ - 0x1f00002c, 0x0000002c, /* 098 - 152 */ - 0x808c0003, 0x00000008, /* 0a0 - 160 */ - 0x98080000, 0x0000ff07, /* 0a8 - 168 */ - 0x60000040, 0x00000000, /* 0b0 - 176 */ - 0x1f000034, 0x00000034, /* 0b8 - 184 */ - 0x60000040, 0x00000000, /* 0c0 - 192 */ - 0x80880000, 0xffffff38, /* 0c8 - 200 */ - 0x60000040, 0x00000000, /* 0d0 - 208 */ - 0x48000000, 0x00000000, /* 0d8 - 216 */ - 0x98080000, 0x0000ff02, /* 0e0 - 224 */ - 0x60000040, 0x00000000, /* 0e8 - 232 */ - 0x87830000, 0xffffff10, /* 0f0 - 240 */ - 0x1f00002c, 0x0000002c, /* 0f8 - 248 */ - 0x98040004, 0x0000ff08, /* 100 - 256 */ - 0x60000040, 0x00000000, /* 108 - 264 */ - 0x48000000, 0x00000000, /* 110 - 272 */ - 0x98080000, 0x0000ff01, /* 118 - 280 */ - 0x54000000, 0x00000038, /* 120 - 288 */ - 0x72230000, 0x00000000, /* 128 - 296 */ - 0x6a340000, 0x00000000, /* 130 - 304 */ - 0x9f030000, 0x0000ff09, /* 138 - 312 */ - 0x1f00001c, 0x0000001c, /* 140 - 320 */ - 0x98080000, 0x0000ff03, /* 148 - 328 */ - 0x60000040, 0x00000000, /* 150 - 336 */ - 0x80880000, 0xfffffea8, /* 158 - 344 */ - 0x74011000, 0x00000000, /* 160 - 352 */ - 0x980c0000, 0x0000ff04, /* 168 - 360 */ - 0x74164000, 0x00000000, /* 170 - 368 */ - 0x80880000, 0xffffffa0, /* 178 - 376 */ - 0x1e000004, 0x00000004, /* 180 - 384 */ - 0x80880000, 0xfffffe78, /* 188 - 392 */ - 0x60000008, 0x00000000, /* 190 - 400 */ - 0x1a00000c, 0x0000000c, /* 198 - 408 */ - 0x80880000, 0xfffffe60, /* 1a0 - 416 */ - 0x1800003c, 0x0000003c, /* 1a8 - 424 */ - 0x88830000, 0xfffffe50, /* 1b0 - 432 */ - 0x18000044, 0x00000044, /* 1b8 - 440 */ - 0x88830000, 0xfffffe40, /* 1c0 - 448 */ - 0x1800004c, 0x0000004c, /* 1c8 - 456 */ - 0x88830000, 0xfffffe30, /* 1d0 - 464 */ - 0x18000054, 0x00000054, /* 1d8 - 472 */ - 0x88830000, 0xfffffe20, /* 1e0 - 480 */ - 0x1800005c, 0x0000005c, /* 1e8 - 488 */ - 0x88830000, 0xfffffe10, /* 1f0 - 496 */ - 0x18000064, 0x00000064, /* 1f8 - 504 */ - 0x88830000, 0xfffffe00, /* 200 - 512 */ - 0x1800006c, 0x0000006c, /* 208 - 520 */ - 0x88830000, 0xfffffdf0, /* 210 - 528 */ - 0x18000074, 0x00000074, /* 218 - 536 */ - 0x88830000, 0xfffffde0, /* 220 - 544 */ - 0x1800007c, 0x0000007c, /* 228 - 552 */ - 0x88830000, 0xfffffdd0, /* 230 - 560 */ - 0x18000084, 0x00000084, /* 238 - 568 */ - 0x88830000, 0xfffffdc0, /* 240 - 576 */ - 0x1800008c, 0x0000008c, /* 248 - 584 */ - 0x88830000, 0xfffffdb0, /* 250 - 592 */ - 0x18000094, 0x00000094, /* 258 - 600 */ - 0x88830000, 0xfffffda0, /* 260 - 608 */ - 0x1800009c, 0x0000009c, /* 268 - 616 */ - 0x88830000, 0xfffffd90, /* 270 - 624 */ - 0x180000a4, 0x000000a4, /* 278 - 632 */ - 0x88830000, 0xfffffd80, /* 280 - 640 */ - 0x180000ac, 0x000000ac, /* 288 - 648 */ - 0x88830000, 0xfffffd70, /* 290 - 656 */ - 0x180000b4, 0x000000b4, /* 298 - 664 */ - 0x88830000, 0xfffffd60, /* 2a0 - 672 */ - 0x180000bc, 0x000000bc, /* 2a8 - 680 */ - 0x88880000, 0xfffffd50, /* 2b0 - 688 */ - 0x1900003c, 0x0000003c, /* 2b8 - 696 */ - 0x89830000, 0xfffffd40, /* 2c0 - 704 */ - 0x19000044, 0x00000044, /* 2c8 - 712 */ - 0x89830000, 0xfffffd30, /* 2d0 - 720 */ - 0x1900004c, 0x0000004c, /* 2d8 - 728 */ - 0x89830000, 0xfffffd20, /* 2e0 - 736 */ - 0x19000054, 0x00000054, /* 2e8 - 744 */ - 0x89830000, 0xfffffd10, /* 2f0 - 752 */ - 0x1900005c, 0x0000005c, /* 2f8 - 760 */ - 0x89830000, 0xfffffd00, /* 300 - 768 */ - 0x19000064, 0x00000064, /* 308 - 776 */ - 0x89830000, 0xfffffcf0, /* 310 - 784 */ - 0x1900006c, 0x0000006c, /* 318 - 792 */ - 0x89830000, 0xfffffce0, /* 320 - 800 */ - 0x19000074, 0x00000074, /* 328 - 808 */ - 0x89830000, 0xfffffcd0, /* 330 - 816 */ - 0x1900007c, 0x0000007c, /* 338 - 824 */ - 0x89830000, 0xfffffcc0, /* 340 - 832 */ - 0x19000084, 0x00000084, /* 348 - 840 */ - 0x89830000, 0xfffffcb0, /* 350 - 848 */ - 0x1900008c, 0x0000008c, /* 358 - 856 */ - 0x89830000, 0xfffffca0, /* 360 - 864 */ - 0x19000094, 0x00000094, /* 368 - 872 */ - 0x89830000, 0xfffffc90, /* 370 - 880 */ - 0x1900009c, 0x0000009c, /* 378 - 888 */ - 0x89830000, 0xfffffc80, /* 380 - 896 */ - 0x190000a4, 0x000000a4, /* 388 - 904 */ - 0x89830000, 0xfffffc70, /* 390 - 912 */ - 0x190000ac, 0x000000ac, /* 398 - 920 */ - 0x89830000, 0xfffffc60, /* 3a0 - 928 */ - 0x190000b4, 0x000000b4, /* 3a8 - 936 */ - 0x89830000, 0xfffffc50, /* 3b0 - 944 */ - 0x190000bc, 0x000000bc, /* 3b8 - 952 */ - 0x88880000, 0xfffffc40, /* 3c0 - 960 */ - 0x1b000014, 0x00000014, /* 3c8 - 968 */ - 0x9f030000, 0x0000ff0a, /* 3d0 - 976 */ - 0x1f00001c, 0x0000001c, /* 3d8 - 984 */ - 0x60000040, 0x00000000, /* 3e0 - 992 */ - 0x48000000, 0x00000000, /* 3e8 - 1000 */ - 0x98080000, 0x0000ff00, /* 3f0 - 1008 */ - 0x80880000, 0xfffffd20, /* 3f8 - 1016 */ -}; - -#define A_ds_Device 0x00000000 -#define A_ds_MsgOut 0x00000004 -#define A_ds_Cmd 0x0000000c -#define A_ds_Status 0x00000014 -#define A_ds_Msg 0x0000001c -#define A_ds_MsgIn 0x00000024 -#define A_ds_ExtMsg 0x0000002c -#define A_ds_SyncMsg 0x00000034 -#define A_ds_Data1 0x0000003c -#define A_ds_Data2 0x00000044 -#define A_ds_Data3 0x0000004c -#define A_ds_Data4 0x00000054 -#define A_ds_Data5 0x0000005c -#define A_ds_Data6 0x00000064 -#define A_ds_Data7 0x0000006c -#define A_ds_Data8 0x00000074 -#define A_ds_Data9 0x0000007c -#define A_ds_Data10 0x00000084 -#define A_ds_Data11 0x0000008c -#define A_ds_Data12 0x00000094 -#define A_ds_Data13 0x0000009c -#define A_ds_Data14 0x000000a4 -#define A_ds_Data15 0x000000ac -#define A_ds_Data16 0x000000b4 -#define A_ds_Data17 0x000000bc -#define A_ok 0x0000ff00 -#define A_err1 0x0000ff01 -#define A_err2 0x0000ff02 -#define A_err3 0x0000ff03 -#define A_err4 0x0000ff04 -#define A_err5 0x0000ff05 -#define A_err6 0x0000ff06 -#define A_err7 0x0000ff07 -#define A_err8 0x0000ff08 -#define A_err9 0x0000ff09 -#define A_err10 0x0000ff0a -#define Ent_scripts 0x00000000 -#define Ent_switch 0x00000008 -#define Ent_wait_reselect 0x00000120 -#define Ent_dataout 0x000001a8 -#define Ent_datain 0x000002b8 - -unsigned long INSTRUCTIONS = 0x00000080; -unsigned long PATCHES = 0x00000000; diff --git a/sys/arch/mvme88k/dev/siop_script.ss b/sys/arch/mvme88k/dev/siop_script.ss deleted file mode 100644 index c107e71469b..00000000000 --- a/sys/arch/mvme88k/dev/siop_script.ss +++ /dev/null @@ -1,205 +0,0 @@ -; $OpenBSD: siop_script.ss,v 1.2 1998/12/15 05:52:31 smurph Exp $ - -; -; Copyright (c) 1995 Michael L. Hitch -; 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 Michael L. Hitch. -; 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. -; - -; NCR 53c710 script -; -ABSOLUTE ds_Device = 0 -ABSOLUTE ds_MsgOut = ds_Device + 4 -ABSOLUTE ds_Cmd = ds_MsgOut + 8 -ABSOLUTE ds_Status = ds_Cmd + 8 -ABSOLUTE ds_Msg = ds_Status + 8 -ABSOLUTE ds_MsgIn = ds_Msg + 8 -ABSOLUTE ds_ExtMsg = ds_MsgIn + 8 -ABSOLUTE ds_SyncMsg = ds_ExtMsg + 8 -ABSOLUTE ds_Data1 = ds_SyncMsg + 8 -ABSOLUTE ds_Data2 = ds_Data1 + 8 -ABSOLUTE ds_Data3 = ds_Data2 + 8 -ABSOLUTE ds_Data4 = ds_Data3 + 8 -ABSOLUTE ds_Data5 = ds_Data4 + 8 -ABSOLUTE ds_Data6 = ds_Data5 + 8 -ABSOLUTE ds_Data7 = ds_Data6 + 8 -ABSOLUTE ds_Data8 = ds_Data7 + 8 -ABSOLUTE ds_Data9 = ds_Data8 + 8 - -ABSOLUTE ok = 0xff00 -ABSOLUTE err1 = 0xff01 -ABSOLUTE err2 = 0xff02 -ABSOLUTE err3 = 0xff03 -ABSOLUTE err4 = 0xff04 -ABSOLUTE err5 = 0xff05 -ABSOLUTE err6 = 0xff06 -ABSOLUTE err7 = 0xff07 -ABSOLUTE err8 = 0xff08 -ABSOLUTE err9 = 0xff09 -ABSOLUTE err10 = 0xff0a - -ENTRY scripts -ENTRY switch -ENTRY wait_reselect -ENTRY dataout -ENTRY datain - -PROC scripts: - -scripts: - - SELECT ATN FROM ds_Device, REL(reselect) -; -switch: - JUMP REL(msgin), WHEN MSG_IN - JUMP REL(msgout), IF MSG_OUT - JUMP REL(command_phase), IF CMD - JUMP REL(dataout), IF DATA_OUT - JUMP REL(datain), IF DATA_IN - JUMP REL(end), IF STATUS - - INT err5 ; Unrecognized phase - -msgin: - MOVE FROM ds_MsgIn, WHEN MSG_IN - JUMP REL(ext_msg), IF 0x01 ; extended message - JUMP REL(disc), IF 0x04 ; disconnect message - JUMP REL(msg_sdp), IF 0x02 ; save data pointers - JUMP REL(msg_rej), IF 0x07 ; message reject - JUMP REL(msg_rdp), IF 0x03 ; restore data pointers - INT err6 ; unrecognized message - -msg_rdp: -msg_rej: - CLEAR ACK - CLEAR ATN - JUMP REL(switch) - -ext_msg: - CLEAR ACK - MOVE FROM ds_ExtMsg, WHEN MSG_IN - JUMP REL(sync_msg), IF 0x03 - int err7 ; extended message not SDTR - -sync_msg: - CLEAR ACK - MOVE FROM ds_SyncMsg, WHEN MSG_IN - CLEAR ACK - JUMP REL(switch) - -disc: - CLEAR ACK - WAIT DISCONNECT - - int err2 ; signal disconnect w/o save DP - -msg_sdp: - CLEAR ACK ; acknowledge message - JUMP REL(switch), WHEN NOT MSG_IN - MOVE FROM ds_ExtMsg, WHEN MSG_IN - INT err8, IF NOT 0x04 ; interrupt if not disconnect - CLEAR ACK - WAIT DISCONNECT - - INT err1 ; signal disconnect - -reselect: -wait_reselect: - WAIT RESELECT REL(select_adr) - MOVE LCRC to SFBR ; Save reselect ID - MOVE SFBR to SCRATCH0 - - INT err9, WHEN NOT MSG_IN ; didn't get IDENTIFY - MOVE FROM ds_Msg, WHEN MSG_IN - INT err3 ; let host know about reconnect - CLEAR ACK ; acknowlege the message - JUMP REL(switch) - - -select_adr: - MOVE SCNTL1 & 0x10 to SFBR ; get connected status - INT err4, IF 0x00 ; tell host if not connected - MOVE CTEST2 & 0x40 to SFBR ; clear Sig_P - JUMP REL(wait_reselect) ; and try reselect again - -msgout: - MOVE FROM ds_MsgOut, WHEN MSG_OUT - JUMP REL(switch) - -command_phase: - CLEAR ATN - MOVE FROM ds_Cmd, WHEN CMD - JUMP REL(switch) - -dataout: - MOVE FROM ds_Data1, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data2, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data3, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data4, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data5, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data6, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data7, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data8, WHEN DATA_OUT - CALL REL(switch), WHEN NOT DATA_OUT - MOVE FROM ds_Data9, WHEN DATA_OUT - CALL REL(switch) - -datain: - MOVE FROM ds_Data1, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data2, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data3, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data4, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data5, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data6, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data7, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data8, WHEN DATA_IN - CALL REL(switch), WHEN NOT DATA_IN - MOVE FROM ds_Data9, WHEN DATA_IN - CALL REL(switch) - -end: - MOVE FROM ds_Status, WHEN STATUS - int err10, WHEN NOT MSG_IN ; status not followed by msg - MOVE FROM ds_Msg, WHEN MSG_IN - CLEAR ACK - WAIT DISCONNECT - INT ok ; signal completion - JUMP REL(wait_reselect) diff --git a/sys/arch/mvme88k/dev/siopdma.c b/sys/arch/mvme88k/dev/siopdma.c deleted file mode 100644 index 698793e0af8..00000000000 --- a/sys/arch/mvme88k/dev/siopdma.c +++ /dev/null @@ -1,295 +0,0 @@ -/* $OpenBSD: siopdma.c,v 1.3 2001/01/13 05:18:58 smurph Exp $ */ - -/* - * Copyright (c) 1996 Nivas Madhur - * Copyright (c) 1995 Theo de Raadt - * Copyright (c) 1994 Michael L. Hitch - * Copyright (c) 1982, 1990 The Regents of the University of California. - * 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 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. - * - * @(#)dma.c - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(MVME187) -#include -#endif /* MVME187 */ - -#if defined(MVME187) -#include -#include -#else -#include -#include -#endif /* defined(MVME187) */ - -#if !defined(MVME187) -#include "mc.h" -#endif /* MVME187 */ -#include "pcctwo.h" - -#if NMC > 0 -#include -#endif -#if NPCCTWO > 0 -#if defined(MVME187) -#include -#else -#include -#endif /* defined(MVME187) */ -#endif - -#if defined(MVME187) -#include "machine/mmu.h" -#endif /* defined(MVME187) */ - -extern struct pmap kernel_pmap_store; -#define pmap_kernel() (&kernel_pmap_store) - -int afscmatch __P((struct device *, void *, void *)); -void afscattach __P((struct device *, struct device *, void *)); - -int afscprint __P((void *auxp, char *)); -int siopintr __P((struct siop_softc *)); -int afsc_dmaintr __P((struct siop_softc *)); - -struct scsi_adapter afsc_scsiswitch = { - siop_scsicmd, - siop_minphys, - 0, /* no lun support */ - 0, /* no lun support */ -}; - -struct scsi_device afsc_scsidev = { - NULL, /* use default error handler */ - NULL, /* do not have a start function */ - NULL, /* have no async handler */ - NULL, /* Use default done routine */ -}; - -struct cfattach siop_ca = { - sizeof(struct siop_softc), afscmatch, afscattach, -}; - -struct cfdriver siop_cd = { - NULL, "siop", DV_DULL, 0 -}; - -int -afscmatch(pdp, vcf, args) - struct device *pdp; - void *vcf, *args; -{ - struct cfdata *cf = vcf; - struct confargs *ca = args; - int ret; - - if ((ret = badvaddr(IIOV(ca->ca_vaddr), 4)) <=0){ - printf("==> siop: failed address check returning %ld.\n", ret); - return(0); - } - - return (1); -} - -void -afscattach(parent, self, auxp) - struct device *parent, *self; - void *auxp; -{ - struct siop_softc *sc = (struct siop_softc *)self; - struct confargs *ca = auxp; - siop_regmap_p rp; - int tmp; - extern int cpuspeed; - - sc->sc_siopp = rp = ca->ca_vaddr; - - /* - * siop uses sc_clock_freq to define the dcntl & ctest7 reg values - * (was 0x0221, but i added SIOP_CTEST7_SC0 for snooping control) - * XXX does the clock frequency change for the 33MHz processors? - */ - sc->sc_clock_freq = cpuspeed * 2; -#ifdef MVME177 - /* XXX this is a guess! */ - if (cputyp == CPU_177) - sc->sc_clock_freq = cpuspeed; -#endif - sc->sc_dcntl = SIOP_DCNTL_EA; -/*X*/ if (sc->sc_clock_freq <= 25) -/*X*/ sc->sc_dcntl |= (2 << 6); -/*X*/ else if (sc->sc_clock_freq <= 37) -/*X*/ sc->sc_dcntl |= (1 << 6); -/*X*/ else if (sc->sc_clock_freq <= 50) -/*X*/ sc->sc_dcntl |= (0 << 6); -/*X*/ else -/*X*/ sc->sc_dcntl |= (3 << 6); - - sc->sc_ctest0 = SIOP_CTEST0_BTD | SIOP_CTEST0_EAN; - -#ifdef MVME187 - /* - * MVME187 doesn't implement snooping... - */ - sc->sc_ctest7 = SIOP_CTEST7_TT1; -#else - sc->sc_ctest7 = SIOP_CTEST7_SNOOP | SIOP_CTEST7_TT1 | SIOP_CTEST7_STD; -#endif /* MVME187 */ - - sc->sc_link.adapter_softc = sc; - sc->sc_link.adapter_target = 7; /* XXXX should ask ROM */ - sc->sc_link.adapter = &afsc_scsiswitch; - sc->sc_link.device = &afsc_scsidev; - sc->sc_link.openings = 1; - - sc->sc_ih.ih_fn = afsc_dmaintr; - sc->sc_ih.ih_arg = sc; - sc->sc_ih.ih_ipl = ca->ca_ipl; - - siopinitialize(sc); - - switch (ca->ca_bustype) { -#if NMC > 0 - case BUS_MC: - { - struct mcreg *mc = (struct mcreg *)ca->ca_master; - - mcintr_establish(MCV_NCR, &sc->sc_ih); - mc->mc_ncrirq = ca->ca_ipl | MC_IRQ_IEN; - break; - } -#endif -#if NPCCTWO > 0 - case BUS_PCCTWO: - { -#if defined(MVME187) - /* - * Disable caching for the softc. Actually, I want - * to disable cache for acb structures, but they are - * part of softc, and I am disabling the entire softc - * just in case. - */ - - struct pcctworeg *pcc2 = (struct pcctworeg *)ca->ca_master; - - pmap_cache_ctrl(pmap_kernel(), M88K_TRUNC_PAGE((vm_offset_t)sc), - M88K_ROUND_PAGE((vm_offset_t)sc + sizeof(*sc)), - CACHE_INH); -#endif - pcctwointr_establish(PCC2V_NCR, &sc->sc_ih); -/* intr_establish(PCC2_VECT + SCSIIRQ, &sc->sc_ih);*/ - /* enable interrupts at ca_ipl */ - pcc2->pcc2_ncrirq = ca->ca_ipl | PCC2_IRQ_IEN; -/* pcc2->pcc2_scsiirq = ca->ca_ipl | PCC2_SCSIIRQ_IEN;*/ - break; - } -#endif - } - - evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); - - /* - * attach all scsi units on us, watching for boot device - * (see dk_establish). - */ - tmp = bootpart; - if (ca->ca_paddr != bootaddr) - bootpart = -1; /* invalid flag to dk_establish */ - config_found(self, &sc->sc_link, scsiprint); - bootpart = tmp; /* restore old value */ -} -/* - * print diag if pnp is NULL else just extra - */ -int -afscprint(auxp, pnp) - void *auxp; - char *pnp; -{ - if (pnp == NULL) - return (UNCONF); - return (QUIET); -} - -int -afsc_dmaintr(sc) - struct siop_softc *sc; -{ - siop_regmap_p rp; - u_char istat; - - rp = sc->sc_siopp; - istat = rp->siop_istat; - if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) - return (0); - if ((rp->siop_sien | rp->siop_dien) == 0) - return (0); /* no interrupts enabled */ - - /* - * 53c710 manual recommends reading dstat and sstat0 at least - * 12 clk cycles apart if reading as bytes (which is what - * pcc2 permits). Stick in a 1us delay between accessing dstat and - * sstat0 below. - * - * save interrupt status, DMA status, and SCSI status 0 - * (may need to deal with stacked interrupts?) - */ - sc->sc_istat = istat; - if (istat & SIOP_ISTAT_SIP) { - sc->sc_sstat0 = rp->siop_sstat0; - } - if (istat & SIOP_ISTAT_DIP) { - delay(3); - sc->sc_dstat = rp->siop_dstat; - } - siopintr(sc); - sc->sc_intrcnt.ev_count++; - return (1); -} - -#ifdef XXX_CD_DEBUG /* XXXsmurph What is afsccd ?? */ -void -afsc_dump() -{ - int i; - - for (i = 0; i < afsccd.cd_ndevs; ++i) - if (afsccd.cd_devs[i]) - siop_dump(afsccd.cd_devs[i]); -} -#endif diff --git a/sys/arch/mvme88k/dev/siopreg.h b/sys/arch/mvme88k/dev/siopreg.h deleted file mode 100644 index d4345934bb5..00000000000 --- a/sys/arch/mvme88k/dev/siopreg.h +++ /dev/null @@ -1,336 +0,0 @@ -/* $OpenBSD: siopreg.h,v 1.2 1998/12/15 05:52:31 smurph Exp $ */ - -/* - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson of Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)siopreg.h 7.3 (Berkeley) 2/5/91 - */ - -/* - * NCR 53C710 SCSI interface hardware description. - * - * From the Mach scsi driver for the 53C700 - */ - -typedef struct { -/*00*/ volatile unsigned char siop_sien; /* rw: SCSI Interrupt Enable */ -/*01*/ volatile unsigned char siop_sdid; /* rw: SCSI Destination ID */ -/*02*/ volatile unsigned char siop_scntl1; /* rw: SCSI control reg 1 */ -/*03*/ volatile unsigned char siop_scntl0; /* rw: SCSI control reg 0 */ -/*04*/ volatile unsigned char siop_socl; /* rw: SCSI Output Control Latch */ -/*05*/ volatile unsigned char siop_sodl; /* rw: SCSI Output Data Latch */ -/*06*/ volatile unsigned char siop_sxfer; /* rw: SCSI Transfer reg */ -/*07*/ volatile unsigned char siop_scid; /* rw: SCSI Chip ID reg */ -/*08*/ volatile unsigned char siop_sbcl; /* ro: SCSI Bus Control Lines */ -/*09*/ volatile unsigned char siop_sbdl; /* ro: SCSI Bus Data Lines */ -/*0a*/ volatile unsigned char siop_sidl; /* ro: SCSI Input Data Latch */ -/*0b*/ volatile unsigned char siop_sfbr; /* ro: SCSI First Byte Received */ -/*0c*/ volatile unsigned char siop_sstat2; /* ro: SCSI status reg 2 */ -/*0d*/ volatile unsigned char siop_sstat1; /* ro: SCSI status reg 1 */ -/*0e*/ volatile unsigned char siop_sstat0; /* ro: SCSI status reg 0 */ -/*0f*/ volatile unsigned char siop_dstat; /* ro: DMA status */ -/*10*/ volatile unsigned long siop_dsa; /* rw: Data Structure Address */ -/*14*/ volatile unsigned char siop_ctest3; /* ro: Chip test register 3 */ -/*15*/ volatile unsigned char siop_ctest2; /* ro: Chip test register 2 */ -/*16*/ volatile unsigned char siop_ctest1; /* ro: Chip test register 1 */ -/*17*/ volatile unsigned char siop_ctest0; /* ro: Chip test register 0 */ -/*18*/ volatile unsigned char siop_ctest7; /* rw: Chip test register 7 */ -/*19*/ volatile unsigned char siop_ctest6; /* rw: Chip test register 6 */ -/*1a*/ volatile unsigned char siop_ctest5; /* rw: Chip test register 5 */ -/*1b*/ volatile unsigned char siop_ctest4; /* rw: Chip test register 4 */ -/*1c*/ volatile unsigned long siop_temp; /* rw: Temporary Stack reg */ -/*20*/ volatile unsigned char siop_lcrc; /* rw: LCRC value */ -/*21*/ volatile unsigned char siop_ctest8; /* rw: Chip test register 8 */ -/*22*/ volatile unsigned char siop_istat; /* rw: Interrupt Status reg */ -/*23*/ volatile unsigned char siop_dfifo; /* rw: DMA FIFO */ -/*24*/ volatile unsigned char siop_dcmd; /* rw: DMA Command Register */ -/*25*/ volatile unsigned char siop_dbc2; /* rw: DMA Byte Counter reg */ -/*26*/ volatile unsigned char siop_dbc1; -/*27*/ volatile unsigned char siop_dbc0; -/*28*/ volatile unsigned long siop_dnad; /* rw: DMA Next Address */ -/*2c*/ volatile unsigned long siop_dsp; /* rw: DMA SCRIPTS Pointer reg */ -/*30*/ volatile unsigned long siop_dsps; /* rw: DMA SCRIPTS Pointer Save reg */ -/*34*/ volatile unsigned long siop_scratch; /* rw: Scratch Register */ -/*38*/ volatile unsigned char siop_dcntl; /* rw: DMA Control reg */ -/*39*/ volatile unsigned char siop_dwt; /* rw: DMA Watchdog Timer */ -/*3a*/ volatile unsigned char siop_dien; /* rw: DMA Interrupt Enable */ -/*3b*/ volatile unsigned char siop_dmode; /* rw: DMA Mode reg */ -/*3c*/ volatile unsigned long siop_adder; - -} siop_regmap_t; -typedef volatile siop_regmap_t *siop_regmap_p; - -/* - * Register defines - */ - -/* Scsi control register 0 (scntl0) */ - -#define SIOP_SCNTL0_ARB 0xc0 /* Arbitration mode */ -# define SIOP_ARB_SIMPLE 0x00 -# define SIOP_ARB_FULL 0xc0 -#define SIOP_SCNTL0_START 0x20 /* Start Sequence */ -#define SIOP_SCNTL0_WATN 0x10 /* (Select) With ATN */ -#define SIOP_SCNTL0_EPC 0x08 /* Enable Parity Checking */ -#define SIOP_SCNTL0_EPG 0x04 /* Enable Parity Generation */ -#define SIOP_SCNTL0_AAP 0x02 /* Assert ATN on Parity Error */ -#define SIOP_SCNTL0_TRG 0x01 /* Target Mode */ - -/* Scsi control register 1 (scntl1) */ - -#define SIOP_SCNTL1_EXC 0x80 /* Extra Clock Cycle of data setup */ -#define SIOP_SCNTL1_ADB 0x40 /* Assert Data Bus */ -#define SIOP_SCNTL1_ESR 0x20 /* Enable Selection/Reselection */ -#define SIOP_SCNTL1_CON 0x10 /* Connected */ -#define SIOP_SCNTL1_RST 0x08 /* Assert RST */ -#define SIOP_SCNTL1_AESP 0x04 /* Assert even SCSI parity */ -#define SIOP_SCNTL1_RES0 0x02 /* Reserved */ -#define SIOP_SCNTL1_RES1 0x01 /* Reserved */ - -/* Scsi interrupt enable register (sien) */ - -#define SIOP_SIEN_M_A 0x80 /* Phase Mismatch or ATN active */ -#define SIOP_SIEN_FCMP 0x40 /* Function Complete */ -#define SIOP_SIEN_STO 0x20 /* (Re)Selection timeout */ -#define SIOP_SIEN_SEL 0x10 /* (Re)Selected */ -#define SIOP_SIEN_SGE 0x08 /* SCSI Gross Error */ -#define SIOP_SIEN_UDC 0x04 /* Unexpected Disconnect */ -#define SIOP_SIEN_RST 0x02 /* RST asserted */ -#define SIOP_SIEN_PAR 0x01 /* Parity Error */ - -/* Scsi chip ID (scid) */ - -#define SIOP_SCID_VALUE(i) (1< asserted */ -#define SIOP_ACK 0x40 -#define SIOP_BSY 0x20 -#define SIOP_SEL 0x10 -#define SIOP_ATN 0x08 -#define SIOP_MSG 0x04 -#define SIOP_CD 0x02 -#define SIOP_IO 0x01 - -#define SIOP_PHASE(socl) SCSI_PHASE(socl) - -/* Scsi first byte received register (sfbr) */ - -/* Scsi input data latch register (sidl) */ - -/* Scsi bus data lines register (sbdl) */ - -/* Scsi bus control lines register (sbcl). Same as socl */ - -/* DMA status register (dstat) */ - -#define SIOP_DSTAT_DFE 0x80 /* DMA FIFO empty */ -#define SIOP_DSTAT_RES 0x40 -#define SIOP_DSTAT_BF 0x20 /* Bus fault */ -#define SIOP_DSTAT_ABRT 0x10 /* Aborted */ -#define SIOP_DSTAT_SSI 0x08 /* SCRIPT Single Step */ -#define SIOP_DSTAT_SIR 0x04 /* SCRIPT Interrupt Instruction */ -#define SIOP_DSTAT_WTD 0x02 /* Watchdog Timeout Detected */ -#define SIOP_DSTAT_IID 0x01 /* Invalid Instruction Detected */ - -/* Scsi status register 0 (sstat0) */ - -#define SIOP_SSTAT0_M_A 0x80 /* Phase Mismatch or ATN active */ -#define SIOP_SSTAT0_FCMP 0x40 /* Function Complete */ -#define SIOP_SSTAT0_STO 0x20 /* (Re)Selection timeout */ -#define SIOP_SSTAT0_SEL 0x10 /* (Re)Selected */ -#define SIOP_SSTAT0_SGE 0x08 /* SCSI Gross Error */ -#define SIOP_SSTAT0_UDC 0x04 /* Unexpected Disconnect */ -#define SIOP_SSTAT0_RST 0x02 /* RST asserted */ -#define SIOP_SSTAT0_PAR 0x01 /* Parity Error */ - -/* Scsi status register 1 (sstat1) */ - -#define SIOP_SSTAT1_ILF 0x80 /* Input latch (sidl) full */ -#define SIOP_SSTAT1_ORF 0x40 /* output reg (sodr) full */ -#define SIOP_SSTAT1_OLF 0x20 /* output latch (sodl) full */ -#define SIOP_SSTAT1_AIP 0x10 /* Arbitration in progress */ -#define SIOP_SSTAT1_LOA 0x08 /* Lost arbitration */ -#define SIOP_SSTAT1_WOA 0x04 /* Won arbitration */ -#define SIOP_SSTAT1_RST 0x02 /* SCSI RST current value */ -#define SIOP_SSTAT1_SDP 0x01 /* SCSI SDP current value */ - -/* Scsi status register 2 (sstat2) */ - -#define SIOP_SSTAT2_FF 0xf0 /* SCSI FIFO flags (bytecount) */ -# define SIOP_SCSI_FIFO_DEEP 8 -#define SIOP_SSTAT2_SDP 0x08 /* Latched (on REQ) SCSI SDP */ -#define SIOP_SSTAT2_MSG 0x04 /* Latched SCSI phase */ -#define SIOP_SSTAT2_CD 0x02 -#define SIOP_SSTAT2_IO 0x01 - -/* Chip test register 0 (ctest0) */ - -#define SIOP_CTEST0_RES0 0x80 -#define SIOP_CTEST0_BTD 0x40 /* Byte-to-byte Timer Disable */ -#define SIOP_CTEST0_GRP 0x20 /* Generate Receive Parity for Passthrough */ -#define SIOP_CTEST0_EAN 0x10 /* Enable Active Negation */ -#define SIOP_CTEST0_HSC 0x08 /* Halt SCSI clock */ -#define SIOP_CTEST0_ERF 0x04 /* Extend REQ/ACK Filtering */ -#define SIOP_CTEST0_RES1 0x02 -#define SIOP_CTEST0_DDIR 0x01 /* Xfer direction (1-> from SCSI bus) */ - -/* Chip test register 1 (ctest1) */ - -#define SIOP_CTEST1_FMT 0xf0 /* Byte empty in DMA FIFO bottom (high->byte3) */ -#define SIOP_CTEST1_FFL 0x0f /* Byte full in DMA FIFO top, same */ - -/* Chip test register 2 (ctest2) */ - -#define SIOP_CTEST2_RES 0x80 -#define SIOP_CTEST2_SIGP 0x40 /* Signal process */ -#define SIOP_CTEST2_SOFF 0x20 /* Synch Offset compare (1-> zero Init, max Tgt */ -#define SIOP_CTEST2_SFP 0x10 /* SCSI FIFO Parity */ -#define SIOP_CTEST2_DFP 0x08 /* DMA FIFO Parity */ -#define SIOP_CTEST2_TEOP 0x04 /* True EOP (a-la 5380) */ -#define SIOP_CTEST2_DREQ 0x02 /* DREQ status */ -#define SIOP_CTEST2_DACK 0x01 /* DACK status */ - -/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */ - -/* Chip test register 4 (ctest4) */ - -#define SIOP_CTEST4_MUX 0x80 /* Host bus multiplex mode */ -#define SIOP_CTEST4_ZMOD 0x40 /* High-impedance outputs */ -#define SIOP_CTEST4_SZM 0x20 /* ditto, SCSI "outputs" */ -#define SIOP_CTEST4_SLBE 0x10 /* SCSI loobpack enable */ -#define SIOP_CTEST4_SFWR 0x08 /* SCSI FIFO write enable (from sodl) */ -#define SIOP_CTEST4_FBL 0x07 /* DMA FIFO Byte Lane select (from ctest6) - 4->0, .. 7->3 */ - -/* Chip test register 5 (ctest5) */ - -#define SIOP_CTEST5_ADCK 0x80 /* Clock Address Incrementor */ -#define SIOP_CTEST5_BBCK 0x40 /* Clock Byte counter */ -#define SIOP_CTEST5_ROFF 0x20 /* Reset SCSI offset */ -#define SIOP_CTEST5_MASR 0x10 /* Master set/reset pulses (of bits 3-0) */ -#define SIOP_CTEST5_DDIR 0x08 /* (re)set internal DMA direction */ -#define SIOP_CTEST5_EOP 0x04 /* (re)set internal EOP */ -#define SIOP_CTEST5_DREQ 0x02 /* (re)set internal REQ */ -#define SIOP_CTEST5_DACK 0x01 /* (re)set internal ACK */ - -/* Chip test register 6 (ctest6) DMA FIFO access */ - -/* Chip test register 7 (ctest7) */ - -#define SIOP_CTEST7_CDIS 0x80 /* Cache burst disable */ -#define SIOP_CTEST7_SC1 0x40 /* Snoop control 1 */ -#define SIOP_CTEST7_SC0 0x20 /* Snoop contorl 0 */ -#define SIOP_CTEST7_INHIBIT (0 << 5) -#define SIOP_CTEST7_SNOOP (1 << 5) -#define SIOP_CTEST7_INVAL (2 << 5) -#define SIOP_CTEST7_RESV (3 << 5) -#define SIOP_CTEST7_STD 0x10 /* Selection timeout disable */ -#define SIOP_CTEST7_DFP 0x08 /* DMA FIFO parity bit */ -#define SIOP_CTEST7_EVP 0x04 /* Even parity (to host bus) */ -#define SIOP_CTEST7_TT1 0x02 /* Transfer type bit */ -#define SIOP_CTEST7_DIFF 0x01 /* Differential mode */ - -/* DMA FIFO register (dfifo) */ - -#define SIOP_DFIFO_RES 0x80 -#define SIOP_DFIFO_BO 0x7f /* FIFO byte offset counter */ - -/* Interrupt status register (istat) */ - -#define SIOP_ISTAT_ABRT 0x80 /* Abort operation */ -#define SIOP_ISTAT_RST 0x40 /* Software reset */ -#define SIOP_ISTAT_SIGP 0x20 /* Signal process */ -#define SIOP_ISTAT_RES 0x10 -#define SIOP_ISTAT_CON 0x08 /* Connected */ -#define SIOP_ISTAT_RES1 0x04 -#define SIOP_ISTAT_SIP 0x02 /* SCSI Interrupt pending */ -#define SIOP_ISTAT_DIP 0x01 /* DMA Interrupt pending */ - -/* Chip test register 8 (ctest8) - -#define SIOP_CTEST8_V 0xf0 /* Chip revision level */ -#define SIOP_CTEST8_FLF 0x08 /* Flush DMA FIFO */ -#define SIOP_CTEST8_CLF 0x04 /* Clear DMA and SCSI FIFOs */ -#define SIOP_CTEST8_FM 0x02 /* Fetch pin mode */ -#define SIOP_CTEST8_SM 0x01 /* Snoop pins mode */ - -/* DMA Mode register (dmode) */ - -#define SIOP_DMODE_BL_MASK 0xc0 /* 0->1 1->2 2->4 3->8 */ -#define SIOP_DMODE_FC 0x30 /* Function code */ -#define SIOP_DMODE_PD 0x08 /* Program/data */ -#define SIOP_DMODE_FAM 0x04 /* Fixed address mode */ -#define SIOP_DMODE_U0 0x02 /* User programmable transfer type */ -#define SIOP_DMODE_MAN 0x01 /* Manual start mode */ - -/* DMA interrupt enable register (dien) */ - -#define SIOP_DIEN_RES 0xc0 -#define SIOP_DIEN_BF 0x20 /* On Bus Fault */ -#define SIOP_DIEN_ABRT 0x10 /* On Abort */ -#define SIOP_DIEN_SSI 0x08 /* On SCRIPTS sstep */ -#define SIOP_DIEN_SIR 0x04 /* On SCRIPTS intr instruction */ -#define SIOP_DIEN_WTD 0x02 /* On watchdog timeout */ -#define SIOP_DIEN_IID 0x01 /* On illegal instruction detected */ - -/* DMA control register (dcntl) */ - -#define SIOP_DCNTL_CF_MASK 0xc0 /* Clock frequency dividers: - 0 --> 37.51..50.00 Mhz, div=2 - 1 --> 25.01..37.50 Mhz, div=1.5 - 2 --> 16.67..25.00 Mhz, div=1 - 3 --> 50.01..66.67 Mhz, div=3 - */ -#define SIOP_DCNTL_EA 0x20 /* Enable ack */ -#define SIOP_DCNTL_SSM 0x10 /* Single step mode */ -#define SIOP_DCNTL_LLM 0x08 /* Enable SCSI Low-level mode */ -#define SIOP_DCNTL_STD 0x04 /* Start DMA operation */ -#define SIOP_DCNTL_FA 0x02 /* Fast arbitration */ -#define SIOP_DCNTL_COM 0x01 /* 53C700 compatibility */ diff --git a/sys/arch/mvme88k/dev/siopvar.h b/sys/arch/mvme88k/dev/siopvar.h deleted file mode 100644 index 0e61b358401..00000000000 --- a/sys/arch/mvme88k/dev/siopvar.h +++ /dev/null @@ -1,204 +0,0 @@ -/* $OpenBSD: siopvar.h,v 1.2 1998/12/15 05:52:31 smurph Exp $ */ - -/* - * Copyright (c) 1995 Theo de Raadt - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson of Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)siopvar.h 7.1 (Berkeley) 5/8/90 - */ -#ifndef _SIOPVAR_H_ -#define _SIOPVAR_H_ - -/* - * The largest single request will be MAXPHYS bytes which will require - * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of - * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the - * buffer is not page aligned (+1). - */ -#define DMAMAXIO (MAXPHYS/NBPG+1) - -/* - * Data Structure for SCRIPTS program - */ -struct siop_ds { -/*00*/ long scsi_addr; /* SCSI ID & sync */ -/*04*/ long idlen; /* Identify message */ -/*08*/ char *idbuf; -/*0c*/ long cmdlen; /* SCSI command */ -/*10*/ char *cmdbuf; -/*14*/ long stslen; /* Status */ -/*18*/ char *stsbuf; -/*1c*/ long msglen; /* Message */ -/*20*/ char *msgbuf; -/*24*/ long msginlen; /* Message in */ -/*28*/ char *msginbuf; -/*2c*/ long extmsglen; /* Extended message in */ -/*30*/ char *extmsgbuf; -/*34*/ long synmsglen; /* Sync transfer request */ -/*38*/ char *synmsgbuf; - struct { -/*3c*/ long datalen; -/*40*/ char *databuf; - } chain[DMAMAXIO]; -}; - -/* - * ACB. 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 siop_acb { -/*00*/ TAILQ_ENTRY(siop_acb) chain; -/*08*/ struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ -/*0c*/ int flags; /* Status */ -#define ACB_FREE 0x00 -#define ACB_ACTIVE 0x01 -#define ACB_DONE 0x04 -#define ACB_CHKSENSE 0x08 -/*10*/ struct scsi_generic cmd; /* SCSI command block */ -/*1c*/ struct siop_ds ds; -/*a0*/ void *iob_buf; -/*a4*/ u_long iob_curbuf; -/*a8*/ u_long iob_len, iob_curlen; -/*b0*/ u_char msgout[6]; -/*b6*/ u_char msg[6]; -/*bc*/ u_char stat[1]; -/*bd*/ u_char status; -/*be*/ u_char dummy[2]; -/*c0*/ int clen; -/*c4*/ char *daddr; /* Saved data pointer */ -/*c8*/ int dleft; /* Residue */ -}; - -/* - * 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 siop_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; - u_char period; /* Period suggestion */ - u_char offset; /* Offset suggestion */ -} tinfo_t; - -struct siop_softc { - struct device sc_dev; - struct intrhand sc_ih; - struct evcnt sc_intrcnt; - - u_char sc_istat; - u_char sc_dstat; - u_char sc_sstat0; - u_char sc_sstat1; - u_long sc_intcode; - struct scsi_link sc_link; /* proto for sub devices */ - u_long sc_scriptspa; /* physical address of scripts */ - siop_regmap_p sc_siopp; /* the SIOP */ - u_long sc_active; /* number of active I/O's */ - - /* Lists of command blocks */ - TAILQ_HEAD(acb_list, siop_acb) free_list, - ready_list, - nexus_list; - - struct siop_acb *sc_nexus; /* current command */ -#define SIOP_NACB 8 - struct siop_acb *sc_acb; /* the real command blocks */ - struct siop_tinfo sc_tinfo[8]; - - u_short sc_clock_freq; - u_char sc_dcntl; - u_char sc_ctest0; - u_char sc_ctest7; - u_short sc_tcp[4]; - u_char sc_flags; - u_char sc_sien; - u_char sc_dien; - u_char sc_minsync; - /* one for each target */ - struct syncpar { - u_char state; - u_char sxfer; - u_char sbcl; - } sc_sync[8]; -}; - -/* sc_flags */ -#define SIOP_INTSOFF 0x80 /* Interrupts turned off */ -#define SIOP_INTDEFER 0x40 /* Level 6 interrupt has been deferred */ -#define SIOP_ALIVE 0x01 /* controller initialized */ -#define SIOP_SELECTED 0x04 /* bus is in selected state. Needed for - correct abort procedure. */ - -/* sync states */ -#define SYNC_START 0 /* no sync handshake started */ -#define SYNC_SENT 1 /* we sent sync request, no answer yet */ -#define SYNC_DONE 2 /* target accepted our (or inferior) settings, - or it rejected the request and we stay async */ - -#define MSG_CMD_COMPLETE 0x00 -#define MSG_EXT_MESSAGE 0x01 -#define MSG_SAVE_DATA_PTR 0x02 -#define MSG_RESTORE_PTR 0x03 -#define MSG_DISCONNECT 0x04 -#define MSG_INIT_DETECT_ERROR 0x05 -#define MSG_ABORT 0x06 -#define MSG_REJECT 0x07 -#define MSG_NOOP 0x08 -#define MSG_PARITY_ERROR 0x09 -#define MSG_BUS_DEVICE_RESET 0x0C -#define MSG_IDENTIFY 0x80 -#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */ -#define MSG_SYNC_REQ 0x01 - -#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */ -#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */ -#define STS_BUSY 0x08 -#define STS_INTERMED 0x10 /* Intermediate status sent */ -#define STS_EXT 0x80 /* Extended status valid */ - -void siop_minphys __P((struct buf *bp)); -int siop_scsicmd __P((struct scsi_xfer *)); - -#endif /* _SIOPVAR_H */ diff --git a/sys/arch/mvme88k/dev/ssh.c b/sys/arch/mvme88k/dev/ssh.c new file mode 100644 index 00000000000..f029e67f2a2 --- /dev/null +++ b/sys/arch/mvme88k/dev/ssh.c @@ -0,0 +1,1941 @@ +/* $OpenBSD: ssh.c,v 1.1 2001/03/07 01:57:56 miod Exp $ */ + +/* + * Copyright (c) 1994 Michael L. Hitch + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ssh.c 7.5 (Berkeley) 5/4/91 + */ + +/* + * 53C710 scsi adaptor driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(MVME187) +#include +#include +#else +#include +#include +#endif /* MVME187 */ + +#if defined(MVME187) +#include "machine/mmu.h" +#endif /* defined(MVME187) */ + + +extern u_int kvtop(); + +/* + * SCSI delays + * In u-seconds, primarily for state changes on the SPC. + */ +#define SCSI_CMD_WAIT 500000 /* wait per step of 'immediate' cmds */ +#define SCSI_DATA_WAIT 500000 /* wait per data in/out step */ +#define SCSI_INIT_WAIT 500000 /* wait per step (both) during init */ + +void ssh_select __P((struct ssh_softc *)); +void sshabort __P((struct ssh_softc *, ssh_regmap_p, char *)); +void ssherror __P((struct ssh_softc *, ssh_regmap_p, u_char)); +void sshstart __P((struct ssh_softc *)); +int ssh_checkintr __P((struct ssh_softc *, u_char, u_char, u_char, int *)); +void sshreset __P((struct ssh_softc *)); +void sshsetdelay __P((int)); +void ssh_scsidone __P((struct ssh_acb *, int)); +void ssh_sched __P((struct ssh_softc *)); +int ssh_poll __P((struct ssh_softc *, struct ssh_acb *)); +int sshintr __P((struct ssh_softc *)); +void scsi_period_to_ssh __P((struct ssh_softc *, int)); +void ssh_start __P((struct ssh_softc *, int, int, u_char *, int, u_char *, int)); +void ssh_dump_acb __P((struct ssh_acb *)); + +/* 53C710 script */ +const +#if defined(MVME187) +#include +#else +#include +#endif /* MVME187 */ + +u_long scsi_nosync = 0; +int shift_nosync; + +/* default to not inhibit sync negotiation on any drive */ +u_char ssh_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0 }; /* initialize, so patchable */ +u_char ssh_allow_disc[8] = {3, 3, 3, 3, 3, 3, 3, 3}; +int ssh_no_dma = 0; + +int ssh_reset_delay = 250; /* delay after reset, in milleseconds */ + +int ssh_cmd_wait = SCSI_CMD_WAIT; +int ssh_data_wait = SCSI_DATA_WAIT; +int ssh_init_wait = SCSI_INIT_WAIT; + +extern struct pmap kernel_pmap_store; +#define pmap_kernel() (&kernel_pmap_store) + +#ifdef DEBUG_SYNC +/* + * sync period transfer lookup - only valid for 66Mhz clock + */ +static struct { + unsigned char p; /* period from sync request message */ + unsigned char r; /* ssh_period << 4 | sbcl */ +} sync_tab[] = { + { 60/4, 0<<4 | 1}, + { 76/4, 1<<4 | 1}, + { 92/4, 2<<4 | 1}, + { 92/4, 0<<4 | 2}, + {108/4, 3<<4 | 1}, + {116/4, 1<<4 | 2}, + {120/4, 4<<4 | 1}, + {120/4, 0<<4 | 3}, + {136/4, 5<<4 | 1}, + {140/4, 2<<4 | 2}, + {152/4, 6<<4 | 1}, + {152/4, 1<<4 | 3}, + {164/4, 3<<4 | 2}, + {168/4, 7<<4 | 1}, + {180/4, 2<<4 | 3}, + {184/4, 4<<4 | 2}, + {208/4, 5<<4 | 2}, + {212/4, 3<<4 | 3}, + {232/4, 6<<4 | 2}, + {240/4, 4<<4 | 3}, + {256/4, 7<<4 | 2}, + {272/4, 5<<4 | 3}, + {300/4, 6<<4 | 3}, + {332/4, 7<<4 | 3} +}; +#endif + +#ifdef DEBUG +/* + * 0x01 - full debug + * 0x02 - DMA chaining + * 0x04 - sshintr + * 0x08 - phase mismatch + * 0x10 - + * 0x20 - panic on unhandled exceptions + * 0x100 - disconnect/reselect + */ +int ssh_debug = 0; +int sshsync_debug = 0; +int sshdma_hits = 0; +int sshdma_misses = 0; +int sshchain_ints = 0; +int sshstarts = 0; +int sshints = 0; +int sshphmm = 0; +#define SSH_TRACE_SIZE 128 +#define SSH_TRACE(a,b,c,d) \ + ssh_trbuf[ssh_trix] = (a); \ + ssh_trbuf[ssh_trix+1] = (b); \ + ssh_trbuf[ssh_trix+2] = (c); \ + ssh_trbuf[ssh_trix+3] = (d); \ + ssh_trix = (ssh_trix + 4) & (SSH_TRACE_SIZE - 1); +u_char ssh_trbuf[SSH_TRACE_SIZE]; +int ssh_trix; +void ssh_dump __P((struct ssh_softc *)); +void ssh_dump_trace __P((void)); +#else +#define SSH_TRACE(a,b,c,d) +#endif + +int kludge_city = 1; + +/* + * dummy routine to debug while loops + */ +void +wdummy(void) +{ + static int wcount; + wcount++; + if (wcount > 400000) { + wcount = 0; + } +} + +/* + * default minphys routine for ssh based controllers + */ +void +ssh_minphys(bp) + struct buf *bp; +{ + + /* + * No max transfer at this level. + */ + minphys(bp); +} + +/* + * used by specific ssh controller + * + */ +int +ssh_scsicmd(xs) + struct scsi_xfer *xs; +{ + struct ssh_acb *acb; + struct ssh_softc *sc; + struct scsi_link *slp; + int flags, s, i; + + slp = xs->sc_link; + sc = slp->adapter_softc; + flags = xs->flags; + xs->error = XS_NOERROR; + + /* XXXX ?? */ + if (flags & SCSI_DATA_UIO) + panic("ssh: scsi data uio requested"); + + /* XXXX ?? */ + if (sc->sc_nexus && flags & SCSI_POLL) +/* panic("ssh_scsicmd: busy");*/ + printf("ssh_scsicmd: busy\n"); + + s = splbio(); + acb = sc->free_list.tqh_first; + if (acb) { + TAILQ_REMOVE(&sc->free_list, acb, chain); + } + splx(s); + + if (acb == NULL) { + xs->error = XS_DRIVER_STUFFUP; + return(TRY_AGAIN_LATER); + } + + acb->flags = ACB_ACTIVE; + acb->xs = xs; + bcopy(xs->cmd, &acb->cmd, xs->cmdlen); + acb->clen = xs->cmdlen; + acb->daddr = xs->data; + acb->dleft = xs->datalen; + +#if defined(MVME187) + /* + * Since the 187 doesn't support cache snooping, we have + * to flush the cache for a write and flush with inval for + * a read, prior to starting the IO. + * We should move this ssh_sched() XXX + */ + if (xs->flags & SCSI_DATA_IN) { /* read */ + dma_cachectl((vm_offset_t)xs->data, xs->datalen, + DMA_CACHE_SYNC_INVAL); + } else { /* write */ + dma_cachectl((vm_offset_t)xs->data, xs->datalen, + DMA_CACHE_SYNC); + } +#endif + s = splbio(); + TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain); + + if (sc->sc_nexus == NULL) + ssh_sched(sc); + + splx(s); + + if (flags & SCSI_POLL || ssh_no_dma) + return(ssh_poll(sc, acb)); + return(SUCCESSFULLY_QUEUED); +} + +int +ssh_poll(sc, acb) + struct ssh_softc *sc; + struct ssh_acb *acb; +{ + ssh_regmap_p rp = sc->sc_sshp; + struct scsi_xfer *xs = acb->xs; + int i; + int status; + u_char istat; + u_char dstat; + u_char sstat0; + int s; + int to; + + s = splbio(); + to = xs->timeout / 1000; + if (sc->nexus_list.tqh_first) + printf("%s: ssh_poll called with disconnected device\n", + sc->sc_dev.dv_xname); + for (;;) { + /* use cmd_wait values? */ + i = 50000; + spl0(); + while (((istat = rp->ssh_istat) & + (SSH_ISTAT_SIP | SSH_ISTAT_DIP)) == 0) { + if (--i <= 0) { +#ifdef DEBUG + printf ("waiting: tgt %d cmd %02x sbcl %02x dsp %x (+%x) dcmd %x ds %x timeout %d\n", + xs->sc_link->target, acb->cmd.opcode, + rp->ssh_sbcl, rp->ssh_dsp, + rp->ssh_dsp - sc->sc_scriptspa, + *((long *)&rp->ssh_dcmd), &acb->ds, acb->xs->timeout); +#endif + i = 50000; + --to; + if (to <= 0) { + sshreset(sc); + return(COMPLETE); + } + } + delay(10); + } + sstat0 = rp->ssh_sstat0; + delay(10); + dstat = rp->ssh_dstat; + if (ssh_checkintr(sc, istat, dstat, sstat0, &status)) { + if (acb != sc->sc_nexus) + printf("%s: ssh_poll disconnected device completed\n", + sc->sc_dev.dv_xname); + else if ((sc->sc_flags & SSH_INTDEFER) == 0) { + sc->sc_flags &= ~SSH_INTSOFF; + rp->ssh_sien = sc->sc_sien; + rp->ssh_dien = sc->sc_dien; + } + ssh_scsidone(sc->sc_nexus, status); + } + if (xs->flags & ITSDONE) + break; + } + splx(s); + return (COMPLETE); +} + +/* + * start next command that's ready + */ +void +ssh_sched(sc) + struct ssh_softc *sc; +{ + struct scsi_link *slp; + struct ssh_acb *acb; + int stat, i; + +#ifdef DEBUG + if (sc->sc_nexus) { + printf("%s: ssh_sched- nexus %x/%d ready %x/%d\n", + sc->sc_dev.dv_xname, sc->sc_nexus, + sc->sc_nexus->xs->sc_link->target, + sc->ready_list.tqh_first, + sc->ready_list.tqh_first->xs->sc_link->target); + return; + } +#endif + for (acb = sc->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) { + slp = acb->xs->sc_link; + i = slp->target; + if(!(sc->sc_tinfo[i].lubusy & (1 << slp->lun))) { + struct ssh_tinfo *ti = &sc->sc_tinfo[i]; + + TAILQ_REMOVE(&sc->ready_list, acb, chain); + sc->sc_nexus = acb; + slp = acb->xs->sc_link; + ti = &sc->sc_tinfo[slp->target]; + ti->lubusy |= (1 << slp->lun); + break; + } + } + + if (acb == NULL) { +#ifdef DEBUGXXX + printf("%s: ssh_sched didn't find ready command\n", + sc->sc_dev.dv_xname); +#endif + return; + } + + if (acb->xs->flags & SCSI_RESET) + sshreset(sc); + +#if 0 + acb->cmd.bytes[0] |= slp->lun << 5; /* XXXX */ +#endif + ++sc->sc_active; + ssh_select(sc); +} + +void +ssh_scsidone(acb, stat) + struct ssh_acb *acb; + int stat; +{ + struct scsi_xfer *xs = acb->xs; + struct scsi_link *slp = xs->sc_link; + struct ssh_softc *sc = slp->adapter_softc; + int s, dosched = 0; + + if (acb == NULL || (xs = acb->xs) == NULL) { +#ifdef DIAGNOSTIC + printf("ssh_scsidone: NULL acb or scsi_xfer\n"); +#if defined(DEBUG) && defined(DDB) + Debugger(); +#endif +#endif + return; + } + slp = xs->sc_link; + sc = slp->adapter_softc; + /* + * is this right? + */ + xs->status = stat; + + if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) { + if (stat == SCSI_CHECK) { + struct scsi_sense *ss = (void *)&acb->cmd; + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = slp->lun << 5; + ss->length = sizeof(struct scsi_sense_data); + acb->clen = sizeof(*ss); + acb->daddr = (char *)&xs->sense; + acb->dleft = sizeof(struct scsi_sense_data); + acb->flags = ACB_ACTIVE | ACB_CHKSENSE; + TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain); + --sc->sc_active; + sc->sc_tinfo[slp->target].lubusy &= + ~(1 << slp->lun); + sc->sc_tinfo[slp->target].senses++; + if (sc->sc_nexus == acb) { + sc->sc_nexus = NULL; + ssh_sched(sc); + } + SSH_TRACE('d','s',0,0) + return; + } + } + if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) { + xs->error = XS_SENSE; + } else { + xs->resid = 0; /* XXXX */ + } +#if whataboutthisone + case SCSI_BUSY: + xs->error = XS_BUSY; + break; +#endif + xs->flags |= ITSDONE; + + /* + * Remove the ACB from whatever queue it's on. We have to do a bit of + * a hack to figure out which queue it's on. Note that it is *not* + * necessary to cdr down the ready queue, but we must cdr down the + * nexus queue and see if it's there, so we can mark the unit as no + * longer busy. This code is sickening, but it works. + */ + if (acb == sc->sc_nexus) { + sc->sc_nexus = NULL; + sc->sc_tinfo[slp->target].lubusy &= ~(1<lun); + if (sc->ready_list.tqh_first) + dosched = 1; /* start next command */ + --sc->sc_active; + SSH_TRACE('d','a',stat,0) + } else if (sc->ready_list.tqh_last == &acb->chain.tqe_next) { + TAILQ_REMOVE(&sc->ready_list, acb, chain); + SSH_TRACE('d','r',stat,0) + } else { + register struct ssh_acb *acb2; + for (acb2 = sc->nexus_list.tqh_first; acb2; + acb2 = acb2->chain.tqe_next) + if (acb2 == acb) { + TAILQ_REMOVE(&sc->nexus_list, acb, chain); + sc->sc_tinfo[slp->target].lubusy + &= ~(1<lun); + --sc->sc_active; + break; + } + if (acb2) + ; + else if (acb->chain.tqe_next) { + TAILQ_REMOVE(&sc->ready_list, acb, chain); + --sc->sc_active; + } else { + printf("%s: can't find matching acb\n", + sc->sc_dev.dv_xname); +#ifdef DDB +/* Debugger(); */ +#endif + } + SSH_TRACE('d','n',stat,0); + } + /* Put it on the free list. */ + acb->flags = ACB_FREE; + TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); + + sc->sc_tinfo[slp->target].cmds++; + + scsi_done(xs); + + if (dosched && sc->sc_nexus == NULL) + ssh_sched(sc); +} + +void +sshabort(sc, rp, where) + register struct ssh_softc *sc; + ssh_regmap_p rp; + char *where; +{ + int i; + + printf ("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n", + sc->sc_dev.dv_xname, + where, rp->ssh_dstat, rp->ssh_sstat0, rp->ssh_sbcl); + + if (sc->sc_active > 0) { +#ifdef TODO + SET_SBIC_cmd (rp, SBIC_CMD_ABORT); + WAIT_CIP (rp); + + GET_SBIC_asr (rp, asr); + if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) + { + /* ok, get more drastic.. */ + + SET_SBIC_cmd (rp, SBIC_CMD_RESET); + delay(25); + SBIC_WAIT(rp, SBIC_ASR_INT, 0); + GET_SBIC_csr (rp, csr); /* clears interrupt also */ + + return; + } + + do + { + SBIC_WAIT (rp, SBIC_ASR_INT, 0); + GET_SBIC_csr (rp, csr); + } + while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) + && (csr != SBIC_CSR_CMD_INVALID)); +#endif + + /* lets just hope it worked.. */ +#ifdef fix_this + for (i = 0; i < 2; ++i) { + if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] != + sc->sc_cur) { + printf ("sshabort: cleanup!\n"); + sc->sc_iob[i].sc_xs = NULL; + } + } +#endif /* fix_this */ +/* sc->sc_active = 0; */ + } +} + +void +sshinitialize(sc) + struct ssh_softc *sc; +{ + /* + * Need to check that scripts is on a long word boundary + * Also should verify that dev doesn't span non-contiguous + * physical pages. + */ + sc->sc_scriptspa = kvtop(scripts); + + /* + * malloc sc_acb to ensure that DS is on a long word boundary. + */ + + MALLOC(sc->sc_acb, struct ssh_acb *, + sizeof(struct ssh_acb) * SSH_NACB, M_DEVBUF, M_NOWAIT); + if (sc->sc_acb == NULL) + panic("sshinitialize: ACB malloc failed!"); + + sc->sc_tcp[1] = 1000 / sc->sc_clock_freq; + sc->sc_tcp[2] = 1500 / sc->sc_clock_freq; + sc->sc_tcp[3] = 2000 / sc->sc_clock_freq; + sc->sc_minsync = sc->sc_tcp[1]; /* in 4ns units */ + if (sc->sc_minsync < 25) + sc->sc_minsync = 25; +#if not_used + if (sc->sc_clock_freq <= 25) + sc->sc_tcp[0] = sc->sc_tcp[1]; + else if (sc->sc_clock_freq <= 37) + sc->sc_tcp[0] = sc->sc_tcp[2]; + else if (sc->sc_clock_freq <= 50) + sc->sc_tcp[0] = sc->sc_tcp[3]; + else + sc->sc_tcp[0] = 3000 / sc->sc_clock_freq; +#endif + + sshreset (sc); +} + +void +sshreset(sc) + struct ssh_softc *sc; +{ + ssh_regmap_p rp; + u_int i, s; + u_char dummy; + struct ssh_acb *acb; + + rp = sc->sc_sshp; + + if (sc->sc_flags & SSH_ALIVE) + sshabort(sc, rp, "reset"); + + s = splbio(); + + /* + * Reset the chip + * XXX - is this really needed? + */ + rp->ssh_istat |= SSH_ISTAT_ABRT; /* abort current script */ + rp->ssh_istat |= SSH_ISTAT_RST; /* reset chip */ + rp->ssh_istat &= ~SSH_ISTAT_RST; + /* + * Reset SCSI bus (do we really want this?) + */ + rp->ssh_sien = 0; + rp->ssh_scntl1 |= SSH_SCNTL1_RST; + delay(25); + rp->ssh_scntl1 &= ~SSH_SCNTL1_RST; + + /* + * Set up various chip parameters + */ + rp->ssh_scntl0 = SSH_ARB_FULL | SSH_SCNTL0_EPC | SSH_SCNTL0_EPG; + rp->ssh_scntl1 = SSH_SCNTL1_ESR; + rp->ssh_dcntl = sc->sc_dcntl; + rp->ssh_dmode = 0x80; /* burst length = 4 */ + rp->ssh_sien = 0x00; /* don't enable interrupts yet */ + rp->ssh_dien = 0x00; /* don't enable interrupts yet */ + rp->ssh_scid = 1 << sc->sc_link.adapter_target; + rp->ssh_dwt = 0x00; + rp->ssh_ctest0 |= SSH_CTEST0_BTD | SSH_CTEST0_EAN; + rp->ssh_ctest7 = sc->sc_ctest7; + + /* will need to re-negotiate sync xfers */ + bzero(&sc->sc_sync, sizeof (sc->sc_sync)); + + i = rp->ssh_istat; + if (i & SSH_ISTAT_SIP) + dummy = rp->ssh_sstat0; + delay(1); + if (i & SSH_ISTAT_DIP) + dummy = rp->ssh_dstat; + + splx (s); + + delay (ssh_reset_delay * 1000); + printf(": version %d target %d\n", rp->ssh_ctest8 >> 4, + sc->sc_link.adapter_target); + + if ((sc->sc_flags & SSH_ALIVE) == 0) { + TAILQ_INIT(&sc->ready_list); + TAILQ_INIT(&sc->nexus_list); + TAILQ_INIT(&sc->free_list); + sc->sc_nexus = NULL; + acb = sc->sc_acb; + bzero(acb, sizeof(struct ssh_acb) * SSH_NACB); + for (i = 0; i < SSH_NACB; i++) { + + pmap_cache_ctrl(pmap_kernel(), + M88K_TRUNC_PAGE((vm_offset_t)acb), + M88K_ROUND_PAGE((vm_offset_t)acb+sizeof(*acb)), + CACHE_INH); + + TAILQ_INSERT_TAIL(&sc->free_list, acb, chain); + acb++; + } + bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo)); + } else { + if (sc->sc_nexus != NULL) { + sc->sc_nexus->xs->error = XS_DRIVER_STUFFUP; + ssh_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]); + } + while (acb = sc->nexus_list.tqh_first) { + acb->xs->error = XS_DRIVER_STUFFUP; + ssh_scsidone(acb, acb->stat[0]); + } + } + + sc->sc_flags |= SSH_ALIVE; + sc->sc_flags &= ~(SSH_INTDEFER|SSH_INTSOFF); + /* enable SCSI and DMA interrupts */ + /* XXX turn on SEL interrupt? nivas */ + sc->sc_sien = SSH_SIEN_M_A | SSH_SIEN_STO | /*SSH_SIEN_SEL |*/ SSH_SIEN_SGE | + SSH_SIEN_UDC | SSH_SIEN_RST | SSH_SIEN_PAR; + sc->sc_dien = SSH_DIEN_BF | SSH_DIEN_ABRT | SSH_DIEN_SIR | + /*SSH_DIEN_WTD |*/ SSH_DIEN_IID; + rp->ssh_sien = sc->sc_sien; + rp->ssh_dien = sc->sc_dien; +} + +/* + * Setup Data Storage for 53C710 and start SCRIPTS processing + */ + +void +ssh_start (sc, target, lun, cbuf, clen, buf, len) + struct ssh_softc *sc; + int target; + int lun; + u_char *cbuf; + int clen; + u_char *buf; + int len; +{ + ssh_regmap_p rp = sc->sc_sshp; + int i; + int nchain; + int count, tcount; + char *addr, *dmaend; + struct ssh_acb *acb = sc->sc_nexus; + +#ifdef DEBUG + if (ssh_debug & 0x100 && rp->ssh_sbcl & SSH_BSY) { + printf ("ACK! ssh was busy: rp %x script %x dsa %x active %d\n", + rp, &scripts, &acb->ds, sc->sc_active); + printf ("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n", + rp->ssh_istat, rp->ssh_sfbr, rp->ssh_lcrc, + rp->ssh_sien, rp->ssh_dien); +#ifdef DDB + /*Debugger();*/ +#endif + } +#endif + acb->msgout[0] = MSG_IDENTIFY | lun; + if (ssh_allow_disc[target] & 2 || + (ssh_allow_disc[target] && len == 0)) + acb->msgout[0] = MSG_IDENTIFY_DR | lun; + acb->status = 0; + acb->stat[0] = -1; + acb->msg[0] = -1; + acb->ds.scsi_addr = (0x10000 << target) | (sc->sc_sync[target].sxfer << 8); + acb->ds.idlen = 1; + acb->ds.idbuf = (char *) kvtop(&acb->msgout[0]); + acb->ds.cmdlen = clen; + acb->ds.cmdbuf = (char *) kvtop(cbuf); + acb->ds.stslen = 1; + acb->ds.stsbuf = (char *) kvtop(&acb->stat[0]); + acb->ds.msglen = 1; + acb->ds.msgbuf = (char *) kvtop(&acb->msg[0]); + acb->msg[1] = -1; + acb->ds.msginlen = 1; + acb->ds.extmsglen = 1; + acb->ds.synmsglen = 3; + acb->ds.msginbuf = (char *) kvtop(&acb->msg[1]); + acb->ds.extmsgbuf = (char *) kvtop(&acb->msg[2]); + acb->ds.synmsgbuf = (char *) kvtop(&acb->msg[3]); + bzero(&acb->ds.chain, sizeof (acb->ds.chain)); + + if (sc->sc_sync[target].state == SYNC_START) { + if (ssh_inhibit_sync[target]) { + sc->sc_sync[target].state = SYNC_DONE; + sc->sc_sync[target].sbcl = 0; + sc->sc_sync[target].sxfer = 0; +#ifdef DEBUG + if (sshsync_debug) + printf ("Forcing target %d asynchronous\n", target); +#endif + } + else { + acb->msg[2] = -1; + acb->msgout[1] = MSG_EXT_MESSAGE; + acb->msgout[2] = 3; + acb->msgout[3] = MSG_SYNC_REQ; +#ifdef MAXTOR_SYNC_KLUDGE + acb->msgout[4] = 50 / 4; /* ask for ridiculous period */ +#else + acb->msgout[4] = sc->sc_minsync; +#endif + acb->msgout[5] = SSH_MAX_OFFSET; + acb->ds.idlen = 6; + sc->sc_sync[target].state = SYNC_SENT; +#ifdef DEBUG + if (sshsync_debug) + printf ("Sending sync request to target %d\n", target); +#endif + } + } + +/* + * Build physical DMA addresses for scatter/gather I/O + */ + acb->iob_buf = buf; + acb->iob_len = len; + acb->iob_curbuf = acb->iob_curlen = 0; + nchain = 0; + count = len; + addr = buf; + dmaend = NULL; + while (count > 0) { + acb->ds.chain[nchain].databuf = (char *) kvtop (addr); + if (count < (tcount = NBPG - ((int) addr & PGOFSET))) + tcount = count; + acb->ds.chain[nchain].datalen = tcount; + addr += tcount; + count -= tcount; + if (acb->ds.chain[nchain].databuf == dmaend) { + dmaend += acb->ds.chain[nchain].datalen; + acb->ds.chain[nchain].datalen = 0; + acb->ds.chain[--nchain].datalen += tcount; +#ifdef DEBUG + ++sshdma_hits; +#endif + } + else { + dmaend = acb->ds.chain[nchain].databuf + + acb->ds.chain[nchain].datalen; + acb->ds.chain[nchain].datalen = tcount; +#ifdef DEBUG + if (nchain) /* Don't count miss on first one */ + ++sshdma_misses; +#endif + } + ++nchain; + } +#ifdef DEBUG + if (nchain != 1 && len != 0 && ssh_debug & 3) { + printf ("DMA chaining set: %d\n", nchain); + for (i = 0; i < nchain; ++i) { + printf (" [%d] %8x %4x\n", i, acb->ds.chain[i].databuf, + acb->ds.chain[i].datalen); + } + } +#endif + +#if CACHECTL + /* push data cache for all data the 53c710 needs to access */ + dma_cachectl(sc, sizeof (struct ssh_softc), DMA_CACHE_SYNC); + dma_cachectl(acb, sizeof (*acb), DMA_CACHE_SYNC); +#endif + dma_cachectl((vm_offset_t)cbuf, clen, DMA_CACHE_SYNC); + +#if defined(MVME187) + /* + * Flushing the buf from data cache is very important for MVME187 + * since the board does not snoop the local bus. + * We have to flush the cache for a write and flush with inval for + * a read. + */ + if (buf != NULL && len != 0) { + if (acb->xs->flags & SCSI_DATA_IN) { /* read */ + dma_cachectl((vm_offset_t)buf, len, + DMA_CACHE_SYNC_INVAL); + } else { /* write */ + dma_cachectl((vm_offset_t)buf, len, DMA_CACHE_SYNC); + } + } +#endif + +#ifdef DEBUG + if (ssh_debug & 0x100 && rp->ssh_sbcl & SSH_BSY) { + printf ("ACK! ssh was busy at start: rp %x script %x dsa %x active %d\n", + rp, &scripts, &acb->ds, sc->sc_active); +#ifdef DDB + /*Debugger();*/ +#endif + } +#endif + if (sc->nexus_list.tqh_first == NULL) { + if (rp->ssh_istat & SSH_ISTAT_CON) + printf("%s: ssh_select while connected?\n", + sc->sc_dev.dv_xname); + rp->ssh_temp = 0; + rp->ssh_sbcl = sc->sc_sync[target].sbcl; + rp->ssh_dsa = kvtop(&acb->ds); + rp->ssh_dsp = sc->sc_scriptspa; + SSH_TRACE('s',1,0,0) + } else { + /* + * SSH is waiting for a reselect. If it is not + * yet connected to the BUS, signal to change state. + * Else, leave it alone - later on, the reselect interrupt + * will take care of this request. + */ + if ((rp->ssh_istat & SSH_ISTAT_CON) == 0) { + rp->ssh_istat = SSH_ISTAT_SIGP; + SSH_TRACE('s',2,0,0); + } + else { + SSH_TRACE('s',3,rp->ssh_istat,0); + } + } +#ifdef DEBUG + ++sshstarts; +#endif +} + +/* + * Process a DMA or SCSI interrupt from the 53C710 SSH + */ + +int +ssh_checkintr(sc, istat, dstat, sstat0, status) + struct ssh_softc *sc; + u_char istat; + u_char dstat; + u_char sstat0; + int *status; +{ + ssh_regmap_p rp = sc->sc_sshp; + struct ssh_acb *acb = sc->sc_nexus; + int target = 0; + int dfifo, dbc, sstat1; + int dummy; + + dfifo = rp->ssh_dfifo; + dbc = rp->ssh_dbc0; + sstat1 = rp->ssh_sstat1; + + /* + * Flush DMA and SCSI FIFOs. + */ + rp->ssh_ctest8 |= SSH_CTEST8_CLF; + while ((rp->ssh_ctest1 & SSH_CTEST1_FMT) != SSH_CTEST1_FMT){ + wdummy(); + } + ; + rp->ssh_ctest8 &= ~SSH_CTEST8_CLF; +#ifdef DEBUG + ++sshints; +#if 0 + if (ssh_debug & 0x100) { + DCIAS(&acb->stat[0]); /* XXX */ + printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n", + istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_sbcl, acb->stat[0], acb->msg[0]); + printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", + acb->msg[0], acb->msg[1], acb->msg[2], + acb->msg[3], acb->msg[4], acb->msg[5]); + } +#endif + if (rp->ssh_dsp && (rp->ssh_dsp < sc->sc_scriptspa || + rp->ssh_dsp >= sc->sc_scriptspa + sizeof(scripts))) { + printf ("%s: dsp not within script dsp %x scripts %x:%x", + sc->sc_dev.dv_xname, rp->ssh_dsp, sc->sc_scriptspa, + sc->sc_scriptspa + sizeof(scripts)); + printf(" istat %x dstat %x sstat0 %x\n", + istat, dstat, sstat0); +#ifdef DDB + Debugger(); +#endif + } +#endif + SSH_TRACE('i',dstat,istat,(istat&SSH_ISTAT_DIP)?rp->ssh_dsps&0xff:sstat0); + if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff00) { + /* Normal completion status, or check condition */ +#ifdef DEBUG + if (rp->ssh_dsa != kvtop(&acb->ds)) { + printf ("ssh: invalid dsa: %x %x\n", rp->ssh_dsa, + kvtop(&acb->ds)); + panic("*** ssh DSA invalid ***"); + } +#endif + if (acb == NULL) { + printf("%s: Command complete with no active command?\n", + sc->sc_dev.dv_xname); + return (0); + } + + target = acb->xs->sc_link->target; + if (sc->sc_sync[target].state == SYNC_SENT) { +#ifdef DEBUG + if (sshsync_debug) + printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", + acb->msg[0], acb->msg[1], acb->msg[2], + acb->msg[3], acb->msg[4], acb->msg[5]); +#endif + if (acb->msg[1] == 0xff) + printf ("%s: target %d ignored sync request\n", + sc->sc_dev.dv_xname, target); + else if (acb->msg[1] == MSG_REJECT) + printf ("%s: target %d rejected sync request\n", + sc->sc_dev.dv_xname, target); + sc->sc_sync[target].state = SYNC_DONE; + sc->sc_sync[target].sxfer = 0; + sc->sc_sync[target].sbcl = 0; + if (acb->msg[2] == 3 && + acb->msg[3] == MSG_SYNC_REQ && + acb->msg[5] != 0) { +#ifdef MAXTOR_KLUDGE + /* + * Kludge for my Maxtor XT8580S + * It accepts whatever we request, even + * though it won't work. So we ask for + * a short period than we can handle. If + * the device says it can do it, use 208ns. + * If the device says it can do less than + * 100ns, then we limit it to 100ns. + */ + if (acb->msg[4] && acb->msg[4] < 100 / 4) { +#ifdef DEBUG + printf ("%d: target %d wanted %dns period\n", + sc->sc_dev.dv_xname, target, + acb->msg[4] * 4); +#endif + if (acb->msg[4] == 50 / 4) + acb->msg[4] = 208 / 4; + else + acb->msg[4] = 100 / 4; + } +#endif /* MAXTOR_KLUDGE */ + printf ("%s: target %d now synchronous, period=%dns, offset=%d\n", + sc->sc_dev.dv_xname, target, + acb->msg[4] * 4, acb->msg[5]); + scsi_period_to_ssh (sc, target); + } + } +#if CACHECTL + /*cmmu_inval_cache(kvtop(&acb->stat[0]), 1);*/ + dma_cachectl(&acb->stat[0], 1); +#endif + *status = acb->stat[0]; +#ifdef DEBUG + if (rp->ssh_sbcl & SSH_BSY) { + /*printf ("ACK! ssh was busy at end: rp %x script %x dsa %x\n", + rp, &scripts, &acb->ds);*/ +#ifdef DDB + /*Debugger();*/ +#endif + } + if (acb->msg[0] != 0x00) + printf("%s: message was not COMMAND COMPLETE: %x\n", + sc->sc_dev.dv_xname, acb->msg[0]); +#endif + if (sc->nexus_list.tqh_first) + rp->ssh_dcntl |= SSH_DCNTL_STD; + return 1; + } + if (sstat0 & SSH_SSTAT0_M_A) { /* Phase mismatch */ +#ifdef DEBUG + ++sshphmm; + if (acb == NULL) + printf("%s: Phase mismatch with no active command?\n", + sc->sc_dev.dv_xname); +#endif + if (acb->iob_len) { + int adjust; + adjust = ((dfifo - (dbc & 0x7f)) & 0x7f); + if (sstat1 & SSH_SSTAT1_ORF) + ++adjust; + if (sstat1 & SSH_SSTAT1_OLF) + ++adjust; + acb->iob_curlen = *((long *)&rp->ssh_dcmd) & 0xffffff; + acb->iob_curlen += adjust; + acb->iob_curbuf = *((long *)&rp->ssh_dnad) - adjust; +#ifdef DEBUG + if (ssh_debug & 0x100) { + int i; + printf ("Phase mismatch: curbuf %x curlen %x dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %x\n", + acb->iob_curbuf, acb->iob_curlen, dfifo, + dbc, sstat1, adjust, rp->ssh_sbcl, sshstarts, acb); + if (acb->ds.chain[1].datalen) { + for (i = 0; acb->ds.chain[i].datalen; ++i) + printf("chain[%d] addr %x len %x\n", + i, acb->ds.chain[i].databuf, + acb->ds.chain[i].datalen); + } + } +#endif + +#if 0 + dma_cachectl (acb, sizeof(*acb), DMA_CACHE_SYNC)); +#endif + } +#ifdef DEBUG + SSH_TRACE('m',rp->ssh_sbcl,(rp->ssh_dsp>>8),rp->ssh_dsp); + if (ssh_debug & 9) + printf ("Phase mismatch: %x dsp +%x dcmd %x\n", + rp->ssh_sbcl, + rp->ssh_dsp - sc->sc_scriptspa, + *((long *)&rp->ssh_dcmd)); +#endif + if ((rp->ssh_sbcl & SSH_REQ) == 0) { + printf ("Phase mismatch: REQ not asserted! %02x dsp %x\n", + rp->ssh_sbcl, rp->ssh_dsp); +#ifdef DEBUG + Debugger(); +#endif + } + switch (rp->ssh_sbcl & 7) { + case 0: /* data out */ + case 1: /* data in */ + case 2: /* status */ + case 3: /* command */ + case 6: /* message in */ + case 7: /* message out */ + rp->ssh_dsp = sc->sc_scriptspa + Ent_switch; + break; + default: + goto bad_phase; + } + return 0; + } + if (sstat0 & SSH_SSTAT0_STO) { /* Select timed out */ +#ifdef DEBUG + if (acb == NULL) + printf("%s: Select timeout with no active command?\n", + sc->sc_dev.dv_xname); + if (rp->ssh_sbcl & SSH_BSY) { + printf ("ACK! ssh was busy at timeout: rp %x script %x dsa %x\n", + rp, &scripts, &acb->ds); + printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n", + rp->ssh_sbcl, rp->ssh_sdid, istat, dstat, sstat0); + if (!(rp->ssh_sbcl & SSH_BSY)) { + printf ("Yikes, it's not busy now!\n"); +#if 0 + *status = -1; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; +#endif + } +/* rp->ssh_dcntl |= SSH_DCNTL_STD;*/ + return (0); +#ifdef DDB + Debugger(); +#endif + } +#endif + *status = -1; + acb->xs->error = XS_SELTIMEOUT; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; + } + if (acb) + target = acb->xs->sc_link->target; + else + target = 7; + if (sstat0 & SSH_SSTAT0_UDC) { +#ifdef DEBUG + if (acb == NULL) + printf("%s: Unexpected disconnect with no active command?\n", + sc->sc_dev.dv_xname); + printf ("%s: target %d disconnected unexpectedly\n", + sc->sc_dev.dv_xname, target); +#endif +#if 0 + sshabort (sc, rp, "sshchkintr"); +#endif + *status = STS_BUSY; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; + } + if (dstat & SSH_DSTAT_SIR && (rp->ssh_dsps == 0xff01 || + rp->ssh_dsps == 0xff02)) { +#ifdef DEBUG + if (ssh_debug & 0x100) + printf ("%s: ID %02x disconnected TEMP %x (+%x) curbuf %x curlen %x buf %x len %x dfifo %x dbc %x sstat1 %x starts %d acb %x\n", + sc->sc_dev.dv_xname, 1 << target, rp->ssh_temp, + rp->ssh_temp ? rp->ssh_temp - sc->sc_scriptspa : 0, + acb->iob_curbuf, acb->iob_curlen, + acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, sshstarts, acb); +#endif + if (acb == NULL) { + printf("%s: Disconnect with no active command?\n", + sc->sc_dev.dv_xname); + return (0); + } + /* + * XXXX need to update iob_curbuf/iob_curlen to reflect + * current data transferred. If device disconnected in + * the middle of a DMA block, they should already be set + * by the phase change interrupt. If the disconnect + * occurs on a DMA block boundary, we have to figure out + * which DMA block it was. + */ + if (acb->iob_len && rp->ssh_temp) { + int n = rp->ssh_temp - sc->sc_scriptspa; + + if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen) + printf("%s: iob_curbuf/len already set? n %x iob %x/%x chain[0] %x/%x\n", + sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen, + acb->ds.chain[0].databuf, acb->ds.chain[0].datalen); + if (n < Ent_datain) + n = (n - Ent_dataout) / 16; + else + n = (n - Ent_datain) / 16; + if (n <= 0 && n > DMAMAXIO) + printf("TEMP invalid %d\n", n); + else { + acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf; + acb->iob_curlen = acb->ds.chain[n].datalen; + } +#ifdef DEBUG + if (ssh_debug & 0x100) { + printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n); + printf(" curbuf %x curlen %x\n", acb->iob_curbuf, + acb->iob_curlen); + } +#endif + } + /* + * If data transfer was interrupted by disconnect, iob_curbuf + * and iob_curlen should reflect the point of interruption. + * Adjust the DMA chain so that the data transfer begins + * at the appropriate place upon reselection. + * XXX This should only be done on save data pointer message? + */ + if (acb->iob_curlen) { + int i, j; + +#ifdef DEBUG + if (ssh_debug & 0x100) + printf ("%s: adjusting DMA chain\n", + sc->sc_dev.dv_xname); + if (rp->ssh_dsps == 0xff02) + printf ("%s: ID %02x disconnected without Save Data Pointers\n", + sc->sc_dev.dv_xname, 1 << target); +#endif + for (i = 0; i < DMAMAXIO; ++i) { + if (acb->ds.chain[i].datalen == 0) + break; + if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf && + acb->iob_curbuf < (long)(acb->ds.chain[i].databuf + + acb->ds.chain[i].datalen)) + break; + } + if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) + printf("couldn't find saved data pointer\n"); +#ifdef DEBUG + if (ssh_debug & 0x100) + printf(" chain[0]: %x/%x -> %x/%x\n", + acb->ds.chain[0].databuf, + acb->ds.chain[0].datalen, + acb->iob_curbuf, + acb->iob_curlen); +#endif + acb->ds.chain[0].databuf = (char *)acb->iob_curbuf; + acb->ds.chain[0].datalen = acb->iob_curlen; + for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) { +#ifdef DEBUG + if (ssh_debug & 0x100) + printf(" chain[%d]: %x/%x -> %x/%x\n", j, + acb->ds.chain[j].databuf, + acb->ds.chain[j].datalen, + acb->ds.chain[i].databuf, + acb->ds.chain[i].datalen); +#endif + acb->ds.chain[j].databuf = acb->ds.chain[i].databuf; + acb->ds.chain[j].datalen = acb->ds.chain[i].datalen; + } + if (j < DMAMAXIO) + acb->ds.chain[j].datalen = 0; +#if CACHECTL + dma_cachectl(acb->ds.chain, + sizeof(acb->ds.chain)); +#endif + } + ++sc->sc_tinfo[target].dconns; + /* + * add nexus to waiting list + * clear nexus + * try to start another command for another target/lun + */ + acb->status = sc->sc_flags & SSH_INTSOFF; + TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain); + sc->sc_nexus = NULL; /* no current device */ + /* start script to wait for reselect */ + if (sc->sc_nexus == NULL) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; +/* XXXX start another command ? */ + if (sc->ready_list.tqh_first) + ssh_sched(sc); + return (0); + } + if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff03) { + int reselid = rp->ssh_scratch & 0x7f; + int reselun = rp->ssh_sfbr & 0x07; + + sc->sc_sstat1 = rp->ssh_sbcl; /* XXXX save current SBCL */ +#ifdef DEBUG + if (ssh_debug & 0x100) + printf ("%s: target ID %02x reselected dsps %x\n", + sc->sc_dev.dv_xname, reselid, + rp->ssh_dsps); + if ((rp->ssh_sfbr & 0x80) == 0) + printf("%s: Reselect message in was not identify: %x\n", + sc->sc_dev.dv_xname, rp->ssh_sfbr); +#endif + /* + * If we were trying to start a command when the reselect + * occured, need to put it at the head of the ready list, + * mark target/lun unbusy and decrement sc_active count. + */ + if (sc->sc_nexus) { +#ifdef DEBUG + if (ssh_debug & 0x100) + printf ("%s: reselect ID %02x w/active\n", + sc->sc_dev.dv_xname, reselid); +#endif + TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain); + sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target].lubusy + &= ~(1 << sc->sc_nexus->xs->sc_link->lun); + --sc->sc_active; + } + /* + * locate acb of reselecting device + * set sc->sc_nexus to acb + */ + for (acb = sc->nexus_list.tqh_first; acb; + acb = acb->chain.tqe_next) { + if (reselid != (acb->ds.scsi_addr >> 16) || + reselun != (acb->msgout[0] & 0x07)) + continue; + TAILQ_REMOVE(&sc->nexus_list, acb, chain); + sc->sc_nexus = acb; + sc->sc_flags |= acb->status; + acb->status = 0; +#if CACHECTL + dma_cachectl(&acb->stat[0], sizeof(acb->stat[0])); +#endif + rp->ssh_dsa = kvtop(&acb->ds); + rp->ssh_sxfer = sc->sc_sync[acb->xs->sc_link->target].sxfer; + rp->ssh_sbcl = sc->sc_sync[acb->xs->sc_link->target].sbcl; + break; + } + if (acb == NULL) { + printf("%s: target ID %02x reselect nexus_list %x\n", + sc->sc_dev.dv_xname, reselid, + sc->nexus_list.tqh_first); + panic("unable to find reselecting device"); + } +#if CACHECTL + dma_cachectl (acb, sizeof(*acb)); +#endif + rp->ssh_temp = 0; + rp->ssh_dcntl |= SSH_DCNTL_STD; + return (0); + } + if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff04) { + u_short ctest2 = rp->ssh_ctest2; + + /* reselect was interrupted (by Sig_P or select) */ +#ifdef DEBUG + if (ssh_debug & 0x100 || + (ctest2 & SSH_CTEST2_SIGP) == 0) + printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n", + sc->sc_dev.dv_xname, rp->ssh_scntl1, + ctest2, rp->ssh_sfbr, istat, rp->ssh_istat); +#endif + /* XXX assumes it was not select */ + if (sc->sc_nexus == NULL) { + printf("%s: reselect interrupted, sc_nexus == NULL\n", + sc->sc_dev.dv_xname); +#if 0 + ssh_dump(sc); +#ifdef DDB + Debugger(); +#endif +#endif + rp->ssh_dcntl |= SSH_DCNTL_STD; + return(0); + } + target = sc->sc_nexus->xs->sc_link->target; + rp->ssh_temp = 0; + rp->ssh_dsa = kvtop(&sc->sc_nexus->ds); + rp->ssh_sxfer = sc->sc_sync[target].sxfer; + rp->ssh_sbcl = sc->sc_sync[target].sbcl; + rp->ssh_dsp = sc->sc_scriptspa; + return (0); + } + if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff06) { + if (acb == NULL) + printf("%s: Bad message-in with no active command?\n", + sc->sc_dev.dv_xname); + /* Unrecognized message in byte */ +#if CACHECTL + /*cmmu_inval_cache(kvtop(&acb->msg[1]), 1);*/ + dma_cachectl (&acb->msg[1],1); +#endif + printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n", + sc->sc_dev.dv_xname, rp->ssh_sfbr, acb->msg[1], rp->ssh_sbcl); + /* what should be done here? */ + /*DCIAS(kvtop(&acb->msg[1]));*/ + rp->ssh_dsp = sc->sc_scriptspa + Ent_switch; + return (0); + } + if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff0a) { + /* Status phase wasn't followed by message in phase? */ + printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n", + sc->sc_dev.dv_xname, rp->ssh_sbcl, rp->ssh_sbdl); + if (rp->ssh_sbcl == 0xa7) { + /* It is now, just continue the script? */ + rp->ssh_dcntl |= SSH_DCNTL_STD; + return (0); + } + + sshreset (sc); + *status = -1; + return 0; /* sshreset has cleaned up */ + } + + if (sstat0 & SSH_SSTAT0_M_A) { /* Phase mismatch */ + +#ifdef DEBUG + printf("%s: Phase mismatch - expecting %x got %x\n", + sc->sc_dev.dv_xname, rp->ssh_dcmd & 0x07, + rp->ssh_sstat2 & 0x07); + ++sshphmm; +#endif + if (acb == NULL) { + printf("%s: Phase mismatch with no active command- expecting %x got %x\n", + sc->sc_dev.dv_xname, + *((long *)&rp->ssh_dcmd) & 0x07000000, + rp->ssh_sstat2 & 0x07); + goto bad_phase; + } + + if (acb->iob_len) { + int adjust; + adjust = ((dfifo - (dbc & 0x7f)) & 0x7f); + if (sstat1 & SSH_SSTAT1_ORF) + ++adjust; + if (sstat1 & SSH_SSTAT1_OLF) + ++adjust; + /* XXX what's with this ssh_dcmd here? nivas */ + acb->iob_curlen = *((long *)&rp->ssh_dcmd) & 0xffffff; + acb->iob_curlen += adjust; + acb->iob_curbuf = *((long *)&rp->ssh_dnad) - adjust; +#ifdef DEBUG + if (ssh_debug & 0x100) { + int i; + printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n", + acb->iob_curbuf, acb->iob_curlen, dfifo, + dbc, sstat1, adjust, rp->ssh_sbcl, sshstarts, acb); + if (acb->ds.chain[1].datalen) { + for (i = 0; acb->ds.chain[i].datalen; ++i) + printf("chain[%d] addr %p len %lx\n", + i, acb->ds.chain[i].databuf, + acb->ds.chain[i].datalen); + } + } +#endif +#if 0 + dma_cachectl(acb, sizeof(*acb), DMA_CACHE_SYNC); +#endif + } +#ifdef DEBUG + SSH_TRACE('m',rp->ssh_sbcl,(rp->ssh_dsp>>8),rp->ssh_dsp); + if (ssh_debug & 9) + printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n", + rp->ssh_sbcl, + rp->ssh_dsp - sc->sc_scriptspa, + *((long *)&rp->ssh_dcmd)); +#endif + if ((rp->ssh_sbcl & SSH_REQ) == 0) { + printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n", + rp->ssh_sbcl, rp->ssh_dsp); +#if defined(DEBUG) && defined(DDB) + Debugger(); +#endif + goto bad_phase; + } +#if XXX + switch (rp->ssh_sbcl & 7) +#endif + switch (rp->ssh_sstat2 & 7) { + case 0: /* data out */ + case 1: /* data in */ + case 2: /* command */ + case 3: /* status */ + case 6: /* message out */ + case 7: /* message in */ + rp->ssh_dsp = sc->sc_scriptspa + Ent_switch; + break; + default: + goto bad_phase; + } + return 0; + } + + if (sstat0 & SSH_SSTAT0_STO) { /* SCSI bus time out */ + + if (acb == NULL) { + printf("%s: SCSI bus timeout with no active command?\n", + sc->sc_dev.dv_xname); + /*Debugger();*/ + } + + printf ("STO: scripts %x dsp %x dcmd %x dsps %x\n", sc->sc_scriptspa, + rp->ssh_dsp, *((long *)&rp->ssh_dcmd), rp->ssh_dsps); + + if ((istat & SSH_ISTAT_CON) == 0) { + printf("selection of %x timeout\n", rp->ssh_sdid); + } else if ((rp->ssh_ctest0 & SSH_CTEST0_BTD) == 0) { + printf("No SCSI activity for 250ms(ctest0 %x %x dsps %x)\n", + rp->ssh_ctest0, + rp->ssh_ctest0, + rp->ssh_dsps); + } else { + printf("Waited > 250ms for disconnect\n"); + } + +#ifdef DEBUG + printf ("scripts %x dsp %x dcmd %x\n", sc->sc_scriptspa, + rp->ssh_dsp, *((long *)&rp->ssh_dcmd)); + + printf("msg %x status %x\n", acb->msg[0], acb->stat[0]); + + if (rp->ssh_sbcl & SSH_BSY) { + printf ("ACK! ssh was busy at timeout: rp %p script %p dsa %p\n", + rp, &scripts, &acb->ds); + printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n", + rp->ssh_sbcl, rp->ssh_sdid, istat, dstat, sstat0); + if (!(rp->ssh_sbcl & SSH_BSY)) { + printf ("Yikes, it's not busy now!\n"); +#if 0 + *status = -1; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; +#endif + } + + /* + * I am not sure if DCNTL_STD can be used to restart. + * The manual discusses this bit only for manual start + * mode and single step mode, which we are not using. + * I will give it a shot... nivas + */ + + if (kludge_city) { + dummy = rp->ssh_dsp; + rp->ssh_dsp = dummy; + } else { + rp->ssh_dcntl |= SSH_DCNTL_STD; + } + return (0); +#ifdef DDB + Debugger(); +#endif + } +#endif + if (rp->ssh_sbcl & SSH_BSY) { + if (!(rp->ssh_sbcl & SSH_BSY)) { + printf ("Yikes, it's not busy now!\n"); + *status = -1; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; + } + + rp->ssh_dcntl |= SSH_DCNTL_STD; + + return 0; + } + + *status = -1; + if (acb) + acb->xs->error = XS_SELTIMEOUT; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return 1; + } + + if (acb) + target = acb->xs->sc_link->target; + else + target = 7; + + if (sstat0 & SSH_SSTAT0_UDC) { +#ifdef DEBUG + if (acb == NULL) + printf("%s: Unexpected disconnect with no active command?\n", + sc->sc_dev.dv_xname); + printf ("%s: target %d disconnected unexpectedly\n", + sc->sc_dev.dv_xname, target); +#endif +#if 0 + sshabort (sc, rp, "sshchkintr"); +#endif + *status = STS_BUSY; + if (sc->nexus_list.tqh_first) + rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect; + return (acb != NULL); + } + + if (sstat0 == 0 && dstat & SSH_DSTAT_SIR) { +#if CACHECTL + /*cmmu_inval_cache(kvtop(&acb->stat[0]), 1); */ + /*cmmu_inval_cache(kvtop(&acb->msg[0]), 1); */ + dma_cachectl (&acb->stat[0], 1); + dma_cachectl (&acb->msg[0], 1); +#endif + printf ("SSH interrupt: %lx sts %x msg %x %x sbcl %x\n", + rp->ssh_dsps, acb->stat[0], acb->msg[0], acb->msg[1], + rp->ssh_sbcl); + sshreset (sc); + *status = -1; + return 0; /* sshreset has cleaned up */ + } + if (sstat0 & SSH_SSTAT0_SGE) + printf ("SSH: SCSI Gross Error\n"); + if (sstat0 & SSH_SSTAT0_PAR) + printf ("SSH: Parity Error\n"); + + if (dstat & SSH_DSTAT_IID) { + printf ("SSH: Illegal instruction detected (dsp %x dcmd %x dsps %x)\n", + rp->ssh_dsp, *((long *)&rp->ssh_dcmd), + rp->ssh_dsps); + + if (*((long *)&rp->ssh_dcmd) & 0xf8000000 == 0x48000000) { /* wait disconnect */ + printf("SSH was executing wait disconnect\n"); + } + } + +bad_phase: +#if XXX + /* + * temporary panic for unhandled conditions + * displays various things about the 53C710 status and registers + * then panics. + * XXXX need to clean this up to print out the info, reset, and continue + */ + printf ("sshchkintr: target %x ds %x\n", target, &acb->ds); + printf ("scripts %x ds %x rp %x dsp %x dcmd %x\n", sc->sc_scriptspa, + kvtop(&acb->ds), kvtop(rp), rp->ssh_dsp, + *((long *)&rp->ssh_dcmd)); + printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %x " + "dsa %x sbcl %x sts %x msg %x %x sfbr %x\n", + istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_dsa, + rp->ssh_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], + rp->ssh_sfbr); +#ifdef DEBUG + if (ssh_debug & 0x20) + panic("sshchkintr: **** temp ****"); +#ifdef DDB + /* Debugger(); */ +#endif +#endif +#endif /* XXX */ + sshreset (sc); /* hard reset */ + *status = -1; + return 0; /* sshreset cleaned up */ +} + +void +ssh_select(sc) + struct ssh_softc *sc; +{ + ssh_regmap_p rp; + struct ssh_acb *acb = sc->sc_nexus; + +#ifdef DEBUG + if (ssh_debug & 1) + printf ("%s: select ", sc->sc_dev.dv_xname); +#endif + + rp = sc->sc_sshp; + if (acb->xs->flags & SCSI_POLL || ssh_no_dma) { + sc->sc_flags |= SSH_INTSOFF; + sc->sc_flags &= ~SSH_INTDEFER; + if ((rp->ssh_istat & 0x08) == 0) { + rp->ssh_sien = 0; + rp->ssh_dien = 0; + } +#if 0 + } else if ((sc->sc_flags & SSH_INTDEFER) == 0) { + sc->sc_flags &= ~SSH_INTSOFF; + if ((rp->ssh_istat & 0x08) == 0) { + rp->ssh_sien = sc->sc_sien; + rp->ssh_dien = sc->sc_dien; + } +#endif + } +#ifdef DEBUG + if (ssh_debug & 1) + printf ("ssh_select: target %x cmd %02x ds %x\n", + acb->xs->sc_link->target, acb->cmd.opcode, + &sc->sc_nexus->ds); +#endif + + ssh_start(sc, acb->xs->sc_link->target, acb->xs->sc_link->lun, + (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft); + + return; +} + +/* + * 53C710 interrupt handler + */ + +int +sshintr (sc) + register struct ssh_softc *sc; +{ + ssh_regmap_p rp; + register u_char istat, dstat, sstat0; + int status; + int s = splbio(); + + istat = sc->sc_istat; + if ((istat & (SSH_ISTAT_SIP | SSH_ISTAT_DIP)) == 0) { + /* is this possible? we won't come here if there is not int!!! XXX */ + splx(s); + return; + } + + /* Got a valid interrupt on this device */ + rp = sc->sc_sshp; + dstat = sc->sc_dstat; + sstat0 = sc->sc_sstat0; + if (dstat & SSH_DSTAT_SIR) + sc->sc_intcode = rp->ssh_dsps; /* XXX use sc_intcode instead of dsps */ + + /* Clear the copies in sc */ + sc->sc_istat = 0; + sc->sc_dstat = 0; + sc->sc_sstat0 = 0; + +#ifdef DEBUG + if (ssh_debug & 1) + printf ("%s: intr istat %x dstat %x sstat0 %x\n", + sc->sc_dev.dv_xname, istat, dstat, sstat0); + if (!sc->sc_active) { + printf ("%s: spurious interrupt? istat %x dstat %x sstat0 %x status %x\n", + sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus->stat[0]); + } +#endif + +#ifdef DEBUG + if (ssh_debug & 5) { +#if CACHECTL + /*cmmu_inval_cache(kvtop(&sc->sc_nexus->stat[0]), + sizeof(sc->sc_nexus->stat[0])); */ + dma_cachectl(&sc->sc_nexus->stat[0], + sizeof(sc->sc_nexus->stat[0])); +#endif + printf ("%s: intr istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n", + sc->sc_dev.dv_xname, istat, dstat, sstat0, + rp->ssh_dsps, rp->ssh_sbcl, + sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]); + } +#endif + if (sc->sc_flags & SSH_INTDEFER) { + sc->sc_flags &= ~(SSH_INTDEFER | SSH_INTSOFF); + rp->ssh_sien = sc->sc_sien; + rp->ssh_dien = sc->sc_dien; + } + if (ssh_checkintr (sc, istat, dstat, sstat0, &status)) { +#if 1 + if (status == 0xff) + printf ("sshintr: status == 0xff\n"); +#endif + if ((sc->sc_flags & (SSH_INTSOFF | SSH_INTDEFER)) != SSH_INTSOFF) { +#if 0 + if (rp->ssh_sbcl & SSH_BSY) { + printf ("%s: SCSI bus busy at completion", + sc->sc_dev.dv_xname); + printf(" targ %d sbcl %02x sfbr %x lcrc %02x dsp +%x\n", + sc->sc_nexus->xs->sc_link->target, + rp->ssh_sbcl, rp->ssh_sfbr, rp->ssh_lcrc, + rp->ssh_dsp - sc->sc_scriptspa); + } +#endif + ssh_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]); + } + } + splx(s); +} + +/* + * This is based on the Progressive Peripherals 33Mhz Zeus driver and will + * not be correct for other 53c710 boards. + * XXX fix this - nivas + */ +void +scsi_period_to_ssh (sc, target) + struct ssh_softc *sc; + int target; +{ + int period, offset, sxfer, sbcl = 0; +#ifdef DEBUG_SYNC + int i; +#endif + + period = sc->sc_nexus->msg[4]; + offset = sc->sc_nexus->msg[5]; +#ifdef DEBUG_SYNC + sxfer = 0; + if (offset <= SSH_MAX_OFFSET) + sxfer = offset; + for (i = 0; i < sizeof (sync_tab) / 2; ++i) { + if (period <= sync_tab[i].p) { + sxfer |= sync_tab[i].r & 0x70; + sbcl = sync_tab[i].r & 0x03; + break; + } + } + printf ("ssh sync old: ssh_sxfr %02x, ssh_sbcl %02x\n", sxfer, sbcl); +#endif + for (sbcl = 1; sbcl < 4; ++sbcl) { + sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3; + if (sxfer >= 0 && sxfer <= 7) + break; + } + if (sbcl > 3) { + printf("ssh_sync: unable to compute sync params for period %dns\n", + period * 4); + /* + * XXX need to pick a value we can do and renegotiate + */ + sxfer = sbcl = 0; + } else { + sxfer = (sxfer << 4) | ((offset <= SSH_MAX_OFFSET) ? + offset : SSH_MAX_OFFSET); +#ifdef DEBUG_SYNC + printf("ssh sync: params for period %dns: sxfer %x sbcl %x", + period * 4, sxfer, sbcl); + printf(" actual period %dns\n", + sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4)); +#endif + } + sc->sc_sync[target].sxfer = sxfer; + sc->sc_sync[target].sbcl = sbcl; +#ifdef DEBUG_SYNC + printf ("ssh sync: ssh_sxfr %02x, ssh_sbcl %02x\n", sxfer, sbcl); +#endif +} + +#ifdef DEBUG + +#if SSH_TRACE_SIZE +void +ssh_dump_trace() +{ + int i; + + printf("ssh trace: next index %d\n", ssh_trix); + i = ssh_trix; + do { + printf("%3d: '%c' %02x %02x %02x\n", i, ssh_trbuf[i], + ssh_trbuf[i + 1], ssh_trbuf[i + 2], ssh_trbuf[i + 3]); + i = (i + 4) & (SSH_TRACE_SIZE - 1); + } while (i != ssh_trix); +} +#endif + +void +ssh_dump_acb(acb) + struct ssh_acb *acb; +{ + u_char *b = (u_char *) &acb->cmd; + int i; + + printf("acb@%p ", acb); + if (acb->xs == NULL) { + printf("\n"); + return; + } + printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target, + acb->xs->sc_link->lun, acb->flags, acb->clen); + for (i = acb->clen; i; --i) + printf(" %02x", *b++); + printf("\n"); + printf(" xs: %08x data %8x:%04x ", acb->xs, acb->xs->data, + acb->xs->datalen); + printf("va %8x:%04x ", acb->iob_buf, acb->iob_len); + printf("cur %8x:%04x\n", acb->iob_curbuf, acb->iob_curlen); +} + +void +ssh_dump(sc) + struct ssh_softc *sc; +{ + struct ssh_acb *acb; + ssh_regmap_p rp = sc->sc_sshp; + int s; + int i; + + s = splbio(); +#if SSH_TRACE_SIZE + ssh_dump_trace(); +#endif + printf("%s@%p regs %p istat %x\n", + sc->sc_dev.dv_xname, sc, rp, rp->ssh_istat); + if (acb = sc->free_list.tqh_first) { + printf("Free list:\n"); + while (acb) { + ssh_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if (acb = sc->ready_list.tqh_first) { + printf("Ready list:\n"); + while (acb) { + ssh_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if (acb = sc->nexus_list.tqh_first) { + printf("Nexus list:\n"); + while (acb) { + ssh_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if (sc->sc_nexus) { + printf("Nexus:\n"); + ssh_dump_acb(sc->sc_nexus); + } + for (i = 0; i < 8; ++i) { + if (sc->sc_tinfo[i].cmds > 2) { + printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n", + i, sc->sc_tinfo[i].cmds, + sc->sc_tinfo[i].dconns, + sc->sc_tinfo[i].senses, + sc->sc_tinfo[i].lubusy); + } + } + splx(s); +} +#endif diff --git a/sys/arch/mvme88k/dev/ssh_script.out b/sys/arch/mvme88k/dev/ssh_script.out new file mode 100644 index 00000000000..c6a91178fc8 --- /dev/null +++ b/sys/arch/mvme88k/dev/ssh_script.out @@ -0,0 +1,175 @@ +unsigned long scripts[] = { + 0x47000000, 0x00000118, /* 000 - 0 */ + 0x878b0000, 0x00000030, /* 008 - 8 */ + 0x868a0000, 0x00000168, /* 010 - 16 */ + 0x828a0000, 0x00000170, /* 018 - 24 */ + 0x808a0000, 0x00000180, /* 020 - 32 */ + 0x818a0000, 0x00000288, /* 028 - 40 */ + 0x838a0000, 0x00000390, /* 030 - 48 */ + 0x98080000, 0x0000ff05, /* 038 - 56 */ + 0x1f000024, 0x00000024, /* 040 - 64 */ + 0x808c0001, 0x00000040, /* 048 - 72 */ + 0x808c0004, 0x00000078, /* 050 - 80 */ + 0x808c0002, 0x00000088, /* 058 - 88 */ + 0x808c0007, 0x00000010, /* 060 - 96 */ + 0x808c0003, 0x00000008, /* 068 - 104 */ + 0x98080000, 0x0000ff06, /* 070 - 112 */ + 0x60000040, 0x00000000, /* 078 - 120 */ + 0x60000008, 0x00000000, /* 080 - 128 */ + 0x80880000, 0xffffff78, /* 088 - 136 */ + 0x60000040, 0x00000000, /* 090 - 144 */ + 0x1f00002c, 0x0000002c, /* 098 - 152 */ + 0x808c0003, 0x00000008, /* 0a0 - 160 */ + 0x98080000, 0x0000ff07, /* 0a8 - 168 */ + 0x60000040, 0x00000000, /* 0b0 - 176 */ + 0x1f000034, 0x00000034, /* 0b8 - 184 */ + 0x60000040, 0x00000000, /* 0c0 - 192 */ + 0x80880000, 0xffffff38, /* 0c8 - 200 */ + 0x60000040, 0x00000000, /* 0d0 - 208 */ + 0x48000000, 0x00000000, /* 0d8 - 216 */ + 0x98080000, 0x0000ff02, /* 0e0 - 224 */ + 0x60000040, 0x00000000, /* 0e8 - 232 */ + 0x87830000, 0xffffff10, /* 0f0 - 240 */ + 0x1f00002c, 0x0000002c, /* 0f8 - 248 */ + 0x98040004, 0x0000ff08, /* 100 - 256 */ + 0x60000040, 0x00000000, /* 108 - 264 */ + 0x48000000, 0x00000000, /* 110 - 272 */ + 0x98080000, 0x0000ff01, /* 118 - 280 */ + 0x54000000, 0x00000038, /* 120 - 288 */ + 0x72230000, 0x00000000, /* 128 - 296 */ + 0x6a340000, 0x00000000, /* 130 - 304 */ + 0x9f030000, 0x0000ff09, /* 138 - 312 */ + 0x1f00001c, 0x0000001c, /* 140 - 320 */ + 0x98080000, 0x0000ff03, /* 148 - 328 */ + 0x60000040, 0x00000000, /* 150 - 336 */ + 0x80880000, 0xfffffea8, /* 158 - 344 */ + 0x74011000, 0x00000000, /* 160 - 352 */ + 0x980c0000, 0x0000ff04, /* 168 - 360 */ + 0x74164000, 0x00000000, /* 170 - 368 */ + 0x80880000, 0xffffffa0, /* 178 - 376 */ + 0x1e000004, 0x00000004, /* 180 - 384 */ + 0x80880000, 0xfffffe78, /* 188 - 392 */ + 0x60000008, 0x00000000, /* 190 - 400 */ + 0x1a00000c, 0x0000000c, /* 198 - 408 */ + 0x80880000, 0xfffffe60, /* 1a0 - 416 */ + 0x1800003c, 0x0000003c, /* 1a8 - 424 */ + 0x88830000, 0xfffffe50, /* 1b0 - 432 */ + 0x18000044, 0x00000044, /* 1b8 - 440 */ + 0x88830000, 0xfffffe40, /* 1c0 - 448 */ + 0x1800004c, 0x0000004c, /* 1c8 - 456 */ + 0x88830000, 0xfffffe30, /* 1d0 - 464 */ + 0x18000054, 0x00000054, /* 1d8 - 472 */ + 0x88830000, 0xfffffe20, /* 1e0 - 480 */ + 0x1800005c, 0x0000005c, /* 1e8 - 488 */ + 0x88830000, 0xfffffe10, /* 1f0 - 496 */ + 0x18000064, 0x00000064, /* 1f8 - 504 */ + 0x88830000, 0xfffffe00, /* 200 - 512 */ + 0x1800006c, 0x0000006c, /* 208 - 520 */ + 0x88830000, 0xfffffdf0, /* 210 - 528 */ + 0x18000074, 0x00000074, /* 218 - 536 */ + 0x88830000, 0xfffffde0, /* 220 - 544 */ + 0x1800007c, 0x0000007c, /* 228 - 552 */ + 0x88830000, 0xfffffdd0, /* 230 - 560 */ + 0x18000084, 0x00000084, /* 238 - 568 */ + 0x88830000, 0xfffffdc0, /* 240 - 576 */ + 0x1800008c, 0x0000008c, /* 248 - 584 */ + 0x88830000, 0xfffffdb0, /* 250 - 592 */ + 0x18000094, 0x00000094, /* 258 - 600 */ + 0x88830000, 0xfffffda0, /* 260 - 608 */ + 0x1800009c, 0x0000009c, /* 268 - 616 */ + 0x88830000, 0xfffffd90, /* 270 - 624 */ + 0x180000a4, 0x000000a4, /* 278 - 632 */ + 0x88830000, 0xfffffd80, /* 280 - 640 */ + 0x180000ac, 0x000000ac, /* 288 - 648 */ + 0x88830000, 0xfffffd70, /* 290 - 656 */ + 0x180000b4, 0x000000b4, /* 298 - 664 */ + 0x88830000, 0xfffffd60, /* 2a0 - 672 */ + 0x180000bc, 0x000000bc, /* 2a8 - 680 */ + 0x88880000, 0xfffffd50, /* 2b0 - 688 */ + 0x1900003c, 0x0000003c, /* 2b8 - 696 */ + 0x89830000, 0xfffffd40, /* 2c0 - 704 */ + 0x19000044, 0x00000044, /* 2c8 - 712 */ + 0x89830000, 0xfffffd30, /* 2d0 - 720 */ + 0x1900004c, 0x0000004c, /* 2d8 - 728 */ + 0x89830000, 0xfffffd20, /* 2e0 - 736 */ + 0x19000054, 0x00000054, /* 2e8 - 744 */ + 0x89830000, 0xfffffd10, /* 2f0 - 752 */ + 0x1900005c, 0x0000005c, /* 2f8 - 760 */ + 0x89830000, 0xfffffd00, /* 300 - 768 */ + 0x19000064, 0x00000064, /* 308 - 776 */ + 0x89830000, 0xfffffcf0, /* 310 - 784 */ + 0x1900006c, 0x0000006c, /* 318 - 792 */ + 0x89830000, 0xfffffce0, /* 320 - 800 */ + 0x19000074, 0x00000074, /* 328 - 808 */ + 0x89830000, 0xfffffcd0, /* 330 - 816 */ + 0x1900007c, 0x0000007c, /* 338 - 824 */ + 0x89830000, 0xfffffcc0, /* 340 - 832 */ + 0x19000084, 0x00000084, /* 348 - 840 */ + 0x89830000, 0xfffffcb0, /* 350 - 848 */ + 0x1900008c, 0x0000008c, /* 358 - 856 */ + 0x89830000, 0xfffffca0, /* 360 - 864 */ + 0x19000094, 0x00000094, /* 368 - 872 */ + 0x89830000, 0xfffffc90, /* 370 - 880 */ + 0x1900009c, 0x0000009c, /* 378 - 888 */ + 0x89830000, 0xfffffc80, /* 380 - 896 */ + 0x190000a4, 0x000000a4, /* 388 - 904 */ + 0x89830000, 0xfffffc70, /* 390 - 912 */ + 0x190000ac, 0x000000ac, /* 398 - 920 */ + 0x89830000, 0xfffffc60, /* 3a0 - 928 */ + 0x190000b4, 0x000000b4, /* 3a8 - 936 */ + 0x89830000, 0xfffffc50, /* 3b0 - 944 */ + 0x190000bc, 0x000000bc, /* 3b8 - 952 */ + 0x88880000, 0xfffffc40, /* 3c0 - 960 */ + 0x1b000014, 0x00000014, /* 3c8 - 968 */ + 0x9f030000, 0x0000ff0a, /* 3d0 - 976 */ + 0x1f00001c, 0x0000001c, /* 3d8 - 984 */ + 0x60000040, 0x00000000, /* 3e0 - 992 */ + 0x48000000, 0x00000000, /* 3e8 - 1000 */ + 0x98080000, 0x0000ff00, /* 3f0 - 1008 */ + 0x80880000, 0xfffffd20, /* 3f8 - 1016 */ +}; + +#define A_ds_Device 0x00000000 +#define A_ds_MsgOut 0x00000004 +#define A_ds_Cmd 0x0000000c +#define A_ds_Status 0x00000014 +#define A_ds_Msg 0x0000001c +#define A_ds_MsgIn 0x00000024 +#define A_ds_ExtMsg 0x0000002c +#define A_ds_SyncMsg 0x00000034 +#define A_ds_Data1 0x0000003c +#define A_ds_Data2 0x00000044 +#define A_ds_Data3 0x0000004c +#define A_ds_Data4 0x00000054 +#define A_ds_Data5 0x0000005c +#define A_ds_Data6 0x00000064 +#define A_ds_Data7 0x0000006c +#define A_ds_Data8 0x00000074 +#define A_ds_Data9 0x0000007c +#define A_ds_Data10 0x00000084 +#define A_ds_Data11 0x0000008c +#define A_ds_Data12 0x00000094 +#define A_ds_Data13 0x0000009c +#define A_ds_Data14 0x000000a4 +#define A_ds_Data15 0x000000ac +#define A_ds_Data16 0x000000b4 +#define A_ds_Data17 0x000000bc +#define A_ok 0x0000ff00 +#define A_err1 0x0000ff01 +#define A_err2 0x0000ff02 +#define A_err3 0x0000ff03 +#define A_err4 0x0000ff04 +#define A_err5 0x0000ff05 +#define A_err6 0x0000ff06 +#define A_err7 0x0000ff07 +#define A_err8 0x0000ff08 +#define A_err9 0x0000ff09 +#define A_err10 0x0000ff0a +#define Ent_scripts 0x00000000 +#define Ent_switch 0x00000008 +#define Ent_wait_reselect 0x00000120 +#define Ent_dataout 0x000001a8 +#define Ent_datain 0x000002b8 + +unsigned long INSTRUCTIONS = 0x00000080; +unsigned long PATCHES = 0x00000000; diff --git a/sys/arch/mvme88k/dev/ssh_script.ss b/sys/arch/mvme88k/dev/ssh_script.ss new file mode 100644 index 00000000000..c11fd3991f4 --- /dev/null +++ b/sys/arch/mvme88k/dev/ssh_script.ss @@ -0,0 +1,205 @@ +; $OpenBSD: ssh_script.ss,v 1.1 2001/03/07 01:57:56 miod Exp $ + +; +; Copyright (c) 1995 Michael L. Hitch +; 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 Michael L. Hitch. +; 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. +; + +; NCR 53c710 script +; +ABSOLUTE ds_Device = 0 +ABSOLUTE ds_MsgOut = ds_Device + 4 +ABSOLUTE ds_Cmd = ds_MsgOut + 8 +ABSOLUTE ds_Status = ds_Cmd + 8 +ABSOLUTE ds_Msg = ds_Status + 8 +ABSOLUTE ds_MsgIn = ds_Msg + 8 +ABSOLUTE ds_ExtMsg = ds_MsgIn + 8 +ABSOLUTE ds_SyncMsg = ds_ExtMsg + 8 +ABSOLUTE ds_Data1 = ds_SyncMsg + 8 +ABSOLUTE ds_Data2 = ds_Data1 + 8 +ABSOLUTE ds_Data3 = ds_Data2 + 8 +ABSOLUTE ds_Data4 = ds_Data3 + 8 +ABSOLUTE ds_Data5 = ds_Data4 + 8 +ABSOLUTE ds_Data6 = ds_Data5 + 8 +ABSOLUTE ds_Data7 = ds_Data6 + 8 +ABSOLUTE ds_Data8 = ds_Data7 + 8 +ABSOLUTE ds_Data9 = ds_Data8 + 8 + +ABSOLUTE ok = 0xff00 +ABSOLUTE err1 = 0xff01 +ABSOLUTE err2 = 0xff02 +ABSOLUTE err3 = 0xff03 +ABSOLUTE err4 = 0xff04 +ABSOLUTE err5 = 0xff05 +ABSOLUTE err6 = 0xff06 +ABSOLUTE err7 = 0xff07 +ABSOLUTE err8 = 0xff08 +ABSOLUTE err9 = 0xff09 +ABSOLUTE err10 = 0xff0a + +ENTRY scripts +ENTRY switch +ENTRY wait_reselect +ENTRY dataout +ENTRY datain + +PROC scripts: + +scripts: + + SELECT ATN FROM ds_Device, REL(reselect) +; +switch: + JUMP REL(msgin), WHEN MSG_IN + JUMP REL(msgout), IF MSG_OUT + JUMP REL(command_phase), IF CMD + JUMP REL(dataout), IF DATA_OUT + JUMP REL(datain), IF DATA_IN + JUMP REL(end), IF STATUS + + INT err5 ; Unrecognized phase + +msgin: + MOVE FROM ds_MsgIn, WHEN MSG_IN + JUMP REL(ext_msg), IF 0x01 ; extended message + JUMP REL(disc), IF 0x04 ; disconnect message + JUMP REL(msg_sdp), IF 0x02 ; save data pointers + JUMP REL(msg_rej), IF 0x07 ; message reject + JUMP REL(msg_rdp), IF 0x03 ; restore data pointers + INT err6 ; unrecognized message + +msg_rdp: +msg_rej: + CLEAR ACK + CLEAR ATN + JUMP REL(switch) + +ext_msg: + CLEAR ACK + MOVE FROM ds_ExtMsg, WHEN MSG_IN + JUMP REL(sync_msg), IF 0x03 + int err7 ; extended message not SDTR + +sync_msg: + CLEAR ACK + MOVE FROM ds_SyncMsg, WHEN MSG_IN + CLEAR ACK + JUMP REL(switch) + +disc: + CLEAR ACK + WAIT DISCONNECT + + int err2 ; signal disconnect w/o save DP + +msg_sdp: + CLEAR ACK ; acknowledge message + JUMP REL(switch), WHEN NOT MSG_IN + MOVE FROM ds_ExtMsg, WHEN MSG_IN + INT err8, IF NOT 0x04 ; interrupt if not disconnect + CLEAR ACK + WAIT DISCONNECT + + INT err1 ; signal disconnect + +reselect: +wait_reselect: + WAIT RESELECT REL(select_adr) + MOVE LCRC to SFBR ; Save reselect ID + MOVE SFBR to SCRATCH0 + + INT err9, WHEN NOT MSG_IN ; didn't get IDENTIFY + MOVE FROM ds_Msg, WHEN MSG_IN + INT err3 ; let host know about reconnect + CLEAR ACK ; acknowlege the message + JUMP REL(switch) + + +select_adr: + MOVE SCNTL1 & 0x10 to SFBR ; get connected status + INT err4, IF 0x00 ; tell host if not connected + MOVE CTEST2 & 0x40 to SFBR ; clear Sig_P + JUMP REL(wait_reselect) ; and try reselect again + +msgout: + MOVE FROM ds_MsgOut, WHEN MSG_OUT + JUMP REL(switch) + +command_phase: + CLEAR ATN + MOVE FROM ds_Cmd, WHEN CMD + JUMP REL(switch) + +dataout: + MOVE FROM ds_Data1, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data2, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data3, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data4, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data5, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data6, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data7, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data8, WHEN DATA_OUT + CALL REL(switch), WHEN NOT DATA_OUT + MOVE FROM ds_Data9, WHEN DATA_OUT + CALL REL(switch) + +datain: + MOVE FROM ds_Data1, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data2, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data3, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data4, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data5, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data6, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data7, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data8, WHEN DATA_IN + CALL REL(switch), WHEN NOT DATA_IN + MOVE FROM ds_Data9, WHEN DATA_IN + CALL REL(switch) + +end: + MOVE FROM ds_Status, WHEN STATUS + int err10, WHEN NOT MSG_IN ; status not followed by msg + MOVE FROM ds_Msg, WHEN MSG_IN + CLEAR ACK + WAIT DISCONNECT + INT ok ; signal completion + JUMP REL(wait_reselect) diff --git a/sys/arch/mvme88k/dev/sshdma.c b/sys/arch/mvme88k/dev/sshdma.c new file mode 100644 index 00000000000..14b892a5fa4 --- /dev/null +++ b/sys/arch/mvme88k/dev/sshdma.c @@ -0,0 +1,295 @@ +/* $OpenBSD: sshdma.c,v 1.1 2001/03/07 01:57:56 miod Exp $ */ + +/* + * Copyright (c) 1996 Nivas Madhur + * Copyright (c) 1995 Theo de Raadt + * Copyright (c) 1994 Michael L. Hitch + * Copyright (c) 1982, 1990 The Regents of the University of California. + * 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 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. + * + * @(#)dma.c + */ + +#include +#include +#include +#include +#include +#include +#include +#if defined(MVME187) +#include +#endif /* MVME187 */ + +#if defined(MVME187) +#include +#include +#else +#include +#include +#endif /* defined(MVME187) */ + +#if !defined(MVME187) +#include "mc.h" +#endif /* MVME187 */ +#include "pcctwo.h" + +#if NMC > 0 +#include +#endif +#if NPCCTWO > 0 +#if defined(MVME187) +#include +#else +#include +#endif /* defined(MVME187) */ +#endif + +#if defined(MVME187) +#include "machine/mmu.h" +#endif /* defined(MVME187) */ + +extern struct pmap kernel_pmap_store; +#define pmap_kernel() (&kernel_pmap_store) + +int afscmatch __P((struct device *, void *, void *)); +void afscattach __P((struct device *, struct device *, void *)); + +int afscprint __P((void *auxp, char *)); +int sshintr __P((struct ssh_softc *)); +int afsc_dmaintr __P((struct ssh_softc *)); + +struct scsi_adapter afsc_scsiswitch = { + ssh_scsicmd, + ssh_minphys, + 0, /* no lun support */ + 0, /* no lun support */ +}; + +struct scsi_device afsc_scsidev = { + NULL, /* use default error handler */ + NULL, /* do not have a start function */ + NULL, /* have no async handler */ + NULL, /* Use default done routine */ +}; + +struct cfattach ssh_ca = { + sizeof(struct ssh_softc), afscmatch, afscattach, +}; + +struct cfdriver ssh_cd = { + NULL, "ssh", DV_DULL, 0 +}; + +int +afscmatch(pdp, vcf, args) + struct device *pdp; + void *vcf, *args; +{ + struct cfdata *cf = vcf; + struct confargs *ca = args; + int ret; + + if ((ret = badvaddr(IIOV(ca->ca_vaddr), 4)) <=0){ + printf("==> ssh: failed address check returning %ld.\n", ret); + return(0); + } + + return (1); +} + +void +afscattach(parent, self, auxp) + struct device *parent, *self; + void *auxp; +{ + struct ssh_softc *sc = (struct ssh_softc *)self; + struct confargs *ca = auxp; + ssh_regmap_p rp; + int tmp; + extern int cpuspeed; + + sc->sc_sshp = rp = ca->ca_vaddr; + + /* + * ssh uses sc_clock_freq to define the dcntl & ctest7 reg values + * (was 0x0221, but i added SSH_CTEST7_SC0 for snooping control) + * XXX does the clock frequency change for the 33MHz processors? + */ + sc->sc_clock_freq = cpuspeed * 2; +#ifdef MVME177 + /* XXX this is a guess! */ + if (cputyp == CPU_177) + sc->sc_clock_freq = cpuspeed; +#endif + sc->sc_dcntl = SSH_DCNTL_EA; +/*X*/ if (sc->sc_clock_freq <= 25) +/*X*/ sc->sc_dcntl |= (2 << 6); +/*X*/ else if (sc->sc_clock_freq <= 37) +/*X*/ sc->sc_dcntl |= (1 << 6); +/*X*/ else if (sc->sc_clock_freq <= 50) +/*X*/ sc->sc_dcntl |= (0 << 6); +/*X*/ else +/*X*/ sc->sc_dcntl |= (3 << 6); + + sc->sc_ctest0 = SSH_CTEST0_BTD | SSH_CTEST0_EAN; + +#ifdef MVME187 + /* + * MVME187 doesn't implement snooping... + */ + sc->sc_ctest7 = SSH_CTEST7_TT1; +#else + sc->sc_ctest7 = SSH_CTEST7_SNOOP | SSH_CTEST7_TT1 | SSH_CTEST7_STD; +#endif /* MVME187 */ + + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter_target = 7; /* XXXX should ask ROM */ + sc->sc_link.adapter = &afsc_scsiswitch; + sc->sc_link.device = &afsc_scsidev; + sc->sc_link.openings = 1; + + sc->sc_ih.ih_fn = afsc_dmaintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_ipl = ca->ca_ipl; + + sshinitialize(sc); + + switch (ca->ca_bustype) { +#if NMC > 0 + case BUS_MC: + { + struct mcreg *mc = (struct mcreg *)ca->ca_master; + + mcintr_establish(MCV_NCR, &sc->sc_ih); + mc->mc_ncrirq = ca->ca_ipl | MC_IRQ_IEN; + break; + } +#endif +#if NPCCTWO > 0 + case BUS_PCCTWO: + { +#if defined(MVME187) + /* + * Disable caching for the softc. Actually, I want + * to disable cache for acb structures, but they are + * part of softc, and I am disabling the entire softc + * just in case. + */ + + struct pcctworeg *pcc2 = (struct pcctworeg *)ca->ca_master; + + pmap_cache_ctrl(pmap_kernel(), M88K_TRUNC_PAGE((vm_offset_t)sc), + M88K_ROUND_PAGE((vm_offset_t)sc + sizeof(*sc)), + CACHE_INH); +#endif + pcctwointr_establish(PCC2V_NCR, &sc->sc_ih); +/* intr_establish(PCC2_VECT + SCSIIRQ, &sc->sc_ih);*/ + /* enable interrupts at ca_ipl */ + pcc2->pcc2_ncrirq = ca->ca_ipl | PCC2_IRQ_IEN; +/* pcc2->pcc2_scsiirq = ca->ca_ipl | PCC2_SCSIIRQ_IEN;*/ + break; + } +#endif + } + + evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); + + /* + * attach all scsi units on us, watching for boot device + * (see dk_establish). + */ + tmp = bootpart; + if (ca->ca_paddr != bootaddr) + bootpart = -1; /* invalid flag to dk_establish */ + config_found(self, &sc->sc_link, scsiprint); + bootpart = tmp; /* restore old value */ +} +/* + * print diag if pnp is NULL else just extra + */ +int +afscprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp == NULL) + return (UNCONF); + return (QUIET); +} + +int +afsc_dmaintr(sc) + struct ssh_softc *sc; +{ + ssh_regmap_p rp; + u_char istat; + + rp = sc->sc_sshp; + istat = rp->ssh_istat; + if ((istat & (SSH_ISTAT_SIP | SSH_ISTAT_DIP)) == 0) + return (0); + if ((rp->ssh_sien | rp->ssh_dien) == 0) + return (0); /* no interrupts enabled */ + + /* + * 53c710 manual recommends reading dstat and sstat0 at least + * 12 clk cycles apart if reading as bytes (which is what + * pcc2 permits). Stick in a 1us delay between accessing dstat and + * sstat0 below. + * + * save interrupt status, DMA status, and SCSI status 0 + * (may need to deal with stacked interrupts?) + */ + sc->sc_istat = istat; + if (istat & SSH_ISTAT_SIP) { + sc->sc_sstat0 = rp->ssh_sstat0; + } + if (istat & SSH_ISTAT_DIP) { + delay(3); + sc->sc_dstat = rp->ssh_dstat; + } + sshintr(sc); + sc->sc_intrcnt.ev_count++; + return (1); +} + +#ifdef XXX_CD_DEBUG /* XXXsmurph What is afsccd ?? */ +void +afsc_dump() +{ + int i; + + for (i = 0; i < afsccd.cd_ndevs; ++i) + if (afsccd.cd_devs[i]) + ssh_dump(afsccd.cd_devs[i]); +} +#endif diff --git a/sys/arch/mvme88k/dev/sshreg.h b/sys/arch/mvme88k/dev/sshreg.h new file mode 100644 index 00000000000..41a3407a1b2 --- /dev/null +++ b/sys/arch/mvme88k/dev/sshreg.h @@ -0,0 +1,336 @@ +/* $OpenBSD: sshreg.h,v 1.1 2001/03/07 01:57:56 miod Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sshreg.h 7.3 (Berkeley) 2/5/91 + */ + +/* + * NCR 53C710 SCSI interface hardware description. + * + * From the Mach scsi driver for the 53C700 + */ + +typedef struct { +/*00*/ volatile unsigned char ssh_sien; /* rw: SCSI Interrupt Enable */ +/*01*/ volatile unsigned char ssh_sdid; /* rw: SCSI Destination ID */ +/*02*/ volatile unsigned char ssh_scntl1; /* rw: SCSI control reg 1 */ +/*03*/ volatile unsigned char ssh_scntl0; /* rw: SCSI control reg 0 */ +/*04*/ volatile unsigned char ssh_socl; /* rw: SCSI Output Control Latch */ +/*05*/ volatile unsigned char ssh_sodl; /* rw: SCSI Output Data Latch */ +/*06*/ volatile unsigned char ssh_sxfer; /* rw: SCSI Transfer reg */ +/*07*/ volatile unsigned char ssh_scid; /* rw: SCSI Chip ID reg */ +/*08*/ volatile unsigned char ssh_sbcl; /* ro: SCSI Bus Control Lines */ +/*09*/ volatile unsigned char ssh_sbdl; /* ro: SCSI Bus Data Lines */ +/*0a*/ volatile unsigned char ssh_sidl; /* ro: SCSI Input Data Latch */ +/*0b*/ volatile unsigned char ssh_sfbr; /* ro: SCSI First Byte Received */ +/*0c*/ volatile unsigned char ssh_sstat2; /* ro: SCSI status reg 2 */ +/*0d*/ volatile unsigned char ssh_sstat1; /* ro: SCSI status reg 1 */ +/*0e*/ volatile unsigned char ssh_sstat0; /* ro: SCSI status reg 0 */ +/*0f*/ volatile unsigned char ssh_dstat; /* ro: DMA status */ +/*10*/ volatile unsigned long ssh_dsa; /* rw: Data Structure Address */ +/*14*/ volatile unsigned char ssh_ctest3; /* ro: Chip test register 3 */ +/*15*/ volatile unsigned char ssh_ctest2; /* ro: Chip test register 2 */ +/*16*/ volatile unsigned char ssh_ctest1; /* ro: Chip test register 1 */ +/*17*/ volatile unsigned char ssh_ctest0; /* ro: Chip test register 0 */ +/*18*/ volatile unsigned char ssh_ctest7; /* rw: Chip test register 7 */ +/*19*/ volatile unsigned char ssh_ctest6; /* rw: Chip test register 6 */ +/*1a*/ volatile unsigned char ssh_ctest5; /* rw: Chip test register 5 */ +/*1b*/ volatile unsigned char ssh_ctest4; /* rw: Chip test register 4 */ +/*1c*/ volatile unsigned long ssh_temp; /* rw: Temporary Stack reg */ +/*20*/ volatile unsigned char ssh_lcrc; /* rw: LCRC value */ +/*21*/ volatile unsigned char ssh_ctest8; /* rw: Chip test register 8 */ +/*22*/ volatile unsigned char ssh_istat; /* rw: Interrupt Status reg */ +/*23*/ volatile unsigned char ssh_dfifo; /* rw: DMA FIFO */ +/*24*/ volatile unsigned char ssh_dcmd; /* rw: DMA Command Register */ +/*25*/ volatile unsigned char ssh_dbc2; /* rw: DMA Byte Counter reg */ +/*26*/ volatile unsigned char ssh_dbc1; +/*27*/ volatile unsigned char ssh_dbc0; +/*28*/ volatile unsigned long ssh_dnad; /* rw: DMA Next Address */ +/*2c*/ volatile unsigned long ssh_dsp; /* rw: DMA SCRIPTS Pointer reg */ +/*30*/ volatile unsigned long ssh_dsps; /* rw: DMA SCRIPTS Pointer Save reg */ +/*34*/ volatile unsigned long ssh_scratch; /* rw: Scratch Register */ +/*38*/ volatile unsigned char ssh_dcntl; /* rw: DMA Control reg */ +/*39*/ volatile unsigned char ssh_dwt; /* rw: DMA Watchdog Timer */ +/*3a*/ volatile unsigned char ssh_dien; /* rw: DMA Interrupt Enable */ +/*3b*/ volatile unsigned char ssh_dmode; /* rw: DMA Mode reg */ +/*3c*/ volatile unsigned long ssh_adder; + +} ssh_regmap_t; +typedef volatile ssh_regmap_t *ssh_regmap_p; + +/* + * Register defines + */ + +/* Scsi control register 0 (scntl0) */ + +#define SSH_SCNTL0_ARB 0xc0 /* Arbitration mode */ +# define SSH_ARB_SIMPLE 0x00 +# define SSH_ARB_FULL 0xc0 +#define SSH_SCNTL0_START 0x20 /* Start Sequence */ +#define SSH_SCNTL0_WATN 0x10 /* (Select) With ATN */ +#define SSH_SCNTL0_EPC 0x08 /* Enable Parity Checking */ +#define SSH_SCNTL0_EPG 0x04 /* Enable Parity Generation */ +#define SSH_SCNTL0_AAP 0x02 /* Assert ATN on Parity Error */ +#define SSH_SCNTL0_TRG 0x01 /* Target Mode */ + +/* Scsi control register 1 (scntl1) */ + +#define SSH_SCNTL1_EXC 0x80 /* Extra Clock Cycle of data setup */ +#define SSH_SCNTL1_ADB 0x40 /* Assert Data Bus */ +#define SSH_SCNTL1_ESR 0x20 /* Enable Selection/Reselection */ +#define SSH_SCNTL1_CON 0x10 /* Connected */ +#define SSH_SCNTL1_RST 0x08 /* Assert RST */ +#define SSH_SCNTL1_AESP 0x04 /* Assert even SCSI parity */ +#define SSH_SCNTL1_RES0 0x02 /* Reserved */ +#define SSH_SCNTL1_RES1 0x01 /* Reserved */ + +/* Scsi interrupt enable register (sien) */ + +#define SSH_SIEN_M_A 0x80 /* Phase Mismatch or ATN active */ +#define SSH_SIEN_FCMP 0x40 /* Function Complete */ +#define SSH_SIEN_STO 0x20 /* (Re)Selection timeout */ +#define SSH_SIEN_SEL 0x10 /* (Re)Selected */ +#define SSH_SIEN_SGE 0x08 /* SCSI Gross Error */ +#define SSH_SIEN_UDC 0x04 /* Unexpected Disconnect */ +#define SSH_SIEN_RST 0x02 /* RST asserted */ +#define SSH_SIEN_PAR 0x01 /* Parity Error */ + +/* Scsi chip ID (scid) */ + +#define SSH_SCID_VALUE(i) (1< asserted */ +#define SSH_ACK 0x40 +#define SSH_BSY 0x20 +#define SSH_SEL 0x10 +#define SSH_ATN 0x08 +#define SSH_MSG 0x04 +#define SSH_CD 0x02 +#define SSH_IO 0x01 + +#define SSH_PHASE(socl) SCSI_PHASE(socl) + +/* Scsi first byte received register (sfbr) */ + +/* Scsi input data latch register (sidl) */ + +/* Scsi bus data lines register (sbdl) */ + +/* Scsi bus control lines register (sbcl). Same as socl */ + +/* DMA status register (dstat) */ + +#define SSH_DSTAT_DFE 0x80 /* DMA FIFO empty */ +#define SSH_DSTAT_RES 0x40 +#define SSH_DSTAT_BF 0x20 /* Bus fault */ +#define SSH_DSTAT_ABRT 0x10 /* Aborted */ +#define SSH_DSTAT_SSI 0x08 /* SCRIPT Single Step */ +#define SSH_DSTAT_SIR 0x04 /* SCRIPT Interrupt Instruction */ +#define SSH_DSTAT_WTD 0x02 /* Watchdog Timeout Detected */ +#define SSH_DSTAT_IID 0x01 /* Invalid Instruction Detected */ + +/* Scsi status register 0 (sstat0) */ + +#define SSH_SSTAT0_M_A 0x80 /* Phase Mismatch or ATN active */ +#define SSH_SSTAT0_FCMP 0x40 /* Function Complete */ +#define SSH_SSTAT0_STO 0x20 /* (Re)Selection timeout */ +#define SSH_SSTAT0_SEL 0x10 /* (Re)Selected */ +#define SSH_SSTAT0_SGE 0x08 /* SCSI Gross Error */ +#define SSH_SSTAT0_UDC 0x04 /* Unexpected Disconnect */ +#define SSH_SSTAT0_RST 0x02 /* RST asserted */ +#define SSH_SSTAT0_PAR 0x01 /* Parity Error */ + +/* Scsi status register 1 (sstat1) */ + +#define SSH_SSTAT1_ILF 0x80 /* Input latch (sidl) full */ +#define SSH_SSTAT1_ORF 0x40 /* output reg (sodr) full */ +#define SSH_SSTAT1_OLF 0x20 /* output latch (sodl) full */ +#define SSH_SSTAT1_AIP 0x10 /* Arbitration in progress */ +#define SSH_SSTAT1_LOA 0x08 /* Lost arbitration */ +#define SSH_SSTAT1_WOA 0x04 /* Won arbitration */ +#define SSH_SSTAT1_RST 0x02 /* SCSI RST current value */ +#define SSH_SSTAT1_SDP 0x01 /* SCSI SDP current value */ + +/* Scsi status register 2 (sstat2) */ + +#define SSH_SSTAT2_FF 0xf0 /* SCSI FIFO flags (bytecount) */ +# define SSH_SCSI_FIFO_DEEP 8 +#define SSH_SSTAT2_SDP 0x08 /* Latched (on REQ) SCSI SDP */ +#define SSH_SSTAT2_MSG 0x04 /* Latched SCSI phase */ +#define SSH_SSTAT2_CD 0x02 +#define SSH_SSTAT2_IO 0x01 + +/* Chip test register 0 (ctest0) */ + +#define SSH_CTEST0_RES0 0x80 +#define SSH_CTEST0_BTD 0x40 /* Byte-to-byte Timer Disable */ +#define SSH_CTEST0_GRP 0x20 /* Generate Receive Parity for Passthrough */ +#define SSH_CTEST0_EAN 0x10 /* Enable Active Negation */ +#define SSH_CTEST0_HSC 0x08 /* Halt SCSI clock */ +#define SSH_CTEST0_ERF 0x04 /* Extend REQ/ACK Filtering */ +#define SSH_CTEST0_RES1 0x02 +#define SSH_CTEST0_DDIR 0x01 /* Xfer direction (1-> from SCSI bus) */ + +/* Chip test register 1 (ctest1) */ + +#define SSH_CTEST1_FMT 0xf0 /* Byte empty in DMA FIFO bottom (high->byte3) */ +#define SSH_CTEST1_FFL 0x0f /* Byte full in DMA FIFO top, same */ + +/* Chip test register 2 (ctest2) */ + +#define SSH_CTEST2_RES 0x80 +#define SSH_CTEST2_SIGP 0x40 /* Signal process */ +#define SSH_CTEST2_SOFF 0x20 /* Synch Offset compare (1-> zero Init, max Tgt */ +#define SSH_CTEST2_SFP 0x10 /* SCSI FIFO Parity */ +#define SSH_CTEST2_DFP 0x08 /* DMA FIFO Parity */ +#define SSH_CTEST2_TEOP 0x04 /* True EOP (a-la 5380) */ +#define SSH_CTEST2_DREQ 0x02 /* DREQ status */ +#define SSH_CTEST2_DACK 0x01 /* DACK status */ + +/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */ + +/* Chip test register 4 (ctest4) */ + +#define SSH_CTEST4_MUX 0x80 /* Host bus multiplex mode */ +#define SSH_CTEST4_ZMOD 0x40 /* High-impedance outputs */ +#define SSH_CTEST4_SZM 0x20 /* ditto, SCSI "outputs" */ +#define SSH_CTEST4_SLBE 0x10 /* SCSI loobpack enable */ +#define SSH_CTEST4_SFWR 0x08 /* SCSI FIFO write enable (from sodl) */ +#define SSH_CTEST4_FBL 0x07 /* DMA FIFO Byte Lane select (from ctest6) + 4->0, .. 7->3 */ + +/* Chip test register 5 (ctest5) */ + +#define SSH_CTEST5_ADCK 0x80 /* Clock Address Incrementor */ +#define SSH_CTEST5_BBCK 0x40 /* Clock Byte counter */ +#define SSH_CTEST5_ROFF 0x20 /* Reset SCSI offset */ +#define SSH_CTEST5_MASR 0x10 /* Master set/reset pulses (of bits 3-0) */ +#define SSH_CTEST5_DDIR 0x08 /* (re)set internal DMA direction */ +#define SSH_CTEST5_EOP 0x04 /* (re)set internal EOP */ +#define SSH_CTEST5_DREQ 0x02 /* (re)set internal REQ */ +#define SSH_CTEST5_DACK 0x01 /* (re)set internal ACK */ + +/* Chip test register 6 (ctest6) DMA FIFO access */ + +/* Chip test register 7 (ctest7) */ + +#define SSH_CTEST7_CDIS 0x80 /* Cache burst disable */ +#define SSH_CTEST7_SC1 0x40 /* Snoop control 1 */ +#define SSH_CTEST7_SC0 0x20 /* Snoop contorl 0 */ +#define SSH_CTEST7_INHIBIT (0 << 5) +#define SSH_CTEST7_SNOOP (1 << 5) +#define SSH_CTEST7_INVAL (2 << 5) +#define SSH_CTEST7_RESV (3 << 5) +#define SSH_CTEST7_STD 0x10 /* Selection timeout disable */ +#define SSH_CTEST7_DFP 0x08 /* DMA FIFO parity bit */ +#define SSH_CTEST7_EVP 0x04 /* Even parity (to host bus) */ +#define SSH_CTEST7_TT1 0x02 /* Transfer type bit */ +#define SSH_CTEST7_DIFF 0x01 /* Differential mode */ + +/* DMA FIFO register (dfifo) */ + +#define SSH_DFIFO_RES 0x80 +#define SSH_DFIFO_BO 0x7f /* FIFO byte offset counter */ + +/* Interrupt status register (istat) */ + +#define SSH_ISTAT_ABRT 0x80 /* Abort operation */ +#define SSH_ISTAT_RST 0x40 /* Software reset */ +#define SSH_ISTAT_SIGP 0x20 /* Signal process */ +#define SSH_ISTAT_RES 0x10 +#define SSH_ISTAT_CON 0x08 /* Connected */ +#define SSH_ISTAT_RES1 0x04 +#define SSH_ISTAT_SIP 0x02 /* SCSI Interrupt pending */ +#define SSH_ISTAT_DIP 0x01 /* DMA Interrupt pending */ + +/* Chip test register 8 (ctest8) + +#define SSH_CTEST8_V 0xf0 /* Chip revision level */ +#define SSH_CTEST8_FLF 0x08 /* Flush DMA FIFO */ +#define SSH_CTEST8_CLF 0x04 /* Clear DMA and SCSI FIFOs */ +#define SSH_CTEST8_FM 0x02 /* Fetch pin mode */ +#define SSH_CTEST8_SM 0x01 /* Snoop pins mode */ + +/* DMA Mode register (dmode) */ + +#define SSH_DMODE_BL_MASK 0xc0 /* 0->1 1->2 2->4 3->8 */ +#define SSH_DMODE_FC 0x30 /* Function code */ +#define SSH_DMODE_PD 0x08 /* Program/data */ +#define SSH_DMODE_FAM 0x04 /* Fixed address mode */ +#define SSH_DMODE_U0 0x02 /* User programmable transfer type */ +#define SSH_DMODE_MAN 0x01 /* Manual start mode */ + +/* DMA interrupt enable register (dien) */ + +#define SSH_DIEN_RES 0xc0 +#define SSH_DIEN_BF 0x20 /* On Bus Fault */ +#define SSH_DIEN_ABRT 0x10 /* On Abort */ +#define SSH_DIEN_SSI 0x08 /* On SCRIPTS sstep */ +#define SSH_DIEN_SIR 0x04 /* On SCRIPTS intr instruction */ +#define SSH_DIEN_WTD 0x02 /* On watchdog timeout */ +#define SSH_DIEN_IID 0x01 /* On illegal instruction detected */ + +/* DMA control register (dcntl) */ + +#define SSH_DCNTL_CF_MASK 0xc0 /* Clock frequency dividers: + 0 --> 37.51..50.00 Mhz, div=2 + 1 --> 25.01..37.50 Mhz, div=1.5 + 2 --> 16.67..25.00 Mhz, div=1 + 3 --> 50.01..66.67 Mhz, div=3 + */ +#define SSH_DCNTL_EA 0x20 /* Enable ack */ +#define SSH_DCNTL_SSM 0x10 /* Single step mode */ +#define SSH_DCNTL_LLM 0x08 /* Enable SCSI Low-level mode */ +#define SSH_DCNTL_STD 0x04 /* Start DMA operation */ +#define SSH_DCNTL_FA 0x02 /* Fast arbitration */ +#define SSH_DCNTL_COM 0x01 /* 53C700 compatibility */ diff --git a/sys/arch/mvme88k/dev/sshvar.h b/sys/arch/mvme88k/dev/sshvar.h new file mode 100644 index 00000000000..f5067562611 --- /dev/null +++ b/sys/arch/mvme88k/dev/sshvar.h @@ -0,0 +1,204 @@ +/* $OpenBSD: sshvar.h,v 1.1 2001/03/07 01:57:56 miod Exp $ */ + +/* + * Copyright (c) 1995 Theo de Raadt + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sshvar.h 7.1 (Berkeley) 5/8/90 + */ +#ifndef _SSHVAR_H_ +#define _SSHVAR_H_ + +/* + * The largest single request will be MAXPHYS bytes which will require + * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of + * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the + * buffer is not page aligned (+1). + */ +#define DMAMAXIO (MAXPHYS/NBPG+1) + +/* + * Data Structure for SCRIPTS program + */ +struct ssh_ds { +/*00*/ long scsi_addr; /* SCSI ID & sync */ +/*04*/ long idlen; /* Identify message */ +/*08*/ char *idbuf; +/*0c*/ long cmdlen; /* SCSI command */ +/*10*/ char *cmdbuf; +/*14*/ long stslen; /* Status */ +/*18*/ char *stsbuf; +/*1c*/ long msglen; /* Message */ +/*20*/ char *msgbuf; +/*24*/ long msginlen; /* Message in */ +/*28*/ char *msginbuf; +/*2c*/ long extmsglen; /* Extended message in */ +/*30*/ char *extmsgbuf; +/*34*/ long synmsglen; /* Sync transfer request */ +/*38*/ char *synmsgbuf; + struct { +/*3c*/ long datalen; +/*40*/ char *databuf; + } chain[DMAMAXIO]; +}; + +/* + * ACB. 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 ssh_acb { +/*00*/ TAILQ_ENTRY(ssh_acb) chain; +/*08*/ struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ +/*0c*/ int flags; /* Status */ +#define ACB_FREE 0x00 +#define ACB_ACTIVE 0x01 +#define ACB_DONE 0x04 +#define ACB_CHKSENSE 0x08 +/*10*/ struct scsi_generic cmd; /* SCSI command block */ +/*1c*/ struct ssh_ds ds; +/*a0*/ void *iob_buf; +/*a4*/ u_long iob_curbuf; +/*a8*/ u_long iob_len, iob_curlen; +/*b0*/ u_char msgout[6]; +/*b6*/ u_char msg[6]; +/*bc*/ u_char stat[1]; +/*bd*/ u_char status; +/*be*/ u_char dummy[2]; +/*c0*/ int clen; +/*c4*/ char *daddr; /* Saved data pointer */ +/*c8*/ int dleft; /* Residue */ +}; + +/* + * 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 ssh_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; + u_char period; /* Period suggestion */ + u_char offset; /* Offset suggestion */ +} tinfo_t; + +struct ssh_softc { + struct device sc_dev; + struct intrhand sc_ih; + struct evcnt sc_intrcnt; + + u_char sc_istat; + u_char sc_dstat; + u_char sc_sstat0; + u_char sc_sstat1; + u_long sc_intcode; + struct scsi_link sc_link; /* proto for sub devices */ + u_long sc_scriptspa; /* physical address of scripts */ + ssh_regmap_p sc_sshp; /* the SSH */ + u_long sc_active; /* number of active I/O's */ + + /* Lists of command blocks */ + TAILQ_HEAD(acb_list, ssh_acb) free_list, + ready_list, + nexus_list; + + struct ssh_acb *sc_nexus; /* current command */ +#define SSH_NACB 8 + struct ssh_acb *sc_acb; /* the real command blocks */ + struct ssh_tinfo sc_tinfo[8]; + + u_short sc_clock_freq; + u_char sc_dcntl; + u_char sc_ctest0; + u_char sc_ctest7; + u_short sc_tcp[4]; + u_char sc_flags; + u_char sc_sien; + u_char sc_dien; + u_char sc_minsync; + /* one for each target */ + struct syncpar { + u_char state; + u_char sxfer; + u_char sbcl; + } sc_sync[8]; +}; + +/* sc_flags */ +#define SSH_INTSOFF 0x80 /* Interrupts turned off */ +#define SSH_INTDEFER 0x40 /* Level 6 interrupt has been deferred */ +#define SSH_ALIVE 0x01 /* controller initialized */ +#define SSH_SELECTED 0x04 /* bus is in selected state. Needed for + correct abort procedure. */ + +/* sync states */ +#define SYNC_START 0 /* no sync handshake started */ +#define SYNC_SENT 1 /* we sent sync request, no answer yet */ +#define SYNC_DONE 2 /* target accepted our (or inferior) settings, + or it rejected the request and we stay async */ + +#define MSG_CMD_COMPLETE 0x00 +#define MSG_EXT_MESSAGE 0x01 +#define MSG_SAVE_DATA_PTR 0x02 +#define MSG_RESTORE_PTR 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_INIT_DETECT_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT 0x07 +#define MSG_NOOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define MSG_BUS_DEVICE_RESET 0x0C +#define MSG_IDENTIFY 0x80 +#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */ +#define MSG_SYNC_REQ 0x01 + +#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */ +#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */ +#define STS_BUSY 0x08 +#define STS_INTERMED 0x10 /* Intermediate status sent */ +#define STS_EXT 0x80 /* Extended status valid */ + +void ssh_minphys __P((struct buf *bp)); +int ssh_scsicmd __P((struct scsi_xfer *)); + +#endif /* _SSHVAR_H */ diff --git a/sys/arch/mvme88k/dev/vsvar.h b/sys/arch/mvme88k/dev/vsvar.h index 56440eb28c3..367719b7295 100644 --- a/sys/arch/mvme88k/dev/vsvar.h +++ b/sys/arch/mvme88k/dev/vsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vsvar.h,v 1.2 2001/02/01 03:38:16 smurph Exp $ */ +/* $OpenBSD: vsvar.h,v 1.3 2001/03/07 01:57:56 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * Copyright (c) 1990 The Regents of the University of California. @@ -124,8 +124,8 @@ struct vs_softc { u_long sc_chnl; /* channel 0 or 1 for dual bus cards */ u_long sc_qhp; /* Command queue head pointer */ struct vsreg *sc_vsreg; -#define SIOP_NACB 8 - struct vs_tinfo sc_tinfo[8]; +#define SSH_NACB 8 + struct vs_tinfo sc_tinfo[SSH_NACB]; u_char sc_flags; u_char sc_sien; u_char sc_dien; -- cgit v1.2.3