📄 cmm_data.c
字号:
// to the first scatter buffer size // // Initialize TX 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// pAd->CommonCfg.MlmeTransmit.field.MODE = 1; // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;// pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;#ifdef BIG_ENDIAN RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);#endif SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, PCI_DMA_TODEVICE); RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); pTxD->LastSec0 = 1; pTxD->LastSec1 = 1; pTxD->SDLen0 = SrcBufLen; pTxD->SDLen1 = 0; pTxD->SDPtr0 = SrcBufPA; pTxD->DMADONE = 0;#ifdef BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);#endif pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; // Increase TX_CTX_IDX, but write to register later. INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); // Make sure to release MGMT ring resource// NdisReleaseSpinLock(&pAd->TxRingLock); return NDIS_STATUS_SUCCESS;}NDIS_STATUS MlmeHardTransmitMgmtRing( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket){ PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; PTXD_STRUC pTxD;#ifdef BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD;#endif PHEADER_802_11 pHeader_802_11; BOOLEAN bAckRequired, bInsertTimestamp; ULONG SrcBufPA; //UCHAR TxBufIdx; UCHAR MlmeRate; ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; PTXWI_STRUC pFirstTxWI; UCHAR IrqState; //ULONG i; //HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); // Make sure MGMT ring resource won't be used by other threads IrqState = pAd->irq_disabled; if (!IrqState) RTMP_SEM_LOCK(&pAd->MgmtRingLock);#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;#else pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);#endif if (pSrcBufVA == NULL) { // The buffer shouldn't be NULL if (!IrqState) RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return NDIS_STATUS_FAILURE; } // outgoing frame always wakeup PHY to prevent frame lost // if (pAd->StaCfg.Psm == PWR_SAVE) if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) AsicForceWakeup(pAd); pFirstTxWI =(PTXWI_STRUC)pSrcBufVA; pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE); if (pHeader_802_11->Addr1[0] & 0x01) { MlmeRate = pAd->CommonCfg.BasicMlmeRate; } else { MlmeRate = pAd->CommonCfg.MlmeRate; } // Verify Mlme rate for a / g bands. if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band MlmeRate = RATE_6; // // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) // Snice it's been set to 0 while on MgtMacHeaderInit // By the way this will cause frame to be send on PWR_SAVE failed. // // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); // // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame#ifdef CONFIG_STA_SUPPORT // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD if (pHeader_802_11->FC.Type != BTYPE_DATA) {#endif // CONFIG_STA_SUPPORT // if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) { pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; } else { pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave; }#ifdef CONFIG_STA_SUPPORT }#endif // CONFIG_STA_SUPPORT // bInsertTimestamp = FALSE; if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL { bAckRequired = FALSE; } else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) { //pAd->Sequence++; //pHeader_802_11->Sequence = pAd->Sequence; if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST { bAckRequired = FALSE; pHeader_802_11->Duration = 0; } else { bAckRequired = TRUE; pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) { bInsertTimestamp = TRUE; } } } pHeader_802_11->Sequence = pAd->Sequence++; if (pAd->Sequence >0xfff) pAd->Sequence = 0; // 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->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); if (!IrqState) RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return (NDIS_STATUS_FAILURE); }#ifdef BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);#endif // // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET // should always has only one ohysical buffer, and the whole frame size equals // to the first scatter buffer size // // Initialize TX 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// pAd->CommonCfg.MlmeTransmit.field.MODE = 1; // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);// pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; // pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;#ifdef BIG_ENDIAN RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);#endif SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, PCI_DMA_TODEVICE); RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); pTxD->LastSec0 = 1; pTxD->LastSec1 = 1; pTxD->DMADONE = 0; pTxD->SDLen0 = SrcBufLen; pTxD->SDLen1 = 0; pTxD->SDPtr0 = SrcBufPA;#ifdef BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);#endif //==================================================================/* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n")); for (i = 0; i < (TXWI_SIZE+24); i++) { DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i))); if ( i%4 == 3) DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: ")); if ( i%16 == 15) DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n ")); } DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*///======================================================================= pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; // Increase TX_CTX_IDX, but write to register later. INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); // Make sure to release MGMT ring resource if (!IrqState) RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); return NDIS_STATUS_SUCCESS;}/* ======================================================================== 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 IRQL = DISPATCH_LEVEL Note: ========================================================================*/VOID RTMPDeQueuePacket( IN PRTMP_ADAPTER pAd, IN BOOLEAN bIntContext, IN UCHAR Max_Tx_Packets){ PQUEUE_ENTRY pEntry; PNDIS_PACKET pPacket; UCHAR MpduRequired; NDIS_STATUS Status; UCHAR Count=0; PQUEUE_HEADER pQueue; ULONG FreeNumber[NUM_OF_TX_RING]; //Number, FreeNumber[NUM_OF_TX_RING]; CHAR QueIdx; unsigned long IrqFlags = 0; UCHAR TxRate; DBGPRINT(RT_DEBUG_INFO,("RTMPDeQueuePacket (Tx:%d)--> \n", Max_Tx_Packets)); //Max_Tx_Packets = 32; for (QueIdx=0; QueIdx<=3; QueIdx++) { Count=0; while (1) { 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))) return; if (Count >= Max_Tx_Packets) { break; } if (bIntContext == FALSE) RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); //if ((pQueue = RTMPCheckTxSwQueue(pAd, &QueIdx)) != NULL) pQueue = &pAd->TxSwQueue[QueIdx]; if (pQueue->Head != NULL) { // probe the Queue Head pEntry = pQueue->Head; } else { if (bIntContext == FALSE) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); break; } // static rate also need NICUpdateFifoStaCounters() function. //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) NICUpdateFifoStaCounters(pAd); FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); pPacket = QUEUE_ENTRY_TO_PKT(pEntry); // 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 if required MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pPacket); TxRate = RTMP_GET_PACKET_TXRATE(pPacket); if (FreeNumber[QueIdx] <= 5) { // free Tx(QueIdx) resources RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); } // rough estimate we will use 3 more descriptor. if (FreeNumber[QueIdx] >= (ULONG)(MpduRequired+3)) { pEntry = RemoveHeadQueue(pQueue); // Enhance SW Aggregation Mechanism// if (pAd->CommonCfg.BACapability.field.AmsduEnable && ((FreeNumber[QueIdx] != (TX_RING_SIZE-1) && pAd->TxSwQueue[QueIdx].Number == 0) || (FreeNumber[QueIdx]<3))) if (((FreeNumber[QueIdx] != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (FreeNumber[QueIdx]<3)) { if ((pAd->CommonCfg.BACapability.field.AmsduEnable) || (pAd->CommonCfg.bAggregationCapable && (TxRate >= RATE_6) && (TxRate <= RATE_54))) { InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); DBGPRINT(RT_DEBUG_LOUD, ("Hw Q(%d) Free = %lu, Sw Qlen = %lu\n", QueIdx, FreeNumber[QueIdx], pAd->TxSwQueue[QueIdx].Number)); if (bIntContext == FALSE) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); break; } }#ifdef CONFIG_STA_SUPPORT // else Status = RTMPHardTransmit(pAd, pPacket, QueIdx, &FreeNumber[QueIdx]);#endif // CONFIG_STA_SUPPORT // if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_INFO,("RTMPHardTransmit return failed!!!\n")); if (bIntContext == FALSE) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); break; } } else { pAd->PrivateInfo.TxRingFullCnt++; DBGPRINT(RT_DEBUG_LOUD, ("Sw Q(%d) len = %lu\n", QueIdx, pAd->TxSwQueue[QueIdx].Number)); DBGPRINT(RT_DEBUG_INFO,("DeqPkt -> Not enough free TxD[%d] (TX_CTX_IDX=%lu, TxSwFreeIdx=%lu)!!!\n", QueIdx, pAd->TxRing[QueIdx].TxCpuIdx, pAd->TxRing[QueIdx].TxSwFreeIdx)); if (bIntContext == FALSE) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); break; } if (bIntContext == FALSE) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); Count++; }#ifdef BLOCK_NET_IF if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) && (pAd->TxSwQueue[QueIdx].Number < 1)) { releaseNetIf(&pAd->blockQueueTab[QueIdx]); }#endif // BLOCK_NET_IF // }}BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx){ PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD;#ifdef BIG_ENDIAN PTXD_STRUC pDestTxD;#endif PNDIS_PACKET pPacket; UCHAR FREE = 0; TXD_STRUC TxD, *pOriTxD; //ULONG IrqFlags; BOOLEAN bReschedule = FALSE; ASSERT(QueIdx < NUM_OF_TX_RING); pTxRing = &pAd->TxRing[QueIdx]; RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) {// RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);#ifdef RALINK_ATE#ifdef RALINK_2860_QA PHEADER_802_11 pHeader80211; if ((pAd->ate.Mode != ATE_STOP) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == QueIdx) { pAd->ate.TxDoneCount++; //pAd->ate.Repeat++; pAd->RalinkCounters.KickTxCount++; if (pAd->ate.QID == 0) pAd->ate.TxAc0++; else if (pAd->ate.QID == 1) pAd->ate.TxAc1++; else if (pAd->ate.QID == 2) pAd->ate.TxAc2++; else if (pAd->ate.QID == 3) pAd->ate.TxAc3++; else if (pAd->ate.QID == 4) pAd->ate.TxHCCA++; else if (pAd->ate.QID == 5) pAd->ate.TxMgmt++; pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -