📄 ndisoid.c
字号:
/* ---------------------------------------------------------------------------
Copyright (c) 2003-2006 Micrel, Inc. All rights reserved.
---------------------------------------------------------------------------
NdisOid.c - NDIS driver OID query functions.
Author Date Description
THa 12/01/03 Created file.
THa 06/27/05 Updated for version 0.1.5.
THa 02/23/06 Updated for WinCE 5.0.
THa 04/13/06 Add EEPROM access support.
THa 06/02/06 Report statistics from MIB counters.
THa 07/27/06 Version 1.4 supports NDIS 5.
---------------------------------------------------------------------------
*/
#include "target.h"
#include "NdisDevice.h"
#include "NdisOid.h"
/* -------------------------------------------------------------------------- */
#define OID_DEVICE_MODE 0xff0100cc
// List of supported OID for this driver
NDIS_OID SupportedOids[] =
{
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
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_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_DRIVER_VERSION,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_MAC_OPTIONS,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_MAXIMUM_SEND_PACKETS,
OID_GEN_VENDOR_DRIVER_VERSION,
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MAXIMUM_LIST_SIZE,
OID_802_3_MULTICAST_LIST,
OID_GEN_XMIT_OK,
OID_GEN_RCV_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
OID_GEN_DIRECTED_FRAMES_XMIT,
OID_GEN_MULTICAST_FRAMES_XMIT,
OID_GEN_BROADCAST_FRAMES_XMIT,
OID_GEN_DIRECTED_FRAMES_RCV,
OID_GEN_MULTICAST_FRAMES_RCV,
OID_GEN_BROADCAST_FRAMES_RCV,
OID_GEN_RCV_CRC_ERROR,
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS,
OID_802_3_XMIT_DEFERRED,
OID_802_3_XMIT_MAX_COLLISIONS,
OID_802_3_XMIT_LATE_COLLISIONS,
#if 0
OID_GEN_PHYSICAL_MEDIUM,
#endif
#if (NDISVER >= 50)
OID_PNP_CAPABILITIES,
OID_PNP_SET_POWER,
OID_PNP_QUERY_POWER,
OID_PNP_ADD_WAKE_UP_PATTERN,
OID_PNP_REMOVE_WAKE_UP_PATTERN,
OID_PNP_ENABLE_WAKE_UP,
OID_PNP_WAKE_UP_OK,
OID_PNP_WAKE_UP_ERROR,
#endif
};
/* -------------------------------------------------------------------------- */
static
NDIS_STATUS QueryTaskOffload (
IN PNDIS_ADAPTER pAdapter,
IN ULONG ulBufferLength,
OUT PNDIS_TASK_OFFLOAD_HEADER pOffLoadHeader,
OUT PULONG pulBytesNeeded,
OUT PULONG pulBytesWritten )
{
NDIS_TASK_OFFLOAD *pTaskOffLoad;
NDIS_TASK_TCP_IP_CHECKSUM *pCheckSum;
UINT uiMoveBytes;
uiMoveBytes = sizeof( NDIS_TASK_OFFLOAD_HEADER ) +
sizeof( NDIS_TASK_OFFLOAD ) +
sizeof( NDIS_TASK_TCP_IP_CHECKSUM );
if ( ulBufferLength < uiMoveBytes )
{
*pulBytesNeeded = uiMoveBytes;
return( NDIS_STATUS_INVALID_LENGTH );
}
// validatation, according to latest MS's DDK document, it should return NDIS_STATUS_NOT_SUPPORTED
// if parameters are not supported by the driver
if ( NDIS_TASK_OFFLOAD_VERSION != pOffLoadHeader->Version ||
sizeof( NDIS_TASK_OFFLOAD_HEADER ) != pOffLoadHeader->Size ||
IEEE_802_3_Encapsulation !=
pOffLoadHeader->EncapsulationFormat.Encapsulation )
{
return( NDIS_STATUS_NOT_SUPPORTED );
}
// tell upper edge protocol driver that we support OFFLOAD task!
pOffLoadHeader->OffsetFirstTask = sizeof( NDIS_TASK_OFFLOAD_HEADER );
pOffLoadHeader++;
pTaskOffLoad = ( NDIS_TASK_OFFLOAD* ) pOffLoadHeader;
pTaskOffLoad->Version = NDIS_TASK_OFFLOAD_VERSION;
pTaskOffLoad->Size = sizeof( NDIS_TASK_OFFLOAD );
pTaskOffLoad->Task = TcpIpChecksumNdisTask;
// currently supports only one TASK_OFFLOAD
pTaskOffLoad->OffsetNextTask = 0;
pTaskOffLoad->TaskBufferLength = sizeof( NDIS_TASK_TCP_IP_CHECKSUM );
// fill task buffer
pCheckSum = ( NDIS_TASK_TCP_IP_CHECKSUM* ) pTaskOffLoad->TaskBuffer;
if ( pAdapter->m_ulTxChecksum )
{
// Need to verify IpOptionsSupported and TcpOptionsSupported support, user select options?
pCheckSum->V4Transmit.IpOptionsSupported = FALSE;
pCheckSum->V4Transmit.TcpOptionsSupported = FALSE;
pCheckSum->V4Transmit.TcpChecksum = TRUE;
pCheckSum->V4Transmit.UdpChecksum = FALSE;
pCheckSum->V4Transmit.IpChecksum = TRUE;
}
else
{
pCheckSum->V4Transmit.IpOptionsSupported = FALSE;
pCheckSum->V4Transmit.TcpOptionsSupported = FALSE;
pCheckSum->V4Transmit.TcpChecksum = FALSE;
pCheckSum->V4Transmit.UdpChecksum = FALSE;
pCheckSum->V4Transmit.IpChecksum = FALSE;
}
if ( pAdapter )
{
pCheckSum->V4Receive.IpOptionsSupported = FALSE;
pCheckSum->V4Receive.TcpOptionsSupported = FALSE;
pCheckSum->V4Receive.TcpChecksum = TRUE;
pCheckSum->V4Receive.UdpChecksum = FALSE;
pCheckSum->V4Receive.IpChecksum = TRUE;
}
else
{
pCheckSum->V4Receive.IpOptionsSupported = FALSE;
pCheckSum->V4Receive.TcpOptionsSupported = FALSE;
pCheckSum->V4Receive.TcpChecksum = FALSE;
pCheckSum->V4Receive.UdpChecksum = FALSE;
pCheckSum->V4Receive.IpChecksum = FALSE;
}
// we don't support V6 currently
pCheckSum->V6Transmit.IpOptionsSupported = FALSE;
pCheckSum->V6Transmit.TcpOptionsSupported = FALSE;
pCheckSum->V6Transmit.TcpChecksum = FALSE;
pCheckSum->V6Transmit.UdpChecksum = FALSE;
pCheckSum->V6Receive.IpOptionsSupported = FALSE;
pCheckSum->V6Receive.TcpOptionsSupported = FALSE;
pCheckSum->V6Receive.TcpChecksum = FALSE;
pCheckSum->V6Receive.UdpChecksum = FALSE;
*pulBytesWritten += uiMoveBytes;
#if DBG
DBG_PRINT( "query offload: %u"NEWLINE, *pulBytesWritten );
#endif
return( NDIS_STATUS_SUCCESS );
} /* QueryTaskOffload */
static
NDIS_STATUS SetTaskOffload (
IN PNDIS_ADAPTER pAdapter,
IN PNDIS_TASK_OFFLOAD_HEADER pOffLoadHeader,
OUT PULONG pulBytesRead )
{
NDIS_TASK_OFFLOAD *pTaskOffLoad;
NDIS_TASK_TCP_IP_CHECKSUM *pCheckSum;
BOOLEAN bFound;
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
// validatation again?
if ( sizeof( NDIS_TASK_OFFLOAD_HEADER ) != pOffLoadHeader->Size ||
NDIS_TASK_OFFLOAD_VERSION != pOffLoadHeader->Version ||
IEEE_802_3_Encapsulation !=
pOffLoadHeader->EncapsulationFormat.Encapsulation )
{
return( NDIS_STATUS_NOT_SUPPORTED );
}
*pulBytesRead += sizeof( NDIS_TASK_OFFLOAD_HEADER );
// if disable NIC's all offload caps
if ( 0 == pOffLoadHeader->OffsetFirstTask )
{
if ( pAdapter->m_ulTxChecksum )
{
// We can't modify the TX mode register directly if it is running,
// so call a newly created (in reset.c) function instead
pAdapter->m_ulTxChecksum &= ~(
TASK_OFFLOAD_IP_CHECKSUM |
TASK_OFFLOAD_TCP_CHECKSUM |
TASK_OFFLOAD_UDP_CHECKSUM );
}
if ( pAdapter->m_ulRxChecksum )
{
pAdapter->m_ulRxChecksum &= ~(
TASK_OFFLOAD_IP_CHECKSUM |
TASK_OFFLOAD_TCP_CHECKSUM |
TASK_OFFLOAD_UDP_CHECKSUM );
}
return NdisStatus;
}
/* Look through task chain to see whether suitable task(s) were set by the
upper edge driver and take the last one to set.
*/
pTaskOffLoad = ( NDIS_TASK_OFFLOAD* )(( PUCHAR ) pOffLoadHeader +
pOffLoadHeader->OffsetFirstTask );
bFound = FALSE;
while ( pTaskOffLoad )
{
*pulBytesRead += sizeof( NDIS_TASK_OFFLOAD );
/* Check to see whether it is the checksum task we support. */
if ( TcpIpChecksumNdisTask == pTaskOffLoad->Task )
{
pCheckSum = ( NDIS_TASK_TCP_IP_CHECKSUM* )
pTaskOffLoad->TaskBuffer;
*pulBytesRead += sizeof( NDIS_TASK_TCP_IP_CHECKSUM );
/* We need to detect to see whether unsupported settings are passed
from upper edge before following the instruction.
*/
if ( pCheckSum->V4Transmit.TcpOptionsSupported ||
pCheckSum->V4Transmit.IpOptionsSupported )
{
pCheckSum->V4Transmit.TcpOptionsSupported = FALSE;
pCheckSum->V4Transmit.IpOptionsSupported = FALSE;
return NDIS_STATUS_NOT_SUPPORTED;
}
if ( pCheckSum->V4Receive.TcpOptionsSupported ||
pCheckSum->V4Receive.IpOptionsSupported )
{
pCheckSum->V4Receive.TcpOptionsSupported = FALSE;
pCheckSum->V4Receive.IpOptionsSupported = FALSE;
return NDIS_STATUS_NOT_SUPPORTED;
}
bFound = TRUE;
if ( pAdapter->m_ulTxChecksum )
{
if ( pCheckSum->V4Transmit.TcpChecksum )
pAdapter->m_ulTxChecksum |= TASK_OFFLOAD_TCP_CHECKSUM;
if ( pCheckSum->V4Transmit.UdpChecksum )
pAdapter->m_ulTxChecksum |= TASK_OFFLOAD_UDP_CHECKSUM;
if ( pCheckSum->V4Transmit.IpChecksum )
pAdapter->m_ulTxChecksum |= TASK_OFFLOAD_IP_CHECKSUM;
}
if ( pAdapter->m_ulRxChecksum )
{
if ( pCheckSum->V4Receive.TcpChecksum )
pAdapter->m_ulRxChecksum |= TASK_OFFLOAD_TCP_CHECKSUM;
if ( pCheckSum->V4Receive.UdpChecksum )
pAdapter->m_ulRxChecksum |= TASK_OFFLOAD_UDP_CHECKSUM;
if ( pCheckSum->V4Receive.IpChecksum )
pAdapter->m_ulRxChecksum |= TASK_OFFLOAD_IP_CHECKSUM;
}
}
/* To next offload task if any. */
if ( 0 == pTaskOffLoad->OffsetNextTask )
break;
pTaskOffLoad = ( NDIS_TASK_OFFLOAD* )(( PUCHAR ) pTaskOffLoad +
pTaskOffLoad->OffsetNextTask );
}
#if DBG
DBG_PRINT( "checksum offload: %x %x; %u"NEWLINE, pAdapter->m_ulRxChecksum,
pAdapter->m_ulTxChecksum, *pulBytesRead );
#endif
return( FALSE == bFound ? NDIS_STATUS_NOT_SUPPORTED : NdisStatus );
} /* SetTaskOffload */
#if (NDISVER >= 50) || defined( UNDER_CE )
static
NDIS_STATUS AddWakeUpPattern (
IN PNDIS_ADAPTER pAdapter,
IN PNDIS_PM_PACKET_PATTERN pPattern,
OUT PULONG pulBytesRead )
{
NDIS_STATUS NdisStatus;
PWAKE_UP_PACKET pWakeUpPacket;
if ( pAdapter->m_cnWakeUpPacket < MAX_WAKE_UP_PACKET &&
pPattern->MaskSize <= MAX_PATTERN_LENGTH / 8 &&
pPattern->PatternSize <= MAX_PATTERN_LENGTH )
{
/* Move the packet pattern separately in case they are not
continuous.
*/
pWakeUpPacket = &pAdapter->WakeUpPacket[
pAdapter->m_cnWakeUpPacket ];
pAdapter->m_cnWakeUpPacket++;
/* Copy the NDIS_PM_PACKET_PATTERN. */
pWakeUpPacket->NdisPacketPattern = *pPattern;
pWakeUpPacket->NdisPacketPattern.PatternOffset =
sizeof( NDIS_PM_PACKET_PATTERN ) + pPattern->MaskSize;
*pulBytesRead += sizeof( NDIS_PM_PACKET_PATTERN );
/* Copy the MASK. */
NdisMoveMemory(
&pWakeUpPacket->MaskAndPattern[ 0 ], ( pPattern + 1 ),
pPattern->MaskSize );
*pulBytesRead += pPattern->MaskSize;
/* Copy the PATTERN. */
NdisMoveMemory(
&pWakeUpPacket->MaskAndPattern[ pPattern->MaskSize ],
( PUCHAR ) pPattern + pPattern->PatternOffset,
pPattern->PatternSize );
*pulBytesRead += pPattern->PatternSize;
#if DBG
{
UINT i;
for ( i = 0; i < pPattern->MaskSize; i++ )
DBG_PRINT( "%02X ", pWakeUpPacket->MaskAndPattern[ i ]);
DBG_PRINT( NEWLINE );
for ( ; i < pPattern->MaskSize + pPattern->PatternSize; i++ )
DBG_PRINT( "%02X ", pWakeUpPacket->MaskAndPattern[ i ]);
DBG_PRINT( NEWLINE );
}
DBG_PRINT( "Added: %u"NEWLINE, *pulBytesRead );
#endif
#if 0
SetWakeupRegs(pAdapter, pAdapter->nWakeUpPacketCount - 1);
#endif
NdisStatus = NDIS_STATUS_SUCCESS;
}
else
{
*pulBytesRead = 0;
NdisStatus = NDIS_STATUS_RESOURCES;
}
return NdisStatus;
} /* AddWakeUpPattern */
static
NDIS_STATUS RemoveWakeUpPattern (
IN PNDIS_ADAPTER pAdapter,
IN PNDIS_PM_PACKET_PATTERN pPattern,
OUT PULONG pulBytesRead )
{
NDIS_STATUS NdisStatus;
PWAKE_UP_PACKET pWakeUpPacket;
UINT nCount;
int nIndex;
PUCHAR pSource;
PUCHAR pTarget;
for ( nIndex = 0; nIndex < pAdapter->m_cnWakeUpPacket; nIndex++ )
{
pWakeUpPacket = &pAdapter->WakeUpPacket[ nIndex ];
if ( pPattern->MaskSize == pWakeUpPacket->NdisPacketPattern.MaskSize
&& pPattern->PatternSize ==
pWakeUpPacket->NdisPacketPattern.PatternSize )
{
/* Compare the mask. */
for ( nCount = 0,
pSource = ( PUCHAR ) pPattern +
sizeof( NDIS_PM_PACKET_PATTERN ),
pTarget = pWakeUpPacket->MaskAndPattern;
nCount < pWakeUpPacket->NdisPacketPattern.MaskSize;
nCount++ )
if ( pSource[ nCount ] != pTarget[ nCount ] )
break;
if ( nCount < pWakeUpPacket->NdisPacketPattern.MaskSize )
continue;
/* Compare the pattern. */
for ( nCount = 0,
pSource = ( PUCHAR ) pPattern + pPattern->PatternOffset,
pTarget = &pWakeUpPacket->MaskAndPattern[
pPattern->MaskSize ];
nCount < pWakeUpPacket->NdisPacketPattern.PatternSize;
nCount++ )
if ( pSource[ nCount ] != pTarget[ nCount ] )
break;
if ( nCount == pWakeUpPacket->NdisPacketPattern.PatternSize )
break;
}
}
if ( nIndex < pAdapter->m_cnWakeUpPacket )
{
for ( ; nIndex < pAdapter->m_cnWakeUpPacket; nIndex++ )
pAdapter->WakeUpPacket[ nIndex ] =
pAdapter->WakeUpPacket[ nIndex + 1 ];
pAdapter->m_cnWakeUpPacket--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -