halether.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 960 行 · 第 1/2 页

C
960
字号
        }
    }

    if (!( pBootArgs->ucLoaderFlags & LDRFL_JUMPIMG )) {
        pAdapter->DHCPLeaseTime = DHCPLeaseTime;
        pAdapter->EdbgFlags = EdbgFlags;
    }

#endif	// !KITL.

    // Enable filtering of broadcast packets (all except ARP packets) to reduce overhead.  We still have
    // to take an interrupt, but the driver can quickly determine whether a packet may be discarded without
    // having to copy all the data from the chip.   Note that we cannot turn this option on until DHCP is
    // done processing, since some DHCP servers return responses in broadcast frames.

    pfnEDbgSetOptions(OPT_BROADCAST_FILTERING);

DEBUGMSG(1, (TEXT("-OEMEthInit\r\n")));

    return (TRUE);
}

/* OEMEthEnableInts
 *
 *  Turn on HW interrupts.  Return TRUE if interrupts supported, or FALSE
 *  to run in polling mode for all clients.
 */
void
OEMEthEnableInts()
{
    pfnEDbgEnableInts();
}

/* OEMEthDisableInts
 *
 *  Disable HW interrupts.
 */
void
OEMEthDisableInts()
{
    pfnEDbgDisableInts();
}

#ifdef IMGSHAREETH

/* ProcessVMiniSend()
 *
 *		This routine drains the pending VMINI TX.
 * 
 */

void
ProcessVMiniSend(void)
{
	PBYTE   pVMiniData;
    DWORD   dwVMiniDataLength;

	////////////////////////////////////////////////////////////////////////////
	//	Handle the filter if we need to..
	//
	if (bNewFilter && pfnCurrentPacketFilter)
	{
		bNewFilter = FALSE;		
		pfnCurrentPacketFilter(dwFilter);
	}		

	//
	//	Handle new multicast list..
	//	
	
	if (bNewMulticast && pfnMulticastList)
	{
		bNewMulticast = FALSE;
		pfnMulticastList(
			(PUCHAR)ucMultiAddr,
			dwNoOfEntry);
	}

    ////////////////////////////////////////////////////////////////////////////
    //  Consume all the client packets.
    //
    while (VBridgeKGetOneTxBuffer(&pVMiniData, &dwVMiniDataLength) == TRUE)
    {
        pfnEDbgSendFrame (pVMiniData, dwVMiniDataLength);
        VBridgeKGetOneTxBufferComplete(pVMiniData);
    } 

}	//	ProcessVMiniSend()

#endif

/* OEMEthISR
 *
 *    ISR routine, called by EDBG IST when Ethernet controller interrupts. Also
 *    called in polling mode, to check for received data.
 *
 * Return Value:
 *    Return bitmask indicating which interrupts are pending.  Currently, the ones
 *    that EDBG cares about are the following (others should be handled internally):
 *       INTR_TYPE_RX   -- Receive interrupt. IST will call into GetFrame to read data.
 */
DWORD
OEMEthISR()
{

#ifdef IMGSHAREETH
	ProcessVMiniSend();
#endif

    return (pfnEDbgGetPendingInts());    
}

/* OEMEthGetFrame
 *
 *   Check to see if a frame has been received, and if so copy to buffer. An optimization
 *   which may be performed in the Ethernet driver is to filter out all received broadcast
 *   packets except for ARPs.  This is done in both the SMC9000 and NE2000 drivers.
 *
 * Return Value:
 *    Return TRUE if frame has been received, FALSE if not.
 */

BOOL
OEMEthGetFrame(
              BYTE *pData,       // OUT - Receives frame data
              UINT16 *pwLength)  // IN  - Length of Rx buffer
                                 // OUT - Number of bytes received
{

#ifdef IMGSHAREETH
    BOOL    bStatus;
    BOOL    bTaken;
	UINT16	wOriginalLength;


	ProcessVMiniSend();

	//
	//	ne2000 ether library has a minor problem of returning incorrect
	//	Ethernet packet size if we give it buffer > max Ether MTU.
	//	So, pass in only ether MTU if the incoming buffer is greater
	//	than ether MTU.
	//

	if (*pwLength >= 1514)
		wOriginalLength = 1514;
	else
		wOriginalLength = *pwLength;
	
    while (1)
    {   
		*pwLength = wOriginalLength;

        bStatus  = pfnEDbgGetFrame(pData, pwLength);
        
        if (bStatus)
        {
            VBridgeKIndicateOneRxBuffer(pData, *pwLength, FALSE, &bTaken);
            if (!bTaken)              
                return bStatus;            
        }
        else
            break;
    }

    return (FALSE);
#else

    return (pfnEDbgGetFrame(pData, pwLength));

#endif
    
}

/* OEMEthSendFrame
 *
 *   Send Ethernet frame.  
 *
 *  Return Value:
 *   TRUE if frame successfully sent, FALSE otherwise.
 */
BOOL
OEMEthSendFrame(
               BYTE *pData,     // IN - Data buffer
               DWORD dwLength)  // IN - Length of buffer    
{
    int retries = 0;
    while ( retries++ < 4 ) {
        if ( !pfnEDbgSendFrame(pData, dwLength) )
        {

#ifdef IMGSHAREETH
			ProcessVMiniSend();
#endif
            return (TRUE);
        }
        else
            EdbgOutputDebugString("!OEMEthSendFrame failure, retry %u\n",retries);
    }
    return (FALSE);
}

/* OEMEthQueryClientInfo
 *
 *    Return address information for default ethernet services, plus a buffer pool to use
 *    for formatting and receiving EDBG packets (single buffer pool specified, divided in
 *    two for Rx and Tx buffers).  By specifying a smaller window size, less memory can be
 *    used (but the protocol will be less efficient...).  The amount of memory required per
 *    client is (2*WindowSize*1500) bytes.
 *
 *    For Odo, we reserve 3 buffer pools worth of memory in the bib file, based on the IMGEBOOT
 *    flag being set.
 *
 *  Return Value:
 *    If client can be configured, return TRUE and fill in addressing and buffer info. Otherwise
 *    return FALSE.  For Odo, configure clients based on the flags set by Eshell (received in the
 *    JUMPIMG command by eboot, and placed in the uninitalized driver globals section).
 */
BOOL
OEMEthQueryClientInfo(
                     UCHAR Service,         // IN - Service ID (one of EDBG_SVC defs from ethdbg.h).
                     EDBG_ADDR *pPeerAddr,  // OUT -Filled in with the peer Ether/IP address and UDP port number.
                     PUCHAR  pWindowSize,   // OUT -Filled in with the client window size.
                     PUCHAR *ppBufferPool)  // OUT -Filled in with the packet buffer pool address.
{

    // We use the default window size (8) for all services
    *pWindowSize = EDBG_WINDOW_SIZE;

    switch ( Service ) {
    // Check the flag in driver globals (set by eboot when it receives the JUMPIMG command)
    case EDBG_SVC_DBGMSG:
        if ( ! (pBootArgs->ucEshellFlags & EDBG_FL_DBGMSG) ) {
            return (FALSE);
        }
        memcpy(pPeerAddr, &pBootArgs->DbgHostAddr,sizeof(EDBG_ADDR));
        *ppBufferPool = (UCHAR *)EDBG_MEMORY_START;
        break;
    case EDBG_SVC_PPSH:
        if ( ! (pBootArgs->ucEshellFlags & EDBG_FL_PPSH) ) {
            return (FALSE);
        }
        memcpy(pPeerAddr, &pBootArgs->CeshHostAddr,sizeof(EDBG_ADDR));
        *ppBufferPool = (UCHAR *)EDBG_MEMORY_START + EDBG_DFLT_BUFFER_POOL_SIZE;
        break;
    case EDBG_SVC_KDBG:
        if ( ! (pBootArgs->ucEshellFlags & EDBG_FL_KDBG) ) {
            return (FALSE);
        }
        memcpy(pPeerAddr, &pBootArgs->KdbgHostAddr,sizeof(EDBG_ADDR));    
        *ppBufferPool = (UCHAR *)EDBG_MEMORY_START + 2*EDBG_DFLT_BUFFER_POOL_SIZE;
        break;            
    default:
        return (FALSE);
    }
    return (TRUE);
}



/* OEMEthGetSecs
 *
 *  Return a count of seconds from some arbitrary time (the absolute value is not important,
 *  so long as it increments appropriately). Read this value from the RTC values in CMOS. Note
 *  that reading the CMOS requires multiple register operations, so this function must be called
 *  only when scheduling is disabled.
 */
DWORD OEMEthGetSecs(void)
{

    /*
     * Returning counter value for Integrator RTC.
     * WARNING: this assumes RTC CLK1HZ signal is
     * set for 1 Hz = 1 tick/second.
     */
    return(*(DWORD *)VA_RTC_BASE);
}


#ifdef IMGSHAREETH

//
//	These functions are only needed if vmini is in.
//	i.e. if IMGSHAREETH is set.
//


////////////////////////////////////////////////////////////////////////////////
//	OEMEthSetFilter()
//
//	Description:
//		
//		This function is used by VMINI to inform the underlying ethernet
//		library on the filtering mode it requires.
//
//	Arguments:
//
//		pdwRequestedFilter	:: The requested filter.
//							   Identical constants have been added in 
//							   that mimics NDIS_PACKET_TYPE_XXX constants.
//
//	Return Value:
//
//		TRUE	:: if we can set the filter.
//		FALSE	:: otherwise..
//
//
//	Note:
//		
//		As a minimum to get vmini to work, we need to support
//		PACKET_TYPE_DIRECTED 
//		PACKET_TYPE_BROADCAST
//
//	
BOOL
OEMEthCurrentPacketFilter(PDWORD pdwRequestedFilter)
{

	if (pfnCurrentPacketFilter)
	{
		EdbgOutputDebugString(
			"OEMEthCurrentPacketFilter set to [0x%x]\r\n",
			*pdwRequestedFilter);	

		//
		//	Note that we can't do it immediately here, since we are called 
		//	by user mode code.
		//	So what we do is to set the flag here for the kernel mode code
		//	to pick up.
		//

		dwFilter   = *pdwRequestedFilter;
		bNewFilter = TRUE;
		return TRUE;
	}
	else
	{
		//
		//	Oh well, eth driver does not yet support filter setting
		//	So if it is PACKET_TYPE_DIRECTED, PACKET_TYPE_MULTICAST, 
		//	PACKET_TYPE_BROADCAST, we just lie that we are ok with it.
		//	Since EDBG will run in this mode anyway..
		//

		DWORD	dwInherentlySupported = 
					PACKET_TYPE_MULTICAST	| 
					PACKET_TYPE_DIRECTED	| 
					PACKET_TYPE_BROADCAST;

		if (*pdwRequestedFilter == dwInherentlySupported)
			return TRUE;
		else
			return FALSE;
	}

}	//	OEMEthCurrentPacketFilter()



////////////////////////////////////////////////////////////////////////////////
//	OEMEthMulticastList()
//
//	Description:
//
//		This function is used by VMINI to inform the underlying ethernet 
//		library on multicast addresses that winsock app is interested in.
//		
//	Arguments:
//
//		pucMulticastAddressList	:: Pointer to an array of multicast addresses.
//		dwNoOfAddresses			:: Number of addresses passed in to us.
//
//	Return Value:
//		
//		TRUE	::  if we can set the underlying edbg ethernet libary to start
//						filtering on these multicast addresses.
//
//		FALSE	::  otherwise.
//
BOOL
OEMEthMulticastList(PUCHAR	pucMulticastAddressList, DWORD	dwNoOfAddresses)
{
	//
	//	This platform does not support multicast yet..
	//

	DWORD	i;
	BOOL	bReturnValue;

	EdbgOutputDebugString(
		"OEMEthMulticastList():: No of Entries [%d]\r\n",
			dwNoOfAddresses);	

	//
	//	We can check how many entries an adapter that are attached to 
	//	can support.
	//	To make things simple, we just assume we can support minimum that
	//	vmini thinks we support (i.e. 8).
	//

	if (dwNoOfAddresses > 8)
	{
		//
		//	This should never happen, since VMINI is known to support
		//	8 entries only... 
		//
		
		EdbgOutputDebugString(
			"Multicast list requeste [%d] > 8 !!!\r\n",
			dwNoOfAddresses);

		return FALSE;
	}


	//
	//	 8 entries, 6 bytes each..
	//

	memset(
		ucMultiAddr,
		0x00,
		8 * 6);		

	//
	//	6 bytes per entry..
	//

	memcpy(
		ucMultiAddr,
		pucMulticastAddressList,
		dwNoOfAddresses * 6);


	for (i = 0 ; i < dwNoOfAddresses ; i++)
	{
		EdbgOutputDebugString(
			"[%d] : %x - %x - %x - %x - %x - %x\r\n",
			i,
			pucMulticastAddressList[6*i+0],
			pucMulticastAddressList[6*i+1],
			pucMulticastAddressList[6*i+2],
			pucMulticastAddressList[6*i+3],
			pucMulticastAddressList[6*i+4],
			pucMulticastAddressList[6*i+5]);
	}

	if (pfnMulticastList)
	{
		//
		//	We are in KernelIOCTL call, some h/w requires the 
		//	setting of the MULTICAST addresses in interrupt service routine.
		//	So we will do it later, and mark it so the ISR will know about it..
		//	Note:
		//	Order is important here.    Don't set bNewMulticast to true until
		//	all the entries and the dwNoOfEntry are properly set up.
		//	This is because we can be switched out in the middle of 
		///	KernelIOCTL!!
		//

		dwNoOfEntry   = dwNoOfAddresses;
		bNewMulticast = TRUE;		
		bReturnValue  = TRUE;
	}
	else
		bReturnValue = FALSE;

	
	EdbgOutputDebugString(
		"OEMEthMulticastList returning [%d]\r\n",
		bReturnValue);


	return bReturnValue;
	

}	//	OEMEthMulticastList()

#endif

⌨️ 快捷键说明

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