|
|
1.1 ! root 1: /* ! 2: ! 3: Linux Driver for BusLogic MultiMaster SCSI Host Adapters ! 4: ! 5: Copyright 1995 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, provided that none of the source code or runtime ! 10: copyright notices are removed or modified. ! 11: ! 12: This program is distributed in the hope that it will be useful, but ! 13: WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY ! 14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 15: for complete details. ! 16: ! 17: The author respectfully requests that all modifications to this software be ! 18: sent directly to him for evaluation and testing. ! 19: ! 20: Special thanks to Alex T. Win of BusLogic, whose advice has been invaluable, ! 21: to David B. Gentzel, for writing the original Linux BusLogic driver, and to ! 22: Paul Gortmaker, for being such a dedicated test site. ! 23: ! 24: */ ! 25: ! 26: ! 27: #define BusLogic_DriverVersion "1.3.1" ! 28: #define BusLogic_DriverDate "31 December 1995" ! 29: ! 30: ! 31: #include <linux/module.h> ! 32: #include <linux/config.h> ! 33: #include <linux/types.h> ! 34: #include <linux/blkdev.h> ! 35: #include <linux/delay.h> ! 36: #include <linux/ioport.h> ! 37: #include <linux/kernel_stat.h> ! 38: #include <linux/mm.h> ! 39: #include <linux/sched.h> ! 40: #include <linux/stat.h> ! 41: #include <linux/pci.h> ! 42: #include <linux/bios32.h> ! 43: #include <asm/dma.h> ! 44: #include <asm/io.h> ! 45: #include <asm/system.h> ! 46: #include "scsi.h" ! 47: #include "hosts.h" ! 48: #include "sd.h" ! 49: #include "BusLogic.h" ! 50: ! 51: ! 52: /* ! 53: BusLogic_CommandLineEntryCount is a count of the number of "BusLogic=" ! 54: entries provided on the Linux Kernel Command Line. ! 55: */ ! 56: ! 57: static int ! 58: BusLogic_CommandLineEntryCount = 0; ! 59: ! 60: ! 61: /* ! 62: BusLogic_CommandLineEntries is an array of Command Line Entry structures ! 63: representing the "BusLogic=" entries provided on the Linux Kernel Command ! 64: Line. ! 65: */ ! 66: ! 67: static BusLogic_CommandLineEntry_T ! 68: BusLogic_CommandLineEntries[BusLogic_MaxHostAdapters]; ! 69: ! 70: ! 71: /* ! 72: BusLogic_GlobalOptions is a bit mask of Global Options to be applied ! 73: across all Host Adapters. ! 74: */ ! 75: ! 76: static int ! 77: BusLogic_GlobalOptions = 0; ! 78: ! 79: ! 80: /* ! 81: BusLogic_RegisteredHostAdapters is a linked list of all the registered ! 82: BusLogic Host Adapters. ! 83: */ ! 84: ! 85: static BusLogic_HostAdapter_T ! 86: *BusLogic_RegisteredHostAdapters = NULL; ! 87: ! 88: ! 89: /* ! 90: BusLogic_Standard_IO_Addresses is the list of standard I/O Addresses at which ! 91: BusLogic Host Adapters may potentially be found. ! 92: */ ! 93: ! 94: static unsigned short ! 95: BusLogic_IO_StandardAddresses[] = ! 96: { 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0 }; ! 97: ! 98: ! 99: /* ! 100: BusLogic_IO_AddressProbeList is the list of I/O Addresses to be probed for ! 101: potential BusLogic Host Adapters. It is initialized by interrogating the ! 102: PCI Configuration Space on PCI machines as well as from the list of ! 103: standard BusLogic I/O Addresses. ! 104: */ ! 105: ! 106: static unsigned short ! 107: BusLogic_IO_AddressProbeList[BusLogic_IO_MaxProbeAddresses+1] = { 0 }; ! 108: ! 109: ! 110: /* ! 111: BusLogic_IRQ_UsageCount stores a count of the number of Host Adapters using ! 112: a given IRQ Channel, which is necessary to support PCI, EISA, or MCA shared ! 113: interrupts. Only IRQ Channels 9, 10, 11, 12, 14, and 15 are supported by ! 114: BusLogic Host Adapters. ! 115: */ ! 116: ! 117: static short ! 118: BusLogic_IRQ_UsageCount[7] = { 0 }; ! 119: ! 120: ! 121: /* ! 122: BusLogic_CommandFailureReason holds a string identifying the reason why a ! 123: call to BusLogic_Command failed. It is only valid when BusLogic_Command ! 124: returns a failure code. ! 125: */ ! 126: ! 127: static char ! 128: *BusLogic_CommandFailureReason; ! 129: ! 130: ! 131: /* ! 132: BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry. ! 133: */ ! 134: ! 135: static struct proc_dir_entry ! 136: BusLogic_ProcDirectoryEntry = ! 137: { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; ! 138: ! 139: ! 140: /* ! 141: BusLogic_AnnounceDriver announces the Driver Version and Date, Author's ! 142: Name, Copyright Notice, and Contact Address. ! 143: */ ! 144: ! 145: static void BusLogic_AnnounceDriver(void) ! 146: { ! 147: static boolean DriverAnnouncementPrinted = false; ! 148: if (DriverAnnouncementPrinted) return; ! 149: printk("scsi: ***** BusLogic SCSI Driver Version " ! 150: BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n"); ! 151: printk("scsi: Copyright 1995 by Leonard N. Zubkoff <[email protected]>\n"); ! 152: DriverAnnouncementPrinted = true; ! 153: } ! 154: ! 155: ! 156: /* ! 157: BusLogic_DriverInfo returns the Board Name to identify this SCSI Driver ! 158: and Host Adapter. ! 159: */ ! 160: ! 161: const char *BusLogic_DriverInfo(SCSI_Host_T *Host) ! 162: { ! 163: BusLogic_HostAdapter_T *HostAdapter = ! 164: (BusLogic_HostAdapter_T *) Host->hostdata; ! 165: return HostAdapter->BoardName; ! 166: } ! 167: ! 168: ! 169: /* ! 170: BusLogic_InitializeAddressProbeList initializes the list of I/O Addresses ! 171: to be probed for potential BusLogic SCSI Host Adapters by interrogating the ! 172: PCI Configuration Space on PCI machines as well as from the list of standard ! 173: BusLogic I/O Addresses. ! 174: */ ! 175: ! 176: static void BusLogic_InitializeAddressProbeList(void) ! 177: { ! 178: int DestinationIndex = 0, SourceIndex = 0; ! 179: /* ! 180: If BusLogic_Setup has been called, do not override the Kernel Command ! 181: Line specifications. ! 182: */ ! 183: if (BusLogic_IO_AddressProbeList[0] != 0) return; ! 184: #ifdef CONFIG_PCI ! 185: /* ! 186: Interrogate PCI Configuration Space for any BusLogic SCSI Host Adapters. ! 187: */ ! 188: if (pcibios_present()) ! 189: { ! 190: unsigned short Index = 0, VendorID; ! 191: unsigned char Bus, DeviceAndFunction; ! 192: unsigned int BaseAddress0; ! 193: while (pcibios_find_class(PCI_CLASS_STORAGE_SCSI<<8, Index++, ! 194: &Bus, &DeviceAndFunction) == 0) ! 195: if (pcibios_read_config_word(Bus, DeviceAndFunction, ! 196: PCI_VENDOR_ID, &VendorID) == 0 && ! 197: VendorID == PCI_VENDOR_ID_BUSLOGIC && ! 198: pcibios_read_config_dword(Bus, DeviceAndFunction, ! 199: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && ! 200: (BaseAddress0 & PCI_BASE_ADDRESS_SPACE) == ! 201: PCI_BASE_ADDRESS_SPACE_IO) ! 202: { ! 203: BusLogic_IO_AddressProbeList[DestinationIndex++] = ! 204: BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; ! 205: } ! 206: } ! 207: #endif ! 208: /* ! 209: Append the list of standard BusLogic I/O Addresses. ! 210: */ ! 211: while (DestinationIndex < BusLogic_IO_MaxProbeAddresses && ! 212: BusLogic_IO_StandardAddresses[SourceIndex] > 0) ! 213: BusLogic_IO_AddressProbeList[DestinationIndex++] = ! 214: BusLogic_IO_StandardAddresses[SourceIndex++]; ! 215: BusLogic_IO_AddressProbeList[DestinationIndex] = 0; ! 216: } ! 217: ! 218: ! 219: /* ! 220: BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered ! 221: BusLogic Host Adapters. ! 222: */ ! 223: ! 224: static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 225: { ! 226: HostAdapter->Next = NULL; ! 227: if (BusLogic_RegisteredHostAdapters != NULL) ! 228: { ! 229: BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; ! 230: BusLogic_HostAdapter_T *NextHostAdapter; ! 231: while ((NextHostAdapter = LastHostAdapter->Next) != NULL) ! 232: LastHostAdapter = NextHostAdapter; ! 233: LastHostAdapter->Next = HostAdapter; ! 234: } ! 235: else BusLogic_RegisteredHostAdapters = HostAdapter; ! 236: } ! 237: ! 238: ! 239: /* ! 240: BusLogic_UnregisterHostAdapter removes Host Adapter from the list of ! 241: registered BusLogic Host Adapters. ! 242: */ ! 243: ! 244: static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 245: { ! 246: if (BusLogic_RegisteredHostAdapters != HostAdapter) ! 247: { ! 248: BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; ! 249: while (LastHostAdapter != NULL && LastHostAdapter->Next != HostAdapter) ! 250: LastHostAdapter = LastHostAdapter->Next; ! 251: if (LastHostAdapter != NULL) ! 252: LastHostAdapter->Next = HostAdapter->Next; ! 253: } ! 254: else BusLogic_RegisteredHostAdapters = HostAdapter->Next; ! 255: HostAdapter->Next = NULL; ! 256: } ! 257: ! 258: ! 259: /* ! 260: BusLogic_CreateCCBs allocates the initial Command Control Blocks (CCBs) ! 261: for Host Adapter. ! 262: */ ! 263: ! 264: static boolean BusLogic_CreateCCBs(BusLogic_HostAdapter_T *HostAdapter) ! 265: { ! 266: int i; ! 267: for (i = 0; i < BusLogic_InitialCCBs; i++) ! 268: { ! 269: BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ! 270: scsi_init_malloc(sizeof(BusLogic_CCB_T), GFP_ATOMIC | GFP_DMA); ! 271: if (CCB == NULL) ! 272: { ! 273: printk("scsi%d: UNABLE TO ALLOCATE CCB %d - DETACHING\n", ! 274: HostAdapter->HostNumber, i); ! 275: return false; ! 276: } ! 277: memset(CCB, 0, sizeof(BusLogic_CCB_T)); ! 278: CCB->HostAdapter = HostAdapter; ! 279: CCB->Status = BusLogic_CCB_Free; ! 280: CCB->Next = HostAdapter->Free_CCBs; ! 281: CCB->NextAll = HostAdapter->All_CCBs; ! 282: HostAdapter->Free_CCBs = CCB; ! 283: HostAdapter->All_CCBs = CCB; ! 284: } ! 285: return true; ! 286: } ! 287: ! 288: ! 289: /* ! 290: BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter. ! 291: */ ! 292: ! 293: static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter) ! 294: { ! 295: BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB; ! 296: HostAdapter->All_CCBs = NULL; ! 297: HostAdapter->Free_CCBs = NULL; ! 298: while ((CCB = NextCCB) != NULL) ! 299: { ! 300: NextCCB = CCB->NextAll; ! 301: scsi_init_free((char *) CCB, sizeof(BusLogic_CCB_T)); ! 302: } ! 303: } ! 304: ! 305: ! 306: /* ! 307: BusLogic_AllocateCCB allocates a CCB from the Host Adapter's free list, ! 308: allocating more memory from the Kernel if necessary. ! 309: */ ! 310: ! 311: static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T *HostAdapter) ! 312: { ! 313: static unsigned int SerialNumber = 0; ! 314: BusLogic_CCB_T *CCB; ! 315: BusLogic_LockHostAdapter(HostAdapter); ! 316: CCB = HostAdapter->Free_CCBs; ! 317: if (CCB != NULL) ! 318: { ! 319: CCB->SerialNumber = ++SerialNumber; ! 320: HostAdapter->Free_CCBs = CCB->Next; ! 321: CCB->Next = NULL; ! 322: BusLogic_UnlockHostAdapter(HostAdapter); ! 323: return CCB; ! 324: } ! 325: BusLogic_UnlockHostAdapter(HostAdapter); ! 326: CCB = (BusLogic_CCB_T *) scsi_init_malloc(sizeof(BusLogic_CCB_T), ! 327: GFP_ATOMIC | GFP_DMA); ! 328: if (CCB == NULL) ! 329: { ! 330: printk("scsi%d: Failed to allocate an additional CCB\n", ! 331: HostAdapter->HostNumber); ! 332: return NULL; ! 333: } ! 334: printk("scsi%d: Allocated an additional CCB\n", HostAdapter->HostNumber); ! 335: memset(CCB, 0, sizeof(BusLogic_CCB_T)); ! 336: CCB->HostAdapter = HostAdapter; ! 337: CCB->Status = BusLogic_CCB_Free; ! 338: BusLogic_LockHostAdapter(HostAdapter); ! 339: CCB->SerialNumber = ++SerialNumber; ! 340: CCB->NextAll = HostAdapter->All_CCBs; ! 341: HostAdapter->All_CCBs = CCB; ! 342: BusLogic_UnlockHostAdapter(HostAdapter); ! 343: return CCB; ! 344: } ! 345: ! 346: ! 347: /* ! 348: BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's ! 349: free list. ! 350: */ ! 351: ! 352: static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB) ! 353: { ! 354: BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; ! 355: BusLogic_LockHostAdapter(HostAdapter); ! 356: CCB->Command = NULL; ! 357: CCB->Status = BusLogic_CCB_Free; ! 358: CCB->Next = HostAdapter->Free_CCBs; ! 359: HostAdapter->Free_CCBs = CCB; ! 360: BusLogic_UnlockHostAdapter(HostAdapter); ! 361: } ! 362: ! 363: ! 364: /* ! 365: BusLogic_Command sends the command OperationCode to HostAdapter, optionally ! 366: providing ParameterLength bytes of ParameterData and receiving at most ! 367: ReplyLength bytes of ReplyData; any excess reply data is received but ! 368: discarded. ! 369: ! 370: On success, this function returns the number of reply bytes read from ! 371: the Host Adapter (including any discarded data); on failure, it returns ! 372: -1 if the command was invalid, or -2 if a timeout occurred. ! 373: ! 374: This function is only called during board detection and initialization, so ! 375: performance and latency are not critical, and exclusive access to the Host ! 376: Adapter hardware is assumed. Once the board and driver are initialized, the ! 377: only Host Adapter command that is issued is the single byte Start Mailbox ! 378: Scan command, which does not require waiting for the Host Adapter Ready bit ! 379: to be set in the Status Register. ! 380: */ ! 381: ! 382: static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, ! 383: BusLogic_OperationCode_T OperationCode, ! 384: void *ParameterData, ! 385: int ParameterLength, ! 386: void *ReplyData, ! 387: int ReplyLength) ! 388: { ! 389: unsigned char *ParameterPointer = (unsigned char *) ParameterData; ! 390: unsigned char *ReplyPointer = (unsigned char *) ReplyData; ! 391: unsigned char StatusRegister = 0, InterruptRegister; ! 392: long TimeoutCounter; ! 393: int ReplyBytes = 0; ! 394: /* ! 395: Clear out the Reply Data if provided. ! 396: */ ! 397: if (ReplyLength > 0) ! 398: memset(ReplyData, 0, ReplyLength); ! 399: /* ! 400: Wait for the Host Adapter Ready bit to be set and the Command/Parameter ! 401: Register Busy bit to be reset in the Status Register. ! 402: */ ! 403: TimeoutCounter = loops_per_sec >> 3; ! 404: while (--TimeoutCounter >= 0) ! 405: { ! 406: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 407: if ((StatusRegister & BusLogic_HostAdapterReady) && ! 408: !(StatusRegister & BusLogic_CommandParameterRegisterBusy)) ! 409: break; ! 410: } ! 411: BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; ! 412: if (TimeoutCounter < 0) return -2; ! 413: /* ! 414: Write the OperationCode to the Command/Parameter Register. ! 415: */ ! 416: HostAdapter->HostAdapterCommandCompleted = false; ! 417: BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); ! 418: /* ! 419: Write any additional Parameter Bytes. ! 420: */ ! 421: TimeoutCounter = 10000; ! 422: while (ParameterLength > 0 && --TimeoutCounter >= 0) ! 423: { ! 424: /* ! 425: Wait 100 microseconds to give the Host Adapter enough time to determine ! 426: whether the last value written to the Command/Parameter Register was ! 427: valid or not. If the Command Complete bit is set in the Interrupt ! 428: Register, then the Command Invalid bit in the Status Register will be ! 429: reset if the Operation Code or Parameter was valid and the command ! 430: has completed, or set if the Operation Code or Parameter was invalid. ! 431: If the Data In Register Ready bit is set in the Status Register, then ! 432: the Operation Code was valid, and data is waiting to be read back ! 433: from the Host Adapter. Otherwise, wait for the Command/Parameter ! 434: Register Busy bit in the Status Register to be reset. ! 435: */ ! 436: udelay(100); ! 437: InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); ! 438: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 439: if (InterruptRegister & BusLogic_CommandComplete) break; ! 440: if (HostAdapter->HostAdapterCommandCompleted) break; ! 441: if (StatusRegister & BusLogic_DataInRegisterReady) break; ! 442: if (StatusRegister & BusLogic_CommandParameterRegisterBusy) continue; ! 443: BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); ! 444: ParameterLength--; ! 445: } ! 446: BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; ! 447: if (TimeoutCounter < 0) return -2; ! 448: /* ! 449: The Modify I/O Address command does not cause a Command Complete Interrupt. ! 450: */ ! 451: if (OperationCode == BusLogic_ModifyIOAddress) ! 452: { ! 453: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 454: BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; ! 455: if (StatusRegister & BusLogic_CommandInvalid) return -1; ! 456: BusLogic_CommandFailureReason = NULL; ! 457: return 0; ! 458: } ! 459: /* ! 460: Select an appropriate timeout value for awaiting command completion. ! 461: */ ! 462: switch (OperationCode) ! 463: { ! 464: case BusLogic_InquireInstalledDevicesID0to7: ! 465: case BusLogic_InquireInstalledDevicesID8to15: ! 466: /* Approximately 60 seconds. */ ! 467: TimeoutCounter = loops_per_sec << 2; ! 468: break; ! 469: default: ! 470: /* Approximately 1 second. */ ! 471: TimeoutCounter = loops_per_sec >> 4; ! 472: break; ! 473: } ! 474: /* ! 475: Receive any Reply Bytes, waiting for either the Command Complete bit to ! 476: be set in the Interrupt Register, or for the Interrupt Handler to set the ! 477: Host Adapter Command Completed bit in the Host Adapter structure. ! 478: */ ! 479: while (--TimeoutCounter >= 0) ! 480: { ! 481: InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); ! 482: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 483: if (InterruptRegister & BusLogic_CommandComplete) break; ! 484: if (HostAdapter->HostAdapterCommandCompleted) break; ! 485: if (StatusRegister & BusLogic_DataInRegisterReady) ! 486: if (++ReplyBytes <= ReplyLength) ! 487: *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); ! 488: else BusLogic_ReadDataInRegister(HostAdapter); ! 489: } ! 490: BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; ! 491: if (TimeoutCounter < 0) return -2; ! 492: /* ! 493: If testing Command Complete Interrupts, wait a short while in case the ! 494: loop immediately above terminated due to the Command Complete bit being ! 495: set in the Interrupt Register, but the interrupt hasn't actually been ! 496: processed yet. Otherwise, acknowledging the interrupt here could prevent ! 497: the interrupt test from succeeding. ! 498: */ ! 499: if (OperationCode == BusLogic_TestCommandCompleteInterrupt) ! 500: udelay(10000); ! 501: /* ! 502: Clear any pending Command Complete Interrupt. ! 503: */ ! 504: BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset); ! 505: if (BusLogic_GlobalOptions & BusLogic_TraceConfiguration) ! 506: if (OperationCode != BusLogic_TestCommandCompleteInterrupt) ! 507: { ! 508: int i; ! 509: printk("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", ! 510: OperationCode, StatusRegister, ReplyLength, ReplyBytes); ! 511: if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; ! 512: for (i = 0; i < ReplyLength; i++) ! 513: printk(" %02X", ((unsigned char *) ReplyData)[i]); ! 514: printk("\n"); ! 515: } ! 516: /* ! 517: Process Command Invalid conditions. ! 518: */ ! 519: if (StatusRegister & BusLogic_CommandInvalid) ! 520: { ! 521: /* ! 522: Some early BusLogic Host Adapters may not recover properly from ! 523: a Command Invalid condition, so if this appears to be the case, ! 524: a Soft Reset is issued to the Host Adapter. Potentially invalid ! 525: commands are never attempted after Mailbox Initialization is ! 526: performed, so there should be no Host Adapter state lost by a ! 527: Soft Reset in response to a Command Invalid condition. ! 528: */ ! 529: udelay(1000); ! 530: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 531: if (StatusRegister != (BusLogic_HostAdapterReady | ! 532: BusLogic_InitializationRequired)) ! 533: { ! 534: BusLogic_WriteControlRegister(HostAdapter, BusLogic_SoftReset); ! 535: udelay(1000); ! 536: } ! 537: BusLogic_CommandFailureReason = "Command Invalid"; ! 538: return -1; ! 539: } ! 540: /* ! 541: Handle Excess Parameters Supplied conditions. ! 542: */ ! 543: BusLogic_CommandFailureReason = "Excess Parameters Supplied"; ! 544: if (ParameterLength > 0) return -1; ! 545: /* ! 546: Indicate the command completed successfully. ! 547: */ ! 548: BusLogic_CommandFailureReason = NULL; ! 549: return ReplyBytes; ! 550: } ! 551: ! 552: ! 553: /* ! 554: BusLogic_Failure prints a standardized error message, and then returns false. ! 555: */ ! 556: ! 557: static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter, ! 558: char *ErrorMessage) ! 559: { ! 560: BusLogic_AnnounceDriver(); ! 561: printk("While configuring BusLogic Host Adapter at I/O Address 0x%X:\n", ! 562: HostAdapter->IO_Address); ! 563: printk("%s FAILED - DETACHING\n", ErrorMessage); ! 564: if (BusLogic_CommandFailureReason != NULL) ! 565: printk("ADDITIONAL FAILURE INFO - %s\n", BusLogic_CommandFailureReason); ! 566: return false; ! 567: } ! 568: ! 569: ! 570: /* ! 571: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. ! 572: */ ! 573: ! 574: static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 575: { ! 576: boolean TraceProbe = (BusLogic_GlobalOptions & BusLogic_TraceProbe); ! 577: unsigned char StatusRegister, GeometryRegister; ! 578: /* ! 579: Read the Status Register to test if there is an I/O port that responds. A ! 580: nonexistent I/O port will return 0xFF, in which case there is definitely no ! 581: BusLogic Host Adapter at this base I/O Address. ! 582: */ ! 583: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 584: if (TraceProbe) ! 585: printk("BusLogic_Probe(0x%X): Status 0x%02X\n", ! 586: HostAdapter->IO_Address, StatusRegister); ! 587: if (StatusRegister == 0xFF) return false; ! 588: /* ! 589: Read the undocumented BusLogic Geometry Register to test if there is an I/O ! 590: port that responds. Adaptec Host Adapters do not implement the Geometry ! 591: Register, so this test helps serve to avoid incorrectly recognizing an ! 592: Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C ! 593: series does respond to the Geometry Register I/O port, but it will be ! 594: rejected later when the Inquire Extended Setup Information command is ! 595: issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a ! 596: BusLogic clone that implements the same interface as earlier BusLogic ! 597: boards, including the undocumented commands, and is therefore supported by ! 598: this driver. However, the AMI FastDisk always returns 0x00 upon reading ! 599: the Geometry Register, so the extended translation option should always be ! 600: left disabled on the AMI FastDisk. ! 601: */ ! 602: GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter); ! 603: if (TraceProbe) ! 604: printk("BusLogic_Probe(0x%X): Geometry 0x%02X\n", ! 605: HostAdapter->IO_Address, GeometryRegister); ! 606: if (GeometryRegister == 0xFF) return false; ! 607: /* ! 608: Indicate the Host Adapter Probe completed successfully. ! 609: */ ! 610: return true; ! 611: } ! 612: ! 613: ! 614: /* ! 615: BusLogic_HardResetHostAdapter issues a Hard Reset to the Host Adapter, ! 616: and waits for Host Adapter Diagnostics to complete. ! 617: */ ! 618: ! 619: static boolean BusLogic_HardResetHostAdapter(BusLogic_HostAdapter_T ! 620: *HostAdapter) ! 621: { ! 622: boolean TraceHardReset = (BusLogic_GlobalOptions & BusLogic_TraceHardReset); ! 623: long TimeoutCounter = loops_per_sec >> 2; ! 624: unsigned char StatusRegister = 0; ! 625: /* ! 626: Issue a Hard Reset Command to the Host Adapter. The Host Adapter should ! 627: respond by setting Diagnostic Active in the Status Register. ! 628: */ ! 629: BusLogic_WriteControlRegister(HostAdapter, BusLogic_HardReset); ! 630: /* ! 631: Wait until Diagnostic Active is set in the Status Register. ! 632: */ ! 633: while (--TimeoutCounter >= 0) ! 634: { ! 635: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 636: if ((StatusRegister & BusLogic_DiagnosticActive)) break; ! 637: } ! 638: if (TraceHardReset) ! 639: printk("BusLogic_HardReset(0x%X): Diagnostic Active, Status 0x%02X\n", ! 640: HostAdapter->IO_Address, StatusRegister); ! 641: if (TimeoutCounter < 0) return false; ! 642: /* ! 643: Wait 100 microseconds to allow completion of any initial diagnostic ! 644: activity which might leave the contents of the Status Register ! 645: unpredictable. ! 646: */ ! 647: udelay(100); ! 648: /* ! 649: Wait until Diagnostic Active is reset in the Status Register. ! 650: */ ! 651: while (--TimeoutCounter >= 0) ! 652: { ! 653: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 654: if (!(StatusRegister & BusLogic_DiagnosticActive)) break; ! 655: } ! 656: if (TraceHardReset) ! 657: printk("BusLogic_HardReset(0x%X): Diagnostic Completed, Status 0x%02X\n", ! 658: HostAdapter->IO_Address, StatusRegister); ! 659: if (TimeoutCounter < 0) return false; ! 660: /* ! 661: Wait until at least one of the Diagnostic Failure, Host Adapter Ready, ! 662: or Data In Register Ready bits is set in the Status Register. ! 663: */ ! 664: while (--TimeoutCounter >= 0) ! 665: { ! 666: StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); ! 667: if (StatusRegister & (BusLogic_DiagnosticFailure | ! 668: BusLogic_HostAdapterReady | ! 669: BusLogic_DataInRegisterReady)) ! 670: break; ! 671: } ! 672: if (TraceHardReset) ! 673: printk("BusLogic_HardReset(0x%X): Host Adapter Ready, Status 0x%02X\n", ! 674: HostAdapter->IO_Address, StatusRegister); ! 675: if (TimeoutCounter < 0) return false; ! 676: /* ! 677: If Diagnostic Failure is set or Host Adapter Ready is reset, then an ! 678: error occurred during the Host Adapter diagnostics. If Data In Register ! 679: Ready is set, then there is an Error Code available. ! 680: */ ! 681: if ((StatusRegister & BusLogic_DiagnosticFailure) || ! 682: !(StatusRegister & BusLogic_HostAdapterReady)) ! 683: { ! 684: BusLogic_CommandFailureReason = NULL; ! 685: BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); ! 686: printk("HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister); ! 687: if (StatusRegister & BusLogic_DataInRegisterReady) ! 688: { ! 689: unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); ! 690: printk("HOST ADAPTER ERROR CODE = %d\n", ErrorCode); ! 691: } ! 692: return false; ! 693: } ! 694: /* ! 695: Indicate the Host Adapter Hard Reset completed successfully. ! 696: */ ! 697: return true; ! 698: } ! 699: ! 700: ! 701: /* ! 702: BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic ! 703: Host Adapter. ! 704: */ ! 705: ! 706: static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) ! 707: { ! 708: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; ! 709: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 710: unsigned long ProcessorFlags; ! 711: int Result; ! 712: /* ! 713: Issue the Inquire Extended Setup Information command. Only genuine ! 714: BusLogic Host Adapters and true clones support this command. Adaptec 1542C ! 715: series Host Adapters that respond to the Geometry Register I/O port will ! 716: fail this command. Interrupts must be disabled around the call to ! 717: BusLogic_Command since a Command Complete interrupt could occur if the IRQ ! 718: Channel was previously enabled for another BusLogic Host Adapter sharing ! 719: the same IRQ Channel. ! 720: */ ! 721: save_flags(ProcessorFlags); ! 722: cli(); ! 723: RequestedReplyLength = sizeof(ExtendedSetupInformation); ! 724: Result = BusLogic_Command(HostAdapter, ! 725: BusLogic_InquireExtendedSetupInformation, ! 726: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 727: &ExtendedSetupInformation, ! 728: sizeof(ExtendedSetupInformation)); ! 729: restore_flags(ProcessorFlags); ! 730: if (BusLogic_GlobalOptions & BusLogic_TraceProbe) ! 731: printk("BusLogic_Check(0x%X): Result %d\n", ! 732: HostAdapter->IO_Address, Result); ! 733: return (Result == sizeof(ExtendedSetupInformation)); ! 734: } ! 735: ! 736: ! 737: /* ! 738: BusLogic_ReadHostAdapterConfiguration reads the Configuration Information ! 739: from Host Adapter. ! 740: */ ! 741: ! 742: static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T ! 743: *HostAdapter) ! 744: { ! 745: BusLogic_BoardID_T BoardID; ! 746: BusLogic_Configuration_T Configuration; ! 747: BusLogic_SetupInformation_T SetupInformation; ! 748: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; ! 749: BusLogic_BoardModelNumber_T BoardModelNumber; ! 750: BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; ! 751: BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; ! 752: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 753: unsigned char GeometryRegister, *TargetPointer, Character; ! 754: unsigned short AllTargetsMask, DisconnectPermitted; ! 755: unsigned short TaggedQueuingPermitted, TaggedQueuingPermittedDefault; ! 756: boolean CommonErrorRecovery; ! 757: int TargetID, i; ! 758: /* ! 759: Issue the Inquire Board ID command. ! 760: */ ! 761: if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, ! 762: &BoardID, sizeof(BoardID)) != sizeof(BoardID)) ! 763: return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); ! 764: /* ! 765: Issue the Inquire Configuration command. ! 766: */ ! 767: if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, ! 768: &Configuration, sizeof(Configuration)) ! 769: != sizeof(Configuration)) ! 770: return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); ! 771: /* ! 772: Issue the Inquire Setup Information command. ! 773: */ ! 774: RequestedReplyLength = sizeof(SetupInformation); ! 775: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, ! 776: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 777: &SetupInformation, sizeof(SetupInformation)) ! 778: != sizeof(SetupInformation)) ! 779: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); ! 780: /* ! 781: Issue the Inquire Extended Setup Information command. ! 782: */ ! 783: RequestedReplyLength = sizeof(ExtendedSetupInformation); ! 784: if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, ! 785: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 786: &ExtendedSetupInformation, ! 787: sizeof(ExtendedSetupInformation)) ! 788: != sizeof(ExtendedSetupInformation)) ! 789: return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); ! 790: /* ! 791: Issue the Inquire Board Model Number command. ! 792: */ ! 793: if (!(BoardID.FirmwareVersion1stDigit == '2' && ! 794: ExtendedSetupInformation.BusType == 'A')) ! 795: { ! 796: RequestedReplyLength = sizeof(BoardModelNumber); ! 797: if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardModelNumber, ! 798: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 799: &BoardModelNumber, sizeof(BoardModelNumber)) ! 800: != sizeof(BoardModelNumber)) ! 801: return BusLogic_Failure(HostAdapter, "INQUIRE BOARD MODEL NUMBER"); ! 802: } ! 803: else strcpy(BoardModelNumber, "542B"); ! 804: /* ! 805: Issue the Inquire Firmware Version 3rd Digit command. ! 806: */ ! 807: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, ! 808: NULL, 0, &FirmwareVersion3rdDigit, ! 809: sizeof(FirmwareVersion3rdDigit)) ! 810: != sizeof(FirmwareVersion3rdDigit)) ! 811: return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); ! 812: /* ! 813: Issue the Inquire Firmware Version Letter command. ! 814: */ ! 815: FirmwareVersionLetter = '\0'; ! 816: if (BoardID.FirmwareVersion1stDigit > '3' || ! 817: (BoardID.FirmwareVersion1stDigit == '3' && ! 818: BoardID.FirmwareVersion2ndDigit >= '3')) ! 819: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, ! 820: NULL, 0, &FirmwareVersionLetter, ! 821: sizeof(FirmwareVersionLetter)) ! 822: != sizeof(FirmwareVersionLetter)) ! 823: return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER"); ! 824: /* ! 825: BusLogic Host Adapters can be identified by their model number and ! 826: the major version number of their firmware as follows: ! 827: ! 828: 4.xx BusLogic "C" Series Host Adapters: ! 829: BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF ! 830: 3.xx BusLogic "S" Series Host Adapters: ! 831: BT-747S/747D/757S/757D/445S/545S/542D ! 832: BT-542B/742A (revision H) ! 833: 2.xx BusLogic "A" Series Host Adapters: ! 834: BT-542B/742A (revision G and below) ! 835: 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter ! 836: */ ! 837: /* ! 838: Save the Model Name and Board Name in the Host Adapter structure. ! 839: */ ! 840: TargetPointer = HostAdapter->ModelName; ! 841: *TargetPointer++ = 'B'; ! 842: *TargetPointer++ = 'T'; ! 843: *TargetPointer++ = '-'; ! 844: for (i = 0; i < sizeof(BoardModelNumber); i++) ! 845: { ! 846: Character = BoardModelNumber[i]; ! 847: if (Character == ' ' || Character == '\0') break; ! 848: *TargetPointer++ = Character; ! 849: } ! 850: *TargetPointer++ = '\0'; ! 851: strcpy(HostAdapter->BoardName, "BusLogic "); ! 852: strcat(HostAdapter->BoardName, HostAdapter->ModelName); ! 853: strcpy(HostAdapter->InterruptLabel, HostAdapter->BoardName); ! 854: /* ! 855: Save the Firmware Version in the Host Adapter structure. ! 856: */ ! 857: TargetPointer = HostAdapter->FirmwareVersion; ! 858: *TargetPointer++ = BoardID.FirmwareVersion1stDigit; ! 859: *TargetPointer++ = '.'; ! 860: *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; ! 861: if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') ! 862: *TargetPointer++ = FirmwareVersion3rdDigit; ! 863: if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') ! 864: *TargetPointer++ = FirmwareVersionLetter; ! 865: *TargetPointer++ = '\0'; ! 866: /* ! 867: Determine the IRQ Channel and save it in the Host Adapter structure. ! 868: */ ! 869: if (Configuration.IRQ_Channel9) ! 870: HostAdapter->IRQ_Channel = 9; ! 871: else if (Configuration.IRQ_Channel10) ! 872: HostAdapter->IRQ_Channel = 10; ! 873: else if (Configuration.IRQ_Channel11) ! 874: HostAdapter->IRQ_Channel = 11; ! 875: else if (Configuration.IRQ_Channel12) ! 876: HostAdapter->IRQ_Channel = 12; ! 877: else if (Configuration.IRQ_Channel14) ! 878: HostAdapter->IRQ_Channel = 14; ! 879: else if (Configuration.IRQ_Channel15) ! 880: HostAdapter->IRQ_Channel = 15; ! 881: /* ! 882: Determine the DMA Channel and save it in the Host Adapter structure. ! 883: */ ! 884: if (Configuration.DMA_Channel5) ! 885: HostAdapter->DMA_Channel = 5; ! 886: else if (Configuration.DMA_Channel6) ! 887: HostAdapter->DMA_Channel = 6; ! 888: else if (Configuration.DMA_Channel7) ! 889: HostAdapter->DMA_Channel = 7; ! 890: /* ! 891: Save the Host Adapter SCSI ID in the Host Adapter structure. ! 892: */ ! 893: HostAdapter->SCSI_ID = Configuration.HostAdapterID; ! 894: /* ! 895: Save the Synchronous Initiation flag and SCSI Parity Checking flag ! 896: in the Host Adapter structure. ! 897: */ ! 898: HostAdapter->SynchronousInitiation = ! 899: SetupInformation.SynchronousInitiationEnabled; ! 900: HostAdapter->ParityChecking = SetupInformation.ParityCheckEnabled; ! 901: /* ! 902: Determine the Bus Type and save it in the Host Adapter structure, ! 903: overriding the DMA Channel if it is inappropriate for the bus type. ! 904: */ ! 905: if (ExtendedSetupInformation.BusType == 'A') ! 906: HostAdapter->BusType = BusLogic_ISA_Bus; ! 907: else ! 908: switch (HostAdapter->ModelName[3]) ! 909: { ! 910: case '4': ! 911: HostAdapter->BusType = BusLogic_VESA_Bus; ! 912: HostAdapter->DMA_Channel = 0; ! 913: break; ! 914: case '5': ! 915: HostAdapter->BusType = BusLogic_ISA_Bus; ! 916: break; ! 917: case '6': ! 918: HostAdapter->BusType = BusLogic_MCA_Bus; ! 919: HostAdapter->DMA_Channel = 0; ! 920: break; ! 921: case '7': ! 922: HostAdapter->BusType = BusLogic_EISA_Bus; ! 923: HostAdapter->DMA_Channel = 0; ! 924: break; ! 925: case '9': ! 926: HostAdapter->BusType = BusLogic_PCI_Bus; ! 927: HostAdapter->DMA_Channel = 0; ! 928: break; ! 929: } ! 930: /* ! 931: Determine whether Extended Translation is enabled and save it in ! 932: the Host Adapter structure. ! 933: */ ! 934: GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter); ! 935: if (GeometryRegister & BusLogic_ExtendedTranslationEnabled) ! 936: HostAdapter->ExtendedTranslation = true; ! 937: /* ! 938: Save the Disconnect/Reconnect Permitted flag bits in the Host Adapter ! 939: structure. The Disconnect Permitted information is only valid on "C" ! 940: Series boards, but Disconnect/Reconnect is always permitted on "S" and ! 941: "A" Series boards. ! 942: */ ! 943: if (HostAdapter->FirmwareVersion[0] >= '4') ! 944: HostAdapter->DisconnectPermitted = ! 945: (SetupInformation.DisconnectPermittedID8to15 << 8) ! 946: | SetupInformation.DisconnectPermittedID0to7; ! 947: else HostAdapter->DisconnectPermitted = 0xFF; ! 948: /* ! 949: Save the Scatter Gather Limits, Level Sensitive Interrupts flag, ! 950: Wide SCSI flag, and Differential SCSI flag in the Host Adapter structure. ! 951: */ ! 952: HostAdapter->HostAdapterScatterGatherLimit = ! 953: ExtendedSetupInformation.ScatterGatherLimit; ! 954: HostAdapter->DriverScatterGatherLimit = ! 955: HostAdapter->HostAdapterScatterGatherLimit; ! 956: if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) ! 957: HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; ! 958: if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupts) ! 959: HostAdapter->LevelSensitiveInterrupts = true; ! 960: if (ExtendedSetupInformation.HostWideSCSI) ! 961: { ! 962: HostAdapter->HostWideSCSI = true; ! 963: HostAdapter->MaxTargetIDs = 16; ! 964: HostAdapter->MaxLogicalUnits = 64; ! 965: } ! 966: else ! 967: { ! 968: HostAdapter->HostWideSCSI = false; ! 969: HostAdapter->MaxTargetIDs = 8; ! 970: HostAdapter->MaxLogicalUnits = 8; ! 971: } ! 972: HostAdapter->HostDifferentialSCSI = ! 973: ExtendedSetupInformation.HostDifferentialSCSI; ! 974: /* ! 975: Determine the Host Adapter BIOS Address if the BIOS is enabled and ! 976: save it in the Host Adapter structure. The BIOS is disabled if the ! 977: BIOS_Address is 0. ! 978: */ ! 979: HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; ! 980: /* ! 981: BusLogic BT-445S Host Adapters prior to board revision D have a hardware ! 982: bug whereby when the BIOS is enabled, transfers to/from the same address ! 983: range the BIOS occupies modulo 16MB are handled incorrectly. Only properly ! 984: functioning BT-445S boards have firmware version 3.37, so we require that ! 985: ISA bounce buffers be used for the buggy BT-445S models as well as for all ! 986: ISA models. ! 987: */ ! 988: if (HostAdapter->BusType == BusLogic_ISA_Bus || ! 989: (HostAdapter->BIOS_Address > 0 && ! 990: strcmp(HostAdapter->ModelName, "BT-445S") == 0 && ! 991: strcmp(HostAdapter->FirmwareVersion, "3.37") < 0)) ! 992: HostAdapter->BounceBuffersRequired = true; ! 993: /* ! 994: Select an appropriate value for Concurrency (Commands per Logical Unit) ! 995: either from a Command Line Entry, or based on whether this Host Adapter ! 996: requires that ISA bounce buffers be used. ! 997: */ ! 998: if (HostAdapter->CommandLineEntry != NULL && ! 999: HostAdapter->CommandLineEntry->Concurrency > 0) ! 1000: HostAdapter->Concurrency = HostAdapter->CommandLineEntry->Concurrency; ! 1001: else if (HostAdapter->BounceBuffersRequired) ! 1002: HostAdapter->Concurrency = BusLogic_Concurrency_BB; ! 1003: else HostAdapter->Concurrency = BusLogic_Concurrency; ! 1004: /* ! 1005: Select an appropriate value for Bus Settle Time either from a Command ! 1006: Line Entry, or from BusLogic_DefaultBusSettleTime. ! 1007: */ ! 1008: if (HostAdapter->CommandLineEntry != NULL && ! 1009: HostAdapter->CommandLineEntry->BusSettleTime > 0) ! 1010: HostAdapter->BusSettleTime = HostAdapter->CommandLineEntry->BusSettleTime; ! 1011: else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; ! 1012: /* ! 1013: Select an appropriate value for Local Options from a Command Line Entry. ! 1014: */ ! 1015: if (HostAdapter->CommandLineEntry != NULL) ! 1016: HostAdapter->LocalOptions = HostAdapter->CommandLineEntry->LocalOptions; ! 1017: /* ! 1018: Select appropriate values for the Error Recovery Option array either from ! 1019: a Command Line Entry, or using BusLogic_ErrorRecoveryDefault. ! 1020: */ ! 1021: if (HostAdapter->CommandLineEntry != NULL) ! 1022: memcpy(HostAdapter->ErrorRecoveryOption, ! 1023: HostAdapter->CommandLineEntry->ErrorRecoveryOption, ! 1024: sizeof(HostAdapter->ErrorRecoveryOption)); ! 1025: else memset(HostAdapter->ErrorRecoveryOption, ! 1026: BusLogic_ErrorRecoveryDefault, ! 1027: sizeof(HostAdapter->ErrorRecoveryOption)); ! 1028: /* ! 1029: Tagged Queuing support is available and operates properly only on "C" ! 1030: Series boards with firmware version 4.22 and above and on "S" Series ! 1031: boards with firmware version 3.35 and above. Tagged Queuing is disabled ! 1032: by default when the Concurrency value is 1 since queuing multiple commands ! 1033: is not possible. ! 1034: */ ! 1035: TaggedQueuingPermittedDefault = 0; ! 1036: if (HostAdapter->Concurrency > 1) ! 1037: switch (HostAdapter->FirmwareVersion[0]) ! 1038: { ! 1039: case '5': ! 1040: TaggedQueuingPermittedDefault = 0xFFFF; ! 1041: break; ! 1042: case '4': ! 1043: if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) ! 1044: TaggedQueuingPermittedDefault = 0xFFFF; ! 1045: break; ! 1046: case '3': ! 1047: if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) ! 1048: TaggedQueuingPermittedDefault = 0xFFFF; ! 1049: break; ! 1050: } ! 1051: /* ! 1052: Tagged Queuing is only useful if Disconnect/Reconnect is permitted. ! 1053: Therefore, mask the Tagged Queuing Permitted Default bits with the ! 1054: Disconnect/Reconnect Permitted bits. ! 1055: */ ! 1056: TaggedQueuingPermittedDefault &= HostAdapter->DisconnectPermitted; ! 1057: /* ! 1058: Combine the default Tagged Queuing Permitted Default bits with any ! 1059: Command Line Entry Tagged Queuing specification. ! 1060: */ ! 1061: if (HostAdapter->CommandLineEntry != NULL) ! 1062: HostAdapter->TaggedQueuingPermitted = ! 1063: (HostAdapter->CommandLineEntry->TaggedQueuingPermitted & ! 1064: HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask) | ! 1065: (TaggedQueuingPermittedDefault & ! 1066: ~HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask); ! 1067: else HostAdapter->TaggedQueuingPermitted = TaggedQueuingPermittedDefault; ! 1068: /* ! 1069: Announce the Host Adapter Configuration. ! 1070: */ ! 1071: printk("scsi%d: Configuring BusLogic Model %s %s%s%s SCSI Host Adapter\n", ! 1072: HostAdapter->HostNumber, HostAdapter->ModelName, ! 1073: BusLogic_BusNames[HostAdapter->BusType], ! 1074: (HostAdapter->HostWideSCSI ? " Wide" : ""), ! 1075: (HostAdapter->HostDifferentialSCSI ? " Differential" : "")); ! 1076: printk("scsi%d: Firmware Version: %s, I/O Address: 0x%X, " ! 1077: "IRQ Channel: %d/%s\n", ! 1078: HostAdapter->HostNumber, HostAdapter->FirmwareVersion, ! 1079: HostAdapter->IO_Address, HostAdapter->IRQ_Channel, ! 1080: (HostAdapter->LevelSensitiveInterrupts ? "Level" : "Edge")); ! 1081: printk("scsi%d: DMA Channel: ", HostAdapter->HostNumber); ! 1082: if (HostAdapter->DMA_Channel > 0) ! 1083: printk("%d, ", HostAdapter->DMA_Channel); ! 1084: else printk("None, "); ! 1085: if (HostAdapter->BIOS_Address > 0) ! 1086: printk("BIOS Address: 0x%lX, ", HostAdapter->BIOS_Address); ! 1087: else printk("BIOS Address: None, "); ! 1088: printk("Host Adapter SCSI ID: %d\n", HostAdapter->SCSI_ID); ! 1089: printk("scsi%d: Scatter/Gather Limit: %d segments, " ! 1090: "Synchronous Initiation: %s\n", HostAdapter->HostNumber, ! 1091: HostAdapter->HostAdapterScatterGatherLimit, ! 1092: (HostAdapter->SynchronousInitiation ? "Enabled" : "Disabled")); ! 1093: printk("scsi%d: SCSI Parity Checking: %s, " ! 1094: "Extended Disk Translation: %s\n", HostAdapter->HostNumber, ! 1095: (HostAdapter->ParityChecking ? "Enabled" : "Disabled"), ! 1096: (HostAdapter->ExtendedTranslation ? "Enabled" : "Disabled")); ! 1097: AllTargetsMask = (1 << HostAdapter->MaxTargetIDs) - 1; ! 1098: DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; ! 1099: printk("scsi%d: Disconnect/Reconnect: ", HostAdapter->HostNumber); ! 1100: if (DisconnectPermitted == 0) ! 1101: printk("Disabled"); ! 1102: else if (DisconnectPermitted == AllTargetsMask) ! 1103: printk("Enabled"); ! 1104: else ! 1105: for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1106: printk("%c", (DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); ! 1107: printk(", Tagged Queuing: "); ! 1108: TaggedQueuingPermitted = ! 1109: HostAdapter->TaggedQueuingPermitted & AllTargetsMask; ! 1110: if (TaggedQueuingPermitted == 0) ! 1111: printk("Disabled"); ! 1112: else if (TaggedQueuingPermitted == AllTargetsMask) ! 1113: printk("Enabled"); ! 1114: else ! 1115: for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1116: printk("%c", (TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); ! 1117: printk("\n"); ! 1118: CommonErrorRecovery = true; ! 1119: for (TargetID = 1; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1120: if (HostAdapter->ErrorRecoveryOption[TargetID] != ! 1121: HostAdapter->ErrorRecoveryOption[0]) ! 1122: { ! 1123: CommonErrorRecovery = false; ! 1124: break; ! 1125: } ! 1126: printk("scsi%d: Error Recovery: ", HostAdapter->HostNumber); ! 1127: if (CommonErrorRecovery) ! 1128: printk("%s", BusLogic_ErrorRecoveryOptions[ ! 1129: HostAdapter->ErrorRecoveryOption[0]]); ! 1130: else ! 1131: for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1132: printk("%s", BusLogic_ErrorRecoveryOptions2[ ! 1133: HostAdapter->ErrorRecoveryOption[TargetID]]); ! 1134: printk(", Mailboxes: %d, Initial CCBs: %d\n", ! 1135: BusLogic_MailboxCount, BusLogic_InitialCCBs); ! 1136: printk("scsi%d: Driver Scatter/Gather Limit: %d segments, " ! 1137: "Concurrency: %d\n", HostAdapter->HostNumber, ! 1138: HostAdapter->DriverScatterGatherLimit, HostAdapter->Concurrency); ! 1139: /* ! 1140: Indicate reading the Host Adapter Configuration completed successfully. ! 1141: */ ! 1142: return true; ! 1143: } ! 1144: ! 1145: ! 1146: /* ! 1147: BusLogic_AcquireResources acquires the system resources necessary to use Host ! 1148: Adapter, and initializes the fields in the SCSI Host structure. The base, ! 1149: io_port, n_io_ports, irq, and dma_channel fields in the SCSI Host structure ! 1150: are intentionally left uninitialized, as this driver handles acquisition and ! 1151: release of these resources explicitly, as well as ensuring exclusive access ! 1152: to the Host Adapter hardware and data structures through explicit locking. ! 1153: */ ! 1154: ! 1155: static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter, ! 1156: SCSI_Host_T *Host) ! 1157: { ! 1158: /* ! 1159: Acquire exclusive or shared access to the IRQ Channel. A usage count is ! 1160: maintained so that PCI, EISA, or MCA shared Interrupts can be supported. ! 1161: */ ! 1162: if (BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]++ == 0) ! 1163: { ! 1164: if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, ! 1165: SA_INTERRUPT, HostAdapter->InterruptLabel) < 0) ! 1166: { ! 1167: BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]--; ! 1168: printk("scsi%d: UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", ! 1169: HostAdapter->HostNumber, HostAdapter->IRQ_Channel); ! 1170: return false; ! 1171: } ! 1172: } ! 1173: else ! 1174: { ! 1175: BusLogic_HostAdapter_T *FirstHostAdapter = ! 1176: BusLogic_RegisteredHostAdapters; ! 1177: while (FirstHostAdapter != NULL) ! 1178: { ! 1179: if (FirstHostAdapter->IRQ_Channel == HostAdapter->IRQ_Channel) ! 1180: { ! 1181: if (strlen(FirstHostAdapter->InterruptLabel) + 11 ! 1182: < sizeof(FirstHostAdapter->InterruptLabel)) ! 1183: { ! 1184: strcat(FirstHostAdapter->InterruptLabel, " + "); ! 1185: strcat(FirstHostAdapter->InterruptLabel, ! 1186: HostAdapter->ModelName); ! 1187: } ! 1188: break; ! 1189: } ! 1190: FirstHostAdapter = FirstHostAdapter->Next; ! 1191: } ! 1192: } ! 1193: HostAdapter->IRQ_ChannelAcquired = true; ! 1194: /* ! 1195: Acquire exclusive access to the DMA Channel. ! 1196: */ ! 1197: if (HostAdapter->DMA_Channel > 0) ! 1198: { ! 1199: if (request_dma(HostAdapter->DMA_Channel, HostAdapter->BoardName) < 0) ! 1200: { ! 1201: printk("scsi%d: UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", ! 1202: HostAdapter->HostNumber, HostAdapter->DMA_Channel); ! 1203: return false; ! 1204: } ! 1205: set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); ! 1206: enable_dma(HostAdapter->DMA_Channel); ! 1207: HostAdapter->DMA_ChannelAcquired = true; ! 1208: } ! 1209: /* ! 1210: Initialize necessary fields in the SCSI Host structure. ! 1211: */ ! 1212: Host->max_id = HostAdapter->MaxTargetIDs; ! 1213: Host->max_lun = HostAdapter->MaxLogicalUnits; ! 1214: Host->max_channel = 0; ! 1215: Host->this_id = HostAdapter->SCSI_ID; ! 1216: Host->can_queue = BusLogic_MailboxCount; ! 1217: Host->cmd_per_lun = HostAdapter->Concurrency; ! 1218: Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; ! 1219: Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; ! 1220: /* ! 1221: Indicate the System Resource Acquisition completed successfully, ! 1222: */ ! 1223: return true; ! 1224: } ! 1225: ! 1226: ! 1227: /* ! 1228: BusLogic_ReleaseResources releases any system resources previously acquired ! 1229: by BusLogic_AcquireResources. ! 1230: */ ! 1231: ! 1232: static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter) ! 1233: { ! 1234: /* ! 1235: Release exclusive or shared access to the IRQ Channel. ! 1236: */ ! 1237: if (HostAdapter->IRQ_ChannelAcquired) ! 1238: if (--BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9] == 0) ! 1239: free_irq(HostAdapter->IRQ_Channel); ! 1240: /* ! 1241: Release exclusive access to the DMA Channel. ! 1242: */ ! 1243: if (HostAdapter->DMA_ChannelAcquired) ! 1244: free_dma(HostAdapter->DMA_Channel); ! 1245: } ! 1246: ! 1247: ! 1248: /* ! 1249: BusLogic_TestInterrupts tests for proper functioning of the Host Adapter ! 1250: Interrupt Register and that interrupts generated by the Host Adapter are ! 1251: getting through to the Interrupt Handler. A large proportion of initial ! 1252: problems with installing PCI Host Adapters are due to configuration problems ! 1253: where either the Host Adapter or Motherboard is configured incorrectly, and ! 1254: interrupts do not get through as a result. ! 1255: */ ! 1256: ! 1257: static boolean BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter) ! 1258: { ! 1259: unsigned int InitialInterruptCount, FinalInterruptCount; ! 1260: int TestCount = 5, i; ! 1261: InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; ! 1262: /* ! 1263: Issue the Test Command Complete Interrupt commands. ! 1264: */ ! 1265: for (i = 0; i < TestCount; i++) ! 1266: BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt, ! 1267: NULL, 0, NULL, 0); ! 1268: /* ! 1269: Verify that BusLogic_InterruptHandler was called at least TestCount times. ! 1270: Shared IRQ Channels could cause more than TestCount interrupts to occur, ! 1271: but there should never be fewer than TestCount. ! 1272: */ ! 1273: FinalInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; ! 1274: if (FinalInterruptCount < InitialInterruptCount + TestCount) ! 1275: { ! 1276: BusLogic_Failure(HostAdapter, "HOST ADAPTER INTERRUPT TEST"); ! 1277: printk("\n\ ! 1278: Interrupts are not getting through from the Host Adapter to the BusLogic\n\ ! 1279: Driver Interrupt Handler. The most likely cause is that either the Host\n\ ! 1280: Adapter or Motherboard is configured incorrectly. Please check the Host\n\ ! 1281: Adapter configuration with AutoSCSI or by examining any dip switch and\n\ ! 1282: jumper settings on the Host Adapter, and verify that no other device is\n\ ! 1283: attempting to use the same IRQ Channel. For PCI Host Adapters, it may also\n\ ! 1284: be necessary to investigate and manually set the PCI interrupt assignments\n\ ! 1285: and edge/level interrupt type selection in the BIOS Setup Program or with\n\ ! 1286: Motherboard jumpers.\n\n"); ! 1287: return false; ! 1288: } ! 1289: /* ! 1290: Indicate the Host Adapter Interrupt Test completed successfully. ! 1291: */ ! 1292: return true; ! 1293: } ! 1294: ! 1295: ! 1296: /* ! 1297: BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only ! 1298: function called during SCSI Host Adapter detection which modifies the state ! 1299: of the Host Adapter from its initial power on or hard reset state. ! 1300: */ ! 1301: ! 1302: static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T ! 1303: *HostAdapter) ! 1304: { ! 1305: BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; ! 1306: BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest; ! 1307: BusLogic_WideModeCCBRequest_T WideModeCCBRequest; ! 1308: BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; ! 1309: /* ! 1310: Initialize the Command Successful Flag, Read/Write Operation Count, ! 1311: and Queued Operation Count for each Target. ! 1312: */ ! 1313: memset(HostAdapter->CommandSuccessfulFlag, false, ! 1314: sizeof(HostAdapter->CommandSuccessfulFlag)); ! 1315: memset(HostAdapter->ReadWriteOperationCount, 0, ! 1316: sizeof(HostAdapter->ReadWriteOperationCount)); ! 1317: memset(HostAdapter->QueuedOperationCount, 0, ! 1318: sizeof(HostAdapter->QueuedOperationCount)); ! 1319: /* ! 1320: Initialize the Outgoing and Incoming Mailbox structures. ! 1321: */ ! 1322: memset(HostAdapter->OutgoingMailboxes, 0, ! 1323: sizeof(HostAdapter->OutgoingMailboxes)); ! 1324: memset(HostAdapter->IncomingMailboxes, 0, ! 1325: sizeof(HostAdapter->IncomingMailboxes)); ! 1326: /* ! 1327: Initialize the pointers to the First, Last, and Next Mailboxes. ! 1328: */ ! 1329: HostAdapter->FirstOutgoingMailbox = &HostAdapter->OutgoingMailboxes[0]; ! 1330: HostAdapter->LastOutgoingMailbox = ! 1331: &HostAdapter->OutgoingMailboxes[BusLogic_MailboxCount-1]; ! 1332: HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; ! 1333: HostAdapter->FirstIncomingMailbox = &HostAdapter->IncomingMailboxes[0]; ! 1334: HostAdapter->LastIncomingMailbox = ! 1335: &HostAdapter->IncomingMailboxes[BusLogic_MailboxCount-1]; ! 1336: HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; ! 1337: /* ! 1338: Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. ! 1339: */ ! 1340: ExtendedMailboxRequest.MailboxCount = BusLogic_MailboxCount; ! 1341: ExtendedMailboxRequest.BaseMailboxAddress = HostAdapter->OutgoingMailboxes; ! 1342: if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, ! 1343: &ExtendedMailboxRequest, ! 1344: sizeof(ExtendedMailboxRequest), NULL, 0) < 0) ! 1345: return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); ! 1346: /* ! 1347: Enable Strict Round Robin Mode if supported by the Host Adapter. In Strict ! 1348: Round Robin Mode, the Host Adapter only looks at the next Outgoing Mailbox ! 1349: for each new command, rather than scanning through all the Outgoing ! 1350: Mailboxes to find any that have new commands in them. BusLogic indicates ! 1351: that Strict Round Robin Mode is significantly more efficient. ! 1352: */ ! 1353: if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) ! 1354: { ! 1355: RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; ! 1356: if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, ! 1357: &RoundRobinModeRequest, ! 1358: sizeof(RoundRobinModeRequest), NULL, 0) < 0) ! 1359: return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); ! 1360: } ! 1361: /* ! 1362: For Wide SCSI Host Adapters, issue the Enable Wide Mode CCB command to ! 1363: allow more than 8 Logical Units per Target to be supported. ! 1364: */ ! 1365: if (HostAdapter->HostWideSCSI) ! 1366: { ! 1367: WideModeCCBRequest = BusLogic_WideModeCCB; ! 1368: if (BusLogic_Command(HostAdapter, BusLogic_EnableWideModeCCB, ! 1369: &WideModeCCBRequest, ! 1370: sizeof(WideModeCCBRequest), NULL, 0) < 0) ! 1371: return BusLogic_Failure(HostAdapter, "ENABLE WIDE MODE CCB"); ! 1372: } ! 1373: /* ! 1374: For PCI Host Adapters being accessed through the PCI compliant I/O ! 1375: Address, disable the ISA compatible I/O Address to avoid detecting the ! 1376: same Host Adapter at both I/O Addresses. ! 1377: */ ! 1378: if (HostAdapter->BusType == BusLogic_PCI_Bus) ! 1379: { ! 1380: int Index; ! 1381: for (Index = 0; BusLogic_IO_StandardAddresses[Index] > 0; Index++) ! 1382: if (HostAdapter->IO_Address == BusLogic_IO_StandardAddresses[Index]) ! 1383: break; ! 1384: if (BusLogic_IO_StandardAddresses[Index] == 0) ! 1385: { ! 1386: ModifyIOAddressRequest = BusLogic_ModifyIO_Disable; ! 1387: if (BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, ! 1388: &ModifyIOAddressRequest, ! 1389: sizeof(ModifyIOAddressRequest), NULL, 0) < 0) ! 1390: return BusLogic_Failure(HostAdapter, "MODIFY I/O ADDRESS"); ! 1391: } ! 1392: } ! 1393: /* ! 1394: Announce Successful Initialization. ! 1395: */ ! 1396: printk("scsi%d: *** %s Initialized Successfully ***\n", ! 1397: HostAdapter->HostNumber, HostAdapter->BoardName); ! 1398: /* ! 1399: Indicate the Host Adapter Initialization completed successfully. ! 1400: */ ! 1401: return true; ! 1402: } ! 1403: ! 1404: ! 1405: /* ! 1406: BusLogic_InquireTargetDevices inquires about the Target Devices accessible ! 1407: through Host Adapter and reports on the results. ! 1408: */ ! 1409: ! 1410: static boolean BusLogic_InquireTargetDevices(BusLogic_HostAdapter_T ! 1411: *HostAdapter) ! 1412: { ! 1413: BusLogic_InstalledDevices8_T InstalledDevicesID0to7; ! 1414: BusLogic_InstalledDevices8_T InstalledDevicesID8to15; ! 1415: BusLogic_SetupInformation_T SetupInformation; ! 1416: BusLogic_SynchronousPeriod_T SynchronousPeriod; ! 1417: BusLogic_RequestedReplyLength_T RequestedReplyLength; ! 1418: int TargetDevicesFound = 0, TargetID; ! 1419: /* ! 1420: Wait a few seconds between the Host Adapter Hard Reset which initiates ! 1421: a SCSI Bus Reset and issuing any SCSI commands. Some SCSI devices get ! 1422: confused if they receive SCSI commands too soon after a SCSI Bus Reset. ! 1423: */ ! 1424: BusLogic_Delay(HostAdapter->BusSettleTime); ! 1425: /* ! 1426: Inhibit the Target Devices Inquiry if requested. ! 1427: */ ! 1428: if (HostAdapter->LocalOptions & BusLogic_InhibitTargetInquiry) ! 1429: { ! 1430: printk("scsi%d: Target Device Inquiry Inhibited\n", ! 1431: HostAdapter->HostNumber); ! 1432: return true; ! 1433: } ! 1434: /* ! 1435: Issue the Inquire Installed Devices ID 0 to 7 command, and for Wide SCSI ! 1436: Host Adapters the Inquire Installed Devices ID 8 to 15 command. This is ! 1437: necessary to force Synchronous Transfer Negotiation so that the Inquire ! 1438: Setup Information and Inquire Synchronous Period commands will return ! 1439: valid data. ! 1440: */ ! 1441: if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, ! 1442: NULL, 0, &InstalledDevicesID0to7, ! 1443: sizeof(InstalledDevicesID0to7)) ! 1444: != sizeof(InstalledDevicesID0to7)) ! 1445: return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7"); ! 1446: if (HostAdapter->HostWideSCSI) ! 1447: if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID8to15, ! 1448: NULL, 0, &InstalledDevicesID8to15, ! 1449: sizeof(InstalledDevicesID8to15)) ! 1450: != sizeof(InstalledDevicesID8to15)) ! 1451: return BusLogic_Failure(HostAdapter, ! 1452: "INQUIRE INSTALLED DEVICES ID 8 TO 15"); ! 1453: /* ! 1454: Issue the Inquire Setup Information command. ! 1455: */ ! 1456: RequestedReplyLength = sizeof(SetupInformation); ! 1457: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, ! 1458: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 1459: &SetupInformation, sizeof(SetupInformation)) ! 1460: != sizeof(SetupInformation)) ! 1461: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); ! 1462: /* ! 1463: Issue the Inquire Synchronous Period command. ! 1464: */ ! 1465: if (HostAdapter->FirmwareVersion[0] >= '3') ! 1466: { ! 1467: RequestedReplyLength = sizeof(SynchronousPeriod); ! 1468: if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, ! 1469: &RequestedReplyLength, sizeof(RequestedReplyLength), ! 1470: &SynchronousPeriod, sizeof(SynchronousPeriod)) ! 1471: != sizeof(SynchronousPeriod)) ! 1472: return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); ! 1473: } ! 1474: else ! 1475: for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1476: if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) ! 1477: SynchronousPeriod[TargetID] = ! 1478: 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] ! 1479: .TransferPeriod; ! 1480: else SynchronousPeriod[TargetID] = 0; ! 1481: /* ! 1482: Save the Installed Devices, Synchronous Values, and Synchronous Period ! 1483: information in the Host Adapter structure. ! 1484: */ ! 1485: memcpy(HostAdapter->InstalledDevices, InstalledDevicesID0to7, ! 1486: sizeof(BusLogic_InstalledDevices8_T)); ! 1487: memcpy(HostAdapter->SynchronousValues, ! 1488: SetupInformation.SynchronousValuesID0to7, ! 1489: sizeof(BusLogic_SynchronousValues8_T)); ! 1490: if (HostAdapter->HostWideSCSI) ! 1491: { ! 1492: memcpy(&HostAdapter->InstalledDevices[8], InstalledDevicesID8to15, ! 1493: sizeof(BusLogic_InstalledDevices8_T)); ! 1494: memcpy(&HostAdapter->SynchronousValues[8], ! 1495: SetupInformation.SynchronousValuesID8to15, ! 1496: sizeof(BusLogic_SynchronousValues8_T)); ! 1497: } ! 1498: memcpy(HostAdapter->SynchronousPeriod, SynchronousPeriod, ! 1499: sizeof(BusLogic_SynchronousPeriod_T)); ! 1500: for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) ! 1501: if (HostAdapter->InstalledDevices[TargetID] != 0) ! 1502: { ! 1503: int SynchronousPeriod = HostAdapter->SynchronousPeriod[TargetID]; ! 1504: if (SynchronousPeriod > 10) ! 1505: { ! 1506: int SynchronousTransferRate = 100000000 / SynchronousPeriod; ! 1507: int RoundedSynchronousTransferRate = ! 1508: (SynchronousTransferRate + 5000) / 10000; ! 1509: printk("scsi%d: Target %d: Synchronous at " ! 1510: "%d.%02d mega-transfers/second, offset %d\n", ! 1511: HostAdapter->HostNumber, TargetID, ! 1512: RoundedSynchronousTransferRate / 100, ! 1513: RoundedSynchronousTransferRate % 100, ! 1514: HostAdapter->SynchronousValues[TargetID].Offset); ! 1515: } ! 1516: else if (SynchronousPeriod > 0) ! 1517: { ! 1518: int SynchronousTransferRate = 100000000 / SynchronousPeriod; ! 1519: int RoundedSynchronousTransferRate = ! 1520: (SynchronousTransferRate + 50000) / 100000; ! 1521: printk("scsi%d: Target %d: Synchronous at " ! 1522: "%d.%01d mega-transfers/second, offset %d\n", ! 1523: HostAdapter->HostNumber, TargetID, ! 1524: RoundedSynchronousTransferRate / 10, ! 1525: RoundedSynchronousTransferRate % 10, ! 1526: HostAdapter->SynchronousValues[TargetID].Offset); ! 1527: } ! 1528: else printk("scsi%d: Target %d: Asynchronous\n", ! 1529: HostAdapter->HostNumber, TargetID); ! 1530: TargetDevicesFound++; ! 1531: } ! 1532: if (TargetDevicesFound == 0) ! 1533: printk("scsi%d: No Target Devices Found\n", HostAdapter->HostNumber); ! 1534: /* ! 1535: Indicate the Target Device Inquiry completed successfully. ! 1536: */ ! 1537: return true; ! 1538: } ! 1539: ! 1540: ! 1541: /* ! 1542: BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard ! 1543: I/O Addresses where they may be located, initializing, registering, and ! 1544: reporting the configuration of each BusLogic Host Adapter it finds. It ! 1545: returns the number of BusLogic Host Adapters successfully initialized and ! 1546: registered. ! 1547: */ ! 1548: ! 1549: int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate) ! 1550: { ! 1551: int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0; ! 1552: int AddressProbeIndex = 0; ! 1553: BusLogic_InitializeAddressProbeList(); ! 1554: while (BusLogic_IO_AddressProbeList[AddressProbeIndex] > 0) ! 1555: { ! 1556: BusLogic_HostAdapter_T HostAdapterPrototype; ! 1557: BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; ! 1558: SCSI_Host_T *Host; ! 1559: memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); ! 1560: HostAdapter->IO_Address = ! 1561: BusLogic_IO_AddressProbeList[AddressProbeIndex++]; ! 1562: /* ! 1563: Initialize the Command Line Entry field if an explicit I/O Address ! 1564: was specified. ! 1565: */ ! 1566: if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount && ! 1567: BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address == ! 1568: HostAdapter->IO_Address) ! 1569: HostAdapter->CommandLineEntry = ! 1570: &BusLogic_CommandLineEntries[CommandLineEntryIndex++]; ! 1571: /* ! 1572: Check whether the I/O Address range is already in use. ! 1573: */ ! 1574: if (check_region(HostAdapter->IO_Address, BusLogic_IO_PortCount) < 0) ! 1575: continue; ! 1576: /* ! 1577: Probe the Host Adapter. If unsuccessful, abort further initialization. ! 1578: */ ! 1579: if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue; ! 1580: /* ! 1581: Hard Reset the Host Adapter. If unsuccessful, abort further ! 1582: initialization. ! 1583: */ ! 1584: if (!BusLogic_HardResetHostAdapter(HostAdapter)) continue; ! 1585: /* ! 1586: Check the Host Adapter. If unsuccessful, abort further initialization. ! 1587: */ ! 1588: if (!BusLogic_CheckHostAdapter(HostAdapter)) continue; ! 1589: /* ! 1590: Initialize the Command Line Entry field if an explicit I/O Address ! 1591: was not specified. ! 1592: */ ! 1593: if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount && ! 1594: BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address == 0) ! 1595: HostAdapter->CommandLineEntry = ! 1596: &BusLogic_CommandLineEntries[CommandLineEntryIndex++]; ! 1597: /* ! 1598: Announce the Driver Version and Date, Author's Name, Copyright Notice, ! 1599: and Contact Address. ! 1600: */ ! 1601: BusLogic_AnnounceDriver(); ! 1602: /* ! 1603: Register usage of the I/O Address range. From this point onward, any ! 1604: failure will be assumed to be due to a problem with the Host Adapter, ! 1605: rather than due to having mistakenly identified this port as belonging ! 1606: to a BusLogic Host Adapter. The I/O Address range will not be ! 1607: released, thereby preventing it from being incorrectly identified as ! 1608: any other type of Host Adapter. ! 1609: */ ! 1610: request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, ! 1611: "BusLogic"); ! 1612: /* ! 1613: Register the SCSI Host structure. ! 1614: */ ! 1615: HostTemplate->proc_dir = &BusLogic_ProcDirectoryEntry; ! 1616: Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T)); ! 1617: HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; ! 1618: memcpy(HostAdapter, &HostAdapterPrototype, ! 1619: sizeof(BusLogic_HostAdapter_T)); ! 1620: HostAdapter->SCSI_Host = Host; ! 1621: HostAdapter->HostNumber = Host->host_no; ! 1622: /* ! 1623: Add Host Adapter to the end of the list of registered BusLogic ! 1624: Host Adapters. In order for Command Complete Interrupts to be ! 1625: properly dismissed by BusLogic_InterruptHandler, the Host Adapter ! 1626: must be registered. This must be done before the IRQ Channel is ! 1627: acquired, and in a shared IRQ Channel environment, must be done ! 1628: before any Command Complete Interrupts occur, since the IRQ Channel ! 1629: may have already been acquired by a previous BusLogic Host Adapter. ! 1630: */ ! 1631: BusLogic_RegisterHostAdapter(HostAdapter); ! 1632: /* ! 1633: Read the Host Adapter Configuration, Acquire the System Resources ! 1634: necessary to use Host Adapter and initialize the fields in the SCSI ! 1635: Host structure, then Test Interrupts, Create the CCBs, Initialize ! 1636: the Host Adapter, and finally Inquire about the Target Devices. ! 1637: */ ! 1638: if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && ! 1639: BusLogic_AcquireResources(HostAdapter, Host) && ! 1640: BusLogic_TestInterrupts(HostAdapter) && ! 1641: BusLogic_CreateCCBs(HostAdapter) && ! 1642: BusLogic_InitializeHostAdapter(HostAdapter) && ! 1643: BusLogic_InquireTargetDevices(HostAdapter)) ! 1644: { ! 1645: /* ! 1646: Initialization has been completed successfully. Release and ! 1647: re-register usage of the I/O Address range so that the Model ! 1648: Name of the Host Adapter will appear. ! 1649: */ ! 1650: release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); ! 1651: request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, ! 1652: HostAdapter->BoardName); ! 1653: BusLogicHostAdapterCount++; ! 1654: } ! 1655: else ! 1656: { ! 1657: /* ! 1658: An error occurred during Host Adapter Configuration Querying, ! 1659: Resource Acquisition, Interrupt Testing, CCB Creation, Host ! 1660: Adapter Initialization, or Target Device Inquiry, so remove ! 1661: Host Adapter from the list of registered BusLogic Host Adapters, ! 1662: destroy the CCBs, Release the System Resources, and Unregister ! 1663: the SCSI Host. ! 1664: */ ! 1665: BusLogic_DestroyCCBs(HostAdapter); ! 1666: BusLogic_ReleaseResources(HostAdapter); ! 1667: BusLogic_UnregisterHostAdapter(HostAdapter); ! 1668: scsi_unregister(Host); ! 1669: } ! 1670: } ! 1671: return BusLogicHostAdapterCount; ! 1672: } ! 1673: ! 1674: ! 1675: /* ! 1676: BusLogic_ReleaseHostAdapter releases all resources previously acquired to ! 1677: support a specific Host Adapter, including the I/O Address range, and ! 1678: unregisters the BusLogic Host Adapter. ! 1679: */ ! 1680: ! 1681: int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host) ! 1682: { ! 1683: BusLogic_HostAdapter_T *HostAdapter = ! 1684: (BusLogic_HostAdapter_T *) Host->hostdata; ! 1685: /* ! 1686: Destroy the CCBs and release any system resources acquired to use ! 1687: Host Adapter. ! 1688: */ ! 1689: BusLogic_DestroyCCBs(HostAdapter); ! 1690: BusLogic_ReleaseResources(HostAdapter); ! 1691: /* ! 1692: Release usage of the I/O Address range. ! 1693: */ ! 1694: release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); ! 1695: /* ! 1696: Remove Host Adapter from the list of registered BusLogic Host Adapters. ! 1697: */ ! 1698: BusLogic_UnregisterHostAdapter(HostAdapter); ! 1699: return 0; ! 1700: } ! 1701: ! 1702: ! 1703: /* ! 1704: BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from ! 1705: the Host Adapter Status and Target Device Status. ! 1706: */ ! 1707: ! 1708: static int BusLogic_ComputeResultCode(BusLogic_HostAdapterStatus_T ! 1709: HostAdapterStatus, ! 1710: BusLogic_TargetDeviceStatus_T ! 1711: TargetDeviceStatus) ! 1712: { ! 1713: int HostStatus; ! 1714: switch (HostAdapterStatus) ! 1715: { ! 1716: case BusLogic_CommandCompletedNormally: ! 1717: case BusLogic_LinkedCommandCompleted: ! 1718: case BusLogic_LinkedCommandCompletedWithFlag: ! 1719: HostStatus = DID_OK; ! 1720: break; ! 1721: case BusLogic_SCSISelectionTimeout: ! 1722: HostStatus = DID_TIME_OUT; ! 1723: break; ! 1724: case BusLogic_InvalidOutgoingMailboxActionCode: ! 1725: case BusLogic_InvalidCommandOperationCode: ! 1726: case BusLogic_InvalidCommandParameter: ! 1727: printk("BusLogic: BusLogic Driver Protocol Error 0x%02X\n", ! 1728: HostAdapterStatus); ! 1729: case BusLogic_DataOverUnderRun: ! 1730: case BusLogic_UnexpectedBusFree: ! 1731: case BusLogic_LinkedCCBhasInvalidLUN: ! 1732: case BusLogic_AutoRequestSenseFailed: ! 1733: case BusLogic_TaggedQueuingMessageRejected: ! 1734: case BusLogic_UnsupportedMessageReceived: ! 1735: case BusLogic_HostAdapterHardwareFailed: ! 1736: case BusLogic_TargetDeviceReconnectedImproperly: ! 1737: case BusLogic_AbortQueueGenerated: ! 1738: case BusLogic_HostAdapterSoftwareError: ! 1739: case BusLogic_HostAdapterHardwareTimeoutError: ! 1740: case BusLogic_SCSIParityErrorDetected: ! 1741: HostStatus = DID_ERROR; ! 1742: break; ! 1743: case BusLogic_InvalidBusPhaseRequested: ! 1744: case BusLogic_TargetFailedResponseToATN: ! 1745: case BusLogic_HostAdapterAssertedRST: ! 1746: case BusLogic_OtherDeviceAssertedRST: ! 1747: case BusLogic_HostAdapterAssertedBusDeviceReset: ! 1748: HostStatus = DID_RESET; ! 1749: break; ! 1750: default: ! 1751: printk("BusLogic: unknown Host Adapter Status 0x%02X\n", ! 1752: HostAdapterStatus); ! 1753: HostStatus = DID_ERROR; ! 1754: break; ! 1755: } ! 1756: return (HostStatus << 16) | TargetDeviceStatus; ! 1757: } ! 1758: ! 1759: ! 1760: /* ! 1761: BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host ! 1762: Adapters. To simplify handling shared IRQ Channels, all installed BusLogic ! 1763: Host Adapters are scanned whenever any one of them signals a hardware ! 1764: interrupt. ! 1765: */ ! 1766: ! 1767: static void BusLogic_InterruptHandler(int IRQ_Channel, ! 1768: Registers_T *InterruptRegisters) ! 1769: { ! 1770: BusLogic_CCB_T *FirstCompletedCCB = NULL, *LastCompletedCCB = NULL; ! 1771: BusLogic_HostAdapter_T *HostAdapter; ! 1772: int HostAdapterResetPendingCount = 0; ! 1773: /* ! 1774: Iterate over the installed BusLogic Host Adapters accepting any Incoming ! 1775: Mailbox entries and saving the completed CCBs for processing. This ! 1776: interrupt handler is installed with SA_INTERRUPT, so interrupts are ! 1777: disabled when the interrupt handler is entered. ! 1778: */ ! 1779: for (HostAdapter = BusLogic_RegisteredHostAdapters; ! 1780: HostAdapter != NULL; ! 1781: HostAdapter = HostAdapter->Next) ! 1782: { ! 1783: unsigned char InterruptRegister; ! 1784: /* ! 1785: Acquire exclusive access to Host Adapter. ! 1786: */ ! 1787: BusLogic_LockHostAdapterID(HostAdapter); ! 1788: /* ! 1789: Read the Host Adapter Interrupt Register. ! 1790: */ ! 1791: InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); ! 1792: if (InterruptRegister & BusLogic_InterruptValid) ! 1793: { ! 1794: /* ! 1795: Acknowledge the interrupt and reset the Host Adapter ! 1796: Interrupt Register. ! 1797: */ ! 1798: BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset); ! 1799: /* ! 1800: Process valid SCSI Reset State and Incoming Mailbox Loaded ! 1801: interrupts. Command Complete interrupts are noted, and ! 1802: Outgoing Mailbox Available interrupts are ignored, as they ! 1803: are never enabled. ! 1804: */ ! 1805: if (InterruptRegister & BusLogic_SCSIResetState) ! 1806: { ! 1807: HostAdapter->HostAdapterResetPending = true; ! 1808: HostAdapterResetPendingCount++; ! 1809: } ! 1810: else if (InterruptRegister & BusLogic_IncomingMailboxLoaded) ! 1811: { ! 1812: /* ! 1813: Scan through the Incoming Mailboxes in Strict Round Robin ! 1814: fashion, saving any completed CCBs for further processing. ! 1815: It is essential that for each CCB and SCSI Command issued, ! 1816: command completion processing is performed exactly once. ! 1817: Therefore, only Incoming Mailboxes with completion code ! 1818: Command Completed Without Error, Command Completed With ! 1819: Error, or Command Aborted At Host Request are saved for ! 1820: completion processing. When an Incoming Mailbox has a ! 1821: completion code of Aborted Command Not Found, the CCB had ! 1822: already completed or been aborted before the current Abort ! 1823: request was processed, and so completion processing has ! 1824: already occurred and no further action should be taken. ! 1825: */ ! 1826: BusLogic_IncomingMailbox_T *NextIncomingMailbox = ! 1827: HostAdapter->NextIncomingMailbox; ! 1828: BusLogic_CompletionCode_T MailboxCompletionCode; ! 1829: while ((MailboxCompletionCode = ! 1830: NextIncomingMailbox->CompletionCode) != ! 1831: BusLogic_IncomingMailboxFree) ! 1832: { ! 1833: BusLogic_CCB_T *CCB = NextIncomingMailbox->CCB; ! 1834: if (MailboxCompletionCode != BusLogic_AbortedCommandNotFound) ! 1835: if (CCB->Status == BusLogic_CCB_Active) ! 1836: { ! 1837: /* ! 1838: Mark this CCB as completed and add it to the end ! 1839: of the list of completed CCBs. ! 1840: */ ! 1841: CCB->Status = BusLogic_CCB_Completed; ! 1842: CCB->MailboxCompletionCode = MailboxCompletionCode; ! 1843: CCB->Next = NULL; ! 1844: if (FirstCompletedCCB == NULL) ! 1845: { ! 1846: FirstCompletedCCB = CCB; ! 1847: LastCompletedCCB = CCB; ! 1848: } ! 1849: else ! 1850: { ! 1851: LastCompletedCCB->Next = CCB; ! 1852: LastCompletedCCB = CCB; ! 1853: } ! 1854: HostAdapter->QueuedOperationCount[CCB->TargetID]--; ! 1855: } ! 1856: else ! 1857: { ! 1858: /* ! 1859: If a CCB ever appears in an Incoming Mailbox and ! 1860: is not marked as status Active, then there is ! 1861: most likely a bug in the Host Adapter firmware. ! 1862: */ ! 1863: printk("scsi%d: Illegal CCB #%d status %d in " ! 1864: "Incoming Mailbox\n", HostAdapter->HostNumber, ! 1865: CCB->SerialNumber, CCB->Status); ! 1866: } ! 1867: else printk("scsi%d: Aborted CCB #%d to Target %d " ! 1868: "Not Found\n", HostAdapter->HostNumber, ! 1869: CCB->SerialNumber, CCB->TargetID); ! 1870: NextIncomingMailbox->CompletionCode = ! 1871: BusLogic_IncomingMailboxFree; ! 1872: if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) ! 1873: NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; ! 1874: } ! 1875: HostAdapter->NextIncomingMailbox = NextIncomingMailbox; ! 1876: } ! 1877: else if (InterruptRegister & BusLogic_CommandComplete) ! 1878: HostAdapter->HostAdapterCommandCompleted = true; ! 1879: } ! 1880: /* ! 1881: Release exclusive access to Host Adapter. ! 1882: */ ! 1883: BusLogic_UnlockHostAdapterID(HostAdapter); ! 1884: } ! 1885: /* ! 1886: Enable interrupts while the completed CCBs are processed. ! 1887: */ ! 1888: sti(); ! 1889: /* ! 1890: Iterate over the Host Adapters performing any pending Host Adapter Resets. ! 1891: */ ! 1892: if (HostAdapterResetPendingCount > 0) ! 1893: for (HostAdapter = BusLogic_RegisteredHostAdapters; ! 1894: HostAdapter != NULL; ! 1895: HostAdapter = HostAdapter->Next) ! 1896: if (HostAdapter->HostAdapterResetPending) ! 1897: { ! 1898: BusLogic_ResetHostAdapter(HostAdapter, NULL); ! 1899: HostAdapter->HostAdapterResetPending = false; ! 1900: scsi_mark_host_bus_reset(HostAdapter->SCSI_Host); ! 1901: } ! 1902: /* ! 1903: Iterate over the completed CCBs setting the SCSI Command Result Codes, ! 1904: deallocating the CCBs, and calling the Completion Routines. ! 1905: */ ! 1906: while (FirstCompletedCCB != NULL) ! 1907: { ! 1908: BusLogic_CCB_T *CCB = FirstCompletedCCB; ! 1909: SCSI_Command_T *Command = CCB->Command; ! 1910: FirstCompletedCCB = FirstCompletedCCB->Next; ! 1911: HostAdapter = CCB->HostAdapter; ! 1912: /* ! 1913: Bus Device Reset CCBs have the Command field non-NULL only when a Bus ! 1914: Device Reset was requested for a command that was not currently active ! 1915: in the Host Adapter, and hence would not have its Completion Routine ! 1916: called otherwise. ! 1917: */ ! 1918: if (CCB->Opcode == BusLogic_SCSIBusDeviceReset) ! 1919: { ! 1920: printk("scsi%d: Bus Device Reset CCB #%d to Target %d Completed\n", ! 1921: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 1922: if (Command != NULL) Command->result = DID_RESET << 16; ! 1923: } ! 1924: else ! 1925: /* ! 1926: Translate the Mailbox Completion Code, Host Adapter Status, and ! 1927: Target Device Status into a SCSI Subsystem Result Code. ! 1928: */ ! 1929: switch (CCB->MailboxCompletionCode) ! 1930: { ! 1931: case BusLogic_IncomingMailboxFree: ! 1932: case BusLogic_AbortedCommandNotFound: ! 1933: printk("scsi%d: CCB #%d to Target %d Impossible State\n", ! 1934: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 1935: break; ! 1936: case BusLogic_CommandCompletedWithoutError: ! 1937: HostAdapter->CommandSuccessfulFlag[CCB->TargetID] = true; ! 1938: Command->result = DID_OK << 16; ! 1939: break; ! 1940: case BusLogic_CommandAbortedAtHostRequest: ! 1941: printk("scsi%d: CCB #%d to Target %d Aborted\n", ! 1942: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 1943: Command->result = DID_ABORT << 16; ! 1944: break; ! 1945: case BusLogic_CommandCompletedWithError: ! 1946: Command->result = ! 1947: BusLogic_ComputeResultCode(CCB->HostAdapterStatus, ! 1948: CCB->TargetDeviceStatus); ! 1949: if (BusLogic_GlobalOptions & BusLogic_TraceErrors) ! 1950: if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) ! 1951: { ! 1952: int i; ! 1953: printk("scsi%d: CCB #%d Target %d: Result %X " ! 1954: "Host Adapter Status %02X Target Status %02X\n", ! 1955: HostAdapter->HostNumber, CCB->SerialNumber, ! 1956: CCB->TargetID, Command->result, ! 1957: CCB->HostAdapterStatus, CCB->TargetDeviceStatus); ! 1958: printk("scsi%d: CDB ", HostAdapter->HostNumber); ! 1959: for (i = 0; i < CCB->CDB_Length; i++) ! 1960: printk(" %02X", CCB->CDB[i]); ! 1961: printk("\n"); ! 1962: printk("scsi%d: Sense ", HostAdapter->HostNumber); ! 1963: for (i = 0; i < CCB->SenseDataLength; i++) ! 1964: printk(" %02X", (*CCB->SenseDataPointer)[i]); ! 1965: printk("\n"); ! 1966: } ! 1967: break; ! 1968: } ! 1969: /* ! 1970: Place CCB back on the Host Adapter's free list. ! 1971: */ ! 1972: BusLogic_DeallocateCCB(CCB); ! 1973: /* ! 1974: Call the SCSI Command Completion Routine if appropriate. ! 1975: */ ! 1976: if (Command != NULL) Command->scsi_done(Command); ! 1977: } ! 1978: } ! 1979: ! 1980: ! 1981: /* ! 1982: BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing ! 1983: Mailbox for execution by Host Adapter. ! 1984: */ ! 1985: ! 1986: static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T ! 1987: *HostAdapter, ! 1988: BusLogic_ActionCode_T ActionCode, ! 1989: BusLogic_CCB_T *CCB) ! 1990: { ! 1991: BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; ! 1992: boolean Result = false; ! 1993: BusLogic_LockHostAdapter(HostAdapter); ! 1994: NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; ! 1995: if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) ! 1996: { ! 1997: CCB->Status = BusLogic_CCB_Active; ! 1998: /* ! 1999: The CCB field must be written before the Action Code field since ! 2000: the Host Adapter is operating asynchronously and the locking code ! 2001: does not protect against simultaneous access by the Host Adapter. ! 2002: */ ! 2003: NextOutgoingMailbox->CCB = CCB; ! 2004: NextOutgoingMailbox->ActionCode = ActionCode; ! 2005: BusLogic_StartMailboxScan(HostAdapter); ! 2006: if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) ! 2007: NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; ! 2008: HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; ! 2009: if (ActionCode == BusLogic_MailboxStartCommand) ! 2010: HostAdapter->QueuedOperationCount[CCB->TargetID]++; ! 2011: Result = true; ! 2012: } ! 2013: BusLogic_UnlockHostAdapter(HostAdapter); ! 2014: return Result; ! 2015: } ! 2016: ! 2017: ! 2018: /* ! 2019: BusLogic_QueueCommand creates a CCB for Command and places it into an ! 2020: Outgoing Mailbox for execution by the associated Host Adapter. ! 2021: */ ! 2022: ! 2023: int BusLogic_QueueCommand(SCSI_Command_T *Command, ! 2024: void (*CompletionRoutine)(SCSI_Command_T *)) ! 2025: { ! 2026: BusLogic_HostAdapter_T *HostAdapter = ! 2027: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 2028: unsigned char *CDB = Command->cmnd; ! 2029: unsigned char CDB_Length = Command->cmd_len; ! 2030: unsigned char TargetID = Command->target; ! 2031: unsigned char LogicalUnit = Command->lun; ! 2032: void *BufferPointer = Command->request_buffer; ! 2033: int BufferLength = Command->request_bufflen; ! 2034: int SegmentCount = Command->use_sg; ! 2035: BusLogic_CCB_T *CCB; ! 2036: long EnableTQ; ! 2037: /* ! 2038: SCSI REQUEST_SENSE commands will be executed automatically by the Host ! 2039: Adapter for any errors, so they should not be executed explicitly unless ! 2040: the Sense Data is zero indicating that no error occurred. ! 2041: */ ! 2042: if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) ! 2043: { ! 2044: Command->result = DID_OK << 16; ! 2045: CompletionRoutine(Command); ! 2046: return 0; ! 2047: } ! 2048: /* ! 2049: Allocate a CCB from the Host Adapter's free list. If there are none ! 2050: available and memory allocation fails, return a result code of Bus Busy ! 2051: so that this Command will be retried. ! 2052: */ ! 2053: CCB = BusLogic_AllocateCCB(HostAdapter); ! 2054: if (CCB == NULL) ! 2055: { ! 2056: Command->result = DID_BUS_BUSY << 16; ! 2057: CompletionRoutine(Command); ! 2058: return 0; ! 2059: } ! 2060: /* ! 2061: Initialize the fields in the BusLogic Command Control Block (CCB). ! 2062: */ ! 2063: if (SegmentCount == 0) ! 2064: { ! 2065: CCB->Opcode = BusLogic_InitiatorCCB; ! 2066: CCB->DataLength = BufferLength; ! 2067: CCB->DataPointer = BufferPointer; ! 2068: } ! 2069: else ! 2070: { ! 2071: SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer; ! 2072: int Segment; ! 2073: CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; ! 2074: CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T); ! 2075: CCB->DataPointer = CCB->ScatterGatherList; ! 2076: for (Segment = 0; Segment < SegmentCount; Segment++) ! 2077: { ! 2078: CCB->ScatterGatherList[Segment].SegmentByteCount = ! 2079: ScatterList[Segment].length; ! 2080: CCB->ScatterGatherList[Segment].SegmentDataPointer = ! 2081: ScatterList[Segment].address; ! 2082: } ! 2083: } ! 2084: switch (CDB[0]) ! 2085: { ! 2086: case READ_6: ! 2087: case READ_10: ! 2088: CCB->DataDirection = BusLogic_DataInLengthChecked; ! 2089: HostAdapter->ReadWriteOperationCount[TargetID]++; ! 2090: break; ! 2091: case WRITE_6: ! 2092: case WRITE_10: ! 2093: CCB->DataDirection = BusLogic_DataOutLengthChecked; ! 2094: HostAdapter->ReadWriteOperationCount[TargetID]++; ! 2095: break; ! 2096: default: ! 2097: CCB->DataDirection = BusLogic_UncheckedDataTransfer; ! 2098: break; ! 2099: } ! 2100: CCB->CDB_Length = CDB_Length; ! 2101: CCB->SenseDataLength = sizeof(Command->sense_buffer); ! 2102: CCB->HostAdapterStatus = 0; ! 2103: CCB->TargetDeviceStatus = 0; ! 2104: CCB->TargetID = TargetID; ! 2105: CCB->LogicalUnit = LogicalUnit; ! 2106: /* ! 2107: For Wide SCSI Host Adapters, Wide Mode CCBs are used to support more than ! 2108: 8 Logical Units per Target, and this requires setting the overloaded ! 2109: TagEnable field to Logical Unit bit 5. ! 2110: */ ! 2111: if (HostAdapter->HostWideSCSI) ! 2112: { ! 2113: CCB->TagEnable = LogicalUnit >> 5; ! 2114: CCB->WideModeTagEnable = false; ! 2115: } ! 2116: else CCB->TagEnable = false; ! 2117: /* ! 2118: BusLogic recommends that after a Reset the first couple of commands that ! 2119: are sent to a Target be sent in a non Tagged Queue fashion so that the Host ! 2120: Adapter and Target can establish Synchronous Transfer before Queue Tag ! 2121: messages can interfere with the Synchronous Negotiation message. By ! 2122: waiting to enable tagged Queuing until after the first 16 read/write ! 2123: commands have been sent, it is assured that the Tagged Queuing message ! 2124: will not occur while the partition table is printed. ! 2125: */ ! 2126: if ((HostAdapter->TaggedQueuingPermitted & (1 << TargetID)) && ! 2127: Command->device->tagged_supported && ! 2128: (EnableTQ = HostAdapter->ReadWriteOperationCount[TargetID] - 16) >= 0) ! 2129: { ! 2130: BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; ! 2131: unsigned long CurrentTime = jiffies; ! 2132: if (EnableTQ == 0) ! 2133: printk("scsi%d: Tagged Queuing now active for Target %d\n", ! 2134: HostAdapter->HostNumber, TargetID); ! 2135: /* ! 2136: When using Tagged Queuing with Simple Queue Tags, it appears that disk ! 2137: drive controllers do not guarantee that a queued command will not ! 2138: remain in a disconnected state indefinitely if commands that read or ! 2139: write nearer the head position continue to arrive without interruption. ! 2140: Therefore, for each Target Device this driver keeps track of the last ! 2141: time either the queue was empty or an Ordered Queue Tag was issued. If ! 2142: more than 2 seconds have elapsed since this last sequence point, this ! 2143: command will be issued with an Ordered Queue Tag rather than a Simple ! 2144: Queue Tag, which forces the Target Device to complete all previously ! 2145: queued commands before this command may be executed. ! 2146: */ ! 2147: if (HostAdapter->QueuedOperationCount[TargetID] == 0) ! 2148: HostAdapter->LastSequencePoint[TargetID] = CurrentTime; ! 2149: else if (CurrentTime - HostAdapter->LastSequencePoint[TargetID] > 2*HZ) ! 2150: { ! 2151: HostAdapter->LastSequencePoint[TargetID] = CurrentTime; ! 2152: QueueTag = BusLogic_OrderedQueueTag; ! 2153: } ! 2154: if (HostAdapter->HostWideSCSI) ! 2155: { ! 2156: CCB->WideModeTagEnable = true; ! 2157: CCB->WideModeQueueTag = QueueTag; ! 2158: } ! 2159: else ! 2160: { ! 2161: CCB->TagEnable = true; ! 2162: CCB->QueueTag = QueueTag; ! 2163: } ! 2164: } ! 2165: memcpy(CCB->CDB, CDB, CDB_Length); ! 2166: CCB->SenseDataPointer = (SCSI_SenseData_T *) &Command->sense_buffer; ! 2167: CCB->Command = Command; ! 2168: Command->scsi_done = CompletionRoutine; ! 2169: /* ! 2170: Place the CCB in an Outgoing Mailbox. If there are no Outgoing ! 2171: Mailboxes available, return a result code of Bus Busy so that this ! 2172: Command will be retried. ! 2173: */ ! 2174: if (!(BusLogic_WriteOutgoingMailbox(HostAdapter, ! 2175: BusLogic_MailboxStartCommand, CCB))) ! 2176: { ! 2177: printk("scsi%d: cannot write Outgoing Mailbox\n", ! 2178: HostAdapter->HostNumber); ! 2179: BusLogic_DeallocateCCB(CCB); ! 2180: Command->result = DID_BUS_BUSY << 16; ! 2181: CompletionRoutine(Command); ! 2182: } ! 2183: return 0; ! 2184: } ! 2185: ! 2186: ! 2187: /* ! 2188: BusLogic_AbortCommand aborts Command if possible. ! 2189: */ ! 2190: ! 2191: int BusLogic_AbortCommand(SCSI_Command_T *Command) ! 2192: { ! 2193: BusLogic_HostAdapter_T *HostAdapter = ! 2194: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 2195: unsigned long CommandPID = Command->pid; ! 2196: unsigned char InterruptRegister; ! 2197: BusLogic_CCB_T *CCB; ! 2198: int Result; ! 2199: /* ! 2200: If the Host Adapter has posted an interrupt but the Interrupt Handler ! 2201: has not been called for some reason (i.e. the interrupt was lost), try ! 2202: calling the Interrupt Handler directly to process the commands that ! 2203: have been completed. ! 2204: */ ! 2205: InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); ! 2206: if (InterruptRegister & BusLogic_InterruptValid) ! 2207: { ! 2208: unsigned long ProcessorFlags; ! 2209: printk("scsi%d: Recovering Lost/Delayed Interrupt for IRQ Channel %d\n", ! 2210: HostAdapter->HostNumber, HostAdapter->IRQ_Channel); ! 2211: save_flags(ProcessorFlags); ! 2212: cli(); ! 2213: BusLogic_InterruptHandler(HostAdapter->IRQ_Channel, NULL); ! 2214: restore_flags(ProcessorFlags); ! 2215: return SCSI_ABORT_SNOOZE; ! 2216: } ! 2217: /* ! 2218: Find the CCB to be aborted if possible. ! 2219: */ ! 2220: BusLogic_LockHostAdapter(HostAdapter); ! 2221: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 2222: if (CCB->Command == Command) break; ! 2223: BusLogic_UnlockHostAdapter(HostAdapter); ! 2224: if (CCB == NULL) ! 2225: { ! 2226: printk("scsi%d: Unable to Abort Command to Target %d - No CCB Found\n", ! 2227: HostAdapter->HostNumber, Command->target); ! 2228: return SCSI_ABORT_NOT_RUNNING; ! 2229: } ! 2230: /* ! 2231: Briefly pause to see if this command will complete. ! 2232: */ ! 2233: printk("scsi%d: Pausing briefly to see if CCB #%d " ! 2234: "to Target %d will complete\n", ! 2235: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 2236: BusLogic_Delay(2); ! 2237: /* ! 2238: If this CCB is still Active and still refers to the same Command, then ! 2239: actually aborting this Command is necessary. ! 2240: */ ! 2241: BusLogic_LockHostAdapter(HostAdapter); ! 2242: Result = SCSI_ABORT_NOT_RUNNING; ! 2243: if (CCB->Status == BusLogic_CCB_Active && ! 2244: CCB->Command == Command && Command->pid == CommandPID) ! 2245: { ! 2246: /* ! 2247: Attempt to abort this CCB. ! 2248: */ ! 2249: if (BusLogic_WriteOutgoingMailbox(HostAdapter, ! 2250: BusLogic_MailboxAbortCommand, CCB)) ! 2251: { ! 2252: printk("scsi%d: Aborting CCB #%d to Target %d\n", ! 2253: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 2254: Result = SCSI_ABORT_PENDING; ! 2255: } ! 2256: else ! 2257: { ! 2258: printk("scsi%d: Unable to Abort CCB #%d to Target %d - " ! 2259: "No Outgoing Mailboxes\n", HostAdapter->HostNumber, ! 2260: CCB->SerialNumber, CCB->TargetID); ! 2261: Result = SCSI_ABORT_BUSY; ! 2262: } ! 2263: } ! 2264: else printk("scsi%d: CCB #%d to Target %d completed\n", ! 2265: HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); ! 2266: BusLogic_UnlockHostAdapter(HostAdapter); ! 2267: return Result; ! 2268: } ! 2269: ! 2270: ! 2271: /* ! 2272: BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all ! 2273: currently executing SCSI commands as having been reset, as well as ! 2274: the specified Command if non-NULL. ! 2275: */ ! 2276: ! 2277: static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, ! 2278: SCSI_Command_T *Command) ! 2279: { ! 2280: BusLogic_CCB_T *CCB; ! 2281: if (Command == NULL) ! 2282: printk("scsi%d: Resetting %s due to SCSI Reset State Interrupt\n", ! 2283: HostAdapter->HostNumber, HostAdapter->BoardName); ! 2284: else printk("scsi%d: Resetting %s due to Target %d\n", ! 2285: HostAdapter->HostNumber, HostAdapter->BoardName, Command->target); ! 2286: /* ! 2287: Attempt to Reset and Reinitialize the Host Adapter. ! 2288: */ ! 2289: BusLogic_LockHostAdapter(HostAdapter); ! 2290: if (!(BusLogic_HardResetHostAdapter(HostAdapter) && ! 2291: BusLogic_InitializeHostAdapter(HostAdapter))) ! 2292: { ! 2293: printk("scsi%d: Resetting %s Failed\n", ! 2294: HostAdapter->HostNumber, HostAdapter->BoardName); ! 2295: BusLogic_UnlockHostAdapter(HostAdapter); ! 2296: return SCSI_RESET_ERROR; ! 2297: } ! 2298: BusLogic_UnlockHostAdapter(HostAdapter); ! 2299: /* ! 2300: Wait a few seconds between the Host Adapter Hard Reset which initiates ! 2301: a SCSI Bus Reset and issuing any SCSI commands. Some SCSI devices get ! 2302: confused if they receive SCSI commands too soon after a SCSI Bus Reset. ! 2303: */ ! 2304: BusLogic_Delay(HostAdapter->BusSettleTime); ! 2305: /* ! 2306: Mark all currently executing CCBs as having been reset. ! 2307: */ ! 2308: BusLogic_LockHostAdapter(HostAdapter); ! 2309: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 2310: if (CCB->Status == BusLogic_CCB_Active) ! 2311: { ! 2312: CCB->Status = BusLogic_CCB_Reset; ! 2313: if (CCB->Command == Command) ! 2314: { ! 2315: CCB->Command = NULL; ! 2316: /* ! 2317: Disable Tagged Queuing if it was active for this Target Device. ! 2318: */ ! 2319: if (((HostAdapter->HostWideSCSI && CCB->WideModeTagEnable) || ! 2320: (!HostAdapter->HostWideSCSI && CCB->TagEnable)) && ! 2321: (HostAdapter->TaggedQueuingPermitted & (1 << CCB->TargetID))) ! 2322: { ! 2323: HostAdapter->TaggedQueuingPermitted &= ~(1 << CCB->TargetID); ! 2324: printk("scsi%d: Tagged Queuing now disabled for Target %d\n", ! 2325: HostAdapter->HostNumber, CCB->TargetID); ! 2326: } ! 2327: } ! 2328: } ! 2329: BusLogic_UnlockHostAdapter(HostAdapter); ! 2330: /* ! 2331: Perform completion processing for the Command being Reset. ! 2332: */ ! 2333: if (Command != NULL) ! 2334: { ! 2335: Command->result = DID_RESET << 16; ! 2336: Command->scsi_done(Command); ! 2337: } ! 2338: /* ! 2339: Perform completion processing for any other active CCBs. ! 2340: */ ! 2341: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) ! 2342: if (CCB->Status == BusLogic_CCB_Reset) ! 2343: { ! 2344: Command = CCB->Command; ! 2345: BusLogic_DeallocateCCB(CCB); ! 2346: if (Command != NULL) ! 2347: { ! 2348: Command->result = DID_RESET << 16; ! 2349: Command->scsi_done(Command); ! 2350: } ! 2351: } ! 2352: return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; ! 2353: } ! 2354: ! 2355: ! 2356: /* ! 2357: BusLogic_BusDeviceReset sends a Bus Device Reset to the Target ! 2358: associated with Command. ! 2359: */ ! 2360: ! 2361: static int BusLogic_BusDeviceReset(BusLogic_HostAdapter_T *HostAdapter, ! 2362: SCSI_Command_T *Command) ! 2363: { ! 2364: BusLogic_CCB_T *CCB = BusLogic_AllocateCCB(HostAdapter), *XCCB; ! 2365: unsigned char TargetID = Command->target; ! 2366: /* ! 2367: If sending a Bus Device Reset is impossible, attempt a full Host ! 2368: Adapter Hard Reset and SCSI Bus Reset. ! 2369: */ ! 2370: if (CCB == NULL) ! 2371: return BusLogic_ResetHostAdapter(HostAdapter, Command); ! 2372: printk("scsi%d: Sending Bus Device Reset CCB #%d to Target %d\n", ! 2373: HostAdapter->HostNumber, CCB->SerialNumber, TargetID); ! 2374: CCB->Opcode = BusLogic_SCSIBusDeviceReset; ! 2375: CCB->TargetID = TargetID; ! 2376: CCB->Command = Command; ! 2377: /* ! 2378: If there is a currently executing CCB in the Host Adapter for this Command, ! 2379: then an Incoming Mailbox entry will be made with a completion code of ! 2380: BusLogic_HostAdapterAssertedBusDeviceReset. Otherwise, the CCB's Command ! 2381: field will be left pointing to the Command so that the interrupt for the ! 2382: completion of the Bus Device Reset can call the Completion Routine for the ! 2383: Command. ! 2384: */ ! 2385: BusLogic_LockHostAdapter(HostAdapter); ! 2386: for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll) ! 2387: if (XCCB->Command == Command && XCCB->Status == BusLogic_CCB_Active) ! 2388: { ! 2389: CCB->Command = NULL; ! 2390: /* ! 2391: Disable Tagged Queuing if it was active for this Target Device. ! 2392: */ ! 2393: if (((HostAdapter->HostWideSCSI && XCCB->WideModeTagEnable) || ! 2394: (!HostAdapter->HostWideSCSI && XCCB->TagEnable)) && ! 2395: (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) ! 2396: { ! 2397: HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); ! 2398: printk("scsi%d: Tagged Queuing now disabled for Target %d\n", ! 2399: HostAdapter->HostNumber, TargetID); ! 2400: } ! 2401: break; ! 2402: } ! 2403: BusLogic_UnlockHostAdapter(HostAdapter); ! 2404: /* ! 2405: Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. ! 2406: If sending a Bus Device Reset is impossible, attempt a full Host ! 2407: Adapter Hard Reset and SCSI Bus Reset. ! 2408: */ ! 2409: if (!(BusLogic_WriteOutgoingMailbox(HostAdapter, ! 2410: BusLogic_MailboxStartCommand, CCB))) ! 2411: { ! 2412: printk("scsi%d: cannot write Outgoing Mailbox for Bus Device Reset\n", ! 2413: HostAdapter->HostNumber); ! 2414: BusLogic_DeallocateCCB(CCB); ! 2415: return BusLogic_ResetHostAdapter(HostAdapter, Command); ! 2416: } ! 2417: HostAdapter->ReadWriteOperationCount[TargetID] = 0; ! 2418: HostAdapter->QueuedOperationCount[TargetID] = 0; ! 2419: return SCSI_RESET_PENDING; ! 2420: } ! 2421: ! 2422: ! 2423: /* ! 2424: BusLogic_ResetCommand takes appropriate action to reset Command. ! 2425: */ ! 2426: ! 2427: int BusLogic_ResetCommand(SCSI_Command_T *Command) ! 2428: { ! 2429: BusLogic_HostAdapter_T *HostAdapter = ! 2430: (BusLogic_HostAdapter_T *) Command->host->hostdata; ! 2431: unsigned char TargetID = Command->target; ! 2432: unsigned char ErrorRecoveryOption = ! 2433: HostAdapter->ErrorRecoveryOption[TargetID]; ! 2434: if (ErrorRecoveryOption == BusLogic_ErrorRecoveryDefault) ! 2435: if (Command->host->suggest_bus_reset) ! 2436: ErrorRecoveryOption = BusLogic_ErrorRecoveryHardReset; ! 2437: else ErrorRecoveryOption = BusLogic_ErrorRecoveryBusDeviceReset; ! 2438: switch (ErrorRecoveryOption) ! 2439: { ! 2440: case BusLogic_ErrorRecoveryHardReset: ! 2441: return BusLogic_ResetHostAdapter(HostAdapter, Command); ! 2442: case BusLogic_ErrorRecoveryBusDeviceReset: ! 2443: if (HostAdapter->CommandSuccessfulFlag[TargetID]) ! 2444: { ! 2445: HostAdapter->CommandSuccessfulFlag[TargetID] = false; ! 2446: return BusLogic_BusDeviceReset(HostAdapter, Command); ! 2447: } ! 2448: else return BusLogic_ResetHostAdapter(HostAdapter, Command); ! 2449: } ! 2450: printk("scsi%d: Error Recovery for Target %d Suppressed\n", ! 2451: HostAdapter->HostNumber, TargetID); ! 2452: return SCSI_RESET_PUNT; ! 2453: } ! 2454: ! 2455: ! 2456: /* ! 2457: BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk ! 2458: Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and ! 2459: the appropriate number of cylinders so as not to exceed drive capacity. In ! 2460: order for disks equal to or larger than 1 GB to be addressable by the BIOS ! 2461: without exceeding the BIOS limitation of 1024 cylinders, Extended Translation ! 2462: may be enabled in AutoSCSI on "C" Series boards or by a dip switch setting ! 2463: on older boards. With Extended Translation enabled, drives between 1 GB ! 2464: inclusive and 2 GB exclusive are given a disk geometry of 128 heads and 32 ! 2465: sectors, and drives between 2 GB inclusive and 8 GB exclusive are given a ! 2466: disk geometry of 255 heads and 63 sectors. On "C" Series boards the firmware ! 2467: can be queried for the precise translation in effect for each drive ! 2468: individually, but there is really no need to do so since we know the total ! 2469: capacity of the drive and whether Extended Translation is enabled, hence we ! 2470: can deduce the BIOS disk geometry that must be in effect. ! 2471: */ ! 2472: ! 2473: int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device, ! 2474: int *Parameters) ! 2475: { ! 2476: BusLogic_HostAdapter_T *HostAdapter = ! 2477: (BusLogic_HostAdapter_T *) Disk->device->host->hostdata; ! 2478: BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters; ! 2479: if (HostAdapter->ExtendedTranslation && ! 2480: Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) ! 2481: if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) ! 2482: { ! 2483: DiskParameters->Heads = 255; ! 2484: DiskParameters->Sectors = 63; ! 2485: } ! 2486: else ! 2487: { ! 2488: DiskParameters->Heads = 128; ! 2489: DiskParameters->Sectors = 32; ! 2490: } ! 2491: else ! 2492: { ! 2493: DiskParameters->Heads = 64; ! 2494: DiskParameters->Sectors = 32; ! 2495: } ! 2496: DiskParameters->Cylinders = ! 2497: Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); ! 2498: return 0; ! 2499: } ! 2500: ! 2501: ! 2502: /* ! 2503: BusLogic_Setup handles processing of Kernel Command Line Arguments. ! 2504: ! 2505: For the BusLogic driver, a kernel command line entry comprises the driver ! 2506: identifier "BusLogic=" optionally followed by a comma-separated sequence of ! 2507: integers and then optionally followed by a comma-separated sequence of ! 2508: strings. Each command line entry applies to one BusLogic Host Adapter. ! 2509: Multiple command line entries may be used in systems which contain multiple ! 2510: BusLogic Host Adapters. ! 2511: ! 2512: The first integer specified is the I/O Address at which the Host Adapter is ! 2513: located. If unspecified, it defaults to 0 which means to apply this entry to ! 2514: the first BusLogic Host Adapter found during the default probe sequence. If ! 2515: any I/O Address parameters are provided on the command line, then the default ! 2516: probe sequence is omitted. ! 2517: ! 2518: The second integer specified is the number of Concurrent Commands per Logical ! 2519: Unit to allow for Target Devices on the Host Adapter. If unspecified, it ! 2520: defaults to 0 which means to use the value of BusLogic_Concurrency for ! 2521: non-ISA Host Adapters, or BusLogic_Concurrency_ISA for ISA Host Adapters. ! 2522: ! 2523: The third integer specified is the Bus Settle Time in seconds. This is ! 2524: the amount of time to wait between a Host Adapter Hard Reset which initiates ! 2525: a SCSI Bus Reset and issuing any SCSI commands. If unspecified, it defaults ! 2526: to 0 which means to use the value of BusLogic_DefaultBusSettleTime. ! 2527: ! 2528: The fourth integer specified is the Local Options. If unspecified, it ! 2529: defaults to 0. Note that Local Options are only applied to a specific Host ! 2530: Adapter. ! 2531: ! 2532: The fifth integer specified is the Global Options. If unspecified, it ! 2533: defaults to 0. Note that Global Options are applied across all Host ! 2534: Adapters. ! 2535: ! 2536: The string options are used to provide control over Tagged Queuing and Error ! 2537: Recovery. If both Tagged Queuing and Error Recovery strings are provided, the ! 2538: Tagged Queuing specification string must come first. ! 2539: ! 2540: The Tagged Queuing specification begins with "TQ:" and allows for explicitly ! 2541: specifying whether Tagged Queuing is permitted on Target Devices that support ! 2542: it. The following specification options are available: ! 2543: ! 2544: TQ:Default Tagged Queuing will be permitted based on the firmware ! 2545: version of the BusLogic Host Adapter and based on ! 2546: whether the Concurrency value allows queuing multiple ! 2547: commands. ! 2548: ! 2549: TQ:Enable Tagged Queuing will be enabled for all Target Devices ! 2550: on this Host Adapter overriding any limitation that ! 2551: would otherwise be imposed based on the Host Adapter ! 2552: firmware version. ! 2553: ! 2554: TQ:Disable Tagged Queuing will be disabled for all Target Devices ! 2555: on this Host Adapter. ! 2556: ! 2557: TQ:<Per-Target-Spec> Tagged Queuing will be controlled individually for each ! 2558: Target Device. <Per-Target-Spec> is a sequence of "Y", ! 2559: "N", and "X" characters. "Y" enabled Tagged Queuing, ! 2560: "N" disables Tagged Queuing, and "X" accepts the ! 2561: default based on the firmware version. The first ! 2562: character refers to Target 0, the second to Target 1, ! 2563: and so on; if the sequence of "Y", "N", and "X" ! 2564: characters does not cover all the Target Devices, ! 2565: unspecified characters are assumed to be "X". ! 2566: ! 2567: Note that explicitly requesting Tagged Queuing may lead to problems; this ! 2568: facility is provided primarily to allow disabling Tagged Queuing on Target ! 2569: Devices that do not implement it correctly. ! 2570: ! 2571: The Error Recovery specification begins with "ER:" and allows for explicitly ! 2572: specifying the Error Recovery action to be performed when ResetCommand is ! 2573: called due to a SCSI Command failing to complete successfully. The following ! 2574: specification options are available: ! 2575: ! 2576: ER:Default Error Recovery will select between the Hard Reset and ! 2577: Bus Device Reset options based on the recommendation ! 2578: of the SCSI Subsystem. ! 2579: ! 2580: ER:HardReset Error Recovery will initiate a Host Adapter Hard Reset ! 2581: which also causes a SCSI Bus Reset. ! 2582: ! 2583: ER:BusDeviceReset Error Recovery will send a Bus Device Reset message to ! 2584: the individual Target Device causing the error. If ! 2585: Error Recovery is again initiated for this Target ! 2586: Device and no SCSI Command to this Target Device has ! 2587: completed successfully since the Bus Device Reset ! 2588: message was sent, then a Hard Reset will be attempted. ! 2589: ! 2590: ER:None Error Recovery will be suppressed. This option should ! 2591: only be selected if a SCSI Bus Reset or Bus Device ! 2592: Reset will cause the Target Device to fail completely ! 2593: and unrecoverably. ! 2594: ! 2595: ER:<Per-Target-Spec> Error Recovery will be controlled individually for each ! 2596: Target Device. <Per-Target-Spec> is a sequence of "D", ! 2597: "H", "B", and "N" characters. "D" selects Default, "H" ! 2598: selects Hard Reset, "B" selects Bus Device Reset, and ! 2599: "N" selects None. The first character refers to Target ! 2600: 0, the second to Target 1, and so on; if the sequence ! 2601: of "D", "H", "B", and "N" characters does not cover all ! 2602: the Target Devices, unspecified characters are assumed ! 2603: to be "D". ! 2604: */ ! 2605: ! 2606: void BusLogic_Setup(char *Strings, int *Integers) ! 2607: { ! 2608: BusLogic_CommandLineEntry_T *CommandLineEntry = ! 2609: &BusLogic_CommandLineEntries[BusLogic_CommandLineEntryCount++]; ! 2610: static int ProbeListIndex = 0; ! 2611: int IntegerCount = Integers[0], TargetID, i; ! 2612: CommandLineEntry->IO_Address = 0; ! 2613: CommandLineEntry->Concurrency = 0; ! 2614: CommandLineEntry->BusSettleTime = 0; ! 2615: CommandLineEntry->LocalOptions = 0; ! 2616: CommandLineEntry->TaggedQueuingPermitted = 0; ! 2617: CommandLineEntry->TaggedQueuingPermittedMask = 0; ! 2618: memset(CommandLineEntry->ErrorRecoveryOption, ! 2619: BusLogic_ErrorRecoveryDefault, ! 2620: sizeof(CommandLineEntry->ErrorRecoveryOption)); ! 2621: if (IntegerCount > 5) ! 2622: printk("BusLogic: Unexpected Command Line Integers ignored\n"); ! 2623: if (IntegerCount >= 1) ! 2624: { ! 2625: unsigned short IO_Address = Integers[1]; ! 2626: if (IO_Address > 0) ! 2627: { ! 2628: for (i = 0; ; i++) ! 2629: if (BusLogic_IO_StandardAddresses[i] == 0) ! 2630: { ! 2631: printk("BusLogic: Invalid Command Line Entry " ! 2632: "(illegal I/O Address 0x%X)\n", IO_Address); ! 2633: return; ! 2634: } ! 2635: else if (i < ProbeListIndex && ! 2636: IO_Address == BusLogic_IO_AddressProbeList[i]) ! 2637: { ! 2638: printk("BusLogic: Invalid Command Line Entry " ! 2639: "(duplicate I/O Address 0x%X)\n", IO_Address); ! 2640: return; ! 2641: } ! 2642: else if (IO_Address >= 0x1000 || ! 2643: IO_Address == BusLogic_IO_StandardAddresses[i]) break; ! 2644: BusLogic_IO_AddressProbeList[ProbeListIndex++] = IO_Address; ! 2645: BusLogic_IO_AddressProbeList[ProbeListIndex] = 0; ! 2646: } ! 2647: CommandLineEntry->IO_Address = IO_Address; ! 2648: } ! 2649: if (IntegerCount >= 2) ! 2650: { ! 2651: unsigned short Concurrency = Integers[2]; ! 2652: if (Concurrency > BusLogic_MailboxCount) ! 2653: { ! 2654: printk("BusLogic: Invalid Command Line Entry " ! 2655: "(illegal Concurrency %d)\n", Concurrency); ! 2656: return; ! 2657: } ! 2658: CommandLineEntry->Concurrency = Concurrency; ! 2659: } ! 2660: if (IntegerCount >= 3) ! 2661: CommandLineEntry->BusSettleTime = Integers[3]; ! 2662: if (IntegerCount >= 4) ! 2663: CommandLineEntry->LocalOptions = Integers[4]; ! 2664: if (IntegerCount >= 5) ! 2665: BusLogic_GlobalOptions |= Integers[5]; ! 2666: if (!(BusLogic_CommandLineEntryCount == 0 || ProbeListIndex == 0 || ! 2667: BusLogic_CommandLineEntryCount == ProbeListIndex)) ! 2668: { ! 2669: printk("BusLogic: Invalid Command Line Entry " ! 2670: "(all or no I/O Addresses must be specified)\n"); ! 2671: return; ! 2672: } ! 2673: if (Strings == NULL) return; ! 2674: if (strncmp(Strings, "TQ:", 3) == 0) ! 2675: { ! 2676: Strings += 3; ! 2677: if (strncmp(Strings, "Default", 7) == 0) ! 2678: Strings += 7; ! 2679: else if (strncmp(Strings, "Enable", 6) == 0) ! 2680: { ! 2681: Strings += 6; ! 2682: CommandLineEntry->TaggedQueuingPermitted = 0xFFFF; ! 2683: CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF; ! 2684: } ! 2685: else if (strncmp(Strings, "Disable", 7) == 0) ! 2686: { ! 2687: Strings += 7; ! 2688: CommandLineEntry->TaggedQueuingPermitted = 0x0000; ! 2689: CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF; ! 2690: } ! 2691: else ! 2692: for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++) ! 2693: switch (*Strings++) ! 2694: { ! 2695: case 'Y': ! 2696: CommandLineEntry->TaggedQueuingPermitted |= 1 << TargetID; ! 2697: CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID; ! 2698: break; ! 2699: case 'N': ! 2700: CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID; ! 2701: break; ! 2702: case 'X': ! 2703: break; ! 2704: default: ! 2705: Strings--; ! 2706: TargetID = BusLogic_MaxTargetIDs; ! 2707: break; ! 2708: } ! 2709: } ! 2710: if (*Strings == ',') Strings++; ! 2711: if (strncmp(Strings, "ER:", 3) == 0) ! 2712: { ! 2713: Strings += 3; ! 2714: if (strncmp(Strings, "Default", 7) == 0) ! 2715: Strings += 7; ! 2716: else if (strncmp(Strings, "HardReset", 9) == 0) ! 2717: { ! 2718: Strings += 9; ! 2719: memset(CommandLineEntry->ErrorRecoveryOption, ! 2720: BusLogic_ErrorRecoveryHardReset, ! 2721: sizeof(CommandLineEntry->ErrorRecoveryOption)); ! 2722: } ! 2723: else if (strncmp(Strings, "BusDeviceReset", 14) == 0) ! 2724: { ! 2725: Strings += 14; ! 2726: memset(CommandLineEntry->ErrorRecoveryOption, ! 2727: BusLogic_ErrorRecoveryBusDeviceReset, ! 2728: sizeof(CommandLineEntry->ErrorRecoveryOption)); ! 2729: } ! 2730: else if (strncmp(Strings, "None", 4) == 0) ! 2731: { ! 2732: Strings += 4; ! 2733: memset(CommandLineEntry->ErrorRecoveryOption, ! 2734: BusLogic_ErrorRecoveryNone, ! 2735: sizeof(CommandLineEntry->ErrorRecoveryOption)); ! 2736: } ! 2737: else ! 2738: for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++) ! 2739: switch (*Strings++) ! 2740: { ! 2741: case 'D': ! 2742: CommandLineEntry->ErrorRecoveryOption[TargetID] = ! 2743: BusLogic_ErrorRecoveryDefault; ! 2744: break; ! 2745: case 'H': ! 2746: CommandLineEntry->ErrorRecoveryOption[TargetID] = ! 2747: BusLogic_ErrorRecoveryHardReset; ! 2748: break; ! 2749: case 'B': ! 2750: CommandLineEntry->ErrorRecoveryOption[TargetID] = ! 2751: BusLogic_ErrorRecoveryBusDeviceReset; ! 2752: break; ! 2753: case 'N': ! 2754: CommandLineEntry->ErrorRecoveryOption[TargetID] = ! 2755: BusLogic_ErrorRecoveryNone; ! 2756: break; ! 2757: default: ! 2758: Strings--; ! 2759: TargetID = BusLogic_MaxTargetIDs; ! 2760: break; ! 2761: } ! 2762: } ! 2763: if (*Strings != '\0') ! 2764: printk("BusLogic: Unexpected Command Line String '%s' ignored\n", Strings); ! 2765: } ! 2766: ! 2767: ! 2768: /* ! 2769: Include Module support if requested. ! 2770: */ ! 2771: ! 2772: ! 2773: #ifdef MODULE ! 2774: ! 2775: SCSI_Host_Template_T driver_template = BUSLOGIC; ! 2776: ! 2777: #include "scsi_module.c" ! 2778: ! 2779: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.