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.15 1998/12/25 17:33:27 garloff Exp $ */
10 dc390_StartSCSI(PACB pACB
, PDCB pDCB
, PSRB pSRB
)
16 DC390_write8(Scsi_Dest_ID
, pDCB
->UnitSCSIID
);
17 DC390_write8(Sync_Period
, pDCB
->SyncPeriod
);
18 DC390_write8(Sync_Offset
, pDCB
->SyncOffset
);
19 DC390_write8(CtrlReg1
, pDCB
->CtrlR1
);
20 DC390_write8(CtrlReg3
, pDCB
->CtrlR3
);
21 DC390_write8(CtrlReg4
, pDCB
->CtrlR4
);
22 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
); /* Flush FIFO */
23 DEBUG1(printk(KERN_INFO
"DC390: Start SCSI command: %02x (Sync:%02x)\n", \
24 pSRB
->CmdBlock
[0], pDCB
->SyncMode
);
26 pSRB
->ScsiPhase
= SCSI_NOP0
;
27 //pSRB->MsgOutBuf[0] = MSG_NOP;
29 bval
= pDCB
->IdentifyMsg
;
30 if (!(pDCB
->SyncMode
& EN_ATN_STOP
)) { /* Don't always try send Extended messages on arbitration */
31 if ((pSRB
->CmdBlock
[0] == INQUIRY
) ||
32 (pSRB
->CmdBlock
[0] == REQUEST_SENSE
) ||
33 (pSRB
->SRBFlag
& AUTO_REQSENSE
)) {
34 bval
&= 0xBF; /* No DisConn */
35 DC390_write8(ScsiFifo
, bval
);
37 pSRB
->SRBState
= SRB_START_
;
38 DEBUG1(printk(KERN_DEBUG
"DC390: No DisCn, No TagQ (%02x, %02x)\n", bval
, bval1
);
40 if (pDCB
->SyncMode
& SYNC_ENABLE
) {
41 if (!(pDCB
->IdentifyMsg
& 7) || /* LUN == 0 || Cmd != INQUIRY */
42 (pSRB
->CmdBlock
[0] != INQUIRY
)) {
43 bval1
= SEL_W_ATN_STOP
; /* Try to establish SYNC nego */
44 pSRB
->SRBState
= SRB_MSGOUT
;
48 DC390_write8(ScsiFifo
, bval
);
49 if (pDCB
->SyncMode
& EN_TAG_QUEUEING
) {
50 DC390_write8(ScsiFifo
, MSG_SIMPLE_QTAG
);
51 DEBUG1(printk(KERN_DEBUG
"DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval
& 0x40 ? "" : "No "), bval
, SEL_W_ATN3
, pDCB
->TagMask
);
55 while (wlval
& pDCB
->TagMask
) {
59 pDCB
->TagMask
|= wlval
;
60 DC390_write8(ScsiFifo
, bval
);
61 pSRB
->TagNumber
= bval
;
62 DEBUG1(printk(KERN_DEBUG
"DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB
, pSRB
->pcmd
->pid
, bval
);
65 pSRB
->SRBState
= SRB_START_
;
66 } else { /* No TagQ */
68 DEBUG1(printk(KERN_DEBUG
"DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval
& 0x40 ? "" : "No "), bval
, bval1
, pDCB
->TagMask
);
70 pSRB
->SRBState
= SRB_START_
;
74 } else { /* ATN_STOP: Always try to establish Sync nego */
75 if ((pSRB
->CmdBlock
[0] == INQUIRY
) ||
76 (pSRB
->CmdBlock
[0] == REQUEST_SENSE
) ||
77 (pSRB
->SRBFlag
& AUTO_REQSENSE
)) {
78 bval
&= 0xBF; /* No DisConn */
79 DC390_write8(ScsiFifo
, bval
);
81 DEBUG1(printk(KERN_DEBUG
"DC390: No DisCn, No TagQ (%02x, %02x)\n", bval
, bval1
);
83 pSRB
->SRBState
= SRB_START_
;
85 if (pDCB
->SyncMode
& SYNC_ENABLE
) {
86 if (!(pDCB
->IdentifyMsg
& 7) || /* LUN == 0 || Cmd != INQUIRY */
87 (pSRB
->CmdBlock
[0] != INQUIRY
)) {
88 bval1
= SEL_W_ATN_STOP
; /* Try to establish Sync nego */
89 pSRB
->SRBState
= SRB_MSGOUT
;
93 DC390_write8(ScsiFifo
, bval
);
94 if (pDCB
->SyncMode
& EN_TAG_QUEUEING
) {
95 pSRB
->MsgOutBuf
[0] = MSG_SIMPLE_QTAG
;
96 DEBUG1(printk(KERN_DEBUG
"DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval
& 0x40 ? "" : "No "), bval
, SEL_W_ATN_STOP
, pDCB
->TagMask
);
100 while (wlval
& pDCB
->TagMask
) {
104 pDCB
->TagMask
|= wlval
;
105 pSRB
->TagNumber
= bval
;
106 DEBUG1(printk(KERN_DEBUG
"DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB
, pSRB
->pcmd
->pid
, bval
);
108 pSRB
->MsgOutBuf
[1] = bval
;
110 bval1
= SEL_W_ATN_STOP
;
111 pSRB
->SRBState
= SRB_START_
; /* ?? */
112 } else { /* No TagQ */
113 pSRB
->MsgOutBuf
[0] = MSG_NOP
;
115 pSRB
->SRBState
= SRB_START_
;
116 bval1
= SEL_W_ATN_STOP
;
117 DEBUG1(printk(KERN_DEBUG
"DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval
& 0x40 ? "" : "No "), bval
, bval1
, pDCB
->TagMask
);
122 if (bval1
!= SEL_W_ATN_STOP
) { /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
123 if (pSRB
->SRBFlag
& AUTO_REQSENSE
) {
125 DC390_write8(ScsiFifo
, REQUEST_SENSE
);
126 DC390_write8(ScsiFifo
, pDCB
->IdentifyMsg
<< 5);
127 DC390_write8(ScsiFifo
, bval
);
128 DC390_write8(ScsiFifo
, bval
);
129 DC390_write8(ScsiFifo
, sizeof(pSRB
->pcmd
->sense_buffer
));
130 DC390_write8(ScsiFifo
, bval
);
131 DEBUG1(printk(KERN_DEBUG
"DC390: AutoReqSense !\n");
133 } else { /* write cmnd to bus */
136 ptr
= (PUCHAR
) pSRB
->CmdBlock
;
137 for (i
= 0; i
< pSRB
->ScsiCmdLen
; i
++)
138 DC390_write8(ScsiFifo
, *(ptr
++));
141 /* Check if we can't win arbitration */
142 if (DC390_read8(Scsi_Status
) & INTERRUPT
) {
143 pSRB
->SRBState
= SRB_READY
;
144 pDCB
->TagMask
&= ~(1 << pSRB
->TagNumber
);
145 DEBUG0(printk(KERN_WARNING
"DC390: Interrupt during StartSCSI!\n");
149 pSRB
->ScsiPhase
= SCSI_NOP1
;
150 DEBUG0(if (pACB
->pActiveDCB
) \
151 printk(KERN_WARNING
"DC390: ActiveDCB != 0\n");)
152 DEBUG0(if (pDCB
->pActiveSRB
) \
153 printk(KERN_WARNING
"DC390: ActiveSRB != 0\n");)
154 pACB
->pActiveDCB
= pDCB
;
155 pDCB
->pActiveSRB
= pSRB
;
156 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
157 DC390_write8(ScsiCmd
, bval1
);
162 //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
166 /* This is similar to AM53C974.c ... */
168 dc390_dma_intr(PACB pACB
)
172 DEBUG0(USHORT pstate
;
177 DEBUG0(PCI_READ_CONFIG_WORD(PDEV
, PCI_STATUS
, &pstate
);
179 DEBUG0(if (pstate
& (PCI_STATUS_SIG_SYSTEM_ERROR
| PCI_STATUS_DETECTED_PARITY
)) \
181 printk(KERN_WARNING
"DC390: PCI state = %04x!\n", pstate
); \
182 PCI_WRITE_CONFIG_WORD(PDEV
, PCI_STATUS
, (PCI_STATUS_SIG_SYSTEM_ERROR
| PCI_STATUS_DETECTED_PARITY
));
185 dstate
= DC390_read8(DMA_Status
);
187 if (!pACB
->pActiveDCB
|| !pACB
->pActiveDCB
->pActiveSRB
)
190 pSRB
= pACB
->pActiveDCB
->pActiveSRB
;
192 if (dstate
& (DMA_XFER_ABORT
| DMA_XFER_ERROR
| POWER_DOWN
| PCI_MS_ABORT
)) {
193 printk(KERN_ERR
"DC390: DMA error (%02x)!\n", dstate
);
196 if (dstate
& DMA_XFER_DONE
) {
197 ULONG residual
, xferCnt
;
199 if (!(DC390_read8(DMA_Cmd
) & READ_DIRECTION
)) {
201 DEBUG1(printk(KERN_DEBUG
"DC390: read residual bytes ... \n");
203 dstate
= DC390_read8(DMA_Status
);
204 residual
= DC390_read8(CtcReg_Low
) | DC390_read8(CtcReg_Mid
) << 8 |
205 DC390_read8(CtcReg_High
) << 16;
206 residual
+= DC390_read8(Current_Fifo
) & 0x1f;
207 } while (residual
&& !(dstate
& SCSI_INTERRUPT
) && --ctr
);
209 printk(KERN_CRIT
"DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr
));
216 xferCnt
= pSRB
->SGToBeXferLen
- residual
;
217 pSRB
->SGBusAddr
+= xferCnt
;
218 pSRB
->TotalXferredLen
+= xferCnt
;
219 pSRB
->SGToBeXferLen
= residual
;
221 printk(KERN_INFO
"DC390: DMA: residual = %i, xfer = %i\n",
222 (unsigned int) residual
, (unsigned int) xferCnt
);
225 DC390_write8(DMA_Cmd
, DMA_IDLE_CMD
);
227 dc390_laststatus
&= ~0xff000000;
228 dc390_laststatus
|= dstate
<< 24;
234 DC390_Interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
241 void (*stateV
) (PACB
, PSRB
, PUCHAR
);
242 UCHAR istate
, istatus
;
246 DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS
248 pACB
= dc390_pACB_start
;
251 printk(KERN_WARNING
"DC390: Interrupt on uninitialized adapter!\n");
256 for (i
= 0; i
< dc390_adapterCnt
; i
++) {
257 if (pACB
->IRQLevel
== (UCHAR
) irq
) {
258 sstatus
= DC390_read8(Scsi_Status
);
259 if (sstatus
& INTERRUPT
)
262 pACB
= pACB
->pNextACB
;
264 pACB
= pACB
->pNextACB
;
268 DEBUG1(printk(KERN_DEBUG
"sstatus=%02x,", sstatus
);
278 dstatus
= dc390_dma_intr(pACB
);
282 DEBUG1(printk(KERN_DEBUG
"dstatus=%02x,", dstatus
);
284 if (!(dstatus
& SCSI_INTERRUPT
)) {
285 DEBUG0(printk(KERN_WARNING
"DC390 Int w/o SCSI actions (only DMA?)\n");
291 //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
292 //dstatus = DC390_read8 (DMA_Status);
293 //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
298 DC390_UNLOCK_DRV_NI
; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */
300 istate
= DC390_read8(Intern_State
);
301 istatus
= DC390_read8(INT_Status
); /* This clears Scsi_Status, Intern_State and INT_Status ! */
303 DEBUG1(printk(KERN_INFO
"Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,", istatus
);
305 dc390_laststatus
&= ~0x00ffffff;
306 dc390_laststatus
|= /* dstatus<<24 | */ sstatus
<< 16 | istate
<< 8 | istatus
;
308 if (sstatus
& ILLEGAL_OP_ERR
) {
309 printk("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus
);
310 dc390_dumpinfo(pACB
, pACB
->pActiveDCB
, pACB
->pActiveDCB
->pActiveSRB
);
313 if (istatus
& DISCONNECTED
) {
314 dc390_Disconnect(pACB
);
317 if (istatus
& RESELECTED
) {
318 dc390_Reselect(pACB
);
321 if (istatus
& (SUCCESSFUL_OP
| SERVICE_REQUEST
)) {
322 pDCB
= pACB
->pActiveDCB
;
324 printk(KERN_ERR
"DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
327 pSRB
= pDCB
->pActiveSRB
;
328 if (pDCB
->DCBFlag
& ABORT_DEV_
)
329 dc390_EnableMsgOut_Abort(pACB
, pSRB
);
331 phase
= pSRB
->ScsiPhase
;
332 DEBUG1(printk(KERN_INFO
"DC390: [%i]%s(0) (%02x)\n", phase
, dc390_p0_str
[phase
], sstatus
);
334 stateV
= (void *) dc390_phase0
[phase
];
335 (*stateV
) (pACB
, pSRB
, &sstatus
);
337 pSRB
->ScsiPhase
= sstatus
& 7;
338 phase
= (UCHAR
) sstatus
& 7;
339 DEBUG1(printk(KERN_INFO
"DC390: [%i]%s(1) (%02x)\n", phase
, dc390_p1_str
[phase
], sstatus
);
341 stateV
= (void *) dc390_phase1
[phase
];
342 (*stateV
) (pACB
, pSRB
, &sstatus
);
345 if (istatus
& INVALID_CMD
) {
346 dc390_InvalidCmd(pACB
);
349 if (istatus
& SCSI_RESET
) {
350 dc390_ScsiRstDetect(pACB
);
357 DC390_UNLOCK_DRV
; /* Restore initial flags */
360 void do_DC390_Interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
362 DEBUG1(printk(KERN_INFO
"DC390: Irq (%i) caught: ", irq
);
364 /* Locking is done in DC390_Interrupt */
365 DC390_Interrupt(irq
, dev_id
, regs
);
366 DEBUG1(printk(".. IRQ returned\n");
370 void dc390_DataOut_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
374 ULONG ResidCnt
, xferCnt
;
379 if (!(pSRB
->SRBState
& SRB_XFERPAD
)) {
380 if (sstatus
& (PARITY_ERR
| ILLEGAL_OP_ERR
))
381 pSRB
->SRBStatus
|= PARITY_ERROR
;
383 if (sstatus
& COUNT_2_ZERO
) {
384 int ctr
= 5000000; /* only try for about a tenth of a second */
385 while (--ctr
&& !((dstate
= DC390_read8(DMA_Status
)) & DMA_XFER_DONE
) && pSRB
->SGToBeXferLen
);
387 printk(KERN_CRIT
"DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr
));
388 dc390_laststatus
&= ~0xff000000;
389 dc390_laststatus
|= dstate
<< 24;
390 pSRB
->TotalXferredLen
+= pSRB
->SGToBeXferLen
;
392 if (pSRB
->SGIndex
< pSRB
->SGcount
) {
393 pSRB
->pSegmentList
++;
394 psgl
= pSRB
->pSegmentList
;
396 pSRB
->SGBusAddr
= virt_to_bus(psgl
->address
);
397 pSRB
->SGToBeXferLen
= (ULONG
) psgl
->length
;
399 pSRB
->SGToBeXferLen
= 0;
401 ResidCnt
= (ULONG
) DC390_read8(Current_Fifo
) & 0x1f;
402 ResidCnt
|= (ULONG
) DC390_read8(CtcReg_High
) << 16;
403 ResidCnt
|= (ULONG
) DC390_read8(CtcReg_Mid
) << 8;
404 ResidCnt
+= (ULONG
) DC390_read8(CtcReg_Low
);
406 xferCnt
= pSRB
->SGToBeXferLen
- ResidCnt
;
407 pSRB
->SGBusAddr
+= xferCnt
;
408 pSRB
->TotalXferredLen
+= xferCnt
;
409 pSRB
->SGToBeXferLen
= ResidCnt
;
412 DC390_write8(DMA_Cmd
, WRITE_DIRECTION
+ DMA_IDLE_CMD
); /* | DMA_INT */
415 void dc390_DataIn_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
417 UCHAR sstatus
, residual
, bval
;
419 ULONG ResidCnt
, xferCnt
, i
;
424 if (!(pSRB
->SRBState
& SRB_XFERPAD
)) {
425 if (sstatus
& (PARITY_ERR
| ILLEGAL_OP_ERR
))
426 pSRB
->SRBStatus
|= PARITY_ERROR
;
428 if (sstatus
& COUNT_2_ZERO
) {
429 int ctr
= 5000000; /* only try for about a tenth of a second */
431 while (--ctr
&& !((dstate
= DC390_read8(DMA_Status
)) & DMA_XFER_DONE
) && pSRB
->SGToBeXferLen
);
433 printk(KERN_CRIT
"DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr
));
435 printk(KERN_CRIT
"DC390: DataIn_0: DMA State: %i\n", dstate
);
436 dc390_laststatus
&= ~0xff000000;
437 dc390_laststatus
|= dstate
<< 24;
438 DEBUG1(ResidCnt
= ((ULONG
) DC390_read8(CtcReg_High
) << 16) \
439 +((ULONG
) DC390_read8(CtcReg_Mid
) << 8) \
440 +((ULONG
) DC390_read8(CtcReg_Low
));
442 DEBUG1(printk(KERN_DEBUG
"Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt
, pSRB
->SGToBeXferLen
);
444 DC390_write8(DMA_Cmd
, READ_DIRECTION
+ DMA_IDLE_CMD
); /* | DMA_INT */
446 pSRB
->TotalXferredLen
+= pSRB
->SGToBeXferLen
;
448 if (pSRB
->SGIndex
< pSRB
->SGcount
) {
449 pSRB
->pSegmentList
++;
450 psgl
= pSRB
->pSegmentList
;
452 pSRB
->SGBusAddr
= virt_to_bus(psgl
->address
);
453 pSRB
->SGToBeXferLen
= (ULONG
) psgl
->length
;
455 pSRB
->SGToBeXferLen
= 0;
456 } else { /* phase changed */
458 bval
= DC390_read8(Current_Fifo
);
459 while (bval
& 0x1f) {
460 DEBUG1(printk(KERN_DEBUG
"Check for residuals,");
462 if ((bval
& 0x1f) == 1) {
463 for (i
= 0; i
< 0x100; i
++) {
464 bval
= DC390_read8(Current_Fifo
);
467 else if (i
== 0x0ff) {
468 residual
= 1; /* ;1 residual byte */
473 bval
= DC390_read8(Current_Fifo
);
476 DC390_write8(DMA_Cmd
, READ_DIRECTION
+ DMA_BLAST_CMD
);
477 for (i
= 0xa000; i
; i
--) {
478 bval
= DC390_read8(DMA_Status
);
479 if (bval
& BLAST_COMPLETE
)
482 /* It seems a DMA Blast abort isn't that bad ... */
484 printk(KERN_ERR
"DC390: DMA Blast aborted unfinished!\n");
485 //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
486 dc390_laststatus
&= ~0xff000000;
487 dc390_laststatus
|= bval
<< 24;
489 DEBUG1(printk(KERN_DEBUG
"Blast: Read %li times DMA_Status %02x", 0xa000 - i
, bval
);
491 ResidCnt
= (ULONG
) DC390_read8(CtcReg_High
);
493 ResidCnt
|= (ULONG
) DC390_read8(CtcReg_Mid
);
495 ResidCnt
|= (ULONG
) DC390_read8(CtcReg_Low
);
497 xferCnt
= pSRB
->SGToBeXferLen
- ResidCnt
;
498 pSRB
->SGBusAddr
+= xferCnt
;
499 pSRB
->TotalXferredLen
+= xferCnt
;
500 pSRB
->SGToBeXferLen
= ResidCnt
;
503 bval
= DC390_read8(ScsiFifo
); /* get one residual byte */
504 ptr
= (PUCHAR
) bus_to_virt(pSRB
->SGBusAddr
);
508 pSRB
->TotalXferredLen
++;
509 pSRB
->SGToBeXferLen
--;
511 DEBUG1(printk(KERN_DEBUG
"Xfered: %li, Total: %li, Remaining: %li\n", xferCnt
, \
512 pSRB
->TotalXferredLen
, pSRB
->SGToBeXferLen
);
518 static void dc390_Command_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
522 static void dc390_Status_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
525 pSRB
->TargetStatus
= DC390_read8(ScsiFifo
);
527 pSRB
->EndMessage
= DC390_read8(ScsiFifo
); /* get message */
529 *psstatus
= SCSI_NOP0
;
530 pSRB
->SRBState
= SRB_COMPLETED
;
531 DC390_write8(ScsiCmd
, MSG_ACCEPTED_CMD
);
534 static void dc390_MsgOut_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
536 if (pSRB
->SRBState
& (SRB_UNEXPECT_RESEL
+ SRB_ABORT_SENT
))
537 *psstatus
= SCSI_NOP0
;
538 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
542 static void __inline__
543 dc390_reprog(PACB pACB
, PDCB pDCB
)
545 DC390_write8(Sync_Period
, pDCB
->SyncPeriod
);
546 DC390_write8(Sync_Offset
, pDCB
->SyncOffset
);
547 DC390_write8(CtrlReg3
, pDCB
->CtrlR3
);
548 DC390_write8(CtrlReg4
, pDCB
->CtrlR4
);
549 dc390_SetXferRate(pACB
, pDCB
);
554 static void dc390_printMsg(UCHAR
* MsgBuf
, UCHAR len
)
557 printk(" %02x", MsgBuf
[0]);
558 for (i
= 1; i
< len
; i
++)
559 printk(" %02x", MsgBuf
[i
]);
564 #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
567 static void __inline__
568 dc390_MsgIn_reject(PACB pACB
, PSRB pSRB
)
570 pSRB
->MsgOutBuf
[0] = MSG_REJECT_
;
573 DEBUG0(printk(KERN_INFO
"DC390: Reject message\n");
578 static void __inline__
579 dc390_EnableMsgOut_Abort(PACB pACB
, PSRB pSRB
)
581 pSRB
->MsgOutBuf
[0] = MSG_ABORT
;
584 pSRB
->pSRBDCB
->DCBFlag
&= ~ABORT_DEV_
;
588 dc390_MsgIn_QTag(PACB pACB
, PDCB pDCB
, UCHAR tag
)
590 PSRB lastSRB
= pDCB
->pGoingLast
;
591 PSRB pSRB
= pDCB
->pGoingSRB
;
595 if (pSRB
->TagNumber
== tag
)
599 pSRB
= pSRB
->pNextSRB
;
602 if (pDCB
->DCBFlag
& ABORT_DEV_
) {
603 pSRB
->SRBState
= SRB_ABORT_SENT
;
604 dc390_EnableMsgOut_Abort(pACB
, pSRB
);
606 if (!(pSRB
->SRBState
& SRB_DISCONNECT
))
609 pDCB
->pActiveSRB
= pSRB
;
610 pSRB
->SRBState
= SRB_DATA_XFER
;
613 pSRB
= pACB
->pTmpSRB
;
614 pSRB
->SRBState
= SRB_UNEXPECT_RESEL
;
615 pDCB
->pActiveSRB
= pSRB
;
616 pSRB
->MsgOutBuf
[0] = MSG_ABORT_TAG
;
624 /* set async transfer mode */
625 static void dc390_MsgIn_set_async(PACB pACB
, PSRB pSRB
)
627 PDCB pDCB
= pSRB
->pSRBDCB
;
628 if (!(pSRB
->SRBState
& DO_SYNC_NEGO
))
629 printk("DC390: Target %i initiates Non-Sync?\n", pDCB
->UnitSCSIID
);
630 pSRB
->SRBState
&= ~DO_SYNC_NEGO
;
631 pDCB
->SyncMode
&= ~(SYNC_ENABLE
+ SYNC_NEGO_DONE
);
632 pDCB
->SyncPeriod
= 0;
633 pDCB
->SyncOffset
= 0;
634 //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
635 pDCB
->CtrlR3
= FAST_CLK
; /* fast clock / normal scsi */
636 pDCB
->CtrlR4
&= 0x3f;
637 pDCB
->CtrlR4
|= pACB
->glitch_cfg
; /* glitch eater */
638 dc390_reprog(pACB
, pDCB
);
641 /* set sync transfer mode */
642 static void dc390_MsgIn_set_sync(PACB pACB
, PSRB pSRB
)
646 PDCB pDCB
= pSRB
->pSRBDCB
;
647 UCHAR oldsyncperiod
= pDCB
->SyncPeriod
;
648 UCHAR oldsyncoffset
= pDCB
->SyncOffset
;
650 if (!(pSRB
->SRBState
& DO_SYNC_NEGO
)) {
651 printk("DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
652 pDCB
->UnitSCSIID
, pSRB
->MsgInBuf
[3] << 2, pSRB
->MsgInBuf
[4]);
655 //dc390_MsgIn_reject (pACB, pSRB);
656 //return dc390_MsgIn_set_async (pACB, pSRB);
658 /* Reply with corrected SDTR Message */
659 if (pSRB
->MsgInBuf
[4] > 15) {
660 printk("DC390: Lower Sync Offset to 15\n");
661 pSRB
->MsgInBuf
[4] = 15;
663 if (pSRB
->MsgInBuf
[3] < pDCB
->NegoPeriod
) {
664 printk("DC390: Set sync nego period to %ins\n", pDCB
->NegoPeriod
<< 2);
665 pSRB
->MsgInBuf
[3] = pDCB
->NegoPeriod
;
667 memcpy(pSRB
->MsgOutBuf
, pSRB
->MsgInBuf
, 5);
672 pSRB
->SRBState
&= ~DO_SYNC_NEGO
;
673 pDCB
->SyncMode
|= SYNC_ENABLE
+ SYNC_NEGO_DONE
;
674 pDCB
->SyncOffset
&= 0x0f0;
675 pDCB
->SyncOffset
|= pSRB
->MsgInBuf
[4];
676 pDCB
->NegoPeriod
= pSRB
->MsgInBuf
[3];
678 wval
= (USHORT
) pSRB
->MsgInBuf
[3];
681 wval1
= wval
/ 25; /* compute speed */
682 if ((wval1
* 25) != wval
)
684 bval
= FAST_CLK
+ FAST_SCSI
; /* fast clock / fast scsi */
686 pDCB
->CtrlR4
&= 0x3f; /* Glitch eater: 12ns less than normal */
687 if (pACB
->glitch_cfg
!= NS_TO_GLITCH(0))
688 pDCB
->CtrlR4
|= NS_TO_GLITCH(((GLITCH_TO_NS(pACB
->glitch_cfg
)) - 1));
690 pDCB
->CtrlR4
|= NS_TO_GLITCH(0);
692 pDCB
->CtrlR4
|= NS_TO_GLITCH(0); /* Ultra */
695 wval1
--; /* Timing computation differs by 1 from FAST_SCSI */
696 bval
= FAST_CLK
; /* fast clock / normal scsi */
697 pDCB
->CtrlR4
|= pACB
->glitch_cfg
; /* glitch eater */
700 pDCB
->SyncPeriod
= (UCHAR
) wval1
;
702 if ((oldsyncperiod
!= wval1
|| oldsyncoffset
!= pDCB
->SyncOffset
) && pDCB
->UnitSCSILUN
== 0) {
703 if (!(bval
& FAST_SCSI
))
705 printk("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB
->UnitSCSIID
,
706 40 / wval1
, ((40 % wval1
) * 10 + wval1
/ 2) / wval1
, pDCB
->SyncOffset
& 0x0f);
708 dc390_reprog(pACB
, pDCB
);
712 /* According to the docs, the AM53C974 reads the message and
713 * generates a Succesful Operation IRQ before asserting ACK for
714 * the last byte (how does it know whether it's the last ?) */
715 /* The old code handled it in another way, indicating, that on
716 * every message byte an IRQ is generated and every byte has to
717 * be manually ACKed. Hmmm ? (KG, 98/11/28) */
718 /* The old implementation was correct. Sigh! */
720 /* Check if the message is complete */
721 static UCHAR __inline__
722 dc390_MsgIn_complete(UCHAR
* msgbuf
, ULONG len
)
724 if (*msgbuf
== MSG_EXTENDED
) {
727 if (len
< msgbuf
[1] + 2)
729 } else if (*msgbuf
>= 0x20 && *msgbuf
<= 0x2f) // two byte messages
738 /* read and eval received messages */
739 void dc390_MsgIn_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
741 PDCB pDCB
= pACB
->pActiveDCB
;
745 pSRB
->MsgInBuf
[pACB
->MsgLen
++] = DC390_read8(ScsiFifo
);
746 //pSRB->SRBState = 0;
749 if (dc390_MsgIn_complete(pSRB
->MsgInBuf
, pACB
->MsgLen
)) {
750 DEBUG0(printk(KERN_INFO
"DC390: MsgIn:");
751 dc390_printMsg(pSRB
->MsgInBuf
, pACB
->MsgLen
);
753 /* Now eval the msg */
754 switch (pSRB
->MsgInBuf
[0]) {
756 pSRB
->SRBState
= SRB_DISCONNECT
;
759 case MSG_SIMPLE_QTAG
:
762 pSRB
= dc390_MsgIn_QTag(pACB
, pDCB
, pSRB
->MsgInBuf
[1]);
766 DC390_write8(ScsiCmd
, RESET_ATN_CMD
);
767 pDCB
->NegoPeriod
= 50; /* 200ns <=> 5 MHz */
768 if (pSRB
->SRBState
& DO_SYNC_NEGO
)
769 dc390_MsgIn_set_async(pACB
, pSRB
);
773 /* reject every extended msg but SDTR */
774 if (pSRB
->MsgInBuf
[1] != 3 || pSRB
->MsgInBuf
[2] != EXTENDED_SDTR
)
775 dc390_MsgIn_reject(pACB
, pSRB
);
777 if (pSRB
->MsgInBuf
[3] == 0 || pSRB
->MsgInBuf
[4] == 0)
778 dc390_MsgIn_set_async(pACB
, pSRB
);
780 dc390_MsgIn_set_sync(pACB
, pSRB
);
783 // nothing has to be done
787 // SAVE POINTER my be ignored as we have the PSRB associated with the
788 // scsi command. Thanks, Gerard, for pointing it out.
791 // The device might want to restart transfer with a RESTORE
792 case MSG_RESTORE_PTR
:
793 printk("DC390: RESTORE POINTER message received ... reject\n");
796 // reject unknown messages
798 dc390_MsgIn_reject(pACB
, pSRB
);
801 /* Clear counter and MsgIn state */
802 pSRB
->SRBState
&= ~SRB_MSGIN
;
806 *psstatus
= SCSI_NOP0
;
807 DC390_write8(ScsiCmd
, MSG_ACCEPTED_CMD
);
808 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
812 void dc390_DataIO_Comm(PACB pACB
, PSRB pSRB
, UCHAR ioDir
)
817 if (pSRB
->SGIndex
< pSRB
->SGcount
) {
818 DC390_write8(DMA_Cmd
, DMA_IDLE_CMD
| ioDir
/* | DMA_INT */ );
819 if (!pSRB
->SGToBeXferLen
) {
820 psgl
= pSRB
->pSegmentList
;
821 pSRB
->SGBusAddr
= virt_to_bus(psgl
->address
);
822 pSRB
->SGToBeXferLen
= (ULONG
) psgl
->length
;
823 DEBUG1(printk(KERN_DEBUG
" DC390: Next SG segment.");
826 lval
= pSRB
->SGToBeXferLen
;
827 DEBUG1(printk(KERN_DEBUG
" DC390: Transfer %li bytes (address %08lx)\n", lval
, pSRB
->SGBusAddr
);
829 DC390_write8(CtcReg_Low
, (UCHAR
) lval
);
831 DC390_write8(CtcReg_Mid
, (UCHAR
) lval
);
833 DC390_write8(CtcReg_High
, (UCHAR
) lval
);
835 DC390_write32(DMA_XferCnt
, pSRB
->SGToBeXferLen
);
836 DC390_write32(DMA_XferAddr
, pSRB
->SGBusAddr
);
838 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
839 pSRB
->SRBState
= SRB_DATA_XFER
;
841 DC390_write8(ScsiCmd
, DMA_COMMAND
+ INFO_XFER_CMD
);
843 DC390_write8(DMA_Cmd
, DMA_START_CMD
| ioDir
| DMA_INT
);
844 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);)
845 //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
846 //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);)
847 } else { /* xfer pad */
849 pSRB
->AdaptStatus
= H_OVER_UNDER_RUN
;
850 pSRB
->SRBStatus
|= OVER_RUN
;
851 DEBUG0(printk(KERN_WARNING
" DC390: Overrun -");
854 DEBUG0(printk(KERN_WARNING
" Clear transfer pad \n");
856 DC390_write8(CtcReg_Low
, 0);
857 DC390_write8(CtcReg_Mid
, 0);
858 DC390_write8(CtcReg_High
, 0);
860 pSRB
->SRBState
|= SRB_XFERPAD
;
861 DC390_write8(ScsiCmd
, DMA_COMMAND
+ XFER_PAD_BYTE
);
863 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
864 DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
870 static void dc390_DataOutPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
872 dc390_DataIO_Comm(pACB
, pSRB
, WRITE_DIRECTION
);
875 static void dc390_DataInPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
877 dc390_DataIO_Comm(pACB
, pSRB
, READ_DIRECTION
);
880 void dc390_CommandPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
886 DC390_write8(ScsiCmd
, RESET_ATN_CMD
);
887 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
888 if (!(pSRB
->SRBFlag
& AUTO_REQSENSE
)) {
889 cnt
= (UCHAR
) pSRB
->ScsiCmdLen
;
890 ptr
= (PUCHAR
) pSRB
->CmdBlock
;
891 for (i
= 0; i
< cnt
; i
++)
892 DC390_write8(ScsiFifo
, *(ptr
++));
895 DC390_write8(ScsiFifo
, REQUEST_SENSE
);
896 pDCB
= pACB
->pActiveDCB
;
897 DC390_write8(ScsiFifo
, pDCB
->IdentifyMsg
<< 5);
898 DC390_write8(ScsiFifo
, bval
);
899 DC390_write8(ScsiFifo
, bval
);
900 DC390_write8(ScsiFifo
, sizeof(pSRB
->pcmd
->sense_buffer
));
901 DC390_write8(ScsiFifo
, bval
);
903 pSRB
->SRBState
= SRB_COMMAND
;
904 DC390_write8(ScsiCmd
, INFO_XFER_CMD
);
907 static void dc390_StatusPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
909 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
910 pSRB
->SRBState
= SRB_STATUS
;
911 DC390_write8(ScsiCmd
, INITIATOR_CMD_CMPLTE
);
912 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
915 void dc390_MsgOutPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
921 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
922 pDCB
= pACB
->pActiveDCB
;
923 if (!(pSRB
->SRBState
& SRB_MSGOUT
)) {
926 ptr
= (PUCHAR
) pSRB
->MsgOutBuf
;
927 for (i
= 0; i
< cnt
; i
++)
928 DC390_write8(ScsiFifo
, *(ptr
++));
930 if ((pDCB
->DCBFlag
& ABORT_DEV_
) &&
931 (pSRB
->MsgOutBuf
[0] == MSG_ABORT
))
932 pSRB
->SRBState
= SRB_ABORT_SENT
;
934 bval
= MSG_ABORT
; /* ??? MSG_NOP */
935 if ((pSRB
->CmdBlock
[0] == INQUIRY
) ||
936 (pSRB
->CmdBlock
[0] == REQUEST_SENSE
) ||
937 (pSRB
->SRBFlag
& AUTO_REQSENSE
)) {
938 if (pDCB
->SyncMode
& SYNC_ENABLE
)
941 DC390_write8(ScsiFifo
, bval
);
943 DC390_write8(ScsiCmd
, INFO_XFER_CMD
);
946 //printk ("DC390: Send SDTR message to %i %i ... \n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
947 DC390_write8(ScsiFifo
, MSG_EXTENDED
);
948 DC390_write8(ScsiFifo
, 3); /* ;length of extended msg */
949 DC390_write8(ScsiFifo
, EXTENDED_SDTR
); /* ; sync nego */
950 DC390_write8(ScsiFifo
, pDCB
->NegoPeriod
);
951 if (pDCB
->SyncOffset
& 0x0f)
952 DC390_write8(ScsiFifo
, pDCB
->SyncOffset
);
954 DC390_write8(ScsiFifo
, SYNC_NEGO_OFFSET
);
955 pSRB
->SRBState
|= DO_SYNC_NEGO
;
956 DC390_write8(ScsiCmd
, INFO_XFER_CMD
);
960 static void dc390_MsgInPhase(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
962 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
963 if (!(pSRB
->SRBState
& SRB_MSGIN
)) {
964 pSRB
->SRBState
&= ~SRB_DISCONNECT
;
965 pSRB
->SRBState
|= SRB_MSGIN
;
967 DC390_write8(ScsiCmd
, INFO_XFER_CMD
);
968 //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
971 static void dc390_Nop_0(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
975 static void dc390_Nop_1(PACB pACB
, PSRB pSRB
, PUCHAR psstatus
)
980 static void dc390_SetXferRate(PACB pACB
, PDCB pDCB
)
985 if (!(pDCB
->IdentifyMsg
& 0x07)) {
986 if (pACB
->scan_devices
) {
987 dc390_CurrSyncOffset
= pDCB
->SyncOffset
;
989 ptr
= pACB
->pLinkDCB
;
991 bval
= pDCB
->UnitSCSIID
;
992 for (i
= 0; i
< cnt
; i
++) {
993 if (ptr
->UnitSCSIID
== bval
) {
994 ptr
->SyncPeriod
= pDCB
->SyncPeriod
;
995 ptr
->SyncOffset
= pDCB
->SyncOffset
;
996 ptr
->CtrlR3
= pDCB
->CtrlR3
;
997 ptr
->CtrlR4
= pDCB
->CtrlR4
;
998 ptr
->SyncMode
= pDCB
->SyncMode
;
1000 ptr
= ptr
->pNextDCB
;
1008 void dc390_Disconnect(PACB pACB
)
1014 DEBUG0(printk(KERN_INFO
"DISC,");
1016 pDCB
= pACB
->pActiveDCB
;
1019 DEBUG0(printk(KERN_WARNING
"ACB:%08lx->ActiveDCB:%08lx IOPort:%04x IRQ:%02x !\n", \
1020 (ULONG
) pACB
, (ULONG
) pDCB
, pACB
->IOPortBase
, pACB
->IRQLevel
);
1024 DC390_read8(INT_Status
); /* Reset Pending INT */
1025 DC390_write8(ScsiCmd
, EN_SEL_RESEL
);
1028 pSRB
= pDCB
->pActiveSRB
;
1029 pACB
->pActiveDCB
= 0;
1030 pSRB
->ScsiPhase
= SCSI_NOP0
;
1031 DC390_write8(ScsiCmd
, EN_SEL_RESEL
);
1032 if (pSRB
->SRBState
& SRB_UNEXPECT_RESEL
) {
1034 dc390_DoWaitingSRB(pACB
);
1035 } else if (pSRB
->SRBState
& SRB_ABORT_SENT
) {
1038 cnt
= pDCB
->GoingSRBCnt
;
1039 pDCB
->GoingSRBCnt
= 0;
1040 pSRB
= pDCB
->pGoingSRB
;
1041 for (i
= 0; i
< cnt
; i
++) {
1042 psrb
= pSRB
->pNextSRB
;
1043 pSRB
->pNextSRB
= pACB
->pFreeSRB
;
1044 pACB
->pFreeSRB
= pSRB
;
1047 pDCB
->pGoingSRB
= 0;
1048 dc390_DoWaitingSRB(pACB
);
1050 if ((pSRB
->SRBState
& (SRB_START_
+ SRB_MSGOUT
)) ||
1051 !(pSRB
->SRBState
& (SRB_DISCONNECT
+ SRB_COMPLETED
))) { /* Selection time out */
1052 if (!(pACB
->scan_devices
)) {
1053 pSRB
->SRBState
= SRB_READY
;
1054 dc390_RewaitSRB(pDCB
, pSRB
);
1056 pSRB
->TargetStatus
= SCSI_STAT_SEL_TIMEOUT
;
1059 } else if (pSRB
->SRBState
& SRB_DISCONNECT
) {
1060 dc390_DoWaitingSRB(pACB
);
1061 } else if (pSRB
->SRBState
& SRB_COMPLETED
) {
1063 if (pDCB
->MaxCommand
> 1) {
1064 pDCB
->TagMask
&= (~(1 << pSRB
->TagNumber
)); /* free tag mask */
1066 pDCB
->pActiveSRB
= 0;
1067 pSRB
->SRBState
= SRB_FREE
;
1068 dc390_SRBdone(pACB
, pDCB
, pSRB
);
1075 void dc390_Reselect(PACB pACB
)
1082 DEBUG0(printk(KERN_INFO
"RSEL,");
1084 pDCB
= pACB
->pActiveDCB
;
1085 if (pDCB
) { /* Arbitration lost but Reselection won */
1086 DEBUG0(printk("(ActiveDCB != 0)");
1088 pSRB
= pDCB
->pActiveSRB
;
1089 if (!(pACB
->scan_devices
)) {
1090 pSRB
->SRBState
= SRB_READY
;
1091 dc390_RewaitSRB(pDCB
, pSRB
);
1094 bval
= DC390_read8(ScsiFifo
); /* get ID */
1095 DEBUG0(printk("Dev %02x,", bval
);
1097 bval
^= 1 << pACB
->pScsiHost
->this_id
; /* Mask AdapterID */
1101 wval
|= ((USHORT
) DC390_read8(ScsiFifo
) & 7) << 8; /* get LUN */
1102 DEBUG0(printk("(ID %02x, LUN %02x),", wval
& 0xff, (wval
& 0xff00) >> 8);
1104 pDCB
= pACB
->pLinkDCB
;
1105 while (wval
!= *((PUSHORT
) & pDCB
->UnitSCSIID
)) {
1106 pDCB
= pDCB
->pNextDCB
;
1107 if (pDCB
== pACB
->pLinkDCB
) {
1108 printk(KERN_ERR
"DC390: Reselect from non existing device (ID %02x, LUN %02x)\n",
1109 wval
& 0xff, (wval
& 0xff00) >> 8);
1113 pACB
->pActiveDCB
= pDCB
;
1114 if (pDCB
->SyncMode
& EN_TAG_QUEUEING
) {
1115 pSRB
= pACB
->pTmpSRB
; /* ?? */
1116 pDCB
->pActiveSRB
= pSRB
;
1118 pSRB
= pDCB
->pActiveSRB
;
1119 if (!pSRB
|| !(pSRB
->SRBState
& SRB_DISCONNECT
)) {
1120 pSRB
= pACB
->pTmpSRB
;
1121 pSRB
->SRBState
= SRB_UNEXPECT_RESEL
;
1122 printk(KERN_ERR
"DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n",
1123 wval
& 0xff, (wval
& 0xff00) >> 8);
1124 pDCB
->pActiveSRB
= pSRB
;
1125 dc390_EnableMsgOut_Abort(pACB
, pSRB
);
1127 if (pDCB
->DCBFlag
& ABORT_DEV_
) {
1128 pSRB
->SRBState
= SRB_ABORT_SENT
;
1129 printk(KERN_INFO
"DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
1130 wval
& 0xff, (wval
& 0xff00) >> 8);
1131 dc390_EnableMsgOut_Abort(pACB
, pSRB
);
1133 pSRB
->SRBState
= SRB_DATA_XFER
;
1137 DEBUG1(printk(KERN_DEBUG
"Resel SRB(%p): TagNum (%02x)\n", pSRB
, pSRB
->TagNumber
);
1139 pSRB
->ScsiPhase
= SCSI_NOP0
;
1140 DC390_write8(Scsi_Dest_ID
, pDCB
->UnitSCSIID
);
1141 DC390_write8(Sync_Period
, pDCB
->SyncPeriod
);
1142 DC390_write8(Sync_Offset
, pDCB
->SyncOffset
);
1143 DC390_write8(CtrlReg1
, pDCB
->CtrlR1
);
1144 DC390_write8(CtrlReg3
, pDCB
->CtrlR3
);
1145 DC390_write8(CtrlReg4
, pDCB
->CtrlR4
); /* ; Glitch eater */
1146 DC390_write8(ScsiCmd
, MSG_ACCEPTED_CMD
); /* ;to release the /ACK signal */
1150 static void dc390_remove_dev(PACB pACB
, PDCB pDCB
)
1152 PDCB pPrevDCB
= pACB
->pLinkDCB
;
1154 pACB
->DCBmap
[pDCB
->UnitSCSIID
] &= ~(1 << pDCB
->UnitSCSILUN
);
1155 if (pDCB
->GoingSRBCnt
> 1) {
1156 DCBDEBUG(printk(KERN_INFO
"DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n", \
1157 pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
, (int) pDCB
, pDCB
->GoingSRBCnt
);
1162 if (pDCB
== pACB
->pLinkDCB
) {
1163 if (pDCB
->pNextDCB
== pDCB
)
1165 pACB
->pLinkDCB
= pDCB
->pNextDCB
;
1166 pACB
->pLastDCB
->pNextDCB
= pDCB
->pNextDCB
;
1168 while (pPrevDCB
->pNextDCB
!= pDCB
)
1169 pPrevDCB
= pPrevDCB
->pNextDCB
;
1170 pPrevDCB
->pNextDCB
= pDCB
->pNextDCB
;
1171 if (pDCB
== pACB
->pLastDCB
)
1172 pACB
->pLastDCB
= pPrevDCB
;
1175 DCBDEBUG(printk(KERN_INFO
"DC390: Driver about to free DCB (ID %i, LUN %i): 0x%08x\n", \
1176 pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
, (int) pDCB
);
1179 if (pDCB
== pACB
->pActiveDCB
)
1180 pACB
->pActiveDCB
= 0;
1182 /* pACB->DeviceCnt--; */
1186 static UCHAR __inline__
1187 dc390_tagq_blacklist(char *name
)
1190 for (i
= 0; i
< BADDEVCNT
; i
++)
1191 if (memcmp(name
, dc390_baddevname1
[i
], 28) == 0)
1197 static void dc390_disc_tagq_set(PDCB pDCB
, PSCSI_INQDATA ptr
)
1199 /* Check for SCSI format (ANSI and Response data format) */
1200 if ((ptr
->Vers
& 0x07) >= 2 || (ptr
->RDF
& 0x0F) == 2) {
1201 if ((ptr
->Flags
& SCSI_INQ_CMDQUEUE
) &&
1202 (pDCB
->DevMode
& TAG_QUEUEING_
) &&
1203 /* ((pDCB->DevType == TYPE_DISK)
1204 || (pDCB->DevType == TYPE_MOD)) && */
1205 !dc390_tagq_blacklist(((char *) ptr
) + 8)) {
1206 pDCB
->MaxCommand
= pDCB
->pDCBACB
->TagMaxNum
;
1207 pDCB
->SyncMode
|= EN_TAG_QUEUEING
/* | EN_ATN_STOP */ ;
1210 /* Do we really need to check for DevType here ? */
1211 if (0 /*(pDCB->DevMode & EN_DISCONNECT_) */
1212 /* && ((pDCB->DevType == TYPE_DISK)
1213 || (pDCB->DevType == TYPE_MOD)) */ )
1214 pDCB
->SyncMode
|= EN_ATN_STOP
;
1216 //pDCB->SyncMode &= ~EN_ATN_STOP;
1217 pDCB
->SyncMode
&= ~0;
1223 static void dc390_add_dev(PACB pACB
, PDCB pDCB
, PSCSI_INQDATA ptr
)
1225 UCHAR bval1
= ptr
->DevType
& SCSI_DEVTYPE
;
1226 pDCB
->DevType
= bval1
;
1227 /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
1228 dc390_disc_tagq_set(pDCB
, ptr
);
1232 void dc390_SRBdone(PACB pACB
, PDCB pDCB
, PSRB pSRB
)
1235 UCHAR bval
, status
, i
;
1242 status
= pSRB
->TargetStatus
;
1243 DEBUG0(printk(" SRBdone (%02x,%08x), SRB %p, pid %li\n", status
, pcmd
->result
, \
1246 if (pSRB
->SRBFlag
& AUTO_REQSENSE
) { /* Last command was a Request Sense */
1247 pSRB
->SRBFlag
&= ~AUTO_REQSENSE
;
1248 pSRB
->AdaptStatus
= 0;
1249 pSRB
->TargetStatus
= SCSI_STAT_CHECKCOND
;
1250 #ifdef DC390_REMOVABLEDEBUG
1251 switch (pcmd
->sense_buffer
[2] & 0x0f) {
1253 printk(KERN_INFO
"DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1254 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
,
1255 status
, pACB
->scan_devices
);
1257 case UNIT_ATTENTION
:
1258 printk(KERN_INFO
"DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1259 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
,
1260 status
, pACB
->scan_devices
);
1262 case ILLEGAL_REQUEST
:
1263 printk(KERN_INFO
"DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1264 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
,
1265 status
, pACB
->scan_devices
);
1268 printk(KERN_INFO
"DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1269 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
,
1270 status
, pACB
->scan_devices
);
1272 case HARDWARE_ERROR
:
1273 printk(KERN_INFO
"DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1274 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
,
1275 status
, pACB
->scan_devices
);
1279 //pcmd->result = DRIVER_SENSE << 24 | DID_OK << 16 | status;
1280 if (status
== SCSI_STAT_CHECKCOND
) {
1281 pcmd
->result
= DID_BAD_TARGET
<< 16;
1284 if (pSRB
->RetryCnt
== 0) {
1285 (ULONG
) (pSRB
->CmdBlock
[0]) = pSRB
->Segment0
[0];
1286 pSRB
->TotalXferredLen
= pSRB
->Segment1
[1];
1287 if ((pSRB
->TotalXferredLen
) &&
1288 (pSRB
->TotalXferredLen
>= pcmd
->underflow
))
1289 pcmd
->result
|= (DID_OK
<< 16);
1291 pcmd
->result
= (DRIVER_SENSE
<< 24) | (DRIVER_OK
<< 16) |
1292 SCSI_STAT_CHECKCOND
;
1293 REMOVABLEDEBUG(printk(KERN_INFO
"Cmd=%02x,Result=%08x,XferL=%08x\n", pSRB
->CmdBlock
[0], \
1294 (UINT
) pcmd
->result
, (UINT
) pSRB
->TotalXferredLen
);
1297 } else { /* Retry */
1299 pSRB
->AdaptStatus
= 0;
1300 pSRB
->TargetStatus
= 0;
1301 *((PULONG
) & (pSRB
->CmdBlock
[0])) = pSRB
->Segment0
[0];
1302 *((PULONG
) & (pSRB
->CmdBlock
[4])) = pSRB
->Segment0
[1];
1303 /* Don't retry on TEST_UNIT_READY */
1304 if (pSRB
->CmdBlock
[0] == TEST_UNIT_READY
/* || pSRB->CmdBlock[0] == START_STOP */ ) {
1305 pcmd
->result
= (DRIVER_SENSE
<< 24) | (DRIVER_OK
<< 16)
1306 | SCSI_STAT_CHECKCOND
;
1307 REMOVABLEDEBUG(printk(KERN_INFO
"Cmd=%02x, Result=%08x, XferL=%08x\n", pSRB
->CmdBlock
[0], \
1308 (UINT
) pcmd
->result
, (UINT
) pSRB
->TotalXferredLen
);
1312 pcmd
->result
|= (DRIVER_SENSE
<< 24);
1313 pSRB
->SGcount
= (UCHAR
) pSRB
->Segment1
[0];
1314 pSRB
->ScsiCmdLen
= (UCHAR
) (pSRB
->Segment1
[0] >> 8);
1316 pSRB
->TotalXferredLen
= 0;
1317 pSRB
->SGToBeXferLen
= 0;
1319 pSRB
->pSegmentList
= (PSGL
) pcmd
->request_buffer
;
1320 else if (pcmd
->request_buffer
) {
1321 pSRB
->pSegmentList
= (PSGL
) & pSRB
->Segmentx
;
1322 pSRB
->Segmentx
.address
= (PUCHAR
) pcmd
->request_buffer
;
1323 pSRB
->Segmentx
.length
= pcmd
->request_bufflen
;
1325 if (dc390_StartSCSI(pACB
, pDCB
, pSRB
))
1326 dc390_RewaitSRB(pDCB
, pSRB
);
1331 if (status
== SCSI_STAT_CHECKCOND
) {
1332 REMOVABLEDEBUG(printk(KERN_INFO
"DC390: Scsi_Stat_CheckCond (Cmd %02x, Id %02x, LUN %02x)\n", \
1333 pcmd
->cmnd
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
);
1335 if ((pSRB
->SGIndex
< pSRB
->SGcount
) && (pSRB
->SGcount
) && (pSRB
->SGToBeXferLen
)) {
1336 bval
= pSRB
->SGcount
;
1338 ptr2
= pSRB
->pSegmentList
;
1339 for (i
= pSRB
->SGIndex
; i
< bval
; i
++) {
1340 swlval
+= ptr2
->length
;
1343 REMOVABLEDEBUG(printk(KERN_INFO
"XferredLen=%08x,NotXferLen=%08x\n", \
1344 (UINT
) pSRB
->TotalXferredLen
, (UINT
) swlval
);
1347 dc390_RequestSense(pACB
, pDCB
, pSRB
);
1349 } else if (status
== SCSI_STAT_QUEUEFULL
) {
1350 bval
= (UCHAR
) pDCB
->GoingSRBCnt
;
1352 pDCB
->MaxCommand
= bval
;
1353 dc390_RewaitSRB(pDCB
, pSRB
);
1354 pSRB
->AdaptStatus
= 0;
1355 pSRB
->TargetStatus
= 0;
1357 } else if (status
== SCSI_STAT_SEL_TIMEOUT
) {
1358 pSRB
->AdaptStatus
= H_SEL_TIMEOUT
;
1359 pSRB
->TargetStatus
= 0;
1360 pcmd
->result
= DID_BAD_TARGET
<< 16;
1361 /* Devices are removed below ... */
1362 } else if (status
== SCSI_STAT_BUSY
&&
1363 (pSRB
->CmdBlock
[0] == TEST_UNIT_READY
|| pSRB
->CmdBlock
[0] == INQUIRY
) &&
1364 pACB
->scan_devices
) {
1365 pSRB
->AdaptStatus
= 0;
1366 pSRB
->TargetStatus
= status
;
1367 pcmd
->result
= (ULONG
) (pSRB
->EndMessage
<< 8)
1368 /* | (ULONG) status */ ;
1369 } else { /* Another error */
1370 pSRB
->AdaptStatus
= 0;
1371 if (pSRB
->RetryCnt
) { /* Retry */
1373 pSRB
->TargetStatus
= 0;
1375 pSRB
->TotalXferredLen
= 0;
1376 pSRB
->SGToBeXferLen
= 0;
1378 pSRB
->pSegmentList
= (PSGL
) pcmd
->request_buffer
;
1379 else if (pcmd
->request_buffer
) {
1380 pSRB
->pSegmentList
= (PSGL
) & pSRB
->Segmentx
;
1381 pSRB
->Segmentx
.address
= (PUCHAR
) pcmd
->request_buffer
;
1382 pSRB
->Segmentx
.length
= pcmd
->request_bufflen
;
1384 if (dc390_StartSCSI(pACB
, pDCB
, pSRB
))
1385 dc390_RewaitSRB(pDCB
, pSRB
);
1387 } else { /* Report error */
1388 pcmd
->result
|= (DID_ERROR
<< 16) | (ULONG
) (pSRB
->EndMessage
<< 8) |
1392 } else { /* Target status == 0 */
1393 status
= pSRB
->AdaptStatus
;
1394 if (status
& H_OVER_UNDER_RUN
) {
1395 pSRB
->TargetStatus
= 0;
1396 pcmd
->result
|= (DID_OK
<< 16) | (pSRB
->EndMessage
<< 8);
1397 } else if (pSRB
->SRBStatus
& PARITY_ERROR
) {
1398 pcmd
->result
|= (DID_PARITY
<< 16) | (pSRB
->EndMessage
<< 8);
1399 } else { /* No error */
1400 pSRB
->AdaptStatus
= 0;
1401 pSRB
->TargetStatus
= 0;
1402 pcmd
->result
|= (DID_OK
<< 16);
1407 if (pACB
->scan_devices
) {
1408 if (pSRB
->CmdBlock
[0] == TEST_UNIT_READY
) {
1410 printk(KERN_INFO
"DC390: Test_Unit_Ready: result: %08x", pcmd
->result
);
1411 if (pcmd
->result
& DRIVER_SENSE
<< 24)
1412 printk(" (sense: %02x %02x %02x %02x)\n",
1413 pcmd
->sense_buffer
[0], pcmd
->sense_buffer
[1],
1414 pcmd
->sense_buffer
[2], pcmd
->sense_buffer
[3]);
1418 if ((pcmd
->result
!= (DID_OK
<< 16) && !(pcmd
->result
& SCSI_STAT_CHECKCOND
) && !(pcmd
->result
& SCSI_STAT_BUSY
)) ||
1419 ((pcmd
->result
& DRIVER_SENSE
<< 24) && (pcmd
->sense_buffer
[0] & 0x70) == 0x70 &&
1420 (pcmd
->sense_buffer
[2] & 0xf) == ILLEGAL_REQUEST
) || pcmd
->result
& DID_ERROR
<< 16) {
1421 /* device not present: remove */
1422 dc390_remove_dev(pACB
, pDCB
);
1424 if ((pcmd
->target
== pACB
->pScsiHost
->max_id
- 1) &&
1425 ((pcmd
->lun
== 0) || (pcmd
->lun
== pACB
->pScsiHost
->max_lun
- 1)))
1426 pACB
->scan_devices
= 0;
1428 /* device present: add */
1429 if ((pcmd
->target
== pACB
->pScsiHost
->max_id
- 1) &&
1430 (pcmd
->lun
== pACB
->pScsiHost
->max_lun
- 1))
1431 pACB
->scan_devices
= END_SCAN
;
1432 /* pACB->DeviceCnt++; *//* Dev is added on INQUIRY */
1436 if (pSRB
->CmdBlock
[0] == INQUIRY
&&
1437 (pcmd
->result
== DID_OK
<< 16 || pcmd
->result
& SCSI_STAT_CHECKCOND
)) {
1438 ptr
= (PSCSI_INQDATA
) (pcmd
->request_buffer
);
1440 ptr
= (PSCSI_INQDATA
) (((PSGL
) ptr
)->address
);
1441 if ((ptr
->DevType
& SCSI_DEVTYPE
) == TYPE_NODEV
) {
1442 /* device not present: remove */
1443 dc390_remove_dev(pACB
, pDCB
);
1445 /* device found: add */
1446 dc390_add_dev(pACB
, pDCB
, ptr
);
1447 if (pACB
->scan_devices
)
1450 if ((pcmd
->target
== pACB
->pScsiHost
->max_id
- 1) &&
1451 (pcmd
->lun
== pACB
->pScsiHost
->max_lun
- 1))
1452 pACB
->scan_devices
= 0;
1454 /* dc390_ReleaseSRB( pDCB, pSRB ); */
1456 if (pSRB
== pDCB
->pGoingSRB
) {
1457 pDCB
->pGoingSRB
= pSRB
->pNextSRB
;
1459 psrb
= pDCB
->pGoingSRB
;
1460 while (psrb
->pNextSRB
!= pSRB
)
1461 psrb
= psrb
->pNextSRB
;
1462 psrb
->pNextSRB
= pSRB
->pNextSRB
;
1463 if (pSRB
== pDCB
->pGoingLast
)
1464 pDCB
->pGoingLast
= psrb
;
1466 pSRB
->pNextSRB
= pACB
->pFreeSRB
;
1467 pACB
->pFreeSRB
= pSRB
;
1468 pDCB
->GoingSRBCnt
--;
1470 dc390_DoWaitingSRB(pACB
);
1472 DC390_UNLOCK_ACB_NI
;
1473 pcmd
->scsi_done(pcmd
);
1477 dc390_DoNextCmd(pACB
, pDCB
);
1482 /* Remove all SRBs and tell midlevel code DID_RESET */
1483 void dc390_DoingSRB_Done(PACB pACB
)
1490 pDCB
= pACB
->pLinkDCB
;
1495 psrb
= pdcb
->pGoingSRB
;
1496 for (i
= 0; i
< pdcb
->GoingSRBCnt
; i
++) {
1497 psrb2
= psrb
->pNextSRB
;
1499 pcmd
->result
= DID_RESET
<< 16;
1501 /* ReleaseSRB( pDCB, pSRB ); */
1503 psrb
->pNextSRB
= pACB
->pFreeSRB
;
1504 pACB
->pFreeSRB
= psrb
;
1506 DC390_UNLOCK_ACB_NI
;
1507 pcmd
->scsi_done(pcmd
);
1511 pdcb
->GoingSRBCnt
= 0;;
1512 pdcb
->pGoingSRB
= NULL
;
1514 pdcb
= pdcb
->pNextDCB
;
1515 } while (pdcb
!= pDCB
);
1519 static void dc390_ResetSCSIBus(PACB pACB
)
1521 pACB
->ACBFlag
|= RESET_DEV
;
1523 DC390_write8(ScsiCmd
, RST_DEVICE_CMD
);
1525 DC390_write8(ScsiCmd
, NOP_CMD
);
1527 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
1528 DC390_write8(DMA_Cmd
, DMA_IDLE_CMD
);
1529 DC390_write8(ScsiCmd
, RST_SCSI_BUS_CMD
);
1534 static void dc390_ScsiRstDetect(PACB pACB
)
1536 printk("DC390: Rst_Detect: laststat = %08lx\n", dc390_laststatus
);
1537 //DEBUG0(printk(KERN_INFO "RST_DETECT,");)
1539 DC390_write8(DMA_Cmd
, DMA_IDLE_CMD
);
1540 /* Unlock before ? */
1541 /* delay a second */
1543 unsigned int msec
= 1 * 1000;
1547 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);
1549 if (pACB
->ACBFlag
& RESET_DEV
)
1550 pACB
->ACBFlag
|= RESET_DONE
;
1552 pACB
->ACBFlag
|= RESET_DETECT
;
1554 dc390_ResetDevParam(pACB
);
1555 /* dc390_DoingSRB_Done( pACB ); ???? */
1556 dc390_RecoverSRB(pACB
);
1557 pACB
->pActiveDCB
= NULL
;
1559 dc390_DoWaitingSRB(pACB
);
1565 static void __inline__
1566 dc390_RequestSense(PACB pACB
, PDCB pDCB
, PSRB pSRB
)
1570 REMOVABLEDEBUG(printk(KERN_INFO
"DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n", \
1571 pSRB
->CmdBlock
[0], pDCB
->UnitSCSIID
, pDCB
->UnitSCSILUN
);
1573 pSRB
->SRBFlag
|= AUTO_REQSENSE
;
1574 pSRB
->Segment0
[0] = (ULONG
) pSRB
->CmdBlock
[0];
1575 pSRB
->Segment0
[1] = (ULONG
) pSRB
->CmdBlock
[4];
1576 pSRB
->Segment1
[0] = (ULONG
) ((pSRB
->ScsiCmdLen
<< 8) + pSRB
->SGcount
);
1577 pSRB
->Segment1
[1] = pSRB
->TotalXferredLen
;
1578 pSRB
->AdaptStatus
= 0;
1579 pSRB
->TargetStatus
= 0; /* SCSI_STAT_CHECKCOND; */
1583 pSRB
->Segmentx
.address
= (PUCHAR
) & (pcmd
->sense_buffer
);
1584 pSRB
->Segmentx
.length
= sizeof(pcmd
->sense_buffer
);
1585 pSRB
->pSegmentList
= &pSRB
->Segmentx
;
1589 pSRB
->CmdBlock
[0] = REQUEST_SENSE
;
1590 pSRB
->CmdBlock
[1] = pDCB
->IdentifyMsg
<< 5;
1591 (USHORT
) pSRB
->CmdBlock
[2] = 0;
1592 (USHORT
) pSRB
->CmdBlock
[4] = sizeof(pcmd
->sense_buffer
);
1593 pSRB
->ScsiCmdLen
= 6;
1595 pSRB
->TotalXferredLen
= 0;
1596 pSRB
->SGToBeXferLen
= 0;
1597 if (dc390_StartSCSI(pACB
, pDCB
, pSRB
))
1598 dc390_RewaitSRB(pDCB
, pSRB
);
1603 static void __inline__
1604 dc390_InvalidCmd(PACB pACB
)
1606 if (pACB
->pActiveDCB
->pActiveSRB
->SRBState
& (SRB_START_
+ SRB_MSGOUT
))
1607 DC390_write8(ScsiCmd
, CLEAR_FIFO_CMD
);