|
|
1.1 root 1: /***********************************************************************
2: * FILE NAME : SCSIIO.C *
3: * BY : C.L. Huang *
4: * Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI *
5: * Bus Master Host Adapter *
6: ***********************************************************************/
7:
8:
9: static void
10: PrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB )
11: {
12: ULONG retAddr,wlval;
13: USHORT wval,i;
14: PSGL psgl;
15: PSGE psge;
16:
17:
18: retAddr = pACB->jmp_table8;
19: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
20: retAddr += jmp_table16;
21: wval = (USHORT)(pSRB->SGcount);
22: wval <<= 4; /* 16 bytes per entry, datain=8, dataout=8 */
23: /* (4 bytes for count, 4 bytes for addr) */
24: retAddr -= (ULONG)wval;
25: pSRB->ReturnAddr = retAddr; /* return address for SCRIPT */
26: if(wval)
27: {
28: wval >>= 1;
29: wlval = (ULONG) pSRB->SegmentPad;
30: wlval -= (ULONG)wval;
31: wval >>= 3;
32: psge = (PSGE) wlval;
33: psgl = pSRB->pSegmentList;
34: for(i=0; i<wval; i++)
35: {
36: #ifndef VERSION_ELF_1_2_13
37: psge->SGXPtr = virt_to_phys( psgl->address );
38: #else
39: psge->SGXPtr = (ULONG) psgl->address;
40: #endif
41: psge->SGXLen = psgl->length;
42: psge++;
43: psgl++;
44: }
45: }
46: }
47:
48:
49: static void
50: DC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
51: {
52: USHORT ioport;
53: UCHAR bval;
54:
55: pSRB->TagNumber = 31;
56: ioport = pACB->IOPortBase;
57: bval = SIGNAL_PROC;
58: outb(bval,ioport+ISTAT);
59: pACB->pActiveDCB = pDCB;
60: pDCB->pActiveSRB = pSRB;
61: return;
62: }
63:
64:
65: #ifndef VERSION_ELF_1_2_13
66: static void
67: DC390W_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
68: #else
69: static void
70: DC390W_Interrupt( int irq, struct pt_regs *regs)
71: #endif
72: {
73: PACB pACB;
74: PDCB pDCB;
75: ULONG wlval;
76: USHORT ioport = 0;
77: USHORT wval, i;
78: void (*stateV)( PACB );
79: UCHAR istat = 0;
80: UCHAR bval;
81:
82: pACB = pACB_start;
83: if( pACB == NULL )
84: return;
85: for( i=0; i < adapterCnt; i++ )
86: {
87: if( pACB->IRQLevel == (UCHAR) irq )
88: {
89: ioport = pACB->IOPortBase;
90: istat = inb( ioport+ISTAT );
91: if( istat & (ABORT_OP+SCSI_INT_PENDING+DMA_INT_PENDING) )
92: break;
93: else
94: pACB = pACB->pNextACB;
95: }
96: else
97: {
98: pACB = pACB->pNextACB;
99: }
100: }
101:
102: if( pACB == (PACB )-1 )
103: {
104: printk("DC390W_intr: Spurious interrupt detected!\n");
105: return;
106: }
107:
108:
109: #ifdef DC390W_DEBUG1
110: printk("Istate=%2x,",istat);
111: #endif
112: /* if Abort operation occurred, reset abort bit before reading DMA status
113: to prevent further aborted interrupt. */
114:
115: if(istat & ABORT_OP)
116: {
117: istat &= ~ABORT_OP;
118: outb(istat,ioport+ISTAT);
119: }
120:
121: pDCB = pACB->pActiveDCB;
122: bval = inb(ioport+CTEST2); /* Clear Signal Bit */
123:
124: /* If Scsi Interrupt, then clear Interrupt Status by reading
125: Scsi interrupt status register 0. */
126:
127: wlval = 0;
128: if(istat & SCSI_INT_PENDING)
129: {
130: wlval = (ULONG)inw( ioport+SIST0 );
131: wlval <<= 8;
132: }
133:
134: /* If DMA Interrupt, then read the DMA status register to see what happen */
135:
136: if(istat & DMA_INT_PENDING)
137: {
138: bval = inb(ioport+DSTAT);
139: wlval |= (ULONG) bval;
140: }
141:
142: #ifdef DC390W_DEBUG1
143: printk("IDstate=%8x,",(UINT) wlval);
144: #endif
145: if(wlval & ( (SEL_TIMEOUT << 16)+
146: ((SCSI_GERROR+UNEXPECT_DISC+SCSI_RESET) << 8)+
147: ILLEGAL_INSTRUC+ABORT_) )
148: {
149: ExceptionHandler( wlval, pACB, pDCB );
150: }
151: else if( wlval & SCRIPTS_INT )
152: {
153: wval = inw( ioport+DSPS );
154: stateV = (void *) IntVector[wval];
155: stateV( pACB );
156: }
157: else if( wlval & ( PARITY_ERROR << 8) )
158: ParityError( pACB, pDCB );
159: else if( wlval & ( PHASE_MISMATCH << 8) )
160: PhaseMismatch( pACB );
161: return;
162: }
163:
164:
165: static void
166: ExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB)
167: {
168: PSRB pSRB;
169: UCHAR bval;
170: USHORT ioport;
171:
172: /* disconnect/scsi reset/illegal instruction */
173:
174: ioport = pACB->IOPortBase;
175: if(wlval & ( (SCSI_RESET+SCSI_GERROR) << 8) )
176: DC390W_ScsiRstDetect( pACB );
177: else if(wlval & ABORT_)
178: {
179: #ifdef DC390W_DEBUG0
180: printk("AboRst,");
181: #endif
182: if( !InitialTime )
183: DC390W_ResetSCSIBus2( pACB );
184: }
185: else if(wlval & (SEL_TIMEOUT << 16) )
186: {
187: pACB->status = SCSI_STAT_SEL_TIMEOUT;
188: #ifdef DC390W_DEBUG1
189: printk("Selto,");
190: #endif
191: DC390W_CmdCompleted( pACB );
192: }
193: else if(wlval & (UNEXPECT_DISC << 8) )
194: {
195: bval = inb(ioport+STEST3);
196: bval |= CLR_SCSI_FIFO;
197: outb(bval,ioport+STEST3);
198: bval = CLR_DMA_FIFO;
199: outb(bval,ioport+CTEST3);
200: pSRB = pDCB->pActiveSRB;
201: if( pSRB->SRBState & DO_SYNC_NEGO )
202: {
203: pDCB->DevMode &= ~SYNC_NEGO_;
204: pACB->status = SCSI_STAT_CHECKCOND;
205: DC390W_CmdCompleted( pACB );
206: }
207: else if( pSRB->SRBState & DO_WIDE_NEGO )
208: {
209: pDCB->DevMode &= ~WIDE_NEGO_;
210: pACB->status = SCSI_STAT_CHECKCOND;
211: DC390W_CmdCompleted( pACB );
212: }
213: else
214: {
215: pACB->status = SCSI_STAT_UNEXP_BUS_F;
216: DC390W_CmdCompleted( pACB );
217: }
218: #ifdef DC390W_DEBUG0
219: printk("Uxpbf,");
220: #endif
221: }
222: else
223: {
224: #ifdef DC390W_DEBUG0
225: printk("Except,");
226: #endif
227: DC390W_ResetSCSIBus( pACB );
228: }
229: }
230:
231:
232: static void
233: ParityError( PACB pACB, PDCB pDCB )
234: {
235: ULONG ioport;
236: UCHAR bval,msg;
237: ULONG wlval;
238: PSRB pSRB;
239:
240: ioport = pACB->IOPortBase;
241: bval = inb(ioport+SCRATCHA);
242: if(bval & RE_SELECTED_)
243: {
244: #ifdef DC390W_DEBUG0
245: printk("ParityErr,");
246: #endif
247: DC390W_ResetSCSIBus( pACB );
248: return;
249: }
250: else
251: {
252: pSRB = pDCB->pActiveSRB;
253: bval = inb(ioport+STEST3);
254: bval |= CLR_SCSI_FIFO;
255: outb(bval,ioport+STEST3);
256: bval = CLR_DMA_FIFO;
257: outb(bval,ioport+CTEST3);
258:
259: bval = inb(ioport+DCMD);
260: bval &= 0x07; /* get phase bits */
261: if(bval == 0x07) /* message in phase */
262: {
263: msg = MSG_PARITY_ERROR;
264: wlval = pACB->jmp_clear_ack;
265: }
266: else
267: {
268: msg = MSG_INITIATOR_ERROR;
269: wlval = pACB->jmp_next;
270: }
271: pSRB->__msgout0[0] = 1;
272: pSRB->MsgOutBuf[0] = msg;
273: outl(wlval,(ioport+DSP));
274: return;
275: }
276: }
277:
278:
279: static void
280: DC390W_Signal( PACB pACB )
281: {
282: PDCB pDCB;
283: PSRB pSRB;
284: USHORT ioport;
285: ULONG wlval, flags;
286: UCHAR bval,msgcnt,tagnum;
287:
288: save_flags(flags);
289: cli();
290: ioport = pACB->IOPortBase;
291: pDCB = pACB->pActiveDCB;
292: pSRB = pDCB->pActiveSRB;
293: #ifdef DC390W_DEBUG0
294: printk("Signal,Cmd=%2x", pSRB->CmdBlock[0]);
295: #endif
296: wlval = pSRB->PhysSRB;
297: outl(wlval,(ioport+DSA));
298: wlval = pSRB->ReturnAddr;
299: outl(wlval,(ioport+TEMP));
300: msgcnt = 1;
301: bval = pDCB->IdentifyMsg;
302: pSRB->MsgOutBuf[0] = bval;
303: if( (pSRB->CmdBlock[0] != INQUIRY) &&
304: (pSRB->CmdBlock[0] != REQUEST_SENSE) )
305: {
306: if(pDCB->MaxCommand > 1)
307: {
308: wlval = 1;
309: tagnum = 0;
310: while( wlval & pDCB->TagMask )
311: {
312: wlval = wlval << 1;
313: tagnum++;
314: }
315: pDCB->TagMask |= wlval;
316: pSRB->TagNumber = tagnum;
317: pSRB->MsgOutBuf[1] = MSG_SIMPLE_QTAG;
318: pSRB->MsgOutBuf[2] = tagnum;
319: msgcnt = 3;
320: }
321: }
322: else
323: {
324: pSRB->MsgOutBuf[0] &= 0xBF; /* Diable Disconnected */
325: if(pSRB->CmdBlock[0] == INQUIRY)
326: {
327: if(bval & 0x07)
328: goto type_6_3;
329: }
330: if(pDCB->DevMode & WIDE_NEGO_)
331: {
332: msgcnt = 5;
333: *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x01030201;
334: pSRB->SRBState |= DO_WIDE_NEGO;
335: }
336: else if(pDCB->DevMode & SYNC_NEGO_)
337: {
338: msgcnt = 6;
339: *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x00010301;
340: pSRB->MsgOutBuf[4] = pDCB->NegoPeriod;
341: pSRB->MsgOutBuf[5] = SYNC_NEGO_OFFSET;
342: pSRB->SRBState |= DO_SYNC_NEGO;
343: }
344: }
345: type_6_3:
346: pSRB->__msgout0[0] = (ULONG) msgcnt;
347: wlval = 0;
348: outl(wlval,(ioport+SCRATCHA));
349: bval = pDCB->DCBscntl0;
350: outb(bval,ioport+SCNTL0);
351: pSRB->__select = *((PULONG) &(pDCB->DCBselect));
352: #ifdef DC390W_DEBUG0
353: printk("__sel=%8x,", (UINT)(pSRB->__select));
354: #endif
355: wlval = pACB->jmp_select;
356: outl(wlval,(ioport+DSP));
357: restore_flags(flags);
358: return;
359: }
360:
361:
362: static void
363: DC390W_MessageWide( PACB pACB )
364: {
365: PDCB pDCB;
366: PSRB pSRB;
367: PUCHAR msgoutPtr;
368: USHORT ioport;
369: ULONG wlval;
370: UCHAR bval,msgcnt;
371:
372:
373: #ifdef DC390W_DEBUG0
374: printk("MsgWide,");
375: #endif
376: ioport = pACB->IOPortBase;
377: pDCB = pACB->pActiveDCB;
378: pSRB = pDCB->pActiveSRB;
379: msgcnt = 0;
380: pDCB->DCBscntl3 &= ~EN_WIDE_SCSI;
381: msgoutPtr = pSRB->MsgOutBuf;
382: if( pSRB->SRBState & DO_WIDE_NEGO )
383: {
384: pSRB->SRBState &= ~DO_WIDE_NEGO;
385: if( pACB->msgin123[0] == 3 )
386: {
387: bval = pACB->msgin123[1];
388: if(bval == 1)
389: {
390: pDCB->DCBscntl3 |= EN_WIDE_SCSI;
391: goto x5;
392: }
393: if(bval < 1)
394: goto x5;
395: }
396: }
397:
398: /*type_11_1:*/
399: msgcnt = 1;
400: *msgoutPtr = MSG_REJECT_;
401: msgoutPtr++;
402: x5:
403: bval = pDCB->DCBscntl3;
404: outb(bval,ioport+SCNTL3);
405: AdjustTemp(pACB,pDCB,pSRB);
406: SetXferRate(pACB,pDCB);
407: if( pDCB->DevMode & SYNC_NEGO_ )
408: {
409: *((PULONG)msgoutPtr) = 0x00010301;
410: *(msgoutPtr + 3) = pDCB->NegoPeriod;
411: *(msgoutPtr + 4) = SYNC_NEGO_OFFSET;
412: msgcnt += 5;
413: pSRB->SRBState |= DO_SYNC_NEGO;
414: }
415:
416: pSRB->__msgout0[0] = (ULONG) msgcnt;
417: wlval = pACB->jmp_clear_ack;
418: if(msgcnt)
419: wlval = pACB->jmp_set_atn;
420: outl(wlval,(ioport+DSP));
421: return;
422: }
423:
424:
425: static void
426: DC390W_MessageSync( PACB pACB )
427: {
428: PDCB pDCB;
429: PSRB pSRB;
430: USHORT ioport;
431: ULONG wlval;
432: USHORT wval,wval1;
433: UCHAR bval,bval1;
434:
435: #ifdef DC390W_DEBUG0
436: printk("MsgSync,");
437: #endif
438: ioport = pACB->IOPortBase;
439: pDCB = pACB->pActiveDCB;
440: pSRB = pDCB->pActiveSRB;
441: if( !(pSRB->SRBState & DO_SYNC_NEGO) )
442: goto MessageExtnd;
443: pSRB->SRBState &= ~DO_SYNC_NEGO;
444: if(pACB->msgin123[0] != 1)
445: {
446: MessageExtnd:
447: pSRB->__msgout0[0] = 1;
448: pSRB->MsgOutBuf[0] = MSG_REJECT_;
449: wlval = pACB->jmp_set_atn;
450: outl(wlval,(ioport+DSP));
451: return;
452: }
453: bval = pACB->msgin123[2]; /* offset */
454: asyncx:
455: pDCB->DCBsxfer = bval;
456: if(bval == 0) /* if offset or period == 0, async */
457: {
458: if( pACB->AdaptType == DC390W )
459: bval = SYNC_CLK_F2+ASYNC_CLK_F2;
460: else
461: bval = SYNC_CLK_F4+ASYNC_CLK_F4;
462: pDCB->DCBscntl3 = bval;
463: }
464: else
465: {
466: bval = pACB->msgin123[1];
467: if(bval == 0)
468: goto asyncx;
469: pDCB->SyncPeriod = bval;
470: wval = (USHORT)bval;
471: wval <<= 3;
472: bval = pDCB->DCBscntl3;
473: bval &= 0x0f;
474: if(wval < 200) /* < 100 ns ==> Fast-20 */
475: {
476: bval |= 0x90; /* Fast-20 and div 1 */
477: bval1 = 25; /* 12.5 ns */
478: }
479: else if(wval < 400)
480: {
481: bval |= 0x30; /* 1 cycle = 25ns */
482: bval1 = 50;
483: }
484: else /* Non Fast */
485: {
486: bval |= 0x50; /* 1 cycle = 50ns */
487: bval1 = 100;
488: }
489: if( pACB->AdaptType == DC390W )
490: bval -= 0x20; /* turn down to 40Mhz scsi clock */
491: /* assume 390W will not receive fast-20 */
492: wval1 = wval;
493: wval /= bval1;
494: if(wval * bval1 < wval1)
495: wval++;
496: /* XFERP TP2 TP1 TP0 */
497: wval -= 4; /* 4 0 0 0 */
498: /* 5 0 0 1 */
499: wval <<= 5;
500: pDCB->DCBsxfer |= (UCHAR)wval;
501: pDCB->DCBscntl3 = bval;
502: }
503: /*sync_2:*/
504: SetXferRate( pACB,pDCB );
505: wlval = pACB->jmp_clear_ack;
506: /*sync_3:*/
507: bval = pDCB->DCBscntl3;
508: outb(bval,ioport+SCNTL3);
509: bval = pDCB->DCBsxfer;
510: outb(bval,ioport+SXFER);
511: outl(wlval,(ioport+DSP));
512: return;
513: }
514:
515:
516: static void
517: DC390W_MsgReject( PACB pACB )
518: {
519: PDCB pDCB;
520: PSRB pSRB;
521: ULONG wlval;
522: USHORT ioport;
523: UCHAR bval;
524:
525: #ifdef DC390W_DEBUG0
526: printk("Msgrjt,");
527: #endif
528: pDCB = pACB->pActiveDCB;
529: pSRB = pDCB->pActiveSRB;
530: wlval = pACB->jmp_clear_ack;
531: if(pSRB->SRBState & DO_WIDE_NEGO)
532: {
533: pSRB->SRBState &= ~DO_WIDE_NEGO;
534: pDCB->DCBscntl3 &= ~EN_WIDE_SCSI;
535: AdjustTemp( pACB, pDCB, pSRB );
536: SetXferRate( pACB, pDCB );
537: if( pDCB->DevMode & SYNC_NEGO_ )
538: {
539: *((PULONG) &(pSRB->MsgOutBuf[0])) = 0x00010301;
540: pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
541: pSRB->MsgOutBuf[4] = SYNC_NEGO_OFFSET;
542: pSRB->__msgout0[0] = 5;
543: pSRB->SRBState |= DO_SYNC_NEGO;
544: wlval = pACB->jmp_set_atn;
545: }
546: }
547: else
548: {
549: if(pSRB->SRBState & DO_SYNC_NEGO)
550: {
551: pSRB->SRBState &= ~DO_SYNC_NEGO;
552: pDCB->DCBsxfer = 0; /* reject sync msg, set aync */
553: if( pACB->AdaptType == DC390W )
554: bval = SYNC_CLK_F2+ASYNC_CLK_F2;
555: else
556: bval = SYNC_CLK_F4+ASYNC_CLK_F4;
557: pDCB->DCBscntl3 = bval;
558: SetXferRate(pACB,pDCB);
559: wlval = pACB->jmp_clear_ack;
560: }
561: }
562: ioport = pACB->IOPortBase;
563: bval = pDCB->DCBscntl3;
564: outb(bval,ioport+SCNTL3);
565: bval = pDCB->DCBsxfer;
566: outb(bval,ioport+SXFER);
567: outl(wlval,(ioport+DSP));
568: return;
569: }
570:
571:
572: static void
573: AdjustTemp( PACB pACB, PDCB pDCB, PSRB pSRB )
574: {
575: USHORT ioport;
576: ULONG wlval;
577:
578: wlval = pSRB->ReturnAddr;
579: if(wlval <= pACB->jmp_table8)
580: {
581: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
582: wlval += jmp_table16;
583: }
584: else
585: {
586: if((pDCB->DCBscntl3 & EN_WIDE_SCSI) == 0)
587: wlval -= jmp_table16;
588: }
589: pSRB->ReturnAddr = wlval;
590: ioport = pACB->IOPortBase;
591: outl(wlval,(ioport+TEMP));
592: return;
593: }
594:
595:
596: static void
597: SetXferRate( PACB pACB, PDCB pDCB )
598: {
599: UCHAR bval;
600: USHORT cnt, i;
601: PDCB ptr;
602:
603: if( !(pDCB->IdentifyMsg & 0x07) )
604: {
605: if( pACB->scan_devices )
606: {
607: CurrDCBscntl3 = pDCB->DCBscntl3;
608: }
609: else
610: {
611: ptr = pACB->pLinkDCB;
612: cnt = pACB->DeviceCnt;
613: bval = pDCB->UnitSCSIID;
614: for(i=0; i<cnt; i++)
615: {
616: if( ptr->UnitSCSIID == bval )
617: {
618: ptr->DCBsxfer = pDCB->DCBsxfer;
619: ptr->DCBscntl3 = pDCB->DCBscntl3;
620: }
621: ptr = ptr->pNextDCB;
622: }
623: }
624: }
625: return;
626: }
627:
628:
629: static void
630: DC390W_UnknownMsg( PACB pACB )
631: {
632: PSRB pSRB;
633: ULONG wlval;
634: USHORT ioport;
635:
636: pSRB = pACB->pActiveDCB->pActiveSRB;
637: pSRB->__msgout0[0] = 1;
638: pSRB->MsgOutBuf[0] = MSG_REJECT_;
639: wlval = pACB->jmp_set_atn;
640: ioport = pACB->IOPortBase;
641: outl(wlval,(ioport+DSP));
642: return;
643: }
644:
645:
646: static void
647: DC390W_MessageExtnd( PACB pACB )
648: {
649: DC390W_UnknownMsg( pACB );
650: }
651:
652:
653: static void
654: DC390W_Disconnected( PACB pACB )
655: {
656: PDCB pDCB;
657: PSRB pSRB;
658: ULONG wlval, flags;
659: USHORT ioport;
660: UCHAR bval;
661:
662: #ifdef DC390W_DEBUG0
663: printk("Discnet,");
664: #endif
665: save_flags(flags);
666: cli();
667: pDCB = pACB->pActiveDCB;
668: if (! pDCB)
669: {
670: #ifdef DC390W_DEBUG0
671: printk("ACB:%08lx->ActiveDCB:%08lx !,", (ULONG)pACB, (ULONG)pDCB);
672: #endif
673: restore_flags(flags); return;
674: }
675:
676: pSRB = pDCB->pActiveSRB;
677:
678: ioport = pACB->IOPortBase;
679: bval = inb(ioport+SCRATCHA);
680: pSRB->ScratchABuf = bval;
681: pSRB->SRBState |= SRB_DISCONNECT; /* 1.02 */
682: wlval = pACB->jmp_reselect;
683: outl(wlval,(ioport+DSP));
684: pACB->pActiveDCB = 0;
685: DoWaitingSRB( pACB );
686: restore_flags(flags);
687: return;
688: }
689:
690:
691: static void
692: DC390W_Reselected( PACB pACB )
693: {
694: #ifdef DC390W_DEBUG0
695: printk("Rsel,");
696: #endif
697: pACB->msgin123[0] = 0x80; /* set identify byte 80h */
698: DC390W_Reselected1(pACB);
699: return;
700: }
701:
702:
703: static void
704: DC390W_Reselected1( PACB pACB )
705: {
706: PDCB pDCB;
707: PSRB pSRB;
708: USHORT ioport, wval;
709: ULONG wlval, flags;
710: UCHAR bval;
711:
712:
713: #ifdef DC390W_DEBUG0
714: printk("Rsel1,");
715: #endif
716: ioport = pACB->IOPortBase;
717: pDCB = pACB->pActiveDCB;
718: if(pDCB)
719: {
720: pSRB = pDCB->pActiveSRB;
721: RewaitSRB( pDCB, pSRB );
722: }
723:
724: wval = (USHORT) (pACB->msgin123[0]);
725: wval = (wval & 7) << 8; /* get LUN */
726: wval |= (USHORT) (inb(ioport+SSID) & 0x0f); /* get ID */
727: pDCB = pACB->pLinkDCB;
728: while( *((PUSHORT) &pDCB->UnitSCSIID) != wval )
729: pDCB = pDCB->pNextDCB;
730: pACB->pActiveDCB = pDCB;
731: bval = pDCB->DCBscntl3;
732: outb(bval,ioport+SCNTL3);
733: bval = pDCB->DCBsxfer;
734: outb(bval,ioport+SXFER);
735: bval = pDCB->DCBscntl0;
736: outb(bval,ioport+SCNTL0);
737: if(pDCB->MaxCommand > 1)
738: {
739: wlval = pACB->jmp_reselecttag;
740: outl(wlval,(ioport+DSP));
741: }
742: else
743: {
744: pSRB = pDCB->pActiveSRB;
745: if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
746: {
747: save_flags(flags);
748: cli();
749: pSRB = pACB->pFreeSRB;
750: pACB->pFreeSRB = pSRB->pNextSRB;
751: restore_flags(flags);
752: pSRB->SRBState = SRB_UNEXPECT_RESEL;
753: pDCB->pActiveSRB = pSRB;
754: pSRB->MsgOutBuf[0] = MSG_ABORT;
755: pSRB->__msgout0[0] = 1;
756: }
757: pSRB->SRBState &= ~SRB_DISCONNECT;
758: wlval = pSRB->PhysSRB;
759: outl(wlval,(ioport+DSA));
760: wlval = pSRB->ReturnAddr;
761: outl(wlval,(ioport+TEMP));
762: bval = pSRB->ScratchABuf;
763: outb(bval,ioport+SCRATCHA);
764: if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
765: wlval = pACB->jmp_set_atn;
766: else
767: wlval = pACB->jmp_clear_ack;
768: outl(wlval,(ioport+DSP));
769: }
770: return;
771: }
772:
773:
774: static void
775: DC390W_ReselectedT( PACB pACB )
776: {
777: PDCB pDCB;
778: PSRB pSRB, psrb1;
779: USHORT ioport;
780: ULONG wlval, flags;
781: UCHAR bval;
782:
783: #ifdef DC390W_DEBUG0
784: printk("RselT,");
785: #endif
786: ioport = pACB->IOPortBase;
787: bval = pACB->msgin123[1];
788: pDCB = pACB->pActiveDCB;
789: pSRB = pDCB->pGoingSRB;
790: psrb1 = pDCB->pGoingLast;
791: if( !pSRB )
792: goto UXP_RSL;
793: for(;;)
794: {
795: if(pSRB->TagNumber != bval)
796: {
797: if( pSRB != psrb1 )
798: pSRB = pSRB->pNextSRB;
799: else
800: goto UXP_RSL;
801: }
802: else
803: break;
804: }
805: if( !(pSRB->SRBState & SRB_DISCONNECT) )
806: {
807: UXP_RSL:
808: save_flags(flags);
809: cli();
810: pSRB = pACB->pFreeSRB;
811: pACB->pFreeSRB = pSRB->pNextSRB;
812: restore_flags(flags);
813: pSRB->SRBState = SRB_UNEXPECT_RESEL;
814: pDCB->pActiveSRB = pSRB;
815: pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
816: pSRB->__msgout0[0] = 1;
817: }
818: else
819: {
820: pSRB->SRBState &= ~SRB_DISCONNECT;
821: pDCB->pActiveSRB = pSRB;
822: }
823: wlval = pSRB->PhysSRB;
824: outl(wlval,(ioport+DSA));
825: wlval = pSRB->ReturnAddr;
826: outl(wlval,(ioport+TEMP));
827: bval = pSRB->ScratchABuf;
828: outb(bval,ioport+SCRATCHA);
829: if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
830: wlval = pACB->jmp_set_atn;
831: else
832: wlval = pACB->jmp_clear_ack;
833: outl(wlval,(ioport+DSP));
834: return;
835: }
836:
837:
838: static void
839: DC390W_RestorePtr( PACB pACB )
840: {
841: PSRB pSRB;
842: USHORT ioport;
843: ULONG wlval;
844:
845: pSRB = pACB->pActiveDCB->pActiveSRB;
846: wlval = pSRB->ReturnAddr;
847: ioport = pACB->IOPortBase;
848: outl(wlval,(ioport+TEMP));
849: wlval = inl(ioport+DSP);
850: outl(wlval,(ioport+DSP));
851: return;
852: }
853:
854:
855: static void
856: PhaseMismatch( PACB pACB )
857: {
858: USHORT ioport;
859: ULONG wlval,swlval;
860: USHORT wval;
861: UCHAR bval,phase;
862: PDCB pDCB;
863:
864: #ifdef DC390W_DEBUG0
865: printk("Mismatch,");
866: #endif
867: ioport = pACB->IOPortBase;
868: bval = inb(ioport+SCRATCHA);
869: if(bval & OVER_RUN_) /* xfer PAD */
870: {
871: bval = inb(ioport+STEST3);
872: bval |= CLR_SCSI_FIFO;
873: outb(bval,ioport+STEST3);
874: bval = CLR_DMA_FIFO;
875: outb(bval,ioport+CTEST3);
876: wlval = pACB->jmp_next; /* check phase */
877: outl(wlval,(ioport+DSP));
878: return;
879: }
880: pDCB = pACB->pActiveDCB;
881: wlval = inl(ioport+DBC);
882: phase = (UCHAR)((wlval & 0x07000000) >> 24);
883: wlval &= 0xffffff; /* bytes not xferred */
884: if( phase == SCSI_DATA_IN )
885: {
886: swlval = pACB->jmp_din8;
887: if( pDCB->DCBscntl3 & EN_WIDE_SCSI )
888: swlval += jmp_din16;
889: DataIOcommon(pACB,swlval,wlval);
890: }
891: else if( phase == SCSI_DATA_OUT )
892: {
893: wval = (USHORT)inb(ioport+CTEST5);
894: wval <<= 8;
895: bval = inb(ioport+DFIFO);
896: wval |= (USHORT) bval;
897: wval -= ((USHORT)(wlval & 0xffff));
898: wval &= 0x3ff;
899: wlval += (ULONG)wval; /* # of bytes remains in FIFO */
900: bval = inb(ioport+SSTAT0);
901: if(bval & SODR_LSB_FULL)
902: wlval++; /* data left in Scsi Output Data Buffer */
903: if(bval & SODL_LSB_FULL)
904: wlval++; /* data left in Scsi Output Data Latch */
905: swlval = pACB->jmp_dout8;
906: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
907: {
908: swlval += jmp_dout16;
909: bval = inb(ioport+SSTAT2);
910: if(bval & SODR_MSB_FULL)
911: wlval++;
912: if(bval & SODL_MSB_FULL)
913: wlval++;
914: }
915: bval = inb(ioport+STEST3);
916: bval |= CLR_SCSI_FIFO;
917: outb(bval,ioport+STEST3);
918: bval = CLR_DMA_FIFO;
919: outb(bval,ioport+CTEST3);
920: DataIOcommon(pACB,swlval,wlval);
921: }
922: else
923: {
924: bval = inb(ioport+STEST3);
925: bval |= CLR_SCSI_FIFO;
926: outb(bval,ioport+STEST3);
927: bval = CLR_DMA_FIFO;
928: outb(bval,ioport+CTEST3);
929: if(phase == SCSI_MSG_OUT)
930: wlval = pACB->jmp_clear_atn;
931: else
932: wlval = pACB->jmp_next; /* check phase */
933: outl(wlval,(ioport+DSP));
934: }
935: return;
936: }
937:
938:
939: static void
940: DataIOcommon( PACB pACB, ULONG Swlval, ULONG Cwlval )
941: {
942: /* Swlval - script address */
943: /* Cwlval - bytes not xferred */
944: PDCB pDCB;
945: PSRB pSRB;
946: PSGE Segptr;
947: USHORT ioport;
948: ULONG wlval,swlval,dataXferCnt;
949: UCHAR bval,bvald;
950:
951: ioport = pACB->IOPortBase;
952: wlval = inl((ioport+DSP));
953: pDCB = pACB->pActiveDCB;
954: pSRB = pDCB->pActiveSRB;
955: wlval -= Swlval;
956: bval = inb(ioport+SBCL);
957: bval &= 0x07;
958: if(bval == SCSI_MSG_IN)
959: {
960: bval = pDCB->DCBscntl3;
961: bval &= ~EN_WIDE_SCSI;
962: outb(bval,ioport+SCNTL3);
963: bval = inb(ioport+SBDL);
964: bvald = pDCB->DCBscntl3; /* enable WIDE SCSI */
965: outb(bvald,ioport+SCNTL3);
966: if(bval == MSG_DISCONNECT || bval == MSG_SAVE_PTR)
967: {
968: Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval);
969: dataXferCnt = Segptr->SGXLen - Cwlval;
970: Segptr->SGXLen = Cwlval; /* modified count */
971: Segptr->SGXPtr += dataXferCnt; /* modified address */
972: swlval = pACB->jmp_table8;
973: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
974: swlval += jmp_table16;
975: wlval <<= 1;
976: swlval += wlval;
977: swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16);
978: pSRB->ReturnAddr = swlval;
979: }
980: }
981: else if( Cwlval ) /* Remaining not xferred -- UNDER_RUN */
982: {
983: Segptr = (PSGE)((ULONG) &(pSRB->Segment0[0][0]) + wlval);
984: dataXferCnt = Segptr->SGXLen - Cwlval;
985: Segptr->SGXLen = Cwlval; /* modified count */
986: Segptr->SGXPtr += dataXferCnt; /* modified address */
987: swlval = pACB->jmp_table8;
988: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
989: swlval += jmp_table16;
990: wlval <<= 1;
991: swlval += wlval;
992: swlval = swlval - ((MAX_SG_LIST_BUF+1) * 16);
993: pSRB->RemainSegPtr = swlval;
994: }
995: /* pm__1: */
996: wlval = pSRB->ReturnAddr;
997: outl(wlval,(ioport+TEMP));
998: wlval = pACB->jmp_next;
999: outl(wlval,(ioport+DSP));
1000: return;
1001: }
1002:
1003:
1004: static void
1005: DC390W_CmdCompleted( PACB pACB )
1006: {
1007: PDCB pDCB;
1008: PSRB pSRB;
1009: USHORT ioport;
1010: ULONG wlval, flags;
1011: UCHAR bval;
1012:
1013: #ifdef DC390W_DEBUG0
1014: printk("Cmplete,");
1015: #endif
1016: save_flags(flags);
1017: cli();
1018: pDCB = pACB->pActiveDCB;
1019: pSRB = pDCB->pActiveSRB;
1020: pDCB->pActiveSRB = NULL;
1021: ioport = pACB->IOPortBase;
1022:
1023: bval = inb(ioport+SCRATCHA);
1024: pSRB->ScratchABuf = bval; /* save status */
1025: bval = pSRB->TagNumber;
1026: if(pDCB->MaxCommand > 1)
1027: pDCB->TagMask &= (~(1 << bval)); /* free tag mask */
1028: pACB->pActiveDCB = NULL; /* no active device */
1029: wlval = pACB->jmp_reselect; /* enable reselection */
1030: outl(wlval,(ioport+DSP));
1031: SRBdone( pACB, pDCB, pSRB);
1032: restore_flags(flags);
1033: return;
1034: }
1035:
1036:
1037: static void
1038: SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
1039: {
1040: PSRB psrb;
1041: UCHAR bval, bval1, i, j, status;
1042: PSCSICMD pcmd;
1043: PSCSI_INQDATA ptr;
1044: USHORT disable_tag;
1045: ULONG flags;
1046: PSGE ptr1;
1047: PSGL ptr2;
1048: ULONG wlval,swlval;
1049:
1050: pcmd = pSRB->pcmd;
1051: status = pACB->status;
1052: if(pSRB->SRBFlag & AUTO_REQSENSE)
1053: {
1054: pSRB->SRBFlag &= ~AUTO_REQSENSE;
1055: pSRB->AdaptStatus = 0;
1056: pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
1057: if(status == SCSI_STAT_CHECKCOND)
1058: {
1059: pcmd->result = DID_BAD_TARGET << 16;
1060: goto ckc_e;
1061: }
1062: if(pSRB->RetryCnt == 0)
1063: {
1064: *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0];
1065: pSRB->XferredLen = pSRB->Segment0[2][1];
1066: if( (pSRB->XferredLen) &&
1067: (pSRB->XferredLen >= pcmd->underflow) )
1068: {
1069: pcmd->result |= (DID_OK << 16);
1070: }
1071: else
1072: pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
1073: SCSI_STAT_CHECKCOND;
1074: goto ckc_e;
1075: }
1076: else
1077: {
1078: pSRB->RetryCnt--;
1079: pSRB->TargetStatus = 0;
1080: *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0][0];
1081: *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[0][1];
1082: *((PULONG) &(pSRB->CmdBlock[8])) = pSRB->Segment0[1][0];
1083: pSRB->__command[0] = pSRB->Segment0[1][1] & 0xff;
1084: pSRB->SGcount = (UCHAR) (pSRB->Segment0[1][1] >> 8);
1085: *((PULONG) &(pSRB->pSegmentList))= pSRB->Segment0[2][0];
1086: if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1087: {
1088: pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
1089: SCSI_STAT_CHECKCOND;
1090: goto ckc_e;
1091: }
1092: pcmd->result |= (DRIVER_SENSE << 24);
1093: PrepareSG(pACB,pDCB,pSRB);
1094: pSRB->XferredLen = 0;
1095: DC390W_StartSCSI( pACB, pDCB, pSRB );
1096: return;
1097: }
1098: }
1099: if( status )
1100: {
1101: if( status == SCSI_STAT_CHECKCOND)
1102: {
1103: if( !(pSRB->ScratchABuf & SRB_OK) && (pSRB->SGcount) && (pSRB->RemainSegPtr) )
1104: {
1105: wlval = pSRB->RemainSegPtr;
1106: swlval = pACB->jmp_table8;
1107: if(pDCB->DCBscntl3 & EN_WIDE_SCSI)
1108: swlval += jmp_table16;
1109: swlval -= wlval;
1110: swlval >>= 4;
1111: bval = (UCHAR) swlval;
1112: wlval = 0;
1113: ptr1 = (PSGE) &pSRB->Segment0[MAX_SG_LIST_BUF+1][0];
1114: for( i=0; i< bval; i++)
1115: {
1116: wlval += ptr1->SGXLen;
1117: ptr1--;
1118: }
1119:
1120: bval = pSRB->SGcount;
1121: swlval = 0;
1122: ptr2 = pSRB->pSegmentList;
1123: for( i=0; i< bval; i++)
1124: {
1125: swlval += ptr2->length;
1126: ptr2++;
1127: }
1128: pSRB->XferredLen = swlval - wlval;
1129: pSRB->RemainSegPtr = 0;
1130: #ifdef DC390W_DEBUG0
1131: printk("XferredLen=%8x,NotXferLen=%8x,",(UINT) pSRB->XferredLen,(UINT) wlval);
1132: #endif
1133: }
1134: RequestSense( pACB, pDCB, pSRB );
1135: return;
1136: }
1137: else if( status == SCSI_STAT_QUEUEFULL )
1138: {
1139: bval = (UCHAR) pDCB->GoingSRBCnt;
1140: bval--;
1141: pDCB->MaxCommand = bval;
1142: RewaitSRB( pDCB, pSRB );
1143: pSRB->AdaptStatus = 0;
1144: pSRB->TargetStatus = 0;
1145: return;
1146: }
1147: else if(status == SCSI_STAT_SEL_TIMEOUT)
1148: {
1149: pSRB->AdaptStatus = H_SEL_TIMEOUT;
1150: pSRB->TargetStatus = 0;
1151: pcmd->result = DID_BAD_TARGET << 16;
1152: }
1153: else if(status == SCSI_STAT_UNEXP_BUS_F)
1154: {
1155: pSRB->AdaptStatus = H_UNEXP_BUS_FREE;
1156: pSRB->TargetStatus = 0;
1157: pcmd->result |= DID_NO_CONNECT << 16;
1158: }
1159: else if(status == SCSI_STAT_BUS_RST_DETECT )
1160: {
1161: pSRB->AdaptStatus = H_ABORT;
1162: pSRB->TargetStatus = 0;
1163: pcmd->result = DID_RESET << 16;
1164: }
1165: else
1166: {
1167: pSRB->AdaptStatus = 0;
1168: pSRB->TargetStatus = status;
1169: if( pSRB->RetryCnt )
1170: {
1171: pSRB->RetryCnt--;
1172: pSRB->TargetStatus = 0;
1173: PrepareSG(pACB,pDCB,pSRB);
1174: pSRB->XferredLen = 0;
1175: DC390W_StartSCSI( pACB, pDCB, pSRB );
1176: return;
1177: }
1178: else
1179: {
1180: pcmd->result |= (DID_ERROR << 16) | (ULONG) (pACB->msgin123[0] << 8) |
1181: (ULONG) status;
1182: }
1183: }
1184: }
1185: else
1186: {
1187: status = pSRB->ScratchABuf;
1188: if(status & OVER_RUN_)
1189: {
1190: pSRB->AdaptStatus = H_OVER_UNDER_RUN;
1191: pSRB->TargetStatus = 0;
1192: pcmd->result |= (DID_OK << 16) | (pACB->msgin123[0] << 8);
1193: }
1194: else /* No error */
1195: {
1196: pSRB->AdaptStatus = 0;
1197: pSRB->TargetStatus = 0;
1198: pcmd->result |= (DID_OK << 16);
1199: }
1200: }
1201: ckc_e:
1202:
1203: if( pACB->scan_devices )
1204: {
1205: if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1206: {
1207: if(pcmd->result != (DID_OK << 16))
1208: {
1209: if( pcmd->result & SCSI_STAT_CHECKCOND )
1210: {
1211: goto RTN_OK;
1212: }
1213: else
1214: {
1215: pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
1216: pPrevDCB->pNextDCB = pACB->pLinkDCB;
1217: if( (pcmd->target == pACB->max_id) &&
1218: ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) )
1219: {
1220: pACB->scan_devices = 0;
1221: }
1222: }
1223: }
1224: else
1225: {
1226: RTN_OK:
1227: pPrevDCB->pNextDCB = pDCB;
1228: pDCB->pNextDCB = pACB->pLinkDCB;
1229: if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) )
1230: pACB->scan_devices = END_SCAN;
1231: }
1232: }
1233: else if( pSRB->CmdBlock[0] == INQUIRY )
1234: {
1235: if( (pcmd->target == pACB->max_id) &&
1236: (pcmd->lun == pACB->max_lun) )
1237: {
1238: pACB->scan_devices = 0;
1239: }
1240: ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1241: if( pcmd->use_sg )
1242: ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
1243: bval1 = ptr->DevType & SCSI_DEVTYPE;
1244: if(bval1 == SCSI_NODEV)
1245: {
1246: pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun);
1247: pPrevDCB->pNextDCB = pACB->pLinkDCB;
1248: }
1249: else
1250: {
1251: pACB->DeviceCnt++;
1252: pPrevDCB = pDCB;
1253: pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390W_DCB ));
1254: pDCB->DevType = bval1;
1255: if(bval1 == TYPE_DISK || bval1 == TYPE_MOD)
1256: {
1257: if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
1258: (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1259: (pDCB->DevMode & TAG_QUEUING_) &&
1260: (pDCB->DevMode & EN_DISCONNECT_) )
1261: {
1262: disable_tag = 0;
1263: for(i=0; i<BADDEVCNT; i++)
1264: {
1265: for(j=0; j<28; j++)
1266: {
1267: if( ((PUCHAR)ptr)[8+j] != baddevname[i][j])
1268: break;
1269: }
1270: if(j == 28)
1271: {
1272: disable_tag = 1;
1273: break;
1274: }
1275: }
1276:
1277: if( !disable_tag )
1278: {
1279: pDCB->MaxCommand = pACB->TagMaxNum;
1280: pDCB->TagMask = 0;
1281: }
1282: }
1283: }
1284: }
1285: }
1286: }
1287:
1288: save_flags( flags );
1289: cli();
1290: /* ReleaseSRB( pDCB, pSRB ); */
1291:
1292: if(pSRB == pDCB->pGoingSRB )
1293: {
1294: pDCB->pGoingSRB = pSRB->pNextSRB;
1295: }
1296: else
1297: {
1298: psrb = pDCB->pGoingSRB;
1299: while( psrb->pNextSRB != pSRB )
1300: psrb = psrb->pNextSRB;
1301: psrb->pNextSRB = pSRB->pNextSRB;
1302: if( pSRB == pDCB->pGoingLast )
1303: pDCB->pGoingLast = psrb;
1304: }
1305: pSRB->pNextSRB = pACB->pFreeSRB;
1306: pACB->pFreeSRB = pSRB;
1307: pDCB->GoingSRBCnt--;
1308:
1309: DoWaitingSRB( pACB );
1310: restore_flags(flags);
1311:
1312: /* Notify cmd done */
1313: pcmd->scsi_done( pcmd );
1314:
1315: if( pDCB->QIORBCnt )
1316: DoNextCmd( pACB, pDCB );
1317: return;
1318: }
1319:
1320:
1321: static void
1322: DoingSRB_Done( PACB pACB )
1323: {
1324: PDCB pDCB, pdcb;
1325: PSRB psrb, psrb2;
1326: USHORT cnt, i;
1327: PSCSICMD pcmd;
1328:
1329: pDCB = pACB->pLinkDCB;
1330: pdcb = pDCB;
1331: do
1332: {
1333: cnt = pdcb->GoingSRBCnt;
1334: psrb = pdcb->pGoingSRB;
1335: for( i=0; i<cnt; i++)
1336: {
1337: psrb2 = psrb->pNextSRB;
1338: pcmd = psrb->pcmd;
1339: pcmd->result = DID_RESET << 16;
1340:
1341: /* ReleaseSRB( pDCB, pSRB ); */
1342:
1343: psrb->pNextSRB = pACB->pFreeSRB;
1344: pACB->pFreeSRB = psrb;
1345:
1346: pcmd->scsi_done( pcmd );
1347: psrb = psrb2;
1348: }
1349: pdcb->GoingSRBCnt = 0;;
1350: pdcb->pGoingSRB = NULL;
1351: pdcb->TagMask = 0;
1352: pdcb = pdcb->pNextDCB;
1353: }
1354: while( pdcb != pDCB );
1355: }
1356:
1357:
1358: static void
1359: DC390W_ResetSCSIBus( PACB pACB )
1360: {
1361: USHORT ioport;
1362: UCHAR bval;
1363: ULONG flags;
1364:
1365: save_flags(flags);
1366: cli();
1367: pACB->ACBFlag |= RESET_DEV;
1368: ioport = pACB->IOPortBase;
1369: bval = ABORT_OP;
1370: outb(bval,ioport+ISTAT);
1371: udelay(25);
1372: bval = 0;
1373: outb(bval,ioport+ISTAT);
1374:
1375: bval = ASSERT_RST;
1376: outb(bval,ioport+SCNTL1);
1377: udelay(25); /* 25 us */
1378: bval = 0;
1379: outb(bval,ioport+SCNTL1);
1380: restore_flags(flags);
1381: return;
1382: }
1383:
1384:
1385:
1386: static void
1387: DC390W_ResetSCSIBus2( PACB pACB )
1388: {
1389: USHORT ioport;
1390: UCHAR bval;
1391: ULONG flags;
1392:
1393: save_flags(flags);
1394: cli();
1395: ioport = pACB->IOPortBase;
1396: bval = ASSERT_RST;
1397: outb(bval,ioport+SCNTL1);
1398: udelay(25); /* 25 us */
1399: bval = 0;
1400: outb(bval,ioport+SCNTL1);
1401: restore_flags(flags);
1402: return;
1403: }
1404:
1405:
1406:
1407: static void
1408: DC390W_ScsiRstDetect( PACB pACB )
1409: {
1410: ULONG wlval, flags;
1411: USHORT ioport;
1412: UCHAR bval;
1413:
1414: save_flags(flags);
1415: sti();
1416: #ifdef DC390W_DEBUG0
1417: printk("Reset_Detect0,");
1418: #endif
1419: /* delay 1 sec */
1420: wlval = jiffies + HZ;
1421: while( jiffies < wlval );
1422: /* USHORT i;
1423: for( i=0; i<1000; i++ )
1424: udelay(1000); */
1425:
1426: cli();
1427: ioport = pACB->IOPortBase;
1428: bval = inb(ioport+STEST3);
1429: bval |= CLR_SCSI_FIFO;
1430: outb(bval,ioport+STEST3);
1431: bval = CLR_DMA_FIFO;
1432: outb(bval,ioport+CTEST3);
1433:
1434: if( pACB->ACBFlag & RESET_DEV )
1435: pACB->ACBFlag |= RESET_DONE;
1436: else
1437: {
1438: pACB->ACBFlag |= RESET_DETECT;
1439:
1440: ResetDevParam( pACB );
1441: /* DoingSRB_Done( pACB ); ???? */
1442: RecoverSRB( pACB );
1443: pACB->pActiveDCB = NULL;
1444: wlval = pACB->jmp_reselect;
1445: outl(wlval,(ioport+DSP));
1446: pACB->ACBFlag = 0;
1447: DoWaitingSRB( pACB );
1448: }
1449: restore_flags(flags);
1450: return;
1451: }
1452:
1453:
1454: static void
1455: RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1456: {
1457: PSCSICMD pcmd;
1458:
1459: pSRB->SRBFlag |= AUTO_REQSENSE;
1460: pSRB->Segment0[0][0] = *((PULONG) &(pSRB->CmdBlock[0]));
1461: pSRB->Segment0[0][1] = *((PULONG) &(pSRB->CmdBlock[4]));
1462: pSRB->Segment0[1][0] = *((PULONG) &(pSRB->CmdBlock[8]));
1463: pSRB->Segment0[1][1] = pSRB->__command[0] | (pSRB->SGcount << 8);
1464: pSRB->Segment0[2][0] = *((PULONG) &(pSRB->pSegmentList));
1465: pSRB->Segment0[2][1] = pSRB->XferredLen;
1466: pSRB->AdaptStatus = 0;
1467: pSRB->TargetStatus = 0;
1468:
1469: pcmd = pSRB->pcmd;
1470:
1471: pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
1472: pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
1473: pSRB->pSegmentList = &pSRB->Segmentx;
1474: pSRB->SGcount = 1;
1475:
1476: *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
1477: pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
1478: *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer);
1479: pSRB->__command[0] = 6;
1480: PrepareSG( pACB, pDCB, pSRB );
1481: pSRB->XferredLen = 0;
1482: DC390W_StartSCSI( pACB, pDCB, pSRB );
1483: return;
1484: }
1485:
1486:
1487: static void
1488: DC390W_MessageOut( PACB pACB )
1489: {
1490: DC390W_FatalError( pACB );
1491: }
1492:
1493:
1494: static void
1495: DC390W_FatalError( PACB pACB )
1496: {
1497: PSRB pSRB;
1498: PDCB pDCB;
1499: ULONG flags;
1500:
1501: #ifdef DC390W_DEBUG0
1502: printk("DC390W: Fatal Error!!\n");
1503: #endif
1504:
1505: pDCB = pACB->pActiveDCB;
1506: pSRB = pDCB->pActiveSRB;
1507: if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
1508: {
1509: save_flags(flags);
1510: cli();
1511: pSRB->SRBState &= ~SRB_UNEXPECT_RESEL;
1512: pSRB->pNextSRB = pACB->pFreeSRB;
1513: pACB->pFreeSRB = pSRB;
1514: pACB->pActiveDCB = NULL;
1515: pDCB->pActiveSRB = NULL;
1516: restore_flags(flags);
1517: DoWaitingSRB( pACB );
1518: }
1519: else
1520: DC390W_ResetSCSIBus(pACB);
1521: return;
1522: }
1523:
1524:
1525: static void
1526: DC390W_Debug( PACB pACB )
1527: {
1528: ULONG wlval;
1529: USHORT ioport;
1530:
1531: ioport = pACB->IOPortBase;
1532: wlval = inl(ioport+DSP);
1533: outl(wlval,(ioport+DSP));
1534: return;
1535: }
1536:
1537:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.