|
|
1.1 ! root 1: /* ! 2: ! 3: Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters ! 4: ! 5: Copyright 1995-1998 by Leonard N. Zubkoff <[email protected]> ! 6: ! 7: This program is free software; you may redistribute and/or modify it under ! 8: the terms of the GNU General Public License Version 2 as published by the ! 9: Free Software Foundation. ! 10: ! 11: This program is distributed in the hope that it will be useful, but ! 12: WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY ! 13: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 14: for complete details. ! 15: ! 16: The author respectfully requests that any modifications to this software be ! 17: sent directly to him for evaluation and testing. ! 18: ! 19: Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose ! 20: advice has been invaluable, to David Gentzel, for writing the original Linux ! 21: BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site. ! 22: ! 23: Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB ! 24: Manager available as freely redistributable source code. ! 25: ! 26: */ ! 27: ! 28: ! 29: #define BusLogic_DriverVersion "2.0.15" ! 30: #define BusLogic_DriverDate "17 August 1998" ! 31: ! 32: ! 33: #include <linux/version.h> ! 34: #include <linux/module.h> ! 35: #include <linux/config.h> ! 36: #include <linux/types.h> ! 37: #include <linux/blkdev.h> ! 38: #include <linux/delay.h> ! 39: #include <linux/ioport.h> ! 40: #include <linux/mm.h> ! 41: #include <linux/sched.h> ! 42: #include <linux/stat.h> ! 43: #include <linux/pci.h> ! 44: #include <linux/bios32.h> ! 45: #include <asm/dma.h> ! 46: #include <asm/io.h> ! 47: #include <asm/irq.h> ! 48: #include <asm/system.h> ! 49: #include "scsi.h" ! 50: #include "hosts.h" ! 51: #include "sd.h" ! 52: #include "BusLogic.h" ! 53: #include "FlashPoint.c" ! 54: ! 55: ! 56: /* ! 57: BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver ! 58: Options specifications provided via the Linux Kernel Command Line or via ! 59: the Loadable Kernel Module Installation Facility. ! 60: */ ! 61: ! 62: static int ! 63: BusLogic_DriverOptionsCount = 0; ! 64: ! 65: ! 66: /* ! 67: BusLogic_DriverOptions is an array of Driver Options structures representing ! 68: BusLogic Driver Options specifications provided via the Linux Kernel Command ! 69: Line or via the Loadable Kernel Module Installation Facility. ! 70: */ ! 71: ! 72: static BusLogic_DriverOptions_T ! 73: BusLogic_DriverOptions[BusLogic_MaxHostAdapters]; ! 74: ! 75: ! 76: /* ! 77: BusLogic_Options can be assigned a string by the Loadable Kernel Module ! 78: Installation Facility to be parsed for BusLogic Driver Options ! 79: specifications. ! 80: */ ! 81: ! 82: static char ! 83: *BusLogic_Options = NULL; ! 84: ! 85: ! 86: /* ! 87: BusLogic_ProbeOptions is a set of Probe Options to be applied across ! 88: all BusLogic Host Adapters. ! 89: */ ! 90: ! 91: static BusLogic_ProbeOptions_T ! 92: BusLogic_ProbeOptions = { 0 }; ! 93: ! 94: ! 95: /* ! 96: BusLogic_GlobalOptions is a set of Global Options to be applied across ! 97: all BusLogic Host Adapters. ! 98: */ ! 99: ! 100: static BusLogic_GlobalOptions_T ! 101: BusLogic_GlobalOptions = { 0 }; ! 102: ! 103: ! 104: /* ! 105: BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter ! 106: are pointers to the first and last registered BusLogic Host Adapters. ! 107: */ ! 108: ! 109: static BusLogic_HostAdapter_T ! 110: *BusLogic_FirstRegisteredHostAdapter = NULL, ! 111: *BusLogic_LastRegisteredHostAdapter = NULL; ! 112: ! 113: ! 114: /* ! 115: BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList. ! 116: */ ! 117: ! 118: static int ! 119: BusLogic_ProbeInfoCount = 0; ! 120: ! 121: ! 122: /* ! 123: BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information ! 124: to be checked for potential BusLogic Host Adapters. It is initialized by ! 125: interrogating the PCI Configuration Space on PCI machines as well as from the ! 126: list of standard BusLogic I/O Addresses. ! 127: */ ! 128: ! 129: static BusLogic_ProbeInfo_T ! 130: *BusLogic_ProbeInfoList = NULL; ! 131: ! 132: ! 133: /* ! 134: BusLogic_CommandFailureReason holds a string identifying the reason why a ! 135: call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command ! 136: returns a failure code. ! 137: */ ! 138: ! 139: static char ! 140: *BusLogic_CommandFailureReason; ! 141: ! 142: ! 143: /* ! 144: BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry. ! 145: */ ! 146: ! 147: PROC_DirectoryEntry_T ! 148: BusLogic_ProcDirectoryEntry = ! 149: { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; ! 150: ! 151: ! 152: /* ! 153: BusLogic_AnnounceDriver announces the Driver Version and Date, Author's ! 154: Name, Copyright Notice, and Electronic Mail Address. ! 155: */ ! 156: ! 157: static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter) ! 158: { ! 159: BusLogic_Announce("***** BusLogic SCSI Driver Version " ! 160: BusLogic_DriverVersion " of " ! 161: BusLogic_DriverDate " *****\n", HostAdapter); ! 162: BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " ! 163: "<[email protected]>\n", HostAdapter); ! 164: } ! 165: ! 166: ! 167: /* ! 168: BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI ! 169: Driver and Host Adapter. ! 170: */ ! 171: ! 172: const char *BusLogic_DriverInfo(SCSI_Host_T *Host) ! 173: { ! 174: BusLogic_HostAdapter_T *HostAdapter = ! 175: (BusLogic_HostAdapter_T *) Host->hostdata; ! 176: return HostAdapter->FullModelName; ! 177: } ! 178: ! 179: ! 180: /* ! 181: BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered ! 182: BusLogic Host Adapters. ! 183: */ ! 184: ! 185: static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 186: { ! 187: HostAdapter->Next = NULL; ! 188: if (BusLogic_FirstRegisteredHostAdapter == NULL) ! 189: { ! 190: BusLogic_FirstRegisteredHostAdapter = HostAdapter; ! 191: BusLogic_LastRegisteredHostAdapter = HostAdapter; ! 192: } ! 193: else ! 194: { ! 195: BusLogic_LastRegisteredHostAdapter->Next = HostAdapter; ! 196: BusLogic_LastRegisteredHostAdapter = HostAdapter; ! 197: } ! 198: } ! 199: ! 200: ! 201: /* ! 202: BusLogic_UnregisterHostAdapter removes Host Adapter from the list of ! 203: registered BusLogic Host Adapters. ! 204: */ ! 205: ! 206: static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 207: { ! 208: if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) ! 209: { ! 210: BusLogic_FirstRegisteredHostAdapter = ! 211: BusLogic_FirstRegisteredHostAdapter->Next; ! 212: if (HostAdapter == BusLogic_LastRegisteredHostAdapter) ! 213: BusLogic_LastRegisteredHostAdapter = NULL; ! 214: } ! 215: else ! 216: { ! 217: BusLogic_HostAdapter_T *PreviousHostAdapter = ! 218: BusLogic_FirstRegisteredHostAdapter; ! 219: while (PreviousHostAdapter != NULL && ! 220: PreviousHostAdapter->Next != HostAdapter) ! 221: PreviousHostAdapter = PreviousHostAdapter->Next; ! 222: if (PreviousHostAdapter != NULL) ! 223: PreviousHostAdapter->Next = HostAdapter->Next; ! 224: } ! 225: HostAdapter->Next = NULL; ! 226: } ! 227: ! 228: ! 229: /* ! 230: BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs) ! 231: for Host Adapter from the BlockSize bytes located at BlockPointer. The newly ! 232: created CCBs are added to Host Adapter's free list. ! 233: */ ! 234: ! 235: static void BusLogic_InitializeCCBs(BusLogic_HostAdapter_T *HostAdapter, ! 236: void *BlockPointer, int BlockSize) ! 237: { ! 238: BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) BlockPointer; ! 239: memset(BlockPointer, 0, BlockSize); ! 240: CCB->AllocationGroupHead = true; ! 241: while ((BlockSize -= sizeof(BusLogic_CCB_T)) >= 0) ! 242: { ! 243: CCB->Status = BusLogic_CCB_Free; ! 244: CCB->HostAdapter = HostAdapter; ! 245: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 246: { ! 247: CCB->CallbackFunction = BusLogic_QueueCompletedCCB; ! 248: CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress; ! 249: } ! 250: CCB->Next = HostAdapter->Free_CCBs; ! 251: CCB->NextAll = HostAdapter->All_CCBs; ! 252: HostAdapter->Free_CCBs = CCB; ! 253: HostAdapter->All_CCBs = CCB; ! 254: HostAdapter->AllocatedCCBs++; ! 255: CCB++; ! 256: } ! 257: } ! 258: ! 259: ! 260: /* ! 261: BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter. ! 262: */ ! 263: ! 264: static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter) ! 265: { ! 266: int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T); ! 267: while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) ! 268: { ! 269: void *BlockPointer = kmalloc(BlockSize, ! 270: (HostAdapter->BounceBuffersRequired ! 271: ? GFP_ATOMIC | GFP_DMA ! 272: : GFP_ATOMIC)); ! 273: if (BlockPointer == NULL) ! 274: { ! 275: BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", ! 276: HostAdapter); ! 277: return false; ! 278: } ! 279: BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize); ! 280: } ! 281: return true; ! 282: } ! 283: ! 284: ! 285: /* ! 286: BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter. ! 287: */ ! 288: ! 289: static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter) ! 290: { ! 291: BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB; ! 292: HostAdapter->All_CCBs = NULL; ! 293: HostAdapter->Free_CCBs = NULL; ! 294: while ((CCB = NextCCB) != NULL) ! 295: { ! 296: NextCCB = CCB->NextAll; ! 297: if (CCB->AllocationGroupHead) ! 298: kfree(CCB); ! 299: } ! 300: } ! 301: ! 302: ! 303: /* ! 304: BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If ! 305: allocation fails and there are no remaining CCBs available, the Driver Queue ! 306: Depth is decreased to a known safe value to avoid potential deadlocks when ! 307: multiple host adapters share the same IRQ Channel. ! 308: */ ! 309: ! 310: static void BusLogic_CreateAdditionalCCBs(BusLogic_HostAdapter_T *HostAdapter, ! 311: int AdditionalCCBs, ! 312: boolean SuccessMessageP) ! 313: { ! 314: int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T); ! 315: int PreviouslyAllocated = HostAdapter->AllocatedCCBs; ! 316: if (AdditionalCCBs <= 0) return; ! 317: while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) ! 318: { ! 319: void *BlockPointer = kmalloc(BlockSize, ! 320: (HostAdapter->BounceBuffersRequired ! 321: ? GFP_ATOMIC | GFP_DMA ! 322: : GFP_ATOMIC)); ! 323: if (BlockPointer == NULL) break; ! 324: BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize); ! 325: } ! 326: if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) ! 327: { ! 328: if (SuccessMessageP) ! 329: BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", ! 330: HostAdapter, ! 331: HostAdapter->AllocatedCCBs - PreviouslyAllocated, ! 332: HostAdapter->AllocatedCCBs); ! 333: return; ! 334: } ! 335: BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter); ! 336: if (HostAdapter->DriverQueueDepth > ! 337: HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) ! 338: { ! 339: HostAdapter->DriverQueueDepth = ! 340: HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount; ! 341: HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth; ! 342: } ! 343: } ! 344: ! 345: ! 346: /* ! 347: BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list, ! 348: allocating more memory from the Kernel if necessary. The Host Adapter's ! 349: Lock should already have been acquired by the caller. ! 350: */ ! 351: ! 352: static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T ! 353: *HostAdapter) ! 354: { ! 355: static unsigned long SerialNumber = 0; ! 356: BusLogic_CCB_T *CCB; ! 357: CCB = HostAdapter->Free_CCBs; ! 358: if (CCB != NULL) ! 359: { ! 360: CCB->SerialNumber = ++SerialNumber; ! 361: HostAdapter->Free_CCBs = CCB->Next; ! 362: CCB->Next = NULL; ! 363: if (HostAdapter->Free_CCBs == NULL) ! 364: BusLogic_CreateAdditionalCCBs(HostAdapter, ! 365: HostAdapter->IncrementalCCBs, ! 366: true); ! 367: return CCB; ! 368: } ! 369: BusLogic_CreateAdditionalCCBs(HostAdapter, ! 370: HostAdapter->IncrementalCCBs, ! 371: true); ! 372: CCB = HostAdapter->Free_CCBs; ! 373: if (CCB == NULL) return NULL; ! 374: CCB->SerialNumber = ++SerialNumber; ! 375: HostAdapter->Free_CCBs = CCB->Next; ! 376: CCB->Next = NULL; ! 377: return CCB; ! 378: } ! 379: ! 380: ! 381: /* ! 382: BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's ! 383: free list. The Host Adapter's Lock should already have been acquired by the ! 384: caller. ! 385: */ ! 386: ! 387: static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB) ! 388: { ! 389: BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; ! 390: CCB->Command = NULL; ! 391: CCB->Status = BusLogic_CCB_Free; ! 392: CCB->Next = HostAdapter->Free_CCBs; ! 393: HostAdapter->Free_CCBs = CCB; ! 394: } ! 395: ! 396: ! 397: /* ! 398: BusLogic_Command sends the command OperationCode to HostAdapter, optionally ! 399: providing ParameterLength bytes of ParameterData and receiving at most ! 400: ReplyLength bytes of ReplyData; any excess reply data is received but ! 401: discarded. ! 402: ! 403: On success, this function returns the number of reply bytes read from ! 404: the Host Adapter (including any discarded data); on failure, it returns ! 405: -1 if the command was invalid, or -2 if a timeout occurred. ! 406: ! 407: BusLogic_Command is called exclusively during host adapter detection and ! 408: initialization, so performance and latency are not critical, and exclusive ! 409: access to the Host Adapter hardware is assumed. Once the host adapter and ! 410: driver are initialized, the only Host Adapter command that is issued is the ! 411: single byte Execute Mailbox Command operation code, which does not require ! 412: waiting for the Host Adapter Ready bit to be set in the Status Register. ! 413: */ ! 414: ! 415: static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, ! 416: BusLogic_OperationCode_T OperationCode, ! 417: void *ParameterData, ! 418: int ParameterLength, ! 419: void *ReplyData, ! 420: int ReplyLength) ! 421: { ! 422: unsigned char *ParameterPointer = (unsigned char *) ParameterData; ! 423: unsigned char *ReplyPointer = (unsigned char *) ReplyData; ! 424: BusLogic_StatusRegister_T StatusRegister; ! 425: BusLogic_InterruptRegister_T InterruptRegister; ! 426: ProcessorFlags_T ProcessorFlags = 0; ! 427: int ReplyBytes = 0, Result; ! 428: long TimeoutCounter; ! 429: /* ! 430: Clear out the Reply Data if provided. ! 431: */ ! 432: if (ReplyLength > 0) ! 433: memset(ReplyData, 0, ReplyLength); ! 434: /* ! 435: If the IRQ Channel has not yet been acquired, then interrupts must be ! 436: disabled while issuing host adapter commands since a Command Complete ! 437: interrupt could occur if the IRQ Channel was previously enabled by another ! 438: BusLogic Host Adapter or another driver sharing the same IRQ Channel. ! 439: */ ! 440: if (!HostAdapter->IRQ_ChannelAcquired) ! 441: { ! 442: save_flags(ProcessorFlags); ! 443: cli(); ! 444: } ! 445: /* ! 446: Wait for the Host Adapter Ready bit to be set and the Command/Parameter ! 447: Register Busy bit to be reset in the Status Register. ! 448: */ ! 449: TimeoutCounter = 10000; ! 450: while (--TimeoutCounter >= 0) ! 451: { ! 452: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 453: if (StatusRegister.Bits.HostAdapterReady && ! 454: !StatusRegister.Bits.CommandParameterRegisterBusy) ! 455: break; ! 456: udelay(100); ! 457: } ! 458: if (TimeoutCounter < 0) ! 459: { ! 460: BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; ! 461: Result = -2; ! 462: goto Done; ! 463: } ! 464: /* ! 465: Write the OperationCode to the Command/Parameter Register. ! 466: */ ! 467: HostAdapter->HostAdapterCommandCompleted = false; ! 468: BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); ! 469: /* ! 470: Write any additional Parameter Bytes. ! 471: */ ! 472: TimeoutCounter = 10000; ! 473: while (ParameterLength > 0 && --TimeoutCounter >= 0) ! 474: { ! 475: /* ! 476: Wait 100 microseconds to give the Host Adapter enough time to determine ! 477: whether the last value written to the Command/Parameter Register was ! 478: valid or not. If the Command Complete bit is set in the Interrupt ! 479: Register, then the Command Invalid bit in the Status Register will be ! 480: reset if the Operation Code or Parameter was valid and the command ! 481: has completed, or set if the Operation Code or Parameter was invalid. ! 482: If the Data In Register Ready bit is set in the Status Register, then ! 483: the Operation Code was valid, and data is waiting to be read back ! 484: from the Host Adapter. Otherwise, wait for the Command/Parameter ! 485: Register Busy bit in the Status Register to be reset. ! 486: */ ! 487: udelay(100); ! 488: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); ! 489: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 490: if (InterruptRegister.Bits.CommandComplete) break; ! 491: if (HostAdapter->HostAdapterCommandCompleted) break; ! 492: if (StatusRegister.Bits.DataInRegisterReady) break; ! 493: if (StatusRegister.Bits.CommandParameterRegisterBusy) continue; ! 494: BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); ! 495: ParameterLength--; ! 496: } ! 497: if (TimeoutCounter < 0) ! 498: { ! 499: BusLogic_CommandFailureReason = ! 500: "Timeout waiting for Parameter Acceptance"; ! 501: Result = -2; ! 502: goto Done; ! 503: } ! 504: /* ! 505: The Modify I/O Address command does not cause a Command Complete Interrupt. ! 506: */ ! 507: if (OperationCode == BusLogic_ModifyIOAddress) ! 508: { ! 509: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 510: if (StatusRegister.Bits.CommandInvalid) ! 511: { ! 512: BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; ! 513: Result = -1; ! 514: goto Done; ! 515: } ! 516: if (BusLogic_GlobalOptions.TraceConfiguration) ! 517: BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " ! 518: "(Modify I/O Address)\n", HostAdapter, ! 519: OperationCode, StatusRegister.All); ! 520: Result = 0; ! 521: goto Done; ! 522: } ! 523: /* ! 524: Select an appropriate timeout value for awaiting command completion. ! 525: */ ! 526: switch (OperationCode) ! 527: { ! 528: case BusLogic_InquireInstalledDevicesID0to7: ! 529: case BusLogic_InquireInstalledDevicesID8to15: ! 530: case BusLogic_InquireTargetDevices: ! 531: /* Approximately 60 seconds. */ ! 532: TimeoutCounter = 60*10000; ! 533: break; ! 534: default: ! 535: /* Approximately 1 second. */ ! 536: TimeoutCounter = 10000; ! 537: break; ! 538: } ! 539: /* ! 540: Receive any Reply Bytes, waiting for either the Command Complete bit to ! 541: be set in the Interrupt Register, or for the Interrupt Handler to set the ! 542: Host Adapter Command Completed bit in the Host Adapter structure. ! 543: */ ! 544: while (--TimeoutCounter >= 0) ! 545: { ! 546: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); ! 547: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 548: if (InterruptRegister.Bits.CommandComplete) break; ! 549: if (HostAdapter->HostAdapterCommandCompleted) break; ! 550: if (StatusRegister.Bits.DataInRegisterReady) ! 551: { ! 552: if (++ReplyBytes <= ReplyLength) ! 553: *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); ! 554: else BusLogic_ReadDataInRegister(HostAdapter); ! 555: } ! 556: if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && ! 557: StatusRegister.Bits.HostAdapterReady) break; ! 558: udelay(100); ! 559: } ! 560: if (TimeoutCounter < 0) ! 561: { ! 562: BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; ! 563: Result = -2; ! 564: goto Done; ! 565: } ! 566: /* ! 567: Clear any pending Command Complete Interrupt. ! 568: */ ! 569: BusLogic_InterruptReset(HostAdapter); ! 570: /* ! 571: Provide tracing information if requested. ! 572: */ ! 573: if (BusLogic_GlobalOptions.TraceConfiguration) ! 574: { ! 575: int i; ! 576: BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", ! 577: HostAdapter, OperationCode, ! 578: StatusRegister.All, ReplyLength, ReplyBytes); ! 579: if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; ! 580: for (i = 0; i < ReplyLength; i++) ! 581: BusLogic_Notice(" %02X", HostAdapter, ! 582: ((unsigned char *) ReplyData)[i]); ! 583: BusLogic_Notice("\n", HostAdapter); ! 584: } ! 585: /* ! 586: Process Command Invalid conditions. ! 587: */ ! 588: if (StatusRegister.Bits.CommandInvalid) ! 589: { ! 590: /* ! 591: Some early BusLogic Host Adapters may not recover properly from ! 592: a Command Invalid condition, so if this appears to be the case, ! 593: a Soft Reset is issued to the Host Adapter. Potentially invalid ! 594: commands are never attempted after Mailbox Initialization is ! 595: performed, so there should be no Host Adapter state lost by a ! 596: Soft Reset in response to a Command Invalid condition. ! 597: */ ! 598: udelay(1000); ! 599: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 600: if (StatusRegister.Bits.CommandInvalid || ! 601: StatusRegister.Bits.Reserved || ! 602: StatusRegister.Bits.DataInRegisterReady || ! 603: StatusRegister.Bits.CommandParameterRegisterBusy || ! 604: !StatusRegister.Bits.HostAdapterReady || ! 605: !StatusRegister.Bits.InitializationRequired || ! 606: StatusRegister.Bits.DiagnosticActive || ! 607: StatusRegister.Bits.DiagnosticFailure) ! 608: { ! 609: BusLogic_SoftReset(HostAdapter); ! 610: udelay(1000); ! 611: } ! 612: BusLogic_CommandFailureReason = "Command Invalid"; ! 613: Result = -1; ! 614: goto Done; ! 615: } ! 616: /* ! 617: Handle Excess Parameters Supplied conditions. ! 618: */ ! 619: if (ParameterLength > 0) ! 620: { ! 621: BusLogic_CommandFailureReason = "Excess Parameters Supplied"; ! 622: Result = -1; ! 623: goto Done; ! 624: } ! 625: /* ! 626: Indicate the command completed successfully. ! 627: */ ! 628: BusLogic_CommandFailureReason = NULL; ! 629: Result = ReplyBytes; ! 630: /* ! 631: Restore the interrupt status if necessary and return. ! 632: */ ! 633: Done: ! 634: if (!HostAdapter->IRQ_ChannelAcquired) ! 635: restore_flags(ProcessorFlags); ! 636: return Result; ! 637: } ! 638: ! 639: ! 640: /* ! 641: BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list ! 642: of I/O Address and Bus Probe Information to be checked for potential BusLogic ! 643: Host Adapters. ! 644: */ ! 645: ! 646: static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address) ! 647: { ! 648: BusLogic_ProbeInfo_T *ProbeInfo; ! 649: if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return; ! 650: ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; ! 651: ProbeInfo->HostAdapterType = BusLogic_MultiMaster; ! 652: ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; ! 653: ProbeInfo->IO_Address = IO_Address; ! 654: } ! 655: ! 656: ! 657: /* ! 658: BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and ! 659: Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters ! 660: only from the list of standard BusLogic MultiMaster ISA I/O Addresses. ! 661: */ ! 662: ! 663: static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T ! 664: *PrototypeHostAdapter) ! 665: { ! 666: /* ! 667: If BusLogic Driver Options specifications requested that ISA Bus Probes ! 668: be inhibited, do not proceed further. ! 669: */ ! 670: if (BusLogic_ProbeOptions.NoProbeISA) return; ! 671: /* ! 672: Append the list of standard BusLogic MultiMaster ISA I/O Addresses. ! 673: */ ! 674: if (BusLogic_ProbeOptions.LimitedProbeISA ! 675: ? BusLogic_ProbeOptions.Probe330 ! 676: : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) ! 677: BusLogic_AppendProbeAddressISA(0x330); ! 678: if (BusLogic_ProbeOptions.LimitedProbeISA ! 679: ? BusLogic_ProbeOptions.Probe334 ! 680: : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) ! 681: BusLogic_AppendProbeAddressISA(0x334); ! 682: if (BusLogic_ProbeOptions.LimitedProbeISA ! 683: ? BusLogic_ProbeOptions.Probe230 ! 684: : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) ! 685: BusLogic_AppendProbeAddressISA(0x230); ! 686: if (BusLogic_ProbeOptions.LimitedProbeISA ! 687: ? BusLogic_ProbeOptions.Probe234 ! 688: : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) ! 689: BusLogic_AppendProbeAddressISA(0x234); ! 690: if (BusLogic_ProbeOptions.LimitedProbeISA ! 691: ? BusLogic_ProbeOptions.Probe130 ! 692: : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) ! 693: BusLogic_AppendProbeAddressISA(0x130); ! 694: if (BusLogic_ProbeOptions.LimitedProbeISA ! 695: ? BusLogic_ProbeOptions.Probe134 ! 696: : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) ! 697: BusLogic_AppendProbeAddressISA(0x134); ! 698: } ! 699: ! 700: ! 701: #ifdef CONFIG_PCI ! 702: ! 703: ! 704: /* ! 705: BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order ! 706: of increasing PCI Bus and Device Number. ! 707: */ ! 708: ! 709: static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList, ! 710: int ProbeInfoCount) ! 711: { ! 712: int LastInterchange = ProbeInfoCount-1, Bound, j; ! 713: while (LastInterchange > 0) ! 714: { ! 715: Bound = LastInterchange; ! 716: LastInterchange = 0; ! 717: for (j = 0; j < Bound; j++) ! 718: { ! 719: BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j]; ! 720: BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1]; ! 721: if (ProbeInfo1->Bus > ProbeInfo2->Bus || ! 722: (ProbeInfo1->Bus == ProbeInfo2->Bus && ! 723: (ProbeInfo1->Device > ProbeInfo2->Device))) ! 724: { ! 725: BusLogic_ProbeInfo_T TempProbeInfo; ! 726: memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T)); ! 727: memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T)); ! 728: memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T)); ! 729: LastInterchange = j; ! 730: } ! 731: } ! 732: } ! 733: } ! 734: ! 735: ! 736: /* ! 737: BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address ! 738: and Bus Probe Information to be checked for potential BusLogic MultiMaster ! 739: SCSI Host Adapters by interrogating the PCI Configuration Space on PCI ! 740: machines as well as from the list of standard BusLogic MultiMaster ISA ! 741: I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found. ! 742: */ ! 743: ! 744: static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T ! 745: *PrototypeHostAdapter) ! 746: { ! 747: BusLogic_ProbeInfo_T *PrimaryProbeInfo = ! 748: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; ! 749: int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; ! 750: int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; ! 751: boolean ForceBusDeviceScanningOrder = false; ! 752: boolean ForceBusDeviceScanningOrderChecked = false; ! 753: boolean StandardAddressSeen[6]; ! 754: unsigned char Bus, DeviceFunction; ! 755: unsigned int BaseAddress0, BaseAddress1; ! 756: unsigned char IRQ_Channel; ! 757: BusLogic_IO_Address_T IO_Address; ! 758: BusLogic_PCI_Address_T PCI_Address; ! 759: unsigned short Index = 0; ! 760: int i; ! 761: if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0; ! 762: BusLogic_ProbeInfoCount++; ! 763: for (i = 0; i < 6; i++) ! 764: StandardAddressSeen[i] = false; ! 765: /* ! 766: Iterate over the MultiMaster PCI Host Adapters. For each enumerated host ! 767: adapter, determine whether its ISA Compatible I/O Port is enabled and if ! 768: so, whether it is assigned the Primary I/O Address. A host adapter that is ! 769: assigned the Primary I/O Address will always be the preferred boot device. ! 770: The MultiMaster BIOS will first recognize a host adapter at the Primary I/O ! 771: Address, then any other PCI host adapters, and finally any host adapters ! 772: located at the remaining standard ISA I/O Addresses. When a PCI host ! 773: adapter is found with its ISA Compatible I/O Port enabled, a command is ! 774: issued to disable the ISA Compatible I/O Port, and it is noted that the ! 775: particular standard ISA I/O Address need not be probed. ! 776: */ ! 777: PrimaryProbeInfo->IO_Address = 0; ! 778: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC, ! 779: PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, ! 780: Index++, &Bus, &DeviceFunction) == 0) ! 781: if (pcibios_read_config_dword(Bus, DeviceFunction, ! 782: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && ! 783: pcibios_read_config_dword(Bus, DeviceFunction, ! 784: PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 && ! 785: pcibios_read_config_byte(Bus, DeviceFunction, ! 786: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0) ! 787: { ! 788: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; ! 789: BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; ! 790: BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; ! 791: unsigned char Device = DeviceFunction >> 3; ! 792: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; ! 793: PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK; ! 794: if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE) ! 795: != PCI_BASE_ADDRESS_SPACE_IO) ! 796: { ! 797: BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " ! 798: "MultiMaster Host Adapter\n", NULL, BaseAddress0); ! 799: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", ! 800: NULL, Bus, Device, IO_Address); ! 801: continue; ! 802: } ! 803: if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE) ! 804: != PCI_BASE_ADDRESS_SPACE_MEMORY) ! 805: { ! 806: BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " ! 807: "MultiMaster Host Adapter\n", NULL, BaseAddress1); ! 808: BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", ! 809: NULL, Bus, Device, PCI_Address); ! 810: continue; ! 811: } ! 812: if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS) ! 813: { ! 814: BusLogic_Error("BusLogic: IRQ Channel %d illegal for " ! 815: "MultiMaster Host Adapter\n", NULL, IRQ_Channel); ! 816: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", ! 817: NULL, Bus, Device, IO_Address); ! 818: continue; ! 819: } ! 820: if (BusLogic_GlobalOptions.TraceProbe) ! 821: { ! 822: BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " ! 823: "detected at\n", NULL); ! 824: BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " ! 825: "0x%X PCI Address 0x%X\n", NULL, ! 826: Bus, Device, IO_Address, PCI_Address); ! 827: } ! 828: /* ! 829: Issue the Inquire PCI Host Adapter Information command to determine ! 830: the ISA Compatible I/O Port. If the ISA Compatible I/O Port is ! 831: known and enabled, note that the particular Standard ISA I/O ! 832: Address should not be probed. ! 833: */ ! 834: HostAdapter->IO_Address = IO_Address; ! 835: BusLogic_InterruptReset(HostAdapter); ! 836: if (BusLogic_Command(HostAdapter, ! 837: BusLogic_InquirePCIHostAdapterInformation, ! 838: NULL, 0, &PCIHostAdapterInformation, ! 839: sizeof(PCIHostAdapterInformation)) ! 840: == sizeof(PCIHostAdapterInformation)) ! 841: { ! 842: if (PCIHostAdapterInformation.ISACompatibleIOPort < 6) ! 843: StandardAddressSeen[PCIHostAdapterInformation ! 844: .ISACompatibleIOPort] = true; ! 845: } ! 846: else PCIHostAdapterInformation.ISACompatibleIOPort = ! 847: BusLogic_IO_Disable; ! 848: /* ! 849: Issue the Modify I/O Address command to disable the ISA Compatible ! 850: I/O Port. ! 851: */ ! 852: ModifyIOAddressRequest = BusLogic_IO_Disable; ! 853: BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, ! 854: &ModifyIOAddressRequest, ! 855: sizeof(ModifyIOAddressRequest), NULL, 0); ! 856: /* ! 857: For the first MultiMaster Host Adapter enumerated, issue the Fetch ! 858: Host Adapter Local RAM command to read byte 45 of the AutoSCSI area, ! 859: for the setting of the "Use Bus And Device # For PCI Scanning Seq." ! 860: option. Issue the Inquire Board ID command since this option is ! 861: only valid for the BT-948/958/958D. ! 862: */ ! 863: if (!ForceBusDeviceScanningOrderChecked) ! 864: { ! 865: BusLogic_FetchHostAdapterLocalRAMRequest_T ! 866: FetchHostAdapterLocalRAMRequest; ! 867: BusLogic_AutoSCSIByte45_T AutoSCSIByte45; ! 868: BusLogic_BoardID_T BoardID; ! 869: FetchHostAdapterLocalRAMRequest.ByteOffset = ! 870: BusLogic_AutoSCSI_BaseOffset + 45; ! 871: FetchHostAdapterLocalRAMRequest.ByteCount = ! 872: sizeof(AutoSCSIByte45); ! 873: BusLogic_Command(HostAdapter, ! 874: BusLogic_FetchHostAdapterLocalRAM, ! 875: &FetchHostAdapterLocalRAMRequest, ! 876: sizeof(FetchHostAdapterLocalRAMRequest), ! 877: &AutoSCSIByte45, sizeof(AutoSCSIByte45)); ! 878: BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, ! 879: NULL, 0, &BoardID, sizeof(BoardID)); ! 880: if (BoardID.FirmwareVersion1stDigit == '5') ! 881: ForceBusDeviceScanningOrder = ! 882: AutoSCSIByte45.ForceBusDeviceScanningOrder; ! 883: ForceBusDeviceScanningOrderChecked = true; ! 884: } ! 885: /* ! 886: Determine whether this MultiMaster Host Adapter has its ISA ! 887: Compatible I/O Port enabled and is assigned the Primary I/O Address. ! 888: If it does, then it is the Primary MultiMaster Host Adapter and must ! 889: be recognized first. If it does not, then it is added to the list ! 890: for probing after any Primary MultiMaster Host Adapter is probed. ! 891: */ ! 892: if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) ! 893: { ! 894: PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; ! 895: PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; ! 896: PrimaryProbeInfo->IO_Address = IO_Address; ! 897: PrimaryProbeInfo->PCI_Address = PCI_Address; ! 898: PrimaryProbeInfo->Bus = Bus; ! 899: PrimaryProbeInfo->Device = Device; ! 900: PrimaryProbeInfo->IRQ_Channel = IRQ_Channel; ! 901: PCIMultiMasterCount++; ! 902: } ! 903: else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) ! 904: { ! 905: BusLogic_ProbeInfo_T *ProbeInfo = ! 906: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; ! 907: ProbeInfo->HostAdapterType = BusLogic_MultiMaster; ! 908: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; ! 909: ProbeInfo->IO_Address = IO_Address; ! 910: ProbeInfo->PCI_Address = PCI_Address; ! 911: ProbeInfo->Bus = Bus; ! 912: ProbeInfo->Device = Device; ! 913: ProbeInfo->IRQ_Channel = IRQ_Channel; ! 914: NonPrimaryPCIMultiMasterCount++; ! 915: PCIMultiMasterCount++; ! 916: } ! 917: else BusLogic_Warning("BusLogic: Too many Host Adapters " ! 918: "detected\n", NULL); ! 919: } ! 920: /* ! 921: If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON ! 922: for the first enumerated MultiMaster Host Adapter, and if that host adapter ! 923: is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster ! 924: Host Adapters in the order of increasing PCI Bus and Device Number. In ! 925: that case, sort the probe information into the same order the BIOS uses. ! 926: If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster ! 927: Host Adapters in the order they are enumerated by the PCI BIOS, and hence ! 928: no sorting is necessary. ! 929: */ ! 930: if (ForceBusDeviceScanningOrder) ! 931: BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[ ! 932: NonPrimaryPCIMultiMasterIndex], ! 933: NonPrimaryPCIMultiMasterCount); ! 934: /* ! 935: If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address, ! 936: then the Primary I/O Address must be probed explicitly before any PCI ! 937: host adapters are probed. ! 938: */ ! 939: if (!BusLogic_ProbeOptions.NoProbeISA) ! 940: if (PrimaryProbeInfo->IO_Address == 0 && ! 941: (BusLogic_ProbeOptions.LimitedProbeISA ! 942: ? BusLogic_ProbeOptions.Probe330 ! 943: : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) ! 944: { ! 945: PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; ! 946: PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; ! 947: PrimaryProbeInfo->IO_Address = 0x330; ! 948: } ! 949: /* ! 950: Append the list of standard BusLogic MultiMaster ISA I/O Addresses, ! 951: omitting the Primary I/O Address which has already been handled. ! 952: */ ! 953: if (!BusLogic_ProbeOptions.NoProbeISA) ! 954: { ! 955: if (!StandardAddressSeen[1] && ! 956: (BusLogic_ProbeOptions.LimitedProbeISA ! 957: ? BusLogic_ProbeOptions.Probe334 ! 958: : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)) ! 959: BusLogic_AppendProbeAddressISA(0x334); ! 960: if (!StandardAddressSeen[2] && ! 961: (BusLogic_ProbeOptions.LimitedProbeISA ! 962: ? BusLogic_ProbeOptions.Probe230 ! 963: : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)) ! 964: BusLogic_AppendProbeAddressISA(0x230); ! 965: if (!StandardAddressSeen[3] && ! 966: (BusLogic_ProbeOptions.LimitedProbeISA ! 967: ? BusLogic_ProbeOptions.Probe234 ! 968: : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)) ! 969: BusLogic_AppendProbeAddressISA(0x234); ! 970: if (!StandardAddressSeen[4] && ! 971: (BusLogic_ProbeOptions.LimitedProbeISA ! 972: ? BusLogic_ProbeOptions.Probe130 ! 973: : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)) ! 974: BusLogic_AppendProbeAddressISA(0x130); ! 975: if (!StandardAddressSeen[5] && ! 976: (BusLogic_ProbeOptions.LimitedProbeISA ! 977: ? BusLogic_ProbeOptions.Probe134 ! 978: : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)) ! 979: BusLogic_AppendProbeAddressISA(0x134); ! 980: } ! 981: /* ! 982: Iterate over the older non-compliant MultiMaster PCI Host Adapters, ! 983: noting the PCI bus location and assigned IRQ Channel. ! 984: */ ! 985: Index = 0; ! 986: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC, ! 987: PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, ! 988: Index++, &Bus, &DeviceFunction) == 0) ! 989: if (pcibios_read_config_dword(Bus, DeviceFunction, ! 990: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && ! 991: pcibios_read_config_byte(Bus, DeviceFunction, ! 992: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0) ! 993: { ! 994: unsigned char Device = DeviceFunction >> 3; ! 995: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; ! 996: if (IO_Address == 0 || IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS) ! 997: continue; ! 998: for (i = 0; i < BusLogic_ProbeInfoCount; i++) ! 999: { ! 1000: BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[i]; ! 1001: if (ProbeInfo->IO_Address == IO_Address && ! 1002: ProbeInfo->HostAdapterType == BusLogic_MultiMaster) ! 1003: { ! 1004: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; ! 1005: ProbeInfo->PCI_Address = 0; ! 1006: ProbeInfo->Bus = Bus; ! 1007: ProbeInfo->Device = Device; ! 1008: ProbeInfo->IRQ_Channel = IRQ_Channel; ! 1009: break; ! 1010: } ! 1011: } ! 1012: } ! 1013: return PCIMultiMasterCount; ! 1014: } ! 1015: ! 1016: ! 1017: /* ! 1018: BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address ! 1019: and Bus Probe Information to be checked for potential BusLogic FlashPoint ! 1020: Host Adapters by interrogating the PCI Configuration Space. It returns the ! 1021: number of FlashPoint Host Adapters found. ! 1022: */ ! 1023: ! 1024: static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T ! 1025: *PrototypeHostAdapter) ! 1026: { ! 1027: int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0; ! 1028: unsigned char Bus, DeviceFunction; ! 1029: unsigned int BaseAddress0, BaseAddress1; ! 1030: unsigned char IRQ_Channel; ! 1031: BusLogic_IO_Address_T IO_Address; ! 1032: BusLogic_PCI_Address_T PCI_Address; ! 1033: unsigned short Index = 0; ! 1034: /* ! 1035: Interrogate PCI Configuration Space for any FlashPoint Host Adapters. ! 1036: */ ! 1037: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC, ! 1038: PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, ! 1039: Index++, &Bus, &DeviceFunction) == 0) ! 1040: if (pcibios_read_config_dword(Bus, DeviceFunction, ! 1041: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && ! 1042: pcibios_read_config_dword(Bus, DeviceFunction, ! 1043: PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 && ! 1044: pcibios_read_config_byte(Bus, DeviceFunction, ! 1045: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0) ! 1046: { ! 1047: unsigned char Device = DeviceFunction >> 3; ! 1048: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; ! 1049: PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK; ! 1050: #ifndef CONFIG_SCSI_OMIT_FLASHPOINT ! 1051: if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE) ! 1052: != PCI_BASE_ADDRESS_SPACE_IO) ! 1053: { ! 1054: BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " ! 1055: "FlashPoint Host Adapter\n", NULL, BaseAddress0); ! 1056: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", ! 1057: NULL, Bus, Device, IO_Address); ! 1058: continue; ! 1059: } ! 1060: if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE) ! 1061: != PCI_BASE_ADDRESS_SPACE_MEMORY) ! 1062: { ! 1063: BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " ! 1064: "FlashPoint Host Adapter\n", NULL, BaseAddress1); ! 1065: BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", ! 1066: NULL, Bus, Device, PCI_Address); ! 1067: continue; ! 1068: } ! 1069: if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS) ! 1070: { ! 1071: BusLogic_Error("BusLogic: IRQ Channel %d illegal for " ! 1072: "FlashPoint Host Adapter\n", NULL, IRQ_Channel); ! 1073: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", ! 1074: NULL, Bus, Device, IO_Address); ! 1075: continue; ! 1076: } ! 1077: if (BusLogic_GlobalOptions.TraceProbe) ! 1078: { ! 1079: BusLogic_Notice("BusLogic: FlashPoint Host Adapter " ! 1080: "detected at\n", NULL); ! 1081: BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " ! 1082: "0x%X PCI Address 0x%X\n", NULL, ! 1083: Bus, Device, IO_Address, PCI_Address); ! 1084: } ! 1085: if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) ! 1086: { ! 1087: BusLogic_ProbeInfo_T *ProbeInfo = ! 1088: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; ! 1089: ProbeInfo->HostAdapterType = BusLogic_FlashPoint; ! 1090: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; ! 1091: ProbeInfo->IO_Address = IO_Address; ! 1092: ProbeInfo->PCI_Address = PCI_Address; ! 1093: ProbeInfo->Bus = Bus; ! 1094: ProbeInfo->Device = Device; ! 1095: ProbeInfo->IRQ_Channel = IRQ_Channel; ! 1096: FlashPointCount++; ! 1097: } ! 1098: else BusLogic_Warning("BusLogic: Too many Host Adapters " ! 1099: "detected\n", NULL); ! 1100: #else ! 1101: BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " ! 1102: "PCI Bus %d Device %d\n", NULL, Bus, Device); ! 1103: BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " ! 1104: "but FlashPoint\n", NULL, IO_Address, PCI_Address); ! 1105: BusLogic_Error("BusLogic: support was omitted in this kernel " ! 1106: "configuration.\n", NULL); ! 1107: #endif ! 1108: } ! 1109: /* ! 1110: The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of ! 1111: increasing PCI Bus and Device Number, so sort the probe information into ! 1112: the same order the BIOS uses. ! 1113: */ ! 1114: BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], ! 1115: FlashPointCount); ! 1116: return FlashPointCount; ! 1117: } ! 1118: ! 1119: ! 1120: /* ! 1121: BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus ! 1122: Probe Information to be checked for potential BusLogic SCSI Host Adapters by ! 1123: interrogating the PCI Configuration Space on PCI machines as well as from the ! 1124: list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both ! 1125: FlashPoint and PCI MultiMaster Host Adapters are present, this driver will ! 1126: probe for FlashPoint Host Adapters first unless the BIOS primary disk is ! 1127: controlled by the first PCI MultiMaster Host Adapter, in which case ! 1128: MultiMaster Host Adapters will be probed first. The BusLogic Driver Options ! 1129: specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force ! 1130: a particular probe order. ! 1131: */ ! 1132: ! 1133: static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T ! 1134: *PrototypeHostAdapter) ! 1135: { ! 1136: /* ! 1137: If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint ! 1138: Host Adapters; otherwise, default to the standard ISA MultiMaster probe. ! 1139: */ ! 1140: if (!BusLogic_ProbeOptions.NoProbePCI && pcibios_present()) ! 1141: { ! 1142: if (BusLogic_ProbeOptions.MultiMasterFirst) ! 1143: { ! 1144: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); ! 1145: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); ! 1146: } ! 1147: else if (BusLogic_ProbeOptions.FlashPointFirst) ! 1148: { ! 1149: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); ! 1150: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); ! 1151: } ! 1152: else ! 1153: { ! 1154: int FlashPointCount = ! 1155: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); ! 1156: int PCIMultiMasterCount = ! 1157: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); ! 1158: if (FlashPointCount > 0 && PCIMultiMasterCount > 0) ! 1159: { ! 1160: BusLogic_ProbeInfo_T *ProbeInfo = ! 1161: &BusLogic_ProbeInfoList[FlashPointCount]; ! 1162: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; ! 1163: BusLogic_FetchHostAdapterLocalRAMRequest_T ! 1164: FetchHostAdapterLocalRAMRequest; ! 1165: BusLogic_BIOSDriveMapByte_T Drive0MapByte; ! 1166: while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus) ! 1167: ProbeInfo++; ! 1168: HostAdapter->IO_Address = ProbeInfo->IO_Address; ! 1169: FetchHostAdapterLocalRAMRequest.ByteOffset = ! 1170: BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0; ! 1171: FetchHostAdapterLocalRAMRequest.ByteCount = ! 1172: sizeof(Drive0MapByte); ! 1173: BusLogic_Command(HostAdapter, ! 1174: BusLogic_FetchHostAdapterLocalRAM, ! 1175: &FetchHostAdapterLocalRAMRequest, ! 1176: sizeof(FetchHostAdapterLocalRAMRequest), ! 1177: &Drive0MapByte, sizeof(Drive0MapByte)); ! 1178: /* ! 1179: If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0 ! 1180: is controlled by this PCI MultiMaster Host Adapter, then ! 1181: reverse the probe order so that MultiMaster Host Adapters are ! 1182: probed before FlashPoint Host Adapters. ! 1183: */ ! 1184: if (Drive0MapByte.DiskGeometry != ! 1185: BusLogic_BIOS_Disk_Not_Installed) ! 1186: { ! 1187: BusLogic_ProbeInfo_T ! 1188: SavedProbeInfo[BusLogic_MaxHostAdapters]; ! 1189: int MultiMasterCount = ! 1190: BusLogic_ProbeInfoCount - FlashPointCount; ! 1191: memcpy(SavedProbeInfo, ! 1192: BusLogic_ProbeInfoList, ! 1193: BusLogic_ProbeInfoCount ! 1194: * sizeof(BusLogic_ProbeInfo_T)); ! 1195: memcpy(&BusLogic_ProbeInfoList[0], ! 1196: &SavedProbeInfo[FlashPointCount], ! 1197: MultiMasterCount * sizeof(BusLogic_ProbeInfo_T)); ! 1198: memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], ! 1199: &SavedProbeInfo[0], ! 1200: FlashPointCount * sizeof(BusLogic_ProbeInfo_T)); ! 1201: } ! 1202: } ! 1203: } ! 1204: } ! 1205: else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter); ! 1206: } ! 1207: ! 1208: ! 1209: #endif /* CONFIG_PCI */ ! 1210: ! 1211: ! 1212: /* ! 1213: BusLogic_Failure prints a standardized error message, and then returns false. ! 1214: */ ! 1215: ! 1216: static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter, ! 1217: char *ErrorMessage) ! 1218: { ! 1219: BusLogic_AnnounceDriver(HostAdapter); ! 1220: if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) ! 1221: { ! 1222: BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", ! 1223: HostAdapter); ! 1224: BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", ! 1225: HostAdapter, HostAdapter->Bus, HostAdapter->Device, ! 1226: HostAdapter->IO_Address, HostAdapter->PCI_Address); ! 1227: } ! 1228: else BusLogic_Error("While configuring BusLogic Host Adapter at " ! 1229: "I/O Address 0x%X:\n", HostAdapter, ! 1230: HostAdapter->IO_Address); ! 1231: BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage); ! 1232: if (BusLogic_CommandFailureReason != NULL) ! 1233: BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, ! 1234: BusLogic_CommandFailureReason); ! 1235: return false; ! 1236: } ! 1237: ! 1238: ! 1239: /* ! 1240: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. ! 1241: */ ! 1242: ! 1243: static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 1244: { ! 1245: BusLogic_StatusRegister_T StatusRegister; ! 1246: BusLogic_InterruptRegister_T InterruptRegister; ! 1247: BusLogic_GeometryRegister_T GeometryRegister; ! 1248: /* ! 1249: FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager. ! 1250: */ ! 1251: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 1252: { ! 1253: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; ! 1254: FlashPointInfo->BaseAddress = ! 1255: (BusLogic_Base_Address_T) HostAdapter->IO_Address; ! 1256: FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel; ! 1257: FlashPointInfo->Present = false; ! 1258: if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && ! 1259: FlashPointInfo->Present)) ! 1260: { ! 1261: BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " ! 1262: "PCI Bus %d Device %d\n", HostAdapter, ! 1263: HostAdapter->Bus, HostAdapter->Device); ! 1264: BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " ! 1265: "but FlashPoint\n", HostAdapter, ! 1266: HostAdapter->IO_Address, HostAdapter->PCI_Address); ! 1267: BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", ! 1268: HostAdapter); ! 1269: return false; ! 1270: } ! 1271: if (BusLogic_GlobalOptions.TraceProbe) ! 1272: BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", ! 1273: HostAdapter, HostAdapter->IO_Address); ! 1274: /* ! 1275: Indicate the Host Adapter Probe completed successfully. ! 1276: */ ! 1277: return true; ! 1278: } ! 1279: /* ! 1280: Read the Status, Interrupt, and Geometry Registers to test if there are I/O ! 1281: ports that respond, and to check the values to determine if they are from a ! 1282: BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which ! 1283: case there is definitely no BusLogic Host Adapter at this base I/O Address. ! 1284: The test here is a subset of that used by the BusLogic Host Adapter BIOS. ! 1285: */ ! 1286: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 1287: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); ! 1288: GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); ! 1289: if (BusLogic_GlobalOptions.TraceProbe) ! 1290: BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " ! 1291: "Geometry 0x%02X\n", HostAdapter, ! 1292: HostAdapter->IO_Address, StatusRegister.All, ! 1293: InterruptRegister.All, GeometryRegister.All); ! 1294: if (StatusRegister.All == 0 || ! 1295: StatusRegister.Bits.DiagnosticActive || ! 1296: StatusRegister.Bits.CommandParameterRegisterBusy || ! 1297: StatusRegister.Bits.Reserved || ! 1298: StatusRegister.Bits.CommandInvalid || ! 1299: InterruptRegister.Bits.Reserved != 0) ! 1300: return false; ! 1301: /* ! 1302: Check the undocumented Geometry Register to test if there is an I/O port ! 1303: that responded. Adaptec Host Adapters do not implement the Geometry ! 1304: Register, so this test helps serve to avoid incorrectly recognizing an ! 1305: Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C ! 1306: series does respond to the Geometry Register I/O port, but it will be ! 1307: rejected later when the Inquire Extended Setup Information command is ! 1308: issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a ! 1309: BusLogic clone that implements the same interface as earlier BusLogic ! 1310: Host Adapters, including the undocumented commands, and is therefore ! 1311: supported by this driver. However, the AMI FastDisk always returns 0x00 ! 1312: upon reading the Geometry Register, so the extended translation option ! 1313: should always be left disabled on the AMI FastDisk. ! 1314: */ ! 1315: if (GeometryRegister.All == 0xFF) return false; ! 1316: /* ! 1317: Indicate the Host Adapter Probe completed successfully. ! 1318: */ ! 1319: return true; ! 1320: } ! 1321: ! 1322: ! 1323: /* ! 1324: BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter ! 1325: and waits for Host Adapter Diagnostics to complete. If HardReset is true, a ! 1326: Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a ! 1327: Soft Reset is performed which only resets the Host Adapter without forcing a ! 1328: SCSI Bus Reset. ! 1329: */ ! 1330: ! 1331: static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T ! 1332: *HostAdapter, ! 1333: boolean HardReset) ! 1334: { ! 1335: BusLogic_StatusRegister_T StatusRegister; ! 1336: int TimeoutCounter; ! 1337: /* ! 1338: FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager. ! 1339: */ ! 1340: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 1341: { ! 1342: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; ! 1343: FlashPointInfo->HostSoftReset = !HardReset; ! 1344: FlashPointInfo->ReportDataUnderrun = true; ! 1345: HostAdapter->CardHandle = ! 1346: FlashPoint_HardwareResetHostAdapter(FlashPointInfo); ! 1347: if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false; ! 1348: /* ! 1349: Indicate the Host Adapter Hard Reset completed successfully. ! 1350: */ ! 1351: return true; ! 1352: } ! 1353: /* ! 1354: Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host ! 1355: Adapter should respond by setting Diagnostic Active in the Status Register. ! 1356: */ ! 1357: if (HardReset) ! 1358: BusLogic_HardReset(HostAdapter); ! 1359: else BusLogic_SoftReset(HostAdapter); ! 1360: /* ! 1361: Wait until Diagnostic Active is set in the Status Register. ! 1362: */ ! 1363: TimeoutCounter = 5*10000; ! 1364: while (--TimeoutCounter >= 0) ! 1365: { ! 1366: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 1367: if (StatusRegister.Bits.DiagnosticActive) break; ! 1368: udelay(100); ! 1369: } ! 1370: if (BusLogic_GlobalOptions.TraceHardwareReset) ! 1371: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " ! 1372: "Status 0x%02X\n", HostAdapter, ! 1373: HostAdapter->IO_Address, StatusRegister.All); ! 1374: if (TimeoutCounter < 0) return false; ! 1375: /* ! 1376: Wait 100 microseconds to allow completion of any initial diagnostic ! 1377: activity which might leave the contents of the Status Register ! 1378: unpredictable. ! 1379: */ ! 1380: udelay(100); ! 1381: /* ! 1382: Wait until Diagnostic Active is reset in the Status Register. ! 1383: */ ! 1384: TimeoutCounter = 10*10000; ! 1385: while (--TimeoutCounter >= 0) ! 1386: { ! 1387: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 1388: if (!StatusRegister.Bits.DiagnosticActive) break; ! 1389: udelay(100); ! 1390: } ! 1391: if (BusLogic_GlobalOptions.TraceHardwareReset) ! 1392: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " ! 1393: "Status 0x%02X\n", HostAdapter, ! 1394: HostAdapter->IO_Address, StatusRegister.All); ! 1395: if (TimeoutCounter < 0) return false; ! 1396: /* ! 1397: Wait until at least one of the Diagnostic Failure, Host Adapter Ready, ! 1398: or Data In Register Ready bits is set in the Status Register. ! 1399: */ ! 1400: TimeoutCounter = 10000; ! 1401: while (--TimeoutCounter >= 0) ! 1402: { ! 1403: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); ! 1404: if (StatusRegister.Bits.DiagnosticFailure || ! 1405: StatusRegister.Bits.HostAdapterReady || ! 1406: StatusRegister.Bits.DataInRegisterReady) ! 1407: break; ! 1408: udelay(100); ! 1409: } ! 1410: if (BusLogic_GlobalOptions.TraceHardwareReset) ! 1411: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " ! 1412: "Status 0x%02X\n", HostAdapter, ! 1413: HostAdapter->IO_Address, StatusRegister.All); ! 1414: if (TimeoutCounter < 0) return false; ! 1415: /* ! 1416: If Diagnostic Failure is set or Host Adapter Ready is reset, then an ! 1417: error occurred during the Host Adapter diagnostics. If Data In Register ! 1418: Ready is set, then there is an Error Code available. ! 1419: */ ! 1420: if (StatusRegister.Bits.DiagnosticFailure || ! 1421: !StatusRegister.Bits.HostAdapterReady) ! 1422: { ! 1423: BusLogic_CommandFailureReason = NULL; ! 1424: BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); ! 1425: BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", ! 1426: HostAdapter, StatusRegister.All); ! 1427: if (StatusRegister.Bits.DataInRegisterReady) ! 1428: { ! 1429: unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); ! 1430: BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", ! 1431: HostAdapter, ErrorCode); ! 1432: } ! 1433: return false; ! 1434: } ! 1435: /* ! 1436: Indicate the Host Adapter Hard Reset completed successfully. ! 1437: */ ! 1438: return true; ! 1439: } ! 1440: ! 1441: ! 1442: /* ! 1443: BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic ! 1444: Host Adapter. ! 1445: */ ! 1446: ! 1447: static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 1448: { ! 1449: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; ! 1450: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 1451: boolean Result = true; ! 1452: /* ! 1453: FlashPoint Host Adapters do not require this protection. ! 1454: */ ! 1455: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; ! 1456: /* ! 1457: Issue the Inquire Extended Setup Information command. Only genuine ! 1458: BusLogic Host Adapters and true clones support this command. Adaptec 1542C ! 1459: series Host Adapters that respond to the Geometry Register I/O port will ! 1460: fail this command. ! 1461: */ ! 1462: RequestedReplyLength = sizeof(ExtendedSetupInformation); ! 1463: if (BusLogic_Command(HostAdapter, ! 1464: BusLogic_InquireExtendedSetupInformation, ! 1465: &RequestedReplyLength, ! 1466: sizeof(RequestedReplyLength), ! 1467: &ExtendedSetupInformation, ! 1468: sizeof(ExtendedSetupInformation)) ! 1469: != sizeof(ExtendedSetupInformation)) ! 1470: Result = false; ! 1471: /* ! 1472: Provide tracing information if requested and return. ! 1473: */ ! 1474: if (BusLogic_GlobalOptions.TraceProbe) ! 1475: BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, ! 1476: HostAdapter->IO_Address, (Result ? "Found" : "Not Found")); ! 1477: return Result; ! 1478: } ! 1479: ! 1480: ! 1481: /* ! 1482: BusLogic_ReadHostAdapterConfiguration reads the Configuration Information ! 1483: from Host Adapter and initializes the Host Adapter structure. ! 1484: */ ! 1485: ! 1486: static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T ! 1487: *HostAdapter) ! 1488: { ! 1489: BusLogic_BoardID_T BoardID; ! 1490: BusLogic_Configuration_T Configuration; ! 1491: BusLogic_SetupInformation_T SetupInformation; ! 1492: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; ! 1493: BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber; ! 1494: BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; ! 1495: BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; ! 1496: BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; ! 1497: BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest; ! 1498: BusLogic_AutoSCSIData_T AutoSCSIData; ! 1499: BusLogic_GeometryRegister_T GeometryRegister; ! 1500: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 1501: unsigned char *TargetPointer, Character; ! 1502: int TargetID, i; ! 1503: /* ! 1504: Configuration Information for FlashPoint Host Adapters is provided in the ! 1505: FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function. ! 1506: Initialize fields in the Host Adapter structure from the FlashPoint_Info ! 1507: structure. ! 1508: */ ! 1509: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 1510: { ! 1511: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo; ! 1512: TargetPointer = HostAdapter->ModelName; ! 1513: *TargetPointer++ = 'B'; ! 1514: *TargetPointer++ = 'T'; ! 1515: *TargetPointer++ = '-'; ! 1516: for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++) ! 1517: *TargetPointer++ = FlashPointInfo->ModelNumber[i]; ! 1518: *TargetPointer++ = '\0'; ! 1519: strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion); ! 1520: HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID; ! 1521: HostAdapter->ExtendedTranslationEnabled = ! 1522: FlashPointInfo->ExtendedTranslationEnabled; ! 1523: HostAdapter->ParityCheckingEnabled = ! 1524: FlashPointInfo->ParityCheckingEnabled; ! 1525: HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset; ! 1526: HostAdapter->LevelSensitiveInterrupt = true; ! 1527: HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI; ! 1528: HostAdapter->HostDifferentialSCSI = false; ! 1529: HostAdapter->HostSupportsSCAM = true; ! 1530: HostAdapter->HostUltraSCSI = true; ! 1531: HostAdapter->ExtendedLUNSupport = true; ! 1532: HostAdapter->TerminationInfoValid = true; ! 1533: HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated; ! 1534: HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated; ! 1535: HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled; ! 1536: HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2; ! 1537: HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; ! 1538: HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); ! 1539: HostAdapter->MaxLogicalUnits = 32; ! 1540: HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; ! 1541: HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; ! 1542: HostAdapter->DriverQueueDepth = 255; ! 1543: HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth; ! 1544: HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted; ! 1545: HostAdapter->FastPermitted = FlashPointInfo->FastPermitted; ! 1546: HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted; ! 1547: HostAdapter->WidePermitted = FlashPointInfo->WidePermitted; ! 1548: HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted; ! 1549: HostAdapter->TaggedQueuingPermitted = 0xFFFF; ! 1550: goto Common; ! 1551: } ! 1552: /* ! 1553: Issue the Inquire Board ID command. ! 1554: */ ! 1555: if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, ! 1556: &BoardID, sizeof(BoardID)) != sizeof(BoardID)) ! 1557: return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); ! 1558: /* ! 1559: Issue the Inquire Configuration command. ! 1560: */ ! 1561: if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, ! 1562: &Configuration, sizeof(Configuration)) ! 1563: != sizeof(Configuration)) ! 1564: return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); ! 1565: /* ! 1566: Issue the Inquire Setup Information command. ! 1567: */ ! 1568: RequestedReplyLength = sizeof(SetupInformation); ! 1569: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, ! 1570: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 1571: &SetupInformation, sizeof(SetupInformation)) ! 1572: != sizeof(SetupInformation)) ! 1573: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); ! 1574: /* ! 1575: Issue the Inquire Extended Setup Information command. ! 1576: */ ! 1577: RequestedReplyLength = sizeof(ExtendedSetupInformation); ! 1578: if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, ! 1579: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 1580: &ExtendedSetupInformation, ! 1581: sizeof(ExtendedSetupInformation)) ! 1582: != sizeof(ExtendedSetupInformation)) ! 1583: return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); ! 1584: /* ! 1585: Issue the Inquire Firmware Version 3rd Digit command. ! 1586: */ ! 1587: FirmwareVersion3rdDigit = '\0'; ! 1588: if (BoardID.FirmwareVersion1stDigit > '0') ! 1589: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, ! 1590: NULL, 0, &FirmwareVersion3rdDigit, ! 1591: sizeof(FirmwareVersion3rdDigit)) ! 1592: != sizeof(FirmwareVersion3rdDigit)) ! 1593: return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); ! 1594: /* ! 1595: Issue the Inquire Host Adapter Model Number command. ! 1596: */ ! 1597: if (ExtendedSetupInformation.BusType == 'A' && ! 1598: BoardID.FirmwareVersion1stDigit == '2') ! 1599: /* BusLogic BT-542B ISA 2.xx */ ! 1600: strcpy(HostAdapterModelNumber, "542B"); ! 1601: else if (ExtendedSetupInformation.BusType == 'E' && ! 1602: BoardID.FirmwareVersion1stDigit == '2' && ! 1603: (BoardID.FirmwareVersion2ndDigit <= '1' || ! 1604: (BoardID.FirmwareVersion2ndDigit == '2' && ! 1605: FirmwareVersion3rdDigit == '0'))) ! 1606: /* BusLogic BT-742A EISA 2.1x or 2.20 */ ! 1607: strcpy(HostAdapterModelNumber, "742A"); ! 1608: else if (ExtendedSetupInformation.BusType == 'E' && ! 1609: BoardID.FirmwareVersion1stDigit == '0') ! 1610: /* AMI FastDisk EISA Series 441 0.x */ ! 1611: strcpy(HostAdapterModelNumber, "747A"); ! 1612: else ! 1613: { ! 1614: RequestedReplyLength = sizeof(HostAdapterModelNumber); ! 1615: if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, ! 1616: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 1617: &HostAdapterModelNumber, ! 1618: sizeof(HostAdapterModelNumber)) ! 1619: != sizeof(HostAdapterModelNumber)) ! 1620: return BusLogic_Failure(HostAdapter, ! 1621: "INQUIRE HOST ADAPTER MODEL NUMBER"); ! 1622: } ! 1623: /* ! 1624: BusLogic MultiMaster Host Adapters can be identified by their model number ! 1625: and the major version number of their firmware as follows: ! 1626: ! 1627: 5.xx BusLogic "W" Series Host Adapters: ! 1628: BT-948/958/958D ! 1629: 4.xx BusLogic "C" Series Host Adapters: ! 1630: BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF ! 1631: 3.xx BusLogic "S" Series Host Adapters: ! 1632: BT-747S/747D/757S/757D/445S/545S/542D ! 1633: BT-542B/742A (revision H) ! 1634: 2.xx BusLogic "A" Series Host Adapters: ! 1635: BT-542B/742A (revision G and below) ! 1636: 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter ! 1637: */ ! 1638: /* ! 1639: Save the Model Name and Host Adapter Name in the Host Adapter structure. ! 1640: */ ! 1641: TargetPointer = HostAdapter->ModelName; ! 1642: *TargetPointer++ = 'B'; ! 1643: *TargetPointer++ = 'T'; ! 1644: *TargetPointer++ = '-'; ! 1645: for (i = 0; i < sizeof(HostAdapterModelNumber); i++) ! 1646: { ! 1647: Character = HostAdapterModelNumber[i]; ! 1648: if (Character == ' ' || Character == '\0') break; ! 1649: *TargetPointer++ = Character; ! 1650: } ! 1651: *TargetPointer++ = '\0'; ! 1652: /* ! 1653: Save the Firmware Version in the Host Adapter structure. ! 1654: */ ! 1655: TargetPointer = HostAdapter->FirmwareVersion; ! 1656: *TargetPointer++ = BoardID.FirmwareVersion1stDigit; ! 1657: *TargetPointer++ = '.'; ! 1658: *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; ! 1659: if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') ! 1660: *TargetPointer++ = FirmwareVersion3rdDigit; ! 1661: *TargetPointer = '\0'; ! 1662: /* ! 1663: Issue the Inquire Firmware Version Letter command. ! 1664: */ ! 1665: if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) ! 1666: { ! 1667: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, ! 1668: NULL, 0, &FirmwareVersionLetter, ! 1669: sizeof(FirmwareVersionLetter)) ! 1670: != sizeof(FirmwareVersionLetter)) ! 1671: return BusLogic_Failure(HostAdapter, ! 1672: "INQUIRE FIRMWARE VERSION LETTER"); ! 1673: if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') ! 1674: *TargetPointer++ = FirmwareVersionLetter; ! 1675: *TargetPointer = '\0'; ! 1676: } ! 1677: /* ! 1678: Save the Host Adapter SCSI ID in the Host Adapter structure. ! 1679: */ ! 1680: HostAdapter->SCSI_ID = Configuration.HostAdapterID; ! 1681: /* ! 1682: Determine the Bus Type and save it in the Host Adapter structure, determine ! 1683: and save the IRQ Channel if necessary, and determine and save the DMA ! 1684: Channel for ISA Host Adapters. ! 1685: */ ! 1686: HostAdapter->HostAdapterBusType = ! 1687: BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; ! 1688: if (HostAdapter->IRQ_Channel == 0) ! 1689: { ! 1690: if (Configuration.IRQ_Channel9) ! 1691: HostAdapter->IRQ_Channel = 9; ! 1692: else if (Configuration.IRQ_Channel10) ! 1693: HostAdapter->IRQ_Channel = 10; ! 1694: else if (Configuration.IRQ_Channel11) ! 1695: HostAdapter->IRQ_Channel = 11; ! 1696: else if (Configuration.IRQ_Channel12) ! 1697: HostAdapter->IRQ_Channel = 12; ! 1698: else if (Configuration.IRQ_Channel14) ! 1699: HostAdapter->IRQ_Channel = 14; ! 1700: else if (Configuration.IRQ_Channel15) ! 1701: HostAdapter->IRQ_Channel = 15; ! 1702: } ! 1703: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) ! 1704: { ! 1705: if (Configuration.DMA_Channel5) ! 1706: HostAdapter->DMA_Channel = 5; ! 1707: else if (Configuration.DMA_Channel6) ! 1708: HostAdapter->DMA_Channel = 6; ! 1709: else if (Configuration.DMA_Channel7) ! 1710: HostAdapter->DMA_Channel = 7; ! 1711: } ! 1712: /* ! 1713: Determine whether Extended Translation is enabled and save it in ! 1714: the Host Adapter structure. ! 1715: */ ! 1716: GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); ! 1717: HostAdapter->ExtendedTranslationEnabled = ! 1718: GeometryRegister.Bits.ExtendedTranslationEnabled; ! 1719: /* ! 1720: Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide ! 1721: SCSI flag, Differential SCSI flag, SCAM Supported flag, and ! 1722: Ultra SCSI flag in the Host Adapter structure. ! 1723: */ ! 1724: HostAdapter->HostAdapterScatterGatherLimit = ! 1725: ExtendedSetupInformation.ScatterGatherLimit; ! 1726: HostAdapter->DriverScatterGatherLimit = ! 1727: HostAdapter->HostAdapterScatterGatherLimit; ! 1728: if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) ! 1729: HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; ! 1730: if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) ! 1731: HostAdapter->LevelSensitiveInterrupt = true; ! 1732: HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; ! 1733: HostAdapter->HostDifferentialSCSI = ! 1734: ExtendedSetupInformation.HostDifferentialSCSI; ! 1735: HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; ! 1736: HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; ! 1737: /* ! 1738: Determine whether Extended LUN Format CCBs are supported and save the ! 1739: information in the Host Adapter structure. ! 1740: */ ! 1741: if (HostAdapter->FirmwareVersion[0] == '5' || ! 1742: (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) ! 1743: HostAdapter->ExtendedLUNSupport = true; ! 1744: /* ! 1745: Issue the Inquire PCI Host Adapter Information command to read the ! 1746: Termination Information from "W" series MultiMaster Host Adapters. ! 1747: */ ! 1748: if (HostAdapter->FirmwareVersion[0] == '5') ! 1749: { ! 1750: if (BusLogic_Command(HostAdapter, ! 1751: BusLogic_InquirePCIHostAdapterInformation, ! 1752: NULL, 0, &PCIHostAdapterInformation, ! 1753: sizeof(PCIHostAdapterInformation)) ! 1754: != sizeof(PCIHostAdapterInformation)) ! 1755: return BusLogic_Failure(HostAdapter, ! 1756: "INQUIRE PCI HOST ADAPTER INFORMATION"); ! 1757: /* ! 1758: Save the Termination Information in the Host Adapter structure. ! 1759: */ ! 1760: if (PCIHostAdapterInformation.GenericInfoValid) ! 1761: { ! 1762: HostAdapter->TerminationInfoValid = true; ! 1763: HostAdapter->LowByteTerminated = ! 1764: PCIHostAdapterInformation.LowByteTerminated; ! 1765: HostAdapter->HighByteTerminated = ! 1766: PCIHostAdapterInformation.HighByteTerminated; ! 1767: } ! 1768: } ! 1769: /* ! 1770: Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data ! 1771: from "W" and "C" series MultiMaster Host Adapters. ! 1772: */ ! 1773: if (HostAdapter->FirmwareVersion[0] >= '4') ! 1774: { ! 1775: FetchHostAdapterLocalRAMRequest.ByteOffset = ! 1776: BusLogic_AutoSCSI_BaseOffset; ! 1777: FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); ! 1778: if (BusLogic_Command(HostAdapter, ! 1779: BusLogic_FetchHostAdapterLocalRAM, ! 1780: &FetchHostAdapterLocalRAMRequest, ! 1781: sizeof(FetchHostAdapterLocalRAMRequest), ! 1782: &AutoSCSIData, sizeof(AutoSCSIData)) ! 1783: != sizeof(AutoSCSIData)) ! 1784: return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); ! 1785: /* ! 1786: Save the Parity Checking Enabled, Bus Reset Enabled, and Termination ! 1787: Information in the Host Adapter structure. ! 1788: */ ! 1789: HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; ! 1790: HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; ! 1791: if (HostAdapter->FirmwareVersion[0] == '4') ! 1792: { ! 1793: HostAdapter->TerminationInfoValid = true; ! 1794: HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated; ! 1795: HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated; ! 1796: } ! 1797: /* ! 1798: Save the Wide Permitted, Fast Permitted, Synchronous Permitted, ! 1799: Disconnect Permitted, Ultra Permitted, and SCAM Information in the ! 1800: Host Adapter structure. ! 1801: */ ! 1802: HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; ! 1803: HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; ! 1804: HostAdapter->SynchronousPermitted = ! 1805: AutoSCSIData.SynchronousPermitted; ! 1806: HostAdapter->DisconnectPermitted = ! 1807: AutoSCSIData.DisconnectPermitted; ! 1808: if (HostAdapter->HostUltraSCSI) ! 1809: HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; ! 1810: if (HostAdapter->HostSupportsSCAM) ! 1811: { ! 1812: HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; ! 1813: HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; ! 1814: } ! 1815: } ! 1816: /* ! 1817: Initialize fields in the Host Adapter structure for "S" and "A" series ! 1818: MultiMaster Host Adapters. ! 1819: */ ! 1820: if (HostAdapter->FirmwareVersion[0] < '4') ! 1821: { ! 1822: if (SetupInformation.SynchronousInitiationEnabled) ! 1823: { ! 1824: HostAdapter->SynchronousPermitted = 0xFF; ! 1825: if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) ! 1826: { ! 1827: if (ExtendedSetupInformation.Misc.FastOnEISA) ! 1828: HostAdapter->FastPermitted = 0xFF; ! 1829: if (strcmp(HostAdapter->ModelName, "BT-757") == 0) ! 1830: HostAdapter->WidePermitted = 0xFF; ! 1831: } ! 1832: } ! 1833: HostAdapter->DisconnectPermitted = 0xFF; ! 1834: HostAdapter->ParityCheckingEnabled = ! 1835: SetupInformation.ParityCheckingEnabled; ! 1836: HostAdapter->BusResetEnabled = true; ! 1837: } ! 1838: /* ! 1839: Determine the maximum number of Target IDs and Logical Units supported by ! 1840: this driver for Wide and Narrow Host Adapters. ! 1841: */ ! 1842: HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); ! 1843: HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); ! 1844: /* ! 1845: Select appropriate values for the Mailbox Count, Driver Queue Depth, ! 1846: Initial CCBs, and Incremental CCBs variables based on whether or not Strict ! 1847: Round Robin Mode is supported. If Strict Round Robin Mode is supported, ! 1848: then there is no performance degradation in using the maximum possible ! 1849: number of Outgoing and Incoming Mailboxes and allowing the Tagged and ! 1850: Untagged Queue Depths to determine the actual utilization. If Strict Round ! 1851: Robin Mode is not supported, then the Host Adapter must scan all the ! 1852: Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can ! 1853: cause a substantial performance penalty. The host adapters actually have ! 1854: room to store the following number of CCBs internally; that is, they can ! 1855: internally queue and manage this many active commands on the SCSI bus ! 1856: simultaneously. Performance measurements demonstrate that the Driver Queue ! 1857: Depth should be set to the Mailbox Count, rather than the Host Adapter ! 1858: Queue Depth (internal CCB capacity), as it is more efficient to have the ! 1859: queued commands waiting in Outgoing Mailboxes if necessary than to block ! 1860: the process in the higher levels of the SCSI Subsystem. ! 1861: ! 1862: 192 BT-948/958/958D ! 1863: 100 BT-946C/956C/956CD/747C/757C/757CD/445C ! 1864: 50 BT-545C/540CF ! 1865: 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A ! 1866: */ ! 1867: if (HostAdapter->FirmwareVersion[0] == '5') ! 1868: HostAdapter->HostAdapterQueueDepth = 192; ! 1869: else if (HostAdapter->FirmwareVersion[0] == '4') ! 1870: HostAdapter->HostAdapterQueueDepth = ! 1871: (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50); ! 1872: else HostAdapter->HostAdapterQueueDepth = 30; ! 1873: if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) ! 1874: { ! 1875: HostAdapter->StrictRoundRobinModeSupport = true; ! 1876: HostAdapter->MailboxCount = BusLogic_MaxMailboxes; ! 1877: } ! 1878: else ! 1879: { ! 1880: HostAdapter->StrictRoundRobinModeSupport = false; ! 1881: HostAdapter->MailboxCount = 32; ! 1882: } ! 1883: HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount; ! 1884: HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; ! 1885: HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; ! 1886: /* ! 1887: Tagged Queuing support is available and operates properly on all "W" series ! 1888: MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with ! 1889: firmware version 4.22 and above, and on "S" series MultiMaster Host ! 1890: Adapters with firmware version 3.35 and above. ! 1891: */ ! 1892: HostAdapter->TaggedQueuingPermitted = 0; ! 1893: switch (HostAdapter->FirmwareVersion[0]) ! 1894: { ! 1895: case '5': ! 1896: HostAdapter->TaggedQueuingPermitted = 0xFFFF; ! 1897: break; ! 1898: case '4': ! 1899: if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) ! 1900: HostAdapter->TaggedQueuingPermitted = 0xFFFF; ! 1901: break; ! 1902: case '3': ! 1903: if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) ! 1904: HostAdapter->TaggedQueuingPermitted = 0xFFFF; ! 1905: break; ! 1906: } ! 1907: /* ! 1908: Determine the Host Adapter BIOS Address if the BIOS is enabled and ! 1909: save it in the Host Adapter structure. The BIOS is disabled if the ! 1910: BIOS_Address is 0. ! 1911: */ ! 1912: HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; ! 1913: /* ! 1914: ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. ! 1915: */ ! 1916: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && ! 1917: (void *) high_memory > (void *) MAX_DMA_ADDRESS) ! 1918: HostAdapter->BounceBuffersRequired = true; ! 1919: /* ! 1920: BusLogic BT-445S Host Adapters prior to board revision E have a hardware ! 1921: bug whereby when the BIOS is enabled, transfers to/from the same address ! 1922: range the BIOS occupies modulo 16MB are handled incorrectly. Only properly ! 1923: functioning BT-445S Host Adapters have firmware version 3.37, so require ! 1924: that ISA Bounce Buffers be used for the buggy BT-445S models if there is ! 1925: more than 16MB memory. ! 1926: */ ! 1927: if (HostAdapter->BIOS_Address > 0 && ! 1928: strcmp(HostAdapter->ModelName, "BT-445S") == 0 && ! 1929: strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && ! 1930: (void *) high_memory > (void *) MAX_DMA_ADDRESS) ! 1931: HostAdapter->BounceBuffersRequired = true; ! 1932: /* ! 1933: Initialize parameters common to MultiMaster and FlashPoint Host Adapters. ! 1934: */ ! 1935: Common: ! 1936: /* ! 1937: Initialize the Host Adapter Full Model Name from the Model Name. ! 1938: */ ! 1939: strcpy(HostAdapter->FullModelName, "BusLogic "); ! 1940: strcat(HostAdapter->FullModelName, HostAdapter->ModelName); ! 1941: /* ! 1942: Select an appropriate value for the Tagged Queue Depth either from a ! 1943: BusLogic Driver Options specification, or based on whether this Host ! 1944: Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth ! 1945: is left at 0 for automatic determination in BusLogic_SelectQueueDepths. ! 1946: Initialize the Untagged Queue Depth. ! 1947: */ ! 1948: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) ! 1949: { ! 1950: unsigned char QueueDepth = 0; ! 1951: if (HostAdapter->DriverOptions != NULL && ! 1952: HostAdapter->DriverOptions->QueueDepth[TargetID] > 0) ! 1953: QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID]; ! 1954: else if (HostAdapter->BounceBuffersRequired) ! 1955: QueueDepth = BusLogic_TaggedQueueDepthBB; ! 1956: HostAdapter->QueueDepth[TargetID] = QueueDepth; ! 1957: } ! 1958: if (HostAdapter->BounceBuffersRequired) ! 1959: HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB; ! 1960: else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth; ! 1961: if (HostAdapter->DriverOptions != NULL) ! 1962: HostAdapter->CommonQueueDepth = ! 1963: HostAdapter->DriverOptions->CommonQueueDepth; ! 1964: if (HostAdapter->CommonQueueDepth > 0 && ! 1965: HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth) ! 1966: HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth; ! 1967: /* ! 1968: Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. ! 1969: Therefore, mask the Tagged Queuing Permitted Default bits with the ! 1970: Disconnect/Reconnect Permitted bits. ! 1971: */ ! 1972: HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; ! 1973: /* ! 1974: Combine the default Tagged Queuing Permitted bits with any BusLogic Driver ! 1975: Options Tagged Queuing specification. ! 1976: */ ! 1977: if (HostAdapter->DriverOptions != NULL) ! 1978: HostAdapter->TaggedQueuingPermitted = ! 1979: (HostAdapter->DriverOptions->TaggedQueuingPermitted & ! 1980: HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | ! 1981: (HostAdapter->TaggedQueuingPermitted & ! 1982: ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask); ! 1983: /* ! 1984: Select appropriate values for the Error Recovery Strategy array ! 1985: either from a BusLogic Driver Options specification, or using ! 1986: BusLogic_ErrorRecovery_Default. ! 1987: */ ! 1988: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) ! 1989: if (HostAdapter->DriverOptions != NULL) ! 1990: HostAdapter->ErrorRecoveryStrategy[TargetID] = ! 1991: HostAdapter->DriverOptions->ErrorRecoveryStrategy[TargetID]; ! 1992: else HostAdapter->ErrorRecoveryStrategy[TargetID] = ! 1993: BusLogic_ErrorRecovery_Default; ! 1994: /* ! 1995: Select an appropriate value for Bus Settle Time either from a BusLogic ! 1996: Driver Options specification, or from BusLogic_DefaultBusSettleTime. ! 1997: */ ! 1998: if (HostAdapter->DriverOptions != NULL && ! 1999: HostAdapter->DriverOptions->BusSettleTime > 0) ! 2000: HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime; ! 2001: else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; ! 2002: /* ! 2003: Indicate reading the Host Adapter Configuration completed successfully. ! 2004: */ ! 2005: return true; ! 2006: } ! 2007: ! 2008: ! 2009: /* ! 2010: BusLogic_ReportHostAdapterConfiguration reports the configuration of ! 2011: Host Adapter. ! 2012: */ ! 2013: ! 2014: static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T ! 2015: *HostAdapter) ! 2016: { ! 2017: unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; ! 2018: unsigned short SynchronousPermitted, FastPermitted; ! 2019: unsigned short UltraPermitted, WidePermitted; ! 2020: unsigned short DisconnectPermitted, TaggedQueuingPermitted; ! 2021: boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; ! 2022: boolean CommonErrorRecovery; ! 2023: char SynchronousString[BusLogic_MaxTargetDevices+1]; ! 2024: char WideString[BusLogic_MaxTargetDevices+1]; ! 2025: char DisconnectString[BusLogic_MaxTargetDevices+1]; ! 2026: char TaggedQueuingString[BusLogic_MaxTargetDevices+1]; ! 2027: char ErrorRecoveryString[BusLogic_MaxTargetDevices+1]; ! 2028: char *SynchronousMessage = SynchronousString; ! 2029: char *WideMessage = WideString; ! 2030: char *DisconnectMessage = DisconnectString; ! 2031: char *TaggedQueuingMessage = TaggedQueuingString; ! 2032: char *ErrorRecoveryMessage = ErrorRecoveryString; ! 2033: int TargetID; ! 2034: BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", ! 2035: HostAdapter, HostAdapter->ModelName, ! 2036: BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], ! 2037: (HostAdapter->HostWideSCSI ? " Wide" : ""), ! 2038: (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), ! 2039: (HostAdapter->HostUltraSCSI ? " Ultra" : "")); ! 2040: BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " ! 2041: "IRQ Channel: %d/%s\n", HostAdapter, ! 2042: HostAdapter->FirmwareVersion, ! 2043: HostAdapter->IO_Address, HostAdapter->IRQ_Channel, ! 2044: (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge")); ! 2045: if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) ! 2046: { ! 2047: BusLogic_Info(" DMA Channel: ", HostAdapter); ! 2048: if (HostAdapter->DMA_Channel > 0) ! 2049: BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel); ! 2050: else BusLogic_Info("None, ", HostAdapter); ! 2051: if (HostAdapter->BIOS_Address > 0) ! 2052: BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, ! 2053: HostAdapter->BIOS_Address); ! 2054: else BusLogic_Info("BIOS Address: None, ", HostAdapter); ! 2055: } ! 2056: else ! 2057: { ! 2058: BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", ! 2059: HostAdapter, HostAdapter->Bus, HostAdapter->Device); ! 2060: if (HostAdapter->PCI_Address > 0) ! 2061: BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address); ! 2062: else BusLogic_Info("Unassigned, ", HostAdapter); ! 2063: } ! 2064: BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, ! 2065: HostAdapter->SCSI_ID); ! 2066: BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", ! 2067: HostAdapter, ! 2068: (HostAdapter->ParityCheckingEnabled ! 2069: ? "Enabled" : "Disabled"), ! 2070: (HostAdapter->ExtendedTranslationEnabled ! 2071: ? "Enabled" : "Disabled")); ! 2072: AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID); ! 2073: SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask; ! 2074: FastPermitted = HostAdapter->FastPermitted & AllTargetsMask; ! 2075: UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask; ! 2076: if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && ! 2077: (HostAdapter->FirmwareVersion[0] >= '4' || ! 2078: HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || ! 2079: BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 2080: { ! 2081: CommonSynchronousNegotiation = false; ! 2082: if (SynchronousPermitted == 0) ! 2083: { ! 2084: SynchronousMessage = "Disabled"; ! 2085: CommonSynchronousNegotiation = true; ! 2086: } ! 2087: else if (SynchronousPermitted == AllTargetsMask) ! 2088: { ! 2089: if (FastPermitted == 0) ! 2090: { ! 2091: SynchronousMessage = "Slow"; ! 2092: CommonSynchronousNegotiation = true; ! 2093: } ! 2094: else if (FastPermitted == AllTargetsMask) ! 2095: { ! 2096: if (UltraPermitted == 0) ! 2097: { ! 2098: SynchronousMessage = "Fast"; ! 2099: CommonSynchronousNegotiation = true; ! 2100: } ! 2101: else if (UltraPermitted == AllTargetsMask) ! 2102: { ! 2103: SynchronousMessage = "Ultra"; ! 2104: CommonSynchronousNegotiation = true; ! 2105: } ! 2106: } ! 2107: } ! 2108: if (!CommonSynchronousNegotiation) ! 2109: { ! 2110: for (TargetID = 0; ! 2111: TargetID < HostAdapter->MaxTargetDevices; ! 2112: TargetID++) ! 2113: SynchronousString[TargetID] = ! 2114: ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : ! 2115: (!(FastPermitted & (1 << TargetID)) ? 'S' : ! 2116: (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U'))); ! 2117: SynchronousString[HostAdapter->SCSI_ID] = '#'; ! 2118: SynchronousString[HostAdapter->MaxTargetDevices] = '\0'; ! 2119: } ! 2120: } ! 2121: else SynchronousMessage = ! 2122: (SynchronousPermitted == 0 ? "Disabled" : "Enabled"); ! 2123: WidePermitted = HostAdapter->WidePermitted & AllTargetsMask; ! 2124: if (WidePermitted == 0) ! 2125: WideMessage = "Disabled"; ! 2126: else if (WidePermitted == AllTargetsMask) ! 2127: WideMessage = "Enabled"; ! 2128: else ! 2129: { ! 2130: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2131: WideString[TargetID] = ! 2132: ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N'); ! 2133: WideString[HostAdapter->SCSI_ID] = '#'; ! 2134: WideString[HostAdapter->MaxTargetDevices] = '\0'; ! 2135: } ! 2136: DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; ! 2137: if (DisconnectPermitted == 0) ! 2138: DisconnectMessage = "Disabled"; ! 2139: else if (DisconnectPermitted == AllTargetsMask) ! 2140: DisconnectMessage = "Enabled"; ! 2141: else ! 2142: { ! 2143: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2144: DisconnectString[TargetID] = ! 2145: ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); ! 2146: DisconnectString[HostAdapter->SCSI_ID] = '#'; ! 2147: DisconnectString[HostAdapter->MaxTargetDevices] = '\0'; ! 2148: } ! 2149: TaggedQueuingPermitted = ! 2150: HostAdapter->TaggedQueuingPermitted & AllTargetsMask; ! 2151: if (TaggedQueuingPermitted == 0) ! 2152: TaggedQueuingMessage = "Disabled"; ! 2153: else if (TaggedQueuingPermitted == AllTargetsMask) ! 2154: TaggedQueuingMessage = "Enabled"; ! 2155: else ! 2156: { ! 2157: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2158: TaggedQueuingString[TargetID] = ! 2159: ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); ! 2160: TaggedQueuingString[HostAdapter->SCSI_ID] = '#'; ! 2161: TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0'; ! 2162: } ! 2163: BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", ! 2164: HostAdapter, SynchronousMessage, WideMessage); ! 2165: BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", ! 2166: HostAdapter, DisconnectMessage, TaggedQueuingMessage); ! 2167: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 2168: { ! 2169: BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " ! 2170: "Mailboxes: %d\n", HostAdapter, ! 2171: HostAdapter->DriverScatterGatherLimit, ! 2172: HostAdapter->HostAdapterScatterGatherLimit, ! 2173: HostAdapter->MailboxCount); ! 2174: BusLogic_Info(" Driver Queue Depth: %d, " ! 2175: "Host Adapter Queue Depth: %d\n", ! 2176: HostAdapter, HostAdapter->DriverQueueDepth, ! 2177: HostAdapter->HostAdapterQueueDepth); ! 2178: } ! 2179: else BusLogic_Info(" Driver Queue Depth: %d, " ! 2180: "Scatter/Gather Limit: %d segments\n", ! 2181: HostAdapter, HostAdapter->DriverQueueDepth, ! 2182: HostAdapter->DriverScatterGatherLimit); ! 2183: BusLogic_Info(" Tagged Queue Depth: ", HostAdapter); ! 2184: CommonTaggedQueueDepth = true; ! 2185: for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2186: if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) ! 2187: { ! 2188: CommonTaggedQueueDepth = false; ! 2189: break; ! 2190: } ! 2191: if (CommonTaggedQueueDepth) ! 2192: { ! 2193: if (HostAdapter->QueueDepth[0] > 0) ! 2194: BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]); ! 2195: else BusLogic_Info("Automatic", HostAdapter); ! 2196: } ! 2197: else BusLogic_Info("Individual", HostAdapter); ! 2198: BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, ! 2199: HostAdapter->UntaggedQueueDepth); ! 2200: CommonErrorRecovery = true; ! 2201: for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2202: if (HostAdapter->ErrorRecoveryStrategy[TargetID] != ! 2203: HostAdapter->ErrorRecoveryStrategy[0]) ! 2204: { ! 2205: CommonErrorRecovery = false; ! 2206: break; ! 2207: } ! 2208: if (CommonErrorRecovery) ! 2209: ErrorRecoveryMessage = ! 2210: BusLogic_ErrorRecoveryStrategyNames[ ! 2211: HostAdapter->ErrorRecoveryStrategy[0]]; ! 2212: else ! 2213: { ! 2214: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2215: ErrorRecoveryString[TargetID] = ! 2216: BusLogic_ErrorRecoveryStrategyLetters[ ! 2217: HostAdapter->ErrorRecoveryStrategy[TargetID]]; ! 2218: ErrorRecoveryString[HostAdapter->SCSI_ID] = '#'; ! 2219: ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0'; ! 2220: } ! 2221: BusLogic_Info(" Error Recovery Strategy: %s, SCSI Bus Reset: %s\n", ! 2222: HostAdapter, ErrorRecoveryMessage, ! 2223: (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled")); ! 2224: if (HostAdapter->TerminationInfoValid) ! 2225: { ! 2226: if (HostAdapter->HostWideSCSI) ! 2227: BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, ! 2228: (HostAdapter->LowByteTerminated ! 2229: ? (HostAdapter->HighByteTerminated ! 2230: ? "Both Enabled" : "Low Enabled") ! 2231: : (HostAdapter->HighByteTerminated ! 2232: ? "High Enabled" : "Both Disabled"))); ! 2233: else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, ! 2234: (HostAdapter->LowByteTerminated ? ! 2235: "Enabled" : "Disabled")); ! 2236: if (HostAdapter->HostSupportsSCAM) ! 2237: BusLogic_Info(", SCAM: %s", HostAdapter, ! 2238: (HostAdapter->SCAM_Enabled ! 2239: ? (HostAdapter->SCAM_Level2 ! 2240: ? "Enabled, Level 2" : "Enabled, Level 1") ! 2241: : "Disabled")); ! 2242: BusLogic_Info("\n", HostAdapter); ! 2243: } ! 2244: /* ! 2245: Indicate reporting the Host Adapter configuration completed successfully. ! 2246: */ ! 2247: return true; ! 2248: } ! 2249: ! 2250: ! 2251: /* ! 2252: BusLogic_AcquireResources acquires the system resources necessary to use ! 2253: Host Adapter. ! 2254: */ ! 2255: ! 2256: static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter) ! 2257: { ! 2258: if (HostAdapter->IRQ_Channel == 0) ! 2259: { ! 2260: BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", ! 2261: HostAdapter); ! 2262: return false; ! 2263: } ! 2264: /* ! 2265: Acquire shared access to the IRQ Channel. ! 2266: */ ! 2267: if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, ! 2268: SA_INTERRUPT | SA_SHIRQ, ! 2269: HostAdapter->FullModelName, HostAdapter) < 0) ! 2270: { ! 2271: BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", ! 2272: HostAdapter, HostAdapter->IRQ_Channel); ! 2273: return false; ! 2274: } ! 2275: HostAdapter->IRQ_ChannelAcquired = true; ! 2276: /* ! 2277: Acquire exclusive access to the DMA Channel. ! 2278: */ ! 2279: if (HostAdapter->DMA_Channel > 0) ! 2280: { ! 2281: if (request_dma(HostAdapter->DMA_Channel, ! 2282: HostAdapter->FullModelName) < 0) ! 2283: { ! 2284: BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", ! 2285: HostAdapter, HostAdapter->DMA_Channel); ! 2286: return false; ! 2287: } ! 2288: set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); ! 2289: enable_dma(HostAdapter->DMA_Channel); ! 2290: HostAdapter->DMA_ChannelAcquired = true; ! 2291: } ! 2292: /* ! 2293: Indicate the System Resource Acquisition completed successfully, ! 2294: */ ! 2295: return true; ! 2296: } ! 2297: ! 2298: ! 2299: /* ! 2300: BusLogic_ReleaseResources releases any system resources previously acquired ! 2301: by BusLogic_AcquireResources. ! 2302: */ ! 2303: ! 2304: static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter) ! 2305: { ! 2306: /* ! 2307: Release shared access to the IRQ Channel. ! 2308: */ ! 2309: if (HostAdapter->IRQ_ChannelAcquired) ! 2310: free_irq(HostAdapter->IRQ_Channel, HostAdapter); ! 2311: /* ! 2312: Release exclusive access to the DMA Channel. ! 2313: */ ! 2314: if (HostAdapter->DMA_ChannelAcquired) ! 2315: free_dma(HostAdapter->DMA_Channel); ! 2316: } ! 2317: ! 2318: ! 2319: /* ! 2320: BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only ! 2321: function called during SCSI Host Adapter detection which modifies the state ! 2322: of the Host Adapter from its initial power on or hard reset state. ! 2323: */ ! 2324: ! 2325: static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T ! 2326: *HostAdapter) ! 2327: { ! 2328: BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; ! 2329: BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest; ! 2330: BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest; ! 2331: int TargetID; ! 2332: /* ! 2333: Initialize the pointers to the first and last CCBs that are queued for ! 2334: completion processing. ! 2335: */ ! 2336: HostAdapter->FirstCompletedCCB = NULL; ! 2337: HostAdapter->LastCompletedCCB = NULL; ! 2338: /* ! 2339: Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, ! 2340: Command Successful Flag, Active Commands, and Commands Since Reset ! 2341: for each Target Device. ! 2342: */ ! 2343: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2344: { ! 2345: HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; ! 2346: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; ! 2347: HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; ! 2348: HostAdapter->ActiveCommands[TargetID] = 0; ! 2349: HostAdapter->CommandsSinceReset[TargetID] = 0; ! 2350: } ! 2351: /* ! 2352: FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. ! 2353: */ ! 2354: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done; ! 2355: /* ! 2356: Initialize the Outgoing and Incoming Mailbox pointers. ! 2357: */ ! 2358: HostAdapter->FirstOutgoingMailbox = ! 2359: (BusLogic_OutgoingMailbox_T *) HostAdapter->MailboxSpace; ! 2360: HostAdapter->LastOutgoingMailbox = ! 2361: HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; ! 2362: HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; ! 2363: HostAdapter->FirstIncomingMailbox = ! 2364: (BusLogic_IncomingMailbox_T *) (HostAdapter->LastOutgoingMailbox + 1); ! 2365: HostAdapter->LastIncomingMailbox = ! 2366: HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; ! 2367: HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; ! 2368: /* ! 2369: Initialize the Outgoing and Incoming Mailbox structures. ! 2370: */ ! 2371: memset(HostAdapter->FirstOutgoingMailbox, 0, ! 2372: HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T)); ! 2373: memset(HostAdapter->FirstIncomingMailbox, 0, ! 2374: HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T)); ! 2375: /* ! 2376: Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. ! 2377: */ ! 2378: ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; ! 2379: ExtendedMailboxRequest.BaseMailboxAddress = ! 2380: Virtual_to_Bus(HostAdapter->FirstOutgoingMailbox); ! 2381: if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, ! 2382: &ExtendedMailboxRequest, ! 2383: sizeof(ExtendedMailboxRequest), NULL, 0) < 0) ! 2384: return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); ! 2385: /* ! 2386: Enable Strict Round Robin Mode if supported by the Host Adapter. In ! 2387: Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing ! 2388: Mailbox for each new command, rather than scanning through all the ! 2389: Outgoing Mailboxes to find any that have new commands in them. Strict ! 2390: Round Robin Mode is significantly more efficient. ! 2391: */ ! 2392: if (HostAdapter->StrictRoundRobinModeSupport) ! 2393: { ! 2394: RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; ! 2395: if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, ! 2396: &RoundRobinModeRequest, ! 2397: sizeof(RoundRobinModeRequest), NULL, 0) < 0) ! 2398: return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); ! 2399: } ! 2400: /* ! 2401: For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB ! 2402: Format command to allow 32 Logical Units per Target Device. ! 2403: */ ! 2404: if (HostAdapter->ExtendedLUNSupport) ! 2405: { ! 2406: SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; ! 2407: if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, ! 2408: &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), ! 2409: NULL, 0) < 0) ! 2410: return BusLogic_Failure(HostAdapter, "SET CCB FORMAT"); ! 2411: } ! 2412: /* ! 2413: Announce Successful Initialization. ! 2414: */ ! 2415: Done: ! 2416: if (!HostAdapter->HostAdapterInitialized) ! 2417: { ! 2418: BusLogic_Info("*** %s Initialized Successfully ***\n", ! 2419: HostAdapter, HostAdapter->FullModelName); ! 2420: BusLogic_Info("\n", HostAdapter); ! 2421: } ! 2422: else BusLogic_Warning("*** %s Initialized Successfully ***\n", ! 2423: HostAdapter, HostAdapter->FullModelName); ! 2424: HostAdapter->HostAdapterInitialized = true; ! 2425: /* ! 2426: Indicate the Host Adapter Initialization completed successfully. ! 2427: */ ! 2428: return true; ! 2429: } ! 2430: ! 2431: ! 2432: /* ! 2433: BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible ! 2434: through Host Adapter. ! 2435: */ ! 2436: ! 2437: static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T ! 2438: *HostAdapter) ! 2439: { ! 2440: BusLogic_InstalledDevices_T InstalledDevices; ! 2441: BusLogic_InstalledDevices8_T InstalledDevicesID0to7; ! 2442: BusLogic_SetupInformation_T SetupInformation; ! 2443: BusLogic_SynchronousPeriod_T SynchronousPeriod; ! 2444: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 2445: int TargetID; ! 2446: /* ! 2447: Wait a few seconds between the Host Adapter Hard Reset which initiates ! 2448: a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get ! 2449: confused if they receive SCSI Commands too soon after a SCSI Bus Reset. ! 2450: */ ! 2451: BusLogic_Delay(HostAdapter->BusSettleTime); ! 2452: /* ! 2453: FlashPoint Host Adapters do not provide for Target Device Inquiry. ! 2454: */ ! 2455: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; ! 2456: /* ! 2457: Inhibit the Target Device Inquiry if requested. ! 2458: */ ! 2459: if (HostAdapter->DriverOptions != NULL && ! 2460: HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) ! 2461: return true; ! 2462: /* ! 2463: Issue the Inquire Target Devices command for host adapters with firmware ! 2464: version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command ! 2465: for older host adapters. This is necessary to force Synchronous Transfer ! 2466: Negotiation so that the Inquire Setup Information and Inquire Synchronous ! 2467: Period commands will return valid data. The Inquire Target Devices command ! 2468: is preferable to Inquire Installed Devices ID 0 to 7 since it only probes ! 2469: Logical Unit 0 of each Target Device. ! 2470: */ ! 2471: if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) ! 2472: { ! 2473: if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, ! 2474: &InstalledDevices, sizeof(InstalledDevices)) ! 2475: != sizeof(InstalledDevices)) ! 2476: return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES"); ! 2477: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2478: HostAdapter->TargetFlags[TargetID].TargetExists = ! 2479: (InstalledDevices & (1 << TargetID) ? true : false); ! 2480: } ! 2481: else ! 2482: { ! 2483: if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, ! 2484: NULL, 0, &InstalledDevicesID0to7, ! 2485: sizeof(InstalledDevicesID0to7)) ! 2486: != sizeof(InstalledDevicesID0to7)) ! 2487: return BusLogic_Failure(HostAdapter, ! 2488: "INQUIRE INSTALLED DEVICES ID 0 TO 7"); ! 2489: for (TargetID = 0; TargetID < 8; TargetID++) ! 2490: HostAdapter->TargetFlags[TargetID].TargetExists = ! 2491: (InstalledDevicesID0to7[TargetID] != 0 ? true : false); ! 2492: } ! 2493: /* ! 2494: Issue the Inquire Setup Information command. ! 2495: */ ! 2496: RequestedReplyLength = sizeof(SetupInformation); ! 2497: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, ! 2498: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 2499: &SetupInformation, sizeof(SetupInformation)) ! 2500: != sizeof(SetupInformation)) ! 2501: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); ! 2502: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2503: HostAdapter->SynchronousOffset[TargetID] = ! 2504: (TargetID < 8 ! 2505: ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset ! 2506: : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset); ! 2507: if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0) ! 2508: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2509: HostAdapter->TargetFlags[TargetID].WideTransfersActive = ! 2510: (TargetID < 8 ! 2511: ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) ! 2512: ? true : false) ! 2513: : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8)) ! 2514: ? true : false)); ! 2515: /* ! 2516: Issue the Inquire Synchronous Period command. ! 2517: */ ! 2518: if (HostAdapter->FirmwareVersion[0] >= '3') ! 2519: { ! 2520: RequestedReplyLength = sizeof(SynchronousPeriod); ! 2521: if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, ! 2522: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 2523: &SynchronousPeriod, sizeof(SynchronousPeriod)) ! 2524: != sizeof(SynchronousPeriod)) ! 2525: return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); ! 2526: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2527: HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; ! 2528: } ! 2529: else ! 2530: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2531: if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) ! 2532: HostAdapter->SynchronousPeriod[TargetID] = ! 2533: 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] ! 2534: .TransferPeriod; ! 2535: /* ! 2536: Indicate the Target Device Inquiry completed successfully. ! 2537: */ ! 2538: return true; ! 2539: } ! 2540: ! 2541: ! 2542: /* ! 2543: BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible ! 2544: through Host Adapter. ! 2545: */ ! 2546: ! 2547: static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T ! 2548: *HostAdapter) ! 2549: { ! 2550: int TargetID; ! 2551: /* ! 2552: Inhibit the Target Device Inquiry and Reporting if requested. ! 2553: */ ! 2554: if (BusLogic_MultiMasterHostAdapterP(HostAdapter) && ! 2555: HostAdapter->DriverOptions != NULL && ! 2556: HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) ! 2557: return; ! 2558: /* ! 2559: Report on the Target Devices found. ! 2560: */ ! 2561: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2562: { ! 2563: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 2564: if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported) ! 2565: { ! 2566: int SynchronousTransferRate = 0; ! 2567: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 2568: { ! 2569: boolean WideTransfersActive; ! 2570: FlashPoint_InquireTargetInfo( ! 2571: HostAdapter->CardHandle, TargetID, ! 2572: &HostAdapter->SynchronousPeriod[TargetID], ! 2573: &HostAdapter->SynchronousOffset[TargetID], ! 2574: &WideTransfersActive); ! 2575: TargetFlags->WideTransfersActive = WideTransfersActive; ! 2576: } ! 2577: else if (TargetFlags->WideTransfersSupported && ! 2578: (HostAdapter->WidePermitted & (1 << TargetID)) && ! 2579: strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0) ! 2580: TargetFlags->WideTransfersActive = true; ! 2581: if (HostAdapter->SynchronousPeriod[TargetID] > 0) ! 2582: SynchronousTransferRate = ! 2583: 100000 / HostAdapter->SynchronousPeriod[TargetID]; ! 2584: if (TargetFlags->WideTransfersActive) ! 2585: SynchronousTransferRate <<= 1; ! 2586: if (SynchronousTransferRate >= 9950) ! 2587: { ! 2588: SynchronousTransferRate = (SynchronousTransferRate + 50) / 100; ! 2589: BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at " ! 2590: "%d.%01d MB/sec, offset %d\n", ! 2591: HostAdapter, TargetID, ! 2592: HostAdapter->QueueDepth[TargetID], ! 2593: (TargetFlags->WideTransfersActive ? "Wide " : ""), ! 2594: SynchronousTransferRate / 10, ! 2595: SynchronousTransferRate % 10, ! 2596: HostAdapter->SynchronousOffset[TargetID]); ! 2597: } ! 2598: else if (SynchronousTransferRate > 0) ! 2599: { ! 2600: SynchronousTransferRate = (SynchronousTransferRate + 5) / 10; ! 2601: BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at " ! 2602: "%d.%02d MB/sec, offset %d\n", ! 2603: HostAdapter, TargetID, ! 2604: HostAdapter->QueueDepth[TargetID], ! 2605: (TargetFlags->WideTransfersActive ? "Wide " : ""), ! 2606: SynchronousTransferRate / 100, ! 2607: SynchronousTransferRate % 100, ! 2608: HostAdapter->SynchronousOffset[TargetID]); ! 2609: } ! 2610: else BusLogic_Info("Target %d: Queue Depth %d, Asynchronous\n", ! 2611: HostAdapter, TargetID, ! 2612: HostAdapter->QueueDepth[TargetID]); ! 2613: TargetFlags->TargetInfoReported = true; ! 2614: } ! 2615: } ! 2616: } ! 2617: ! 2618: ! 2619: /* ! 2620: BusLogic_InitializeHostStructure initializes the fields in the SCSI Host ! 2621: structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the ! 2622: SCSI Host structure are intentionally left uninitialized, as this driver ! 2623: handles acquisition and release of these resources explicitly, as well as ! 2624: ensuring exclusive access to the Host Adapter hardware and data structures ! 2625: through explicit acquisition and release of the Host Adapter's Lock. ! 2626: */ ! 2627: ! 2628: static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T ! 2629: *HostAdapter, ! 2630: SCSI_Host_T *Host) ! 2631: { ! 2632: Host->max_id = HostAdapter->MaxTargetDevices; ! 2633: Host->max_lun = HostAdapter->MaxLogicalUnits; ! 2634: Host->max_channel = 0; ! 2635: Host->unique_id = HostAdapter->IO_Address; ! 2636: Host->this_id = HostAdapter->SCSI_ID; ! 2637: Host->can_queue = HostAdapter->DriverQueueDepth; ! 2638: Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; ! 2639: Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; ! 2640: Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth; ! 2641: } ! 2642: ! 2643: ! 2644: /* ! 2645: BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based ! 2646: on the Host Adapter's Total Queue Depth and the number, type, speed, and ! 2647: capabilities of the Target Devices. When called for the last Host Adapter, ! 2648: it reports on the Target Device Information for all BusLogic Host Adapters ! 2649: since all the Target Devices have now been probed. ! 2650: */ ! 2651: ! 2652: static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host, ! 2653: SCSI_Device_T *DeviceList) ! 2654: { ! 2655: BusLogic_HostAdapter_T *HostAdapter = ! 2656: (BusLogic_HostAdapter_T *) Host->hostdata; ! 2657: int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0; ! 2658: int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0; ! 2659: int AllocatedQueueDepth = 0; ! 2660: SCSI_Device_T *Device; ! 2661: int TargetID; ! 2662: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2663: if (HostAdapter->TargetFlags[TargetID].TargetExists) ! 2664: { ! 2665: int QueueDepth = HostAdapter->QueueDepth[TargetID]; ! 2666: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && ! 2667: (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) ! 2668: { ! 2669: TaggedDeviceCount++; ! 2670: if (QueueDepth == 0) AutomaticTaggedDeviceCount++; ! 2671: } ! 2672: else ! 2673: { ! 2674: UntaggedDeviceCount++; ! 2675: if (QueueDepth == 0 || ! 2676: QueueDepth > HostAdapter->UntaggedQueueDepth) ! 2677: { ! 2678: QueueDepth = HostAdapter->UntaggedQueueDepth; ! 2679: HostAdapter->QueueDepth[TargetID] = QueueDepth; ! 2680: } ! 2681: } ! 2682: AllocatedQueueDepth += QueueDepth; ! 2683: if (QueueDepth == 1) ! 2684: HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); ! 2685: } ! 2686: HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount; ! 2687: if (AutomaticTaggedDeviceCount > 0) ! 2688: { ! 2689: AutomaticTaggedQueueDepth = ! 2690: (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth) ! 2691: / AutomaticTaggedDeviceCount; ! 2692: if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth) ! 2693: AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth; ! 2694: if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth) ! 2695: AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth; ! 2696: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 2697: if (HostAdapter->TargetFlags[TargetID].TargetExists && ! 2698: HostAdapter->QueueDepth[TargetID] == 0) ! 2699: { ! 2700: AllocatedQueueDepth += AutomaticTaggedQueueDepth; ! 2701: HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth; ! 2702: } ! 2703: } ! 2704: for (Device = DeviceList; Device != NULL; Device = Device->next) ! 2705: if (Device->host == Host) ! 2706: Device->queue_depth = HostAdapter->QueueDepth[Device->id]; ! 2707: /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */ ! 2708: AllocatedQueueDepth += HostAdapter->TargetDeviceCount; ! 2709: if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth) ! 2710: AllocatedQueueDepth = HostAdapter->DriverQueueDepth; ! 2711: BusLogic_CreateAdditionalCCBs(HostAdapter, ! 2712: AllocatedQueueDepth ! 2713: - HostAdapter->AllocatedCCBs, ! 2714: false); ! 2715: if (HostAdapter == BusLogic_LastRegisteredHostAdapter) ! 2716: for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; ! 2717: HostAdapter != NULL; ! 2718: HostAdapter = HostAdapter->Next) ! 2719: BusLogic_ReportTargetDeviceInfo(HostAdapter); ! 2720: } ! 2721: ! 2722: ! 2723: /* ! 2724: BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard ! 2725: I/O Addresses where they may be located, initializing, registering, and ! 2726: reporting the configuration of each BusLogic Host Adapter it finds. It ! 2727: returns the number of BusLogic Host Adapters successfully initialized and ! 2728: registered. ! 2729: */ ! 2730: ! 2731: int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate) ! 2732: { ! 2733: int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; ! 2734: BusLogic_HostAdapter_T *PrototypeHostAdapter; ! 2735: if (BusLogic_ProbeOptions.NoProbe) return 0; ! 2736: BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *) ! 2737: kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T), ! 2738: GFP_ATOMIC); ! 2739: if (BusLogic_ProbeInfoList == NULL) ! 2740: { ! 2741: BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); ! 2742: return 0; ! 2743: } ! 2744: memset(BusLogic_ProbeInfoList, 0, ! 2745: BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T)); ! 2746: PrototypeHostAdapter = (BusLogic_HostAdapter_T *) ! 2747: kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC); ! 2748: if (PrototypeHostAdapter == NULL) ! 2749: { ! 2750: kfree(BusLogic_ProbeInfoList); ! 2751: BusLogic_Error("BusLogic: Unable to allocate Prototype " ! 2752: "Host Adapter\n", NULL); ! 2753: return 0; ! 2754: } ! 2755: memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); ! 2756: if (BusLogic_Options != NULL) ! 2757: BusLogic_ParseDriverOptions(BusLogic_Options); ! 2758: BusLogic_InitializeProbeInfoList(PrototypeHostAdapter); ! 2759: for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) ! 2760: { ! 2761: BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex]; ! 2762: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter; ! 2763: SCSI_Host_T *Host; ! 2764: if (ProbeInfo->IO_Address == 0) continue; ! 2765: memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); ! 2766: HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType; ! 2767: HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType; ! 2768: HostAdapter->IO_Address = ProbeInfo->IO_Address; ! 2769: HostAdapter->PCI_Address = ProbeInfo->PCI_Address; ! 2770: HostAdapter->Bus = ProbeInfo->Bus; ! 2771: HostAdapter->Device = ProbeInfo->Device; ! 2772: HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; ! 2773: HostAdapter->AddressCount = ! 2774: BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; ! 2775: /* ! 2776: Probe the Host Adapter. If unsuccessful, abort further initialization. ! 2777: */ ! 2778: if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue; ! 2779: /* ! 2780: Hard Reset the Host Adapter. If unsuccessful, abort further ! 2781: initialization. ! 2782: */ ! 2783: if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue; ! 2784: /* ! 2785: Check the Host Adapter. If unsuccessful, abort further initialization. ! 2786: */ ! 2787: if (!BusLogic_CheckHostAdapter(HostAdapter)) continue; ! 2788: /* ! 2789: Initialize the Driver Options field if provided. ! 2790: */ ! 2791: if (DriverOptionsIndex < BusLogic_DriverOptionsCount) ! 2792: HostAdapter->DriverOptions = ! 2793: &BusLogic_DriverOptions[DriverOptionsIndex++]; ! 2794: /* ! 2795: Announce the Driver Version and Date, Author's Name, Copyright Notice, ! 2796: and Electronic Mail Address. ! 2797: */ ! 2798: BusLogic_AnnounceDriver(HostAdapter); ! 2799: /* ! 2800: Register usage of the I/O Address range. From this point onward, any ! 2801: failure will be assumed to be due to a problem with the Host Adapter, ! 2802: rather than due to having mistakenly identified this port as belonging ! 2803: to a BusLogic Host Adapter. The I/O Address range will not be ! 2804: released, thereby preventing it from being incorrectly identified as ! 2805: any other type of Host Adapter. ! 2806: */ ! 2807: request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, ! 2808: "BusLogic"); ! 2809: /* ! 2810: Register the SCSI Host structure. ! 2811: */ ! 2812: Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T)); ! 2813: HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; ! 2814: memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T)); ! 2815: HostAdapter->SCSI_Host = Host; ! 2816: HostAdapter->HostNumber = Host->host_no; ! 2817: Host->select_queue_depths = BusLogic_SelectQueueDepths; ! 2818: /* ! 2819: Add Host Adapter to the end of the list of registered BusLogic ! 2820: Host Adapters. ! 2821: */ ! 2822: BusLogic_RegisterHostAdapter(HostAdapter); ! 2823: /* ! 2824: Read the Host Adapter Configuration, Configure the Host Adapter, ! 2825: Acquire the System Resources necessary to use the Host Adapter, then ! 2826: Create the Initial CCBs, Initialize the Host Adapter, and finally ! 2827: perform Target Device Inquiry. ! 2828: */ ! 2829: if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && ! 2830: BusLogic_ReportHostAdapterConfiguration(HostAdapter) && ! 2831: BusLogic_AcquireResources(HostAdapter) && ! 2832: BusLogic_CreateInitialCCBs(HostAdapter) && ! 2833: BusLogic_InitializeHostAdapter(HostAdapter) && ! 2834: BusLogic_TargetDeviceInquiry(HostAdapter)) ! 2835: { ! 2836: /* ! 2837: Initialization has been completed successfully. Release and ! 2838: re-register usage of the I/O Address range so that the Model ! 2839: Name of the Host Adapter will appear, and initialize the SCSI ! 2840: Host structure. ! 2841: */ ! 2842: release_region(HostAdapter->IO_Address, ! 2843: HostAdapter->AddressCount); ! 2844: request_region(HostAdapter->IO_Address, ! 2845: HostAdapter->AddressCount, ! 2846: HostAdapter->FullModelName); ! 2847: BusLogic_InitializeHostStructure(HostAdapter, Host); ! 2848: BusLogicHostAdapterCount++; ! 2849: } ! 2850: else ! 2851: { ! 2852: /* ! 2853: An error occurred during Host Adapter Configuration Querying, Host ! 2854: Adapter Configuration, Resource Acquisition, CCB Creation, Host ! 2855: Adapter Initialization, or Target Device Inquiry, so remove Host ! 2856: Adapter from the list of registered BusLogic Host Adapters, destroy ! 2857: the CCBs, Release the System Resources, and Unregister the SCSI ! 2858: Host. ! 2859: */ ! 2860: BusLogic_DestroyCCBs(HostAdapter); ! 2861: BusLogic_ReleaseResources(HostAdapter); ! 2862: BusLogic_UnregisterHostAdapter(HostAdapter); ! 2863: scsi_unregister(Host); ! 2864: } ! 2865: } ! 2866: kfree(PrototypeHostAdapter); ! 2867: kfree(BusLogic_ProbeInfoList); ! 2868: BusLogic_ProbeInfoList = NULL; ! 2869: return BusLogicHostAdapterCount; ! 2870: } ! 2871: ! 2872: ! 2873: /* ! 2874: BusLogic_ReleaseHostAdapter releases all resources previously acquired to ! 2875: support a specific Host Adapter, including the I/O Address range, and ! 2876: unregisters the BusLogic Host Adapter. ! 2877: */ ! 2878: ! 2879: int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host) ! 2880: { ! 2881: BusLogic_HostAdapter_T *HostAdapter = ! 2882: (BusLogic_HostAdapter_T *) Host->hostdata; ! 2883: /* ! 2884: FlashPoint Host Adapters must first be released by the FlashPoint ! 2885: SCCB Manager. ! 2886: */ ! 2887: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 2888: FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle); ! 2889: /* ! 2890: Destroy the CCBs and release any system resources acquired to ! 2891: support Host Adapter. ! 2892: */ ! 2893: BusLogic_DestroyCCBs(HostAdapter); ! 2894: BusLogic_ReleaseResources(HostAdapter); ! 2895: /* ! 2896: Release usage of the I/O Address range. ! 2897: */ ! 2898: release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); ! 2899: /* ! 2900: Remove Host Adapter from the list of registered BusLogic Host Adapters. ! 2901: */ ! 2902: BusLogic_UnregisterHostAdapter(HostAdapter); ! 2903: return 0; ! 2904: } ! 2905: ! 2906: ! 2907: /* ! 2908: BusLogic_QueueCompletedCCB queues CCB for completion processing. ! 2909: */ ! 2910: ! 2911: static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB) ! 2912: { ! 2913: BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; ! 2914: CCB->Status = BusLogic_CCB_Completed; ! 2915: CCB->Next = NULL; ! 2916: if (HostAdapter->FirstCompletedCCB == NULL) ! 2917: { ! 2918: HostAdapter->FirstCompletedCCB = CCB; ! 2919: HostAdapter->LastCompletedCCB = CCB; ! 2920: } ! 2921: else ! 2922: { ! 2923: HostAdapter->LastCompletedCCB->Next = CCB; ! 2924: HostAdapter->LastCompletedCCB = CCB; ! 2925: } ! 2926: HostAdapter->ActiveCommands[CCB->TargetID]--; ! 2927: } ! 2928: ! 2929: ! 2930: /* ! 2931: BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from ! 2932: the Host Adapter Status and Target Device Status. ! 2933: */ ! 2934: ! 2935: static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter, ! 2936: BusLogic_HostAdapterStatus_T ! 2937: HostAdapterStatus, ! 2938: BusLogic_TargetDeviceStatus_T ! 2939: TargetDeviceStatus) ! 2940: { ! 2941: int HostStatus; ! 2942: switch (HostAdapterStatus) ! 2943: { ! 2944: case BusLogic_CommandCompletedNormally: ! 2945: case BusLogic_LinkedCommandCompleted: ! 2946: case BusLogic_LinkedCommandCompletedWithFlag: ! 2947: HostStatus = DID_OK; ! 2948: break; ! 2949: case BusLogic_SCSISelectionTimeout: ! 2950: HostStatus = DID_TIME_OUT; ! 2951: break; ! 2952: case BusLogic_InvalidOutgoingMailboxActionCode: ! 2953: case BusLogic_InvalidCommandOperationCode: ! 2954: case BusLogic_InvalidCommandParameter: ! 2955: BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", ! 2956: HostAdapter, HostAdapterStatus); ! 2957: case BusLogic_DataUnderRun: ! 2958: case BusLogic_DataOverRun: ! 2959: case BusLogic_UnexpectedBusFree: ! 2960: case BusLogic_LinkedCCBhasInvalidLUN: ! 2961: case BusLogic_AutoRequestSenseFailed: ! 2962: case BusLogic_TaggedQueuingMessageRejected: ! 2963: case BusLogic_UnsupportedMessageReceived: ! 2964: case BusLogic_HostAdapterHardwareFailed: ! 2965: case BusLogic_TargetDeviceReconnectedImproperly: ! 2966: case BusLogic_AbortQueueGenerated: ! 2967: case BusLogic_HostAdapterSoftwareError: ! 2968: case BusLogic_HostAdapterHardwareTimeoutError: ! 2969: case BusLogic_SCSIParityErrorDetected: ! 2970: HostStatus = DID_ERROR; ! 2971: break; ! 2972: case BusLogic_InvalidBusPhaseRequested: ! 2973: case BusLogic_TargetFailedResponseToATN: ! 2974: case BusLogic_HostAdapterAssertedRST: ! 2975: case BusLogic_OtherDeviceAssertedRST: ! 2976: case BusLogic_HostAdapterAssertedBusDeviceReset: ! 2977: HostStatus = DID_RESET; ! 2978: break; ! 2979: default: ! 2980: BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", ! 2981: HostAdapter, HostAdapterStatus); ! 2982: HostStatus = DID_ERROR; ! 2983: break; ! 2984: } ! 2985: return (HostStatus << 16) | TargetDeviceStatus; ! 2986: } ! 2987: ! 2988: ! 2989: /* ! 2990: BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any ! 2991: Incoming Mailbox entries for completion processing. ! 2992: */ ! 2993: ! 2994: static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter) ! 2995: { ! 2996: /* ! 2997: Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving ! 2998: any completed CCBs for further processing. It is essential that for each ! 2999: CCB and SCSI Command issued, command completion processing is performed ! 3000: exactly once. Therefore, only Incoming Mailboxes with completion code ! 3001: Command Completed Without Error, Command Completed With Error, or Command ! 3002: Aborted At Host Request are saved for completion processing. When an ! 3003: Incoming Mailbox has a completion code of Aborted Command Not Found, the ! 3004: CCB had already completed or been aborted before the current Abort request ! 3005: was processed, and so completion processing has already occurred and no ! 3006: further action should be taken. ! 3007: */ ! 3008: BusLogic_IncomingMailbox_T *NextIncomingMailbox = ! 3009: HostAdapter->NextIncomingMailbox; ! 3010: BusLogic_CompletionCode_T CompletionCode; ! 3011: while ((CompletionCode = NextIncomingMailbox->CompletionCode) != ! 3012: BusLogic_IncomingMailboxFree) ! 3013: { ! 3014: BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ! 3015: Bus_to_Virtual(NextIncomingMailbox->CCB); ! 3016: if (CompletionCode != BusLogic_AbortedCommandNotFound) ! 3017: { ! 3018: if (CCB->Status == BusLogic_CCB_Active || ! 3019: CCB->Status == BusLogic_CCB_Reset) ! 3020: { ! 3021: /* ! 3022: Save the Completion Code for this CCB and queue the CCB ! 3023: for completion processing. ! 3024: */ ! 3025: CCB->CompletionCode = CompletionCode; ! 3026: BusLogic_QueueCompletedCCB(CCB); ! 3027: } ! 3028: else ! 3029: { ! 3030: /* ! 3031: If a CCB ever appears in an Incoming Mailbox and is not marked ! 3032: as status Active or Reset, then there is most likely a bug in ! 3033: the Host Adapter firmware. ! 3034: */ ! 3035: BusLogic_Warning("Illegal CCB #%ld status %d in " ! 3036: "Incoming Mailbox\n", HostAdapter, ! 3037: CCB->SerialNumber, CCB->Status); ! 3038: } ! 3039: } ! 3040: NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; ! 3041: if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) ! 3042: NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; ! 3043: } ! 3044: HostAdapter->NextIncomingMailbox = NextIncomingMailbox; ! 3045: } ! 3046: ! 3047: ! 3048: /* ! 3049: BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host ! 3050: Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and ! 3051: calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock ! 3052: should already have been acquired by the caller. ! 3053: */ ! 3054: ! 3055: static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter) ! 3056: { ! 3057: if (HostAdapter->ProcessCompletedCCBsActive) return; ! 3058: HostAdapter->ProcessCompletedCCBsActive = true; ! 3059: while (HostAdapter->FirstCompletedCCB != NULL) ! 3060: { ! 3061: BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB; ! 3062: SCSI_Command_T *Command = CCB->Command; ! 3063: HostAdapter->FirstCompletedCCB = CCB->Next; ! 3064: if (HostAdapter->FirstCompletedCCB == NULL) ! 3065: HostAdapter->LastCompletedCCB = NULL; ! 3066: /* ! 3067: Process the Completed CCB. ! 3068: */ ! 3069: if (CCB->Opcode == BusLogic_BusDeviceReset) ! 3070: { ! 3071: int TargetID = CCB->TargetID; ! 3072: BusLogic_Warning("Bus Device Reset CCB #%ld to Target " ! 3073: "%d Completed\n", HostAdapter, ! 3074: CCB->SerialNumber, TargetID); ! 3075: BusLogic_IncrementErrorCounter( ! 3076: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); ! 3077: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; ! 3078: HostAdapter->CommandsSinceReset[TargetID] = 0; ! 3079: HostAdapter->LastResetCompleted[TargetID] = jiffies; ! 3080: /* ! 3081: Place CCB back on the Host Adapter's free list. ! 3082: */ ! 3083: BusLogic_DeallocateCCB(CCB); ! 3084: /* ! 3085: Bus Device Reset CCBs have the Command field non-NULL only when a ! 3086: Bus Device Reset was requested for a Command that did not have a ! 3087: currently active CCB in the Host Adapter (i.e., a Synchronous ! 3088: Bus Device Reset), and hence would not have its Completion Routine ! 3089: called otherwise. ! 3090: */ ! 3091: while (Command != NULL) ! 3092: { ! 3093: SCSI_Command_T *NextCommand = Command->reset_chain; ! 3094: Command->reset_chain = NULL; ! 3095: Command->result = DID_RESET << 16; ! 3096: Command->scsi_done(Command); ! 3097: Command = NextCommand; ! 3098: } ! 3099: /* ! 3100: Iterate over the CCBs for this Host Adapter performing completion ! 3101: processing for any CCBs marked as Reset for this Target. ! 3102: */ ! 3103: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3104: if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) ! 3105: { ! 3106: Command = CCB->Command; ! 3107: BusLogic_DeallocateCCB(CCB); ! 3108: HostAdapter->ActiveCommands[TargetID]--; ! 3109: Command->result = DID_RESET << 16; ! 3110: Command->scsi_done(Command); ! 3111: } ! 3112: HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; ! 3113: } ! 3114: else ! 3115: { ! 3116: /* ! 3117: Translate the Completion Code, Host Adapter Status, and Target ! 3118: Device Status into a SCSI Subsystem Result Code. ! 3119: */ ! 3120: switch (CCB->CompletionCode) ! 3121: { ! 3122: case BusLogic_IncomingMailboxFree: ! 3123: case BusLogic_AbortedCommandNotFound: ! 3124: case BusLogic_InvalidCCB: ! 3125: BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", ! 3126: HostAdapter, CCB->SerialNumber, CCB->TargetID); ! 3127: break; ! 3128: case BusLogic_CommandCompletedWithoutError: ! 3129: HostAdapter->TargetStatistics[CCB->TargetID] ! 3130: .CommandsCompleted++; ! 3131: HostAdapter->TargetFlags[CCB->TargetID] ! 3132: .CommandSuccessfulFlag = true; ! 3133: Command->result = DID_OK << 16; ! 3134: break; ! 3135: case BusLogic_CommandAbortedAtHostRequest: ! 3136: BusLogic_Warning("CCB #%ld to Target %d Aborted\n", ! 3137: HostAdapter, CCB->SerialNumber, CCB->TargetID); ! 3138: BusLogic_IncrementErrorCounter( ! 3139: &HostAdapter->TargetStatistics[CCB->TargetID] ! 3140: .CommandAbortsCompleted); ! 3141: Command->result = DID_ABORT << 16; ! 3142: break; ! 3143: case BusLogic_CommandCompletedWithError: ! 3144: Command->result = ! 3145: BusLogic_ComputeResultCode(HostAdapter, ! 3146: CCB->HostAdapterStatus, ! 3147: CCB->TargetDeviceStatus); ! 3148: if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) ! 3149: { ! 3150: HostAdapter->TargetStatistics[CCB->TargetID] ! 3151: .CommandsCompleted++; ! 3152: if (BusLogic_GlobalOptions.TraceErrors) ! 3153: { ! 3154: int i; ! 3155: BusLogic_Notice("CCB #%ld Target %d: Result %X Host " ! 3156: "Adapter Status %02X " ! 3157: "Target Status %02X\n", ! 3158: HostAdapter, CCB->SerialNumber, ! 3159: CCB->TargetID, Command->result, ! 3160: CCB->HostAdapterStatus, ! 3161: CCB->TargetDeviceStatus); ! 3162: BusLogic_Notice("CDB ", HostAdapter); ! 3163: for (i = 0; i < CCB->CDB_Length; i++) ! 3164: BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); ! 3165: BusLogic_Notice("\n", HostAdapter); ! 3166: BusLogic_Notice("Sense ", HostAdapter); ! 3167: for (i = 0; i < CCB->SenseDataLength; i++) ! 3168: BusLogic_Notice(" %02X", HostAdapter, ! 3169: Command->sense_buffer[i]); ! 3170: BusLogic_Notice("\n", HostAdapter); ! 3171: } ! 3172: } ! 3173: break; ! 3174: } ! 3175: /* ! 3176: When an INQUIRY command completes normally, save the ! 3177: CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit ! 3178: Wide Data Transfers Supported) bits. ! 3179: */ ! 3180: if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && ! 3181: CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) ! 3182: { ! 3183: BusLogic_TargetFlags_T *TargetFlags = ! 3184: &HostAdapter->TargetFlags[CCB->TargetID]; ! 3185: SCSI_Inquiry_T *InquiryResult = ! 3186: (SCSI_Inquiry_T *) Command->request_buffer; ! 3187: TargetFlags->TargetExists = true; ! 3188: TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; ! 3189: TargetFlags->WideTransfersSupported = InquiryResult->WBus16; ! 3190: } ! 3191: /* ! 3192: Place CCB back on the Host Adapter's free list. ! 3193: */ ! 3194: BusLogic_DeallocateCCB(CCB); ! 3195: /* ! 3196: Call the SCSI Command Completion Routine. ! 3197: */ ! 3198: Command->scsi_done(Command); ! 3199: } ! 3200: } ! 3201: HostAdapter->ProcessCompletedCCBsActive = false; ! 3202: } ! 3203: ! 3204: ! 3205: /* ! 3206: BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host ! 3207: Adapters. ! 3208: */ ! 3209: ! 3210: static void BusLogic_InterruptHandler(int IRQ_Channel, ! 3211: void *DeviceIdentifier, ! 3212: Registers_T *InterruptRegisters) ! 3213: { ! 3214: BusLogic_HostAdapter_T *HostAdapter = ! 3215: (BusLogic_HostAdapter_T *) DeviceIdentifier; ! 3216: ProcessorFlags_T ProcessorFlags; ! 3217: /* ! 3218: Acquire exclusive access to Host Adapter. ! 3219: */ ! 3220: BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags); ! 3221: /* ! 3222: Handle Interrupts appropriately for each Host Adapter type. ! 3223: */ ! 3224: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3225: { ! 3226: BusLogic_InterruptRegister_T InterruptRegister; ! 3227: /* ! 3228: Read the Host Adapter Interrupt Register. ! 3229: */ ! 3230: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); ! 3231: if (InterruptRegister.Bits.InterruptValid) ! 3232: { ! 3233: /* ! 3234: Acknowledge the interrupt and reset the Host Adapter ! 3235: Interrupt Register. ! 3236: */ ! 3237: BusLogic_InterruptReset(HostAdapter); ! 3238: /* ! 3239: Process valid External SCSI Bus Reset and Incoming Mailbox ! 3240: Loaded Interrupts. Command Complete Interrupts are noted, ! 3241: and Outgoing Mailbox Available Interrupts are ignored, as ! 3242: they are never enabled. ! 3243: */ ! 3244: if (InterruptRegister.Bits.ExternalBusReset) ! 3245: HostAdapter->HostAdapterExternalReset = true; ! 3246: else if (InterruptRegister.Bits.IncomingMailboxLoaded) ! 3247: BusLogic_ScanIncomingMailboxes(HostAdapter); ! 3248: else if (InterruptRegister.Bits.CommandComplete) ! 3249: HostAdapter->HostAdapterCommandCompleted = true; ! 3250: } ! 3251: } ! 3252: else ! 3253: { ! 3254: /* ! 3255: Check if there is a pending interrupt for this Host Adapter. ! 3256: */ ! 3257: if (FlashPoint_InterruptPending(HostAdapter->CardHandle)) ! 3258: switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) ! 3259: { ! 3260: case FlashPoint_NormalInterrupt: ! 3261: break; ! 3262: case FlashPoint_ExternalBusReset: ! 3263: HostAdapter->HostAdapterExternalReset = true; ! 3264: break; ! 3265: case FlashPoint_InternalError: ! 3266: BusLogic_Warning("Internal FlashPoint Error detected" ! 3267: " - Resetting Host Adapter\n", HostAdapter); ! 3268: HostAdapter->HostAdapterInternalError = true; ! 3269: break; ! 3270: } ! 3271: } ! 3272: /* ! 3273: Process any completed CCBs. ! 3274: */ ! 3275: if (HostAdapter->FirstCompletedCCB != NULL) ! 3276: BusLogic_ProcessCompletedCCBs(HostAdapter); ! 3277: /* ! 3278: Reset the Host Adapter if requested. ! 3279: */ ! 3280: if (HostAdapter->HostAdapterExternalReset || ! 3281: HostAdapter->HostAdapterInternalError) ! 3282: { ! 3283: BusLogic_ResetHostAdapter(HostAdapter, NULL, 0); ! 3284: HostAdapter->HostAdapterExternalReset = false; ! 3285: HostAdapter->HostAdapterInternalError = false; ! 3286: scsi_mark_host_reset(HostAdapter->SCSI_Host); ! 3287: } ! 3288: /* ! 3289: Release exclusive access to Host Adapter. ! 3290: */ ! 3291: BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags); ! 3292: } ! 3293: ! 3294: ! 3295: /* ! 3296: BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing ! 3297: Mailbox for execution by Host Adapter. The Host Adapter's Lock should ! 3298: already have been acquired by the caller. ! 3299: */ ! 3300: ! 3301: static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T ! 3302: *HostAdapter, ! 3303: BusLogic_ActionCode_T ActionCode, ! 3304: BusLogic_CCB_T *CCB) ! 3305: { ! 3306: BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; ! 3307: NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; ! 3308: if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) ! 3309: { ! 3310: CCB->Status = BusLogic_CCB_Active; ! 3311: /* ! 3312: The CCB field must be written before the Action Code field since ! 3313: the Host Adapter is operating asynchronously and the locking code ! 3314: does not protect against simultaneous access by the Host Adapter. ! 3315: */ ! 3316: NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB); ! 3317: NextOutgoingMailbox->ActionCode = ActionCode; ! 3318: BusLogic_StartMailboxCommand(HostAdapter); ! 3319: if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) ! 3320: NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; ! 3321: HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; ! 3322: if (ActionCode == BusLogic_MailboxStartCommand) ! 3323: { ! 3324: HostAdapter->ActiveCommands[CCB->TargetID]++; ! 3325: if (CCB->Opcode != BusLogic_BusDeviceReset) ! 3326: HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; ! 3327: } ! 3328: return true; ! 3329: } ! 3330: return false; ! 3331: } ! 3332: ! 3333: ! 3334: /* ! 3335: BusLogic_QueueCommand creates a CCB for Command and places it into an ! 3336: Outgoing Mailbox for execution by the associated Host Adapter. ! 3337: */ ! 3338: ! 3339: int BusLogic_QueueCommand(SCSI_Command_T *Command, ! 3340: void (*CompletionRoutine)(SCSI_Command_T *)) ! 3341: { ! 3342: BusLogic_HostAdapter_T *HostAdapter = ! 3343: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 3344: BusLogic_TargetFlags_T *TargetFlags = ! 3345: &HostAdapter->TargetFlags[Command->target]; ! 3346: BusLogic_TargetStatistics_T *TargetStatistics = ! 3347: HostAdapter->TargetStatistics; ! 3348: unsigned char *CDB = Command->cmnd; ! 3349: int CDB_Length = Command->cmd_len; ! 3350: int TargetID = Command->target; ! 3351: int LogicalUnit = Command->lun; ! 3352: void *BufferPointer = Command->request_buffer; ! 3353: int BufferLength = Command->request_bufflen; ! 3354: int SegmentCount = Command->use_sg; ! 3355: ProcessorFlags_T ProcessorFlags; ! 3356: BusLogic_CCB_T *CCB; ! 3357: /* ! 3358: SCSI REQUEST_SENSE commands will be executed automatically by the Host ! 3359: Adapter for any errors, so they should not be executed explicitly unless ! 3360: the Sense Data is zero indicating that no error occurred. ! 3361: */ ! 3362: if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) ! 3363: { ! 3364: Command->result = DID_OK << 16; ! 3365: CompletionRoutine(Command); ! 3366: return 0; ! 3367: } ! 3368: /* ! 3369: Acquire exclusive access to Host Adapter. ! 3370: */ ! 3371: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3372: /* ! 3373: Allocate a CCB from the Host Adapter's free list. In the unlikely event ! 3374: that there are none available and memory allocation fails, wait 1 second ! 3375: and try again. If that fails, the Host Adapter is probably hung so signal ! 3376: an error as a Host Adapter Hard Reset should be initiated soon. ! 3377: */ ! 3378: CCB = BusLogic_AllocateCCB(HostAdapter); ! 3379: if (CCB == NULL) ! 3380: { ! 3381: BusLogic_Delay(1); ! 3382: CCB = BusLogic_AllocateCCB(HostAdapter); ! 3383: if (CCB == NULL) ! 3384: { ! 3385: Command->result = DID_ERROR << 16; ! 3386: CompletionRoutine(Command); ! 3387: goto Done; ! 3388: } ! 3389: } ! 3390: /* ! 3391: Initialize the fields in the BusLogic Command Control Block (CCB). ! 3392: */ ! 3393: if (SegmentCount == 0) ! 3394: { ! 3395: CCB->Opcode = BusLogic_InitiatorCCB; ! 3396: CCB->DataLength = BufferLength; ! 3397: CCB->DataPointer = Virtual_to_Bus(BufferPointer); ! 3398: } ! 3399: else ! 3400: { ! 3401: SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer; ! 3402: int Segment; ! 3403: CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; ! 3404: CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T); ! 3405: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3406: CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList); ! 3407: else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList); ! 3408: for (Segment = 0; Segment < SegmentCount; Segment++) ! 3409: { ! 3410: CCB->ScatterGatherList[Segment].SegmentByteCount = ! 3411: ScatterList[Segment].length; ! 3412: CCB->ScatterGatherList[Segment].SegmentDataPointer = ! 3413: Virtual_to_Bus(ScatterList[Segment].address); ! 3414: } ! 3415: } ! 3416: switch (CDB[0]) ! 3417: { ! 3418: case READ_6: ! 3419: case READ_10: ! 3420: CCB->DataDirection = BusLogic_DataInLengthChecked; ! 3421: TargetStatistics[TargetID].ReadCommands++; ! 3422: BusLogic_IncrementByteCounter( ! 3423: &TargetStatistics[TargetID].TotalBytesRead, BufferLength); ! 3424: BusLogic_IncrementSizeBucket( ! 3425: TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength); ! 3426: break; ! 3427: case WRITE_6: ! 3428: case WRITE_10: ! 3429: CCB->DataDirection = BusLogic_DataOutLengthChecked; ! 3430: TargetStatistics[TargetID].WriteCommands++; ! 3431: BusLogic_IncrementByteCounter( ! 3432: &TargetStatistics[TargetID].TotalBytesWritten, BufferLength); ! 3433: BusLogic_IncrementSizeBucket( ! 3434: TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength); ! 3435: break; ! 3436: default: ! 3437: CCB->DataDirection = BusLogic_UncheckedDataTransfer; ! 3438: break; ! 3439: } ! 3440: CCB->CDB_Length = CDB_Length; ! 3441: CCB->SenseDataLength = sizeof(Command->sense_buffer); ! 3442: CCB->HostAdapterStatus = 0; ! 3443: CCB->TargetDeviceStatus = 0; ! 3444: CCB->TargetID = TargetID; ! 3445: CCB->LogicalUnit = LogicalUnit; ! 3446: CCB->TagEnable = false; ! 3447: CCB->LegacyTagEnable = false; ! 3448: /* ! 3449: BusLogic recommends that after a Reset the first couple of commands that ! 3450: are sent to a Target Device be sent in a non Tagged Queue fashion so that ! 3451: the Host Adapter and Target Device can establish Synchronous and Wide ! 3452: Transfer before Queue Tag messages can interfere with the Synchronous and ! 3453: Wide Negotiation messages. By waiting to enable Tagged Queuing until after ! 3454: the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is ! 3455: assured that after a Reset any pending commands are requeued before Tagged ! 3456: Queuing is enabled and that the Tagged Queuing message will not occur while ! 3457: the partition table is being printed. In addition, some devices do not ! 3458: properly handle the transition from non-tagged to tagged commands, so it is ! 3459: necessary to wait until there are no pending commands for a target device ! 3460: before queuing tagged commands. ! 3461: */ ! 3462: if (HostAdapter->CommandsSinceReset[TargetID]++ >= ! 3463: BusLogic_MaxTaggedQueueDepth && ! 3464: !TargetFlags->TaggedQueuingActive && ! 3465: HostAdapter->ActiveCommands[TargetID] == 0 && ! 3466: TargetFlags->TaggedQueuingSupported && ! 3467: (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) ! 3468: { ! 3469: TargetFlags->TaggedQueuingActive = true; ! 3470: BusLogic_Notice("Tagged Queuing now active for Target %d\n", ! 3471: HostAdapter, TargetID); ! 3472: } ! 3473: if (TargetFlags->TaggedQueuingActive) ! 3474: { ! 3475: BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; ! 3476: /* ! 3477: When using Tagged Queuing with Simple Queue Tags, it appears that disk ! 3478: drive controllers do not guarantee that a queued command will not ! 3479: remain in a disconnected state indefinitely if commands that read or ! 3480: write nearer the head position continue to arrive without interruption. ! 3481: Therefore, for each Target Device this driver keeps track of the last ! 3482: time either the queue was empty or an Ordered Queue Tag was issued. If ! 3483: more than 4 seconds (one fifth of the 20 second disk timeout) have ! 3484: elapsed since this last sequence point, this command will be issued ! 3485: with an Ordered Queue Tag rather than a Simple Queue Tag, which forces ! 3486: the Target Device to complete all previously queued commands before ! 3487: this command may be executed. ! 3488: */ ! 3489: if (HostAdapter->ActiveCommands[TargetID] == 0) ! 3490: HostAdapter->LastSequencePoint[TargetID] = jiffies; ! 3491: else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ) ! 3492: { ! 3493: HostAdapter->LastSequencePoint[TargetID] = jiffies; ! 3494: QueueTag = BusLogic_OrderedQueueTag; ! 3495: } ! 3496: if (HostAdapter->ExtendedLUNSupport) ! 3497: { ! 3498: CCB->TagEnable = true; ! 3499: CCB->QueueTag = QueueTag; ! 3500: } ! 3501: else ! 3502: { ! 3503: CCB->LegacyTagEnable = true; ! 3504: CCB->LegacyQueueTag = QueueTag; ! 3505: } ! 3506: } ! 3507: memcpy(CCB->CDB, CDB, CDB_Length); ! 3508: CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer); ! 3509: CCB->Command = Command; ! 3510: Command->scsi_done = CompletionRoutine; ! 3511: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3512: { ! 3513: /* ! 3514: Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI ! 3515: Subsystem should not attempt to queue more commands than can be placed ! 3516: in Outgoing Mailboxes, so there should always be one free. In the ! 3517: unlikely event that there are none available, wait 1 second and try ! 3518: again. If that fails, the Host Adapter is probably hung so signal an ! 3519: error as a Host Adapter Hard Reset should be initiated soon. ! 3520: */ ! 3521: if (!BusLogic_WriteOutgoingMailbox( ! 3522: HostAdapter, BusLogic_MailboxStartCommand, CCB)) ! 3523: { ! 3524: BusLogic_Warning("Unable to write Outgoing Mailbox - " ! 3525: "Pausing for 1 second\n", HostAdapter); ! 3526: BusLogic_Delay(1); ! 3527: if (!BusLogic_WriteOutgoingMailbox( ! 3528: HostAdapter, BusLogic_MailboxStartCommand, CCB)) ! 3529: { ! 3530: BusLogic_Warning("Still unable to write Outgoing Mailbox - " ! 3531: "Host Adapter Dead?\n", HostAdapter); ! 3532: BusLogic_DeallocateCCB(CCB); ! 3533: Command->result = DID_ERROR << 16; ! 3534: Command->scsi_done(Command); ! 3535: } ! 3536: } ! 3537: } ! 3538: else ! 3539: { ! 3540: /* ! 3541: Call the FlashPoint SCCB Manager to start execution of the CCB. ! 3542: */ ! 3543: CCB->Status = BusLogic_CCB_Active; ! 3544: HostAdapter->ActiveCommands[TargetID]++; ! 3545: TargetStatistics[TargetID].CommandsAttempted++; ! 3546: FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); ! 3547: /* ! 3548: The Command may have already completed and BusLogic_QueueCompletedCCB ! 3549: been called, or it may still be pending. ! 3550: */ ! 3551: if (CCB->Status == BusLogic_CCB_Completed) ! 3552: BusLogic_ProcessCompletedCCBs(HostAdapter); ! 3553: } ! 3554: /* ! 3555: Release exclusive access to Host Adapter. ! 3556: */ ! 3557: Done: ! 3558: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3559: return 0; ! 3560: } ! 3561: ! 3562: ! 3563: /* ! 3564: BusLogic_AbortCommand aborts Command if possible. ! 3565: */ ! 3566: ! 3567: int BusLogic_AbortCommand(SCSI_Command_T *Command) ! 3568: { ! 3569: BusLogic_HostAdapter_T *HostAdapter = ! 3570: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 3571: int TargetID = Command->target; ! 3572: ProcessorFlags_T ProcessorFlags; ! 3573: BusLogic_CCB_T *CCB; ! 3574: int Result; ! 3575: BusLogic_IncrementErrorCounter( ! 3576: &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested); ! 3577: /* ! 3578: Acquire exclusive access to Host Adapter. ! 3579: */ ! 3580: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3581: /* ! 3582: If this Command has already completed, then no Abort is necessary. ! 3583: */ ! 3584: if (Command->serial_number != Command->serial_number_at_timeout) ! 3585: { ! 3586: BusLogic_Warning("Unable to Abort Command to Target %d - " ! 3587: "Already Completed\n", HostAdapter, TargetID); ! 3588: Result = SCSI_ABORT_NOT_RUNNING; ! 3589: goto Done; ! 3590: } ! 3591: /* ! 3592: Attempt to find an Active CCB for this Command. If no Active CCB for this ! 3593: Command is found, then no Abort is necessary. ! 3594: */ ! 3595: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3596: if (CCB->Command == Command) break; ! 3597: if (CCB == NULL) ! 3598: { ! 3599: BusLogic_Warning("Unable to Abort Command to Target %d - " ! 3600: "No CCB Found\n", HostAdapter, TargetID); ! 3601: Result = SCSI_ABORT_NOT_RUNNING; ! 3602: goto Done; ! 3603: } ! 3604: else if (CCB->Status == BusLogic_CCB_Completed) ! 3605: { ! 3606: BusLogic_Warning("Unable to Abort Command to Target %d - " ! 3607: "CCB Completed\n", HostAdapter, TargetID); ! 3608: Result = SCSI_ABORT_NOT_RUNNING; ! 3609: goto Done; ! 3610: } ! 3611: else if (CCB->Status == BusLogic_CCB_Reset) ! 3612: { ! 3613: BusLogic_Warning("Unable to Abort Command to Target %d - " ! 3614: "CCB Reset\n", HostAdapter, TargetID); ! 3615: Result = SCSI_ABORT_PENDING; ! 3616: goto Done; ! 3617: } ! 3618: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3619: { ! 3620: /* ! 3621: Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx ! 3622: do not generate Abort Tag messages, but only generate the non-tagged ! 3623: Abort message. Since non-tagged commands are not sent by the Host ! 3624: Adapter until the queue of outstanding tagged commands has completed, ! 3625: and the Abort message is treated as a non-tagged command, it is ! 3626: effectively impossible to abort commands when Tagged Queuing is active. ! 3627: Firmware version 5.xx does generate Abort Tag messages, so it is ! 3628: possible to abort commands when Tagged Queuing is active. ! 3629: */ ! 3630: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && ! 3631: HostAdapter->FirmwareVersion[0] < '5') ! 3632: { ! 3633: BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " ! 3634: "Abort Tag Not Supported\n", ! 3635: HostAdapter, CCB->SerialNumber, TargetID); ! 3636: Result = SCSI_ABORT_SNOOZE; ! 3637: } ! 3638: else if (BusLogic_WriteOutgoingMailbox( ! 3639: HostAdapter, BusLogic_MailboxAbortCommand, CCB)) ! 3640: { ! 3641: BusLogic_Warning("Aborting CCB #%ld to Target %d\n", ! 3642: HostAdapter, CCB->SerialNumber, TargetID); ! 3643: BusLogic_IncrementErrorCounter( ! 3644: &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); ! 3645: Result = SCSI_ABORT_PENDING; ! 3646: } ! 3647: else ! 3648: { ! 3649: BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " ! 3650: "No Outgoing Mailboxes\n", ! 3651: HostAdapter, CCB->SerialNumber, TargetID); ! 3652: Result = SCSI_ABORT_BUSY; ! 3653: } ! 3654: } ! 3655: else ! 3656: { ! 3657: /* ! 3658: Call the FlashPoint SCCB Manager to abort execution of the CCB. ! 3659: */ ! 3660: BusLogic_Warning("Aborting CCB #%ld to Target %d\n", ! 3661: HostAdapter, CCB->SerialNumber, TargetID); ! 3662: BusLogic_IncrementErrorCounter( ! 3663: &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); ! 3664: FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB); ! 3665: /* ! 3666: The Abort may have already been completed and ! 3667: BusLogic_QueueCompletedCCB been called, or it ! 3668: may still be pending. ! 3669: */ ! 3670: Result = SCSI_ABORT_PENDING; ! 3671: if (CCB->Status == BusLogic_CCB_Completed) ! 3672: { ! 3673: BusLogic_ProcessCompletedCCBs(HostAdapter); ! 3674: Result = SCSI_ABORT_SUCCESS; ! 3675: } ! 3676: } ! 3677: /* ! 3678: Release exclusive access to Host Adapter. ! 3679: */ ! 3680: Done: ! 3681: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3682: return Result; ! 3683: } ! 3684: ! 3685: ! 3686: /* ! 3687: BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all ! 3688: currently executing SCSI Commands as having been Reset. ! 3689: */ ! 3690: ! 3691: static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, ! 3692: SCSI_Command_T *Command, ! 3693: unsigned int ResetFlags) ! 3694: { ! 3695: ProcessorFlags_T ProcessorFlags; ! 3696: BusLogic_CCB_T *CCB; ! 3697: int TargetID, Result; ! 3698: boolean HardReset; ! 3699: if (HostAdapter->HostAdapterExternalReset) ! 3700: { ! 3701: BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); ! 3702: HardReset = false; ! 3703: } ! 3704: else if (HostAdapter->HostAdapterInternalError) ! 3705: { ! 3706: BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); ! 3707: HardReset = true; ! 3708: } ! 3709: else ! 3710: { ! 3711: BusLogic_IncrementErrorCounter( ! 3712: &HostAdapter->TargetStatistics[Command->target] ! 3713: .HostAdapterResetsRequested); ! 3714: HardReset = true; ! 3715: } ! 3716: /* ! 3717: Acquire exclusive access to Host Adapter. ! 3718: */ ! 3719: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3720: /* ! 3721: If this is an Asynchronous Reset and this Command has already completed, ! 3722: then no Reset is necessary. ! 3723: */ ! 3724: if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) ! 3725: { ! 3726: TargetID = Command->target; ! 3727: if (Command->serial_number != Command->serial_number_at_timeout) ! 3728: { ! 3729: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3730: "Already Completed or Reset\n", ! 3731: HostAdapter, TargetID); ! 3732: Result = SCSI_RESET_NOT_RUNNING; ! 3733: goto Done; ! 3734: } ! 3735: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3736: if (CCB->Command == Command) break; ! 3737: if (CCB == NULL) ! 3738: { ! 3739: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3740: "No CCB Found\n", HostAdapter, TargetID); ! 3741: Result = SCSI_RESET_NOT_RUNNING; ! 3742: goto Done; ! 3743: } ! 3744: else if (CCB->Status == BusLogic_CCB_Completed) ! 3745: { ! 3746: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3747: "CCB Completed\n", HostAdapter, TargetID); ! 3748: Result = SCSI_RESET_NOT_RUNNING; ! 3749: goto Done; ! 3750: } ! 3751: else if (CCB->Status == BusLogic_CCB_Reset && ! 3752: HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL) ! 3753: { ! 3754: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3755: "Reset Pending\n", HostAdapter, TargetID); ! 3756: Result = SCSI_RESET_PENDING; ! 3757: goto Done; ! 3758: } ! 3759: } ! 3760: if (Command == NULL) ! 3761: { ! 3762: if (HostAdapter->HostAdapterInternalError) ! 3763: BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", ! 3764: HostAdapter, HostAdapter->FullModelName); ! 3765: else BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", ! 3766: HostAdapter, HostAdapter->FullModelName); ! 3767: } ! 3768: else ! 3769: { ! 3770: BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter, ! 3771: HostAdapter->FullModelName, Command->target); ! 3772: BusLogic_IncrementErrorCounter( ! 3773: &HostAdapter->TargetStatistics[Command->target] ! 3774: .HostAdapterResetsAttempted); ! 3775: } ! 3776: /* ! 3777: Attempt to Reset and Reinitialize the Host Adapter. ! 3778: */ ! 3779: if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && ! 3780: BusLogic_InitializeHostAdapter(HostAdapter))) ! 3781: { ! 3782: BusLogic_Error("Resetting %s Failed\n", HostAdapter, ! 3783: HostAdapter->FullModelName); ! 3784: Result = SCSI_RESET_ERROR; ! 3785: goto Done; ! 3786: } ! 3787: if (Command != NULL) ! 3788: BusLogic_IncrementErrorCounter( ! 3789: &HostAdapter->TargetStatistics[Command->target] ! 3790: .HostAdapterResetsCompleted); ! 3791: /* ! 3792: Mark all currently executing CCBs as having been Reset. ! 3793: */ ! 3794: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3795: if (CCB->Status == BusLogic_CCB_Active) ! 3796: CCB->Status = BusLogic_CCB_Reset; ! 3797: /* ! 3798: Wait a few seconds between the Host Adapter Hard Reset which initiates ! 3799: a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get ! 3800: confused if they receive SCSI Commands too soon after a SCSI Bus Reset. ! 3801: Note that a timer interrupt may occur here, but all active CCBs have ! 3802: already been marked Reset and so a reentrant call will return Pending. ! 3803: */ ! 3804: if (HardReset) ! 3805: BusLogic_Delay(HostAdapter->BusSettleTime); ! 3806: /* ! 3807: If this is a Synchronous Reset, perform completion processing for ! 3808: the Command being Reset. ! 3809: */ ! 3810: if (ResetFlags & SCSI_RESET_SYNCHRONOUS) ! 3811: { ! 3812: Command->result = DID_RESET << 16; ! 3813: Command->scsi_done(Command); ! 3814: } ! 3815: /* ! 3816: Perform completion processing for all CCBs marked as Reset. ! 3817: */ ! 3818: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3819: if (CCB->Status == BusLogic_CCB_Reset) ! 3820: { ! 3821: Command = CCB->Command; ! 3822: BusLogic_DeallocateCCB(CCB); ! 3823: while (Command != NULL) ! 3824: { ! 3825: SCSI_Command_T *NextCommand = Command->reset_chain; ! 3826: Command->reset_chain = NULL; ! 3827: Command->result = DID_RESET << 16; ! 3828: Command->scsi_done(Command); ! 3829: Command = NextCommand; ! 3830: } ! 3831: } ! 3832: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 3833: { ! 3834: HostAdapter->LastResetAttempted[TargetID] = jiffies; ! 3835: HostAdapter->LastResetCompleted[TargetID] = jiffies; ! 3836: } ! 3837: Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET; ! 3838: /* ! 3839: Release exclusive access to Host Adapter. ! 3840: */ ! 3841: Done: ! 3842: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3843: return Result; ! 3844: } ! 3845: ! 3846: ! 3847: /* ! 3848: BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target ! 3849: Device associated with Command. ! 3850: */ ! 3851: ! 3852: static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter, ! 3853: SCSI_Command_T *Command, ! 3854: unsigned int ResetFlags) ! 3855: { ! 3856: int TargetID = Command->target; ! 3857: BusLogic_CCB_T *CCB, *XCCB; ! 3858: ProcessorFlags_T ProcessorFlags; ! 3859: int Result = -1; ! 3860: BusLogic_IncrementErrorCounter( ! 3861: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested); ! 3862: /* ! 3863: Acquire exclusive access to Host Adapter. ! 3864: */ ! 3865: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags); ! 3866: /* ! 3867: If this is an Asynchronous Reset and this Command has already completed, ! 3868: then no Reset is necessary. ! 3869: */ ! 3870: if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) ! 3871: { ! 3872: if (Command->serial_number != Command->serial_number_at_timeout) ! 3873: { ! 3874: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3875: "Already Completed\n", HostAdapter, TargetID); ! 3876: Result = SCSI_RESET_NOT_RUNNING; ! 3877: goto Done; ! 3878: } ! 3879: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 3880: if (CCB->Command == Command) break; ! 3881: if (CCB == NULL) ! 3882: { ! 3883: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3884: "No CCB Found\n", HostAdapter, TargetID); ! 3885: Result = SCSI_RESET_NOT_RUNNING; ! 3886: goto Done; ! 3887: } ! 3888: else if (CCB->Status == BusLogic_CCB_Completed) ! 3889: { ! 3890: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3891: "CCB Completed\n", HostAdapter, TargetID); ! 3892: Result = SCSI_RESET_NOT_RUNNING; ! 3893: goto Done; ! 3894: } ! 3895: else if (CCB->Status == BusLogic_CCB_Reset) ! 3896: { ! 3897: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3898: "Reset Pending\n", HostAdapter, TargetID); ! 3899: Result = SCSI_RESET_PENDING; ! 3900: goto Done; ! 3901: } ! 3902: else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL) ! 3903: { ! 3904: BusLogic_Warning("Bus Device Reset already pending to Target %d\n", ! 3905: HostAdapter, TargetID); ! 3906: goto Done; ! 3907: } ! 3908: } ! 3909: /* ! 3910: If this is a Synchronous Reset and a Bus Device Reset is already pending ! 3911: for this Target Device, do not send a second one. Add this Command to ! 3912: the list of Commands for which completion processing must be performed ! 3913: when the Bus Device Reset CCB completes. ! 3914: */ ! 3915: if (ResetFlags & SCSI_RESET_SYNCHRONOUS) ! 3916: if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL) ! 3917: { ! 3918: Command->reset_chain = CCB->Command; ! 3919: CCB->Command = Command; ! 3920: BusLogic_Warning("Unable to Reset Command to Target %d - " ! 3921: "Reset Pending\n", HostAdapter, TargetID); ! 3922: Result = SCSI_RESET_PENDING; ! 3923: goto Done; ! 3924: } ! 3925: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3926: { ! 3927: /* ! 3928: MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as ! 3929: a non-tagged command. Since non-tagged commands are not sent by the ! 3930: Host Adapter until the queue of outstanding tagged commands has ! 3931: completed, it is effectively impossible to send a Bus Device Reset ! 3932: while there are tagged commands outstanding. Therefore, in that case a ! 3933: full Host Adapter Hard Reset and SCSI Bus Reset must be done. ! 3934: */ ! 3935: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && ! 3936: HostAdapter->ActiveCommands[TargetID] > 0 && ! 3937: HostAdapter->FirmwareVersion[0] < '5') ! 3938: goto Done; ! 3939: } ! 3940: /* ! 3941: Allocate a CCB from the Host Adapter's free list. In the unlikely event ! 3942: that there are none available and memory allocation fails, attempt a full ! 3943: Host Adapter Hard Reset and SCSI Bus Reset. ! 3944: */ ! 3945: CCB = BusLogic_AllocateCCB(HostAdapter); ! 3946: if (CCB == NULL) goto Done; ! 3947: BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n", ! 3948: HostAdapter, CCB->SerialNumber, TargetID); ! 3949: CCB->Opcode = BusLogic_BusDeviceReset; ! 3950: CCB->TargetID = TargetID; ! 3951: /* ! 3952: For Synchronous Resets, arrange for the interrupt handler to perform ! 3953: completion processing for the Command being Reset. ! 3954: */ ! 3955: if (ResetFlags & SCSI_RESET_SYNCHRONOUS) ! 3956: { ! 3957: Command->reset_chain = NULL; ! 3958: CCB->Command = Command; ! 3959: } ! 3960: if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) ! 3961: { ! 3962: /* ! 3963: Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. ! 3964: If sending a Bus Device Reset is impossible, attempt a full Host ! 3965: Adapter Hard Reset and SCSI Bus Reset. ! 3966: */ ! 3967: if (!(BusLogic_WriteOutgoingMailbox( ! 3968: HostAdapter, BusLogic_MailboxStartCommand, CCB))) ! 3969: { ! 3970: BusLogic_Warning("Unable to write Outgoing Mailbox for " ! 3971: "Bus Device Reset\n", HostAdapter); ! 3972: BusLogic_DeallocateCCB(CCB); ! 3973: goto Done; ! 3974: } ! 3975: } ! 3976: else ! 3977: { ! 3978: /* ! 3979: Call the FlashPoint SCCB Manager to start execution of the CCB. ! 3980: */ ! 3981: CCB->Status = BusLogic_CCB_Active; ! 3982: HostAdapter->ActiveCommands[TargetID]++; ! 3983: FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); ! 3984: } ! 3985: /* ! 3986: If there is a currently executing CCB in the Host Adapter for this Command ! 3987: (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be ! 3988: made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset. ! 3989: If there is no active CCB for this Command (i.e. this is a Synchronous ! 3990: Reset), then the Bus Device Reset CCB's Command field will have been set ! 3991: to the Command so that the interrupt for the completion of the Bus Device ! 3992: Reset can call the Completion Routine for the Command. On successful ! 3993: execution of a Bus Device Reset, older firmware versions did return the ! 3994: pending CCBs with the appropriate completion code, but more recent firmware ! 3995: versions only return the Bus Device Reset CCB itself. This driver handles ! 3996: both cases by marking all the currently executing CCBs to this Target ! 3997: Device as Reset. When the Bus Device Reset CCB is processed by the ! 3998: interrupt handler, any remaining CCBs marked as Reset will have completion ! 3999: processing performed. ! 4000: */ ! 4001: BusLogic_IncrementErrorCounter( ! 4002: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted); ! 4003: HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB; ! 4004: HostAdapter->LastResetAttempted[TargetID] = jiffies; ! 4005: for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll) ! 4006: if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID) ! 4007: XCCB->Status = BusLogic_CCB_Reset; ! 4008: /* ! 4009: FlashPoint Host Adapters may have already completed the Bus Device ! 4010: Reset and BusLogic_QueueCompletedCCB been called, or it may still be ! 4011: pending. ! 4012: */ ! 4013: Result = SCSI_RESET_PENDING; ! 4014: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) ! 4015: if (CCB->Status == BusLogic_CCB_Completed) ! 4016: { ! 4017: BusLogic_ProcessCompletedCCBs(HostAdapter); ! 4018: Result = SCSI_RESET_SUCCESS; ! 4019: } ! 4020: /* ! 4021: If a Bus Device Reset was not possible for some reason, force a full ! 4022: Host Adapter Hard Reset and SCSI Bus Reset. ! 4023: */ ! 4024: Done: ! 4025: if (Result < 0) ! 4026: Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); ! 4027: /* ! 4028: Release exclusive access to Host Adapter. ! 4029: */ ! 4030: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags); ! 4031: return Result; ! 4032: } ! 4033: ! 4034: ! 4035: /* ! 4036: BusLogic_ResetCommand takes appropriate action to reset Command. ! 4037: */ ! 4038: ! 4039: int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags) ! 4040: { ! 4041: BusLogic_HostAdapter_T *HostAdapter = ! 4042: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 4043: int TargetID = Command->target; ! 4044: BusLogic_ErrorRecoveryStrategy_T ! 4045: ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID]; ! 4046: /* ! 4047: Disable Tagged Queuing if it is active for this Target Device and if ! 4048: it has been less than 10 minutes since the last reset occurred, or since ! 4049: the system was initialized if no prior resets have occurred. ! 4050: */ ! 4051: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && ! 4052: jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ) ! 4053: { ! 4054: HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); ! 4055: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; ! 4056: BusLogic_Warning("Tagged Queuing now disabled for Target %d\n", ! 4057: HostAdapter, TargetID); ! 4058: } ! 4059: switch (ErrorRecoveryStrategy) ! 4060: { ! 4061: case BusLogic_ErrorRecovery_Default: ! 4062: if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET) ! 4063: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); ! 4064: else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET) ! 4065: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); ! 4066: /* Fall through to Bus Device Reset case. */ ! 4067: case BusLogic_ErrorRecovery_BusDeviceReset: ! 4068: /* ! 4069: The Bus Device Reset Error Recovery Strategy only graduates to a Hard ! 4070: Reset when no commands have completed successfully since the last Bus ! 4071: Device Reset and it has been at least 100 milliseconds. This prevents ! 4072: a sequence of commands that all timeout together from immediately ! 4073: forcing a Hard Reset before the Bus Device Reset has had a chance to ! 4074: clear the error condition. ! 4075: */ ! 4076: if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag || ! 4077: jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10) ! 4078: { ! 4079: HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; ! 4080: return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags); ! 4081: } ! 4082: /* Fall through to Hard Reset case. */ ! 4083: case BusLogic_ErrorRecovery_HardReset: ! 4084: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); ! 4085: case BusLogic_ErrorRecovery_None: ! 4086: BusLogic_Warning("Error Recovery for Target %d Suppressed\n", ! 4087: HostAdapter, TargetID); ! 4088: break; ! 4089: } ! 4090: return SCSI_RESET_PUNT; ! 4091: } ! 4092: ! 4093: ! 4094: /* ! 4095: BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk ! 4096: Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and ! 4097: the appropriate number of cylinders so as not to exceed drive capacity. In ! 4098: order for disks equal to or larger than 1 GB to be addressable by the BIOS ! 4099: without exceeding the BIOS limitation of 1024 cylinders, Extended Translation ! 4100: may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C" ! 4101: series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A" ! 4102: series MultiMaster Host Adapters. With Extended Translation enabled, drives ! 4103: between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128 ! 4104: heads and 32 sectors, and drives above 2 GB inclusive are given a disk ! 4105: geometry of 255 heads and 63 sectors. However, if the BIOS detects that the ! 4106: Extended Translation setting does not match the geometry in the partition ! 4107: table, then the translation inferred from the partition table will be used by ! 4108: the BIOS, and a warning may be displayed. ! 4109: */ ! 4110: ! 4111: int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device, ! 4112: int *Parameters) ! 4113: { ! 4114: BusLogic_HostAdapter_T *HostAdapter = ! 4115: (BusLogic_HostAdapter_T *) Disk->device->host->hostdata; ! 4116: BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters; ! 4117: struct buffer_head *BufferHead; ! 4118: if (HostAdapter->ExtendedTranslationEnabled && ! 4119: Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) ! 4120: { ! 4121: if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) ! 4122: { ! 4123: DiskParameters->Heads = 255; ! 4124: DiskParameters->Sectors = 63; ! 4125: } ! 4126: else ! 4127: { ! 4128: DiskParameters->Heads = 128; ! 4129: DiskParameters->Sectors = 32; ! 4130: } ! 4131: } ! 4132: else ! 4133: { ! 4134: DiskParameters->Heads = 64; ! 4135: DiskParameters->Sectors = 32; ! 4136: } ! 4137: DiskParameters->Cylinders = ! 4138: Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); ! 4139: /* ! 4140: Attempt to read the first 1024 bytes from the disk device. ! 4141: */ ! 4142: BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, 1024); ! 4143: if (BufferHead == NULL) return 0; ! 4144: /* ! 4145: If the boot sector partition table flag is valid, search for a partition ! 4146: table entry whose end_head matches one of the standard BusLogic geometry ! 4147: translations (64/32, 128/32, or 255/63). ! 4148: */ ! 4149: if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55) ! 4150: { ! 4151: PartitionTable_T *FirstPartitionEntry = ! 4152: (PartitionTable_T *) (BufferHead->b_data + 0x1BE); ! 4153: PartitionTable_T *PartitionEntry = FirstPartitionEntry; ! 4154: int SavedCylinders = DiskParameters->Cylinders, PartitionNumber; ! 4155: unsigned char PartitionEntryEndHead, PartitionEntryEndSector; ! 4156: for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) ! 4157: { ! 4158: PartitionEntryEndHead = PartitionEntry->end_head; ! 4159: PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F; ! 4160: if (PartitionEntryEndHead == 64-1) ! 4161: { ! 4162: DiskParameters->Heads = 64; ! 4163: DiskParameters->Sectors = 32; ! 4164: break; ! 4165: } ! 4166: else if (PartitionEntryEndHead == 128-1) ! 4167: { ! 4168: DiskParameters->Heads = 128; ! 4169: DiskParameters->Sectors = 32; ! 4170: break; ! 4171: } ! 4172: else if (PartitionEntryEndHead == 255-1) ! 4173: { ! 4174: DiskParameters->Heads = 255; ! 4175: DiskParameters->Sectors = 63; ! 4176: break; ! 4177: } ! 4178: PartitionEntry++; ! 4179: } ! 4180: if (PartitionNumber == 4) ! 4181: { ! 4182: PartitionEntryEndHead = FirstPartitionEntry->end_head; ! 4183: PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F; ! 4184: } ! 4185: DiskParameters->Cylinders = ! 4186: Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); ! 4187: if (PartitionNumber < 4 && ! 4188: PartitionEntryEndSector == DiskParameters->Sectors) ! 4189: { ! 4190: if (DiskParameters->Cylinders != SavedCylinders) ! 4191: BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", ! 4192: HostAdapter, ! 4193: DiskParameters->Heads, DiskParameters->Sectors); ! 4194: } ! 4195: else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) ! 4196: { ! 4197: BusLogic_Warning("Warning: Partition Table appears to " ! 4198: "have Geometry %d/%d which is\n", HostAdapter, ! 4199: PartitionEntryEndHead + 1, ! 4200: PartitionEntryEndSector); ! 4201: BusLogic_Warning("not compatible with current BusLogic " ! 4202: "Host Adapter Geometry %d/%d\n", HostAdapter, ! 4203: DiskParameters->Heads, DiskParameters->Sectors); ! 4204: } ! 4205: } ! 4206: brelse(BufferHead); ! 4207: return 0; ! 4208: } ! 4209: ! 4210: ! 4211: /* ! 4212: BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>. ! 4213: */ ! 4214: ! 4215: int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer, ! 4216: off_t Offset, int BytesAvailable, ! 4217: int HostNumber, int WriteFlag) ! 4218: { ! 4219: BusLogic_HostAdapter_T *HostAdapter; ! 4220: BusLogic_TargetStatistics_T *TargetStatistics; ! 4221: int TargetID, Length; ! 4222: char *Buffer; ! 4223: for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; ! 4224: HostAdapter != NULL; ! 4225: HostAdapter = HostAdapter->Next) ! 4226: if (HostAdapter->HostNumber == HostNumber) break; ! 4227: if (HostAdapter == NULL) ! 4228: { ! 4229: BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", ! 4230: NULL, HostNumber); ! 4231: return 0; ! 4232: } ! 4233: TargetStatistics = HostAdapter->TargetStatistics; ! 4234: if (WriteFlag) ! 4235: { ! 4236: HostAdapter->ExternalHostAdapterResets = 0; ! 4237: HostAdapter->HostAdapterInternalErrors = 0; ! 4238: memset(TargetStatistics, 0, ! 4239: BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T)); ! 4240: return 0; ! 4241: } ! 4242: Buffer = HostAdapter->MessageBuffer; ! 4243: Length = HostAdapter->MessageBufferLength; ! 4244: Length += sprintf(&Buffer[Length], "\n\ ! 4245: Current Driver Queue Depth: %d\n\ ! 4246: Currently Allocated CCBs: %d\n", ! 4247: HostAdapter->DriverQueueDepth, ! 4248: HostAdapter->AllocatedCCBs); ! 4249: Length += sprintf(&Buffer[Length], "\n\n\ ! 4250: DATA TRANSFER STATISTICS\n\ ! 4251: \n\ ! 4252: Target Tagged Queuing Queue Depth Active Attempted Completed\n\ ! 4253: ====== ============== =========== ====== ========= =========\n"); ! 4254: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 4255: { ! 4256: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 4257: if (!TargetFlags->TargetExists) continue; ! 4258: Length += ! 4259: sprintf(&Buffer[Length], " %2d %s", TargetID, ! 4260: (TargetFlags->TaggedQueuingSupported ! 4261: ? (TargetFlags->TaggedQueuingActive ! 4262: ? " Active" ! 4263: : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID) ! 4264: ? " Permitted" : " Disabled")) ! 4265: : "Not Supported")); ! 4266: Length += sprintf(&Buffer[Length], ! 4267: " %3d %3u %9u %9u\n", ! 4268: HostAdapter->QueueDepth[TargetID], ! 4269: HostAdapter->ActiveCommands[TargetID], ! 4270: TargetStatistics[TargetID].CommandsAttempted, ! 4271: TargetStatistics[TargetID].CommandsCompleted); ! 4272: } ! 4273: Length += sprintf(&Buffer[Length], "\n\ ! 4274: Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\ ! 4275: ====== ============= ============== =================== ===================\n"); ! 4276: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 4277: { ! 4278: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 4279: if (!TargetFlags->TargetExists) continue; ! 4280: Length += ! 4281: sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, ! 4282: TargetStatistics[TargetID].ReadCommands, ! 4283: TargetStatistics[TargetID].WriteCommands); ! 4284: if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0) ! 4285: Length += ! 4286: sprintf(&Buffer[Length], " %9u%09u", ! 4287: TargetStatistics[TargetID].TotalBytesRead.Billions, ! 4288: TargetStatistics[TargetID].TotalBytesRead.Units); ! 4289: else ! 4290: Length += ! 4291: sprintf(&Buffer[Length], " %9u", ! 4292: TargetStatistics[TargetID].TotalBytesRead.Units); ! 4293: if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0) ! 4294: Length += ! 4295: sprintf(&Buffer[Length], " %9u%09u\n", ! 4296: TargetStatistics[TargetID].TotalBytesWritten.Billions, ! 4297: TargetStatistics[TargetID].TotalBytesWritten.Units); ! 4298: else ! 4299: Length += ! 4300: sprintf(&Buffer[Length], " %9u\n", ! 4301: TargetStatistics[TargetID].TotalBytesWritten.Units); ! 4302: } ! 4303: Length += sprintf(&Buffer[Length], "\n\ ! 4304: Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\ ! 4305: ====== ======= ========= ========= ========= ========= =========\n"); ! 4306: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 4307: { ! 4308: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 4309: if (!TargetFlags->TargetExists) continue; ! 4310: Length += ! 4311: sprintf(&Buffer[Length], ! 4312: " %2d Read %9u %9u %9u %9u %9u\n", TargetID, ! 4313: TargetStatistics[TargetID].ReadCommandSizeBuckets[0], ! 4314: TargetStatistics[TargetID].ReadCommandSizeBuckets[1], ! 4315: TargetStatistics[TargetID].ReadCommandSizeBuckets[2], ! 4316: TargetStatistics[TargetID].ReadCommandSizeBuckets[3], ! 4317: TargetStatistics[TargetID].ReadCommandSizeBuckets[4]); ! 4318: Length += ! 4319: sprintf(&Buffer[Length], ! 4320: " %2d Write %9u %9u %9u %9u %9u\n", TargetID, ! 4321: TargetStatistics[TargetID].WriteCommandSizeBuckets[0], ! 4322: TargetStatistics[TargetID].WriteCommandSizeBuckets[1], ! 4323: TargetStatistics[TargetID].WriteCommandSizeBuckets[2], ! 4324: TargetStatistics[TargetID].WriteCommandSizeBuckets[3], ! 4325: TargetStatistics[TargetID].WriteCommandSizeBuckets[4]); ! 4326: } ! 4327: Length += sprintf(&Buffer[Length], "\n\ ! 4328: Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\ ! 4329: ====== ======= ========= ========= ========= ========= =========\n"); ! 4330: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 4331: { ! 4332: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 4333: if (!TargetFlags->TargetExists) continue; ! 4334: Length += ! 4335: sprintf(&Buffer[Length], ! 4336: " %2d Read %9u %9u %9u %9u %9u\n", TargetID, ! 4337: TargetStatistics[TargetID].ReadCommandSizeBuckets[5], ! 4338: TargetStatistics[TargetID].ReadCommandSizeBuckets[6], ! 4339: TargetStatistics[TargetID].ReadCommandSizeBuckets[7], ! 4340: TargetStatistics[TargetID].ReadCommandSizeBuckets[8], ! 4341: TargetStatistics[TargetID].ReadCommandSizeBuckets[9]); ! 4342: Length += ! 4343: sprintf(&Buffer[Length], ! 4344: " %2d Write %9u %9u %9u %9u %9u\n", TargetID, ! 4345: TargetStatistics[TargetID].WriteCommandSizeBuckets[5], ! 4346: TargetStatistics[TargetID].WriteCommandSizeBuckets[6], ! 4347: TargetStatistics[TargetID].WriteCommandSizeBuckets[7], ! 4348: TargetStatistics[TargetID].WriteCommandSizeBuckets[8], ! 4349: TargetStatistics[TargetID].WriteCommandSizeBuckets[9]); ! 4350: } ! 4351: Length += sprintf(&Buffer[Length], "\n\n\ ! 4352: ERROR RECOVERY STATISTICS\n\ ! 4353: \n\ ! 4354: Command Aborts Bus Device Resets Host Adapter Resets\n\ ! 4355: Target Requested Completed Requested Completed Requested Completed\n\ ! 4356: ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\ ! 4357: ====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n"); ! 4358: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) ! 4359: { ! 4360: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID]; ! 4361: if (!TargetFlags->TargetExists) continue; ! 4362: Length += ! 4363: sprintf(&Buffer[Length], "\ ! 4364: %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, ! 4365: TargetStatistics[TargetID].CommandAbortsRequested, ! 4366: TargetStatistics[TargetID].CommandAbortsAttempted, ! 4367: TargetStatistics[TargetID].CommandAbortsCompleted, ! 4368: TargetStatistics[TargetID].BusDeviceResetsRequested, ! 4369: TargetStatistics[TargetID].BusDeviceResetsAttempted, ! 4370: TargetStatistics[TargetID].BusDeviceResetsCompleted, ! 4371: TargetStatistics[TargetID].HostAdapterResetsRequested, ! 4372: TargetStatistics[TargetID].HostAdapterResetsAttempted, ! 4373: TargetStatistics[TargetID].HostAdapterResetsCompleted); ! 4374: } ! 4375: Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", ! 4376: HostAdapter->ExternalHostAdapterResets); ! 4377: Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", ! 4378: HostAdapter->HostAdapterInternalErrors); ! 4379: if (Length >= BusLogic_MessageBufferSize) ! 4380: BusLogic_Error("Message Buffer length %d exceeds size %d\n", ! 4381: HostAdapter, Length, BusLogic_MessageBufferSize); ! 4382: if ((Length -= Offset) <= 0) return 0; ! 4383: if (Length >= BytesAvailable) Length = BytesAvailable; ! 4384: *StartPointer = &HostAdapter->MessageBuffer[Offset]; ! 4385: return Length; ! 4386: } ! 4387: ! 4388: ! 4389: /* ! 4390: BusLogic_Message prints Driver Messages. ! 4391: */ ! 4392: ! 4393: static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel, ! 4394: char *Format, ! 4395: BusLogic_HostAdapter_T *HostAdapter, ! 4396: ...) ! 4397: { ! 4398: static char Buffer[BusLogic_LineBufferSize]; ! 4399: static boolean BeginningOfLine = true; ! 4400: va_list Arguments; ! 4401: int Length = 0; ! 4402: va_start(Arguments, HostAdapter); ! 4403: Length = vsprintf(Buffer, Format, Arguments); ! 4404: va_end(Arguments); ! 4405: if (MessageLevel == BusLogic_AnnounceLevel) ! 4406: { ! 4407: static int AnnouncementLines = 0; ! 4408: strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], ! 4409: Buffer); ! 4410: HostAdapter->MessageBufferLength += Length; ! 4411: if (++AnnouncementLines <= 2) ! 4412: printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer); ! 4413: } ! 4414: else if (MessageLevel == BusLogic_InfoLevel) ! 4415: { ! 4416: strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], ! 4417: Buffer); ! 4418: HostAdapter->MessageBufferLength += Length; ! 4419: if (BeginningOfLine) ! 4420: { ! 4421: if (Buffer[0] != '\n' || Length > 1) ! 4422: printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], ! 4423: HostAdapter->HostNumber, Buffer); ! 4424: } ! 4425: else printk("%s", Buffer); ! 4426: } ! 4427: else ! 4428: { ! 4429: if (BeginningOfLine) ! 4430: { ! 4431: if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized) ! 4432: printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], ! 4433: HostAdapter->HostNumber, Buffer); ! 4434: else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer); ! 4435: } ! 4436: else printk("%s", Buffer); ! 4437: } ! 4438: BeginningOfLine = (Buffer[Length-1] == '\n'); ! 4439: } ! 4440: ! 4441: ! 4442: /* ! 4443: BusLogic_ParseKeyword parses an individual option keyword. It returns true ! 4444: and updates the pointer if the keyword is recognized and false otherwise. ! 4445: */ ! 4446: ! 4447: static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword) ! 4448: { ! 4449: char *Pointer = *StringPointer; ! 4450: while (*Keyword != '\0') ! 4451: { ! 4452: char StringChar = *Pointer++; ! 4453: char KeywordChar = *Keyword++; ! 4454: if (StringChar >= 'A' && StringChar <= 'Z') ! 4455: StringChar += 'a' - 'Z'; ! 4456: if (KeywordChar >= 'A' && KeywordChar <= 'Z') ! 4457: KeywordChar += 'a' - 'Z'; ! 4458: if (StringChar != KeywordChar) return false; ! 4459: } ! 4460: *StringPointer = Pointer; ! 4461: return true; ! 4462: } ! 4463: ! 4464: ! 4465: /* ! 4466: BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options ! 4467: specifications. ! 4468: ! 4469: BusLogic Driver Options may be specified either via the Linux Kernel Command ! 4470: Line or via the Loadable Kernel Module Installation Facility. Driver Options ! 4471: for multiple host adapters may be specified either by separating the option ! 4472: strings by a semicolon, or by specifying multiple "BusLogic=" strings on the ! 4473: command line. Individual option specifications for a single host adapter are ! 4474: separated by commas. The Probing and Debugging Options apply to all host ! 4475: adapters whereas the remaining options apply individually only to the ! 4476: selected host adapter. ! 4477: ! 4478: The BusLogic Driver Probing Options comprise the following: ! 4479: ! 4480: IO:<integer> ! 4481: ! 4482: The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI ! 4483: MultiMaster Host Adapter. If neither "IO:" nor "NoProbeISA" options are ! 4484: specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses ! 4485: will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134). Multiple ! 4486: "IO:" options may be specified to precisely determine the I/O Addresses to ! 4487: be probed, but the probe order will always follow the standard list. ! 4488: ! 4489: NoProbe ! 4490: ! 4491: The "NoProbe" option disables all probing and therefore no BusLogic Host ! 4492: Adapters will be detected. ! 4493: ! 4494: NoProbeISA ! 4495: ! 4496: The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O ! 4497: Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters ! 4498: will be detected. ! 4499: ! 4500: NoProbePCI ! 4501: ! 4502: The "NoProbePCI" options disables the interrogation of PCI Configuration ! 4503: Space and therefore only ISA Multimaster Host Adapters will be detected, as ! 4504: well as PCI Multimaster Host Adapters that have their ISA Compatible I/O ! 4505: Port set to "Primary" or "Alternate". ! 4506: ! 4507: NoSortPCI ! 4508: ! 4509: The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be ! 4510: enumerated in the order provided by the PCI BIOS, ignoring any setting of ! 4511: the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option. ! 4512: ! 4513: MultiMasterFirst ! 4514: ! 4515: The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed ! 4516: before FlashPoint Host Adapters. By default, if both FlashPoint and PCI ! 4517: MultiMaster Host Adapters are present, this driver will probe for ! 4518: FlashPoint Host Adapters first unless the BIOS primary disk is controlled ! 4519: by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host ! 4520: Adapters will be probed first. ! 4521: ! 4522: FlashPointFirst ! 4523: ! 4524: The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed ! 4525: before MultiMaster Host Adapters. ! 4526: ! 4527: The BusLogic Driver Tagged Queuing Options allow for explicitly specifying ! 4528: the Queue Depth and whether Tagged Queuing is permitted for each Target ! 4529: Device (assuming that the Target Device supports Tagged Queuing). The Queue ! 4530: Depth is the number of SCSI Commands that are allowed to be concurrently ! 4531: presented for execution (either to the Host Adapter or Target Device). Note ! 4532: that explicitly enabling Tagged Queuing may lead to problems; the option to ! 4533: enable or disable Tagged Queuing is provided primarily to allow disabling ! 4534: Tagged Queuing on Target Devices that do not implement it correctly. The ! 4535: following options are available: ! 4536: ! 4537: QueueDepth:<integer> ! 4538: ! 4539: The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all ! 4540: Target Devices that support Tagged Queuing, as well as the maximum Queue ! 4541: Depth for devices that do not support Tagged Queuing. If no Queue Depth ! 4542: option is provided, the Queue Depth will be determined automatically based ! 4543: on the Host Adapter's Total Queue Depth and the number, type, speed, and ! 4544: capabilities of the detected Target Devices. For Host Adapters that ! 4545: require ISA Bounce Buffers, the Queue Depth is automatically set by default ! 4546: to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid ! 4547: excessive preallocation of DMA Bounce Buffer memory. Target Devices that ! 4548: do not support Tagged Queuing always have their Queue Depth set to ! 4549: BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a ! 4550: lower Queue Depth option is provided. A Queue Depth of 1 automatically ! 4551: disables Tagged Queuing. ! 4552: ! 4553: QueueDepth:[<integer>,<integer>...] ! 4554: ! 4555: The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth ! 4556: individually for each Target Device. If an <integer> is omitted, the ! 4557: associated Target Device will have its Queue Depth selected automatically. ! 4558: ! 4559: TaggedQueuing:Default ! 4560: ! 4561: The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing ! 4562: based on the firmware version of the BusLogic Host Adapter and based on ! 4563: whether the Queue Depth allows queuing multiple commands. ! 4564: ! 4565: TaggedQueuing:Enable ! 4566: ! 4567: The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for ! 4568: all Target Devices on this Host Adapter, overriding any limitation that ! 4569: would otherwise be imposed based on the Host Adapter firmware version. ! 4570: ! 4571: TaggedQueuing:Disable ! 4572: ! 4573: The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing ! 4574: for all Target Devices on this Host Adapter. ! 4575: ! 4576: TaggedQueuing:<Target-Spec> ! 4577: ! 4578: The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls ! 4579: Tagged Queuing individually for each Target Device. <Target-Spec> is a ! 4580: sequence of "Y", "N", and "X" characters. "Y" enables Tagged Queuing, "N" ! 4581: disables Tagged Queuing, and "X" accepts the default based on the firmware ! 4582: version. The first character refers to Target Device 0, the second to ! 4583: Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters ! 4584: does not cover all the Target Devices, unspecified characters are assumed ! 4585: to be "X". ! 4586: ! 4587: The BusLogic Driver Error Recovery Option allows for explicitly specifying ! 4588: the Error Recovery action to be performed when BusLogic_ResetCommand is ! 4589: called due to a SCSI Command failing to complete successfully. The following ! 4590: options are available: ! 4591: ! 4592: ErrorRecovery:Default ! 4593: ! 4594: The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard ! 4595: Reset and Bus Device Reset options based on the recommendation of the SCSI ! 4596: Subsystem. ! 4597: ! 4598: ErrorRecovery:HardReset ! 4599: ! 4600: The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host ! 4601: Adapter Hard Reset which also causes a SCSI Bus Reset. ! 4602: ! 4603: ErrorRecovery:BusDeviceReset ! 4604: ! 4605: The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send ! 4606: a Bus Device Reset message to the individual Target Device causing the ! 4607: error. If Error Recovery is again initiated for this Target Device and no ! 4608: SCSI Command to this Target Device has completed successfully since the Bus ! 4609: Device Reset message was sent, then a Hard Reset will be attempted. ! 4610: ! 4611: ErrorRecovery:None ! 4612: ! 4613: The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery. ! 4614: This option should only be selected if a SCSI Bus Reset or Bus Device Reset ! 4615: will cause the Target Device or a critical operation to suffer a complete ! 4616: and unrecoverable failure. ! 4617: ! 4618: ErrorRecovery:<Target-Spec> ! 4619: ! 4620: The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls ! 4621: Error Recovery individually for each Target Device. <Target-Spec> is a ! 4622: sequence of "D", "H", "B", and "N" characters. "D" selects Default, "H" ! 4623: selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None. ! 4624: The first character refers to Target Device 0, the second to Target Device ! 4625: 1, and so on; if the sequence of "D", "H", "B", and "N" characters does not ! 4626: cover all the possible Target Devices, unspecified characters are assumed ! 4627: to be "D". ! 4628: ! 4629: The BusLogic Driver Miscellaneous Options comprise the following: ! 4630: ! 4631: BusSettleTime:<seconds> ! 4632: ! 4633: The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in ! 4634: seconds. The Bus Settle Time is the amount of time to wait between a Host ! 4635: Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI ! 4636: Commands. If unspecified, it defaults to BusLogic_DefaultBusSettleTime. ! 4637: ! 4638: InhibitTargetInquiry ! 4639: ! 4640: The "InhibitTargetInquiry" option inhibits the execution of an Inquire ! 4641: Target Devices or Inquire Installed Devices command on MultiMaster Host ! 4642: Adapters. This may be necessary with some older Target Devices that do not ! 4643: respond correctly when Logical Units above 0 are addressed. ! 4644: ! 4645: The BusLogic Driver Debugging Options comprise the following: ! 4646: ! 4647: TraceProbe ! 4648: ! 4649: The "TraceProbe" option enables tracing of Host Adapter Probing. ! 4650: ! 4651: TraceHardwareReset ! 4652: ! 4653: The "TraceHardwareReset" option enables tracing of Host Adapter Hardware ! 4654: Reset. ! 4655: ! 4656: TraceConfiguration ! 4657: ! 4658: The "TraceConfiguration" option enables tracing of Host Adapter ! 4659: Configuration. ! 4660: ! 4661: TraceErrors ! 4662: ! 4663: The "TraceErrors" option enables tracing of SCSI Commands that return an ! 4664: error from the Target Device. The CDB and Sense Data will be printed for ! 4665: each SCSI Command that fails. ! 4666: ! 4667: Debug ! 4668: ! 4669: The "Debug" option enables all debugging options. ! 4670: ! 4671: The following examples demonstrate setting the Queue Depth for Target Devices ! 4672: 1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target ! 4673: Devices on the second host adapter to 31, and the Bus Settle Time on the ! 4674: second host adapter to 30 seconds. ! 4675: ! 4676: Linux Kernel Command Line: ! 4677: ! 4678: linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30 ! 4679: ! 4680: LILO Linux Boot Loader (in /etc/lilo.conf): ! 4681: ! 4682: append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30" ! 4683: ! 4684: INSMOD Loadable Kernel Module Installation Facility: ! 4685: ! 4686: insmod BusLogic.o \ ! 4687: 'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' ! 4688: ! 4689: NOTE: Module Utilities 2.1.71 or later is required for correct parsing ! 4690: of driver options containing commas. ! 4691: ! 4692: */ ! 4693: ! 4694: static void BusLogic_ParseDriverOptions(char *OptionsString) ! 4695: { ! 4696: while (true) ! 4697: { ! 4698: BusLogic_DriverOptions_T *DriverOptions = ! 4699: &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++]; ! 4700: int TargetID; ! 4701: memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T)); ! 4702: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) ! 4703: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4704: BusLogic_ErrorRecovery_Default; ! 4705: while (*OptionsString != '\0' && *OptionsString != ';') ! 4706: { ! 4707: /* Probing Options. */ ! 4708: if (BusLogic_ParseKeyword(&OptionsString, "IO:")) ! 4709: { ! 4710: BusLogic_IO_Address_T IO_Address = ! 4711: simple_strtoul(OptionsString, &OptionsString, 0); ! 4712: BusLogic_ProbeOptions.LimitedProbeISA = true; ! 4713: switch (IO_Address) ! 4714: { ! 4715: case 0x330: ! 4716: BusLogic_ProbeOptions.Probe330 = true; ! 4717: break; ! 4718: case 0x334: ! 4719: BusLogic_ProbeOptions.Probe334 = true; ! 4720: break; ! 4721: case 0x230: ! 4722: BusLogic_ProbeOptions.Probe230 = true; ! 4723: break; ! 4724: case 0x234: ! 4725: BusLogic_ProbeOptions.Probe234 = true; ! 4726: break; ! 4727: case 0x130: ! 4728: BusLogic_ProbeOptions.Probe130 = true; ! 4729: break; ! 4730: case 0x134: ! 4731: BusLogic_ProbeOptions.Probe134 = true; ! 4732: break; ! 4733: default: ! 4734: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4735: "(illegal I/O Address 0x%X)\n", ! 4736: NULL, IO_Address); ! 4737: return; ! 4738: } ! 4739: } ! 4740: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA")) ! 4741: BusLogic_ProbeOptions.NoProbeISA = true; ! 4742: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI")) ! 4743: BusLogic_ProbeOptions.NoProbePCI = true; ! 4744: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe")) ! 4745: BusLogic_ProbeOptions.NoProbe = true; ! 4746: else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI")) ! 4747: BusLogic_ProbeOptions.NoSortPCI = true; ! 4748: else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst")) ! 4749: BusLogic_ProbeOptions.MultiMasterFirst = true; ! 4750: else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst")) ! 4751: BusLogic_ProbeOptions.FlashPointFirst = true; ! 4752: /* Tagged Queuing Options. */ ! 4753: else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || ! 4754: BusLogic_ParseKeyword(&OptionsString, "QD:[")) ! 4755: { ! 4756: for (TargetID = 0; ! 4757: TargetID < BusLogic_MaxTargetDevices; ! 4758: TargetID++) ! 4759: { ! 4760: unsigned short QueueDepth = ! 4761: simple_strtoul(OptionsString, &OptionsString, 0); ! 4762: if (QueueDepth > BusLogic_MaxTaggedQueueDepth) ! 4763: { ! 4764: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4765: "(illegal Queue Depth %d)\n", ! 4766: NULL, QueueDepth); ! 4767: return; ! 4768: } ! 4769: DriverOptions->QueueDepth[TargetID] = QueueDepth; ! 4770: if (*OptionsString == ',') ! 4771: OptionsString++; ! 4772: else if (*OptionsString == ']') ! 4773: break; ! 4774: else ! 4775: { ! 4776: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4777: "(',' or ']' expected at '%s')\n", ! 4778: NULL, OptionsString); ! 4779: return; ! 4780: } ! 4781: } ! 4782: if (*OptionsString != ']') ! 4783: { ! 4784: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4785: "(']' expected at '%s')\n", ! 4786: NULL, OptionsString); ! 4787: return; ! 4788: } ! 4789: else OptionsString++; ! 4790: } ! 4791: else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || ! 4792: BusLogic_ParseKeyword(&OptionsString, "QD:")) ! 4793: { ! 4794: unsigned short QueueDepth = ! 4795: simple_strtoul(OptionsString, &OptionsString, 0); ! 4796: if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) ! 4797: { ! 4798: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4799: "(illegal Queue Depth %d)\n", ! 4800: NULL, QueueDepth); ! 4801: return; ! 4802: } ! 4803: DriverOptions->CommonQueueDepth = QueueDepth; ! 4804: for (TargetID = 0; ! 4805: TargetID < BusLogic_MaxTargetDevices; ! 4806: TargetID++) ! 4807: DriverOptions->QueueDepth[TargetID] = QueueDepth; ! 4808: } ! 4809: else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || ! 4810: BusLogic_ParseKeyword(&OptionsString, "TQ:")) ! 4811: { ! 4812: if (BusLogic_ParseKeyword(&OptionsString, "Default")) ! 4813: { ! 4814: DriverOptions->TaggedQueuingPermitted = 0x0000; ! 4815: DriverOptions->TaggedQueuingPermittedMask = 0x0000; ! 4816: } ! 4817: else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) ! 4818: { ! 4819: DriverOptions->TaggedQueuingPermitted = 0xFFFF; ! 4820: DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; ! 4821: } ! 4822: else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) ! 4823: { ! 4824: DriverOptions->TaggedQueuingPermitted = 0x0000; ! 4825: DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; ! 4826: } ! 4827: else ! 4828: { ! 4829: unsigned short TargetBit; ! 4830: for (TargetID = 0, TargetBit = 1; ! 4831: TargetID < BusLogic_MaxTargetDevices; ! 4832: TargetID++, TargetBit <<= 1) ! 4833: switch (*OptionsString++) ! 4834: { ! 4835: case 'Y': ! 4836: DriverOptions->TaggedQueuingPermitted |= TargetBit; ! 4837: DriverOptions->TaggedQueuingPermittedMask |= TargetBit; ! 4838: break; ! 4839: case 'N': ! 4840: DriverOptions->TaggedQueuingPermitted &= ~TargetBit; ! 4841: DriverOptions->TaggedQueuingPermittedMask |= TargetBit; ! 4842: break; ! 4843: case 'X': ! 4844: break; ! 4845: default: ! 4846: OptionsString--; ! 4847: TargetID = BusLogic_MaxTargetDevices; ! 4848: break; ! 4849: } ! 4850: } ! 4851: } ! 4852: /* Error Recovery Option. */ ! 4853: else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") || ! 4854: BusLogic_ParseKeyword(&OptionsString, "ER:")) ! 4855: { ! 4856: if (BusLogic_ParseKeyword(&OptionsString, "Default")) ! 4857: for (TargetID = 0; ! 4858: TargetID < BusLogic_MaxTargetDevices; ! 4859: TargetID++) ! 4860: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4861: BusLogic_ErrorRecovery_Default; ! 4862: else if (BusLogic_ParseKeyword(&OptionsString, "HardReset")) ! 4863: for (TargetID = 0; ! 4864: TargetID < BusLogic_MaxTargetDevices; ! 4865: TargetID++) ! 4866: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4867: BusLogic_ErrorRecovery_HardReset; ! 4868: else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset")) ! 4869: for (TargetID = 0; ! 4870: TargetID < BusLogic_MaxTargetDevices; ! 4871: TargetID++) ! 4872: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4873: BusLogic_ErrorRecovery_BusDeviceReset; ! 4874: else if (BusLogic_ParseKeyword(&OptionsString, "None")) ! 4875: for (TargetID = 0; ! 4876: TargetID < BusLogic_MaxTargetDevices; ! 4877: TargetID++) ! 4878: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4879: BusLogic_ErrorRecovery_None; ! 4880: else ! 4881: for (TargetID = 0; ! 4882: TargetID < BusLogic_MaxTargetDevices; ! 4883: TargetID++) ! 4884: switch (*OptionsString++) ! 4885: { ! 4886: case 'D': ! 4887: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4888: BusLogic_ErrorRecovery_Default; ! 4889: break; ! 4890: case 'H': ! 4891: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4892: BusLogic_ErrorRecovery_HardReset; ! 4893: break; ! 4894: case 'B': ! 4895: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4896: BusLogic_ErrorRecovery_BusDeviceReset; ! 4897: break; ! 4898: case 'N': ! 4899: DriverOptions->ErrorRecoveryStrategy[TargetID] = ! 4900: BusLogic_ErrorRecovery_None; ! 4901: break; ! 4902: default: ! 4903: OptionsString--; ! 4904: TargetID = BusLogic_MaxTargetDevices; ! 4905: break; ! 4906: } ! 4907: } ! 4908: /* Miscellaneous Options. */ ! 4909: else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || ! 4910: BusLogic_ParseKeyword(&OptionsString, "BST:")) ! 4911: { ! 4912: unsigned short BusSettleTime = ! 4913: simple_strtoul(OptionsString, &OptionsString, 0); ! 4914: if (BusSettleTime > 5 * 60) ! 4915: { ! 4916: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4917: "(illegal Bus Settle Time %d)\n", ! 4918: NULL, BusSettleTime); ! 4919: return; ! 4920: } ! 4921: DriverOptions->BusSettleTime = BusSettleTime; ! 4922: } ! 4923: else if (BusLogic_ParseKeyword(&OptionsString, ! 4924: "InhibitTargetInquiry")) ! 4925: DriverOptions->LocalOptions.InhibitTargetInquiry = true; ! 4926: /* Debugging Options. */ ! 4927: else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe")) ! 4928: BusLogic_GlobalOptions.TraceProbe = true; ! 4929: else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset")) ! 4930: BusLogic_GlobalOptions.TraceHardwareReset = true; ! 4931: else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration")) ! 4932: BusLogic_GlobalOptions.TraceConfiguration = true; ! 4933: else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors")) ! 4934: BusLogic_GlobalOptions.TraceErrors = true; ! 4935: else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) ! 4936: { ! 4937: BusLogic_GlobalOptions.TraceProbe = true; ! 4938: BusLogic_GlobalOptions.TraceHardwareReset = true; ! 4939: BusLogic_GlobalOptions.TraceConfiguration = true; ! 4940: BusLogic_GlobalOptions.TraceErrors = true; ! 4941: } ! 4942: if (*OptionsString == ',') ! 4943: OptionsString++; ! 4944: else if (*OptionsString != ';' && *OptionsString != '\0') ! 4945: { ! 4946: BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " ! 4947: "ignored\n", NULL, OptionsString); ! 4948: *OptionsString = '\0'; ! 4949: } ! 4950: } ! 4951: if (!(BusLogic_DriverOptionsCount == 0 || ! 4952: BusLogic_ProbeInfoCount == 0 || ! 4953: BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) ! 4954: { ! 4955: BusLogic_Error("BusLogic: Invalid Driver Options " ! 4956: "(all or no I/O Addresses must be specified)\n", NULL); ! 4957: return; ! 4958: } ! 4959: /* ! 4960: Tagged Queuing is disabled when the Queue Depth is 1 since queuing ! 4961: multiple commands is not possible. ! 4962: */ ! 4963: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) ! 4964: if (DriverOptions->QueueDepth[TargetID] == 1) ! 4965: { ! 4966: unsigned short TargetBit = 1 << TargetID; ! 4967: DriverOptions->TaggedQueuingPermitted &= ~TargetBit; ! 4968: DriverOptions->TaggedQueuingPermittedMask |= TargetBit; ! 4969: } ! 4970: if (*OptionsString == ';') OptionsString++; ! 4971: if (*OptionsString == '\0') return; ! 4972: } ! 4973: } ! 4974: ! 4975: ! 4976: /* ! 4977: BusLogic_Setup handles processing of Kernel Command Line Arguments. ! 4978: */ ! 4979: ! 4980: void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers) ! 4981: { ! 4982: if (CommandLineIntegers[0] != 0) ! 4983: { ! 4984: BusLogic_Error("BusLogic: Obsolete Command Line Entry " ! 4985: "Format Ignored\n", NULL); ! 4986: return; ! 4987: } ! 4988: if (CommandLineString == NULL || *CommandLineString == '\0') return; ! 4989: BusLogic_ParseDriverOptions(CommandLineString); ! 4990: } ! 4991: ! 4992: ! 4993: /* ! 4994: Include Module support if requested. ! 4995: */ ! 4996: ! 4997: #ifdef MODULE ! 4998: ! 4999: SCSI_Host_Template_T driver_template = BUSLOGIC; ! 5000: ! 5001: #include "scsi_module.c" ! 5002: ! 5003: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.