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