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

1.1     ! root        1: /***********************************************************************
        !             2:  *     FILE NAME : SCSIIOM.C                                          *
        !             3:  *          BY   : C.L. Huang,    [email protected]                 *
        !             4:  *     Description: Device Driver for Tekram DC-390 (T) PCI SCSI      *
        !             5:  *                  Bus Master Host Adapter                           *
        !             6:  ***********************************************************************/
        !             7: 
        !             8: 
        !             9: static USHORT
        !            10: DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
        !            11: {
        !            12:     USHORT ioport, rc;
        !            13:     UCHAR  bval, bval1, i, cnt;
        !            14:     PUCHAR ptr;
        !            15:     ULONG  wlval;
        !            16: 
        !            17:     pSRB->TagNumber = 31;
        !            18:     ioport = pACB->IOPortBase;
        !            19:     bval = pDCB->UnitSCSIID;
        !            20:     outb(bval,ioport+Scsi_Dest_ID);
        !            21:     bval = pDCB->SyncPeriod;
        !            22:     outb(bval,ioport+Sync_Period);
        !            23:     bval = pDCB->SyncOffset;
        !            24:     outb(bval,ioport+Sync_Offset);
        !            25:     bval = pDCB->CtrlR1;
        !            26:     outb(bval,ioport+CtrlReg1);
        !            27:     bval = pDCB->CtrlR3;
        !            28:     outb(bval,ioport+CtrlReg3);
        !            29:     bval = pDCB->CtrlR4;
        !            30:     outb(bval,ioport+CtrlReg4);
        !            31:     bval = CLEAR_FIFO_CMD;        /* Flush FIFO */
        !            32:     outb(bval,ioport+ScsiCmd);
        !            33: 
        !            34:     pSRB->ScsiPhase = SCSI_NOP0;
        !            35:     bval = pDCB->IdentifyMsg;
        !            36:     if( !(pDCB->SyncMode & EN_ATN_STOP) )
        !            37:     {
        !            38:        if( (pSRB->CmdBlock[0] == INQUIRY) ||
        !            39:            (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
        !            40:            (pSRB->SRBFlag & AUTO_REQSENSE) )
        !            41:        {
        !            42:            bval &= 0xBF;       /* NO disconnection */
        !            43:            outb(bval,ioport+ScsiFifo);
        !            44:            bval1 = SELECT_W_ATN;
        !            45:            pSRB->SRBState = SRB_START_;
        !            46:            if( pDCB->SyncMode & SYNC_ENABLE )
        !            47:            {
        !            48:                if( !(pDCB->IdentifyMsg & 7) ||
        !            49:                    (pSRB->CmdBlock[0] != INQUIRY) )
        !            50:                {
        !            51:                    bval1 = SEL_W_ATN_STOP;
        !            52:                    pSRB->SRBState = SRB_MSGOUT;
        !            53:                }
        !            54:            }
        !            55:        }
        !            56:        else
        !            57:        {
        !            58:            if(pDCB->SyncMode & EN_TAG_QUEUING)
        !            59:            {
        !            60:                outb(bval,ioport+ScsiFifo);
        !            61:                bval = MSG_SIMPLE_QTAG;
        !            62:                outb(bval,ioport+ScsiFifo);
        !            63:                wlval = 1;
        !            64:                bval = 0;
        !            65:                while( wlval & pDCB->TagMask )
        !            66:                {
        !            67:                    wlval = wlval << 1;
        !            68:                    bval++;
        !            69:                }
        !            70:                outb(bval,ioport+ScsiFifo);
        !            71:                pDCB->TagMask |= wlval;
        !            72:                pSRB->TagNumber = bval;
        !            73:                bval1 = SEL_W_ATN2;
        !            74:                pSRB->SRBState = SRB_START_;
        !            75:            }
        !            76:            else
        !            77:            {
        !            78:                outb(bval,ioport+ScsiFifo);
        !            79:                bval1 = SELECT_W_ATN;
        !            80:                pSRB->SRBState = SRB_START_;
        !            81:            }
        !            82:        }
        !            83: 
        !            84:        if( pSRB->SRBFlag & AUTO_REQSENSE )
        !            85:        {
        !            86:            bval = REQUEST_SENSE;
        !            87:            outb(bval,ioport+ScsiFifo);
        !            88:            bval = pDCB->IdentifyMsg << 5;
        !            89:            outb(bval,ioport+ScsiFifo);
        !            90:            bval = 0;
        !            91:            outb(bval,ioport+ScsiFifo);
        !            92:            outb(bval,ioport+ScsiFifo);
        !            93:            bval = sizeof(pSRB->pcmd->sense_buffer);
        !            94:            outb(bval,ioport+ScsiFifo);
        !            95:            bval = 0;
        !            96:            outb(bval,ioport+ScsiFifo);
        !            97:        }
        !            98:        else
        !            99:        {
        !           100:            cnt = pSRB->ScsiCmdLen;
        !           101:            ptr = (PUCHAR) pSRB->CmdBlock;
        !           102:            for(i=0; i<cnt; i++)
        !           103:            {
        !           104:                bval = *ptr++;
        !           105:                outb(bval,ioport+ScsiFifo);
        !           106:            }
        !           107:        }
        !           108:     }
        !           109:     else       /* ATN_STOP */
        !           110:     {
        !           111:        if( (pSRB->CmdBlock[0] == INQUIRY) ||
        !           112:            (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
        !           113:            (pSRB->SRBFlag & AUTO_REQSENSE) )
        !           114:        {
        !           115:            bval &= 0xBF;
        !           116:            outb(bval,ioport+ScsiFifo);
        !           117:            bval1 = SELECT_W_ATN;
        !           118:            pSRB->SRBState = SRB_START_;
        !           119:            if( pDCB->SyncMode & SYNC_ENABLE )
        !           120:            {
        !           121:                if( !(pDCB->IdentifyMsg & 7) ||
        !           122:                    (pSRB->CmdBlock[0] != INQUIRY) )
        !           123:                {
        !           124:                    bval1 = SEL_W_ATN_STOP;
        !           125:                    pSRB->SRBState = SRB_MSGOUT;
        !           126:                }
        !           127:            }
        !           128:        }
        !           129:        else
        !           130:        {
        !           131:            if(pDCB->SyncMode & EN_TAG_QUEUING)
        !           132:            {
        !           133:                outb(bval,ioport+ScsiFifo);
        !           134:                pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
        !           135:                wlval = 1;
        !           136:                bval = 0;
        !           137:                while( wlval & pDCB->TagMask )
        !           138:                {
        !           139:                    wlval = wlval << 1;
        !           140:                    bval++;
        !           141:                }
        !           142:                pDCB->TagMask |= wlval;
        !           143:                pSRB->TagNumber = bval;
        !           144:                pSRB->MsgOutBuf[1] = bval;
        !           145:                pSRB->MsgCnt = 2;
        !           146:                bval1 = SEL_W_ATN_STOP;
        !           147:                pSRB->SRBState = SRB_START_;
        !           148:            }
        !           149:            else
        !           150:            {
        !           151:                outb(bval,ioport+ScsiFifo);
        !           152:                pSRB->MsgOutBuf[0] = MSG_NOP;
        !           153:                pSRB->MsgCnt = 1;
        !           154:                pSRB->SRBState = SRB_START_;
        !           155:                bval1 = SEL_W_ATN_STOP;
        !           156:            }
        !           157:        }
        !           158:     }
        !           159:     bval = inb( ioport+Scsi_Status );
        !           160:     if( bval & INTERRUPT )
        !           161:     {
        !           162:        pSRB->SRBState = SRB_READY;
        !           163:        pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
        !           164:        rc = 1;
        !           165:     }
        !           166:     else
        !           167:     {
        !           168:        pSRB->ScsiPhase = SCSI_NOP1;
        !           169:        pACB->pActiveDCB = pDCB;
        !           170:        pDCB->pActiveSRB = pSRB;
        !           171:        rc = 0;
        !           172:        outb(bval1,ioport+ScsiCmd);
        !           173:     }
        !           174:     return( rc );
        !           175: }
        !           176: 
        !           177: 
        !           178: #ifndef  VERSION_ELF_1_2_13
        !           179: static void
        !           180: DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
        !           181: #else
        !           182: static void
        !           183: DC390_Interrupt( int irq, struct pt_regs *regs)
        !           184: #endif
        !           185: {
        !           186:     PACB   pACB;
        !           187:     PDCB   pDCB;
        !           188:     PSRB   pSRB;
        !           189:     USHORT ioport = 0;
        !           190:     USHORT phase, i;
        !           191:     void   (*stateV)( PACB, PSRB, PUCHAR );
        !           192:     UCHAR  istate = 0;
        !           193:     UCHAR  sstatus=0, istatus;
        !           194: 
        !           195:     pACB = pACB_start;
        !           196:     if( pACB == NULL )
        !           197:        return;
        !           198:     for( i=0; i < adapterCnt; i++ )
        !           199:     {
        !           200:        if( pACB->IRQLevel == (UCHAR) irq )
        !           201:        {
        !           202:             ioport = pACB->IOPortBase;
        !           203:             sstatus = inb( ioport+Scsi_Status );
        !           204:             if( sstatus & INTERRUPT )
        !           205:                 break;
        !           206:             else
        !           207:                pACB = pACB->pNextACB;
        !           208:        }
        !           209:        else
        !           210:        {
        !           211:            pACB = pACB->pNextACB;
        !           212:        }
        !           213:     }
        !           214: 
        !           215: #ifdef DC390_DEBUG1
        !           216:        printk("sstatus=%2x,",sstatus);
        !           217: #endif
        !           218: 
        !           219:     if( pACB == (PACB )-1 )
        !           220:     {
        !           221:        printk("DC390: Spurious interrupt detected!\n");
        !           222:        return;
        !           223:     }
        !           224: 
        !           225:     istate = inb( ioport+Intern_State );
        !           226:     istatus = inb( ioport+INT_Status );
        !           227: 
        !           228: #ifdef DC390_DEBUG1
        !           229:        printk("Istatus=%2x,",istatus);
        !           230: #endif
        !           231: 
        !           232:     if(istatus &  DISCONNECTED)
        !           233:     {
        !           234:        DC390_Disconnect( pACB );
        !           235:        return;
        !           236:     }
        !           237: 
        !           238:     if(istatus &  RESELECTED)
        !           239:     {
        !           240:        DC390_Reselect( pACB );
        !           241:        return;
        !           242:     }
        !           243: 
        !           244:     if(istatus &  INVALID_CMD)
        !           245:     {
        !           246:        DC390_InvalidCmd( pACB );
        !           247:        return;
        !           248:     }
        !           249: 
        !           250:     if(istatus &  SCSI_RESET)
        !           251:     {
        !           252:        DC390_ScsiRstDetect( pACB );
        !           253:        return;
        !           254:     }
        !           255: 
        !           256:     if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) )
        !           257:     {
        !           258:        pDCB = pACB->pActiveDCB;
        !           259:        pSRB = pDCB->pActiveSRB;
        !           260:        if( pDCB )
        !           261:        {
        !           262:            if( pDCB->DCBFlag & ABORT_DEV_ )
        !           263:                EnableMsgOut( pACB, pSRB );
        !           264:        }
        !           265: 
        !           266:        phase = (USHORT) pSRB->ScsiPhase;
        !           267:        stateV = (void *) DC390_phase0[phase];
        !           268:        stateV( pACB, pSRB, &sstatus );
        !           269: 
        !           270:        pSRB->ScsiPhase = sstatus & 7;
        !           271:        phase = (USHORT) sstatus & 7;
        !           272:        stateV = (void *) DC390_phase1[phase];
        !           273:        stateV( pACB, pSRB, &sstatus );
        !           274:     }
        !           275: }
        !           276: 
        !           277: 
        !           278: static void
        !           279: DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           280: {
        !           281:     UCHAR   sstatus, bval;
        !           282:     USHORT  ioport;
        !           283:     PSGL    psgl;
        !           284:     ULONG   ResidCnt, xferCnt;
        !           285: 
        !           286:     ioport = pACB->IOPortBase;
        !           287:     sstatus = *psstatus;
        !           288: 
        !           289:     if( !(pSRB->SRBState & SRB_XFERPAD) )
        !           290:     {
        !           291:        if( sstatus & PARITY_ERR )
        !           292:            pSRB->SRBStatus |= PARITY_ERROR;
        !           293: 
        !           294:        if( sstatus & COUNT_2_ZERO )
        !           295:        {
        !           296:            bval = inb(ioport+DMA_Status);
        !           297:            while( !(bval & DMA_XFER_DONE) )
        !           298:                bval = inb(ioport+DMA_Status);
        !           299:            pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
        !           300:            pSRB->SGIndex++;
        !           301:            if( pSRB->SGIndex < pSRB->SGcount )
        !           302:            {
        !           303:                pSRB->pSegmentList++;
        !           304:                psgl = pSRB->pSegmentList;
        !           305: 
        !           306: #ifndef VERSION_ELF_1_2_13
        !           307:                pSRB->SGPhysAddr = virt_to_phys( psgl->address );
        !           308: #else
        !           309:                pSRB->SGPhysAddr = (ULONG) psgl->address;
        !           310: #endif
        !           311:                pSRB->SGToBeXferLen = (ULONG) psgl->length;
        !           312:            }
        !           313:            else
        !           314:                pSRB->SGToBeXferLen = 0;
        !           315:        }
        !           316:        else
        !           317:        {
        !           318:            bval = inb( ioport+Current_Fifo );
        !           319:            bval &= 0x1f;
        !           320:            ResidCnt = (ULONG) inb(ioport+CtcReg_High);
        !           321:            ResidCnt = ResidCnt << 8;
        !           322:            ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
        !           323:            ResidCnt = ResidCnt << 8;
        !           324:            ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
        !           325:            ResidCnt += (ULONG) bval;
        !           326: 
        !           327:            xferCnt = pSRB->SGToBeXferLen - ResidCnt;
        !           328:            pSRB->SGPhysAddr += xferCnt;
        !           329:            pSRB->TotalXferredLen += xferCnt;
        !           330:            pSRB->SGToBeXferLen = ResidCnt;
        !           331:        }
        !           332:     }
        !           333:     bval = WRITE_DIRECTION+DMA_IDLE_CMD;
        !           334:     outb( bval, ioport+DMA_Cmd);
        !           335: }
        !           336: 
        !           337: static void
        !           338: DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           339: {
        !           340:     UCHAR   sstatus, bval;
        !           341:     USHORT  i, ioport, residual;
        !           342:     PSGL    psgl;
        !           343:     ULONG   ResidCnt, xferCnt;
        !           344:     PUCHAR  ptr;
        !           345: 
        !           346: 
        !           347:     ioport = pACB->IOPortBase;
        !           348:     sstatus = *psstatus;
        !           349: 
        !           350:     if( !(pSRB->SRBState & SRB_XFERPAD) )
        !           351:     {
        !           352:        if( sstatus & PARITY_ERR )
        !           353:            pSRB->SRBStatus |= PARITY_ERROR;
        !           354: 
        !           355:        if( sstatus & COUNT_2_ZERO )
        !           356:        {
        !           357:            bval = inb(ioport+DMA_Status);
        !           358:            while( !(bval & DMA_XFER_DONE) )
        !           359:                bval = inb(ioport+DMA_Status);
        !           360: 
        !           361:            bval = READ_DIRECTION+DMA_IDLE_CMD;
        !           362:            outb( bval, ioport+DMA_Cmd);
        !           363: 
        !           364:            pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
        !           365:            pSRB->SGIndex++;
        !           366:            if( pSRB->SGIndex < pSRB->SGcount )
        !           367:            {
        !           368:                pSRB->pSegmentList++;
        !           369:                psgl = pSRB->pSegmentList;
        !           370: 
        !           371: #ifndef VERSION_ELF_1_2_13
        !           372:                pSRB->SGPhysAddr = virt_to_phys( psgl->address );
        !           373: #else
        !           374:                pSRB->SGPhysAddr = (ULONG) psgl->address;
        !           375: #endif
        !           376:                pSRB->SGToBeXferLen = (ULONG) psgl->length;
        !           377:            }
        !           378:            else
        !           379:                pSRB->SGToBeXferLen = 0;
        !           380:        }
        !           381:        else    /* phase changed */
        !           382:        {
        !           383:            residual = 0;
        !           384:            bval = inb(ioport+Current_Fifo);
        !           385:            while( bval & 0x1f )
        !           386:            {
        !           387:                if( (bval & 0x1f) == 1 )
        !           388:                {
        !           389:                    for(i=0; i< 0x100; i++)
        !           390:                    {
        !           391:                        bval = inb(ioport+Current_Fifo);
        !           392:                        if( !(bval & 0x1f) )
        !           393:                            goto din_1;
        !           394:                        else if( i == 0x0ff )
        !           395:                        {
        !           396:                            residual = 1;   /* ;1 residual byte */
        !           397:                            goto din_1;
        !           398:                        }
        !           399:                    }
        !           400:                }
        !           401:                else
        !           402:                    bval = inb(ioport+Current_Fifo);
        !           403:            }
        !           404: din_1:
        !           405:            bval = READ_DIRECTION+DMA_BLAST_CMD;
        !           406:            outb(bval, ioport+DMA_Cmd);
        !           407:            for(i=0; i<0x8000; i++)
        !           408:            {
        !           409:                bval = inb(ioport+DMA_Status);
        !           410:                if(bval & BLAST_COMPLETE)
        !           411:                    break;
        !           412:            }
        !           413:            bval = READ_DIRECTION+DMA_IDLE_CMD;
        !           414:            outb(bval, ioport+DMA_Cmd);
        !           415: 
        !           416:            ResidCnt = (ULONG) inb(ioport+CtcReg_High);
        !           417:            ResidCnt = ResidCnt << 8;
        !           418:            ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
        !           419:            ResidCnt = ResidCnt << 8;
        !           420:            ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
        !           421: 
        !           422:            xferCnt = pSRB->SGToBeXferLen - ResidCnt;
        !           423:            pSRB->SGPhysAddr += xferCnt;
        !           424:            pSRB->TotalXferredLen += xferCnt;
        !           425:            pSRB->SGToBeXferLen = ResidCnt;
        !           426: 
        !           427:            if( residual )
        !           428:            {
        !           429:                bval = inb(ioport+ScsiFifo);        /* get residual byte */
        !           430: #ifndef VERSION_ELF_1_2_13
        !           431:                ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr );
        !           432: #else
        !           433:                ptr = (PUCHAR) pSRB->SGPhysAddr;
        !           434: #endif
        !           435:                *ptr = bval;
        !           436:                pSRB->SGPhysAddr++;
        !           437:                pSRB->TotalXferredLen++;
        !           438:                pSRB->SGToBeXferLen--;
        !           439:            }
        !           440:        }
        !           441:     }
        !           442: }
        !           443: 
        !           444: static void
        !           445: DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           446: {
        !           447: }
        !           448: 
        !           449: static void
        !           450: DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           451: {
        !           452:     UCHAR  bval;
        !           453:     USHORT ioport;
        !           454: 
        !           455:     ioport = pACB->IOPortBase;
        !           456:     bval = inb(ioport+ScsiFifo);
        !           457:     pSRB->TargetStatus = bval;
        !           458:     bval++;
        !           459:     bval = inb(ioport+ScsiFifo);       /* get message */
        !           460:     pSRB->EndMessage = bval;
        !           461: 
        !           462:     *psstatus = SCSI_NOP0;
        !           463:     pSRB->SRBState = SRB_COMPLETED;
        !           464:     bval = MSG_ACCEPTED_CMD;
        !           465:     outb(bval, ioport+ScsiCmd);
        !           466: }
        !           467: 
        !           468: static void
        !           469: DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           470: {
        !           471:     if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
        !           472:        *psstatus = SCSI_NOP0;
        !           473: }
        !           474: 
        !           475: static void
        !           476: DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           477: {
        !           478:     UCHAR  bval;
        !           479:     USHORT ioport, wval, wval1;
        !           480:     PDCB   pDCB;
        !           481:     PSRB   psrb;
        !           482: 
        !           483:     ioport = pACB->IOPortBase;
        !           484:     pDCB = pACB->pActiveDCB;
        !           485: 
        !           486:     bval = inb( ioport+ScsiFifo );
        !           487:     if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )
        !           488:     {
        !           489:        if(bval == MSG_DISCONNECT)
        !           490:        {
        !           491:            pSRB->SRBState = SRB_DISCONNECT;
        !           492:        }
        !           493:        else if( bval == MSG_SAVE_PTR )
        !           494:            goto  min6;
        !           495:        else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&
        !           496:                                            (bval <= MSG_ORDER_QTAG)) )
        !           497:        {
        !           498:            pSRB->SRBState |= SRB_MSGIN_MULTI;
        !           499:            pSRB->MsgInBuf[0] = bval;
        !           500:            pSRB->MsgCnt = 1;
        !           501:            pSRB->pMsgPtr = &pSRB->MsgInBuf[1];
        !           502:        }
        !           503:        else if(bval == MSG_REJECT_)
        !           504:        {
        !           505:            bval = RESET_ATN_CMD;
        !           506:            outb(bval, ioport+ScsiCmd);
        !           507:            if( pSRB->SRBState & DO_SYNC_NEGO)
        !           508:                goto  set_async;
        !           509:        }
        !           510:        else if( bval == MSG_RESTORE_PTR)
        !           511:            goto  min6;
        !           512:        else
        !           513:            goto  min6;
        !           514:     }
        !           515:     else
        !           516:     {  /* minx: */
        !           517: 
        !           518:        *pSRB->pMsgPtr = bval;
        !           519:        pSRB->MsgCnt++;
        !           520:        pSRB->pMsgPtr++;
        !           521:        if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) &&
        !           522:            (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) )
        !           523:        {
        !           524:            if( pSRB->MsgCnt == 2)
        !           525:            {
        !           526:                pSRB->SRBState = 0;
        !           527:                bval = pSRB->MsgInBuf[1];
        !           528:                pSRB = pDCB->pGoingSRB;
        !           529:                psrb = pDCB->pGoingLast;
        !           530:                if( pSRB )
        !           531:                {
        !           532:                    for( ;; )
        !           533:                    {
        !           534:                        if(pSRB->TagNumber != bval)
        !           535:                        {
        !           536:                            if( pSRB == psrb )
        !           537:                                goto  mingx0;
        !           538:                            pSRB = pSRB->pNextSRB;
        !           539:                        }
        !           540:                        else
        !           541:                            break;
        !           542:                    }
        !           543:                    if( pDCB->DCBFlag & ABORT_DEV_ )
        !           544:                    {
        !           545:                        pSRB->SRBState = SRB_ABORT_SENT;
        !           546:                        EnableMsgOut( pACB, pSRB );
        !           547:                    }
        !           548:                    if( !(pSRB->SRBState & SRB_DISCONNECT) )
        !           549:                        goto  mingx0;
        !           550:                    pDCB->pActiveSRB = pSRB;
        !           551:                    pSRB->SRBState = SRB_DATA_XFER;
        !           552:                }
        !           553:                else
        !           554:                {
        !           555: mingx0:
        !           556:                    pSRB = pACB->pTmpSRB;
        !           557:                    pSRB->SRBState = SRB_UNEXPECT_RESEL;
        !           558:                    pDCB->pActiveSRB = pSRB;
        !           559:                    pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
        !           560:                    EnableMsgOut2( pACB, pSRB );
        !           561:                }
        !           562:            }
        !           563:        }
        !           564:        else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) )
        !           565:        {
        !           566:            pSRB->SRBState &= ~(SRB_MSGIN_MULTI+DO_SYNC_NEGO);
        !           567:            if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != 1) )
        !           568:            {   /* reject_msg: */
        !           569:                pSRB->MsgCnt = 1;
        !           570:                pSRB->MsgInBuf[0] = MSG_REJECT_;
        !           571:                bval = SET_ATN_CMD;
        !           572:                outb(bval, ioport+ScsiCmd);
        !           573:            }
        !           574:            else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) )
        !           575:            {
        !           576: set_async:
        !           577:                pDCB = pSRB->pSRBDCB;
        !           578:                pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
        !           579:                pDCB->SyncPeriod = 0;
        !           580:                pDCB->SyncOffset = 0;
        !           581:                pDCB->CtrlR3 = FAST_CLK;     /* ;non_fast */
        !           582:                pDCB->CtrlR4 &= 0x3f;
        !           583:                pDCB->CtrlR4 |= EATER_25NS;  /* ; 25ns glitch eater */
        !           584:                goto  re_prog;
        !           585:            }
        !           586:            else
        !           587:            {   /* set_sync: */
        !           588: 
        !           589:                pDCB = pSRB->pSRBDCB;
        !           590:                pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
        !           591:                pDCB->SyncOffset &= 0x0f0;
        !           592:                pDCB->SyncOffset |= pSRB->MsgInBuf[4];
        !           593:                pDCB->NegoPeriod = pSRB->MsgInBuf[3];
        !           594:                wval = (USHORT) pSRB->MsgInBuf[3];
        !           595:                wval = wval << 2;
        !           596:                wval--;
        !           597:                wval1 = wval / 25;
        !           598:                if( (wval1 * 25) != wval)
        !           599:                    wval1++;
        !           600:                bval = FAST_CLK+FAST_SCSI;
        !           601:                pDCB->CtrlR4 &= 0x3f;
        !           602:                if(wval1 >= 8)
        !           603:                {
        !           604:                    wval1--;
        !           605:                    bval = FAST_CLK;        /* ;fast clock/normal scsi */
        !           606:                    pDCB->CtrlR4 |= EATER_25NS;   /* ;25 ns glitch eater */
        !           607:                }
        !           608:                pDCB->CtrlR3 = bval;
        !           609:                pDCB->SyncPeriod = (UCHAR)wval1;
        !           610: re_prog:
        !           611:                bval = pDCB->SyncPeriod;
        !           612:                outb(bval, ioport+Sync_Period);
        !           613:                bval = pDCB->SyncOffset;
        !           614:                outb(bval, ioport+Sync_Offset);
        !           615:                bval = pDCB->CtrlR3;
        !           616:                outb(bval, ioport+CtrlReg3);
        !           617:                bval = pDCB->CtrlR4;
        !           618:                outb(bval, ioport+CtrlReg4);
        !           619:                SetXferRate( pACB, pDCB);
        !           620:            }
        !           621:        }
        !           622:     }
        !           623: min6:
        !           624:     *psstatus = SCSI_NOP0;
        !           625:     bval = MSG_ACCEPTED_CMD;
        !           626:     outb(bval, ioport+ScsiCmd);
        !           627: }
        !           628: 
        !           629: static void
        !           630: DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
        !           631: {
        !           632:     PSGL   psgl;
        !           633:     UCHAR  bval;
        !           634:     USHORT ioport;
        !           635:     ULONG  lval;
        !           636: 
        !           637: 
        !           638:     ioport = pACB->IOPortBase;
        !           639:     if( pSRB->SGIndex < pSRB->SGcount )
        !           640:     {
        !           641:        bval = DMA_IDLE_CMD | ioDir;   /* ;+EN_DMA_INT */
        !           642:        outb( bval, ioport+DMA_Cmd);
        !           643:        if( !pSRB->SGToBeXferLen )
        !           644:        {
        !           645:            psgl = pSRB->pSegmentList;
        !           646: #ifndef VERSION_ELF_1_2_13
        !           647:            pSRB->SGPhysAddr = virt_to_phys( psgl->address );
        !           648: #else
        !           649:            pSRB->SGPhysAddr = (ULONG) psgl->address;
        !           650: #endif
        !           651:            pSRB->SGToBeXferLen = (ULONG) psgl->length;
        !           652:        }
        !           653:        lval = pSRB->SGToBeXferLen;
        !           654:        bval = (UCHAR) lval;
        !           655:        outb(bval,ioport+CtcReg_Low);
        !           656:        lval = lval >> 8;
        !           657:        bval = (UCHAR) lval;
        !           658:        outb(bval,ioport+CtcReg_Mid);
        !           659:        lval = lval >> 8;
        !           660:        bval = (UCHAR) lval;
        !           661:        outb(bval,ioport+CtcReg_High);
        !           662: 
        !           663:        lval = pSRB->SGToBeXferLen;
        !           664:        outl(lval, ioport+DMA_XferCnt);
        !           665: 
        !           666:        lval = pSRB->SGPhysAddr;
        !           667:        outl( lval, ioport+DMA_XferAddr);
        !           668: 
        !           669:        bval = DMA_COMMAND+INFO_XFER_CMD;
        !           670:        outb(bval, ioport+ScsiCmd);
        !           671: 
        !           672:        pSRB->SRBState = SRB_DATA_XFER;
        !           673: 
        !           674:        bval = DMA_IDLE_CMD | ioDir;    /* ;+EN_DMA_INT */
        !           675:        outb(bval, ioport+DMA_Cmd);
        !           676: 
        !           677:        bval = DMA_START_CMD | ioDir;   /* ;+EN_DMA_INT */
        !           678:        outb(bval, ioport+DMA_Cmd);
        !           679:     }
        !           680:     else    /* xfer pad */
        !           681:     {
        !           682:        if( pSRB->SGcount )
        !           683:        {
        !           684:            pSRB->AdaptStatus = H_OVER_UNDER_RUN;
        !           685:            pSRB->SRBStatus |= OVER_RUN;
        !           686:        }
        !           687:        bval = 0;
        !           688:        outb(bval,ioport+CtcReg_Low);
        !           689:        outb(bval,ioport+CtcReg_Mid);
        !           690:        outb(bval,ioport+CtcReg_High);
        !           691: 
        !           692:        pSRB->SRBState |= SRB_XFERPAD;
        !           693:        bval = DMA_COMMAND+XFER_PAD_BYTE;
        !           694:        outb(bval, ioport+ScsiCmd);
        !           695: /*
        !           696:        bval = DMA_IDLE_CMD | ioDir;    ;+EN_DMA_INT
        !           697:        outb(bval, ioport+DMA_Cmd);
        !           698:        bval = DMA_START_CMD | ioDir;   ;+EN_DMA_INT
        !           699:        outb(bval, ioport+DMA_Cmd);
        !           700: */
        !           701:     }
        !           702: }
        !           703: 
        !           704: 
        !           705: static void
        !           706: DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           707: {
        !           708:     UCHAR  ioDir;
        !           709: 
        !           710:     ioDir = WRITE_DIRECTION;
        !           711:     DataIO_Comm( pACB, pSRB, ioDir);
        !           712: }
        !           713: 
        !           714: static void
        !           715: DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           716: {
        !           717:     UCHAR  ioDir;
        !           718: 
        !           719:     ioDir = READ_DIRECTION;
        !           720:     DataIO_Comm( pACB, pSRB, ioDir);
        !           721: }
        !           722: 
        !           723: static void
        !           724: DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           725: {
        !           726:     PDCB   pDCB;
        !           727:     UCHAR  bval;
        !           728:     PUCHAR ptr;
        !           729:     USHORT ioport, i,  cnt;
        !           730: 
        !           731: 
        !           732:     ioport = pACB->IOPortBase;
        !           733:     bval = RESET_ATN_CMD;
        !           734:     outb(bval, ioport+ScsiCmd);
        !           735:     bval = CLEAR_FIFO_CMD;
        !           736:     outb(bval, ioport+ScsiCmd);
        !           737:     if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
        !           738:     {
        !           739:        cnt = (USHORT) pSRB->ScsiCmdLen;
        !           740:        ptr = (PUCHAR) pSRB->CmdBlock;
        !           741:        for(i=0; i < cnt; i++)
        !           742:        {
        !           743:            outb(*ptr, ioport+ScsiFifo);
        !           744:            ptr++;
        !           745:        }
        !           746:     }
        !           747:     else
        !           748:     {
        !           749:        bval = REQUEST_SENSE;
        !           750:        outb(bval, ioport+ScsiFifo);
        !           751:        pDCB = pACB->pActiveDCB;
        !           752:        bval = pDCB->IdentifyMsg << 5;
        !           753:        outb(bval, ioport+ScsiFifo);
        !           754:        bval = 0;
        !           755:        outb(bval, ioport+ScsiFifo);
        !           756:        outb(bval, ioport+ScsiFifo);
        !           757:        bval = sizeof(pSRB->pcmd->sense_buffer);
        !           758:        outb(bval, ioport+ScsiFifo);
        !           759:        bval = 0;
        !           760:        outb(bval, ioport+ScsiFifo);
        !           761:     }
        !           762:     pSRB->SRBState = SRB_COMMAND;
        !           763:     bval = INFO_XFER_CMD;
        !           764:     outb(bval, ioport+ScsiCmd);
        !           765: }
        !           766: 
        !           767: static void
        !           768: DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           769: {
        !           770:     UCHAR  bval;
        !           771:     USHORT ioport;
        !           772: 
        !           773:     ioport = pACB->IOPortBase;
        !           774:     bval = CLEAR_FIFO_CMD;
        !           775:     outb(bval, ioport+ScsiCmd);
        !           776:     pSRB->SRBState = SRB_STATUS;
        !           777:     bval = INITIATOR_CMD_CMPLTE;
        !           778:     outb(bval, ioport+ScsiCmd);
        !           779: }
        !           780: 
        !           781: static void
        !           782: DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           783: {
        !           784:     UCHAR   bval;
        !           785:     USHORT  ioport, i, cnt;
        !           786:     PUCHAR  ptr;
        !           787:     PDCB    pDCB;
        !           788: 
        !           789:     ioport = pACB->IOPortBase;
        !           790:     bval = CLEAR_FIFO_CMD;
        !           791:     outb(bval, ioport+ScsiCmd);
        !           792:     pDCB = pACB->pActiveDCB;
        !           793:     if( !(pSRB->SRBState & SRB_MSGOUT) )
        !           794:     {
        !           795:        cnt = pSRB->MsgCnt;
        !           796:        if( cnt )
        !           797:        {
        !           798:            ptr = (PUCHAR) pSRB->MsgOutBuf;
        !           799:            for(i=0; i < cnt; i++)
        !           800:            {
        !           801:                outb(*ptr, ioport+ScsiFifo);
        !           802:                ptr++;
        !           803:            }
        !           804:            pSRB->MsgCnt = 0;
        !           805:            if( (pDCB->DCBFlag & ABORT_DEV_) &&
        !           806:                (pSRB->MsgOutBuf[0] == MSG_ABORT) )
        !           807:                pSRB->SRBState = SRB_ABORT_SENT;
        !           808:        }
        !           809:        else
        !           810:        {
        !           811:            bval = MSG_ABORT;   /* ??? MSG_NOP */
        !           812:            if( (pSRB->CmdBlock[0] == INQUIRY ) ||
        !           813:                (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
        !           814:                (pSRB->SRBFlag & AUTO_REQSENSE) )
        !           815:            {
        !           816:                if( pDCB->SyncMode & SYNC_ENABLE )
        !           817:                    goto  mop1;
        !           818:            }
        !           819:            outb(bval, ioport+ScsiFifo);
        !           820:        }
        !           821:        bval = INFO_XFER_CMD;
        !           822:        outb( bval, ioport+ScsiCmd);
        !           823:     }
        !           824:     else
        !           825:     {
        !           826: mop1:
        !           827:        bval = MSG_EXTENDED;
        !           828:        outb(bval, ioport+ScsiFifo);
        !           829:        bval = 3;       /*    ;length of extended msg */
        !           830:        outb(bval, ioport+ScsiFifo);
        !           831:        bval = 1;       /*    ; sync nego */
        !           832:        outb(bval, ioport+ScsiFifo);
        !           833:        bval = pDCB->NegoPeriod;
        !           834:        outb(bval, ioport+ScsiFifo);
        !           835:        bval = SYNC_NEGO_OFFSET;
        !           836:        outb(bval, ioport+ScsiFifo);
        !           837:        pSRB->SRBState |= DO_SYNC_NEGO;
        !           838:        bval = INFO_XFER_CMD;
        !           839:        outb(bval, ioport+ScsiCmd);
        !           840:     }
        !           841: }
        !           842: 
        !           843: static void
        !           844: DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           845: {
        !           846:     UCHAR  bval;
        !           847:     USHORT ioport;
        !           848: 
        !           849:     ioport = pACB->IOPortBase;
        !           850:     bval = CLEAR_FIFO_CMD;
        !           851:     outb(bval, ioport+ScsiCmd);
        !           852:     if( !(pSRB->SRBState & SRB_MSGIN) )
        !           853:     {
        !           854:        pSRB->SRBState &= SRB_DISCONNECT;
        !           855:        pSRB->SRBState |= SRB_MSGIN;
        !           856:     }
        !           857:     bval = INFO_XFER_CMD;
        !           858:     outb(bval, ioport+ScsiCmd);
        !           859: }
        !           860: 
        !           861: static void
        !           862: DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           863: {
        !           864: }
        !           865: 
        !           866: static void
        !           867: DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus)
        !           868: {
        !           869: }
        !           870: 
        !           871: 
        !           872: static void
        !           873: SetXferRate( PACB pACB, PDCB pDCB )
        !           874: {
        !           875:     UCHAR  bval;
        !           876:     USHORT cnt, i;
        !           877:     PDCB   ptr;
        !           878: 
        !           879:     if( !(pDCB->IdentifyMsg & 0x07) )
        !           880:     {
        !           881:        if( pACB->scan_devices )
        !           882:        {
        !           883:            CurrSyncOffset = pDCB->SyncOffset;
        !           884:        }
        !           885:        else
        !           886:        {
        !           887:            ptr = pACB->pLinkDCB;
        !           888:            cnt = pACB->DeviceCnt;
        !           889:            bval = pDCB->UnitSCSIID;
        !           890:            for(i=0; i<cnt; i++)
        !           891:            {
        !           892:                if( ptr->UnitSCSIID == bval )
        !           893:                {
        !           894:                    ptr->SyncPeriod = pDCB->SyncPeriod;
        !           895:                    ptr->SyncOffset = pDCB->SyncOffset;
        !           896:                    ptr->CtrlR3 = pDCB->CtrlR3;
        !           897:                    ptr->CtrlR4 = pDCB->CtrlR4;
        !           898:                    ptr->SyncMode = pDCB->SyncMode;
        !           899:                }
        !           900:                ptr = ptr->pNextDCB;
        !           901:            }
        !           902:        }
        !           903:     }
        !           904:     return;
        !           905: }
        !           906: 
        !           907: 
        !           908: static void
        !           909: DC390_Disconnect( PACB pACB )
        !           910: {
        !           911:     PDCB   pDCB;
        !           912:     PSRB   pSRB, psrb;
        !           913:     ULONG  flags;
        !           914:     USHORT ioport, i, cnt;
        !           915:     UCHAR  bval;
        !           916: 
        !           917: #ifdef DC390_DEBUG0
        !           918:     printk("DISC,");
        !           919: #endif
        !           920: 
        !           921:     save_flags(flags);
        !           922:     cli();
        !           923:     ioport = pACB->IOPortBase;
        !           924:     pDCB = pACB->pActiveDCB;
        !           925:     if (!pDCB)
        !           926:      {
        !           927: #ifdef DC390_DEBUG0
        !           928:        printk("ACB:%08lx->ActiveDCB:%08lx !,",(ULONG)pACB,(ULONG)pDCB);
        !           929: #endif
        !           930:        restore_flags(flags); return;
        !           931:      }
        !           932:     pSRB = pDCB->pActiveSRB;
        !           933:     pACB->pActiveDCB = 0;
        !           934:     pSRB->ScsiPhase = SCSI_NOP0;
        !           935:     bval = EN_SEL_RESEL;
        !           936:     outb(bval, ioport+ScsiCmd);
        !           937:     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
        !           938:     {
        !           939:        pSRB->SRBState = 0;
        !           940:        DoWaitingSRB( pACB );
        !           941:     }
        !           942:     else if( pSRB->SRBState & SRB_ABORT_SENT )
        !           943:     {
        !           944:        pDCB->TagMask = 0;
        !           945:        pDCB->DCBFlag = 0;
        !           946:        cnt = pDCB->GoingSRBCnt;
        !           947:        pDCB->GoingSRBCnt = 0;
        !           948:        pSRB = pDCB->pGoingSRB;
        !           949:        for( i=0; i < cnt; i++)
        !           950:        {
        !           951:            psrb = pSRB->pNextSRB;
        !           952:            pSRB->pNextSRB = pACB->pFreeSRB;
        !           953:            pACB->pFreeSRB = pSRB;
        !           954:            pSRB = psrb;
        !           955:        }
        !           956:        pDCB->pGoingSRB = 0;
        !           957:        DoWaitingSRB( pACB );
        !           958:     }
        !           959:     else
        !           960:     {
        !           961:        if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
        !           962:           !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
        !           963:        {       /* Selection time out */
        !           964:            if( !(pACB->scan_devices) )
        !           965:            {
        !           966:                pSRB->SRBState = SRB_READY;
        !           967:                RewaitSRB( pDCB, pSRB);
        !           968:            }
        !           969:            else
        !           970:            {
        !           971:                pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
        !           972:                goto  disc1;
        !           973:            }
        !           974:        }
        !           975:        else if( pSRB->SRBState & SRB_DISCONNECT )
        !           976:        {
        !           977:            DoWaitingSRB( pACB );
        !           978:        }
        !           979:        else if( pSRB->SRBState & SRB_COMPLETED )
        !           980:        {
        !           981: disc1:
        !           982:            if(pDCB->MaxCommand > 1)
        !           983:            {
        !           984:               bval = pSRB->TagNumber;
        !           985:               pDCB->TagMask &= (~(1 << bval));   /* free tag mask */
        !           986:            }
        !           987:            pDCB->pActiveSRB = 0;
        !           988:            pSRB->SRBState = SRB_FREE;
        !           989:            SRBdone( pACB, pDCB, pSRB);
        !           990:        }
        !           991:     }
        !           992:     restore_flags(flags);
        !           993:     return;
        !           994: }
        !           995: 
        !           996: 
        !           997: static void
        !           998: DC390_Reselect( PACB pACB )
        !           999: {
        !          1000:     PDCB   pDCB, pdcb;
        !          1001:     PSRB   pSRB;
        !          1002:     USHORT ioport, wval;
        !          1003:     UCHAR  bval, bval1;
        !          1004: 
        !          1005: 
        !          1006: #ifdef DC390_DEBUG0
        !          1007:     printk("RSEL,");
        !          1008: #endif
        !          1009:     ioport = pACB->IOPortBase;
        !          1010:     pDCB = pACB->pActiveDCB;
        !          1011:     if( pDCB )
        !          1012:     {  /* Arbitration lost but Reselection win */
        !          1013:        pSRB = pDCB->pActiveSRB;
        !          1014:        if( !( pACB->scan_devices ) )
        !          1015:        {
        !          1016:            pSRB->SRBState = SRB_READY;
        !          1017:            RewaitSRB( pDCB, pSRB);
        !          1018:        }
        !          1019:     }
        !          1020:     bval = inb(ioport+ScsiFifo);       /* get ID */
        !          1021:     bval = bval ^ pACB->HostID_Bit;
        !          1022:     wval = 0;
        !          1023:     bval1 = 1;
        !          1024:     for(;;)
        !          1025:     {
        !          1026:        if( !(bval & bval1) )
        !          1027:        {
        !          1028:            bval1 = bval1 << 1;
        !          1029:            wval++;
        !          1030:        }
        !          1031:        else
        !          1032:            break;
        !          1033:     }
        !          1034:     wval |=  ( (USHORT) inb(ioport+ScsiFifo) & 7) << 8;  /* get LUN */
        !          1035:     pDCB = pACB->pLinkDCB;
        !          1036:     pdcb = pDCB;
        !          1037:     while( wval != *((PUSHORT) &pDCB->UnitSCSIID) )
        !          1038:     {
        !          1039:        pDCB = pDCB->pNextDCB;
        !          1040:        if( pDCB == pdcb )
        !          1041:            return;
        !          1042:     }
        !          1043:     pACB->pActiveDCB = pDCB;
        !          1044:     if( pDCB->SyncMode & EN_TAG_QUEUING )
        !          1045:     {
        !          1046:        pSRB = pACB->pTmpSRB;
        !          1047:        pDCB->pActiveSRB = pSRB;
        !          1048:     }
        !          1049:     else
        !          1050:     {
        !          1051:        pSRB = pDCB->pActiveSRB;
        !          1052:        if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
        !          1053:        {
        !          1054:            pSRB= pACB->pTmpSRB;
        !          1055:            pSRB->SRBState = SRB_UNEXPECT_RESEL;
        !          1056:            pDCB->pActiveSRB = pSRB;
        !          1057:            EnableMsgOut( pACB, pSRB );
        !          1058:        }
        !          1059:        else
        !          1060:        {
        !          1061:            if( pDCB->DCBFlag & ABORT_DEV_ )
        !          1062:            {
        !          1063:                pSRB->SRBState = SRB_ABORT_SENT;
        !          1064:                EnableMsgOut( pACB, pSRB );
        !          1065:            }
        !          1066:            else
        !          1067:                pSRB->SRBState = SRB_DATA_XFER;
        !          1068:        }
        !          1069:     }
        !          1070:     pSRB->ScsiPhase = SCSI_NOP0;
        !          1071:     bval = pDCB->UnitSCSIID;
        !          1072:     outb( bval, ioport+Scsi_Dest_ID);
        !          1073:     bval = pDCB->SyncPeriod;
        !          1074:     outb(bval, ioport+Sync_Period);
        !          1075:     bval = pDCB->SyncOffset;
        !          1076:     outb( bval, ioport+Sync_Offset);
        !          1077:     bval = pDCB->CtrlR1;
        !          1078:     outb(bval, ioport+CtrlReg1);
        !          1079:     bval = pDCB->CtrlR3;
        !          1080:     outb(bval, ioport+CtrlReg3);
        !          1081:     bval = pDCB->CtrlR4;       /* ; Glitch eater */
        !          1082:     outb(bval, ioport+CtrlReg4);
        !          1083:     bval = MSG_ACCEPTED_CMD;   /* ;to rls the /ACK signal */
        !          1084:     outb(bval, ioport+ScsiCmd);
        !          1085: }
        !          1086: 
        !          1087: 
        !          1088: static void
        !          1089: SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
        !          1090: {
        !          1091:     PSRB   psrb;
        !          1092:     UCHAR  bval, bval1, i, j, status;
        !          1093:     PSCSICMD pcmd;
        !          1094:     PSCSI_INQDATA  ptr;
        !          1095:     USHORT disable_tag;
        !          1096:     ULONG  flags;
        !          1097:     PSGL   ptr2;
        !          1098:     ULONG  swlval;
        !          1099: 
        !          1100:     pcmd = pSRB->pcmd;
        !          1101:     status = pSRB->TargetStatus;
        !          1102:     if(pSRB->SRBFlag & AUTO_REQSENSE)
        !          1103:     {
        !          1104:        pSRB->SRBFlag &= ~AUTO_REQSENSE;
        !          1105:        pSRB->AdaptStatus = 0;
        !          1106:        pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
        !          1107:        if(status == SCSI_STAT_CHECKCOND)
        !          1108:        {
        !          1109:            pcmd->result = DID_BAD_TARGET << 16;
        !          1110:            goto ckc_e;
        !          1111:        }
        !          1112:        if(pSRB->RetryCnt == 0)
        !          1113:        {
        !          1114:            *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
        !          1115:            pSRB->TotalXferredLen = pSRB->Segment1[1];
        !          1116:            if( (pSRB->TotalXferredLen) &&
        !          1117:                (pSRB->TotalXferredLen >= pcmd->underflow) )
        !          1118:                pcmd->result |= (DID_OK << 16);
        !          1119:            else
        !          1120:                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
        !          1121:                                SCSI_STAT_CHECKCOND;
        !          1122: #ifdef DC390_DEBUG0
        !          1123:        printk("Cmd=%2x,Result=%8x,XferL=%8x,",pSRB->CmdBlock[0],
        !          1124:                (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);
        !          1125: #endif
        !          1126:            goto ckc_e;
        !          1127:        }
        !          1128:        else
        !          1129:        {
        !          1130:            pSRB->RetryCnt--;
        !          1131:            pSRB->AdaptStatus = 0;
        !          1132:            pSRB->TargetStatus = 0;
        !          1133:            *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
        !          1134:            *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
        !          1135:            if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
        !          1136:            {
        !          1137:                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
        !          1138:                                SCSI_STAT_CHECKCOND;
        !          1139:                goto ckc_e;
        !          1140:            }
        !          1141:            pcmd->result |= (DRIVER_SENSE << 24);
        !          1142:            pSRB->SGcount                = (UCHAR) pSRB->Segment1[0];
        !          1143:            pSRB->ScsiCmdLen             = (UCHAR) (pSRB->Segment1[0] >> 8);
        !          1144:            pSRB->SGIndex = 0;
        !          1145:            pSRB->TotalXferredLen = 0;
        !          1146:            pSRB->SGToBeXferLen = 0;
        !          1147:            if( pcmd->use_sg )
        !          1148:                pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
        !          1149:            else if( pcmd->request_buffer )
        !          1150:            {
        !          1151:                pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
        !          1152:                pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
        !          1153:                pSRB->Segmentx.length = pcmd->request_bufflen;
        !          1154:            }
        !          1155:            if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
        !          1156:                RewaitSRB( pDCB, pSRB );
        !          1157:            return;
        !          1158:        }
        !          1159:     }
        !          1160:     if( status )
        !          1161:     {
        !          1162:        if( status == SCSI_STAT_CHECKCOND)
        !          1163:        {
        !          1164:            if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
        !          1165:            {
        !          1166:                bval = pSRB->SGcount;
        !          1167:                swlval = 0;
        !          1168:                ptr2 = pSRB->pSegmentList;
        !          1169:                for( i=pSRB->SGIndex; i < bval; i++)
        !          1170:                {
        !          1171:                    swlval += ptr2->length;
        !          1172:                    ptr2++;
        !          1173:                }
        !          1174: #ifdef DC390_DEBUG0
        !          1175:                printk("XferredLen=%8x,NotXferLen=%8x,",
        !          1176:                        (UINT) pSRB->TotalXferredLen, (UINT) swlval);
        !          1177: #endif
        !          1178:            }
        !          1179:            RequestSense( pACB, pDCB, pSRB );
        !          1180:            return;
        !          1181:        }
        !          1182:        else if( status == SCSI_STAT_QUEUEFULL )
        !          1183:        {
        !          1184:            bval = (UCHAR) pDCB->GoingSRBCnt;
        !          1185:            bval--;
        !          1186:            pDCB->MaxCommand = bval;
        !          1187:            RewaitSRB( pDCB, pSRB );
        !          1188:            pSRB->AdaptStatus = 0;
        !          1189:            pSRB->TargetStatus = 0;
        !          1190:            return;
        !          1191:        }
        !          1192:        else if(status == SCSI_STAT_SEL_TIMEOUT)
        !          1193:        {
        !          1194:            pSRB->AdaptStatus = H_SEL_TIMEOUT;
        !          1195:            pSRB->TargetStatus = 0;
        !          1196:            pcmd->result = DID_BAD_TARGET << 16;
        !          1197:        }
        !          1198:        else
        !          1199:        {
        !          1200:            pSRB->AdaptStatus = 0;
        !          1201:            if( pSRB->RetryCnt )
        !          1202:            {
        !          1203:                pSRB->RetryCnt--;
        !          1204:                pSRB->TargetStatus = 0;
        !          1205:                pSRB->SGIndex = 0;
        !          1206:                pSRB->TotalXferredLen = 0;
        !          1207:                pSRB->SGToBeXferLen = 0;
        !          1208:                if( pcmd->use_sg )
        !          1209:                    pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
        !          1210:                else if( pcmd->request_buffer )
        !          1211:                {
        !          1212:                    pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
        !          1213:                    pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
        !          1214:                    pSRB->Segmentx.length = pcmd->request_bufflen;
        !          1215:                }
        !          1216:                if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
        !          1217:                    RewaitSRB( pDCB, pSRB );
        !          1218:                return;
        !          1219:            }
        !          1220:            else
        !          1221:            {
        !          1222:                pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) |
        !          1223:                               (ULONG) status;
        !          1224:            }
        !          1225:        }
        !          1226:     }
        !          1227:     else
        !          1228:     {
        !          1229:        status = pSRB->AdaptStatus;
        !          1230:        if(status & H_OVER_UNDER_RUN)
        !          1231:        {
        !          1232:            pSRB->TargetStatus = 0;
        !          1233:            pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8);
        !          1234:        }
        !          1235:        else if( pSRB->SRBStatus & PARITY_ERROR)
        !          1236:        {
        !          1237:            pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8);
        !          1238:        }
        !          1239:        else                   /* No error */
        !          1240:        {
        !          1241:            pSRB->AdaptStatus = 0;
        !          1242:            pSRB->TargetStatus = 0;
        !          1243:            pcmd->result |= (DID_OK << 16);
        !          1244:        }
        !          1245:     }
        !          1246: 
        !          1247: ckc_e:
        !          1248:     if( pACB->scan_devices )
        !          1249:     {
        !          1250:        if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
        !          1251:        {
        !          1252:            if(pcmd->result != (DID_OK << 16))
        !          1253:            {
        !          1254:                if( pcmd->result & SCSI_STAT_CHECKCOND )
        !          1255:                {
        !          1256:                    goto RTN_OK;
        !          1257:                }
        !          1258:                else
        !          1259:                {
        !          1260:                    pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
        !          1261:                    pPrevDCB->pNextDCB = pACB->pLinkDCB;
        !          1262:                    if( (pcmd->target == pACB->max_id) &&
        !          1263:                       ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) )
        !          1264:                    {
        !          1265:                        pACB->scan_devices = 0;
        !          1266:                    }
        !          1267:                }
        !          1268:            }
        !          1269:            else
        !          1270:            {
        !          1271: RTN_OK:
        !          1272:                pPrevDCB->pNextDCB = pDCB;
        !          1273:                pDCB->pNextDCB = pACB->pLinkDCB;
        !          1274:                if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) )
        !          1275:                    pACB->scan_devices = END_SCAN;
        !          1276:            }
        !          1277:        }
        !          1278:        else if( pSRB->CmdBlock[0] == INQUIRY )
        !          1279:        {
        !          1280:            if( (pcmd->target == pACB->max_id) &&
        !          1281:                (pcmd->lun == pACB->max_lun) )
        !          1282:            {
        !          1283:                pACB->scan_devices = 0;
        !          1284:            }
        !          1285:            ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
        !          1286:            if( pcmd->use_sg )
        !          1287:                ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
        !          1288:            bval1 = ptr->DevType & SCSI_DEVTYPE;
        !          1289:            if(bval1 == SCSI_NODEV)
        !          1290:            {
        !          1291:                pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
        !          1292:                pPrevDCB->pNextDCB = pACB->pLinkDCB;
        !          1293:            }
        !          1294:            else
        !          1295:            {
        !          1296:                pACB->DeviceCnt++;
        !          1297:                pPrevDCB = pDCB;
        !          1298:                pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390_DCB ));
        !          1299:                pDCB->DevType = bval1;
        !          1300:                if(bval1 == TYPE_DISK || bval1 == TYPE_MOD)
        !          1301:                {
        !          1302:                    if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
        !          1303:                        (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
        !          1304:                        (pDCB->DevMode & TAG_QUEUING_) &&
        !          1305:                        (pDCB->DevMode & EN_DISCONNECT_) )
        !          1306:                    {
        !          1307:                        disable_tag = 0;
        !          1308:                        for(i=0; i<BADDEVCNT; i++)
        !          1309:                        {
        !          1310:                            for(j=0; j<28; j++)
        !          1311:                            {
        !          1312:                                if( ((PUCHAR)ptr)[8+j] != baddevname1[i][j])
        !          1313:                                    break;
        !          1314:                            }
        !          1315:                            if(j == 28)
        !          1316:                            {
        !          1317:                                disable_tag = 1;
        !          1318:                                break;
        !          1319:                            }
        !          1320:                        }
        !          1321: 
        !          1322:                        if( !disable_tag )
        !          1323:                        {
        !          1324:                            pDCB->MaxCommand = pACB->TagMaxNum;
        !          1325:                            pDCB->SyncMode |= EN_TAG_QUEUING;
        !          1326:                            pDCB->TagMask = 0;
        !          1327:                        }
        !          1328:                        else
        !          1329:                        {
        !          1330:                            pDCB->SyncMode |= EN_ATN_STOP;
        !          1331:                        }
        !          1332:                    }
        !          1333:                }
        !          1334:            }
        !          1335:        }
        !          1336:     }
        !          1337: 
        !          1338:     save_flags( flags );
        !          1339:     cli();
        !          1340: /*  ReleaseSRB( pDCB, pSRB ); */
        !          1341: 
        !          1342:     if(pSRB == pDCB->pGoingSRB )
        !          1343:     {
        !          1344:        pDCB->pGoingSRB = pSRB->pNextSRB;
        !          1345:     }
        !          1346:     else
        !          1347:     {
        !          1348:        psrb = pDCB->pGoingSRB;
        !          1349:        while( psrb->pNextSRB != pSRB )
        !          1350:            psrb = psrb->pNextSRB;
        !          1351:        psrb->pNextSRB = pSRB->pNextSRB;
        !          1352:        if( pSRB == pDCB->pGoingLast )
        !          1353:            pDCB->pGoingLast = psrb;
        !          1354:     }
        !          1355:     pSRB->pNextSRB = pACB->pFreeSRB;
        !          1356:     pACB->pFreeSRB = pSRB;
        !          1357:     pDCB->GoingSRBCnt--;
        !          1358: 
        !          1359:     DoWaitingSRB( pACB );
        !          1360:     restore_flags(flags);
        !          1361: 
        !          1362: /*  Notify cmd done */
        !          1363:     pcmd->scsi_done( pcmd );
        !          1364: 
        !          1365:     if( pDCB->QIORBCnt )
        !          1366:        DoNextCmd( pACB, pDCB );
        !          1367:     return;
        !          1368: }
        !          1369: 
        !          1370: 
        !          1371: static void
        !          1372: DoingSRB_Done( PACB pACB )
        !          1373: {
        !          1374:     PDCB  pDCB, pdcb;
        !          1375:     PSRB  psrb, psrb2;
        !          1376:     USHORT  cnt, i;
        !          1377:     PSCSICMD pcmd;
        !          1378: 
        !          1379:     pDCB = pACB->pLinkDCB;
        !          1380:     pdcb = pDCB;
        !          1381:     do
        !          1382:     {
        !          1383:        cnt = pdcb->GoingSRBCnt;
        !          1384:        psrb = pdcb->pGoingSRB;
        !          1385:        for( i=0; i<cnt; i++)
        !          1386:        {
        !          1387:            psrb2 = psrb->pNextSRB;
        !          1388:            pcmd = psrb->pcmd;
        !          1389:            pcmd->result = DID_RESET << 16;
        !          1390: 
        !          1391: /*         ReleaseSRB( pDCB, pSRB ); */
        !          1392: 
        !          1393:            psrb->pNextSRB = pACB->pFreeSRB;
        !          1394:            pACB->pFreeSRB = psrb;
        !          1395: 
        !          1396:            pcmd->scsi_done( pcmd );
        !          1397:            psrb  = psrb2;
        !          1398:        }
        !          1399:        pdcb->GoingSRBCnt = 0;;
        !          1400:        pdcb->pGoingSRB = NULL;
        !          1401:        pdcb->TagMask = 0;
        !          1402:        pdcb = pdcb->pNextDCB;
        !          1403:     }
        !          1404:     while( pdcb != pDCB );
        !          1405: }
        !          1406: 
        !          1407: 
        !          1408: static void
        !          1409: DC390_ResetSCSIBus( PACB pACB )
        !          1410: {
        !          1411:     USHORT ioport;
        !          1412:     UCHAR  bval;
        !          1413:     ULONG  flags;
        !          1414: 
        !          1415:     save_flags(flags);
        !          1416:     cli();
        !          1417:     pACB->ACBFlag |= RESET_DEV;
        !          1418:     ioport = pACB->IOPortBase;
        !          1419: 
        !          1420:     bval = DMA_IDLE_CMD;
        !          1421:     outb(bval,ioport+DMA_Cmd);
        !          1422: 
        !          1423:     bval = RST_SCSI_BUS_CMD;
        !          1424:     outb(bval,ioport+ScsiCmd);
        !          1425: 
        !          1426:     restore_flags(flags);
        !          1427:     return;
        !          1428: }
        !          1429: 
        !          1430: 
        !          1431: static void
        !          1432: DC390_ScsiRstDetect( PACB pACB )
        !          1433: {
        !          1434:     ULONG wlval, flags;
        !          1435:     USHORT ioport;
        !          1436:     UCHAR  bval;
        !          1437: 
        !          1438: #ifdef DC390_DEBUG0
        !          1439:     printk("RST_DETEC");
        !          1440: #endif
        !          1441:     save_flags(flags);
        !          1442:     sti();
        !          1443:     wlval = jiffies + HZ;
        !          1444:     while( jiffies < wlval );   /* delay 1 sec */
        !          1445: 
        !          1446:     cli();
        !          1447:     ioport = pACB->IOPortBase;
        !          1448:     bval = DMA_IDLE_CMD;
        !          1449:     outb(bval,ioport+DMA_Cmd);
        !          1450:     bval = CLEAR_FIFO_CMD;
        !          1451:     outb(bval,ioport+ScsiCmd);
        !          1452: 
        !          1453:     if( pACB->ACBFlag & RESET_DEV )
        !          1454:        pACB->ACBFlag |= RESET_DONE;
        !          1455:     else
        !          1456:     {
        !          1457:        pACB->ACBFlag |= RESET_DETECT;
        !          1458: 
        !          1459:        ResetDevParam( pACB );
        !          1460: /*     DoingSRB_Done( pACB ); ???? */
        !          1461:        RecoverSRB( pACB );
        !          1462:        pACB->pActiveDCB = NULL;
        !          1463:        pACB->ACBFlag = 0;
        !          1464:        DoWaitingSRB( pACB );
        !          1465:     }
        !          1466:     restore_flags(flags);
        !          1467:     return;
        !          1468: }
        !          1469: 
        !          1470: 
        !          1471: static void
        !          1472: RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
        !          1473: {
        !          1474:     PSCSICMD  pcmd;
        !          1475: 
        !          1476:     pSRB->SRBFlag |= AUTO_REQSENSE;
        !          1477:     pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0]));
        !          1478:     pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4]));
        !          1479:     pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount);
        !          1480:     pSRB->Segment1[1] = pSRB->TotalXferredLen;
        !          1481:     pSRB->AdaptStatus = 0;
        !          1482:     pSRB->TargetStatus = 0;
        !          1483: 
        !          1484:     pcmd = pSRB->pcmd;
        !          1485: 
        !          1486:     pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
        !          1487:     pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
        !          1488:     pSRB->pSegmentList = &pSRB->Segmentx;
        !          1489:     pSRB->SGcount = 1;
        !          1490:     pSRB->SGIndex = 0;
        !          1491: 
        !          1492:     *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
        !          1493:     pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
        !          1494:     *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer);
        !          1495:     pSRB->ScsiCmdLen = 6;
        !          1496: 
        !          1497:     pSRB->TotalXferredLen = 0;
        !          1498:     pSRB->SGToBeXferLen = 0;
        !          1499:     if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
        !          1500:        RewaitSRB( pDCB, pSRB );
        !          1501: }
        !          1502: 
        !          1503: 
        !          1504: static void
        !          1505: EnableMsgOut2( PACB pACB, PSRB pSRB )
        !          1506: {
        !          1507:     USHORT ioport;
        !          1508:     UCHAR  bval;
        !          1509: 
        !          1510:     ioport = pACB->IOPortBase;
        !          1511:     pSRB->MsgCnt = 1;
        !          1512:     bval = SET_ATN_CMD;
        !          1513:     outb(bval, ioport+ScsiCmd);
        !          1514: }
        !          1515: 
        !          1516: 
        !          1517: static void
        !          1518: EnableMsgOut( PACB pACB, PSRB pSRB )
        !          1519: {
        !          1520:     pSRB->MsgOutBuf[0] = MSG_ABORT;
        !          1521:     EnableMsgOut2( pACB, pSRB );
        !          1522: }
        !          1523: 
        !          1524: 
        !          1525: static void
        !          1526: DC390_InvalidCmd( PACB pACB )
        !          1527: {
        !          1528:    UCHAR bval;
        !          1529:    USHORT ioport;
        !          1530:    PSRB   pSRB;
        !          1531: 
        !          1532:     pSRB = pACB->pActiveDCB->pActiveSRB;
        !          1533:     if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
        !          1534:     {
        !          1535:        ioport = pACB->IOPortBase;
        !          1536:        bval = CLEAR_FIFO_CMD;
        !          1537:        outb(bval,(ioport+ScsiCmd));
        !          1538:     }
        !          1539: }
        !          1540: 

unix.superglobalmegacorp.com

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