📄 fec.c
字号:
// Returns NDIS_STATUS_PENDING if success
// Returns NDIS_STATUS_FAILURE if bad frame encountered
//
//------------------------------------------------------------------------------
NDIS_STATUS FECSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT SendFlags
)
{
UINT PacketLength;
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECSend\r\n")));
NdisQueryPacket( Packet,NULL,NULL,NULL,&PacketLength);
if( (PacketLength > PKT_MAXBUF_SIZE) ||(PacketLength < ETHER_HDR_SIZE))
{
pEthernet->TxdStatus.FramesXmitBad++;
return NDIS_STATUS_FAILURE;
}
// Put the packet on the send queue
EnterCriticalSection(&gFECBufCs);
if(pEthernet->HeadPacket == NULL)
{
pEthernet->HeadPacket = Packet;
}
else
{
RESERVED(pEthernet->TailPacket)->Next = Packet;
}
RESERVED(Packet)->Next = NULL;
pEthernet->TailPacket = Packet;
LeaveCriticalSection (&gFECBufCs);
if(pEthernet->TransmitInProgress == FALSE)
{
pEthernet->TransmitInProgress = TRUE;
FECStartXmit(pEthernet);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECSend\r\n")));
return NDIS_STATUS_PENDING;
}
//------------------------------------------------------------------------------
//
// Function: FECTransferData
//
// This function copies the content of the received packet to a given
// protocol-allocated packet.
//
// Parameters:
// Packet
// [out] Point to a packet descriptor with chained buffers into which
// FECTransferData should copy the received data
//
// BytesTransferred
// [out] Points to a variable that FECTransferData sets to the number
// of bytes it copied into the packet
//
// MiniportAdapterContext
// [in] Specifies the handle to a miniport-allocated context area in
// which the driver maintains FEC adapter state, set up by
// FECInitialize
//
// MiniportReceiveContext
// [in] Specifies the context handle previously passed to
// NdisMEthIndicateReceive. The miniport can examine this value
// to determine which recieve to copy
//
// ByteOffset
// [in] Specifies the offset within the received packet at which
// FECTransferData should begin the copy. If the entire packet
// is to be copied, should be set to zero.
//
// BytesToTransfer
// [in] Specifies how many bytes to copy
//
// Return Value:
// Returns NDIS_STATUS_SUCCESS if success
// Return NDIS_STATUS_FAILURE if not
//
//------------------------------------------------------------------------------
NDIS_STATUS
FECTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
{
PNDIS_BUFFER pCurrentBuffer;
UINT BufferLength;
PUCHAR pBufferSource;
PUCHAR pBufferStart;
UINT BytesWanted, BytesCopied, BytesLeft;
ULONG PacketSize;
// The adapter to transfer from
pFEC_t pEthernet = ((pFEC_t)(MiniportReceiveContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECTransferData\r\n")));
// Add the packet header onto the offset
ByteOffset += ETHER_HDR_SIZE;
pBufferSource = pEthernet->ReceiveBuffer + ByteOffset;
PacketSize = pEthernet->ReceivePacketSize;
if((BytesToTransfer == 0) || (ByteOffset >= PacketSize))
{
*BytesTransferred = 0;
return NDIS_STATUS_FAILURE;
}
NdisQueryPacket( Packet, NULL, NULL, &pCurrentBuffer, NULL );
NdisQueryBuffer( pCurrentBuffer, &pBufferStart, &BufferLength );
*BytesTransferred = 0;
BytesWanted = 0;
BytesCopied = 0;
BytesLeft = BytesToTransfer;
do {
if( !BufferLength )
{
NdisGetNextBuffer( pCurrentBuffer, &pCurrentBuffer );
NdisQueryBuffer( pCurrentBuffer, &pBufferStart, &BufferLength );
}
if( BufferLength > BytesLeft )
{
BytesCopied += BytesLeft;
BytesWanted = BytesLeft;
}
else
{
BytesCopied += BufferLength;
BytesWanted = BufferLength;
BufferLength = 0;
}
NdisMoveMemory( pBufferStart, pBufferSource, BytesWanted );
pBufferStart += BytesWanted;
pBufferSource += BytesWanted;
BytesLeft -= BytesWanted;
} while(BytesCopied < BytesToTransfer);
*BytesTransferred = BytesCopied;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECTransferData\r\n")));
return NDIS_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: FECSetInformation
//
// This function is a required function that allows NDIS to request changes in
// the state information that the FEC driver maintains for particular object
// identifiers, such as changes in multicast addresses.
//
// Parameters:
// MiniportAdapterContext
// [in] Specifies the handle to a FEC driver allocated context area
// in which the FEC driver maintains FEC adapter state, set up
// by FECInitialize function.
//
// Oid
// [in] Specifies the system-defined OID_XXX code designating the
// set operation the FEC driver should carry out.
//
// InformationBuffer
// [in] Points to a buffer containing the OID-specific data used by
// FECSetInformation for the set.
//
// InformationBufferLength
// [in] Specifies the number of bytes at InformationBuffer.
//
// BytesRead
// [out] Points to a variable that FECSetInformation sets to the number
// of bytes it read from the buffer at InformationBuffer.
//
// BytesNeeded
// [out] Points to a variable that FECSetInformation sets to the number
// of additional bytes it needs to satisfy the request if
// InformationBufferLength is less than Oid requires.
//
// Return Value:
// Return NDIS_STATUS_SUCCESS if the required Oid is set successfully.
// Return NDIS_STATUS_INVALID_LENGTH if the InformationBufferLength does not
// match the length required by the given Oid.
//
//---------------------------------------------------------------------------------
NDIS_STATUS FECSetInformation (
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
{
UINT BytesLeft = InformationBufferLength;
PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
// Variables for a particular request
UINT OidLength;
// Variables for holding the new values to be used
ULONG LookAhead;
ULONG Filter;
// Status of the operation
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECSetInformation\r\n")));
// Get Oid and Length of request
OidLength = BytesLeft;
switch (Oid)
{
case OID_802_3_MULTICAST_LIST:
// Verify length
if ((OidLength % ETHER_ADDR_SIZE) != 0)
{
StatusToReturn = NDIS_STATUS_INVALID_DATA;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
else
{
// Ensure that the multi cast list is not full yet
if(OidLength <= (MCAST_LIST_SIZE * ETHER_ADDR_SIZE))
{
// Get the multicast address and update hash table
NdisMoveMemory(pEthernet->McastList, InfoBuffer, OidLength);
*BytesRead = OidLength;
pEthernet->NumMulticastAddressesInUse = OidLength / ETHER_ADDR_SIZE;
// clear all the content in hardware Hash Table
ClearAllMultiCast();
// Add the hash table value according to the multicast address
for(LookAhead=0; LookAhead < pEthernet->NumMulticastAddressesInUse; LookAhead++)
{
AddMultiCast(&(pEthernet->McastList[LookAhead][0]));
}
}
else
{
*BytesRead = 0;
StatusToReturn = NDIS_STATUS_MULTICAST_FULL;
}
}
break;
case OID_GEN_CURRENT_PACKET_FILTER:
// check for length
if( OidLength != 4 )
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
NdisMoveMemory((PUCHAR)&Filter, (PUCHAR)InfoBuffer, 4);
if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
NDIS_PACKET_TYPE_SMT |
NDIS_PACKET_TYPE_MAC_FRAME |
NDIS_PACKET_TYPE_FUNCTIONAL |
NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
NDIS_PACKET_TYPE_GROUP |
NDIS_PACKET_TYPE_ALL_MULTICAST
))
{
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
*BytesRead = 4;
*BytesNeeded = 0;
}
else
{
pEthernet->PacketFilter = Filter;
if(Filter & NDIS_PACKET_TYPE_MULTICAST )
{
// clear all the content in hardware Hash Table
ClearAllMultiCast();
// Add the hash table value according to the multicast address
for(LookAhead=0; LookAhead < pEthernet->NumMulticastAddressesInUse; LookAhead++)
{
AddMultiCast(&(pEthernet->McastList[LookAhead][0]));
}
}
// TODO: how to set the FEC hardware filter? NO IDEA
StatusToReturn = NDIS_STATUS_SUCCESS;
}
break;
case OID_GEN_CURRENT_LOOKAHEAD:
// check for length
if( OidLength != 4 )
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
// Stores the new lookahead value
NdisMoveMemory(&LookAhead, InfoBuffer, 4);
if( LookAhead <= (PKT_MAXBUF_SIZE - ETHER_HDR_SIZE - PKT_CRC_SIZE) )
{
pEthernet->CurrentLookAhead= LookAhead;
}
else
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
}
break;
case OID_GEN_PROTOCOL_OPTIONS:
break;
default:
*BytesRead = 0;
*BytesNeeded = 0;
StatusToReturn = NDIS_STATUS_INVALID_OID;
break;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECSetInformation\r\n")));
return (StatusToReturn);
}
//------------------------------------------------------------------------------
//
// Function: FECShutdown
//
// Restore the FEC adapter to its initial state when the system is shut down,
// whether by the user or because an unrecoverable system error occurred.
//
// Parameters:
// ShutdownContext
// [in] Points to a context area supplied when the FECInitialize
// function calls NdisMRegisterAdapterShutdownHandler.
//
// Return Value:
// None.
//
//------------------------------------------------------------------------------
void FECShutdown(
IN PVOID ShutdownContext
)
{
pFEC_t pEthernet = ((pFEC_t)(ShutdownContext));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECShutdown\r\n")));
pEthernet->CurrentState = NdisHardwareStatusNotReady;
DeleteCriticalSection (&gFECRegCs);
DeleteCriticalSection (&gFECBufCs);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECShutdown\r\n")));
return;
}
//------------------------------------------------------------------------------
//
// Function: FECCheckForHang
//
// This function reports the link status of the FEC network adapter. Bu default,
// the NDIS library calls this function approximately every two seconds.
//
// Parameters:
// MiniportAdapterContext
// [in] Specifies the handle to a FEC driver allocated context area
// in which the FEC driver maintains FEC adapter state, set up
// by FECInitialize function.
//
// Return Values:
// return TRUE if this function detects that the network adapter is not
// operating correctly, otherwise FALSE.
//
//------------------------------------------------------------------------------
BOOLEAN FECCheckForHang(IN NDIS_HANDLE MiniportAdapterContext)
{
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterContext));
NDIS_MEDIA_STATE OldMediaState = pEthernet->MediaState;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECCheckForHang\r\n")));
if(pEthernet->MediaStateChecking == TRUE)
{
// Media state is checking by the MII interrupt handler now,
// just return FALSE
return FALSE;
}
else
{
// send the cmd to the external PHY to get the link status
pEthernet->MediaStateChecking = TRUE;
FECGetLinkStatus(MiniportAdapterContext);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECCheckForHang\r\n")));
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -