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 plink = pcmd->sc_link;
1084 status = pSRB->TargetStatus;
1085 if(pSRB->SRBFlag & AUTO_REQSENSE)
1086 {
1087 pSRB->SRBFlag &= ~AUTO_REQSENSE;
1088 pSRB->AdaptStatus = 0;
1089 pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
1090 if(status == SCSI_STAT_CHECKCOND)
1091 {
1092 pcmd->error = XS_TIMEOUT;
1093 goto ckc_e;
1094 }
1095
1096 if(pSRB->RetryCnt == 0)
1097 {
1098 *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1099 pSRB->TotalXferredLen = pSRB->Segment1[1];
1100 if( pSRB->TotalXferredLen )
1101 {
1102 pcmd->resid = pcmd->datalen - pSRB->TotalXferredLen;
1103 pcmd->error = XS_SENSE;
1104 pcmd->flags |= SCSI_RESID_VALID;
1105 }
1106 else
1107 {
1108 pcmd->error = XS_SENSE;
1109 pcmd->status = SCSI_STAT_CHECKCOND;
1110 }
1111 goto ckc_e;
1112 }
1113 else
1114 {
1115 pSRB->RetryCnt--;
1116 pSRB->AdaptStatus = 0;
1117 pSRB->TargetStatus = 0;
1118 *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1119 *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
1120 if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1121 {
1122 pcmd->error = XS_SENSE;
1123 pcmd->status = SCSI_STAT_CHECKCOND;
1124 goto ckc_e;
1125 }
1126 pcmd->error = XS_SENSE;
1127 pSRB->SGcount = (UCHAR) pSRB->Segment1[0];
1128 pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8);
1129 pSRB->pSegmentList = (PSEG) &pSRB->SGsegment[0];
1130 pSRB->SGIndex = 0;
1131 pSRB->TotalXferredLen = 0;
1132 pSRB->SGToBeXferLen = 0;
1133 if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1134 RewaitSRB( pDCB, pSRB );
1135 return;
1136 }
1137 }
1138 if( status )
1139 {
1140 if( status == SCSI_STAT_CHECKCOND)
1141 {
1142 if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
1143 {
1144 bval = pSRB->SGcount;
1145 swlval = pSRB->SGToBeXferLen;
1146 ptr2 = pSRB->pSegmentList;
1147 ptr2++;
1148 for( i=pSRB->SGIndex+1; i < bval; i++)
1149 {
1150 swlval += ptr2->SGXLen;
1151 ptr2++;
1152 }
1153 #ifdef DC390_DEBUG0
1154 printf("XferredLen=%8x,NotXferLen=%8x,",
1155 (UINT) pSRB->TotalXferredLen, (UINT) swlval);
1156 #endif
1157 }
1158 RequestSense( pACB, pDCB, pSRB );
1159 return;
1160 }
1161 else if( status == SCSI_STAT_QUEUEFULL )
1162 {
1163 bval = (UCHAR) pDCB->GoingSRBCnt;
1164 bval--;
1165 pDCB->MaxCommand = bval;
1166 RewaitSRB( pDCB, pSRB );
1167 pSRB->AdaptStatus = 0;
1168 pSRB->TargetStatus = 0;
1169 return;
1170 }
1171 else if(status == SCSI_STAT_SEL_TIMEOUT)
1172 {
1173 pSRB->AdaptStatus = H_SEL_TIMEOUT;
1174 pSRB->TargetStatus = 0;
1175 pcmd->error = XS_TIMEOUT;
1176 }
1177 else if (status == SCSI_STAT_BUSY)
1178 {
1179 #ifdef DC390_DEBUG0
1180 printf("DC390: target busy at %s %d\n", __FILE__, __LINE__);
1181 #endif
1182 pcmd->error = XS_BUSY;
1183 }
1184 else if (status == SCSI_STAT_RESCONFLICT)
1185 {
1186 #ifdef DC390_DEBUG0
1187 printf("DC390: target reserved at %s %d\n", __FILE__, __LINE__);
1188 #endif
1189 pcmd->error = XS_BUSY; /*XXX*/
1190 }
1191 else
1192 {
1193 pSRB->AdaptStatus = 0;
1194 if( pSRB->RetryCnt )
1195 {
1196 pSRB->RetryCnt--;
1197 pSRB->TargetStatus = 0;
1198 pSRB->SGIndex = 0;
1199 pSRB->TotalXferredLen = 0;
1200 pSRB->SGToBeXferLen = 0;
1201 pSRB->pSegmentList = (PSEG) &pSRB->SGsegment[0];
1202 if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1203 RewaitSRB( pDCB, pSRB );
1204 return;
1205 }
1206 else
1207 {
1208 #ifdef DC390_DEBUG0
1209 printf("DC390: driver stuffup at %s %d\n", __FILE__, __LINE__);
1210 #endif
1211 pcmd->error = XS_DRIVER_STUFFUP;
1212 }
1213 }
1214 }
1215 else
1216 {
1217 status = pSRB->AdaptStatus;
1218 if(status & H_OVER_UNDER_RUN)
1219 {
1220 pSRB->TargetStatus = 0;
1221 pcmd->error = XS_LENGTH;
1222 }
1223 else if( pSRB->SRBStatus & PARITY_ERROR)
1224 {
1225 #ifdef DC390_DEBUG0
1226 printf("DC390: driver stuffup %s %d\n", __FILE__, __LINE__);
1227 #endif
1228 pcmd->error = XS_DRIVER_STUFFUP;
1229 }
1230 else /* No error */
1231 {
1232 pSRB->AdaptStatus = 0;
1233 pSRB->TargetStatus = 0;
1234 pcmd->error = XS_NOERROR;
1235 }
1236 }
1237
1238 ckc_e:
1239 if( pACB->scan_devices )
1240 {
1241 if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1242 {
1243 if(pcmd->error == XS_TIMEOUT )
1244 {
1245 pACB->DCBmap[plink->target] &= ~(1 << plink->lun);
1246 pPrevDCB->pNextDCB = pACB->pLinkDCB;
1247 }
1248 else
1249 {
1250 pPrevDCB->pNextDCB = pDCB;
1251 pDCB->pNextDCB = pACB->pLinkDCB;
1252 }
1253 }
1254 else if( pSRB->CmdBlock[0] == INQUIRY )
1255 {
1256 if( (plink->target == pACB->max_id) && (plink->lun == pACB->max_lun) )
1257 pACB->scan_devices = 0;
1258 if(pcmd->error == XS_TIMEOUT )
1259 goto NO_DEV;
1260 ptr = (PSCSI_INQDATA) (pcmd->data);
1261 bval1 = ptr->DevType & SCSI_DEVTYPE;
1262 if(bval1 == SCSI_NODEV)
1263 {
1264 NO_DEV:
1265 pACB->DCBmap[plink->target] &= ~(1 << plink->lun);
1266 pPrevDCB->pNextDCB = pACB->pLinkDCB;
1267 }
1268 else
1269 {
1270 pACB->DeviceCnt++;
1271 pPrevDCB = pDCB;
1272 pACB->pDCB_free = (PDCB) ((uintptr_t) (pACB->pDCB_free) + sizeof( DC390_DCB ));
1273 pDCB->DevType = bval1;
1274 if(bval1 == SCSI_DASD || bval1 == SCSI_OPTICAL)
1275 {
1276 if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) &&
1277 (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1278 (pDCB->DevMode & TAG_QUEUING_) &&
1279 (pDCB->DevMode & EN_DISCONNECT_) )
1280 {
1281 disable_tag = 0;
1282 for(i=0; i<BADDEVCNT; i++)
1283 {
1284 for(j=0; j<28; j++)
1285 {
1286 if( ((PUCHAR)ptr)[8+j] != baddevname1[i][j])
1287 break;
1288 }
1289 if(j == 28)
1290 {
1291 disable_tag = 1;
1292 break;
1293 }
1294 }
1295
1296 if( !disable_tag )
1297 {
1298 pDCB->MaxCommand = pACB->TagMaxNum;
1299 pDCB->SyncMode |= EN_TAG_QUEUING;
1300 pDCB->TagMask = 0;
1301 }
1302 else
1303 {
1304 pDCB->SyncMode |= EN_ATN_STOP;
1305 }
1306 }
1307 }
1308 }
1309 }
1310 }
1311
1312 flags = splbio();
1313 /* ReleaseSRB( pDCB, pSRB ); */
1314
1315 if(pSRB == pDCB->pGoingSRB )
1316 {
1317 pDCB->pGoingSRB = pSRB->pNextSRB;
1318 }
1319 else
1320 {
1321 psrb = pDCB->pGoingSRB;
1322 while( psrb->pNextSRB != pSRB )
1323 psrb = psrb->pNextSRB;
1324 psrb->pNextSRB = pSRB->pNextSRB;
1325 if( pSRB == pDCB->pGoingLast )
1326 pDCB->pGoingLast = psrb;
1327 }
1328 pSRB->pNextSRB = pACB->pFreeSRB;
1329 pACB->pFreeSRB = pSRB;
1330 pDCB->GoingSRBCnt--;
1331
1332 DoWaitingSRB( pACB );
1333 splx(flags);
1334
1335 pcmd->flags |= ITSDONE;
1336
1337 /* Notify cmd done */
1338 scsi_done( pcmd );
1339 }
1340
1341
1342 static void
1343 DoingSRB_Done( PACB pACB )
1344 {
1345 PDCB pDCB, pdcb;
1346 PSRB psrb, psrb2;
1347 USHORT cnt, i;
1348 PSCSICMD pcmd;
1349
1350 pDCB = pACB->pLinkDCB;
1351 pdcb = pDCB;
1352 do
1353 {
1354 cnt = pdcb->GoingSRBCnt;
1355 psrb = pdcb->pGoingSRB;
1356 for( i=0; i<cnt; i++)
1357 {
1358 psrb2 = psrb->pNextSRB;
1359 pcmd = psrb->pcmd;
1360 pcmd->error = XS_TIMEOUT;
1361
1362 /* ReleaseSRB( pDCB, pSRB ); */
1363
1364 psrb->pNextSRB = pACB->pFreeSRB;
1365 pACB->pFreeSRB = psrb;
1366
1367 scsi_done( pcmd );
1368 psrb = psrb2;
1369 }
1370 pdcb->GoingSRBCnt = 0;;
1371 pdcb->pGoingSRB = NULL;
1372 pdcb->TagMask = 0;
1373 pdcb = pdcb->pNextDCB;
1374 }
1375 while( pdcb != pDCB );
1376 }
1377
1378
1379 static void
1380 DC390_ResetSCSIBus( PACB pACB )
1381 {
1382 USHORT ioport;
1383 UCHAR bval;
1384 int flags;
1385
1386 flags = splbio();
1387 pACB->ACBFlag |= RESET_DEV;
1388 ioport = pACB->IOPortBase;
1389
1390 bval = DMA_IDLE_CMD;
1391 OutB(bval,ioport+DMA_Cmd);
1392
1393 bval = RST_SCSI_BUS_CMD;
1394 OutB(bval,ioport+ScsiCmd);
1395
1396 splx(flags);
1397 return;
1398 }
1399
1400
1401 static void
1402 DC390_ScsiRstDetect( PACB pACB )
1403 {
1404 int flags;
1405 ULONG wlval;
1406 USHORT ioport;
1407 UCHAR bval;
1408
1409 #ifdef DC390_DEBUG0
1410 printf("RST_DETEC");
1411 #endif
1412 wlval = 1000;
1413 while( --wlval ) /* delay 1 sec */
1414 {
1415 DELAY(1000);
1416 }
1417 flags = splbio();
1418 ioport = pACB->IOPortBase;
1419 bval = DMA_IDLE_CMD;
1420 OutB(bval,ioport+DMA_Cmd);
1421 bval = CLEAR_FIFO_CMD;
1422 OutB(bval,ioport+ScsiCmd);
1423
1424 if( pACB->ACBFlag & RESET_DEV )
1425 pACB->ACBFlag |= RESET_DONE;
1426 else
1427 {
1428 pACB->ACBFlag |= RESET_DETECT;
1429
1430 ResetDevParam( pACB );
1431 /* DoingSRB_Done( pACB ); ???? */
1432 RecoverSRB( pACB );
1433 pACB->pActiveDCB = NULL;
1434 pACB->ACBFlag = 0;
1435 DoWaitingSRB( pACB );
1436 }
1437 splx(flags);
1438 return;
1439 }
1440
1441
1442 static void
1443 RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1444 {
1445 PSCSICMD pcmd;
1446
1447 pSRB->SRBFlag |= AUTO_REQSENSE;
1448 pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0]));
1449 pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4]));
1450 pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount);
1451 pSRB->Segment1[1] = pSRB->TotalXferredLen;
1452 pSRB->AdaptStatus = 0;
1453 pSRB->TargetStatus = 0;
1454
1455 pcmd = pSRB->pcmd;
1456
1457 pSRB->Segmentx.SGXPtr = (ULONG) vtophys(&pcmd->sense);
1458 pSRB->Segmentx.SGXLen = (ULONG) sizeof(struct scsi_sense_data);
1459 pSRB->pSegmentList = &pSRB->Segmentx;
1460 pSRB->SGcount = 1;
1461 pSRB->SGIndex = 0;
1462
1463 *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003;
1464 pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
1465 *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(struct scsi_sense_data);
1466 pSRB->ScsiCmdLen = 6;
1467
1468 pSRB->TotalXferredLen = 0;
1469 pSRB->SGToBeXferLen = 0;
1470 if( DC390_StartSCSI( pACB, pDCB, pSRB ) )
1471 RewaitSRB( pDCB, pSRB );
1472 }
1473
1474
1475 static void
1476 EnableMsgOut2( PACB pACB, PSRB pSRB )
1477 {
1478 USHORT ioport;
1479 UCHAR bval;
1480
1481 ioport = pACB->IOPortBase;
1482 pSRB->MsgCnt = 1;
1483 bval = SET_ATN_CMD;
1484 OutB(bval, ioport+ScsiCmd);
1485 }
1486
1487
1488 static void
1489 EnableMsgOut( PACB pACB, PSRB pSRB )
1490 {
1491 pSRB->MsgOutBuf[0] = MSG_ABORT;
1492 EnableMsgOut2( pACB, pSRB );
1493 }
1494
1495
1496 static void
1497 DC390_InvalidCmd( PACB pACB )
1498 {
1499 UCHAR bval;
1500 USHORT ioport;
1501 PSRB pSRB;
1502
1503 pSRB = pACB->pActiveDCB->pActiveSRB;
1504 if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
1505 {
1506 ioport = pACB->IOPortBase;
1507 bval = CLEAR_FIFO_CMD;
1508 OutB(bval,(ioport+ScsiCmd));
1509 }
1510 }
1511
Cache object: 34b2c55a8782fd6765f0a4581db41e1a
|