|
|
1.1 ! root 1: /*********************************************************************** ! 2: * FILE NAME : TMSCSIM.C * ! 3: * BY : C.L. Huang, [email protected] * ! 4: * Description: Device Driver for Tekram DC-390(T) PCI SCSI * ! 5: * Bus Master Host Adapter * ! 6: * (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/24/96 CLH First release * ! 15: * 1.01 06/12/96 CLH Fixed bug of Media Change for Removable * ! 16: * Device, scan all LUN. Support Pre2.0.10 * ! 17: * 1.02 06/18/96 CLH Fixed bug of Command timeout ... * ! 18: * 1.03 09/25/96 KG Added tmscsim_proc_info() * ! 19: * 1.04 10/11/96 CLH Updating for support KV 2.0.x * ! 20: * 1.05 10/18/96 KG Fixed bug in DC390_abort(null ptr deref)* ! 21: * 1.06 10/25/96 KG Fixed module support * ! 22: * 1.07 11/09/96 KG Fixed tmscsim_proc_info() * ! 23: * 1.08 11/18/96 KG Fixed null ptr in DC390_Disconnect() * ! 24: * 1.09 11/30/96 KG Added register the allocated IO space * ! 25: * 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset * ! 26: * pending interrupt in DC390_detect() * ! 27: * 1.11 02/05/97 KG/CLH Fixeds problem with partitions greater * ! 28: * than 1GB * ! 29: ***********************************************************************/ ! 30: ! 31: ! 32: #define DC390_DEBUG ! 33: ! 34: #define SCSI_MALLOC ! 35: ! 36: #ifdef MODULE ! 37: #include <linux/module.h> ! 38: #endif ! 39: ! 40: #include <asm/dma.h> ! 41: #include <asm/io.h> ! 42: #include <asm/system.h> ! 43: #include <linux/delay.h> ! 44: #include <linux/signal.h> ! 45: #include <linux/sched.h> ! 46: #include <linux/errno.h> ! 47: #include <linux/kernel.h> ! 48: #include <linux/ioport.h> ! 49: #include <linux/bios32.h> ! 50: #include <linux/pci.h> ! 51: #include <linux/proc_fs.h> ! 52: #include <linux/string.h> ! 53: #include <linux/mm.h> ! 54: #include <linux/config.h> ! 55: ! 56: #include <linux/version.h> ! 57: #if LINUX_VERSION_CODE < 66354 /* 1.3.50 */ ! 58: #include "../block/blk.h" ! 59: #else ! 60: #include <linux/blk.h> ! 61: #endif ! 62: ! 63: #include "scsi.h" ! 64: #include "hosts.h" ! 65: #include "tmscsim.h" ! 66: #include "constants.h" ! 67: #include "sd.h" ! 68: #include <linux/stat.h> ! 69: ! 70: #include "dc390.h" ! 71: ! 72: #define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI ! 73: ! 74: ! 75: #ifndef VERSION_ELF_1_2_13 ! 76: struct proc_dir_entry proc_scsi_tmscsim ={ ! 77: PROC_SCSI_DC390T, 7 ,"tmscsim", ! 78: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 79: }; ! 80: #endif ! 81: ! 82: static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 83: static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 84: static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 85: static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 86: static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 87: static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 88: static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 89: static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 90: static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 91: static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 92: static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 93: static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 94: static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 95: static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 96: static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); ! 97: ! 98: static void SetXferRate( PACB pACB, PDCB pDCB ); ! 99: static void DC390_Disconnect( PACB pACB ); ! 100: static void DC390_Reselect( PACB pACB ); ! 101: static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 102: static void DoingSRB_Done( PACB pACB ); ! 103: static void DC390_ScsiRstDetect( PACB pACB ); ! 104: static void DC390_ResetSCSIBus( PACB pACB ); ! 105: static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); ! 106: static void EnableMsgOut2( PACB pACB, PSRB pSRB ); ! 107: static void EnableMsgOut( PACB pACB, PSRB pSRB ); ! 108: static void DC390_InvalidCmd( PACB pACB ); ! 109: ! 110: int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ); ! 111: void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); ! 112: ! 113: #ifdef MODULE ! 114: static int DC390_release(struct Scsi_Host *host); ! 115: static int DC390_shutdown (struct Scsi_Host *host); ! 116: #endif ! 117: ! 118: ! 119: static PSHT pSHT_start = NULL; ! 120: static PSH pSH_start = NULL; ! 121: static PSH pSH_current = NULL; ! 122: static PACB pACB_start= NULL; ! 123: static PACB pACB_current = NULL; ! 124: static PDCB pPrevDCB = NULL; ! 125: static USHORT adapterCnt = 0; ! 126: static USHORT InitialTime = 0; ! 127: static USHORT CurrSyncOffset = 0; ! 128: static ULONG mech1addr; ! 129: static UCHAR mech2bus, mech2Agent, mech2CfgSPenR; ! 130: ! 131: static PVOID DC390_phase0[]={ ! 132: DC390_DataOut_0, ! 133: DC390_DataIn_0, ! 134: DC390_Command_0, ! 135: DC390_Status_0, ! 136: DC390_Nop_0, ! 137: DC390_Nop_0, ! 138: DC390_MsgOut_0, ! 139: DC390_MsgIn_0, ! 140: DC390_Nop_1 ! 141: }; ! 142: ! 143: static PVOID DC390_phase1[]={ ! 144: DC390_DataOutPhase, ! 145: DC390_DataInPhase, ! 146: DC390_CommandPhase, ! 147: DC390_StatusPhase, ! 148: DC390_Nop_0, ! 149: DC390_Nop_0, ! 150: DC390_MsgOutPhase, ! 151: DC390_MsgInPhase, ! 152: DC390_Nop_1, ! 153: }; ! 154: ! 155: UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; ! 156: ! 157: ! 158: UCHAR clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; ! 159: ! 160: UCHAR baddevname1[2][28] ={ ! 161: "SEAGATE ST3390N 9546", ! 162: "HP C3323-300 4269"}; ! 163: ! 164: #define BADDEVCNT 2 ! 165: ! 166: ! 167: /*********************************************************************** ! 168: * ! 169: * ! 170: * ! 171: **********************************************************************/ ! 172: static void ! 173: QLinkcmd( PSCSICMD cmd, PDCB pDCB ) ! 174: { ! 175: ULONG flags; ! 176: PSCSICMD pcmd; ! 177: ! 178: save_flags(flags); ! 179: cli(); ! 180: ! 181: if( !pDCB->QIORBCnt ) ! 182: { ! 183: pDCB->pQIORBhead = cmd; ! 184: pDCB->pQIORBtail = cmd; ! 185: pDCB->QIORBCnt++; ! 186: cmd->next = NULL; ! 187: } ! 188: else ! 189: { ! 190: pcmd = pDCB->pQIORBtail; ! 191: pcmd->next = cmd; ! 192: pDCB->pQIORBtail = cmd; ! 193: pDCB->QIORBCnt++; ! 194: cmd->next = NULL; ! 195: } ! 196: ! 197: restore_flags(flags); ! 198: } ! 199: ! 200: ! 201: static PSCSICMD ! 202: Getcmd( PDCB pDCB ) ! 203: { ! 204: ULONG flags; ! 205: PSCSICMD pcmd; ! 206: ! 207: save_flags(flags); ! 208: cli(); ! 209: ! 210: pcmd = pDCB->pQIORBhead; ! 211: pDCB->pQIORBhead = pcmd->next; ! 212: pcmd->next = NULL; ! 213: pDCB->QIORBCnt--; ! 214: ! 215: restore_flags(flags); ! 216: return( pcmd ); ! 217: } ! 218: ! 219: ! 220: static PSRB ! 221: GetSRB( PACB pACB ) ! 222: { ! 223: ULONG flags; ! 224: PSRB pSRB; ! 225: ! 226: save_flags(flags); ! 227: cli(); ! 228: ! 229: pSRB = pACB->pFreeSRB; ! 230: if( pSRB ) ! 231: { ! 232: pACB->pFreeSRB = pSRB->pNextSRB; ! 233: pSRB->pNextSRB = NULL; ! 234: } ! 235: restore_flags(flags); ! 236: return( pSRB ); ! 237: } ! 238: ! 239: ! 240: static void ! 241: RewaitSRB0( PDCB pDCB, PSRB pSRB ) ! 242: { ! 243: PSRB psrb1; ! 244: ULONG flags; ! 245: ! 246: save_flags(flags); ! 247: cli(); ! 248: ! 249: if( (psrb1 = pDCB->pWaitingSRB) ) ! 250: { ! 251: pSRB->pNextSRB = psrb1; ! 252: pDCB->pWaitingSRB = pSRB; ! 253: } ! 254: else ! 255: { ! 256: pSRB->pNextSRB = NULL; ! 257: pDCB->pWaitingSRB = pSRB; ! 258: pDCB->pWaitLast = pSRB; ! 259: } ! 260: restore_flags(flags); ! 261: } ! 262: ! 263: ! 264: static void ! 265: RewaitSRB( PDCB pDCB, PSRB pSRB ) ! 266: { ! 267: PSRB psrb1; ! 268: ULONG flags; ! 269: UCHAR bval; ! 270: ! 271: save_flags(flags); ! 272: cli(); ! 273: pDCB->GoingSRBCnt--; ! 274: psrb1 = pDCB->pGoingSRB; ! 275: if( pSRB == psrb1 ) ! 276: { ! 277: pDCB->pGoingSRB = psrb1->pNextSRB; ! 278: } ! 279: else ! 280: { ! 281: while( pSRB != psrb1->pNextSRB ) ! 282: psrb1 = psrb1->pNextSRB; ! 283: psrb1->pNextSRB = pSRB->pNextSRB; ! 284: if( pSRB == pDCB->pGoingLast ) ! 285: pDCB->pGoingLast = psrb1; ! 286: } ! 287: if( (psrb1 = pDCB->pWaitingSRB) ) ! 288: { ! 289: pSRB->pNextSRB = psrb1; ! 290: pDCB->pWaitingSRB = pSRB; ! 291: } ! 292: else ! 293: { ! 294: pSRB->pNextSRB = NULL; ! 295: pDCB->pWaitingSRB = pSRB; ! 296: pDCB->pWaitLast = pSRB; ! 297: } ! 298: ! 299: bval = pSRB->TagNumber; ! 300: pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ ! 301: restore_flags(flags); ! 302: } ! 303: ! 304: ! 305: static void ! 306: DoWaitingSRB( PACB pACB ) ! 307: { ! 308: ULONG flags; ! 309: PDCB ptr, ptr1; ! 310: PSRB pSRB; ! 311: ! 312: save_flags(flags); ! 313: cli(); ! 314: ! 315: if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) ! 316: { ! 317: ptr = pACB->pDCBRunRobin; ! 318: if( !ptr ) ! 319: { ! 320: ptr = pACB->pLinkDCB; ! 321: pACB->pDCBRunRobin = ptr; ! 322: } ! 323: ptr1 = ptr; ! 324: for( ;ptr1; ) ! 325: { ! 326: pACB->pDCBRunRobin = ptr1->pNextDCB; ! 327: if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || ! 328: !( pSRB = ptr1->pWaitingSRB ) ) ! 329: { ! 330: if(pACB->pDCBRunRobin == ptr) ! 331: break; ! 332: ptr1 = ptr1->pNextDCB; ! 333: } ! 334: else ! 335: { ! 336: if( !DC390_StartSCSI(pACB, ptr1, pSRB) ) ! 337: { ! 338: ptr1->GoingSRBCnt++; ! 339: if( ptr1->pWaitLast == pSRB ) ! 340: { ! 341: ptr1->pWaitingSRB = NULL; ! 342: ptr1->pWaitLast = NULL; ! 343: } ! 344: else ! 345: { ! 346: ptr1->pWaitingSRB = pSRB->pNextSRB; ! 347: } ! 348: pSRB->pNextSRB = NULL; ! 349: ! 350: if( ptr1->pGoingSRB ) ! 351: ptr1->pGoingLast->pNextSRB = pSRB; ! 352: else ! 353: ptr1->pGoingSRB = pSRB; ! 354: ptr1->pGoingLast = pSRB; ! 355: } ! 356: break; ! 357: } ! 358: } ! 359: } ! 360: restore_flags(flags); ! 361: return; ! 362: } ! 363: ! 364: ! 365: static void ! 366: SRBwaiting( PDCB pDCB, PSRB pSRB) ! 367: { ! 368: if( pDCB->pWaitingSRB ) ! 369: { ! 370: pDCB->pWaitLast->pNextSRB = pSRB; ! 371: pDCB->pWaitLast = pSRB; ! 372: pSRB->pNextSRB = NULL; ! 373: } ! 374: else ! 375: { ! 376: pDCB->pWaitingSRB = pSRB; ! 377: pDCB->pWaitLast = pSRB; ! 378: } ! 379: } ! 380: ! 381: ! 382: static void ! 383: SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) ! 384: { ! 385: ULONG flags; ! 386: PDCB pDCB; ! 387: ! 388: save_flags(flags); ! 389: cli(); ! 390: ! 391: pDCB = pSRB->pSRBDCB; ! 392: if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || ! 393: (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) ! 394: { ! 395: SRBwaiting(pDCB, pSRB); ! 396: goto SND_EXIT; ! 397: } ! 398: ! 399: if( pDCB->pWaitingSRB ) ! 400: { ! 401: SRBwaiting(pDCB, pSRB); ! 402: /* pSRB = GetWaitingSRB(pDCB); */ ! 403: pSRB = pDCB->pWaitingSRB; ! 404: pDCB->pWaitingSRB = pSRB->pNextSRB; ! 405: pSRB->pNextSRB = NULL; ! 406: } ! 407: ! 408: if( !DC390_StartSCSI(pACB, pDCB, pSRB) ) ! 409: { ! 410: pDCB->GoingSRBCnt++; ! 411: if( pDCB->pGoingSRB ) ! 412: { ! 413: pDCB->pGoingLast->pNextSRB = pSRB; ! 414: pDCB->pGoingLast = pSRB; ! 415: } ! 416: else ! 417: { ! 418: pDCB->pGoingSRB = pSRB; ! 419: pDCB->pGoingLast = pSRB; ! 420: } ! 421: } ! 422: else ! 423: RewaitSRB0( pDCB, pSRB ); ! 424: ! 425: SND_EXIT: ! 426: restore_flags(flags); ! 427: return; ! 428: } ! 429: ! 430: ! 431: /*********************************************************************** ! 432: * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, ! 433: * void (*done)(Scsi_Cmnd *)) ! 434: * ! 435: * Purpose : enqueues a SCSI command ! 436: * ! 437: * Inputs : cmd - SCSI command, done - function called on completion, with ! 438: * a pointer to the command descriptor. ! 439: * ! 440: * Returns : 0 ! 441: * ! 442: ***********************************************************************/ ! 443: ! 444: int ! 445: DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ! 446: { ! 447: USHORT ioport, i; ! 448: Scsi_Cmnd *pcmd; ! 449: struct Scsi_Host *psh; ! 450: PACB pACB; ! 451: PDCB pDCB; ! 452: PSRB pSRB; ! 453: ULONG flags; ! 454: PUCHAR ptr,ptr1; ! 455: ! 456: psh = cmd->host; ! 457: pACB = (PACB ) psh->hostdata; ! 458: ioport = pACB->IOPortBase; ! 459: ! 460: #ifdef DC390_DEBUG0 ! 461: /* if(pACB->scan_devices) */ ! 462: printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun); ! 463: #endif ! 464: ! 465: if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) ! 466: { ! 467: pACB->scan_devices = 0; ! 468: pPrevDCB->pNextDCB = pACB->pLinkDCB; ! 469: } ! 470: else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) ) ! 471: { ! 472: pACB->scan_devices = 0; ! 473: pPrevDCB->pNextDCB = pACB->pLinkDCB; ! 474: } ! 475: ! 476: if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) ) ! 477: { ! 478: /* printk("DC390: Ignore target %d lun %d\n", ! 479: cmd->target, cmd->lun); */ ! 480: cmd->result = (DID_BAD_TARGET << 16); ! 481: done(cmd); ! 482: return( 0 ); ! 483: } ! 484: ! 485: if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) ! 486: { ! 487: if( pACB->DeviceCnt < MAX_DEVICES ) ! 488: { ! 489: pACB->DCBmap[cmd->target] |= (1 << cmd->lun); ! 490: pDCB = pACB->pDCB_free; ! 491: #ifdef DC390_DEBUG0 ! 492: printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); ! 493: #endif ! 494: DC390_initDCB( pACB, pDCB, cmd ); ! 495: } ! 496: else /* ???? */ ! 497: { ! 498: /* printk("DC390: Ignore target %d lun %d\n", ! 499: cmd->target, cmd->lun); */ ! 500: cmd->result = (DID_BAD_TARGET << 16); ! 501: done(cmd); ! 502: return(0); ! 503: } ! 504: } ! 505: else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) ! 506: { ! 507: /* printk("DC390: Ignore target %d lun %d\n", ! 508: cmd->target, cmd->lun); */ ! 509: cmd->result = (DID_BAD_TARGET << 16); ! 510: done(cmd); ! 511: return(0); ! 512: } ! 513: else ! 514: { ! 515: pDCB = pACB->pLinkDCB; ! 516: while( (pDCB->UnitSCSIID != cmd->target) || ! 517: (pDCB->UnitSCSILUN != cmd->lun) ) ! 518: { ! 519: pDCB = pDCB->pNextDCB; ! 520: } ! 521: #ifdef DC390_DEBUG0 ! 522: printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); ! 523: #endif ! 524: } ! 525: ! 526: cmd->scsi_done = done; ! 527: cmd->result = 0; ! 528: ! 529: save_flags(flags); ! 530: cli(); ! 531: ! 532: if( pDCB->QIORBCnt ) ! 533: { ! 534: QLinkcmd( cmd, pDCB ); ! 535: pcmd = Getcmd( pDCB ); ! 536: } ! 537: else ! 538: pcmd = cmd; ! 539: ! 540: pSRB = GetSRB( pACB ); ! 541: ! 542: if( !pSRB ) ! 543: { ! 544: QLinkcmd( pcmd, pDCB ); ! 545: restore_flags(flags); ! 546: return(0); ! 547: } ! 548: ! 549: /* BuildSRB(pSRB); */ ! 550: ! 551: pSRB->pSRBDCB = pDCB; ! 552: pSRB->pcmd = pcmd; ! 553: ptr = (PUCHAR) pSRB->CmdBlock; ! 554: ptr1 = (PUCHAR) pcmd->cmnd; ! 555: pSRB->ScsiCmdLen = pcmd->cmd_len; ! 556: for(i=0; i< pcmd->cmd_len; i++) ! 557: { ! 558: *ptr = *ptr1; ! 559: ptr++; ! 560: ptr1++; ! 561: } ! 562: if( pcmd->use_sg ) ! 563: { ! 564: pSRB->SGcount = (UCHAR) pcmd->use_sg; ! 565: pSRB->pSegmentList = (PSGL) pcmd->request_buffer; ! 566: } ! 567: else if( pcmd->request_buffer ) ! 568: { ! 569: pSRB->SGcount = 1; ! 570: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; ! 571: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; ! 572: pSRB->Segmentx.length = pcmd->request_bufflen; ! 573: } ! 574: else ! 575: pSRB->SGcount = 0; ! 576: ! 577: pSRB->SGIndex = 0; ! 578: pSRB->AdaptStatus = 0; ! 579: pSRB->TargetStatus = 0; ! 580: pSRB->MsgCnt = 0; ! 581: if( pDCB->DevType != TYPE_TAPE ) ! 582: pSRB->RetryCnt = 1; ! 583: else ! 584: pSRB->RetryCnt = 0; ! 585: pSRB->SRBStatus = 0; ! 586: pSRB->SRBFlag = 0; ! 587: pSRB->SRBState = 0; ! 588: pSRB->TotalXferredLen = 0; ! 589: pSRB->SGPhysAddr = 0; ! 590: pSRB->SGToBeXferLen = 0; ! 591: pSRB->ScsiPhase = 0; ! 592: pSRB->EndMessage = 0; ! 593: SendSRB( pcmd, pACB, pSRB ); ! 594: ! 595: restore_flags(flags); ! 596: return(0); ! 597: } ! 598: ! 599: ! 600: static void ! 601: DoNextCmd( PACB pACB, PDCB pDCB ) ! 602: { ! 603: Scsi_Cmnd *pcmd; ! 604: PSRB pSRB; ! 605: ULONG flags; ! 606: PUCHAR ptr,ptr1; ! 607: USHORT i; ! 608: ! 609: ! 610: if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ! 611: return; ! 612: save_flags(flags); ! 613: cli(); ! 614: ! 615: pcmd = Getcmd( pDCB ); ! 616: pSRB = GetSRB( pACB ); ! 617: if( !pSRB ) ! 618: { ! 619: QLinkcmd( pcmd, pDCB ); ! 620: restore_flags(flags); ! 621: return; ! 622: } ! 623: ! 624: pSRB->pSRBDCB = pDCB; ! 625: pSRB->pcmd = pcmd; ! 626: ptr = (PUCHAR) pSRB->CmdBlock; ! 627: ptr1 = (PUCHAR) pcmd->cmnd; ! 628: pSRB->ScsiCmdLen = pcmd->cmd_len; ! 629: for(i=0; i< pcmd->cmd_len; i++) ! 630: { ! 631: *ptr = *ptr1; ! 632: ptr++; ! 633: ptr1++; ! 634: } ! 635: if( pcmd->use_sg ) ! 636: { ! 637: pSRB->SGcount = (UCHAR) pcmd->use_sg; ! 638: pSRB->pSegmentList = (PSGL) pcmd->request_buffer; ! 639: } ! 640: else if( pcmd->request_buffer ) ! 641: { ! 642: pSRB->SGcount = 1; ! 643: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; ! 644: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; ! 645: pSRB->Segmentx.length = pcmd->request_bufflen; ! 646: } ! 647: else ! 648: pSRB->SGcount = 0; ! 649: ! 650: pSRB->SGIndex = 0; ! 651: pSRB->AdaptStatus = 0; ! 652: pSRB->TargetStatus = 0; ! 653: pSRB->MsgCnt = 0; ! 654: if( pDCB->DevType != TYPE_TAPE ) ! 655: pSRB->RetryCnt = 1; ! 656: else ! 657: pSRB->RetryCnt = 0; ! 658: pSRB->SRBStatus = 0; ! 659: pSRB->SRBFlag = 0; ! 660: pSRB->SRBState = 0; ! 661: pSRB->TotalXferredLen = 0; ! 662: pSRB->SGPhysAddr = 0; ! 663: pSRB->SGToBeXferLen = 0; ! 664: pSRB->ScsiPhase = 0; ! 665: pSRB->EndMessage = 0; ! 666: SendSRB( pcmd, pACB, pSRB ); ! 667: ! 668: restore_flags(flags); ! 669: return; ! 670: } ! 671: ! 672: ! 673: /*********************************************************************** ! 674: * Function: ! 675: * DC390_bios_param ! 676: * ! 677: * Description: ! 678: * Return the disk geometry for the given SCSI device. ! 679: ***********************************************************************/ ! 680: #ifdef VERSION_ELF_1_2_13 ! 681: int DC390_bios_param(Disk *disk, int devno, int geom[]) ! 682: #else ! 683: int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]) ! 684: #endif ! 685: { ! 686: int heads, sectors, cylinders; ! 687: PACB pACB; ! 688: ! 689: pACB = (PACB) disk->device->host->hostdata; ! 690: heads = 64; ! 691: sectors = 32; ! 692: cylinders = disk->capacity / (heads * sectors); ! 693: ! 694: if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) ! 695: { ! 696: heads = 255; ! 697: sectors = 63; ! 698: cylinders = disk->capacity / (heads * sectors); ! 699: } ! 700: ! 701: geom[0] = heads; ! 702: geom[1] = sectors; ! 703: geom[2] = cylinders; ! 704: ! 705: return (0); ! 706: } ! 707: ! 708: ! 709: /*********************************************************************** ! 710: * Function : int DC390_abort (Scsi_Cmnd *cmd) ! 711: * ! 712: * Purpose : Abort an errant SCSI command ! 713: * ! 714: * Inputs : cmd - command to abort ! 715: * ! 716: * Returns : 0 on success, -1 on failure. ! 717: ***********************************************************************/ ! 718: ! 719: int ! 720: DC390_abort (Scsi_Cmnd *cmd) ! 721: { ! 722: ULONG flags; ! 723: PACB pACB; ! 724: PDCB pDCB, pdcb; ! 725: PSRB pSRB, psrb; ! 726: USHORT count, i; ! 727: PSCSICMD pcmd, pcmd1; ! 728: int status; ! 729: ! 730: ! 731: #ifdef DC390_DEBUG0 ! 732: printk("DC390 : Abort Cmd."); ! 733: #endif ! 734: ! 735: save_flags(flags); ! 736: cli(); ! 737: ! 738: pACB = (PACB) cmd->host->hostdata; ! 739: pDCB = pACB->pLinkDCB; ! 740: pdcb = pDCB; ! 741: while( (pDCB->UnitSCSIID != cmd->target) || ! 742: (pDCB->UnitSCSILUN != cmd->lun) ) ! 743: { ! 744: pDCB = pDCB->pNextDCB; ! 745: if( pDCB == pdcb ) ! 746: goto NOT_RUN; ! 747: } ! 748: ! 749: if( pDCB->QIORBCnt ) ! 750: { ! 751: pcmd = pDCB->pQIORBhead; ! 752: if( pcmd == cmd ) ! 753: { ! 754: pDCB->pQIORBhead = pcmd->next; ! 755: pcmd->next = NULL; ! 756: pDCB->QIORBCnt--; ! 757: status = SCSI_ABORT_SUCCESS; ! 758: goto ABO_X; ! 759: } ! 760: for( count = pDCB->QIORBCnt, i=0; i<count-1; i++) ! 761: { ! 762: if( pcmd->next == cmd ) ! 763: { ! 764: pcmd1 = pcmd->next; ! 765: pcmd->next = pcmd1->next; ! 766: pcmd1->next = NULL; ! 767: pDCB->QIORBCnt--; ! 768: status = SCSI_ABORT_SUCCESS; ! 769: goto ABO_X; ! 770: } ! 771: else ! 772: { ! 773: pcmd = pcmd->next; ! 774: } ! 775: } ! 776: } ! 777: ! 778: pSRB = pDCB->pWaitingSRB; ! 779: if( !pSRB ) ! 780: goto ON_GOING; ! 781: if( pSRB->pcmd == cmd ) ! 782: { ! 783: pDCB->pWaitingSRB = pSRB->pNextSRB; ! 784: goto IN_WAIT; ! 785: } ! 786: else ! 787: { ! 788: psrb = pSRB; ! 789: if( !(psrb->pNextSRB) ) ! 790: goto ON_GOING; ! 791: while( psrb->pNextSRB->pcmd != cmd ) ! 792: { ! 793: psrb = psrb->pNextSRB; ! 794: if( !(psrb->pNextSRB) ) ! 795: goto ON_GOING; ! 796: } ! 797: pSRB = psrb->pNextSRB; ! 798: psrb->pNextSRB = pSRB->pNextSRB; ! 799: if( pSRB == pDCB->pWaitLast ) ! 800: pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */ ! 801: IN_WAIT: ! 802: pSRB->pNextSRB = pACB->pFreeSRB; ! 803: pACB->pFreeSRB = pSRB; ! 804: cmd->next = NULL; ! 805: status = SCSI_ABORT_SUCCESS; ! 806: goto ABO_X; ! 807: } ! 808: ! 809: ON_GOING: ! 810: pSRB = pDCB->pGoingSRB; ! 811: for( count = pDCB->GoingSRBCnt, i=0; i<count; i++) ! 812: { ! 813: if( pSRB->pcmd != cmd ) ! 814: pSRB = pSRB->pNextSRB; ! 815: else ! 816: { ! 817: if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) ! 818: { ! 819: status = SCSI_ABORT_BUSY; ! 820: goto ABO_X; ! 821: } ! 822: else ! 823: { ! 824: status = SCSI_ABORT_SNOOZE; ! 825: goto ABO_X; ! 826: } ! 827: } ! 828: } ! 829: ! 830: NOT_RUN: ! 831: status = SCSI_ABORT_NOT_RUNNING; ! 832: ! 833: ABO_X: ! 834: cmd->result = DID_ABORT << 16; ! 835: cmd->scsi_done(cmd); ! 836: restore_flags(flags); ! 837: return( status ); ! 838: } ! 839: ! 840: ! 841: static void ! 842: ResetDevParam( PACB pACB ) ! 843: { ! 844: PDCB pDCB, pdcb; ! 845: ! 846: pDCB = pACB->pLinkDCB; ! 847: if( pDCB == NULL ) ! 848: return; ! 849: pdcb = pDCB; ! 850: do ! 851: { ! 852: pDCB->SyncMode &= ~SYNC_NEGO_DONE; ! 853: pDCB->SyncPeriod = 0; ! 854: pDCB->SyncOffset = 0; ! 855: pDCB->CtrlR3 = FAST_CLK; ! 856: pDCB->CtrlR4 &= NEGATE_REQACKDATA; ! 857: pDCB->CtrlR4 |= EATER_25NS; ! 858: pDCB = pDCB->pNextDCB; ! 859: } ! 860: while( pdcb != pDCB ); ! 861: } ! 862: ! 863: ! 864: static void ! 865: RecoverSRB( PACB pACB ) ! 866: { ! 867: PDCB pDCB, pdcb; ! 868: PSRB psrb, psrb2; ! 869: USHORT cnt, i; ! 870: ! 871: pDCB = pACB->pLinkDCB; ! 872: if( pDCB == NULL ) ! 873: return; ! 874: pdcb = pDCB; ! 875: do ! 876: { ! 877: cnt = pdcb->GoingSRBCnt; ! 878: psrb = pdcb->pGoingSRB; ! 879: for (i=0; i<cnt; i++) ! 880: { ! 881: psrb2 = psrb; ! 882: psrb = psrb->pNextSRB; ! 883: /* RewaitSRB( pDCB, psrb ); */ ! 884: if( pdcb->pWaitingSRB ) ! 885: { ! 886: psrb2->pNextSRB = pdcb->pWaitingSRB; ! 887: pdcb->pWaitingSRB = psrb2; ! 888: } ! 889: else ! 890: { ! 891: pdcb->pWaitingSRB = psrb2; ! 892: pdcb->pWaitLast = psrb2; ! 893: psrb2->pNextSRB = NULL; ! 894: } ! 895: } ! 896: pdcb->GoingSRBCnt = 0; ! 897: pdcb->pGoingSRB = NULL; ! 898: pdcb->TagMask = 0; ! 899: pdcb = pdcb->pNextDCB; ! 900: } ! 901: while( pdcb != pDCB ); ! 902: } ! 903: ! 904: ! 905: /*********************************************************************** ! 906: * Function : int DC390_reset (Scsi_Cmnd *cmd, ...) ! 907: * ! 908: * Purpose : perform a hard reset on the SCSI bus ! 909: * ! 910: * Inputs : cmd - command which caused the SCSI RESET ! 911: * ! 912: * Returns : 0 on success. ! 913: ***********************************************************************/ ! 914: ! 915: #ifdef VERSION_2_0_0 ! 916: int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) ! 917: #else ! 918: int DC390_reset (Scsi_Cmnd *cmd) ! 919: #endif ! 920: { ! 921: USHORT ioport; ! 922: unsigned long flags; ! 923: PACB pACB; ! 924: UCHAR bval; ! 925: USHORT i; ! 926: ! 927: ! 928: #ifdef DC390_DEBUG1 ! 929: printk("DC390: RESET,"); ! 930: #endif ! 931: ! 932: pACB = (PACB ) cmd->host->hostdata; ! 933: ioport = pACB->IOPortBase; ! 934: save_flags(flags); ! 935: cli(); ! 936: bval = inb(ioport+CtrlReg1); ! 937: bval |= DIS_INT_ON_SCSI_RST; ! 938: outb(bval,ioport+CtrlReg1); /* disable interrupt */ ! 939: DC390_ResetSCSIBus( pACB ); ! 940: for( i=0; i<500; i++ ) ! 941: udelay(1000); ! 942: bval = inb(ioport+CtrlReg1); ! 943: bval &= ~DIS_INT_ON_SCSI_RST; ! 944: outb(bval,ioport+CtrlReg1); /* re-enable interrupt */ ! 945: ! 946: bval = DMA_IDLE_CMD; ! 947: outb(bval,ioport+DMA_Cmd); ! 948: bval = CLEAR_FIFO_CMD; ! 949: outb(bval,ioport+ScsiCmd); ! 950: ! 951: ResetDevParam( pACB ); ! 952: DoingSRB_Done( pACB ); ! 953: pACB->pActiveDCB = NULL; ! 954: ! 955: pACB->ACBFlag = 0; ! 956: DoWaitingSRB( pACB ); ! 957: ! 958: restore_flags(flags); ! 959: #ifdef DC390_DEBUG1 ! 960: printk("DC390: RESET1,"); ! 961: #endif ! 962: return( SCSI_RESET_SUCCESS ); ! 963: } ! 964: ! 965: ! 966: #include "scsiiom.c" ! 967: ! 968: ! 969: /*********************************************************************** ! 970: * Function : static void DC390_initDCB ! 971: * ! 972: * Purpose : initialize the internal structures for a given DCB ! 973: * ! 974: * Inputs : cmd - pointer to this scsi cmd request block structure ! 975: * ! 976: ***********************************************************************/ ! 977: void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) ! 978: { ! 979: PEEprom prom; ! 980: UCHAR bval; ! 981: USHORT index; ! 982: ! 983: if( pACB->DeviceCnt == 0 ) ! 984: { ! 985: pACB->pLinkDCB = pDCB; ! 986: pACB->pDCBRunRobin = pDCB; ! 987: pDCB->pNextDCB = pDCB; ! 988: pPrevDCB = pDCB; ! 989: } ! 990: else ! 991: pPrevDCB->pNextDCB = pDCB; ! 992: ! 993: pDCB->pDCBACB = pACB; ! 994: pDCB->QIORBCnt = 0; ! 995: pDCB->UnitSCSIID = cmd->target; ! 996: pDCB->UnitSCSILUN = cmd->lun; ! 997: pDCB->pWaitingSRB = NULL; ! 998: pDCB->pGoingSRB = NULL; ! 999: pDCB->GoingSRBCnt = 0; ! 1000: pDCB->pActiveSRB = NULL; ! 1001: pDCB->TagMask = 0; ! 1002: pDCB->MaxCommand = 1; ! 1003: pDCB->AdaptIndex = pACB->AdapterIndex; ! 1004: index = pACB->AdapterIndex; ! 1005: pDCB->DCBFlag = 0; ! 1006: ! 1007: prom = (PEEprom) &eepromBuf[index][cmd->target << 2]; ! 1008: pDCB->DevMode = prom->EE_MODE1; ! 1009: pDCB->AdpMode = eepromBuf[index][EE_MODE2]; ! 1010: ! 1011: if( pDCB->DevMode & EN_DISCONNECT_ ) ! 1012: bval = 0xC0; ! 1013: else ! 1014: bval = 0x80; ! 1015: bval |= cmd->lun; ! 1016: pDCB->IdentifyMsg = bval; ! 1017: ! 1018: pDCB->SyncMode = 0; ! 1019: if( pDCB->DevMode & SYNC_NEGO_ ) ! 1020: { ! 1021: if( !(cmd->lun) || CurrSyncOffset ) ! 1022: pDCB->SyncMode = SYNC_ENABLE; ! 1023: } ! 1024: ! 1025: pDCB->SyncPeriod = 0; ! 1026: pDCB->SyncOffset = 0; ! 1027: pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2; ! 1028: ! 1029: pDCB->CtrlR1 = pACB->AdaptSCSIID; ! 1030: if( pDCB->DevMode & PARITY_CHK_ ) ! 1031: pDCB->CtrlR1 |= PARITY_ERR_REPO; ! 1032: ! 1033: pDCB->CtrlR3 = FAST_CLK; ! 1034: ! 1035: pDCB->CtrlR4 = EATER_25NS; ! 1036: if( pDCB->AdpMode & ACTIVE_NEGATION) ! 1037: pDCB->CtrlR4 |= NEGATE_REQACKDATA; ! 1038: } ! 1039: ! 1040: ! 1041: /*********************************************************************** ! 1042: * Function : static void DC390_initSRB ! 1043: * ! 1044: * Purpose : initialize the internal structures for a given SRB ! 1045: * ! 1046: * Inputs : psrb - pointer to this scsi request block structure ! 1047: * ! 1048: ***********************************************************************/ ! 1049: void DC390_initSRB( PSRB psrb ) ! 1050: { ! 1051: #ifndef VERSION_ELF_1_2_13 ! 1052: #ifdef DC390_DEBUG0 ! 1053: printk("DC390 init: %08lx %08lx,",(ULONG)psrb,(ULONG)virt_to_bus(psrb)); ! 1054: #endif ! 1055: psrb->PhysSRB = virt_to_bus( psrb ); ! 1056: #else ! 1057: psrb->PhysSRB = (ULONG) psrb; ! 1058: #endif ! 1059: } ! 1060: ! 1061: ! 1062: void DC390_linkSRB( PACB pACB ) ! 1063: { ! 1064: USHORT count, i; ! 1065: PSRB psrb; ! 1066: ! 1067: count = pACB->SRBCount; ! 1068: ! 1069: for( i=0; i< count; i++) ! 1070: { ! 1071: if( i != count - 1) ! 1072: pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; ! 1073: else ! 1074: pACB->SRB_array[i].pNextSRB = NULL; ! 1075: psrb = (PSRB) &pACB->SRB_array[i]; ! 1076: DC390_initSRB( psrb ); ! 1077: } ! 1078: } ! 1079: ! 1080: ! 1081: /*********************************************************************** ! 1082: * Function : static void DC390_initACB ! 1083: * ! 1084: * Purpose : initialize the internal structures for a given SCSI host ! 1085: * ! 1086: * Inputs : psh - pointer to this host adapter's structure ! 1087: * ! 1088: ***********************************************************************/ ! 1089: void DC390_initACB( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) ! 1090: { ! 1091: PACB pACB; ! 1092: USHORT i; ! 1093: ! 1094: psh->can_queue = MAX_CMD_QUEUE; ! 1095: psh->cmd_per_lun = MAX_CMD_PER_LUN; ! 1096: psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID]; ! 1097: psh->io_port = io_port; ! 1098: psh->n_io_port = 0x80; ! 1099: psh->irq = Irq; ! 1100: ! 1101: pACB = (PACB) psh->hostdata; ! 1102: ! 1103: #ifndef VERSION_ELF_1_2_13 ! 1104: psh->max_id = 8; ! 1105: #ifdef CONFIG_SCSI_MULTI_LUN ! 1106: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1107: psh->max_lun = 8; ! 1108: else ! 1109: #endif ! 1110: psh->max_lun = 1; ! 1111: #endif ! 1112: ! 1113: pACB->max_id = 7; ! 1114: if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) ! 1115: pACB->max_id--; ! 1116: #ifdef CONFIG_SCSI_MULTI_LUN ! 1117: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1118: pACB->max_lun = 7; ! 1119: else ! 1120: #endif ! 1121: pACB->max_lun = 0; ! 1122: ! 1123: pACB->pScsiHost = psh; ! 1124: pACB->IOPortBase = (USHORT) io_port; ! 1125: pACB->pLinkDCB = NULL; ! 1126: pACB->pDCBRunRobin = NULL; ! 1127: pACB->pActiveDCB = NULL; ! 1128: pACB->pFreeSRB = pACB->SRB_array; ! 1129: pACB->SRBCount = MAX_SRB_CNT; ! 1130: pACB->AdapterIndex = index; ! 1131: pACB->status = 0; ! 1132: pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; ! 1133: pACB->HostID_Bit = (1 << pACB->AdaptSCSIID); ! 1134: pACB->AdaptSCSILUN = 0; ! 1135: pACB->DeviceCnt = 0; ! 1136: pACB->IRQLevel = Irq; ! 1137: pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2; ! 1138: pACB->ACBFlag = 0; ! 1139: pACB->scan_devices = 1; ! 1140: pACB->Gmode2 = eepromBuf[index][EE_MODE2]; ! 1141: if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) ! 1142: pACB->LUNchk = 1; ! 1143: pACB->pDCB_free = &pACB->DCB_array[0]; ! 1144: DC390_linkSRB( pACB ); ! 1145: pACB->pTmpSRB = &pACB->TmpSRB; ! 1146: DC390_initSRB( pACB->pTmpSRB ); ! 1147: for(i=0; i<MAX_SCSI_ID; i++) ! 1148: pACB->DCBmap[i] = 0; ! 1149: } ! 1150: ! 1151: ! 1152: /*********************************************************************** ! 1153: * Function : static int DC390_initAdapter ! 1154: * ! 1155: * Purpose : initialize the SCSI chip ctrl registers ! 1156: * ! 1157: * Inputs : psh - pointer to this host adapter's structure ! 1158: * ! 1159: ***********************************************************************/ ! 1160: int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) ! 1161: { ! 1162: USHORT ioport; ! 1163: UCHAR bval; ! 1164: PACB pACB, pacb; ! 1165: USHORT used_irq = 0; ! 1166: ! 1167: pacb = pACB_start; ! 1168: if( pacb != NULL ) ! 1169: { ! 1170: for ( ; (pacb != (PACB) -1) ; ) ! 1171: { ! 1172: if( pacb->IRQLevel == Irq ) ! 1173: { ! 1174: used_irq = 1; ! 1175: break; ! 1176: } ! 1177: else ! 1178: pacb = pacb->pNextACB; ! 1179: } ! 1180: } ! 1181: ! 1182: if( !used_irq ) ! 1183: { ! 1184: #ifdef VERSION_ELF_1_2_13 ! 1185: if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim")) ! 1186: #else ! 1187: if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsim", NULL)) ! 1188: #endif ! 1189: { ! 1190: printk("DC390: register IRQ error!\n"); ! 1191: return( -1 ); ! 1192: } ! 1193: } ! 1194: ! 1195: request_region(io_port,psh->n_io_port,"tmscsim"); ! 1196: ! 1197: ioport = (USHORT) io_port; ! 1198: ! 1199: pACB = (PACB) psh->hostdata; ! 1200: bval = SEL_TIMEOUT; /* 250ms selection timeout */ ! 1201: outb(bval,ioport+Scsi_TimeOut); ! 1202: ! 1203: bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */ ! 1204: outb(bval,ioport+Clk_Factor); ! 1205: ! 1206: bval = NOP_CMD; /* NOP cmd - clear command register */ ! 1207: outb(bval,ioport+ScsiCmd); ! 1208: ! 1209: bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */ ! 1210: outb(bval,ioport+CtrlReg2); ! 1211: ! 1212: bval = FAST_CLK; /* fast clock */ ! 1213: outb(bval,ioport+CtrlReg3); ! 1214: ! 1215: bval = EATER_25NS; ! 1216: if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) ! 1217: bval |= NEGATE_REQACKDATA; ! 1218: outb(bval,ioport+CtrlReg4); ! 1219: ! 1220: bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */ ! 1221: outb(bval,ioport+CtrlReg1); ! 1222: ! 1223: return(0); ! 1224: } ! 1225: ! 1226: ! 1227: void ! 1228: DC390_EnableCfg( USHORT mechnum, UCHAR regval ) ! 1229: { ! 1230: ULONG wlval; ! 1231: ! 1232: if(mechnum == 2) ! 1233: { ! 1234: outb(mech2bus, PCI_CFG2_FORWARD_REG); ! 1235: outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG); ! 1236: } ! 1237: else ! 1238: { ! 1239: regval &= 0xFC; ! 1240: wlval = mech1addr; ! 1241: wlval |= (((ULONG)regval) & 0xff); ! 1242: outl(wlval, PCI_CFG1_ADDRESS_REG); ! 1243: } ! 1244: } ! 1245: ! 1246: ! 1247: void ! 1248: DC390_DisableCfg( USHORT mechnum ) ! 1249: { ! 1250: ! 1251: if(mechnum == 2) ! 1252: outb(0, PCI_CFG2_ENABLE_REG); ! 1253: else ! 1254: outl(0, PCI_CFG1_ADDRESS_REG); ! 1255: } ! 1256: ! 1257: ! 1258: UCHAR ! 1259: DC390_inByte( USHORT mechnum, UCHAR regval ) ! 1260: { ! 1261: UCHAR bval; ! 1262: ULONG wval; ! 1263: ULONG flags; ! 1264: ! 1265: save_flags(flags); ! 1266: cli(); ! 1267: DC390_EnableCfg( mechnum, regval ); ! 1268: if(mechnum == 2) ! 1269: { ! 1270: wval = mech2Agent; ! 1271: wval <<= 8; ! 1272: wval |= ((USHORT) regval) & 0xff; ! 1273: bval = inb(wval); ! 1274: } ! 1275: else ! 1276: { ! 1277: regval &= 3; ! 1278: bval = inb(PCI_CFG1_DATA_REG | regval); ! 1279: } ! 1280: DC390_DisableCfg(mechnum); ! 1281: restore_flags(flags); ! 1282: return(bval); ! 1283: } ! 1284: ! 1285: ! 1286: USHORT ! 1287: DC390_inWord( USHORT mechnum, UCHAR regval ) ! 1288: { ! 1289: USHORT wval; ! 1290: ULONG flags; ! 1291: ! 1292: save_flags(flags); ! 1293: cli(); ! 1294: DC390_EnableCfg(mechnum,regval); ! 1295: if(mechnum == 2) ! 1296: { ! 1297: wval = mech2Agent; ! 1298: wval <<= 8; ! 1299: wval |= regval; ! 1300: wval = inw(wval); ! 1301: } ! 1302: else ! 1303: { ! 1304: regval &= 3; ! 1305: wval = inw(PCI_CFG1_DATA_REG | regval); ! 1306: } ! 1307: DC390_DisableCfg(mechnum); ! 1308: restore_flags(flags); ! 1309: return(wval); ! 1310: } ! 1311: ! 1312: ! 1313: ULONG ! 1314: DC390_inDword(USHORT mechnum, UCHAR regval ) ! 1315: { ! 1316: ULONG wlval; ! 1317: ULONG flags; ! 1318: USHORT wval; ! 1319: ! 1320: save_flags(flags); ! 1321: cli(); ! 1322: DC390_EnableCfg(mechnum,regval); ! 1323: if(mechnum == 2) ! 1324: { ! 1325: wval = mech2Agent; ! 1326: wval <<= 8; ! 1327: wval |= regval; ! 1328: wlval = inl(wval); ! 1329: } ! 1330: else ! 1331: { ! 1332: wlval = inl(PCI_CFG1_DATA_REG); ! 1333: } ! 1334: DC390_DisableCfg(mechnum); ! 1335: restore_flags(flags); ! 1336: return(wlval); ! 1337: } ! 1338: ! 1339: ! 1340: void ! 1341: DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ) ! 1342: { ! 1343: ! 1344: USHORT wval; ! 1345: ULONG flags; ! 1346: ! 1347: save_flags(flags); ! 1348: cli(); ! 1349: DC390_EnableCfg(mechnum,regval); ! 1350: if(mechnum == 2) ! 1351: { ! 1352: wval = mech2Agent; ! 1353: wval <<= 8; ! 1354: wval |= regval; ! 1355: outb(bval, wval); ! 1356: } ! 1357: else ! 1358: { ! 1359: regval &= 3; ! 1360: outb(bval, PCI_CFG1_DATA_REG | regval); ! 1361: } ! 1362: DC390_DisableCfg(mechnum); ! 1363: restore_flags(flags); ! 1364: } ! 1365: ! 1366: ! 1367: void ! 1368: DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ) ! 1369: { ! 1370: ! 1371: UCHAR bval; ! 1372: ! 1373: bval = 0; ! 1374: if(mode == ENABLE_CE) ! 1375: *regval = 0xc0; ! 1376: else ! 1377: *regval = 0x80; ! 1378: DC390_OutB(mechnum,*regval,bval); ! 1379: if(mode == DISABLE_CE) ! 1380: DC390_OutB(mechnum,*regval,bval); ! 1381: udelay(160); ! 1382: } ! 1383: ! 1384: ! 1385: void ! 1386: DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ) ! 1387: { ! 1388: UCHAR bval; ! 1389: ! 1390: bval = 0; ! 1391: if(Carry) ! 1392: { ! 1393: bval = 0x40; ! 1394: *regval = 0x80; ! 1395: DC390_OutB(mechnum,*regval,bval); ! 1396: } ! 1397: udelay(160); ! 1398: bval |= 0x80; ! 1399: DC390_OutB(mechnum,*regval,bval); ! 1400: udelay(160); ! 1401: bval = 0; ! 1402: DC390_OutB(mechnum,*regval,bval); ! 1403: udelay(160); ! 1404: } ! 1405: ! 1406: ! 1407: UCHAR ! 1408: DC390_EEpromInDO( USHORT mechnum ) ! 1409: { ! 1410: UCHAR bval,regval; ! 1411: ! 1412: regval = 0x80; ! 1413: bval = 0x80; ! 1414: DC390_OutB(mechnum,regval,bval); ! 1415: udelay(160); ! 1416: bval = 0x40; ! 1417: DC390_OutB(mechnum,regval,bval); ! 1418: udelay(160); ! 1419: regval = 0x0; ! 1420: bval = DC390_inByte(mechnum,regval); ! 1421: if(bval == 0x22) ! 1422: return(1); ! 1423: else ! 1424: return(0); ! 1425: } ! 1426: ! 1427: ! 1428: USHORT ! 1429: EEpromGetData1( USHORT mechnum ) ! 1430: { ! 1431: UCHAR i; ! 1432: UCHAR carryFlag; ! 1433: USHORT wval; ! 1434: ! 1435: wval = 0; ! 1436: for(i=0; i<16; i++) ! 1437: { ! 1438: wval <<= 1; ! 1439: carryFlag = DC390_EEpromInDO(mechnum); ! 1440: wval |= carryFlag; ! 1441: } ! 1442: return(wval); ! 1443: } ! 1444: ! 1445: ! 1446: void ! 1447: DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ) ! 1448: { ! 1449: UCHAR i,j; ! 1450: USHORT carryFlag; ! 1451: ! 1452: carryFlag = 1; ! 1453: j = 0x80; ! 1454: for(i=0; i<9; i++) ! 1455: { ! 1456: DC390_EEpromOutDI(mechnum,regval,carryFlag); ! 1457: carryFlag = (EEpromCmd & j) ? 1 : 0; ! 1458: j >>= 1; ! 1459: } ! 1460: } ! 1461: ! 1462: ! 1463: void ! 1464: DC390_ReadEEprom( USHORT mechnum, USHORT index ) ! 1465: { ! 1466: UCHAR regval,cmd; ! 1467: PUSHORT ptr; ! 1468: USHORT i; ! 1469: ! 1470: ptr = (PUSHORT) &eepromBuf[index][0]; ! 1471: cmd = EEPROM_READ; ! 1472: for(i=0; i<0x40; i++) ! 1473: { ! 1474: DC390_EnDisableCE(ENABLE_CE, mechnum, ®val); ! 1475: DC390_Prepare(mechnum, ®val, cmd); ! 1476: *ptr = EEpromGetData1(mechnum); ! 1477: ptr++; ! 1478: cmd++; ! 1479: DC390_EnDisableCE(DISABLE_CE,mechnum,®val); ! 1480: } ! 1481: } ! 1482: ! 1483: ! 1484: USHORT ! 1485: DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ) ! 1486: { ! 1487: USHORT wval, rc, *ptr; ! 1488: UCHAR i; ! 1489: ! 1490: DC390_ReadEEprom( MechNum, index ); ! 1491: wval = 0; ! 1492: ptr = (PUSHORT) &eepromBuf[index][0]; ! 1493: for(i=0; i<128 ;i+=2, ptr++) ! 1494: wval += *ptr; ! 1495: if( wval == 0x1234 ) ! 1496: rc = 0; ! 1497: else ! 1498: rc = -1; ! 1499: return( rc ); ! 1500: } ! 1501: ! 1502: ! 1503: USHORT ! 1504: DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum ) ! 1505: { ! 1506: USHORT devnum; ! 1507: ! 1508: devnum = BusDevFunNum; ! 1509: ! 1510: if(Mechnum == 2) ! 1511: { ! 1512: if(devnum & 0x80) ! 1513: return(-1); ! 1514: mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */ ! 1515: mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */ ! 1516: mech2Agent |= 0xc0; ! 1517: mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */ ! 1518: mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20; ! 1519: } ! 1520: else /* use mech #1 method */ ! 1521: { ! 1522: mech1addr = 0x80000000 | ((ULONG)devnum << 8); ! 1523: } ! 1524: return(0); ! 1525: } ! 1526: ! 1527: /*********************************************************************** ! 1528: * Function : static int DC390_init (struct Scsi_Host *host) ! 1529: * ! 1530: * Purpose : initialize the internal structures for a given SCSI host ! 1531: * ! 1532: * Inputs : host - pointer to this host adapter's structure/ ! 1533: * ! 1534: * Preconditions : when this function is called, the chip_type ! 1535: * field of the pACB structure MUST have been set. ! 1536: ***********************************************************************/ ! 1537: ! 1538: static int ! 1539: DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum) ! 1540: { ! 1541: PSH psh; ! 1542: PACB pACB; ! 1543: ! 1544: if( !DC390_CheckEEpromCheckSum( MechNum, index) ) ! 1545: { ! 1546: psh = scsi_register( psht, sizeof(DC390_ACB) ); ! 1547: if( !psh ) ! 1548: return( -1 ); ! 1549: if( !pSH_start ) ! 1550: { ! 1551: pSH_start = psh; ! 1552: pSH_current = psh; ! 1553: } ! 1554: else ! 1555: { ! 1556: pSH_current->next = psh; ! 1557: pSH_current = psh; ! 1558: } ! 1559: ! 1560: #ifdef DC390_DEBUG0 ! 1561: printk("DC390: pSH = %8x,", (UINT) psh); ! 1562: printk("DC390: Index %02i,", index); ! 1563: #endif ! 1564: ! 1565: DC390_initACB( psh, io_port, Irq, index ); ! 1566: if( !DC390_initAdapter( psh, io_port, Irq, index ) ) ! 1567: { ! 1568: pACB = (PACB) psh->hostdata; ! 1569: if( !pACB_start ) ! 1570: { ! 1571: pACB_start = pACB; ! 1572: pACB_current = pACB; ! 1573: pACB->pNextACB = (PACB) -1; ! 1574: } ! 1575: else ! 1576: { ! 1577: pACB_current->pNextACB = pACB; ! 1578: pACB_current = pACB; ! 1579: pACB->pNextACB = (PACB) -1; ! 1580: } ! 1581: ! 1582: #ifdef DC390_DEBUG0 ! 1583: printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", ! 1584: (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); ! 1585: printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n", ! 1586: sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) ); ! 1587: #endif ! 1588: ! 1589: } ! 1590: else ! 1591: { ! 1592: pSH_start = NULL; ! 1593: scsi_unregister( psh ); ! 1594: return( -1 ); ! 1595: } ! 1596: return( 0 ); ! 1597: } ! 1598: else ! 1599: { ! 1600: printk("DC390_init: EEPROM reading error!\n"); ! 1601: return( -1 ); ! 1602: } ! 1603: } ! 1604: ! 1605: ! 1606: /*********************************************************************** ! 1607: * Function : int DC390_detect(Scsi_Host_Template *psht) ! 1608: * ! 1609: * Purpose : detects and initializes AMD53C974 SCSI chips ! 1610: * that were autoprobed, overridden on the LILO command line, ! 1611: * or specified at compile time. ! 1612: * ! 1613: * Inputs : psht - template for this SCSI adapter ! 1614: * ! 1615: * Returns : number of host adapters detected ! 1616: * ! 1617: ***********************************************************************/ ! 1618: ! 1619: int ! 1620: DC390_detect(Scsi_Host_Template *psht) ! 1621: { ! 1622: #ifdef FOR_PCI_OK ! 1623: UCHAR pci_bus, pci_device_fn; ! 1624: int error = 0; ! 1625: USHORT chipType = 0; ! 1626: USHORT i; ! 1627: #endif ! 1628: ! 1629: UCHAR irq; ! 1630: UCHAR istatus; ! 1631: #ifndef VERSION_ELF_1_2_13 ! 1632: UINT io_port; ! 1633: #else ! 1634: ULONG io_port; ! 1635: #endif ! 1636: USHORT adaptCnt = 0; /* Number of boards detected */ ! 1637: USHORT pci_index = 0; /* Device index to PCI BIOS calls */ ! 1638: USHORT MechNum, BusDevFunNum; ! 1639: ULONG wlval; ! 1640: ! 1641: #ifndef VERSION_ELF_1_2_13 ! 1642: psht->proc_dir = &proc_scsi_tmscsim; ! 1643: #endif ! 1644: ! 1645: InitialTime = 1; ! 1646: pSHT_start = psht; ! 1647: pACB_start = NULL; ! 1648: ! 1649: MechNum = 1; ! 1650: for( ; (MechNum < 3) && (!adaptCnt); MechNum++) ! 1651: { ! 1652: BusDevFunNum = 0; ! 1653: for (; adaptCnt < MAX_ADAPTER_NUM ;) ! 1654: { ! 1655: if( !DC390_ToMech( MechNum, BusDevFunNum) ) ! 1656: { ! 1657: wlval = DC390_inDword( MechNum, PCI_VENDOR_ID); ! 1658: if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+ ! 1659: PCI_VENDOR_ID_AMD) ) ! 1660: { ! 1661: io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE; ! 1662: irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE); ! 1663: #ifdef DC390_DEBUG0 ! 1664: printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); ! 1665: #endif ! 1666: if( !DC390_init(psht, io_port, irq, pci_index, MechNum) ) ! 1667: { ! 1668: adaptCnt++; ! 1669: pci_index++; ! 1670: istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */ ! 1671: #ifdef DC390_DEBUG0 ! 1672: printk("DC390: Mech=%2x,\n",(UCHAR) MechNum); ! 1673: #endif ! 1674: } ! 1675: } ! 1676: } ! 1677: if( BusDevFunNum != 0xfff8 ) ! 1678: BusDevFunNum += 8; /* next device # */ ! 1679: else ! 1680: break; ! 1681: } ! 1682: } ! 1683: ! 1684: #ifdef FOR_PCI_OK ! 1685: if ( pcibios_present() ) ! 1686: { ! 1687: for (i = 0; i < MAX_ADAPTER_NUM; ++i) ! 1688: { ! 1689: if( !pcibios_find_device( PCI_VENDOR_ID_AMD, ! 1690: PCI_DEVICE_ID_AMD53C974, ! 1691: pci_index, &pci_bus, &pci_device_fn) ) ! 1692: { ! 1693: chipType = PCI_DEVICE_ID_AMD53C974; ! 1694: pci_index++; ! 1695: } ! 1696: ! 1697: if( chipType ) ! 1698: { ! 1699: ! 1700: error = pcibios_read_config_dword(pci_bus, pci_device_fn, ! 1701: PCI_BASE_ADDRESS_0, &io_port); ! 1702: error |= pcibios_read_config_byte(pci_bus, pci_device_fn, ! 1703: PCI_INTERRUPT_LINE, &irq); ! 1704: if( error ) ! 1705: { ! 1706: printk("DC390_detect: reading configuration registers error!\n"); ! 1707: InitialTime = 0; ! 1708: return( 0 ); ! 1709: } ! 1710: ! 1711: (USHORT) io_port = (USHORT) io_port & 0xFFFE; ! 1712: #ifdef DC390_DEBUG0 ! 1713: printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); ! 1714: #endif ! 1715: if( !DC390_init(psht, io_port, irq, i) ) ! 1716: adaptCnt++; ! 1717: chipType = 0; ! 1718: } ! 1719: else ! 1720: break; ! 1721: } ! 1722: } ! 1723: #endif ! 1724: ! 1725: InitialTime = 0; ! 1726: adapterCnt = adaptCnt; ! 1727: return( adaptCnt ); ! 1728: } ! 1729: ! 1730: ! 1731: #ifndef VERSION_ELF_1_2_13 ! 1732: ! 1733: /******************************************************************** ! 1734: * Function: tmscsim_set_info() ! 1735: * ! 1736: * Purpose: Set adapter info (!) ! 1737: * ! 1738: * Not yet implemented ! 1739: * ! 1740: *******************************************************************/ ! 1741: ! 1742: int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt) ! 1743: { ! 1744: return(-ENOSYS); /* Currently this is a no-op */ ! 1745: } ! 1746: ! 1747: /******************************************************************** ! 1748: * Function: tmscsim_proc_info(char* buffer, char **start, ! 1749: * off_t offset, int length, int hostno, int inout) ! 1750: * ! 1751: * Purpose: return SCSI Adapter/Device Info ! 1752: * ! 1753: * Input: buffer: Pointer to a buffer where to write info ! 1754: * start : ! 1755: * offset: ! 1756: * hostno: Host adapter index ! 1757: * inout : Read (=0) or set(!=0) info ! 1758: * ! 1759: * Output: buffer: contains info ! 1760: * length; length of info in buffer ! 1761: * ! 1762: * return value: length ! 1763: * ! 1764: ********************************************************************/ ! 1765: ! 1766: /* KG: proc_info taken from driver aha152x.c */ ! 1767: ! 1768: #undef SPRINTF ! 1769: #define SPRINTF(args...) pos += sprintf(pos, ## args) ! 1770: ! 1771: #define YESNO(YN)\ ! 1772: if (YN) SPRINTF(" Yes ");\ ! 1773: else SPRINTF(" No ") ! 1774: ! 1775: int tmscsim_proc_info(char *buffer, char **start, ! 1776: off_t offset, int length, int hostno, int inout) ! 1777: { ! 1778: int dev, spd, spd1; ! 1779: char *pos = buffer; ! 1780: PSH shpnt; ! 1781: PACB acbpnt; ! 1782: PDCB dcbpnt; ! 1783: unsigned long flags; ! 1784: /* Scsi_Cmnd *ptr; */ ! 1785: ! 1786: acbpnt = pACB_start; ! 1787: ! 1788: while(acbpnt != (PACB)-1) ! 1789: { ! 1790: shpnt = acbpnt->pScsiHost; ! 1791: if (shpnt->host_no == hostno) break; ! 1792: acbpnt = acbpnt->pNextACB; ! 1793: } ! 1794: ! 1795: if (acbpnt == (PACB)-1) return(-ESRCH); ! 1796: if(!shpnt) return(-ESRCH); ! 1797: ! 1798: if(inout) /* Has data been written to the file ? */ ! 1799: return(tmscsim_set_info(buffer, length, shpnt)); ! 1800: ! 1801: SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, "); ! 1802: SPRINTF("Driver Version 1.10, 1996/12/05\n"); ! 1803: ! 1804: save_flags(flags); ! 1805: cli(); ! 1806: ! 1807: SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); ! 1808: SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex); ! 1809: SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase); ! 1810: SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel); ! 1811: ! 1812: SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun); ! 1813: SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); ! 1814: ! 1815: SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); ! 1816: ! 1817: SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); ! 1818: ! 1819: SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n"); ! 1820: ! 1821: dcbpnt = acbpnt->pLinkDCB; ! 1822: for (dev = 0; dev < acbpnt->DeviceCnt; dev++) ! 1823: { ! 1824: SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); ! 1825: YESNO(dcbpnt->DevMode & PARITY_CHK_); ! 1826: YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE); ! 1827: YESNO(dcbpnt->DevMode & EN_DISCONNECT_); ! 1828: YESNO(dcbpnt->DevMode & SEND_START_); ! 1829: YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING); ! 1830: SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); ! 1831: if (dcbpnt->SyncOffset & 0x0f) ! 1832: { ! 1833: spd = 1000/(dcbpnt->NegoPeriod <<2); ! 1834: spd1 = 1000%(dcbpnt->NegoPeriod <<2); ! 1835: spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2); ! 1836: SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f)); ! 1837: } ! 1838: else SPRINTF("\n"); ! 1839: /* Add more info ...*/ ! 1840: dcbpnt = dcbpnt->pNextDCB; ! 1841: } ! 1842: ! 1843: restore_flags(flags); ! 1844: *start = buffer + offset; ! 1845: ! 1846: if (pos - buffer < offset) ! 1847: return 0; ! 1848: else if (pos - buffer - offset < length) ! 1849: return pos - buffer - offset; ! 1850: else ! 1851: return length; ! 1852: } ! 1853: #endif /* VERSION_ELF_1_2_13 */ ! 1854: ! 1855: ! 1856: #ifdef MODULE ! 1857: ! 1858: /*********************************************************************** ! 1859: * Function : static int DC390_shutdown (struct Scsi_Host *host) ! 1860: * ! 1861: * Purpose : does a clean (we hope) shutdown of the SCSI chip. ! 1862: * Use prior to dumping core, unloading the driver, etc. ! 1863: * ! 1864: * Returns : 0 on success ! 1865: ***********************************************************************/ ! 1866: static int ! 1867: DC390_shutdown (struct Scsi_Host *host) ! 1868: { ! 1869: UCHAR bval; ! 1870: USHORT ioport; ! 1871: unsigned long flags; ! 1872: PACB pACB = (PACB)(host->hostdata); ! 1873: ! 1874: ioport = (unsigned int) pACB->IOPortBase; ! 1875: ! 1876: save_flags (flags); ! 1877: cli(); ! 1878: ! 1879: /* pACB->soft_reset(host); */ ! 1880: ! 1881: #ifdef DC390_DEBUG0 ! 1882: printk("DC390: shutdown,"); ! 1883: #endif ! 1884: ! 1885: bval = inb(ioport+CtrlReg1); ! 1886: bval |= DIS_INT_ON_SCSI_RST; ! 1887: outb(bval,ioport+CtrlReg1); /* disable interrupt */ ! 1888: DC390_ResetSCSIBus( pACB ); ! 1889: ! 1890: restore_flags (flags); ! 1891: return( 0 ); ! 1892: } ! 1893: ! 1894: ! 1895: int DC390_release(struct Scsi_Host *host) ! 1896: { ! 1897: int irq_count; ! 1898: struct Scsi_Host *tmp; ! 1899: ! 1900: DC390_shutdown (host); ! 1901: ! 1902: if (host->irq != IRQ_NONE) ! 1903: { ! 1904: for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) ! 1905: { ! 1906: if ( tmp->irq == host->irq ) ! 1907: ++irq_count; ! 1908: } ! 1909: if (irq_count == 1) ! 1910: { ! 1911: #ifdef DC390_DEBUG0 ! 1912: printk("DC390: Free IRQ %i.",host->irq); ! 1913: #endif ! 1914: #ifndef VERSION_ELF_1_2_13 ! 1915: free_irq(host->irq,NULL); ! 1916: #else ! 1917: free_irq(host->irq); ! 1918: #endif ! 1919: } ! 1920: } ! 1921: ! 1922: release_region(host->io_port,host->n_io_port); ! 1923: ! 1924: return( 1 ); ! 1925: } ! 1926: ! 1927: Scsi_Host_Template driver_template = DC390_T; ! 1928: #include "scsi_module.c" ! 1929: #endif /* def MODULE */ ! 1930:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.