|
|
1.1 root 1: /***********************************************************************
2: * FILE NAME : SCSIIOM.C *
3: * BY : C.L. Huang, [email protected] *
4: * Description: Device Driver for Tekram DC-390 (T) PCI SCSI *
5: * Bus Master Host Adapter *
6: ***********************************************************************/
7:
8:
9: static USHORT
10: DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
11: {
12: USHORT ioport, rc;
13: UCHAR bval, bval1, i, cnt;
14: PUCHAR ptr;
15: ULONG wlval;
16:
17: pSRB->TagNumber = 31;
18: ioport = pACB->IOPortBase;
19: bval = pDCB->UnitSCSIID;
20: outb(bval,ioport+Scsi_Dest_ID);
21: bval = pDCB->SyncPeriod;
22: outb(bval,ioport+Sync_Period);
23: bval = pDCB->SyncOffset;
24: outb(bval,ioport+Sync_Offset);
25: bval = pDCB->CtrlR1;
26: outb(bval,ioport+CtrlReg1);
27: bval = pDCB->CtrlR3;
28: outb(bval,ioport+CtrlReg3);
29: bval = pDCB->CtrlR4;
30: outb(bval,ioport+CtrlReg4);
31: bval = CLEAR_FIFO_CMD; /* Flush FIFO */
32: outb(bval,ioport+ScsiCmd);
33:
34: pSRB->ScsiPhase = SCSI_NOP0;
35: bval = pDCB->IdentifyMsg;
36: if( !(pDCB->SyncMode & EN_ATN_STOP) )
37: {
38: if( (pSRB->CmdBlock[0] == INQUIRY) ||
39: (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
40: (pSRB->SRBFlag & AUTO_REQSENSE) )
41: {
42: bval &= 0xBF; /* NO disconnection */
43: outb(bval,ioport+ScsiFifo);
44: bval1 = SELECT_W_ATN;
45: pSRB->SRBState = SRB_START_;
46: if( pDCB->SyncMode & SYNC_ENABLE )
47: {
48: if( !(pDCB->IdentifyMsg & 7) ||
49: (pSRB->CmdBlock[0] != INQUIRY) )
50: {
51: bval1 = SEL_W_ATN_STOP;
52: pSRB->SRBState = SRB_MSGOUT;
53: }
54: }
55: }
56: else
57: {
58: if(pDCB->SyncMode & EN_TAG_QUEUING)
59: {
60: outb(bval,ioport+ScsiFifo);
61: bval = MSG_SIMPLE_QTAG;
62: outb(bval,ioport+ScsiFifo);
63: wlval = 1;
64: bval = 0;
65: while( wlval & pDCB->TagMask )
66: {
67: wlval = wlval << 1;
68: bval++;
69: }
70: outb(bval,ioport+ScsiFifo);
71: pDCB->TagMask |= wlval;
72: pSRB->TagNumber = bval;
73: bval1 = SEL_W_ATN2;
74: pSRB->SRBState = SRB_START_;
75: }
76: else
77: {
78: outb(bval,ioport+ScsiFifo);
79: bval1 = SELECT_W_ATN;
80: pSRB->SRBState = SRB_START_;
81: }
82: }
83:
84: if( pSRB->SRBFlag & AUTO_REQSENSE )
85: {
86: bval = REQUEST_SENSE;
87: outb(bval,ioport+ScsiFifo);
88: bval = pDCB->IdentifyMsg << 5;
89: outb(bval,ioport+ScsiFifo);
90: bval = 0;
91: outb(bval,ioport+ScsiFifo);
92: outb(bval,ioport+ScsiFifo);
93: bval = sizeof(pSRB->pcmd->sense_buffer);
94: outb(bval,ioport+ScsiFifo);
95: bval = 0;
96: outb(bval,ioport+ScsiFifo);
97: }
98: else
99: {
100: cnt = pSRB->ScsiCmdLen;
101: ptr = (PUCHAR) pSRB->CmdBlock;
102: for(i=0; i<cnt; i++)
103: {
104: bval = *ptr++;
105: outb(bval,ioport+ScsiFifo);
106: }
107: }
108: }
109: else /* ATN_STOP */
110: {
111: if( (pSRB->CmdBlock[0] == INQUIRY) ||
112: (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
113: (pSRB->SRBFlag & AUTO_REQSENSE) )
114: {
115: bval &= 0xBF;
116: outb(bval,ioport+ScsiFifo);
117: bval1 = SELECT_W_ATN;
118: pSRB->SRBState = SRB_START_;
119: if( pDCB->SyncMode & SYNC_ENABLE )
120: {
121: if( !(pDCB->IdentifyMsg & 7) ||
122: (pSRB->CmdBlock[0] != INQUIRY) )
123: {
124: bval1 = SEL_W_ATN_STOP;
125: pSRB->SRBState = SRB_MSGOUT;
126: }
127: }
128: }
129: else
130: {
131: if(pDCB->SyncMode & EN_TAG_QUEUING)
132: {
133: outb(bval,ioport+ScsiFifo);
134: pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
135: wlval = 1;
136: bval = 0;
137: while( wlval & pDCB->TagMask )
138: {
139: wlval = wlval << 1;
140: bval++;
141: }
142: pDCB->TagMask |= wlval;
143: pSRB->TagNumber = bval;
144: pSRB->MsgOutBuf[1] = bval;
145: pSRB->MsgCnt = 2;
146: bval1 = SEL_W_ATN_STOP;
147: pSRB->SRBState = SRB_START_;
148: }
149: else
150: {
151: outb(bval,ioport+ScsiFifo);
152: pSRB->MsgOutBuf[0] = MSG_NOP;
153: pSRB->MsgCnt = 1;
154: pSRB->SRBState = SRB_START_;
155: bval1 = SEL_W_ATN_STOP;
156: }
157: }
158: }
159: bval = inb( ioport+Scsi_Status );
160: if( bval & INTERRUPT )
161: {
162: pSRB->SRBState = SRB_READY;
163: pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
164: rc = 1;
165: }
166: else
167: {
168: pSRB->ScsiPhase = SCSI_NOP1;
169: pACB->pActiveDCB = pDCB;
170: pDCB->pActiveSRB = pSRB;
171: rc = 0;
172: outb(bval1,ioport+ScsiCmd);
173: }
174: return( rc );
175: }
176:
177:
178: #ifndef VERSION_ELF_1_2_13
179: static void
180: DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
181: #else
182: static void
183: DC390_Interrupt( int irq, struct pt_regs *regs)
184: #endif
185: {
186: PACB pACB;
187: PDCB pDCB;
188: PSRB pSRB;
189: USHORT ioport = 0;
190: USHORT phase, i;
191: void (*stateV)( PACB, PSRB, PUCHAR );
192: UCHAR istate = 0;
193: UCHAR sstatus=0, istatus;
194:
195: pACB = pACB_start;
196: if( pACB == NULL )
197: return;
198: for( i=0; i < adapterCnt; i++ )
199: {
200: if( pACB->IRQLevel == (UCHAR) irq )
201: {
202: ioport = pACB->IOPortBase;
203: sstatus = inb( ioport+Scsi_Status );
204: if( sstatus & INTERRUPT )
205: break;
206: else
207: pACB = pACB->pNextACB;
208: }
209: else
210: {
211: pACB = pACB->pNextACB;
212: }
213: }
214:
215: #ifdef DC390_DEBUG1
216: printk("sstatus=%2x,",sstatus);
217: #endif
218:
219: if( pACB == (PACB )-1 )
220: {
221: printk("DC390: Spurious interrupt detected!\n");
222: return;
223: }
224:
225: istate = inb( ioport+Intern_State );
226: istatus = inb( ioport+INT_Status );
227:
228: #ifdef DC390_DEBUG1
229: printk("Istatus=%2x,",istatus);
230: #endif
231:
232: if(istatus & DISCONNECTED)
233: {
234: DC390_Disconnect( pACB );
235: return;
236: }
237:
238: if(istatus & RESELECTED)
239: {
240: DC390_Reselect( pACB );
241: return;
242: }
243:
244: if(istatus & INVALID_CMD)
245: {
246: DC390_InvalidCmd( pACB );
247: return;
248: }
249:
250: if(istatus & SCSI_RESET)
251: {
252: DC390_ScsiRstDetect( pACB );
253: return;
254: }
255:
256: if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) )
257: {
258: pDCB = pACB->pActiveDCB;
259: pSRB = pDCB->pActiveSRB;
260: if( pDCB )
261: {
262: if( pDCB->DCBFlag & ABORT_DEV_ )
263: EnableMsgOut( pACB, pSRB );
264: }
265:
266: phase = (USHORT) pSRB->ScsiPhase;
267: stateV = (void *) DC390_phase0[phase];
268: stateV( pACB, pSRB, &sstatus );
269:
270: pSRB->ScsiPhase = sstatus & 7;
271: phase = (USHORT) sstatus & 7;
272: stateV = (void *) DC390_phase1[phase];
273: stateV( pACB, pSRB, &sstatus );
274: }
275: }
276:
277:
278: static void
279: DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
280: {
281: UCHAR sstatus, bval;
282: USHORT ioport;
283: PSGL psgl;
284: ULONG ResidCnt, xferCnt;
285:
286: ioport = pACB->IOPortBase;
287: sstatus = *psstatus;
288:
289: if( !(pSRB->SRBState & SRB_XFERPAD) )
290: {
291: if( sstatus & PARITY_ERR )
292: pSRB->SRBStatus |= PARITY_ERROR;
293:
294: if( sstatus & COUNT_2_ZERO )
295: {
296: bval = inb(ioport+DMA_Status);
297: while( !(bval & DMA_XFER_DONE) )
298: bval = inb(ioport+DMA_Status);
299: pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
300: pSRB->SGIndex++;
301: if( pSRB->SGIndex < pSRB->SGcount )
302: {
303: pSRB->pSegmentList++;
304: psgl = pSRB->pSegmentList;
305:
306: #ifndef VERSION_ELF_1_2_13
307: pSRB->SGPhysAddr = virt_to_phys( psgl->address );
308: #else
309: pSRB->SGPhysAddr = (ULONG) psgl->address;
310: #endif
311: pSRB->SGToBeXferLen = (ULONG) psgl->length;
312: }
313: else
314: pSRB->SGToBeXferLen = 0;
315: }
316: else
317: {
318: bval = inb( ioport+Current_Fifo );
319: bval &= 0x1f;
320: ResidCnt = (ULONG) inb(ioport+CtcReg_High);
321: ResidCnt = ResidCnt << 8;
322: ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
323: ResidCnt = ResidCnt << 8;
324: ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
325: ResidCnt += (ULONG) bval;
326:
327: xferCnt = pSRB->SGToBeXferLen - ResidCnt;
328: pSRB->SGPhysAddr += xferCnt;
329: pSRB->TotalXferredLen += xferCnt;
330: pSRB->SGToBeXferLen = ResidCnt;
331: }
332: }
333: bval = WRITE_DIRECTION+DMA_IDLE_CMD;
334: outb( bval, ioport+DMA_Cmd);
335: }
336:
337: static void
338: DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
339: {
340: UCHAR sstatus, bval;
341: USHORT i, ioport, residual;
342: PSGL psgl;
343: ULONG ResidCnt, xferCnt;
344: PUCHAR ptr;
345:
346:
347: ioport = pACB->IOPortBase;
348: sstatus = *psstatus;
349:
350: if( !(pSRB->SRBState & SRB_XFERPAD) )
351: {
352: if( sstatus & PARITY_ERR )
353: pSRB->SRBStatus |= PARITY_ERROR;
354:
355: if( sstatus & COUNT_2_ZERO )
356: {
357: bval = inb(ioport+DMA_Status);
358: while( !(bval & DMA_XFER_DONE) )
359: bval = inb(ioport+DMA_Status);
360:
361: bval = READ_DIRECTION+DMA_IDLE_CMD;
362: outb( bval, ioport+DMA_Cmd);
363:
364: pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
365: pSRB->SGIndex++;
366: if( pSRB->SGIndex < pSRB->SGcount )
367: {
368: pSRB->pSegmentList++;
369: psgl = pSRB->pSegmentList;
370:
371: #ifndef VERSION_ELF_1_2_13
372: pSRB->SGPhysAddr = virt_to_phys( psgl->address );
373: #else
374: pSRB->SGPhysAddr = (ULONG) psgl->address;
375: #endif
376: pSRB->SGToBeXferLen = (ULONG) psgl->length;
377: }
378: else
379: pSRB->SGToBeXferLen = 0;
380: }
381: else /* phase changed */
382: {
383: residual = 0;
384: bval = inb(ioport+Current_Fifo);
385: while( bval & 0x1f )
386: {
387: if( (bval & 0x1f) == 1 )
388: {
389: for(i=0; i< 0x100; i++)
390: {
391: bval = inb(ioport+Current_Fifo);
392: if( !(bval & 0x1f) )
393: goto din_1;
394: else if( i == 0x0ff )
395: {
396: residual = 1; /* ;1 residual byte */
397: goto din_1;
398: }
399: }
400: }
401: else
402: bval = inb(ioport+Current_Fifo);
403: }
404: din_1:
405: bval = READ_DIRECTION+DMA_BLAST_CMD;
406: outb(bval, ioport+DMA_Cmd);
407: for(i=0; i<0x8000; i++)
408: {
409: bval = inb(ioport+DMA_Status);
410: if(bval & BLAST_COMPLETE)
411: break;
412: }
413: bval = READ_DIRECTION+DMA_IDLE_CMD;
414: outb(bval, ioport+DMA_Cmd);
415:
416: ResidCnt = (ULONG) inb(ioport+CtcReg_High);
417: ResidCnt = ResidCnt << 8;
418: ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);
419: ResidCnt = ResidCnt << 8;
420: ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);
421:
422: xferCnt = pSRB->SGToBeXferLen - ResidCnt;
423: pSRB->SGPhysAddr += xferCnt;
424: pSRB->TotalXferredLen += xferCnt;
425: pSRB->SGToBeXferLen = ResidCnt;
426:
427: if( residual )
428: {
429: bval = inb(ioport+ScsiFifo); /* get residual byte */
430: #ifndef VERSION_ELF_1_2_13
431: ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr );
432: #else
433: ptr = (PUCHAR) pSRB->SGPhysAddr;
434: #endif
435: *ptr = bval;
436: pSRB->SGPhysAddr++;
437: pSRB->TotalXferredLen++;
438: pSRB->SGToBeXferLen--;
439: }
440: }
441: }
442: }
443:
444: static void
445: DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
446: {
447: }
448:
449: static void
450: DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
451: {
452: UCHAR bval;
453: USHORT ioport;
454:
455: ioport = pACB->IOPortBase;
456: bval = inb(ioport+ScsiFifo);
457: pSRB->TargetStatus = bval;
458: bval++;
459: bval = inb(ioport+ScsiFifo); /* get message */
460: pSRB->EndMessage = bval;
461:
462: *psstatus = SCSI_NOP0;
463: pSRB->SRBState = SRB_COMPLETED;
464: bval = MSG_ACCEPTED_CMD;
465: outb(bval, ioport+ScsiCmd);
466: }
467:
468: static void
469: DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
470: {
471: if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
472: *psstatus = SCSI_NOP0;
473: }
474:
475: static void
476: DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
477: {
478: UCHAR bval;
479: USHORT ioport, wval, wval1;
480: PDCB pDCB;
481: PSRB psrb;
482:
483: ioport = pACB->IOPortBase;
484: pDCB = pACB->pActiveDCB;
485:
486: bval = inb( ioport+ScsiFifo );
487: if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )
488: {
489: if(bval == MSG_DISCONNECT)
490: {
491: pSRB->SRBState = SRB_DISCONNECT;
492: }
493: else if( bval == MSG_SAVE_PTR )
494: goto min6;
495: else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&
496: (bval <= MSG_ORDER_QTAG)) )
497: {
498: pSRB->SRBState |= SRB_MSGIN_MULTI;
499: pSRB->MsgInBuf[0] = bval;
500: pSRB->MsgCnt = 1;
501: pSRB->pMsgPtr = &pSRB->MsgInBuf[1];
502: }
503: else if(bval == MSG_REJECT_)
504: {
505: bval = RESET_ATN_CMD;
506: outb(bval, ioport+ScsiCmd);
507: if( pSRB->SRBState & DO_SYNC_NEGO)
508: goto set_async;
509: }
510: else if( bval == MSG_RESTORE_PTR)
511: goto min6;
512: else
513: goto min6;
514: }
515: else
516: { /* minx: */
517:
518: *pSRB->pMsgPtr = bval;
519: pSRB->MsgCnt++;
520: pSRB->pMsgPtr++;
521: if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) &&
522: (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) )
523: {
524: if( pSRB->MsgCnt == 2)
525: {
526: pSRB->SRBState = 0;
527: bval = pSRB->MsgInBuf[1];
528: pSRB = pDCB->pGoingSRB;
529: psrb = pDCB->pGoingLast;
530: if( pSRB )
531: {
532: for( ;; )
533: {
534: if(pSRB->TagNumber != bval)
535: {
536: if( pSRB == psrb )
537: goto mingx0;
538: pSRB = pSRB->pNextSRB;
539: }
540: else
541: break;
542: }
543: if( pDCB->DCBFlag & ABORT_DEV_ )
544: {
545: pSRB->SRBState = SRB_ABORT_SENT;
546: EnableMsgOut( pACB, pSRB );
547: }
548: if( !(pSRB->SRBState & SRB_DISCONNECT) )
549: goto mingx0;
550: pDCB->pActiveSRB = pSRB;
551: pSRB->SRBState = SRB_DATA_XFER;
552: }
553: else
554: {
555: mingx0:
556: pSRB = pACB->pTmpSRB;
557: pSRB->SRBState = SRB_UNEXPECT_RESEL;
558: pDCB->pActiveSRB = pSRB;
559: pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
560: EnableMsgOut2( pACB, pSRB );
561: }
562: }
563: }
564: else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) )
565: {
566: pSRB->SRBState &= ~(SRB_MSGIN_MULTI+DO_SYNC_NEGO);
567: if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != 1) )
568: { /* reject_msg: */
569: pSRB->MsgCnt = 1;
570: pSRB->MsgInBuf[0] = MSG_REJECT_;
571: bval = SET_ATN_CMD;
572: outb(bval, ioport+ScsiCmd);
573: }
574: else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) )
575: {
576: set_async:
577: pDCB = pSRB->pSRBDCB;
578: pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
579: pDCB->SyncPeriod = 0;
580: pDCB->SyncOffset = 0;
581: pDCB->CtrlR3 = FAST_CLK; /* ;non_fast */
582: pDCB->CtrlR4 &= 0x3f;
583: pDCB->CtrlR4 |= EATER_25NS; /* ; 25ns glitch eater */
584: goto re_prog;
585: }
586: else
587: { /* set_sync: */
588:
589: pDCB = pSRB->pSRBDCB;
590: pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
591: pDCB->SyncOffset &= 0x0f0;
592: pDCB->SyncOffset |= pSRB->MsgInBuf[4];
593: pDCB->NegoPeriod = pSRB->MsgInBuf[3];
594: wval = (USHORT) pSRB->MsgInBuf[3];
595: wval = wval << 2;
596: wval--;
597: wval1 = wval / 25;
598: if( (wval1 * 25) != wval)
599: wval1++;
600: bval = FAST_CLK+FAST_SCSI;
601: pDCB->CtrlR4 &= 0x3f;
602: if(wval1 >= 8)
603: {
604: wval1--;
605: bval = FAST_CLK; /* ;fast clock/normal scsi */
606: pDCB->CtrlR4 |= EATER_25NS; /* ;25 ns glitch eater */
607: }
608: pDCB->CtrlR3 = bval;
609: pDCB->SyncPeriod = (UCHAR)wval1;
610: re_prog:
611: bval = pDCB->SyncPeriod;
612: outb(bval, ioport+Sync_Period);
613: bval = pDCB->SyncOffset;
614: outb(bval, ioport+Sync_Offset);
615: bval = pDCB->CtrlR3;
616: outb(bval, ioport+CtrlReg3);
617: bval = pDCB->CtrlR4;
618: outb(bval, ioport+CtrlReg4);
619: SetXferRate( pACB, pDCB);
620: }
621: }
622: }
623: min6:
624: *psstatus = SCSI_NOP0;
625: bval = MSG_ACCEPTED_CMD;
626: outb(bval, ioport+ScsiCmd);
627: }
628:
629: static void
630: DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
631: {
632: PSGL psgl;
633: UCHAR bval;
634: USHORT ioport;
635: ULONG lval;
636:
637:
638: ioport = pACB->IOPortBase;
639: if( pSRB->SGIndex < pSRB->SGcount )
640: {
641: bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */
642: outb( bval, ioport+DMA_Cmd);
643: if( !pSRB->SGToBeXferLen )
644: {
645: psgl = pSRB->pSegmentList;
646: #ifndef VERSION_ELF_1_2_13
647: pSRB->SGPhysAddr = virt_to_phys( psgl->address );
648: #else
649: pSRB->SGPhysAddr = (ULONG) psgl->address;
650: #endif
651: pSRB->SGToBeXferLen = (ULONG) psgl->length;
652: }
653: lval = pSRB->SGToBeXferLen;
654: bval = (UCHAR) lval;
655: outb(bval,ioport+CtcReg_Low);
656: lval = lval >> 8;
657: bval = (UCHAR) lval;
658: outb(bval,ioport+CtcReg_Mid);
659: lval = lval >> 8;
660: bval = (UCHAR) lval;
661: outb(bval,ioport+CtcReg_High);
662:
663: lval = pSRB->SGToBeXferLen;
664: outl(lval, ioport+DMA_XferCnt);
665:
666: lval = pSRB->SGPhysAddr;
667: outl( lval, ioport+DMA_XferAddr);
668:
669: bval = DMA_COMMAND+INFO_XFER_CMD;
670: outb(bval, ioport+ScsiCmd);
671:
672: pSRB->SRBState = SRB_DATA_XFER;
673:
674: bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */
675: outb(bval, ioport+DMA_Cmd);
676:
677: bval = DMA_START_CMD | ioDir; /* ;+EN_DMA_INT */
678: outb(bval, ioport+DMA_Cmd);
679: }
680: else /* xfer pad */
681: {
682: if( pSRB->SGcount )
683: {
684: pSRB->AdaptStatus = H_OVER_UNDER_RUN;
685: pSRB->SRBStatus |= OVER_RUN;
686: }
687: bval = 0;
688: outb(bval,ioport+CtcReg_Low);
689: outb(bval,ioport+CtcReg_Mid);
690: outb(bval,ioport+CtcReg_High);
691:
692: pSRB->SRBState |= SRB_XFERPAD;
693: bval = DMA_COMMAND+XFER_PAD_BYTE;
694: outb(bval, ioport+ScsiCmd);
695: /*
696: bval = DMA_IDLE_CMD | ioDir; ;+EN_DMA_INT
697: outb(bval, ioport+DMA_Cmd);
698: bval = DMA_START_CMD | ioDir; ;+EN_DMA_INT
699: outb(bval, ioport+DMA_Cmd);
700: */
701: }
702: }
703:
704:
705: static void
706: DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
707: {
708: UCHAR ioDir;
709:
710: ioDir = WRITE_DIRECTION;
711: DataIO_Comm( pACB, pSRB, ioDir);
712: }
713:
714: static void
715: DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
716: {
717: UCHAR ioDir;
718:
719: ioDir = READ_DIRECTION;
720: DataIO_Comm( pACB, pSRB, ioDir);
721: }
722:
723: static void
724: DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
725: {
726: PDCB pDCB;
727: UCHAR bval;
728: PUCHAR ptr;
729: USHORT ioport, i, cnt;
730:
731:
732: ioport = pACB->IOPortBase;
733: bval = RESET_ATN_CMD;
734: outb(bval, ioport+ScsiCmd);
735: bval = CLEAR_FIFO_CMD;
736: outb(bval, ioport+ScsiCmd);
737: if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
738: {
739: cnt = (USHORT) pSRB->ScsiCmdLen;
740: ptr = (PUCHAR) pSRB->CmdBlock;
741: for(i=0; i < cnt; i++)
742: {
743: outb(*ptr, ioport+ScsiFifo);
744: ptr++;
745: }
746: }
747: else
748: {
749: bval = REQUEST_SENSE;
750: outb(bval, ioport+ScsiFifo);
751: pDCB = pACB->pActiveDCB;
752: bval = pDCB->IdentifyMsg << 5;
753: outb(bval, ioport+ScsiFifo);
754: bval = 0;
755: outb(bval, ioport+ScsiFifo);
756: outb(bval, ioport+ScsiFifo);
757: bval = sizeof(pSRB->pcmd->sense_buffer);
758: outb(bval, ioport+ScsiFifo);
759: bval = 0;
760: outb(bval, ioport+ScsiFifo);
761: }
762: pSRB->SRBState = SRB_COMMAND;
763: bval = INFO_XFER_CMD;
764: outb(bval, ioport+ScsiCmd);
765: }
766:
767: static void
768: DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
769: {
770: UCHAR bval;
771: USHORT ioport;
772:
773: ioport = pACB->IOPortBase;
774: bval = CLEAR_FIFO_CMD;
775: outb(bval, ioport+ScsiCmd);
776: pSRB->SRBState = SRB_STATUS;
777: bval = INITIATOR_CMD_CMPLTE;
778: outb(bval, ioport+ScsiCmd);
779: }
780:
781: static void
782: DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
783: {
784: UCHAR bval;
785: USHORT ioport, i, cnt;
786: PUCHAR ptr;
787: PDCB pDCB;
788:
789: ioport = pACB->IOPortBase;
790: bval = CLEAR_FIFO_CMD;
791: outb(bval, ioport+ScsiCmd);
792: pDCB = pACB->pActiveDCB;
793: if( !(pSRB->SRBState & SRB_MSGOUT) )
794: {
795: cnt = pSRB->MsgCnt;
796: if( cnt )
797: {
798: ptr = (PUCHAR) pSRB->MsgOutBuf;
799: for(i=0; i < cnt; i++)
800: {
801: outb(*ptr, ioport+ScsiFifo);
802: ptr++;
803: }
804: pSRB->MsgCnt = 0;
805: if( (pDCB->DCBFlag & ABORT_DEV_) &&
806: (pSRB->MsgOutBuf[0] == MSG_ABORT) )
807: pSRB->SRBState = SRB_ABORT_SENT;
808: }
809: else
810: {
811: bval = MSG_ABORT; /* ??? MSG_NOP */
812: if( (pSRB->CmdBlock[0] == INQUIRY ) ||
813: (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
814: (pSRB->SRBFlag & AUTO_REQSENSE) )
815: {
816: if( pDCB->SyncMode & SYNC_ENABLE )
817: goto mop1;
818: }
819: outb(bval, ioport+ScsiFifo);
820: }
821: bval = INFO_XFER_CMD;
822: outb( bval, ioport+ScsiCmd);
823: }
824: else
825: {
826: mop1:
827: bval = MSG_EXTENDED;
828: outb(bval, ioport+ScsiFifo);
829: bval = 3; /* ;length of extended msg */
830: outb(bval, ioport+ScsiFifo);
831: bval = 1; /* ; sync nego */
832: outb(bval, ioport+ScsiFifo);
833: bval = pDCB->NegoPeriod;
834: outb(bval, ioport+ScsiFifo);
835: bval = SYNC_NEGO_OFFSET;
836: outb(bval, ioport+ScsiFifo);
837: pSRB->SRBState |= DO_SYNC_NEGO;
838: bval = INFO_XFER_CMD;
839: outb(bval, ioport+ScsiCmd);
840: }
841: }
842:
843: static void
844: DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
845: {
846: UCHAR bval;
847: USHORT ioport;
848:
849: ioport = pACB->IOPortBase;
850: bval = CLEAR_FIFO_CMD;
851: outb(bval, ioport+ScsiCmd);
852: if( !(pSRB->SRBState & SRB_MSGIN) )
853: {
854: pSRB->SRBState &= SRB_DISCONNECT;
855: pSRB->SRBState |= SRB_MSGIN;
856: }
857: bval = INFO_XFER_CMD;
858: outb(bval, ioport+ScsiCmd);
859: }
860:
861: static void
862: DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
863: {
864: }
865:
866: static void
867: DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus)
868: {
869: }
870:
871:
872: static void
873: SetXferRate( PACB pACB, PDCB pDCB )
874: {
875: UCHAR bval;
876: USHORT cnt, i;
877: PDCB ptr;
878:
879: if( !(pDCB->IdentifyMsg & 0x07) )
880: {
881: if( pACB->scan_devices )
882: {
883: CurrSyncOffset = pDCB->SyncOffset;
884: }
885: else
886: {
887: ptr = pACB->pLinkDCB;
888: cnt = pACB->DeviceCnt;
889: bval = pDCB->UnitSCSIID;
890: for(i=0; i<cnt; i++)
891: {
892: if( ptr->UnitSCSIID == bval )
893: {
894: ptr->SyncPeriod = pDCB->SyncPeriod;
895: ptr->SyncOffset = pDCB->SyncOffset;
896: ptr->CtrlR3 = pDCB->CtrlR3;
897: ptr->CtrlR4 = pDCB->CtrlR4;
898: ptr->SyncMode = pDCB->SyncMode;
899: }
900: ptr = ptr->pNextDCB;
901: }
902: }
903: }
904: return;
905: }
906:
907:
908: static void
909: DC390_Disconnect( PACB pACB )
910: {
911: PDCB pDCB;
912: PSRB pSRB, psrb;
913: ULONG flags;
914: USHORT ioport, i, cnt;
915: UCHAR bval;
916:
917: #ifdef DC390_DEBUG0
918: printk("DISC,");
919: #endif
920:
921: save_flags(flags);
922: cli();
923: ioport = pACB->IOPortBase;
924: pDCB = pACB->pActiveDCB;
925: if (!pDCB)
926: {
927: #ifdef DC390_DEBUG0
928: printk("ACB:%08lx->ActiveDCB:%08lx !,",(ULONG)pACB,(ULONG)pDCB);
929: #endif
930: restore_flags(flags); return;
931: }
932: pSRB = pDCB->pActiveSRB;
933: pACB->pActiveDCB = 0;
934: pSRB->ScsiPhase = SCSI_NOP0;
935: bval = EN_SEL_RESEL;
936: outb(bval, ioport+ScsiCmd);
937: if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
938: {
939: pSRB->SRBState = 0;
940: DoWaitingSRB( pACB );
941: }
942: else if( pSRB->SRBState & SRB_ABORT_SENT )
943: {
944: pDCB->TagMask = 0;
945: pDCB->DCBFlag = 0;
946: cnt = pDCB->GoingSRBCnt;
947: pDCB->GoingSRBCnt = 0;
948: pSRB = pDCB->pGoingSRB;
949: for( i=0; i < cnt; i++)
950: {
951: psrb = pSRB->pNextSRB;
952: pSRB->pNextSRB = pACB->pFreeSRB;
953: pACB->pFreeSRB = pSRB;
954: pSRB = psrb;
955: }
956: pDCB->pGoingSRB = 0;
957: DoWaitingSRB( pACB );
958: }
959: else
960: {
961: if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
962: !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
963: { /* Selection time out */
964: if( !(pACB->scan_devices) )
965: {
966: pSRB->SRBState = SRB_READY;
967: RewaitSRB( pDCB, pSRB);
968: }
969: else
970: {
971: pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
972: goto disc1;
973: }
974: }
975: else if( pSRB->SRBState & SRB_DISCONNECT )
976: {
977: DoWaitingSRB( pACB );
978: }
979: else if( pSRB->SRBState & SRB_COMPLETED )
980: {
981: disc1:
982: if(pDCB->MaxCommand > 1)
983: {
984: bval = pSRB->TagNumber;
985: pDCB->TagMask &= (~(1 << bval)); /* free tag mask */
986: }
987: pDCB->pActiveSRB = 0;
988: pSRB->SRBState = SRB_FREE;
989: SRBdone( pACB, pDCB, pSRB);
990: }
991: }
992: restore_flags(flags);
993: return;
994: }
995:
996:
997: static void
998: DC390_Reselect( PACB pACB )
999: {
1000: PDCB pDCB, pdcb;
1001: PSRB pSRB;
1002: USHORT ioport, wval;
1003: UCHAR bval, bval1;
1004:
1005:
1006: #ifdef DC390_DEBUG0
1007: printk("RSEL,");
1008: #endif
1009: ioport = pACB->IOPortBase;
1010: pDCB = pACB->pActiveDCB;
1011: if( pDCB )
1012: { /* Arbitration lost but Reselection win */
1013: pSRB = pDCB->pActiveSRB;
1014: if( !( pACB->scan_devices ) )
1015: {
1016: pSRB->SRBState = SRB_READY;
1017: RewaitSRB( pDCB, pSRB);
1018: }
1019: }
1020: bval = inb(ioport+ScsiFifo); /* get ID */
1021: bval = bval ^ pACB->HostID_Bit;
1022: wval = 0;
1023: bval1 = 1;
1024: for(;;)
1025: {
1026: if( !(bval & bval1) )
1027: {
1028: bval1 = bval1 << 1;
1029: wval++;
1030: }
1031: else
1032: break;
1033: }
1034: wval |= ( (USHORT) inb(ioport+ScsiFifo) & 7) << 8; /* get LUN */
1035: pDCB = pACB->pLinkDCB;
1036: pdcb = pDCB;
1037: while( wval != *((PUSHORT) &pDCB->UnitSCSIID) )
1038: {
1039: pDCB = pDCB->pNextDCB;
1040: if( pDCB == pdcb )
1041: return;
1042: }
1043: pACB->pActiveDCB = pDCB;
1044: if( pDCB->SyncMode & EN_TAG_QUEUING )
1045: {
1046: pSRB = pACB->pTmpSRB;
1047: pDCB->pActiveSRB = pSRB;
1048: }
1049: else
1050: {
1051: pSRB = pDCB->pActiveSRB;
1052: if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
1053: {
1054: pSRB= pACB->pTmpSRB;
1055: pSRB->SRBState = SRB_UNEXPECT_RESEL;
1056: pDCB->pActiveSRB = pSRB;
1057: EnableMsgOut( pACB, pSRB );
1058: }
1059: else
1060: {
1061: if( pDCB->DCBFlag & ABORT_DEV_ )
1062: {
1063: pSRB->SRBState = SRB_ABORT_SENT;
1064: EnableMsgOut( pACB, pSRB );
1065: }
1066: else
1067: pSRB->SRBState = SRB_DATA_XFER;
1068: }
1069: }
1070: pSRB->ScsiPhase = SCSI_NOP0;
1071: bval = pDCB->UnitSCSIID;
1072: outb( bval, ioport+Scsi_Dest_ID);
1073: bval = pDCB->SyncPeriod;
1074: outb(bval, ioport+Sync_Period);
1075: bval = pDCB->SyncOffset;
1076: outb( bval, ioport+Sync_Offset);
1077: bval = pDCB->CtrlR1;
1078: outb(bval, ioport+CtrlReg1);
1079: bval = pDCB->CtrlR3;
1080: outb(bval, ioport+CtrlReg3);
1081: bval = pDCB->CtrlR4; /* ; Glitch eater */
1082: outb(bval, ioport+CtrlReg4);
1083: bval = MSG_ACCEPTED_CMD; /* ;to rls the /ACK signal */
1084: outb(bval, ioport+ScsiCmd);
1085: }
1086:
1087:
1088: static void
1089: SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
1090: {
1091: PSRB psrb;
1092: UCHAR bval, bval1, i, j, status;
1093: PSCSICMD pcmd;
1094: PSCSI_INQDATA ptr;
1095: USHORT disable_tag;
1096: ULONG flags;
1097: PSGL ptr2;
1098: ULONG swlval;
1099:
1100: pcmd = pSRB->pcmd;
1101: status = pSRB->TargetStatus;
1102: if(pSRB->SRBFlag & AUTO_REQSENSE)
1103: {
1104: pSRB->SRBFlag &= ~AUTO_REQSENSE;
1105: pSRB->AdaptStatus = 0;
1106: pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
1107: if(status == SCSI_STAT_CHECKCOND)
1108: {
1109: pcmd->result = DID_BAD_TARGET << 16;
1110: goto ckc_e;
1111: }
1112: if(pSRB->RetryCnt == 0)
1113: {
1114: *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1115: pSRB->TotalXferredLen = pSRB->Segment1[1];
1116: if( (pSRB->TotalXferredLen) &&
1117: (pSRB->TotalXferredLen >= pcmd->underflow) )
1118: pcmd->result |= (DID_OK << 16);
1119: else
1120: pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
1121: SCSI_STAT_CHECKCOND;
1122: #ifdef DC390_DEBUG0
1123: printk("Cmd=%2x,Result=%8x,XferL=%8x,",pSRB->CmdBlock[0],
1124: (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);
1125: #endif
1126: goto ckc_e;
1127: }
1128: else
1129: {
1130: pSRB->RetryCnt--;
1131: pSRB->AdaptStatus = 0;
1132: pSRB->TargetStatus = 0;
1133: *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1134: *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
1135: if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1136: {
1137: pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
1138: SCSI_STAT_CHECKCOND;
1139: goto ckc_e;
1140: }
1141: pcmd->result |= (DRIVER_SENSE << 24);
1142: pSRB->SGcount = (UCHAR) pSRB->Segment1[0];
1143: pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8);
1144: pSRB->SGIndex = 0;
1145: pSRB->TotalXferredLen = 0;
1146: pSRB->SGToBeXferLen = 0;
1147: if( pcmd->use_sg )
1148: pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1149: else if( pcmd->request_buffer )
1150: {
1151: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1152: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1153: pSRB->Segmentx.length = pcmd->request_bufflen;
1154: }
1155: if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1156: RewaitSRB( pDCB, pSRB );
1157: return;
1158: }
1159: }
1160: if( status )
1161: {
1162: if( status == SCSI_STAT_CHECKCOND)
1163: {
1164: if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
1165: {
1166: bval = pSRB->SGcount;
1167: swlval = 0;
1168: ptr2 = pSRB->pSegmentList;
1169: for( i=pSRB->SGIndex; i < bval; i++)
1170: {
1171: swlval += ptr2->length;
1172: ptr2++;
1173: }
1174: #ifdef DC390_DEBUG0
1175: printk("XferredLen=%8x,NotXferLen=%8x,",
1176: (UINT) pSRB->TotalXferredLen, (UINT) swlval);
1177: #endif
1178: }
1179: RequestSense( pACB, pDCB, pSRB );
1180: return;
1181: }
1182: else if( status == SCSI_STAT_QUEUEFULL )
1183: {
1184: bval = (UCHAR) pDCB->GoingSRBCnt;
1185: bval--;
1186: pDCB->MaxCommand = bval;
1187: RewaitSRB( pDCB, pSRB );
1188: pSRB->AdaptStatus = 0;
1189: pSRB->TargetStatus = 0;
1190: return;
1191: }
1192: else if(status == SCSI_STAT_SEL_TIMEOUT)
1193: {
1194: pSRB->AdaptStatus = H_SEL_TIMEOUT;
1195: pSRB->TargetStatus = 0;
1196: pcmd->result = DID_BAD_TARGET << 16;
1197: }
1198: else
1199: {
1200: pSRB->AdaptStatus = 0;
1201: if( pSRB->RetryCnt )
1202: {
1203: pSRB->RetryCnt--;
1204: pSRB->TargetStatus = 0;
1205: pSRB->SGIndex = 0;
1206: pSRB->TotalXferredLen = 0;
1207: pSRB->SGToBeXferLen = 0;
1208: if( pcmd->use_sg )
1209: pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1210: else if( pcmd->request_buffer )
1211: {
1212: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1213: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1214: pSRB->Segmentx.length = pcmd->request_bufflen;
1215: }
1216: if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1217: RewaitSRB( pDCB, pSRB );
1218: return;
1219: }
1220: else
1221: {
1222: pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) |
1223: (ULONG) status;
1224: }
1225: }
1226: }
1227: else
1228: {
1229: status = pSRB->AdaptStatus;
1230: if(status & H_OVER_UNDER_RUN)
1231: {
1232: pSRB->TargetStatus = 0;
1233: pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8);
1234: }
1235: else if( pSRB->SRBStatus & PARITY_ERROR)
1236: {
1237: pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8);
1238: }
1239: else /* No error */
1240: {
1241: pSRB->AdaptStatus = 0;
1242: pSRB->TargetStatus = 0;
1243: pcmd->result |= (DID_OK << 16);
1244: }
1245: }
1246:
1247: ckc_e:
1248: if( pACB->scan_devices )
1249: {
1250: if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1251: {
1252: if(pcmd->result != (DID_OK << 16))
1253: {
1254: if( pcmd->result & SCSI_STAT_CHECKCOND )
1255: {
1256: goto RTN_OK;
1257: }
1258: else
1259: {
1260: pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
1261: pPrevDCB->pNextDCB = pACB->pLinkDCB;
1262: if( (pcmd->target == pACB->max_id) &&
1263: ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) )
1264: {
1265: pACB->scan_devices = 0;
1266: }
1267: }
1268: }
1269: else
1270: {
1271: RTN_OK:
1272: pPrevDCB->pNextDCB = pDCB;
1273: pDCB->pNextDCB = pACB->pLinkDCB;
1274: if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) )
1275: pACB->scan_devices = END_SCAN;
1276: }
1277: }
1278: else if( pSRB->CmdBlock[0] == INQUIRY )
1279: {
1280: if( (pcmd->target == pACB->max_id) &&
1281: (pcmd->lun == pACB->max_lun) )
1282: {
1283: pACB->scan_devices = 0;
1284: }
1285: ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1286: if( pcmd->use_sg )
1287: ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
1288: bval1 = ptr->DevType & SCSI_DEVTYPE;
1289: if(bval1 == SCSI_NODEV)
1290: {
1291: pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
1292: pPrevDCB->pNextDCB = pACB->pLinkDCB;
1293: }
1294: else
1295: {
1296: pACB->DeviceCnt++;
1297: pPrevDCB = pDCB;
1298: pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390_DCB ));
1299: pDCB->DevType = bval1;
1300: if(bval1 == TYPE_DISK || bval1 == TYPE_MOD)
1301: {
1302: if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
1303: (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1304: (pDCB->DevMode & TAG_QUEUING_) &&
1305: (pDCB->DevMode & EN_DISCONNECT_) )
1306: {
1307: disable_tag = 0;
1308: for(i=0; i<BADDEVCNT; i++)
1309: {
1310: for(j=0; j<28; j++)
1311: {
1312: if( ((PUCHAR)ptr)[8+j] != baddevname1[i][j])
1313: break;
1314: }
1315: if(j == 28)
1316: {
1317: disable_tag = 1;
1318: break;
1319: }
1320: }
1321:
1322: if( !disable_tag )
1323: {
1324: pDCB->MaxCommand = pACB->TagMaxNum;
1325: pDCB->SyncMode |= EN_TAG_QUEUING;
1326: pDCB->TagMask = 0;
1327: }
1328: else
1329: {
1330: pDCB->SyncMode |= EN_ATN_STOP;
1331: }
1332: }
1333: }
1334: }
1335: }
1336: }
1337:
1338: save_flags( flags );
1339: cli();
1340: /* ReleaseSRB( pDCB, pSRB ); */
1341:
1342: if(pSRB == pDCB->pGoingSRB )
1343: {
1344: pDCB->pGoingSRB = pSRB->pNextSRB;
1345: }
1346: else
1347: {
1348: psrb = pDCB->pGoingSRB;
1349: while( psrb->pNextSRB != pSRB )
1350: psrb = psrb->pNextSRB;
1351: psrb->pNextSRB = pSRB->pNextSRB;
1352: if( pSRB == pDCB->pGoingLast )
1353: pDCB->pGoingLast = psrb;
1354: }
1355: pSRB->pNextSRB = pACB->pFreeSRB;
1356: pACB->pFreeSRB = pSRB;
1357: pDCB->GoingSRBCnt--;
1358:
1359: DoWaitingSRB( pACB );
1360: restore_flags(flags);
1361:
1362: /* Notify cmd done */
1363: pcmd->scsi_done( pcmd );
1364:
1365: if( pDCB->QIORBCnt )
1366: DoNextCmd( pACB, pDCB );
1367: return;
1368: }
1369:
1370:
1371: static void
1372: DoingSRB_Done( PACB pACB )
1373: {
1374: PDCB pDCB, pdcb;
1375: PSRB psrb, psrb2;
1376: USHORT cnt, i;
1377: PSCSICMD pcmd;
1378:
1379: pDCB = pACB->pLinkDCB;
1380: pdcb = pDCB;
1381: do
1382: {
1383: cnt = pdcb->GoingSRBCnt;
1384: psrb = pdcb->pGoingSRB;
1385: for( i=0; i<cnt; i++)
1386: {
1387: psrb2 = psrb->pNextSRB;
1388: pcmd = psrb->pcmd;
1389: pcmd->result = DID_RESET << 16;
1390:
1391: /* ReleaseSRB( pDCB, pSRB ); */
1392:
1393: psrb->pNextSRB = pACB->pFreeSRB;
1394: pACB->pFreeSRB = psrb;
1395:
1396: pcmd->scsi_done( pcmd );
1397: psrb = psrb2;
1398: }
1399: pdcb->GoingSRBCnt = 0;;
1400: pdcb->pGoingSRB = NULL;
1401: pdcb->TagMask = 0;
1402: pdcb = pdcb->pNextDCB;
1403: }
1404: while( pdcb != pDCB );
1405: }
1406:
1407:
1408: static void
1409: DC390_ResetSCSIBus( PACB pACB )
1410: {
1411: USHORT ioport;
1412: UCHAR bval;
1413: ULONG flags;
1414:
1415: save_flags(flags);
1416: cli();
1417: pACB->ACBFlag |= RESET_DEV;
1418: ioport = pACB->IOPortBase;
1419:
1420: bval = DMA_IDLE_CMD;
1421: outb(bval,ioport+DMA_Cmd);
1422:
1423: bval = RST_SCSI_BUS_CMD;
1424: outb(bval,ioport+ScsiCmd);
1425:
1426: restore_flags(flags);
1427: return;
1428: }
1429:
1430:
1431: static void
1432: DC390_ScsiRstDetect( PACB pACB )
1433: {
1434: ULONG wlval, flags;
1435: USHORT ioport;
1436: UCHAR bval;
1437:
1438: #ifdef DC390_DEBUG0
1439: printk("RST_DETEC");
1440: #endif
1441: save_flags(flags);
1442: sti();
1443: wlval = jiffies + HZ;
1444: while( jiffies < wlval ); /* delay 1 sec */
1445:
1446: cli();
1447: ioport = pACB->IOPortBase;
1448: bval = DMA_IDLE_CMD;
1449: outb(bval,ioport+DMA_Cmd);
1450: bval = CLEAR_FIFO_CMD;
1451: outb(bval,ioport+ScsiCmd);
1452:
1453: if( pACB->ACBFlag & RESET_DEV )
1454: pACB->ACBFlag |= RESET_DONE;
1455: else
1456: {
1457: pACB->ACBFlag |= RESET_DETECT;
1458:
1459: ResetDevParam( pACB );
1460: /* DoingSRB_Done( pACB ); ???? */
1461: RecoverSRB( pACB );
1462: pACB->pActiveDCB = NULL;
1463: pACB->ACBFlag = 0;
1464: DoWaitingSRB( pACB );
1465: }
1466: restore_flags(flags);
1467: return;
1468: }
1469:
1470:
1471: static void
1472: RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1473: {
1474: PSCSICMD pcmd;
1475:
1476: pSRB->SRBFlag |= AUTO_REQSENSE;
1477: pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0]));
1478: pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4]));
1479: pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount);
1480: pSRB->Segment1[1] = pSRB->TotalXferredLen;
1481: pSRB->AdaptStatus = 0;
1482: pSRB->TargetStatus = 0;
1483:
1484: pcmd = pSRB->pcmd;
1485:
1486: pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
1487: pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
1488: pSRB->pSegmentList = &pSRB->Segmentx;
1489: pSRB->SGcount = 1;
1490: pSRB->SGIndex = 0;
1491:
1492: *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
1493: pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
1494: *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer);
1495: pSRB->ScsiCmdLen = 6;
1496:
1497: pSRB->TotalXferredLen = 0;
1498: pSRB->SGToBeXferLen = 0;
1499: if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1500: RewaitSRB( pDCB, pSRB );
1501: }
1502:
1503:
1504: static void
1505: EnableMsgOut2( PACB pACB, PSRB pSRB )
1506: {
1507: USHORT ioport;
1508: UCHAR bval;
1509:
1510: ioport = pACB->IOPortBase;
1511: pSRB->MsgCnt = 1;
1512: bval = SET_ATN_CMD;
1513: outb(bval, ioport+ScsiCmd);
1514: }
1515:
1516:
1517: static void
1518: EnableMsgOut( PACB pACB, PSRB pSRB )
1519: {
1520: pSRB->MsgOutBuf[0] = MSG_ABORT;
1521: EnableMsgOut2( pACB, pSRB );
1522: }
1523:
1524:
1525: static void
1526: DC390_InvalidCmd( PACB pACB )
1527: {
1528: UCHAR bval;
1529: USHORT ioport;
1530: PSRB pSRB;
1531:
1532: pSRB = pACB->pActiveDCB->pActiveSRB;
1533: if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
1534: {
1535: ioport = pACB->IOPortBase;
1536: bval = CLEAR_FIFO_CMD;
1537: outb(bval,(ioport+ScsiCmd));
1538: }
1539: }
1540:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.