MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / scsi / scsiiom.c
blobbc690794367738eb29cc003948f46a0db2525c71
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 static void __inline__
9 dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
11 if (pSRB->TagNumber < 255) {
12 pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */
13 pSRB->TagNumber = 255;
18 static u8
19 dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
21 u8 cmd; u8 disc_allowed, try_sync_nego;
23 pSRB->ScsiPhase = SCSI_NOP0;
25 if (pACB->Connected)
27 // Should not happen normally
28 printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n",
29 pSRB->SRBState, pSRB->SRBFlag);
30 pSRB->SRBState = SRB_READY;
31 pACB->SelConn++;
32 return 1;
34 if (time_before (jiffies, pACB->pScsiHost->last_reset))
36 DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
37 return 1;
39 /* KG: Moved pci mapping here */
40 dc390_pci_map(pSRB);
41 /* TODO: error handling */
42 DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
43 DC390_write8 (Sync_Period, pDCB->SyncPeriod);
44 DC390_write8 (Sync_Offset, pDCB->SyncOffset);
45 DC390_write8 (CtrlReg1, pDCB->CtrlR1);
46 DC390_write8 (CtrlReg3, pDCB->CtrlR3);
47 DC390_write8 (CtrlReg4, pDCB->CtrlR4);
48 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); /* Flush FIFO */
49 DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
50 pSRB->pcmd->cmnd[0], pDCB->SyncMode));
51 disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
52 try_sync_nego = 0;
53 /* Don't disconnect on AUTO_REQSENSE, cause it might be an
54 * Contingent Allegiance Condition (6.6), where no tags should be used.
55 * All other have to be allowed to disconnect to prevent Incorrect
56 * Initiator Connection (6.8.2/6.5.2) */
57 /* Changed KG, 99/06/06 */
58 if( /*(((pSRB->pcmd->cmnd[0] == INQUIRY) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
59 * (pSRB->pcmd->cmnd[0] == TEST_UNIT_READY)) && pACB->scan_devices)
60 ||*/ (pSRB->SRBFlag & AUTO_REQSENSE) )
61 disc_allowed = 0;
62 if ( (pDCB->SyncMode & SYNC_ENABLE) && (pDCB->TargetLUN == 0) && (pDCB->Inquiry7 & 0x10) &&
63 ( ( ( (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) )
64 && !(pDCB->SyncMode & SYNC_NEGO_DONE) ) || (pSRB->pcmd->cmnd[0] == INQUIRY) ) )
65 try_sync_nego = 1;
67 pSRB->MsgCnt = 0; cmd = SEL_W_ATN;
68 DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
69 /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
70 if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed)
72 u8 tag_no = 0;
73 while ((1 << tag_no) & pDCB->TagMask) tag_no++;
74 if (tag_no >= sizeof (pDCB->TagMask)*8 || tag_no >= pDCB->MaxCommand) {
75 printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->TargetID, pDCB->TargetLUN);
76 return 1;
77 //goto no_tag;
79 DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG);
80 pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no;
81 DC390_write8 (ScsiFifo, tag_no);
82 DEBUG1(printk (KERN_DEBUG "DC390: Select w/DisCn for Cmd %li (SRB %p), Using Tag %02x\n", pSRB->pcmd->pid, pSRB, tag_no));
83 cmd = SEL_W_ATN3;
85 else /* No TagQ */
87 // no_tag:
88 DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB));
91 pSRB->SRBState = SRB_START_;
93 if (try_sync_nego)
95 u8 Sync_Off = pDCB->SyncOffset;
96 DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
97 pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
98 pSRB->MsgOutBuf[1] = 3;
99 pSRB->MsgOutBuf[2] = EXTENDED_SDTR;
100 pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
101 if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET;
102 pSRB->MsgOutBuf[4] = Sync_Off;
103 pSRB->MsgCnt = 5;
104 //pSRB->SRBState = SRB_MSGOUT_;
105 pSRB->SRBState |= DO_SYNC_NEGO;
106 cmd = SEL_W_ATN_STOP;
109 /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
110 if (cmd != SEL_W_ATN_STOP)
112 if( pSRB->SRBFlag & AUTO_REQSENSE )
114 DC390_write8 (ScsiFifo, REQUEST_SENSE);
115 DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
116 DC390_write8 (ScsiFifo, 0);
117 DC390_write8 (ScsiFifo, 0);
118 DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
119 DC390_write8 (ScsiFifo, 0);
120 DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
122 else /* write cmnd to bus */
124 u8 *ptr; u8 i;
125 ptr = (u8 *) pSRB->pcmd->cmnd;
126 for (i=0; i<pSRB->pcmd->cmd_len; i++)
127 DC390_write8 (ScsiFifo, *(ptr++));
130 DEBUG0(if (pACB->pActiveDCB) \
131 printk (KERN_WARNING "DC390: ActiveDCB != 0\n"));
132 DEBUG0(if (pDCB->pActiveSRB) \
133 printk (KERN_WARNING "DC390: ActiveSRB != 0\n"));
134 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
135 if (DC390_read8 (Scsi_Status) & INTERRUPT)
137 dc390_freetag (pDCB, pSRB);
138 DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n",
139 pSRB->pcmd->pid, pSRB->pcmd->device->id, pSRB->pcmd->device->lun));
140 pSRB->SRBState = SRB_READY;
141 //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
142 pACB->SelLost++;
143 return 1;
145 DC390_write8 (ScsiCmd, cmd);
146 pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB;
147 pACB->Connected = 1;
148 pSRB->ScsiPhase = SCSI_NOP1;
149 return 0;
152 //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
153 #define DMA_INT 0
155 #if DMA_INT
156 /* This is similar to AM53C974.c ... */
157 static u8
158 dc390_dma_intr (struct dc390_acb* pACB)
160 struct dc390_srb* pSRB;
161 u8 dstate;
162 DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev);
164 DEBUG0(pci_read_config_word(pdev, PCI_STATUS, &pstate));
165 DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
166 { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
167 pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));});
169 dstate = DC390_read8 (DMA_Status);
171 if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
172 else pSRB = pACB->pActiveDCB->pActiveSRB;
174 if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
176 printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
177 return dstate;
179 if (dstate & DMA_XFER_DONE)
181 u32 residual, xferCnt; int ctr = 6000000;
182 if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
186 DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n"));
187 dstate = DC390_read8 (DMA_Status);
188 residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
189 DC390_read8 (CtcReg_High) << 16;
190 residual += DC390_read8 (Current_Fifo) & 0x1f;
191 } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
192 if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
193 /* residual = ... */
195 else
196 residual = 0;
198 /* ??? */
200 xferCnt = pSRB->SGToBeXferLen - residual;
201 pSRB->SGBusAddr += xferCnt;
202 pSRB->TotalXferredLen += xferCnt;
203 pSRB->SGToBeXferLen = residual;
204 # ifdef DC390_DEBUG0
205 printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n",
206 (unsigned int)residual, (unsigned int)xferCnt);
207 # endif
209 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
211 dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
212 return dstate;
214 #endif
217 static void __inline__
218 dc390_InvalidCmd(struct dc390_acb* pACB)
220 if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
221 DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
225 static irqreturn_t __inline__
226 DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
228 struct dc390_acb *pACB, *pACB2;
229 struct dc390_dcb *pDCB;
230 struct dc390_srb *pSRB;
231 u8 sstatus=0;
232 u8 phase;
233 void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
234 u8 istate, istatus;
235 #if DMA_INT
236 u8 dstatus;
237 #endif
239 pACB = (struct dc390_acb*)dev_id;
240 for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB);
241 if (!pACB2)
243 printk ("DC390: IRQ called with foreign dev_id %p!\n", pACB);
244 return IRQ_NONE;
247 sstatus = DC390_read8 (Scsi_Status);
248 if( !(sstatus & INTERRUPT) )
249 return IRQ_NONE;
251 DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
253 #if DMA_INT
254 spin_lock_irq(pACB->pScsiHost->host_lock);
255 dstatus = dc390_dma_intr (pACB);
256 spin_unlock_irq(pACB->pScsiHost->host_lock);
258 DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus));
259 if (! (dstatus & SCSI_INTERRUPT))
261 DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"));
262 return IRQ_NONE;
264 #else
265 //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
266 //dstatus = DC390_read8 (DMA_Status);
267 //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
268 #endif
270 spin_lock_irq(pACB->pScsiHost->host_lock);
272 istate = DC390_read8 (Intern_State);
273 istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
275 DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
276 dc390_laststatus &= ~0x00ffffff;
277 dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
279 if (sstatus & ILLEGAL_OP_ERR)
281 printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
282 dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
285 else if (istatus & INVALID_CMD)
287 printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus);
288 dc390_InvalidCmd( pACB );
289 goto unlock;
292 if (istatus & SCSI_RESET)
294 dc390_ScsiRstDetect( pACB );
295 goto unlock;
298 if (istatus & DISCONNECTED)
300 dc390_Disconnect( pACB );
301 goto unlock;
304 if (istatus & RESELECTED)
306 dc390_Reselect( pACB );
307 goto unlock;
310 else if (istatus & (SELECTED | SEL_ATTENTION))
312 printk (KERN_ERR "DC390: Target mode not supported!\n");
313 goto unlock;
316 if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
318 pDCB = pACB->pActiveDCB;
319 if (!pDCB)
321 printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
322 goto unlock;
324 pSRB = pDCB->pActiveSRB;
325 if( pDCB->DCBFlag & ABORT_DEV_ )
326 dc390_EnableMsgOut_Abort (pACB, pSRB);
328 phase = pSRB->ScsiPhase;
329 DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
330 stateV = (void *) dc390_phase0[phase];
331 ( *stateV )( pACB, pSRB, &sstatus );
333 pSRB->ScsiPhase = sstatus & 7;
334 phase = (u8) sstatus & 7;
335 DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
336 stateV = (void *) dc390_phase1[phase];
337 ( *stateV )( pACB, pSRB, &sstatus );
340 unlock:
341 spin_unlock_irq(pACB->pScsiHost->host_lock);
342 return IRQ_HANDLED;
345 static irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
347 irqreturn_t ret;
348 DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
349 /* Locking is done in DC390_Interrupt */
350 ret = DC390_Interrupt(irq, dev_id, regs);
351 DEBUG1(printk (".. IRQ returned\n"));
352 return ret;
355 static void
356 dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
358 u8 sstatus;
359 struct scatterlist *psgl;
360 u32 ResidCnt, xferCnt;
361 u8 dstate = 0;
363 sstatus = *psstatus;
365 if( !(pSRB->SRBState & SRB_XFERPAD) )
367 if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
368 pSRB->SRBStatus |= PARITY_ERROR;
370 if( sstatus & COUNT_2_ZERO )
372 unsigned long timeout = jiffies + HZ;
374 /* Function called from the ISR with the host_lock held and interrupts disabled */
375 if (pSRB->SGToBeXferLen)
376 while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
377 spin_unlock_irq(pACB->pScsiHost->host_lock);
378 udelay(50);
379 spin_lock_irq(pACB->pScsiHost->host_lock);
381 if (!time_before(jiffies, timeout))
382 printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
383 DC390_read32 (DMA_Wk_ByteCntr));
384 dc390_laststatus &= ~0xff000000;
385 dc390_laststatus |= dstate << 24;
386 pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
387 pSRB->SGIndex++;
388 if( pSRB->SGIndex < pSRB->SGcount )
390 pSRB->pSegmentList++;
391 psgl = pSRB->pSegmentList;
393 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
394 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
396 else
397 pSRB->SGToBeXferLen = 0;
399 else
401 ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f;
402 ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16;
403 ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8;
404 ResidCnt += (u32) DC390_read8 (CtcReg_Low);
406 xferCnt = pSRB->SGToBeXferLen - ResidCnt;
407 pSRB->SGBusAddr += xferCnt;
408 pSRB->TotalXferredLen += xferCnt;
409 pSRB->SGToBeXferLen = ResidCnt;
412 if ((*psstatus & 7) != SCSI_DATA_OUT)
414 DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
415 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
419 static void
420 dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
422 u8 sstatus, residual, bval;
423 struct scatterlist *psgl;
424 u32 ResidCnt, i;
425 unsigned long xferCnt;
426 u8 *ptr;
428 sstatus = *psstatus;
430 if( !(pSRB->SRBState & SRB_XFERPAD) )
432 if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
433 pSRB->SRBStatus |= PARITY_ERROR;
435 if( sstatus & COUNT_2_ZERO )
437 int dstate = 0;
438 unsigned long timeout = jiffies + HZ;
440 /* Function called from the ISR with the host_lock held and interrupts disabled */
441 if (pSRB->SGToBeXferLen)
442 while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
443 spin_unlock_irq(pACB->pScsiHost->host_lock);
444 udelay(50);
445 spin_lock_irq(pACB->pScsiHost->host_lock);
447 if (!time_before(jiffies, timeout)) {
448 printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
449 DC390_read32 (DMA_Wk_ByteCntr));
450 printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
452 dc390_laststatus &= ~0xff000000;
453 dc390_laststatus |= dstate << 24;
454 DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
455 + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \
456 + ((unsigned long) DC390_read8 (CtcReg_Low)));
457 DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen));
459 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
461 pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
462 pSRB->SGIndex++;
463 if( pSRB->SGIndex < pSRB->SGcount )
465 pSRB->pSegmentList++;
466 psgl = pSRB->pSegmentList;
468 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
469 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
471 else
472 pSRB->SGToBeXferLen = 0;
474 else /* phase changed */
476 residual = 0;
477 bval = DC390_read8 (Current_Fifo);
478 while( bval & 0x1f )
480 DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
481 if( (bval & 0x1f) == 1 )
483 for(i=0; i < 0x100; i++)
485 bval = DC390_read8 (Current_Fifo);
486 if( !(bval & 0x1f) )
487 goto din_1;
488 else if( i == 0x0ff )
490 residual = 1; /* ;1 residual byte */
491 goto din_1;
495 else
496 bval = DC390_read8 (Current_Fifo);
498 din_1:
499 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
500 for (i = 0xa000; i; i--)
502 bval = DC390_read8 (DMA_Status);
503 if (bval & BLAST_COMPLETE)
504 break;
506 /* It seems a DMA Blast abort isn't that bad ... */
507 if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
508 //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
509 dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
511 DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
512 ResidCnt = (u32) DC390_read8 (CtcReg_High);
513 ResidCnt <<= 8;
514 ResidCnt |= (u32) DC390_read8 (CtcReg_Mid);
515 ResidCnt <<= 8;
516 ResidCnt |= (u32) DC390_read8 (CtcReg_Low);
518 xferCnt = pSRB->SGToBeXferLen - ResidCnt;
519 pSRB->SGBusAddr += xferCnt;
520 pSRB->TotalXferredLen += xferCnt;
521 pSRB->SGToBeXferLen = ResidCnt;
523 if( residual )
525 bval = DC390_read8 (ScsiFifo); /* get one residual byte */
526 ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr );
527 *ptr = bval;
528 pSRB->SGBusAddr++; xferCnt++;
529 pSRB->TotalXferredLen++;
530 pSRB->SGToBeXferLen--;
532 DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
533 pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
537 if ((*psstatus & 7) != SCSI_DATA_IN)
539 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
540 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
544 static void
545 dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
549 static void
550 dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
553 pSRB->TargetStatus = DC390_read8 (ScsiFifo);
554 //udelay (1);
555 pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
557 *psstatus = SCSI_NOP0;
558 pSRB->SRBState = SRB_COMPLETED;
559 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
562 static void
563 dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
565 if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
566 *psstatus = SCSI_NOP0;
567 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
571 static void __inline__
572 dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
574 DC390_write8 (Sync_Period, pDCB->SyncPeriod);
575 DC390_write8 (Sync_Offset, pDCB->SyncOffset);
576 DC390_write8 (CtrlReg3, pDCB->CtrlR3);
577 DC390_write8 (CtrlReg4, pDCB->CtrlR4);
578 dc390_SetXferRate (pACB, pDCB);
582 #ifdef DC390_DEBUG0
583 static void
584 dc390_printMsg (u8 *MsgBuf, u8 len)
586 int i;
587 printk (" %02x", MsgBuf[0]);
588 for (i = 1; i < len; i++)
589 printk (" %02x", MsgBuf[i]);
590 printk ("\n");
592 #endif
594 #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
596 /* reject_msg */
597 static void __inline__
598 dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
600 pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
601 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
602 DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
605 /* abort command */
606 static void
607 dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
609 pSRB->MsgOutBuf[0] = ABORT;
610 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
611 pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
614 static struct dc390_srb*
615 dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, u8 tag)
617 struct dc390_srb* lastSRB = pDCB->pGoingLast;
618 struct dc390_srb* pSRB = pDCB->pGoingSRB;
620 if (pSRB)
622 for( ;pSRB ; )
624 if (pSRB->TagNumber == tag) break;
625 if (pSRB == lastSRB) goto mingx0;
626 pSRB = pSRB->pNextSRB;
629 if( pDCB->DCBFlag & ABORT_DEV_ )
631 pSRB->SRBState = SRB_ABORT_SENT;
632 dc390_EnableMsgOut_Abort( pACB, pSRB );
635 if( !(pSRB->SRBState & SRB_DISCONNECT) )
636 goto mingx0;
638 pDCB->pActiveSRB = pSRB;
639 pSRB->SRBState = SRB_DATA_XFER;
641 else
643 mingx0:
644 pSRB = pACB->pTmpSRB;
645 pSRB->SRBState = SRB_UNEXPECT_RESEL;
646 pDCB->pActiveSRB = pSRB;
647 pSRB->MsgOutBuf[0] = ABORT_TAG;
648 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
650 return pSRB;
654 /* set async transfer mode */
655 static void
656 dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
658 struct dc390_dcb* pDCB = pSRB->pSRBDCB;
659 if (!(pSRB->SRBState & DO_SYNC_NEGO))
660 printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
661 pSRB->SRBState &= ~DO_SYNC_NEGO;
662 pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
663 pDCB->SyncPeriod = 0;
664 pDCB->SyncOffset = 0;
665 //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
666 pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
667 pDCB->CtrlR4 &= 0x3f;
668 pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
669 dc390_reprog (pACB, pDCB);
672 /* set sync transfer mode */
673 static void
674 dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
676 u8 bval;
677 u16 wval, wval1;
678 struct dc390_dcb* pDCB = pSRB->pSRBDCB;
679 u8 oldsyncperiod = pDCB->SyncPeriod;
680 u8 oldsyncoffset = pDCB->SyncOffset;
682 if (!(pSRB->SRBState & DO_SYNC_NEGO))
684 printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
685 pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
687 /* reject */
688 //dc390_MsgIn_reject (pACB, pSRB);
689 //return dc390_MsgIn_set_async (pACB, pSRB);
691 /* Reply with corrected SDTR Message */
692 if (pSRB->MsgInBuf[4] > 15)
694 printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
695 pSRB->MsgInBuf[4] = 15;
697 if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
699 printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
700 pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
702 memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
703 pSRB->MsgCnt = 5;
704 DC390_ENABLE_MSGOUT;
707 pSRB->SRBState &= ~DO_SYNC_NEGO;
708 pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
709 pDCB->SyncOffset &= 0x0f0;
710 pDCB->SyncOffset |= pSRB->MsgInBuf[4];
711 pDCB->NegoPeriod = pSRB->MsgInBuf[3];
713 wval = (u16) pSRB->MsgInBuf[3];
714 wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
715 if( (wval1 * 25) != wval) wval1++;
716 bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
718 pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
719 if (pACB->glitch_cfg != NS_TO_GLITCH(0))
720 pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
721 else
722 pDCB->CtrlR4 |= NS_TO_GLITCH(0);
723 if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
725 if (wval1 >= 8)
727 wval1--; /* Timing computation differs by 1 from FAST_SCSI */
728 bval = FAST_CLK; /* fast clock / normal scsi */
729 pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
732 pDCB->CtrlR3 = bval;
733 pDCB->SyncPeriod = (u8)wval1;
735 if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
737 if (! (bval & FAST_SCSI)) wval1++;
738 printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
739 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
742 dc390_reprog (pACB, pDCB);
746 /* handle RESTORE_PTR */
747 /* I presume, this command is already mapped, so, have to remap. */
748 static void
749 dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
751 struct scsi_cmnd *pcmd = pSRB->pcmd;
752 struct scatterlist *psgl;
753 pSRB->TotalXferredLen = 0;
754 pSRB->SGIndex = 0;
755 if (pcmd->use_sg) {
756 pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
757 psgl = pSRB->pSegmentList;
758 //dc390_pci_sync(pSRB);
760 while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
762 pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
763 pSRB->SGIndex++;
764 if( pSRB->SGIndex < pSRB->SGcount )
766 pSRB->pSegmentList++;
767 psgl = pSRB->pSegmentList;
768 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
769 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
771 else
772 pSRB->SGToBeXferLen = 0;
774 pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
775 pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
776 printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
777 pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
779 } else if(pcmd->request_buffer) {
780 //dc390_pci_sync(pSRB);
782 sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr;
783 pSRB->SGcount = 1;
784 pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
785 } else {
786 pSRB->SGcount = 0;
787 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
790 pSRB->TotalXferredLen = pSRB->Saved_Ptr;
794 /* According to the docs, the AM53C974 reads the message and
795 * generates a Successful Operation IRQ before asserting ACK for
796 * the last byte (how does it know whether it's the last ?) */
797 /* The old code handled it in another way, indicating, that on
798 * every message byte an IRQ is generated and every byte has to
799 * be manually ACKed. Hmmm ? (KG, 98/11/28) */
800 /* The old implementation was correct. Sigh! */
802 /* Check if the message is complete */
803 static u8 __inline__
804 dc390_MsgIn_complete (u8 *msgbuf, u32 len)
806 if (*msgbuf == EXTENDED_MESSAGE)
808 if (len < 2) return 0;
809 if (len < msgbuf[1] + 2) return 0;
811 else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
812 if (len < 2) return 0;
813 return 1;
818 /* read and eval received messages */
819 static void
820 dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
822 struct dc390_dcb* pDCB = pACB->pActiveDCB;
824 /* Read the msg */
826 pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
827 //pSRB->SRBState = 0;
829 /* Msg complete ? */
830 if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
832 DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
833 /* Now eval the msg */
834 switch (pSRB->MsgInBuf[0])
836 case DISCONNECT:
837 pSRB->SRBState = SRB_DISCONNECT; break;
839 case SIMPLE_QUEUE_TAG:
840 case HEAD_OF_QUEUE_TAG:
841 case ORDERED_QUEUE_TAG:
842 pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
843 break;
845 case MESSAGE_REJECT:
846 DC390_write8 (ScsiCmd, RESET_ATN_CMD);
847 pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
848 if( pSRB->SRBState & DO_SYNC_NEGO)
849 dc390_MsgIn_set_async (pACB, pSRB);
850 break;
852 case EXTENDED_MESSAGE:
853 /* reject every extended msg but SDTR */
854 if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
855 dc390_MsgIn_reject (pACB, pSRB);
856 else
858 if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
859 dc390_MsgIn_set_async (pACB, pSRB);
860 else
861 dc390_MsgIn_set_sync (pACB, pSRB);
864 // nothing has to be done
865 case COMMAND_COMPLETE: break;
867 // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
868 // scsi command. Thanks, Gerard, for pointing it out.
869 case SAVE_POINTERS:
870 pSRB->Saved_Ptr = pSRB->TotalXferredLen;
871 break;
872 // The device might want to restart transfer with a RESTORE
873 case RESTORE_POINTERS:
874 DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n"));
875 dc390_restore_ptr (pACB, pSRB);
876 break;
878 // reject unknown messages
879 default: dc390_MsgIn_reject (pACB, pSRB);
882 /* Clear counter and MsgIn state */
883 pSRB->SRBState &= ~SRB_MSGIN;
884 pACB->MsgLen = 0;
887 *psstatus = SCSI_NOP0;
888 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
889 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
893 static void
894 dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
896 struct scatterlist *psgl;
897 unsigned long lval;
898 struct dc390_dcb* pDCB = pACB->pActiveDCB;
900 if (pSRB == pACB->pTmpSRB)
902 if (pDCB)
903 printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
904 else
905 printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
907 /* Try to recover - some broken disks react badly to tagged INQUIRY */
908 if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
909 pSRB = pDCB->pGoingSRB;
910 pDCB->pActiveSRB = pSRB;
911 } else {
912 pSRB->pSRBDCB = pDCB;
913 dc390_EnableMsgOut_Abort(pACB, pSRB);
914 if (pDCB)
915 pDCB->DCBFlag |= ABORT_DEV;
916 return;
920 if( pSRB->SGIndex < pSRB->SGcount )
922 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
923 if( !pSRB->SGToBeXferLen )
925 psgl = pSRB->pSegmentList;
926 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
927 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
928 DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
930 lval = pSRB->SGToBeXferLen;
931 DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
932 DC390_write8 (CtcReg_Low, (u8) lval);
933 lval >>= 8;
934 DC390_write8 (CtcReg_Mid, (u8) lval);
935 lval >>= 8;
936 DC390_write8 (CtcReg_High, (u8) lval);
938 DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
939 DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
941 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
942 pSRB->SRBState = SRB_DATA_XFER;
944 DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
946 DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
947 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
948 //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
949 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
951 else /* xfer pad */
953 if( pSRB->SGcount )
955 pSRB->AdaptStatus = H_OVER_UNDER_RUN;
956 pSRB->SRBStatus |= OVER_RUN;
957 DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
959 DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
960 DC390_write8 (CtcReg_Low, 0);
961 DC390_write8 (CtcReg_Mid, 0);
962 DC390_write8 (CtcReg_High, 0);
964 pSRB->SRBState |= SRB_XFERPAD;
965 DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
967 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
968 DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
974 static void
975 dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
977 dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
980 static void
981 dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
983 dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
986 static void
987 dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
989 struct dc390_dcb* pDCB;
990 u8 i, cnt;
991 u8 *ptr;
993 DC390_write8 (ScsiCmd, RESET_ATN_CMD);
994 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
995 if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
997 cnt = (u8) pSRB->pcmd->cmd_len;
998 ptr = (u8 *) pSRB->pcmd->cmnd;
999 for(i=0; i < cnt; i++)
1000 DC390_write8 (ScsiFifo, *(ptr++));
1002 else
1004 u8 bval = 0;
1005 DC390_write8 (ScsiFifo, REQUEST_SENSE);
1006 pDCB = pACB->pActiveDCB;
1007 DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
1008 DC390_write8 (ScsiFifo, bval);
1009 DC390_write8 (ScsiFifo, bval);
1010 DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
1011 DC390_write8 (ScsiFifo, bval);
1012 DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
1014 pSRB->SRBState = SRB_COMMAND;
1015 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1018 static void
1019 dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1021 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1022 pSRB->SRBState = SRB_STATUS;
1023 DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
1024 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1027 static void
1028 dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1030 u8 bval, i, cnt;
1031 u8 *ptr;
1032 struct dc390_dcb* pDCB;
1034 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1035 pDCB = pACB->pActiveDCB;
1036 if( !(pSRB->SRBState & SRB_MSGOUT) )
1038 cnt = pSRB->MsgCnt;
1039 if( cnt )
1041 ptr = (u8 *) pSRB->MsgOutBuf;
1042 for(i=0; i < cnt; i++)
1043 DC390_write8 (ScsiFifo, *(ptr++));
1044 pSRB->MsgCnt = 0;
1045 if( (pDCB->DCBFlag & ABORT_DEV_) &&
1046 (pSRB->MsgOutBuf[0] == ABORT) )
1047 pSRB->SRBState = SRB_ABORT_SENT;
1049 else
1051 bval = ABORT; /* ??? MSG_NOP */
1052 if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
1053 (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
1054 (pSRB->SRBFlag & AUTO_REQSENSE) )
1056 if( pDCB->SyncMode & SYNC_ENABLE )
1057 goto mop1;
1059 DC390_write8 (ScsiFifo, bval);
1061 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1063 else
1065 mop1:
1066 printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
1067 DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
1068 DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */
1069 DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */
1070 DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
1071 if (pDCB->SyncOffset & 0x0f)
1072 DC390_write8 (ScsiFifo, pDCB->SyncOffset);
1073 else
1074 DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
1075 pSRB->SRBState |= DO_SYNC_NEGO;
1076 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1080 static void
1081 dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1083 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1084 if( !(pSRB->SRBState & SRB_MSGIN) )
1086 pSRB->SRBState &= ~SRB_DISCONNECT;
1087 pSRB->SRBState |= SRB_MSGIN;
1089 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1090 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1093 static void
1094 dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1098 static void
1099 dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1104 static void
1105 dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
1107 u8 bval, i, cnt;
1108 struct dc390_dcb* ptr;
1110 if( !(pDCB->TargetLUN) )
1112 if( !pACB->scan_devices )
1114 ptr = pACB->pLinkDCB;
1115 cnt = pACB->DCBCnt;
1116 bval = pDCB->TargetID;
1117 for(i=0; i<cnt; i++)
1119 if( ptr->TargetID == bval )
1121 ptr->SyncPeriod = pDCB->SyncPeriod;
1122 ptr->SyncOffset = pDCB->SyncOffset;
1123 ptr->CtrlR3 = pDCB->CtrlR3;
1124 ptr->CtrlR4 = pDCB->CtrlR4;
1125 ptr->SyncMode = pDCB->SyncMode;
1127 ptr = ptr->pNextDCB;
1131 return;
1135 static void
1136 dc390_Disconnect( struct dc390_acb* pACB )
1138 struct dc390_dcb *pDCB;
1139 struct dc390_srb *pSRB, *psrb;
1140 u8 i, cnt;
1142 DEBUG0(printk(KERN_INFO "DISC,"));
1144 if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
1145 pACB->Connected = 0;
1146 pDCB = pACB->pActiveDCB;
1147 if (!pDCB)
1149 DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
1150 pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
1151 mdelay(400);
1152 DC390_read8 (INT_Status); /* Reset Pending INT */
1153 DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1154 return;
1156 DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1157 pSRB = pDCB->pActiveSRB;
1158 pACB->pActiveDCB = NULL;
1159 pSRB->ScsiPhase = SCSI_NOP0;
1160 if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
1162 pSRB->SRBState = 0;
1163 dc390_Waiting_process ( pACB );
1165 else if( pSRB->SRBState & SRB_ABORT_SENT )
1167 pDCB->TagMask = 0;
1168 pDCB->DCBFlag = 0;
1169 cnt = pDCB->GoingSRBCnt;
1170 pDCB->GoingSRBCnt = 0;
1171 pSRB = pDCB->pGoingSRB;
1172 for( i=0; i < cnt; i++)
1174 psrb = pSRB->pNextSRB;
1175 dc390_Free_insert (pACB, pSRB);
1176 pSRB = psrb;
1178 pDCB->pGoingSRB = NULL;
1179 dc390_Waiting_process (pACB);
1181 else
1183 if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
1184 !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
1185 { /* Selection time out */
1186 if( !(1/*pACB->scan_devices*/) )
1188 pSRB->SRBState = SRB_READY;
1189 dc390_freetag (pDCB, pSRB);
1190 dc390_Going_to_Waiting (pDCB, pSRB);
1191 dc390_waiting_timer (pACB, HZ/5);
1193 else
1195 pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
1196 goto disc1;
1199 else if( pSRB->SRBState & SRB_DISCONNECT )
1201 dc390_Waiting_process ( pACB );
1203 else if( pSRB->SRBState & SRB_COMPLETED )
1205 disc1:
1206 dc390_freetag (pDCB, pSRB);
1207 pDCB->pActiveSRB = NULL;
1208 pSRB->SRBState = SRB_FREE;
1209 dc390_SRBdone( pACB, pDCB, pSRB);
1212 pACB->MsgLen = 0;
1216 static void
1217 dc390_Reselect( struct dc390_acb* pACB )
1219 struct dc390_dcb* pDCB;
1220 struct dc390_srb* pSRB;
1221 u8 id, lun;
1223 DEBUG0(printk(KERN_INFO "RSEL,"));
1224 pACB->Connected = 1;
1225 pDCB = pACB->pActiveDCB;
1226 if( pDCB )
1227 { /* Arbitration lost but Reselection won */
1228 DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
1229 pSRB = pDCB->pActiveSRB;
1230 if( !( pACB->scan_devices ) )
1232 pSRB->SRBState = SRB_READY;
1233 dc390_freetag (pDCB, pSRB);
1234 dc390_Going_to_Waiting ( pDCB, pSRB);
1235 dc390_waiting_timer (pACB, HZ/5);
1238 /* Get ID */
1239 lun = DC390_read8 (ScsiFifo);
1240 DEBUG0(printk ("Dev %02x,", lun));
1241 if (!(lun & (1 << pACB->pScsiHost->this_id)))
1242 printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
1243 else
1244 lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
1245 id = 0; while (lun >>= 1) id++;
1246 /* Get LUN */
1247 lun = DC390_read8 (ScsiFifo);
1248 if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
1249 lun &= 7;
1250 DEBUG0(printk ("(%02i-%i),", id, lun));
1251 pDCB = dc390_findDCB (pACB, id, lun);
1252 if (!pDCB)
1254 printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
1255 id, lun);
1256 return;
1258 pACB->pActiveDCB = pDCB;
1259 /* TagQ: We expect a message soon, so never mind the exact SRB */
1260 if( pDCB->SyncMode & EN_TAG_QUEUEING )
1262 pSRB = pACB->pTmpSRB;
1263 pDCB->pActiveSRB = pSRB;
1265 else
1267 pSRB = pDCB->pActiveSRB;
1268 if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
1270 pSRB= pACB->pTmpSRB;
1271 pSRB->SRBState = SRB_UNEXPECT_RESEL;
1272 printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
1273 id, lun);
1274 pDCB->pActiveSRB = pSRB;
1275 dc390_EnableMsgOut_Abort ( pACB, pSRB );
1277 else
1279 if( pDCB->DCBFlag & ABORT_DEV_ )
1281 pSRB->SRBState = SRB_ABORT_SENT;
1282 printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
1283 id, lun);
1284 dc390_EnableMsgOut_Abort( pACB, pSRB );
1286 else
1287 pSRB->SRBState = SRB_DATA_XFER;
1291 DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
1292 pSRB->ScsiPhase = SCSI_NOP0;
1293 DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
1294 DC390_write8 (Sync_Period, pDCB->SyncPeriod);
1295 DC390_write8 (Sync_Offset, pDCB->SyncOffset);
1296 DC390_write8 (CtrlReg1, pDCB->CtrlR1);
1297 DC390_write8 (CtrlReg3, pDCB->CtrlR3);
1298 DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
1299 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */
1302 static u8 __inline__
1303 dc390_tagq_blacklist (char* name)
1305 u8 i;
1306 for(i=0; i<BADDEVCNT; i++)
1307 if (memcmp (name, dc390_baddevname1[i], 28) == 0)
1308 return 1;
1309 return 0;
1313 static void
1314 dc390_disc_tagq_set (struct dc390_dcb* pDCB, PSCSI_INQDATA ptr)
1316 /* Check for SCSI format (ANSI and Response data format) */
1317 if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 )
1319 if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1320 (pDCB->DevMode & TAG_QUEUEING_) &&
1321 /* ((pDCB->DevType == TYPE_DISK)
1322 || (pDCB->DevType == TYPE_MOD)) &&*/
1323 !dc390_tagq_blacklist (((char*)ptr)+8) )
1325 if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum;
1326 pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */;
1327 //pDCB->TagMask = 0;
1329 else
1330 pDCB->MaxCommand = 1;
1335 static void
1336 dc390_add_dev (struct dc390_acb* pACB, struct dc390_dcb* pDCB, PSCSI_INQDATA ptr)
1338 u8 bval1 = ptr->DevType & SCSI_DEVTYPE;
1339 pDCB->DevType = bval1;
1340 /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
1341 dc390_disc_tagq_set (pDCB, ptr);
1345 static void __inline__
1346 dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
1348 struct scsi_cmnd *pcmd;
1350 pcmd = pSRB->pcmd;
1352 REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
1353 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
1355 pSRB->SRBFlag |= AUTO_REQSENSE;
1356 pSRB->SavedSGCount = pcmd->use_sg;
1357 pSRB->SavedTotXLen = pSRB->TotalXferredLen;
1358 pSRB->AdaptStatus = 0;
1359 pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
1361 /* We are called from SRBdone, original PCI mapping has been removed
1362 * already, new one is set up from StartSCSI */
1363 pSRB->SGIndex = 0;
1365 pSRB->TotalXferredLen = 0;
1366 pSRB->SGToBeXferLen = 0;
1367 if (dc390_StartSCSI(pACB, pDCB, pSRB)) {
1368 dc390_Going_to_Waiting(pDCB, pSRB);
1369 dc390_waiting_timer(pACB, HZ/5);
1374 static void
1375 dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
1377 u8 bval, status, i;
1378 struct scsi_cmnd *pcmd;
1379 PSCSI_INQDATA ptr;
1380 struct scatterlist *ptr2;
1381 unsigned long swlval;
1383 pcmd = pSRB->pcmd;
1384 /* KG: Moved pci_unmap here */
1385 dc390_pci_unmap(pSRB);
1387 status = pSRB->TargetStatus;
1388 if (pcmd->use_sg) {
1389 ptr2 = (struct scatterlist *) (pcmd->request_buffer);
1390 ptr = (PSCSI_INQDATA) (page_address(ptr2->page) + ptr2->offset);
1391 } else
1392 ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1394 DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
1395 pSRB, pcmd->pid));
1396 if(pSRB->SRBFlag & AUTO_REQSENSE)
1397 { /* Last command was a Request Sense */
1398 pSRB->SRBFlag &= ~AUTO_REQSENSE;
1399 pSRB->AdaptStatus = 0;
1400 pSRB->TargetStatus = CHECK_CONDITION << 1;
1402 //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
1403 if (status == (CHECK_CONDITION << 1))
1405 pcmd->result = MK_RES_LNX(0,DID_BAD_TARGET,0,/*CHECK_CONDITION*/0);
1406 goto ckc_e;
1408 if(pSRB->RetryCnt == 0)
1410 //(u32)(pSRB->pcmd->cmnd[0]) = pSRB->Segment0[0];
1411 pSRB->TotalXferredLen = pSRB->SavedTotXLen;
1412 if( (pSRB->TotalXferredLen) &&
1413 (pSRB->TotalXferredLen >= pcmd->underflow) )
1414 SET_RES_DID(pcmd->result,DID_OK)
1415 else
1416 pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
1417 REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->pcmd->cmnd[0],\
1418 (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
1419 goto ckc_e;
1421 else /* Retry */
1423 pSRB->RetryCnt--;
1424 pSRB->AdaptStatus = 0;
1425 pSRB->TargetStatus = 0;
1426 /* Don't retry on TEST_UNIT_READY */
1427 if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
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 (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
1432 goto ckc_e;
1434 SET_RES_DRV(pcmd->result,DRIVER_SENSE);
1435 pcmd->use_sg = pSRB->SavedSGCount;
1436 //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8);
1437 DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
1438 pSRB->SGIndex = 0;
1439 pSRB->TotalXferredLen = 0;
1440 pSRB->SGToBeXferLen = 0;
1442 if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1443 dc390_Going_to_Waiting ( pDCB, pSRB );
1444 dc390_waiting_timer (pACB, HZ/5);
1446 return;
1449 if( status )
1451 if( status_byte(status) == CHECK_CONDITION )
1453 REMOVABLEDEBUG(printk (KERN_INFO "DC390: Check_Condition (Cmd %02x, Id %02x, LUN %02x)\n",\
1454 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
1455 if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
1457 bval = pSRB->SGcount;
1458 swlval = 0;
1459 ptr2 = pSRB->pSegmentList;
1460 for( i=pSRB->SGIndex; i < bval; i++)
1462 swlval += sg_dma_len(ptr2);
1463 ptr2++;
1465 REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
1466 (u32) pSRB->TotalXferredLen, (u32) swlval));
1468 dc390_RequestSense( pACB, pDCB, pSRB );
1469 return;
1471 else if( status_byte(status) == QUEUE_FULL )
1473 bval = (u8) pDCB->GoingSRBCnt;
1474 bval--;
1475 pDCB->MaxCommand = bval;
1476 dc390_freetag (pDCB, pSRB);
1477 dc390_Going_to_Waiting ( pDCB, pSRB );
1478 dc390_waiting_timer (pACB, HZ/5);
1479 pSRB->AdaptStatus = 0;
1480 pSRB->TargetStatus = 0;
1481 return;
1483 else if(status == SCSI_STAT_SEL_TIMEOUT)
1485 pSRB->AdaptStatus = H_SEL_TIMEOUT;
1486 pSRB->TargetStatus = 0;
1487 pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0);
1488 /* Devices are removed below ... */
1490 else if (status_byte(status) == BUSY &&
1491 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
1492 pACB->scan_devices)
1494 pSRB->AdaptStatus = 0;
1495 pSRB->TargetStatus = status;
1496 pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
1498 else
1499 { /* Another error */
1500 pSRB->AdaptStatus = 0;
1501 if( pSRB->RetryCnt )
1502 { /* Retry */
1503 //printk ("DC390: retry\n");
1504 pSRB->RetryCnt--;
1505 pSRB->TargetStatus = 0;
1506 pSRB->SGIndex = 0;
1507 pSRB->TotalXferredLen = 0;
1508 pSRB->SGToBeXferLen = 0;
1509 if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1510 dc390_Going_to_Waiting ( pDCB, pSRB );
1511 dc390_waiting_timer (pACB, HZ/5);
1513 return;
1515 else
1516 { /* Report error */
1517 //pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status);
1518 SET_RES_DID(pcmd->result,DID_ERROR);
1519 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1520 SET_RES_TARGET(pcmd->result,status);
1524 else
1525 { /* Target status == 0 */
1526 status = pSRB->AdaptStatus;
1527 if(status & H_OVER_UNDER_RUN)
1529 pSRB->TargetStatus = 0;
1530 SET_RES_DID(pcmd->result,DID_OK);
1531 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1533 else if( pSRB->SRBStatus & PARITY_ERROR)
1535 //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
1536 SET_RES_DID(pcmd->result,DID_PARITY);
1537 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1539 else /* No error */
1541 pSRB->AdaptStatus = 0;
1542 pSRB->TargetStatus = 0;
1543 SET_RES_DID(pcmd->result,DID_OK);
1546 if ((pcmd->result & RES_DID) == 0 &&
1547 pcmd->cmnd[0] == INQUIRY &&
1548 pcmd->cmnd[2] == 0 &&
1549 pcmd->request_bufflen >= 8 &&
1550 ptr &&
1551 (ptr->Vers & 0x07) >= 2)
1552 pDCB->Inquiry7 = ptr->Flags;
1554 ckc_e:
1555 if( pcmd->cmnd[0] == INQUIRY &&
1556 (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
1558 if ((ptr->DevType & SCSI_DEVTYPE) != TYPE_NODEV)
1560 /* device found: add */
1561 dc390_add_dev (pACB, pDCB, ptr);
1565 pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
1567 dc390_Going_remove (pDCB, pSRB);
1568 /* Add to free list */
1569 dc390_Free_insert (pACB, pSRB);
1571 DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid));
1572 pcmd->scsi_done (pcmd);
1574 dc390_Waiting_process (pACB);
1575 return;
1579 /* Remove all SRBs from Going list and inform midlevel */
1580 static void
1581 dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
1583 struct dc390_dcb *pDCB, *pdcb;
1584 struct dc390_srb *psrb, *psrb2;
1585 u8 i;
1586 struct scsi_cmnd *pcmd;
1588 pDCB = pACB->pLinkDCB;
1589 pdcb = pDCB;
1590 if (! pdcb) return;
1593 psrb = pdcb->pGoingSRB;
1594 for( i=0; i<pdcb->GoingSRBCnt; i++)
1596 psrb2 = psrb->pNextSRB;
1597 pcmd = psrb->pcmd;
1598 dc390_Free_insert (pACB, psrb);
1599 psrb = psrb2;
1601 pdcb->GoingSRBCnt = 0;
1602 pdcb->pGoingSRB = NULL;
1603 pdcb->TagMask = 0;
1604 pdcb = pdcb->pNextDCB;
1605 } while( pdcb != pDCB );
1609 static void
1610 dc390_ResetSCSIBus( struct dc390_acb* pACB )
1612 //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1613 //udelay (250);
1614 //DC390_write8 (ScsiCmd, NOP_CMD);
1616 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1617 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1618 DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
1619 pACB->Connected = 0;
1621 return;
1624 static void
1625 dc390_ScsiRstDetect( struct dc390_acb* pACB )
1627 printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
1628 //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
1630 if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
1631 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1632 /* Unlock before ? */
1633 /* delay half a second */
1634 udelay (1000);
1635 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1636 pACB->pScsiHost->last_reset = jiffies + 5*HZ/2
1637 + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
1638 pACB->Connected = 0;
1640 if( pACB->ACBFlag & RESET_DEV )
1641 pACB->ACBFlag |= RESET_DONE;
1642 else
1643 { /* Reset was issued by sb else */
1644 pACB->ACBFlag |= RESET_DETECT;
1646 dc390_ResetDevParam( pACB );
1647 dc390_DoingSRB_Done( pACB, NULL );
1648 //dc390_RecoverSRB( pACB );
1649 pACB->pActiveDCB = NULL;
1650 pACB->ACBFlag = 0;
1651 dc390_Waiting_process( pACB );
1653 return;