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