Annotation of Gnu-Mach/linux/src/drivers/scsi/scsiio.c, revision 1.1

1.1     ! root        1: /***********************************************************************
        !             2:  *     FILE NAME : SCSIIO.C                                           *
        !             3:  *          BY   : C.L. Huang                                         *
        !             4:  *     Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI *
        !             5:  *                  Bus Master Host Adapter                           *
        !             6:  ***********************************************************************/
        !             7: 
        !             8: 
        !             9: static void
        !            10: PrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB )
        !            11: {
        !            12:     ULONG  retAddr,wlval;
        !            13:     USHORT wval,i;
        !            14:     PSGL   psgl;
        !            15:     PSGE   psge;
        !            16: 
        !            17: 
        !            18:     retAddr = pACB->jmp_table8;
        !            19:     if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !            20:        retAddr += jmp_table16;
        !            21:     wval = (USHORT)(pSRB->SGcount);
        !            22:     wval <<= 4;        /* 16 bytes per entry, datain=8, dataout=8 */
        !            23:                        /* (4 bytes for count, 4 bytes for addr) */
        !            24:     retAddr -= (ULONG)wval;
        !            25:     pSRB->ReturnAddr = retAddr;    /* return address for SCRIPT */
        !            26:     if(wval)
        !            27:     {
        !            28:        wval >>= 1;
        !            29:        wlval = (ULONG) pSRB->SegmentPad;
        !            30:        wlval -= (ULONG)wval;
        !            31:        wval >>= 3;
        !            32:        psge = (PSGE) wlval;
        !            33:        psgl = pSRB->pSegmentList;
        !            34:        for(i=0; i<wval; i++)
        !            35:        {
        !            36: #ifndef VERSION_ELF_1_2_13
        !            37:            psge->SGXPtr = virt_to_phys( psgl->address );
        !            38: #else
        !            39:            psge->SGXPtr = (ULONG) psgl->address;
        !            40: #endif
        !            41:            psge->SGXLen = psgl->length;
        !            42:            psge++;
        !            43:            psgl++;
        !            44:        }
        !            45:     }
        !            46: }
        !            47: 
        !            48: 
        !            49: static void
        !            50: DC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
        !            51: {
        !            52:     USHORT ioport;
        !            53:     UCHAR  bval;
        !            54: 
        !            55:     pSRB->TagNumber = 31;
        !            56:     ioport = pACB->IOPortBase;
        !            57:     bval = SIGNAL_PROC;
        !            58:     outb(bval,ioport+ISTAT);
        !            59:     pACB->pActiveDCB = pDCB;
        !            60:     pDCB->pActiveSRB = pSRB;
        !            61:     return;
        !            62: }
        !            63: 
        !            64: 
        !            65: #ifndef  VERSION_ELF_1_2_13
        !            66: static void
        !            67: DC390W_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
        !            68: #else
        !            69: static void
        !            70: DC390W_Interrupt( int irq, struct pt_regs *regs)
        !            71: #endif
        !            72: {
        !            73:     PACB pACB;
        !            74:     PDCB pDCB;
        !            75:     ULONG  wlval;
        !            76:     USHORT ioport = 0;
        !            77:     USHORT wval, i;
        !            78:     void  (*stateV)( PACB );
        !            79:     UCHAR  istat = 0;
        !            80:     UCHAR  bval;
        !            81: 
        !            82:     pACB = pACB_start;
        !            83:     if( pACB == NULL )
        !            84:        return;
        !            85:     for( i=0; i < adapterCnt; i++ )
        !            86:     {
        !            87:        if( pACB->IRQLevel == (UCHAR) irq )
        !            88:        {
        !            89:             ioport = pACB->IOPortBase;
        !            90:             istat = inb( ioport+ISTAT );
        !            91:             if( istat & (ABORT_OP+SCSI_INT_PENDING+DMA_INT_PENDING) )
        !            92:                 break;
        !            93:             else
        !            94:                pACB = pACB->pNextACB;
        !            95:        }
        !            96:        else
        !            97:        {
        !            98:            pACB = pACB->pNextACB;
        !            99:        }
        !           100:     }
        !           101: 
        !           102:     if( pACB == (PACB )-1 )
        !           103:     {
        !           104:        printk("DC390W_intr: Spurious interrupt detected!\n");
        !           105:        return;
        !           106:     }
        !           107: 
        !           108: 
        !           109: #ifdef DC390W_DEBUG1
        !           110:        printk("Istate=%2x,",istat);
        !           111: #endif
        !           112:     /* if Abort operation occurred, reset abort bit before reading DMA status
        !           113:        to prevent further aborted interrupt.  */
        !           114: 
        !           115:     if(istat & ABORT_OP)
        !           116:     {
        !           117:        istat &= ~ABORT_OP;
        !           118:        outb(istat,ioport+ISTAT);
        !           119:     }
        !           120: 
        !           121:     pDCB = pACB->pActiveDCB;
        !           122:     bval = inb(ioport+CTEST2);  /* Clear Signal Bit */
        !           123: 
        !           124:     /* If Scsi Interrupt, then clear Interrupt Status by reading
        !           125:        Scsi interrupt status register 0. */
        !           126: 
        !           127:     wlval = 0;
        !           128:     if(istat & SCSI_INT_PENDING)
        !           129:     {
        !           130:        wlval = (ULONG)inw( ioport+SIST0 );
        !           131:        wlval <<= 8;
        !           132:     }
        !           133: 
        !           134:     /* If DMA Interrupt, then read the DMA status register to see what happen */
        !           135: 
        !           136:     if(istat & DMA_INT_PENDING)
        !           137:     {
        !           138:        bval = inb(ioport+DSTAT);
        !           139:        wlval |= (ULONG) bval;
        !           140:     }
        !           141: 
        !           142: #ifdef DC390W_DEBUG1
        !           143:        printk("IDstate=%8x,",(UINT) wlval);
        !           144: #endif
        !           145:     if(wlval & ( (SEL_TIMEOUT << 16)+
        !           146:                 ((SCSI_GERROR+UNEXPECT_DISC+SCSI_RESET) << 8)+
        !           147:                 ILLEGAL_INSTRUC+ABORT_) )
        !           148:     {
        !           149:         ExceptionHandler( wlval, pACB, pDCB );
        !           150:     }
        !           151:     else if( wlval & SCRIPTS_INT )
        !           152:     {
        !           153:         wval = inw( ioport+DSPS );
        !           154:         stateV = (void *) IntVector[wval];
        !           155:         stateV( pACB );
        !           156:     }
        !           157:     else if( wlval & ( PARITY_ERROR << 8) )
        !           158:        ParityError( pACB, pDCB );
        !           159:     else if( wlval & ( PHASE_MISMATCH << 8) )
        !           160:        PhaseMismatch( pACB );
        !           161:     return;
        !           162: }
        !           163: 
        !           164: 
        !           165: static void
        !           166: ExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB)
        !           167: {
        !           168:     PSRB  pSRB;
        !           169:     UCHAR bval;
        !           170:     USHORT ioport;
        !           171: 
        !           172: /* disconnect/scsi reset/illegal instruction */
        !           173: 
        !           174:     ioport = pACB->IOPortBase;
        !           175:     if(wlval & ( (SCSI_RESET+SCSI_GERROR) << 8) )
        !           176:        DC390W_ScsiRstDetect( pACB );
        !           177:     else if(wlval & ABORT_)
        !           178:     {
        !           179: #ifdef DC390W_DEBUG0
        !           180:        printk("AboRst,");
        !           181: #endif
        !           182:        if( !InitialTime )
        !           183:            DC390W_ResetSCSIBus2( pACB );
        !           184:     }
        !           185:     else if(wlval & (SEL_TIMEOUT << 16) )
        !           186:     {
        !           187:        pACB->status = SCSI_STAT_SEL_TIMEOUT;
        !           188: #ifdef DC390W_DEBUG1
        !           189:        printk("Selto,");
        !           190: #endif
        !           191:        DC390W_CmdCompleted( pACB );
        !           192:     }
        !           193:     else if(wlval & (UNEXPECT_DISC << 8) )
        !           194:     {
        !           195:        bval = inb(ioport+STEST3);
        !           196:        bval |= CLR_SCSI_FIFO;
        !           197:        outb(bval,ioport+STEST3);
        !           198:        bval = CLR_DMA_FIFO;
        !           199:        outb(bval,ioport+CTEST3);
        !           200:        pSRB = pDCB->pActiveSRB;
        !           201:        if( pSRB->SRBState & DO_SYNC_NEGO )
        !           202:        {
        !           203:            pDCB->DevMode &= ~SYNC_NEGO_;
        !           204:            pACB->status = SCSI_STAT_CHECKCOND;
        !           205:            DC390W_CmdCompleted( pACB );
        !           206:        }
        !           207:        else if( pSRB->SRBState & DO_WIDE_NEGO )
        !           208:        {
        !           209:            pDCB->DevMode &= ~WIDE_NEGO_;
        !           210:            pACB->status = SCSI_STAT_CHECKCOND;
        !           211:            DC390W_CmdCompleted( pACB );
        !           212:        }
        !           213:        else
        !           214:        {
        !           215:            pACB->status = SCSI_STAT_UNEXP_BUS_F;
        !           216:            DC390W_CmdCompleted( pACB );
        !           217:        }
        !           218: #ifdef DC390W_DEBUG0
        !           219:        printk("Uxpbf,");
        !           220: #endif
        !           221:     }
        !           222:     else
        !           223:     {
        !           224: #ifdef DC390W_DEBUG0
        !           225:        printk("Except,");
        !           226: #endif
        !           227:        DC390W_ResetSCSIBus( pACB );
        !           228:     }
        !           229: }
        !           230: 
        !           231: 
        !           232: static void
        !           233: ParityError( PACB pACB, PDCB pDCB )
        !           234: {
        !           235:     ULONG   ioport;
        !           236:     UCHAR   bval,msg;
        !           237:     ULONG   wlval;
        !           238:     PSRB    pSRB;
        !           239: 
        !           240:     ioport = pACB->IOPortBase;
        !           241:     bval = inb(ioport+SCRATCHA);
        !           242:     if(bval & RE_SELECTED_)
        !           243:     {
        !           244: #ifdef DC390W_DEBUG0
        !           245:        printk("ParityErr,");
        !           246: #endif
        !           247:        DC390W_ResetSCSIBus( pACB );
        !           248:        return;
        !           249:     }
        !           250:     else
        !           251:     {
        !           252:        pSRB = pDCB->pActiveSRB;
        !           253:        bval = inb(ioport+STEST3);
        !           254:        bval |= CLR_SCSI_FIFO;
        !           255:        outb(bval,ioport+STEST3);
        !           256:        bval = CLR_DMA_FIFO;
        !           257:        outb(bval,ioport+CTEST3);
        !           258: 
        !           259:        bval = inb(ioport+DCMD);
        !           260:        bval &= 0x07;       /* get phase bits */
        !           261:        if(bval == 0x07)    /* message in phase */
        !           262:        {
        !           263:            msg = MSG_PARITY_ERROR;
        !           264:            wlval = pACB->jmp_clear_ack;
        !           265:        }
        !           266:        else
        !           267:        {
        !           268:            msg = MSG_INITIATOR_ERROR;
        !           269:            wlval = pACB->jmp_next;
        !           270:        }
        !           271:        pSRB->__msgout0[0] = 1;
        !           272:        pSRB->MsgOutBuf[0] = msg;
        !           273:        outl(wlval,(ioport+DSP));
        !           274:        return;
        !           275:     }
        !           276: }
        !           277: 
        !           278: 
        !           279: static void
        !           280: DC390W_Signal( PACB pACB )
        !           281: {
        !           282:     PDCB pDCB;
        !           283:     PSRB pSRB;
        !           284:     USHORT ioport;
        !           285:     ULONG wlval, flags;
        !           286:     UCHAR bval,msgcnt,tagnum;
        !           287: 
        !           288:     save_flags(flags);
        !           289:     cli();
        !           290:     ioport = pACB->IOPortBase;
        !           291:     pDCB = pACB->pActiveDCB;
        !           292:     pSRB = pDCB->pActiveSRB;
        !           293: #ifdef DC390W_DEBUG0
        !           294:     printk("Signal,Cmd=%2x", pSRB->CmdBlock[0]);
        !           295: #endif
        !           296:     wlval = pSRB->PhysSRB;
        !           297:     outl(wlval,(ioport+DSA));
        !           298:     wlval = pSRB->ReturnAddr;
        !           299:     outl(wlval,(ioport+TEMP));
        !           300:     msgcnt = 1;
        !           301:     bval = pDCB->IdentifyMsg;
        !           302:     pSRB->MsgOutBuf[0] = bval;
        !           303:     if( (pSRB->CmdBlock[0] != INQUIRY) &&
        !           304:        (pSRB->CmdBlock[0] != REQUEST_SENSE) )
        !           305:     {
        !           306:        if(pDCB->MaxCommand > 1)
        !           307:        {
        !           308:            wlval = 1;
        !           309:            tagnum = 0;
        !           310:            while( wlval & pDCB->TagMask )
        !           311:            {
        !           312:                wlval = wlval << 1;
        !           313:                tagnum++;
        !           314:            }
        !           315:            pDCB->TagMask |= wlval;
        !           316:            pSRB->TagNumber = tagnum;
        !           317:            pSRB->MsgOutBuf[1] = MSG_SIMPLE_QTAG;
        !           318:            pSRB->MsgOutBuf[2] = tagnum;
        !           319:            msgcnt = 3;
        !           320:        }
        !           321:     }
        !           322:     else
        !           323:     {
        !           324:        pSRB->MsgOutBuf[0] &= 0xBF;        /* Diable Disconnected */
        !           325:        if(pSRB->CmdBlock[0] == INQUIRY)
        !           326:        {
        !           327:            if(bval & 0x07)
        !           328:                goto type_6_3;
        !           329:        }
        !           330:        if(pDCB->DevMode & WIDE_NEGO_)
        !           331:        {
        !           332:            msgcnt = 5;
        !           333:            *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x01030201;
        !           334:            pSRB->SRBState |= DO_WIDE_NEGO;
        !           335:        }
        !           336:        else if(pDCB->DevMode & SYNC_NEGO_)
        !           337:        {
        !           338:            msgcnt = 6;
        !           339:            *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x00010301;
        !           340:            pSRB->MsgOutBuf[4] = pDCB->NegoPeriod;
        !           341:            pSRB->MsgOutBuf[5] = SYNC_NEGO_OFFSET;
        !           342:            pSRB->SRBState |= DO_SYNC_NEGO;
        !           343:        }
        !           344:     }
        !           345: type_6_3:
        !           346:     pSRB->__msgout0[0] = (ULONG) msgcnt;
        !           347:     wlval = 0;
        !           348:     outl(wlval,(ioport+SCRATCHA));
        !           349:     bval = pDCB->DCBscntl0;
        !           350:     outb(bval,ioport+SCNTL0);
        !           351:     pSRB->__select = *((PULONG) &(pDCB->DCBselect));
        !           352: #ifdef DC390W_DEBUG0
        !           353:     printk("__sel=%8x,", (UINT)(pSRB->__select));
        !           354: #endif
        !           355:     wlval = pACB->jmp_select;
        !           356:     outl(wlval,(ioport+DSP));
        !           357:     restore_flags(flags);
        !           358:     return;
        !           359: }
        !           360: 
        !           361: 
        !           362: static void
        !           363: DC390W_MessageWide( PACB pACB )
        !           364: {
        !           365:     PDCB pDCB;
        !           366:     PSRB pSRB;
        !           367:     PUCHAR msgoutPtr;
        !           368:     USHORT ioport;
        !           369:     ULONG wlval;
        !           370:     UCHAR bval,msgcnt;
        !           371: 
        !           372: 
        !           373: #ifdef DC390W_DEBUG0
        !           374:     printk("MsgWide,");
        !           375: #endif
        !           376:     ioport = pACB->IOPortBase;
        !           377:     pDCB = pACB->pActiveDCB;
        !           378:     pSRB = pDCB->pActiveSRB;
        !           379:     msgcnt = 0;
        !           380:     pDCB->DCBscntl3 &= ~EN_WIDE_SCSI;
        !           381:     msgoutPtr = pSRB->MsgOutBuf;
        !           382:     if( pSRB->SRBState & DO_WIDE_NEGO )
        !           383:     {
        !           384:        pSRB->SRBState &= ~DO_WIDE_NEGO;
        !           385:        if( pACB->msgin123[0] == 3 )
        !           386:        {
        !           387:            bval = pACB->msgin123[1];
        !           388:            if(bval == 1)
        !           389:            {
        !           390:                pDCB->DCBscntl3 |= EN_WIDE_SCSI;
        !           391:                goto x5;
        !           392:            }
        !           393:            if(bval < 1)
        !           394:                goto x5;
        !           395:        }
        !           396:     }
        !           397: 
        !           398: /*type_11_1:*/
        !           399:     msgcnt = 1;
        !           400:     *msgoutPtr = MSG_REJECT_;
        !           401:     msgoutPtr++;
        !           402: x5:
        !           403:     bval = pDCB->DCBscntl3;
        !           404:     outb(bval,ioport+SCNTL3);
        !           405:     AdjustTemp(pACB,pDCB,pSRB);
        !           406:     SetXferRate(pACB,pDCB);
        !           407:     if( pDCB->DevMode & SYNC_NEGO_ )
        !           408:     {
        !           409:        *((PULONG)msgoutPtr) = 0x00010301;
        !           410:        *(msgoutPtr + 3) = pDCB->NegoPeriod;
        !           411:        *(msgoutPtr + 4) = SYNC_NEGO_OFFSET;
        !           412:        msgcnt += 5;
        !           413:        pSRB->SRBState |= DO_SYNC_NEGO;
        !           414:     }
        !           415: 
        !           416:     pSRB->__msgout0[0] = (ULONG) msgcnt;
        !           417:     wlval = pACB->jmp_clear_ack;
        !           418:     if(msgcnt)
        !           419:        wlval = pACB->jmp_set_atn;
        !           420:     outl(wlval,(ioport+DSP));
        !           421:     return;
        !           422: }
        !           423: 
        !           424: 
        !           425: static void
        !           426: DC390W_MessageSync( PACB pACB )
        !           427: {
        !           428:     PDCB pDCB;
        !           429:     PSRB pSRB;
        !           430:     USHORT ioport;
        !           431:     ULONG wlval;
        !           432:     USHORT wval,wval1;
        !           433:     UCHAR bval,bval1;
        !           434: 
        !           435: #ifdef DC390W_DEBUG0
        !           436:     printk("MsgSync,");
        !           437: #endif
        !           438:     ioport = pACB->IOPortBase;
        !           439:     pDCB = pACB->pActiveDCB;
        !           440:     pSRB = pDCB->pActiveSRB;
        !           441:     if( !(pSRB->SRBState & DO_SYNC_NEGO) )
        !           442:         goto MessageExtnd;
        !           443:     pSRB->SRBState &= ~DO_SYNC_NEGO;
        !           444:     if(pACB->msgin123[0] != 1)
        !           445:     {
        !           446: MessageExtnd:
        !           447:        pSRB->__msgout0[0] = 1;
        !           448:        pSRB->MsgOutBuf[0] = MSG_REJECT_;
        !           449:        wlval = pACB->jmp_set_atn;
        !           450:        outl(wlval,(ioport+DSP));
        !           451:        return;
        !           452:     }
        !           453:     bval = pACB->msgin123[2];  /* offset */
        !           454: asyncx:
        !           455:     pDCB->DCBsxfer = bval;
        !           456:     if(bval == 0)       /* if offset or period == 0, async */
        !           457:     {
        !           458:        if( pACB->AdaptType == DC390W )
        !           459:            bval = SYNC_CLK_F2+ASYNC_CLK_F2;
        !           460:        else
        !           461:            bval = SYNC_CLK_F4+ASYNC_CLK_F4;
        !           462:        pDCB->DCBscntl3 = bval;
        !           463:     }
        !           464:     else
        !           465:     {
        !           466:        bval = pACB->msgin123[1];
        !           467:        if(bval == 0)
        !           468:            goto asyncx;
        !           469:        pDCB->SyncPeriod = bval;
        !           470:        wval = (USHORT)bval;
        !           471:        wval <<= 3;
        !           472:        bval = pDCB->DCBscntl3;
        !           473:        bval &= 0x0f;
        !           474:        if(wval < 200)          /* < 100 ns ==> Fast-20 */
        !           475:        {
        !           476:            bval |= 0x90;       /* Fast-20 and div 1 */
        !           477:            bval1 = 25;         /* 12.5 ns */
        !           478:        }
        !           479:        else if(wval < 400)
        !           480:        {
        !           481:            bval |= 0x30;       /* 1 cycle = 25ns */
        !           482:            bval1 = 50;
        !           483:        }
        !           484:        else                    /* Non Fast */
        !           485:        {
        !           486:            bval |= 0x50;       /* 1 cycle = 50ns */
        !           487:            bval1 = 100;
        !           488:        }
        !           489:        if( pACB->AdaptType == DC390W )
        !           490:            bval -= 0x20;  /* turn down to 40Mhz scsi clock */
        !           491:                           /* assume 390W will not receive fast-20 */
        !           492:        wval1 = wval;
        !           493:        wval /= bval1;
        !           494:        if(wval * bval1 < wval1)
        !           495:            wval++;
        !           496:                            /* XFERP     TP2 TP1 TP0  */
        !           497:        wval -= 4;          /*   4        0   0   0   */
        !           498:                            /*   5        0   0   1   */
        !           499:        wval <<= 5;
        !           500:        pDCB->DCBsxfer |= (UCHAR)wval;
        !           501:        pDCB->DCBscntl3 = bval;
        !           502:     }
        !           503: /*sync_2:*/
        !           504:     SetXferRate( pACB,pDCB );
        !           505:     wlval = pACB->jmp_clear_ack;
        !           506: /*sync_3:*/
        !           507:     bval = pDCB->DCBscntl3;
        !           508:     outb(bval,ioport+SCNTL3);
        !           509:     bval = pDCB->DCBsxfer;
        !           510:     outb(bval,ioport+SXFER);
        !           511:     outl(wlval,(ioport+DSP));
        !           512:     return;
        !           513: }
        !           514: 
        !           515: 
        !           516: static void
        !           517: DC390W_MsgReject( PACB pACB )
        !           518: {
        !           519:     PDCB pDCB;
        !           520:     PSRB pSRB;
        !           521:     ULONG wlval;
        !           522:     USHORT ioport;
        !           523:     UCHAR bval;
        !           524: 
        !           525: #ifdef DC390W_DEBUG0
        !           526:     printk("Msgrjt,");
        !           527: #endif
        !           528:     pDCB = pACB->pActiveDCB;
        !           529:     pSRB = pDCB->pActiveSRB;
        !           530:     wlval = pACB->jmp_clear_ack;
        !           531:     if(pSRB->SRBState & DO_WIDE_NEGO)
        !           532:     {
        !           533:        pSRB->SRBState &= ~DO_WIDE_NEGO;
        !           534:        pDCB->DCBscntl3 &= ~EN_WIDE_SCSI;
        !           535:        AdjustTemp( pACB, pDCB, pSRB );
        !           536:        SetXferRate( pACB, pDCB );
        !           537:        if( pDCB->DevMode & SYNC_NEGO_ )
        !           538:        {
        !           539:            *((PULONG) &(pSRB->MsgOutBuf[0])) = 0x00010301;
        !           540:            pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
        !           541:            pSRB->MsgOutBuf[4] = SYNC_NEGO_OFFSET;
        !           542:            pSRB->__msgout0[0] = 5;
        !           543:            pSRB->SRBState |= DO_SYNC_NEGO;
        !           544:            wlval = pACB->jmp_set_atn;
        !           545:        }
        !           546:     }
        !           547:     else
        !           548:     {
        !           549:        if(pSRB->SRBState & DO_SYNC_NEGO)
        !           550:        {
        !           551:            pSRB->SRBState &= ~DO_SYNC_NEGO;
        !           552:            pDCB->DCBsxfer = 0; /* reject sync msg, set aync */
        !           553:            if( pACB->AdaptType == DC390W )
        !           554:                bval = SYNC_CLK_F2+ASYNC_CLK_F2;
        !           555:            else
        !           556:                bval = SYNC_CLK_F4+ASYNC_CLK_F4;
        !           557:            pDCB->DCBscntl3 = bval;
        !           558:            SetXferRate(pACB,pDCB);
        !           559:            wlval = pACB->jmp_clear_ack;
        !           560:        }
        !           561:     }
        !           562:     ioport = pACB->IOPortBase;
        !           563:     bval = pDCB->DCBscntl3;
        !           564:     outb(bval,ioport+SCNTL3);
        !           565:     bval = pDCB->DCBsxfer;
        !           566:     outb(bval,ioport+SXFER);
        !           567:     outl(wlval,(ioport+DSP));
        !           568:     return;
        !           569: }
        !           570: 
        !           571: 
        !           572: static void
        !           573: AdjustTemp( PACB pACB, PDCB pDCB, PSRB pSRB )
        !           574: {
        !           575:     USHORT ioport;
        !           576:     ULONG wlval;
        !           577: 
        !           578:     wlval = pSRB->ReturnAddr;
        !           579:     if(wlval <= pACB->jmp_table8)
        !           580:     {
        !           581:        if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !           582:            wlval +=  jmp_table16;
        !           583:     }
        !           584:     else
        !           585:     {
        !           586:        if((pDCB->DCBscntl3 & EN_WIDE_SCSI) == 0)
        !           587:            wlval -= jmp_table16;
        !           588:     }
        !           589:     pSRB->ReturnAddr = wlval;
        !           590:     ioport = pACB->IOPortBase;
        !           591:     outl(wlval,(ioport+TEMP));
        !           592:     return;
        !           593: }
        !           594: 
        !           595: 
        !           596: static void
        !           597: SetXferRate( PACB pACB, PDCB pDCB )
        !           598: {
        !           599:     UCHAR  bval;
        !           600:     USHORT cnt, i;
        !           601:     PDCB   ptr;
        !           602: 
        !           603:     if( !(pDCB->IdentifyMsg & 0x07) )
        !           604:     {
        !           605:        if( pACB->scan_devices )
        !           606:        {
        !           607:            CurrDCBscntl3 = pDCB->DCBscntl3;
        !           608:        }
        !           609:        else
        !           610:        {
        !           611:            ptr = pACB->pLinkDCB;
        !           612:            cnt = pACB->DeviceCnt;
        !           613:            bval = pDCB->UnitSCSIID;
        !           614:            for(i=0; i<cnt; i++)
        !           615:            {
        !           616:                if( ptr->UnitSCSIID == bval )
        !           617:                {
        !           618:                    ptr->DCBsxfer = pDCB->DCBsxfer;
        !           619:                    ptr->DCBscntl3 = pDCB->DCBscntl3;
        !           620:                }
        !           621:                ptr = ptr->pNextDCB;
        !           622:            }
        !           623:        }
        !           624:     }
        !           625:     return;
        !           626: }
        !           627: 
        !           628: 
        !           629: static void
        !           630: DC390W_UnknownMsg( PACB pACB )
        !           631: {
        !           632:     PSRB pSRB;
        !           633:     ULONG wlval;
        !           634:     USHORT ioport;
        !           635: 
        !           636:     pSRB = pACB->pActiveDCB->pActiveSRB;
        !           637:     pSRB->__msgout0[0] = 1;
        !           638:     pSRB->MsgOutBuf[0] = MSG_REJECT_;
        !           639:     wlval = pACB->jmp_set_atn;
        !           640:     ioport = pACB->IOPortBase;
        !           641:     outl(wlval,(ioport+DSP));
        !           642:     return;
        !           643: }
        !           644: 
        !           645: 
        !           646: static void
        !           647: DC390W_MessageExtnd( PACB pACB )
        !           648: {
        !           649:     DC390W_UnknownMsg( pACB );
        !           650: }
        !           651: 
        !           652: 
        !           653: static void
        !           654: DC390W_Disconnected( PACB pACB )
        !           655: {
        !           656:     PDCB pDCB;
        !           657:     PSRB pSRB;
        !           658:     ULONG  wlval, flags;
        !           659:     USHORT ioport;
        !           660:     UCHAR bval;
        !           661: 
        !           662: #ifdef DC390W_DEBUG0
        !           663:     printk("Discnet,");
        !           664: #endif
        !           665:     save_flags(flags);
        !           666:     cli();
        !           667:     pDCB = pACB->pActiveDCB;
        !           668:     if (! pDCB)
        !           669:      {
        !           670: #ifdef DC390W_DEBUG0
        !           671:        printk("ACB:%08lx->ActiveDCB:%08lx !,", (ULONG)pACB, (ULONG)pDCB);
        !           672: #endif
        !           673:        restore_flags(flags); return;
        !           674:      }
        !           675: 
        !           676:     pSRB = pDCB->pActiveSRB;
        !           677: 
        !           678:     ioport = pACB->IOPortBase;
        !           679:     bval = inb(ioport+SCRATCHA);
        !           680:     pSRB->ScratchABuf = bval;
        !           681:     pSRB->SRBState |= SRB_DISCONNECT;  /* 1.02 */
        !           682:     wlval = pACB->jmp_reselect;
        !           683:     outl(wlval,(ioport+DSP));
        !           684:     pACB->pActiveDCB = 0;
        !           685:     DoWaitingSRB( pACB );
        !           686:     restore_flags(flags);
        !           687:     return;
        !           688: }
        !           689: 
        !           690: 
        !           691: static void
        !           692: DC390W_Reselected( PACB pACB )
        !           693: {
        !           694: #ifdef DC390W_DEBUG0
        !           695:     printk("Rsel,");
        !           696: #endif
        !           697:     pACB->msgin123[0] = 0x80;   /* set identify byte 80h */
        !           698:     DC390W_Reselected1(pACB);
        !           699:     return;
        !           700: }
        !           701: 
        !           702: 
        !           703: static void
        !           704: DC390W_Reselected1( PACB pACB )
        !           705: {
        !           706:     PDCB   pDCB;
        !           707:     PSRB   pSRB;
        !           708:     USHORT ioport, wval;
        !           709:     ULONG  wlval, flags;
        !           710:     UCHAR  bval;
        !           711: 
        !           712: 
        !           713: #ifdef DC390W_DEBUG0
        !           714:     printk("Rsel1,");
        !           715: #endif
        !           716:     ioport = pACB->IOPortBase;
        !           717:     pDCB = pACB->pActiveDCB;
        !           718:     if(pDCB)
        !           719:     {
        !           720:        pSRB = pDCB->pActiveSRB;
        !           721:        RewaitSRB( pDCB, pSRB );
        !           722:     }
        !           723: 
        !           724:     wval = (USHORT) (pACB->msgin123[0]);
        !           725:     wval = (wval & 7) << 8;            /* get LUN */
        !           726:     wval |= (USHORT) (inb(ioport+SSID) & 0x0f); /* get ID */
        !           727:     pDCB = pACB->pLinkDCB;
        !           728:     while( *((PUSHORT) &pDCB->UnitSCSIID) != wval )
        !           729:        pDCB = pDCB->pNextDCB;
        !           730:     pACB->pActiveDCB = pDCB;
        !           731:     bval = pDCB->DCBscntl3;
        !           732:     outb(bval,ioport+SCNTL3);
        !           733:     bval = pDCB->DCBsxfer;
        !           734:     outb(bval,ioport+SXFER);
        !           735:     bval = pDCB->DCBscntl0;
        !           736:     outb(bval,ioport+SCNTL0);
        !           737:     if(pDCB->MaxCommand > 1)
        !           738:     {
        !           739:        wlval = pACB->jmp_reselecttag;
        !           740:        outl(wlval,(ioport+DSP));
        !           741:     }
        !           742:     else
        !           743:     {
        !           744:        pSRB = pDCB->pActiveSRB;
        !           745:        if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
        !           746:        {
        !           747:            save_flags(flags);
        !           748:            cli();
        !           749:            pSRB = pACB->pFreeSRB;
        !           750:            pACB->pFreeSRB = pSRB->pNextSRB;
        !           751:            restore_flags(flags);
        !           752:            pSRB->SRBState = SRB_UNEXPECT_RESEL;
        !           753:            pDCB->pActiveSRB = pSRB;
        !           754:            pSRB->MsgOutBuf[0] = MSG_ABORT;
        !           755:            pSRB->__msgout0[0] = 1;
        !           756:        }
        !           757:        pSRB->SRBState &= ~SRB_DISCONNECT;
        !           758:        wlval = pSRB->PhysSRB;
        !           759:        outl(wlval,(ioport+DSA));
        !           760:        wlval = pSRB->ReturnAddr;
        !           761:        outl(wlval,(ioport+TEMP));
        !           762:        bval = pSRB->ScratchABuf;
        !           763:        outb(bval,ioport+SCRATCHA);
        !           764:        if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
        !           765:            wlval = pACB->jmp_set_atn;
        !           766:        else
        !           767:            wlval = pACB->jmp_clear_ack;
        !           768:        outl(wlval,(ioport+DSP));
        !           769:     }
        !           770:     return;
        !           771: }
        !           772: 
        !           773: 
        !           774: static void
        !           775: DC390W_ReselectedT( PACB pACB )
        !           776: {
        !           777:     PDCB pDCB;
        !           778:     PSRB pSRB, psrb1;
        !           779:     USHORT ioport;
        !           780:     ULONG wlval, flags;
        !           781:     UCHAR bval;
        !           782: 
        !           783: #ifdef DC390W_DEBUG0
        !           784:     printk("RselT,");
        !           785: #endif
        !           786:     ioport = pACB->IOPortBase;
        !           787:     bval = pACB->msgin123[1];
        !           788:     pDCB = pACB->pActiveDCB;
        !           789:     pSRB = pDCB->pGoingSRB;
        !           790:     psrb1 = pDCB->pGoingLast;
        !           791:     if( !pSRB )
        !           792:        goto  UXP_RSL;
        !           793:     for(;;)
        !           794:     {
        !           795:        if(pSRB->TagNumber != bval)
        !           796:        {
        !           797:            if( pSRB != psrb1 )
        !           798:                pSRB = pSRB->pNextSRB;
        !           799:            else
        !           800:                goto  UXP_RSL;
        !           801:        }
        !           802:        else
        !           803:            break;
        !           804:     }
        !           805:     if( !(pSRB->SRBState & SRB_DISCONNECT) )
        !           806:     {
        !           807: UXP_RSL:
        !           808:            save_flags(flags);
        !           809:            cli();
        !           810:            pSRB = pACB->pFreeSRB;
        !           811:            pACB->pFreeSRB = pSRB->pNextSRB;
        !           812:            restore_flags(flags);
        !           813:            pSRB->SRBState = SRB_UNEXPECT_RESEL;
        !           814:            pDCB->pActiveSRB = pSRB;
        !           815:            pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
        !           816:            pSRB->__msgout0[0] = 1;
        !           817:     }
        !           818:     else
        !           819:     {
        !           820:        pSRB->SRBState &= ~SRB_DISCONNECT;
        !           821:        pDCB->pActiveSRB = pSRB;
        !           822:     }
        !           823:     wlval = pSRB->PhysSRB;
        !           824:     outl(wlval,(ioport+DSA));
        !           825:     wlval = pSRB->ReturnAddr;
        !           826:     outl(wlval,(ioport+TEMP));
        !           827:     bval = pSRB->ScratchABuf;
        !           828:     outb(bval,ioport+SCRATCHA);
        !           829:     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
        !           830:        wlval = pACB->jmp_set_atn;
        !           831:     else
        !           832:        wlval = pACB->jmp_clear_ack;
        !           833:     outl(wlval,(ioport+DSP));
        !           834:     return;
        !           835: }
        !           836: 
        !           837: 
        !           838: static void
        !           839: DC390W_RestorePtr( PACB pACB )
        !           840: {
        !           841:    PSRB pSRB;
        !           842:    USHORT ioport;
        !           843:    ULONG wlval;
        !           844: 
        !           845:    pSRB = pACB->pActiveDCB->pActiveSRB;
        !           846:    wlval = pSRB->ReturnAddr;
        !           847:    ioport = pACB->IOPortBase;
        !           848:    outl(wlval,(ioport+TEMP));
        !           849:    wlval = inl(ioport+DSP);
        !           850:    outl(wlval,(ioport+DSP));
        !           851:    return;
        !           852: }
        !           853: 
        !           854: 
        !           855: static void
        !           856: PhaseMismatch( PACB pACB )
        !           857: {
        !           858:     USHORT  ioport;
        !           859:     ULONG   wlval,swlval;
        !           860:     USHORT  wval;
        !           861:     UCHAR   bval,phase;
        !           862:     PDCB    pDCB;
        !           863: 
        !           864: #ifdef DC390W_DEBUG0
        !           865:     printk("Mismatch,");
        !           866: #endif
        !           867:     ioport = pACB->IOPortBase;
        !           868:     bval = inb(ioport+SCRATCHA);
        !           869:     if(bval & OVER_RUN_)       /* xfer PAD */
        !           870:     {
        !           871:        bval = inb(ioport+STEST3);
        !           872:        bval |= CLR_SCSI_FIFO;
        !           873:        outb(bval,ioport+STEST3);
        !           874:        bval = CLR_DMA_FIFO;
        !           875:        outb(bval,ioport+CTEST3);
        !           876:        wlval = pACB->jmp_next;          /* check phase */
        !           877:        outl(wlval,(ioport+DSP));
        !           878:        return;
        !           879:     }
        !           880:     pDCB = pACB->pActiveDCB;
        !           881:     wlval = inl(ioport+DBC);
        !           882:     phase = (UCHAR)((wlval & 0x07000000) >> 24);
        !           883:     wlval &= 0xffffff; /* bytes not xferred */
        !           884:     if( phase == SCSI_DATA_IN )
        !           885:     {
        !           886:        swlval = pACB->jmp_din8;
        !           887:        if( pDCB->DCBscntl3 & EN_WIDE_SCSI )
        !           888:             swlval += jmp_din16;
        !           889:        DataIOcommon(pACB,swlval,wlval);
        !           890:     }
        !           891:     else if( phase == SCSI_DATA_OUT )
        !           892:     {
        !           893:        wval = (USHORT)inb(ioport+CTEST5);
        !           894:        wval <<= 8;
        !           895:        bval = inb(ioport+DFIFO);
        !           896:        wval |= (USHORT) bval;
        !           897:        wval -= ((USHORT)(wlval & 0xffff));
        !           898:        wval &= 0x3ff;
        !           899:        wlval += (ULONG)wval;  /* # of bytes remains in FIFO */
        !           900:        bval = inb(ioport+SSTAT0);
        !           901:        if(bval & SODR_LSB_FULL)
        !           902:           wlval++;            /* data left in Scsi Output Data Buffer */
        !           903:        if(bval & SODL_LSB_FULL)
        !           904:           wlval++;            /* data left in Scsi Output Data Latch */
        !           905:        swlval = pACB->jmp_dout8;
        !           906:        if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !           907:        {
        !           908:           swlval += jmp_dout16;
        !           909:           bval = inb(ioport+SSTAT2);
        !           910:           if(bval & SODR_MSB_FULL)
        !           911:               wlval++;
        !           912:           if(bval & SODL_MSB_FULL)
        !           913:               wlval++;
        !           914:        }
        !           915:        bval = inb(ioport+STEST3);
        !           916:        bval |= CLR_SCSI_FIFO;
        !           917:        outb(bval,ioport+STEST3);
        !           918:        bval = CLR_DMA_FIFO;
        !           919:        outb(bval,ioport+CTEST3);
        !           920:        DataIOcommon(pACB,swlval,wlval);
        !           921:     }
        !           922:     else
        !           923:     {
        !           924:        bval = inb(ioport+STEST3);
        !           925:        bval |= CLR_SCSI_FIFO;
        !           926:        outb(bval,ioport+STEST3);
        !           927:        bval = CLR_DMA_FIFO;
        !           928:        outb(bval,ioport+CTEST3);
        !           929:        if(phase == SCSI_MSG_OUT)
        !           930:            wlval = pACB->jmp_clear_atn;
        !           931:        else
        !           932:            wlval = pACB->jmp_next;     /* check phase */
        !           933:        outl(wlval,(ioport+DSP));
        !           934:     }
        !           935:     return;
        !           936: }
        !           937: 
        !           938: 
        !           939: static void
        !           940: DataIOcommon( PACB pACB, ULONG Swlval, ULONG  Cwlval )
        !           941: {
        !           942:     /* Swlval - script address */
        !           943:     /* Cwlval - bytes not xferred */
        !           944:     PDCB pDCB;
        !           945:     PSRB pSRB;
        !           946:     PSGE Segptr;
        !           947:     USHORT ioport;
        !           948:     ULONG  wlval,swlval,dataXferCnt;
        !           949:     UCHAR  bval,bvald;
        !           950: 
        !           951:     ioport = pACB->IOPortBase;
        !           952:     wlval = inl((ioport+DSP));
        !           953:     pDCB = pACB->pActiveDCB;
        !           954:     pSRB = pDCB->pActiveSRB;
        !           955:     wlval -= Swlval;
        !           956:     bval = inb(ioport+SBCL);
        !           957:     bval &= 0x07;
        !           958:     if(bval == SCSI_MSG_IN)
        !           959:     {
        !           960:        bval = pDCB->DCBscntl3;
        !           961:        bval &= ~EN_WIDE_SCSI;
        !           962:        outb(bval,ioport+SCNTL3);
        !           963:        bval = inb(ioport+SBDL);
        !           964:        bvald = pDCB->DCBscntl3;    /* enable WIDE SCSI */
        !           965:        outb(bvald,ioport+SCNTL3);
        !           966:        if(bval == MSG_DISCONNECT || bval == MSG_SAVE_PTR)
        !           967:        {
        !           968:            Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval);
        !           969:            dataXferCnt = Segptr->SGXLen - Cwlval;
        !           970:            Segptr->SGXLen = Cwlval;            /* modified count */
        !           971:            Segptr->SGXPtr += dataXferCnt;      /* modified address */
        !           972:            swlval = pACB->jmp_table8;
        !           973:            if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !           974:                swlval += jmp_table16;
        !           975:            wlval <<= 1;
        !           976:            swlval += wlval;
        !           977:            swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16);
        !           978:            pSRB->ReturnAddr = swlval;
        !           979:        }
        !           980:     }
        !           981:     else if( Cwlval )  /* Remaining not xferred -- UNDER_RUN */
        !           982:     {
        !           983:        Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval);
        !           984:        dataXferCnt = Segptr->SGXLen - Cwlval;
        !           985:        Segptr->SGXLen = Cwlval;            /* modified count */
        !           986:        Segptr->SGXPtr += dataXferCnt;      /* modified address */
        !           987:        swlval = pACB->jmp_table8;
        !           988:        if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !           989:            swlval += jmp_table16;
        !           990:        wlval <<= 1;
        !           991:        swlval += wlval;
        !           992:        swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16);
        !           993:        pSRB->RemainSegPtr = swlval;
        !           994:     }
        !           995: /* pm__1: */
        !           996:     wlval = pSRB->ReturnAddr;
        !           997:     outl(wlval,(ioport+TEMP));
        !           998:     wlval = pACB->jmp_next;
        !           999:     outl(wlval,(ioport+DSP));
        !          1000:     return;
        !          1001: }
        !          1002: 
        !          1003: 
        !          1004: static void
        !          1005: DC390W_CmdCompleted( PACB pACB )
        !          1006: {
        !          1007:     PDCB pDCB;
        !          1008:     PSRB pSRB;
        !          1009:     USHORT ioport;
        !          1010:     ULONG  wlval, flags;
        !          1011:     UCHAR  bval;
        !          1012: 
        !          1013: #ifdef DC390W_DEBUG0
        !          1014:     printk("Cmplete,");
        !          1015: #endif
        !          1016:     save_flags(flags);
        !          1017:     cli();
        !          1018:     pDCB = pACB->pActiveDCB;
        !          1019:     pSRB = pDCB->pActiveSRB;
        !          1020:     pDCB->pActiveSRB = NULL;
        !          1021:     ioport = pACB->IOPortBase;
        !          1022: 
        !          1023:     bval  = inb(ioport+SCRATCHA);
        !          1024:     pSRB->ScratchABuf = bval;          /* save status */
        !          1025:     bval = pSRB->TagNumber;
        !          1026:     if(pDCB->MaxCommand > 1)
        !          1027:        pDCB->TagMask &= (~(1 << bval));   /* free tag mask */
        !          1028:     pACB->pActiveDCB = NULL;           /* no active device */
        !          1029:     wlval = pACB->jmp_reselect;        /* enable reselection */
        !          1030:     outl(wlval,(ioport+DSP));
        !          1031:     SRBdone( pACB, pDCB, pSRB);
        !          1032:     restore_flags(flags);
        !          1033:     return;
        !          1034: }
        !          1035: 
        !          1036: 
        !          1037: static void
        !          1038: SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
        !          1039: {
        !          1040:     PSRB   psrb;
        !          1041:     UCHAR  bval, bval1, i, j, status;
        !          1042:     PSCSICMD pcmd;
        !          1043:     PSCSI_INQDATA  ptr;
        !          1044:     USHORT  disable_tag;
        !          1045:     ULONG  flags;
        !          1046:     PSGE   ptr1;
        !          1047:     PSGL   ptr2;
        !          1048:     ULONG  wlval,swlval;
        !          1049: 
        !          1050:     pcmd = pSRB->pcmd;
        !          1051:     status = pACB->status;
        !          1052:     if(pSRB->SRBFlag & AUTO_REQSENSE)
        !          1053:     {
        !          1054:        pSRB->SRBFlag &= ~AUTO_REQSENSE;
        !          1055:        pSRB->AdaptStatus = 0;
        !          1056:        pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
        !          1057:        if(status == SCSI_STAT_CHECKCOND)
        !          1058:        {
        !          1059:            pcmd->result = DID_BAD_TARGET << 16;
        !          1060:            goto ckc_e;
        !          1061:        }
        !          1062:        if(pSRB->RetryCnt == 0)
        !          1063:        {
        !          1064:            *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0];
        !          1065:            pSRB->XferredLen = pSRB->Segment0[2][1];
        !          1066:            if( (pSRB->XferredLen) &&
        !          1067:                (pSRB->XferredLen >= pcmd->underflow) )
        !          1068:            {
        !          1069:                pcmd->result |= (DID_OK << 16);
        !          1070:            }
        !          1071:            else
        !          1072:                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
        !          1073:                                SCSI_STAT_CHECKCOND;
        !          1074:            goto ckc_e;
        !          1075:        }
        !          1076:        else
        !          1077:        {
        !          1078:            pSRB->RetryCnt--;
        !          1079:            pSRB->TargetStatus = 0;
        !          1080:            *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0];
        !          1081:            *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[0][1];
        !          1082:            *((PULONG) &(pSRB->CmdBlock[8])) = pSRB->Segment0[1][0];
        !          1083:            pSRB->__command[0]               = pSRB->Segment0[1][1] & 0xff;
        !          1084:            pSRB->SGcount                    = (UCHAR) (pSRB->Segment0[1][1] >> 8);
        !          1085:            *((PULONG) &(pSRB->pSegmentList))= pSRB->Segment0[2][0];
        !          1086:            if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
        !          1087:            {
        !          1088:                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
        !          1089:                                SCSI_STAT_CHECKCOND;
        !          1090:                goto ckc_e;
        !          1091:            }
        !          1092:            pcmd->result |= (DRIVER_SENSE << 24);
        !          1093:            PrepareSG(pACB,pDCB,pSRB);
        !          1094:            pSRB->XferredLen = 0;
        !          1095:            DC390W_StartSCSI( pACB, pDCB, pSRB );
        !          1096:            return;
        !          1097:        }
        !          1098:     }
        !          1099:     if( status )
        !          1100:     {
        !          1101:        if( status == SCSI_STAT_CHECKCOND)
        !          1102:        {
        !          1103:            if( !(pSRB->ScratchABuf & SRB_OK) && (pSRB->SGcount) && (pSRB->RemainSegPtr) )
        !          1104:            {
        !          1105:                wlval = pSRB->RemainSegPtr;
        !          1106:                swlval = pACB->jmp_table8;
        !          1107:                if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
        !          1108:                    swlval += jmp_table16;
        !          1109:                swlval -= wlval;
        !          1110:                swlval >>= 4;
        !          1111:                bval = (UCHAR) swlval;
        !          1112:                wlval = 0;
        !          1113:                ptr1 = (PSGE) &pSRB->Segment0[MAX_SG_LIST_BUF+1][0];
        !          1114:                for( i=0; i< bval; i++)
        !          1115:                {
        !          1116:                    wlval += ptr1->SGXLen;
        !          1117:                    ptr1--;
        !          1118:                }
        !          1119: 
        !          1120:                bval = pSRB->SGcount;
        !          1121:                swlval = 0;
        !          1122:                ptr2 = pSRB->pSegmentList;
        !          1123:                for( i=0; i< bval; i++)
        !          1124:                {
        !          1125:                    swlval += ptr2->length;
        !          1126:                    ptr2++;
        !          1127:                }
        !          1128:                pSRB->XferredLen = swlval - wlval;
        !          1129:                pSRB->RemainSegPtr = 0;
        !          1130: #ifdef DC390W_DEBUG0
        !          1131:                printk("XferredLen=%8x,NotXferLen=%8x,",(UINT) pSRB->XferredLen,(UINT) wlval);
        !          1132: #endif
        !          1133:            }
        !          1134:            RequestSense( pACB, pDCB, pSRB );
        !          1135:            return;
        !          1136:        }
        !          1137:        else if( status == SCSI_STAT_QUEUEFULL )
        !          1138:        {
        !          1139:            bval = (UCHAR) pDCB->GoingSRBCnt;
        !          1140:            bval--;
        !          1141:            pDCB->MaxCommand = bval;
        !          1142:            RewaitSRB( pDCB, pSRB );
        !          1143:            pSRB->AdaptStatus = 0;
        !          1144:            pSRB->TargetStatus = 0;
        !          1145:            return;
        !          1146:        }
        !          1147:        else if(status == SCSI_STAT_SEL_TIMEOUT)
        !          1148:        {
        !          1149:            pSRB->AdaptStatus = H_SEL_TIMEOUT;
        !          1150:            pSRB->TargetStatus = 0;
        !          1151:            pcmd->result = DID_BAD_TARGET << 16;
        !          1152:        }
        !          1153:        else if(status == SCSI_STAT_UNEXP_BUS_F)
        !          1154:        {
        !          1155:            pSRB->AdaptStatus = H_UNEXP_BUS_FREE;
        !          1156:            pSRB->TargetStatus = 0;
        !          1157:            pcmd->result |= DID_NO_CONNECT << 16;
        !          1158:        }
        !          1159:        else if(status == SCSI_STAT_BUS_RST_DETECT )
        !          1160:        {
        !          1161:            pSRB->AdaptStatus = H_ABORT;
        !          1162:            pSRB->TargetStatus = 0;
        !          1163:            pcmd->result = DID_RESET << 16;
        !          1164:        }
        !          1165:        else
        !          1166:        {
        !          1167:            pSRB->AdaptStatus = 0;
        !          1168:            pSRB->TargetStatus = status;
        !          1169:            if( pSRB->RetryCnt )
        !          1170:            {
        !          1171:                pSRB->RetryCnt--;
        !          1172:                pSRB->TargetStatus = 0;
        !          1173:                PrepareSG(pACB,pDCB,pSRB);
        !          1174:                pSRB->XferredLen = 0;
        !          1175:                DC390W_StartSCSI( pACB, pDCB, pSRB );
        !          1176:                return;
        !          1177:            }
        !          1178:            else
        !          1179:            {
        !          1180:                pcmd->result |= (DID_ERROR << 16) | (ULONG) (pACB->msgin123[0] << 8) |
        !          1181:                               (ULONG) status;
        !          1182:            }
        !          1183:        }
        !          1184:     }
        !          1185:     else
        !          1186:     {
        !          1187:        status = pSRB->ScratchABuf;
        !          1188:        if(status & OVER_RUN_)
        !          1189:        {
        !          1190:            pSRB->AdaptStatus = H_OVER_UNDER_RUN;
        !          1191:            pSRB->TargetStatus = 0;
        !          1192:            pcmd->result |= (DID_OK << 16) | (pACB->msgin123[0] << 8);
        !          1193:        }
        !          1194:        else                   /* No error */
        !          1195:        {
        !          1196:            pSRB->AdaptStatus = 0;
        !          1197:            pSRB->TargetStatus = 0;
        !          1198:            pcmd->result |= (DID_OK << 16);
        !          1199:        }
        !          1200:     }
        !          1201: ckc_e:
        !          1202: 
        !          1203:     if( pACB->scan_devices )
        !          1204:     {
        !          1205:        if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
        !          1206:        {
        !          1207:            if(pcmd->result != (DID_OK << 16))
        !          1208:            {
        !          1209:                if( pcmd->result & SCSI_STAT_CHECKCOND )
        !          1210:                {
        !          1211:                    goto RTN_OK;
        !          1212:                }
        !          1213:                else
        !          1214:                {
        !          1215:                    pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
        !          1216:                    pPrevDCB->pNextDCB = pACB->pLinkDCB;
        !          1217:                    if( (pcmd->target == pACB->max_id) &&
        !          1218:                       ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) )
        !          1219:                    {
        !          1220:                        pACB->scan_devices = 0;
        !          1221:                    }
        !          1222:                }
        !          1223:            }
        !          1224:            else
        !          1225:            {
        !          1226: RTN_OK:
        !          1227:                pPrevDCB->pNextDCB = pDCB;
        !          1228:                pDCB->pNextDCB = pACB->pLinkDCB;
        !          1229:                if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) )
        !          1230:                    pACB->scan_devices = END_SCAN;
        !          1231:            }
        !          1232:        }
        !          1233:        else if( pSRB->CmdBlock[0] == INQUIRY )
        !          1234:        {
        !          1235:            if( (pcmd->target == pACB->max_id) &&
        !          1236:                (pcmd->lun == pACB->max_lun) )
        !          1237:            {
        !          1238:                pACB->scan_devices = 0;
        !          1239:            }
        !          1240:            ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
        !          1241:            if( pcmd->use_sg )
        !          1242:                ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
        !          1243:            bval1 = ptr->DevType & SCSI_DEVTYPE;
        !          1244:            if(bval1 == SCSI_NODEV)
        !          1245:            {
        !          1246:                pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
        !          1247:                pPrevDCB->pNextDCB = pACB->pLinkDCB;
        !          1248:            }
        !          1249:            else
        !          1250:            {
        !          1251:                pACB->DeviceCnt++;
        !          1252:                pPrevDCB = pDCB;
        !          1253:                pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390W_DCB ));
        !          1254:                pDCB->DevType = bval1;
        !          1255:                if(bval1 == TYPE_DISK || bval1 == TYPE_MOD)
        !          1256:                {
        !          1257:                    if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
        !          1258:                        (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
        !          1259:                        (pDCB->DevMode & TAG_QUEUING_) &&
        !          1260:                        (pDCB->DevMode & EN_DISCONNECT_) )
        !          1261:                    {
        !          1262:                        disable_tag = 0;
        !          1263:                        for(i=0; i<BADDEVCNT; i++)
        !          1264:                        {
        !          1265:                            for(j=0; j<28; j++)
        !          1266:                            {
        !          1267:                                if( ((PUCHAR)ptr)[8+j] != baddevname[i][j])
        !          1268:                                    break;
        !          1269:                            }
        !          1270:                            if(j == 28)
        !          1271:                            {
        !          1272:                                disable_tag = 1;
        !          1273:                                break;
        !          1274:                            }
        !          1275:                        }
        !          1276: 
        !          1277:                        if( !disable_tag )
        !          1278:                        {
        !          1279:                            pDCB->MaxCommand = pACB->TagMaxNum;
        !          1280:                            pDCB->TagMask = 0;
        !          1281:                        }
        !          1282:                    }
        !          1283:                }
        !          1284:            }
        !          1285:        }
        !          1286:     }
        !          1287: 
        !          1288:     save_flags( flags );
        !          1289:     cli();
        !          1290: /*  ReleaseSRB( pDCB, pSRB ); */
        !          1291: 
        !          1292:     if(pSRB == pDCB->pGoingSRB )
        !          1293:     {
        !          1294:        pDCB->pGoingSRB = pSRB->pNextSRB;
        !          1295:     }
        !          1296:     else
        !          1297:     {
        !          1298:        psrb = pDCB->pGoingSRB;
        !          1299:        while( psrb->pNextSRB != pSRB )
        !          1300:            psrb = psrb->pNextSRB;
        !          1301:        psrb->pNextSRB = pSRB->pNextSRB;
        !          1302:        if( pSRB == pDCB->pGoingLast )
        !          1303:            pDCB->pGoingLast = psrb;
        !          1304:     }
        !          1305:     pSRB->pNextSRB = pACB->pFreeSRB;
        !          1306:     pACB->pFreeSRB = pSRB;
        !          1307:     pDCB->GoingSRBCnt--;
        !          1308: 
        !          1309:     DoWaitingSRB( pACB );
        !          1310:     restore_flags(flags);
        !          1311: 
        !          1312: /*  Notify cmd done */
        !          1313:     pcmd->scsi_done( pcmd );
        !          1314: 
        !          1315:     if( pDCB->QIORBCnt )
        !          1316:        DoNextCmd( pACB, pDCB );
        !          1317:     return;
        !          1318: }
        !          1319: 
        !          1320: 
        !          1321: static void
        !          1322: DoingSRB_Done( PACB pACB )
        !          1323: {
        !          1324:     PDCB  pDCB, pdcb;
        !          1325:     PSRB  psrb, psrb2;
        !          1326:     USHORT  cnt, i;
        !          1327:     PSCSICMD pcmd;
        !          1328: 
        !          1329:     pDCB = pACB->pLinkDCB;
        !          1330:     pdcb = pDCB;
        !          1331:     do
        !          1332:     {
        !          1333:        cnt = pdcb->GoingSRBCnt;
        !          1334:        psrb = pdcb->pGoingSRB;
        !          1335:        for( i=0; i<cnt; i++)
        !          1336:        {
        !          1337:            psrb2 = psrb->pNextSRB;
        !          1338:            pcmd = psrb->pcmd;
        !          1339:            pcmd->result = DID_RESET << 16;
        !          1340: 
        !          1341: /*         ReleaseSRB( pDCB, pSRB ); */
        !          1342: 
        !          1343:            psrb->pNextSRB = pACB->pFreeSRB;
        !          1344:            pACB->pFreeSRB = psrb;
        !          1345: 
        !          1346:            pcmd->scsi_done( pcmd );
        !          1347:            psrb  = psrb2;
        !          1348:        }
        !          1349:        pdcb->GoingSRBCnt = 0;;
        !          1350:        pdcb->pGoingSRB = NULL;
        !          1351:        pdcb->TagMask = 0;
        !          1352:        pdcb = pdcb->pNextDCB;
        !          1353:     }
        !          1354:     while( pdcb != pDCB );
        !          1355: }
        !          1356: 
        !          1357: 
        !          1358: static void
        !          1359: DC390W_ResetSCSIBus( PACB pACB )
        !          1360: {
        !          1361:     USHORT ioport;
        !          1362:     UCHAR  bval;
        !          1363:     ULONG  flags;
        !          1364: 
        !          1365:     save_flags(flags);
        !          1366:     cli();
        !          1367:     pACB->ACBFlag |= RESET_DEV;
        !          1368:     ioport = pACB->IOPortBase;
        !          1369:     bval = ABORT_OP;
        !          1370:     outb(bval,ioport+ISTAT);
        !          1371:     udelay(25);
        !          1372:     bval = 0;
        !          1373:     outb(bval,ioport+ISTAT);
        !          1374: 
        !          1375:     bval = ASSERT_RST;
        !          1376:     outb(bval,ioport+SCNTL1);
        !          1377:     udelay(25);         /* 25 us */
        !          1378:     bval = 0;
        !          1379:     outb(bval,ioport+SCNTL1);
        !          1380:     restore_flags(flags);
        !          1381:     return;
        !          1382: }
        !          1383: 
        !          1384: 
        !          1385: 
        !          1386: static void
        !          1387: DC390W_ResetSCSIBus2( PACB pACB )
        !          1388: {
        !          1389:     USHORT ioport;
        !          1390:     UCHAR  bval;
        !          1391:     ULONG  flags;
        !          1392: 
        !          1393:     save_flags(flags);
        !          1394:     cli();
        !          1395:     ioport = pACB->IOPortBase;
        !          1396:     bval = ASSERT_RST;
        !          1397:     outb(bval,ioport+SCNTL1);
        !          1398:     udelay(25);         /* 25 us */
        !          1399:     bval = 0;
        !          1400:     outb(bval,ioport+SCNTL1);
        !          1401:     restore_flags(flags);
        !          1402:     return;
        !          1403: }
        !          1404: 
        !          1405: 
        !          1406: 
        !          1407: static void
        !          1408: DC390W_ScsiRstDetect( PACB pACB )
        !          1409: {
        !          1410:     ULONG wlval, flags;
        !          1411:     USHORT ioport;
        !          1412:     UCHAR  bval;
        !          1413: 
        !          1414:     save_flags(flags);
        !          1415:     sti();
        !          1416: #ifdef DC390W_DEBUG0
        !          1417:     printk("Reset_Detect0,");
        !          1418: #endif
        !          1419: /* delay 1 sec */
        !          1420:     wlval = jiffies + HZ;
        !          1421:     while( jiffies < wlval );
        !          1422: /*  USHORT  i;
        !          1423:     for( i=0; i<1000; i++ )
        !          1424:        udelay(1000); */
        !          1425: 
        !          1426:     cli();
        !          1427:     ioport = pACB->IOPortBase;
        !          1428:     bval = inb(ioport+STEST3);
        !          1429:     bval |= CLR_SCSI_FIFO;
        !          1430:     outb(bval,ioport+STEST3);
        !          1431:     bval = CLR_DMA_FIFO;
        !          1432:     outb(bval,ioport+CTEST3);
        !          1433: 
        !          1434:     if( pACB->ACBFlag & RESET_DEV )
        !          1435:        pACB->ACBFlag |= RESET_DONE;
        !          1436:     else
        !          1437:     {
        !          1438:        pACB->ACBFlag |= RESET_DETECT;
        !          1439: 
        !          1440:        ResetDevParam( pACB );
        !          1441: /*     DoingSRB_Done( pACB ); ???? */
        !          1442:        RecoverSRB( pACB );
        !          1443:        pACB->pActiveDCB = NULL;
        !          1444:        wlval = pACB->jmp_reselect;
        !          1445:        outl(wlval,(ioport+DSP));
        !          1446:        pACB->ACBFlag = 0;
        !          1447:        DoWaitingSRB( pACB );
        !          1448:     }
        !          1449:     restore_flags(flags);
        !          1450:     return;
        !          1451: }
        !          1452: 
        !          1453: 
        !          1454: static void
        !          1455: RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
        !          1456: {
        !          1457:     PSCSICMD  pcmd;
        !          1458: 
        !          1459:     pSRB->SRBFlag |= AUTO_REQSENSE;
        !          1460:     pSRB->Segment0[0][0] = *((PULONG) &(pSRB->CmdBlock[0]));
        !          1461:     pSRB->Segment0[0][1] = *((PULONG) &(pSRB->CmdBlock[4]));
        !          1462:     pSRB->Segment0[1][0] = *((PULONG) &(pSRB->CmdBlock[8]));
        !          1463:     pSRB->Segment0[1][1] = pSRB->__command[0] | (pSRB->SGcount << 8);
        !          1464:     pSRB->Segment0[2][0] = *((PULONG) &(pSRB->pSegmentList));
        !          1465:     pSRB->Segment0[2][1] = pSRB->XferredLen;
        !          1466:     pSRB->AdaptStatus = 0;
        !          1467:     pSRB->TargetStatus = 0;
        !          1468: 
        !          1469:     pcmd = pSRB->pcmd;
        !          1470: 
        !          1471:     pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
        !          1472:     pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
        !          1473:     pSRB->pSegmentList = &pSRB->Segmentx;
        !          1474:     pSRB->SGcount = 1;
        !          1475: 
        !          1476:     *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
        !          1477:     pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
        !          1478:     *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer);
        !          1479:     pSRB->__command[0] = 6;
        !          1480:     PrepareSG( pACB, pDCB, pSRB );
        !          1481:     pSRB->XferredLen = 0;
        !          1482:     DC390W_StartSCSI( pACB, pDCB, pSRB );
        !          1483:     return;
        !          1484: }
        !          1485: 
        !          1486: 
        !          1487: static void
        !          1488: DC390W_MessageOut( PACB pACB )
        !          1489: {
        !          1490:     DC390W_FatalError( pACB );
        !          1491: }
        !          1492: 
        !          1493: 
        !          1494: static void
        !          1495: DC390W_FatalError( PACB pACB )
        !          1496: {
        !          1497:     PSRB  pSRB;
        !          1498:     PDCB  pDCB;
        !          1499:     ULONG flags;
        !          1500: 
        !          1501: #ifdef DC390W_DEBUG0
        !          1502:    printk("DC390W: Fatal Error!!\n");
        !          1503: #endif
        !          1504: 
        !          1505:     pDCB = pACB->pActiveDCB;
        !          1506:     pSRB = pDCB->pActiveSRB;
        !          1507:     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
        !          1508:     {
        !          1509:        save_flags(flags);
        !          1510:        cli();
        !          1511:        pSRB->SRBState &= ~SRB_UNEXPECT_RESEL;
        !          1512:        pSRB->pNextSRB = pACB->pFreeSRB;
        !          1513:        pACB->pFreeSRB = pSRB;
        !          1514:        pACB->pActiveDCB = NULL;
        !          1515:        pDCB->pActiveSRB = NULL;
        !          1516:        restore_flags(flags);
        !          1517:        DoWaitingSRB( pACB );
        !          1518:     }
        !          1519:     else
        !          1520:        DC390W_ResetSCSIBus(pACB);
        !          1521:     return;
        !          1522: }
        !          1523: 
        !          1524: 
        !          1525: static void
        !          1526: DC390W_Debug( PACB pACB )
        !          1527: {
        !          1528:    ULONG wlval;
        !          1529:    USHORT ioport;
        !          1530: 
        !          1531:    ioport = pACB->IOPortBase;
        !          1532:    wlval = inl(ioport+DSP);
        !          1533:    outl(wlval,(ioport+DSP));
        !          1534:    return;
        !          1535: }
        !          1536: 
        !          1537: 

unix.superglobalmegacorp.com

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