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

📄 vmini.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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:  
    VMini.c

Abstract:  
    The Null miniport implementation.
    This module uses the KernelIoCtl() calls to get it's jobs
    done.
    

Functions:

    
--*/

#include <windows.h>
#include <pkfuncs.h>
#include <nkintr.h>
#include <ndis.h>
#include <VMini.h>
#include <zone.h>

//
//	This is how much virtual address we reserve for TX or RX buffer..
//	2M each, VBridge needs to be modified if it needs more than this!!!
//

#define	VIRTUAL_MEMORY_TO_ALLOC		0x200000
#define DEFAULT_RX_THREAD_PRIORITY  131         


//
//  Set this to non-zero when EDBG starts to use
//  name event: EDBG_INTERRUPT_EVENT
//

#define EDBG_USE_NAME_EVENT			0x01


#ifndef net_short
#define net_short(x)	((((x)&0xff) << 8) | (((x)&0xff00) >> 8))
#endif


#ifdef DEBUG
DBGPARAM dpCurSettings = 
{
    TEXT("VMINI"), 
    {
        TEXT("INIT"),
        TEXT("SEND"),       
        TEXT("RECEIVE"),
        TEXT("SET"),
        TEXT("GET"),
        TEXT("MEMORY"),
        TEXT("<unused>"),
        TEXT("<unused>"),
        TEXT("<unused>"),
        TEXT("<unused>"),
        TEXT("<unused>"),       
        TEXT("<unused>"),
        TEXT("<unused>"),       
        TEXT("<unused>"),
        TEXT("Warning"),
        TEXT("Error"),
    },

    0xC000
}; 
#endif  //  DEBUG


//
//	typedef..
//

#include <pshpack1.h>

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;


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

} ENetHeaderFormat, *pENetHeaderFormat;


typedef struct IPHeaderFormatTag 
{
	BYTE	bVersionLength;
	BYTE	bTypeOfService;
	UINT16	cwTotalLength;
	UINT16	wIdentification;
	UINT16	wFragment;
	BYTE	bTimeToLive;
	BYTE	bProtocol;
	UINT16	wCRC;
	DWORD	dwSrcIP;
	DWORD	dwDestIP;

} IPHeaderFormat, *pIPHeaderFormat;


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

} UDPHeaderFormat, *pUDPHeaderFormat;


#define CHADDR_LEN	16
#define SNAME_LEN	64
#define FILE_LEN	128
#define OPTIONS_LEN	312

typedef struct {
	
	unsigned char	Op;
	unsigned char	Htype;
	unsigned char	Hlen;
	unsigned char	Hops;
	unsigned int	Xid;
	unsigned short	Secs;
	unsigned short	Flags;
	unsigned int	Ciaddr;
	unsigned int	Yiaddr;
	unsigned int	Siaddr;
	unsigned int	Giaddr;
	unsigned char	aChaddr[CHADDR_LEN];
	unsigned char	aSname[SNAME_LEN];
	unsigned char	aFile[FILE_LEN];
	unsigned char	aOptions[OPTIONS_LEN];

} DHCP_PACKET, *PDHCP_PACKET;

#include <poppack.h>


//
//  Forward decl.
//

VOID
VMiniMShutdownHandler(
    IN PVOID Context
    );


//
//  Global variables.
//

STRUCT_VMINI        VMini;				//  Miniport global var.
CRITICAL_SECTION	g_csSend;			//	Only one send at a time.

DWORD				dwTxPA = 0x00;		//	TX buffers..
DWORD				dwTxVA;
DWORD				dwTxOffset;
DWORD				dwTxPAMax;

DWORD				dwRxPA = 0x00;		//	RX buffers..
DWORD				dwRxVA;
DWORD				dwRxOffset;
DWORD				dwRxPAMax;



////////////////////////////////////////////////////////////////////////////////
//	PA2VA()
//
//	Routine Description:
//
//		This function is responsible in converting the PA to VA.
//
//	Arguments:	
//
//		dwPA	::	The physical address.
//
//		bIsTx	::	Whether this is TX buffer or RX buffer.
//					We only do the conversion once with each type of the buffer.
//					i.e for the very first buffer coming from VBridge.
//					We then reserve VIRTUAL_MEMORY_TO_ALLOC virtual memory 
//					mapped to this buffer..
//
//	Return Value:
//
//		NULL	::	If can't convert.
//
//		VA		::	The virtual address of the given Physical Address.
//

PUCHAR
PA2VA(DWORD dwPA, BOOL bIsTx)
{
	PDWORD		pdwPA;
	PDWORD		pdwVA;
	PDWORD		pdwOffset;
	PDWORD		pdwPAMax;

	if (bIsTx)
	{
		pdwPA	  = &dwTxPA;
		pdwVA	  = &dwTxVA;
		pdwOffset =	&dwTxOffset;
		pdwPAMax  = &dwTxPAMax;
	}
	else
	{
		pdwPA	  = &dwRxPA;
		pdwVA	  = &dwRxVA;
		pdwOffset =	&dwRxOffset;
		pdwPAMax  = &dwRxPAMax;
	}
	

	if (*pdwPA != 0x00)
	{
		//
		//	Already mapped, make sure this PA is in range and calculate the VA.
		//

		if (dwPA >= *pdwPAMax)
			return NULL;

		
		//
		//	In range, calculate the VA to use..
		//

		return (PUCHAR)(*pdwVA + (dwPA - *pdwPA));
	}


	//
	//	Nop, first time mapping..
	//

	*pdwOffset = dwPA % PAGE_SIZE;           
    *pdwVA	   = (DWORD)VirtualAlloc(
							0, 
							VIRTUAL_MEMORY_TO_ALLOC + *pdwOffset, 
							MEM_RESERVE, 
							PAGE_NOACCESS);
    
	if (!VirtualCopy(
            (PVOID)*pdwVA, 
            (LPVOID)(dwPA - *pdwOffset),
            VIRTUAL_MEMORY_TO_ALLOC + *pdwOffset,
            PAGE_READWRITE | PAGE_NOCACHE))
    {
        RETAILMSG (1, 
			(TEXT("VMini:: Failed VirtualCopy()!! PA[0x%x] Offset[0x%x]\r\n"),
			dwPA,
			*pdwOffset));
        
        return NULL;
    }

	*pdwVA	   += *pdwOffset;
	*pdwPA		= dwPA;
	*pdwPAMax	= dwPA + VIRTUAL_MEMORY_TO_ALLOC;
    
    return (PUCHAR)(*pdwVA);

}   //  PA2VA()



////////////////////////////////////////////////////////////////////////////////
//	VirtMiniISR()
//
//	Routine Description:
//
//		This thread handles RX from VBridge..
//		Thread will quit when VMini.vm_bHalt is set..
//
//	Arguments:	
//
//		None.
//
//	Return Value:
//
//		None.
//

void
VirtMiniISR(void)
{
    DWORD                   BufferAddress;
    DWORD                   dwReturnedBytes;
    PBYTE                   pVA;
    PNDIS_BUFFER            pNdisBuffer;    
    PNDIS_PACKET_OOB_DATA   OobyDoobyData;
    NDIS_STATUS             Status;

#ifndef NDIS50_MINIPORT
    NDIS_HANDLE             SwitchHandle;
#endif    

    DWORD                   dwWaitTime;
	BOOL					bConvert = FALSE;
    
    DEBUGMSG (ZONE_RECEIVE, (TEXT("VMini:: $$$$..VirtMiniISR() started..$$$$\r\n")));
    

    //
    //  Create the event that we will be waiting for when kernel has 
    //  RX packets for us.
    //  
    
    VMini.vm_hInterruptEvent = CreateEvent(NULL, FALSE, FALSE, VMINI_RX_EVENT);  

    
	//
    //  Revert to polling mode if we fail this.
    //          

    if (InterruptInitialize(SYSINTR_VMINI, VMini.vm_hInterruptEvent, NULL, 0x00))
    {
        RETAILMSG (1, (TEXT("VMini:: Successfully initialize SYSINTR_VMINI..\r\n")));
        dwWaitTime = INFINITE;
    }
    else
    {
        RETAILMSG (1, (TEXT("VMini:: Warning!! Use polling mode for RX.\r\n")));
        dwWaitTime = 10;
    }   

    while(1)
    {       
        WaitForSingleObject (VMini.vm_hInterruptEvent, dwWaitTime);

        DEBUGMSG (ZONE_RECEIVE, (TEXT("RX Interrupt!\r\n")));

        while (KernelIoControl (
                    IOCTL_VBRIDGE_GET_RX_PACKET,
                    NULL,
                    0x00,
                    (LPVOID)&BufferAddress,
                    sizeof(DWORD),      
                    &dwReturnedBytes))
        {
            //
            //  Okay, we have a packet to indicate..
            //  KernelIoCtl returns us the PA hence we need to get the VA
            //  out of it.   
            //  
			
			//
			//	Make sure we get 0x8xxxxxxx region since on x86 the 0xAxxxxxxx
			//	will not work if you pass it into VirtualCopy.	
			//

			if (BufferAddress & 0x20000000)
			{
				bConvert = TRUE;
				BufferAddress &= ~0x20000000;
			}

            if (!(pVA = PA2VA(BufferAddress, FALSE)))
				goto NextLoop;
            
            DEBUGMSG (0, (TEXT("Rcvd Dest = %x-%x-%x-%x-%x-%x :: [%d] bytes.\r\n"),
                pVA[0],
                pVA[1],
                pVA[2],
                pVA[3],
                pVA[4],
                pVA[5],
                dwReturnedBytes));          

			//
			//	Do not indicate if we are in HALT state.
			//		

			if (VMini.vm_bHalt)
			{
				DEBUGMSG (1, (TEXT("VMini:: HALT!  No indicate.\r\n")));
				goto NextLoop;
			}


            //
            //  Now, link the VA to the NdisPacket, and prepare the 
            //  NdisPacket for take off..
            //
            
			NdisAllocateBuffer(
                &Status,
                &pNdisBuffer,
                VMini.NdisBufferPool,
                pVA,
                dwReturnedBytes);

            if (Status != NDIS_STATUS_SUCCESS)
            {
                DEBUGMSG (ZONE_ERROR, (TEXT("VMini:: Error!   Bad NdisAllocateBuffer() in VMiniISR().\r\n")));
                goto NextLoop;
            }

            NdisChainBufferAtFront(VMini.pNdisPacket, pNdisBuffer);
            
            OobyDoobyData = NDIS_OOB_DATA_FROM_PACKET (VMini.pNdisPacket);
            NdisZeroMemory (OobyDoobyData, sizeof(NDIS_PACKET_OOB_DATA));
            OobyDoobyData->HeaderSize               = 14;
            OobyDoobyData->SizeMediaSpecificInfo    = 0;
            OobyDoobyData->MediaSpecificInformation = NULL;
            OobyDoobyData->Status                   = NDIS_STATUS_RESOURCES;


            //
            //  Final touch up just before it is sent up.
            //

            NdisAdjustBufferLength(
               pNdisBuffer,
               dwReturnedBytes
               );   
            NdisSetPacketFlags (VMini.pNdisPacket, NDIS_FLAGS_DONT_LOOPBACK);             
            NdisRecalculatePacketCounts (VMini.pNdisPacket);

            
#if 0
            //
            //  Use this to see packet details..
            //

            {
                DWORD   dwPhysicalBufferCount;
                DWORD   dwBufferCount;
                DWORD   dwTotalPacketLength;

                NdisQueryPacket(
                    VMini.pNdisPacket,
                    &dwPhysicalBufferCount,
                    &dwBufferCount,
                    NULL,
                    &dwTotalPacketLength);


                DEBUGMSG (1, (TEXT("VMini:: RX:: dwBufferCount[%d] - dwTotalPktLength[%d] - Actual[%d]\r\n"),                       
                    dwBufferCount,
                    dwTotalPacketLength,
                    dwReturnedBytes));              
            }
#endif

            //
            //  Of it goes..
            //


#ifndef NDIS50_MINIPORT
            NdisIMSwitchToMiniport(
                VMini.vm_VMiniportHandle,
                &SwitchHandle);
#endif	

            NdisMIndicateReceivePacket(
                VMini.vm_VMiniportHandle,
                &VMini.pNdisPacket, 
                1);

#ifndef NDIS50_MINIPORT
            NdisIMRevertBack(
                VMini.vm_VMiniportHandle,
                SwitchHandle);
#endif	            

            //
            //  Free up all the resources..
            //

            NdisUnchainBufferAtFront (VMini.pNdisPacket, &pNdisBuffer);                   
            NdisFreeBuffer(pNdisBuffer);            

⌨️ 快捷键说明

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