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

📄 vbridge.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
void
ProduceBufferDone(BOOL	bIsTx, PUCHAR pucBuffer)
{
	PACKET_HEADER	*pPacketHeader;

	pPacketHeader = (PPACKET_HEADER)(pucBuffer - sizeof(PACKET_HEADER));

	ASSERT(pPacketHeader->dwSignature == HEADER_SIGNATURE);

	//
	//	Off it goes..
	//

	pPacketHeader->dwFlag = FLAG_PRODUCED;

}	//	ProduceBufferDone()	



////////////////////////////////////////////////////////////////////////////////
//	ConsumeBuffer()
//
//	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 Kernel code.
//					For Rx case, it will be called by User code.
//
//		pdwSize	::	[o] size of the buffer returned..
//
//	Return Value:
//
//		Null if no buffer available, otherwise pointer to buffer to be used.
//

PUCHAR
ConsumeBuffer(BOOL	bIsTx, DWORD *pdwSize)
{
	PUCHAR			*ppucProducer;
	PUCHAR			*ppucBufferStart;
	PUCHAR			*ppucBufferEnd;
	PUCHAR			*ppucConsumer;	
	PACKET_HEADER	*pPacketHeader;

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


	//
	//	Anything at all ???
	//

	if (*ppucProducer == *ppucConsumer)
		return NULL;


	//
	//	Something avail..  SKIP if it's SKIP buffer..
	//

	pPacketHeader = (PACKET_HEADER *)*ppucConsumer;

	ASSERT(pPacketHeader->dwSignature == HEADER_SIGNATURE);

	if (pPacketHeader->dwFlag & FLAG_SKIP_BUFFER)
	{
		PRINTMSG (0, ("SKIP consumed [0x%x].\r\n",
			*ppucConsumer));

		*ppucConsumer = pPacketHeader->pucNextBuffer;		

		//
		//	Now, check if producer has produced after the SKIP buffer 
		//

		if (*ppucProducer == *ppucConsumer)
			return NULL;
	}

	//
	//	By now we may have data..
	//

	pPacketHeader = (PACKET_HEADER *)*ppucConsumer;

	ASSERT(pPacketHeader->dwSignature == HEADER_SIGNATURE);
	

	//
	//	See if it is ready for consumption..
	//

	if (!(pPacketHeader->dwFlag & FLAG_PRODUCED))
	{
		//
		//	Buffer not yet cooked..
		//

		return NULL;
	}

	
	//
	//	This buffer is now in the process of being consumed..
	//

	pPacketHeader->dwFlag &= ~FLAG_PRODUCED;

	*pdwSize = pPacketHeader->dwCurrentSize;

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

}	//	ConsumeBuffer()	



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

void
ConsumeBufferDone(BOOL	bIsTx, PUCHAR pucBuffer)
{
	PACKET_HEADER	*pPacketHeader;
	PUCHAR			*ppucConsumer;		

	if (bIsTx)
	{	
		ppucConsumer	=	&pucTxConsumer;			
	}
	else
	{		
		ppucConsumer	=	&pucRxConsumer;	
	}


	pPacketHeader = (PPACKET_HEADER)(pucBuffer - sizeof(PACKET_HEADER));

	//
	//	This means we require only one outstanding consumer at anyone time..
	//

	ASSERT(*ppucConsumer == (pucBuffer - sizeof(PACKET_HEADER)));
	ASSERT(pPacketHeader->dwSignature == HEADER_SIGNATURE);

	pPacketHeader->dwFlag = FLAG_CONSUMED;
	
	*ppucConsumer = pPacketHeader->pucNextBuffer;

}	//	ConsumeBufferDone()	



////////////////////////////////////////////////////////////////////////////////
//	SetInterruptEvent()
//
//	Routine Description:
//
//		Copied here from coredll..
//
//	Arguments:	
//
//		idInt	:: the SYSINTR value to trigger..
//
//	Return Value:
//
//		None.
//

BOOL SetInterruptEvent(DWORD idInt) 
{
    long mask;
    long pend;
    long *ptrPend;
	
    if ((idInt < SYSINTR_DEVICES) || (idInt >= SYSINTR_MAXIMUM))
        return FALSE;
    idInt -= SYSINTR_DEVICES;
    mask = 1 << idInt;
    ptrPend = (long*)(UserKInfo[KINX_KDATA_ADDR]+KINFO_OFFSET) + KINX_PENDEVENTS;
    do {
        pend = *ptrPend;
        if (pend & mask)
            return TRUE;    // The bit is already set, so all done.
    } while (InterlockedTestExchange(ptrPend, pend, pend|mask) != pend);
    return TRUE;

}	//	SetInterruptEvent()



/* -------------------------------------------------------------------------- */
/* Start of VBridge exported functions.                                       */
/* -------------------------------------------------------------------------- */



////////////////////////////////////////////////////////////////////////////////
//	VBridgeInit()
//
//	Routine Description:
//
//		Called to initialize all the VBridge related variables.
//		This should be called by OEMEthInit() code, and hence it will be running
//		in KERNEL mode.
//
//	Arguments:	
//
//		None.
//
//	Return Value:
//
//		TRUE	::	Successful.
//		FALSE	::	Otherwise..
//

BOOL
VBridgeInit()
{
	//
	//	Use UNCACHED regions..
	//

	pucTxProducer = (PUCHAR)((DWORD)&TxBuffers[0] | 0x20000000);
	pucTxConsumer = (PUCHAR)((DWORD)&TxBuffers[0] | 0x20000000);
	pucRxProducer = (PUCHAR)((DWORD)&RxBuffers[0] | 0x20000000);
	pucRxConsumer = (PUCHAR)((DWORD)&RxBuffers[0] | 0x20000000);

	pucTxMax      = (PUCHAR)((DWORD)&TxBuffers[TX_BUFFERS_DWORD] | 0x20000000);
	pucTxMin	  = pucTxProducer;

	pucRxMax      = (PUCHAR)((DWORD)&RxBuffers[RX_BUFFERS_DWORD] | 0x20000000);
	pucRxMin	  = pucRxProducer;	

	PRINTMSG (1, ("VBridgeInit()...TX = [%d] bytes -- Rx = [%d] bytes\r\n",
		pucTxMax - pucTxProducer,
		pucRxMax - pucRxProducer));

	PRINTMSG (1, ("Tx buffer [0x%x] to [0x%x].\r\n",
		pucTxMin,
		pucTxMax));

	PRINTMSG (1, ("Rx buffer [0x%x] to [0x%x].\r\n",
		pucRxMin,
		pucRxMax));

	
	//
	//	Start off with VMINI having getting nothing..
	//
	
	dwCurrentPacketFilter = 0x00;

	g_bResetBuffer = FALSE;

	return TRUE;

}	//	VBridgeInit()



////////////////////////////////////////////////////////////////////////////////
//	VBridgeKGetOneTxBuffer()
//
//	Routine Description:
//
//		Called by kernel mode code to query if there is any packet to be sent.
//		This function will return the pointer to the buffer (containing ethernet
//		packet) and the length of the actual data.
//		
//	Arguments:	
//
//		ppucBuffer	::	Points to the start of the ethernet packet.
//		puiLength	::	Length of the packet..
//
//	Return Value:
//
//		TRUE	::	There is data to be sent.
//		FALSE	::	No data to be sent.
//

BOOL
VBridgeKGetOneTxBuffer(
	PUCHAR	*ppucBuffer,
	UINT	*puiLength)
{
	if (g_bResetBuffer)
		VBridgeInit();

    if (ppucBuffer == NULL || puiLength == NULL)
    {
        PRINTMSG (1, ("VBridgeKGetOneTxBuffer() Err! [0x%x] [0x%x]\r\n",
		    ppucBuffer,
		    puiLength));

        return FALSE;
    }

	*ppucBuffer = ConsumeBuffer(TRUE, puiLength);

	if (*ppucBuffer)
	{
		PRINTMSG (0, ("> "));
		return TRUE;
	}
	else 
		return FALSE;

}	//	VBridgeKGetOneTxBuffer()



////////////////////////////////////////////////////////////////////////////////
//	VBridgeKGetOneTxBufferComplete()
//
//	Routine Description:
//
//		This must follow VBridgeKGetOneTxBuffer().
//
//	Arguments:
//
//		pucBuffer	::	Pointer to the buffer that kernel is returning to 
//						VBridge.
//
//	Return Values:
//
//		None.
//
//	Mode:
//
//		Kernel mode only.
//
//

void		
VBridgeKGetOneTxBufferComplete(PUCHAR pucBuffer)
{
	if (g_bResetBuffer)
		VBridgeInit();

    if (pucBuffer == NULL)
    {
        PRINTMSG (1, 
            ("VBridgeKGetOneTxBufferComplete(), NULL pucBuffer!\r\n"));
        return;
    }

	ConsumeBufferDone(TRUE, pucBuffer);

}	//	VBridgeKGetOneTxBufferComplete()



////////////////////////////////////////////////////////////////////////////////
//	VBridgeKIndicateOneRxBuffer()
//
//	Routine Description:
//
//		This is called by kernel code to insert an RX ethernet packet for 
//		VMini.
//
//	Arguments:
//
//		pBuffer		::	Points to the the rx'ed ethernet buffer.
//		uiLength	::	Length of the packet.
//		bSwappable	::	IGNORED (no longer supported)..
//						
//	Return Values:
//		
//		The original buffer pointer, contents are copied locally.
//
//	Mode:
//		Kernel Mode only.
//

#include <pshpack1.h>

typedef struct IPHeaderFormatTag 
{
	BYTE	bVersionLength;
	BYTE	bTypeOfService;
	UINT16	cwTotalLength;
	UINT16	wIdentification;
	UINT16	wFragment;
	BYTE	bTimeToLive;
	BYTE	bProtocol;
	UINT16	wCRC;
	DWORD	dwSrcIP;
	DWORD	dwDestIP;
	
	//
	//	Options can go in here, then comes the data
	//

} IPHeaderFormat, *pIPHeaderFormat;


typedef struct UDPHeaderFormatTag 
{
	UINT16	wSrcPort;
	UINT16	wDestPort;
	UINT16	cwTotalUDPLength;
	UINT16	wCRC;

	//
	//	Then comes data..
	//

} UDPHeaderFormat, *pUDPHeaderFormat;



typedef struct  ENetHeader 
{
    uchar	eh_daddr[6];
    uchar   eh_saddr[6];
    ushort  eh_type;

} ENetHeaderFormat, *pENetHeaderFormat;


typedef struct SNAPHeader 
{
	uchar		eh_daddr[6];
    uchar		eh_saddr[6];
    uchar       sh_dsap;
    uchar       sh_ssap;
    uchar       sh_ctl;
    uchar       sh_protid[3];
    ushort      sh_etype;

} SNAPHeaderFormat, *pSNAPHeaderFormat;

#include <poppack.h>


#define MIN_ETYPE				0x0600		//	Minimum valid Ethertype
#define	IP_TYPE					0x0800		//	IP frame.
#define SNAP_SAP				0xAA
#define SNAP_UI					0x3
#define	PROTOCOL_UDP			0x11
#define	EDBG_UDP_PORT			0x03d5
#define DHCP_CLIENT_PORT		0x0044
#ifndef net_short
#define net_short(x)	((((x)&0xff) << 8) | (((x)&0xff00) >> 8))
#endif

#pragma optimize("",off)
PUCHAR
VBridgeKIndicateOneRxBuffer(PUCHAR pBuffer, UINT uiLength, BOOL bSwappable, BOOL *pbTaken)
{
	PUCHAR	pucKernelBuffer;	

	////////////////////////////////////////////////////////////////////////////
	//	We share MAC address with the EDBG, don't want to eat EDBG
	//	packet.
	//	The following packet types will be return to EDBG:
	//	- Broadcast.
	//	- Any DHCP packet directed to us.
	//	- Any EDBG packet.
	//
	IPHeaderFormat		UNALIGNED	*pIPHeader;
	UDPHeaderFormat		UNALIGNED	*pUDPHeader;
	ENetHeaderFormat	UNALIGNED	*pEnetHeader;
	KITL_HDR			UNALIGNED	*pKitlHdr;
	USHORT				usEType;
	BOOL				bBroadcast	= FALSE;	//	is it Broadcast???
	BOOL				bDhcp		= FALSE;	//	is it DHCP packet???


	//
	//	Platform may have bug not calling VBridgeKSetLocalMacAddress()...
	//	Pass all the packets to EDBG..
	//

	if (g_bResetBuffer)
		VBridgeInit();

    if (pBuffer == NULL || uiLength > MAX_8023_PDU || pbTaken == NULL)
    {
        PRINTMSG(1,
            ("VBridgeKIndicateOneRxBuffer() Err [0x%x] [0x%x] [0x%x]\r\n",
            pBuffer,
            uiLength,
            pbTaken));

        return FALSE;
    }

	if (!bValidAddress)
	{				
		if (!bWarnNoMacDone)
		{
			PRINTMSG (1, 
				("** WARNING!!! ** Device MAC addr not set to VBridge..\r\n"));
			bWarnNoMacDone = TRUE;
		}

		*pbTaken = FALSE;
		return pBuffer;
	}

	PRINTMSG (0, ("Rx: [%x%x%x%x%x%x] --> [%x%x%x%x%x%x] [%x%x]\r\n",
		pBuffer[6],
		pBuffer[7],
		pBuffer[8],
		pBuffer[9],
		pBuffer[10],
		pBuffer[11],
		pBuffer[0],
		pBuffer[1],
		pBuffer[2],
		pBuffer[3],
		pBuffer[4],
		pBuffer[5],
		pBuffer[12],
		pBuffer[13]));
	
	//
	//	Immediately toss the packet if it is > max Ethernet MTU..
	//
	
	if (uiLength > MAX_8023_PDU)
	{
		//
		//	a corrupt packet, don't even pass it to EDBG.
		//	Pretend we consume it..
		//

⌨️ 快捷键说明

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