[BACK]Return to ssh.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme68k / dev

Annotation of sys/arch/mvme68k/dev/ssh.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ssh.c,v 1.16 2007/05/29 13:56:13 pyr Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1994 Michael L. Hitch
        !             5:  * Copyright (c) 1990 The Regents of the University of California.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to Berkeley by
        !             9:  * Van Jacobson of Lawrence Berkeley Laboratory.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  *     @(#)ssh.c       7.5 (Berkeley) 5/4/91
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * 53C710 scsi adaptor driver
        !            40:  */
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/device.h>
        !            45: #include <sys/disklabel.h>
        !            46: #include <sys/dkstat.h>
        !            47: #include <sys/buf.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/queue.h>
        !            50:
        !            51: #include <scsi/scsi_all.h>
        !            52: #include <scsi/scsiconf.h>
        !            53:
        !            54: #include <machine/autoconf.h>
        !            55: #include <machine/cpu.h>
        !            56:
        !            57: #include <mvme68k/dev/sshreg.h>
        !            58: #include <mvme68k/dev/sshvar.h>
        !            59:
        !            60: /*
        !            61:  * SCSI delays
        !            62:  * In u-seconds, primarily for state changes on the SPC.
        !            63:  */
        !            64: #define        SCSI_CMD_WAIT   500000  /* wait per step of 'immediate' cmds */
        !            65: #define        SCSI_DATA_WAIT  500000  /* wait per data in/out step */
        !            66: #define        SCSI_INIT_WAIT  500000  /* wait per step (both) during init */
        !            67:
        !            68: void ssh_select(struct ssh_softc *);
        !            69: void sshabort(struct ssh_softc *, ssh_regmap_p, char *);
        !            70: void ssherror(struct ssh_softc *, ssh_regmap_p, u_char);
        !            71: void sshstart(struct ssh_softc *);
        !            72: void sshreset(struct ssh_softc *);
        !            73: void sshsetdelay(int);
        !            74: void ssh_scsidone(struct ssh_acb *, int);
        !            75: void ssh_sched(struct ssh_softc *);
        !            76: int  ssh_poll(struct ssh_softc *, struct ssh_acb *);
        !            77: void sshintr(struct ssh_softc *);
        !            78: void sshinitialize(struct ssh_softc *);
        !            79: void ssh_start(struct ssh_softc *, int, int, u_char *, int, u_char *, int);
        !            80: int  ssh_checkintr(struct ssh_softc *, u_char, u_char, u_char, int *);
        !            81: void scsi_period_to_ssh(struct ssh_softc *, int);
        !            82:
        !            83: /* 53C710 script */
        !            84: const
        !            85: #include <mvme68k/dev/ssh_script.out>
        !            86:
        !            87: /* default to not inhibit sync negotiation on any drive */
        !            88: u_char ssh_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0};   /* initialize, so patchable */
        !            89: u_char ssh_allow_disc[8] = { 3, 3, 3, 3, 3, 3, 3, 3};
        !            90: int ssh_no_dma = 0;
        !            91:
        !            92: int ssh_reset_delay = 250;     /* delay after reset, in milleseconds */
        !            93:
        !            94: int ssh_cmd_wait = SCSI_CMD_WAIT;
        !            95: int ssh_data_wait = SCSI_DATA_WAIT;
        !            96: int ssh_init_wait = SCSI_INIT_WAIT;
        !            97:
        !            98: #ifdef DEBUG
        !            99: /*
        !           100:  *     0x01 - full debug
        !           101:  *     0x02 - DMA chaining
        !           102:  *     0x04 - sshintr
        !           103:  *     0x08 - phase mismatch
        !           104:  *     0x10 - <not used>
        !           105:  *     0x20 - panic on unhandled exceptions
        !           106:  *     0x100 - disconnect/reselect
        !           107:  */
        !           108: int   ssh_debug = 0;
        !           109: int   sshsync_debug = 0;
        !           110: int   sshdma_hits = 0;
        !           111: int   sshdma_misses = 0;
        !           112: int   sshchain_ints = 0;
        !           113: int   sshstarts = 0;
        !           114: int   sshints = 0;
        !           115: int   sshphmm = 0;
        !           116: #define SSH_TRACE_SIZE 128
        !           117: #define SSH_TRACE(a,b,c,d) \
        !           118:        ssh_trbuf[ssh_trix] = (a); \
        !           119:        ssh_trbuf[ssh_trix+1] = (b); \
        !           120:        ssh_trbuf[ssh_trix+2] = (c); \
        !           121:        ssh_trbuf[ssh_trix+3] = (d); \
        !           122:        ssh_trix = (ssh_trix + 4) & (SSH_TRACE_SIZE - 1);
        !           123: u_char   ssh_trbuf[SSH_TRACE_SIZE];
        !           124: int   ssh_trix;
        !           125: #else
        !           126: #define SSH_TRACE(a,b,c,d)
        !           127: #endif
        !           128:
        !           129:
        !           130: /*
        !           131:  * default minphys routine for ssh based controllers
        !           132:  */
        !           133: void
        !           134: ssh_minphys(bp)
        !           135: struct buf *bp;
        !           136: {
        !           137:
        !           138:        /*
        !           139:         * No max transfer at this level.
        !           140:         */
        !           141:        minphys(bp);
        !           142: }
        !           143:
        !           144: /*
        !           145:  * used by specific ssh controller
        !           146:  *
        !           147:  */
        !           148: int
        !           149: ssh_scsicmd(xs)
        !           150: struct scsi_xfer *xs;
        !           151: {
        !           152:        struct ssh_acb *acb;
        !           153:        struct ssh_softc *sc;
        !           154:        struct scsi_link *slp;
        !           155:        int flags, s;
        !           156:
        !           157:        slp = xs->sc_link;
        !           158:        sc = slp->adapter_softc;
        !           159:        flags = xs->flags;
        !           160:
        !           161:        /* XXXX ?? */
        !           162:        if (flags & SCSI_DATA_UIO)
        !           163:                panic("ssh: scsi data uio requested");
        !           164:
        !           165:        /* XXXX ?? */
        !           166:        if (sc->sc_nexus && flags & SCSI_POLL)
        !           167:                panic("ssh_scsicmd: busy");
        !           168:
        !           169:        s = splbio();
        !           170:        acb = TAILQ_FIRST(&sc->free_list);
        !           171:        if (acb) {
        !           172:                TAILQ_REMOVE(&sc->free_list, acb, chain);
        !           173:        }
        !           174:        splx(s);
        !           175:
        !           176:        if (acb == NULL) {
        !           177:                return (TRY_AGAIN_LATER);
        !           178:        }
        !           179:
        !           180:        acb->flags = ACB_ACTIVE;
        !           181:        acb->xs = xs;
        !           182:        bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
        !           183:        acb->clen = xs->cmdlen;
        !           184:        acb->daddr = xs->data;
        !           185:        acb->dleft = xs->datalen;
        !           186:
        !           187:        s = splbio();
        !           188:        TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
        !           189:
        !           190:        if (sc->sc_nexus == NULL)
        !           191:                ssh_sched(sc);
        !           192:
        !           193:        splx(s);
        !           194:
        !           195:        if (flags & SCSI_POLL || ssh_no_dma)
        !           196:                return (ssh_poll(sc, acb));
        !           197:        return (SUCCESSFULLY_QUEUED);
        !           198: }
        !           199:
        !           200: int
        !           201: ssh_poll(sc, acb)
        !           202: struct ssh_softc *sc;
        !           203: struct ssh_acb *acb;
        !           204: {
        !           205:        ssh_regmap_p rp = sc->sc_sshp;
        !           206:        struct scsi_xfer *xs = acb->xs;
        !           207:        int i;
        !           208:        int status;
        !           209:        u_char istat;
        !           210:        u_char dstat;
        !           211:        u_char sstat0;
        !           212:        int s;
        !           213:        int to;
        !           214:
        !           215:        s = splbio();
        !           216:        to = xs->timeout / 1000;
        !           217:        if (!TAILQ_EMPTY(&sc->nexus_list))
        !           218:                printf("%s: ssh_poll called with disconnected device\n",
        !           219:                                 sc->sc_dev.dv_xname);
        !           220:        for (;;) {
        !           221:                /* use cmd_wait values? */
        !           222:                i = 50000;
        !           223:                while (((istat = rp->ssh_istat) &
        !           224:                                  (SSH_ISTAT_SIP | SSH_ISTAT_DIP)) == 0) {
        !           225:                        if (--i <= 0) {
        !           226: #ifdef DEBUG
        !           227:                                printf ("waiting: tgt %d cmd %02x sbcl %02x dsp %x (+%x) dcmd %x ds %x timeout %d\n",
        !           228:                                                  xs->sc_link->target, acb->cmd.opcode,
        !           229:                                                  rp->ssh_sbcl, rp->ssh_dsp,
        !           230:                                                  rp->ssh_dsp - sc->sc_scriptspa,
        !           231:                                                  *((long *)&rp->ssh_dcmd), &acb->ds, acb->xs->timeout);
        !           232: #endif
        !           233:                                i = 50000;
        !           234:                                --to;
        !           235:                                if (to <= 0) {
        !           236:                                        sshreset(sc);
        !           237:                                        return (COMPLETE);
        !           238:                                }
        !           239:                        }
        !           240:                        delay(10);
        !           241:                }
        !           242:                sstat0 = rp->ssh_sstat0;
        !           243:                dstat = rp->ssh_dstat;
        !           244:                if (ssh_checkintr(sc, istat, dstat, sstat0, &status)) {
        !           245:                        if (acb != sc->sc_nexus)
        !           246:                                printf("%s: ssh_poll disconnected device completed\n",
        !           247:                                                 sc->sc_dev.dv_xname);
        !           248:                        else if ((sc->sc_flags & SSH_INTDEFER) == 0) {
        !           249:                                sc->sc_flags &= ~SSH_INTSOFF;
        !           250:                                rp->ssh_sien = sc->sc_sien;
        !           251:                                rp->ssh_dien = sc->sc_dien;
        !           252:                        }
        !           253:                        ssh_scsidone(sc->sc_nexus, status);
        !           254:                }
        !           255:                if (xs->flags & ITSDONE)
        !           256:                        break;
        !           257:        }
        !           258:        splx(s);
        !           259:        return (COMPLETE);
        !           260: }
        !           261:
        !           262: /*
        !           263:  * start next command that's ready
        !           264:  */
        !           265: void
        !           266: ssh_sched(sc)
        !           267: struct ssh_softc *sc;
        !           268: {
        !           269:        struct scsi_link *slp;
        !           270:        struct ssh_acb *acb;
        !           271:        int i;
        !           272:
        !           273: #ifdef DEBUG
        !           274:        if (sc->sc_nexus) {
        !           275:                printf("%s: ssh_sched- nexus %x/%d ready %x/%d\n",
        !           276:                                 sc->sc_dev.dv_xname, sc->sc_nexus,
        !           277:                                 sc->sc_nexus->xs->sc_link->target,
        !           278:                                 TAILQ_FIRST(&sc->ready_list),
        !           279:                                 TAILQ_FIRST(&sc->ready_list)->xs->sc_link->target);
        !           280:                return;
        !           281:        }
        !           282: #endif
        !           283:        TAILQ_FOREACH(acb, &sc->ready_list, chain) {
        !           284:                slp = acb->xs->sc_link;
        !           285:                i = slp->target;
        !           286:                if (!(sc->sc_tinfo[i].lubusy & (1 << slp->lun))) {
        !           287:                        struct ssh_tinfo *ti = &sc->sc_tinfo[i];
        !           288:
        !           289:                        TAILQ_REMOVE(&sc->ready_list, acb, chain);
        !           290:                        sc->sc_nexus = acb;
        !           291:                        slp = acb->xs->sc_link;
        !           292:                        ti = &sc->sc_tinfo[slp->target];
        !           293:                        ti->lubusy |= (1 << slp->lun);
        !           294:                        break;
        !           295:                }
        !           296:        }
        !           297:
        !           298:        if (acb == NULL) {
        !           299: #ifdef DEBUGXXX
        !           300:                printf("%s: ssh_sched didn't find ready command\n",
        !           301:                                 sc->sc_dev.dv_xname);
        !           302: #endif
        !           303:                return;
        !           304:        }
        !           305:
        !           306:        if (acb->xs->flags & SCSI_RESET)
        !           307:                sshreset(sc);
        !           308:
        !           309: #if 0
        !           310:        acb->cmd.bytes[0] |= slp->lun << 5;     /* XXXX */
        !           311: #endif
        !           312:        ++sc->sc_active;
        !           313:        ssh_select(sc);
        !           314: }
        !           315:
        !           316: void
        !           317: ssh_scsidone(acb, stat)
        !           318:        struct ssh_acb *acb;
        !           319:        int stat;
        !           320: {
        !           321:        struct scsi_xfer *xs;
        !           322:        struct scsi_link *slp;
        !           323:        struct ssh_softc *sc;
        !           324:        int dosched = 0;
        !           325:
        !           326:        if (acb == NULL || (xs = acb->xs) == NULL) {
        !           327: #ifdef DIAGNOSTIC
        !           328:                printf("ssh_scsidone: NULL acb or scsi_xfer\n");
        !           329: #if defined(DEBUG) && defined(DDB)
        !           330:                Debugger();
        !           331: #endif
        !           332: #endif
        !           333:                return;
        !           334:        }
        !           335:        slp = xs->sc_link;
        !           336:        sc = slp->adapter_softc;
        !           337:
        !           338:        /*
        !           339:         * is this right?
        !           340:         */
        !           341:        xs->status = stat;
        !           342:
        !           343:        if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) {
        !           344:                if (stat == SCSI_CHECK) {
        !           345:                        struct scsi_sense *ss = (void *)&acb->cmd;
        !           346:                        bzero(ss, sizeof(*ss));
        !           347:                        ss->opcode = REQUEST_SENSE;
        !           348:                        ss->byte2 = slp->lun << 5;
        !           349:                        ss->length = sizeof(struct scsi_sense_data);
        !           350:                        acb->clen = sizeof(*ss);
        !           351:                        acb->daddr = (char *)&xs->sense;
        !           352:                        acb->dleft = sizeof(struct scsi_sense_data);
        !           353:                        acb->flags = ACB_ACTIVE | ACB_CHKSENSE;
        !           354:                        TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
        !           355:                        --sc->sc_active;
        !           356:                        sc->sc_tinfo[slp->target].lubusy &=
        !           357:                        ~(1 << slp->lun);
        !           358:                        sc->sc_tinfo[slp->target].senses++;
        !           359:                        if (sc->sc_nexus == acb) {
        !           360:                                sc->sc_nexus = NULL;
        !           361:                                ssh_sched(sc);
        !           362:                        }
        !           363:                        SSH_TRACE('d','s',0,0)
        !           364:                        return;
        !           365:                }
        !           366:        }
        !           367:        if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) {
        !           368:                xs->error = XS_SENSE;
        !           369:        } else {
        !           370:                xs->resid = 0;          /* XXXX */
        !           371:        }
        !           372:
        !           373: #if whataboutthisone
        !           374:                case SCSI_BUSY:
        !           375:                        xs->error = XS_BUSY;
        !           376:                        break;
        !           377: #endif
        !           378:
        !           379:        xs->flags |= ITSDONE;
        !           380:
        !           381:        /*
        !           382:         * Remove the ACB from whatever queue it's on.  We have to do a bit of
        !           383:         * a hack to figure out which queue it's on.  Note that it is *not*
        !           384:         * necessary to cdr down the ready queue, but we must cdr down the
        !           385:         * nexus queue and see if it's there, so we can mark the unit as no
        !           386:         * longer busy.  This code is sickening, but it works.
        !           387:         */
        !           388:        if (acb == sc->sc_nexus) {
        !           389:                sc->sc_nexus = NULL;
        !           390:                sc->sc_tinfo[slp->target].lubusy &= ~(1<<slp->lun);
        !           391:                if (!TAILQ_EMPTY(&sc->ready_list))
        !           392:                        dosched = 1;    /* start next command */
        !           393:                --sc->sc_active;
        !           394:                SSH_TRACE('d','a',stat,0)
        !           395:        } else if (TAILQ_LAST(&sc->ready_list, acb_list) ==
        !           396:            TAILQ_NEXT(acb, chain)) {
        !           397:                TAILQ_REMOVE(&sc->ready_list, acb, chain);
        !           398:                SSH_TRACE('d','r',stat,0)
        !           399:        } else {
        !           400:                register struct ssh_acb *acb2;
        !           401:                TAILQ_FOREACH(acb2, &sc->nexus_list, chain)
        !           402:                        if (acb2 == acb) {
        !           403:                                TAILQ_REMOVE(&sc->nexus_list, acb, chain);
        !           404:                                sc->sc_tinfo[slp->target].lubusy
        !           405:                                &= ~(1<<slp->lun);
        !           406:                                --sc->sc_active;
        !           407:                                break;
        !           408:                        }
        !           409:                if (acb2)
        !           410:                        ;
        !           411:                else if (TAILQ_NEXT(acb, chain) != NULL) {
        !           412:                        TAILQ_REMOVE(&sc->ready_list, acb, chain);
        !           413:                        --sc->sc_active;
        !           414:                } else {
        !           415:                        printf("%s: can't find matching acb\n",
        !           416:                                         sc->sc_dev.dv_xname);
        !           417: #ifdef DDB
        !           418: /*                     Debugger(); */
        !           419: #endif
        !           420:                }
        !           421:                SSH_TRACE('d','n',stat,0);
        !           422:        }
        !           423:        /* Put it on the free list. */
        !           424:        acb->flags = ACB_FREE;
        !           425:        TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
        !           426:
        !           427:        sc->sc_tinfo[slp->target].cmds++;
        !           428:
        !           429:        scsi_done(xs);
        !           430:
        !           431:        if (dosched && sc->sc_nexus == NULL)
        !           432:                ssh_sched(sc);
        !           433: }
        !           434:
        !           435: void
        !           436: sshabort(sc, rp, where)
        !           437: register struct ssh_softc *sc;
        !           438: ssh_regmap_p rp;
        !           439: char *where;
        !           440: {
        !           441: #ifdef fix_this
        !           442:        int i;
        !           443: #endif
        !           444:
        !           445:        printf ("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
        !           446:                          sc->sc_dev.dv_xname,
        !           447:                          where, rp->ssh_dstat, rp->ssh_sstat0, rp->ssh_sbcl);
        !           448:
        !           449:        if (sc->sc_active > 0) {
        !           450: #ifdef TODO
        !           451:                SET_SBIC_cmd (rp, SBIC_CMD_ABORT);
        !           452:                WAIT_CIP (rp);
        !           453:
        !           454:                GET_SBIC_asr (rp, asr);
        !           455:                if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) {
        !           456:                        /* ok, get more drastic.. */
        !           457:
        !           458:                        SET_SBIC_cmd (rp, SBIC_CMD_RESET);
        !           459:                        delay(25);
        !           460:                        SBIC_WAIT(rp, SBIC_ASR_INT, 0);
        !           461:                        GET_SBIC_csr (rp, csr);                 /* clears interrupt also */
        !           462:
        !           463:                        return;
        !           464:                }
        !           465:
        !           466:                do {
        !           467:                        SBIC_WAIT (rp, SBIC_ASR_INT, 0);
        !           468:                        GET_SBIC_csr (rp, csr);
        !           469:                }
        !           470:                while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
        !           471:                                 && (csr != SBIC_CSR_CMD_INVALID));
        !           472: #endif
        !           473:
        !           474:                /* lets just hope it worked.. */
        !           475: #ifdef fix_this
        !           476:                for (i = 0; i < 2; ++i) {
        !           477:                        if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] !=
        !           478:                                 sc->sc_cur) {
        !           479:                                printf ("sshabort: cleanup!\n");
        !           480:                                sc->sc_iob[i].sc_xs = NULL;
        !           481:                        }
        !           482:                }
        !           483: #endif /* fix_this */
        !           484: /*             sc->sc_active = 0; */
        !           485:        }
        !           486: }
        !           487:
        !           488: void
        !           489: sshinitialize(sc)
        !           490:        struct ssh_softc *sc;
        !           491: {
        !           492:        /*
        !           493:         * Need to check that scripts is on a long word boundary
        !           494:         * Also should verify that dev doesn't span non-contiguous
        !           495:         * physical pages.
        !           496:         */
        !           497:        sc->sc_scriptspa = kvtop((vaddr_t)scripts);
        !           498:
        !           499:        /*
        !           500:         * malloc sc_acb to ensure that DS is on a long word boundary.
        !           501:         */
        !           502:
        !           503:        MALLOC(sc->sc_acb, struct ssh_acb *,
        !           504:                         sizeof(struct ssh_acb) * SSH_NACB, M_DEVBUF, M_NOWAIT);
        !           505:        if (sc->sc_acb == NULL)
        !           506:                panic("sshinitialize: ACB malloc failed!");
        !           507:
        !           508:        sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
        !           509:        sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
        !           510:        sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
        !           511:        sc->sc_minsync = sc->sc_tcp[1];         /* in 4ns units */
        !           512:        if (sc->sc_minsync < 25)
        !           513:                sc->sc_minsync = 25;
        !           514: #if not_used
        !           515:        if (sc->sc_clock_freq <= 25)
        !           516:                sc->sc_tcp[0] = sc->sc_tcp[1];
        !           517:        else if (sc->sc_clock_freq <= 37)
        !           518:                sc->sc_tcp[0] = sc->sc_tcp[2];
        !           519:        else if (sc->sc_clock_freq <= 50)
        !           520:                sc->sc_tcp[0] = sc->sc_tcp[3];
        !           521:        else
        !           522:                sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
        !           523: #endif
        !           524:
        !           525:        sshreset (sc);
        !           526: }
        !           527:
        !           528: void
        !           529: sshreset(sc)
        !           530: struct ssh_softc *sc;
        !           531: {
        !           532:        ssh_regmap_p rp;
        !           533:        u_int i, s;
        !           534:        u_char  dummy;
        !           535:        struct ssh_acb *acb;
        !           536:
        !           537:        rp = sc->sc_sshp;
        !           538:
        !           539:        if (sc->sc_flags & SSH_ALIVE)
        !           540:                sshabort(sc, rp, "reset");
        !           541:
        !           542:        s = splbio();
        !           543:
        !           544:        /*
        !           545:         * Reset the chip
        !           546:         * XXX - is this really needed?
        !           547:         */
        !           548:        rp->ssh_istat |= SSH_ISTAT_ABRT;        /* abort current script */
        !           549:        rp->ssh_istat |= SSH_ISTAT_RST;         /* reset chip */
        !           550:        rp->ssh_istat &= ~SSH_ISTAT_RST;
        !           551:        /*
        !           552:         * Reset SCSI bus (do we really want this?)
        !           553:         */
        !           554:        rp->ssh_sien = 0;
        !           555:        rp->ssh_scntl1 |= SSH_SCNTL1_RST;
        !           556:        delay(1);
        !           557:        rp->ssh_scntl1 &= ~SSH_SCNTL1_RST;
        !           558:
        !           559:        /*
        !           560:         * Set up various chip parameters
        !           561:         */
        !           562:        rp->ssh_scntl0 = SSH_ARB_FULL | SSH_SCNTL0_EPC | SSH_SCNTL0_EPG;
        !           563:        rp->ssh_scntl1 = SSH_SCNTL1_ESR;
        !           564:        rp->ssh_dcntl = sc->sc_dcntl;
        !           565:        rp->ssh_dmode = 0x80;   /* burst length = 4 */
        !           566:        rp->ssh_sien = 0x00;    /* don't enable interrupts yet */
        !           567:        rp->ssh_dien = 0x00;    /* don't enable interrupts yet */
        !           568:        rp->ssh_scid = 1 << sc->sc_link.adapter_target;
        !           569:        rp->ssh_dwt = 0x00;
        !           570:        rp->ssh_ctest0 |= SSH_CTEST0_BTD | SSH_CTEST0_EAN;
        !           571:        rp->ssh_ctest7 = sc->sc_ctest7;
        !           572:
        !           573:        /* will need to re-negotiate sync xfers */
        !           574:        bzero(&sc->sc_sync, sizeof (sc->sc_sync));
        !           575:
        !           576:        i = rp->ssh_istat;
        !           577:        if (i & SSH_ISTAT_SIP)
        !           578:                dummy = rp->ssh_sstat0;
        !           579:        if (i & SSH_ISTAT_DIP)
        !           580:                dummy = rp->ssh_dstat;
        !           581:
        !           582:        splx(s);
        !           583:
        !           584:        delay(ssh_reset_delay * 1000);
        !           585:        printf(": version %d target %d\n", rp->ssh_ctest8 >> 4,
        !           586:                         sc->sc_link.adapter_target);
        !           587:
        !           588:        if ((sc->sc_flags & SSH_ALIVE) == 0) {
        !           589:                TAILQ_INIT(&sc->ready_list);
        !           590:                TAILQ_INIT(&sc->nexus_list);
        !           591:                TAILQ_INIT(&sc->free_list);
        !           592:                sc->sc_nexus = NULL;
        !           593:                acb = sc->sc_acb;
        !           594:                bzero(acb, sizeof(struct ssh_acb) * SSH_NACB);
        !           595:                for (i = 0; i < SSH_NACB; i++) {
        !           596:                        TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
        !           597:                        acb++;
        !           598:                }
        !           599:                bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
        !           600:        } else {
        !           601:                if (sc->sc_nexus != NULL) {
        !           602:                        sc->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
        !           603:                        ssh_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]);
        !           604:                }
        !           605:                while ((acb = TAILQ_FIRST(&sc->nexus_list))) {
        !           606:                        acb->xs->error = XS_DRIVER_STUFFUP;
        !           607:                        ssh_scsidone(acb, acb->stat[0]);
        !           608:                }
        !           609:        }
        !           610:
        !           611:        sc->sc_flags |= SSH_ALIVE;
        !           612:        sc->sc_flags &= ~(SSH_INTDEFER|SSH_INTSOFF);
        !           613:        /* enable SCSI and DMA interrupts */
        !           614:        sc->sc_sien = SSH_SIEN_M_A | SSH_SIEN_STO | /*SSH_SIEN_SEL |*/ SSH_SIEN_SGE |
        !           615:                                          SSH_SIEN_UDC | SSH_SIEN_RST | SSH_SIEN_PAR;
        !           616:        sc->sc_dien = SSH_DIEN_BF | SSH_DIEN_ABRT | SSH_DIEN_SIR |
        !           617:                                          /*SSH_DIEN_WTD |*/ SSH_DIEN_IID;
        !           618:        rp->ssh_sien = sc->sc_sien;
        !           619:        rp->ssh_dien = sc->sc_dien;
        !           620: }
        !           621:
        !           622: /*
        !           623:  * Setup Data Storage for 53C710 and start SCRIPTS processing
        !           624:  */
        !           625:
        !           626: void
        !           627: ssh_start (sc, target, lun, cbuf, clen, buf, len)
        !           628:        struct ssh_softc *sc;
        !           629:        int target;
        !           630:        int lun;
        !           631:        u_char *cbuf;
        !           632:        int clen;
        !           633:        u_char *buf;
        !           634:        int len;
        !           635: {
        !           636:        ssh_regmap_p rp = sc->sc_sshp;
        !           637: #ifdef DEBUG
        !           638:        int i;
        !           639: #endif
        !           640:        int nchain;
        !           641:        int count, tcount;
        !           642:        char *addr, *dmaend;
        !           643:        struct ssh_acb *acb = sc->sc_nexus;
        !           644:
        !           645: #ifdef DEBUG
        !           646:        if (ssh_debug & 0x100 && rp->ssh_sbcl & SSH_BSY) {
        !           647:                printf ("ACK! ssh was busy: rp %x script %x dsa %x active %d\n",
        !           648:                                  rp, &scripts, &acb->ds, sc->sc_active);
        !           649:                printf ("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n",
        !           650:                                  rp->ssh_istat, rp->ssh_sfbr, rp->ssh_lcrc,
        !           651:                                  rp->ssh_sien, rp->ssh_dien);
        !           652: #ifdef DDB
        !           653:                /*Debugger();*/
        !           654: #endif
        !           655:        }
        !           656: #endif
        !           657:        acb->msgout[0] = MSG_IDENTIFY | lun;
        !           658:        if (ssh_allow_disc[target] & 2 ||
        !           659:                 (ssh_allow_disc[target] && len == 0))
        !           660:                acb->msgout[0] = MSG_IDENTIFY_DR | lun;
        !           661:        acb->status = 0;
        !           662:        acb->stat[0] = -1;
        !           663:        acb->msg[0] = -1;
        !           664:        acb->ds.scsi_addr = (0x10000 << target) | (sc->sc_sync[target].sxfer << 8);
        !           665:        acb->ds.idlen = 1;
        !           666:        acb->ds.idbuf = (char *) kvtop((vaddr_t)&acb->msgout[0]);
        !           667:        acb->ds.cmdlen = clen;
        !           668:        acb->ds.cmdbuf = (char *) kvtop((vaddr_t)cbuf);
        !           669:        acb->ds.stslen = 1;
        !           670:        acb->ds.stsbuf = (char *) kvtop((vaddr_t)&acb->stat[0]);
        !           671:        acb->ds.msglen = 1;
        !           672:        acb->ds.msgbuf = (char *) kvtop((vaddr_t)&acb->msg[0]);
        !           673:        acb->msg[1] = -1;
        !           674:        acb->ds.msginlen = 1;
        !           675:        acb->ds.extmsglen = 1;
        !           676:        acb->ds.synmsglen = 3;
        !           677:        acb->ds.msginbuf = (char *) kvtop((vaddr_t)&acb->msg[1]);
        !           678:        acb->ds.extmsgbuf = (char *) kvtop((vaddr_t)&acb->msg[2]);
        !           679:        acb->ds.synmsgbuf = (char *) kvtop((vaddr_t)&acb->msg[3]);
        !           680:        bzero(&acb->ds.chain, sizeof (acb->ds.chain));
        !           681:
        !           682:        if (sc->sc_sync[target].state == SYNC_START) {
        !           683:                if (ssh_inhibit_sync[target]) {
        !           684:                        sc->sc_sync[target].state = SYNC_DONE;
        !           685:                        sc->sc_sync[target].sbcl = 0;
        !           686:                        sc->sc_sync[target].sxfer = 0;
        !           687: #ifdef DEBUG
        !           688:                        if (sshsync_debug)
        !           689:                                printf ("Forcing target %d asynchronous\n", target);
        !           690: #endif
        !           691:                } else {
        !           692:                        acb->msg[2] = -1;
        !           693:                        acb->msgout[1] = MSG_EXT_MESSAGE;
        !           694:                        acb->msgout[2] = 3;
        !           695:                        acb->msgout[3] = MSG_SYNC_REQ;
        !           696: #ifdef MAXTOR_SYNC_KLUDGE
        !           697:                        acb->msgout[4] = 50 / 4;        /* ask for ridiculous period */
        !           698: #else
        !           699:                        acb->msgout[4] = sc->sc_minsync;
        !           700: #endif
        !           701:                        acb->msgout[5] = SSH_MAX_OFFSET;
        !           702:                        acb->ds.idlen = 6;
        !           703:                        sc->sc_sync[target].state = SYNC_SENT;
        !           704: #ifdef DEBUG
        !           705:                        if (sshsync_debug)
        !           706:                                printf ("Sending sync request to target %d\n", target);
        !           707: #endif
        !           708:                }
        !           709:        }
        !           710:
        !           711: /*
        !           712:  * Build physical DMA addresses for scatter/gather I/O
        !           713:  */
        !           714:        acb->iob_buf = buf;
        !           715:        acb->iob_len = len;
        !           716:        acb->iob_curbuf = acb->iob_curlen = 0;
        !           717:        nchain = 0;
        !           718:        count = len;
        !           719:        addr = buf;
        !           720:        dmaend = NULL;
        !           721:        while (count > 0) {
        !           722:                acb->ds.chain[nchain].databuf = (char *) kvtop ((vaddr_t)addr);
        !           723:                if (count < (tcount = NBPG - ((int) addr & PGOFSET)))
        !           724:                        tcount = count;
        !           725:                acb->ds.chain[nchain].datalen = tcount;
        !           726:                addr += tcount;
        !           727:                count -= tcount;
        !           728:                if (acb->ds.chain[nchain].databuf == dmaend) {
        !           729:                        dmaend += acb->ds.chain[nchain].datalen;
        !           730:                        acb->ds.chain[nchain].datalen = 0;
        !           731:                        acb->ds.chain[--nchain].datalen += tcount;
        !           732: #ifdef DEBUG
        !           733:                        ++sshdma_hits;
        !           734: #endif
        !           735:                } else {
        !           736:                        dmaend = acb->ds.chain[nchain].databuf +
        !           737:                                                acb->ds.chain[nchain].datalen;
        !           738:                        acb->ds.chain[nchain].datalen = tcount;
        !           739: #ifdef DEBUG
        !           740:                        if (nchain)     /* Don't count miss on first one */
        !           741:                                ++sshdma_misses;
        !           742: #endif
        !           743:                }
        !           744:                ++nchain;
        !           745:        }
        !           746: #ifdef DEBUG
        !           747:        if (nchain != 1 && len != 0 && ssh_debug & 3) {
        !           748:                printf ("DMA chaining set: %d\n", nchain);
        !           749:                for (i = 0; i < nchain; ++i) {
        !           750:                        printf ("  [%d] %8x %4x\n", i, acb->ds.chain[i].databuf,
        !           751:                                          acb->ds.chain[i].datalen);
        !           752:                }
        !           753:        }
        !           754: #endif
        !           755:
        !           756:        /* push data cache for all data the 53c710 needs to access */
        !           757:        dma_cachectl((caddr_t)acb, sizeof (struct ssh_acb));
        !           758:        dma_cachectl(cbuf, clen);
        !           759:        if (buf != NULL && len != 0)
        !           760:                dma_cachectl(buf, len);
        !           761:
        !           762: #ifdef DEBUG
        !           763:        if (ssh_debug & 0x100 && rp->ssh_sbcl & SSH_BSY) {
        !           764:                printf ("ACK! ssh was busy at start: rp %x script %x dsa %x active %d\n",
        !           765:                                  rp, &scripts, &acb->ds, sc->sc_active);
        !           766: #ifdef DDB
        !           767:                /*Debugger();*/
        !           768: #endif
        !           769:        }
        !           770: #endif
        !           771:
        !           772:        if (TAILQ_EMPTY(&sc->nexus_list)) {
        !           773:                if (rp->ssh_istat & SSH_ISTAT_CON)
        !           774:                        printf("%s: ssh_select while connected?\n",
        !           775:                                         sc->sc_dev.dv_xname);
        !           776:                rp->ssh_temp = 0;
        !           777:                rp->ssh_sbcl = sc->sc_sync[target].sbcl;
        !           778:                rp->ssh_dsa = kvtop((vaddr_t)&acb->ds);
        !           779:                rp->ssh_dsp = sc->sc_scriptspa;
        !           780:                SSH_TRACE('s',1,0,0)
        !           781:        } else {
        !           782:                if ((rp->ssh_istat & SSH_ISTAT_CON) == 0) {
        !           783:                        rp->ssh_istat = SSH_ISTAT_SIGP;
        !           784:                        SSH_TRACE('s',2,0,0);
        !           785:                } else {
        !           786:                        SSH_TRACE('s',3,rp->ssh_istat,0);
        !           787:                }
        !           788:        }
        !           789: #ifdef DEBUG
        !           790:        ++sshstarts;
        !           791: #endif
        !           792: }
        !           793:
        !           794: /*
        !           795:  * Process a DMA or SCSI interrupt from the 53C710 SSH
        !           796:  */
        !           797:
        !           798: int
        !           799: ssh_checkintr(sc, istat, dstat, sstat0, status)
        !           800:        struct   ssh_softc *sc;
        !           801:        u_char   istat;
        !           802:        u_char   dstat;
        !           803:        u_char   sstat0;
        !           804:        int   *status;
        !           805: {
        !           806:        ssh_regmap_p rp = sc->sc_sshp;
        !           807:        struct ssh_acb *acb = sc->sc_nexus;
        !           808:        int   target;
        !           809:        int   dfifo, dbc, sstat1;
        !           810:
        !           811:        dfifo = rp->ssh_dfifo;
        !           812:        dbc = rp->ssh_dbc0;
        !           813:        sstat1 = rp->ssh_sstat1;
        !           814:        rp->ssh_ctest8 |= SSH_CTEST8_CLF;
        !           815:        while ((rp->ssh_ctest1 & SSH_CTEST1_FMT) != SSH_CTEST1_FMT)
        !           816:                ;
        !           817:        rp->ssh_ctest8 &= ~SSH_CTEST8_CLF;
        !           818: #ifdef DEBUG
        !           819:        ++sshints;
        !           820: #if 0
        !           821:        if (ssh_debug & 0x100) {
        !           822:                dma_cachectl(&acb->stat[0], 1);
        !           823:                printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
        !           824:                                  istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_sbcl, acb->stat[0], acb->msg[0]);
        !           825:                printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
        !           826:                                  acb->msg[0], acb->msg[1], acb->msg[2],
        !           827:                                  acb->msg[3], acb->msg[4], acb->msg[5]);
        !           828:        }
        !           829: #endif
        !           830:        if (rp->ssh_dsp && (rp->ssh_dsp < sc->sc_scriptspa ||
        !           831:                                                                rp->ssh_dsp >= sc->sc_scriptspa + sizeof(scripts))) {
        !           832:                printf ("%s: dsp not within script dsp %x scripts %x:%x",
        !           833:                                  sc->sc_dev.dv_xname, rp->ssh_dsp, sc->sc_scriptspa,
        !           834:                                  sc->sc_scriptspa + sizeof(scripts));
        !           835:                printf(" istat %x dstat %x sstat0 %x\n",
        !           836:                                 istat, dstat, sstat0);
        !           837:                Debugger();
        !           838:        }
        !           839: #endif
        !           840:        SSH_TRACE('i',dstat,istat,(istat&SSH_ISTAT_DIP)?rp->ssh_dsps&0xff:sstat0);
        !           841:        if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff00) {
        !           842:                /* Normal completion status, or check condition */
        !           843: #ifdef DEBUG
        !           844:                if (rp->ssh_dsa != kvtop(&acb->ds)) {
        !           845:                        printf ("ssh: invalid dsa: %x %x\n", rp->ssh_dsa,
        !           846:                                          kvtop(&acb->ds));
        !           847:                        panic("*** ssh DSA invalid ***");
        !           848:                }
        !           849: #endif
        !           850:                target = acb->xs->sc_link->target;
        !           851:                if (sc->sc_sync[target].state == SYNC_SENT) {
        !           852: #ifdef DEBUG
        !           853:                        if (sshsync_debug)
        !           854:                                printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
        !           855:                                                  acb->msg[0], acb->msg[1], acb->msg[2],
        !           856:                                                  acb->msg[3], acb->msg[4], acb->msg[5]);
        !           857: #endif
        !           858:                        if (acb->msg[1] == 0xff)
        !           859:                                printf ("%s: target %d ignored sync request\n",
        !           860:                                                  sc->sc_dev.dv_xname, target);
        !           861:                        else if (acb->msg[1] == MSG_REJECT)
        !           862:                                printf ("%s: target %d rejected sync request\n",
        !           863:                                                  sc->sc_dev.dv_xname, target);
        !           864:                        sc->sc_sync[target].state = SYNC_DONE;
        !           865:                        sc->sc_sync[target].sxfer = 0;
        !           866:                        sc->sc_sync[target].sbcl = 0;
        !           867:                        if (acb->msg[2] == 3 &&
        !           868:                                 acb->msg[3] == MSG_SYNC_REQ &&
        !           869:                                 acb->msg[5] != 0) {
        !           870: #ifdef MAXTOR_KLUDGE
        !           871:                                /*
        !           872:                                 * Kludge for my Maxtor XT8580S
        !           873:                                 * It accepts whatever we request, even
        !           874:                                 * though it won't work.  So we ask for
        !           875:                                 * a short period than we can handle.  If
        !           876:                                 * the device says it can do it, use 208ns.
        !           877:                                 * If the device says it can do less than
        !           878:                                 * 100ns, then we limit it to 100ns.
        !           879:                                 */
        !           880:                                if (acb->msg[4] && acb->msg[4] < 100 / 4) {
        !           881: #ifdef DEBUG
        !           882:                                        printf ("%d: target %d wanted %dns period\n",
        !           883:                                                          sc->sc_dev.dv_xname, target,
        !           884:                                                          acb->msg[4] * 4);
        !           885: #endif
        !           886:                                        if (acb->msg[4] == 50 / 4)
        !           887:                                                acb->msg[4] = 208 / 4;
        !           888:                                        else
        !           889:                                                acb->msg[4]     = 100 / 4;
        !           890:                                }
        !           891: #endif /* MAXTOR_KLUDGE */
        !           892:                                printf ("%s: target %d now synchronous, period=%dns, offset=%d\n",
        !           893:                                                  sc->sc_dev.dv_xname, target,
        !           894:                                                  acb->msg[4] * 4, acb->msg[5]);
        !           895:                                scsi_period_to_ssh (sc, target);
        !           896:                        }
        !           897:                }
        !           898:                dma_cachectl(&acb->stat[0], 1);
        !           899:                *status = acb->stat[0];
        !           900: #ifdef DEBUG
        !           901:                if (rp->ssh_sbcl & SSH_BSY) {
        !           902:                        /*printf ("ACK! ssh was busy at end: rp %x script %x dsa %x\n",
        !           903:                                 rp, &scripts, &acb->ds);*/
        !           904: #ifdef DDB
        !           905:                        /*Debugger();*/
        !           906: #endif
        !           907:                }
        !           908:                if (acb->msg[0] != 0x00)
        !           909:                        printf("%s: message was not COMMAND COMPLETE: %x\n",
        !           910:                                         sc->sc_dev.dv_xname, acb->msg[0]);
        !           911: #endif
        !           912:                if (!TAILQ_EMPTY(&sc->nexus_list))
        !           913:                        rp->ssh_dcntl |= SSH_DCNTL_STD;
        !           914:                return 1;
        !           915:        }
        !           916:        if (sstat0 & SSH_SSTAT0_M_A) {          /* Phase mismatch */
        !           917: #ifdef DEBUG
        !           918:                ++sshphmm;
        !           919:                if (acb == NULL)
        !           920:                        printf("%s: Phase mismatch with no active command?\n",
        !           921:                                         sc->sc_dev.dv_xname);
        !           922: #endif
        !           923:                if (acb->iob_len) {
        !           924:                        int adjust;
        !           925:                        adjust = ((dfifo - (dbc & 0x7f)) & 0x7f);
        !           926:                        if (sstat1 & SSH_SSTAT1_ORF)
        !           927:                                ++adjust;
        !           928:                        if (sstat1 & SSH_SSTAT1_OLF)
        !           929:                                ++adjust;
        !           930:                        acb->iob_curlen = *((long *)&rp->ssh_dcmd) & 0xffffff;
        !           931:                        acb->iob_curlen += adjust;
        !           932:                        acb->iob_curbuf = *((long *)&rp->ssh_dnad) - adjust;
        !           933: #ifdef DEBUG
        !           934:                        if (ssh_debug & 0x100) {
        !           935:                                int i;
        !           936:                                printf ("Phase mismatch: curbuf %x curlen %x dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %x\n",
        !           937:                                                  acb->iob_curbuf, acb->iob_curlen, dfifo,
        !           938:                                                  dbc, sstat1, adjust, rp->ssh_sbcl, sshstarts, acb);
        !           939:                                if (acb->ds.chain[1].datalen) {
        !           940:                                        for (i = 0; acb->ds.chain[i].datalen; ++i)
        !           941:                                                printf("chain[%d] addr %x len %x\n",
        !           942:                                                                 i, acb->ds.chain[i].databuf,
        !           943:                                                                 acb->ds.chain[i].datalen);
        !           944:                                }
        !           945:                        }
        !           946: #endif
        !           947:                        dma_cachectl((caddr_t)acb, sizeof(*acb));
        !           948:                }
        !           949: #ifdef DEBUG
        !           950:                SSH_TRACE('m',rp->ssh_sbcl,(rp->ssh_dsp>>8),rp->ssh_dsp);
        !           951:                if (ssh_debug & 9)
        !           952:                        printf ("Phase mismatch: %x dsp +%x dcmd %x\n",
        !           953:                                          rp->ssh_sbcl,
        !           954:                                          rp->ssh_dsp - sc->sc_scriptspa,
        !           955:                                          *((long *)&rp->ssh_dcmd));
        !           956: #endif
        !           957:                if ((rp->ssh_sbcl & SSH_REQ) == 0) {
        !           958:                        printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n",
        !           959:                                          rp->ssh_sbcl, rp->ssh_dsp);
        !           960: #ifdef DEBUG
        !           961:                        Debugger();
        !           962: #endif
        !           963:                }
        !           964:                switch (rp->ssh_sbcl & 7) {
        !           965:                        case 0:         /* data out */
        !           966:                        case 1:         /* data in */
        !           967:                        case 2:         /* status */
        !           968:                        case 3:         /* command */
        !           969:                        case 6:         /* message in */
        !           970:                        case 7:         /* message out */
        !           971:                                rp->ssh_dsp = sc->sc_scriptspa + Ent_switch;
        !           972:                                break;
        !           973:                        default:
        !           974:                                goto bad_phase;
        !           975:                }
        !           976:                return 0;
        !           977:        }
        !           978:        if (sstat0 & SSH_SSTAT0_STO) {          /* Select timed out */
        !           979: #ifdef DEBUG
        !           980:                if (acb == NULL)
        !           981:                        printf("%s: Select timeout with no active command?\n",
        !           982:                                         sc->sc_dev.dv_xname);
        !           983:                if (rp->ssh_sbcl & SSH_BSY) {
        !           984:                        printf ("ACK! ssh was busy at timeout: rp %x script %x dsa %x\n",
        !           985:                                          rp, &scripts, &acb->ds);
        !           986:                        printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n",
        !           987:                                         rp->ssh_sbcl, rp->ssh_sdid, istat, dstat, sstat0);
        !           988:                        if (!(rp->ssh_sbcl & SSH_BSY)) {
        !           989:                                printf ("Yikes, it's not busy now!\n");
        !           990: #if 0
        !           991:                                *status = -1;
        !           992:                                if (!TAILQ_EMPTY(&sc->nexus_list))
        !           993:                                        rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;
        !           994:                                return 1;
        !           995: #endif
        !           996:                        }
        !           997: /*                     rp->ssh_dcntl |= SSH_DCNTL_STD;*/
        !           998:                        return (0);
        !           999: #ifdef DDB
        !          1000:                        Debugger();
        !          1001: #endif
        !          1002:                }
        !          1003: #endif
        !          1004:                *status = -1;
        !          1005:                acb->xs->error = XS_SELTIMEOUT;
        !          1006:                if (!TAILQ_EMPTY(&sc->nexus_list))
        !          1007:                        rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;
        !          1008:                return 1;
        !          1009:        }
        !          1010:        if (acb)
        !          1011:                target = acb->xs->sc_link->target;
        !          1012:        else
        !          1013:                target = 7;
        !          1014:        if (sstat0 & SSH_SSTAT0_UDC) {
        !          1015: #ifdef DEBUG
        !          1016:                if (acb == NULL)
        !          1017:                        printf("%s: Unexpected disconnect with no active command?\n",
        !          1018:                                         sc->sc_dev.dv_xname);
        !          1019:                printf ("%s: target %d disconnected unexpectedly\n",
        !          1020:                                  sc->sc_dev.dv_xname, target);
        !          1021: #endif
        !          1022: #if 0
        !          1023:                sshabort (sc, rp, "sshchkintr");
        !          1024: #endif
        !          1025:                *status = STS_BUSY;
        !          1026:                if (!TAILQ_EMPTY(&sc->nexus_list))
        !          1027:                        rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;
        !          1028:                return 1;
        !          1029:        }
        !          1030:        if (dstat & SSH_DSTAT_SIR && (rp->ssh_dsps == 0xff01 ||
        !          1031:                                                                                         rp->ssh_dsps == 0xff02)) {
        !          1032: #ifdef DEBUG
        !          1033:                if (ssh_debug & 0x100)
        !          1034:                        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",
        !          1035:                                          sc->sc_dev.dv_xname, 1 << target, rp->ssh_temp,
        !          1036:                                          rp->ssh_temp ? rp->ssh_temp - sc->sc_scriptspa : 0,
        !          1037:                                          acb->iob_curbuf, acb->iob_curlen,
        !          1038:                                          acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, sshstarts, acb);
        !          1039: #endif
        !          1040:                if (acb == NULL) {
        !          1041:                        printf("%s: Disconnect with no active command?\n",
        !          1042:                                         sc->sc_dev.dv_xname);
        !          1043:                        return (0);
        !          1044:                }
        !          1045:                /*
        !          1046:                 * XXXX need to update iob_curbuf/iob_curlen to reflect
        !          1047:                 * current data transferred.  If device disconnected in
        !          1048:                 * the middle of a DMA block, they should already be set
        !          1049:                 * by the phase change interrupt.  If the disconnect
        !          1050:                 * occurs on a DMA block boundary, we have to figure out
        !          1051:                 * which DMA block it was.
        !          1052:                 */
        !          1053:                if (acb->iob_len && rp->ssh_temp) {
        !          1054:                        int n = rp->ssh_temp - sc->sc_scriptspa;
        !          1055:
        !          1056:                        if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen)
        !          1057:                                printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n",
        !          1058:                                                 sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen,
        !          1059:                                                 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen);
        !          1060:                        if (n < Ent_datain)
        !          1061:                                n = (n - Ent_dataout) / 16;
        !          1062:                        else
        !          1063:                                n = (n - Ent_datain) / 16;
        !          1064:                        if (n <= 0 || n >= DMAMAXIO)
        !          1065:                                printf("TEMP invalid %d\n", n);
        !          1066:                        else {
        !          1067:                                acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf;
        !          1068:                                acb->iob_curlen = acb->ds.chain[n].datalen;
        !          1069:                        }
        !          1070: #ifdef DEBUG
        !          1071:                        if (ssh_debug & 0x100) {
        !          1072:                                printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n);
        !          1073:                                printf(" curbuf %x curlen %x\n", acb->iob_curbuf,
        !          1074:                                                 acb->iob_curlen);
        !          1075:                        }
        !          1076: #endif
        !          1077:                }
        !          1078:                /*
        !          1079:                 * If data transfer was interrupted by disconnect, iob_curbuf
        !          1080:                 * and iob_curlen should reflect the point of interruption.
        !          1081:                 * Adjust the DMA chain so that the data transfer begins
        !          1082:                 * at the appropriate place upon reselection.
        !          1083:                 * XXX This should only be done on save data pointer message?
        !          1084:                 */
        !          1085:                if (acb->iob_curlen) {
        !          1086:                        int i, j;
        !          1087:
        !          1088: #ifdef DEBUG
        !          1089:                        if (ssh_debug & 0x100)
        !          1090:                                printf ("%s: adjusting DMA chain\n",
        !          1091:                                                  sc->sc_dev.dv_xname);
        !          1092:                        if (rp->ssh_dsps == 0xff02)
        !          1093:                                printf ("%s: ID %02x disconnected without Save Data Pointers\n",
        !          1094:                                                  sc->sc_dev.dv_xname, 1 << target);
        !          1095: #endif
        !          1096:                        for (i = 0; i < DMAMAXIO; ++i) {
        !          1097:                                if (acb->ds.chain[i].datalen == 0)
        !          1098:                                        break;
        !          1099:                                if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf &&
        !          1100:                                         acb->iob_curbuf < (long)(acb->ds.chain[i].databuf +
        !          1101:                                                                                                          acb->ds.chain[i].datalen))
        !          1102:                                        break;
        !          1103:                        }
        !          1104:                        if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0)
        !          1105:                                printf("couldn't find saved data pointer\n");
        !          1106: #ifdef DEBUG
        !          1107:                        if (ssh_debug & 0x100)
        !          1108:                                printf("  chain[0]: %x/%x -> %x/%x\n",
        !          1109:                                                 acb->ds.chain[0].databuf,
        !          1110:                                                 acb->ds.chain[0].datalen,
        !          1111:                                                 acb->iob_curbuf,
        !          1112:                                                 acb->iob_curlen);
        !          1113: #endif
        !          1114:                        acb->ds.chain[0].databuf = (char *)acb->iob_curbuf;
        !          1115:                        acb->ds.chain[0].datalen = acb->iob_curlen;
        !          1116:                        for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) {
        !          1117: #ifdef DEBUG
        !          1118:                                if (ssh_debug & 0x100)
        !          1119:                                        printf("  chain[%d]: %x/%x -> %x/%x\n", j,
        !          1120:                                                         acb->ds.chain[j].databuf,
        !          1121:                                                         acb->ds.chain[j].datalen,
        !          1122:                                                         acb->ds.chain[i].databuf,
        !          1123:                                                         acb->ds.chain[i].datalen);
        !          1124: #endif
        !          1125:                                acb->ds.chain[j].databuf = acb->ds.chain[i].databuf;
        !          1126:                                acb->ds.chain[j].datalen = acb->ds.chain[i].datalen;
        !          1127:                        }
        !          1128:                        if (j < DMAMAXIO)
        !          1129:                                acb->ds.chain[j++].datalen = 0;
        !          1130:                        dma_cachectl((caddr_t)&acb->ds.chain,
        !          1131:                            j * sizeof(acb->ds.chain[0]));
        !          1132:                }
        !          1133:                ++sc->sc_tinfo[target].dconns;
        !          1134:                /*
        !          1135:                 * add nexus to waiting list
        !          1136:                 * clear nexus
        !          1137:                 * try to start another command for another target/lun
        !          1138:                 */
        !          1139:                acb->status = sc->sc_flags & SSH_INTSOFF;
        !          1140:                TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
        !          1141:                sc->sc_nexus = NULL;            /* no current device */
        !          1142:                /* start script to wait for reselect */
        !          1143:                if (sc->sc_nexus == NULL)
        !          1144:                        rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;
        !          1145: /* XXXX start another command ? */
        !          1146:                if (!TAILQ_EMPTY(&sc->ready_list))
        !          1147:                        ssh_sched(sc);
        !          1148:                return (0);
        !          1149:        }
        !          1150:        if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff03) {
        !          1151:                int reselid = rp->ssh_scratch & 0x7f;
        !          1152:                int reselun = rp->ssh_sfbr & 0x07;
        !          1153:
        !          1154:                sc->sc_sstat1 = rp->ssh_sbcl;   /* XXXX save current SBCL */
        !          1155: #ifdef DEBUG
        !          1156:                if (ssh_debug & 0x100)
        !          1157:                        printf ("%s: target ID %02x reselected dsps %x\n",
        !          1158:                                          sc->sc_dev.dv_xname, reselid,
        !          1159:                                          rp->ssh_dsps);
        !          1160:                if ((rp->ssh_sfbr & 0x80) == 0)
        !          1161:                        printf("%s: Reselect message in was not identify: %x\n",
        !          1162:                                         sc->sc_dev.dv_xname, rp->ssh_sfbr);
        !          1163: #endif
        !          1164:                if (sc->sc_nexus) {
        !          1165: #ifdef DEBUG
        !          1166:                        if (ssh_debug & 0x100)
        !          1167:                                printf ("%s: reselect ID %02x w/active\n",
        !          1168:                                                  sc->sc_dev.dv_xname, reselid);
        !          1169: #endif
        !          1170:                        TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain);
        !          1171:                        sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target].lubusy
        !          1172:                        &= ~(1 << sc->sc_nexus->xs->sc_link->lun);
        !          1173:                        --sc->sc_active;
        !          1174:                }
        !          1175:                /*
        !          1176:                 * locate acb of reselecting device
        !          1177:                 * set sc->sc_nexus to acb
        !          1178:                 */
        !          1179:                TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
        !          1180:                        if (reselid != (acb->ds.scsi_addr >> 16) ||
        !          1181:                                 reselun != (acb->msgout[0] & 0x07))
        !          1182:                                continue;
        !          1183:                        TAILQ_REMOVE(&sc->nexus_list, acb, chain);
        !          1184:                        sc->sc_nexus = acb;
        !          1185:                        sc->sc_flags |= acb->status;
        !          1186:                        acb->status = 0;
        !          1187:                        dma_cachectl(&acb->stat[0], 1); /* XXX necessary? */
        !          1188:                        rp->ssh_dsa = kvtop((vaddr_t)&acb->ds);
        !          1189:                        rp->ssh_sxfer = sc->sc_sync[acb->xs->sc_link->target].sxfer;
        !          1190:                        rp->ssh_sbcl = sc->sc_sync[acb->xs->sc_link->target].sbcl;
        !          1191:                        break;
        !          1192:                }
        !          1193:                if (acb == NULL) {
        !          1194:                        printf("%s: target ID %02x reselect nexus_list %p\n",
        !          1195:                                         sc->sc_dev.dv_xname, reselid,
        !          1196:                                         TAILQ_FIRST(&sc->nexus_list));
        !          1197:                        panic("unable to find reselecting device");
        !          1198:                }
        !          1199:                dma_cachectl((caddr_t)acb, sizeof(*acb));
        !          1200:                rp->ssh_temp = 0;
        !          1201:                rp->ssh_dcntl |= SSH_DCNTL_STD;
        !          1202:                return (0);
        !          1203:        }
        !          1204:        if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff04) {
        !          1205: #ifdef DEBUG
        !          1206:                u_short ctest2 = rp->ssh_ctest2;
        !          1207:
        !          1208:                /* reselect was interrupted (by Sig_P or select) */
        !          1209:                if (ssh_debug & 0x100 ||
        !          1210:                         (ctest2 & SSH_CTEST2_SIGP) == 0)
        !          1211:                        printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x
        !          1212:                                          sfbr %x istat %x/%x\n", sc->sc_dev.dv_xname, rp->ssh_scntl1,
        !          1213:                                          ctest2, rp->ssh_sfbr, istat, rp->ssh_istat);
        !          1214: #endif
        !          1215:                /* XXX assumes it was not select */
        !          1216:                if (sc->sc_nexus == NULL) {
        !          1217:                        printf("%s: reselect interrupted, sc_nexus == NULL\n",
        !          1218:                                         sc->sc_dev.dv_xname);
        !          1219: #if 0
        !          1220:                        ssh_dump(sc);
        !          1221: #ifdef DDB
        !          1222:                        Debugger();
        !          1223: #endif
        !          1224: #endif
        !          1225:                        rp->ssh_dcntl |= SSH_DCNTL_STD;
        !          1226:                        return (0);
        !          1227:                }
        !          1228:                target = sc->sc_nexus->xs->sc_link->target;
        !          1229:                rp->ssh_temp = 0;
        !          1230:                rp->ssh_dsa = kvtop((vaddr_t)&sc->sc_nexus->ds);
        !          1231:                rp->ssh_sxfer = sc->sc_sync[target].sxfer;
        !          1232:                rp->ssh_sbcl = sc->sc_sync[target].sbcl;
        !          1233:                rp->ssh_dsp = sc->sc_scriptspa;
        !          1234:                return (0);
        !          1235:        }
        !          1236:        if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff06) {
        !          1237:                if (acb == NULL)
        !          1238:                        printf("%s: Bad message-in with no active command?\n",
        !          1239:                                         sc->sc_dev.dv_xname);
        !          1240:                /* Unrecognized message in byte */
        !          1241:                dma_cachectl(&acb->msg[1],1);
        !          1242:                printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n",
        !          1243:                                  sc->sc_dev.dv_xname, rp->ssh_sfbr, acb->msg[1], rp->ssh_sbcl);
        !          1244:                /* what should be done here? */
        !          1245:                rp->ssh_dsp = sc->sc_scriptspa + Ent_switch;
        !          1246:                return (0);
        !          1247:        }
        !          1248:        if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff0a) {
        !          1249:                /* Status phase wasn't followed by message in phase? */
        !          1250:                printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n",
        !          1251:                                  sc->sc_dev.dv_xname, rp->ssh_sbcl, rp->ssh_sbdl);
        !          1252:                if (rp->ssh_sbcl == 0xa7) {
        !          1253:                        /* It is now, just continue the script? */
        !          1254:                        rp->ssh_dcntl |= SSH_DCNTL_STD;
        !          1255:                        return (0);
        !          1256:                }
        !          1257:        }
        !          1258:        if (sstat0 == 0 && dstat & SSH_DSTAT_SIR) {
        !          1259:                dma_cachectl(&acb->stat[0], 1);
        !          1260:                dma_cachectl(&acb->msg[0], 1);
        !          1261:                printf ("SSH interrupt: %lx sts %x msg %x %x sbcl %x\n",
        !          1262:                                  rp->ssh_dsps, acb->stat[0], acb->msg[0], acb->msg[1],
        !          1263:                                  rp->ssh_sbcl);
        !          1264:                sshreset (sc);
        !          1265:                *status = -1;
        !          1266:                return 0;       /* sshreset has cleaned up */
        !          1267:        }
        !          1268:        if (sstat0 & SSH_SSTAT0_SGE)
        !          1269:                printf ("SSH: SCSI Gross Error\n");
        !          1270:        if (sstat0 & SSH_SSTAT0_PAR)
        !          1271:                printf ("SSH: Parity Error\n");
        !          1272:        if (dstat & SSH_DSTAT_IID)
        !          1273:                printf ("SSH: Invalid instruction detected\n");
        !          1274:        bad_phase:
        !          1275:        /*
        !          1276:         * temporary panic for unhandled conditions
        !          1277:         * displays various things about the 53C710 status and registers
        !          1278:         * then panics.
        !          1279:         * XXXX need to clean this up to print out the info, reset, and continue
        !          1280:         */
        !          1281:        printf ("sshchkintr: target %x ds %p\n", target, &acb->ds);
        !          1282:        printf ("scripts %lx ds %lx rp %lx dsp %lx dcmd %lx\n", sc->sc_scriptspa,
        !          1283:          kvtop((vaddr_t)&acb->ds), kvtop((vaddr_t)rp), rp->ssh_dsp,
        !          1284:          *((long *)&rp->ssh_dcmd));
        !          1285:        printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %lx "
        !          1286:                          "dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n",
        !          1287:                          istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_dsa,
        !          1288:                          rp->ssh_sbcl, acb->stat[0], acb->msg[0], acb->msg[1],
        !          1289:                          rp->ssh_sfbr);
        !          1290: #ifdef DEBUG
        !          1291:        if (ssh_debug & 0x20)
        !          1292:                panic("sshchkintr: **** temp ****");
        !          1293: #ifdef DDB
        !          1294:        /* Debugger(); */
        !          1295: #endif
        !          1296: #endif
        !          1297:        sshreset (sc);          /* hard reset */
        !          1298:        *status = -1;
        !          1299:        return 0;               /* sshreset cleaned up */
        !          1300: }
        !          1301:
        !          1302: void
        !          1303: ssh_select(sc)
        !          1304: struct ssh_softc *sc;
        !          1305: {
        !          1306:        ssh_regmap_p rp;
        !          1307:        struct ssh_acb *acb = sc->sc_nexus;
        !          1308:
        !          1309: #ifdef DEBUG
        !          1310:        if (ssh_debug & 1)
        !          1311:                printf ("%s: select ", sc->sc_dev.dv_xname);
        !          1312: #endif
        !          1313:
        !          1314:        rp = sc->sc_sshp;
        !          1315:        if (acb->xs->flags & SCSI_POLL || ssh_no_dma) {
        !          1316:                sc->sc_flags |= SSH_INTSOFF;
        !          1317:                sc->sc_flags &= ~SSH_INTDEFER;
        !          1318:                if ((rp->ssh_istat & 0x08) == 0) {
        !          1319:                        rp->ssh_sien = 0;
        !          1320:                        rp->ssh_dien = 0;
        !          1321:                }
        !          1322: #if 0
        !          1323:        } else if ((sc->sc_flags & SSH_INTDEFER) == 0) {
        !          1324:                sc->sc_flags &= ~SSH_INTSOFF;
        !          1325:                if ((rp->ssh_istat & 0x08) == 0) {
        !          1326:                        rp->ssh_sien = sc->sc_sien;
        !          1327:                        rp->ssh_dien = sc->sc_dien;
        !          1328:                }
        !          1329: #endif
        !          1330:        }
        !          1331: #ifdef DEBUG
        !          1332:        if (ssh_debug & 1)
        !          1333:                printf ("ssh_select: target %x cmd %02x ds %x\n",
        !          1334:                                  acb->xs->sc_link->target, acb->cmd.opcode,
        !          1335:                                  &sc->sc_nexus->ds);
        !          1336: #endif
        !          1337:
        !          1338:        ssh_start(sc, acb->xs->sc_link->target, acb->xs->sc_link->lun,
        !          1339:          (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft);
        !          1340:
        !          1341:        return;
        !          1342: }
        !          1343:
        !          1344: /*
        !          1345:  * 53C710 interrupt handler
        !          1346:  */
        !          1347: void
        !          1348: sshintr(sc)
        !          1349:        register struct ssh_softc *sc;
        !          1350: {
        !          1351:        ssh_regmap_p rp;
        !          1352:        register u_char istat, dstat, sstat0;
        !          1353:        int status;
        !          1354:        int s = splbio();
        !          1355:
        !          1356:        istat = sc->sc_istat;
        !          1357:        if ((istat & (SSH_ISTAT_SIP | SSH_ISTAT_DIP)) == 0) {
        !          1358:                splx(s);
        !          1359:                return;
        !          1360:        }
        !          1361:
        !          1362:        /* Got a valid interrupt on this device */
        !          1363:        rp = sc->sc_sshp;
        !          1364:        dstat = sc->sc_dstat;
        !          1365:        sstat0 = sc->sc_sstat0;
        !          1366:        if (dstat & SSH_DSTAT_SIR)
        !          1367:                sc->sc_intcode = rp->ssh_dsps;
        !          1368:        sc->sc_istat = 0;
        !          1369:
        !          1370: #ifdef DEBUG
        !          1371:        if (ssh_debug & 1)
        !          1372:                printf ("%s: intr istat %x dstat %x sstat0 %x\n",
        !          1373:                                  sc->sc_dev.dv_xname, istat, dstat, sstat0);
        !          1374:        if (!sc->sc_active) {
        !          1375:                printf ("%s: spurious interrupt? istat %x dstat %x sstat0 %x status %x\n",
        !          1376:                                  sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus->stat[0]);
        !          1377:        }
        !          1378: #else
        !          1379:        if (!sc->sc_active) {
        !          1380:                printf ("%s: spurious interrupt? istat %x dstat %x sstat0 %x status %x\n",
        !          1381:                                  sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus->stat[0]);
        !          1382:                return;
        !          1383:        }
        !          1384: #endif
        !          1385:
        !          1386: #ifdef DEBUG
        !          1387:        if (ssh_debug & 5) {
        !          1388:                dma_cachectl(&sc->sc_nexus->stat[0], 1);
        !          1389:                printf ("%s: intr istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
        !          1390:                                  sc->sc_dev.dv_xname, istat, dstat, sstat0,
        !          1391:                                  rp->ssh_dsps,  rp->ssh_sbcl,
        !          1392:                                  sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]);
        !          1393:        }
        !          1394: #endif
        !          1395:        if (sc->sc_flags & SSH_INTDEFER) {
        !          1396:                sc->sc_flags &= ~(SSH_INTDEFER | SSH_INTSOFF);
        !          1397:                rp->ssh_sien = sc->sc_sien;
        !          1398:                rp->ssh_dien = sc->sc_dien;
        !          1399:        }
        !          1400:        if (ssh_checkintr (sc, istat, dstat, sstat0, &status)) {
        !          1401: #if 1
        !          1402:                if (status == 0xff)
        !          1403:                        printf ("sshintr: status == 0xff\n");
        !          1404: #endif
        !          1405:                if ((sc->sc_flags & (SSH_INTSOFF | SSH_INTDEFER)) != SSH_INTSOFF) {
        !          1406: #if 0
        !          1407:                        if (rp->ssh_sbcl & SSH_BSY) {
        !          1408:                                printf ("%s: SCSI bus busy at completion",
        !          1409:                                                  sc->sc_dev.dv_xname);
        !          1410:                                printf(" targ %d sbcl %02x sfbr %x lcrc %02x dsp +%x\n",
        !          1411:                                                 sc->sc_nexus->xs->sc_link->target,
        !          1412:                                                 rp->ssh_sbcl, rp->ssh_sfbr, rp->ssh_lcrc,
        !          1413:                                                 rp->ssh_dsp - sc->sc_scriptspa);
        !          1414:                        }
        !          1415: #endif
        !          1416:                        ssh_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]);
        !          1417:                }
        !          1418:        }
        !          1419:        splx(s);
        !          1420: }
        !          1421:
        !          1422: /*
        !          1423:  * This is based on the Progressive Peripherals 33MHz Zeus driver and will
        !          1424:  * not be correct for other 53c710 boards.
        !          1425:  *
        !          1426:  */
        !          1427: void
        !          1428: scsi_period_to_ssh (sc, target)
        !          1429:        struct ssh_softc *sc;
        !          1430:        int target;
        !          1431: {
        !          1432:        int period, offset, sxfer, sbcl;
        !          1433:
        !          1434:        period = sc->sc_nexus->msg[4];
        !          1435:        offset = sc->sc_nexus->msg[5];
        !          1436:        for (sbcl = 1; sbcl < 4; ++sbcl) {
        !          1437:                sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3;
        !          1438:                if (sxfer >= 0 && sxfer <= 7)
        !          1439:                        break;
        !          1440:        }
        !          1441:        if (sbcl > 3) {
        !          1442:                printf("ssh_sync: unable to compute sync params for period %dns\n",
        !          1443:                                 period * 4);
        !          1444:                /*
        !          1445:                 * XXX need to pick a value we can do and renegotiate
        !          1446:                 */
        !          1447:                sxfer = sbcl = 0;
        !          1448:        } else
        !          1449:                sxfer   = (sxfer << 4) | ((offset <= SSH_MAX_OFFSET) ?
        !          1450:                                                                                offset : SSH_MAX_OFFSET);
        !          1451:        sc->sc_sync[target].sxfer = sxfer;
        !          1452:        sc->sc_sync[target].sbcl = sbcl;
        !          1453: #ifdef DEBUG
        !          1454:        printf ("ssh sync: ssh_sxfr %02x, ssh_sbcl %02x\n", sxfer, sbcl);
        !          1455: #endif
        !          1456: }
        !          1457:
        !          1458: #ifdef DEBUG
        !          1459:
        !          1460: #if SSH_TRACE_SIZE
        !          1461: void
        !          1462: ssh_dump_trace()
        !          1463: {
        !          1464:        int i;
        !          1465:
        !          1466:        printf("ssh trace: next index %d\n", ssh_trix);
        !          1467:        i = ssh_trix;
        !          1468:        do {
        !          1469:                printf("%3d: '%c' %02x %02x %02x\n", i, ssh_trbuf[i],
        !          1470:                                 ssh_trbuf[i + 1], ssh_trbuf[i + 2], ssh_trbuf[i + 3]);
        !          1471:                i = (i + 4) & (SSH_TRACE_SIZE - 1);
        !          1472:        } while (i != ssh_trix);
        !          1473: }
        !          1474: #endif
        !          1475:
        !          1476: void
        !          1477: ssh_dump_acb(acb)
        !          1478: struct ssh_acb *acb;
        !          1479: {
        !          1480:        u_char *b = (u_char *) &acb->cmd;
        !          1481:        int i;
        !          1482:
        !          1483: #if SSH_TRACE_SIZE
        !          1484:        ssh_dump_trace();
        !          1485: #endif
        !          1486:        printf("acb@%x ", acb);
        !          1487:        if (acb->xs == NULL) {
        !          1488:                printf("<unused>\n");
        !          1489:                return;
        !          1490:        }
        !          1491:        printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target,
        !          1492:                         acb->xs->sc_link->lun, acb->flags, acb->clen);
        !          1493:        for (i = acb->clen; i; --i)
        !          1494:                printf(" %02x", *b++);
        !          1495:        printf("\n");
        !          1496:        printf("  xs: %08x data %8x:%04x ", acb->xs, acb->xs->data,
        !          1497:                         acb->xs->datalen);
        !          1498:        printf("va %8x:%04x ", acb->iob_buf, acb->iob_len);
        !          1499:        printf("cur %8x:%04x\n", acb->iob_curbuf, acb->iob_curlen);
        !          1500: }
        !          1501:
        !          1502: void
        !          1503: ssh_dump(sc)
        !          1504: struct ssh_softc *sc;
        !          1505: {
        !          1506:        struct ssh_acb *acb;
        !          1507:        ssh_regmap_p rp = sc->sc_sshp;
        !          1508:        int s;
        !          1509:        int i;
        !          1510:
        !          1511:        s = splbio();
        !          1512:        printf("%s@%x regs %x istat %x\n",
        !          1513:                         sc->sc_dev.dv_xname, sc, rp, rp->ssh_istat);
        !          1514:        if (acb = TAILQ_FIRST(&sc->free_list)) {
        !          1515:                printf("Free list:\n");
        !          1516:                while (acb) {
        !          1517:                        ssh_dump_acb(acb);
        !          1518:                        acb = TAILQ_NEXT(acb, chain);
        !          1519:                }
        !          1520:        }
        !          1521:        if (acb = TAILQ_FIRST(&sc->ready_list)) {
        !          1522:                printf("Ready list:\n");
        !          1523:                while (acb) {
        !          1524:                        ssh_dump_acb(acb);
        !          1525:                        acb = TAILQ_NEXT(acb, chain);
        !          1526:                }
        !          1527:        }
        !          1528:        if (acb = TAILQ_FIRST(&sc->nexus_list)) {
        !          1529:                printf("Nexus list:\n");
        !          1530:                while (acb) {
        !          1531:                        ssh_dump_acb(acb);
        !          1532:                        acb = TAILQ_NEXT(acb, chain);
        !          1533:                }
        !          1534:        }
        !          1535:        if (sc->sc_nexus) {
        !          1536:                printf("Nexus:\n");
        !          1537:                ssh_dump_acb(sc->sc_nexus);
        !          1538:        }
        !          1539:        for (i = 0; i < 8; ++i) {
        !          1540:                if (sc->sc_tinfo[i].cmds > 2) {
        !          1541:                        printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n",
        !          1542:                                         i, sc->sc_tinfo[i].cmds,
        !          1543:                                         sc->sc_tinfo[i].dconns,
        !          1544:                                         sc->sc_tinfo[i].senses,
        !          1545:                                         sc->sc_tinfo[i].lubusy);
        !          1546:                }
        !          1547:        }
        !          1548:        splx(s);
        !          1549: }
        !          1550: #endif

CVSweb