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