BusLogic.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:180k
- */
- if (HostAdapter->FirmwareVersion[0] >= '3')
- {
- RequestedReplyLength = sizeof(SynchronousPeriod);
- if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
- &RequestedReplyLength, sizeof(RequestedReplyLength),
- &SynchronousPeriod, sizeof(SynchronousPeriod))
- != sizeof(SynchronousPeriod))
- return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
- }
- else
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
- HostAdapter->SynchronousPeriod[TargetID] =
- 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
- .TransferPeriod;
- /*
- Indicate the Target Device Inquiry completed successfully.
- */
- return true;
- }
- /*
- BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible
- through Host Adapter.
- */
- static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T
- *HostAdapter)
- {
- int TargetID;
- /*
- Inhibit the Target Device Inquiry and Reporting if requested.
- */
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
- HostAdapter->DriverOptions != NULL &&
- HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
- return;
- /*
- Report on the Target Devices found.
- */
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported)
- {
- int SynchronousTransferRate = 0;
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
- {
- unsigned char WideTransfersActive;
- FlashPoint_InquireTargetInfo(
- HostAdapter->CardHandle, TargetID,
- &HostAdapter->SynchronousPeriod[TargetID],
- &HostAdapter->SynchronousOffset[TargetID],
- &WideTransfersActive);
- TargetFlags->WideTransfersActive = WideTransfersActive;
- }
- else if (TargetFlags->WideTransfersSupported &&
- (HostAdapter->WidePermitted & (1 << TargetID)) &&
- strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0)
- TargetFlags->WideTransfersActive = true;
- if (HostAdapter->SynchronousPeriod[TargetID] > 0)
- SynchronousTransferRate =
- 100000 / HostAdapter->SynchronousPeriod[TargetID];
- if (TargetFlags->WideTransfersActive)
- SynchronousTransferRate <<= 1;
- if (SynchronousTransferRate >= 9950)
- {
- SynchronousTransferRate = (SynchronousTransferRate + 50) / 100;
- BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
- "%d.%01d MB/sec, offset %dn",
- HostAdapter, TargetID,
- HostAdapter->QueueDepth[TargetID],
- (TargetFlags->WideTransfersActive ? "Wide " : ""),
- SynchronousTransferRate / 10,
- SynchronousTransferRate % 10,
- HostAdapter->SynchronousOffset[TargetID]);
- }
- else if (SynchronousTransferRate > 0)
- {
- SynchronousTransferRate = (SynchronousTransferRate + 5) / 10;
- BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
- "%d.%02d MB/sec, offset %dn",
- HostAdapter, TargetID,
- HostAdapter->QueueDepth[TargetID],
- (TargetFlags->WideTransfersActive ? "Wide " : ""),
- SynchronousTransferRate / 100,
- SynchronousTransferRate % 100,
- HostAdapter->SynchronousOffset[TargetID]);
- }
- else BusLogic_Info("Target %d: Queue Depth %d, Asynchronousn",
- HostAdapter, TargetID,
- HostAdapter->QueueDepth[TargetID]);
- TargetFlags->TargetInfoReported = true;
- }
- }
- }
- /*
- BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
- structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
- SCSI Host structure are intentionally left uninitialized, as this driver
- handles acquisition and release of these resources explicitly, as well as
- ensuring exclusive access to the Host Adapter hardware and data structures
- through explicit acquisition and release of the Host Adapter's Lock.
- */
- static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
- *HostAdapter,
- SCSI_Host_T *Host)
- {
- Host->max_id = HostAdapter->MaxTargetDevices;
- Host->max_lun = HostAdapter->MaxLogicalUnits;
- Host->max_channel = 0;
- Host->unique_id = HostAdapter->IO_Address;
- Host->this_id = HostAdapter->SCSI_ID;
- Host->can_queue = HostAdapter->DriverQueueDepth;
- Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
- Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
- Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
- }
- /*
- BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based
- on the Host Adapter's Total Queue Depth and the number, type, speed, and
- capabilities of the Target Devices. When called for the last Host Adapter,
- it reports on the Target Device Information for all BusLogic Host Adapters
- since all the Target Devices have now been probed.
- */
- static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host,
- SCSI_Device_T *DeviceList)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Host->hostdata;
- int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0;
- int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0;
- int AllocatedQueueDepth = 0;
- SCSI_Device_T *Device;
- int TargetID;
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (HostAdapter->TargetFlags[TargetID].TargetExists)
- {
- int QueueDepth = HostAdapter->QueueDepth[TargetID];
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
- (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
- {
- TaggedDeviceCount++;
- if (QueueDepth == 0) AutomaticTaggedDeviceCount++;
- }
- else
- {
- UntaggedDeviceCount++;
- if (QueueDepth == 0 ||
- QueueDepth > HostAdapter->UntaggedQueueDepth)
- {
- QueueDepth = HostAdapter->UntaggedQueueDepth;
- HostAdapter->QueueDepth[TargetID] = QueueDepth;
- }
- }
- AllocatedQueueDepth += QueueDepth;
- if (QueueDepth == 1)
- HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
- }
- HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount;
- if (AutomaticTaggedDeviceCount > 0)
- {
- AutomaticTaggedQueueDepth =
- (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth)
- / AutomaticTaggedDeviceCount;
- if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth)
- AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
- if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth)
- AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth;
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- if (HostAdapter->TargetFlags[TargetID].TargetExists &&
- HostAdapter->QueueDepth[TargetID] == 0)
- {
- AllocatedQueueDepth += AutomaticTaggedQueueDepth;
- HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth;
- }
- }
- for (Device = DeviceList; Device != NULL; Device = Device->next)
- if (Device->host == Host)
- Device->queue_depth = HostAdapter->QueueDepth[Device->id];
- /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */
- AllocatedQueueDepth += HostAdapter->TargetDeviceCount;
- if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth)
- AllocatedQueueDepth = HostAdapter->DriverQueueDepth;
- BusLogic_CreateAdditionalCCBs(HostAdapter,
- AllocatedQueueDepth
- - HostAdapter->AllocatedCCBs,
- false);
- if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
- for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
- HostAdapter != NULL;
- HostAdapter = HostAdapter->Next)
- BusLogic_ReportTargetDeviceInfo(HostAdapter);
- }
- /*
- BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
- I/O Addresses where they may be located, initializing, registering, and
- reporting the configuration of each BusLogic Host Adapter it finds. It
- returns the number of BusLogic Host Adapters successfully initialized and
- registered.
- */
- int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
- {
- int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
- BusLogic_HostAdapter_T *PrototypeHostAdapter;
- if (BusLogic_ProbeOptions.NoProbe) return 0;
- BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *)
- kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T),
- GFP_ATOMIC);
- if (BusLogic_ProbeInfoList == NULL)
- {
- BusLogic_Error("BusLogic: Unable to allocate Probe Info Listn", NULL);
- return 0;
- }
- memset(BusLogic_ProbeInfoList, 0,
- BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T));
- PrototypeHostAdapter = (BusLogic_HostAdapter_T *)
- kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC);
- if (PrototypeHostAdapter == NULL)
- {
- kfree(BusLogic_ProbeInfoList);
- BusLogic_Error("BusLogic: Unable to allocate Prototype "
- "Host Adaptern", NULL);
- return 0;
- }
- memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
- #ifdef MODULE
- if (BusLogic != NULL)
- BusLogic_Setup(BusLogic);
- #endif
- BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
- for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
- {
- BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
- BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
- SCSI_Host_T *Host;
- if (ProbeInfo->IO_Address == 0) continue;
- memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
- HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
- HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
- HostAdapter->IO_Address = ProbeInfo->IO_Address;
- HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
- HostAdapter->Bus = ProbeInfo->Bus;
- HostAdapter->Device = ProbeInfo->Device;
- HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
- HostAdapter->AddressCount =
- BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
- /*
- Probe the Host Adapter. If unsuccessful, abort further initialization.
- */
- if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
- /*
- Hard Reset the Host Adapter. If unsuccessful, abort further
- initialization.
- */
- if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
- /*
- Check the Host Adapter. If unsuccessful, abort further initialization.
- */
- if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
- /*
- Initialize the Driver Options field if provided.
- */
- if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
- HostAdapter->DriverOptions =
- &BusLogic_DriverOptions[DriverOptionsIndex++];
- /*
- Announce the Driver Version and Date, Author's Name, Copyright Notice,
- and Electronic Mail Address.
- */
- BusLogic_AnnounceDriver(HostAdapter);
- /*
- Register usage of the I/O Address range. From this point onward, any
- failure will be assumed to be due to a problem with the Host Adapter,
- rather than due to having mistakenly identified this port as belonging
- to a BusLogic Host Adapter. The I/O Address range will not be
- released, thereby preventing it from being incorrectly identified as
- any other type of Host Adapter.
- */
- request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
- "BusLogic");
- /*
- Register the SCSI Host structure.
- */
- Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T));
- if(Host==NULL)
- {
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
- continue;
- }
- HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata;
- memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T));
- HostAdapter->SCSI_Host = Host;
- HostAdapter->HostNumber = Host->host_no;
- Host->select_queue_depths = BusLogic_SelectQueueDepths;
- /*
- Add Host Adapter to the end of the list of registered BusLogic
- Host Adapters.
- */
- BusLogic_RegisterHostAdapter(HostAdapter);
- /*
- Read the Host Adapter Configuration, Configure the Host Adapter,
- Acquire the System Resources necessary to use the Host Adapter, then
- Create the Initial CCBs, Initialize the Host Adapter, and finally
- perform Target Device Inquiry.
- */
- if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
- BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
- BusLogic_AcquireResources(HostAdapter) &&
- BusLogic_CreateInitialCCBs(HostAdapter) &&
- BusLogic_InitializeHostAdapter(HostAdapter) &&
- BusLogic_TargetDeviceInquiry(HostAdapter))
- {
- /*
- Initialization has been completed successfully. Release and
- re-register usage of the I/O Address range so that the Model
- Name of the Host Adapter will appear, and initialize the SCSI
- Host structure.
- */
- release_region(HostAdapter->IO_Address,
- HostAdapter->AddressCount);
- request_region(HostAdapter->IO_Address,
- HostAdapter->AddressCount,
- HostAdapter->FullModelName);
- BusLogic_InitializeHostStructure(HostAdapter, Host);
- BusLogicHostAdapterCount++;
- }
- else
- {
- /*
- An error occurred during Host Adapter Configuration Querying, Host
- Adapter Configuration, Resource Acquisition, CCB Creation, Host
- Adapter Initialization, or Target Device Inquiry, so remove Host
- Adapter from the list of registered BusLogic Host Adapters, destroy
- the CCBs, Release the System Resources, and Unregister the SCSI
- Host.
- */
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
- BusLogic_UnregisterHostAdapter(HostAdapter);
- scsi_unregister(Host);
- }
- }
- kfree(PrototypeHostAdapter);
- kfree(BusLogic_ProbeInfoList);
- BusLogic_ProbeInfoList = NULL;
- return BusLogicHostAdapterCount;
- }
- /*
- BusLogic_ReleaseHostAdapter releases all resources previously acquired to
- support a specific Host Adapter, including the I/O Address range, and
- unregisters the BusLogic Host Adapter.
- */
- int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Host->hostdata;
- /*
- FlashPoint Host Adapters must first be released by the FlashPoint
- SCCB Manager.
- */
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
- FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
- /*
- Destroy the CCBs and release any system resources acquired to
- support Host Adapter.
- */
- BusLogic_DestroyCCBs(HostAdapter);
- BusLogic_ReleaseResources(HostAdapter);
- /*
- Release usage of the I/O Address range.
- */
- release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
- /*
- Remove Host Adapter from the list of registered BusLogic Host Adapters.
- */
- BusLogic_UnregisterHostAdapter(HostAdapter);
- return 0;
- }
- /*
- BusLogic_QueueCompletedCCB queues CCB for completion processing.
- */
- static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB)
- {
- BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
- CCB->Status = BusLogic_CCB_Completed;
- CCB->Next = NULL;
- if (HostAdapter->FirstCompletedCCB == NULL)
- {
- HostAdapter->FirstCompletedCCB = CCB;
- HostAdapter->LastCompletedCCB = CCB;
- }
- else
- {
- HostAdapter->LastCompletedCCB->Next = CCB;
- HostAdapter->LastCompletedCCB = CCB;
- }
- HostAdapter->ActiveCommands[CCB->TargetID]--;
- }
- /*
- BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
- the Host Adapter Status and Target Device Status.
- */
- static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
- BusLogic_HostAdapterStatus_T
- HostAdapterStatus,
- BusLogic_TargetDeviceStatus_T
- TargetDeviceStatus)
- {
- int HostStatus;
- switch (HostAdapterStatus)
- {
- case BusLogic_CommandCompletedNormally:
- case BusLogic_LinkedCommandCompleted:
- case BusLogic_LinkedCommandCompletedWithFlag:
- HostStatus = DID_OK;
- break;
- case BusLogic_SCSISelectionTimeout:
- HostStatus = DID_TIME_OUT;
- break;
- case BusLogic_InvalidOutgoingMailboxActionCode:
- case BusLogic_InvalidCommandOperationCode:
- case BusLogic_InvalidCommandParameter:
- BusLogic_Warning("BusLogic Driver Protocol Error 0x%02Xn",
- HostAdapter, HostAdapterStatus);
- case BusLogic_DataUnderRun:
- case BusLogic_DataOverRun:
- case BusLogic_UnexpectedBusFree:
- case BusLogic_LinkedCCBhasInvalidLUN:
- case BusLogic_AutoRequestSenseFailed:
- case BusLogic_TaggedQueuingMessageRejected:
- case BusLogic_UnsupportedMessageReceived:
- case BusLogic_HostAdapterHardwareFailed:
- case BusLogic_TargetDeviceReconnectedImproperly:
- case BusLogic_AbortQueueGenerated:
- case BusLogic_HostAdapterSoftwareError:
- case BusLogic_HostAdapterHardwareTimeoutError:
- case BusLogic_SCSIParityErrorDetected:
- HostStatus = DID_ERROR;
- break;
- case BusLogic_InvalidBusPhaseRequested:
- case BusLogic_TargetFailedResponseToATN:
- case BusLogic_HostAdapterAssertedRST:
- case BusLogic_OtherDeviceAssertedRST:
- case BusLogic_HostAdapterAssertedBusDeviceReset:
- HostStatus = DID_RESET;
- break;
- default:
- BusLogic_Warning("Unknown Host Adapter Status 0x%02Xn",
- HostAdapter, HostAdapterStatus);
- HostStatus = DID_ERROR;
- break;
- }
- return (HostStatus << 16) | TargetDeviceStatus;
- }
- /*
- BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
- Incoming Mailbox entries for completion processing.
- */
- static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter)
- {
- /*
- Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
- any completed CCBs for further processing. It is essential that for each
- CCB and SCSI Command issued, command completion processing is performed
- exactly once. Therefore, only Incoming Mailboxes with completion code
- Command Completed Without Error, Command Completed With Error, or Command
- Aborted At Host Request are saved for completion processing. When an
- Incoming Mailbox has a completion code of Aborted Command Not Found, the
- CCB had already completed or been aborted before the current Abort request
- was processed, and so completion processing has already occurred and no
- further action should be taken.
- */
- BusLogic_IncomingMailbox_T *NextIncomingMailbox =
- HostAdapter->NextIncomingMailbox;
- BusLogic_CompletionCode_T CompletionCode;
- while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
- BusLogic_IncomingMailboxFree)
- {
- BusLogic_CCB_T *CCB = (BusLogic_CCB_T *)
- Bus_to_Virtual(NextIncomingMailbox->CCB);
- if (CompletionCode != BusLogic_AbortedCommandNotFound)
- {
- if (CCB->Status == BusLogic_CCB_Active ||
- CCB->Status == BusLogic_CCB_Reset)
- {
- /*
- Save the Completion Code for this CCB and queue the CCB
- for completion processing.
- */
- CCB->CompletionCode = CompletionCode;
- BusLogic_QueueCompletedCCB(CCB);
- }
- else
- {
- /*
- If a CCB ever appears in an Incoming Mailbox and is not marked
- as status Active or Reset, then there is most likely a bug in
- the Host Adapter firmware.
- */
- BusLogic_Warning("Illegal CCB #%ld status %d in "
- "Incoming Mailboxn", HostAdapter,
- CCB->SerialNumber, CCB->Status);
- }
- }
- NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
- if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
- NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
- }
- HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
- }
- /*
- BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
- Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
- calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
- should already have been acquired by the caller.
- */
- static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
- {
- if (HostAdapter->ProcessCompletedCCBsActive) return;
- HostAdapter->ProcessCompletedCCBsActive = true;
- while (HostAdapter->FirstCompletedCCB != NULL)
- {
- BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
- SCSI_Command_T *Command = CCB->Command;
- HostAdapter->FirstCompletedCCB = CCB->Next;
- if (HostAdapter->FirstCompletedCCB == NULL)
- HostAdapter->LastCompletedCCB = NULL;
- /*
- Process the Completed CCB.
- */
- if (CCB->Opcode == BusLogic_BusDeviceReset)
- {
- int TargetID = CCB->TargetID;
- BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
- "%d Completedn", HostAdapter,
- CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
- HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
- HostAdapter->CommandsSinceReset[TargetID] = 0;
- HostAdapter->LastResetCompleted[TargetID] = jiffies;
- /*
- Place CCB back on the Host Adapter's free list.
- */
- BusLogic_DeallocateCCB(CCB);
- /*
- Bus Device Reset CCBs have the Command field non-NULL only when a
- Bus Device Reset was requested for a Command that did not have a
- currently active CCB in the Host Adapter (i.e., a Synchronous
- Bus Device Reset), and hence would not have its Completion Routine
- called otherwise.
- */
- while (Command != NULL)
- {
- SCSI_Command_T *NextCommand = Command->reset_chain;
- Command->reset_chain = NULL;
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
- Command = NextCommand;
- }
- /*
- Iterate over the CCBs for this Host Adapter performing completion
- processing for any CCBs marked as Reset for this Target.
- */
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
- {
- Command = CCB->Command;
- BusLogic_DeallocateCCB(CCB);
- HostAdapter->ActiveCommands[TargetID]--;
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
- }
- HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
- }
- else
- {
- /*
- Translate the Completion Code, Host Adapter Status, and Target
- Device Status into a SCSI Subsystem Result Code.
- */
- switch (CCB->CompletionCode)
- {
- case BusLogic_IncomingMailboxFree:
- case BusLogic_AbortedCommandNotFound:
- case BusLogic_InvalidCCB:
- BusLogic_Warning("CCB #%ld to Target %d Impossible Staten",
- HostAdapter, CCB->SerialNumber, CCB->TargetID);
- break;
- case BusLogic_CommandCompletedWithoutError:
- HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandsCompleted++;
- HostAdapter->TargetFlags[CCB->TargetID]
- .CommandSuccessfulFlag = true;
- Command->result = DID_OK << 16;
- break;
- case BusLogic_CommandAbortedAtHostRequest:
- BusLogic_Warning("CCB #%ld to Target %d Abortedn",
- HostAdapter, CCB->SerialNumber, CCB->TargetID);
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandAbortsCompleted);
- Command->result = DID_ABORT << 16;
- break;
- case BusLogic_CommandCompletedWithError:
- Command->result =
- BusLogic_ComputeResultCode(HostAdapter,
- CCB->HostAdapterStatus,
- CCB->TargetDeviceStatus);
- if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
- {
- HostAdapter->TargetStatistics[CCB->TargetID]
- .CommandsCompleted++;
- if (BusLogic_GlobalOptions.TraceErrors)
- {
- int i;
- BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
- "Adapter Status %02X "
- "Target Status %02Xn",
- HostAdapter, CCB->SerialNumber,
- CCB->TargetID, Command->result,
- CCB->HostAdapterStatus,
- CCB->TargetDeviceStatus);
- BusLogic_Notice("CDB ", HostAdapter);
- for (i = 0; i < CCB->CDB_Length; i++)
- BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
- BusLogic_Notice("n", HostAdapter);
- BusLogic_Notice("Sense ", HostAdapter);
- for (i = 0; i < CCB->SenseDataLength; i++)
- BusLogic_Notice(" %02X", HostAdapter,
- Command->sense_buffer[i]);
- BusLogic_Notice("n", HostAdapter);
- }
- }
- break;
- }
- /*
- When an INQUIRY command completes normally, save the
- CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
- Wide Data Transfers Supported) bits.
- */
- if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 &&
- CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
- {
- BusLogic_TargetFlags_T *TargetFlags =
- &HostAdapter->TargetFlags[CCB->TargetID];
- SCSI_Inquiry_T *InquiryResult =
- (SCSI_Inquiry_T *) Command->request_buffer;
- TargetFlags->TargetExists = true;
- TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
- TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
- }
- /*
- Place CCB back on the Host Adapter's free list.
- */
- BusLogic_DeallocateCCB(CCB);
- /*
- Call the SCSI Command Completion Routine.
- */
- Command->scsi_done(Command);
- }
- }
- HostAdapter->ProcessCompletedCCBsActive = false;
- }
- /*
- BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
- Adapters.
- */
- static void BusLogic_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- Registers_T *InterruptRegisters)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) DeviceIdentifier;
- ProcessorFlags_T ProcessorFlags;
- /*
- Acquire exclusive access to Host Adapter.
- */
- BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
- /*
- Handle Interrupts appropriately for each Host Adapter type.
- */
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- {
- BusLogic_InterruptRegister_T InterruptRegister;
- /*
- Read the Host Adapter Interrupt Register.
- */
- InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
- if (InterruptRegister.Bits.InterruptValid)
- {
- /*
- Acknowledge the interrupt and reset the Host Adapter
- Interrupt Register.
- */
- BusLogic_InterruptReset(HostAdapter);
- /*
- Process valid External SCSI Bus Reset and Incoming Mailbox
- Loaded Interrupts. Command Complete Interrupts are noted,
- and Outgoing Mailbox Available Interrupts are ignored, as
- they are never enabled.
- */
- if (InterruptRegister.Bits.ExternalBusReset)
- HostAdapter->HostAdapterExternalReset = true;
- else if (InterruptRegister.Bits.IncomingMailboxLoaded)
- BusLogic_ScanIncomingMailboxes(HostAdapter);
- else if (InterruptRegister.Bits.CommandComplete)
- HostAdapter->HostAdapterCommandCompleted = true;
- }
- }
- else
- {
- /*
- Check if there is a pending interrupt for this Host Adapter.
- */
- if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
- switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
- {
- case FlashPoint_NormalInterrupt:
- break;
- case FlashPoint_ExternalBusReset:
- HostAdapter->HostAdapterExternalReset = true;
- break;
- case FlashPoint_InternalError:
- BusLogic_Warning("Internal FlashPoint Error detected"
- " - Resetting Host Adaptern", HostAdapter);
- HostAdapter->HostAdapterInternalError = true;
- break;
- }
- }
- /*
- Process any completed CCBs.
- */
- if (HostAdapter->FirstCompletedCCB != NULL)
- BusLogic_ProcessCompletedCCBs(HostAdapter);
- /*
- Reset the Host Adapter if requested.
- */
- if (HostAdapter->HostAdapterExternalReset ||
- HostAdapter->HostAdapterInternalError)
- {
- BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
- HostAdapter->HostAdapterExternalReset = false;
- HostAdapter->HostAdapterInternalError = false;
- scsi_mark_host_reset(HostAdapter->SCSI_Host);
- }
- /*
- Release exclusive access to Host Adapter.
- */
- BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
- }
- /*
- BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
- Mailbox for execution by Host Adapter. The Host Adapter's Lock should
- already have been acquired by the caller.
- */
- static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T
- *HostAdapter,
- BusLogic_ActionCode_T ActionCode,
- BusLogic_CCB_T *CCB)
- {
- BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
- NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
- if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
- {
- CCB->Status = BusLogic_CCB_Active;
- /*
- The CCB field must be written before the Action Code field since
- the Host Adapter is operating asynchronously and the locking code
- does not protect against simultaneous access by the Host Adapter.
- */
- NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB);
- NextOutgoingMailbox->ActionCode = ActionCode;
- BusLogic_StartMailboxCommand(HostAdapter);
- if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
- NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
- HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
- if (ActionCode == BusLogic_MailboxStartCommand)
- {
- HostAdapter->ActiveCommands[CCB->TargetID]++;
- if (CCB->Opcode != BusLogic_BusDeviceReset)
- HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
- }
- return true;
- }
- return false;
- }
- /*
- BusLogic_QueueCommand creates a CCB for Command and places it into an
- Outgoing Mailbox for execution by the associated Host Adapter.
- */
- int BusLogic_QueueCommand(SCSI_Command_T *Command,
- void (*CompletionRoutine)(SCSI_Command_T *))
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Command->host->hostdata;
- BusLogic_TargetFlags_T *TargetFlags =
- &HostAdapter->TargetFlags[Command->target];
- BusLogic_TargetStatistics_T *TargetStatistics =
- HostAdapter->TargetStatistics;
- unsigned char *CDB = Command->cmnd;
- int CDB_Length = Command->cmd_len;
- int TargetID = Command->target;
- int LogicalUnit = Command->lun;
- void *BufferPointer = Command->request_buffer;
- int BufferLength = Command->request_bufflen;
- int SegmentCount = Command->use_sg;
- ProcessorFlags_T ProcessorFlags;
- BusLogic_CCB_T *CCB;
- /*
- SCSI REQUEST_SENSE commands will be executed automatically by the Host
- Adapter for any errors, so they should not be executed explicitly unless
- the Sense Data is zero indicating that no error occurred.
- */
- if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
- {
- Command->result = DID_OK << 16;
- CompletionRoutine(Command);
- return 0;
- }
- /*
- Acquire exclusive access to Host Adapter.
- */
- BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
- /*
- Allocate a CCB from the Host Adapter's free list. In the unlikely event
- that there are none available and memory allocation fails, wait 1 second
- and try again. If that fails, the Host Adapter is probably hung so signal
- an error as a Host Adapter Hard Reset should be initiated soon.
- */
- CCB = BusLogic_AllocateCCB(HostAdapter);
- if (CCB == NULL)
- {
- BusLogic_Delay(1);
- CCB = BusLogic_AllocateCCB(HostAdapter);
- if (CCB == NULL)
- {
- Command->result = DID_ERROR << 16;
- CompletionRoutine(Command);
- goto Done;
- }
- }
- /*
- Initialize the fields in the BusLogic Command Control Block (CCB).
- */
- if (SegmentCount == 0)
- {
- CCB->Opcode = BusLogic_InitiatorCCB;
- CCB->DataLength = BufferLength;
- CCB->DataPointer = Virtual_to_Bus(BufferPointer);
- }
- else
- {
- SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer;
- int Segment;
- CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
- CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T);
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList);
- else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
- for (Segment = 0; Segment < SegmentCount; Segment++)
- {
- CCB->ScatterGatherList[Segment].SegmentByteCount =
- ScatterList[Segment].length;
- CCB->ScatterGatherList[Segment].SegmentDataPointer =
- Virtual_to_Bus(ScatterList[Segment].address);
- }
- }
- switch (CDB[0])
- {
- case READ_6:
- case READ_10:
- CCB->DataDirection = BusLogic_DataInLengthChecked;
- TargetStatistics[TargetID].ReadCommands++;
- BusLogic_IncrementByteCounter(
- &TargetStatistics[TargetID].TotalBytesRead, BufferLength);
- BusLogic_IncrementSizeBucket(
- TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
- break;
- case WRITE_6:
- case WRITE_10:
- CCB->DataDirection = BusLogic_DataOutLengthChecked;
- TargetStatistics[TargetID].WriteCommands++;
- BusLogic_IncrementByteCounter(
- &TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
- BusLogic_IncrementSizeBucket(
- TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
- break;
- default:
- CCB->DataDirection = BusLogic_UncheckedDataTransfer;
- break;
- }
- CCB->CDB_Length = CDB_Length;
- CCB->SenseDataLength = sizeof(Command->sense_buffer);
- CCB->HostAdapterStatus = 0;
- CCB->TargetDeviceStatus = 0;
- CCB->TargetID = TargetID;
- CCB->LogicalUnit = LogicalUnit;
- CCB->TagEnable = false;
- CCB->LegacyTagEnable = false;
- /*
- BusLogic recommends that after a Reset the first couple of commands that
- are sent to a Target Device be sent in a non Tagged Queue fashion so that
- the Host Adapter and Target Device can establish Synchronous and Wide
- Transfer before Queue Tag messages can interfere with the Synchronous and
- Wide Negotiation messages. By waiting to enable Tagged Queuing until after
- the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
- assured that after a Reset any pending commands are requeued before Tagged
- Queuing is enabled and that the Tagged Queuing message will not occur while
- the partition table is being printed. In addition, some devices do not
- properly handle the transition from non-tagged to tagged commands, so it is
- necessary to wait until there are no pending commands for a target device
- before queuing tagged commands.
- */
- if (HostAdapter->CommandsSinceReset[TargetID]++ >=
- BusLogic_MaxTaggedQueueDepth &&
- !TargetFlags->TaggedQueuingActive &&
- HostAdapter->ActiveCommands[TargetID] == 0 &&
- TargetFlags->TaggedQueuingSupported &&
- (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
- {
- TargetFlags->TaggedQueuingActive = true;
- BusLogic_Notice("Tagged Queuing now active for Target %dn",
- HostAdapter, TargetID);
- }
- if (TargetFlags->TaggedQueuingActive)
- {
- BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
- /*
- When using Tagged Queuing with Simple Queue Tags, it appears that disk
- drive controllers do not guarantee that a queued command will not
- remain in a disconnected state indefinitely if commands that read or
- write nearer the head position continue to arrive without interruption.
- Therefore, for each Target Device this driver keeps track of the last
- time either the queue was empty or an Ordered Queue Tag was issued. If
- more than 4 seconds (one fifth of the 20 second disk timeout) have
- elapsed since this last sequence point, this command will be issued
- with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
- the Target Device to complete all previously queued commands before
- this command may be executed.
- */
- if (HostAdapter->ActiveCommands[TargetID] == 0)
- HostAdapter->LastSequencePoint[TargetID] = jiffies;
- else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
- {
- HostAdapter->LastSequencePoint[TargetID] = jiffies;
- QueueTag = BusLogic_OrderedQueueTag;
- }
- if (HostAdapter->ExtendedLUNSupport)
- {
- CCB->TagEnable = true;
- CCB->QueueTag = QueueTag;
- }
- else
- {
- CCB->LegacyTagEnable = true;
- CCB->LegacyQueueTag = QueueTag;
- }
- }
- memcpy(CCB->CDB, CDB, CDB_Length);
- CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer);
- CCB->Command = Command;
- Command->scsi_done = CompletionRoutine;
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- {
- /*
- Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI
- Subsystem should not attempt to queue more commands than can be placed
- in Outgoing Mailboxes, so there should always be one free. In the
- unlikely event that there are none available, wait 1 second and try
- again. If that fails, the Host Adapter is probably hung so signal an
- error as a Host Adapter Hard Reset should be initiated soon.
- */
- if (!BusLogic_WriteOutgoingMailbox(
- HostAdapter, BusLogic_MailboxStartCommand, CCB))
- {
- BusLogic_Warning("Unable to write Outgoing Mailbox - "
- "Pausing for 1 secondn", HostAdapter);
- BusLogic_Delay(1);
- if (!BusLogic_WriteOutgoingMailbox(
- HostAdapter, BusLogic_MailboxStartCommand, CCB))
- {
- BusLogic_Warning("Still unable to write Outgoing Mailbox - "
- "Host Adapter Dead?n", HostAdapter);
- BusLogic_DeallocateCCB(CCB);
- Command->result = DID_ERROR << 16;
- Command->scsi_done(Command);
- }
- }
- }
- else
- {
- /*
- Call the FlashPoint SCCB Manager to start execution of the CCB.
- */
- CCB->Status = BusLogic_CCB_Active;
- HostAdapter->ActiveCommands[TargetID]++;
- TargetStatistics[TargetID].CommandsAttempted++;
- FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
- /*
- The Command may have already completed and BusLogic_QueueCompletedCCB
- been called, or it may still be pending.
- */
- if (CCB->Status == BusLogic_CCB_Completed)
- BusLogic_ProcessCompletedCCBs(HostAdapter);
- }
- /*
- Release exclusive access to Host Adapter.
- */
- Done:
- BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
- return 0;
- }
- /*
- BusLogic_AbortCommand aborts Command if possible.
- */
- int BusLogic_AbortCommand(SCSI_Command_T *Command)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Command->host->hostdata;
- int TargetID = Command->target;
- ProcessorFlags_T ProcessorFlags;
- BusLogic_CCB_T *CCB;
- int Result;
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
- /*
- Acquire exclusive access to Host Adapter.
- */
- BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
- /*
- If this Command has already completed, then no Abort is necessary.
- */
- if (Command->serial_number != Command->serial_number_at_timeout)
- {
- BusLogic_Warning("Unable to Abort Command to Target %d - "
- "Already Completedn", HostAdapter, TargetID);
- Result = SCSI_ABORT_NOT_RUNNING;
- goto Done;
- }
- /*
- Attempt to find an Active CCB for this Command. If no Active CCB for this
- Command is found, then no Abort is necessary.
- */
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Command == Command) break;
- if (CCB == NULL)
- {
- BusLogic_Warning("Unable to Abort Command to Target %d - "
- "No CCB Foundn", HostAdapter, TargetID);
- Result = SCSI_ABORT_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Completed)
- {
- BusLogic_Warning("Unable to Abort Command to Target %d - "
- "CCB Completedn", HostAdapter, TargetID);
- Result = SCSI_ABORT_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Reset)
- {
- BusLogic_Warning("Unable to Abort Command to Target %d - "
- "CCB Resetn", HostAdapter, TargetID);
- Result = SCSI_ABORT_PENDING;
- goto Done;
- }
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- {
- /*
- Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx
- do not generate Abort Tag messages, but only generate the non-tagged
- Abort message. Since non-tagged commands are not sent by the Host
- Adapter until the queue of outstanding tagged commands has completed,
- and the Abort message is treated as a non-tagged command, it is
- effectively impossible to abort commands when Tagged Queuing is active.
- Firmware version 5.xx does generate Abort Tag messages, so it is
- possible to abort commands when Tagged Queuing is active.
- */
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
- HostAdapter->FirmwareVersion[0] < '5')
- {
- BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
- "Abort Tag Not Supportedn",
- HostAdapter, CCB->SerialNumber, TargetID);
- Result = SCSI_ABORT_SNOOZE;
- }
- else if (BusLogic_WriteOutgoingMailbox(
- HostAdapter, BusLogic_MailboxAbortCommand, CCB))
- {
- BusLogic_Warning("Aborting CCB #%ld to Target %dn",
- HostAdapter, CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
- Result = SCSI_ABORT_PENDING;
- }
- else
- {
- BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
- "No Outgoing Mailboxesn",
- HostAdapter, CCB->SerialNumber, TargetID);
- Result = SCSI_ABORT_BUSY;
- }
- }
- else
- {
- /*
- Call the FlashPoint SCCB Manager to abort execution of the CCB.
- */
- BusLogic_Warning("Aborting CCB #%ld to Target %dn",
- HostAdapter, CCB->SerialNumber, TargetID);
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
- FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
- /*
- The Abort may have already been completed and
- BusLogic_QueueCompletedCCB been called, or it
- may still be pending.
- */
- Result = SCSI_ABORT_PENDING;
- if (CCB->Status == BusLogic_CCB_Completed)
- {
- BusLogic_ProcessCompletedCCBs(HostAdapter);
- Result = SCSI_ABORT_SUCCESS;
- }
- }
- /*
- Release exclusive access to Host Adapter.
- */
- Done:
- BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
- return Result;
- }
- /*
- BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
- currently executing SCSI Commands as having been Reset.
- */
- static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
- SCSI_Command_T *Command,
- unsigned int ResetFlags)
- {
- ProcessorFlags_T ProcessorFlags;
- BusLogic_CCB_T *CCB;
- int TargetID, Result;
- boolean HardReset;
- if (HostAdapter->HostAdapterExternalReset)
- {
- BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
- HardReset = false;
- }
- else if (HostAdapter->HostAdapterInternalError)
- {
- BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
- HardReset = true;
- }
- else
- {
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[Command->target]
- .HostAdapterResetsRequested);
- HardReset = true;
- }
- /*
- Acquire exclusive access to Host Adapter.
- */
- BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
- /*
- If this is an Asynchronous Reset and this Command has already completed,
- then no Reset is necessary.
- */
- if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
- {
- TargetID = Command->target;
- if (Command->serial_number != Command->serial_number_at_timeout)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "Already Completed or Resetn",
- HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Command == Command) break;
- if (CCB == NULL)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "No CCB Foundn", HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Completed)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "CCB Completedn", HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Reset &&
- HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "Reset Pendingn", HostAdapter, TargetID);
- Result = SCSI_RESET_PENDING;
- goto Done;
- }
- }
- if (Command == NULL)
- {
- if (HostAdapter->HostAdapterInternalError)
- BusLogic_Warning("Resetting %s due to Host Adapter Internal Errorn",
- HostAdapter, HostAdapter->FullModelName);
- else BusLogic_Warning("Resetting %s due to External SCSI Bus Resetn",
- HostAdapter, HostAdapter->FullModelName);
- }
- else
- {
- BusLogic_Warning("Resetting %s due to Target %dn", HostAdapter,
- HostAdapter->FullModelName, Command->target);
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[Command->target]
- .HostAdapterResetsAttempted);
- }
- /*
- Attempt to Reset and Reinitialize the Host Adapter.
- */
- if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
- BusLogic_InitializeHostAdapter(HostAdapter)))
- {
- BusLogic_Error("Resetting %s Failedn", HostAdapter,
- HostAdapter->FullModelName);
- Result = SCSI_RESET_ERROR;
- goto Done;
- }
- if (Command != NULL)
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[Command->target]
- .HostAdapterResetsCompleted);
- /*
- Mark all currently executing CCBs as having been Reset.
- */
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Status == BusLogic_CCB_Active)
- CCB->Status = BusLogic_CCB_Reset;
- /*
- Wait a few seconds between the Host Adapter Hard Reset which initiates
- a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
- confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
- Note that a timer interrupt may occur here, but all active CCBs have
- already been marked Reset and so a reentrant call will return Pending.
- */
- if (HardReset)
- BusLogic_Delay(HostAdapter->BusSettleTime);
- /*
- If this is a Synchronous Reset, perform completion processing for
- the Command being Reset.
- */
- if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
- {
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
- }
- /*
- Perform completion processing for all CCBs marked as Reset.
- */
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Status == BusLogic_CCB_Reset)
- {
- Command = CCB->Command;
- BusLogic_DeallocateCCB(CCB);
- while (Command != NULL)
- {
- SCSI_Command_T *NextCommand = Command->reset_chain;
- Command->reset_chain = NULL;
- Command->result = DID_RESET << 16;
- Command->scsi_done(Command);
- Command = NextCommand;
- }
- }
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- HostAdapter->LastResetAttempted[TargetID] = jiffies;
- HostAdapter->LastResetCompleted[TargetID] = jiffies;
- }
- Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
- /*
- Release exclusive access to Host Adapter.
- */
- Done:
- BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
- return Result;
- }
- /*
- BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target
- Device associated with Command.
- */
- static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
- SCSI_Command_T *Command,
- unsigned int ResetFlags)
- {
- int TargetID = Command->target;
- BusLogic_CCB_T *CCB, *XCCB;
- ProcessorFlags_T ProcessorFlags;
- int Result = -1;
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
- /*
- Acquire exclusive access to Host Adapter.
- */
- BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
- /*
- If this is an Asynchronous Reset and this Command has already completed,
- then no Reset is necessary.
- */
- if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
- {
- if (Command->serial_number != Command->serial_number_at_timeout)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "Already Completedn", HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
- if (CCB->Command == Command) break;
- if (CCB == NULL)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "No CCB Foundn", HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Completed)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "CCB Completedn", HostAdapter, TargetID);
- Result = SCSI_RESET_NOT_RUNNING;
- goto Done;
- }
- else if (CCB->Status == BusLogic_CCB_Reset)
- {
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "Reset Pendingn", HostAdapter, TargetID);
- Result = SCSI_RESET_PENDING;
- goto Done;
- }
- else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
- {
- BusLogic_Warning("Bus Device Reset already pending to Target %dn",
- HostAdapter, TargetID);
- goto Done;
- }
- }
- /*
- If this is a Synchronous Reset and a Bus Device Reset is already pending
- for this Target Device, do not send a second one. Add this Command to
- the list of Commands for which completion processing must be performed
- when the Bus Device Reset CCB completes.
- */
- if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
- if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL)
- {
- Command->reset_chain = CCB->Command;
- CCB->Command = Command;
- BusLogic_Warning("Unable to Reset Command to Target %d - "
- "Reset Pendingn", HostAdapter, TargetID);
- Result = SCSI_RESET_PENDING;
- goto Done;
- }
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- {
- /*
- MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as
- a non-tagged command. Since non-tagged commands are not sent by the
- Host Adapter until the queue of outstanding tagged commands has
- completed, it is effectively impossible to send a Bus Device Reset
- while there are tagged commands outstanding. Therefore, in that case a
- full Host Adapter Hard Reset and SCSI Bus Reset must be done.
- */
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
- HostAdapter->ActiveCommands[TargetID] > 0 &&
- HostAdapter->FirmwareVersion[0] < '5')
- goto Done;
- }
- /*
- Allocate a CCB from the Host Adapter's free list. In the unlikely event
- that there are none available and memory allocation fails, attempt a full
- Host Adapter Hard Reset and SCSI Bus Reset.
- */
- CCB = BusLogic_AllocateCCB(HostAdapter);
- if (CCB == NULL) goto Done;
- BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %dn",
- HostAdapter, CCB->SerialNumber, TargetID);
- CCB->Opcode = BusLogic_BusDeviceReset;
- CCB->TargetID = TargetID;
- /*
- For Synchronous Resets, arrange for the interrupt handler to perform
- completion processing for the Command being Reset.
- */
- if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
- {
- Command->reset_chain = NULL;
- CCB->Command = Command;
- }
- if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
- {
- /*
- Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
- If sending a Bus Device Reset is impossible, attempt a full Host
- Adapter Hard Reset and SCSI Bus Reset.
- */
- if (!(BusLogic_WriteOutgoingMailbox(
- HostAdapter, BusLogic_MailboxStartCommand, CCB)))
- {
- BusLogic_Warning("Unable to write Outgoing Mailbox for "
- "Bus Device Resetn", HostAdapter);
- BusLogic_DeallocateCCB(CCB);
- goto Done;
- }
- }
- else
- {
- /*
- Call the FlashPoint SCCB Manager to start execution of the CCB.
- */
- CCB->Status = BusLogic_CCB_Active;
- HostAdapter->ActiveCommands[TargetID]++;
- FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
- }
- /*
- If there is a currently executing CCB in the Host Adapter for this Command
- (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
- made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
- If there is no active CCB for this Command (i.e. this is a Synchronous
- Reset), then the Bus Device Reset CCB's Command field will have been set
- to the Command so that the interrupt for the completion of the Bus Device
- Reset can call the Completion Routine for the Command. On successful
- execution of a Bus Device Reset, older firmware versions did return the
- pending CCBs with the appropriate completion code, but more recent firmware
- versions only return the Bus Device Reset CCB itself. This driver handles
- both cases by marking all the currently executing CCBs to this Target
- Device as Reset. When the Bus Device Reset CCB is processed by the
- interrupt handler, any remaining CCBs marked as Reset will have completion
- processing performed.
- */
- BusLogic_IncrementErrorCounter(
- &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
- HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
- HostAdapter->LastResetAttempted[TargetID] = jiffies;
- for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll)
- if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID)
- XCCB->Status = BusLogic_CCB_Reset;
- /*
- FlashPoint Host Adapters may have already completed the Bus Device
- Reset and BusLogic_QueueCompletedCCB been called, or it may still be
- pending.
- */
- Result = SCSI_RESET_PENDING;
- if (BusLogic_FlashPointHostAdapterP(HostAdapter))
- if (CCB->Status == BusLogic_CCB_Completed)
- {
- BusLogic_ProcessCompletedCCBs(HostAdapter);
- Result = SCSI_RESET_SUCCESS;
- }
- /*
- If a Bus Device Reset was not possible for some reason, force a full
- Host Adapter Hard Reset and SCSI Bus Reset.
- */
- Done:
- if (Result < 0)
- Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
- /*
- Release exclusive access to Host Adapter.
- */
- BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
- return Result;
- }
- /*
- BusLogic_ResetCommand takes appropriate action to reset Command.
- */
- int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Command->host->hostdata;
- int TargetID = Command->target;
- BusLogic_ErrorRecoveryStrategy_T
- ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID];
- /*
- Disable Tagged Queuing if it is active for this Target Device and if
- it has been less than 10 minutes since the last reset occurred, or since
- the system was initialized if no prior resets have occurred.
- */
- if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
- jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ)
- {
- HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
- HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
- BusLogic_Warning("Tagged Queuing now disabled for Target %dn",
- HostAdapter, TargetID);
- }
- switch (ErrorRecoveryStrategy)
- {
- case BusLogic_ErrorRecovery_Default:
- if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET)
- return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
- else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
- return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
- /* Fall through to Bus Device Reset case. */
- case BusLogic_ErrorRecovery_BusDeviceReset:
- /*
- The Bus Device Reset Error Recovery Strategy only graduates to a Hard
- Reset when no commands have completed successfully since the last Bus
- Device Reset and it has been at least 100 milliseconds. This prevents
- a sequence of commands that all timeout together from immediately
- forcing a Hard Reset before the Bus Device Reset has had a chance to
- clear the error condition.
- */
- if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag ||
- jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10)
- {
- HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
- return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags);
- }
- /* Fall through to Hard Reset case. */
- case BusLogic_ErrorRecovery_HardReset:
- return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
- case BusLogic_ErrorRecovery_None:
- BusLogic_Warning("Error Recovery for Target %d Suppressedn",
- HostAdapter, TargetID);
- break;
- }
- return SCSI_RESET_PUNT;
- }
- /*
- BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
- Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
- the appropriate number of cylinders so as not to exceed drive capacity. In
- order for disks equal to or larger than 1 GB to be addressable by the BIOS
- without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
- may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
- series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
- series MultiMaster Host Adapters. With Extended Translation enabled, drives
- between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
- heads and 32 sectors, and drives above 2 GB inclusive are given a disk
- geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
- Extended Translation setting does not match the geometry in the partition
- table, then the translation inferred from the partition table will be used by
- the BIOS, and a warning may be displayed.
- */
- int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
- int *Parameters)
- {
- BusLogic_HostAdapter_T *HostAdapter =
- (BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
- BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
- struct buffer_head *BufferHead;
- if (HostAdapter->ExtendedTranslationEnabled &&
- Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
- {
- if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
- {
- DiskParameters->Heads = 255;
- DiskParameters->Sectors = 63;
- }
- else
- {
- DiskParameters->Heads = 128;
- DiskParameters->Sectors = 32;
- }
- }
- else
- {
- DiskParameters->Heads = 64;
- DiskParameters->Sectors = 32;
- }
- DiskParameters->Cylinders =
- Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
- /*
- Attempt to read the first 1024 bytes from the disk device.
- */
- BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, block_size(Device));
- if (BufferHead == NULL) return 0;
- /*
- If the boot sector partition table flag is valid, search for a partition
- table entry whose end_head matches one of the standard BusLogic geometry
- translations (64/32, 128/32, or 255/63).
- */
- if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55)
- {
- PartitionTable_T *FirstPartitionEntry =
- (PartitionTable_T *) (BufferHead->b_data + 0x1BE);
- PartitionTable_T *PartitionEntry = FirstPartitionEntry;
- int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
- unsigned char PartitionEntryEndHead, PartitionEntryEndSector;
- for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
- {
- PartitionEntryEndHead = PartitionEntry->end_head;
- PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
- if (PartitionEntryEndHead == 64-1)
- {
- DiskParameters->Heads = 64;
- DiskParameters->Sectors = 32;
- break;
- }
- else if (PartitionEntryEndHead == 128-1)
- {
- DiskParameters->Heads = 128;
- DiskParameters->Sectors = 32;
- break;
- }
- else if (PartitionEntryEndHead == 255-1)
- {
- DiskParameters->Heads = 255;
- DiskParameters->Sectors = 63;
- break;
- }
- PartitionEntry++;
- }
- if (PartitionNumber == 4)
- {
- PartitionEntryEndHead = FirstPartitionEntry->end_head;
- PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
- }
- DiskParameters->Cylinders =
- Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
- if (PartitionNumber < 4 &&
- PartitionEntryEndSector == DiskParameters->Sectors)
- {
- if (DiskParameters->Cylinders != SavedCylinders)
- BusLogic_Warning("Adopting Geometry %d/%d from Partition Tablen",
- HostAdapter,
- DiskParameters->Heads, DiskParameters->Sectors);
- }
- else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
- {
- BusLogic_Warning("Warning: Partition Table appears to "
- "have Geometry %d/%d which isn", HostAdapter,
- PartitionEntryEndHead + 1,
- PartitionEntryEndSector);
- BusLogic_Warning("not compatible with current BusLogic "
- "Host Adapter Geometry %d/%dn", HostAdapter,
- DiskParameters->Heads, DiskParameters->Sectors);
- }
- }
- brelse(BufferHead);
- return 0;
- }
- /*
- BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
- */
- int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer,
- off_t Offset, int BytesAvailable,
- int HostNumber, int WriteFlag)
- {
- BusLogic_HostAdapter_T *HostAdapter;
- BusLogic_TargetStatistics_T *TargetStatistics;
- int TargetID, Length;
- char *Buffer;
- for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
- HostAdapter != NULL;
- HostAdapter = HostAdapter->Next)
- if (HostAdapter->HostNumber == HostNumber) break;
- if (HostAdapter == NULL)
- {
- BusLogic_Error("Cannot find Host Adapter for SCSI Host %dn",
- NULL, HostNumber);
- return 0;
- }
- TargetStatistics = HostAdapter->TargetStatistics;
- if (WriteFlag)
- {
- HostAdapter->ExternalHostAdapterResets = 0;
- HostAdapter->HostAdapterInternalErrors = 0;
- memset(TargetStatistics, 0,
- BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T));
- return 0;
- }
- Buffer = HostAdapter->MessageBuffer;
- Length = HostAdapter->MessageBufferLength;
- Length += sprintf(&Buffer[Length], "n
- Current Driver Queue Depth: %dn
- Currently Allocated CCBs: %dn",
- HostAdapter->DriverQueueDepth,
- HostAdapter->AllocatedCCBs);
- Length += sprintf(&Buffer[Length], "nn
- DATA TRANSFER STATISTICSn
- n
- Target Tagged Queuing Queue Depth Active Attempted Completedn
- ====== ============== =========== ====== ========= =========n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists) continue;
- Length +=
- sprintf(&Buffer[Length], " %2d %s", TargetID,
- (TargetFlags->TaggedQueuingSupported
- ? (TargetFlags->TaggedQueuingActive
- ? " Active"
- : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
- ? " Permitted" : " Disabled"))
- : "Not Supported"));
- Length += sprintf(&Buffer[Length],
- " %3d %3u %9u %9un",
- HostAdapter->QueueDepth[TargetID],
- HostAdapter->ActiveCommands[TargetID],
- TargetStatistics[TargetID].CommandsAttempted,
- TargetStatistics[TargetID].CommandsCompleted);
- }
- Length += sprintf(&Buffer[Length], "n
- Target Read Commands Write Commands Total Bytes Read Total Bytes Writtenn
- ====== ============= ============== =================== ===================n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists) continue;
- Length +=
- sprintf(&Buffer[Length], " %2d %9u %9u", TargetID,
- TargetStatistics[TargetID].ReadCommands,
- TargetStatistics[TargetID].WriteCommands);
- if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
- Length +=
- sprintf(&Buffer[Length], " %9u%09u",
- TargetStatistics[TargetID].TotalBytesRead.Billions,
- TargetStatistics[TargetID].TotalBytesRead.Units);
- else
- Length +=
- sprintf(&Buffer[Length], " %9u",
- TargetStatistics[TargetID].TotalBytesRead.Units);
- if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
- Length +=
- sprintf(&Buffer[Length], " %9u%09un",
- TargetStatistics[TargetID].TotalBytesWritten.Billions,
- TargetStatistics[TargetID].TotalBytesWritten.Units);
- else
- Length +=
- sprintf(&Buffer[Length], " %9un",
- TargetStatistics[TargetID].TotalBytesWritten.Units);
- }
- Length += sprintf(&Buffer[Length], "n
- Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KBn
- ====== ======= ========= ========= ========= ========= =========n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists) continue;
- Length +=
- sprintf(&Buffer[Length],
- " %2d Read %9u %9u %9u %9u %9un", TargetID,
- TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
- Length +=
- sprintf(&Buffer[Length],
- " %2d Write %9u %9u %9u %9u %9un", TargetID,
- TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
- }
- Length += sprintf(&Buffer[Length], "n
- Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+n
- ====== ======= ========= ========= ========= ========= =========n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists) continue;
- Length +=
- sprintf(&Buffer[Length],
- " %2d Read %9u %9u %9u %9u %9un", TargetID,
- TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
- TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
- Length +=
- sprintf(&Buffer[Length],
- " %2d Write %9u %9u %9u %9u %9un", TargetID,
- TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
- TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
- }
- Length += sprintf(&Buffer[Length], "nn
- ERROR RECOVERY STATISTICSn
- n
- Command Aborts Bus Device Resets Host Adapter Resetsn
- Target Requested Completed Requested Completed Requested Completedn
- ID \\\\ Attempted //// \\\\ Attempted //// \\\\ Attempted ////n
- ====== ===== ===== ===== ===== ===== ===== ===== ===== =====n");
- for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
- {
- BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
- if (!TargetFlags->TargetExists) continue;
- Length +=
- sprintf(&Buffer[Length], "
- %2d %5d %5d %5d %5d %5d %5d %5d %5d %5dn", TargetID,
- TargetStatistics[TargetID].CommandAbortsRequested,
- TargetStatistics[TargetID].CommandAbortsAttempted,
- TargetStatistics[TargetID].CommandAbortsCompleted,
- TargetStatistics[TargetID].BusDeviceResetsRequested,
- TargetStatistics[TargetID].BusDeviceResetsAttempted,
- TargetStatistics[TargetID].BusDeviceResetsCompleted,
- TargetStatistics[TargetID].HostAdapterResetsRequested,
- TargetStatistics[TargetID].HostAdapterResetsAttempted,
- TargetStatistics[TargetID].HostAdapterResetsCompleted);
- }
- Length += sprintf(&Buffer[Length], "nExternal Host Adapter Resets: %dn",
- HostAdapter->ExternalHostAdapterResets);
- Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %dn",
- HostAdapter->HostAdapterInternalErrors);
- if (Length >= BusLogic_MessageBufferSize)
- BusLogic_Error("Message Buffer length %d exceeds size %dn",
- HostAdapter, Length, BusLogic_MessageBufferSize);
- if ((Length -= Offset) <= 0) return 0;
- if (Length >= BytesAvailable) Length = BytesAvailable;
- memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
- *StartPointer = ProcBuffer;
- return Length;
- }
- /*
- BusLogic_Message prints Driver Messages.
- */
- static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel,
- char *Format,
- BusLogic_HostAdapter_T *HostAdapter,
- ...)
- {
- static char Buffer[BusLogic_LineBufferSize];
- static boolean BeginningOfLine = true;
- va_list Arguments;
- int Length = 0;
- va_start(Arguments, HostAdapter);
- Length = vsprintf(Buffer, Format, Arguments);
- va_end(Arguments);
- if (MessageLevel == BusLogic_AnnounceLevel)
- {
- static int AnnouncementLines = 0;
- strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
- Buffer);
- HostAdapter->MessageBufferLength += Length;
- if (++AnnouncementLines <= 2)
- printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
- }
- else if (MessageLevel == BusLogic_InfoLevel)
- {
- strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
- Buffer);
- HostAdapter->MessageBufferLength += Length;
- if (BeginningOfLine)
- {
- if (Buffer[0] != 'n' || Length > 1)
- printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
- HostAdapter->HostNumber, Buffer);
- }
- else printk("%s", Buffer);
- }
- else
- {
- if (BeginningOfLine)
- {
- if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
- printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
- HostAdapter->HostNumber, Buffer);
- else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
- }
- else printk("%s", Buffer);
- }
- BeginningOfLine = (Buffer[Length-1] == 'n');
- }
- /*
- BusLogic_ParseKeyword parses an individual option keyword. It returns true
- and updates the pointer if the keyword is recognized and false otherwise.
- */
- static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
- {
- char *Pointer = *StringPointer;
- while (*Keyword != ' ')
- {
- char StringChar = *Pointer++;
- char KeywordChar = *Keyword++;
- if (StringChar >= 'A' && StringChar <= 'Z')
- StringChar += 'a' - 'Z';
- if (KeywordChar >= 'A' && KeywordChar <= 'Z')
- KeywordChar += 'a' - 'Z';
- if (StringChar != KeywordChar) return false;
- }
- *StringPointer = Pointer;
- return true;
- }
- /*
- BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
- specifications.
- BusLogic Driver Options may be specified either via the Linux Kernel Command
- Line or via the Loadable Kernel Module Installation Facility. Driver Options
- for multiple host adapters may be specified either by separating the option
- strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
- command line. Individual option specifications for a single host adapter are
- separated by commas. The Probing and Debugging Options apply to all host
- adapters whereas the remaining options apply individually only to the
- selected host adapter.
- The BusLogic Driver Probing Options comprise the following:
- IO:<integer>
- The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
- MultiMaster Host Adapter. If neither "IO:" nor "NoProbeISA" options are
- specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
- will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134). Multiple
- "IO:" options may be specified to precisely determine the I/O Addresses to
- be probed, but the probe order will always follow the standard list.
- NoProbe
- The "NoProbe" option disables all probing and therefore no BusLogic Host
- Adapters will be detected.
- NoProbeISA
- The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
- Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
- will be detected.
- NoProbePCI
- The "NoProbePCI" options disables the interrogation of PCI Configuration
- Space and therefore only ISA Multimaster Host Adapters will be detected, as
- well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
- Port set to "Primary" or "Alternate".
- NoSortPCI
- The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
- enumerated in the order provided by the PCI BIOS, ignoring any setting of
- the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
- MultiMasterFirst
- The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
- before FlashPoint Host Adapters. By default, if both FlashPoint and PCI
- MultiMaster Host Adapters are present, this driver will probe for
- FlashPoint Host Adapters first unless the BIOS primary disk is controlled
- by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
- Adapters will be probed first.
- FlashPointFirst
- The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
- before MultiMaster Host Adapters.
- The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
- the Queue Depth and whether Tagged Queuing is permitted for each Target
- Device (assuming that the Target Device supports Tagged Queuing). The Queue
- Depth is the number of SCSI Commands that are allowed to be concurrently
- presented for execution (either to the Host Adapter or Target Device). Note
- that explicitly enabling Tagged Queuing may lead to problems; the option to
- enable or disable Tagged Queuing is provided primarily to allow disabling
- Tagged Queuing on Target Devices that do not implement it correctly. The
- following options are available:
- QueueDepth:<integer>
- The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
- Target Devices that support Tagged Queuing, as well as the maximum Queue
- Depth for devices that do not support Tagged Queuing. If no Queue Depth
- option is provided, the Queue Depth will be determined automatically based
- on the Host Adapter's Total Queue Depth and the number, type, speed, and
- capabilities of the detected Target Devices. For Host Adapters that
- require ISA Bounce Buffers, the Queue Depth is automatically set by default
- to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
- excessive preallocation of DMA Bounce Buffer memory. Target Devices that
- do not support Tagged Queuing always have their Queue Depth set to
- BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
- lower Queue Depth option is provided. A Queue Depth of 1 automatically
- disables Tagged Queuing.
- QueueDepth:[<integer>,<integer>...]
- The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
- individually for each Target Device. If an <integer> is omitted, the
- associated Target Device will have its Queue Depth selected automatically.
- TaggedQueuing:Default
- The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
- based on the firmware version of the BusLogic Host Adapter and based on
- whether the Queue Depth allows queuing multiple commands.
- TaggedQueuing:Enable
- The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
- all Target Devices on this Host Adapter, overriding any limitation that
- would otherwise be imposed based on the Host Adapter firmware version.
- TaggedQueuing:Disable
- The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
- for all Target Devices on this Host Adapter.
- TaggedQueuing:<Target-Spec>
- The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
- Tagged Queuing individually for each Target Device. <Target-Spec> is a
- sequence of "Y", "N", and "X" characters. "Y" enables Tagged Queuing, "N"
- disables Tagged Queuing, and "X" accepts the default based on the firmware
- version. The first character refers to Target Device 0, the second to
- Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
- does not cover all the Target Devices, unspecified characters are assumed
- to be "X".
- The BusLogic Driver Error Recovery Option allows for explicitly specifying
- the Error Recovery action to be performed when BusLogic_ResetCommand is
- called due to a SCSI Command failing to complete successfully. The following
- options are available:
- ErrorRecovery:Default
- The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
- Reset and Bus Device Reset options based on the recommendation of the SCSI
- Subsystem.
- ErrorRecovery:HardReset
- The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
- Adapter Hard Reset which also causes a SCSI Bus Reset.
- ErrorRecovery:BusDeviceReset
- The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
- a Bus Device Reset message to the individual Target Device causing the
- error. If Error Recovery is again initiated for this Target Device and no
- SCSI Command to this Target Device has completed successfully since the Bus
- Device Reset message was sent, then a Hard Reset will be attempted.
- ErrorRecovery:None
- The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
- This option should only be selected if a SCSI Bus Reset or Bus Device Reset
- will cause the Target Device or a critical operation to suffer a complete
- and unrecoverable failure.
- ErrorRecovery:<Target-Spec>
- The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
- Error Recovery individually for each Target Device. <Target-Spec> is a
- sequence of "D", "H", "B", and "N" characters. "D" selects Default, "H"
- selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
- The first character refers to Target Device 0, the second to Target Device
- 1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
- cover all the possible Target Devices, unspecified characters are assumed
- to be "D".
- The BusLogic Driver Miscellaneous Options comprise the following:
- BusSettleTime:<seconds>
- The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
- seconds. The Bus Settle Time is the amount of time to wait between a Host
- Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
- Commands. If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
- InhibitTargetInquiry
- The "InhibitTargetInquiry" option inhibits the execution of an Inquire
- Target Devices or Inquire Installed Devices command on MultiMaster Host
- Adapters. This may be necessary with some older Target Devices that do not
- respond correctly when Logical Units above 0 are addressed.
- The BusLogic Driver Debugging Options comprise the following:
- TraceProbe
- The "TraceProbe" option enables tracing of Host Adapter Probing.
- TraceHardwareReset
- The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
- Reset.
- TraceConfiguration
- The "TraceConfiguration" option enables tracing of Host Adapter
- Configuration.
- TraceErrors
- The "TraceErrors" option enables tracing of SCSI Commands that return an
- error from the Target Device. The CDB and Sense Data will be printed for
- each SCSI Command that fails.
- Debug
- The "Debug" option enables all debugging options.
- The following examples demonstrate setting the Queue Depth for Target Devices
- 1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
- Devices on the second host adapter to 31, and the Bus Settle Time on the
- second host adapter to 30 seconds.
- Linux Kernel Command Line:
- linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
- LILO Linux Boot Loader (in /etc/lilo.conf):
- append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
- INSMOD Loadable Kernel Module Installation Facility:
- insmod BusLogic.o
- 'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
- NOTE: Module Utilities 2.1.71 or later is required for correct parsing
- of driver options containing commas.
- */
- static int __init BusLogic_ParseDriverOptions(char *OptionsString)
- {
- while (true)
- {
- BusLogic_DriverOptions_T *DriverOptions =
- &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
- int TargetID;
- memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T));
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_Default;
- while (*OptionsString != ' ' && *OptionsString != ';')
- {
- /* Probing Options. */
- if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
- {
- BusLogic_IO_Address_T IO_Address =
- simple_strtoul(OptionsString, &OptionsString, 0);
- BusLogic_ProbeOptions.LimitedProbeISA = true;
- switch (IO_Address)
- {
- case 0x330:
- BusLogic_ProbeOptions.Probe330 = true;
- break;
- case 0x334:
- BusLogic_ProbeOptions.Probe334 = true;
- break;
- case 0x230:
- BusLogic_ProbeOptions.Probe230 = true;
- break;
- case 0x234:
- BusLogic_ProbeOptions.Probe234 = true;
- break;
- case 0x130:
- BusLogic_ProbeOptions.Probe130 = true;
- break;
- case 0x134:
- BusLogic_ProbeOptions.Probe134 = true;
- break;
- default:
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(illegal I/O Address 0x%X)n",
- NULL, IO_Address);
- return 0;
- }
- }
- else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
- BusLogic_ProbeOptions.NoProbeISA = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
- BusLogic_ProbeOptions.NoProbePCI = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
- BusLogic_ProbeOptions.NoProbe = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
- BusLogic_ProbeOptions.NoSortPCI = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
- BusLogic_ProbeOptions.MultiMasterFirst = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
- BusLogic_ProbeOptions.FlashPointFirst = true;
- /* Tagged Queuing Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
- BusLogic_ParseKeyword(&OptionsString, "QD:["))
- {
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- {
- unsigned short QueueDepth =
- simple_strtoul(OptionsString, &OptionsString, 0);
- if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(illegal Queue Depth %d)n",
- NULL, QueueDepth);
- return 0;
- }
- DriverOptions->QueueDepth[TargetID] = QueueDepth;
- if (*OptionsString == ',')
- OptionsString++;
- else if (*OptionsString == ']')
- break;
- else
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(',' or ']' expected at '%s')n",
- NULL, OptionsString);
- return 0;
- }
- }
- if (*OptionsString != ']')
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(']' expected at '%s')n",
- NULL, OptionsString);
- return 0;
- }
- else OptionsString++;
- }
- else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
- BusLogic_ParseKeyword(&OptionsString, "QD:"))
- {
- unsigned short QueueDepth =
- simple_strtoul(OptionsString, &OptionsString, 0);
- if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(illegal Queue Depth %d)n",
- NULL, QueueDepth);
- return 0;
- }
- DriverOptions->CommonQueueDepth = QueueDepth;
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- DriverOptions->QueueDepth[TargetID] = QueueDepth;
- }
- else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
- BusLogic_ParseKeyword(&OptionsString, "TQ:"))
- {
- if (BusLogic_ParseKeyword(&OptionsString, "Default"))
- {
- DriverOptions->TaggedQueuingPermitted = 0x0000;
- DriverOptions->TaggedQueuingPermittedMask = 0x0000;
- }
- else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
- {
- DriverOptions->TaggedQueuingPermitted = 0xFFFF;
- DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
- }
- else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
- {
- DriverOptions->TaggedQueuingPermitted = 0x0000;
- DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
- }
- else
- {
- unsigned short TargetBit;
- for (TargetID = 0, TargetBit = 1;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++, TargetBit <<= 1)
- switch (*OptionsString++)
- {
- case 'Y':
- DriverOptions->TaggedQueuingPermitted |= TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
- break;
- case 'N':
- DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
- break;
- case 'X':
- break;
- default:
- OptionsString--;
- TargetID = BusLogic_MaxTargetDevices;
- break;
- }
- }
- }
- /* Error Recovery Option. */
- else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") ||
- BusLogic_ParseKeyword(&OptionsString, "ER:"))
- {
- if (BusLogic_ParseKeyword(&OptionsString, "Default"))
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_Default;
- else if (BusLogic_ParseKeyword(&OptionsString, "HardReset"))
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_HardReset;
- else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset"))
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_BusDeviceReset;
- else if (BusLogic_ParseKeyword(&OptionsString, "None"))
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_None;
- else
- for (TargetID = 0;
- TargetID < BusLogic_MaxTargetDevices;
- TargetID++)
- switch (*OptionsString++)
- {
- case 'D':
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_Default;
- break;
- case 'H':
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_HardReset;
- break;
- case 'B':
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_BusDeviceReset;
- break;
- case 'N':
- DriverOptions->ErrorRecoveryStrategy[TargetID] =
- BusLogic_ErrorRecovery_None;
- break;
- default:
- OptionsString--;
- TargetID = BusLogic_MaxTargetDevices;
- break;
- }
- }
- /* Miscellaneous Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
- BusLogic_ParseKeyword(&OptionsString, "BST:"))
- {
- unsigned short BusSettleTime =
- simple_strtoul(OptionsString, &OptionsString, 0);
- if (BusSettleTime > 5 * 60)
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(illegal Bus Settle Time %d)n",
- NULL, BusSettleTime);
- return 0;
- }
- DriverOptions->BusSettleTime = BusSettleTime;
- }
- else if (BusLogic_ParseKeyword(&OptionsString,
- "InhibitTargetInquiry"))
- DriverOptions->LocalOptions.InhibitTargetInquiry = true;
- /* Debugging Options. */
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
- BusLogic_GlobalOptions.TraceProbe = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
- BusLogic_GlobalOptions.TraceHardwareReset = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
- BusLogic_GlobalOptions.TraceConfiguration = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
- BusLogic_GlobalOptions.TraceErrors = true;
- else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
- {
- BusLogic_GlobalOptions.TraceProbe = true;
- BusLogic_GlobalOptions.TraceHardwareReset = true;
- BusLogic_GlobalOptions.TraceConfiguration = true;
- BusLogic_GlobalOptions.TraceErrors = true;
- }
- if (*OptionsString == ',')
- OptionsString++;
- else if (*OptionsString != ';' && *OptionsString != ' ')
- {
- BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
- "ignoredn", NULL, OptionsString);
- *OptionsString = ' ';
- }
- }
- if (!(BusLogic_DriverOptionsCount == 0 ||
- BusLogic_ProbeInfoCount == 0 ||
- BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
- {
- BusLogic_Error("BusLogic: Invalid Driver Options "
- "(all or no I/O Addresses must be specified)n", NULL);
- return 0;
- }
- /*
- Tagged Queuing is disabled when the Queue Depth is 1 since queuing
- multiple commands is not possible.
- */
- for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
- if (DriverOptions->QueueDepth[TargetID] == 1)
- {
- unsigned short TargetBit = 1 << TargetID;
- DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
- DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
- }
- if (*OptionsString == ';') OptionsString++;
- if (*OptionsString == ' ') return 0;
- }
- return 1;
- }
- /*
- BusLogic_Setup handles processing of Kernel Command Line Arguments.
- */
- static int __init
- BusLogic_Setup(char *str)
- {
- int ints[3];
- (void)get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] != 0) {
- BusLogic_Error("BusLogic: Obsolete Command Line Entry "
- "Format Ignoredn", NULL);
- return 0;
- }
- if (str == NULL || *str == ' ')
- return 0;
- return BusLogic_ParseDriverOptions(str);
- }
- __setup("BusLogic=", BusLogic_Setup);
- /*
- Get it all started
- */
- MODULE_LICENSE("GPL");
- static SCSI_Host_Template_T driver_template = BUSLOGIC;
- #include "scsi_module.c"