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

📄 rtusb_data.c

📁 经过修改的在uClinux2.6上正常运行的ralink rt2571芯片组的设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
	*pDestTxD = TxD;
	pTxD = pDestTxD;
#endif
	RTUSBWriteTxDescriptor(pAd, pTxD, CIPHER_NONE, 0,0, AckRequired, FALSE, FALSE, SHORT_RETRY,
			IFS_BACKOFF, MlmeRate, /*Length+4*/ Length, QueIdx, PID_MGMT_FRAME, FALSE);


	// Build our URB for USBD
	TransferBufferLength = sizeof(TXD_STRUC) + Length;
	if ((TransferBufferLength % 2) == 1)
		TransferBufferLength++;

	
	if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0)
		TransferBufferLength += 2;
	
	pMLMEContext->BulkOutSize = TransferBufferLength;
	RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
	
	DBGPRINT(RT_DEBUG_INFO, "<---MlmeHardTransmit\n");
}

/*
	========================================================================

	Routine	Description:
		This subroutine will scan through releative ring descriptor to find
		out avaliable free ring descriptor and compare with request size.
		
	Arguments:
		pAd			Pointer	to our adapter
		RingType	Selected Ring
		
	Return Value:
		NDIS_STATUS_FAILURE		Not enough free descriptor
		NDIS_STATUS_SUCCESS		Enough free descriptor

	Note:
	
	========================================================================
*/
NDIS_STATUS	RTUSBFreeDescriptorRequest(
	IN	PRTMP_ADAPTER	pAd,
	IN	UCHAR			RingType,
	IN	UCHAR			BulkOutPipeId,
	IN	UCHAR			NumberRequired)
{
	UCHAR			FreeNumber = 0;
	UINT			Index;
	NDIS_STATUS		Status = NDIS_STATUS_FAILURE;

	switch (RingType)
	{
		case TX_RING:
			Index = (pAd->NextTxIndex[BulkOutPipeId] + 1) % TX_RING_SIZE;
			do
			{
				PTX_CONTEXT	pTxD  = &pAd->TxContext[BulkOutPipeId][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 = pAd->NextMLMEIndex;
			do
			{
				PTX_CONTEXT	pTxD  = &pAd->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:
			DBGPRINT_RAW(RT_DEBUG_ERROR, "--->RTUSBFreeDescriptorRequest() -----!! \n");
			
			break;
	}
	
	return (Status);
}

/*
	========================================================================
	
	Routine Description:

	Arguments:

	Return Value:
	
	Note:
	
	========================================================================
*/
VOID	RTUSBRejectPendingPackets(
	IN	PRTMP_ADAPTER	pAd)
{		
	UCHAR			Index;
	PQUEUE_HEADER	pQueue;
	struct sk_buff	*skb;
	ULONG			IrqFlags;
	
	DBGPRINT_RAW(RT_DEBUG_TRACE, "--->RejectPendingPackets\n");

	for (Index = 0; Index < 4; Index++)
	{
		NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[Index], IrqFlags);
		while (pAd->SendTxWaitQueue[Index].Head != NULL)
		{		
			pQueue = (PQUEUE_HEADER) &(pAd->SendTxWaitQueue[Index]);

			skb = (struct sk_buff *)RemoveHeadQueue(pQueue);
			RTUSBFreeSkbBuffer(skb);
		}
		NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[Index], IrqFlags);
	}
	
	DBGPRINT_RAW(RT_DEBUG_TRACE, "<---RejectPendingPackets\n");
}

/*
	========================================================================
	
	Routine	Description:
		Calculates the duration which is required to transmit out frames 
	with given size and specified rate.
		
	Arguments:
		pTxD		Pointer to transmit descriptor
		Ack			Setting for Ack requirement bit
		Fragment	Setting for Fragment bit
		RetryMode	Setting for retry mode
		Ifs			Setting for IFS gap
		Rate		Setting for transmit rate
		Service		Setting for service
		Length		Frame length
		TxPreamble	Short or Long preamble when using CCK rates
		QueIdx - 0-3, according to 802.11e/d4.4 June/2003
		
	Return Value:
		None
		
	========================================================================
*/
VOID	RTUSBWriteTxDescriptor(
	IN	PRTMP_ADAPTER pAd,
	IN	PTXD_STRUC	pSourceTxD,
	IN	UCHAR		CipherAlg,
	IN	UCHAR		KeyTable,
	IN	UCHAR		KeyIdx,
	IN	BOOLEAN		Ack,
	IN	BOOLEAN		Fragment,
	IN	BOOLEAN 	InsTimestamp,
	IN	UCHAR		RetryMode,
	IN	UCHAR		Ifs,
	IN	UINT		Rate,
	IN	ULONG		Length,
	IN	UCHAR		QueIdx,
	IN	UCHAR		PID,
	IN	BOOLEAN		bAfterRTSCTS)
{
	UINT	Residual;

	PTXD_STRUC		pTxD;
	
#ifndef BIG_ENDIAN
	pTxD = pSourceTxD;
#else
	TXD_STRUC		TxD;
	
	TxD = *pSourceTxD;
	pTxD = &TxD;
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif


	pTxD->HostQId	  = QueIdx;
	pTxD->MoreFrag	  = Fragment;
	pTxD->ACK		  = Ack;
	pTxD->Timestamp   = InsTimestamp;
	pTxD->RetryMd	  = RetryMode;
	pTxD->Ofdm		  = (Rate < RATE_FIRST_OFDM_RATE)? 0:1;
	pTxD->IFS		  = Ifs;
	pTxD->PktId 	  = PID;
	pTxD->Drop		  = 1;	 // 1:valid, 0:drop
	pTxD->HwSeq 	  = 1;	  // (QueIdx == QID_MGMT)? 1:0; 
	pTxD->BbpTxPower  = DEFAULT_BBP_TX_POWER; // TODO: to be modified
	pTxD->DataByteCnt = Length;
	
	RTMPCckBbpTuning(pAd, Rate);
	
	// fill encryption related information, if required
	pTxD->CipherAlg   = CipherAlg;
	if (CipherAlg != CIPHER_NONE)
	{
		pTxD->KeyTable	  = KeyTable;
		pTxD->KeyIndex	  = KeyIdx;
		pTxD->TkipMic	  = 1;
	}

	// In TKIP+fragmentation. TKIP MIC is already appended by driver. MAC needs not generate MIC
	if (CipherAlg == CIPHER_TKIP_NO_MIC)
	{
		pTxD->CipherAlg   = CIPHER_TKIP;
		pTxD->TkipMic	  = 0;	 // tell MAC need not insert TKIP MIC
	}

	
	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
	{	 
		if ((pAd->PortCfg.APEdcaParm.bValid) && (QueIdx <= QID_AC_VO))
		{
			pTxD->Cwmin = pAd->PortCfg.APEdcaParm.Cwmin[QueIdx];
			pTxD->Cwmax = pAd->PortCfg.APEdcaParm.Cwmax[QueIdx];
			pTxD->Aifsn = pAd->PortCfg.APEdcaParm.Aifsn[QueIdx];
		}
		else
		{
			DBGPRINT(RT_DEBUG_ERROR," WMM in used but EDCA not valid ERROR !!\n)");
		}
	}
	else
	{   
        if (bAfterRTSCTS)
        {
            // After RTS/CTS frame, data frame should use SIFS time.
            // To patch this code, add the following code.
            // Recommended by Jerry 2005/07/25 for WiFi testing with Proxim AP
            pTxD->Cwmin = 0;
            pTxD->Cwmax = 0;
            pTxD->Aifsn = 1;
            pTxD->IFS = IFS_BACKOFF;
        }   
        else
        {
            pTxD->Cwmin = CW_MIN_IN_BITS;
            pTxD->Cwmax = CW_MAX_IN_BITS;
            pTxD->Aifsn = 2;
	    }
	}

	// fill up PLCP SIGNAL field
	pTxD->PlcpSignal = RateIdToPlcpSignal[Rate];
	if (((Rate == RATE_2) || (Rate == RATE_5_5) || (Rate == RATE_11)) && 
		(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)))
	{
		pTxD->PlcpSignal |= 0x0008;
	}

	// fill up PLCP SERVICE field, not used for OFDM rates
	pTxD->PlcpService = 4; // Service;

	// file up PLCP LENGTH_LOW and LENGTH_HIGH fields
	Length += LENGTH_CRC;	// CRC length
	switch (CipherAlg) 
	{
		case CIPHER_WEP64:		 Length += 8;	 break;  // IV + ICV
		case CIPHER_WEP128: 	 Length += 8;	 break;  // IV + ICV
		case CIPHER_TKIP:		 Length += 20;	 break;  // IV + EIV + MIC + ICV
		case CIPHER_AES:		 Length += 16;	 break;  // IV + EIV + MIC
		case CIPHER_CKIP64: 	 Length += 8;	 break;  // IV + CMIC + ICV, but CMIC already inserted by driver
		case CIPHER_CKIP128:	 Length += 8;	 break;  // IV + CMIC + ICV, but CMIC already inserted by driver
		case CIPHER_TKIP_NO_MIC: Length += 12;	 break;  // IV + EIV + ICV
		default:								 break;
	}
 
	if (Rate < RATE_FIRST_OFDM_RATE)	// 11b - RATE_1, RATE_2, RATE_5_5, RATE_11
	{
		if ((Rate == RATE_1) || ( Rate == RATE_2))
		{
			Length = Length * 8 / (Rate + 1);
		}
		else
		{
			Residual = ((Length * 16) % (11 * (1 + Rate - RATE_5_5)));
			Length = Length * 16 / (11 * (1 + Rate - RATE_5_5));
			if (Residual != 0)
			{
				Length++;
			}
			if ((Residual <= (3 * (1 + Rate - RATE_5_5))) && (Residual != 0))
			{
				if (Rate == RATE_11)			// Only 11Mbps require length extension bit
					pTxD->PlcpService |= 0x80; // 11b's PLCP Length extension bit
			}
		}

		pTxD->PlcpLengthHigh = Length >> 8; // 256;
		pTxD->PlcpLengthLow = Length % 256;
	}
	else	// OFDM - RATE_6, RATE_9, RATE_12, RATE_18, RATE_24, RATE_36, RATE_48, RATE_54
	{
		pTxD->PlcpLengthHigh = Length >> 6; // 64;	// high 6-bit of total byte count
		pTxD->PlcpLengthLow = Length % 64;	 // low 6-bit of total byte count
	}
	
	pTxD->Burst  = Fragment;
	pTxD->Burst2 = pTxD->Burst;

#ifdef BIG_ENDIAN
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
	WriteBackToDescriptor((PUCHAR)pSourceTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
#endif
}

/*
	========================================================================

	Routine	Description:
		To do the enqueue operation and extract the first item of waiting 
		list. If a number of available shared memory segments could meet 
		the request of extracted item, the extracted item will be fragmented
		into shared memory segments.
		
	Arguments:
		pAd			Pointer	to our adapter
		pQueue		Pointer to Waiting Queue
		
	Return Value:
		None

	Note:
	
	========================================================================
*/
VOID	RTMPDeQueuePacket(
	IN	PRTMP_ADAPTER	pAd,
	IN	UCHAR			BulkOutPipeId)
{
	struct sk_buff	*pSkb;
	UCHAR			FragmentRequired;
	NDIS_STATUS		Status;
	UCHAR			Count = 0;
	PQUEUE_HEADER	pQueue;
	UCHAR			QueIdx;
	ULONG			IrqFlags;

	NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
	if (pAd->DeQueueRunning[BulkOutPipeId])
	{
		NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
		return;
	}
	else
	{
		pAd->DeQueueRunning[BulkOutPipeId] = TRUE;
		NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
	}

	QueIdx = BulkOutPipeId;
	
	if (pAd->TxRingTotalNumber[BulkOutPipeId])
		DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d TxRingTotalNumber= %d !!--\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId]);
		
	// Make sure SendTxWait queue resource won't be used by other threads 
	NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);

	// Select Queue
	pQueue = &pAd->SendTxWaitQueue[BulkOutPipeId];
		
	// Check queue before dequeue
	while ((pQueue->Head != NULL) && (Count < MAX_TX_PROCESS))
	{		
		// Reset is in progress, stop immediately
		if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
			 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
			 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
		{
			DBGPRINT(RT_DEBUG_ERROR,"--RTMPDeQueuePacket %d reset-in-progress !!--\n", BulkOutPipeId);
			break;
		}
			
		// Dequeue the first entry from head of queue list
		pSkb = (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(pSkb) + RTMP_GET_PACKET_RTS(pSkb);
		
		if ((RTUSBFreeDescriptorRequest(pAd, TX_RING, BulkOutPipeId, FragmentRequired) == NDIS_STATUS_SUCCESS)) 
		{
			// Avaliable ring descriptors are enough for this frame
			// Call hard transmit
			// Nitro mode / Normal mode selection

⌨️ 快捷键说明

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