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