1 /***********************************************************************
2  *	FILE NAME : SCSIIOM.C					       *
3  *	     BY   : C.L. Huang,    ching@tekram.com.tw		       *
4  *	Description: Device Driver for Tekram DC-390 (T) PCI SCSI      *
5  *		     Bus Master Host Adapter			       *
6  ***********************************************************************/
7 /* $Id: scsiiom.c,v 2.55.2.17 2000/12/20 00:39:37 garloff Exp $ */
8 
9 static void __inline__
dc390_freetag(PDCB pDCB,PSRB pSRB)10 dc390_freetag (PDCB pDCB, PSRB pSRB)
11 {
12 	if (pSRB->TagNumber < 255) {
13 		pDCB->TagMask &= ~(1 << pSRB->TagNumber);   /* free tag mask */
14 		pSRB->TagNumber = 255;
15 	}
16 };
17 
18 
19 UCHAR
dc390_StartSCSI(PACB pACB,PDCB pDCB,PSRB pSRB)20 dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
21 {
22     UCHAR cmd; UCHAR  disc_allowed, try_sync_nego;
23 
24     pSRB->ScsiPhase = SCSI_NOP0;
25 
26     if (pACB->Connected)
27     {
28 	// Should not happen normally
29 	printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n",
30 		pSRB->SRBState, pSRB->SRBFlag);
31 	pSRB->SRBState = SRB_READY;
32 	pACB->SelConn++;
33 	return 1;
34     }
35     if (time_before (jiffies, pACB->pScsiHost->last_reset))
36     {
37 	DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n");)
38 	return 1;
39     }
40     DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
41     DC390_write8 (Sync_Period, pDCB->SyncPeriod);
42     DC390_write8 (Sync_Offset, pDCB->SyncOffset);
43     DC390_write8 (CtrlReg1, pDCB->CtrlR1);
44     DC390_write8 (CtrlReg3, pDCB->CtrlR3);
45     DC390_write8 (CtrlReg4, pDCB->CtrlR4);
46     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);		/* Flush FIFO */
47     DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
48 	    pSRB->pcmd->cmnd[0], pDCB->SyncMode);)
49     disc_allowed = pDCB->DevMode & EN_DISCONNECT_; try_sync_nego = 0;
50     /* Don't disconnect on AUTO_REQSENSE, cause it might be an
51      * Contingent Allegiance Condition (6.6), where no tags should be used.
52      * All other have to be allowed to disconnect to prevent Incorrect
53      * Initiator Connection (6.8.2/6.5.2) */
54     /* Changed KG, 99/06/06 */
55     if( /*(((pSRB->pcmd->cmnd[0] == INQUIRY) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
56 	 * (pSRB->pcmd->cmnd[0] == TEST_UNIT_READY)) && pACB->scan_devices)
57 		||*/ (pSRB->SRBFlag & AUTO_REQSENSE) )
58       disc_allowed = 0;
59     if ( (pDCB->SyncMode & SYNC_ENABLE) && (pDCB->TargetLUN == 0) && (pDCB->Inquiry7 & 0x10) &&
60 	( ( ( (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) )
61 	  && !(pDCB->SyncMode & SYNC_NEGO_DONE) ) || (pSRB->pcmd->cmnd[0] == INQUIRY) ) )
62       try_sync_nego = 1;
63 
64     pSRB->MsgCnt = 0; cmd = SEL_W_ATN;
65     DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
66     /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
67     if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed)
68       {
69 	UCHAR tag_no = 0;
70 	while ((1 << tag_no) & pDCB->TagMask) tag_no++;
71 	if (tag_no >= sizeof (pDCB->TagMask)*8 || tag_no >= pDCB->MaxCommand) {
72 		printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->TargetID, pDCB->TargetLUN);
73 		return 1;
74 		//goto no_tag;
75 	};
76 	DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG);
77 	pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no;
78 	DC390_write8 (ScsiFifo, tag_no);
79 	DEBUG1(printk (KERN_DEBUG "DC390: Select w/DisCn for Cmd %li (SRB %p), Using Tag %02x\n", pSRB->pcmd->pid, pSRB, tag_no);)
80 	cmd = SEL_W_ATN3;
81       }
82     else	/* No TagQ */
83       {
84 //      no_tag:
85 	DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB);)
86       };
87 
88     pSRB->SRBState = SRB_START_;
89 
90     if (try_sync_nego)
91       {
92 	UCHAR Sync_Off = pDCB->SyncOffset;
93         DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);)
94 	pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
95 	pSRB->MsgOutBuf[1] = 3;
96 	pSRB->MsgOutBuf[2] = EXTENDED_SDTR;
97 	pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
98 	if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET;
99 	pSRB->MsgOutBuf[4] = Sync_Off;
100 	pSRB->MsgCnt = 5;
101 	//pSRB->SRBState = SRB_MSGOUT_;
102 	pSRB->SRBState |= DO_SYNC_NEGO;
103 	cmd = SEL_W_ATN_STOP;
104       };
105 
106     /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
107     if (cmd != SEL_W_ATN_STOP)
108       {
109 	if( pSRB->SRBFlag & AUTO_REQSENSE )
110 	  {
111 	    DC390_write8 (ScsiFifo, REQUEST_SENSE);
112 	    DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
113 	    DC390_write8 (ScsiFifo, 0);
114 	    DC390_write8 (ScsiFifo, 0);
115 	    DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
116 	    DC390_write8 (ScsiFifo, 0);
117 	    DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");)
118 	  }
119 	else	/* write cmnd to bus */
120 	  {
121 	    PUCHAR ptr; UCHAR i;
122 	    ptr = (PUCHAR) pSRB->pcmd->cmnd;
123 	    for (i=0; i<pSRB->pcmd->cmd_len; i++)
124 	      DC390_write8 (ScsiFifo, *(ptr++));
125 	  };
126       }
127     DEBUG0(if (pACB->pActiveDCB)	\
128 	   printk (KERN_WARNING "DC390: ActiveDCB != 0\n");)
129     DEBUG0(if (pDCB->pActiveSRB)	\
130 	   printk (KERN_WARNING "DC390: ActiveSRB != 0\n");)
131     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
132     if (DC390_read8 (Scsi_Status) & INTERRUPT)
133     {
134 	dc390_freetag (pDCB, pSRB);
135 	DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n",
136 		pSRB->pcmd->pid, pSRB->pcmd->target, pSRB->pcmd->lun);)
137 	pSRB->SRBState = SRB_READY;
138 	//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
139 	pACB->SelLost++;
140 	return 1;
141     };
142     DC390_write8 (ScsiCmd, cmd);
143     pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB;
144     pACB->Connected = 1;
145     pSRB->ScsiPhase = SCSI_NOP1;
146     return 0;
147 }
148 
149 //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
150 #define DMA_INT 0
151 
152 #if DMA_INT
153 /* This is similar to AM53C974.c ... */
154 static UCHAR
dc390_dma_intr(PACB pACB)155 dc390_dma_intr (PACB pACB)
156 {
157   PSRB pSRB;
158   UCHAR dstate;
159   DEBUG0(USHORT pstate;PDEVDECL1;)
160 
161   DEBUG0(PDEVSET1;)
162   DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);)
163   DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
164 	{ printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
165 	  PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};)
166 
167   dstate = DC390_read8 (DMA_Status);
168 
169   if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
170   else pSRB  = pACB->pActiveDCB->pActiveSRB;
171 
172   if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
173     {
174 	printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
175 	return dstate;
176     };
177   if (dstate & DMA_XFER_DONE)
178     {
179 	UINT residual, xferCnt; int ctr = 6000000;
180 	if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
181 	  {
182 	    do
183 	      {
184 		DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");)
185 		dstate = DC390_read8 (DMA_Status);
186 		residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
187 		  DC390_read8 (CtcReg_High) << 16;
188 		residual += DC390_read8 (Current_Fifo) & 0x1f;
189 	      } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
190 	    if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
191 	    /* residual =  ... */
192 	  }
193 	else
194 	    residual = 0;
195 
196 	/* ??? */
197 
198 	xferCnt = pSRB->SGToBeXferLen - residual;
199 	pSRB->SGBusAddr += xferCnt;
200 	pSRB->TotalXferredLen += xferCnt;
201 	pSRB->SGToBeXferLen = residual;
202 # ifdef DC390_DEBUG0
203 	printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n",
204 		(unsigned int)residual, (unsigned int)xferCnt);
205 # endif
206 
207 	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
208     }
209   dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
210   return dstate;
211 };
212 #endif
213 
214 static void __inline__
dc390_InvalidCmd(PACB pACB)215 dc390_InvalidCmd( PACB pACB )
216 {
217     if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
218 	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
219 }
220 
221 #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
222 
223 /* abort command */
224 static void __inline__
dc390_EnableMsgOut_Abort(PACB pACB,PSRB pSRB)225 dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
226 {
227     pSRB->MsgOutBuf[0] = ABORT;
228     pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
229     pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
230 }
231 
232 void __inline__
DC390_Interrupt(int irq,void * dev_id,struct pt_regs * regs)233 DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
234 {
235     PACB   pACB, pACB2;
236     PDCB   pDCB;
237     PSRB   pSRB;
238     UCHAR  sstatus=0;
239     UCHAR  phase;
240     void   (*stateV)( PACB, PSRB, PUCHAR );
241     UCHAR  istate, istatus;
242 #if DMA_INT
243     UCHAR  dstatus;
244 #endif
245     DC390_AFLAGS DC390_IFLAGS //DC390_DFLAGS
246 
247     pACB = (PACB)dev_id;
248     for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB);
249     if (!pACB2)
250     {
251 	printk ("DC390: IRQ called with foreign dev_id %p!\n", pACB);
252 	return;
253     }
254 
255     //DC390_LOCK_DRV;
256 
257     sstatus = DC390_read8 (Scsi_Status);
258     if( !(sstatus & INTERRUPT) )
259 	{ /*DC390_UNLOCK_DRV;*/ return; };
260 
261     DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);)
262 
263 #if DMA_INT
264     DC390_LOCK_IO;
265     DC390_LOCK_ACB;
266     dstatus = dc390_dma_intr (pACB);
267     DC390_UNLOCK_ACB;
268     DC390_UNLOCK_IO;
269 
270     DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);)
271     if (! (dstatus & SCSI_INTERRUPT))
272       {
273 	DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");)
274 	//DC390_UNLOCK_DRV;
275 	return;
276       };
277 #else
278     //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
279     //dstatus = DC390_read8 (DMA_Status);
280     //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
281 #endif
282 
283     DC390_LOCK_IO;
284     DC390_LOCK_ACB;
285     //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */
286 
287     istate = DC390_read8 (Intern_State);
288     istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
289 
290     DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
291     dc390_laststatus &= ~0x00ffffff;
292     dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
293 
294     if (sstatus & ILLEGAL_OP_ERR)
295     {
296 	printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
297 	dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
298     }
299 
300     else if (istatus &  INVALID_CMD)
301     {
302 	printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus);
303 	dc390_InvalidCmd( pACB );
304 	goto unlock;
305     }
306 
307     if (istatus &  SCSI_RESET)
308     {
309 	dc390_ScsiRstDetect( pACB );
310 	goto unlock;
311     }
312 
313     if (istatus &  DISCONNECTED)
314     {
315 	dc390_Disconnect( pACB );
316 	goto unlock;
317     }
318 
319     if (istatus &  RESELECTED)
320     {
321 	dc390_Reselect( pACB );
322 	goto unlock;
323     }
324 
325     else if (istatus & (SELECTED | SEL_ATTENTION))
326     {
327 	printk (KERN_ERR "DC390: Target mode not supported!\n");
328 	goto unlock;
329     }
330 
331     if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
332     {
333 	pDCB = pACB->pActiveDCB;
334 	if (!pDCB)
335 	{
336 		printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
337 		goto unlock;
338 	};
339 	pSRB = pDCB->pActiveSRB;
340 	if( pDCB->DCBFlag & ABORT_DEV_ )
341 	  dc390_EnableMsgOut_Abort (pACB, pSRB);
342 
343 	phase = pSRB->ScsiPhase;
344 	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);)
345 	stateV = (void *) dc390_phase0[phase];
346 	( *stateV )( pACB, pSRB, &sstatus );
347 
348 	pSRB->ScsiPhase = sstatus & 7;
349 	phase = (UCHAR) sstatus & 7;
350 	DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);)
351 	stateV = (void *) dc390_phase1[phase];
352 	( *stateV )( pACB, pSRB, &sstatus );
353 	goto unlock;
354     }
355 
356  unlock:
357     //DC390_LOCK_DRV_NI;
358     DC390_UNLOCK_ACB;
359     DC390_UNLOCK_IO;
360     //DC390_UNLOCK_DRV; /* Restore initial flags */
361 }
362 
363 void
do_DC390_Interrupt(int irq,void * dev_id,struct pt_regs * regs)364 do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
365 {
366     DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq);)
367     /* Locking is done in DC390_Interrupt */
368     DC390_Interrupt(irq, dev_id, regs);
369     DEBUG1(printk (".. IRQ returned\n");)
370 }
371 
372 void
dc390_DataOut_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)373 dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
374 {
375     UCHAR   sstatus;
376     PSGL    psgl;
377     UINT    ResidCnt, xferCnt;
378     UCHAR   dstate = 0;
379 
380     sstatus = *psstatus;
381 
382     if( !(pSRB->SRBState & SRB_XFERPAD) )
383     {
384 	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
385 	    pSRB->SRBStatus |= PARITY_ERROR;
386 
387 	if( sstatus & COUNT_2_ZERO )
388 	{
389 	    int ctr = 6000000; /* only try for about a second */
390 	    while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
391 	    if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
392 	    dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
393 	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
394 	    pSRB->SGIndex++;
395 	    if( pSRB->SGIndex < pSRB->SGcount )
396 	    {
397 		pSRB->pSegmentList++;
398 		psgl = pSRB->pSegmentList;
399 
400 		pSRB->SGBusAddr = virt_to_bus( psgl->address );
401 		pSRB->SGToBeXferLen = (ULONG) psgl->length;
402 	    }
403 	    else
404 		pSRB->SGToBeXferLen = 0;
405 	}
406 	else
407 	{
408 	    ResidCnt  = (UINT) DC390_read8 (Current_Fifo) & 0x1f;
409 	    ResidCnt |= (UINT) DC390_read8 (CtcReg_High) << 16;
410 	    ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid) << 8;
411 	    ResidCnt += (UINT) DC390_read8 (CtcReg_Low);
412 
413 	    xferCnt = pSRB->SGToBeXferLen - ResidCnt;
414 	    pSRB->SGBusAddr += xferCnt;
415 	    pSRB->TotalXferredLen += xferCnt;
416 	    pSRB->SGToBeXferLen = ResidCnt;
417 	}
418     }
419     if ((*psstatus & 7) != SCSI_DATA_OUT)
420     {
421 	    DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
422 	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
423     }
424 }
425 
426 void
dc390_DataIn_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)427 dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
428 {
429     UCHAR   sstatus, residual, bval;
430     PSGL    psgl;
431     UINT    ResidCnt, i;
432     ULONG   xferCnt;
433     PUCHAR  ptr;
434 
435     sstatus = *psstatus;
436 
437     if( !(pSRB->SRBState & SRB_XFERPAD) )
438     {
439 	if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
440 	    pSRB->SRBStatus |= PARITY_ERROR;
441 
442 	if( sstatus & COUNT_2_ZERO )
443 	{
444 	    int ctr = 6000000; /* only try for about a second */
445 	    int dstate = 0;
446 	    while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
447 	    if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
448 	    if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
449 	    dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
450 	    DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16)	\
451 		+ ((ULONG) DC390_read8 (CtcReg_Mid) << 8)		\
452 		+ ((ULONG) DC390_read8 (CtcReg_Low));)
453 	    DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
454 
455 	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
456 
457 	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
458 	    pSRB->SGIndex++;
459 	    if( pSRB->SGIndex < pSRB->SGcount )
460 	    {
461 		pSRB->pSegmentList++;
462 		psgl = pSRB->pSegmentList;
463 
464 		pSRB->SGBusAddr = virt_to_bus( psgl->address );
465 		pSRB->SGToBeXferLen = (ULONG) psgl->length;
466 	    }
467 	    else
468 		pSRB->SGToBeXferLen = 0;
469 	}
470 	else	/* phase changed */
471 	{
472 	    residual = 0;
473 	    bval = DC390_read8 (Current_Fifo);
474 	    while( bval & 0x1f )
475 	    {
476 		DEBUG1(printk (KERN_DEBUG "Check for residuals,");)
477 		if( (bval & 0x1f) == 1 )
478 		{
479 		    for(i=0; i < 0x100; i++)
480 		    {
481 			bval = DC390_read8 (Current_Fifo);
482 			if( !(bval & 0x1f) )
483 			    goto din_1;
484 			else if( i == 0x0ff )
485 			{
486 			    residual = 1;   /* ;1 residual byte */
487 			    goto din_1;
488 			}
489 		    }
490 		}
491 		else
492 		    bval = DC390_read8 (Current_Fifo);
493 	    }
494 din_1:
495 	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
496 	    for (i = 0xa000; i; i--)
497 	    {
498 		bval = DC390_read8 (DMA_Status);
499 		if (bval & BLAST_COMPLETE)
500 		    break;
501 	    }
502 	    /* It seems a DMA Blast abort isn't that bad ... */
503 	    if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
504 	    //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
505 	    dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
506 
507 	    DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval);)
508 	    ResidCnt = (UINT) DC390_read8 (CtcReg_High);
509 	    ResidCnt <<= 8;
510 	    ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid);
511 	    ResidCnt <<= 8;
512 	    ResidCnt |= (UINT) DC390_read8 (CtcReg_Low);
513 
514 	    xferCnt = pSRB->SGToBeXferLen - ResidCnt;
515 	    pSRB->SGBusAddr += xferCnt;
516 	    pSRB->TotalXferredLen += xferCnt;
517 	    pSRB->SGToBeXferLen = ResidCnt;
518 
519 	    if( residual )
520 	    {
521 		bval = DC390_read8 (ScsiFifo);	    /* get one residual byte */
522 		ptr = (PUCHAR) bus_to_virt( pSRB->SGBusAddr );
523 		*ptr = bval;
524 		pSRB->SGBusAddr++; xferCnt++;
525 		pSRB->TotalXferredLen++;
526 		pSRB->SGToBeXferLen--;
527 	    }
528 	    DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
529 			   pSRB->TotalXferredLen, pSRB->SGToBeXferLen);)
530 
531 	}
532     }
533     if ((*psstatus & 7) != SCSI_DATA_IN)
534     {
535 	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
536 	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
537     }
538 }
539 
540 static void
dc390_Command_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)541 dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
542 {
543 }
544 
545 static void
dc390_Status_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)546 dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
547 {
548 
549     pSRB->TargetStatus = DC390_read8 (ScsiFifo);
550     //udelay (1);
551     pSRB->EndMessage = DC390_read8 (ScsiFifo);	/* get message */
552 
553     *psstatus = SCSI_NOP0;
554     pSRB->SRBState = SRB_COMPLETED;
555     DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
556 }
557 
558 static void
dc390_MsgOut_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)559 dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
560 {
561     if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
562 	*psstatus = SCSI_NOP0;
563     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
564 }
565 
566 
567 static void __inline__
dc390_reprog(PACB pACB,PDCB pDCB)568 dc390_reprog (PACB pACB, PDCB pDCB)
569 {
570   DC390_write8 (Sync_Period, pDCB->SyncPeriod);
571   DC390_write8 (Sync_Offset, pDCB->SyncOffset);
572   DC390_write8 (CtrlReg3, pDCB->CtrlR3);
573   DC390_write8 (CtrlReg4, pDCB->CtrlR4);
574   dc390_SetXferRate (pACB, pDCB);
575 };
576 
577 
578 #ifdef DC390_DEBUG0
579 static void
dc390_printMsg(UCHAR * MsgBuf,UCHAR len)580 dc390_printMsg (UCHAR *MsgBuf, UCHAR len)
581 {
582   int i;
583   printk (" %02x", MsgBuf[0]);
584   for (i = 1; i < len; i++)
585     printk (" %02x", MsgBuf[i]);
586   printk ("\n");
587 };
588 #endif
589 
590 /* reject_msg */
591 static void __inline__
dc390_MsgIn_reject(PACB pACB,PSRB pSRB)592 dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
593 {
594   pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
595   pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
596   DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)
597 }
598 
599 static PSRB
dc390_MsgIn_QTag(PACB pACB,PDCB pDCB,UCHAR tag)600 dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
601 {
602   PSRB lastSRB = pDCB->pGoingLast;
603   PSRB pSRB = pDCB->pGoingSRB;
604 
605   if (pSRB)
606     {
607       for( ;pSRB ; )
608 	{
609 	  if (pSRB->TagNumber == tag) break;
610 	  if (pSRB == lastSRB) goto mingx0;
611 	  pSRB = pSRB->pNextSRB;
612 	}
613 
614       if( pDCB->DCBFlag & ABORT_DEV_ )
615 	{
616 	  pSRB->SRBState = SRB_ABORT_SENT;
617 	  dc390_EnableMsgOut_Abort( pACB, pSRB );
618 	}
619 
620       if( !(pSRB->SRBState & SRB_DISCONNECT) )
621 	goto  mingx0;
622 
623       pDCB->pActiveSRB = pSRB;
624       pSRB->SRBState = SRB_DATA_XFER;
625     }
626   else
627     {
628     mingx0:
629       pSRB = pACB->pTmpSRB;
630       pSRB->SRBState = SRB_UNEXPECT_RESEL;
631       pDCB->pActiveSRB = pSRB;
632       pSRB->MsgOutBuf[0] = ABORT_TAG;
633       pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
634     }
635   return pSRB;
636 }
637 
638 
639 /* set async transfer mode */
640 static void
dc390_MsgIn_set_async(PACB pACB,PSRB pSRB)641 dc390_MsgIn_set_async (PACB pACB, PSRB pSRB)
642 {
643   PDCB pDCB = pSRB->pSRBDCB;
644   if (!(pSRB->SRBState & DO_SYNC_NEGO))
645     printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
646   pSRB->SRBState &= ~DO_SYNC_NEGO;
647   pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
648   pDCB->SyncPeriod = 0;
649   pDCB->SyncOffset = 0;
650   //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
651   pDCB->CtrlR3 = FAST_CLK;	/* fast clock / normal scsi */
652   pDCB->CtrlR4 &= 0x3f;
653   pDCB->CtrlR4 |= pACB->glitch_cfg;	/* glitch eater */
654   dc390_reprog (pACB, pDCB);
655 }
656 
657 /* set sync transfer mode */
658 static void
dc390_MsgIn_set_sync(PACB pACB,PSRB pSRB)659 dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB)
660 {
661   UCHAR bval;
662   USHORT wval, wval1;
663   PDCB pDCB = pSRB->pSRBDCB;
664   UCHAR oldsyncperiod = pDCB->SyncPeriod;
665   UCHAR oldsyncoffset = pDCB->SyncOffset;
666 
667   if (!(pSRB->SRBState & DO_SYNC_NEGO))
668     {
669       printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
670 	      pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
671 
672       /* reject */
673       //dc390_MsgIn_reject (pACB, pSRB);
674       //return dc390_MsgIn_set_async (pACB, pSRB);
675 
676       /* Reply with corrected SDTR Message */
677       if (pSRB->MsgInBuf[4] > 15)
678 	{
679 	  printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
680 	  pSRB->MsgInBuf[4] = 15;
681 	}
682       if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
683 	{
684 	  printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
685 	  pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
686 	};
687       memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
688       pSRB->MsgCnt = 5;
689       DC390_ENABLE_MSGOUT;
690     };
691 
692   pSRB->SRBState &= ~DO_SYNC_NEGO;
693   pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
694   pDCB->SyncOffset &= 0x0f0;
695   pDCB->SyncOffset |= pSRB->MsgInBuf[4];
696   pDCB->NegoPeriod = pSRB->MsgInBuf[3];
697 
698   wval = (USHORT) pSRB->MsgInBuf[3];
699   wval = wval << 2; wval -= 3; wval1 = wval / 25;	/* compute speed */
700   if( (wval1 * 25) != wval) wval1++;
701   bval = FAST_CLK+FAST_SCSI;	/* fast clock / fast scsi */
702 
703   pDCB->CtrlR4 &= 0x3f;		/* Glitch eater: 12ns less than normal */
704   if (pACB->glitch_cfg != NS_TO_GLITCH(0))
705     pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
706   else
707     pDCB->CtrlR4 |= NS_TO_GLITCH(0);
708   if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
709 
710   if (wval1 >= 8)
711     {
712       wval1--;	/* Timing computation differs by 1 from FAST_SCSI */
713       bval = FAST_CLK;		/* fast clock / normal scsi */
714       pDCB->CtrlR4 |= pACB->glitch_cfg; 	/* glitch eater */
715     }
716 
717   pDCB->CtrlR3 = bval;
718   pDCB->SyncPeriod = (UCHAR)wval1;
719 
720   if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
721     {
722       if (! (bval & FAST_SCSI)) wval1++;
723       printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
724 	      40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
725     }
726 
727   dc390_reprog (pACB, pDCB);
728 };
729 
730 
731 /* handle RESTORE_PTR */
732 static void
dc390_restore_ptr(PACB pACB,PSRB pSRB)733 dc390_restore_ptr (PACB pACB, PSRB pSRB)
734 {
735   PSGL psgl;
736   pSRB->TotalXferredLen = 0;
737   pSRB->SGIndex = 0;
738   if( pSRB->pcmd->use_sg )
739     {
740       pSRB->SGcount = (UCHAR) pSRB->pcmd->use_sg;
741       pSRB->pSegmentList = (PSGL) pSRB->pcmd->request_buffer;
742       psgl = pSRB->pSegmentList;
743       while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr)
744 	{
745 	  pSRB->TotalXferredLen += (ULONG) psgl->length;
746 	  pSRB->SGIndex++;
747 	  if( pSRB->SGIndex < pSRB->SGcount )
748 	    {
749 	      pSRB->pSegmentList++;
750 	      psgl = pSRB->pSegmentList;
751 
752 	      pSRB->SGBusAddr = virt_to_bus( psgl->address );
753 	      pSRB->SGToBeXferLen = (ULONG) psgl->length;
754 	    }
755 	  else
756 	    pSRB->SGToBeXferLen = 0;
757 	}
758       pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
759       pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
760       printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
761     }
762     else if( pSRB->pcmd->request_buffer )
763     {
764 	pSRB->SGcount = 1;
765 	pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
766 	pSRB->Segmentx.address = (PUCHAR) pSRB->pcmd->request_buffer + pSRB->Saved_Ptr;
767 	pSRB->Segmentx.length = pSRB->pcmd->request_bufflen - pSRB->Saved_Ptr;
768 	printk (KERN_INFO "DC390: Pointer restored. Total %li, Bus %p\n",
769 		pSRB->Saved_Ptr, pSRB->Segmentx.address);
770     }
771      else
772        {
773 	 pSRB->SGcount = 0;
774 	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
775        };
776 
777   pSRB->TotalXferredLen = pSRB->Saved_Ptr;
778 };
779 
780 
781 /* According to the docs, the AM53C974 reads the message and
782  * generates a Succesful Operation IRQ before asserting ACK for
783  * the last byte (how does it know whether it's the last ?) */
784 /* The old code handled it in another way, indicating, that on
785  * every message byte an IRQ is generated and every byte has to
786  * be manually ACKed. Hmmm ?  (KG, 98/11/28) */
787 /* The old implementation was correct. Sigh! */
788 
789 /* Check if the message is complete */
790 static UCHAR __inline__
dc390_MsgIn_complete(UCHAR * msgbuf,UINT len)791 dc390_MsgIn_complete (UCHAR *msgbuf, UINT len)
792 {
793   if (*msgbuf == EXTENDED_MESSAGE)
794   {
795 	if (len < 2) return 0;
796 	if (len < msgbuf[1] + 2) return 0;
797   }
798   else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
799 	if (len < 2) return 0;
800   return 1;
801 }
802 
803 
804 
805 /* read and eval received messages */
806 void
dc390_MsgIn_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)807 dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
808 {
809     PDCB   pDCB = pACB->pActiveDCB;
810 
811     /* Read the msg */
812 
813     pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
814     //pSRB->SRBState = 0;
815 
816     /* Msg complete ? */
817     if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
818       {
819 	DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);)
820 	/* Now eval the msg */
821 	switch (pSRB->MsgInBuf[0])
822 	  {
823 	  case DISCONNECT:
824 	    pSRB->SRBState = SRB_DISCONNECT; break;
825 
826 	  case SIMPLE_QUEUE_TAG:
827 	  case HEAD_OF_QUEUE_TAG:
828 	  case ORDERED_QUEUE_TAG:
829 	    pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
830 	    break;
831 
832 	  case MESSAGE_REJECT:
833 	    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
834 	    pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
835 	    if( pSRB->SRBState & DO_SYNC_NEGO)
836 	      dc390_MsgIn_set_async (pACB, pSRB);
837 	    break;
838 
839 	  case EXTENDED_MESSAGE:
840 	    /* reject every extended msg but SDTR */
841 	    if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
842 	      dc390_MsgIn_reject (pACB, pSRB);
843 	    else
844 	      {
845 		if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
846 		  dc390_MsgIn_set_async (pACB, pSRB);
847 		else
848 		  dc390_MsgIn_set_sync (pACB, pSRB);
849 	      };
850 
851 	    // nothing has to be done
852 	  case COMMAND_COMPLETE: break;
853 
854 	    // SAVE POINTER may be ignored as we have the PSRB associated with the
855 	    // scsi command. Thanks, Gerard, for pointing it out.
856 	  case SAVE_POINTERS:
857 	    pSRB->Saved_Ptr = pSRB->TotalXferredLen;
858 	    break;
859 	    // The device might want to restart transfer with a RESTORE
860 	  case RESTORE_POINTERS:
861 	    DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n");)
862 	    dc390_restore_ptr (pACB, pSRB);
863 	    break;
864 
865 	    // reject unknown messages
866 	  default: dc390_MsgIn_reject (pACB, pSRB);
867 	  }
868 
869 	/* Clear counter and MsgIn state */
870 	pSRB->SRBState &= ~SRB_MSGIN;
871 	pACB->MsgLen = 0;
872       };
873 
874     *psstatus = SCSI_NOP0;
875     DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
876     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
877 }
878 
879 
880 void
dc390_DataIO_Comm(PACB pACB,PSRB pSRB,UCHAR ioDir)881 dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
882 {
883     PSGL   psgl;
884     ULONG  lval;
885     PDCB   pDCB = pACB->pActiveDCB;
886 
887     if (pSRB == pACB->pTmpSRB)
888     {
889 	if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",
890 			  pDCB->TargetID, pDCB->TargetLUN);
891 	else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
892 	dc390_EnableMsgOut_Abort (pACB, pSRB);
893 	if (pDCB) pDCB->DCBFlag |= ABORT_DEV;
894 	return;
895     }
896 
897     if( pSRB->SGIndex < pSRB->SGcount )
898     {
899 	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
900 	if( !pSRB->SGToBeXferLen )
901 	{
902 	    psgl = pSRB->pSegmentList;
903 	    pSRB->SGBusAddr = virt_to_bus( psgl->address );
904 	    pSRB->SGToBeXferLen = (ULONG) psgl->length;
905 	    DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
906 	}
907 	lval = pSRB->SGToBeXferLen;
908 	DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
909 	DC390_write8 (CtcReg_Low, (UCHAR) lval);
910 	lval >>= 8;
911 	DC390_write8 (CtcReg_Mid, (UCHAR) lval);
912 	lval >>= 8;
913 	DC390_write8 (CtcReg_High, (UCHAR) lval);
914 
915 	DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
916 	DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
917 
918 	//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
919 	pSRB->SRBState = SRB_DATA_XFER;
920 
921 	DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
922 
923 	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
924 	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);)
925 	//DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
926 	//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);)
927     }
928     else    /* xfer pad */
929     {
930 	if( pSRB->SGcount )
931 	{
932 	    pSRB->AdaptStatus = H_OVER_UNDER_RUN;
933 	    pSRB->SRBStatus |= OVER_RUN;
934 	    DEBUG0(printk (KERN_WARNING " DC390: Overrun -");)
935 	}
936 	DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");)
937 	DC390_write8 (CtcReg_Low, 0);
938 	DC390_write8 (CtcReg_Mid, 0);
939 	DC390_write8 (CtcReg_High, 0);
940 
941 	pSRB->SRBState |= SRB_XFERPAD;
942 	DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
943 /*
944 	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
945 	DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
946 */
947     }
948 }
949 
950 
951 static void
dc390_DataOutPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)952 dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
953 {
954     dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
955 }
956 
957 static void
dc390_DataInPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)958 dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
959 {
960     dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
961 }
962 
963 void
dc390_CommandPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)964 dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
965 {
966     PDCB   pDCB;
967     UCHAR  i, cnt;
968     PUCHAR ptr;
969 
970     DC390_write8 (ScsiCmd, RESET_ATN_CMD);
971     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
972     if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
973     {
974 	cnt = (UCHAR) pSRB->pcmd->cmd_len;
975 	ptr = (PUCHAR) pSRB->pcmd->cmnd;
976 	for(i=0; i < cnt; i++)
977 	    DC390_write8 (ScsiFifo, *(ptr++));
978     }
979     else
980     {
981 	UCHAR bval = 0;
982 	DC390_write8 (ScsiFifo, REQUEST_SENSE);
983 	pDCB = pACB->pActiveDCB;
984 	DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
985 	DC390_write8 (ScsiFifo, bval);
986 	DC390_write8 (ScsiFifo, bval);
987 	DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
988 	DC390_write8 (ScsiFifo, bval);
989 	DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n");)
990     }
991     pSRB->SRBState = SRB_COMMAND;
992     DC390_write8 (ScsiCmd, INFO_XFER_CMD);
993 }
994 
995 static void
dc390_StatusPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)996 dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
997 {
998     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
999     pSRB->SRBState = SRB_STATUS;
1000     DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
1001     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1002 }
1003 
1004 void
dc390_MsgOutPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)1005 dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1006 {
1007     UCHAR   bval, i, cnt;
1008     PUCHAR  ptr;
1009     PDCB    pDCB;
1010 
1011     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1012     pDCB = pACB->pActiveDCB;
1013     if( !(pSRB->SRBState & SRB_MSGOUT) )
1014     {
1015 	cnt = pSRB->MsgCnt;
1016 	if( cnt )
1017 	{
1018 	    ptr = (PUCHAR) pSRB->MsgOutBuf;
1019 	    for(i=0; i < cnt; i++)
1020 		DC390_write8 (ScsiFifo, *(ptr++));
1021 	    pSRB->MsgCnt = 0;
1022 	    if( (pDCB->DCBFlag & ABORT_DEV_) &&
1023 		(pSRB->MsgOutBuf[0] == ABORT) )
1024 		pSRB->SRBState = SRB_ABORT_SENT;
1025 	}
1026 	else
1027 	{
1028 	    bval = ABORT;	/* ??? MSG_NOP */
1029 	    if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
1030 		(pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
1031 		(pSRB->SRBFlag & AUTO_REQSENSE) )
1032 	    {
1033 		if( pDCB->SyncMode & SYNC_ENABLE )
1034 		    goto  mop1;
1035 	    }
1036 	    DC390_write8 (ScsiFifo, bval);
1037 	}
1038 	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1039     }
1040     else
1041     {
1042 mop1:
1043         printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
1044 	DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
1045 	DC390_write8 (ScsiFifo, 3);	/*    ;length of extended msg */
1046 	DC390_write8 (ScsiFifo, EXTENDED_SDTR);	/*    ; sync nego */
1047 	DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
1048 	if (pDCB->SyncOffset & 0x0f)
1049 		    DC390_write8 (ScsiFifo, pDCB->SyncOffset);
1050 	else
1051 		    DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
1052 	pSRB->SRBState |= DO_SYNC_NEGO;
1053 	DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1054     }
1055 }
1056 
1057 static void
dc390_MsgInPhase(PACB pACB,PSRB pSRB,PUCHAR psstatus)1058 dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1059 {
1060     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1061     if( !(pSRB->SRBState & SRB_MSGIN) )
1062     {
1063 	pSRB->SRBState &= ~SRB_DISCONNECT;
1064 	pSRB->SRBState |= SRB_MSGIN;
1065     }
1066     DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1067     //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1068 }
1069 
1070 static void
dc390_Nop_0(PACB pACB,PSRB pSRB,PUCHAR psstatus)1071 dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1072 {
1073 }
1074 
1075 static void
dc390_Nop_1(PACB pACB,PSRB pSRB,PUCHAR psstatus)1076 dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1077 {
1078 }
1079 
1080 
1081 static void
dc390_SetXferRate(PACB pACB,PDCB pDCB)1082 dc390_SetXferRate( PACB pACB, PDCB pDCB )
1083 {
1084     UCHAR  bval, i, cnt;
1085     PDCB   ptr;
1086 
1087     if( !(pDCB->TargetLUN) )
1088     {
1089 	if( !pACB->scan_devices )
1090 	{
1091 	    ptr = pACB->pLinkDCB;
1092 	    cnt = pACB->DCBCnt;
1093 	    bval = pDCB->TargetID;
1094 	    for(i=0; i<cnt; i++)
1095 	    {
1096 		if( ptr->TargetID == bval )
1097 		{
1098 		    ptr->SyncPeriod = pDCB->SyncPeriod;
1099 		    ptr->SyncOffset = pDCB->SyncOffset;
1100 		    ptr->CtrlR3 = pDCB->CtrlR3;
1101 		    ptr->CtrlR4 = pDCB->CtrlR4;
1102 		    ptr->SyncMode = pDCB->SyncMode;
1103 		}
1104 		ptr = ptr->pNextDCB;
1105 	    }
1106 	}
1107     }
1108     return;
1109 }
1110 
1111 
1112 void
dc390_Disconnect(PACB pACB)1113 dc390_Disconnect( PACB pACB )
1114 {
1115     PDCB   pDCB;
1116     PSRB   pSRB, psrb;
1117     UCHAR  i, cnt;
1118 
1119     DEBUG0(printk(KERN_INFO "DISC,");)
1120 
1121     if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
1122     pACB->Connected = 0;
1123     pDCB = pACB->pActiveDCB;
1124     if (!pDCB)
1125      {
1126 	int j = 400;
1127 	DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
1128 	       pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel);)
1129 	while (--j) udelay (1000);
1130 	DC390_read8 (INT_Status);	/* Reset Pending INT */
1131 	DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1132 	return;
1133      }
1134     DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1135     pSRB = pDCB->pActiveSRB;
1136     pACB->pActiveDCB = 0;
1137     pSRB->ScsiPhase = SCSI_NOP0;
1138     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
1139     {
1140 	pSRB->SRBState = 0;
1141 	dc390_Waiting_process ( pACB );
1142     }
1143     else if( pSRB->SRBState & SRB_ABORT_SENT )
1144     {
1145 	pDCB->TagMask = 0;
1146 	pDCB->DCBFlag = 0;
1147 	cnt = pDCB->GoingSRBCnt;
1148 	pDCB->GoingSRBCnt = 0;
1149 	pSRB = pDCB->pGoingSRB;
1150 	for( i=0; i < cnt; i++)
1151 	{
1152 	    psrb = pSRB->pNextSRB;
1153 	    dc390_Free_insert (pACB, pSRB);
1154 	    pSRB = psrb;
1155 	}
1156 	pDCB->pGoingSRB = 0;
1157 	dc390_Query_to_Waiting (pACB);
1158 	dc390_Waiting_process (pACB);
1159     }
1160     else
1161     {
1162 	if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
1163 	   !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
1164 	{	/* Selection time out */
1165 	    if( !(1/*pACB->scan_devices*/) )
1166 	    {
1167 		pSRB->SRBState = SRB_READY;
1168 		dc390_freetag (pDCB, pSRB);
1169 		dc390_Going_to_Waiting (pDCB, pSRB);
1170 		dc390_waiting_timer (pACB, HZ/5);
1171 	    }
1172 	    else
1173 	    {
1174 		pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
1175 		goto  disc1;
1176 	    }
1177 	}
1178 	else if( pSRB->SRBState & SRB_DISCONNECT )
1179 	{
1180 	    dc390_Waiting_process ( pACB );
1181 	}
1182 	else if( pSRB->SRBState & SRB_COMPLETED )
1183 	{
1184 disc1:
1185 	    dc390_freetag (pDCB, pSRB);
1186 	    pDCB->pActiveSRB = 0;
1187 	    pSRB->SRBState = SRB_FREE;
1188 	    dc390_SRBdone( pACB, pDCB, pSRB);
1189 	}
1190     }
1191     pACB->MsgLen = 0;
1192 }
1193 
1194 
1195 void
dc390_Reselect(PACB pACB)1196 dc390_Reselect( PACB pACB )
1197 {
1198     PDCB   pDCB;
1199     PSRB   pSRB;
1200     UCHAR  id, lun;
1201 
1202     DEBUG0(printk(KERN_INFO "RSEL,");)
1203     pACB->Connected = 1;
1204     pDCB = pACB->pActiveDCB;
1205     if( pDCB )
1206     {	/* Arbitration lost but Reselection won */
1207 	DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n");)
1208 	pSRB = pDCB->pActiveSRB;
1209 	if( !( pACB->scan_devices ) )
1210 	{
1211 	    pSRB->SRBState = SRB_READY;
1212 	    dc390_freetag (pDCB, pSRB);
1213 	    dc390_Going_to_Waiting ( pDCB, pSRB);
1214 	    dc390_waiting_timer (pACB, HZ/5);
1215 	}
1216     }
1217     /* Get ID */
1218     lun = DC390_read8 (ScsiFifo);
1219     DEBUG0(printk ("Dev %02x,", lun);)
1220     if (!(lun & (1 << pACB->pScsiHost->this_id)))
1221       printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
1222     else
1223       lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
1224     id = 0; while (lun >>= 1) id++;
1225     /* Get LUN */
1226     lun = DC390_read8 (ScsiFifo);
1227     if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
1228     lun &= 7;
1229     DEBUG0(printk ("(%02i-%i),", id, lun);)
1230     pDCB = dc390_findDCB (pACB, id, lun);
1231     if (!pDCB)
1232     {
1233 	printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
1234 		    id, lun);
1235 	return;
1236     }
1237     pACB->pActiveDCB = pDCB;
1238     /* TagQ: We expect a message soon, so never mind the exact SRB */
1239     if( pDCB->SyncMode & EN_TAG_QUEUEING )
1240     {
1241 	pSRB = pACB->pTmpSRB;
1242 	pDCB->pActiveSRB = pSRB;
1243     }
1244     else
1245     {
1246 	pSRB = pDCB->pActiveSRB;
1247 	if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
1248 	{
1249 	    pSRB= pACB->pTmpSRB;
1250 	    pSRB->SRBState = SRB_UNEXPECT_RESEL;
1251 	    printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
1252 		    id, lun);
1253 	    pDCB->pActiveSRB = pSRB;
1254 	    dc390_EnableMsgOut_Abort ( pACB, pSRB );
1255 	}
1256 	else
1257 	{
1258 	    if( pDCB->DCBFlag & ABORT_DEV_ )
1259 	    {
1260 		pSRB->SRBState = SRB_ABORT_SENT;
1261 		printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
1262 			id, lun);
1263 		dc390_EnableMsgOut_Abort( pACB, pSRB );
1264 	    }
1265 	    else
1266 		pSRB->SRBState = SRB_DATA_XFER;
1267 	}
1268     }
1269 
1270     DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
1271     pSRB->ScsiPhase = SCSI_NOP0;
1272     DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
1273     DC390_write8 (Sync_Period, pDCB->SyncPeriod);
1274     DC390_write8 (Sync_Offset, pDCB->SyncOffset);
1275     DC390_write8 (CtrlReg1, pDCB->CtrlR1);
1276     DC390_write8 (CtrlReg3, pDCB->CtrlR3);
1277     DC390_write8 (CtrlReg4, pDCB->CtrlR4);	/* ; Glitch eater */
1278     DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);	/* ;to release the /ACK signal */
1279 }
1280 
1281 
1282 static void
dc390_remove_dev(PACB pACB,PDCB pDCB)1283 dc390_remove_dev (PACB pACB, PDCB pDCB)
1284 {
1285    PDCB pPrevDCB = pACB->pLinkDCB;
1286 
1287    if (pDCB->GoingSRBCnt > 1)
1288      {
1289 	DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\
1290 		pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt);)
1291 	return;
1292      };
1293    pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN);
1294 
1295    // The first one
1296    if (pDCB == pACB->pLinkDCB)
1297    {
1298 	// The last one
1299 	if (pACB->pLastDCB == pDCB) {
1300 		pDCB->pNextDCB = 0; pACB->pLastDCB = 0;
1301 	}
1302 	pACB->pLinkDCB = pDCB->pNextDCB;
1303    }
1304    else
1305    {
1306 	while (pPrevDCB->pNextDCB != pDCB) pPrevDCB = pPrevDCB->pNextDCB;
1307 	pPrevDCB->pNextDCB = pDCB->pNextDCB;
1308 	if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB;
1309    }
1310 
1311    DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\
1312 	   pDCB->TargetID, pDCB->TargetLUN, pDCB);)
1313    if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0;
1314    if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB;
1315    if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB;
1316    kfree (pDCB);
1317    pACB->DCBCnt--;
1318    /* pACB->DeviceCnt--; */
1319 };
1320 
1321 
1322 static UCHAR __inline__
dc390_tagq_blacklist(char * name)1323 dc390_tagq_blacklist (char* name)
1324 {
1325    UCHAR i;
1326    for(i=0; i<BADDEVCNT; i++)
1327      if (memcmp (name, dc390_baddevname1[i], 28) == 0)
1328 	return 1;
1329    return 0;
1330 };
1331 
1332 
1333 static void
dc390_disc_tagq_set(PDCB pDCB,PSCSI_INQDATA ptr)1334 dc390_disc_tagq_set (PDCB pDCB, PSCSI_INQDATA ptr)
1335 {
1336    /* Check for SCSI format (ANSI and Response data format) */
1337    if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 )
1338    {
1339 	if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1340 	    (pDCB->DevMode & TAG_QUEUEING_) &&
1341 	    /* ((pDCB->DevType == TYPE_DISK)
1342 		|| (pDCB->DevType == TYPE_MOD)) &&*/
1343 	    !dc390_tagq_blacklist (((char*)ptr)+8) )
1344 	  {
1345 	     if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum;
1346 	     pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */;
1347 	     //pDCB->TagMask = 0;
1348 	  }
1349 	else
1350 	     pDCB->MaxCommand = 1;
1351      }
1352 };
1353 
1354 
1355 static void
dc390_add_dev(PACB pACB,PDCB pDCB,PSCSI_INQDATA ptr)1356 dc390_add_dev (PACB pACB, PDCB pDCB, PSCSI_INQDATA ptr)
1357 {
1358    UCHAR bval1 = ptr->DevType & SCSI_DEVTYPE;
1359    pDCB->DevType = bval1;
1360    /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
1361 	dc390_disc_tagq_set (pDCB, ptr);
1362 };
1363 
1364 
1365 static void __inline__
dc390_RequestSense(PACB pACB,PDCB pDCB,PSRB pSRB)1366 dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1367 {
1368     PSCSICMD  pcmd;
1369 
1370     REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
1371 	    pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);)
1372 
1373     pSRB->SRBFlag |= AUTO_REQSENSE;
1374     //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0];
1375     //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4];
1376     //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount;
1377     //pSRB->Segment1[1] = pSRB->TotalXferredLen;
1378     pSRB->SavedSGCount = pSRB->SGcount;
1379     pSRB->SavedTotXLen = pSRB->TotalXferredLen;
1380     pSRB->AdaptStatus = 0;
1381     pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
1382 
1383     pcmd = pSRB->pcmd;
1384 
1385     pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
1386     pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
1387     pSRB->pSegmentList = &pSRB->Segmentx;
1388     pSRB->SGcount = 1;
1389     pSRB->SGIndex = 0;
1390 
1391     //pSRB->CmdBlock[0] = REQUEST_SENSE;
1392     //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
1393     //(USHORT) pSRB->CmdBlock[2] = 0;
1394     //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
1395     //pSRB->ScsiCmdLen = 6;
1396 
1397     pSRB->TotalXferredLen = 0;
1398     pSRB->SGToBeXferLen = 0;
1399     if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1400 	dc390_Going_to_Waiting ( pDCB, pSRB );
1401 	dc390_waiting_timer (pACB, HZ/5);
1402     }
1403 }
1404 
1405 
1406 void
dc390_SRBdone(PACB pACB,PDCB pDCB,PSRB pSRB)1407 dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
1408 {
1409     UCHAR  bval, status, i, DCB_removed;
1410     PSCSICMD pcmd;
1411     PSCSI_INQDATA  ptr;
1412     PSGL   ptr2;
1413     ULONG  swlval;
1414 
1415     pcmd = pSRB->pcmd; DCB_removed = 0;
1416     status = pSRB->TargetStatus;
1417     ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1418     if( pcmd->use_sg )
1419 	ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
1420 
1421     DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
1422 		pSRB, pcmd->pid);)
1423     if(pSRB->SRBFlag & AUTO_REQSENSE)
1424     {	/* Last command was a Request Sense */
1425 	pSRB->SRBFlag &= ~AUTO_REQSENSE;
1426 	pSRB->AdaptStatus = 0;
1427 	pSRB->TargetStatus = CHECK_CONDITION << 1;
1428 #ifdef DC390_REMOVABLEDEBUG
1429 	switch (pcmd->sense_buffer[2] & 0x0f)
1430 	{
1431 	 case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1432 				 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1433 				 status, pACB->scan_devices); break;
1434 	 case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1435 				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1436 				      status, pACB->scan_devices); break;
1437 	 case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1438 				       pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1439 				       status, pACB->scan_devices); break;
1440 	 case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1441 				    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1442 				    status, pACB->scan_devices); break;
1443 	 case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1444 				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1445 				      status, pACB->scan_devices); break;
1446 	}
1447 #endif
1448 	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
1449 	if (status == (CHECK_CONDITION << 1))
1450 	{
1451 	    pcmd->result = MK_RES_LNX(0,DID_BAD_TARGET,0,/*CHECK_CONDITION*/0);
1452 	    goto ckc_e;
1453 	}
1454 	if(pSRB->RetryCnt == 0)
1455 	{
1456 	    //(UINT)(pSRB->pcmd->cmnd[0]) = pSRB->Segment0[0];
1457 	    pSRB->TotalXferredLen = pSRB->SavedTotXLen;
1458 	    if( (pSRB->TotalXferredLen) &&
1459 		(pSRB->TotalXferredLen >= pcmd->underflow) )
1460 		  SET_RES_DID(pcmd->result,DID_OK)
1461 	    else
1462 		  pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
1463 		  REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->pcmd->cmnd[0],\
1464 			(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
1465 	    goto ckc_e;
1466 	}
1467 	else /* Retry */
1468 	{
1469 	    pSRB->RetryCnt--;
1470 	    pSRB->AdaptStatus = 0;
1471 	    pSRB->TargetStatus = 0;
1472 	    //*((PUINT) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1473 	    //*((PUINT) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
1474 	    /* Don't retry on TEST_UNIT_READY */
1475 	    if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
1476 	    {
1477 		pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
1478 		REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
1479 		       (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
1480 		goto ckc_e;
1481 	    }
1482 	    SET_RES_DRV(pcmd->result,DRIVER_SENSE);
1483 	    pSRB->SGcount	 = (UCHAR) pSRB->SavedSGCount;
1484 	    //pSRB->ScsiCmdLen	 = (UCHAR) (pSRB->Segment1[0] >> 8);
1485 	    DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->target, pcmd->lun);)
1486 	    pSRB->SGIndex = 0;
1487 	    pSRB->TotalXferredLen = 0;
1488 	    pSRB->SGToBeXferLen = 0;
1489 	    if( pcmd->use_sg )
1490 		pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1491 	    else if( pcmd->request_buffer )
1492 	    {
1493 		pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1494 		pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1495 		pSRB->Segmentx.length = pcmd->request_bufflen;
1496 	    }
1497 	    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1498 		dc390_Going_to_Waiting ( pDCB, pSRB );
1499 		dc390_waiting_timer (pACB, HZ/5);
1500 	    }
1501 	    return;
1502 	}
1503     }
1504     if( status )
1505     {
1506 	if( status_byte(status) == CHECK_CONDITION )
1507 	{
1508 	    REMOVABLEDEBUG(printk (KERN_INFO "DC390: Check_Condition (Cmd %02x, Id %02x, LUN %02x)\n",\
1509 		    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);)
1510 	    if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
1511 	    {
1512 		bval = pSRB->SGcount;
1513 		swlval = 0;
1514 		ptr2 = pSRB->pSegmentList;
1515 		for( i=pSRB->SGIndex; i < bval; i++)
1516 		{
1517 		    swlval += ptr2->length;
1518 		    ptr2++;
1519 		}
1520 		REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
1521 			(UINT) pSRB->TotalXferredLen, (UINT) swlval);)
1522 	    }
1523 	    dc390_RequestSense( pACB, pDCB, pSRB );
1524 	    return;
1525 	}
1526 	else if( status_byte(status) == QUEUE_FULL )
1527 	{
1528 	    bval = (UCHAR) pDCB->GoingSRBCnt;
1529 	    bval--;
1530 	    pDCB->MaxCommand = bval;
1531 	    dc390_freetag (pDCB, pSRB);
1532 	    dc390_Going_to_Waiting ( pDCB, pSRB );
1533 	    dc390_waiting_timer (pACB, HZ/5);
1534 	    pSRB->AdaptStatus = 0;
1535 	    pSRB->TargetStatus = 0;
1536 	    return;
1537 	}
1538 	else if(status == SCSI_STAT_SEL_TIMEOUT)
1539 	{
1540 	    pSRB->AdaptStatus = H_SEL_TIMEOUT;
1541 	    pSRB->TargetStatus = 0;
1542 	    pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0);
1543 	    /* Devices are removed below ... */
1544 	}
1545 	else if (status_byte(status) == BUSY &&
1546 		 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
1547 		 pACB->scan_devices)
1548 	{
1549 	    pSRB->AdaptStatus = 0;
1550 	    pSRB->TargetStatus = status;
1551 	    pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
1552 	}
1553 	else
1554 	{   /* Another error */
1555 	    pSRB->AdaptStatus = 0;
1556 	    if( pSRB->RetryCnt )
1557 	    {	/* Retry */
1558 		//printk ("DC390: retry\n");
1559 		pSRB->RetryCnt--;
1560 		pSRB->TargetStatus = 0;
1561 		pSRB->SGIndex = 0;
1562 		pSRB->TotalXferredLen = 0;
1563 		pSRB->SGToBeXferLen = 0;
1564 		if( pcmd->use_sg )
1565 		    pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1566 		else if( pcmd->request_buffer )
1567 		{
1568 		    pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1569 		    pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1570 		    pSRB->Segmentx.length = pcmd->request_bufflen;
1571 		}
1572 		if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1573 		    dc390_Going_to_Waiting ( pDCB, pSRB );
1574 		    dc390_waiting_timer (pACB, HZ/5);
1575 		}
1576       		return;
1577 	    }
1578 	    else
1579 	    {	/* Report error */
1580 	      //pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status);
1581 	      SET_RES_DID(pcmd->result,DID_ERROR);
1582 	      SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1583 	      SET_RES_TARGET(pcmd->result,status);
1584 	    }
1585 	}
1586     }
1587     else
1588     {	/*  Target status == 0 */
1589 	status = pSRB->AdaptStatus;
1590 	if(status & H_OVER_UNDER_RUN)
1591 	{
1592 	    pSRB->TargetStatus = 0;
1593 	    SET_RES_DID(pcmd->result,DID_OK);
1594 	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1595 	}
1596 	else if( pSRB->SRBStatus & PARITY_ERROR)
1597 	{
1598 	    //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
1599 	    SET_RES_DID(pcmd->result,DID_PARITY);
1600 	    SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1601 	}
1602 	else		       /* No error */
1603 	{
1604 	    pSRB->AdaptStatus = 0;
1605 	    pSRB->TargetStatus = 0;
1606 	    SET_RES_DID(pcmd->result,DID_OK);
1607 	}
1608     }
1609     if ((pcmd->result & RES_DID) == 0 &&
1610 	pcmd->cmnd[0] == INQUIRY &&
1611 	pcmd->cmnd[2] == 0 &&
1612 	pcmd->request_bufflen >= 8 &&
1613 	ptr &&
1614 	(ptr->Vers & 0x07) >= 2)
1615 	    pDCB->Inquiry7 = ptr->Flags;
1616 
1617 ckc_e:
1618     if( pACB->scan_devices )
1619     {
1620 	if( pcmd->cmnd[0] == TEST_UNIT_READY ||
1621 	    pcmd->cmnd[0] == INQUIRY)
1622 	{
1623 #ifdef DC390_DEBUG0
1624 	    printk (KERN_INFO "DC390: %s: result: %08x",
1625 		    (pcmd->cmnd[0] == INQUIRY? "INQUIRY": "TEST_UNIT_READY"),
1626 		    pcmd->result);
1627 	    if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n",
1628 				   pcmd->sense_buffer[0], pcmd->sense_buffer[1],
1629 				   pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
1630 	    else printk ("\n");
1631 #endif
1632 	    if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) ||
1633 	       ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 &&
1634 		(pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR )
1635 	    {
1636 	       /* device not present: remove */
1637 	       //dc390_Going_remove (pDCB, pSRB);
1638 	       dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
1639 
1640 	       if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1641 		  ((pcmd->lun == 0) || (pcmd->lun == pACB->pScsiHost->max_lun - 1)) )
1642 		 pACB->scan_devices = 0;
1643 	    }
1644 	    else
1645 	    {
1646 	        /* device present: add */
1647 		if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1648 		    (pcmd->lun == pACB->pScsiHost->max_lun - 1) )
1649 		    pACB->scan_devices = END_SCAN ;
1650 	        /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */
1651 	    }
1652 	}
1653     }
1654 
1655     //if( pSRB->pcmd->cmnd[0] == INQUIRY &&
1656     //  (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) )
1657     if( pcmd->cmnd[0] == INQUIRY &&
1658 	(pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
1659      {
1660 	if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV && !DCB_removed)
1661 	  {
1662 	     //printk ("DC390: Type = nodev! (%02i-%i)\n", pcmd->target, pcmd->lun);
1663 	     /* device not present: remove */
1664 	     //dc390_Going_remove (pDCB, pSRB);
1665 	     dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
1666 	  }
1667 	else
1668 	  {
1669 	     /* device found: add */
1670 	     dc390_add_dev (pACB, pDCB, ptr);
1671 	     if (pACB->scan_devices) pACB->DeviceCnt++;
1672 	  }
1673 	if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1674 	    (pcmd->lun == pACB->pScsiHost->max_lun - 1) )
1675 	  pACB->scan_devices = 0;
1676      };
1677 
1678 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30)
1679     pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
1680 #endif
1681 
1682     if (!DCB_removed) dc390_Going_remove (pDCB, pSRB);
1683     /* Add to free list */
1684     dc390_Free_insert (pACB, pSRB);
1685 
1686     DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid);)
1687     DC390_UNLOCK_ACB_NI;
1688     pcmd->scsi_done (pcmd);
1689     DC390_LOCK_ACB_NI;
1690 
1691     dc390_Query_to_Waiting (pACB);
1692     dc390_Waiting_process (pACB);
1693     return;
1694 }
1695 
1696 
1697 /* Remove all SRBs from Going list and inform midlevel */
1698 void
dc390_DoingSRB_Done(PACB pACB,PSCSICMD cmd)1699 dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd )
1700 {
1701     PDCB   pDCB, pdcb;
1702     PSRB   psrb, psrb2;
1703     UCHAR  i;
1704     PSCSICMD pcmd;
1705 
1706     pDCB = pACB->pLinkDCB;
1707     pdcb = pDCB;
1708     if (! pdcb) return;
1709     do
1710     {
1711 	psrb = pdcb->pGoingSRB;
1712 	for( i=0; i<pdcb->GoingSRBCnt; i++)
1713 	{
1714 	    psrb2 = psrb->pNextSRB;
1715 	    pcmd = psrb->pcmd;
1716 	    dc390_Free_insert (pACB, psrb);
1717 #ifndef USE_NEW_EH
1718 	    /* New EH will crash on being given timed out cmnds */
1719 	    if (pcmd == cmd)
1720 		pcmd->result = MK_RES(0,DID_ABORT,0,0);
1721 	    else
1722 		pcmd->result = MK_RES(0,DID_RESET,0,0);
1723 
1724 /*	    ReleaseSRB( pDCB, pSRB ); */
1725 
1726 	    DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid);)
1727 	    DC390_UNLOCK_ACB_NI;
1728 	    pcmd->scsi_done( pcmd );
1729 	    DC390_LOCK_ACB_NI;
1730 #endif
1731 	    psrb  = psrb2;
1732 	}
1733 	pdcb->GoingSRBCnt = 0;;
1734 	pdcb->pGoingSRB = NULL;
1735 	pdcb->TagMask = 0;
1736 	pdcb = pdcb->pNextDCB;
1737     } while( pdcb != pDCB );
1738     dc390_Query_to_Waiting (pACB);
1739 }
1740 
1741 
1742 static void
dc390_ResetSCSIBus(PACB pACB)1743 dc390_ResetSCSIBus( PACB pACB )
1744 {
1745     //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1746     //udelay (250);
1747     //DC390_write8 (ScsiCmd, NOP_CMD);
1748 
1749     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1750     DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1751     DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
1752     pACB->Connected = 0;
1753 
1754     return;
1755 }
1756 
1757 static void
dc390_ScsiRstDetect(PACB pACB)1758 dc390_ScsiRstDetect( PACB pACB )
1759 {
1760     printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
1761     //DEBUG0(printk(KERN_INFO "RST_DETECT,");)
1762 
1763     if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
1764     DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1765     /* Unlock before ? */
1766     /* delay half a second */
1767     udelay (1000);
1768     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1769     pACB->pScsiHost->last_reset = jiffies + 5*HZ/2
1770 		    + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
1771     pACB->Connected = 0;
1772 
1773     if( pACB->ACBFlag & RESET_DEV )
1774 	pACB->ACBFlag |= RESET_DONE;
1775     else
1776     {   /* Reset was issued by sb else */
1777 	pACB->ACBFlag |= RESET_DETECT;
1778 
1779 	dc390_ResetDevParam( pACB );
1780 	dc390_DoingSRB_Done( pACB, 0 );
1781 	//dc390_RecoverSRB( pACB );
1782 	pACB->pActiveDCB = NULL;
1783 	pACB->ACBFlag = 0;
1784 	dc390_Waiting_process( pACB );
1785     }
1786     return;
1787 }
1788 
1789