📄 scsiiom.c
字号:
pSRB->SGToBeXferLen = (ULONG) psgl->length; DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");) } lval = pSRB->SGToBeXferLen; DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) DC390_write8 (CtcReg_Low, (UCHAR) lval); lval >>= 8; DC390_write8 (CtcReg_Mid, (UCHAR) lval); lval >>= 8; DC390_write8 (CtcReg_High, (UCHAR) lval); DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen); DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr); //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ pSRB->SRBState = SRB_DATA_XFER; DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);) //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));) //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);) } else /* xfer pad */ { if( pSRB->SGcount ) { pSRB->AdaptStatus = H_OVER_UNDER_RUN; pSRB->SRBStatus |= OVER_RUN; DEBUG0(printk (KERN_WARNING " DC390: Overrun -");) } DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");) DC390_write8 (CtcReg_Low, 0); DC390_write8 (CtcReg_Mid, 0); DC390_write8 (CtcReg_High, 0); pSRB->SRBState |= SRB_XFERPAD; DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);/* DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT; DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);*/ }}static voiddc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);}static voiddc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);}voiddc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ PDCB pDCB; UCHAR i, cnt; PUCHAR ptr; DC390_write8 (ScsiCmd, RESET_ATN_CMD); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) { cnt = (UCHAR) pSRB->pcmd->cmd_len; ptr = (PUCHAR) pSRB->pcmd->cmnd; for(i=0; i < cnt; i++) DC390_write8 (ScsiFifo, *(ptr++)); } else { UCHAR bval = 0; DC390_write8 (ScsiFifo, REQUEST_SENSE); pDCB = pACB->pActiveDCB; DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5); DC390_write8 (ScsiFifo, bval); DC390_write8 (ScsiFifo, bval); DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); DC390_write8 (ScsiFifo, bval); DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n");) } pSRB->SRBState = SRB_COMMAND; DC390_write8 (ScsiCmd, INFO_XFER_CMD);}static voiddc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pSRB->SRBState = SRB_STATUS; DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE); //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);}voiddc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ UCHAR bval, i, cnt; PUCHAR ptr; PDCB pDCB; DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pDCB = pACB->pActiveDCB; if( !(pSRB->SRBState & SRB_MSGOUT) ) { cnt = pSRB->MsgCnt; if( cnt ) { ptr = (PUCHAR) pSRB->MsgOutBuf; for(i=0; i < cnt; i++) DC390_write8 (ScsiFifo, *(ptr++)); pSRB->MsgCnt = 0; if( (pDCB->DCBFlag & ABORT_DEV_) && (pSRB->MsgOutBuf[0] == ABORT) ) pSRB->SRBState = SRB_ABORT_SENT; } else { bval = ABORT; /* ??? MSG_NOP */ if( (pSRB->pcmd->cmnd[0] == INQUIRY ) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) ) { if( pDCB->SyncMode & SYNC_ENABLE ) goto mop1; } DC390_write8 (ScsiFifo, bval); } DC390_write8 (ScsiCmd, INFO_XFER_CMD); } else {mop1: printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN); DC390_write8 (ScsiFifo, EXTENDED_MESSAGE); DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */ DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */ DC390_write8 (ScsiFifo, pDCB->NegoPeriod); if (pDCB->SyncOffset & 0x0f) DC390_write8 (ScsiFifo, pDCB->SyncOffset); else DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET); pSRB->SRBState |= DO_SYNC_NEGO; DC390_write8 (ScsiCmd, INFO_XFER_CMD); }}static voiddc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus){ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); if( !(pSRB->SRBState & SRB_MSGIN) ) { pSRB->SRBState &= ~SRB_DISCONNECT; pSRB->SRBState |= SRB_MSGIN; } DC390_write8 (ScsiCmd, INFO_XFER_CMD); //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);}static voiddc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){}static voiddc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus){}static voiddc390_SetXferRate( PACB pACB, PDCB pDCB ){ UCHAR bval, i, cnt; PDCB ptr; if( !(pDCB->TargetLUN) ) { if( !pACB->scan_devices ) { ptr = pACB->pLinkDCB; cnt = pACB->DCBCnt; bval = pDCB->TargetID; for(i=0; i<cnt; i++) { if( ptr->TargetID == bval ) { ptr->SyncPeriod = pDCB->SyncPeriod; ptr->SyncOffset = pDCB->SyncOffset; ptr->CtrlR3 = pDCB->CtrlR3; ptr->CtrlR4 = pDCB->CtrlR4; ptr->SyncMode = pDCB->SyncMode; } ptr = ptr->pNextDCB; } } } return;}voiddc390_Disconnect( PACB pACB ){ PDCB pDCB; PSRB pSRB, psrb; UCHAR i, cnt; DEBUG0(printk(KERN_INFO "DISC,");) if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n"); pACB->Connected = 0; pDCB = pACB->pActiveDCB; if (!pDCB) { int j = 400; DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\ pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel);) while (--j) udelay (1000); DC390_read8 (INT_Status); /* Reset Pending INT */ DC390_write8 (ScsiCmd, EN_SEL_RESEL); return; } DC390_write8 (ScsiCmd, EN_SEL_RESEL); pSRB = pDCB->pActiveSRB; pACB->pActiveDCB = 0; pSRB->ScsiPhase = SCSI_NOP0; if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) { pSRB->SRBState = 0; dc390_Waiting_process ( pACB ); } else if( pSRB->SRBState & SRB_ABORT_SENT ) { pDCB->TagMask = 0; pDCB->DCBFlag = 0; cnt = pDCB->GoingSRBCnt; pDCB->GoingSRBCnt = 0; pSRB = pDCB->pGoingSRB; for( i=0; i < cnt; i++) { psrb = pSRB->pNextSRB; dc390_Free_insert (pACB, pSRB); pSRB = psrb; } pDCB->pGoingSRB = 0; dc390_Query_to_Waiting (pACB); dc390_Waiting_process (pACB); } else { if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) { /* Selection time out */ if( !(1/*pACB->scan_devices*/) ) { pSRB->SRBState = SRB_READY; dc390_freetag (pDCB, pSRB); dc390_Going_to_Waiting (pDCB, pSRB); dc390_waiting_timer (pACB, HZ/5); } else { pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; goto disc1; } } else if( pSRB->SRBState & SRB_DISCONNECT ) { dc390_Waiting_process ( pACB ); } else if( pSRB->SRBState & SRB_COMPLETED ) {disc1: dc390_freetag (pDCB, pSRB); pDCB->pActiveSRB = 0; pSRB->SRBState = SRB_FREE; dc390_SRBdone( pACB, pDCB, pSRB); } } pACB->MsgLen = 0;}voiddc390_Reselect( PACB pACB ){ PDCB pDCB; PSRB pSRB; UCHAR id, lun; DEBUG0(printk(KERN_INFO "RSEL,");) pACB->Connected = 1; pDCB = pACB->pActiveDCB; if( pDCB ) { /* Arbitration lost but Reselection won */ DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n");) pSRB = pDCB->pActiveSRB; if( !( pACB->scan_devices ) ) { pSRB->SRBState = SRB_READY; dc390_freetag (pDCB, pSRB); dc390_Going_to_Waiting ( pDCB, pSRB); dc390_waiting_timer (pACB, HZ/5); } } /* Get ID */ lun = DC390_read8 (ScsiFifo); DEBUG0(printk ("Dev %02x,", lun);) if (!(lun & (1 << pACB->pScsiHost->this_id))) printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun); else lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ id = 0; while (lun >>= 1) id++; /* Get LUN */ lun = DC390_read8 (ScsiFifo); if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n"); lun &= 7; DEBUG0(printk ("(%02i-%i),", id, lun);) pDCB = dc390_findDCB (pACB, id, lun); if (!pDCB) { printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n", id, lun); return; } pACB->pActiveDCB = pDCB; /* TagQ: We expect a message soon, so never mind the exact SRB */ if( pDCB->SyncMode & EN_TAG_QUEUEING ) { pSRB = pACB->pTmpSRB; pDCB->pActiveSRB = pSRB; } else { pSRB = pDCB->pActiveSRB; if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) { pSRB= pACB->pTmpSRB; pSRB->SRBState = SRB_UNEXPECT_RESEL; printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n", id, lun); pDCB->pActiveSRB = pSRB; dc390_EnableMsgOut_Abort ( pACB, pSRB ); } else { if( pDCB->DCBFlag & ABORT_DEV_ ) { pSRB->SRBState = SRB_ABORT_SENT; printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n", id, lun); dc390_EnableMsgOut_Abort( pACB, pSRB ); } else pSRB->SRBState = SRB_DATA_XFER; } } DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);) pSRB->ScsiPhase = SCSI_NOP0; DC390_write8 (Scsi_Dest_ID, pDCB->TargetID); DC390_write8 (Sync_Period, pDCB->SyncPeriod); DC390_write8 (Sync_Offset, pDCB->SyncOffset); DC390_write8 (CtrlReg1, pDCB->CtrlR1); DC390_write8 (CtrlReg3, pDCB->CtrlR3); DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */ DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */}static void dc390_remove_dev (PACB pACB, PDCB pDCB){ PDCB pPrevDCB = pACB->pLinkDCB; if (pDCB->GoingSRBCnt > 1) { DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\ pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt);) return; }; pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN); // The first one if (pDCB == pACB->pLinkDCB) { // The last one if (pACB->pLastDCB == pDCB) { pDCB->pNextDCB = 0; pACB->pLastDCB = 0; } pACB->pLinkDCB = pDCB->pNextDCB; } else { while (pPrevDCB->pNextDCB != pDCB) pPrevDCB = pPrevDCB->pNextDCB; pPrevDCB->pNextDCB = pDCB->pNextDCB; if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB; } DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\ pDCB->TargetID, pDCB->TargetLUN, pDCB);) if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB; if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; kfree (pDCB); pACB->DCBCnt--; /* pACB->DeviceCnt--; */};static UCHAR __inline__dc390_tagq_blacklist (char* name){ UCHAR i; for(i=0; i<BADDEVCNT; i++) if (memcmp (name, dc390_baddevname1[i], 28) == 0) return 1; return 0;}; static void dc390_disc_tagq_set (PDCB pDCB, PSCSI_INQDATA ptr){ /* Check for SCSI format (ANSI and Response data format) */ if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 ) { if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) && (pDCB->DevMode & TAG_QUEUEING_) && /* ((pDCB->DevType == TYPE_DISK) || (pDCB->DevType == TYPE_MOD)) &&*/ !dc390_tagq_blacklist (((char*)ptr)+8) ) { if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum; pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */; //pDCB->TagMask = 0; } else pDCB->MaxCommand = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -