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 $ */
9 dc390_freetag (PDCB pDCB, PSRB pSRB)
11 if (pSRB->TagNumber < 255) {
12 pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */
13 pSRB->TagNumber = 255;
19 dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
21 UCHAR cmd; UCHAR disc_allowed, try_sync_nego;
23 pSRB->ScsiPhase = SCSI_NOP0;
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;
34 if (time_before (jiffies, pACB->pScsiHost->last_reset))
36 DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
39 /* KG: Moved pci mapping here */
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_;
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) )
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) ) )
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)
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);
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));
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_;
95 UCHAR 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;
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 */
125 ptr = (PUCHAR) 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);
145 DC390_write8 (ScsiCmd, cmd);
146 pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB;
148 pSRB->ScsiPhase = SCSI_NOP1;
152 //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
156 /* This is similar to AM53C974.c ... */
158 dc390_dma_intr (PACB pACB)
162 DEBUG0(USHORT pstate;PDEVDECL1);
165 DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate));
166 DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
167 { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
168 PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));});
170 dstate = DC390_read8 (DMA_Status);
172 if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
173 else pSRB = pACB->pActiveDCB->pActiveSRB;
175 if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
177 printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
180 if (dstate & DMA_XFER_DONE)
182 UINT residual, xferCnt; int ctr = 6000000;
183 if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
187 DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n"));
188 dstate = DC390_read8 (DMA_Status);
189 residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
190 DC390_read8 (CtcReg_High) << 16;
191 residual += DC390_read8 (Current_Fifo) & 0x1f;
192 } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
193 if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
201 xferCnt = pSRB->SGToBeXferLen - residual;
202 pSRB->SGBusAddr += xferCnt;
203 pSRB->TotalXferredLen += xferCnt;
204 pSRB->SGToBeXferLen = residual;
206 printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n",
207 (unsigned int)residual, (unsigned int)xferCnt);
210 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
212 dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
217 static irqreturn_t __inline__
218 DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
225 void (*stateV)( PACB, PSRB, PUCHAR );
226 UCHAR istate, istatus;
230 DC390_AFLAGS DC390_IFLAGS; //DC390_DFLAGS
233 for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB);
236 printk ("DC390: IRQ called with foreign dev_id %p!\n", pACB);
242 sstatus = DC390_read8 (Scsi_Status);
243 if( !(sstatus & INTERRUPT) )
244 { /*DC390_UNLOCK_DRV;*/ return IRQ_NONE; };
246 DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
249 DC390_LOCK_IO(pACB->pScsiHost);
251 dstatus = dc390_dma_intr (pACB);
253 DC390_UNLOCK_IO(pACB->pScsiHost);
255 DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus));
256 if (! (dstatus & SCSI_INTERRUPT))
258 DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"));
263 //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
264 //dstatus = DC390_read8 (DMA_Status);
265 //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
268 DC390_LOCK_IO(pACB->pScsiHost);
270 //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */
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 );
292 if (istatus & SCSI_RESET)
294 dc390_ScsiRstDetect( pACB );
298 if (istatus & DISCONNECTED)
300 dc390_Disconnect( pACB );
304 if (istatus & RESELECTED)
306 dc390_Reselect( pACB );
310 else if (istatus & (SELECTED | SEL_ATTENTION))
312 printk (KERN_ERR "DC390: Target mode not supported!\n");
316 if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
318 pDCB = pACB->pActiveDCB;
321 printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
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 = (UCHAR) 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 );
344 DC390_UNLOCK_IO(pACB->pScsiHost);
345 //DC390_UNLOCK_DRV; /* Restore initial flags */
349 irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
352 DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
353 /* Locking is done in DC390_Interrupt */
354 ret = DC390_Interrupt(irq, dev_id, regs);
355 DEBUG1(printk (".. IRQ returned\n"));
360 dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
364 UINT ResidCnt, xferCnt;
369 if( !(pSRB->SRBState & SRB_XFERPAD) )
371 if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
372 pSRB->SRBStatus |= PARITY_ERROR;
374 if( sstatus & COUNT_2_ZERO )
376 int ctr = 6000000; /* only try for about a second */
377 while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
378 if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
379 dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
380 pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
382 if( pSRB->SGIndex < pSRB->SGcount )
384 pSRB->pSegmentList++;
385 psgl = pSRB->pSegmentList;
387 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
388 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
391 pSRB->SGToBeXferLen = 0;
395 ResidCnt = (UINT) DC390_read8 (Current_Fifo) & 0x1f;
396 ResidCnt |= (UINT) DC390_read8 (CtcReg_High) << 16;
397 ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid) << 8;
398 ResidCnt += (UINT) DC390_read8 (CtcReg_Low);
400 xferCnt = pSRB->SGToBeXferLen - ResidCnt;
401 pSRB->SGBusAddr += xferCnt;
402 pSRB->TotalXferredLen += xferCnt;
403 pSRB->SGToBeXferLen = ResidCnt;
406 if ((*psstatus & 7) != SCSI_DATA_OUT)
408 DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
409 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
414 dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
416 UCHAR sstatus, residual, bval;
424 if( !(pSRB->SRBState & SRB_XFERPAD) )
426 if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
427 pSRB->SRBStatus |= PARITY_ERROR;
429 if( sstatus & COUNT_2_ZERO )
431 int ctr = 6000000; /* only try for about a second */
433 while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
434 if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
435 if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
436 dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
437 DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \
438 + ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \
439 + ((ULONG) DC390_read8 (CtcReg_Low)));
440 DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen));
442 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
444 pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
446 if( pSRB->SGIndex < pSRB->SGcount )
448 pSRB->pSegmentList++;
449 psgl = pSRB->pSegmentList;
451 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
452 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
455 pSRB->SGToBeXferLen = 0;
457 else /* phase changed */
460 bval = DC390_read8 (Current_Fifo);
463 DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
464 if( (bval & 0x1f) == 1 )
466 for(i=0; i < 0x100; i++)
468 bval = DC390_read8 (Current_Fifo);
471 else if( i == 0x0ff )
473 residual = 1; /* ;1 residual byte */
479 bval = DC390_read8 (Current_Fifo);
482 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
483 for (i = 0xa000; i; i--)
485 bval = DC390_read8 (DMA_Status);
486 if (bval & BLAST_COMPLETE)
489 /* It seems a DMA Blast abort isn't that bad ... */
490 if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
491 //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
492 dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
494 DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
495 ResidCnt = (UINT) DC390_read8 (CtcReg_High);
497 ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid);
499 ResidCnt |= (UINT) DC390_read8 (CtcReg_Low);
501 xferCnt = pSRB->SGToBeXferLen - ResidCnt;
502 pSRB->SGBusAddr += xferCnt;
503 pSRB->TotalXferredLen += xferCnt;
504 pSRB->SGToBeXferLen = ResidCnt;
508 bval = DC390_read8 (ScsiFifo); /* get one residual byte */
509 ptr = (PUCHAR) bus_to_virt( pSRB->SGBusAddr );
511 pSRB->SGBusAddr++; xferCnt++;
512 pSRB->TotalXferredLen++;
513 pSRB->SGToBeXferLen--;
515 DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
516 pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
520 if ((*psstatus & 7) != SCSI_DATA_IN)
522 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
523 DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
528 dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
533 dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
536 pSRB->TargetStatus = DC390_read8 (ScsiFifo);
538 pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
540 *psstatus = SCSI_NOP0;
541 pSRB->SRBState = SRB_COMPLETED;
542 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
546 dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
548 if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
549 *psstatus = SCSI_NOP0;
550 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
554 static void __inline__
555 dc390_reprog (PACB pACB, PDCB pDCB)
557 DC390_write8 (Sync_Period, pDCB->SyncPeriod);
558 DC390_write8 (Sync_Offset, pDCB->SyncOffset);
559 DC390_write8 (CtrlReg3, pDCB->CtrlR3);
560 DC390_write8 (CtrlReg4, pDCB->CtrlR4);
561 dc390_SetXferRate (pACB, pDCB);
567 dc390_printMsg (UCHAR *MsgBuf, UCHAR len)
570 printk (" %02x", MsgBuf[0]);
571 for (i = 1; i < len; i++)
572 printk (" %02x", MsgBuf[i]);
577 #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
580 static void __inline__
581 dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
583 pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
584 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
585 DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
589 static void __inline__
590 dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
592 pSRB->MsgOutBuf[0] = ABORT;
593 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
594 pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
598 dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
600 PSRB lastSRB = pDCB->pGoingLast;
601 PSRB pSRB = pDCB->pGoingSRB;
607 if (pSRB->TagNumber == tag) break;
608 if (pSRB == lastSRB) goto mingx0;
609 pSRB = pSRB->pNextSRB;
612 if( pDCB->DCBFlag & ABORT_DEV_ )
614 pSRB->SRBState = SRB_ABORT_SENT;
615 dc390_EnableMsgOut_Abort( pACB, pSRB );
618 if( !(pSRB->SRBState & SRB_DISCONNECT) )
621 pDCB->pActiveSRB = pSRB;
622 pSRB->SRBState = SRB_DATA_XFER;
627 pSRB = pACB->pTmpSRB;
628 pSRB->SRBState = SRB_UNEXPECT_RESEL;
629 pDCB->pActiveSRB = pSRB;
630 pSRB->MsgOutBuf[0] = ABORT_TAG;
631 pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
637 /* set async transfer mode */
639 dc390_MsgIn_set_async (PACB pACB, PSRB pSRB)
641 PDCB pDCB = pSRB->pSRBDCB;
642 if (!(pSRB->SRBState & DO_SYNC_NEGO))
643 printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
644 pSRB->SRBState &= ~DO_SYNC_NEGO;
645 pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
646 pDCB->SyncPeriod = 0;
647 pDCB->SyncOffset = 0;
648 //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
649 pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
650 pDCB->CtrlR4 &= 0x3f;
651 pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
652 dc390_reprog (pACB, pDCB);
655 /* set sync transfer mode */
657 dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB)
661 PDCB pDCB = pSRB->pSRBDCB;
662 UCHAR oldsyncperiod = pDCB->SyncPeriod;
663 UCHAR oldsyncoffset = pDCB->SyncOffset;
665 if (!(pSRB->SRBState & DO_SYNC_NEGO))
667 printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
668 pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
671 //dc390_MsgIn_reject (pACB, pSRB);
672 //return dc390_MsgIn_set_async (pACB, pSRB);
674 /* Reply with corrected SDTR Message */
675 if (pSRB->MsgInBuf[4] > 15)
677 printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
678 pSRB->MsgInBuf[4] = 15;
680 if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
682 printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
683 pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
685 memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
690 pSRB->SRBState &= ~DO_SYNC_NEGO;
691 pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
692 pDCB->SyncOffset &= 0x0f0;
693 pDCB->SyncOffset |= pSRB->MsgInBuf[4];
694 pDCB->NegoPeriod = pSRB->MsgInBuf[3];
696 wval = (USHORT) pSRB->MsgInBuf[3];
697 wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
698 if( (wval1 * 25) != wval) wval1++;
699 bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
701 pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
702 if (pACB->glitch_cfg != NS_TO_GLITCH(0))
703 pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
705 pDCB->CtrlR4 |= NS_TO_GLITCH(0);
706 if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
710 wval1--; /* Timing computation differs by 1 from FAST_SCSI */
711 bval = FAST_CLK; /* fast clock / normal scsi */
712 pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
716 pDCB->SyncPeriod = (UCHAR)wval1;
718 if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
720 if (! (bval & FAST_SCSI)) wval1++;
721 printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
722 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
725 dc390_reprog (pACB, pDCB);
729 /* handle RESTORE_PTR */
730 /* I presume, this command is already mapped, so, have to remap. */
732 dc390_restore_ptr (PACB pACB, PSRB pSRB)
734 Scsi_Cmnd* pcmd = pSRB->pcmd;
736 pSRB->TotalXferredLen = 0;
739 pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
740 psgl = pSRB->pSegmentList;
741 //dc390_pci_sync(pSRB);
743 while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr)
745 pSRB->TotalXferredLen += (ULONG) psgl->length;
747 if( pSRB->SGIndex < pSRB->SGcount )
749 pSRB->pSegmentList++;
750 psgl = pSRB->pSegmentList;
751 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
752 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
755 pSRB->SGToBeXferLen = 0;
757 pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
758 pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
759 printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
760 pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
762 } else if(pcmd->request_buffer) {
763 //dc390_pci_sync(pSRB);
765 pSRB->Segmentx.length = pcmd->request_bufflen - pSRB->Saved_Ptr;
767 pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
770 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
773 pSRB->TotalXferredLen = pSRB->Saved_Ptr;
777 /* According to the docs, the AM53C974 reads the message and
778 * generates a Successful Operation IRQ before asserting ACK for
779 * the last byte (how does it know whether it's the last ?) */
780 /* The old code handled it in another way, indicating, that on
781 * every message byte an IRQ is generated and every byte has to
782 * be manually ACKed. Hmmm ? (KG, 98/11/28) */
783 /* The old implementation was correct. Sigh! */
785 /* Check if the message is complete */
786 static UCHAR __inline__
787 dc390_MsgIn_complete (UCHAR *msgbuf, UINT len)
789 if (*msgbuf == EXTENDED_MESSAGE)
791 if (len < 2) return 0;
792 if (len < msgbuf[1] + 2) return 0;
794 else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
795 if (len < 2) return 0;
801 /* read and eval received messages */
803 dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
805 PDCB pDCB = pACB->pActiveDCB;
809 pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
810 //pSRB->SRBState = 0;
813 if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
815 DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
816 /* Now eval the msg */
817 switch (pSRB->MsgInBuf[0])
820 pSRB->SRBState = SRB_DISCONNECT; break;
822 case SIMPLE_QUEUE_TAG:
823 case HEAD_OF_QUEUE_TAG:
824 case ORDERED_QUEUE_TAG:
825 pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
829 DC390_write8 (ScsiCmd, RESET_ATN_CMD);
830 pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
831 if( pSRB->SRBState & DO_SYNC_NEGO)
832 dc390_MsgIn_set_async (pACB, pSRB);
835 case EXTENDED_MESSAGE:
836 /* reject every extended msg but SDTR */
837 if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
838 dc390_MsgIn_reject (pACB, pSRB);
841 if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
842 dc390_MsgIn_set_async (pACB, pSRB);
844 dc390_MsgIn_set_sync (pACB, pSRB);
847 // nothing has to be done
848 case COMMAND_COMPLETE: break;
850 // SAVE POINTER may be ignored as we have the PSRB associated with the
851 // scsi command. Thanks, Gerard, for pointing it out.
853 pSRB->Saved_Ptr = pSRB->TotalXferredLen;
855 // The device might want to restart transfer with a RESTORE
856 case RESTORE_POINTERS:
857 DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n"));
858 dc390_restore_ptr (pACB, pSRB);
861 // reject unknown messages
862 default: dc390_MsgIn_reject (pACB, pSRB);
865 /* Clear counter and MsgIn state */
866 pSRB->SRBState &= ~SRB_MSGIN;
870 *psstatus = SCSI_NOP0;
871 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
872 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
877 dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
881 PDCB pDCB = pACB->pActiveDCB;
883 if (pSRB == pACB->pTmpSRB)
885 if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",
886 pDCB->TargetID, pDCB->TargetLUN);
887 else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
888 dc390_EnableMsgOut_Abort (pACB, pSRB);
889 if (pDCB) pDCB->DCBFlag |= ABORT_DEV;
893 if( pSRB->SGIndex < pSRB->SGcount )
895 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
896 if( !pSRB->SGToBeXferLen )
898 psgl = pSRB->pSegmentList;
899 pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
900 pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
901 DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
903 lval = pSRB->SGToBeXferLen;
904 DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
905 DC390_write8 (CtcReg_Low, (UCHAR) lval);
907 DC390_write8 (CtcReg_Mid, (UCHAR) lval);
909 DC390_write8 (CtcReg_High, (UCHAR) lval);
911 DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
912 DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
914 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
915 pSRB->SRBState = SRB_DATA_XFER;
917 DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
919 DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
920 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
921 //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
922 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
928 pSRB->AdaptStatus = H_OVER_UNDER_RUN;
929 pSRB->SRBStatus |= OVER_RUN;
930 DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
932 DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
933 DC390_write8 (CtcReg_Low, 0);
934 DC390_write8 (CtcReg_Mid, 0);
935 DC390_write8 (CtcReg_High, 0);
937 pSRB->SRBState |= SRB_XFERPAD;
938 DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
940 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
941 DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
948 dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
950 dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
954 dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
956 dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
960 dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
966 DC390_write8 (ScsiCmd, RESET_ATN_CMD);
967 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
968 if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
970 cnt = (UCHAR) pSRB->pcmd->cmd_len;
971 ptr = (PUCHAR) pSRB->pcmd->cmnd;
972 for(i=0; i < cnt; i++)
973 DC390_write8 (ScsiFifo, *(ptr++));
978 DC390_write8 (ScsiFifo, REQUEST_SENSE);
979 pDCB = pACB->pActiveDCB;
980 DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
981 DC390_write8 (ScsiFifo, bval);
982 DC390_write8 (ScsiFifo, bval);
983 DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
984 DC390_write8 (ScsiFifo, bval);
985 DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
987 pSRB->SRBState = SRB_COMMAND;
988 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
992 dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
994 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
995 pSRB->SRBState = SRB_STATUS;
996 DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
997 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1001 dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1007 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1008 pDCB = pACB->pActiveDCB;
1009 if( !(pSRB->SRBState & SRB_MSGOUT) )
1014 ptr = (PUCHAR) pSRB->MsgOutBuf;
1015 for(i=0; i < cnt; i++)
1016 DC390_write8 (ScsiFifo, *(ptr++));
1018 if( (pDCB->DCBFlag & ABORT_DEV_) &&
1019 (pSRB->MsgOutBuf[0] == ABORT) )
1020 pSRB->SRBState = SRB_ABORT_SENT;
1024 bval = ABORT; /* ??? MSG_NOP */
1025 if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
1026 (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
1027 (pSRB->SRBFlag & AUTO_REQSENSE) )
1029 if( pDCB->SyncMode & SYNC_ENABLE )
1032 DC390_write8 (ScsiFifo, bval);
1034 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1039 printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
1040 DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
1041 DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */
1042 DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */
1043 DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
1044 if (pDCB->SyncOffset & 0x0f)
1045 DC390_write8 (ScsiFifo, pDCB->SyncOffset);
1047 DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
1048 pSRB->SRBState |= DO_SYNC_NEGO;
1049 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1054 dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1056 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1057 if( !(pSRB->SRBState & SRB_MSGIN) )
1059 pSRB->SRBState &= ~SRB_DISCONNECT;
1060 pSRB->SRBState |= SRB_MSGIN;
1062 DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1063 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1067 dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1072 dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1078 dc390_SetXferRate( PACB pACB, PDCB pDCB )
1083 if( !(pDCB->TargetLUN) )
1085 if( !pACB->scan_devices )
1087 ptr = pACB->pLinkDCB;
1089 bval = pDCB->TargetID;
1090 for(i=0; i<cnt; i++)
1092 if( ptr->TargetID == bval )
1094 ptr->SyncPeriod = pDCB->SyncPeriod;
1095 ptr->SyncOffset = pDCB->SyncOffset;
1096 ptr->CtrlR3 = pDCB->CtrlR3;
1097 ptr->CtrlR4 = pDCB->CtrlR4;
1098 ptr->SyncMode = pDCB->SyncMode;
1100 ptr = ptr->pNextDCB;
1109 dc390_Disconnect( PACB pACB )
1115 DEBUG0(printk(KERN_INFO "DISC,"));
1117 if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
1118 pACB->Connected = 0;
1119 pDCB = pACB->pActiveDCB;
1123 DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
1124 pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
1125 while (--j) udelay (1000);
1126 DC390_read8 (INT_Status); /* Reset Pending INT */
1127 DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1130 DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1131 pSRB = pDCB->pActiveSRB;
1132 pACB->pActiveDCB = 0;
1133 pSRB->ScsiPhase = SCSI_NOP0;
1134 if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
1137 dc390_Waiting_process ( pACB );
1139 else if( pSRB->SRBState & SRB_ABORT_SENT )
1143 cnt = pDCB->GoingSRBCnt;
1144 pDCB->GoingSRBCnt = 0;
1145 pSRB = pDCB->pGoingSRB;
1146 for( i=0; i < cnt; i++)
1148 psrb = pSRB->pNextSRB;
1149 dc390_Free_insert (pACB, pSRB);
1152 pDCB->pGoingSRB = 0;
1153 dc390_Query_to_Waiting (pACB);
1154 dc390_Waiting_process (pACB);
1158 if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
1159 !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
1160 { /* Selection time out */
1161 if( !(1/*pACB->scan_devices*/) )
1163 pSRB->SRBState = SRB_READY;
1164 dc390_freetag (pDCB, pSRB);
1165 dc390_Going_to_Waiting (pDCB, pSRB);
1166 dc390_waiting_timer (pACB, HZ/5);
1170 pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
1174 else if( pSRB->SRBState & SRB_DISCONNECT )
1176 dc390_Waiting_process ( pACB );
1178 else if( pSRB->SRBState & SRB_COMPLETED )
1181 dc390_freetag (pDCB, pSRB);
1182 pDCB->pActiveSRB = 0;
1183 pSRB->SRBState = SRB_FREE;
1184 dc390_SRBdone( pACB, pDCB, pSRB);
1192 dc390_Reselect( PACB pACB )
1198 DEBUG0(printk(KERN_INFO "RSEL,"));
1199 pACB->Connected = 1;
1200 pDCB = pACB->pActiveDCB;
1202 { /* Arbitration lost but Reselection won */
1203 DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
1204 pSRB = pDCB->pActiveSRB;
1205 if( !( pACB->scan_devices ) )
1207 pSRB->SRBState = SRB_READY;
1208 dc390_freetag (pDCB, pSRB);
1209 dc390_Going_to_Waiting ( pDCB, pSRB);
1210 dc390_waiting_timer (pACB, HZ/5);
1214 lun = DC390_read8 (ScsiFifo);
1215 DEBUG0(printk ("Dev %02x,", lun));
1216 if (!(lun & (1 << pACB->pScsiHost->this_id)))
1217 printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
1219 lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
1220 id = 0; while (lun >>= 1) id++;
1222 lun = DC390_read8 (ScsiFifo);
1223 if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
1225 DEBUG0(printk ("(%02i-%i),", id, lun));
1226 pDCB = dc390_findDCB (pACB, id, lun);
1229 printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
1233 pACB->pActiveDCB = pDCB;
1234 /* TagQ: We expect a message soon, so never mind the exact SRB */
1235 if( pDCB->SyncMode & EN_TAG_QUEUEING )
1237 pSRB = pACB->pTmpSRB;
1238 pDCB->pActiveSRB = pSRB;
1242 pSRB = pDCB->pActiveSRB;
1243 if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
1245 pSRB= pACB->pTmpSRB;
1246 pSRB->SRBState = SRB_UNEXPECT_RESEL;
1247 printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
1249 pDCB->pActiveSRB = pSRB;
1250 dc390_EnableMsgOut_Abort ( pACB, pSRB );
1254 if( pDCB->DCBFlag & ABORT_DEV_ )
1256 pSRB->SRBState = SRB_ABORT_SENT;
1257 printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
1259 dc390_EnableMsgOut_Abort( pACB, pSRB );
1262 pSRB->SRBState = SRB_DATA_XFER;
1266 DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
1267 pSRB->ScsiPhase = SCSI_NOP0;
1268 DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
1269 DC390_write8 (Sync_Period, pDCB->SyncPeriod);
1270 DC390_write8 (Sync_Offset, pDCB->SyncOffset);
1271 DC390_write8 (CtrlReg1, pDCB->CtrlR1);
1272 DC390_write8 (CtrlReg3, pDCB->CtrlR3);
1273 DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
1274 DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */
1279 dc390_remove_dev (PACB pACB, PDCB pDCB)
1281 PDCB pPrevDCB = pACB->pLinkDCB;
1283 if (pDCB->GoingSRBCnt > 1)
1285 DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\
1286 pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt));
1289 pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN);
1292 if (pDCB == pACB->pLinkDCB)
1295 if (pACB->pLastDCB == pDCB) {
1296 pDCB->pNextDCB = 0; pACB->pLastDCB = 0;
1298 pACB->pLinkDCB = pDCB->pNextDCB;
1302 while (pPrevDCB->pNextDCB != pDCB) pPrevDCB = pPrevDCB->pNextDCB;
1303 pPrevDCB->pNextDCB = pDCB->pNextDCB;
1304 if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB;
1307 DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\
1308 pDCB->TargetID, pDCB->TargetLUN, pDCB));
1309 if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0;
1310 if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB;
1311 if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB;
1314 /* pACB->DeviceCnt--; */
1318 static UCHAR __inline__
1319 dc390_tagq_blacklist (char* name)
1322 for(i=0; i<BADDEVCNT; i++)
1323 if (memcmp (name, dc390_baddevname1[i], 28) == 0)
1330 dc390_disc_tagq_set (PDCB pDCB, PSCSI_INQDATA ptr)
1332 /* Check for SCSI format (ANSI and Response data format) */
1333 if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 )
1335 if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1336 (pDCB->DevMode & TAG_QUEUEING_) &&
1337 /* ((pDCB->DevType == TYPE_DISK)
1338 || (pDCB->DevType == TYPE_MOD)) &&*/
1339 !dc390_tagq_blacklist (((char*)ptr)+8) )
1341 if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum;
1342 pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */;
1343 //pDCB->TagMask = 0;
1346 pDCB->MaxCommand = 1;
1352 dc390_add_dev (PACB pACB, PDCB pDCB, PSCSI_INQDATA ptr)
1354 UCHAR bval1 = ptr->DevType & SCSI_DEVTYPE;
1355 pDCB->DevType = bval1;
1356 /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
1357 dc390_disc_tagq_set (pDCB, ptr);
1362 dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
1364 UCHAR bval, status, i, DCB_removed;
1371 /* KG: Moved pci_unmap here */
1372 dc390_pci_unmap(pSRB);
1375 status = pSRB->TargetStatus;
1376 ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1378 ptr = (PSCSI_INQDATA) sg_dma_address((PSGL) ptr);
1380 DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
1382 if(pSRB->SRBFlag & AUTO_REQSENSE)
1383 { /* Last command was a Request Sense */
1384 pSRB->SRBFlag &= ~AUTO_REQSENSE;
1385 pSRB->AdaptStatus = 0;
1386 pSRB->TargetStatus = CHECK_CONDITION << 1;
1387 #ifdef DC390_REMOVABLEDEBUG
1388 switch (pcmd->sense_buffer[2] & 0x0f)
1390 case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1391 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1392 status, pACB->scan_devices); break;
1393 case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1394 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1395 status, pACB->scan_devices); break;
1396 case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1397 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1398 status, pACB->scan_devices); break;
1399 case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1400 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1401 status, pACB->scan_devices); break;
1402 case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1403 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
1404 status, pACB->scan_devices); break;
1407 //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
1408 if (status == (CHECK_CONDITION << 1))
1410 pcmd->result = MK_RES_LNX(0,DID_BAD_TARGET,0,/*CHECK_CONDITION*/0);
1413 if(pSRB->RetryCnt == 0)
1415 //(UINT)(pSRB->pcmd->cmnd[0]) = pSRB->Segment0[0];
1416 pSRB->TotalXferredLen = pSRB->SavedTotXLen;
1417 if( (pSRB->TotalXferredLen) &&
1418 (pSRB->TotalXferredLen >= pcmd->underflow) )
1419 SET_RES_DID(pcmd->result,DID_OK)
1421 pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
1422 REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->pcmd->cmnd[0],\
1423 (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen));
1429 pSRB->AdaptStatus = 0;
1430 pSRB->TargetStatus = 0;
1431 //*((PUINT) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1432 //*((PUINT) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
1433 /* Don't retry on TEST_UNIT_READY */
1434 if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
1436 pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION);
1437 REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
1438 (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen));
1441 SET_RES_DRV(pcmd->result,DRIVER_SENSE);
1442 pcmd->use_sg = pSRB->SavedSGCount;
1443 //pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8);
1444 DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun));
1446 pSRB->TotalXferredLen = 0;
1447 pSRB->SGToBeXferLen = 0;
1449 if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1450 dc390_Going_to_Waiting ( pDCB, pSRB );
1451 dc390_waiting_timer (pACB, HZ/5);
1458 if( status_byte(status) == CHECK_CONDITION )
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) )
1464 bval = pSRB->SGcount;
1466 ptr2 = pSRB->pSegmentList;
1467 for( i=pSRB->SGIndex; i < bval; i++)
1469 swlval += ptr2->length;
1472 REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
1473 (UINT) pSRB->TotalXferredLen, (UINT) swlval));
1475 dc390_RequestSense( pACB, pDCB, pSRB );
1478 else if( status_byte(status) == QUEUE_FULL )
1480 bval = (UCHAR) pDCB->GoingSRBCnt;
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;
1490 else if(status == SCSI_STAT_SEL_TIMEOUT)
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 ... */
1497 else if (status_byte(status) == BUSY &&
1498 (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
1501 pSRB->AdaptStatus = 0;
1502 pSRB->TargetStatus = status;
1503 pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
1506 { /* Another error */
1507 pSRB->AdaptStatus = 0;
1508 if( pSRB->RetryCnt )
1510 //printk ("DC390: retry\n");
1512 pSRB->TargetStatus = 0;
1514 pSRB->TotalXferredLen = 0;
1515 pSRB->SGToBeXferLen = 0;
1516 if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1517 dc390_Going_to_Waiting ( pDCB, pSRB );
1518 dc390_waiting_timer (pACB, HZ/5);
1523 { /* Report error */
1524 //pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status);
1525 SET_RES_DID(pcmd->result,DID_ERROR);
1526 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1527 SET_RES_TARGET(pcmd->result,status);
1532 { /* Target status == 0 */
1533 status = pSRB->AdaptStatus;
1534 if(status & H_OVER_UNDER_RUN)
1536 pSRB->TargetStatus = 0;
1537 SET_RES_DID(pcmd->result,DID_OK);
1538 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1540 else if( pSRB->SRBStatus & PARITY_ERROR)
1542 //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
1543 SET_RES_DID(pcmd->result,DID_PARITY);
1544 SET_RES_MSG(pcmd->result,pSRB->EndMessage);
1548 pSRB->AdaptStatus = 0;
1549 pSRB->TargetStatus = 0;
1550 SET_RES_DID(pcmd->result,DID_OK);
1553 if ((pcmd->result & RES_DID) == 0 &&
1554 pcmd->cmnd[0] == INQUIRY &&
1555 pcmd->cmnd[2] == 0 &&
1556 pcmd->request_bufflen >= 8 &&
1558 (ptr->Vers & 0x07) >= 2)
1559 pDCB->Inquiry7 = ptr->Flags;
1562 if( pACB->scan_devices )
1564 if( pcmd->cmnd[0] == TEST_UNIT_READY ||
1565 pcmd->cmnd[0] == INQUIRY)
1568 printk (KERN_INFO "DC390: %s: result: %08x",
1569 (pcmd->cmnd[0] == INQUIRY? "INQUIRY": "TEST_UNIT_READY"),
1571 if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n",
1572 pcmd->sense_buffer[0], pcmd->sense_buffer[1],
1573 pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
1576 if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) ||
1577 ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 &&
1578 (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR )
1580 /* device not present: remove */
1581 //dc390_Going_remove (pDCB, pSRB);
1582 dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
1584 if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) &&
1585 ((pcmd->device->lun == 0) || (pcmd->device->lun == pACB->pScsiHost->max_lun - 1)) )
1586 pACB->scan_devices = 0;
1590 /* device present: add */
1591 if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) &&
1592 (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) )
1593 pACB->scan_devices = END_SCAN ;
1594 /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */
1599 //if( pSRB->pcmd->cmnd[0] == INQUIRY &&
1600 // (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) )
1601 if( pcmd->cmnd[0] == INQUIRY &&
1602 (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
1604 if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV && !DCB_removed)
1606 //printk ("DC390: Type = nodev! (%02i-%i)\n", pcmd->target, pcmd->lun);
1607 /* device not present: remove */
1608 //dc390_Going_remove (pDCB, pSRB);
1609 dc390_remove_dev (pACB, pDCB); DCB_removed = 1;
1613 /* device found: add */
1614 dc390_add_dev (pACB, pDCB, ptr);
1615 if (pACB->scan_devices) pACB->DeviceCnt++;
1617 if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) &&
1618 (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) )
1619 pACB->scan_devices = 0;
1622 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30)
1623 pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen;
1626 if (!DCB_removed) dc390_Going_remove (pDCB, pSRB);
1627 /* Add to free list */
1628 dc390_Free_insert (pACB, pSRB);
1630 DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid));
1631 DC390_UNLOCK_ACB_NI;
1632 pcmd->scsi_done (pcmd);
1635 dc390_Query_to_Waiting (pACB);
1636 dc390_Waiting_process (pACB);
1641 /* Remove all SRBs from Going list and inform midlevel */
1643 dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd )
1650 pDCB = pACB->pLinkDCB;
1655 psrb = pdcb->pGoingSRB;
1656 for( i=0; i<pdcb->GoingSRBCnt; i++)
1658 psrb2 = psrb->pNextSRB;
1660 dc390_Free_insert (pACB, psrb);
1662 /* New EH will crash on being given timed out cmnds */
1664 pcmd->result = MK_RES(0,DID_ABORT,0,0);
1666 pcmd->result = MK_RES(0,DID_RESET,0,0);
1668 /* ReleaseSRB( pDCB, pSRB ); */
1670 DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid));
1671 DC390_UNLOCK_ACB_NI;
1672 pcmd->scsi_done( pcmd );
1677 pdcb->GoingSRBCnt = 0;
1678 pdcb->pGoingSRB = NULL;
1680 pdcb = pdcb->pNextDCB;
1681 } while( pdcb != pDCB );
1682 dc390_Query_to_Waiting (pACB);
1687 dc390_ResetSCSIBus( PACB pACB )
1689 //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1691 //DC390_write8 (ScsiCmd, NOP_CMD);
1693 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1694 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1695 DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
1696 pACB->Connected = 0;
1702 dc390_ScsiRstDetect( PACB pACB )
1704 printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
1705 //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
1707 if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
1708 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1709 /* Unlock before ? */
1710 /* delay half a second */
1712 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1713 pACB->pScsiHost->last_reset = jiffies + 5*HZ/2
1714 + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
1715 pACB->Connected = 0;
1717 if( pACB->ACBFlag & RESET_DEV )
1718 pACB->ACBFlag |= RESET_DONE;
1720 { /* Reset was issued by sb else */
1721 pACB->ACBFlag |= RESET_DETECT;
1723 dc390_ResetDevParam( pACB );
1724 dc390_DoingSRB_Done( pACB, 0 );
1725 //dc390_RecoverSRB( pACB );
1726 pACB->pActiveDCB = NULL;
1728 dc390_Waiting_process( pACB );
1734 static void __inline__
1735 dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1741 REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
1742 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
1744 pSRB->SRBFlag |= AUTO_REQSENSE;
1745 //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0];
1746 //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4];
1747 //pSRB->Segment1[0] = ((UINT)(pcmd->cmd_len) << 8) + pSRB->SGcount;
1748 //pSRB->Segment1[1] = pSRB->TotalXferredLen;
1749 pSRB->SavedSGCount = pcmd->use_sg;
1750 pSRB->SavedTotXLen = pSRB->TotalXferredLen;
1751 pSRB->AdaptStatus = 0;
1752 pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
1754 /* We are called from SRBdone, original PCI mapping has been removed
1755 * already, new one is set up from StartSCSI */
1758 //pSRB->CmdBlock[0] = REQUEST_SENSE;
1759 //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
1760 //(USHORT) pSRB->CmdBlock[2] = 0;
1761 //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
1762 //pSRB->ScsiCmdLen = 6;
1764 pSRB->TotalXferredLen = 0;
1765 pSRB->SGToBeXferLen = 0;
1766 if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
1767 dc390_Going_to_Waiting ( pDCB, pSRB );
1768 dc390_waiting_timer (pACB, HZ/5);
1774 static void __inline__
1775 dc390_InvalidCmd( PACB pACB )
1777 if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
1778 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);