📄 buslogic.c
字号:
true); CCB = HostAdapter->Free_CCBs; if (CCB == NULL) return NULL; CCB->SerialNumber = ++SerialNumber; HostAdapter->Free_CCBs = CCB->Next; CCB->Next = NULL; return CCB;}/* BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's free list. The Host Adapter's Lock should already have been acquired by the caller.*/static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB){ BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; CCB->Command = NULL; CCB->Status = BusLogic_CCB_Free; CCB->Next = HostAdapter->Free_CCBs; HostAdapter->Free_CCBs = CCB;}/* BusLogic_Command sends the command OperationCode to HostAdapter, optionally providing ParameterLength bytes of ParameterData and receiving at most ReplyLength bytes of ReplyData; any excess reply data is received but discarded. On success, this function returns the number of reply bytes read from the Host Adapter (including any discarded data); on failure, it returns -1 if the command was invalid, or -2 if a timeout occurred. BusLogic_Command is called exclusively during host adapter detection and initialization, so performance and latency are not critical, and exclusive access to the Host Adapter hardware is assumed. Once the host adapter and driver are initialized, the only Host Adapter command that is issued is the single byte Execute Mailbox Command operation code, which does not require waiting for the Host Adapter Ready bit to be set in the Status Register.*/static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, BusLogic_OperationCode_T OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength){ unsigned char *ParameterPointer = (unsigned char *) ParameterData; unsigned char *ReplyPointer = (unsigned char *) ReplyData; BusLogic_StatusRegister_T StatusRegister; BusLogic_InterruptRegister_T InterruptRegister; ProcessorFlags_T ProcessorFlags = 0; int ReplyBytes = 0, Result; long TimeoutCounter; /* Clear out the Reply Data if provided. */ if (ReplyLength > 0) memset(ReplyData, 0, ReplyLength); /* If the IRQ Channel has not yet been acquired, then interrupts must be disabled while issuing host adapter commands since a Command Complete interrupt could occur if the IRQ Channel was previously enabled by another BusLogic Host Adapter or another driver sharing the same IRQ Channel. */ if (!HostAdapter->IRQ_ChannelAcquired) { save_flags(ProcessorFlags); cli(); } /* Wait for the Host Adapter Ready bit to be set and the Command/Parameter Register Busy bit to be reset in the Status Register. */ TimeoutCounter = 10000; while (--TimeoutCounter >= 0) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); if (StatusRegister.Bits.HostAdapterReady && !StatusRegister.Bits.CommandParameterRegisterBusy) break; udelay(100); } if (TimeoutCounter < 0) { BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; Result = -2; goto Done; } /* Write the OperationCode to the Command/Parameter Register. */ HostAdapter->HostAdapterCommandCompleted = false; BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); /* Write any additional Parameter Bytes. */ TimeoutCounter = 10000; while (ParameterLength > 0 && --TimeoutCounter >= 0) { /* Wait 100 microseconds to give the Host Adapter enough time to determine whether the last value written to the Command/Parameter Register was valid or not. If the Command Complete bit is set in the Interrupt Register, then the Command Invalid bit in the Status Register will be reset if the Operation Code or Parameter was valid and the command has completed, or set if the Operation Code or Parameter was invalid. If the Data In Register Ready bit is set in the Status Register, then the Operation Code was valid, and data is waiting to be read back from the Host Adapter. Otherwise, wait for the Command/Parameter Register Busy bit in the Status Register to be reset. */ udelay(100); InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); if (InterruptRegister.Bits.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; if (StatusRegister.Bits.DataInRegisterReady) break; if (StatusRegister.Bits.CommandParameterRegisterBusy) continue; BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); ParameterLength--; } if (TimeoutCounter < 0) { BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; Result = -2; goto Done; } /* The Modify I/O Address command does not cause a Command Complete Interrupt. */ if (OperationCode == BusLogic_ModifyIOAddress) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); if (StatusRegister.Bits.CommandInvalid) { BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; Result = -1; goto Done; } if (BusLogic_GlobalOptions.TraceConfiguration) BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All); Result = 0; goto Done; } /* Select an appropriate timeout value for awaiting command completion. */ switch (OperationCode) { case BusLogic_InquireInstalledDevicesID0to7: case BusLogic_InquireInstalledDevicesID8to15: case BusLogic_InquireTargetDevices: /* Approximately 60 seconds. */ TimeoutCounter = 60*10000; break; default: /* Approximately 1 second. */ TimeoutCounter = 10000; break; } /* Receive any Reply Bytes, waiting for either the Command Complete bit to be set in the Interrupt Register, or for the Interrupt Handler to set the Host Adapter Command Completed bit in the Host Adapter structure. */ while (--TimeoutCounter >= 0) { InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); if (InterruptRegister.Bits.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; if (StatusRegister.Bits.DataInRegisterReady) { if (++ReplyBytes <= ReplyLength) *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); else BusLogic_ReadDataInRegister(HostAdapter); } if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.Bits.HostAdapterReady) break; udelay(100); } if (TimeoutCounter < 0) { BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; Result = -2; goto Done; } /* Clear any pending Command Complete Interrupt. */ BusLogic_InterruptReset(HostAdapter); /* Provide tracing information if requested. */ if (BusLogic_GlobalOptions.TraceConfiguration) { int i; BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes); if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; for (i = 0; i < ReplyLength; i++) BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]); BusLogic_Notice("\n", HostAdapter); } /* Process Command Invalid conditions. */ if (StatusRegister.Bits.CommandInvalid) { /* Some early BusLogic Host Adapters may not recover properly from a Command Invalid condition, so if this appears to be the case, a Soft Reset is issued to the Host Adapter. Potentially invalid commands are never attempted after Mailbox Initialization is performed, so there should be no Host Adapter state lost by a Soft Reset in response to a Command Invalid condition. */ udelay(1000); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); if (StatusRegister.Bits.CommandInvalid || StatusRegister.Bits.Reserved || StatusRegister.Bits.DataInRegisterReady || StatusRegister.Bits.CommandParameterRegisterBusy || !StatusRegister.Bits.HostAdapterReady || !StatusRegister.Bits.InitializationRequired || StatusRegister.Bits.DiagnosticActive || StatusRegister.Bits.DiagnosticFailure) { BusLogic_SoftReset(HostAdapter); udelay(1000); } BusLogic_CommandFailureReason = "Command Invalid"; Result = -1; goto Done; } /* Handle Excess Parameters Supplied conditions. */ if (ParameterLength > 0) { BusLogic_CommandFailureReason = "Excess Parameters Supplied"; Result = -1; goto Done; } /* Indicate the command completed successfully. */ BusLogic_CommandFailureReason = NULL; Result = ReplyBytes; /* Restore the interrupt status if necessary and return. */Done: if (!HostAdapter->IRQ_ChannelAcquired) restore_flags(ProcessorFlags); return Result;}/* BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list of I/O Address and Bus Probe Information to be checked for potential BusLogic Host Adapters.*/static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address){ BusLogic_ProbeInfo_T *ProbeInfo; if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return; ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; ProbeInfo->HostAdapterType = BusLogic_MultiMaster; ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; ProbeInfo->IO_Address = IO_Address;}/* BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters only from the list of standard BusLogic MultiMaster ISA I/O Addresses.*/static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T *PrototypeHostAdapter){ /* If BusLogic Driver Options specifications requested that ISA Bus Probes be inhibited, do not proceed further. */ if (BusLogic_ProbeOptions.NoProbeISA) return; /* Append the list of standard BusLogic MultiMaster ISA I/O Addresses. */ if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x330); if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x334); if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x230); if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x234); if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x130); if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) BusLogic_AppendProbeAddressISA(0x134);}#ifdef CONFIG_PCI/* BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order of increasing PCI Bus and Device Number.*/static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList, int ProbeInfoCount){ int LastInterchange = ProbeInfoCount-1, Bound, j; while (LastInterchange > 0) { Bound = LastInterchange; LastInterchange = 0; for (j = 0; j < Bound; j++) { BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j]; BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1]; if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) { BusLogic_ProbeInfo_T TempProbeInfo; memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T)); memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T)); memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T)); LastInterchange = j; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -