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

📄 fec.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
//
//------------------------------------------------------------------------------
//
//  File:  fec.c
//
//  Implementation of FEC Driver
//
//  This file implements NDIS interface for FEC.
//
//-----------------------------------------------------------------------------

#include "fec.h"


//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

// Global var of FEC Ndis Handler
NDIS_HANDLE  gFECNdisHandle;
PCSP_FEC_REGS     gpFECReg = NULL;

CRITICAL_SECTION gFECRegCs;
CRITICAL_SECTION gFECBufCs;

//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
static NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);

// List of supported OIDs for the FEC driver
static NDIS_OID FECSupportedOids[] = {
	OID_GEN_VENDOR_DRIVER_VERSION,
	OID_GEN_SUPPORTED_LIST,
	OID_GEN_HARDWARE_STATUS,
	OID_GEN_MEDIA_SUPPORTED,
	OID_GEN_MEDIA_IN_USE,
	OID_GEN_MEDIA_CONNECT_STATUS,
	OID_GEN_MAXIMUM_LOOKAHEAD,
	OID_GEN_MAXIMUM_FRAME_SIZE,
	OID_GEN_MAXIMUM_TOTAL_SIZE,
	OID_GEN_MAC_OPTIONS,
	OID_GEN_PROTOCOL_OPTIONS,
	OID_GEN_LINK_SPEED,
	OID_GEN_TRANSMIT_BUFFER_SPACE,
	OID_GEN_RECEIVE_BUFFER_SPACE,
	OID_GEN_TRANSMIT_BLOCK_SIZE,
	OID_GEN_RECEIVE_BLOCK_SIZE,
	OID_GEN_VENDOR_DESCRIPTION,
	OID_GEN_VENDOR_ID,
	OID_GEN_DRIVER_VERSION,
	OID_GEN_CURRENT_PACKET_FILTER,
	OID_GEN_CURRENT_LOOKAHEAD,
	OID_GEN_XMIT_OK,
	OID_GEN_RCV_OK,
	OID_GEN_XMIT_ERROR,
	OID_GEN_RCV_ERROR,
	OID_GEN_RCV_NO_BUFFER,
	OID_GEN_MAXIMUM_SEND_PACKETS,
	OID_802_3_PERMANENT_ADDRESS,
	OID_802_3_CURRENT_ADDRESS,
	OID_802_3_MULTICAST_LIST,
	OID_802_3_MAXIMUM_LIST_SIZE,
	OID_802_3_RCV_ERROR_ALIGNMENT,
	OID_802_3_XMIT_ONE_COLLISION,
	OID_802_3_XMIT_MORE_COLLISIONS,
	OID_802_3_XMIT_MAX_COLLISIONS,
	OID_802_3_RCV_OVERRUN,
	OID_802_3_XMIT_UNDERRUN
};



//-----------------------------------------------------------------------------
//
// Function: DllEntry
//
//  This function is entry point of the dll.
//
// Parameters:
//      hInstDll
//          [in] .
//      Op
//          [in] .
//      lpvReserved
//          [in] .
//
// Returns:
//    This function always returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL WINAPI DllEntry( HANDLE hInstDll, DWORD  Op, LPVOID lpvReserved )
{
    switch(Op)
    {
        case DLL_PROCESS_ATTACH:
            DEBUGMSG(ZONE_INIT, (TEXT("FEC: DLL Process Attach.\r\n")));

            // Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications
            DisableThreadLibraryCalls((HMODULE) hInstDll);
            break;

        case DLL_PROCESS_DETACH:
            DEBUGMSG(ZONE_INIT, (TEXT("FEC: DLL Process Detach.\r\n")));
            break;

        default:
            break;
    }

    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: DriverEntry
//
// This function is the main entry of driver. It initializes and registers FEC
// driver to NDIS.
//
// Parameters:
//      DriverObject
//          [in] pointer to driver object created by the system.
//
//      RegistryPath
//          [in] Driver Registry path.
//
// Returns:
//		Returns STATUS_SUCCESS if initialization is success. Return 
//		STATUS_UNSUCCESSFUL if not.
//
//------------------------------------------------------------------------------
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NDIS_STATUS Status;
	NDIS_MINIPORT_CHARACTERISTICS FECChar; // Characteristics table for the FEC driver
	
	DEBUGMSG(ZONE_INIT, (TEXT("FEC: +DriverEntry(0x%.8X, 0x%.8X)\r\n"), DriverObject, RegistryPath));

	// Notifies NDIS for new miniport driver
	NdisMInitializeWrapper(&gFECNdisHandle, DriverObject, RegistryPath, NULL);
	
	// Fill-in adapter characterictics before calling NdisMRegisterMiniport
	memset(&FECChar, 0, sizeof(FECChar));
	
	FECChar.MajorNdisVersion = FEC_NDIS_MAJOR_VERSION;
	FECChar.MinorNdisVersion = FEC_NDIS_MINOR_VERSION;
	FECChar.CheckForHangHandler = FECCheckForHang;
	FECChar.DisableInterruptHandler = FECDisableInterrupt;
	FECChar.EnableInterruptHandler = FECEnableInterrupt;
	FECChar.HaltHandler = FECHalt;
	FECChar.HandleInterruptHandler = FECHandleInterrupt; 
	FECChar.InitializeHandler = FECInitialize;
	FECChar.ISRHandler = FECIsr;
	FECChar.QueryInformationHandler = FECQueryInformation;
	FECChar.ReconfigureHandler = NULL;
	FECChar.ResetHandler = FECReset;
	FECChar.SendHandler = FECSend;
	FECChar.SetInformationHandler = FECSetInformation;
	FECChar.TransferDataHandler = FECTransferData;
	
	
	// Now register Miniport
	Status = NdisMRegisterMiniport(gFECNdisHandle, &FECChar, sizeof(FECChar));
	
	if (Status != NDIS_STATUS_SUCCESS)
	{
		DEBUGMSG(ZONE_ERROR, (TEXT("FEC: NdisMRegisterMiniport failure [0x%.8X].\r\n"), Status));
		NdisTerminateWrapper(gFECNdisHandle, NULL);
	}
	
	DEBUGMSG(ZONE_INIT, (TEXT("FEC: -DriverEntry [0x%.8X]\r\n"), Status));

	return (Status);
}

//------------------------------------------------------------------------------
//
// Function: FECInitialize
//
// This function finds and initializes the FEC adapter. When the FEC driver calls 
// the NdisMRegisterMiniport from its DriverEntry function, NDIS will call 
// FECInitialize in the context of NdisMRegisterMiniport.
//
// Parameters:
//		OpenErrorStatus
//			[out] Points to a variable that FECInitialize sets to an NDIS_STATUS_XXX
//				  code information about the error if FECInitialize will return
//				  NDIS_STATUS_OPEN_ERROR.
//
//		SelectedMediumIndex
//			[out] Points to a variable in which FECInitialize sets the index of 
//				  MediumArray element that specifies the medium type the FEC adapter 
//				  uses.
//
//		MediumArray
//			[in]  Specifies an array of NdisMediumXXX values from which FECInitialize
//				  selects one that the FEC adapter supports.
//
//		MediumArraySize
//			[in]  Specifies the number of elements at MediumArray.
//
//		MiniportAdapterHandle
//			[in]  Specifies a handle identifying the FEC driver, which is assigned by
//				  the NDIS library. It is a required parameter in subsequent calls
//				  to NdisXXX functions.
//
//		WrapperConfigurationContext
//			[in]  Specifies a handle used only during initialization for calls to
//				  NdisXXX configuration and initialization functions. For example, 
//				  this handle is a required parameter to NdisOpenConfiguration 
//				  function.
//
// Returns:
//		Returns NDIS_STATUS_SUCCESS if initialization is success.
//		Return NDIS_STATUS_FAILURE or NDIS_STATUS_UNSUPPORTED_MEDIA if not.
//
//------------------------------------------------------------------------------  
#pragma NDIS_PAGEABLE_FUNCTION(FECInitialize)
static NDIS_STATUS FECInitialize(
	OUT PNDIS_STATUS OpenErrorStatus,
	OUT PUINT SelectedMediumIndex,
	IN PNDIS_MEDIUM MediumArray,
	IN UINT MediumArraySize,
	IN NDIS_HANDLE MiniportAdapterHandle,
	IN NDIS_HANDLE WrapperConfigurationContext)
{

	// Pointer to our newly allocated adapter
	pFEC_t pEthernet = NULL;
	
	// The handle for reading from the registry
	NDIS_HANDLE ConfigHandle = NULL;
	
	UINT32 i;
	ULONG  MemPhysAddr;
	//NDIS_PHYSICAL_ADDRESS   PhysicalAddress;
	NDIS_STATUS Status=NDIS_STATUS_SUCCESS, MACStatus;
	BOOL result;
	PNDIS_CONFIGURATION_PARAMETER Value;
	USHORT TmpVal;
	NDIS_STRING MACAddrString[3]= { NDIS_STRING_CONST("MACAddress1"),
									NDIS_STRING_CONST("MACAddress2"),
									NDIS_STRING_CONST("MACAddress3")};
									
	//PHYSICAL_ADDRESS phyAddr;
	// WORD InterruptEvent;

	DEBUGMSG(ZONE_INIT, (TEXT("FEC: +FECInitialize\r\n")));
	InitializeCriticalSection (&gFECRegCs);
	InitializeCriticalSection (&gFECBufCs);
	
	do {
		// Step 1: Search for medium type (802.3) in the given array
		for (i = 0;i < MediumArraySize; i++) {
			if (MediumArray[i] == NdisMedium802_3) {
				*SelectedMediumIndex = i;
				break;
			}
		}
		
		if (i == MediumArraySize) {
			DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("FEC: No supported media\r\n")));
			Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
			break;
		}
		
		*SelectedMediumIndex = i;
		DEBUGMSG(ZONE_INIT, (TEXT("FEC: Search for media success. \r\n")));
		
		// Step 2: Allocate memory for the adapter block now
		Status = NdisAllocateMemory( (PVOID *)&pEthernet, sizeof(FEC_t), 0, HighestAcceptableMax);
		
		if (Status != NDIS_STATUS_SUCCESS)
		{
			DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("FEC: NdisAllocateMemory(FEC_t) failed\n")));
			break;
		}
		
		DEBUGMSG(ZONE_INIT, (TEXT("FEC: Allocate memory for the adapter block success. \r\n")));
		
		
		// Step 3: Clear out and initialize the pEthernet block
		NdisZeroMemory (pEthernet, sizeof(FEC_t));
		pEthernet->ndisAdapterHandle = MiniportAdapterHandle;
		pEthernet->CurrentState = NdisHardwareStatusNotReady;
		pEthernet->CurrentLookAhead = 1500;
		pEthernet->HeadPacket = pEthernet->TailPacket = NULL;
		pEthernet->TransmitInProgress = FALSE;
		pEthernet->StartTx = FALSE;
		pEthernet->SpeedMode = FALSE;
		
		pEthernet->RcvStatus.FrameRcvGood = 0;
		pEthernet->RcvStatus.FrameRcvErrors = 0;
		pEthernet->RcvStatus.FrameRcvExtraDataErrors = 0;
		pEthernet->RcvStatus.FrameRcvShortDataErrors = 0;
		pEthernet->RcvStatus.FrameRcvCRCErrors = 0;
		pEthernet->RcvStatus.FrameRcvOverrunErrors = 0;
		pEthernet->RcvStatus.FrameRcvAllignmentErrors = 0;
		pEthernet->RcvStatus.FrameRcvLCErrors = 0;
		
		pEthernet->TxdStatus.FramesXmitGood = 0;
		pEthernet->TxdStatus.FramesXmitBad = 0;
		pEthernet->TxdStatus.FramesXmitHBErrors = 0;
		pEthernet->TxdStatus.FramesXmitUnderrunErrors = 0;
		pEthernet->TxdStatus.FramesXmitCollisionErrors = 0;
		pEthernet->TxdStatus.FramesXmitAbortedErrors = 0;
		pEthernet->TxdStatus.FramsXmitCarrierErrors = 0;
		
		DEBUGMSG(ZONE_INIT, (TEXT("FEC: NdisZeroMemory success. \r\n")));
		
		NdisMSetAttributes(
			MiniportAdapterHandle,
			(NDIS_HANDLE)pEthernet,
			TRUE,							// DMA involved
			NdisInterfaceInternal);			// host-specific internal interface
			
		DEBUGMSG(ZONE_INIT, (TEXT("FEC: NdisMSetAttributes completed \r\n")));
		
		// Step 4: Open the configuration space and get MAC address
		NdisOpenConfiguration(&Status, &ConfigHandle, WrapperConfigurationContext);
		
		if (Status != NDIS_STATUS_SUCCESS)
		{
			DEBUGMSG(ZONE_INIT, (TEXT("FEC: NdisOpenconfiguration failed 0x%x\n"), Status));
			break;
		}
		
		DEBUGMSG(ZONE_INIT, (TEXT("FEC: NdisOpenconfiguration success. \r\n")));

		// read in the MAC address in registry
		for(i = 0; i < 3; i++)
		{
			NdisReadConfiguration(&MACStatus, &Value, ConfigHandle, 
										&MACAddrString[i], NdisParameterHexInteger);
										
			if(MACStatus == NDIS_STATUS_SUCCESS)
			{
				TmpVal=(USHORT)Value->ParameterData.IntegerData;
				pEthernet->FecMacAddress[i*2] = (UCHAR)((TmpVal & 0xff00) >> 8);
				pEthernet->FecMacAddress[(i*2)+1] = (UCHAR)(TmpVal & 0x00ff);
			}
			else
			{
				UINT32 MacLength = 0;
				
				// assigned all to 0, use MAC settings hardcoded
				for (MacLength = 0; MacLength < ETHER_ADDR_SIZE; MacLength++)
				{
					pEthernet->FecMacAddress[MacLength] = 0;
				}
				
				break;
			}
		}
		
		// Step 5: Map the hardware registers into virtual address
		MemPhysAddr = CSP_BASE_REG_PA_FEC;
		
		Status = NdisMRegisterIoPortRange( (PVOID *)&gpFECReg,
                                       MiniportAdapterHandle,
                                       MemPhysAddr,
                                       sizeof(CSP_FEC_REGS) );

									
		if((Status != NDIS_STATUS_SUCCESS) || !(gpFECReg))
		{
		 	DEBUGMSG(ZONE_ERROR,
		 		(TEXT("FECInitialize: Failed to alloc memory for mapping hardware registers\r\n")));
		 	break;
		}
		
		// Step 6: register for a shutdown function
		NdisMRegisterAdapterShutdownHandler(MiniportAdapterHandle, pEthernet, FECShutdown);
		pEthernet->CurrentState = NdisHardwareStatusInitializing;
		
		// Step 7: do the FEC hardware initialization
		result = FECEnetInit(pEthernet);
		
		if(result == TRUE)
		{
			pEthernet->CurrentState = NdisHardwareStatusReady;
		
			pEthernet->intLine = IRQ_FEC;
			
			// Step 8: if the hardware initialization is successful,
			// register the interrupt
			Status = NdisMRegisterInterrupt(
						(PNDIS_MINIPORT_INTERRUPT)&(pEthernet->interruptObj),
						MiniportAdapterHandle,
						pEthernet->intLine,
						pEthernet->intLine,
						TRUE,
						FALSE,
						NdisInterruptLatched);
						
			if (Status != NDIS_STATUS_SUCCESS)
			{
				DEBUGMSG(ZONE_INIT, 
					(TEXT("FECInitialize: NdisMRegisterInterrupt failed 0x%x\r\n"), Status));
					
				NdisWriteErrorLogEntry(
					MiniportAdapterHandle,
					NDIS_ERROR_CODE_INTERRUPT_CONNECT,
					0);
					
				break;
			}
			else
			{
				// enable interrupt
				FECEnableInterrupt((NDIS_HANDLE)pEthernet);
			}
		}
		else
		{
			Status = NDIS_STATUS_FAILURE;
		}
		
		// Step 9: now the hardware is initialized and interrupt is registered,
		// issue the auto-negotiation process

⌨️ 快捷键说明

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