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