Annotation of Net2/arch/amiga/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:  * AMIGA AMD 33C93 scsi adaptor driver
        !            41:  */
        !            42: #include "scsi.h"
        !            43: #if NSCSI > 0
        !            44: 
        !            45: #ifndef lint
        !            46: static char rcsid[] = "/b/source/CVS/src/sys/arch/amiga/dev/scsi.c,v 1.1.1.1 1993/07/05 19:19:44 mw 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: #include "dmareg.h"
        !            58: 
        !            59: #include "../amiga/custom.h"
        !            60: 
        !            61: #include "machine/cpu.h"
        !            62: 
        !            63: static int sbic_wait (volatile sbic_padded_regmap_t *regs, char until, int timeo, int line);
        !            64: static void scsiabort (register struct scsi_softc *dev, register volatile sbic_padded_regmap_t *regs, char *where);
        !            65: static void scsierror (register struct scsi_softc *dev, register volatile sbic_padded_regmap_t *regs, u_char csr);
        !            66: static int issue_select (register volatile sbic_padded_regmap_t *regs, u_char target, u_char our_addr);
        !            67: static int wait_for_select (register volatile sbic_padded_regmap_t *regs);
        !            68: static int ixfer_start (register volatile sbic_padded_regmap_t *regs, int len, u_char phase, register int wait);
        !            69: static int ixfer_out (register volatile sbic_padded_regmap_t *regs, int len, register u_char *buf, int phase);
        !            70: static void ixfer_in (register volatile sbic_padded_regmap_t *regs, int len, register u_char *buf);
        !            71: static int scsiicmd (struct scsi_softc *dev, int target, u_char *cbuf, int clen, u_char *buf, int len, u_char xferphase);
        !            72: static void finishxfer (struct scsi_softc *dev, register volatile sbic_padded_regmap_t *regs, int target);
        !            73: 
        !            74: 
        !            75: 
        !            76: /*
        !            77:  * SCSI delays
        !            78:  * In u-seconds, primarily for state changes on the SPC.
        !            79:  */
        !            80: #define        SCSI_CMD_WAIT   1000    /* wait per step of 'immediate' cmds */
        !            81: #define        SCSI_DATA_WAIT  1000    /* wait per data in/out step */
        !            82: #define        SCSI_INIT_WAIT  50000   /* wait per step (both) during init */
        !            83: 
        !            84: extern void _insque();
        !            85: extern void _remque();
        !            86: 
        !            87: int    scsiinit(), scsigo(), scsiintr(), scsixfer();
        !            88: void   scsistart(), scsidone(), scsifree(), scsireset();
        !            89: struct driver scsidriver = {
        !            90:        scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr,
        !            91:        (int (*)())scsidone,
        !            92: };
        !            93: 
        !            94: struct scsi_softc scsi_softc;
        !            95: 
        !            96: int scsi_cmd_wait = SCSI_CMD_WAIT;
        !            97: int scsi_data_wait = SCSI_DATA_WAIT;
        !            98: int scsi_init_wait = SCSI_INIT_WAIT;
        !            99: 
        !           100: int scsi_nosync = 1;           /* inhibit sync xfers if 1 */
        !           101: 
        !           102: /* these devices want to be reset before first data transfer access.
        !           103:    This is site specific, you'll know when your drive locks up because it's
        !           104:    still using AmigaDOS sync values... */
        !           105: static u_char reset_devices[] = { 1, 1, 0, 0, 0, 1, 1, 0 };
        !           106: 
        !           107: 
        !           108: #ifdef DEBUG
        !           109: int    scsi_debug = 0;
        !           110: #define WAITHIST
        !           111: #define QUASEL 
        !           112: #endif
        !           113: 
        !           114: #ifdef QUASEL
        !           115: #define QPRINTF(a) if (scsi_debug) printf a
        !           116: #else
        !           117: #define QPRINTF
        !           118: #endif
        !           119: 
        !           120: #ifdef WAITHIST
        !           121: #define MAXWAIT        1022
        !           122: u_int  ixstart_wait[MAXWAIT+2];
        !           123: u_int  ixin_wait[MAXWAIT+2];
        !           124: u_int  ixout_wait[MAXWAIT+2];
        !           125: u_int  mxin_wait[MAXWAIT+2];
        !           126: u_int  mxin2_wait[MAXWAIT+2];
        !           127: u_int  cxin_wait[MAXWAIT+2];
        !           128: u_int  fxfr_wait[MAXWAIT+2];
        !           129: u_int  sgo_wait[MAXWAIT+2];
        !           130: #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]);
        !           131: #else
        !           132: #define HIST(h,w)
        !           133: #endif
        !           134: 
        !           135: #define        b_cylin         b_resid
        !           136: 
        !           137: static sbic_wait (regs, until, timeo, line)
        !           138:     volatile sbic_padded_regmap_t *regs;
        !           139:     char                        until;
        !           140:     int                                timeo;
        !           141:     int                                line;
        !           142: {
        !           143:   register unsigned char        val;
        !           144: 
        !           145:   if (! timeo)
        !           146:     timeo = 1000000;   /* some large value.. */
        !           147: 
        !           148:   GET_SBIC_asr (regs,val);
        !           149:   while ((val & until) == 0) 
        !           150:     {
        !           151:       if (!timeo--) 
        !           152:         {
        !           153:          int csr;
        !           154:          GET_SBIC_csr (regs, csr);
        !           155:           printf("sbic_wait TIMEO @%d with asr=x%x csr=x%x\n", line, val, csr);
        !           156:           break;
        !           157:         }
        !           158:       DELAY(1);
        !           159:       GET_SBIC_asr(regs,val);
        !           160:     }
        !           161:   return val;
        !           162: }
        !           163: 
        !           164: #define SBIC_WAIT(regs, until, timeo) sbic_wait (regs, until, timeo, __LINE__)
        !           165: 
        !           166: 
        !           167: static void
        !           168: scsiabort(dev, regs, where)
        !           169:        register struct scsi_softc *dev;
        !           170:        volatile register sbic_padded_regmap_t *regs;
        !           171:        char *where;
        !           172: {
        !           173:   u_char csr, asr;
        !           174:   
        !           175:   GET_SBIC_csr (regs, csr);
        !           176:   GET_SBIC_asr (regs, asr);
        !           177: 
        !           178:   printf ("scsi: abort %s: csr = 0x%02x, asr = 0x%02x\n", where, csr, asr);
        !           179: 
        !           180:   if (dev->sc_flags & SCSI_SELECTED)
        !           181:     {
        !           182:       SET_SBIC_cmd (regs, SBIC_CMD_ABORT);
        !           183:       WAIT_CIP (regs);
        !           184: 
        !           185:       GET_SBIC_asr (regs, asr);
        !           186:       if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI))
        !           187:         {
        !           188:           /* ok, get more drastic.. */
        !           189:           
        !           190:          SET_SBIC_cmd (regs, SBIC_CMD_RESET);
        !           191:          DELAY(25);
        !           192:          SBIC_WAIT(regs, SBIC_ASR_INT, 0);
        !           193:          GET_SBIC_csr (regs, csr);       /* clears interrupt also */
        !           194: 
        !           195:           dev->sc_flags &= ~SCSI_SELECTED;
        !           196:           return;
        !           197:         }
        !           198: 
        !           199:       do
        !           200:         {
        !           201:           SBIC_WAIT (regs, SBIC_ASR_INT, 0);
        !           202:           GET_SBIC_csr (regs, csr);
        !           203:         }
        !           204:       while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
        !           205:              && (csr != SBIC_CSR_CMD_INVALID));
        !           206:              
        !           207:       /* lets just hope it worked.. */
        !           208:       dev->sc_flags &= ~SCSI_SELECTED;
        !           209:     }
        !           210: }
        !           211: 
        !           212: /*
        !           213:  * XXX Set/reset long delays.
        !           214:  *
        !           215:  * if delay == 0, reset default delays
        !           216:  * if delay < 0,  set both delays to default long initialization values
        !           217:  * if delay > 0,  set both delays to this value
        !           218:  *
        !           219:  * Used when a devices is expected to respond slowly (e.g. during
        !           220:  * initialization).
        !           221:  */
        !           222: void
        !           223: scsi_delay(delay)
        !           224:        int delay;
        !           225: {
        !           226:        static int saved_cmd_wait, saved_data_wait;
        !           227: 
        !           228:        if (delay) {
        !           229:                saved_cmd_wait = scsi_cmd_wait;
        !           230:                saved_data_wait = scsi_data_wait;
        !           231:                if (delay > 0)
        !           232:                        scsi_cmd_wait = scsi_data_wait = delay;
        !           233:                else
        !           234:                        scsi_cmd_wait = scsi_data_wait = scsi_init_wait;
        !           235:        } else {
        !           236:                scsi_cmd_wait = saved_cmd_wait;
        !           237:                scsi_data_wait = saved_data_wait;
        !           238:        }
        !           239: }
        !           240: 
        !           241: int
        !           242: scsiinit(ac)
        !           243:        register struct amiga_ctlr *ac;
        !           244: {
        !           245:   register struct scsi_softc *dev = &scsi_softc;
        !           246:   register sbic_padded_regmap_t *regs;
        !           247:   extern void *SCSI_address;
        !           248:   static int initialized = 0;
        !           249: 
        !           250:   if (initialized)
        !           251:     return 0;
        !           252:  
        !           253:   initialized = 1;
        !           254:   
        !           255:   SDMAC_setup ();
        !           256:   ac->amiga_addr = (caddr_t) regs = (sbic_padded_regmap_t *) SCSI_address;
        !           257: 
        !           258:   /* hardwired IPL */
        !           259:   ac->amiga_ipl = 2;
        !           260:   dev->sc_ac = ac;
        !           261:   dev->sc_dq.dq_driver = &scsidriver;
        !           262:   dev->sc_sq.dq_forw = dev->sc_sq.dq_back = &dev->sc_sq;
        !           263:   scsireset ();
        !           264: 
        !           265:   /* make sure IPL2 interrupts are delivered to the cpu when the sbic
        !           266:      generates some. Note that this does not yet enable sbic-interrupts,
        !           267:      this is handled in dma.c, which selectively enables interrupts only
        !           268:      while DMA requests are pending.
        !           269:      
        !           270:      Note that enabling PORTS interrupts also enables keyboard interrupts
        !           271:      as soon as the corresponding int-enable bit in CIA-A is set. */
        !           272:      
        !           273:   custom.intreq = INTF_PORTS;
        !           274:   custom.intena = INTF_SETCLR | INTF_PORTS;
        !           275:   return(1);
        !           276: }
        !           277: 
        !           278: void
        !           279: scsireset()
        !           280: {
        !           281:   register struct scsi_softc *dev = &scsi_softc;
        !           282:   volatile register sbic_padded_regmap_t *regs =
        !           283:                                (sbic_padded_regmap_t *)dev->sc_ac->amiga_addr;
        !           284:   u_int i, s;
        !           285:   u_char  my_id, csr;
        !           286: 
        !           287:   if (dev->sc_flags & SCSI_ALIVE)
        !           288:     scsiabort(dev, regs, "reset");
        !           289:                
        !           290:   printf("scsi: ");
        !           291: 
        !           292:   /* preserve our ID for now */
        !           293:   GET_SBIC_myid (regs, my_id);
        !           294:   my_id &= SBIC_ID_MASK;
        !           295: 
        !           296:   if (SBIC_CLOCK_FREQUENCY < 110)
        !           297:     my_id |= SBIC_ID_FS_8_10;
        !           298:   else if (SBIC_CLOCK_FREQUENCY < 160)
        !           299:     my_id |= SBIC_ID_FS_12_15;
        !           300:   else if (SBIC_CLOCK_FREQUENCY < 210)
        !           301:     my_id |= SBIC_ID_FS_16_20;
        !           302: 
        !           303:   my_id |= SBIC_ID_EAF/* |SBIC_ID_EHP*/;
        !           304: 
        !           305:   SET_SBIC_myid (regs, my_id);
        !           306: 
        !           307:   /*
        !           308:    * Disable interrupts (in dmainit) then reset the chip
        !           309:    */
        !           310:   SET_SBIC_cmd (regs, SBIC_CMD_RESET);
        !           311:   DELAY(25);
        !           312:   SBIC_WAIT(regs, SBIC_ASR_INT, 0);
        !           313:   GET_SBIC_csr (regs, csr);       /* clears interrupt also */
        !           314: 
        !           315:   /*
        !           316:    * Set up various chip parameters
        !           317:    */
        !           318:   SET_SBIC_control (regs, (/*SBIC_CTL_HHP |*/ SBIC_CTL_EDI | SBIC_CTL_IDI |
        !           319:                            /* | SBIC_CTL_HSP | */ SBIC_MACHINE_DMA_MODE));
        !           320:   /* don't allow (re)selection (SBIC_RID_ES) until we can handle target mode!! */
        !           321:   SET_SBIC_rselid (regs, 0 /* | SBIC_RID_ER | SBIC_RID_ES | SBIC_RID_DSP */);
        !           322:   SET_SBIC_syn (regs, 0);     /* asynch for now */
        !           323: 
        !           324:   /* anything else was zeroed by reset */
        !           325: 
        !           326:   /* go async for now */
        !           327:   dev->sc_sync = 0;
        !           328:   printf ("async");
        !           329: 
        !           330:   printf(", scsi id %d\n", my_id & SBIC_ID_MASK);
        !           331:   dev->sc_flags |= SCSI_ALIVE;
        !           332:   dev->sc_flags &= ~SCSI_SELECTED;
        !           333: }
        !           334: 
        !           335: static void
        !           336: scsierror(dev, regs, csr)
        !           337:        register struct scsi_softc *dev;
        !           338:        volatile register sbic_padded_regmap_t *regs;
        !           339:        u_char csr;
        !           340: {
        !           341:        char *sep = "";
        !           342: 
        !           343:        printf("scsi: ");
        !           344: #if 0
        !           345:        if (ints & INTS_RST) {
        !           346:                DELAY(100);
        !           347:                if (regs->scsi_aconf & HCONF_SD)
        !           348:                        printf("spurious RST interrupt");
        !           349:                else
        !           350:                        printf("hardware error - check fuse");
        !           351:                sep = ", ";
        !           352:        }
        !           353:        if ((ints & INTS_HARD_ERR) || regs->scsi_serr) {
        !           354:                if (regs->scsi_serr & SERR_SCSI_PAR) {
        !           355:                        printf("%sparity err", sep);
        !           356:                        sep = ", ";
        !           357:                }
        !           358:                if (regs->scsi_serr & SERR_SPC_PAR) {
        !           359:                        printf("%sSPC parity err", sep);
        !           360:                        sep = ", ";
        !           361:                }
        !           362:                if (regs->scsi_serr & SERR_TC_PAR) {
        !           363:                        printf("%sTC parity err", sep);
        !           364:                        sep = ", ";
        !           365:                }
        !           366:                if (regs->scsi_serr & SERR_PHASE_ERR) {
        !           367:                        printf("%sphase err", sep);
        !           368:                        sep = ", ";
        !           369:                }
        !           370:                if (regs->scsi_serr & SERR_SHORT_XFR) {
        !           371:                        printf("%ssync short transfer err", sep);
        !           372:                        sep = ", ";
        !           373:                }
        !           374:                if (regs->scsi_serr & SERR_OFFSET) {
        !           375:                        printf("%ssync offset error", sep);
        !           376:                        sep = ", ";
        !           377:                }
        !           378:        }
        !           379:        if (ints & INTS_TIMEOUT)
        !           380:                printf("%sSPC select timeout error", sep);
        !           381:        if (ints & INTS_SRV_REQ)
        !           382:                printf("%sspurious SRV_REQ interrupt", sep);
        !           383:        if (ints & INTS_CMD_DONE)
        !           384:                printf("%sspurious CMD_DONE interrupt", sep);
        !           385:        if (ints & INTS_DISCON)
        !           386:                printf("%sspurious disconnect interrupt", sep);
        !           387:        if (ints & INTS_RESEL)
        !           388:                printf("%sspurious reselect interrupt", sep);
        !           389:        if (ints & INTS_SEL)
        !           390:                printf("%sspurious select interrupt", sep);
        !           391: #else
        !           392:        printf ("csr == 0x%02x", csr);  /* XXX */
        !           393: #endif
        !           394:        printf("\n");
        !           395: }
        !           396: 
        !           397: static int
        !           398: issue_select(regs, target, our_addr)
        !           399:        volatile register sbic_padded_regmap_t *regs;
        !           400:        u_char target, our_addr;
        !           401: {
        !           402:   u_char  asr, csr;
        !           403: 
        !           404:   QPRINTF (("issue_select %d\n", target));
        !           405: 
        !           406:   /* if we're already selected, return */
        !           407:   if (scsi_softc.sc_flags & SCSI_SELECTED)     /* XXXX */
        !           408:     return 1;
        !           409:   
        !           410:   SBIC_TC_PUT (regs, 0);
        !           411:   SET_SBIC_selid (regs, target);
        !           412:   SET_SBIC_timeo (regs, SBIC_TIMEOUT(250,SBIC_CLOCK_FREQUENCY));
        !           413:   SET_SBIC_cmd (regs, SBIC_CMD_SEL_ATN);
        !           414: 
        !           415:   return (0);
        !           416: }
        !           417: 
        !           418: static int
        !           419: wait_for_select(regs)
        !           420:        volatile register sbic_padded_regmap_t *regs;
        !           421: {
        !           422:   u_char  asr, csr;
        !           423: 
        !           424:   QPRINTF (("wait_for_select: "));
        !           425: 
        !           426:   WAIT_CIP (regs);
        !           427:   do
        !           428:     {
        !           429:       SBIC_WAIT (regs, SBIC_ASR_INT, 0);
        !           430:       GET_SBIC_csr (regs, csr);
        !           431:       QPRINTF (("%02x ", csr));
        !           432:     }
        !           433:   while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE)
        !           434:         && csr != SBIC_CSR_SEL_TIMEO);
        !           435: 
        !           436:   /* Send identify message (SCSI-2 requires an identify msg (?)) */
        !           437:   if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE))
        !           438:     {
        !           439:       /* to get rid of amigados sync-settings... a bit kludgy I know.. */
        !           440:       static char sent_reset[8];
        !           441:       int id;
        !           442:       
        !           443:       GET_SBIC_selid (regs, id);
        !           444:       id &= 7;
        !           445:       if (reset_devices[id] && ! sent_reset [id])
        !           446:         {
        !           447:          /* prevent endless recursion.. */
        !           448:           sent_reset[id] = 1;
        !           449:           
        !           450:          SEND_BYTE (regs, MSG_BUS_DEVICE_RESET);
        !           451:          do
        !           452:            {
        !           453:              SBIC_WAIT (regs, SBIC_ASR_INT, 0);
        !           454:              GET_SBIC_csr (regs, csr);
        !           455:            }
        !           456:          while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1));
        !           457:          /* give the device 5s time to get back to life.. might be
        !           458:             too long for many drives, and certainly too short for others,
        !           459:             sigh.. */
        !           460:          DELAY(5000000);
        !           461:          QPRINTF (("[%02x]", csr));
        !           462:          while (issue_select (regs, id, 7) == 1)
        !           463:            {
        !           464:              printf ("select failed, retrying...\n");
        !           465:              DELAY(1000);
        !           466:            }
        !           467:          wait_for_select (regs);
        !           468:         }
        !           469: 
        !           470:       SEND_BYTE (regs, MSG_IDENTIFY);  /* no MSG_IDENTIFY_DR yet */
        !           471:       SBIC_WAIT (regs, SBIC_ASR_INT, 0);
        !           472:       GET_SBIC_csr (regs, csr);
        !           473:       QPRINTF (("[%02x]", csr));
        !           474: 
        !           475:       scsi_softc.sc_flags |= SCSI_SELECTED;
        !           476:     }
        !           477:   
        !           478:   QPRINTF(("\n"));
        !           479: 
        !           480:   return csr == SBIC_CSR_SEL_TIMEO;
        !           481: }
        !           482: 
        !           483: static int
        !           484: ixfer_start(regs, len, phase, wait)
        !           485:        volatile register sbic_padded_regmap_t *regs;
        !           486:        int len;
        !           487:        u_char phase;
        !           488:        register int wait;
        !           489: {
        !           490: #if 0
        !           491:        regs->scsi_tch = len >> 16;
        !           492:        regs->scsi_tcm = len >> 8;
        !           493:        regs->scsi_tcl = len;
        !           494:        regs->scsi_pctl = phase;
        !           495:        regs->scsi_tmod = 0; /*XXX*/
        !           496:        regs->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
        !           497: 
        !           498:        /* wait for xfer to start or svc_req interrupt */
        !           499:        while ((regs->scsi_ssts & SSTS_BUSY) == 0) {
        !           500:                if (regs->scsi_ints || --wait < 0) {
        !           501: #ifdef DEBUG
        !           502:                        if (scsi_debug)
        !           503:                                printf("ixfer_start fail: i%x, w%d\n",
        !           504:                                       regs->scsi_ints, wait);
        !           505: #endif
        !           506:                        HIST(ixstart_wait, wait)
        !           507:                        return (0);
        !           508:                }
        !           509:                DELAY(1);
        !           510:        }
        !           511:        HIST(ixstart_wait, wait)
        !           512:        return (1);
        !           513: #else
        !           514:        if (phase == DATA_IN_PHASE || phase == MESG_IN_PHASE)
        !           515:          {
        !           516:            u_char id;
        !           517: 
        !           518:            GET_SBIC_selid (regs, id);
        !           519:            id |= SBIC_SID_FROM_SCSI;
        !           520:            SET_SBIC_selid (regs, id);
        !           521:            
        !           522:            SBIC_TC_PUT (regs, (unsigned)len);
        !           523:          }
        !           524:        else if (phase == DATA_OUT_PHASE || phase == MESG_OUT_PHASE 
        !           525:                 || phase == CMD_PHASE )
        !           526:          {
        !           527:            SBIC_TC_PUT (regs, (unsigned)len);
        !           528:          }
        !           529:        else
        !           530:          { 
        !           531:            SBIC_TC_PUT (regs, 0);
        !           532:          }
        !           533:   
        !           534:        QPRINTF(("ixfer_start %d, %d, %d\n", len, phase, wait));
        !           535: 
        !           536:        return 1;
        !           537: #endif
        !           538: }
        !           539: 
        !           540: static int
        !           541: ixfer_out(regs, len, buf, phase)
        !           542:        volatile register sbic_padded_regmap_t *regs;
        !           543:        int len;
        !           544:        register u_char *buf;
        !           545:        int phase;
        !           546: {
        !           547:   register int wait = scsi_data_wait;
        !           548:   u_char orig_csr, csr, asr;
        !           549: 
        !           550:   QPRINTF(("ixfer_out {%d} %02x %02x %02x %02x %02x %02x\n", 
        !           551:           len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]));
        !           552: 
        !           553:   GET_SBIC_csr (regs, orig_csr);
        !           554: 
        !           555:   /* sigh.. WD-PROTO strikes again.. sending the command in one go causes
        !           556:      the chip to lock up if talking to certain (misbehaving?) targets.
        !           557:      Anyway, this procedure should work for all targets, but it's slightly
        !           558:      slower due to the overhead */
        !           559: #if 0
        !           560:   if (phase == CMD_PHASE)
        !           561:     {
        !           562:       WAIT_CIP (regs);
        !           563: #if 0
        !           564:       for (; len > 0; len--)
        !           565:         {
        !           566:          /* clear possible last interrupt */
        !           567:          GET_SBIC_csr (regs, csr);
        !           568: 
        !           569:          /* send the byte, and expect an interrupt afterwards */
        !           570:          SEND_BYTE (regs, *buf);
        !           571:           buf++;
        !           572:           SBIC_WAIT (regs, SBIC_ASR_INT, 0);   /* XXX  */
        !           573:         }
        !           574: #else
        !           575:       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
        !           576:       for (;len > 0; len--)
        !           577:         {
        !           578:           WAIT_CIP (regs);
        !           579:           GET_SBIC_csr (regs, csr);
        !           580:          SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO | SBIC_CMD_SBT);
        !           581:           GET_SBIC_asr (regs, asr);
        !           582:           while (!(asr & SBIC_ASR_DBR)) 
        !           583:            {
        !           584:              DELAY(1);
        !           585:              GET_SBIC_asr (regs, asr);
        !           586:            }
        !           587: 
        !           588:           SET_SBIC_data (regs, *buf);
        !           589:           buf++;
        !           590:           while (!(asr & SBIC_ASR_INT)) 
        !           591:            {
        !           592:              DELAY(1);
        !           593:              GET_SBIC_asr (regs, asr);
        !           594:            }
        !           595: 
        !           596:         }
        !           597: 
        !           598: #endif
        !           599:     }
        !           600:   else
        !           601: #endif
        !           602:     {
        !           603:       WAIT_CIP (regs);
        !           604:       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
        !           605:       for (;len > 0; len--)
        !           606:         {
        !           607:           GET_SBIC_asr (regs, asr);
        !           608:           while (!(asr & SBIC_ASR_DBR)) 
        !           609:            {
        !           610:               if ((asr & SBIC_ASR_INT) || --wait < 0) 
        !           611:                {
        !           612: #ifdef DEBUG
        !           613:                  if (scsi_debug)
        !           614:                    printf("ixfer_out fail: l%d i%x w%d\n",
        !           615:                           len, asr, wait);
        !           616: #endif
        !           617:                  HIST(ixout_wait, wait)
        !           618:                  return (len);
        !           619:                }
        !           620:              DELAY(1);
        !           621:              GET_SBIC_asr (regs, asr);
        !           622:            }
        !           623: 
        !           624:           SET_SBIC_data (regs, *buf);
        !           625:           buf++;
        !           626:         }
        !           627:     }
        !           628: 
        !           629:   QPRINTF(("ixfer_out done\n"));
        !           630:   /* this leaves with one csr to be read */
        !           631:   HIST(ixout_wait, wait)
        !           632:   return (0);
        !           633: }
        !           634: 
        !           635: static void
        !           636: ixfer_in(regs, len, buf)
        !           637:        volatile register sbic_padded_regmap_t *regs;
        !           638:        int len;
        !           639:        register u_char *buf;
        !           640: {
        !           641:   register int wait = scsi_data_wait;
        !           642:   u_char *obp = buf;
        !           643:   u_char orig_csr, csr, asr;
        !           644: 
        !           645:   GET_SBIC_csr (regs, orig_csr);
        !           646: 
        !           647:   QPRINTF(("ixfer_in %d, csr=%02x\n", len, orig_csr));
        !           648: 
        !           649:   WAIT_CIP (regs);
        !           650:   SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
        !           651:   for (;len > 0; len--)
        !           652:     {
        !           653:       GET_SBIC_asr (regs, asr);
        !           654:       while (!(asr & SBIC_ASR_DBR)) 
        !           655:        {
        !           656:           if ((asr & SBIC_ASR_INT) || --wait < 0) 
        !           657:            {
        !           658: #ifdef DEBUG
        !           659:              if (scsi_debug)
        !           660:                printf("ixfer_in fail: l%d i%x w%d\n",
        !           661:                       len, asr, wait);
        !           662: #endif
        !           663:              HIST(ixin_wait, wait)
        !           664:              return;
        !           665:            }
        !           666: 
        !           667:          DELAY(1);
        !           668:          GET_SBIC_asr (regs, asr);
        !           669:        }
        !           670: 
        !           671:       GET_SBIC_data (regs, *buf);
        !           672:       buf++;
        !           673:     }
        !           674: 
        !           675:   QPRINTF(("ixfer_in {%d} %02x %02x %02x %02x %02x %02x\n", 
        !           676:           len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5]));
        !           677: 
        !           678:   /* this leaves with one csr to be read */
        !           679:   HIST(ixin_wait, wait)
        !           680: }
        !           681: 
        !           682: 
        !           683: /*
        !           684:  * SCSI 'immediate' command:  issue a command to some SCSI device
        !           685:  * and get back an 'immediate' response (i.e., do programmed xfer
        !           686:  * to get the response data).  'cbuf' is a buffer containing a scsi
        !           687:  * command of length clen bytes.  'buf' is a buffer of length 'len'
        !           688:  * bytes for data.  The transfer direction is determined by the device
        !           689:  * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
        !           690:  * command must supply no data.  'xferphase' is the bus phase the
        !           691:  * caller expects to happen after the command is issued.  It should
        !           692:  * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
        !           693:  */
        !           694: static int
        !           695: scsiicmd(dev, target, cbuf, clen, buf, len, xferphase)
        !           696:        struct scsi_softc *dev;
        !           697:        int target;
        !           698:        u_char *cbuf;
        !           699:        int clen;
        !           700:        u_char *buf;
        !           701:        int len;
        !           702:        u_char xferphase;
        !           703: {
        !           704:   volatile register sbic_padded_regmap_t *regs =
        !           705:                                (sbic_padded_regmap_t *)dev->sc_ac->amiga_addr;
        !           706:   u_char phase, csr, asr;
        !           707:   register int wait;
        !           708: 
        !           709: 
        !           710: #if 0
        !           711:   /* XXXXXXXX */
        !           712:   if (target != 6 && target != 4)
        !           713:     return -1;
        !           714:   /* XXXXXXXX */
        !           715: #endif
        !           716: 
        !           717:   /* set the sbic into non-DMA mode */
        !           718:   SET_SBIC_control (regs, (/*SBIC_CTL_HHP |*/ SBIC_CTL_EDI | SBIC_CTL_IDI |
        !           719:                            /* | SBIC_CTL_HSP | */ 0));
        !           720: 
        !           721:   /* select the SCSI bus (it's an error if bus isn't free) */
        !           722:   if (issue_select (regs, target, dev->sc_scsi_addr))
        !           723:     return -1;
        !           724:   if (wait_for_select (regs))
        !           725:     return -1;
        !           726:   /*
        !           727:    * Wait for a phase change (or error) then let the device
        !           728:    * sequence us through the various SCSI phases.
        !           729:    */
        !           730:   dev->sc_stat[0] = 0xff;
        !           731:   dev->sc_msg[0] = 0xff;
        !           732:   phase = CMD_PHASE;
        !           733:   while (1) 
        !           734:     {
        !           735:       wait = scsi_cmd_wait;
        !           736:       switch (phase) 
        !           737:        {
        !           738:        case CMD_PHASE:
        !           739:          if (ixfer_start (regs, clen, phase, wait))
        !           740:            if (ixfer_out (regs, clen, cbuf, phase))
        !           741:              goto abort;
        !           742:          phase = xferphase;
        !           743:          break;
        !           744: 
        !           745:        case DATA_IN_PHASE:
        !           746:          if (len <= 0)
        !           747:            goto abort;
        !           748:          wait = scsi_data_wait;
        !           749:          if (ixfer_start (regs, len, phase, wait))
        !           750:            ixfer_in (regs, len, buf);
        !           751:          phase = STATUS_PHASE;
        !           752:          break;
        !           753: 
        !           754:        case MESG_IN_PHASE:
        !           755:          if (ixfer_start (regs, sizeof (dev->sc_msg), phase, wait))
        !           756:            {
        !           757:              ixfer_in (regs, sizeof (dev->sc_msg), dev->sc_msg);
        !           758:              /* prepare to reject any mesgin, no matter what it might be.. */
        !           759:              SET_SBIC_cmd (regs, SBIC_CMD_SET_ATN);
        !           760:              WAIT_CIP (regs);
        !           761:              SET_SBIC_cmd (regs, SBIC_CMD_CLR_ACK);
        !           762:              phase = MESG_OUT_PHASE;
        !           763:            }
        !           764:          break;
        !           765: 
        !           766:        case MESG_OUT_PHASE:
        !           767:          SEND_BYTE (regs, MSG_REJECT);
        !           768:          phase = STATUS_PHASE;
        !           769:          break;
        !           770: 
        !           771:        case DATA_OUT_PHASE:
        !           772:          if (len <= 0)
        !           773:            goto abort;
        !           774:          wait = scsi_data_wait;
        !           775:          if (ixfer_start (regs, len, phase, wait)) 
        !           776:            {
        !           777:              if (ixfer_out (regs, len, buf, phase))
        !           778:                goto abort;
        !           779:            }
        !           780:          phase = STATUS_PHASE;
        !           781:          break;
        !           782: 
        !           783:        case STATUS_PHASE:
        !           784:          /* the sbic does the status/cmd-complete reading ok, so do this
        !           785:             with its hi-level commands. */
        !           786:          SBIC_TC_PUT (regs, 0);
        !           787:          SET_SBIC_cmd_phase (regs, 0x46);
        !           788:          SET_SBIC_cmd (regs, SBIC_CMD_SEL_ATN_XFER);
        !           789:          phase = BUS_FREE_PHASE;
        !           790:          break;
        !           791: 
        !           792:        case BUS_FREE_PHASE:
        !           793:          goto out;
        !           794: 
        !           795:        default:
        !           796:          printf("scsi: unexpected phase %d in icmd from %d\n",
        !           797:                 phase, target);
        !           798:          goto abort;
        !           799:        }
        !           800: 
        !           801:       /* make sure the last command was taken, ie. we're not hunting after
        !           802:          an ignored command.. */
        !           803:       GET_SBIC_asr (regs, asr);
        !           804:       if (asr & SBIC_ASR_LCI)
        !           805:         goto abort;
        !           806: 
        !           807:       /* tapes may take a loooong time.. */
        !           808:       while (asr & SBIC_ASR_BSY)
        !           809:         {
        !           810:           DELAY(1);
        !           811:           GET_SBIC_asr (regs, asr);
        !           812:         }
        !           813: 
        !           814:       if (wait <= 0)            
        !           815:        goto abort;
        !           816: 
        !           817:       /* wait for last command to complete */
        !           818:       SBIC_WAIT (regs, SBIC_ASR_INT, wait);
        !           819: 
        !           820:       GET_SBIC_csr (regs, csr);
        !           821:       QPRINTF((">CSR:%02x<", csr));
        !           822: 
        !           823:       HIST(cxin_wait, wait);
        !           824:       if ((csr != 0xff) && (csr & 0xf0) && (csr & 0x08)) /* requesting some new phase */
        !           825:        phase = csr & PHASE;
        !           826:       else if ((csr == SBIC_CSR_DISC) || (csr == SBIC_CSR_DISC_1)
        !           827:               || (csr == SBIC_CSR_S_XFERRED))
        !           828:        {
        !           829:          dev->sc_flags &= ~SCSI_SELECTED;
        !           830:          GET_SBIC_cmd_phase (regs, phase);
        !           831:          if (phase == 0x60)
        !           832:            GET_SBIC_tlun (regs, dev->sc_stat[0]);
        !           833:          else
        !           834:            return -1;
        !           835: 
        !           836:          goto out;
        !           837:        }
        !           838:       else 
        !           839:        {
        !           840:          scsierror(dev, regs, csr);
        !           841:          goto abort;
        !           842:        }
        !           843:     }
        !           844: 
        !           845: abort:
        !           846:   scsiabort(dev, regs, "icmd");
        !           847: out:
        !           848:   return (dev->sc_stat[0]);
        !           849: }
        !           850: 
        !           851: /*
        !           852:  * Finish SCSI xfer command:  After the completion interrupt from
        !           853:  * a read/write operation, sequence through the final phases in
        !           854:  * programmed i/o.  This routine is a lot like scsiicmd except we
        !           855:  * skip (and don't allow) the select, cmd out and data in/out phases.
        !           856:  */
        !           857: static void
        !           858: finishxfer(dev, regs, target)
        !           859:        struct scsi_softc *dev;
        !           860:        volatile register sbic_padded_regmap_t *regs;
        !           861:        int target;
        !           862: {
        !           863:   u_char phase, csr;
        !           864:   int s;
        !           865: 
        !           866:   s = splbio();
        !           867:   /* have the sbic complete on its own */
        !           868:   SBIC_TC_PUT (regs, 0);
        !           869:   SET_SBIC_cmd_phase (regs, 0x46);
        !           870:   SET_SBIC_cmd (regs, SBIC_CMD_SEL_ATN_XFER);
        !           871: 
        !           872:   do
        !           873:     {
        !           874:       SBIC_WAIT (regs, SBIC_ASR_INT, 0);
        !           875:       GET_SBIC_csr (regs, csr);
        !           876:     }
        !           877:   while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
        !           878:          && (csr != SBIC_CSR_S_XFERRED));
        !           879: 
        !           880:   dev->sc_flags &= ~SCSI_SELECTED;
        !           881:   GET_SBIC_cmd_phase (regs, phase);
        !           882:   if (phase == 0x60)
        !           883:     GET_SBIC_tlun (regs, dev->sc_stat[0]);
        !           884:   else
        !           885:     scsierror (dev, regs, csr);
        !           886: 
        !           887:   splx (s);
        !           888: }
        !           889: 
        !           890: int
        !           891: scsi_test_unit_rdy(slave)
        !           892:        int slave;
        !           893: {
        !           894:        register struct scsi_softc *dev = &scsi_softc;
        !           895:        static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
        !           896: 
        !           897:        return (scsiicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), (u_char *)0, 0,
        !           898:                         STATUS_PHASE));
        !           899: }
        !           900: 
        !           901: int
        !           902: scsi_request_sense(slave, buf, len)
        !           903:        int slave;
        !           904:        u_char *buf;
        !           905:        unsigned len;
        !           906: {
        !           907:        register struct scsi_softc *dev = &scsi_softc;
        !           908:        static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
        !           909: 
        !           910:        cdb.len = len;
        !           911:        return (scsiicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
        !           912: }
        !           913: 
        !           914: int
        !           915: scsi_immed_command(slave, cdb, buf, len, rd)
        !           916:        int slave;
        !           917:        struct scsi_fmt_cdb *cdb;
        !           918:        u_char *buf;
        !           919:        unsigned len;
        !           920: {
        !           921:        register struct scsi_softc *dev = &scsi_softc;
        !           922: 
        !           923:        return (scsiicmd(dev, slave, (u_char *) cdb->cdb, cdb->len, buf, len,
        !           924:                         rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE));
        !           925: }
        !           926: 
        !           927: /*
        !           928:  * The following routines are test-and-transfer i/o versions of read/write
        !           929:  * for things like reading disk labels and writing core dumps.  The
        !           930:  * routine scsigo should be used for normal data transfers, NOT these
        !           931:  * routines.
        !           932:  */
        !           933: int
        !           934: scsi_tt_read(slave, buf, len, blk, bshift)
        !           935:        int slave;
        !           936:        u_char *buf;
        !           937:        u_int len;
        !           938:        daddr_t blk;
        !           939:        int bshift;
        !           940: {
        !           941:        register struct scsi_softc *dev = &scsi_softc;
        !           942:        struct scsi_cdb10 cdb;
        !           943:        int stat;
        !           944:        int old_wait = scsi_data_wait;
        !           945: 
        !           946:        scsi_data_wait = 300000;
        !           947:        bzero(&cdb, sizeof(cdb));
        !           948:        cdb.cmd = CMD_READ_EXT;
        !           949:        blk >>= bshift;
        !           950:        cdb.lbah = blk >> 24;
        !           951:        cdb.lbahm = blk >> 16;
        !           952:        cdb.lbalm = blk >> 8;
        !           953:        cdb.lbal = blk;
        !           954:        cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
        !           955:        cdb.lenl = len >> (DEV_BSHIFT + bshift);
        !           956:        stat = scsiicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
        !           957:        scsi_data_wait = old_wait;
        !           958:        return (stat);
        !           959: }
        !           960: 
        !           961: int
        !           962: scsi_tt_write(slave, buf, len, blk, bshift)
        !           963:        int slave;
        !           964:        u_char *buf;
        !           965:        u_int len;
        !           966:        daddr_t blk;
        !           967:        int bshift;
        !           968: {
        !           969:        register struct scsi_softc *dev = &scsi_softc;
        !           970:        struct scsi_cdb10 cdb;
        !           971:        int stat;
        !           972:        int old_wait = scsi_data_wait;
        !           973: 
        !           974:        scsi_data_wait = 300000;
        !           975: 
        !           976:        bzero(&cdb, sizeof(cdb));
        !           977:        cdb.cmd = CMD_WRITE_EXT;
        !           978:        blk >>= bshift;
        !           979:        cdb.lbah = blk >> 24;
        !           980:        cdb.lbahm = blk >> 16;
        !           981:        cdb.lbalm = blk >> 8;
        !           982:        cdb.lbal = blk;
        !           983:        cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
        !           984:        cdb.lenl = len >> (DEV_BSHIFT + bshift);
        !           985:        stat = scsiicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
        !           986:        scsi_data_wait = old_wait;
        !           987:        return (stat);
        !           988: }
        !           989: 
        !           990: int
        !           991: scsireq(dq)
        !           992:        register struct devqueue *dq;
        !           993: {
        !           994:        register struct devqueue *hq;
        !           995: 
        !           996:        hq = &scsi_softc.sc_sq;
        !           997:        insque(dq, hq->dq_back);
        !           998:        if (dq->dq_back == hq)
        !           999:                return(1);
        !          1000:        return(0);
        !          1001: }
        !          1002: 
        !          1003: int
        !          1004: scsiustart (int unit)
        !          1005: {
        !          1006:        register struct scsi_softc *dev = &scsi_softc;
        !          1007: 
        !          1008:        if (dmareq(&dev->sc_dq))
        !          1009:                return(1);
        !          1010:        return(0);
        !          1011: }
        !          1012: 
        !          1013: void
        !          1014: scsistart (int unit)
        !          1015: {
        !          1016:        register struct devqueue *dq;
        !          1017:        
        !          1018:        dq = scsi_softc.sc_sq.dq_forw;
        !          1019:        (dq->dq_driver->d_go)(dq->dq_unit);
        !          1020: }
        !          1021: 
        !          1022: int
        !          1023: scsigo(unit, slave, bp, cdb, pad)
        !          1024:        int unit, slave;
        !          1025:        struct buf *bp;
        !          1026:        struct scsi_fmt_cdb *cdb;
        !          1027:        int pad;
        !          1028: {
        !          1029:   register struct scsi_softc *dev = &scsi_softc;
        !          1030:   volatile register sbic_padded_regmap_t *regs =
        !          1031:                        (sbic_padded_regmap_t *)dev->sc_ac->amiga_addr;
        !          1032:   int i, dmaflags;
        !          1033:   u_char phase, csr, asr, cmd;
        !          1034: 
        !          1035: #if 0
        !          1036:   /* XXXXXXXX */
        !          1037:   if (slave != 6 && slave != 4)
        !          1038:     return -1;
        !          1039:   /* XXXXXXXX */
        !          1040: #endif
        !          1041: 
        !          1042:   /* this should only happen on character devices, and there only if user
        !          1043:      programs have not been written taking care of not passing odd aligned
        !          1044:      buffers. dd was a bad example of this sin.. */
        !          1045: 
        !          1046: /* XXXX do all with polled I/O */
        !          1047: 
        !          1048:   if ((((int)bp->b_un.b_addr & 3) || (bp->b_bcount & 1)))
        !          1049:     {
        !          1050:       register struct devqueue *dq;
        !          1051: 
        !          1052:       dmafree(&dev->sc_dq);
        !          1053: 
        !          1054:       /* in this case do the transfer with programmed I/O :-( This is
        !          1055:          probably still faster than doing the transfer with DMA into a
        !          1056:          buffer and copying it later to its final destination, comments? */
        !          1057:       scsiicmd (dev, slave, (u_char *) cdb->cdb, cdb->len, 
        !          1058:                bp->b_un.b_addr, bp->b_bcount,
        !          1059:                bp->b_flags & B_READ ? DATA_IN_PHASE : DATA_OUT_PHASE);
        !          1060: 
        !          1061:       dq = dev->sc_sq.dq_forw;
        !          1062:              dev->sc_flags &=~ SCSI_IO;
        !          1063:       (dq->dq_driver->d_intr)(dq->dq_unit, dev->sc_stat[0]);
        !          1064:       return dev->sc_stat[0];
        !          1065:     }
        !          1066: 
        !          1067:   /* set the sbic into DMA mode */
        !          1068:   SET_SBIC_control (regs, (/*SBIC_CTL_HHP |*/ SBIC_CTL_EDI | SBIC_CTL_IDI |
        !          1069:                            /* | SBIC_CTL_HSP | */ SBIC_MACHINE_DMA_MODE));
        !          1070: 
        !          1071:   /* select the SCSI bus (it's an error if bus isn't free) */
        !          1072:   if (issue_select(regs, slave, dev->sc_scsi_addr) || wait_for_select(regs)) 
        !          1073:     {
        !          1074:       dmafree(&dev->sc_dq);
        !          1075:       return (1);
        !          1076:     }
        !          1077:   /*
        !          1078:    * Wait for a phase change (or error) then let the device
        !          1079:    * sequence us through command phase (we may have to take
        !          1080:    * a msg in/out before doing the command).  If the disk has
        !          1081:    * to do a seek, it may be a long time until we get a change
        !          1082:    * to data phase so, in the absense of an explicit phase
        !          1083:    * change, we assume data phase will be coming up and tell
        !          1084:    * the SPC to start a transfer whenever it does.  We'll get
        !          1085:    * a service required interrupt later if this assumption is
        !          1086:    * wrong.  Otherwise we'll get a service required int when
        !          1087:    * the transfer changes to status phase.
        !          1088:    */
        !          1089:   phase = CMD_PHASE;
        !          1090:   while (1) 
        !          1091:     {
        !          1092:       register int wait = scsi_cmd_wait;
        !          1093:       register struct devqueue *dq;
        !          1094: 
        !          1095:       switch (phase) 
        !          1096:        {
        !          1097:        case CMD_PHASE:
        !          1098:          if (ixfer_start(regs, cdb->len, phase, wait))
        !          1099:            if (ixfer_out(regs, cdb->len, cdb->cdb, phase))
        !          1100:              goto abort;
        !          1101:          break;
        !          1102: 
        !          1103:        case MESG_IN_PHASE:
        !          1104:          if (ixfer_start (regs, sizeof (dev->sc_msg), phase, wait))
        !          1105:            {
        !          1106:              ixfer_in (regs, sizeof (dev->sc_msg), dev->sc_msg);
        !          1107:              /* prepare to reject any mesgin, no matter what it might be.. */
        !          1108:              SET_SBIC_cmd (regs, SBIC_CMD_SET_ATN);
        !          1109:              WAIT_CIP (regs);
        !          1110:              SET_SBIC_cmd (regs, SBIC_CMD_CLR_ACK);
        !          1111:              phase = MESG_OUT_PHASE;
        !          1112:            }
        !          1113:          break;
        !          1114: 
        !          1115:        case MESG_OUT_PHASE:
        !          1116:          SEND_BYTE (regs, MSG_REJECT);
        !          1117:          phase = STATUS_PHASE;
        !          1118:          break;
        !          1119: 
        !          1120:        case DATA_IN_PHASE:
        !          1121:        case DATA_OUT_PHASE:
        !          1122:          goto out;
        !          1123: 
        !          1124:        /* status phase can happen, if the issued read/write command is
        !          1125:           illegal (for example, reading after EOT on tape) and the device
        !          1126:           doesn't even go to data in/out phase. So handle this here
        !          1127:           normally, instead of going thru abort-handling. */
        !          1128:        case STATUS_PHASE:
        !          1129:           dmafree(&dev->sc_dq);
        !          1130:          finishxfer (dev, regs, slave);
        !          1131:           dq = dev->sc_sq.dq_forw;
        !          1132:          dev->sc_flags &=~ SCSI_IO;
        !          1133:           (dq->dq_driver->d_intr)(dq->dq_unit, dev->sc_stat[0]);
        !          1134:           return 0;
        !          1135: 
        !          1136:        default:
        !          1137:          printf("scsi: unexpected phase %d in go from %d\n",
        !          1138:                 phase, slave);
        !          1139:          goto abort;
        !          1140:        }
        !          1141: 
        !          1142:       /* make sure the last command was taken, ie. we're not hunting after
        !          1143:          an ignored command.. */
        !          1144:       GET_SBIC_asr (regs, asr);
        !          1145:       if (asr & SBIC_ASR_LCI)
        !          1146:         goto abort;
        !          1147: 
        !          1148:       /* tapes may take a loooong time.. */
        !          1149:       while (asr & SBIC_ASR_BSY)
        !          1150:         {
        !          1151:           DELAY(1);
        !          1152:           GET_SBIC_asr (regs, asr);
        !          1153:         }
        !          1154: 
        !          1155:       if (wait <= 0)            
        !          1156:        goto abort;
        !          1157: 
        !          1158:       /* wait for last command to complete */
        !          1159:       SBIC_WAIT (regs, SBIC_ASR_INT, wait);
        !          1160: 
        !          1161:       GET_SBIC_csr (regs, csr);
        !          1162:       QPRINTF((">CSR:%02x<", csr));
        !          1163: 
        !          1164:       HIST(sgo_wait, wait);
        !          1165:       if ((csr != 0xff) && (csr & 0xf0) && (csr & 0x08))       /* requesting some new phase */
        !          1166:        phase = csr & PHASE;
        !          1167:       else 
        !          1168:        {
        !          1169:          scsierror(dev, regs, csr);
        !          1170:          goto abort;
        !          1171:        }
        !          1172:     }
        !          1173: 
        !          1174: out:
        !          1175:   dmaflags = DMAGO_NOINT;
        !          1176:   if (bp->b_flags & B_READ)
        !          1177:     dmaflags |= DMAGO_READ;
        !          1178:   if ((int)bp->b_un.b_addr & 3)
        !          1179:     panic ("not long-aligned buffer address in scsi_go");
        !          1180:   if (bp->b_bcount & 1)
        !          1181:     panic ("odd transfer count in scsi_go");
        !          1182: 
        !          1183:   /* dmago() also enables interrupts for the sbic */
        !          1184:   i = dmago(bp->b_un.b_addr, bp->b_bcount, dmaflags);
        !          1185: 
        !          1186:   SBIC_TC_PUT (regs, (unsigned)i);
        !          1187:   SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
        !          1188: 
        !          1189:   return (0);
        !          1190: 
        !          1191: abort:
        !          1192:   scsiabort(dev, regs, "go");
        !          1193:   dmafree(&dev->sc_dq);
        !          1194:   return (1);
        !          1195: }
        !          1196: 
        !          1197: void
        !          1198: scsidone (int unit)
        !          1199: {
        !          1200:   volatile register sbic_padded_regmap_t *regs =
        !          1201:                        (sbic_padded_regmap_t *)scsi_softc.sc_ac->amiga_addr;
        !          1202: 
        !          1203: #ifdef DEBUG
        !          1204:   if (scsi_debug)
        !          1205:     printf("scsi: done called!\n");
        !          1206: #endif
        !          1207: }
        !          1208: 
        !          1209: int
        !          1210: scsiintr (int unit)
        !          1211: {
        !          1212:   register struct scsi_softc *dev = &scsi_softc;
        !          1213:   volatile register sbic_padded_regmap_t *regs =
        !          1214:                                (sbic_padded_regmap_t *)dev->sc_ac->amiga_addr;
        !          1215:   register u_char asr, csr, phase;
        !          1216:   register struct devqueue *dq;
        !          1217:   int i;
        !          1218: 
        !          1219:   GET_SBIC_asr (regs, asr);
        !          1220:   if (! (asr & SBIC_ASR_INT))
        !          1221:     return 0;
        !          1222: 
        !          1223:   GET_SBIC_csr (regs, csr);
        !          1224: QPRINTF(("[0x%x]", csr));
        !          1225: 
        !          1226:   if (csr == (SBIC_CSR_XFERRED|STATUS_PHASE)
        !          1227:       || csr == (SBIC_CSR_MIS|STATUS_PHASE)
        !          1228:       || csr == (SBIC_CSR_MIS_1|STATUS_PHASE)
        !          1229:       || csr == (SBIC_CSR_MIS_2|STATUS_PHASE))
        !          1230:     {
        !          1231:       /*
        !          1232:        * this should be the normal i/o completion case.
        !          1233:        * get the status & cmd complete msg then let the
        !          1234:        * device driver look at what happened.
        !          1235:        */
        !          1236:       dq = dev->sc_sq.dq_forw;
        !          1237:       finishxfer(dev, regs, dq->dq_slave);
        !          1238:       dev->sc_flags &=~ SCSI_IO;
        !          1239:       dmafree (&dev->sc_dq);
        !          1240:       (dq->dq_driver->d_intr)(dq->dq_unit, dev->sc_stat[0]);
        !          1241:     } 
        !          1242:   else if (csr == (SBIC_CSR_XFERRED|DATA_OUT_PHASE) || csr == (SBIC_CSR_XFERRED|DATA_IN_PHASE)
        !          1243:           || csr == (SBIC_CSR_MIS|DATA_OUT_PHASE) || csr == (SBIC_CSR_MIS|DATA_IN_PHASE)
        !          1244:           || csr == (SBIC_CSR_MIS_1|DATA_OUT_PHASE) || csr == (SBIC_CSR_MIS_1|DATA_IN_PHASE)
        !          1245:           || csr == (SBIC_CSR_MIS_2|DATA_OUT_PHASE) || csr == (SBIC_CSR_MIS_2|DATA_IN_PHASE))
        !          1246:     {
        !          1247:       /* do scatter-gather dma hacking the controller chip, ouch.. */
        !          1248:       i = dmanext ();
        !          1249:       SBIC_TC_PUT (regs, (unsigned)i);
        !          1250:       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
        !          1251:     }
        !          1252:   else 
        !          1253:     {
        !          1254:       /* Something unexpected happened -- deal with it. */
        !          1255:       dmastop ();
        !          1256:       scsierror(dev, regs, csr);
        !          1257:       scsiabort(dev, regs, "intr");
        !          1258:       if (dev->sc_flags & SCSI_IO) 
        !          1259:        {
        !          1260:          dev->sc_flags &=~ SCSI_IO;
        !          1261:          dmafree (&dev->sc_dq);
        !          1262:          dq = dev->sc_sq.dq_forw;
        !          1263:          (dq->dq_driver->d_intr)(dq->dq_unit, -1);
        !          1264:        }
        !          1265:     }
        !          1266: 
        !          1267:   return 1;
        !          1268: }
        !          1269: 
        !          1270: void
        !          1271: scsifree(dq)
        !          1272:        register struct devqueue *dq;
        !          1273: {
        !          1274:        register struct devqueue *hq;
        !          1275: 
        !          1276:        hq = &scsi_softc.sc_sq;
        !          1277:        remque(dq);
        !          1278:        if ((dq = hq->dq_forw) != hq)
        !          1279:                (dq->dq_driver->d_start)(dq->dq_unit);
        !          1280: }
        !          1281: 
        !          1282: /*
        !          1283:  * (XXX) The following routine is needed for the SCSI tape driver
        !          1284:  * to read odd-size records.
        !          1285:  */
        !          1286: 
        !          1287: #include "st.h"
        !          1288: #if NST > 0
        !          1289: int
        !          1290: scsi_tt_oddio(slave, buf, len, b_flags, freedma)
        !          1291:        int slave, b_flags;
        !          1292:        u_char *buf;
        !          1293:        u_int len;
        !          1294: {
        !          1295:        register struct scsi_softc *dev = &scsi_softc;
        !          1296:        struct scsi_cdb6 cdb;
        !          1297:        u_char iphase;
        !          1298:        int stat;
        !          1299: 
        !          1300:        /*
        !          1301:         * First free any DMA channel that was allocated.
        !          1302:         * We can't use DMA to do this transfer.
        !          1303:         */
        !          1304:        if (freedma)
        !          1305:                dmafree(&dev->sc_dq);
        !          1306:        /*
        !          1307:         * Initialize command block
        !          1308:         */
        !          1309:        bzero(&cdb, sizeof(cdb));
        !          1310:        cdb.lbam = (len >> 16) & 0xff;
        !          1311:        cdb.lbal = (len >> 8) & 0xff;
        !          1312:        cdb.len = len & 0xff;
        !          1313:        if (buf == 0) {
        !          1314:                cdb.cmd = CMD_SPACE;
        !          1315:                cdb.lun |= 0x00;
        !          1316:                len = 0;
        !          1317:                iphase = MESG_IN_PHASE;
        !          1318:        } else if (b_flags & B_READ) {
        !          1319:                cdb.cmd = CMD_READ;
        !          1320:                iphase = DATA_IN_PHASE;
        !          1321:        } else {
        !          1322:                cdb.cmd = CMD_WRITE;
        !          1323:                iphase = DATA_OUT_PHASE;
        !          1324:        }
        !          1325:        /*
        !          1326:         * Perform command (with very long delays)
        !          1327:         */
        !          1328:        scsi_delay(30000000);
        !          1329:        stat = scsiicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len, iphase);
        !          1330:        scsi_delay(0);
        !          1331:        return (stat);
        !          1332: }
        !          1333: #endif
        !          1334: #endif

unix.superglobalmegacorp.com

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