📄 lan91c111_filter.c
字号:
/*
*
* Copyright (c) Standard MicroSystems Corporation. All Rights Reserved.
*
* LAN91C111 Driver for Windows CE .NET
*
* Revision History
*_______________________________________________________________________________
* Author Date Version Description
*_______________________________________________________________________________
* Pramod Bhardwaj 6/18/2002 0.1 Beta Release
* 7/15/2002 1.0 Release
* 1/22/2003 1.1 Removed some platform dependencies
* 3/27/2003 1.2 Used alloc interrupt
* TScho 2/15/2004 1.2.0 Performance changes (Beta)
* TScho 2/20/2004 1.2.1 Multi-packet indication (Beta)
* TScho 2/25/2004 1.2.2 Multicast fixed (Beta)
* TScho 2/26/2004 2.1 Release for CE 5.0
*_______________________________________________________________________________
*
*Description:
* Hardware Filters and OID Set/Query functions for the driver
*
*
*/
#include <Ndis.h>
#include "LAN91C111_Adapter.h"
#include "LAN91C111_Proto.h"
#ifdef NDIS50_MINIPORT
#pragma message( "-------------------- SMSC LAN91C111 NDIS 5.0 Miniport Driver V2.1 --------------------" )
#else
#pragma message( "-------------------- SMSC LAN91C111 NDIS 4.0 Miniport Driver V2.1 --------------------" )
#endif
static char _LAN91C111_Filter_C_Date_Code_[] = "082304";
//Activate according to current platform (if not defined - Big Endian is assumed)
#define ENDIAN_LITTLE
USHORT MakeHash_le (UCHAR *);
USHORT MakeHash_be (UCHAR *);
void SetHash (MINIPORT_ADAPTER *,USHORT);
NDIS_STATUS CopyInfo (UCHAR *, UCHAR *, UINT, UINT, UINT *, UINT *);
/*
Function Name : LAN91C111_MiniportSetInformation
Description :
Required function, by the NDIS. Called by the wrapper to
request changes in the state information for the hardware.
Parameters :
NDIS_HANDLE AdapterContext handle to context area
NDIS_OID Oid OID reference for the set operation
PVOID InformationBuffer buffer containing the ODI specific data
ULONG InformationBufferLength length of the information buffer
PULONG BytesRead function sets to the number of bytes
it read from the buffer at InformationBuffer
PULONG BytesNeeded function sets this to number of additional bytes
it needs to satisfy the request, in case buffer
length is not sufficient
Return Value :
NDIS_STATUS Status
*/
NDIS_STATUS LAN91C111_MiniportSetInformation (
NDIS_HANDLE MiniportAdapterContext,
NDIS_OID Oid,
PVOID InformationBuffer,
ULONG InformationBufferLength,
PULONG BytesRead,
PULONG BytesNeeded
)
{
MINIPORT_ADAPTER *Adapter = (MINIPORT_ADAPTER *) MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_OID *NdisOid = (NDIS_OID *) InformationBuffer;
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111:==> MiniPort Set Information OID=0x%.8x, "), Oid));
switch(Oid)
{
//Current packet filter enabled
case OID_GEN_CURRENT_PACKET_FILTER:
PrintDebugMsg(ZONE_INIT, (TEXT("OID_GEN_CURRENT_PACKET_FILTER (=0x%x)\r\n"), *NdisOid));
Status = ChangeFilter(Adapter, *NdisOid);
break;
//Current LookAhead size.
case OID_GEN_CURRENT_LOOKAHEAD:
PrintDebugMsg(ZONE_INIT, (TEXT("OID_GEN_CURRENT_LOOKAHEAD (=%d)\r\n"), *NdisOid));
if(*NdisOid > MAX_LOOKAHEAD_SIZE)
Status = NDIS_STATUS_FAILURE;
Adapter->LookAhead = *NdisOid;
*BytesRead = sizeof(NDIS_OID);
break;
//Reset the list of all multicast addresses enabled.
case OID_802_3_MULTICAST_LIST:
PrintDebugMsg(ZONE_MC, (TEXT("OID_802_3_MULTICAST_LIST (Entries=0x%x)\r\n"), InformationBufferLength / ETH_LENGTH_OF_ADDRESS));
if((InformationBufferLength % ETH_LENGTH_OF_ADDRESS) != 0)
{
Status = NDIS_STATUS_INVALID_LENGTH;
// We don't know how big it is, assume one entry.
*BytesNeeded = InformationBufferLength +
(ETH_LENGTH_OF_ADDRESS -
(InformationBufferLength % ETH_LENGTH_OF_ADDRESS));
*BytesRead = 0;
break;
}
Status = ChangeMulticastAddresses(Adapter,
(UCHAR *) NdisOid,
(UINT) (InformationBufferLength / ETH_LENGTH_OF_ADDRESS));
NdisMoveMemory(Adapter->MulticastTable.MulticastTableEntry,
InformationBuffer,
InformationBufferLength);
Adapter->MulticastTable.MulticastTableEntryCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
*BytesRead = InformationBufferLength;
break;
//Unknown or unsupported Object Identifier.
default:
PrintDebugMsg(ZONE_INIT, (TEXT("Unknown or Unsupported OID Set Request!\r\n")));
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111:<== MiniPort Set Information\r\n")));
return (Status);
}
/*
Function Name : ChangeFilter
Description : Called by the filter library when a significant change has occured to
the filter library. This function updates the driver and the hardware
filters.
Parameters : MINIPORT_ADAPTER *Adapter //Pointer to the adapter structure
NDIS_OID NewFilter //Filter OID
Return Value :
NDIS_STATUS Status
*/
NDIS_STATUS ChangeFilter (MINIPORT_ADAPTER *Adapter, NDIS_OID NewFilter)
{
USHORT NewRCR = 0;
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111==> MiniPort Change Filter\r\n")));
//Check for invalid type.
if (NewFilter & ~((
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_PROMISCUOUS |
NDIS_PACKET_TYPE_ALL_MULTICAST
)))
return (NDIS_STATUS_NOT_SUPPORTED);
//Rcv all directed packets
if (NewFilter & NDIS_PACKET_TYPE_DIRECTED);
//Rcv only the multicast with addresses in the list, by clearing the ALMUL in the RCR
if (NewFilter & NDIS_PACKET_TYPE_MULTICAST);
NewRCR = 0;
if (NewFilter & NDIS_PACKET_TYPE_BROADCAST)
Adapter->RCVBroadcast = TRUE;
else
Adapter->RCVBroadcast = FALSE;
if (NewFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
{
NewRCR = RCR_ALL_MUL;
Adapter->RCVAllMulticast = TRUE;
}
else
Adapter->RCVAllMulticast = FALSE;
if (NewFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
{
NewRCR = RCR_PRMS;
Adapter->PromiscuousMode = TRUE;
}
else
Adapter->PromiscuousMode = FALSE;
NewRCR |= RCR_STRP_CRC;
NewRCR |= RCR_RX_EN;
Adapter->RCR = NewRCR;
//Now load the new RCR value
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, 0);
NdisRawWritePortUshort(Adapter->IOBase + BANK0_RCR, NewRCR);
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111<== MiniPort Change Filter\r\n")));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS ChangeMulticastAddresses (MINIPORT_ADAPTER *Adapter,
UCHAR *AddressList,
UINT AddressCount)
{
USHORT HashBits;
USHORT Count;
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111==> MiniPort Change Address\r\n")));
//Clear the current list.
for (Count = 0; Count < 8; Count++)
Adapter->HashTable[Count] = 0;
//Generate Hash codes for new addresses
while (AddressCount--)
{
#ifdef ENDIAN_LITTLE
HashBits = MakeHash_le(AddressList);
#else
HashBits = MakeHash_be(AddressList);
#endif
SetHash(Adapter, HashBits);
AddressList += ETH_LENGTH_OF_ADDRESS;
};
//Output the new list.
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, (USHORT) 3);
for (Count = 0; Count < 8; Count += 2)
NdisRawWritePortUshort(Adapter->IOBase + BANK3_MT01 + Count, *(USHORT*)(&Adapter->HashTable[Count]));
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111<== MiniPort Change Address\r\n")));
return (NDIS_STATUS_SUCCESS);
}
/*
* Ethernet CRC32 polynomials (big- and little-endian verions).
*/
#define ETHER_CRC_POLY_BE 0xEDB88320
#define ETHER_CRC_POLY_LE 0x04C11DB6
USHORT MakeHash_le (UCHAR *Address)
{
ULONG crc;
USHORT carry;
UCHAR c;
USHORT i, j;
crc = 0xFFFFFFFF; // initial value
for (i = 0; i < 6; i++)
{
c = *Address++;
for (j = 0; j < 8; j++)
{
carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01);
crc <<= 1;
c >>= 1;
if (carry)
crc = (crc ^ ETHER_CRC_POLY_LE) | carry;
}
}
//High order 6 bits are hash value.
return ((USHORT) (crc >> 26));
}
USHORT MakeHash_be (UCHAR *Address)
{
ULONG crc;
USHORT carry;
UCHAR c;
USHORT i, j;
crc = 0xFFFFFFFF; // initial value
for (i = 0; i < 6; i++)
{
c = *Address++;
for (j = 0; j < 8; j++)
{
carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
crc >>= 1;
c >>= 1;
if (carry)
crc = (crc ^ ETHER_CRC_POLY_BE);
}
}
//High order 6 bits are hash value.
return ((USHORT) (crc >> 26));
}
void SetHash(MINIPORT_ADAPTER *Adapter,
USHORT HashValue)
{
PUCHAR WhichByte; // Pick byte out of array
UCHAR WhichBit; // Pick out bit
WhichByte = (UCHAR *) ((&(Adapter->HashTable[0])) + (HashValue >> 3));
WhichBit = (UCHAR) (1 << (HashValue & 7));
*WhichByte |= WhichBit;
}
NDIS_STATUS CopyInfo(UCHAR *InformationBuffer,
UCHAR *Source,
UINT BufferLength,
UINT BytesToMove,
UINT *BytesWritten,
UINT *BytesNeeded)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
if(BufferLength < BytesToMove)
{
PrintDebugMsg(ZONE_INIT, (TEXT("Query Buffer is too small!\r\n")));
*BytesNeeded = BytesToMove;
BytesToMove = BufferLength;
Status = NDIS_STATUS_INVALID_LENGTH;
}
NdisMoveMemory(InformationBuffer,Source,BytesToMove);
*BytesWritten = BytesToMove;
return(Status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -