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

📄 vbridge.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:

   VBridge.c

Abstract:

Notes:

   This file implements or manage the shared ethernet resources
   for EDBG and VMINI.

--*/

#include <windows.h>
#include "nkintr.h"
#include "kitlprot.h"


//
//	Useful defines..
//

#define PRINTMSG(cond, printf_exp)	((void)((cond)?(PRINTF printf_exp) : 0))

#define	PLUSPLUS(a, max)	\
	(((a+1)>=max) ? 0x00 : (a+1))

#define ETH_IS_BROADCAST(Address) 	\
	(((PUCHAR)(Address))[0] == ((UCHAR)0xff))

#define MAX_8023_PDU    1514


//
//	From ndis.h
//

#define ETH_COMPARE_NETWORK_ADDRESSES_EQ(_A,_B, _Result)        \
{                                                               \
    if ((*(ULONG UNALIGNED *)&(_A)[2] ==                        \
            *(ULONG UNALIGNED *)&(_B)[2]) &&                    \
         (*(USHORT UNALIGNED *)(_A) ==                          \
            *(USHORT UNALIGNED *)(_B)))                         \
    {                                                           \
        *(_Result) = 1;                                         \
    }                                                           \
    else                                                        \
    {                                                           \
        *(_Result) = 0;                                         \
    }                                                           \
}


//
//	Buffer manipulations..
//

#define		TX_BUFFERS_DWORD	0x4000 / sizeof(DWORD)	
#define		RX_BUFFERS_DWORD	0x4000 / sizeof(DWORD)
#define		HEADER_SIGNATURE	0x12345678

#define		FLAG_PRODUCED		0x00000001	//	This buffer is produced..
#define		FLAG_CONSUMED		0x00000002	//	This buffer is consumed..
#define		FLAG_SKIP_BUFFER	0x00000004	//	No data skip to next one.

typedef struct _PACKET_HEADER
{

#ifdef DEBUG
	DWORD	dwSignature;					//	Signature of header..
#endif

	DWORD	dwFlag;							//	Miscellaneous flags..
	UCHAR	*pucNextBuffer;					//	The next chunk..
	DWORD	dwCurrentSize;					//	Zero ? go to next chunk..

}	PACKET_HEADER, *PPACKET_HEADER;


PUCHAR		pucTxProducer;					//	Manipulated by User   Code.
PUCHAR		pucTxConsumer;					//	Manipulated by Kernel Code.
PUCHAR		pucRxProducer;					//	Manipulated by Kernel Code.
PUCHAR		pucRxConsumer;					//	Manipulated by User   Code.
PUCHAR		pucTxMax;						//	For convenience..
PUCHAR		pucTxMin;
PUCHAR		pucRxMax;						//	For convenience..
PUCHAR		pucRxMin;

ULONG		TxBuffers[TX_BUFFERS_DWORD];
ULONG		RxBuffers[RX_BUFFERS_DWORD];


DWORD	dwCurrentPacketFilter;				//	Current VMini filter mode..
UCHAR	EDBGMacAddress[6];					//	Address that VMini should use..
BOOL	bValidAddress			= FALSE;	//	Whether EDBGMacAddress is valid.
BOOL	bWarnNoMacDone			= FALSE;	//	One time warning to user.
HANDLE	hRxInterruptEvent		= NULL;
HANDLE	hPKDRxInterruptEvent	= NULL;
BOOL	g_bResetBuffer			= FALSE;	//	Set in IOCTL_VBRIDGE_WILD_CARD_RESET_BUFFER.


//
//	Forward decl..
//

extern void		
OEMWriteDebugByte(BYTE ucChar);

extern void		
SendVMiniPackets(void);



//
//	For debugging purposes..
//

static void OutputString(const unsigned char *s)
{
    while (*s) 
	{
		if (*s == '\n') 
            OEMWriteDebugByte('\r');
        
        OEMWriteDebugByte(*s++);
    }
}


static void pOutputByte(unsigned char c)
{ 
	OEMWriteDebugByte(c);
}


static void pOutputNumHex(unsigned long n, long depth)
{
    if (depth)    
        depth--;
    

    if ((n & ~0xf) || depth)
    {
        pOutputNumHex(n >> 4, depth);
        n &= 0xf;
    }

    if (n < 10)
    {
        pOutputByte((unsigned char)(n + '0'));
    }
    else
    {
        pOutputByte((unsigned char)(n - 10 + 'A'));
    }
}


static void pOutputNumDecimal(unsigned long n)
{
    if (n >= 10) 
	{
        pOutputNumDecimal(n / 10);
        n %= 10;
    }
    pOutputByte((unsigned char)(n + '0'));
}



////////////////////////////////////////////////////////////////////////////////
//	PRINTF()
//  Returns length of formatted string
//  Input:
//		Pointer to string to return formatted output.  
//		User must ensure that buffer is large enough.
//
//  const unsigned char * |   sz,... |
//  Format String:
//
//  @flag Format string | type
//  @flag u | unsigned
//  @flag d | int
//  @flag c | char
//  @flag s | string
//  @flag x | 4-bit hex number
//  @flag B | 8-bit hex number
//  @flag H | 16-bit hex number
//  @flag X | 32-bit hex number
//

void
PRINTF(    
	const	unsigned char *sz, 
	...
)
{
    unsigned char    c;
    va_list         vl;

    va_start(vl, sz);
    
    while (*sz) 
	{
		c = *sz++;
        switch (c) 
		{
            case (unsigned char)'%':
				c = *sz++;
				switch (c) 
				{
					case 'x':
						pOutputNumHex(va_arg(vl, unsigned long), 0);
						break;
					case 'B':
						pOutputNumHex(va_arg(vl, unsigned long), 2);
						break;
					case 'H':
						pOutputNumHex(va_arg(vl, unsigned long), 4);
						break;
					case 'X':
						pOutputNumHex(va_arg(vl, unsigned long), 8);
						break;
					case 'd': 
					{
						long    l;
						l = va_arg(vl, long);
						if (l < 0) 
						{
							pOutputByte('-');
							l = - l;
						}
						pOutputNumDecimal((unsigned long)l);
					}
						break;

					case 'u':
						pOutputNumDecimal(va_arg(vl, unsigned long));
						break;

					case 's':
						OutputString(va_arg(vl, char *));
						break;

					case '%':
						pOutputByte('%');
						break;

					case 'c':
						c = va_arg(vl, unsigned char);
						pOutputByte(c);
						break;

					default:
						pOutputByte(' ');
						break;
				}
				break;
			case '\n':
				pOutputByte('\r');
				// fall through
            
			default:
				pOutputByte(c);
        }
    }

    pOutputByte(0);   
    
    va_end(vl);    

}	//	PRINTF()



////////////////////////////////////////////////////////////////////////////////
//	Misc utility functions.
//

void VBridgeDisplayHex (BYTE data)
{    
    if (data < 0x10)
        PRINTMSG(1, ("0"));
    PRINTMSG (1, ("%x ", data));

}    // DisplayHex()


void VBridgeDumpMemory (PBYTE pSource, DWORD dwLength)
{
    int        i = 0;

    PRINTMSG (1, ("+---- MEM DUMP (%d bytes)----+\r\n", dwLength));
    PRINTMSG (1, ("0x%x: ", pSource));
    while (dwLength--)
    {    
        VBridgeDisplayHex (*pSource++);
        if (++i == 16)
        {
            i = 0;        
            PRINTMSG (1, ("\r\n0x%x: ", pSource));
        }        
    }
    
    PRINTMSG (1, ("\r\n\r\n"));

}    // DumpMemory()



////////////////////////////////////////////////////////////////////////////////
//	EthAddressCmp()
//
//	Routine Description:
//
//		Compares two MAC addresses and returns TRUE if they are the same.
//		Start from LSB as it will perform less comparison.
//
//	Arguments:	
//
//		AddressA	::	Address to be compared.
//		AddressB	::	Address to be compared.
//		usLength	::	Length of the address..
//
//	Return Value:
//
//		TRUE if compared, FALSE otherwise..
//

BOOL
EthAddressCmp (PBYTE AddressA, PBYTE AddressB, SHORT usLength)
{
	int i = 0;
	
	while (i < usLength)
	{		
		if (AddressA[i] != AddressB[i])
			return FALSE;
		i++;
	}
	return TRUE;

}	//	EthAddressCmp()



////////////////////////////////////////////////////////////////////////////////
//	ProduceBuffer()
//
//	Routine Description:
//
//		This function will give a chunck of buffer for the caller.
//
//	Arguments:	
//
//		bIsTx	::	Whether it is TX buffer or RX buffer.
//					For Tx case, it will be called by User code.
//					For Rx case, it will be called by Kernel code.
//
//		dwSize	::	Buffer size requested..
//
//	Return Value:
//
//		Null if no buffer available, otherwise pointer to buffer to be used.
//

PUCHAR
ProduceBuffer(BOOL	bIsTx, DWORD dwSize)
{
	PUCHAR			*ppucProducer;
	PUCHAR			*ppucBufferStart;
	PUCHAR			*ppucBufferEnd;
	PUCHAR			*ppucConsumer;	
	PACKET_HEADER	*pPacketHeader;
	DWORD			dwTotalSize;	
	DWORD			dwAddThis;

	//
	//	Our buffers are always DWORD align.. 
	//

	dwTotalSize = dwSize + sizeof(PACKET_HEADER);	
	dwAddThis   = dwTotalSize % 4;
	if (dwAddThis)
		dwTotalSize +=	(4 - dwAddThis);

	if (bIsTx)
	{
		ppucProducer	=	&pucTxProducer;
		ppucBufferStart	=	&pucTxMin;
		ppucBufferEnd	=	&pucTxMax;
		ppucConsumer	=	&pucTxConsumer;
	}
	else
	{
		ppucProducer	=	&pucRxProducer;
		ppucBufferStart	=	&pucRxMin;
		ppucBufferEnd	=	&pucRxMax;
		ppucConsumer	=	&pucRxConsumer;
	}


	//
	//	First stop is to check we won't overshoot consumer..
	//

	if ((*ppucConsumer > *ppucProducer) && 
		(*ppucProducer + dwTotalSize >= *ppucConsumer))
	{
		return NULL;
	}


	//
	//	Make sure we don't wrap..
	//	And after this requested buffer, we have at least 
	//	enough space for PACKET_HEADER at the end of this buffer for SKIP
	//	BUFFER..
	//

	if ((*ppucProducer + dwTotalSize) > (*ppucBufferEnd - sizeof(PACKET_HEADER)))
	{
		PRINTMSG (0,
			("Producer = [0x%x] : TotalSize = [%d] : BufferEnd[0x%x]\r\n",
			*ppucProducer,
			dwTotalSize,
			*ppucBufferEnd));
		

		//
		//	Nop, and if the consumer is not at the beginning of the 
		//	buffer, then it's safe for us to advance the producer there..
		//

		if (*ppucConsumer == *ppucBufferStart)
		{
			//
			//	Consumer is hogging at the beginning..
			//

			return NULL;
		}

		//
		//	Okay, consumer is not there, so it's safe to mark this as 
		//	SKIP buffer..
		//

		pPacketHeader = (PPACKET_HEADER) *ppucProducer;		

#ifdef DEBUG
		pPacketHeader->dwSignature   = HEADER_SIGNATURE;
#endif
		pPacketHeader->dwFlag		 = FLAG_SKIP_BUFFER;
		pPacketHeader->pucNextBuffer = *ppucBufferStart;


		//
		//	It's safe to move the producer pointer now..
		//

		PRINTMSG (0, ("SKIP produced [0x%x].\r\n",
			*ppucProducer));

		*ppucProducer = *ppucBufferStart;


		//
		//	Now make sure we can fit it without overshooting consumer..
		//

		if ((*ppucConsumer > *ppucProducer) && 
			(*ppucProducer + dwTotalSize >= *ppucConsumer))
		{
			//
			//	Too Bad.. not enough space..
			//

			PRINTMSG (0,
				("-- Producer = [0x%x] : TotalSize = [%d] : BufferEnd[0x%x]\r\n",
				*ppucProducer,
				dwTotalSize,
				*ppucBufferEnd));

			return NULL;
		}
		
	}


	//
	//	By now we are guarantee that the buffer will not wrap..	
	//	And we definitely have space..
	//	

	pPacketHeader   = (PPACKET_HEADER) *ppucProducer;

#ifdef DEBUG
		pPacketHeader->dwSignature   = HEADER_SIGNATURE;
#endif

	//
	//	Packet not ready until the caller calls ProduceBufferDone().
	//

	pPacketHeader->dwFlag	     = 0x00;	
	pPacketHeader->pucNextBuffer = *ppucProducer + dwTotalSize;
	pPacketHeader->dwCurrentSize = dwSize;


	//
	//	Okay, it's safe to move the producer pointer now..
	//	The owner of this buffer is on its own now, it will need to
	//	call ProduceBufferDone() to let the consumer know that it can now
	//	be consumed.   Failure to do so will block the flow!!!
	//

	*ppucProducer	= *ppucProducer + dwTotalSize;

	return ((PUCHAR)pPacketHeader + sizeof(PACKET_HEADER));
	

}	//	ProduceBuffer()	



////////////////////////////////////////////////////////////////////////////////
//	ProduceBufferDone()
//
//	Routine Description:
//
//		This function will mark the buffer to be ready for consumption.
//
//	Arguments:	
//
//		bIsTx		::	Whether it is TX buffer or RX buffer.
//		pucBuffer	::	Points to buffer obtained in ProduceBuffer()
//
//	Return Value:
//
//		None.
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -