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

📄 rtusb_data.c

📁 经过修改的在uClinux2.6上正常运行的ralink rt2571芯片组的设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
			
			NdisMoveMemory(&pTxD->Iv, &Iv16, 4);	// Copy IV
			NdisMoveMemory(&pTxD->Eiv, &Iv32, 4);	// Copy EIV
			INC_TX_TSC(pKey->TxTsc);				// Increase TxTsc for next transmission
		}


		//
		// STEP 5.3 COPY 802.11 HEADER INTO 1ST DMA BUFFER
		//
		pDest = pWirelessPacket;
		NdisMoveMemory(pDest, &Header_802_11, sizeof(Header_802_11));
		pDest		+= sizeof(Header_802_11);

		//
		// Fragmentation is not allowed on multicast & broadcast
		// So, we need to used the MAX_FRAG_THRESHOLD instead of pAd->PortCfg.FragmentThreshold
		// otherwise if pSkb->len > pAd->PortCfg.FragmentThreshold then
		// packet will be fragment on multicast & broadcast.
		//
		// MpduRequired equals to 1 means this could be Aggretaion case.
		//
		if ((Header_802_11.Addr1[0] & 0x01) || MpduRequired == 1)
		{
			FreeMpduSize = MAX_FRAG_THRESHOLD - sizeof(Header_802_11) - LENGTH_CRC;
		}
		else
		{
			FreeMpduSize = pAd->PortCfg.FragmentThreshold - sizeof(Header_802_11) - LENGTH_CRC;
		}

#if 0
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
		{
			// copy QOS CONTROL bytes
			*pDest		  =  (UserPriority & 0x0f) | pAd->PortCfg.AckPolicy[QueIdx];
			*(pDest+1)	  =  0;
			pDest		  += 2;
			FreeMpduSize  -= 2;
			if (pAd->PortCfg.AckPolicy[QueIdx] != NORMAL_ACK)
			{
				bAckRequired = FALSE;
			}
		}
#endif

		//
		// STEP 5.4 COPY LLC/SNAP, CKIP MIC INTO 1ST DMA BUFFER ONLY WHEN THIS 
		//			MPDU IS THE 1ST OR ONLY FRAGMENT 
		//
		if (Header_802_11.Frag == 0)
		{
			if (pExtraLlcSnapEncap)
			{
				if ((CipherAlg == CIPHER_TKIP_NO_MIC) && (pKey != NULL))
				{
					// Calculate MSDU MIC Value
					RTMPCalculateMICValue(pAd, pSkb, pExtraLlcSnapEncap, pKey);
				}
				
				// Insert LLC-SNAP encapsulation
				NdisMoveMemory(pDest, pExtraLlcSnapEncap, 6);
				pDest += 6;
				NdisMoveMemory(pDest, pSrcBufVA + 12, 2);
				pDest += 2;
				pSrcBufVA += LENGTH_802_3;
				FreeMpduSize -= LENGTH_802_1_H;
			
			}
			else
			{
				if ((CipherAlg == CIPHER_TKIP_NO_MIC) && (pKey != NULL))
				{
					// Calculate MSDU MIC Value
					RTMPCalculateMICValue(pAd, pSkb, pExtraLlcSnapEncap, pKey);
				}
				pSrcBufVA += LENGTH_802_3;
			}
		}

		// Start copying payload
		BytesCopied = 0;
		do
		{
			if (SrcBufLen >= FreeMpduSize)
			{
				// Copy only the free fragment size, and save the pointer
				// of current buffer descriptor for next fragment buffer.
				NdisMoveMemory(pDest, pSrcBufVA, FreeMpduSize);
				BytesCopied += FreeMpduSize;
				pSrcBufVA	+= FreeMpduSize;
				pDest		+= FreeMpduSize;
				SrcBufLen	-= FreeMpduSize;
				break;
			}
			else
			{
				// Copy the rest of this buffer descriptor pointed data
				// into ring buffer.
				NdisMoveMemory(pDest, pSrcBufVA, SrcBufLen);
				BytesCopied  += SrcBufLen;
				pDest		 += SrcBufLen;
				FreeMpduSize -= SrcBufLen;
			}
			
			// No more buffer descriptor
			// Add MIC value if needed

			//if ((pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) && 
			//	(MICFrag == FALSE) &&
			//	(pKey != NULL))

			if((CipherAlg == CIPHER_TKIP_NO_MIC) &&
			   (MICFrag == FALSE) &&
				(pKey != NULL))
			{
				// Fregment and TKIP//
				INT i;

				SrcBufLen = 8;		// Set length to MIC length
				DBGPRINT_RAW(RT_DEBUG_INFO, "Calculated TX MIC value =");  
				for (i = 0; i < 8; i++)
				{
					DBGPRINT_RAW(RT_DEBUG_INFO, "%02x:", pAd->PrivateInfo.Tx.MIC[i]);  
				}
					DBGPRINT_RAW(RT_DEBUG_INFO, "\n"); 
								
				if (FreeMpduSize >= SrcBufLen)
				{
					NdisMoveMemory(pDest, pAd->PrivateInfo.Tx.MIC, SrcBufLen);
					BytesCopied  += SrcBufLen;
					pDest		 += SrcBufLen;
					FreeMpduSize -= SrcBufLen;
					SrcBufLen = 0;
				}
				else
				{
					NdisMoveMemory(pDest, pAd->PrivateInfo.Tx.MIC, FreeMpduSize);
					BytesCopied  += FreeMpduSize;
					pSrcBufVA	  = pAd->PrivateInfo.Tx.MIC + FreeMpduSize;
					pDest		 += FreeMpduSize;
					SrcBufLen	 -= FreeMpduSize;
					MICFrag 	  = TRUE;
				}						
			}
		}	while (FALSE); // End of copying payload   
				
		// Real packet size, No 802.1H header for fragments except the first one.
		if ((StartOfFrame == TRUE) && (pExtraLlcSnapEncap != NULL))
		{
			TxSize = BytesCopied + LENGTH_802_11 + LENGTH_802_1_H + LengthQosPAD;
		}
		else
		{
			TxSize = BytesCopied + LENGTH_802_11 + LengthQosPAD;
		}

		SrcRemainingBytes -=  BytesCopied;
	
		//
		// STEP 5.6 MODIFY MORE_FRAGMENT BIT & DURATION FIELD. WRITE TXD
		//
		pHeader80211 = (PHEADER_802_11)pWirelessPacket;
		if (SrcRemainingBytes > 0) // more fragment is required
		{
			 ULONG NextMpduSize;

			 pHeader80211->FC.MoreFrag = 1;
			 NextMpduSize = min((ULONG)SrcRemainingBytes, (ULONG)pAd->PortCfg.FragmentThreshold);

			 if (NextMpduSize < pAd->PortCfg.FragmentThreshold)
			 {
				// In this case, we need to include LENGTH_802_11 and LENGTH_CRC for calculating Duration.
				pHeader80211->Duration = (3 * pAd->PortCfg.Dsifs) + 
									(2 * AckDuration) + 
									RTMPCalcDuration(pAd, TxRate, NextMpduSize + EncryptionOverhead + LENGTH_802_11 + LENGTH_CRC);
			 }
			 else
			 {
				pHeader80211->Duration = (3 * pAd->PortCfg.Dsifs) + 
								(2 * AckDuration) + 
								RTMPCalcDuration(pAd, TxRate, NextMpduSize + EncryptionOverhead);
			 }
			 
#ifdef BIG_ENDIAN
			RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
			RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
			*pDestTxD = TxD;
			pTxD = pDestTxD;
#endif
			RTUSBWriteTxDescriptor(pAd, pTxD, CipherAlg, 0, KeyIdx, bAckRequired, TRUE, FALSE, 
					RetryMode, FrameGap, TxRate, TxSize, QueIdx, 0, bRTS_CTSFrame);

			FrameGap = IFS_SIFS;	 // use SIFS for all subsequent fragments
			Header_802_11.Frag ++;	 // increase Frag #
		}
		else
		{
			pHeader80211->FC.MoreFrag = 0;
			if (pHeader80211->Addr1[0] & 0x01) // multicast/broadcast
				pHeader80211->Duration = 0;
			else
				pHeader80211->Duration = pAd->PortCfg.Dsifs + AckDuration;

			if ((bEAPOLFrame) && (TxRate > RATE_6))
				TxRate = RATE_6;
				
#ifdef BIG_ENDIAN
			RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
			RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
			*pDestTxD = TxD;
			pTxD = pDestTxD;
#endif 
			RTUSBWriteTxDescriptor(pAd, pTxD, CipherAlg, 0, KeyIdx, bAckRequired, FALSE, FALSE, 
					RetryMode, FrameGap, TxRate, TxSize, QueIdx, 0, bRTS_CTSFrame);

			if (pAd->SendTxWaitQueue[QueIdx].Number > 1)
				pTxD->Burst = 1;

		}

		TransferBufferLength = TxSize + sizeof(TXD_STRUC);

		if ((TransferBufferLength % 4) == 1)	
			TransferBufferLength  += 3;
		else if ((TransferBufferLength % 4) == 2)	
			TransferBufferLength  += 2;
		else if ((TransferBufferLength % 4) == 3)	
			TransferBufferLength  += 1;

		
		if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0)
			TransferBufferLength += 4;

		pTxContext->BulkOutSize = TransferBufferLength;
		pTxContext->bWaitingBulkOut = TRUE;
		RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
		
		// Set frame gap for the rest of fragment burst.
		// It won't matter if there is only one fragment (single fragment frame).
		StartOfFrame = FALSE;
		NumberRequired--;
		if (NumberRequired == 0)
		{
			pTxContext->LastOne = TRUE;
		}
		else
		{
			pTxContext->LastOne = FALSE;
		}
		
		pAd->TxRingTotalNumber[QueIdx]++;	// sync. to TxCount
		atomic_inc(&pAd->TxCount);
		
	}	while (NumberRequired > 0);


	//	
	// Check if MIC error twice within 60 seconds and send EAPOL MIC error to TX queue
	// then we enqueue a message for disasociating with the current AP
	//
 
	// Check for EAPOL frame sent after MIC countermeasures
	if (pAd->PortCfg.MicErrCnt >= 3)
	{
		MLME_DISASSOC_REQ_STRUCT	DisassocReq;

		// disassoc from current AP first
              printk("<0>MLME - disassociate with current AP after sending second continuous EAPOL frame\n");
		DBGPRINT(RT_DEBUG_TRACE, "MLME - disassociate with current AP after sending second continuous EAPOL frame\n");
		DisassocParmFill(pAd, &DisassocReq, pAd->PortCfg.Bssid, REASON_MIC_FAILURE);
		MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, 
					sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);

		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
		pAd->PortCfg.bBlockAssoc = TRUE;
		printk("<0>bBlockAssoc = %d\n", pAd->PortCfg.bBlockAssoc);
	}


	// release the skb buffer
	RELEASE_NDIS_PACKET(pAd, pSkb);

	return (NDIS_STATUS_SUCCESS);
}

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

	Routine	Description:
		Copy frame from waiting queue into relative ring buffer and set 
	appropriate ASIC register to kick hardware transmit function
	
	Arguments:
		pAd			Pointer	to our adapter
		pBuffer		Pointer to	memory of outgoing frame
		Length		Size of outgoing management frame
		
	Return Value:
		NDIS_STATUS_FAILURE
		NDIS_STATUS_PENDING
		NDIS_STATUS_SUCCESS

	Note:
	
	========================================================================
*/
VOID	RTUSBMlmeHardTransmit(
	IN	PRTMP_ADAPTER	pAd,
	IN	PMGMT_STRUC		pMgmt)
{
	PTX_CONTEXT		pMLMEContext;
	PTXD_STRUC		pTxD;
#ifdef BIG_ENDIAN
	PTXD_STRUC		pDestTxD;
	TXD_STRUC		TxD;
#endif
	PUCHAR			pDest;	
	PHEADER_802_11	pHeader_802_11;
	BOOLEAN 		AckRequired, InsertTimestamp;
	ULONG			TransferBufferLength;
	PVOID			pBuffer = pMgmt->pBuffer;
	ULONG			Length = pMgmt->Length;
	UCHAR			QueIdx;
	UCHAR			MlmeRate;
	
	DBGPRINT_RAW(RT_DEBUG_INFO, "--->MlmeHardTransmit\n");

	pAd->PrioRingTxCnt++;

	pMLMEContext = &pAd->MLMEContext[pAd->NextMLMEIndex];
	pMLMEContext->InUse = TRUE;

	// Increase & maintain Tx Ring Index
	pAd->NextMLMEIndex++;
	if (pAd->NextMLMEIndex >= PRIO_RING_SIZE)
	{
		pAd->NextMLMEIndex = 0;
	}

	pDest = pMLMEContext->TransferBuffer->WirelessPacket;			   
	
#ifndef BIG_ENDIAN
	pTxD = (PTXD_STRUC)(pMLMEContext->TransferBuffer);
#else
	pDestTxD  = (PTXD_STRUC)(pMLMEContext->TransferBuffer);
	TxD = *pDestTxD;
	pTxD = &TxD;
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif
	NdisZeroMemory(pTxD, sizeof(TXD_STRUC));

	pHeader_802_11 = (PHEADER_802_11) pBuffer;
    
	// Verify Mlme rate for a / g bands.
    if (pHeader_802_11->Addr1[0] & 0x01)
	{
		MlmeRate = pAd->PortCfg.BasicMlmeRate;
	}
	else
	{
		MlmeRate = pAd->PortCfg.MlmeRate;
	}

	if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
		MlmeRate = RATE_6;

	DBGPRINT(RT_DEBUG_TRACE, "<---MlmeRate %d	Channel %d\n",MlmeRate, pAd->LatchRfRegs.Channel );
	


    // Before radar detection done, mgmt frame can not be sent but probe req
	// Because we need to use probe req to trigger driver to send probe req in passive scan
	if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) && (pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
	{
		DBGPRINT(RT_DEBUG_ERROR, "RTUSBMlmeHardTransmit --> radar detect not in normal mode !!!\n");
		return;
	}


	if (pHeader_802_11->FC.PwrMgmt != PWR_SAVE)
	{
		pHeader_802_11->FC.PwrMgmt = (pAd->PortCfg.Psm == PWR_SAVE);
	}
	
	InsertTimestamp = FALSE;
	if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
	{
		AckRequired = FALSE;
	}
	else // BTYPE_MGMT or BMGMT_DATA(must be NULL frame)
	{
		pAd->Sequence		= ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
		pHeader_802_11->Sequence = pAd->Sequence;

		if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
		{
			INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
			AckRequired = FALSE;
			pHeader_802_11->Duration = 0;
		}
		else
		{
			AckRequired = TRUE;
			pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
			if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
			{
				InsertTimestamp = TRUE;
			}
		}
	}

	NdisMoveMemory(pDest, pBuffer, Length);

	// Initialize Priority Descriptor
	// For inter-frame gap, the number is for this frame and next frame
	// For MLME rate, we will fix as 2Mb to match other vendor's implement
	
	QueIdx = QID_AC_BE;

#ifdef BIG_ENDIAN
	RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);

⌨️ 快捷键说明

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