summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsiiom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsiiom.c')
-rw-r--r--drivers/scsi/scsiiom.c570
1 files changed, 337 insertions, 233 deletions
diff --git a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
index e09e7dc3b..14bf46435 100644
--- a/drivers/scsi/scsiiom.c
+++ b/drivers/scsi/scsiiom.c
@@ -4,7 +4,7 @@
* Description: Device Driver for Tekram DC-390 (T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
-/* $Id: scsiiom.c,v 2.3 1998/10/24 09:10:28 garloff Exp $ */
+/* $Id: scsiiom.c,v 1.5 1999/01/04 16:07:12 ralf Exp $ */
UCHAR
dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
@@ -36,7 +36,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
DC390_write8 (ScsiFifo, bval);
bval1 = SEL_W_ATN;
pSRB->SRBState = SRB_START_;
- DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
+ DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
if( pDCB->SyncMode & SYNC_ENABLE )
{
if( !(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */
@@ -53,21 +53,21 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
if(pDCB->SyncMode & EN_TAG_QUEUEING)
{
DC390_write8 (ScsiFifo, MSG_SIMPLE_QTAG);
- DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);)
bval = 0; wlval = 1;
while (wlval & pDCB->TagMask)
{ bval++; wlval <<= 1; };
pDCB->TagMask |= wlval;
DC390_write8 (ScsiFifo, bval);
pSRB->TagNumber = bval;
- DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
+ DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
bval1 = SEL_W_ATN3;
pSRB->SRBState = SRB_START_;
}
else /* No TagQ */
{
bval1 = SEL_W_ATN;
- DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
pSRB->SRBState = SRB_START_;
}
}
@@ -82,7 +82,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
bval &= 0xBF; /* No DisConn */
DC390_write8 (ScsiFifo, bval);
bval1 = SEL_W_ATN;
- DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
+ DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
pSRB->SRBState = SRB_START_;
/* ??? */
if( pDCB->SyncMode & SYNC_ENABLE )
@@ -101,13 +101,13 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
if(pDCB->SyncMode & EN_TAG_QUEUEING)
{
pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
- DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);)
bval = 0; wlval = 1;
while (wlval & pDCB->TagMask)
{ bval++; wlval <<= 1; };
pDCB->TagMask |= wlval;
pSRB->TagNumber = bval;
- DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
+ DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
pSRB->MsgOutBuf[1] = bval;
pSRB->MsgCnt = 2;
bval1 = SEL_W_ATN_STOP;
@@ -119,7 +119,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
pSRB->MsgCnt = 1;
pSRB->SRBState = SRB_START_;
bval1 = SEL_W_ATN_STOP;
- DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
};
}
}
@@ -134,7 +134,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
DC390_write8 (ScsiFifo, bval);
DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
DC390_write8 (ScsiFifo, bval);
- DEBUG1(printk ("DC390: AutoReqSense !\n");)
+ DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");)
}
else /* write cmnd to bus */
{
@@ -150,16 +150,16 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
{
pSRB->SRBState = SRB_READY;
pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
- DEBUG0(printk ("DC390: Interrupt during StartSCSI!\n");)
+ DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");)
return 1;
}
else
{
pSRB->ScsiPhase = SCSI_NOP1;
DEBUG0(if (pACB->pActiveDCB) \
- printk ("DC390: ActiveDCB != 0\n");)
+ printk (KERN_WARNING "DC390: ActiveDCB != 0\n");)
DEBUG0(if (pDCB->pActiveSRB) \
- printk ("DC390: ActiveSRB != 0\n");)
+ printk (KERN_WARNING "DC390: ActiveSRB != 0\n");)
pACB->pActiveDCB = pDCB;
pDCB->pActiveSRB = pSRB;
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
@@ -183,12 +183,10 @@ dc390_dma_intr (PACB pACB)
DEBUG0(PDEVSET1;)
DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);)
DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
- { printk("DC390: PCI state = %04x!\n", pstate); \
+ { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};)
- dstate = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, dstate); /* clear */
- //DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ dstate = DC390_read8 (DMA_Status);
if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
else pSRB = pACB->pActiveDCB->pActiveSRB;
@@ -207,12 +205,11 @@ dc390_dma_intr (PACB pACB)
{
DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");)
dstate = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, dstate); /* clear */
residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
DC390_read8 (CtcReg_High) << 16;
residual += DC390_read8 (Current_Fifo) & 0x1f;
} while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
- if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
/* residual = ... */
}
else
@@ -231,6 +228,7 @@ dc390_dma_intr (PACB pACB)
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
return dstate;
};
#endif
@@ -245,14 +243,16 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
UCHAR phase, i;
void (*stateV)( PACB, PSRB, PUCHAR );
UCHAR istate, istatus;
+#if DMA_INT
UCHAR dstatus;
+#endif
DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS
pACB = dc390_pACB_start;
if (pACB == 0)
{
- printk(KERN_ERR "DC390: Interrupt on uninitialized adapter!\n");
+ printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n");
return;
}
DC390_LOCK_DRV;
@@ -275,8 +275,8 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);)
- if( pACB == (PACB )-1) { DC390_UNLOCK_DRV; return; };
-
+ if( !pACB ) { DC390_UNLOCK_DRV; return; };
+
#if DMA_INT
DC390_LOCK_IO;
DC390_LOCK_ACB;
@@ -284,15 +284,17 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DC390_UNLOCK_ACB;
DC390_UNLOCK_IO;
- DEBUG1(printk ("dstatus=%02x,", dstatus);)
+ DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);)
if (! (dstatus & SCSI_INTERRUPT))
{
- DEBUG0(printk ("DC390 Int w/o SCSI actions (only DMA?)\n");)
+ DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");)
DC390_UNLOCK_DRV;
return;
};
#else
- dstatus = DC390_read8 (DMA_Status);
+ //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
+ //dstatus = DC390_read8 (DMA_Status);
+ //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
#endif
DC390_LOCK_IO;
@@ -302,14 +304,15 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
istate = DC390_read8 (Intern_State);
istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
- DEBUG1(printk ("Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
- dc390_laststatus = dstatus<<24 | sstatus<<16 | istate<<8 | istatus;
+ DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
+ dc390_laststatus &= ~0x00ffffff;
+ dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
if (sstatus & ILLEGAL_OP_ERR)
- {
- printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus);
- dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
- };
+ {
+ printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus);
+ dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
+ };
if(istatus & DISCONNECTED)
{
@@ -323,18 +326,6 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
goto unlock;
}
- if(istatus & INVALID_CMD)
- {
- dc390_InvalidCmd( pACB );
- goto unlock;
- }
-
- if(istatus & SCSI_RESET)
- {
- dc390_ScsiRstDetect( pACB );
- goto unlock;
- }
-
if( istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
{
pDCB = pACB->pActiveDCB;
@@ -345,7 +336,7 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
};
pSRB = pDCB->pActiveSRB;
if( pDCB->DCBFlag & ABORT_DEV_ )
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort (pACB, pSRB);
phase = pSRB->ScsiPhase;
DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);)
@@ -357,7 +348,21 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);)
stateV = (void *) dc390_phase1[phase];
( *stateV )( pACB, pSRB, &sstatus );
+ goto unlock;
}
+
+ if(istatus & INVALID_CMD)
+ {
+ dc390_InvalidCmd( pACB );
+ goto unlock;
+ }
+
+ if(istatus & SCSI_RESET)
+ {
+ dc390_ScsiRstDetect( pACB );
+ goto unlock;
+ }
+
unlock:
DC390_LOCK_DRV_NI;
DC390_UNLOCK_ACB;
@@ -380,6 +385,7 @@ dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
UCHAR sstatus;
PSGL psgl;
ULONG ResidCnt, xferCnt;
+ UCHAR dstate = 0;
sstatus = *psstatus;
@@ -391,10 +397,9 @@ dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
if( sstatus & COUNT_2_ZERO )
{
int ctr = 5000000; /* only try for about a tenth of a second */
- while( --ctr && !(DC390_read8 (DMA_Status) & DMA_XFER_DONE) && pSRB->SGToBeXferLen )
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
- if (!ctr) printk (KERN_CRIT "DC390: DataOut_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
+ if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
pSRB->SGIndex++;
if( pSRB->SGIndex < pSRB->SGcount )
@@ -443,15 +448,14 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
int ctr = 5000000; /* only try for about a tenth of a second */
int dstate = 0;
- while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen )
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
- if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
+ if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \
+ ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \
+ ((ULONG) DC390_read8 (CtcReg_Low));)
- DEBUG1(printk ("Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
@@ -474,7 +478,7 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
bval = DC390_read8 (Current_Fifo);
while( bval & 0x1f )
{
- DEBUG1(printk ("Check for residuals,");)
+ DEBUG1(printk (KERN_DEBUG "Check for residuals,");)
if( (bval & 0x1f) == 1 )
{
for(i=0; i < 0x100; i++)
@@ -494,17 +498,18 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
}
din_1:
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
- for (i=0; i<0x8000; i++)
+ for (i = 0xa000; i; i--)
{
bval = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, BLAST_COMPLETE | DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
if (bval & BLAST_COMPLETE)
break;
}
- if (i == 0x8000) printk (KERN_CRIT "DC390: DMA Blast aborted unfinished!!\n");
+ /* It seems a DMA Blast abort isn't that bad ... */
+ if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
- DEBUG1(printk ("Blast: Read %i times DMA_Status %02x", i, bval);)
+ DEBUG1(printk (KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000-i, bval);)
ResidCnt = (ULONG) DC390_read8 (CtcReg_High);
ResidCnt <<= 8;
ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid);
@@ -525,7 +530,7 @@ din_1:
pSRB->TotalXferredLen++;
pSRB->SGToBeXferLen--;
}
- DEBUG1(printk ("Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
+ DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
pSRB->TotalXferredLen, pSRB->SGToBeXferLen);)
}
@@ -558,164 +563,278 @@ dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
-void
-dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
+
+static void __inline__
+dc390_reprog (PACB pACB, PDCB pDCB)
{
- UCHAR bval;
- USHORT wval, wval1;
- PDCB pDCB;
- PSRB psrb;
+ DC390_write8 (Sync_Period, pDCB->SyncPeriod);
+ DC390_write8 (Sync_Offset, pDCB->SyncOffset);
+ DC390_write8 (CtrlReg3, pDCB->CtrlR3);
+ DC390_write8 (CtrlReg4, pDCB->CtrlR4);
+ dc390_SetXferRate (pACB, pDCB);
+};
- pDCB = pACB->pActiveDCB;
- bval = DC390_read8 (ScsiFifo);
- if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )
+#ifdef DC390_DEBUG0
+static void
+dc390_printMsg (UCHAR *MsgBuf, UCHAR len)
+{
+ int i;
+ printk (" %02x", MsgBuf[0]);
+ for (i = 1; i < len; i++)
+ printk (" %02x", MsgBuf[i]);
+ printk ("\n");
+};
+#endif
+
+#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
+
+/* reject_msg */
+static void __inline__
+dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
+{
+ pSRB->MsgOutBuf[0] = MSG_REJECT_;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)
+}
+
+/* abort command */
+static void __inline__
+dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
+{
+ pSRB->MsgOutBuf[0] = MSG_ABORT;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
+}
+
+static PSRB
+dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
+{
+ PSRB lastSRB = pDCB->pGoingLast;
+ PSRB pSRB = pDCB->pGoingSRB;
+
+ if (pSRB)
{
- if(bval == MSG_DISCONNECT)
- {
- pSRB->SRBState = SRB_DISCONNECT;
- }
- else if( bval == MSG_SAVE_PTR )
- goto min6;
- else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&
- (bval <= MSG_ORDER_QTAG)) )
+ for( ;pSRB ; )
{
- pSRB->SRBState |= SRB_MSGIN_MULTI;
- pSRB->MsgInBuf[0] = bval;
- pSRB->MsgCnt = 1;
- pSRB->pMsgPtr = &(pSRB->MsgInBuf[1]);
+ if (pSRB->TagNumber == tag) break;
+ if (pSRB == lastSRB) goto mingx0;
+ pSRB = pSRB->pNextSRB;
}
- else if(bval == MSG_REJECT_)
+
+ if( pDCB->DCBFlag & ABORT_DEV_ )
{
- DC390_write8 (ScsiCmd, RESET_ATN_CMD);
- pDCB->NegoPeriod = 50;
- if( pSRB->SRBState & DO_SYNC_NEGO)
- goto set_async;
+ pSRB->SRBState = SRB_ABORT_SENT;
+ dc390_EnableMsgOut_Abort( pACB, pSRB );
}
- else if( bval == MSG_RESTORE_PTR)
- goto min6;
- else
- goto min6;
+
+ if( !(pSRB->SRBState & SRB_DISCONNECT) )
+ goto mingx0;
+
+ pDCB->pActiveSRB = pSRB;
+ pSRB->SRBState = SRB_DATA_XFER;
}
- else
- { /* minx: */
+ else
+ {
+ mingx0:
+ pSRB = pACB->pTmpSRB;
+ pSRB->SRBState = SRB_UNEXPECT_RESEL;
+ pDCB->pActiveSRB = pSRB;
+ pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ }
+ return pSRB;
+}
- *pSRB->pMsgPtr = bval;
- pSRB->MsgCnt++;
- pSRB->pMsgPtr++;
- if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) &&
- (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) )
- {
- if( pSRB->MsgCnt == 2)
- {
- pSRB->SRBState = 0;
- bval = pSRB->MsgInBuf[1];
- pSRB = pDCB->pGoingSRB;
- psrb = pDCB->pGoingLast;
- if( pSRB )
- {
- for( ;pSRB ; )
- {
- if(pSRB->TagNumber != bval)
- {
- if( pSRB == psrb )
- goto mingx0;
- pSRB = pSRB->pNextSRB;
- }
- else
- break;
- }
- if( pDCB->DCBFlag & ABORT_DEV_ )
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- dc390_EnableMsgOut( pACB, pSRB );
- }
- if( !(pSRB->SRBState & SRB_DISCONNECT) )
- goto mingx0;
- pDCB->pActiveSRB = pSRB;
- pSRB->SRBState = SRB_DATA_XFER;
- }
- else
- {
-mingx0:
- pSRB = pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- pDCB->pActiveSRB = pSRB;
- pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
- dc390_EnableMsgOut2( pACB, pSRB );
- }
- }
+
+/* set async transfer mode */
+static void
+dc390_MsgIn_set_async (PACB pACB, PSRB pSRB)
+{
+ PDCB pDCB = pSRB->pSRBDCB;
+ if (!(pSRB->SRBState & DO_SYNC_NEGO))
+ printk ("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID);
+ pSRB->SRBState &= ~DO_SYNC_NEGO;
+ pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
+ pDCB->SyncPeriod = 0;
+ pDCB->SyncOffset = 0;
+ //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
+ pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
+ pDCB->CtrlR4 &= 0x3f;
+ pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
+ dc390_reprog (pACB, pDCB);
+}
+
+/* set sync transfer mode */
+static void
+dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB)
+{
+ UCHAR bval;
+ USHORT wval, wval1;
+ PDCB pDCB = pSRB->pSRBDCB;
+ UCHAR oldsyncperiod = pDCB->SyncPeriod;
+ UCHAR oldsyncoffset = pDCB->SyncOffset;
+
+ if (!(pSRB->SRBState & DO_SYNC_NEGO))
+ {
+ printk ("DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
+ pDCB->UnitSCSIID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
+
+ /* reject */
+ //dc390_MsgIn_reject (pACB, pSRB);
+ //return dc390_MsgIn_set_async (pACB, pSRB);
+
+ /* Reply with corrected SDTR Message */
+ if (pSRB->MsgInBuf[4] > 15)
+ {
+ printk ("DC390: Lower Sync Offset to 15\n");
+ pSRB->MsgInBuf[4] = 15;
}
- else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) )
- { /* Note: This will fail for target initiated SDTR ? */
- pSRB->SRBState &= ~(SRB_MSGIN_MULTI);
- if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != EXTENDED_SDTR) )
- { /* reject_msg: */
- pSRB->MsgCnt = 1;
- pSRB->MsgInBuf[0] = MSG_REJECT_;
- DC390_write8 (ScsiCmd, SET_ATN_CMD);
- }
- else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) )
- {
-set_async:
- pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk ("DC390: Target (%i,%i) initiates Non-Sync?\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
- pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
- pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 &= 0x3f;
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- goto re_prog;
- }
+ if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
+ {
+ printk ("DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
+ pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
+ };
+ memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
+ pSRB->MsgCnt = 5;
+ DC390_ENABLE_MSGOUT;
+ };
+
+ pSRB->SRBState &= ~DO_SYNC_NEGO;
+ pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
+ pDCB->SyncOffset &= 0x0f0;
+ pDCB->SyncOffset |= pSRB->MsgInBuf[4];
+ pDCB->NegoPeriod = pSRB->MsgInBuf[3];
+
+ wval = (USHORT) pSRB->MsgInBuf[3];
+ wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
+ if( (wval1 * 25) != wval) wval1++;
+ bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
+
+ pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
+ if (pACB->glitch_cfg != NS_TO_GLITCH(0))
+ pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
+ else
+ pDCB->CtrlR4 |= NS_TO_GLITCH(0);
+ if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
+
+ if (wval1 >= 8)
+ {
+ wval1--; /* Timing computation differs by 1 from FAST_SCSI */
+ bval = FAST_CLK; /* fast clock / normal scsi */
+ pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
+ }
+
+ pDCB->CtrlR3 = bval;
+ pDCB->SyncPeriod = (UCHAR)wval1;
+
+ if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->UnitSCSILUN == 0)
+ {
+ if (! (bval & FAST_SCSI)) wval1++;
+ printk ("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID,
+ 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
+ }
+
+ dc390_reprog (pACB, pDCB);
+};
+
+
+/* According to the docs, the AM53C974 reads the message and
+ * generates a Succesful Operation IRQ before asserting ACK for
+ * the last byte (how does it know whether it's the last ?) */
+/* The old code handled it in another way, indicating, that on
+ * every message byte an IRQ is generated and every byte has to
+ * be manually ACKed. Hmmm ? (KG, 98/11/28) */
+/* The old implementation was correct. Sigh! */
+
+/* Check if the message is complete */
+static UCHAR __inline__
+dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len)
+{
+ if (*msgbuf == MSG_EXTENDED)
+ {
+ if (len < 2) return 0;
+ if (len < msgbuf[1] + 2) return 0;
+ }
+ else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
+ if (len < 2) return 0;
+ return 1;
+}
+
+
+
+/* read and eval received messages */
+void
+dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
+{
+ PDCB pDCB = pACB->pActiveDCB;
+
+ /* Read the msg */
+
+ pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
+ //pSRB->SRBState = 0;
+
+ /* Msg complete ? */
+ if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
+ {
+ DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);)
+ /* Now eval the msg */
+ switch (pSRB->MsgInBuf[0])
+ {
+ case MSG_DISCONNECT:
+ pSRB->SRBState = SRB_DISCONNECT; break;
+
+ case MSG_SIMPLE_QTAG:
+ case MSG_HEAD_QTAG:
+ case MSG_ORDER_QTAG:
+ pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
+ break;
+
+ case MSG_REJECT_:
+ DC390_write8 (ScsiCmd, RESET_ATN_CMD);
+ pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
+ if( pSRB->SRBState & DO_SYNC_NEGO)
+ dc390_MsgIn_set_async (pACB, pSRB);
+ break;
+
+ case MSG_EXTENDED:
+ /* reject every extended msg but SDTR */
+ if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
+ dc390_MsgIn_reject (pACB, pSRB);
else
- { /* set_sync: */
-
- pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk ("DC390: Target (%i,%i) initiates Sync: %ins %i ?\n",
- pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
- pDCB->SyncOffset &= 0x0f0;
- pDCB->SyncOffset |= pSRB->MsgInBuf[4];
- pDCB->NegoPeriod = pSRB->MsgInBuf[3];
- wval = (USHORT) pSRB->MsgInBuf[3];
- wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
- if( (wval1 * 25) != wval)
- wval1++;
- bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
- pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
- if (pACB->glitch_cfg != NS_TO_GLITCH(0))
- pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
+ {
+ if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
+ dc390_MsgIn_set_async (pACB, pSRB);
else
- pDCB->CtrlR4 |= NS_TO_GLITCH(0);
- if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
- if (wval1 >= 8)
- {
- wval1--; /* Timing computation differs by 1 from FAST_SCSI */
- bval = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- }
- pDCB->CtrlR3 = bval;
- pDCB->SyncPeriod = (UCHAR)wval1;
-re_prog:
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4);
- dc390_SetXferRate (pACB, pDCB);
- }
- }
- }
-min6:
+ dc390_MsgIn_set_sync (pACB, pSRB);
+ };
+
+ // nothing has to be done
+ case MSG_COMPLETE: break;
+
+ // SAVE POINTER my be ignored as we have the PSRB associated with the
+ // scsi command. Thanks, Gerard, for pointing it out.
+ case MSG_SAVE_PTR: break;
+ // The device might want to restart transfer with a RESTORE
+ case MSG_RESTORE_PTR:
+ printk ("DC390: RESTORE POINTER message received ... reject\n");
+ // fall through
+
+ // reject unknown messages
+ default: dc390_MsgIn_reject (pACB, pSRB);
+ }
+
+ /* Clear counter and MsgIn state */
+ pSRB->SRBState &= ~SRB_MSGIN;
+ pACB->MsgLen = 0;
+ };
+
*psstatus = SCSI_NOP0;
DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
+
void
dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
{
@@ -730,10 +849,10 @@ dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = virt_to_bus( psgl->address );
pSRB->SGToBeXferLen = (ULONG) psgl->length;
- DEBUG1(printk (" DC390: Next SG segment.");)
+ DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
}
lval = pSRB->SGToBeXferLen;
- DEBUG1(printk (" DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
+ DEBUG1(printk (KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
DC390_write8 (CtcReg_Low, (UCHAR) lval);
lval >>= 8;
DC390_write8 (CtcReg_Mid, (UCHAR) lval);
@@ -749,21 +868,22 @@ dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
- //DEBUG1(printk ("DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
+ //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 */
{
- UCHAR bval = 0;
if( pSRB->SGcount )
{
pSRB->AdaptStatus = H_OVER_UNDER_RUN;
pSRB->SRBStatus |= OVER_RUN;
- DEBUG0(printk (" DC390: Overrun -");)
+ DEBUG0(printk (KERN_WARNING " DC390: Overrun -");)
}
- DEBUG0(printk (" Clear transfer pad \n");)
- DC390_write8 (CtcReg_Low, bval);
- DC390_write8 (CtcReg_Mid, bval);
- DC390_write8 (CtcReg_High, bval);
+ 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);
@@ -1017,7 +1137,7 @@ disc1:
dc390_SRBdone( pACB, pDCB, pSRB);
}
}
- return;
+ pACB->MsgLen = 0;
}
@@ -1032,7 +1152,7 @@ dc390_Reselect( PACB pACB )
DEBUG0(printk(KERN_INFO "RSEL,");)
pDCB = pACB->pActiveDCB;
if( pDCB )
- { /* Arbitration lost but Reselection win */
+ { /* Arbitration lost but Reselection won */
DEBUG0(printk ("(ActiveDCB != 0)");)
pSRB = pDCB->pActiveSRB;
if( !( pACB->scan_devices ) )
@@ -1075,23 +1195,23 @@ dc390_Reselect( PACB pACB )
printk (KERN_ERR "DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n",
wval & 0xff, (wval & 0xff00) >> 8);
pDCB->pActiveSRB = pSRB;
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort ( pACB, pSRB );
}
else
{
if( pDCB->DCBFlag & ABORT_DEV_ )
{
pSRB->SRBState = SRB_ABORT_SENT;
- printk (KERN_NOTICE "DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
+ printk (KERN_INFO "DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
wval & 0xff, (wval & 0xff00) >> 8);
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort( pACB, pSRB );
}
else
pSRB->SRBState = SRB_DATA_XFER;
}
}
- DEBUG1(printk ("Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
+ DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
pSRB->ScsiPhase = SCSI_NOP0;
DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID);
DC390_write8 (Sync_Period, pDCB->SyncPeriod);
@@ -1244,7 +1364,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
else
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
SCSI_STAT_CHECKCOND;
- REMOVABLEDEBUG(printk("Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\
+ REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\
(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
goto ckc_e;
}
@@ -1260,7 +1380,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
{
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16)
| SCSI_STAT_CHECKCOND;
- REMOVABLEDEBUG(printk("Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\
+ REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\
(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
goto ckc_e;
}
@@ -1299,7 +1419,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
swlval += ptr2->length;
ptr2++;
}
- REMOVABLEDEBUG(printk("XferredLen=%08x,NotXferLen=%08x\n",\
+ REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
(UINT) pSRB->TotalXferredLen, (UINT) swlval);)
}
dc390_RequestSense( pACB, pDCB, pSRB );
@@ -1587,22 +1707,6 @@ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
}
-static void __inline__
-dc390_EnableMsgOut2( PACB pACB, PSRB pSRB )
-{
- pSRB->MsgCnt = 1;
- DC390_write8 (ScsiCmd, SET_ATN_CMD);
-}
-
-
-static void __inline__
-dc390_EnableMsgOut( PACB pACB, PSRB pSRB )
-{
- pSRB->MsgOutBuf[0] = MSG_ABORT;
- dc390_EnableMsgOut2( pACB, pSRB );
- pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
static void __inline__
dc390_InvalidCmd( PACB pACB )