~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/scsi/scsiiom.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.