📄 rtusb_data.c
字号:
} 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; } } }#ifdef BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pBuffer, DIR_WRITE, FALSE);#endif 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); *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); #ifdef DBG {#if 0 UINT i; PUCHAR ptr = (PUCHAR)pDestTxD; DBGPRINT(RT_DEBUG_TRACE, "pAd->NextMLMEIndex = %d *pDestTxD :\n", pAd->NextMLMEIndex); DBGPRINT(RT_DEBUG_TRACE, "ptr = %d\n",ptr); for (i=0;i<64; i+=16) { DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x - %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", *ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5),*(ptr+6),*(ptr+7), *(ptr+8),*(ptr+9),*(ptr+10),*(ptr+11),*(ptr+12),*(ptr+13),*(ptr+14),*(ptr+15)); ptr += 16; }#endif }#endif // 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; pMLMEContext->bWaitingBulkOut = TRUE; RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); pAd->PrioRingTxCnt++;//2007/12/24:WY fixed queeue full bug //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; unsigned long 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; unsigned long IrqFlags; NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags); if (pAd->DeQueueRunning[BulkOutPipeId]) { NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags); return; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -