|
|
1.1 ! root 1: /*********************************************************************** ! 2: * FILE NAME : TMSCSIW.C * ! 3: * BY : C.L. Huang ([email protected]) * ! 4: * Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI * ! 5: * Bus Master Host Adapter * ! 6: * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * ! 7: ***********************************************************************/ ! 8: /* Minor enhancements and bugfixes by * ! 9: * Kurt Garloff <[email protected]> * ! 10: ***********************************************************************/ ! 11: /* HISTORY: * ! 12: * * ! 13: * REV# DATE NAME DESCRIPTION * ! 14: * 1.00 04/03/96 CLH First release * ! 15: * 1.01 04/11/96 CLH Maximum support up to 4 Adapters, * ! 16: * support KV 1_3_85 * ! 17: * 1.02 04/26/96 CLH fixed bug about EEpromBuf when >1 HA * ! 18: * 1.03 06/12/96 CLH fixed bug of Media Change for Removable * ! 19: * Device, scan all LUN. Support Pre2.0.10 * ! 20: * 1.04 06/18/96 CLH fixed bug of Command timeout .... * ! 21: * 1.05 10/04/96 CLH Updating for support KV 2.0.0, 2.0.20 * ! 22: * 1.06 10/30/96 KG Fixed bug in DC390W_abort(), module * ! 23: * support, added tmscsiw_proc_info() * ! 24: * 1.07 11/09/96 KG Fixed bug in tmscsiw_proc_info() * ! 25: * 1.08 11/18/96 CLH/KG ditto, null ptr in DC390W_Disconnect() * ! 26: * 1.09 11/30/96 KG Fixed bug in CheckEEpromCheckSum(), * ! 27: * add register the allocated IO space * ! 28: * 1.10 12/05/96 CLH Modify in tmscsiw_proc_info() and add * ! 29: * in DC390W_initAdapter() for 53C875 * ! 30: * Rev. F with double clock. * ! 31: * 1.11 02/04/97 CLH Fixed bug of Formatting a partition that* ! 32: * across 1GB boundary, with bad sector * ! 33: * checking. * ! 34: * 1.12 02/17/97 CLH Fixed bug in CheckEEpromCheckSum() * ! 35: ***********************************************************************/ ! 36: ! 37: ! 38: #define DC390W_DEBUG ! 39: /* #define CHK_UNDER_RUN */ ! 40: ! 41: #define SCSI_MALLOC ! 42: ! 43: #ifdef MODULE ! 44: #include <linux/module.h> ! 45: #endif ! 46: ! 47: #include <asm/dma.h> ! 48: #include <asm/io.h> ! 49: #include <asm/system.h> ! 50: #include <linux/delay.h> ! 51: #include <linux/signal.h> ! 52: #include <linux/sched.h> ! 53: #include <linux/errno.h> ! 54: #include <linux/kernel.h> ! 55: #include <linux/ioport.h> ! 56: #include <linux/bios32.h> ! 57: #include <linux/pci.h> ! 58: #include <linux/proc_fs.h> ! 59: #include <linux/string.h> ! 60: #include <linux/mm.h> ! 61: #include <linux/config.h> ! 62: ! 63: #include <linux/version.h> ! 64: #if LINUX_VERSION_CODE < 66354 /* 1.3.50 */ ! 65: #include "../block/blk.h" ! 66: #else ! 67: #include <linux/blk.h> ! 68: #endif ! 69: ! 70: #include "scsi.h" ! 71: #include "hosts.h" ! 72: #include "tmscsiw.h" ! 73: #include "constants.h" ! 74: #include "sd.h" ! 75: #include "scripts.h" ! 76: #include <linux/stat.h> ! 77: ! 78: #include "dc390w.h" ! 79: ! 80: #ifndef VERSION_ELF_1_2_13 ! 81: struct proc_dir_entry proc_scsi_tmscsiw ={ ! 82: PROC_SCSI_DC390WUF, 7 ,"tmscsiw", ! 83: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 84: }; ! 85: #endif ! 86: ! 87: static void DC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 88: static void PrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 89: static void DoingSRB_Done( PACB pACB ); ! 90: static void ExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB); ! 91: static void ParityError( PACB pACB, PDCB pDCB ); ! 92: static void PhaseMismatch( PACB pACB ); ! 93: static void DC390W_ScsiRstDetect( PACB pACB ); ! 94: static void DC390W_ResetSCSIBus( PACB pACB ); ! 95: static void DC390W_ResetSCSIBus2( PACB pACB ); ! 96: static void AdjustTemp( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 97: static void SetXferRate( PACB pACB, PDCB pDCB ); ! 98: static void DataIOcommon( PACB pACB, ULONG Swlval, ULONG Cwlval ); ! 99: static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 100: static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 101: ! 102: static void DC390W_CmdCompleted( PACB pACB ); ! 103: static void DC390W_Reselected( PACB pACB ); ! 104: static void DC390W_Reselected1( PACB pACB ); ! 105: static void DC390W_ReselectedT( PACB pACB ); ! 106: static void DC390W_Disconnected( PACB pACB ); ! 107: static void DC390W_MessageExtnd( PACB pACB ); ! 108: static void DC390W_Signal( PACB pACB ); ! 109: static void DC390W_UnknownMsg( PACB pACB ); ! 110: static void DC390W_MessageOut( PACB pACB ); ! 111: static void DC390W_FatalError( PACB pACB ); ! 112: static void DC390W_MessageSync( PACB pACB ); ! 113: static void DC390W_MessageWide( PACB pACB ); ! 114: static void DC390W_RestorePtr( PACB pACB ); ! 115: static void DC390W_MsgReject( PACB pACB ); ! 116: static void DC390W_Debug( PACB pACB ); ! 117: static void DC390W_download_script (struct Scsi_Host *host); ! 118: ! 119: int DC390W_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index); ! 120: void DC390W_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); ! 121: void MyDelay( void ); ! 122: void EnDisableCE( UCHAR Flag, USHORT scsiIOPort ); ! 123: void EEpromOutDI( USHORT Carry, USHORT scsiIOPort ); ! 124: void EEpromPrepare( UCHAR EEpromCmd, USHORT scsiIOPort ); ! 125: void ReadEEprom( PUCHAR EEpromBuf, USHORT scsiIOPort ); ! 126: UCHAR EEpromInDo(USHORT scsiIOPort); ! 127: USHORT EEpromGetData(USHORT scsiIOPort); ! 128: USHORT CheckEEpromCheckSum( PUCHAR EEpromBuf, USHORT scsiIOPort); ! 129: ! 130: #ifdef MODULE ! 131: static int DC390W_release(struct Scsi_Host *host); ! 132: static int DC390W_shutdown (struct Scsi_Host *host); ! 133: #endif ! 134: ! 135: ! 136: static ULONG jmp_table16; ! 137: static ULONG jmp_din16; ! 138: static ULONG jmp_dout16; ! 139: static PSHT pSHT_start = NULL; ! 140: static PSH pSH_start = NULL; ! 141: static PSH pSH_current = NULL; ! 142: static PACB pACB_start= NULL; ! 143: static PACB pACB_current = NULL; ! 144: static PDCB pPrevDCB = NULL; ! 145: static USHORT adapterCnt = 0; ! 146: static USHORT InitialTime = 0; ! 147: static USHORT CurrDCBscntl3 = 0; ! 148: static UCHAR pad_buffer[128]; ! 149: ! 150: static PVOID IntVector[]={ ! 151: DC390W_CmdCompleted, ! 152: DC390W_Reselected, ! 153: DC390W_Reselected1, ! 154: DC390W_ReselectedT, ! 155: DC390W_Disconnected, ! 156: DC390W_MessageExtnd, ! 157: DC390W_Signal, ! 158: DC390W_UnknownMsg, ! 159: DC390W_MessageOut, ! 160: DC390W_FatalError, ! 161: DC390W_MessageSync, ! 162: DC390W_MessageWide, ! 163: DC390W_RestorePtr, ! 164: DC390W_MsgReject, ! 165: DC390W_Debug, ! 166: DC390W_FatalError ! 167: }; ! 168: ! 169: UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; ! 170: ! 171: UCHAR clock_period[12] = {25, 31, 37, 43, 50, 62, 75, 125, 12, 15, 18, 21}; ! 172: UCHAR baddevname[2][28] ={ ! 173: "SEAGATE ST3390N 9546", ! 174: "SEAGATE ST3390N ??? 0399"}; ! 175: ! 176: #define BADDEVCNT 2 ! 177: ! 178: /*********************************************************************** ! 179: * ! 180: * ! 181: * ! 182: **********************************************************************/ ! 183: static void ! 184: QLinkcmd( PSCSICMD cmd, PDCB pDCB ) ! 185: { ! 186: ULONG flags; ! 187: PSCSICMD pcmd; ! 188: ! 189: save_flags(flags); ! 190: cli(); ! 191: ! 192: if( !pDCB->QIORBCnt ) ! 193: { ! 194: pDCB->pQIORBhead = cmd; ! 195: pDCB->pQIORBtail = cmd; ! 196: pDCB->QIORBCnt++; ! 197: cmd->next = NULL; ! 198: } ! 199: else ! 200: { ! 201: pcmd = pDCB->pQIORBtail; ! 202: pcmd->next = cmd; ! 203: pDCB->pQIORBtail = cmd; ! 204: pDCB->QIORBCnt++; ! 205: cmd->next = NULL; ! 206: } ! 207: ! 208: restore_flags(flags); ! 209: } ! 210: ! 211: ! 212: static PSCSICMD ! 213: Getcmd( PDCB pDCB ) ! 214: { ! 215: ULONG flags; ! 216: PSCSICMD pcmd; ! 217: ! 218: save_flags(flags); ! 219: cli(); ! 220: ! 221: pcmd = pDCB->pQIORBhead; ! 222: pDCB->pQIORBhead = pcmd->next; ! 223: pcmd->next = NULL; ! 224: pDCB->QIORBCnt--; ! 225: ! 226: restore_flags(flags); ! 227: return( pcmd ); ! 228: } ! 229: ! 230: ! 231: static PSRB ! 232: GetSRB( PACB pACB ) ! 233: { ! 234: ULONG flags; ! 235: PSRB pSRB; ! 236: ! 237: save_flags(flags); ! 238: cli(); ! 239: ! 240: pSRB = pACB->pFreeSRB; ! 241: if( pSRB ) ! 242: { ! 243: pACB->pFreeSRB = pSRB->pNextSRB; ! 244: pSRB->pNextSRB = NULL; ! 245: } ! 246: restore_flags(flags); ! 247: return( pSRB ); ! 248: } ! 249: ! 250: ! 251: static void ! 252: RewaitSRB( PDCB pDCB, PSRB pSRB ) ! 253: { ! 254: PSRB psrb1; ! 255: ULONG flags; ! 256: UCHAR bval; ! 257: ! 258: save_flags(flags); ! 259: cli(); ! 260: pDCB->GoingSRBCnt--; ! 261: psrb1 = pDCB->pGoingSRB; ! 262: if( pSRB == psrb1 ) ! 263: { ! 264: pDCB->pGoingSRB = psrb1->pNextSRB; ! 265: } ! 266: else ! 267: { ! 268: while( pSRB != psrb1->pNextSRB ) ! 269: psrb1 = psrb1->pNextSRB; ! 270: psrb1->pNextSRB = pSRB->pNextSRB; ! 271: if( pSRB == pDCB->pGoingLast ) ! 272: pDCB->pGoingLast = psrb1; ! 273: } ! 274: if( (psrb1 = pDCB->pWaitingSRB) ) ! 275: { ! 276: pSRB->pNextSRB = psrb1; ! 277: pDCB->pWaitingSRB = pSRB; ! 278: } ! 279: else ! 280: { ! 281: pSRB->pNextSRB = NULL; ! 282: pDCB->pWaitingSRB = pSRB; ! 283: pDCB->pWaitLast = pSRB; ! 284: } ! 285: ! 286: bval = pSRB->TagNumber; ! 287: pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ ! 288: restore_flags(flags); ! 289: } ! 290: ! 291: ! 292: static void ! 293: DoWaitingSRB( PACB pACB ) ! 294: { ! 295: ULONG flags; ! 296: PDCB ptr, ptr1; ! 297: PSRB pSRB; ! 298: ! 299: save_flags(flags); ! 300: cli(); ! 301: ! 302: if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) ! 303: { ! 304: ptr = pACB->pDCBRunRobin; ! 305: if( !ptr ) ! 306: { ! 307: ptr = pACB->pLinkDCB; ! 308: pACB->pDCBRunRobin = ptr; ! 309: } ! 310: ptr1 = ptr; ! 311: for( ;ptr1; ) ! 312: { ! 313: pACB->pDCBRunRobin = ptr1->pNextDCB; ! 314: if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || ! 315: !( pSRB = ptr1->pWaitingSRB ) ) ! 316: { ! 317: if(pACB->pDCBRunRobin == ptr) ! 318: break; ! 319: ptr1 = ptr1->pNextDCB; ! 320: } ! 321: else ! 322: { ! 323: DC390W_StartSCSI(pACB, ptr1, pSRB); ! 324: ptr1->GoingSRBCnt++; ! 325: if( ptr1->pWaitLast == pSRB ) ! 326: { ! 327: ptr1->pWaitingSRB = NULL; ! 328: ptr1->pWaitLast = NULL; ! 329: } ! 330: else ! 331: { ! 332: ptr1->pWaitingSRB = pSRB->pNextSRB; ! 333: } ! 334: pSRB->pNextSRB = NULL; ! 335: ! 336: if( ptr1->pGoingSRB ) ! 337: ptr1->pGoingLast->pNextSRB = pSRB; ! 338: else ! 339: ptr1->pGoingSRB = pSRB; ! 340: ptr1->pGoingLast = pSRB; ! 341: ! 342: break; ! 343: } ! 344: } ! 345: } ! 346: restore_flags(flags); ! 347: return; ! 348: } ! 349: ! 350: ! 351: static void ! 352: SRBwaiting( PDCB pDCB, PSRB pSRB) ! 353: { ! 354: if( pDCB->pWaitingSRB ) ! 355: { ! 356: pDCB->pWaitLast->pNextSRB = pSRB; ! 357: pDCB->pWaitLast = pSRB; ! 358: pSRB->pNextSRB = NULL; ! 359: } ! 360: else ! 361: { ! 362: pDCB->pWaitingSRB = pSRB; ! 363: pDCB->pWaitLast = pSRB; ! 364: } ! 365: } ! 366: ! 367: ! 368: static void ! 369: SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) ! 370: { ! 371: ULONG flags; ! 372: PDCB pDCB; ! 373: ! 374: save_flags(flags); ! 375: cli(); ! 376: ! 377: pDCB = pSRB->pSRBDCB; ! 378: PrepareSG( pACB, pDCB, pSRB ); ! 379: if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || ! 380: (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) ! 381: { ! 382: SRBwaiting(pDCB, pSRB); ! 383: goto SND_EXIT; ! 384: } ! 385: ! 386: if( pDCB->pWaitingSRB ) ! 387: { ! 388: SRBwaiting(pDCB, pSRB); ! 389: /* pSRB = GetWaitingSRB(pDCB); */ ! 390: pSRB = pDCB->pWaitingSRB; ! 391: pDCB->pWaitingSRB = pSRB->pNextSRB; ! 392: pSRB->pNextSRB = NULL; ! 393: } ! 394: ! 395: DC390W_StartSCSI(pACB, pDCB, pSRB); ! 396: pDCB->GoingSRBCnt++; ! 397: if( pDCB->pGoingSRB ) ! 398: { ! 399: pDCB->pGoingLast->pNextSRB = pSRB; ! 400: pDCB->pGoingLast = pSRB; ! 401: } ! 402: else ! 403: { ! 404: pDCB->pGoingSRB = pSRB; ! 405: pDCB->pGoingLast = pSRB; ! 406: } ! 407: ! 408: SND_EXIT: ! 409: restore_flags(flags); ! 410: return; ! 411: } ! 412: ! 413: ! 414: /*********************************************************************** ! 415: * Function : static int DC390W_queue_command (Scsi_Cmnd *cmd, ! 416: * void (*done)(Scsi_Cmnd *)) ! 417: * ! 418: * Purpose : enqueues a SCSI command ! 419: * ! 420: * Inputs : cmd - SCSI command, done - function called on completion, with ! 421: * a pointer to the command descriptor. ! 422: * ! 423: * Returns : 0 ! 424: * ! 425: ***********************************************************************/ ! 426: ! 427: int ! 428: DC390W_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ! 429: { ! 430: USHORT ioport, i; ! 431: Scsi_Cmnd *pcmd; ! 432: struct Scsi_Host *psh; ! 433: PACB pACB; ! 434: PDCB pDCB; ! 435: PSRB pSRB; ! 436: ULONG flags; ! 437: PUCHAR ptr,ptr1; ! 438: ! 439: psh = cmd->host; ! 440: pACB = (PACB ) psh->hostdata; ! 441: ioport = pACB->IOPortBase; ! 442: ! 443: #ifdef DC390W_DEBUG0 ! 444: printk("Cmd=%x,",cmd->cmnd[0]); ! 445: #endif ! 446: ! 447: if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) ! 448: { ! 449: pACB->scan_devices = 0; ! 450: pPrevDCB->pNextDCB = pACB->pLinkDCB; ! 451: } ! 452: else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) ) ! 453: { ! 454: pACB->scan_devices = 0; ! 455: pPrevDCB->pNextDCB = pACB->pLinkDCB; ! 456: } ! 457: ! 458: if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) ) ! 459: { ! 460: /* printk("DC390W: Ignore target %d lun %d\n", ! 461: cmd->target, cmd->lun); */ ! 462: cmd->result = (DID_BAD_TARGET << 16); ! 463: done(cmd); ! 464: return( 0 ); ! 465: } ! 466: ! 467: if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) ! 468: { ! 469: if( pACB->DeviceCnt < MAX_DEVICES ) ! 470: { ! 471: pACB->DCBmap[cmd->target] |= (1 << cmd->lun); ! 472: pDCB = pACB->pDCB_free; ! 473: #ifdef DC390W_DEBUG0 ! 474: printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); ! 475: #endif ! 476: DC390W_initDCB( pACB, pDCB, cmd ); ! 477: } ! 478: else /* ???? */ ! 479: { ! 480: /* printk("DC390W: Ignore target %d lun %d\n", ! 481: cmd->target, cmd->lun); */ ! 482: cmd->result = (DID_BAD_TARGET << 16); ! 483: done(cmd); ! 484: return(0); ! 485: } ! 486: } ! 487: else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) ! 488: { ! 489: /* printk("DC390W: Ignore target %d lun %d\n", ! 490: cmd->target, cmd->lun); */ ! 491: cmd->result = (DID_BAD_TARGET << 16); ! 492: done(cmd); ! 493: return(0); ! 494: } ! 495: else ! 496: { ! 497: pDCB = pACB->pLinkDCB; ! 498: while( (pDCB->UnitSCSIID != cmd->target) || ! 499: (pDCB->UnitSCSILUN != cmd->lun) ) ! 500: { ! 501: pDCB = pDCB->pNextDCB; ! 502: } ! 503: #ifdef DC390W_DEBUG0 ! 504: printk("pDCB=%8x,ID=%2x,Scan=%1x", (UINT) pDCB, cmd->target, ! 505: pACB->scan_devices); ! 506: #endif ! 507: } ! 508: ! 509: cmd->scsi_done = done; ! 510: cmd->result = 0; ! 511: ! 512: save_flags(flags); ! 513: cli(); ! 514: ! 515: if( pDCB->QIORBCnt ) ! 516: { ! 517: QLinkcmd( cmd, pDCB ); ! 518: pcmd = Getcmd( pDCB ); ! 519: } ! 520: else ! 521: pcmd = cmd; ! 522: ! 523: pSRB = GetSRB( pACB ); ! 524: ! 525: if( !pSRB ) ! 526: { ! 527: QLinkcmd( pcmd, pDCB ); ! 528: restore_flags(flags); ! 529: return(0); ! 530: } ! 531: ! 532: /* BuildSRB(pSRB); */ ! 533: ! 534: pSRB->pSRBDCB = pDCB; ! 535: pSRB->pcmd = pcmd; ! 536: ptr = (PUCHAR) pSRB->CmdBlock; ! 537: ptr1 = (PUCHAR) pcmd->cmnd; ! 538: (UCHAR) pSRB->__command[0] = pcmd->cmd_len; ! 539: for(i=0; i< pcmd->cmd_len; i++) ! 540: { ! 541: *ptr = *ptr1; ! 542: ptr++; ! 543: ptr1++; ! 544: } ! 545: if( pcmd->use_sg ) ! 546: { ! 547: pSRB->SGcount = (UCHAR) pcmd->use_sg; ! 548: pSRB->pSegmentList = (PSGL) pcmd->request_buffer; ! 549: } ! 550: else if( pcmd->request_buffer ) ! 551: { ! 552: pSRB->SGcount = 1; ! 553: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; ! 554: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; ! 555: pSRB->Segmentx.length = pcmd->request_bufflen; ! 556: } ! 557: else ! 558: pSRB->SGcount = 0; ! 559: ! 560: pSRB->AdaptStatus = 0; ! 561: pSRB->TargetStatus = 0; ! 562: pSRB->MsgCnt = 0; ! 563: if( pDCB->DevType != TYPE_TAPE ) ! 564: pSRB->RetryCnt = 1; ! 565: else ! 566: pSRB->RetryCnt = 0; ! 567: pSRB->SRBStatus = 0; ! 568: pSRB->SRBFlag = 0; ! 569: pSRB->ScratchABuf = 0; ! 570: pSRB->SRBState = 0; ! 571: pSRB->RemainSegPtr = 0; ! 572: pSRB->XferredLen = 0; ! 573: SendSRB( pcmd, pACB, pSRB ); ! 574: ! 575: restore_flags(flags); ! 576: return(0); ! 577: } ! 578: ! 579: ! 580: static void ! 581: DoNextCmd( PACB pACB, PDCB pDCB ) ! 582: { ! 583: Scsi_Cmnd *pcmd; ! 584: PSRB pSRB; ! 585: ULONG flags; ! 586: PUCHAR ptr,ptr1; ! 587: USHORT i; ! 588: ! 589: ! 590: if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ! 591: return; ! 592: save_flags(flags); ! 593: cli(); ! 594: ! 595: pcmd = Getcmd( pDCB ); ! 596: pSRB = GetSRB( pACB ); ! 597: if( !pSRB ) ! 598: { ! 599: QLinkcmd( pcmd, pDCB ); ! 600: restore_flags(flags); ! 601: return; ! 602: } ! 603: ! 604: pSRB->pSRBDCB = pDCB; ! 605: pSRB->pcmd = pcmd; ! 606: ptr = (PUCHAR) pSRB->CmdBlock; ! 607: ptr1 = (PUCHAR) pcmd->cmnd; ! 608: (UCHAR) pSRB->__command[0] = pcmd->cmd_len; ! 609: for(i=0; i< pcmd->cmd_len; i++) ! 610: { ! 611: *ptr = *ptr1; ! 612: ptr++; ! 613: ptr1++; ! 614: } ! 615: if( pcmd->use_sg ) ! 616: { ! 617: pSRB->SGcount = (UCHAR) pcmd->use_sg; ! 618: pSRB->pSegmentList = (PSGL) pcmd->request_buffer; ! 619: } ! 620: else if( pcmd->request_buffer ) ! 621: { ! 622: pSRB->SGcount = 1; ! 623: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; ! 624: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; ! 625: pSRB->Segmentx.length = pcmd->request_bufflen; ! 626: } ! 627: else ! 628: pSRB->SGcount = 0; ! 629: ! 630: pSRB->AdaptStatus = 0; ! 631: pSRB->TargetStatus = 0; ! 632: pSRB->MsgCnt = 0; ! 633: if( pDCB->DevType != TYPE_TAPE ) ! 634: pSRB->RetryCnt = 1; ! 635: else ! 636: pSRB->RetryCnt = 0; ! 637: pSRB->SRBStatus = 0; ! 638: pSRB->SRBFlag = 0; ! 639: pSRB->ScratchABuf = 0; ! 640: pSRB->SRBState = 0; ! 641: SendSRB( pcmd, pACB, pSRB ); ! 642: ! 643: restore_flags(flags); ! 644: return; ! 645: } ! 646: ! 647: ! 648: /*********************************************************************** ! 649: * Function: ! 650: * DC390W_bios_param ! 651: * ! 652: * Description: ! 653: * Return the disk geometry for the given SCSI device. ! 654: ***********************************************************************/ ! 655: #ifdef VERSION_ELF_1_2_13 ! 656: int DC390W_bios_param(Disk *disk, int devno, int geom[]) ! 657: #else ! 658: int DC390W_bios_param(Disk *disk, kdev_t devno, int geom[]) ! 659: #endif ! 660: { ! 661: int heads, sectors, cylinders; ! 662: PACB pACB; ! 663: ! 664: pACB = (PACB) disk->device->host->hostdata; ! 665: heads = 64; ! 666: sectors = 32; ! 667: cylinders = disk->capacity / (heads * sectors); ! 668: ! 669: if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) ! 670: { ! 671: heads = 255; ! 672: sectors = 63; ! 673: cylinders = disk->capacity / (heads * sectors); ! 674: } ! 675: ! 676: geom[0] = heads; ! 677: geom[1] = sectors; ! 678: geom[2] = cylinders; ! 679: ! 680: return (0); ! 681: } ! 682: ! 683: ! 684: /*********************************************************************** ! 685: * Function : int DC390W_abort (Scsi_Cmnd *cmd) ! 686: * ! 687: * Purpose : Abort an errant SCSI command ! 688: * ! 689: * Inputs : cmd - command to abort ! 690: * ! 691: * Returns : 0 on success, -1 on failure. ! 692: ***********************************************************************/ ! 693: ! 694: int ! 695: DC390W_abort (Scsi_Cmnd *cmd) ! 696: { ! 697: ULONG flags; ! 698: PACB pACB; ! 699: PDCB pDCB, pdcb; ! 700: PSRB pSRB, psrb; ! 701: USHORT count, i; ! 702: PSCSICMD pcmd, pcmd1; ! 703: int status; ! 704: ! 705: ! 706: #ifdef DC390W_DEBUG0 ! 707: printk("DC390W : Abort Cmd."); ! 708: #endif ! 709: ! 710: save_flags(flags); ! 711: cli(); ! 712: ! 713: pACB = (PACB) cmd->host->hostdata; ! 714: pDCB = pACB->pLinkDCB; ! 715: pdcb = pDCB; ! 716: while( (pDCB->UnitSCSIID != cmd->target) || ! 717: (pDCB->UnitSCSILUN != cmd->lun) ) ! 718: { ! 719: pDCB = pDCB->pNextDCB; ! 720: if( pDCB == pdcb ) ! 721: goto NOT_RUN; ! 722: } ! 723: ! 724: if( pDCB->QIORBCnt ) ! 725: { ! 726: pcmd = pDCB->pQIORBhead; ! 727: if( pcmd == cmd ) ! 728: { ! 729: pDCB->pQIORBhead = pcmd->next; ! 730: pcmd->next = NULL; ! 731: pDCB->QIORBCnt--; ! 732: status = SCSI_ABORT_SUCCESS; ! 733: goto ABO_X; ! 734: } ! 735: for( count = pDCB->QIORBCnt, i=0; i<count-1; i++) ! 736: { ! 737: if( pcmd->next == cmd ) ! 738: { ! 739: pcmd1 = pcmd->next; ! 740: pcmd->next = pcmd1->next; ! 741: pcmd1->next = NULL; ! 742: pDCB->QIORBCnt--; ! 743: status = SCSI_ABORT_SUCCESS; ! 744: goto ABO_X; ! 745: } ! 746: else ! 747: { ! 748: pcmd = pcmd->next; ! 749: } ! 750: } ! 751: } ! 752: ! 753: pSRB = pDCB->pWaitingSRB; ! 754: if( !pSRB ) ! 755: goto ON_GOING; ! 756: if( pSRB->pcmd == cmd ) ! 757: { ! 758: pDCB->pWaitingSRB = pSRB->pNextSRB; ! 759: goto IN_WAIT; ! 760: } ! 761: else ! 762: { ! 763: psrb = pSRB; ! 764: if( !(psrb->pNextSRB) ) ! 765: goto ON_GOING; ! 766: while( psrb->pNextSRB->pcmd != cmd ) ! 767: { ! 768: psrb = psrb->pNextSRB; ! 769: if( !(psrb->pNextSRB) ) ! 770: goto ON_GOING; ! 771: } ! 772: pSRB = psrb->pNextSRB; ! 773: psrb->pNextSRB = pSRB->pNextSRB; ! 774: if( pSRB == pDCB->pWaitLast ) ! 775: pDCB->pWaitLast = psrb; ! 776: IN_WAIT: ! 777: pSRB->pNextSRB = pACB->pFreeSRB; ! 778: pACB->pFreeSRB = pSRB; ! 779: cmd->next = NULL; ! 780: status = SCSI_ABORT_SUCCESS; ! 781: goto ABO_X; ! 782: } ! 783: ! 784: ON_GOING: ! 785: pSRB = pDCB->pGoingSRB; ! 786: for( count = pDCB->GoingSRBCnt, i=0; i<count; i++) ! 787: { ! 788: if( pSRB->pcmd != cmd ) ! 789: pSRB = pSRB->pNextSRB; ! 790: else ! 791: { ! 792: if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) ! 793: { ! 794: status = SCSI_ABORT_BUSY; ! 795: goto ABO_X; ! 796: } ! 797: else ! 798: { ! 799: status = SCSI_ABORT_SNOOZE; ! 800: goto ABO_X; ! 801: } ! 802: } ! 803: } ! 804: ! 805: NOT_RUN: ! 806: status = SCSI_ABORT_NOT_RUNNING; ! 807: ! 808: ABO_X: ! 809: cmd->result = DID_ABORT << 16; ! 810: cmd->scsi_done(cmd); ! 811: restore_flags(flags); ! 812: return( status ); ! 813: } ! 814: ! 815: ! 816: static void ! 817: ResetDevParam( PACB pACB ) ! 818: { ! 819: PDCB pDCB, pdcb; ! 820: ! 821: pDCB = pACB->pLinkDCB; ! 822: if( pDCB == NULL ) ! 823: return; ! 824: pdcb = pDCB; ! 825: do ! 826: { ! 827: if( pACB->AdaptType == DC390W ) ! 828: pdcb->DCBscntl3 = SYNC_CLK_F2+ASYNC_CLK_F2; ! 829: else ! 830: pdcb->DCBscntl3 = SYNC_CLK_F4+ASYNC_CLK_F4; ! 831: pdcb->DCBsxfer = 0; ! 832: pdcb = pdcb->pNextDCB; ! 833: } ! 834: while( pdcb != pDCB ); ! 835: } ! 836: ! 837: ! 838: static void ! 839: RecoverSRB( PACB pACB ) ! 840: { ! 841: PDCB pDCB, pdcb; ! 842: PSRB psrb, psrb2; ! 843: USHORT cnt, i; ! 844: ! 845: pDCB = pACB->pLinkDCB; ! 846: if( pDCB == NULL ) ! 847: return; ! 848: pdcb = pDCB; ! 849: do ! 850: { ! 851: cnt = pdcb->GoingSRBCnt; ! 852: psrb = pdcb->pGoingSRB; ! 853: for (i=0; i<cnt; i++) ! 854: { ! 855: PrepareSG( pACB, pdcb, psrb ); ! 856: psrb2 = psrb; ! 857: psrb = psrb->pNextSRB; ! 858: /* RewaitSRB( pDCB, psrb ); */ ! 859: if( pdcb->pWaitingSRB ) ! 860: { ! 861: psrb2->pNextSRB = pdcb->pWaitingSRB; ! 862: pdcb->pWaitingSRB = psrb2; ! 863: } ! 864: else ! 865: { ! 866: pdcb->pWaitingSRB = psrb2; ! 867: pdcb->pWaitLast = psrb2; ! 868: psrb2->pNextSRB = NULL; ! 869: } ! 870: } ! 871: pdcb->GoingSRBCnt = 0; ! 872: pdcb->pGoingSRB = NULL; ! 873: pdcb->TagMask = 0; ! 874: pdcb = pdcb->pNextDCB; ! 875: } ! 876: while( pdcb != pDCB ); ! 877: } ! 878: ! 879: ! 880: /*********************************************************************** ! 881: * Function : int DC390W_reset (Scsi_Cmnd *cmd, ...) ! 882: * ! 883: * Purpose : perform a hard reset on the SCSI bus( and NCR chip). ! 884: * ! 885: * Inputs : cmd - command which caused the SCSI RESET ! 886: * ! 887: * Returns : 0 on success. ! 888: ***********************************************************************/ ! 889: ! 890: #ifdef VERSION_2_0_0 ! 891: int DC390W_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) ! 892: #else ! 893: int DC390W_reset (Scsi_Cmnd *cmd) ! 894: #endif ! 895: { ! 896: USHORT ioport; ! 897: unsigned long flags; ! 898: PACB pACB; ! 899: ULONG wlval; ! 900: UCHAR bval; ! 901: USHORT wval; ! 902: USHORT i; ! 903: ! 904: ! 905: #ifdef DC390W_DEBUG0 ! 906: printk("DC390W : Reset Cmd0,"); ! 907: #endif ! 908: ! 909: pACB = (PACB ) cmd->host->hostdata; ! 910: ioport = pACB->IOPortBase; ! 911: save_flags(flags); ! 912: cli(); ! 913: bval = inb(ioport+DCNTL); ! 914: bval |= IRQ_DISABLE; ! 915: outb(bval,ioport+DCNTL); /* disable interrupt */ ! 916: DC390W_ResetSCSIBus( pACB ); ! 917: for( i=0; i<500; i++ ) ! 918: udelay(1000); ! 919: for(;;) ! 920: { ! 921: bval = inb(ioport+ISTAT); ! 922: if( bval & SCSI_INT_PENDING ) ! 923: { ! 924: wval = inw( ioport+SIST0 ); ! 925: if( wval & (SCSI_RESET+SCSI_GERROR) ) ! 926: break; ! 927: } ! 928: if(bval & DMA_INT_PENDING) ! 929: { ! 930: bval = inb(ioport+DSTAT); ! 931: if(bval & ABORT_) ! 932: { ! 933: wval = inw( ioport+SIST0 ); ! 934: break; ! 935: } ! 936: } ! 937: } ! 938: bval = inb(ioport+DCNTL); ! 939: bval &= ~IRQ_DISABLE; ! 940: outb(bval,ioport+DCNTL); /* re-enable interrupt */ ! 941: ! 942: ioport = pACB->IOPortBase; ! 943: bval = inb(ioport+STEST3); ! 944: bval |= CLR_SCSI_FIFO; ! 945: outb(bval,ioport+STEST3); ! 946: bval = CLR_DMA_FIFO; ! 947: outb(bval,ioport+CTEST3); ! 948: ResetDevParam( pACB ); ! 949: DoingSRB_Done( pACB ); ! 950: pACB->pActiveDCB = NULL; ! 951: wlval = pACB->jmp_reselect; ! 952: outl(wlval,(ioport+DSP)); ! 953: ! 954: pACB->ACBFlag = 0; ! 955: DoWaitingSRB( pACB ); ! 956: restore_flags(flags); ! 957: return( SCSI_RESET_SUCCESS ); ! 958: } ! 959: ! 960: ! 961: #include "scsiio.c" ! 962: ! 963: ! 964: /*********************************************************************** ! 965: * Function : static void DC390W_initDCB ! 966: * ! 967: * Purpose : initialize the internal structures for a given DCB ! 968: * ! 969: * Inputs : cmd - pointer to this scsi cmd request block structure ! 970: * ! 971: ***********************************************************************/ ! 972: void DC390W_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) ! 973: { ! 974: PEEprom prom; ! 975: UCHAR bval; ! 976: USHORT index; ! 977: ! 978: if( pACB->DeviceCnt == 0 ) ! 979: { ! 980: pACB->pLinkDCB = pDCB; ! 981: pACB->pDCBRunRobin = pDCB; ! 982: pDCB->pNextDCB = pDCB; ! 983: pPrevDCB = pDCB; ! 984: } ! 985: else ! 986: pPrevDCB->pNextDCB = pDCB; ! 987: ! 988: pDCB->pDCBACB = pACB; ! 989: pDCB->QIORBCnt = 0; ! 990: pDCB->DCBselect = 0; ! 991: pDCB->DCBsxfer = 0; ! 992: pDCB->DCBsdid = cmd->target; ! 993: pDCB->UnitSCSIID = cmd->target; ! 994: pDCB->UnitSCSILUN = cmd->lun; ! 995: pDCB->pWaitingSRB = NULL; ! 996: pDCB->GoingSRBCnt = 0; ! 997: pDCB->TagMask = 0; ! 998: ! 999: pDCB->MaxCommand = 1; ! 1000: pDCB->AdaptIndex = pACB->AdapterIndex; ! 1001: index = pACB->AdapterIndex; ! 1002: ! 1003: prom = (PEEprom) &eepromBuf[index][cmd->target << 2]; ! 1004: pDCB->DevMode = prom->EE_MODE1; ! 1005: pDCB->NegoPeriod = clock_period[prom->EE_SPEED]; ! 1006: ! 1007: if( pACB->AdaptType == DC390W ) ! 1008: pDCB->DCBscntl3 = SYNC_CLK_F2+ASYNC_CLK_F2; ! 1009: else ! 1010: pDCB->DCBscntl3 = SYNC_CLK_F4+ASYNC_CLK_F4; ! 1011: ! 1012: if( pDCB->DevMode & PARITY_CHK_ ) ! 1013: pDCB->DCBscntl0 = EN_PARITY_CHK+SATN_IF_PARITY_ERR+FULL_ARBITRATION; ! 1014: else ! 1015: pDCB->DCBscntl0 = FULL_ARBITRATION; ! 1016: ! 1017: pDCB->AdpMode = eepromBuf[index][EE_MODE2]; ! 1018: ! 1019: if( pDCB->DevMode & EN_DISCONNECT_ ) ! 1020: bval = 0xC0; ! 1021: else ! 1022: bval = 0x80; ! 1023: bval |= cmd->lun; ! 1024: pDCB->IdentifyMsg = bval; ! 1025: ! 1026: if( pDCB->DevMode & SYNC_NEGO_ ) ! 1027: { ! 1028: pDCB->SyncMode = SYNC_ENABLE; ! 1029: pDCB->SyncOffset = SYNC_NEGO_OFFSET; ! 1030: } ! 1031: ! 1032: if( pDCB->DevMode & WIDE_NEGO_ ) ! 1033: { ! 1034: if( cmd->lun ) ! 1035: { ! 1036: if( !(CurrDCBscntl3 & EN_WIDE_SCSI) ) ! 1037: pDCB->DevMode &= ~WIDE_NEGO_; ! 1038: } ! 1039: else ! 1040: CurrDCBscntl3 = 0; ! 1041: } ! 1042: pDCB->DCBFlag = 0; ! 1043: } ! 1044: ! 1045: ! 1046: /*********************************************************************** ! 1047: * Function : static void DC390W_initSRB ! 1048: * ! 1049: * Purpose : initialize the internal structures for a given SRB ! 1050: * ! 1051: * Inputs : psrb - pointer to this scsi request block structure ! 1052: * ! 1053: ***********************************************************************/ ! 1054: void DC390W_initSRB( PSRB psrb ) ! 1055: { ! 1056: #ifndef VERSION_ELF_1_2_13 ! 1057: psrb->PhysSRB = virt_to_phys( psrb ); ! 1058: psrb->__command[1] = virt_to_phys( psrb->CmdBlock ); ! 1059: psrb->__msgout0[0] = 1; ! 1060: psrb->__msgout0[1] = virt_to_phys( psrb->MsgOutBuf ); ! 1061: psrb->SegmentPad[0] = 16; ! 1062: psrb->SegmentPad[1] = virt_to_phys( pad_buffer ); ! 1063: #else ! 1064: psrb->PhysSRB = (ULONG) psrb; ! 1065: psrb->__command[1] = (ULONG) psrb->CmdBlock; ! 1066: psrb->__msgout0[0] = 1; ! 1067: psrb->__msgout0[1] = (ULONG) psrb->MsgOutBuf; ! 1068: psrb->SegmentPad[0] = 16; ! 1069: psrb->SegmentPad[1] = (ULONG) pad_buffer; ! 1070: #endif ! 1071: } ! 1072: ! 1073: ! 1074: void DC390W_linkSRB( PACB pACB ) ! 1075: { ! 1076: USHORT count, i; ! 1077: PSRB psrb; ! 1078: ! 1079: count = pACB->SRBCount; ! 1080: ! 1081: for( i=0; i< count; i++) ! 1082: { ! 1083: if( i != count - 1) ! 1084: pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; ! 1085: else ! 1086: pACB->SRB_array[i].pNextSRB = NULL; ! 1087: psrb = (PSRB) &pACB->SRB_array[i]; ! 1088: DC390W_initSRB( psrb ); ! 1089: } ! 1090: } ! 1091: ! 1092: ! 1093: /*********************************************************************** ! 1094: * Function : static void DC390W_initACB ! 1095: * ! 1096: * Purpose : initialize the internal structures for a given SCSI host ! 1097: * ! 1098: * Inputs : psh - pointer to this host adapter's structure ! 1099: * ! 1100: ***********************************************************************/ ! 1101: void DC390W_initACB( PSH psh, USHORT chipType, ULONG io_port, UCHAR Irq, USHORT index ) ! 1102: { ! 1103: PACB pACB; ! 1104: USHORT i; ! 1105: UCHAR adaptType, bval; ! 1106: ! 1107: ! 1108: psh->can_queue = MAX_CMD_QUEUE; ! 1109: psh->cmd_per_lun = MAX_CMD_PER_LUN; ! 1110: psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID]; ! 1111: psh->io_port = io_port; ! 1112: psh->n_io_port = 0x80; ! 1113: psh->irq = Irq; ! 1114: ! 1115: if( chipType == PCI_DEVICE_ID_NCR53C825A ) ! 1116: adaptType = DC390W; ! 1117: else ! 1118: { ! 1119: outb( 2, io_port+GPREG ); ! 1120: bval = inb( io_port+GPREG ); ! 1121: if( bval & 8 ) ! 1122: adaptType = DC390U; ! 1123: else ! 1124: adaptType = DC390F; ! 1125: } ! 1126: ! 1127: pACB = (PACB) psh->hostdata; ! 1128: ! 1129: #ifndef VERSION_ELF_1_2_13 ! 1130: if( adaptType == DC390U ) ! 1131: { ! 1132: psh->max_id = 8; ! 1133: pACB->max_id = 7; ! 1134: } ! 1135: else ! 1136: { ! 1137: psh->max_id = 16; ! 1138: pACB->max_id = 15; ! 1139: } ! 1140: ! 1141: #ifdef CONFIG_SCSI_MULTI_LUN ! 1142: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1143: psh->max_lun = 8; ! 1144: else ! 1145: #endif ! 1146: psh->max_lun = 1; ! 1147: ! 1148: #else ! 1149: pACB->max_id = 7; ! 1150: #endif ! 1151: if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) ! 1152: pACB->max_id--; ! 1153: ! 1154: #ifdef CONFIG_SCSI_MULTI_LUN ! 1155: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1156: pACB->max_lun = 7; ! 1157: else ! 1158: #endif ! 1159: pACB->max_lun = 0; ! 1160: ! 1161: pACB->pScsiHost = psh; ! 1162: pACB->IOPortBase = (USHORT) io_port; ! 1163: pACB->pLinkDCB = NULL; ! 1164: pACB->pDCBRunRobin = NULL; ! 1165: pACB->pActiveDCB = NULL; ! 1166: pACB->pFreeSRB = pACB->SRB_array; ! 1167: pACB->SRBCount = MAX_SRB_CNT; ! 1168: pACB->AdapterIndex = index; ! 1169: pACB->status = 0; ! 1170: pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; ! 1171: pACB->AdaptSCSILUN = 0; ! 1172: pACB->DeviceCnt = 0; ! 1173: pACB->IRQLevel = Irq; ! 1174: pACB->AdaptType = adaptType; ! 1175: pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2; ! 1176: pACB->ACBFlag = 0; ! 1177: pACB->scan_devices = 1; ! 1178: pACB->Gmode2 = eepromBuf[index][EE_MODE2]; ! 1179: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1180: pACB->LUNchk = 1; ! 1181: pACB->pDCB_free = &pACB->DCB_array[0]; ! 1182: DC390W_linkSRB( pACB ); ! 1183: for(i=0; i<MAX_SCSI_ID; i++) ! 1184: pACB->DCBmap[i] = 0; ! 1185: } ! 1186: ! 1187: ! 1188: /*********************************************************************** ! 1189: * Function : static int DC390W_initAdapter ! 1190: * ! 1191: * Purpose : initialize the SCSI chip ctrl registers ! 1192: * ! 1193: * Inputs : psh - pointer to this host adapter's structure ! 1194: * ! 1195: ***********************************************************************/ ! 1196: int DC390W_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) ! 1197: { ! 1198: USHORT ioport, wval; ! 1199: UCHAR bval; ! 1200: PACB pACB, pacb; ! 1201: USHORT used_irq = 0; ! 1202: ! 1203: pacb = pACB_start; ! 1204: if( pacb != NULL ) ! 1205: { ! 1206: for ( ; (pacb != (PACB) -1) ; ) ! 1207: { ! 1208: if( pacb->IRQLevel == Irq ) ! 1209: { ! 1210: used_irq = 1; ! 1211: break; ! 1212: } ! 1213: else ! 1214: pacb = pacb->pNextACB; ! 1215: } ! 1216: } ! 1217: ! 1218: if( !used_irq ) ! 1219: { ! 1220: #ifdef VERSION_ELF_1_2_13 ! 1221: if( request_irq(Irq, DC390W_Interrupt, SA_INTERRUPT, "tmscsiw")) ! 1222: #else ! 1223: if( request_irq(Irq, DC390W_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsiw", NULL)) ! 1224: #endif ! 1225: { ! 1226: printk("DC390W : register IRQ error!\n"); ! 1227: return( -1 ); ! 1228: } ! 1229: } ! 1230: request_region(io_port,psh->n_io_port,"tmscsiw"); ! 1231: ! 1232: ioport = (USHORT) io_port; ! 1233: outb(IRQ_DISABLE, ioport+DCNTL); ! 1234: outb(ABORT_OP, ioport+ISTAT); ! 1235: udelay(100000); ! 1236: outb(0, ioport+ISTAT); ! 1237: bval = inb(ioport+DSTAT); ! 1238: bval = inb(ioport+ISTAT); ! 1239: wval = inw(ioport+SIST0); ! 1240: ! 1241: pACB = (PACB) psh->hostdata; ! 1242: bval = pACB->AdaptSCSIID; ! 1243: bval |= ENABLE_RESEL; ! 1244: outb(bval,ioport+SCID); ! 1245: ! 1246: if(pACB->AdaptType == DC390W) ! 1247: bval = SYNC_CLK_F2+ASYNC_CLK_F2; ! 1248: else ! 1249: { /* @1.09 */ ! 1250: bval = inb(ioport+CTEST3); ! 1251: if( (bval & CHIP_REV_MASK) < 0x30 ) /* 53C875 Rev. F or later ? */ ! 1252: goto REVF; ! 1253: bval = inb(ioport+STEST1); ! 1254: if( (bval & 0x0C) == 0x0C ) /* double clock already enable ? */ ! 1255: goto REVF; ! 1256: outb(8,ioport+STEST1); /* enable clock doubler */ ! 1257: udelay(20); ! 1258: outb(HALT_SCSI_CLK,ioport+STEST3); /* halt clock */ ! 1259: outb(0x0C,ioport+STEST1); /* select double SCSI clock */ ! 1260: outb(0,ioport+STEST3); /* re-enable clock */ ! 1261: REVF: ! 1262: bval = SYNC_CLK_F4+ASYNC_CLK_F4; ! 1263: } ! 1264: outb(bval,ioport+SCNTL3); ! 1265: ! 1266: bval = SYNC_PERIOD_F4+ASYNCHRONOUS; /* set to async */ ! 1267: outb(bval,ioport+SXFER); ! 1268: ! 1269: bval = WRT_EN_INVALIDATE; /* Enable write and invalidate */ ! 1270: outb(bval,ioport+CTEST3); ! 1271: ! 1272: bval = EN_DMA_FIFO_536+BURST_LEN_MSB; /* select 536 bytes DMA FIFO, burst len bit2=1 */ ! 1273: outb(bval,ioport+CTEST5); ! 1274: ! 1275: bval = BURST_LEN8+EN_READ_LINE+EN_READ_MULTIPLE+BURST_OPCODE_FETCH+AUTO_START; /* set DMA parameter */ ! 1276: outb(bval,ioport+DMODE); ! 1277: ! 1278: bval = EN_ABORTED+EN_SCRIPT_INT+EN_ILLEGAL_INST; /* enable DMA interrupt */ ! 1279: outb(bval,ioport+DIEN); ! 1280: ! 1281: bval = EN_CACHE_LINE_SIZE+EN_PRE_FETCH+TOTEM_POLE_IRQ+COMPATIBLE_700; ! 1282: outb(bval,ioport+DCNTL); ! 1283: ! 1284: bval = EN_PHASE_MISMATCH+EN_SCSI_GERROR+EN_UNEXPECT_DISC+EN_SCSI_RESET+EN_PARITY_ERROR; ! 1285: outb(bval,ioport+SIEN0); ! 1286: ! 1287: bval = EN_SEL_TIMEOUT+EN_GENERAL_TIMEOUT; ! 1288: outb(bval,ioport+SIEN1); ! 1289: ! 1290: bval = SEL_TO_204ms; /* 250ms selection timeout */ ! 1291: outb(bval,ioport+STIME0); ! 1292: ! 1293: wval = 1 << (eepromBuf[index][EE_ADAPT_SCSI_ID]); /* @1.11 */ ! 1294: outw(wval,ioport+RESPID0); ! 1295: ! 1296: bval = DIS_SINGLE_INIT; ! 1297: if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) ! 1298: bval |= ACTIVE_NEGATION_; ! 1299: outb(bval,ioport+STEST3); ! 1300: ! 1301: return(0); ! 1302: } ! 1303: ! 1304: ! 1305: /*********************************************************************** ! 1306: * Function : static int DC390W_init (struct Scsi_Host *host) ! 1307: * ! 1308: * Purpose : initialize the internal structures for a given SCSI host ! 1309: * ! 1310: * Inputs : host - pointer to this host adapter's structure/ ! 1311: * ! 1312: * Preconditions : when this function is called, the chip_type ! 1313: * field of the pACB structure MUST have been set. ! 1314: ***********************************************************************/ ! 1315: ! 1316: static int ! 1317: DC390W_init (PSHT psht, USHORT chipType, ULONG io_port, UCHAR Irq, USHORT index) ! 1318: { ! 1319: PSH psh; ! 1320: PACB pACB; ! 1321: ! 1322: if( ! CheckEEpromCheckSum( &eepromBuf[index][0], (USHORT) io_port) ) ! 1323: { ! 1324: psh = scsi_register( psht, sizeof(DC390W_ACB) ); ! 1325: if( !psh ) ! 1326: return( -1 ); ! 1327: if( !pSH_start ) ! 1328: { ! 1329: pSH_start = psh; ! 1330: pSH_current = psh; ! 1331: } ! 1332: else ! 1333: { ! 1334: pSH_current->next = psh; ! 1335: pSH_current = psh; ! 1336: } ! 1337: ! 1338: #ifdef DC390W_DEBUG0 ! 1339: printk("DC390W : pSH = %8x,", (UINT) psh); ! 1340: #endif ! 1341: ! 1342: DC390W_initACB( psh, chipType, io_port, Irq, index ); ! 1343: if( !DC390W_initAdapter( psh, io_port, Irq, index ) ) ! 1344: { ! 1345: pACB = (PACB) psh->hostdata; ! 1346: if( !pACB_start ) ! 1347: { ! 1348: pACB_start = pACB; ! 1349: pACB_current = pACB; ! 1350: pACB->pNextACB = (PACB) -1; ! 1351: } ! 1352: else ! 1353: { ! 1354: pACB_current->pNextACB = pACB; ! 1355: pACB_current = pACB; ! 1356: pACB->pNextACB = (PACB) -1; ! 1357: } ! 1358: ! 1359: #ifdef DC390W_DEBUG0 ! 1360: printk("DC390W : pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", ! 1361: (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); ! 1362: printk("DC390W : ACB size= %4x, DCB size= %4x, SRB size= %4x\n", ! 1363: sizeof(DC390W_ACB), sizeof(DC390W_DCB), sizeof(DC390W_SRB) ); ! 1364: #endif ! 1365: ! 1366: } ! 1367: else ! 1368: { ! 1369: pSH_start = NULL; ! 1370: scsi_unregister( psh ); ! 1371: return( -1 ); ! 1372: } ! 1373: DC390W_download_script( psh ); ! 1374: return( 0 ); ! 1375: } ! 1376: else ! 1377: { ! 1378: printk("DC390W_init: EEPROM reading error!\n"); ! 1379: return( -1 ); ! 1380: } ! 1381: } ! 1382: ! 1383: ! 1384: void MyDelay( void ) ! 1385: { ! 1386: UCHAR i,j; ! 1387: ! 1388: j = inb(0x61) & 0x10; ! 1389: ! 1390: for(;;) ! 1391: { ! 1392: i = inb(0x61) & 0x10; ! 1393: if( j ^ i) ! 1394: break; ! 1395: } ! 1396: } ! 1397: ! 1398: ! 1399: void EnDisableCE( UCHAR Flag, USHORT scsiIOPort ) ! 1400: { ! 1401: ! 1402: UCHAR bval; ! 1403: USHORT port; ! 1404: ! 1405: port = (scsiIOPort & 0xff00) + GPREG; ! 1406: if(Flag == ENABLE_CE) ! 1407: bval = 0x10; ! 1408: else ! 1409: bval = 0x00; ! 1410: outb(bval,port); ! 1411: udelay(8); /* Delay();*/ ! 1412: } ! 1413: ! 1414: ! 1415: void EEpromOutDI( USHORT Carry, USHORT scsiIOPort ) ! 1416: { ! 1417: UCHAR bval; ! 1418: USHORT port; ! 1419: ! 1420: port = (scsiIOPort & 0xff00) + GPREG; ! 1421: bval = 0x10; ! 1422: if(Carry) ! 1423: bval |= 0x02; /* SK=0, DI */ ! 1424: outb(bval,port); ! 1425: udelay(8); /* Delay();*/ ! 1426: bval |= 0x04; /* SK=1, DI */ ! 1427: outb(bval,port); ! 1428: udelay(8); /* Delay();*/ ! 1429: bval &= 0xfb; /* SK=0, DI */ ! 1430: outb(bval,port); ! 1431: udelay(8); /* Delay();*/ ! 1432: } ! 1433: ! 1434: ! 1435: void EEpromPrepare( UCHAR EEpromCmd, USHORT scsiIOPort ) ! 1436: { ! 1437: UCHAR i,j; ! 1438: USHORT carryFlag; ! 1439: ! 1440: carryFlag = 1; ! 1441: j = 0x80; ! 1442: for(i=0;i<9;i++) ! 1443: { ! 1444: EEpromOutDI(carryFlag,scsiIOPort); ! 1445: carryFlag = (EEpromCmd & j) ? 1 : 0; ! 1446: j >>= 1; ! 1447: } ! 1448: } ! 1449: ! 1450: ! 1451: UCHAR EEpromInDo(USHORT scsiIOPort) ! 1452: { ! 1453: UCHAR bval; ! 1454: USHORT port; ! 1455: ! 1456: port = (scsiIOPort & 0xff00) + GPREG; ! 1457: bval = 0x14; /* SK=1 */ ! 1458: outb(bval,port); ! 1459: udelay(8); /* Delay();*/ ! 1460: bval = 0x10; /* SK=0 */ ! 1461: outb(bval,port); ! 1462: udelay(8); /* Delay();*/ ! 1463: bval = inb(port); ! 1464: if(bval & 0x01) ! 1465: return( 1 ); ! 1466: else ! 1467: return( 0 ); ! 1468: } ! 1469: ! 1470: ! 1471: USHORT EEpromGetData(USHORT scsiIOPort) ! 1472: { ! 1473: UCHAR i; ! 1474: UCHAR carryFlag; ! 1475: USHORT wval; ! 1476: ! 1477: wval = 0; ! 1478: for(i=0;i<16;i++) ! 1479: { ! 1480: wval <<= 1; ! 1481: carryFlag = EEpromInDo(scsiIOPort); ! 1482: wval |= carryFlag; ! 1483: } ! 1484: return( wval ); ! 1485: } ! 1486: ! 1487: ! 1488: void ReadEEprom( PUCHAR EEpromBuf, USHORT scsiIOPort ) ! 1489: { ! 1490: UCHAR cmd; ! 1491: ! 1492: cmd = EEPROM_READ; ! 1493: loop_rd: ! 1494: EnDisableCE(ENABLE_CE, scsiIOPort); ! 1495: EEpromPrepare(cmd, scsiIOPort); ! 1496: *((PUSHORT)EEpromBuf) = EEpromGetData(scsiIOPort); ! 1497: EEpromBuf++; ! 1498: EEpromBuf++; ! 1499: cmd++; ! 1500: EnDisableCE(DISABLE_CE, scsiIOPort); ! 1501: if(cmd & 0x3f) ! 1502: goto loop_rd; ! 1503: } ! 1504: ! 1505: ! 1506: USHORT CheckEEpromCheckSum( PUCHAR EEpromBuf, USHORT scsiIOPort) ! 1507: { ! 1508: USHORT wval,port, *ptr; ! 1509: UCHAR i,bval; ! 1510: ! 1511: port = (scsiIOPort & 0xff00) + GPCNTL; ! 1512: bval = 0x09; /* configure IO Pin */ ! 1513: outb(bval,port); ! 1514: ReadEEprom(EEpromBuf,scsiIOPort); /* read eeprom data */ ! 1515: wval = 0; ! 1516: ptr = (PUSHORT) EEpromBuf; ! 1517: for(i=0; i<128 ;i+=2, ptr++) ! 1518: wval += *ptr; ! 1519: return( (wval == 0x1234) ? 0 : -1); ! 1520: } ! 1521: ! 1522: ! 1523: ! 1524: static void ! 1525: DC390W_download_script (struct Scsi_Host *host) ! 1526: { ! 1527: ULONG wlval, wlval1, length, alignm; ! 1528: USHORT j, k, m; ! 1529: USHORT ioport; ! 1530: UCHAR bval; ! 1531: PACB pACB; ! 1532: PSRB pSRB; ! 1533: void *pSrc, *pSrc1; ! 1534: ULONG *pStart; ! 1535: ULONG Ent_reselected; ! 1536: ULONG Ent_reselecttag; ! 1537: ULONG Ent_select0; ! 1538: ULONG Ent_select1; ! 1539: ULONG Ent_check_phase; ! 1540: ULONG Ent_status1_phase; ! 1541: ULONG Ent_command_phase; ! 1542: ULONG Ent_jump_table0; ! 1543: ULONG Ent_din_phaseB; ! 1544: ULONG Ent_dout_phaseB; ! 1545: ULONG Ent_din_pad_0; ! 1546: ULONG Ent_dout_pad_0; ! 1547: ULONG Ent_jump_tablew; ! 1548: ULONG Ent_din_pad_1; ! 1549: ULONG Ent_dout_pad_1; ! 1550: ULONG Ent_mout_phase; ! 1551: ULONG Ent_status_phase; ! 1552: ULONG Ent_min_phase; ! 1553: ULONG Ent_jump_msgok; ! 1554: ULONG Ent_msg__1; ! 1555: ULONG Ent_msg___3; ! 1556: ULONG Ent_msg___2; ! 1557: ULONG Ent_set_atn; ! 1558: ULONG Ent_msg__a; ! 1559: ULONG Ent_msg__23; ! 1560: ULONG Ent_msg__3; ! 1561: ULONG Ent_msg__4; ! 1562: ULONG Ent_clr_atn; ! 1563: ULONG Ent_din_phaseW; ! 1564: ULONG Ent_dout_phaseW; ! 1565: ULONG Ent_din_pad_addrB; ! 1566: ULONG Ent_dout_pad_addrB; ! 1567: ULONG Ent_din_pad_addrW; ! 1568: ULONG Ent_dout_pad_addrW; ! 1569: ! 1570: ! 1571: pACB = (PACB) host->hostdata; ! 1572: ioport = pACB->IOPortBase; ! 1573: bval = SCRATCHAB_AS_BASE; /* set scratchB contains 4K RAM base address */ ! 1574: outb(bval,ioport+CTEST2); ! 1575: ! 1576: wlval = inl((ioport+SCRATCHB)); /* get starting address of 4K RAM */ ! 1577: /* wlval += 0x800; */ /* point to Upper 2K RAM */ ! 1578: DesPhysAddr[0] = wlval; /* destination address */ ! 1579: ! 1580: #ifdef DC390W_DEBUG0 ! 1581: printk("DesAddr=%8x,",(UINT) wlval); ! 1582: #endif ! 1583: bval = 0; /* set Scratch_A and Scratch_B to normal mode */ ! 1584: outb(bval,ioport+CTEST2); ! 1585: ! 1586: /*------------------------------------------------------------------- ! 1587: * patch the label in jump instruction: using offset relative ! 1588: * to start_script ! 1589: *------------------------------------------------------------------*/ ! 1590: ! 1591: Ent_reselected = (ULONG) reselected - (ULONG) start_script; ! 1592: Ent_reselecttag = (ULONG) reselecttag - (ULONG) start_script; ! 1593: Ent_select0 = (ULONG) select0 - (ULONG) start_script; ! 1594: Ent_select1 = (ULONG) select1 - (ULONG) start_script; ! 1595: Ent_check_phase = (ULONG) check_phase - (ULONG) start_script; ! 1596: Ent_status1_phase = (ULONG) status1_phase - (ULONG) start_script; ! 1597: Ent_command_phase = (ULONG) command_phase - (ULONG) start_script; ! 1598: Ent_din_phaseB = (ULONG) din_phaseB - (ULONG) start_script; ! 1599: Ent_dout_phaseB = (ULONG) dout_phaseB - (ULONG) start_script; ! 1600: Ent_din_phaseW = (ULONG) din_phaseW - (ULONG) start_script; ! 1601: Ent_dout_phaseW = (ULONG) dout_phaseW - (ULONG) start_script; ! 1602: Ent_jump_table0 = (ULONG) jump_table0 - (ULONG) start_script; ! 1603: Ent_din_pad_0 = (ULONG) din_pad_0 - (ULONG) start_script; ! 1604: Ent_din_pad_addrB = (ULONG) din_pad_addrB - (ULONG) start_script; ! 1605: Ent_dout_pad_0 = (ULONG) dout_pad_0 - (ULONG) start_script; ! 1606: Ent_dout_pad_addrB = (ULONG) dout_pad_addrB - (ULONG) start_script; ! 1607: Ent_jump_tablew = (ULONG) jump_tablew - (ULONG) start_script; ! 1608: Ent_din_pad_1 = (ULONG) din_pad_1 - (ULONG) start_script; ! 1609: Ent_din_pad_addrW = (ULONG) din_pad_addrW - (ULONG) start_script; ! 1610: Ent_dout_pad_1 = (ULONG) dout_pad_1 - (ULONG) start_script; ! 1611: Ent_dout_pad_addrW = (ULONG) dout_pad_addrW - (ULONG) start_script; ! 1612: Ent_mout_phase = (ULONG) mout_phase - (ULONG) start_script; ! 1613: Ent_status_phase = (ULONG) status_phase - (ULONG) start_script; ! 1614: Ent_min_phase = (ULONG) min_phase - (ULONG) start_script; ! 1615: Ent_jump_msgok = (ULONG) jump_msgok - (ULONG) start_script; ! 1616: Ent_msg__1 = (ULONG) msg__1 - (ULONG) start_script; ! 1617: Ent_msg___3 = (ULONG) msg___3 - (ULONG) start_script; ! 1618: Ent_msg___2 = (ULONG) msg___2 - (ULONG) start_script; ! 1619: Ent_set_atn = (ULONG) set_atn - (ULONG) start_script; ! 1620: Ent_msg__a = (ULONG) msg__a - (ULONG) start_script; ! 1621: Ent_msg__23 = (ULONG) msg__23 - (ULONG) start_script; ! 1622: Ent_msg__3 = (ULONG) msg__3 - (ULONG) start_script; ! 1623: Ent_msg__4 = (ULONG) msg__4 - (ULONG) start_script; ! 1624: Ent_clr_atn = (ULONG) clr_atn - (ULONG) start_script; ! 1625: ! 1626: jmp_select0[0] = Ent_select0 + wlval; ! 1627: jmp_reselected[0] = Ent_reselected + wlval; ! 1628: jmp_check_phase[0] = Ent_check_phase + wlval; ! 1629: jmp_check_phase1[0] = Ent_check_phase + wlval; ! 1630: jmp_check_phase2[0] = Ent_check_phase + wlval; ! 1631: jmp_check_phase3[0] = Ent_check_phase + wlval; ! 1632: jmp_check_phase4[0] = Ent_check_phase + wlval; ! 1633: jmp_check_phase5[0] = Ent_check_phase + wlval; ! 1634: jmp_check_phase6[0] = Ent_check_phase + wlval; ! 1635: jmp_status1_phase[0] = Ent_status1_phase + wlval; ! 1636: jmp_status1_phase1[0] = Ent_status1_phase + wlval; ! 1637: jmp_status1_phase2[0] = Ent_status1_phase + wlval; ! 1638: jmp_status1_phase3[0] = Ent_status1_phase + wlval; ! 1639: jmp_command_phase[0] = Ent_command_phase + wlval; ! 1640: for(j=0,k=1,m=0; j< (MAX_SG_LIST_BUF+1); j++) ! 1641: { ! 1642: jmp_dio_phaseB[k] = Ent_din_phaseB + m + wlval; ! 1643: jmp_dio_phaseW[k] = Ent_din_phaseW + m + wlval; ! 1644: k += 2; ! 1645: jmp_dio_phaseB[k] = Ent_dout_phaseB + m + wlval; ! 1646: jmp_dio_phaseW[k] = Ent_dout_phaseW + m + wlval; ! 1647: k += 2; ! 1648: m += 8; ! 1649: } ! 1650: jmp_din_pad_0[0] = Ent_din_pad_0 + wlval; ! 1651: jmp_dout_pad_0[0] = Ent_dout_pad_0 + wlval; ! 1652: jmp_din_pad_addrB[0] = Ent_din_pad_addrB + wlval; ! 1653: jmp_dout_pad_addrB[0] = Ent_dout_pad_addrB + wlval; ! 1654: jmp_din_pad_addrW[0] = Ent_din_pad_addrW + wlval; ! 1655: jmp_dout_pad_addrW[0] = Ent_dout_pad_addrW + wlval; ! 1656: jmp_din_pad_1[0] = Ent_din_pad_1 + wlval; ! 1657: jmp_dout_pad_1[0] = Ent_dout_pad_1 + wlval; ! 1658: jmp_status_phase[0] = Ent_status_phase + wlval; ! 1659: jmp_min_phase[0] = Ent_min_phase + wlval; ! 1660: jmp_mout_phase[0] = Ent_mout_phase + wlval; ! 1661: jmp_jump_msgok[0] = Ent_jump_msgok + wlval; ! 1662: jmp_msg__1[0] = Ent_msg__1 + wlval; ! 1663: jmp_msg___3[0] = Ent_msg___3 + wlval; ! 1664: jmp_msg___2[0] = Ent_msg___2 + wlval; ! 1665: jmp_msg__a[0] = Ent_msg__a + wlval; ! 1666: jmp_msg__a1[0] = Ent_msg__a + wlval; ! 1667: jmp_msg__a2[0] = Ent_msg__a + wlval; ! 1668: jmp_msg__23[0] = Ent_msg__23 + wlval; ! 1669: jmp_msg__3[0] = Ent_msg__3 + wlval; ! 1670: jmp_msg__4[0] = Ent_msg__4 + wlval; ! 1671: ! 1672: /*-------------------------------------------------------------------- ! 1673: // patch the element in ACB struct: using Physical address ! 1674: //-------------------------------------------------------------------*/ ! 1675: ! 1676: #ifndef VERSION_ELF_1_2_13 ! 1677: wlval1 = virt_to_phys( pACB->msgin123 ); ! 1678: #else ! 1679: wlval1 = (ULONG) pACB->msgin123; ! 1680: #endif ! 1681: ACB_msgin123_1[0] = wlval1; ! 1682: ACB_msgin123_2[0] = wlval1; ! 1683: ACB_msgin123_3[0] = wlval1; ! 1684: ACB_msgin123_4[0] = wlval1; ! 1685: ACB_msgin123_5[0] = wlval1; ! 1686: ACB_msgin123_6[0] = wlval1; ! 1687: ACB_msgin123_7[0] = wlval1; ! 1688: ! 1689: #ifndef VERSION_ELF_1_2_13 ! 1690: ACB_status[0] = virt_to_phys( &pACB->status ); ! 1691: #else ! 1692: ACB_status[0] = (ULONG) &pACB->status; ! 1693: #endif ! 1694: /*-------------------------------------------------------------------- ! 1695: // patch the element in SRB struct: using offset in struct ! 1696: //-------------------------------------------------------------------*/ ! 1697: ! 1698: pSRB = (PSRB) pACB->SRB_array; ! 1699: select1[0] = (select1[0] & 0xffff0000) + ((ULONG) &pSRB->__select - (ULONG) &pSRB->CmdBlock); ! 1700: SRB_msgout0[0] = (ULONG) &pSRB->__msgout0 - (ULONG) &pSRB->CmdBlock; ! 1701: SRB_msgout01[0] = (ULONG) &pSRB->__msgout0 - (ULONG) &pSRB->CmdBlock; ! 1702: SRB_command[0] = (ULONG) &pSRB->__command - (ULONG) &pSRB->CmdBlock; ! 1703: SRB_SegmentPad[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; ! 1704: SRB_SegmentPad1[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; ! 1705: SRB_SegmentPad2[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; ! 1706: SRB_SegmentPad3[0] = (ULONG) &pSRB->SegmentPad - (ULONG) &pSRB->CmdBlock; ! 1707: wlval = (ULONG) &pSRB->Segment0 - (ULONG) &pSRB->CmdBlock; ! 1708: for(j=0,k=1; j<(MAX_SG_LIST_BUF+1); j++) ! 1709: { ! 1710: din_phaseB[k] = wlval; ! 1711: dout_phaseB[k] = wlval; ! 1712: din_phaseW[k] = wlval; ! 1713: dout_phaseW[k] = wlval; ! 1714: k += 2; ! 1715: wlval += 8; ! 1716: } ! 1717: ! 1718: ! 1719: bval = inb(ioport+DCNTL); ! 1720: bval |= IRQ_DISABLE; ! 1721: outb(bval,ioport+DCNTL); /* disable interrupt */ ! 1722: ! 1723: /* pSrc = scsi_init_malloc( 2048, GFP_ATOMIC); */ ! 1724: pSrc = scsi_init_malloc( 4096, GFP_ATOMIC); /* 1.11 */ ! 1725: #ifdef DC390W_DEBUG0 ! 1726: printk("SrcAlloc=%8x,",(UINT) pSrc); ! 1727: #endif ! 1728: alignm = 4 - (((ULONG) pSrc) & 3); ! 1729: pSrc1 = (void *)(((ULONG) pSrc) + alignm); ! 1730: length = (ULONG) end_script - (ULONG) start_script; ! 1731: memcpy( pSrc1, (void *) start_script, length); ! 1732: pStart = (ULONG *) ((ULONG) start_mov - (ULONG) start_script); ! 1733: pStart =(ULONG *) (((ULONG) pStart) + ((ULONG) pSrc1)); ! 1734: ! 1735: #ifdef DC390W_DEBUG0 ! 1736: printk("SrcAddr=%8x,\n",(UINT) pSrc1); ! 1737: #endif ! 1738: #ifndef VERSION_ELF_1_2_13 ! 1739: (ULONG *)pStart[1] = virt_to_phys( pSrc1 ); ! 1740: #else ! 1741: (ULONG *)pStart[1] = (ULONG) pSrc1; ! 1742: #endif ! 1743: ! 1744: /* wlval = virt_to_phys( start_script ); */ /* physical address of start_script */ ! 1745: /* SrcPhysAddr[0] = wlval; */ /* sources address */ ! 1746: ! 1747: /* start to download SCRIPT instruction to the RAM of NCR53c825A,875 */ ! 1748: ! 1749: /* wlval = virt_to_phys( start_mov ); */ ! 1750: ! 1751: #ifndef VERSION_ELF_1_2_13 ! 1752: wlval = virt_to_phys( pStart ); ! 1753: #else ! 1754: wlval = (ULONG) pStart; ! 1755: #endif ! 1756: ! 1757: outl(wlval,ioport+DSP); ! 1758: ! 1759: bval = inb(ioport+ISTAT); ! 1760: while(!(bval & DMA_INT_PENDING)) /* check load start_script is finished? */ ! 1761: bval = inb(ioport+ISTAT); ! 1762: ! 1763: bval = inb(ioport+DSTAT); /* clear interrupt */ ! 1764: ! 1765: bval = inb(ioport+DCNTL); ! 1766: bval &= ~IRQ_DISABLE; ! 1767: outb(bval,ioport+DCNTL); /* re-enable interrupt */ ! 1768: ! 1769: scsi_init_free((char *) pSrc, 4096); ! 1770: ! 1771: wlval = DesPhysAddr[0]; /* starting addr of RAM */ ! 1772: wlval -= (ULONG) start_script; ! 1773: ! 1774: pACB->jmp_reselect = wlval + (ULONG) start_script; ! 1775: pACB->jmp_select = wlval + (ULONG) select1; ! 1776: pACB->jmp_table8 = wlval + (ULONG) jump_table0; ! 1777: pACB->jmp_set_atn = wlval + (ULONG) set_atn; ! 1778: pACB->jmp_clear_ack = wlval + (ULONG) msg__a; ! 1779: pACB->jmp_next = wlval + (ULONG) check_phase; ! 1780: pACB->jmp_din8 = wlval + (ULONG) din_phaseB+8; ! 1781: pACB->jmp_dout8 = wlval + (ULONG) dout_phaseB+8; ! 1782: pACB->jmp_clear_atn = wlval + (ULONG) clr_atn; ! 1783: pACB->jmp_reselecttag = wlval + (ULONG) reselecttag; ! 1784: ! 1785: wlval = pACB->jmp_reselect; ! 1786: outl(wlval,(ioport+DSP)); ! 1787: return; ! 1788: } ! 1789: ! 1790: ! 1791: /*********************************************************************** ! 1792: * Function : int DC390W_detect(Scsi_Host_Template *psht) ! 1793: * ! 1794: * Purpose : detects and initializes NCR53c825A,875 SCSI chips ! 1795: * that were autoprobed, overridden on the LILO command line, ! 1796: * or specified at compile time. ! 1797: * ! 1798: * Inputs : psht - template for this SCSI adapter ! 1799: * ! 1800: * Returns : number of host adapters detected ! 1801: * ! 1802: ***********************************************************************/ ! 1803: ! 1804: int ! 1805: DC390W_detect(Scsi_Host_Template *psht) ! 1806: { ! 1807: UCHAR pci_bus, pci_device_fn, irq; ! 1808: #ifndef VERSION_ELF_1_2_13 ! 1809: UINT io_port, ram_base; ! 1810: #else ! 1811: ULONG io_port, ram_base; ! 1812: #endif ! 1813: USHORT i; ! 1814: int error = 0; ! 1815: USHORT adaptCnt = 0; /* Number of boards detected */ ! 1816: USHORT pci_index = 0; /* Device index to PCI BIOS calls */ ! 1817: USHORT pci_index2 = 0; /* Device index to PCI BIOS calls */ ! 1818: USHORT chipType = 0; ! 1819: ! 1820: ! 1821: #ifndef VERSION_ELF_1_2_13 ! 1822: psht->proc_dir = &proc_scsi_tmscsiw; ! 1823: #endif ! 1824: ! 1825: InitialTime = 1; ! 1826: pSHT_start = psht; ! 1827: jmp_table16 = (ULONG) jump_tablew - (ULONG) jump_table0; ! 1828: jmp_din16 = (ULONG) din_phaseW - (ULONG) din_phaseB; ! 1829: jmp_dout16 = (ULONG) dout_phaseW - (ULONG) dout_phaseB; ! 1830: pACB_start = NULL; ! 1831: ! 1832: if ( pcibios_present() ) ! 1833: { ! 1834: for (i = 0; i < MAX_ADAPTER_NUM; ++i) ! 1835: { ! 1836: if( !pcibios_find_device( PCI_VENDOR_ID_NCR, ! 1837: PCI_DEVICE_ID_NCR53C825A, ! 1838: pci_index, &pci_bus, &pci_device_fn) ) ! 1839: { ! 1840: chipType = PCI_DEVICE_ID_NCR53C825A; ! 1841: pci_index++; ! 1842: } ! 1843: else if( !pcibios_find_device( PCI_VENDOR_ID_NCR, ! 1844: PCI_DEVICE_ID_NCR53C875, ! 1845: pci_index2, &pci_bus, &pci_device_fn) ) ! 1846: { ! 1847: chipType = PCI_DEVICE_ID_NCR53C875; ! 1848: pci_index2++; ! 1849: } ! 1850: ! 1851: if( chipType ) ! 1852: { ! 1853: error = pcibios_read_config_dword(pci_bus, pci_device_fn, ! 1854: PCI_BASE_ADDRESS_0, &io_port); ! 1855: error |= pcibios_read_config_dword(pci_bus, pci_device_fn, ! 1856: PCI_BASE_ADDRESS_2, &ram_base); ! 1857: error |= pcibios_read_config_byte(pci_bus, pci_device_fn, ! 1858: PCI_INTERRUPT_LINE, &irq); ! 1859: if( error ) ! 1860: { ! 1861: printk("DC390W_detect: reading configuration registers error!\n"); ! 1862: InitialTime = 0; ! 1863: return( 0 ); ! 1864: } ! 1865: ! 1866: (USHORT) io_port = (USHORT) io_port & 0xFFFE; ! 1867: #ifdef DC390W_DEBUG0 ! 1868: printk("DC390W : IO_PORT=%4x,RAM_BASE=%8x,IRQ=%x,CHIPID=%x,\n", ! 1869: (UINT) io_port, (UINT) ram_base, irq, (UCHAR)chipType); ! 1870: #endif ! 1871: ! 1872: if( !DC390W_init(psht, chipType, io_port, irq, i) ) ! 1873: adaptCnt++; ! 1874: chipType = 0; ! 1875: } ! 1876: else ! 1877: break; ! 1878: } ! 1879: } ! 1880: InitialTime = 0; ! 1881: adapterCnt = adaptCnt; ! 1882: return( adaptCnt ); ! 1883: } ! 1884: ! 1885: #ifndef VERSION_ELF_1_2_13 ! 1886: ! 1887: /******************************************************************** ! 1888: * Function: tmscsiw_set_info() ! 1889: * ! 1890: * Purpose: Set adapter info (!) ! 1891: * ! 1892: * Not yet implemented ! 1893: * ! 1894: *******************************************************************/ ! 1895: ! 1896: int tmscsiw_set_info(char *buffer, int length, struct Scsi_Host *shpnt) ! 1897: { ! 1898: return(-ENOSYS); /* Currently this is a no-op */ ! 1899: } ! 1900: ! 1901: /******************************************************************** ! 1902: * Function: tmscsiw_proc_info(char* buffer, char **start, ! 1903: * off_t offset, int length, int hostno, int inout) ! 1904: * ! 1905: * Purpose: return SCSI Adapter/Device Info ! 1906: * ! 1907: * Input: buffer: Pointer to a buffer where to write info ! 1908: * start : ! 1909: * offset: ! 1910: * hostno: Host adapter index ! 1911: * inout : Read (=0) or set(!=0) info ! 1912: * ! 1913: * Output: buffer: contains info ! 1914: * length; length of info in buffer ! 1915: * ! 1916: * return value: length ! 1917: * ! 1918: ********************************************************************/ ! 1919: ! 1920: /* KG: proc_info taken from driver aha152x.c */ ! 1921: ! 1922: #undef SPRINTF ! 1923: #define SPRINTF(args...) pos += sprintf(pos, ## args) ! 1924: ! 1925: #define YESNO(YN)\ ! 1926: if (YN) SPRINTF(" Yes ");\ ! 1927: else SPRINTF(" No ") ! 1928: ! 1929: int tmscsiw_proc_info(char *buffer, char **start, ! 1930: off_t offset, int length, int hostno, int inout) ! 1931: { ! 1932: int dev, spd, spd1; ! 1933: char *pos = buffer; ! 1934: PSH shpnt; ! 1935: PACB acbpnt; ! 1936: PDCB dcbpnt; ! 1937: unsigned long flags; ! 1938: /* Scsi_Cmnd *ptr; */ ! 1939: ! 1940: acbpnt = pACB_start; ! 1941: ! 1942: while(acbpnt != (PACB)-1) ! 1943: { ! 1944: shpnt = acbpnt->pScsiHost; ! 1945: if (shpnt->host_no == hostno) break; ! 1946: acbpnt = acbpnt->pNextACB; ! 1947: } ! 1948: ! 1949: if (acbpnt == (PACB)-1) return(-ESRCH); ! 1950: if (!shpnt) return(-ESRCH); ! 1951: ! 1952: if(inout) /* Has data been written to the file ? */ ! 1953: return(tmscsiw_set_info(buffer, length, shpnt)); ! 1954: ! 1955: SPRINTF("Tekram DC390W/U/F (T) PCI SCSI Host Adadpter, "); ! 1956: SPRINTF("Driver Version 1.12, 1997/02/17\n"); ! 1957: ! 1958: save_flags(flags); ! 1959: cli(); ! 1960: ! 1961: SPRINTF("SCSI Host Nr %i, ", hostno); ! 1962: SPRINTF("DC390WUF Adapter Nr %i\n", acbpnt->AdapterIndex); ! 1963: SPRINTF("IOPortBase 0x%04x, ", acbpnt -> IOPortBase); ! 1964: SPRINTF("IRQLevel 0x%02x\n",acbpnt -> IRQLevel); ! 1965: ! 1966: SPRINTF("Adapter Type: "); ! 1967: switch(acbpnt->AdaptType) ! 1968: { ! 1969: case DC390W: SPRINTF("DC390W, Fast Wide SCSI \n"); break; ! 1970: case DC390U: SPRINTF("DC390U, Ultra SCSI\n"); break; ! 1971: case DC390F: SPRINTF("DC390F, Ultra Wide SCSI\n"); break; ! 1972: default: SPRINTF("Unknown !\n"); ! 1973: } ! 1974: ! 1975: SPRINTF("MaxID %i, MaxLUN %i, ", acbpnt->max_id, acbpnt->max_lun); ! 1976: SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); ! 1977: ! 1978: SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); ! 1979: ! 1980: SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); ! 1981: ! 1982: SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ Wide NegoPeriod SyncSpeed SyncOffs\n"); ! 1983: dcbpnt = acbpnt->pLinkDCB; ! 1984: ! 1985: for (dev = 0; dev < acbpnt->DeviceCnt; dev++) ! 1986: { ! 1987: SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); ! 1988: YESNO(dcbpnt->DevMode & PARITY_CHK_); ! 1989: YESNO(dcbpnt->DCBsxfer & OFFSET_MASK); ! 1990: YESNO(dcbpnt->DevMode & EN_DISCONNECT_); ! 1991: YESNO(dcbpnt->DevMode & SEND_START_); ! 1992: YESNO(dcbpnt->MaxCommand > 1); ! 1993: YESNO(dcbpnt->DCBscntl3 & EN_WIDE_SCSI); ! 1994: SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); ! 1995: if (dcbpnt->DCBsxfer & OFFSET_MASK) ! 1996: { ! 1997: spd = 1000/(dcbpnt->SyncPeriod <<2); ! 1998: spd1 = 1000%(dcbpnt->SyncPeriod <<2); ! 1999: spd1 = (spd1 * 10)/(dcbpnt->SyncPeriod <<2); ! 2000: SPRINTF(" %2i.%1i M %02i\n", spd, spd1, dcbpnt->DCBsxfer & OFFSET_MASK); ! 2001: } ! 2002: else SPRINTF("\n"); ! 2003: /* Add more info ...*/ ! 2004: dcbpnt = dcbpnt->pNextDCB; ! 2005: } ! 2006: ! 2007: restore_flags(flags); ! 2008: *start = buffer + offset; ! 2009: ! 2010: if (pos - buffer < offset) ! 2011: return 0; ! 2012: else if (pos - buffer - offset < length) ! 2013: return pos - buffer - offset; ! 2014: else ! 2015: return length; ! 2016: } ! 2017: #endif /* VERSION_ELF_1_2_13 */ ! 2018: ! 2019: #ifdef MODULE ! 2020: ! 2021: /*********************************************************************** ! 2022: * Function : static int DC390W_shutdown (struct Scsi_Host *host) ! 2023: * ! 2024: * Purpose : does a clean (we hope) shutdown of the NCR SCSI chip. ! 2025: * Use prior to dumping core, unloading the NCR driver, etc. ! 2026: * ! 2027: * Returns : 0 on success ! 2028: ***********************************************************************/ ! 2029: static int ! 2030: DC390W_shutdown (struct Scsi_Host *host) ! 2031: { ! 2032: USHORT ioport; ! 2033: unsigned long flags; ! 2034: PACB pACB = (PACB) host->hostdata; ! 2035: ! 2036: ioport = (unsigned int) pACB->IOPortBase; ! 2037: ! 2038: save_flags (flags); ! 2039: cli(); ! 2040: ! 2041: /* pACB->soft_reset(host); */ ! 2042: /* ! 2043: * For now, we take the simplest solution : reset the SCSI bus. Eventually, ! 2044: * - If a command is connected, kill it with an ABORT message ! 2045: * - If commands are disconnected, connect to each target/LUN and ! 2046: * do a ABORT, followed by a SOFT reset, followed by a hard ! 2047: * reset. ! 2048: */ ! 2049: ! 2050: #ifdef DC390W_DEBUG0 ! 2051: printk("DC390W: shutdown,"); ! 2052: #endif ! 2053: outb(ASSERT_RST, ioport+SCNTL1); ! 2054: udelay(25); /* Minimum amount of time to assert RST */ ! 2055: outb(0, ioport+SCNTL1); ! 2056: restore_flags (flags); ! 2057: return( 0 ); ! 2058: } ! 2059: ! 2060: ! 2061: int DC390W_release(struct Scsi_Host *host) ! 2062: { ! 2063: int irq_count; ! 2064: struct Scsi_Host *tmp; ! 2065: ! 2066: DC390W_shutdown (host); ! 2067: ! 2068: if (host->irq != IRQ_NONE) ! 2069: { ! 2070: for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) ! 2071: { ! 2072: if ( tmp->irq == host->irq ) ! 2073: ++irq_count; ! 2074: } ! 2075: if (irq_count == 1) ! 2076: { ! 2077: #ifdef DC390W_DEBUG0 ! 2078: printk("DC390W: Free IRQ %i.",host->irq); ! 2079: #endif ! 2080: #ifndef VERSION_ELF_1_2_13 ! 2081: free_irq(host->irq,NULL); ! 2082: #else ! 2083: free_irq(host->irq); ! 2084: #endif ! 2085: } ! 2086: } ! 2087: ! 2088: release_region(host->io_port,host->n_io_port); ! 2089: ! 2090: return( 1 ); ! 2091: } ! 2092: ! 2093: Scsi_Host_Template driver_template = DC390WUF; ! 2094: #include "scsi_module.c" ! 2095: #endif /* def MODULE */ ! 2096:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.