📄 rtusb_data.c
字号:
RTMP_SET_PACKET_SOURCE(pSkb, PKTSRC_NDIS); pAd->RalinkCounters.PendingNdisPacketCount ++; Status = RTMPSendPacket(pAd, pSkb); if (Status != NDIS_STATUS_SUCCESS) { // Errors before enqueue stage RELEASE_NDIS_PACKET(pAd, pSkb); 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(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { for (Index = 0; Index < 4; Index++) { if(pAd->SendTxWaitQueue[Index].Number > 0) { RTMPDeQueuePacket(pAd, Index); } } } // Kick bulk out RTUSBKickBulkOut(pAd); DBGPRINT(RT_DEBUG_INFO, "<=== RTMPSendPackets\n"); return 0;}/* ======================================================================== Routine Description: Copy frame from waiting queue into relative ring buffer and set appropriate ASIC register to kick hardware encryption before really sent out to air. Arguments: pAd Pointer to our adapter PNDIS_PACKET Pointer to outgoing Ndis frame NumberOfFrag Number of fragment required Return Value: None Note: ========================================================================*/#ifdef BIG_ENDIAN static inline#endifNDIS_STATUS RTUSBHardTransmit( IN PRTMP_ADAPTER pAd, IN struct sk_buff *pSkb, IN UCHAR NumberRequired, IN UCHAR QueIdx){ UINT LengthQosPAD =0; UINT BytesCopied; UINT TxSize; UINT FreeMpduSize; UINT SrcRemainingBytes; USHORT Protocol; UCHAR FrameGap; HEADER_802_11 Header_802_11; PHEADER_802_11 pHeader80211; PUCHAR pDest;// PUCHAR pSrc; PTX_CONTEXT pTxContext; PTXD_STRUC pTxD;#ifdef BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD;#endif// PURB pUrb; BOOLEAN StartOfFrame; BOOLEAN bEAPOLFrame; ULONG Iv16; ULONG Iv32; BOOLEAN MICFrag;// PCIPHER_KEY pWpaKey = NULL; NDIS_802_11_WEP_STATUS EncryptType = Ndis802_11EncryptionDisabled; ULONG TransferBufferLength; USHORT AckDuration = 0; USHORT EncryptionOverhead = 0; UCHAR CipherAlg; BOOLEAN bAckRequired; UCHAR RetryMode = SHORT_RETRY; UCHAR UserPriority; UCHAR MpduRequired, RtsRequired; UCHAR TxRate; PCIPHER_KEY pKey = NULL ; PUCHAR pSrcBufVA = NULL; ULONG SrcBufLen; PUCHAR pExtraLlcSnapEncap = NULL; // NULL: no extra LLC/SNAP is required UCHAR KeyIdx, KeyLength = 0; UCHAR KeyTable = SHARED_KEY_TABLE; PUCHAR pWirelessPacket; ULONG NextMpduSize; BOOLEAN bRTS_CTSFrame = FALSE; unsigned long IrqFlags; //BensonLiu modify DBGPRINT(RT_DEBUG_INFO, "====> RTUSBHardTransmit\n"); if ((pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit --> radar detect not in normal mode !!!\n"); return (NDIS_STATUS_FAILURE); } TxRate = RTMP_GET_PACKET_TXRATE(pSkb); MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pSkb); RtsRequired = RTMP_GET_PACKET_RTS(pSkb); UserPriority = RTMP_GET_PACKET_UP(pSkb); // // Prepare packet information structure which will be query for buffer descriptor // pSrcBufVA = (PVOID)pSkb->data; SrcBufLen = pSkb->len; // Check for virtual address allocation, it might fail !!! if (pSrcBufVA == NULL) { DBGPRINT_RAW(RT_DEBUG_TRACE, "pSrcBufVA == NULL\n"); return(NDIS_STATUS_RESOURCES); } if (SrcBufLen < 14) { DBGPRINT_RAW(RT_DEBUG_ERROR, "RTUSBHardTransmit --> Skb buffer error !!!\n"); return (NDIS_STATUS_FAILURE); } // // If DHCP datagram or ARP datagram , we need to send it as Low rates. // if (pAd->PortCfg.Channel <= 14) { // // Case 802.11 b/g // basic channel means that we can use CCKM's low rate as RATE_1. // if ((TxRate != RATE_1) && RTMPCheckDHCPFrame(pAd, pSkb)) TxRate = RATE_1; } else { // // Case 802.11a // We must used OFDM's low rate as RATE_6, note RATE_1 is not allow // Only OFDM support on Channel > 14 // if ((TxRate != RATE_6) && RTMPCheckDHCPFrame(pAd, pSkb)) TxRate = RATE_6; } // ------------------------------------------ // STEP 0.1 Add 802.1x protocol check. // ------------------------------------------ // For non-WPA network, 802.1x message should not encrypt even privacy is on. if (NdisEqualMemory(EAPOL, pSrcBufVA + 12, 2)) { bEAPOLFrame = TRUE; if (pAd->PortCfg.MicErrCnt >= 2) pAd->PortCfg.MicErrCnt++; } else bEAPOLFrame = FALSE; // // WPA 802.1x secured port control - drop all non-802.1x frame before port secured // { if (((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)#if defined(RALINK_WPA_SUPPLICANT_SUPPORT) || defined(NATIVE_WPA_SUPPLICANT_SUPPORT) || (pAd->PortCfg.IEEE8021X == TRUE) #endif ) && ((pAd->PortCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->PortCfg.MicErrCnt >= 2)) && (bEAPOLFrame == FALSE)) { DBGPRINT_RAW(RT_DEBUG_INFO, "RTUSBHardTransmit --> Drop packet before port secured !!!\n"); return (NDIS_STATUS_FAILURE); } } if (*pSrcBufVA & 0x01) // Multicast or Broadcast { bAckRequired = FALSE; INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); EncryptType = pAd->PortCfg.GroupCipher; // Cipher for Multicast or Broadcast } else { bAckRequired = TRUE; EncryptType = pAd->PortCfg.PairCipher; // Cipher for Unicast } // 1. traditional TX burst if (pAd->PortCfg.bEnableTxBurst && (pAd->Sequence & 0x7)) FrameGap = IFS_SIFS; // 2. frame belonging to AC that has non-zero TXOP else if (pAd->PortCfg.APEdcaParm.bValid && pAd->PortCfg.APEdcaParm.Txop[QueIdx]) FrameGap = IFS_SIFS; // 3. otherwise, always BACKOFF before transmission else FrameGap = IFS_BACKOFF; // Default frame gap mode Protocol = *(pSrcBufVA + 12) * 256 + *(pSrcBufVA + 13); // if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required if (Protocol > 1500) { pExtraLlcSnapEncap = SNAP_802_1H; if (NdisEqualMemory(IPX, pSrcBufVA + 12, 2) || NdisEqualMemory(APPLE_TALK, pSrcBufVA + 12, 2)) { pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; } } else pExtraLlcSnapEncap = NULL; // Update software power save state OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); pAd->PortCfg.Psm = PWR_ACTIVE; // ----------------------------------------------------------------- // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. // ----------------------------------------------------------------- pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); MAKE_802_11_HEADER(pAd, Header_802_11, pSrcBufVA, pAd->Sequence); // -------------------------------------------------------- // STEP 3. FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM // Find the WPA key, either Group or Pairwise Key // LEAP + TKIP also use WPA key. // -------------------------------------------------------- // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst // In Cisco CCX 2.0 Leap Authentication // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey // Instead of the SharedKey, SharedKey Length may be Zero. KeyIdx = 0xff; KeyTable = SHARED_KEY_TABLE; if (bEAPOLFrame) { ASSERT(pAd->SharedKey[0].CipherAlg <= CIPHER_CKIP128); if ((pAd->SharedKey[0].CipherAlg) && (pAd->SharedKey[0].KeyLen) && ((pAd->PortCfg.PortSecured == WPA_802_1X_PORT_PASS_4_WAY) || (pAd->PortCfg.PortSecured == WPA_802_1X_PORT_SECURED))) { CipherAlg = pAd->SharedKey[0].CipherAlg; KeyIdx = 0; KeyLength = pAd->SharedKey[KeyIdx].KeyLen; } } else if (EncryptType == Ndis802_11Encryption1Enabled) { // standard WEP64 or WEP128 KeyIdx = pAd->PortCfg.DefaultKeyId; KeyLength = pAd->SharedKey[KeyIdx].KeyLen; } else if ((EncryptType == Ndis802_11Encryption2Enabled) || (EncryptType == Ndis802_11Encryption3Enabled)) { if (Header_802_11.Addr1[0] & 0x01) // multicast KeyIdx = pAd->PortCfg.DefaultKeyId; else if (pAd->SharedKey[0].KeyLen) KeyIdx = 0; else KeyIdx = pAd->PortCfg.DefaultKeyId; KeyLength = pAd->SharedKey[KeyIdx].KeyLen; } if (KeyIdx == 0xff) CipherAlg = CIPHER_NONE; else if ((EncryptType == Ndis802_11EncryptionDisabled) || (KeyLength == 0)) CipherAlg = CIPHER_NONE; else { Header_802_11.FC.Wep = 1; CipherAlg = pAd->SharedKey[KeyIdx].CipherAlg; pKey = &pAd->SharedKey[KeyIdx]; } DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit(bEAP=%d) - %s key#%d, KeyLen=%d\n", bEAPOLFrame, CipherName[CipherAlg], KeyIdx, pAd->SharedKey[KeyIdx].KeyLen); // STEP 3.1 if TKIP is used and fragmentation is required. Driver has to // append TKIP MIC at tail of the scatter buffer (This must be the // ONLY scatter buffer in the skb buffer). // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC if ((MpduRequired > 1) && (CipherAlg == CIPHER_TKIP)) { pSkb->len += 8; CipherAlg = CIPHER_TKIP_NO_MIC; } // ---------------------------------------------------------------- // STEP 4. Make RTS frame or CTS-to-self frame if required // ---------------------------------------------------------------- // // calcuate the overhead bytes that encryption algorithm may add. This // affects the calculate of "duration" field // if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; else if (CipherAlg == CIPHER_TKIP_NO_MIC) EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength else if (CipherAlg == CIPHER_TKIP) EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] else if (CipherAlg == CIPHER_AES) EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] else EncryptionOverhead = 0; // decide how much time an ACK/CTS frame will consume in the air AckDuration = RTMPCalcDuration(pAd, pAd->PortCfg.ExpectedACKRate[TxRate], 14); // If fragment required, MPDU size is maximum fragment size // Else, MPDU size should be frame with 802.11 header & CRC if (MpduRequired > 1) NextMpduSize = pAd->PortCfg.FragmentThreshold; else { NextMpduSize = pSkb->len + LENGTH_802_11 + LENGTH_CRC - LENGTH_802_3; if (pExtraLlcSnapEncap) NextMpduSize += LENGTH_802_1_H; } if (RtsRequired || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RTS_PROTECTION_ENABLE)) { RTMPSendRTSCTSFrame(pAd, Header_802_11.Addr1, NextMpduSize + EncryptionOverhead, TxRate, pAd->PortCfg.RtsRate, AckDuration, QueIdx, FrameGap, SUBTYPE_RTS); // RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS RetryMode = LONG_RETRY; FrameGap = IFS_SIFS; bRTS_CTSFrame = TRUE; if (RtsRequired) NumberRequired--; } else if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { RTMPSendRTSCTSFrame(pAd, Header_802_11.Addr1, NextMpduSize + EncryptionOverhead, TxRate, pAd->PortCfg.RtsRate, AckDuration, QueIdx, FrameGap, SUBTYPE_CTS); // RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS RetryMode = LONG_RETRY; FrameGap = IFS_SIFS; bRTS_CTSFrame = TRUE; } // -------------------------------------------------------- // STEP 5. START MAKING MPDU(s) // Start Copy Ndis Packet into Ring buffer. // For frame required more than one ring buffer (fragment), all ring buffers // have to be filled before kicking start tx bit. // Make sure TX ring resource won't be used by other threads // -------------------------------------------------------- SrcRemainingBytes = pSkb->len - LENGTH_802_3; SrcBufLen -= LENGTH_802_3; // skip 802.3 header StartOfFrame = TRUE; MICFrag = FALSE; // Flag to indicate MIC shall spread into two MPDUs NdisAcquireSpinLock(&pAd->TxRingLock, IrqFlags);//BensonLiu modify // Start Copy Ndis Packet into Ring buffer. // For frame required more than one ring buffer (fragment), all ring buffers // have to be filled before kicking start tx bit. do { // // STEP 5.1 Get the Tx Ring descriptor & Dma Buffer address // pTxContext = &pAd->TxContext[QueIdx][pAd->NextTxIndex[QueIdx]]; if ((pTxContext->bWaitingBulkOut == TRUE) || (pTxContext->InUse == TRUE) || (pAd->TxRingTotalNumber[QueIdx] >= TX_RING_SIZE)) { DBGPRINT_ERR("RTUSBHardTransmit: TX RING full\n"); pAd->RalinkCounters.TxRingErrCount++; NdisReleaseSpinLock(&pAd->TxRingLock, IrqFlags);//BensonLiu modify return (NDIS_STATUS_RESOURCES); } pTxContext->InUse = TRUE; // Increase & maintain Tx Ring Index pAd->NextTxIndex[QueIdx]++; if (pAd->NextTxIndex[QueIdx] >= TX_RING_SIZE) { pAd->NextTxIndex[QueIdx] = 0; }#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;#else pDestTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -