Annotation of Net2/arch/hp300/dev/scsi.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1990 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Van Jacobson of Lawrence Berkeley Laboratory.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)scsi.c      7.5 (Berkeley) 5/4/91
        !            37:  */
        !            38: 
        !            39: /*
        !            40:  * HP9000/3xx 98658 SCSI host adaptor driver.
        !            41:  */
        !            42: #include "scsi.h"
        !            43: #if NSCSI > 0
        !            44: 
        !            45: #ifndef lint
        !            46: static char rcsid[] = "$Header: scsi.c,v 1.4 91/01/17 12:50:18 mike Exp $";
        !            47: #endif
        !            48: 
        !            49: #include "sys/param.h"
        !            50: #include "sys/systm.h"
        !            51: #include "sys/buf.h"
        !            52: #include "device.h"
        !            53: 
        !            54: #include "scsivar.h"
        !            55: #include "scsireg.h"
        !            56: #include "dmavar.h"
        !            57: 
        !            58: #include "../include/cpu.h"
        !            59: #include "../hp300/isr.h"
        !            60: 
        !            61: /*
        !            62:  * SCSI delays
        !            63:  * In u-seconds, primarily for state changes on the SPC.
        !            64:  */
        !            65: #define        SCSI_CMD_WAIT   1000    /* wait per step of 'immediate' cmds */
        !            66: #define        SCSI_DATA_WAIT  1000    /* wait per data in/out step */
        !            67: #define        SCSI_INIT_WAIT  50000   /* wait per step (both) during init */
        !            68: 
        !            69: extern void isrlink();
        !            70: extern void _insque();
        !            71: extern void _remque();
        !            72: 
        !            73: int    scsiinit(), scsigo(), scsiintr(), scsixfer();
        !            74: void   scsistart(), scsidone(), scsifree(), scsireset();
        !            75: struct driver scsidriver = {
        !            76:        scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr,
        !            77:        (int (*)())scsidone,
        !            78: };
        !            79: 
        !            80: struct scsi_softc scsi_softc[NSCSI];
        !            81: struct isr scsi_isr[NSCSI];
        !            82: 
        !            83: int scsi_cmd_wait = SCSI_CMD_WAIT;
        !            84: int scsi_data_wait = SCSI_DATA_WAIT;
        !            85: int scsi_init_wait = SCSI_INIT_WAIT;
        !            86: 
        !            87: int scsi_nosync = 1;           /* inhibit sync xfers if 1 */
        !            88: int scsi_pridma = 0;           /* use "priority" dma */
        !            89: 
        !            90: #ifdef DEBUG
        !            91: int    scsi_debug = 0;
        !            92: #define WAITHIST
        !            93: #endif
        !            94: 
        !            95: #ifdef WAITHIST
        !            96: #define MAXWAIT        1022
        !            97: u_int  ixstart_wait[MAXWAIT+2];
        !            98: u_int  ixin_wait[MAXWAIT+2];
        !            99: u_int  ixout_wait[MAXWAIT+2];
        !           100: u_int  mxin_wait[MAXWAIT+2];
        !           101: u_int  mxin2_wait[MAXWAIT+2];
        !           102: u_int  cxin_wait[MAXWAIT+2];
        !           103: u_int  fxfr_wait[MAXWAIT+2];
        !           104: u_int  sgo_wait[MAXWAIT+2];
        !           105: #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]);
        !           106: #else
        !           107: #define HIST(h,w)
        !           108: #endif
        !           109: 
        !           110: #define        b_cylin         b_resid
        !           111: 
        !           112: static void
        !           113: scsiabort(hs, hd, where)
        !           114:        register struct scsi_softc *hs;
        !           115:        volatile register struct scsidevice *hd;
        !           116:        char *where;
        !           117: {
        !           118:        int len;
        !           119:        u_char junk;
        !           120: 
        !           121:        printf("scsi%d: abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n",
        !           122:                hs->sc_hc->hp_unit, where, hd->scsi_psns, hd->scsi_ssts,
        !           123:                hd->scsi_ints);
        !           124: 
        !           125:        hd->scsi_ints = hd->scsi_ints;
        !           126:        hd->scsi_csr = 0;
        !           127:        if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
        !           128:                /* no longer connected to scsi target */
        !           129:                return;
        !           130: 
        !           131:        /* get the number of bytes remaining in current xfer + fudge */
        !           132:        len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
        !           133: 
        !           134:        /* for that many bus cycles, try to send an abort msg */
        !           135:        for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
        !           136:                hd->scsi_scmd = SCMD_SET_ATN;
        !           137:                while ((hd->scsi_psns & PSNS_REQ) == 0) {
        !           138:                        if (! (hd->scsi_ssts & SSTS_INITIATOR))
        !           139:                                goto out;
        !           140:                        DELAY(1);
        !           141:                }
        !           142:                if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
        !           143:                        hd->scsi_scmd = SCMD_RST_ATN;
        !           144:                hd->scsi_pctl = hd->scsi_psns & PHASE;
        !           145:                if (hd->scsi_psns & PHASE_IO) {
        !           146:                        /* one of the input phases - read & discard a byte */
        !           147:                        hd->scsi_scmd = SCMD_SET_ACK;
        !           148:                        if (hd->scsi_tmod == 0)
        !           149:                                while (hd->scsi_psns & PSNS_REQ)
        !           150:                                        DELAY(1);
        !           151:                        junk = hd->scsi_temp;
        !           152:                } else {
        !           153:                        /* one of the output phases - send an abort msg */
        !           154:                        hd->scsi_temp = MSG_ABORT;
        !           155:                        hd->scsi_scmd = SCMD_SET_ACK;
        !           156:                        if (hd->scsi_tmod == 0)
        !           157:                                while (hd->scsi_psns & PSNS_REQ)
        !           158:                                        DELAY(1);
        !           159:                }
        !           160:                hd->scsi_scmd = SCMD_RST_ACK;
        !           161:        }
        !           162: out:
        !           163:        /*
        !           164:         * Either the abort was successful & the bus is disconnected or
        !           165:         * the device didn't listen.  If the latter, announce the problem.
        !           166:         * Either way, reset the card & the SPC.
        !           167:         */
        !           168:        if (len < 0 && hs)
        !           169:                printf("scsi%d: abort failed.  phase=0x%x, ssts=0x%x\n",
        !           170:                        hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
        !           171: 
        !           172:        if (! ((junk = hd->scsi_ints) & INTS_RESEL)) {
        !           173:                hd->scsi_sctl |= SCTL_CTRLRST;
        !           174:                DELAY(1);
        !           175:                hd->scsi_sctl &=~ SCTL_CTRLRST;
        !           176:                hd->scsi_hconf = 0;
        !           177:                hd->scsi_ints = hd->scsi_ints;
        !           178:        }
        !           179: }
        !           180: 
        !           181: /*
        !           182:  * XXX Set/reset long delays.
        !           183:  *
        !           184:  * if delay == 0, reset default delays
        !           185:  * if delay < 0,  set both delays to default long initialization values
        !           186:  * if delay > 0,  set both delays to this value
        !           187:  *
        !           188:  * Used when a devices is expected to respond slowly (e.g. during
        !           189:  * initialization).
        !           190:  */
        !           191: void
        !           192: scsi_delay(delay)
        !           193:        int delay;
        !           194: {
        !           195:        static int saved_cmd_wait, saved_data_wait;
        !           196: 
        !           197:        if (delay) {
        !           198:                saved_cmd_wait = scsi_cmd_wait;
        !           199:                saved_data_wait = scsi_data_wait;
        !           200:                if (delay > 0)
        !           201:                        scsi_cmd_wait = scsi_data_wait = delay;
        !           202:                else
        !           203:                        scsi_cmd_wait = scsi_data_wait = scsi_init_wait;
        !           204:        } else {
        !           205:                scsi_cmd_wait = saved_cmd_wait;
        !           206:                scsi_data_wait = saved_data_wait;
        !           207:        }
        !           208: }
        !           209: 
        !           210: int
        !           211: scsiinit(hc)
        !           212:        register struct hp_ctlr *hc;
        !           213: {
        !           214:        register struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
        !           215:        register struct scsidevice *hd = (struct scsidevice *)hc->hp_addr;
        !           216:        
        !           217:        if ((hd->scsi_id & ID_MASK) != SCSI_ID)
        !           218:                return(0);
        !           219:        hc->hp_ipl = SCSI_IPL(hd->scsi_csr);
        !           220:        hs->sc_hc = hc;
        !           221:        hs->sc_dq.dq_unit = hc->hp_unit;
        !           222:        hs->sc_dq.dq_driver = &scsidriver;
        !           223:        hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;
        !           224:        scsi_isr[hc->hp_unit].isr_intr = scsiintr;
        !           225:        scsi_isr[hc->hp_unit].isr_ipl = hc->hp_ipl;
        !           226:        scsi_isr[hc->hp_unit].isr_arg = hc->hp_unit;
        !           227:        isrlink(&scsi_isr[hc->hp_unit]);
        !           228:        scsireset(hc->hp_unit);
        !           229:        return(1);
        !           230: }
        !           231: 
        !           232: void
        !           233: scsireset(unit)
        !           234:        register int unit;
        !           235: {
        !           236:        register struct scsi_softc *hs = &scsi_softc[unit];
        !           237:        volatile register struct scsidevice *hd =
        !           238:                                (struct scsidevice *)hs->sc_hc->hp_addr;
        !           239:        u_int i;
        !           240: 
        !           241:        if (hs->sc_flags & SCSI_ALIVE)
        !           242:                scsiabort(hs, hd, "reset");
        !           243:                
        !           244:        printf("scsi%d: ", unit);
        !           245: 
        !           246:        hd->scsi_id = 0xFF;
        !           247:        DELAY(100);
        !           248:        /*
        !           249:         * Disable interrupts then reset the FUJI chip.
        !           250:         */
        !           251:        hd->scsi_csr  = 0;
        !           252:        hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
        !           253:        hd->scsi_scmd = 0;
        !           254:        hd->scsi_tmod = 0;
        !           255:        hd->scsi_pctl = 0;
        !           256:        hd->scsi_temp = 0;
        !           257:        hd->scsi_tch  = 0;
        !           258:        hd->scsi_tcm  = 0;
        !           259:        hd->scsi_tcl  = 0;
        !           260:        hd->scsi_ints = 0;
        !           261: 
        !           262:        if ((hd->scsi_id & ID_WORD_DMA) == 0) {
        !           263:                hs->sc_flags |= SCSI_DMA32;
        !           264:                printf("32 bit dma, ");
        !           265:        }
        !           266: 
        !           267:        /* Determine Max Synchronous Transfer Rate */
        !           268:        if (scsi_nosync)
        !           269:                i = 3;
        !           270:        else
        !           271:                i = SCSI_SYNC_XFER(hd->scsi_hconf);
        !           272:        switch (i) {
        !           273:                case 0:
        !           274:                        hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */
        !           275:                        printf("250ns sync");
        !           276:                        break;
        !           277:                case 1:
        !           278:                        hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */
        !           279:                        printf("375ns sync");
        !           280:                        break;
        !           281:                case 2:
        !           282:                        hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */
        !           283:                        printf("500ns sync");
        !           284:                        break;
        !           285:                case 3:
        !           286:                        hs->sc_sync = 0;
        !           287:                        printf("async");
        !           288:                        break;
        !           289:                }
        !           290: 
        !           291:        /*
        !           292:         * Configure the FUJI chip with its SCSI address, all
        !           293:         * interrupts enabled & appropriate parity.
        !           294:         */
        !           295:        i = (~hd->scsi_hconf) & 0x7;
        !           296:        hs->sc_scsi_addr = 1 << i;
        !           297:        hd->scsi_bdid = i;
        !           298:        if (hd->scsi_hconf & HCONF_PARITY)
        !           299:                hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
        !           300:                                SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
        !           301:                                SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
        !           302:        else {
        !           303:                hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
        !           304:                                SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
        !           305:                                SCTL_INTR_ENAB;
        !           306:                printf(", no parity");
        !           307:        }
        !           308:        hd->scsi_sctl &=~ SCTL_DISABLE;
        !           309: 
        !           310:        printf(", scsi id %d\n", i);
        !           311:        hs->sc_flags |= SCSI_ALIVE;
        !           312: }
        !           313: 
        !           314: static void
        !           315: scsierror(hs, hd, ints)
        !           316:        register struct scsi_softc *hs;
        !           317:        volatile register struct scsidevice *hd;
        !           318:        u_char ints;
        !           319: {
        !           320:        int unit = hs->sc_hc->hp_unit;
        !           321:        char *sep = "";
        !           322: 
        !           323:        printf("scsi%d: ", unit);
        !           324:        if (ints & INTS_RST) {
        !           325:                DELAY(100);
        !           326:                if (hd->scsi_hconf & HCONF_SD)
        !           327:                        printf("spurious RST interrupt");
        !           328:                else
        !           329:                        printf("hardware error - check fuse");
        !           330:                sep = ", ";
        !           331:        }
        !           332:        if ((ints & INTS_HARD_ERR) || hd->scsi_serr) {
        !           333:                if (hd->scsi_serr & SERR_SCSI_PAR) {
        !           334:                        printf("%sparity err", sep);
        !           335:                        sep = ", ";
        !           336:                }
        !           337:                if (hd->scsi_serr & SERR_SPC_PAR) {
        !           338:                        printf("%sSPC parity err", sep);
        !           339:                        sep = ", ";
        !           340:                }
        !           341:                if (hd->scsi_serr & SERR_TC_PAR) {
        !           342:                        printf("%sTC parity err", sep);
        !           343:                        sep = ", ";
        !           344:                }
        !           345:                if (hd->scsi_serr & SERR_PHASE_ERR) {
        !           346:                        printf("%sphase err", sep);
        !           347:                        sep = ", ";
        !           348:                }
        !           349:                if (hd->scsi_serr & SERR_SHORT_XFR) {
        !           350:                        printf("%ssync short transfer err", sep);
        !           351:                        sep = ", ";
        !           352:                }
        !           353:                if (hd->scsi_serr & SERR_OFFSET) {
        !           354:                        printf("%ssync offset error", sep);
        !           355:                        sep = ", ";
        !           356:                }
        !           357:        }
        !           358:        if (ints & INTS_TIMEOUT)
        !           359:                printf("%sSPC select timeout error", sep);
        !           360:        if (ints & INTS_SRV_REQ)
        !           361:                printf("%sspurious SRV_REQ interrupt", sep);
        !           362:        if (ints & INTS_CMD_DONE)
        !           363:                printf("%sspurious CMD_DONE interrupt", sep);
        !           364:        if (ints & INTS_DISCON)
        !           365:                printf("%sspurious disconnect interrupt", sep);
        !           366:        if (ints & INTS_RESEL)
        !           367:                printf("%sspurious reselect interrupt", sep);
        !           368:        if (ints & INTS_SEL)
        !           369:                printf("%sspurious select interrupt", sep);
        !           370:        printf("\n");
        !           371: }
        !           372: 
        !           373: static int
        !           374: issue_select(hd, target, our_addr)
        !           375:        volatile register struct scsidevice *hd;
        !           376:        u_char target, our_addr;
        !           377: {
        !           378:        if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
        !           379:                return (1);
        !           380: 
        !           381:        if (hd->scsi_ints & INTS_DISCON)
        !           382:                hd->scsi_ints = INTS_DISCON;
        !           383: 
        !           384:        hd->scsi_pctl = 0;
        !           385:        hd->scsi_temp = (1 << target) | our_addr;
        !           386:        /* select timeout is hardcoded to 2ms */
        !           387:        hd->scsi_tch = 0;
        !           388:        hd->scsi_tcm = 32;
        !           389:        hd->scsi_tcl = 4;
        !           390: 
        !           391:        hd->scsi_scmd = SCMD_SELECT;
        !           392:        return (0);
        !           393: }
        !           394: 
        !           395: static int
        !           396: wait_for_select(hd)
        !           397:        volatile register struct scsidevice *hd;
        !           398: {
        !           399:        u_char ints;
        !           400: 
        !           401:        while ((ints = hd->scsi_ints) == 0)
        !           402:                DELAY(1);
        !           403:        hd->scsi_ints = ints;
        !           404:        return (!(hd->scsi_ssts & SSTS_INITIATOR));
        !           405: }
        !           406: 
        !           407: static int
        !           408: ixfer_start(hd, len, phase, wait)
        !           409:        volatile register struct scsidevice *hd;
        !           410:        int len;
        !           411:        u_char phase;
        !           412:        register int wait;
        !           413: {
        !           414: 
        !           415:        hd->scsi_tch = len >> 16;
        !           416:        hd->scsi_tcm = len >> 8;
        !           417:        hd->scsi_tcl = len;
        !           418:        hd->scsi_pctl = phase;
        !           419:        hd->scsi_tmod = 0; /*XXX*/
        !           420:        hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
        !           421: 
        !           422:        /* wait for xfer to start or svc_req interrupt */
        !           423:        while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
        !           424:                if (hd->scsi_ints || --wait < 0) {
        !           425: #ifdef DEBUG
        !           426:                        if (scsi_debug)
        !           427:                                printf("ixfer_start fail: i%x, w%d\n",
        !           428:                                       hd->scsi_ints, wait);
        !           429: #endif
        !           430:                        HIST(ixstart_wait, wait)
        !           431:                        return (0);
        !           432:                }
        !           433:                DELAY(1);
        !           434:        }
        !           435:        HIST(ixstart_wait, wait)
        !           436:        return (1);
        !           437: }
        !           438: 
        !           439: static int
        !           440: ixfer_out(hd, len, buf)
        !           441:        volatile register struct scsidevice *hd;
        !           442:        int len;
        !           443:        register u_char *buf;
        !           444: {
        !           445:        register int wait = scsi_data_wait;
        !           446: 
        !           447:        for (; len > 0; --len) {
        !           448:                while (hd->scsi_ssts & SSTS_DREG_FULL) {
        !           449:                        if (hd->scsi_ints || --wait < 0) {
        !           450: #ifdef DEBUG
        !           451:                                if (scsi_debug)
        !           452:                                        printf("ixfer_out fail: l%d i%x w%d\n",
        !           453:                                               len, hd->scsi_ints, wait);
        !           454: #endif
        !           455:                                HIST(ixout_wait, wait)
        !           456:                                return (len);
        !           457:                        }
        !           458:                        DELAY(1);
        !           459:                }
        !           460:                hd->scsi_dreg = *buf++;
        !           461:        }
        !           462:        HIST(ixout_wait, wait)
        !           463:        return (0);
        !           464: }
        !           465: 
        !           466: static void
        !           467: ixfer_in(hd, len, buf)
        !           468:        volatile register struct scsidevice *hd;
        !           469:        int len;
        !           470:        register u_char *buf;
        !           471: {
        !           472:        register int wait = scsi_data_wait;
        !           473: 
        !           474:        for (; len > 0; --len) {
        !           475:                while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
        !           476:                        if (hd->scsi_ints || --wait < 0) {
        !           477:                                while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
        !           478:                                        *buf++ = hd->scsi_dreg;
        !           479:                                        --len;
        !           480:                                }
        !           481: #ifdef DEBUG
        !           482:                                if (scsi_debug)
        !           483:                                        printf("ixfer_in fail: l%d i%x w%d\n",
        !           484:                                               len, hd->scsi_ints, wait);
        !           485: #endif
        !           486:                                HIST(ixin_wait, wait)
        !           487:                                return;
        !           488:                        }
        !           489:                        DELAY(1);
        !           490:                }
        !           491:                *buf++ = hd->scsi_dreg;
        !           492:        }
        !           493:        HIST(ixin_wait, wait)
        !           494: }
        !           495: 
        !           496: static int
        !           497: mxfer_in(hd, len, buf, phase)
        !           498:        volatile register struct scsidevice *hd;
        !           499:        register int len;
        !           500:        register u_char *buf;
        !           501:        register u_char phase;
        !           502: {
        !           503:        register int wait = scsi_cmd_wait;
        !           504:        register int i;
        !           505: 
        !           506:        hd->scsi_tmod = 0;
        !           507:        for (i = 0; i < len; ++i) {
        !           508:                /*
        !           509:                 * manual sez: reset ATN before ACK is sent.
        !           510:                 */
        !           511:                if (hd->scsi_psns & PSNS_ATN)
        !           512:                        hd->scsi_scmd = SCMD_RST_ATN;
        !           513:                /*
        !           514:                 * wait for the request line (which says the target
        !           515:                 * wants to give us data).  If the phase changes while
        !           516:                 * we're waiting, we're done.
        !           517:                 */
        !           518:                while ((hd->scsi_psns & PSNS_REQ) == 0) {
        !           519:                        if (--wait < 0) {
        !           520:                                HIST(mxin_wait, wait)
        !           521:                                return (-1);
        !           522:                        }
        !           523:                        if ((hd->scsi_psns & PHASE) != phase ||
        !           524:                            (hd->scsi_ssts & SSTS_INITIATOR) == 0)
        !           525:                                goto out;
        !           526: 
        !           527:                        DELAY(1);
        !           528:                }
        !           529:                /*
        !           530:                 * set ack (which says we're ready for the data, wait for
        !           531:                 * req to go away (target says data is available), grab the
        !           532:                 * data, then reset ack (say we've got the data).
        !           533:                 */
        !           534:                hd->scsi_pctl = phase;
        !           535:                hd->scsi_scmd = SCMD_SET_ACK;
        !           536:                while (hd->scsi_psns & PSNS_REQ) {
        !           537:                        if (--wait < 0) {
        !           538:                                HIST(mxin_wait, wait)
        !           539:                                return (-2);
        !           540:                        }
        !           541:                        DELAY(1);
        !           542:                }
        !           543:                *buf++ = hd->scsi_temp;
        !           544:                hd->scsi_scmd = SCMD_RST_ACK;
        !           545:        }
        !           546: out:
        !           547:        HIST(mxin_wait, wait)
        !           548:        /*
        !           549:         * Wait for manual transfer to finish.
        !           550:         * Avoids occasional "unexpected phase" errors in finishxfer
        !           551:         * formerly addressed by per-slave delays.
        !           552:         */
        !           553:        wait = scsi_cmd_wait;
        !           554:        while ((hd->scsi_ssts & SSTS_ACTIVE) == SSTS_INITIATOR) {
        !           555:                if (--wait < 0)
        !           556:                        break;
        !           557:                DELAY(1);
        !           558:        }
        !           559:        HIST(mxin2_wait, wait)
        !           560:        return (i);
        !           561: }
        !           562: 
        !           563: /*
        !           564:  * SCSI 'immediate' command:  issue a command to some SCSI device
        !           565:  * and get back an 'immediate' response (i.e., do programmed xfer
        !           566:  * to get the response data).  'cbuf' is a buffer containing a scsi
        !           567:  * command of length clen bytes.  'buf' is a buffer of length 'len'
        !           568:  * bytes for data.  The transfer direction is determined by the device
        !           569:  * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
        !           570:  * command must supply no data.  'xferphase' is the bus phase the
        !           571:  * caller expects to happen after the command is issued.  It should
        !           572:  * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
        !           573:  */
        !           574: static int
        !           575: scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
        !           576:        struct scsi_softc *hs;
        !           577:        int target;
        !           578:        u_char *cbuf;
        !           579:        int clen;
        !           580:        u_char *buf;
        !           581:        int len;
        !           582:        u_char xferphase;
        !           583: {
        !           584:        volatile register struct scsidevice *hd =
        !           585:                                (struct scsidevice *)hs->sc_hc->hp_addr;
        !           586:        u_char phase, ints;
        !           587:        register int wait;
        !           588: 
        !           589:        /* select the SCSI bus (it's an error if bus isn't free) */
        !           590:        if (issue_select(hd, target, hs->sc_scsi_addr))
        !           591:                return (-1);
        !           592:        if (wait_for_select(hd))
        !           593:                return (-1);
        !           594:        /*
        !           595:         * Wait for a phase change (or error) then let the device
        !           596:         * sequence us through the various SCSI phases.
        !           597:         */
        !           598:        hs->sc_stat[0] = 0xff;
        !           599:        hs->sc_msg[0] = 0xff;
        !           600:        phase = CMD_PHASE;
        !           601:        while (1) {
        !           602:                wait = scsi_cmd_wait;
        !           603:                switch (phase) {
        !           604: 
        !           605:                case CMD_PHASE:
        !           606:                        if (ixfer_start(hd, clen, phase, wait))
        !           607:                                if (ixfer_out(hd, clen, cbuf))
        !           608:                                        goto abort;
        !           609:                        phase = xferphase;
        !           610:                        break;
        !           611: 
        !           612:                case DATA_IN_PHASE:
        !           613:                        if (len <= 0)
        !           614:                                goto abort;
        !           615:                        wait = scsi_data_wait;
        !           616:                        if (ixfer_start(hd, len, phase, wait) ||
        !           617:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY))
        !           618:                                ixfer_in(hd, len, buf);
        !           619:                        phase = STATUS_PHASE;
        !           620:                        break;
        !           621: 
        !           622:                case DATA_OUT_PHASE:
        !           623:                        if (len <= 0)
        !           624:                                goto abort;
        !           625:                        wait = scsi_data_wait;
        !           626:                        if (ixfer_start(hd, len, phase, wait)) {
        !           627:                                if (ixfer_out(hd, len, buf))
        !           628:                                        goto abort;
        !           629:                        }
        !           630:                        phase = STATUS_PHASE;
        !           631:                        break;
        !           632: 
        !           633:                case STATUS_PHASE:
        !           634:                        wait = scsi_data_wait;
        !           635:                        if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
        !           636:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY))
        !           637:                                ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat);
        !           638:                        phase = MESG_IN_PHASE;
        !           639:                        break;
        !           640: 
        !           641:                case MESG_IN_PHASE:
        !           642:                        if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
        !           643:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
        !           644:                                ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
        !           645:                                hd->scsi_scmd = SCMD_RST_ACK;
        !           646:                        }
        !           647:                        phase = BUS_FREE_PHASE;
        !           648:                        break;
        !           649: 
        !           650:                case BUS_FREE_PHASE:
        !           651:                        goto out;
        !           652: 
        !           653:                default:
        !           654:                        printf("scsi%d: unexpected phase %d in icmd from %d\n",
        !           655:                                hs->sc_hc->hp_unit, phase, target);
        !           656:                        goto abort;
        !           657:                }
        !           658:                /* wait for last command to complete */
        !           659:                while ((ints = hd->scsi_ints) == 0) {
        !           660:                        if (--wait < 0) {
        !           661:                                HIST(cxin_wait, wait)
        !           662:                                goto abort;
        !           663:                        }
        !           664:                        DELAY(1);
        !           665:                }
        !           666:                HIST(cxin_wait, wait)
        !           667:                hd->scsi_ints = ints;
        !           668:                if (ints & INTS_SRV_REQ)
        !           669:                        phase = hd->scsi_psns & PHASE;
        !           670:                else if (ints & INTS_DISCON)
        !           671:                        goto out;
        !           672:                else if ((ints & INTS_CMD_DONE) == 0) {
        !           673:                        scsierror(hs, hd, ints);
        !           674:                        goto abort;
        !           675:                }
        !           676:        }
        !           677: abort:
        !           678:        scsiabort(hs, hd, "icmd");
        !           679: out:
        !           680:        return (hs->sc_stat[0]);
        !           681: }
        !           682: 
        !           683: /*
        !           684:  * Finish SCSI xfer command:  After the completion interrupt from
        !           685:  * a read/write operation, sequence through the final phases in
        !           686:  * programmed i/o.  This routine is a lot like scsiicmd except we
        !           687:  * skip (and don't allow) the select, cmd out and data in/out phases.
        !           688:  */
        !           689: static void
        !           690: finishxfer(hs, hd, target)
        !           691:        struct scsi_softc *hs;
        !           692:        volatile register struct scsidevice *hd;
        !           693:        int target;
        !           694: {
        !           695:        u_char phase, ints;
        !           696: 
        !           697:        /*
        !           698:         * We specified padding xfer so we ended with either a phase
        !           699:         * change interrupt (normal case) or an error interrupt (handled
        !           700:         * elsewhere).  Reset the board dma logic then try to get the
        !           701:         * completion status & command done msg.  The reset confuses
        !           702:         * the SPC REQ/ACK logic so we have to do any status/msg input
        !           703:         * operations via 'manual xfer'.
        !           704:         */
        !           705:        if (hd->scsi_ssts & SSTS_BUSY) {
        !           706:                int wait = scsi_cmd_wait;
        !           707: 
        !           708:                /* wait for dma operation to finish */
        !           709:                while (hd->scsi_ssts & SSTS_BUSY) {
        !           710:                        if (--wait < 0) {
        !           711: #ifdef DEBUG
        !           712:                                if (scsi_debug)
        !           713:                                        printf("finishxfer fail: ssts %x\n",
        !           714:                                               hd->scsi_ssts);
        !           715: #endif
        !           716:                                HIST(fxfr_wait, wait)
        !           717:                                goto abort;
        !           718:                        }
        !           719:                }
        !           720:                HIST(fxfr_wait, wait)
        !           721:        }
        !           722:        hd->scsi_scmd |= SCMD_PROG_XFR;
        !           723:        hd->scsi_sctl |= SCTL_CTRLRST;
        !           724:        DELAY(1);
        !           725:        hd->scsi_sctl &=~ SCTL_CTRLRST;
        !           726:        hd->scsi_hconf = 0;
        !           727:        hs->sc_stat[0] = 0xff;
        !           728:        hs->sc_msg[0] = 0xff;
        !           729:        hd->scsi_csr = 0;
        !           730:        hd->scsi_ints = ints = hd->scsi_ints;
        !           731:        while (1) {
        !           732:                phase = hd->scsi_psns & PHASE;
        !           733:                switch (phase) {
        !           734: 
        !           735:                case STATUS_PHASE:
        !           736:                        if (mxfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat,
        !           737:                                     phase) <= 0)
        !           738:                                goto abort;
        !           739:                        break;
        !           740: 
        !           741:                case MESG_IN_PHASE:
        !           742:                        if (mxfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg,
        !           743:                                     phase) < 0)
        !           744:                                goto abort;
        !           745:                        break;
        !           746: 
        !           747:                case BUS_FREE_PHASE:
        !           748:                        return;
        !           749: 
        !           750:                default:
        !           751:                        printf("scsi%d: unexpected phase %d in finishxfer from %d\n",
        !           752:                                hs->sc_hc->hp_unit, phase, target);
        !           753:                        goto abort;
        !           754:                }
        !           755:                if (ints = hd->scsi_ints) {
        !           756:                        hd->scsi_ints = ints;
        !           757:                        if (ints & INTS_DISCON)
        !           758:                                return;
        !           759:                        else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) {
        !           760:                                scsierror(hs, hd, ints);
        !           761:                                break;
        !           762:                        }
        !           763:                }
        !           764:                if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
        !           765:                        return;
        !           766:        }
        !           767: abort:
        !           768:        scsiabort(hs, hd, "finishxfer");
        !           769:        hs->sc_stat[0] = 0xfe;
        !           770: }
        !           771: 
        !           772: int
        !           773: scsi_test_unit_rdy(ctlr, slave, unit)
        !           774:        int ctlr, slave, unit;
        !           775: {
        !           776:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           777:        static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
        !           778: 
        !           779:        cdb.lun = unit;
        !           780:        return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
        !           781:                         STATUS_PHASE));
        !           782: }
        !           783: 
        !           784: int
        !           785: scsi_request_sense(ctlr, slave, unit, buf, len)
        !           786:        int ctlr, slave, unit;
        !           787:        u_char *buf;
        !           788:        unsigned len;
        !           789: {
        !           790:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           791:        static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
        !           792: 
        !           793:        cdb.lun = unit;
        !           794:        cdb.len = len;
        !           795:        return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
        !           796: }
        !           797: 
        !           798: int
        !           799: scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd)
        !           800:        int ctlr, slave, unit;
        !           801:        struct scsi_fmt_cdb *cdb;
        !           802:        u_char *buf;
        !           803:        unsigned len;
        !           804: {
        !           805:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           806: 
        !           807:        cdb->cdb[1] |= unit << 5;
        !           808:        return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len,
        !           809:                         rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE));
        !           810: }
        !           811: 
        !           812: /*
        !           813:  * The following routines are test-and-transfer i/o versions of read/write
        !           814:  * for things like reading disk labels and writing core dumps.  The
        !           815:  * routine scsigo should be used for normal data transfers, NOT these
        !           816:  * routines.
        !           817:  */
        !           818: int
        !           819: scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift)
        !           820:        int ctlr, slave, unit;
        !           821:        u_char *buf;
        !           822:        u_int len;
        !           823:        daddr_t blk;
        !           824:        int bshift;
        !           825: {
        !           826:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           827:        struct scsi_cdb10 cdb;
        !           828:        int stat;
        !           829:        int old_wait = scsi_data_wait;
        !           830: 
        !           831:        scsi_data_wait = 300000;
        !           832:        bzero(&cdb, sizeof(cdb));
        !           833:        cdb.cmd = CMD_READ_EXT;
        !           834:        cdb.lun = unit;
        !           835:        blk >>= bshift;
        !           836:        cdb.lbah = blk >> 24;
        !           837:        cdb.lbahm = blk >> 16;
        !           838:        cdb.lbalm = blk >> 8;
        !           839:        cdb.lbal = blk;
        !           840:        cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
        !           841:        cdb.lenl = len >> (DEV_BSHIFT + bshift);
        !           842:        stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
        !           843:        scsi_data_wait = old_wait;
        !           844:        return (stat);
        !           845: }
        !           846: 
        !           847: int
        !           848: scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift)
        !           849:        int ctlr, slave, unit;
        !           850:        u_char *buf;
        !           851:        u_int len;
        !           852:        daddr_t blk;
        !           853:        int bshift;
        !           854: {
        !           855:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           856:        struct scsi_cdb10 cdb;
        !           857:        int stat;
        !           858:        int old_wait = scsi_data_wait;
        !           859: 
        !           860:        scsi_data_wait = 300000;
        !           861: 
        !           862:        bzero(&cdb, sizeof(cdb));
        !           863:        cdb.cmd = CMD_WRITE_EXT;
        !           864:        cdb.lun = unit;
        !           865:        blk >>= bshift;
        !           866:        cdb.lbah = blk >> 24;
        !           867:        cdb.lbahm = blk >> 16;
        !           868:        cdb.lbalm = blk >> 8;
        !           869:        cdb.lbal = blk;
        !           870:        cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
        !           871:        cdb.lenl = len >> (DEV_BSHIFT + bshift);
        !           872:        stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
        !           873:        scsi_data_wait = old_wait;
        !           874:        return (stat);
        !           875: }
        !           876: 
        !           877: int
        !           878: scsireq(dq)
        !           879:        register struct devqueue *dq;
        !           880: {
        !           881:        register struct devqueue *hq;
        !           882: 
        !           883:        hq = &scsi_softc[dq->dq_ctlr].sc_sq;
        !           884:        insque(dq, hq->dq_back);
        !           885:        if (dq->dq_back == hq)
        !           886:                return(1);
        !           887:        return(0);
        !           888: }
        !           889: 
        !           890: int
        !           891: scsiustart(unit)
        !           892:        int unit;
        !           893: {
        !           894:        register struct scsi_softc *hs = &scsi_softc[unit];
        !           895: 
        !           896:        hs->sc_dq.dq_ctlr = DMA0 | DMA1;
        !           897:        if (dmareq(&hs->sc_dq))
        !           898:                return(1);
        !           899:        return(0);
        !           900: }
        !           901: 
        !           902: void
        !           903: scsistart(unit)
        !           904:        int unit;
        !           905: {
        !           906:        register struct devqueue *dq;
        !           907:        
        !           908:        dq = scsi_softc[unit].sc_sq.dq_forw;
        !           909:        (dq->dq_driver->d_go)(dq->dq_unit);
        !           910: }
        !           911: 
        !           912: int
        !           913: scsigo(ctlr, slave, unit, bp, cdb, pad)
        !           914:        int ctlr, slave, unit;
        !           915:        struct buf *bp;
        !           916:        struct scsi_fmt_cdb *cdb;
        !           917:        int pad;
        !           918: {
        !           919:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           920:        volatile register struct scsidevice *hd =
        !           921:                                (struct scsidevice *)hs->sc_hc->hp_addr;
        !           922:        int i, dmaflags;
        !           923:        u_char phase, ints, cmd;
        !           924: 
        !           925:        cdb->cdb[1] |= unit << 5;
        !           926: 
        !           927:        /* select the SCSI bus (it's an error if bus isn't free) */
        !           928:        if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) {
        !           929:                dmafree(&hs->sc_dq);
        !           930:                return (1);
        !           931:        }
        !           932:        /*
        !           933:         * Wait for a phase change (or error) then let the device
        !           934:         * sequence us through command phase (we may have to take
        !           935:         * a msg in/out before doing the command).  If the disk has
        !           936:         * to do a seek, it may be a long time until we get a change
        !           937:         * to data phase so, in the absense of an explicit phase
        !           938:         * change, we assume data phase will be coming up and tell
        !           939:         * the SPC to start a transfer whenever it does.  We'll get
        !           940:         * a service required interrupt later if this assumption is
        !           941:         * wrong.  Otherwise we'll get a service required int when
        !           942:         * the transfer changes to status phase.
        !           943:         */
        !           944:        phase = CMD_PHASE;
        !           945:        while (1) {
        !           946:                register int wait = scsi_cmd_wait;
        !           947: 
        !           948:                switch (phase) {
        !           949: 
        !           950:                case CMD_PHASE:
        !           951:                        if (ixfer_start(hd, cdb->len, phase, wait))
        !           952:                                if (ixfer_out(hd, cdb->len, cdb->cdb))
        !           953:                                        goto abort;
        !           954:                        break;
        !           955: 
        !           956:                case MESG_IN_PHASE:
        !           957:                        if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)||
        !           958:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
        !           959:                                ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg);
        !           960:                                hd->scsi_scmd = SCMD_RST_ACK;
        !           961:                        }
        !           962:                        phase = BUS_FREE_PHASE;
        !           963:                        break;
        !           964: 
        !           965:                case DATA_IN_PHASE:
        !           966:                case DATA_OUT_PHASE:
        !           967:                        goto out;
        !           968: 
        !           969:                default:
        !           970:                        printf("scsi%d: unexpected phase %d in go from %d\n",
        !           971:                                hs->sc_hc->hp_unit, phase, slave);
        !           972:                        goto abort;
        !           973:                }
        !           974:                while ((ints = hd->scsi_ints) == 0) {
        !           975:                        if (--wait < 0) {
        !           976:                                HIST(sgo_wait, wait)
        !           977:                                goto abort;
        !           978:                        }
        !           979:                        DELAY(1);
        !           980:                }
        !           981:                HIST(sgo_wait, wait)
        !           982:                hd->scsi_ints = ints;
        !           983:                if (ints & INTS_SRV_REQ)
        !           984:                        phase = hd->scsi_psns & PHASE;
        !           985:                else if (ints & INTS_CMD_DONE)
        !           986:                        goto out;
        !           987:                else {
        !           988:                        scsierror(hs, hd, ints);
        !           989:                        goto abort;
        !           990:                }
        !           991:        }
        !           992: out:
        !           993:        /*
        !           994:         * Reset the card dma logic, setup the dma channel then
        !           995:         * get the dio part of the card set for a dma xfer.
        !           996:         */
        !           997:        hd->scsi_hconf = 0;
        !           998:        cmd = CSR_IE;
        !           999:        dmaflags = DMAGO_NOINT;
        !          1000:        if (scsi_pridma)
        !          1001:                dmaflags |= DMAGO_PRI;
        !          1002:        if (bp->b_flags & B_READ)
        !          1003:                dmaflags |= DMAGO_READ;
        !          1004:        if ((hs->sc_flags & SCSI_DMA32) &&
        !          1005:            ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) {
        !          1006:                cmd |= CSR_DMA32;
        !          1007:                dmaflags |= DMAGO_LWORD;
        !          1008:        } else
        !          1009:                dmaflags |= DMAGO_WORD;
        !          1010:        dmago(hs->sc_dq.dq_ctlr, bp->b_un.b_addr, bp->b_bcount, dmaflags);
        !          1011: 
        !          1012:        if (bp->b_flags & B_READ) {
        !          1013:                cmd |= CSR_DMAIN;
        !          1014:                phase = DATA_IN_PHASE;
        !          1015:        } else
        !          1016:                phase = DATA_OUT_PHASE;
        !          1017:        /*
        !          1018:         * DMA enable bits must be set after size and direction bits.
        !          1019:         */
        !          1020:        hd->scsi_csr = cmd;
        !          1021:        hd->scsi_csr |= (CSR_DE0 << hs->sc_dq.dq_ctlr);
        !          1022:        /*
        !          1023:         * Setup the SPC for the transfer.  We don't want to take
        !          1024:         * first a command complete then a service required interrupt
        !          1025:         * at the end of the transfer so we try to disable the cmd
        !          1026:         * complete by setting the transfer counter to more bytes
        !          1027:         * than we expect.  (XXX - This strategy may have to be
        !          1028:         * modified to deal with devices that return variable length
        !          1029:         * blocks, e.g., some tape drives.)
        !          1030:         */
        !          1031:        cmd = SCMD_XFR;
        !          1032:        i = (unsigned)bp->b_bcount;
        !          1033:        if (pad) {
        !          1034:                cmd |= SCMD_PAD;
        !          1035:                /*
        !          1036:                 * XXX - If we don't do this, the last 2 or 4 bytes
        !          1037:                 * (depending on word/lword DMA) of a read get trashed.
        !          1038:                 * It looks like it is necessary for the DMA to complete
        !          1039:                 * before the SPC goes into "pad mode"???  Note: if we
        !          1040:                 * also do this on a write, the request never completes.
        !          1041:                 */
        !          1042:                if (bp->b_flags & B_READ)
        !          1043:                        i += 2;
        !          1044: #ifdef DEBUG
        !          1045:                hs->sc_flags |= SCSI_PAD;
        !          1046:                if (i & 1)
        !          1047:                        printf("scsi%d: odd byte count: %d bytes @ %d\n",
        !          1048:                                ctlr, i, bp->b_cylin);
        !          1049: #endif
        !          1050:        } else
        !          1051:                i += 4;
        !          1052:        hd->scsi_tch = i >> 16;
        !          1053:        hd->scsi_tcm = i >> 8;
        !          1054:        hd->scsi_tcl = i;
        !          1055:        hd->scsi_pctl = phase;
        !          1056:        hd->scsi_tmod = 0;
        !          1057:        hd->scsi_scmd = cmd;
        !          1058:        hs->sc_flags |= SCSI_IO;
        !          1059:        return (0);
        !          1060: abort:
        !          1061:        scsiabort(hs, hd, "go");
        !          1062:        dmafree(&hs->sc_dq);
        !          1063:        return (1);
        !          1064: }
        !          1065: 
        !          1066: void
        !          1067: scsidone(unit)
        !          1068:        register int unit;
        !          1069: {
        !          1070:        volatile register struct scsidevice *hd =
        !          1071:                        (struct scsidevice *)scsi_softc[unit].sc_hc->hp_addr;
        !          1072: 
        !          1073: #ifdef DEBUG
        !          1074:        if (scsi_debug)
        !          1075:                printf("scsi%d: done called!\n");
        !          1076: #endif
        !          1077:        /* dma operation is done -- turn off card dma */
        !          1078:        hd->scsi_csr &=~ (CSR_DE1|CSR_DE0);
        !          1079: }
        !          1080: 
        !          1081: int
        !          1082: scsiintr(unit)
        !          1083:        register int unit;
        !          1084: {
        !          1085:        register struct scsi_softc *hs = &scsi_softc[unit];
        !          1086:        volatile register struct scsidevice *hd =
        !          1087:                                (struct scsidevice *)hs->sc_hc->hp_addr;
        !          1088:        register u_char ints;
        !          1089:        register struct devqueue *dq;
        !          1090: 
        !          1091:        if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR))
        !          1092:                return (0);
        !          1093: 
        !          1094:        ints = hd->scsi_ints;
        !          1095:        if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) {
        !          1096:                /*
        !          1097:                 * this should be the normal i/o completion case.
        !          1098:                 * get the status & cmd complete msg then let the
        !          1099:                 * device driver look at what happened.
        !          1100:                 */
        !          1101: #ifdef DEBUG
        !          1102:                int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) |
        !          1103:                          hd->scsi_tcl;
        !          1104:                if (!(hs->sc_flags & SCSI_PAD))
        !          1105:                        len -= 4;
        !          1106:                hs->sc_flags &=~ SCSI_PAD;
        !          1107: #endif
        !          1108:                dq = hs->sc_sq.dq_forw;
        !          1109:                finishxfer(hs, hd, dq->dq_slave);
        !          1110:                hs->sc_flags &=~ SCSI_IO;
        !          1111:                dmafree(&hs->sc_dq);
        !          1112:                (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat[0]);
        !          1113:        } else {
        !          1114:                /* Something unexpected happened -- deal with it. */
        !          1115:                hd->scsi_ints = ints;
        !          1116:                hd->scsi_csr = 0;
        !          1117:                scsierror(hs, hd, ints);
        !          1118:                scsiabort(hs, hd, "intr");
        !          1119:                if (hs->sc_flags & SCSI_IO) {
        !          1120:                        hs->sc_flags &=~ SCSI_IO;
        !          1121:                        dmafree(&hs->sc_dq);
        !          1122:                        dq = hs->sc_sq.dq_forw;
        !          1123:                        (dq->dq_driver->d_intr)(dq->dq_unit, -1);
        !          1124:                }
        !          1125:        }
        !          1126:        return(1);
        !          1127: }
        !          1128: 
        !          1129: void
        !          1130: scsifree(dq)
        !          1131:        register struct devqueue *dq;
        !          1132: {
        !          1133:        register struct devqueue *hq;
        !          1134: 
        !          1135:        hq = &scsi_softc[dq->dq_ctlr].sc_sq;
        !          1136:        remque(dq);
        !          1137:        if ((dq = hq->dq_forw) != hq)
        !          1138:                (dq->dq_driver->d_start)(dq->dq_unit);
        !          1139: }
        !          1140: 
        !          1141: /*
        !          1142:  * (XXX) The following routine is needed for the SCSI tape driver
        !          1143:  * to read odd-size records.
        !          1144:  */
        !          1145: 
        !          1146: #include "st.h"
        !          1147: #if NST > 0
        !          1148: int
        !          1149: scsi_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma)
        !          1150:        int ctlr, slave, unit, b_flags;
        !          1151:        u_char *buf;
        !          1152:        u_int len;
        !          1153: {
        !          1154:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !          1155:        struct scsi_cdb6 cdb;
        !          1156:        u_char iphase;
        !          1157:        int stat;
        !          1158: 
        !          1159:        /*
        !          1160:         * First free any DMA channel that was allocated.
        !          1161:         * We can't use DMA to do this transfer.
        !          1162:         */
        !          1163:        if (freedma)
        !          1164:                dmafree(hs->sc_dq);
        !          1165:        /*
        !          1166:         * Initialize command block
        !          1167:         */
        !          1168:        bzero(&cdb, sizeof(cdb));
        !          1169:        cdb.lun = unit;
        !          1170:        cdb.lbam = (len >> 16) & 0xff;
        !          1171:        cdb.lbal = (len >> 8) & 0xff;
        !          1172:        cdb.len = len & 0xff;
        !          1173:        if (buf == 0) {
        !          1174:                cdb.cmd = CMD_SPACE;
        !          1175:                cdb.lun |= 0x00;
        !          1176:                len = 0;
        !          1177:                iphase = MESG_IN_PHASE;
        !          1178:        } else if (b_flags & B_READ) {
        !          1179:                cdb.cmd = CMD_READ;
        !          1180:                iphase = DATA_IN_PHASE;
        !          1181:        } else {
        !          1182:                cdb.cmd = CMD_WRITE;
        !          1183:                iphase = DATA_OUT_PHASE;
        !          1184:        }
        !          1185:        /*
        !          1186:         * Perform command (with very long delays)
        !          1187:         */
        !          1188:        scsi_delay(30000000);
        !          1189:        stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, iphase);
        !          1190:        scsi_delay(0);
        !          1191:        return (stat);
        !          1192: }
        !          1193: #endif
        !          1194: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.