📄 fec.c
字号:
//------------------------------------------------------------------------------
//
// 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 + -