📄 rtmp_data.c
字号:
// STEP 6.1 And 1ST DMA BUFFER // //Save FirstTxWI. Need to fill MPDUtotlabytecount when finish pFirstTxWI = (PTXWI_STRUC)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); // need to fill MPDU total byte count field at last step pDMAHeaderBufPtr = pDMAHeaderBufVA; // // STEP 6.2 COPY TXWI and 802.11 HEADER INTO 1ST DMA BUFFER. IV/EIV will set by ASIC after searching on-chip WC table // NdisZeroMemory(pFirstTxWI, TXWI_SIZE); // bWIV==FALSE, then Driver doesn't need to fill IV/EIV, which is filled by FCE. //as Sta, the RA always is BSSID. So always use BSSID_WCID. // DHCP uses low rate if ((bDHCPFrame == TRUE) || (bEAPOLFrame == TRUE)) { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, FALSE, TXWIAMPDU, bAckRequired, FALSE, TXWIBAWinSize, RAWcid, 0,PID, UserPriority, TxRate, IFS_BACKOFF, bPiggyBack, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode); pAd->LastTxRate = (USHORT)(pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word); DBGPRINT_RAW(RT_DEBUG_INFO,("RTMPHardTransmit-DHCP packet uses MCS=%d, STBC=%d, ShortGI=%d, Mode=%d, BW=%d \n", pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS, pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.STBC, pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.ShortGI, pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MODE, pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.BW)); } else if ((ADHOC_ON(pAd)) && (RAWcid > BSSID_WCID)) // for different adhoc STA, we use the same HTPhyMode as (RAWcid=BSSID_WCID) { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, FALSE, TXWIAMPDU, bAckRequired, FALSE, TXWIBAWinSize, RAWcid, 0,PID, UserPriority, TxRate, FrameGap, bPiggyBack, &pAd->MacTab.Content[BSSID_WCID].HTPhyMode); pAd->LastTxRate = (USHORT)(pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word); } else { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, FALSE, TXWIAMPDU, bAckRequired, FALSE, TXWIBAWinSize, RAWcid, 0,PID, UserPriority, TxRate, FrameGap, bPiggyBack, &pAd->MacTab.Content[RAWcid].HTPhyMode); pAd->LastTxRate = (USHORT)(pAd->MacTab.Content[RAWcid].HTPhyMode.word); } pDMAHeaderBufPtr += TXWI_SIZE; NdisMoveMemory(pDMAHeaderBufPtr, &Header_802_11, sizeof(Header_802_11)); pDMAHeaderBufPtr += sizeof(Header_802_11); MpduSize = sizeof(Header_802_11); // // STEP 6.3 ACQUIRE TXD. Init Ndispacket = NULL. Because it TxD is not necessarily the lastsec //#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;#else pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD;#endif RING_PACKET_INIT(pTxRing, TxIdx); NdisZeroMemory(pTxD, TXD_SIZE); pTxD->DMADONE = 1; ptemp = (PULONG)pTxD;// RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); // 1st Buf always has TXWI+802.11header. This is preallocated DMABuf. But we need to reassign it every beginning of MPDU. //pTxD->SDPtr0 = BufBasePaLow; FreeTXDLeft--; // // Fragmentation is not allowed on multicast & broadcast. and is nether used in HT rate. // So, we need to used the MAX_FRAG_THRESHOLD instead of pAd->CommonCfg.FragmentThreshold // otherwise if PacketInfo.TotalPacketLength > pAd->CommonCfg.FragmentThreshold then // packet will be fragment on multicast & broadcast. // if ((*pSrcBufVA & 0x01) || (bAllowFrag == FALSE)) //(pAd->CommonCfg.HTPhyMode.field.MODE >= MODE_HTMIX)) { FreeMpduSize = MAX_AGGREGATION_SIZE - sizeof(Header_802_11) - LENGTH_CRC; } else { FreeMpduSize = pAd->CommonCfg.FragmentThreshold - sizeof(Header_802_11) - LENGTH_CRC; } // Note: if HT rate, WMM must inused. //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) if (bWMM) { // HT rate must has QOS CONTROL bytes if (bTXBA) *pDMAHeaderBufPtr = (UserPriority & 0x0f) ; else *pDMAHeaderBufPtr = (UserPriority & 0x0f) | pAd->CommonCfg.AckPolicy[QueIdx]; if (bAMSDU == TRUE) { *pDMAHeaderBufPtr |= 0x80; } *(pDMAHeaderBufPtr+1) = 0; pDMAHeaderBufPtr += 2; MpduSize += 2; FreeMpduSize -= 2; // Pad 2 bytes to make 802.11 header 4-byte alignment if (bHTC == TRUE) { // HTC Control field(4 bytes) is following QOS field, padding 2 bytes NdisZeroMemory(pDMAHeaderBufPtr, 6); if (pAd->CommonCfg.bRdg == TRUE) *(pDMAHeaderBufPtr+4)|=0x80; if (pAd->bLinkAdapt == TRUE) { //bit2MRQ=1. Request for MCS feedback *(pDMAHeaderBufPtr) |=0x4; // Set identifier as 2 *(pDMAHeaderBufPtr) |= ((pAd->MRS)<<3); } pDMAHeaderBufPtr += 6; MpduSize += 4; } else { // padding 2 bytes NdisZeroMemory(pDMAHeaderBufPtr, 2); pDMAHeaderBufPtr += 2; } } if (pNextPacket && (bAMSDU == FALSE)) { FreeMpduSize = MAX_AGGREGATION_SIZE; //software aggregation puts the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL. little endian // Handle Aggregation (A-MSUD for 11n station in HTMode or A-Ralink in Legacy 11g Ralink station, ) if (bARALINK) { // For RA Aggregation, // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format *pDMAHeaderBufPtr = (UCHAR)NextPacketBufLen & 0xff; *(pDMAHeaderBufPtr+1) = (UCHAR)(NextPacketBufLen >> 8); pDMAHeaderBufPtr += 2; MpduSize += 2; Header_802_11.FC.Order = 1; // steal "order" bit to mark "aggregation" } } if (bAMSDU) { /* A-MSDU format: DA + SA + Length + MSDU + Padding */ // // use 1st dma buffer to store subframe header // DA(6)+SA(6)+Len(2) // // build subframe header NdisMoveMemory(pDMAHeaderBufPtr, &AMSDUsubheader[0], 14); pDMAHeaderBufPtr += 14; MpduSize += 14; } // // 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 && (bAMSDU == FALSE)) if (pExtraLlcSnapEncap) {#ifdef CONFIG_CKIP_SUPPORT if ((pAd->StaCfg.CkipFlag & 0x08) && (bEAPOLFrame == FALSE)) { // CKIP_LLC_SNAP is inused. The frame format must be - // 802.11 header + CKIP_LLCSNAP(8) + MIC(4) + TxSEQ(4) + Proto(2) + Payload NdisMoveMemory(pDMAHeaderBufPtr, CKIP_LLC_SNAP, sizeof(CKIP_LLC_SNAP)); pDMAHeaderBufPtr += sizeof(CKIP_LLC_SNAP); // // 1.) Insert MIC [4] // RTMPCkipInsertCMIC(pAd, pDMAHeaderBufPtr, (PUCHAR)&Header_802_11, pPacket, pKey, CKIP_LLC_SNAP); pDMAHeaderBufPtr += 4 ; // // 2.) Insert TX Sequence. // NdisMoveMemory(pDMAHeaderBufPtr, pAd->StaCfg.TxSEQ, 4); pDMAHeaderBufPtr += 4; NdisMoveMemory(pDMAHeaderBufPtr, pSrcBufVA + 12, 2); pDMAHeaderBufPtr += 2; MpduSize += 10; FreeMpduSize -= (sizeof(CKIP_LLC_SNAP) + 10); // Update TxSEQ for next TX { int i = 3; pAd->StaCfg.TxSEQ[i] = pAd->StaCfg.TxSEQ[i] + 2; while (pAd->StaCfg.TxSEQ[i] == 0x00) { i--; if (i < 0) break; pAd->StaCfg.TxSEQ[i] ++; } } } else#endif /* CONFIG_CKIP_SUPPORT */ { // Insert LLC-SNAP encapsulation NdisMoveMemory(pDMAHeaderBufPtr, pExtraLlcSnapEncap, 6); pDMAHeaderBufPtr += 6; NdisMoveMemory(pDMAHeaderBufPtr, pSrcBufVA + 12, 2); pDMAHeaderBufPtr += 2; MpduSize += LENGTH_802_1_H; FreeMpduSize -= LENGTH_802_1_H; } } } // // set 1st header size into TX DESC // --- TxWI + 802.11 Header // --- if (!A-MSDU) // + LLC/SNAP Encap // else // + DA(6)+SA(6)+Len(2) // pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = (ULONG)(pDMAHeaderBufPtr - pDMAHeaderBufVA); // // STEP 5.5 TRAVERSE NDIS PACKET TO BUILD THE MPDU PAYLOAD // SrcBytesCopied = 0; // Inner while loop is for getting enough TXD to send this MPDU. // SDPNowUsed starts from 1 because WI and 802.11Header already use SDP0 of 1st TXD. SDPNowUsed = 1; IsSD0 = TRUE; do { // Assign Currently used TxD. SDPNowUsed ++; if (SrcBufLen <= FreeMpduSize) { // scatter-gather buffer still fit into current MPDU if (SrcBufLen != 0) { switch (SDPNowUsed%2) { case 1: { PUCHAR pSubHeader; UCHAR SDLen0 = 0; ASSERT(FreeTXDLeft); ASSERT(bAMSDU); ASSERT(pNextPacket); FreeTXDLeft--; INC_RING_INDEX(TxIdx, TX_RING_SIZE); // // AMSDU packet: 2nd subframe // // Init TxRing#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;#else //Swap the endian of old pTxD and prepare to handle next pTxD. RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD;#endif NdisZeroMemory(pTxD, TXD_SIZE); pTxD->DMADONE = 1; //RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); // // use 1st dma buffer to store sub-frame header // pervious sub-frame padding + DA(6) + SA(6) + Len(2) // BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pSubHeader = pTxRing->Cell[TxIdx].DmaBuf.AllocVa; if (bAMSDU) { ASSERT(padding < 4); pSubHeader += padding; // build sub-frame header NdisMoveMemory(pSubHeader, pNextPacketBufVA, 12); // if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required EXTRA_LLCSNAP_ENCAP(pNextPacketBufVA, pExtraLlcSnapEncap); SDLen0 = padding + 14; NextPacketBufLen -= LENGTH_802_3; if (pExtraLlcSnapEncap) { NextPacketBufLen += LENGTH_802_1_H; NdisMoveMemory(pSubHeader+14, pExtraLlcSnapEncap, 6); NdisMoveMemory(pSubHeader+14+6, pNextPacketBufVA+12, 2); SDLen0 += LENGTH_802_1_H; } pSubHeader[12] = (NextPacketBufLen & 0xFF00) >> 8; pSubHeader[13] = NextPacketBufLen & 0xFF; } else if (bARALINK) { NdisMoveMemory(pSubHeader , pNextPacketBufVA, 12); NdisMoveMemory(pSubHeader+12, pNextPacketBufVA+12, 2); SDLen0 = LENGTH_802_3; //Here we didn't need to subtract the VLAN tag length, because we do it in previous. NextPacketBufLen -= LENGTH_802_3; } // update MPDU size MpduSize += SDLen0; // build TX Desc pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = SDLen0; pTxD->SDPtr1 = SrcBufPA; pTxD->SDLen1 = SrcBufLen; //RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); //pTxD->DMADONE = 0; break;} case 0: pTxD->SDPtr1 = SrcBufPA; pTxD->SDLen1 = SrcBufLen; if (bAMSDU || bARALINK) { pTxRing->Cell[TxIdx].pNdisPacket = pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); } else { ASSERT(OrgSrcBufPA != SrcBufPA); } IsSD0 = FALSE; if (letusprint == TRUE) { ptemp = (PULONG)pTxD; DBGPRINT(RT_DEBUG_TRACE,("HardTx TxD[%ld] SDPtr1 =%d, SDLen1 = %08lx: %08lx: %08lx: %08lx \n", TxIdx, pTxD->SDLen1, *ptemp, *(ptemp+1), *(ptemp+2), *(ptemp+3))); } break; default: // should never happen break; } } else { SDPNowUsed--; // not use this segment. } SrcBytesCopied += SrcBufLen; //pDMAHeaderBufPtr += SrcBufLen; FreeMpduSize -= SrcBufLen; MpduSize += SrcBufLen; SrcBufPA += SrcBufLen; //SrcBufLen = 0; // // calcuate padding bytes for sub-frame // put the padding bytes into 1st DMA buffer of next Tx DESC // if (bAMSDU && (SrcBufIdx == 0)) { ULONG AlignLen; AlignLen = ((14+SrcBufLen)+3) & ~(0x3); padding = AlignLen - (14+SrcBufLen); } // advance to next scatter-gather BUFFER SrcBufIdx++; if (SrcBufIdx < pScatterGatherList->NumberOfElements) { pTxD->LastSec0 = 0; pTxD->LastSec1 = 0; { ULONG OffsetSrcVA = (ULONG) pScatterGatherList->Elements[SrcBufIdx].Address; //UCHAR *Header = (UCHAR *)OffsetSrcVA; SrcBufLen = pScatterGatherList->Elements[SrcBufIdx].Length; OffsetSrcVA += LENGTH_802_3; // skip 802.3 header SrcBufLen -= LENGTH_802_3; // skip 802.3 header SrcBufPA = PCI_MAP_SINGLE(pAd, (char *)OffsetSrcVA, SrcBufLen, PCI_DMA_TODEVICE); SrcRemainingBytes -= LENGTH_802_3; } } else { // Set Last Data Segment pTxD->LastSec0 = 0; pTxD->LastSec1 = 1; SrcBufLen = 0; } if (SrcBufLen == 0) break; } else { //scatter-gather buffer exceed current MPDU. leave some of the buffer to next MPDU switch (SDPNowUsed%2) { case 1: // Init TxRing NdisZeroMemory(pTxD, sizeof(pTxD)); pTxD->SDPtr0 = SrcBufPA; pTxD->SDLen0 = FreeMpduSize; pTxD->LastSec0 = 1; DBGPRINT(RT_DEBUG_INFO,("Last Fraged TXD. Use pTxD[] SDPtr0, SDLen0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -