+ pSRB->SRBState = SRB_COMMAND;
+ DC390_write8 (ScsiCmd, INFO_XFER_CMD);
+}
+
+static void
+dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+{
+ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
+ pSRB->SRBState = SRB_STATUS;
+ DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
+ //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
+}
+
+static void
+dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+{
+ u8 bval, i, cnt;
+ u8 *ptr;
+ struct dc390_dcb* pDCB;
+
+ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
+ pDCB = pACB->pActiveDCB;
+ if( !(pSRB->SRBState & SRB_MSGOUT) )
+ {
+ cnt = pSRB->MsgCnt;
+ if( cnt )
+ {
+ ptr = (u8 *) 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 void
+dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *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 void
+dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+{
+}
+
+static void
+dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
+{
+}
+
+
+static void
+dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
+{
+ u8 bval, i, cnt;
+ struct dc390_dcb* 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;
+}
+
+
+static void
+dc390_Disconnect( struct dc390_acb* pACB )
+{
+ struct dc390_dcb *pDCB;
+ struct dc390_srb *pSRB, *psrb;
+ u8 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)
+ {
+ DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
+ pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
+ mdelay(400);
+ 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 = NULL;
+ pSRB->ScsiPhase = SCSI_NOP0;
+ if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
+ pSRB->SRBState = 0;
+ 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 = NULL;
+ }
+ else
+ {
+ if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
+ !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
+ { /* Selection time out */
+ pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
+ goto disc1;
+ }
+ else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
+ {
+disc1:
+ dc390_freetag (pDCB, pSRB);
+ pDCB->pActiveSRB = NULL;
+ pSRB->SRBState = SRB_FREE;
+ dc390_SRBdone( pACB, pDCB, pSRB);
+ }
+ }
+ pACB->MsgLen = 0;
+}
+
+
+static void
+dc390_Reselect( struct dc390_acb* pACB )
+{
+ struct dc390_dcb* pDCB;
+ struct dc390_srb* pSRB;
+ u8 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 ) )
+ {
+ struct scsi_cmnd *pcmd = pSRB->pcmd;
+ pcmd->resid = pcmd->request_bufflen;
+ SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
+ dc390_Going_remove(pDCB, pSRB);
+ dc390_Free_insert(pACB, pSRB);
+ pcmd->scsi_done (pcmd);
+ DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
+ }
+ }
+ /* 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 int __inline__
+dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
+{
+ struct scsi_cmnd *pcmd;
+
+ pcmd = pSRB->pcmd;
+
+ REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
+ pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
+
+ pSRB->SRBFlag |= AUTO_REQSENSE;
+ pSRB->SavedSGCount = pcmd->use_sg;
+ pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+ pSRB->AdaptStatus = 0;
+ pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+
+ /* We are called from SRBdone, original PCI mapping has been removed
+ * already, new one is set up from StartSCSI */
+ pSRB->SGIndex = 0;
+
+ pSRB->TotalXferredLen = 0;
+ pSRB->SGToBeXferLen = 0;
+ return dc390_StartSCSI(pACB, pDCB, pSRB);
+}