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

📄 lan91c111_filter.c

📁 PXA255/270平台的 LAN91C111网卡驱动程序
💻 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 + -