Annotation of Gnu-Mach/linux/src/drivers/scsi/scsiio.c, revision 1.1.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.