📄 rtusb_data.c
字号:
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(RT_DEBUG_ERROR, "--->RTUSBFreeDescriptorRequest() -----!! \n"); break; } return (Status);}/* ======================================================================== Routine Description: Arguments: Return Value: Note: ========================================================================*/VOID RTUSBRejectPendingPackets( IN PRTMP_ADAPTER pAd){ UCHAR Index; DBGPRINT(RT_DEBUG_TRACE, "--->RejectPendingPackets\n"); for (Index = 0; Index < 4; Index++) { skb_queue_purge(&pAd->SendTxWaitQueue[Index]); } DBGPRINT(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: Called only from process context, protected by the usb semaphore. ========================================================================*/VOID RTMPDeQueuePacket( IN PRTMP_ADAPTER pAd, IN UCHAR BulkOutPipeId){ struct sk_buff *pSkb; UCHAR FragmentRequired; NDIS_STATUS Status; UCHAR Count = 0; struct sk_buff_head *pQueue; UCHAR QueIdx; QueIdx = BulkOutPipeId; if (pAd->TxRingTotalNumber[BulkOutPipeId]) DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d TxRingTotalNumber= %d !!--\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId]); // Select Queue pQueue = &pAd->SendTxWaitQueue[BulkOutPipeId]; // Check queue before dequeue while (!skb_queue_empty(pQueue) && (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_HALT_IN_PROGRESS)) { DBGPRINT(RT_DEBUG_ERROR,"--RTMPDeQueuePacket %d reset-in-progress !!--\n", BulkOutPipeId); RTUSBFreeSkbBuffer(skb_dequeue(pQueue)); continue; } if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { DBGPRINT(RT_DEBUG_TRACE, "RTUSBDeQueuePacket scanning. Flags = 0x%x\n", pAd->Flags); break; } // Dequeue the first entry from head of queue list pSkb = skb_dequeue(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 Status = RTUSBHardTransmit(pAd, pSkb, FragmentRequired, QueIdx); if (Status == NDIS_STATUS_FAILURE) { // Packet failed due to various Ndis Packet error RTUSBFreeSkbBuffer(pSkb); 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 skb_queue_head(pQueue, pSkb); break; }else if(Status == NDIS_STATUS_RINGFULL){//Thomas add pAd->TxRingTotalNumber[QueIdx]= 0; RTUSBFreeSkbBuffer(pSkb); break; } Count++; } else { DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d queue full !! TxRingTotalNumber= %d !! FragmentRequired=%d !!\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId], FragmentRequired); skb_queue_head(pQueue, pSkb); pAd->PrivateInfo.TxRingFullCnt++; break; } }}VOID RTMPDeQueuePackets(IN PRTMP_ADAPTER pAd){ int Index; for (Index = 0; Index < 4; Index++) { if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && !skb_queue_empty(&pAd->SendTxWaitQueue[Index])) { RTMPDeQueuePacket(pAd, Index); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -