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

📄 rtusb_data.c

📁 台湾RALink公司的 rt2570无线 802.11g 网卡的 驱动的源代码 ,支持linux2.4以上的 内河
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 ***************************************************************************
 * Ralink Tech Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2004, Ralink Technology, Inc.
 *
 * This program is free software; you can redistribute it and/or modify  * 
 * it under the terms of the GNU General Public License as published by  * 
 * the Free Software Foundation; either version 2 of the License, or     * 
 * (at your option) any later version.                                   * 
 *                                                                       * 
 * This program is distributed in the hope that it will be useful,       * 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * 
 * GNU General Public License for more details.                          * 
 *                                                                       * 
 * You should have received a copy of the GNU General Public License     * 
 * along with this program; if not, write to the                         * 
 * Free Software Foundation, Inc.,                                       * 
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * 
 *                                                                       * 
 ************************************************************************
	Module Name:
	rtusb_data.c

	Abstract:

	Revision History:
	Who			When			What
	--------	----------		----------------------------------------------
	Name		Date			Modification logs
	Jan Lee		2005-06-01		Release
*/
#include	"rt_config.h"

static  UCHAR PlcpSignal[12] = { 
	 0, /* RATE_1 */    1, /* RATE_2 */     2, /* RATE_5_5 */   3, /* RATE_11 */    // see BBP spec
	11, /* RATE_6 */   15, /* RATE_9 */    10, /* RATE_12 */   14, /* RATE_18 */    // see IEEE802.11a-1999 p.14
	 9, /* RATE_24 */  13, /* RATE_36 */    8, /* RATE_48 */    12  /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
static	UCHAR	SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
static	UCHAR	SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
static	UCHAR	EAPOL[] = {0x88, 0x8e};
static	UCHAR	IPX[] = {0x81, 0x37};
static	UCHAR	APPLE_TALK[] = {0x80, 0xf3};
UCHAR	ARP[]={0x08, 0x06};
////////////////////////////////////////////////////////////////////////////
//
//	FUNCTION
//		RTUSBSendPackets
//		
//	DESCRIPTION
//	  VNETMultipleSend handler is called by NDIS to transmit packets
//	  through the adapter. If there are packets in the Q and the device
//	  can accept the Tx requests initiate a transmission and queue the
//	  rest of the packets (if any...). If we can not transmit or the
//	  station is not ready we imediatelly complete the request
//		
//	INPUT
//	  MiniportAdapterContext		Context registered with the wrapper
//									(Ptr to to the Adapter object)
//	  PacketArray					Array of Ptrs to NDIS_PACKET structs
//	  NumberOfPackets				Number of packets in PacketArray
//		
//	OUTPUT
//		-
//		
////////////////////////////////////////////////////////////////////////////
int RTUSBSendPackets(struct sk_buff *skb, struct net_device *net_dev)
{

	NDIS_STATUS 	Status = NDIS_STATUS_SUCCESS;
	PRT2570ADAPTER	pAdapter = net_dev->priv;
	
	skb->data_len = skb->len;
	if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
		RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS) ||
		RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF) ||
		RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS))
	{
		RTUSBFreeSkbBuffer(skb);
		return 0;
	}
	// Drop packets if no associations
	else if (!INFRA_ON(pAdapter) && !ADHOC_ON(pAdapter))
	{
		RTUSBFreeSkbBuffer(skb);
		return 0;
	}
	else
	{
		Status = RTUSBSendPacket(pAdapter, skb);
	        if (Status != NDIS_STATUS_SUCCESS)
	        {
			// Errors before enqueue stage
			RTUSBFreeSkbBuffer(skb);
			DBGPRINT(RT_DEBUG_TRACE,"<---RTUSBSendPackets not dequeue\n");
			return 0;
	        }
	}
	// Dequeue one frame from SendTxWait queue and process it
	// There are two place calling dequeue for TX ring.
	// 1. Here, right after queueing the frame.
	// 2. At the end of TxRingTxDone service routine.
	if ((!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && 
		(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF)) &&
		(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS)) &&
		(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) &&
		(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
	{
	    //RTMPDeQueuePacket(pAdapter, &pAdapter->TxSwQueue0);
	    // Call dequeue without selected queue, let the subroutine select the right priority
	    // Tx software queue
	    RTUSBDeQueuePacket(pAdapter);
	}

	// Kick bulk out
	RTUSBKickBulkOut(pAdapter);
	return 0;
}

NDIS_STATUS	RTUSBSendPacket(
	IN	PRT2570ADAPTER	pAdapter,
	IN  struct sk_buff  *skb)
{


	PVOID			pVirtualAddress;
	PQUEUE_HEADER			pTxQueue;
	ULONG					Priority;
	UCHAR			NumberOfFrag;
	UCHAR			RTSRequired;
	UINT			AllowFragSize;
	UCHAR                   AccessCategory;
	NDIS_STATUS		Status = NDIS_STATUS_FAILURE;
	UCHAR			PsMode;

	// Init priority value
	Priority = 0;
	AccessCategory = 0;
	
	if (skb)
	{
		Priority = skb->priority;
		// 802.11e/d4.4 June, 2003
		if (Priority <=2)
		    AccessCategory = 0;
		else if (Priority == 3)
		    AccessCategory = 1;
		else if (Priority <= 5)
		    AccessCategory = 2;
		else
		    AccessCategory = 3;
		DBGPRINT(RT_DEBUG_INFO, "Priority = %d, AC = %d\n", Priority, AccessCategory);
	}
	// For TKIP, MIC value is treated as payload, it might be fragmented through
	// different MPDUs.
	if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled)
	{
		skb->data_len += 8;
	}

	pVirtualAddress = (PVOID)skb->data;
	// Check for virtual address allocation, it might fail !!!
	if (pVirtualAddress == NULL)
	{
		DBGPRINT(RT_DEBUG_TRACE,"<---RTUSBSendPacket NULL pVirtualAddress\n");
		// Resourece is low, system did not allocation virtual address
		// return NDIS_STATUS_FAILURE directly to upper layer
		return (Status);
	}

	//
	// Check for multicast or broadcast (First byte of DA)
	//
	if ((*((PUCHAR) pVirtualAddress) & 0x01) != 0)
	{
		// For multicast & broadcast, there is no fragment allowed
		NumberOfFrag = 1;
	}
	else
	{
		// Check for payload allowed for each fragment
		AllowFragSize = (pAdapter->PortCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;

		// Calculate fragments required
		NumberOfFrag = ((skb->data_len - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
		// Minus 1 if the size just match to allowable fragment size
		if (((skb->data_len - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
		{
			NumberOfFrag--;
		}
	}
	
	// Check for requirement of RTS 
	if (NumberOfFrag > 1)
	{
		// If multiple fragment required, RTS is required only for the first fragment
		// if the fragment size large than RTS threshold
		RTSRequired = (pAdapter->PortCfg.FragmentThreshold > pAdapter->PortCfg.RtsThreshold) ? 1 : 0;
	}
	else
	{
		RTSRequired = (skb->data_len > pAdapter->PortCfg.RtsThreshold) ? 1 : 0;
	}

	// RTS/CTS may also be required in order to protect OFDM frame
	if ((pAdapter->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && pAdapter->PortCfg.BGProtectionInUsed)
		RTSRequired = 1;
	//DBGPRINT(RT_DEBUG_TEMP, "Number of fragments :%d , include RTS :%d\n", NumberOfFrag, NumberOfFrag + RTSRequired);
        
	// Save framnet number to Ndis packet reserved field
	RTMP_SET_PACKET_FRAGMENTS(skb, NumberOfFrag);	     

	// Save RTS requirement to Ndis packet reserved field
	RTMP_SET_PACKET_RTS(skb, RTSRequired);

	// Make sure SendTxWait queue resource won't be used by other threads
	NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock);

	pTxQueue = &pAdapter->SendTxWaitQueue;
	if (INFRA_ON(pAdapter))
	{
		if(pTxQueue->Number > MAX_PACKETS_IN_QUEUE)
		    { 
		        DBGPRINT(RT_DEBUG_WARN, "pTxQueue is full!!!\n\n");
		        pAdapter->bNetDeviceStopQueue = TRUE;
		        netif_stop_queue(pAdapter->net);
		    }
		 
		// In infrastructure mode, simply enqueue the packet into Tx waiting queue.
		DBGPRINT(RT_DEBUG_INFO, "Infrastructure -> Enqueue one frame\n");

		// Enqueue Ndis packet to end of Tx wait queue
		InsertTailQueue(pTxQueue, skb);
		Status = NDIS_STATUS_SUCCESS;
	}
	else
	{
		if(pTxQueue->Number > MAX_PACKETS_IN_QUEUE)
		{
			DBGPRINT(RT_DEBUG_WARN, "pTxQueue is full!!!\n");
			pAdapter->bNetDeviceStopQueue = TRUE;
			netif_stop_queue(pAdapter->net);
		}

		// In IBSS mode, power state of destination should be considered.
		PsMode = PWR_ACTIVE;		// Faked
		if (PsMode == PWR_ACTIVE)
		{
			// Enqueue Ndis packet to end of Tx wait queue
			InsertTailQueue(pTxQueue, skb);
			Status = NDIS_STATUS_SUCCESS;
		}
	}
	
	NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock);
	return Status;
}

VOID	RTUSBDeQueuePacket(
	IN	PRT2570ADAPTER	pAdapter)
{

	UCHAR			FragmentRequired;
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
	struct sk_buff  *skb;
	PQUEUE_HEADER	pQueue;
	UCHAR			Count = 0;
	// Make sure SendTxWait queue resource won't be used by other threads
	NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock);

	// Select Queue
	pQueue = &pAdapter->SendTxWaitQueue;

	// Check queue before dequeue
	while ((pQueue->Head != NULL) && (Count < MAX_TX_PROCESS))
	{
		// Reset is in progress, stop immediately
		if ( RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
			 RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS) ||
		     RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS))
		{
			break;
		}
			
		// Dequeue the first entry from head of queue list
		skb = (struct sk_buff *)RemoveHeadQueue(pQueue);


		// RTS or CTS-to-self for B/G protection mode has been set already.
		// There is no need to re-do it here. 
		// Total fragment required = number of fragment + RST if required
		FragmentRequired = RTMP_GET_PACKET_FRAGMENTS(skb) + RTMP_GET_PACKET_RTS(skb);
		
		if (RTUSBFreeDescriptorRequest(pAdapter, TX_RING, FragmentRequired) == NDIS_STATUS_SUCCESS)
		{
			// Avaliable ring descriptors are enough for this frame
			// Call hard transmit
			// Nitro mode / Normal mode selection
			NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock);
			if (pAdapter->PortCfg.EnableTxBurst == 1)
				Status = RTUSBHardEncrypt(pAdapter, skb, FragmentRequired, TRUE);
			else				
				Status = RTUSBHardEncrypt(pAdapter, skb, FragmentRequired, FALSE);
			//
			// Acquire the resource again, snice we may need to process it in this while-loop.
			//
			NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock);
			if (Status == NDIS_STATUS_FAILURE)
			{
				// Packet failed due to various Ndis Packet error
				RTUSBFreeSkbBuffer(skb);
				break;
			}
			else if (Status == NDIS_STATUS_RESOURCES)
			{
				// Not enough free tx ring, it might happen due to free descriptor inquery might be not correct
				// It also might change to NDIS_STATUS_FAILURE to simply drop the frame
				// Put the frame back into head of queue
				InsertHeadQueue(pQueue, skb);
				break;
			}			
			Count++;
		}	
		else
		{
			InsertHeadQueue(pQueue, skb);
			break;
		}
	}
	
	NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock);
	return;
	
}

NDIS_STATUS	RTUSBFreeDescriptorRequest(
	IN		PRT2570ADAPTER	pAdapter,
	IN		UCHAR			RingType,
	IN		UCHAR			NumberRequired)
{
	UCHAR			FreeNumber = 0;
	UINT			Index;
	NDIS_STATUS		Status = NDIS_STATUS_FAILURE;

	switch (RingType)
	{
		case TX_RING:
			Index = pAdapter->NextTxIndex;
			do
			{
				PTX_CONTEXT	pTxD  = &pAdapter->TxContext[Index];
				
				// While Owner bit is NIC, obviously ASIC still need it.
				// If valid bit is TRUE, indicate that TxDone has not process yet
				// We should not use it until TxDone finish cleanup job
				if (pTxD->InUse == FALSE)
				{
					// This one is free
					FreeNumber++;
				}
				else
				{
					break;
				}					
				Index = (Index + 1) % TX_RING_SIZE;				
			}	while (FreeNumber < NumberRequired);	// Quit here ! Free number is enough !
			
			if (FreeNumber >= NumberRequired)
			{
				Status = NDIS_STATUS_SUCCESS;
			}
			
			break;
			
		case PRIO_RING:
			Index = pAdapter->NextMLMEIndex;
			do
			{
				PTX_CONTEXT	pTxD  = &pAdapter->MLMEContext[Index];
				
				// While Owner bit is NIC, obviously ASIC still need it.
				// If valid bit is TRUE, indicate that TxDone has not process yet
				// We should not use it until TxDone finish cleanup job
				if (pTxD->InUse == FALSE)
				{
					// This one is free
					FreeNumber++;
				}
				else
				{
					break;
				}
					
				Index = (Index + 1) % PRIO_RING_SIZE;				
			}	while (FreeNumber < NumberRequired);	// Quit here ! Free number is enough !
			
			if (FreeNumber >= NumberRequired)
			{
				Status = NDIS_STATUS_SUCCESS;
			}
			break;

		default:
			break;


	
	}

	return (Status);

⌨️ 快捷键说明

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