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

📄 car6krx.cpp

📁 Atheros Communications AR6001 WLAN Driver for SDIO installation Read Me March 26,2007 (based on
💻 CPP
字号:
//------------------------------------------------------------------------------
// <copyright file="" company="Atheros and Microsoft">
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//    Copyright (c) 2006 Atheros Corporation.  All rights reserved.
//
//    The use and distribution terms for this software are covered by the
//    Microsoft Limited Permissive License (Ms-LPL) 
//    http://www.microsoft.com/resources/sharedsource/licensingbasics/limitedpermissivelicense.mspx 
//    which can be found in the file MS-LPL.txt at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
//    Windows CE Wifi Driver for AR-6000
// </summary>
//------------------------------------------------------------------------------
//==============================================================================
// AR6000 NDIS Miniport received packet handling functions.
//
// Author(s): ="Atheros and Microsoft"
//==============================================================================


#include <windows.h>
#include <ndis.h>


#include "htc_internal.h"
#include "htc.h"
#include "wmi_api.h"
#include "netbuf.h"
#include "ndisnetbuf.h"
#include "athdefs.h"
extern "C" {
#include "bmi.h"
}

#include "cmini.hpp"
#include "c802_3mini.hpp"
#include "c802_11mini.hpp"
#include "car6k.hpp"
#include "osapi.h"


static const CAP_CONST bridgeTunnel = ETHERNET_TUNNEL;
static const CAP_CONST vrfc1042		= RFC1042SNAP;

void
CAR6KMini::ReceiveWMIDataPacket(
	HTC_EVENT_INFO  *evInfo)
//
//  This function processes data from an HTC_BUFFER_RECEIVED indication
//  not on the WMI_CONTROL_MBOX endpoint.
//
{
	ndis_mini_buf_t *pb = (ndis_mini_buf_t *)evInfo->cookie;
	NDIS_STATUS      Status;
	NDIS_PACKET     *pPacket;
	NDIS_BUFFER     *pBuffer;
	PBYTE            pData;
	ULONG            cbData;
	BOOL			 doDix = FALSE;
	USHORT			 etherType;
	SNAP_HEADER		 *pSnapHdr;
	MAC_ADDRESS		 *pDestAddr,*tempAddr;
	BOOL			 mcForUs = FALSE;
		
	
	NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: +ReceiveWMIDataPacket");

	    
    if (evInfo->status != A_OK) {
		NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket Error in receiving : status = %x\n", evInfo->status);
		if (A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
			a_netbuf_free(pb);
		}
		goto done;
    }
    
	// evInfo->actualLength is the length of the pb->data including
	//      2 bytes: WMI_DATA_HEADER [optional - only if HTC header is 46 00]
	//     14 bytes: 802.3 MAC header
	//      8 bytes: SNAP header (with EthType as last 2 bytes)
	//      N bytes: payload (e.g. IP packet)
	pData = evInfo->buffer; 
	cbData = evInfo->actualLength;

	// Remove the WMI_DATA_HDR.
	if (cbData < sizeof(WMI_DATA_HDR))
	{
		NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing WMI header (%u bytes)\n", evInfo->actualLength);
		if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
			a_netbuf_free(pb);
		}
		goto done;
    }
	pData += sizeof(WMI_DATA_HDR);
	cbData -= sizeof(WMI_DATA_HDR);

	if (cbData < sizeof(ETHERNET_MAC_HEADER) + sizeof(SNAP_HEADER))
	{
		NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing MAC + SNAP (%u bytes)\n", cbData);
		if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
			a_netbuf_free(pb);
		}
		goto done;
	}

#ifdef WMM
	Lock();
    wmi_implicit_create_pstream((wmi_t *)m_pWMI, pb, DNLINK_TRAFFIC,1);
	Unlock();
#endif //WMM

	
	pDestAddr=(MAC_ADDRESS *)pData;
 	
 	/* Apply NDIS receive filter */
     if (isGrp(pDestAddr)) {
         if (isBcast(pDestAddr)) {
			 if (!(m_CurrentPacketFilter & NDIS_PACKET_TYPE_BROADCAST)) {
                 if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
					a_netbuf_free(pb);
				 }			
				 goto done;
             }
         } else {
			 isMcForUs(pDestAddr,&mcForUs);
			 if (!(m_CurrentPacketFilter & (NDIS_PACKET_TYPE_MULTICAST |
				 NDIS_PACKET_TYPE_ALL_MULTICAST)) || !(mcForUs))
             {
				 if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
					a_netbuf_free(pb);
				 }
				 goto done;
             }
		}
 		
     } else {
		tempAddr=(MAC_ADDRESS *) m_PermanentAddress;
		if ((A_MACADDR_COMP(pDestAddr,tempAddr) != 0) &&
             !(m_CurrentPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS))
        {
			if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
				a_netbuf_free(pb);
			}
			goto done;
        }
	}

	 // Allocate an NDIS_PACKET from our packet pool.
	NdisAllocatePacket(&Status, &pPacket, m_RxPacketPool);
	if (NDIS_STATUS_SUCCESS != Status)
	{
		NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - NdisAllocatePacket failed\n");
		if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
			a_netbuf_free(pb);
		}
		goto done;
	}

	// Check for ethernetType in SNAP header for NOVELL_IPX, APPLE_TALK_ARP etc
	// remove 802.3 length and SNAP header if it is not of these types 
	
	pSnapHdr=(SNAP_HEADER *)(pData+sizeof(ETHERNET_MAC_HEADER));
	etherType=A_BE2CPU16(pSnapHdr->Type);
	
	doDix=((A_MEMCMP(pSnapHdr,&bridgeTunnel, sizeof(CAP_CONST))) == 0);
	if((!doDix) && ((A_MEMCMP(pSnapHdr,&vrfc1042, sizeof(CAP_CONST))) == 0))
	{
		doDix = ((etherType != APPLE_TALK_ARP) && (etherType != NOVELL_IPX));
	}
	// Get rid of the 802.3 length and SNAP header by copying
	// the 802.3 DestMACAddr and SrcMACAddr forward so they
	// immediately precede the EthType at the end of the SNAP header.
	// That gives us a DIX packet.

	if (doDix) {
	memmove(pData + sizeof(SNAP_HEADER), pData, ETHERNET_MAC_ADDRESS_LENGTH * 2);
	pData += sizeof(SNAP_HEADER);
	cbData -= sizeof(SNAP_HEADER);
	}


	

	// Setup the fields of NDIS_BUFFER to point to our data.
	pBuffer = &pb->NdisBuffer;
	NdisInitializeBuffer(pBuffer, pData, cbData);

	// Chain the NDIS_BUFFER to the start of the NDIS_PACKET
	NdisChainBufferAtBack(pPacket, pBuffer);
	NDIS_SET_PACKET_HEADER_SIZE(pPacket, sizeof(ETHERNET_MAC_HEADER));
	NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS);

#ifdef NDIS_BUS_DRIVER
	NDIS_PACKET *PacketArray[1];
	PacketArray[0]=pPacket;
	NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, 1);
#else
	// Perform the indicate on the timer thread because tying up the
	// SDIO receive indication thread can result in a deadlock.
	PLIST_ENTRY pEntry = (PLIST_ENTRY)(pPacket->MiniportReserved);
	Lock();
	InsertTailList(&m_RxPendingPacketList, pEntry);
	NdisSetEvent(&m_RxPendingEvent);
	Unlock();
#endif	

done:
	NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: -ReceiveWMIDataPacket");
}

#define MAX_PACKETS_PER_INDICATE	10

void
CAR6KMini::IndicateReceivePackets()
//
//  This function is called on the worker thread to indicate received
//  packets.
//
{
	NDIS_PACKET *pPacket;
	NDIS_PACKET *PacketArray[MAX_PACKETS_PER_INDICATE];
	ULONG        NumPacketsToIndicate;
	LIST_ENTRY  *pNode;
	boolean      bEventSignalled;

	NdisResetEvent(&m_RxWorkItemExitedEvent);

	while (false == m_Halting)
	{
		// Wait for packets to be placed on the list
		bEventSignalled = NdisWaitEvent(&m_RxPendingEvent, 0);
		if (m_Halting || !bEventSignalled)
			break;

		NumPacketsToIndicate = 0;

		//
		// Get up to MAX_PACKET_PER_INDICATE packets from the RxPending list.
		// Put the packet pointers into an array.
		//
		Lock();
		while (!IsListEmpty(&m_RxPendingPacketList))
		{
			pNode = RemoveHeadList(&m_RxPendingPacketList);
			pPacket = (PNDIS_PACKET)((PBYTE)pNode - offsetof(NDIS_PACKET, MiniportReserved));
			PacketArray[NumPacketsToIndicate++] = pPacket;
			if (NumPacketsToIndicate == MAX_PACKETS_PER_INDICATE) {
				Unlock();
				NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, NumPacketsToIndicate);
				Lock();
				NumPacketsToIndicate = 0;
			}
		}
		NdisResetEvent(&m_RxPendingEvent);
		Unlock();

		//
		// Indicate the received packets up to protocol drivers bound to us.
		//
		if (NumPacketsToIndicate)
			NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, NumPacketsToIndicate);
	}

	NdisSetEvent(&m_RxWorkItemExitedEvent);
}

void
CAR6KMini::AllocateHTCPacketBuffers(
	HTC_ENDPOINT_ID  eid,
	UINT             numBuffers)
//
//  This function is called to allocate packet buffers and transfer
//  ownership of them to HTC so that HTC can use them to indicate
//  packet data to us via HTC_BUFFER_RECEIVED indications.
//
{
	ndis_mini_buf_t *pb = NULL;

	for (UINT i = 0; i < numBuffers; i++)
	{
		pb = (ndis_mini_buf_t *)a_netbuf_alloc(AR6000_BUFFER_SIZE);
		if (NULL == pb)
		{
			NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: OOM in AllocateHTCPacketBuffers\n");
			break;
		}
		// Pass ownership of the buffer to HTC
		if ( A_OK != HTCBufferReceive(m_pHTCTarget, eid, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) {
			a_netbuf_free(pb);
		}
	}
}

void
CAR6KMini::ReturnPacket(
	IN PNDIS_PACKET Packet)
//
//  After the miniport passes packets up to NDIS via
//  NdisMIndicateReceivePackets, NDIS will some time later
//  return those packets (one at a time) to the miniport
//  by calling this ReturnPacket handler.
//
{
	NDIS_BUFFER *pBuffer;
	A_STATUS status = A_OK;

	// Remove the NDIS_BUFFER from the packet (should be exactly 1 buffer)
	NdisUnchainBufferAtFront(Packet, &pBuffer);

	// Return the NDIS_PACKET to our pool
	NdisFreePacket(Packet);

	// Return the pb containing the NDIS_BUFFER to the HTC layer
	// to receive a new packet
	ndis_mini_buf_t *pb = (ndis_mini_buf_t *)((PBYTE)pBuffer - offsetof(ndis_mini_buf_t, NdisBuffer));
	status = HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb);

	if ( status != A_OK ) {
		//HTC did'nt accept the buffer. Free it.
		a_netbuf_free(pb);
	}
}

/*****************************************************************************
  * isMcForUs - Filter multicast frames that are not wanted
  *
  * Description:
  * If we're not receiving all m/c pkts, filter such a pkt
  * through the NDIS-supplied list.
  * Note: Promiscuous mode is not currently supported
  */
 
 void
 CAR6KMini::isMcForUs(MAC_ADDRESS *pAddr, BOOL *mcForUs)
 {
     UINT i;
 	MAC_ADDRESS	     *tempAddr;
 
	if (m_CurrentPacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
		*mcForUs = TRUE;
        return;
     }
 	 for (i = 0; i < m_numMulticastAddresses; i++) {
		 tempAddr=(MAC_ADDRESS *) m_MulticastAddresses[i];
		 if ((A_MACADDR_COMP(pAddr, tempAddr) == 0)) {
			 *mcForUs=TRUE;
             return;
         }
 	 }
	 *mcForUs = FALSE; 
     return;
 }

⌨️ 快捷键说明

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