⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buslogic.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  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(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength){	unsigned char *ParameterPointer = (unsigned char *) ParameterData;	unsigned char *ReplyPointer = (unsigned char *) ReplyData;	union BusLogic_StatusRegister StatusRegister;	union BusLogic_InterruptRegister InterruptRegister;	unsigned long 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)		local_irq_save(ProcessorFlags);	/*	   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.sr.HostAdapterReady && !StatusRegister.sr.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.ir.CommandComplete)			break;		if (HostAdapter->HostAdapterCommandCompleted)			break;		if (StatusRegister.sr.DataInRegisterReady)			break;		if (StatusRegister.sr.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.sr.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.ir.CommandComplete)			break;		if (HostAdapter->HostAdapterCommandCompleted)			break;		if (StatusRegister.sr.DataInRegisterReady) {			if (++ReplyBytes <= ReplyLength)				*ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);			else				BusLogic_ReadDataInRegister(HostAdapter);		}		if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.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.sr.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.sr.CommandInvalid ||		    StatusRegister.sr.Reserved ||		    StatusRegister.sr.DataInRegisterReady ||		    StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.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)		local_irq_restore(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 __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address){	struct BusLogic_ProbeInfo *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;	ProbeInfo->PCI_Device = NULL;}/*  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 __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter						       *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)		BusLogic_AppendProbeAddressISA(0x330);	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)		BusLogic_AppendProbeAddressISA(0x334);	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)		BusLogic_AppendProbeAddressISA(0x230);	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)		BusLogic_AppendProbeAddressISA(0x234);	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)		BusLogic_AppendProbeAddressISA(0x130);	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)		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 __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount){	int LastInterchange = ProbeInfoCount - 1, Bound, j;	while (LastInterchange > 0) {		Bound = LastInterchange;		LastInterchange = 0;		for (j = 0; j < Bound; j++) {			struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];			struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1];			if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) {				struct BusLogic_ProbeInfo TempProbeInfo;				memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));				memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));				memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));				LastInterchange = j;			}		}	}}/*  BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address  and Bus Probe Information to be checked for potential BusLogic MultiMaster  SCSI Host Adapters by interrogating the PCI Configuration Space on PCI  machines as well as from the list of standard BusLogic MultiMaster ISA  I/O Addresses.  It returns the number of PCI MultiMaster Host Adapters found.*/static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter							  *PrototypeHostAdapter){	struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];	int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;	int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;	bool ForceBusDeviceScanningOrder = false;	bool ForceBusDeviceScanningOrderChecked = false;	bool StandardAddressSeen[6];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -