/* * FUNCTION: Allocate a packet buffer for DMA * ARGUMENTS: * AdapterHandle: AdapterHandle * Length: Number of bytes to allocate * Cached: Whether or not the memory can be cached * VirtualAddress: Pointer to memory is returned here * PhysicalAddress: Physical address corresponding to virtual address * Notes: * Cached is ignored: always cached memory */ void *RTMP_AllocateRxPacketBuffer(struct rt_rtmp_adapter *pAd, unsigned long Length, IN BOOLEAN Cached, void **VirtualAddress, OUT dma_addr_t * PhysicalAddress) { struct sk_buff *pkt; pkt = dev_alloc_skb(Length); if (pkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n", Length)); } if (pkt) { RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); *VirtualAddress = (void *)pkt->data; *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); } else { *VirtualAddress = (void *)NULL; *PhysicalAddress = (dma_addr_t)NULL; } return (void *)pkt; }
/* * FUNCTION: Allocate a packet buffer for DMA * ARGUMENTS: * AdapterHandle: AdapterHandle * Length: Number of bytes to allocate * Cached: Whether or not the memory can be cached * VirtualAddress: Pointer to memory is returned here * PhysicalAddress: Physical address corresponding to virtual address * Notes: * Cached is ignored: always cached memory */ PNDIS_PACKET RTMP_AllocateRxPacketBuffer( IN PRTMP_ADAPTER pAd, IN ULONG Length, IN BOOLEAN Cached, OUT PVOID *VirtualAddress, OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) { struct sk_buff *pkt; // pkt = dev_alloc_skb(Length); DEV_ALLOC_SKB(pAd, pkt, Length); if (pkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); } if (pkt) { RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); *VirtualAddress = (PVOID) pkt->data; //#ifdef CONFIG_5VT_ENHANCE // *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, 1600, PCI_DMA_FROMDEVICE); //#else *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); //#endif } else { *VirtualAddress = (PVOID) NULL; *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; } return (PNDIS_PACKET) pkt; }
PNDIS_PACKET RTMP_AllocateRxPacketBuffer( IN PRTMP_ADAPTER pAd, IN ULONG Length, IN BOOLEAN Cached, OUT PVOID *VirtualAddress, OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) { PNDIS_PACKET pkt; pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length)); if (pkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length)); } if (pkt) { RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS); *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data; *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE); } else { *VirtualAddress = (PVOID) NULL; *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL; } return (PNDIS_PACKET) pkt; }
void Invalid_Remaining_Packet(struct rt_rtmp_adapter *pAd, unsigned long VirtualAddress) { dma_addr_t PhysicalAddress; PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress + 1600), RX_BUFFER_NORMSIZE - 1600, -1, PCI_DMA_FROMDEVICE); }
VOID Invalid_Remaining_Packet( IN PRTMP_ADAPTER pAd, IN ULONG VirtualAddress) { NDIS_PHYSICAL_ADDRESS PhysicalAddress; PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE); }
u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, IN BOOLEAN bIsLast, u16 * FreeNumber) { u8 *pDMAHeaderBufVA; u16 TxIdx, RetTxIdx; struct rt_txd * pTxD; u32 BufBasePaLow; struct rt_rtmp_tx_ring *pTxRing; u16 hwHeaderLen; /* */ /* get Tx Ring Resource */ /* */ pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; /* */ /* build Tx Descriptor */ /* */ pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); RetTxIdx = TxIdx; /* */ /* Update Tx index */ /* */ INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
int RtmpPCIMgmtKickOut( IN RTMP_ADAPTER *pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket, IN PUCHAR pSrcBufVA, IN UINT SrcBufLen) { PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; #endif pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); pTxD->LastSec0 = 1; pTxD->LastSec1 = 1; pTxD->DMADONE = 0; pTxD->SDLen1 = 0; pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); pTxD->SDLen0 = SrcBufLen; #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); return 0; }
/* Must be run in Interrupt context This function handle PCI specific TxDesc and cpu index update and kick the packet out. */ int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd, u8 QueIdx, void *pPacket, u8 *pSrcBufVA, u32 SrcBufLen) { struct rt_txd * pTxD; unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[SwIdx].AllocVa; pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); pTxD->LastSec0 = 1; pTxD->LastSec1 = 1; pTxD->DMADONE = 0; pTxD->SDLen1 = 0; pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); pTxD->SDLen0 = SrcBufLen; /*================================================================== */ /* 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); return 0; }
NDIS_STATUS MlmeHardTransmitTxRing( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket) { PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; PTXD_STRUC pTxD; #ifdef RT_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->TxRing[QueIdx].TxCpuIdx; PTXWI_STRUC pFirstTxWI; /*ULONG i;*/ /*HTTRANSMIT_SETTING MlmeTransmit; Rate for this MGMT frame.*/ ULONG FreeNum; MAC_TABLE_ENTRY *pMacEntry = NULL; UINT8 TXWISize = pAd->chipCap.TXWISize; #ifdef CONFIG_AP_SUPPORT #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { /* The buffer shouldn't be NULL*/ return NDIS_STATUS_FAILURE; } /* Make sure MGMT ring resource won't be used by other threads*/ /*NdisAcquireSpinLock(&pAd->TxRingLock);*/ FreeNum = GET_TXRING_FREENO(pAd, QueIdx); if (FreeNum == 0) { /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ return NDIS_STATUS_FAILURE; } SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; #endif if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ return NDIS_STATUS_FAILURE; } pFirstTxWI =(PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); pHeader_802_11 = (PHEADER_802_11)(pSrcBufVA + TXINFO_SIZE + TXWISize); if (pHeader_802_11->Addr1[0] & 0x01) { MlmeRate = pAd->CommonCfg.BasicMlmeRate; } else { MlmeRate = pAd->CommonCfg.MlmeRate; } if ((pHeader_802_11->FC.Type == BTYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); } /* 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. */ /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame*/ 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)*/ { 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; #ifdef CONFIG_AP_SUPPORT #ifdef SPECIFIC_TX_POWER_SUPPORT /* Find which MBSSID to be send this probeRsp */ UINT32 apidx; for (apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { if (RTMPEqualMemory(pHeader_802_11->Addr2, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) break; } if (!(apidx >= pAd->ApCfg.BssidNum) && (pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) && (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_CCK) && (pAd->CommonCfg.MlmeTransmit.field.MCS == RATE_1)) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ } } } 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->Dot11_H.RDMode != RD_NORMAL_MODE)) { DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); /*NdisReleaseSpinLock(&pAd->TxRingLock);*/ return (NDIS_STATUS_FAILURE); } #ifdef RT_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.*/ /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.*/ if (pMacEntry == NULL) { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWISize), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT if (IS_RT6352(pAd)) pFirstTxWI->TxPwrAdj = TxPwrAdj; #endif /* SPECIFIC_TX_POWER_SUPPORT */ } else { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWISize), pMacEntry->MaxHTPhyMode.field.MCS, 0, (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); } pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; /* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;*/ #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI); #endif SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, RTMP_PCI_DMA_TODEVICE); pTxD->LastSec0 = 1; pTxD->LastSec1 = 0; pTxD->SDLen1 = 0; pTxD->SDPtr0 = SrcBufPA; pTxD->SDLen0 = SrcBufLen; RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); RTMP_DCACHE_FLUSH(pAd->TxRing[QueIdx].Cell[SwIdx].AllocPa, RXD_SIZE); /* 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; }
USHORT RtmpPCI_WriteTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHeaderLen; pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) { hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; } else { hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; } NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); RetTxIdx = TxIdx; INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
/* ========================================================================== Description: Setup Frame format. NOTE: This routine should only be used in ATE mode. ========================================================================== */ INT ATESetUpFrame( IN PRTMP_ADAPTER pAd, IN UINT32 TxIdx) { PATE_INFO pATEInfo = &(pAd->ate); UINT pos = 0; TXINFO_STRUC *pTxInfo; TXD_STRUC *pTxD; #ifdef RT_BIG_ENDIAN TXD_STRUC *pDestTxD; UCHAR tx_hw_info[TXD_SIZE]; #endif /* RT_BIG_ENDIAN */ PNDIS_PACKET pPacket=NULL; PUCHAR pDest=NULL; PVOID AllocVa=NULL; NDIS_PHYSICAL_ADDRESS AllocPa; HTTRANSMIT_SETTING TxHTPhyMode; RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; TXWI_STRUC *pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; UINT8 TXWISize = pAd->chipCap.TXWISize; #ifdef RALINK_QA PHEADER_802_11 pHeader80211; #endif /* RALINK_QA */ UCHAR bw, sgi, stbc, mcs, phy_mode, frag, cfack, ts, ampdu, ack, nseq, bawinsize, pkt_id, txop; USHORT byte_cnt; bw = sgi = stbc = mcs = phy_mode = frag = cfack = ts =0; ampdu = ack = nseq = bawinsize = pkt_id = txop = 0; byte_cnt = 0; #ifdef RLT_MAC if (pAd->chipCap.hif_type == HIF_RLT) { bw = pATEInfo->TxWI.TXWI_N.BW; sgi = pATEInfo->TxWI.TXWI_N.ShortGI; stbc = pATEInfo->TxWI.TXWI_N.STBC; mcs = pATEInfo->TxWI.TXWI_N.MCS; phy_mode = pATEInfo->TxWI.TXWI_N.PHYMODE; frag = pATEInfo->TxWI.TXWI_N.FRAG; cfack = pATEInfo->TxWI.TXWI_N.CFACK, ts = pATEInfo->TxWI.TXWI_N.TS; ampdu = pATEInfo->TxWI.TXWI_N.AMPDU; ack = pATEInfo->TxWI.TXWI_N.ACK; nseq = pATEInfo->TxWI.TXWI_N.NSEQ; bawinsize =pATEInfo->TxWI.TXWI_N.BAWinSize; byte_cnt = pATEInfo->TxWI.TXWI_N.MPDUtotalByteCnt; pkt_id = pATEInfo->TxWI.TXWI_N.TxPktId; txop = pATEInfo->TxWI.TXWI_N.txop; cfack = pATEInfo->TxWI.TXWI_N.CFACK; } #endif /* RLT_MAC */ /* fill TxWI */ TxHTPhyMode.field.BW = bw; TxHTPhyMode.field.ShortGI = sgi; TxHTPhyMode.field.STBC = stbc; TxHTPhyMode.field.MCS = mcs; TxHTPhyMode.field.MODE = phy_mode; if (pATEInfo->bQATxStart == TRUE) { /* always use QID_AC_BE and FIFO_EDCA */ ATEWriteTxWI(pAd, pTxWI, frag, cfack, ts, ampdu, ack, nseq, bawinsize, 0, byte_cnt, pkt_id, 0, 0, txop, cfack, &TxHTPhyMode); #ifdef TXBF_SUPPORT #ifdef RELEASE_EXCLUDE /* It will affect transmit data rate ??? But QA is tested... */ #endif /* RELEASE_EXCLUDE */ #ifdef RLT_MAC if (IS_MT76x0(pAd)) { /* Must copy rsv bits to actual TxWI */ // pTxWI->TXWI_N.rsv = pATEInfo->TxWI.TXWI_N.rsv; pTxWI->TXWI_N.iTxBF = pATEInfo->TxWI.TXWI_N.iTxBF; pTxWI->TXWI_N.Sounding = pATEInfo->TxWI.TXWI_N.Sounding; pTxWI->TXWI_N.eTxBF = pATEInfo->TxWI.TXWI_N.eTxBF; // pTxWI->TXWI_N.Autofallback = pATEInfo->TxWI.TXWI_N.Autofallback; pTxWI->TXWI_N.NDPSndBW = pATEInfo->TxWI.TXWI_N.NDPSndBW; pTxWI->TXWI_N.NDPSndRate = pATEInfo->TxWI.TXWI_N.NDPSndRate; } #endif /* RLT_MAC */ #endif /* TXBF_SUPPORT */ } else { ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 4, 0, pATEInfo->TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); } /* fill 802.11 header */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { NdisMoveMemory(pDMAHeaderBufVA + TXWISize, pATEInfo->Header, pATEInfo->HLen); } else #endif /* RALINK_QA */ { pATEInfo->HLen = LENGTH_802_11; #ifdef TXBF_SUPPORT TemplateFrame[0] = 0x08; /* Data */ TemplateFrame[1] = 0x00; if (pATEInfo->bTxBF && pATEInfo->txSoundingMode!=0) { /* QoS Data */ pATEInfo->HLen = 32; TemplateFrame[0] = 0x88; TemplateFrame[1] = 0x80; switch (pATEInfo->txSoundingMode) { case 1: /* Data Sounding */ TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; TemplateFrame[29] = 0x00; break; case 2: case 3: /* 2 or 3 Stream NDP */ TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; TemplateFrame[29] = 0x01; /* NDP Announce */ break; default: TemplateFrame[28] = TemplateFrame[29] = 0x0; } } #endif /* TXBF_SUPPORT */ NdisMoveMemory(pDMAHeaderBufVA + TXWISize, TemplateFrame, pATEInfo->HLen); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, pATEInfo->Addr1, MAC_ADDR_LEN); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, MAC_ADDR_LEN); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, MAC_ADDR_LEN); } #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); #endif /* RT_BIG_ENDIAN */ /* alloc buffer for payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->DLen + 0x100, FALSE, &AllocVa, &AllocPa); } else #endif /* RALINK_QA */ { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->TxLength, FALSE, &AllocVa, &AllocPa); } /* error check */ if (pPacket == NULL) { pATEInfo->TxCount = 0; DBGPRINT_ERR(("%s : fail to alloc packet space.\n", __FUNCTION__)); return -1; } pTxRing->Cell[TxIdx].pNdisPacket = pPacket; pDest = (PUCHAR) AllocVa; #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { GET_OS_PKT_LEN(pPacket) = pATEInfo->DLen; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->DLen; #endif /* LIMUX */ } else #endif /* RALINK_QA */ { GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; #endif /* LINUX */ } /* prepare frame payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { /* copy pattern to payload */ if ((pATEInfo->PLen != 0)) { for (pos = 0; pos < pATEInfo->DLen; pos += pATEInfo->PLen) { memcpy(GET_OS_PKT_DATAPTR(pPacket) + pos, pATEInfo->Pattern, pATEInfo->PLen); } } } else #endif /* RALINK_QA */ { for (pos = 0; pos < GET_OS_PKT_LEN(pPacket); pos++) { #ifdef RELEASE_EXCLUDE /* kurtis: 0xAA ATE test EVM will be positive */ #endif /* RELEASE_EXCLUDE */ /* default payload is 0xA5 */ pDest[pos] = pATEInfo->Payload; } } /* build Tx descriptor */ #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); #else pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); pTxD = (TXD_STRUC *)&tx_hw_info[0]; pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); #endif /* !RT_BIG_ENDIAN */ { /* prepare TxD */ TX_BLK txblk; txblk.SrcBufLen = GET_OS_PKT_LEN(pPacket); txblk.pSrcBufData = AllocVa; NdisZeroMemory(pTxD, TXD_SIZE); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + pATEInfo->HLen; pTxD->LastSec0 = 0; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, &txblk, 0, 1, RTMP_PCI_DMA_TODEVICE); pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec1 = 1; ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); } #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { pDest = (PUCHAR)pTxWI; pDest += TXWISize; pHeader80211 = (PHEADER_802_11)pDest; /* modify sequence number... */ if (pATEInfo->TxDoneCount == 0) pATEInfo->seq = pHeader80211->Sequence; else pHeader80211->Sequence = ++pATEInfo->seq; } #endif /* RALINK_QA */ #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif /* RT_BIG_ENDIAN */ return 0; }
/* Must be run in Interrupt context This function handle PCI specific TxDesc and cpu index update and kick the packet out. */ int RtmpPCIMgmtKickOut( IN RTMP_ADAPTER *pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket, IN PUCHAR pSrcBufVA, IN UINT SrcBufLen) { PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa; #endif pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket; pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL; RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT); pTxD->LastSec0 = 1; pTxD->LastSec1 = 1; pTxD->DMADONE = 0; pTxD->SDLen1 = 0; pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE); pTxD->SDLen0 = SrcBufLen; #ifdef RT_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); return 0; }
NDIS_STATUS MlmeHardTransmitTxRing( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket) { PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PHEADER_802_11 pHeader_802_11; BOOLEAN bAckRequired, bInsertTimestamp; ULONG SrcBufPA; UCHAR MlmeRate; ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; PTXWI_STRUC pFirstTxWI; ULONG FreeNum; MAC_TABLE_ENTRY *pMacEntry = NULL; RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { return NDIS_STATUS_FAILURE; } FreeNum = GET_TXRING_FREENO(pAd, QueIdx); if (FreeNum == 0) { return NDIS_STATUS_FAILURE; } SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; #else pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); return NDIS_STATUS_FAILURE; } #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) AsicForceWakeup(pAd, TRUE); } #endif 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; } if ((pHeader_802_11->FC.Type == BTYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); } if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) MlmeRate = RATE_6; #ifdef CONFIG_STA_SUPPORT if (pHeader_802_11->FC.Type != BTYPE_DATA) { 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; } } #endif bInsertTimestamp = FALSE; if (pHeader_802_11->FC.Type == BTYPE_CNTL) { bAckRequired = FALSE; } else { if (pHeader_802_11->Addr1[0] & 0x01) { 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; 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")); return (NDIS_STATUS_FAILURE); } #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); #endif if (pMacEntry == NULL) { 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); } else { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), pMacEntry->MaxHTPhyMode.field.MCS, 0, (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); } pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); #endif SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, 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 RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx); return NDIS_STATUS_SUCCESS; }
int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd, u8 QueIdx, void *pPacket) { struct rt_packet_info PacketInfo; u8 *pSrcBufVA; u32 SrcBufLen; struct rt_txd * pTxD; struct rt_header_802_11 * pHeader_802_11; BOOLEAN bAckRequired, bInsertTimestamp; unsigned long SrcBufPA; /*u8 TxBufIdx; */ u8 MlmeRate; unsigned long SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; struct rt_txwi * pFirstTxWI; /*unsigned long i; */ /*HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. */ unsigned long FreeNum; struct rt_mac_table_entry *pMacEntry = NULL; RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { /* The buffer shouldn't be NULL */ return NDIS_STATUS_FAILURE; } /* Make sure MGMT ring resource won't be used by other threads */ /*NdisAcquireSpinLock(&pAd->TxRingLock); */ FreeNum = GET_TXRING_FREENO(pAd, QueIdx); if (FreeNum == 0) { /*NdisReleaseSpinLock(&pAd->TxRingLock); */ return NDIS_STATUS_FAILURE; } SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; pTxD = (struct rt_txd *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); /*NdisReleaseSpinLock(&pAd->TxRingLock); */ 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, TRUE); } pFirstTxWI = (struct rt_txwi *) pSrcBufVA; pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXWI_SIZE); if (pHeader_802_11->Addr1[0] & 0x01) { MlmeRate = pAd->CommonCfg.BasicMlmeRate; } else { MlmeRate = pAd->CommonCfg.MlmeRate; } if ((pHeader_802_11->FC.Type == BTYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); } /* 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. */ /* */ /* */ /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */ /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */ if (pHeader_802_11->FC.Type != BTYPE_DATA) { 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; } } 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) */ { 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")); /*NdisReleaseSpinLock(&pAd->TxRingLock); */ return (NDIS_STATUS_FAILURE); } /* */ /* 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. */ /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. */ if (pMacEntry == NULL) { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (u8)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); } else { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), pMacEntry->MaxHTPhyMode.field.MCS, 0, (u8)pMacEntry->MaxHTPhyMode.field.MCS, IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); } pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; /* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; */ SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, 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; 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; }
u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u8 frameNum, u16 * FreeNumber) { BOOLEAN bIsLast; u8 *pDMAHeaderBufVA; u16 TxIdx, RetTxIdx; struct rt_txd * pTxD; u32 BufBasePaLow; struct rt_rtmp_tx_ring *pTxRing; u16 hwHdrLen; u32 firstDMALen; bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); /* */ /* get Tx Ring Resource */ /* */ pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); if (frameNum == 0) { /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; } else { firstDMALen = pTxBlk->MpduHeaderLen; } NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; /* */ /* build Tx Descriptor */ /* */ pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa; NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = firstDMALen; /* include padding */ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); RetTxIdx = TxIdx; /* */ /* Update Tx index */ /* */ INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
USHORT RtmpPCI_WriteMultiTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR frameNum, OUT USHORT *FreeNumber) { BOOLEAN bIsLast; UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHdrLen; UINT32 firstDMALen; UINT8 TXWISize = pAd->chipCap.TXWISize; bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); /* get Tx Ring Resource*/ pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); if (frameNum == 0) { /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;*/ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;*/ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; firstDMALen = TXINFO_SIZE + TXWISize + hwHdrLen; } else { firstDMALen = pTxBlk->MpduHeaderLen; } NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; /* build Tx Descriptor*/ #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = firstDMALen; /* include padding*/ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE);; pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = !(pTxD->SDLen1); pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN if (frameNum == 0) RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); if (frameNum != 0) RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif /* RT_BIG_ENDIAN */ RetTxIdx = TxIdx; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); /* Update Tx index*/ INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
USHORT RtmpPCI_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHeaderLen; UINT32 firstDMALen; UINT8 TXWISize = pAd->chipCap.TXWISize; /* Get Tx Ring Resource*/ pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/ /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; firstDMALen = TXINFO_SIZE + TXWISize + hwHeaderLen; NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); /* Build Tx Descriptor*/ #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); if (fragNum == pTxBlk->TotalFragNum) { pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; } pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = firstDMALen; /* include padding*/ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); pTxD->SDLen1 = pTxBlk->SrcBufLen; if (pTxD->SDLen1 > 0) { pTxD->LastSec0 = 0; pTxD->LastSec1 = 1; } else { pTxD->LastSec0 = 1; pTxD->LastSec1 = 0; } RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif /* RT_BIG_ENDIAN */ RetTxIdx = TxIdx; pTxBlk->Priv += pTxBlk->SrcBufLen; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); /* Update Tx index*/ INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
USHORT RtmpPCI_WriteMultiTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR frameNum, OUT USHORT *FreeNumber) { BOOLEAN bIsLast; UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHdrLen; UINT32 firstDMALen; bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0); pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); if (frameNum == 0) { if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; } else { firstDMALen = pTxBlk->MpduHeaderLen; } NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = firstDMALen; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN if (frameNum == 0) RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); if (frameNum != 0) RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif RetTxIdx = TxIdx; INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
NDIS_STATUS MlmeHardTransmitTxRing( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket) { PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; PTXD_STRUC pTxD; #ifdef RT_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->TxRing[QueIdx].TxCpuIdx; PTXWI_STRUC pFirstTxWI; //ULONG i; //HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. ULONG FreeNum; MAC_TABLE_ENTRY *pMacEntry = NULL; RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { // The buffer shouldn't be NULL return NDIS_STATUS_FAILURE; } // Make sure MGMT ring resource won't be used by other threads //NdisAcquireSpinLock(&pAd->TxRingLock); FreeNum = GET_TXRING_FREENO(pAd, QueIdx); if (FreeNum == 0) { //NdisReleaseSpinLock(&pAd->TxRingLock); return NDIS_STATUS_FAILURE; } SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; #else pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) { DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); //NdisReleaseSpinLock(&pAd->TxRingLock); return NDIS_STATUS_FAILURE; } #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // 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, TRUE); } #endif // CONFIG_STA_SUPPORT // 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; } if ((pHeader_802_11->FC.Type == BTYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) { pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); } // 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. // // // 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) { 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; } } #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) { 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")); //NdisReleaseSpinLock(&pAd->TxRingLock); return (NDIS_STATUS_FAILURE); } #ifdef RT_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. // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. if (pMacEntry == NULL) { 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); } else { RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE), pMacEntry->MaxHTPhyMode.field.MCS, 0, (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); } pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; // pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); #endif SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, 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 RT_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; }
USHORT RtmpPCI_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHeaderLen; UINT32 firstDMALen; pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); if (fragNum == pTxBlk->TotalFragNum) { pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; } pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = firstDMALen; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE); pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = 1; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif RetTxIdx = TxIdx; pTxBlk->Priv += pTxBlk->SrcBufLen; INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
USHORT RtmpPCI_WriteSingleTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHeaderLen; // // get Tx Ring Resource // pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; // // build Tx Descriptor // #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif // RT_BIG_ENDIAN // RetTxIdx = TxIdx; // // Update Tx index // INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }
INT ATESetUpNDPAFrame( IN PRTMP_ADAPTER pAd, IN UINT32 TxIdx) { PATE_INFO pATEInfo = &(pAd->ate); UINT pos = 0; TXINFO_STRUC *pTxInfo; TXD_STRUC *pTxD; #ifdef RT_BIG_ENDIAN TXD_STRUC *pDestTxD; UCHAR tx_hw_info[TXD_SIZE]; #endif /* RT_BIG_ENDIAN */ PNDIS_PACKET pPacket=NULL; PUCHAR pDest=NULL; PVOID AllocVa=NULL; NDIS_PHYSICAL_ADDRESS AllocPa; HTTRANSMIT_SETTING TxHTPhyMode; UCHAR *buf; VHT_NDPA_FRAME *vht_ndpa; SNDING_STA_INFO *sta_info; RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; TXWI_STRUC *pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; UINT8 TXWISize = pAd->chipCap.TXWISize; #ifdef RALINK_QA PHEADER_802_11 pHeader80211; #endif /* RALINK_QA */ UCHAR bw, sgi, stbc, mcs, phy_mode, frag, cfack, ts, ampdu, ack, nseq, bawinsize, pkt_id, txop; USHORT byte_cnt; bw = sgi = stbc = mcs = phy_mode = frag = cfack = ts =0; ampdu = ack = nseq = bawinsize = pkt_id = txop = 0; byte_cnt = 0; #ifdef RLT_MAC if (pAd->chipCap.hif_type == HIF_RLT) { bw = pATEInfo->TxWI.TXWI_N.BW; sgi = pATEInfo->TxWI.TXWI_N.ShortGI; stbc = pATEInfo->TxWI.TXWI_N.STBC; mcs = pATEInfo->TxWI.TXWI_N.MCS; phy_mode = pATEInfo->TxWI.TXWI_N.PHYMODE; frag = pATEInfo->TxWI.TXWI_N.FRAG; cfack = pATEInfo->TxWI.TXWI_N.CFACK, ts = pATEInfo->TxWI.TXWI_N.TS; ampdu = pATEInfo->TxWI.TXWI_N.AMPDU; ack = pATEInfo->TxWI.TXWI_N.ACK; nseq = pATEInfo->TxWI.TXWI_N.NSEQ; bawinsize =pATEInfo->TxWI.TXWI_N.BAWinSize; byte_cnt = pATEInfo->TxWI.TXWI_N.MPDUtotalByteCnt; pkt_id = pATEInfo->TxWI.TXWI_N.TxPktId; txop = pATEInfo->TxWI.TXWI_N.txop; cfack = pATEInfo->TxWI.TXWI_N.CFACK; } #endif /* RLT_MAC */ #ifdef RTMP_MAC if (pAd->chipCap.hif_type == HIF_RTMP) { bw = pATEInfo->TxWI.TXWI_O.BW; sgi = pATEInfo->TxWI.TXWI_O.ShortGI; stbc = pATEInfo->TxWI.TXWI_O.STBC; mcs = pATEInfo->TxWI.TXWI_O.MCS; phy_mode = pATEInfo->TxWI.TXWI_O.PHYMODE; frag = pATEInfo->TxWI.TXWI_O.FRAG; cfack = pATEInfo->TxWI.TXWI_O.CFACK, ts = pATEInfo->TxWI.TXWI_O.TS; ampdu = pATEInfo->TxWI.TXWI_O.AMPDU; ack = pATEInfo->TxWI.TXWI_O.ACK; nseq = pATEInfo->TxWI.TXWI_O.NSEQ; bawinsize =pATEInfo->TxWI.TXWI_O.BAWinSize; byte_cnt = pATEInfo->TxWI.TXWI_O.MPDUtotalByteCnt; pkt_id = pATEInfo->TxWI.TXWI_O.PacketId; txop = pATEInfo->TxWI.TXWI_O.txop; cfack = pATEInfo->TxWI.TXWI_O.CFACK; } #endif /* RTMP_MAC */ /* fill TxWI */ TxHTPhyMode.field.BW = bw; TxHTPhyMode.field.ShortGI = sgi; TxHTPhyMode.field.STBC = stbc; TxHTPhyMode.field.MCS = mcs; TxHTPhyMode.field.MODE = phy_mode; if (pATEInfo->bQATxStart == TRUE) { /* always use QID_AC_BE and FIFO_EDCA */ ATEWriteTxWI(pAd, pTxWI, frag, cfack, ts, ampdu, ack, nseq, bawinsize, 0, byte_cnt, pkt_id, 0, 0, txop, cfack, &TxHTPhyMode); #ifdef TXBF_SUPPORT #ifdef RTMP_MAC if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd)) { /* Must copy rsv bits to actual TxWI */ //pTxWI->TXWI_O.rsv = pATEInfo->TxWI.TXWI_O.rsv; pTxWI->TXWI_O.iTxBF = pATEInfo->TxWI.TXWI_O.iTxBF; pTxWI->TXWI_O.Sounding = pATEInfo->TxWI.TXWI_O.Sounding; pTxWI->TXWI_O.eTxBF = pATEInfo->TxWI.TXWI_O.eTxBF; pTxWI->TXWI_O.Autofallback = pATEInfo->TxWI.TXWI_O.Autofallback; pTxWI->TXWI_O.NDPSndBW = pATEInfo->TxWI.TXWI_O.NDPSndBW; pTxWI->TXWI_O.NDPSndRate = pATEInfo->TxWI.TXWI_O.NDPSndRate; } #endif #ifdef RLT_MAC if (IS_MT76x2(pAd)) { /* Must copy rsv bits to actual TxWI */ pTxWI->TXWI_N.Rsv4 = pATEInfo->TxWI.TXWI_N.Rsv4; pTxWI->TXWI_N.iTxBF = pATEInfo->TxWI.TXWI_N.iTxBF; pTxWI->TXWI_N.Sounding = pATEInfo->TxWI.TXWI_N.Sounding; pTxWI->TXWI_N.eTxBF = pATEInfo->TxWI.TXWI_N.eTxBF; //pTxWI->TXWI_N.Autofallback = pATEInfo->TxWI.TXWI_N.Autofallback; pTxWI->TXWI_N.NDPSndBW = pATEInfo->TxWI.TXWI_N.NDPSndBW; pTxWI->TXWI_N.NDPSndRate = pATEInfo->TxWI.TXWI_N.NDPSndRate; pTxWI->TXWI_N.TXBF_PT_SCA = pATEInfo->TxWI.TXWI_N.TXBF_PT_SCA; } #endif #endif /* TXBF_SUPPORT */ } else { ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 4, 0, pATEInfo->TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); #ifdef TXBF_SUPPORT if (pATEInfo->bTxBF == 1) { #ifdef RTMP_MAC if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd)) { //pTxWI->TXWI_O.rsv = 0; pTxWI->TXWI_O.iTxBF = pATEInfo->TxWI.TXWI_O.iTxBF; pTxWI->TXWI_O.Sounding = (pATEInfo->txSoundingMode == 1 ? 1 : 0); pTxWI->TXWI_O.eTxBF = pATEInfo->TxWI.TXWI_O.eTxBF; pTxWI->TXWI_O.Autofallback = pATEInfo->TxWI.TXWI_O.Autofallback; pTxWI->TXWI_O.NDPSndBW = pATEInfo->TxWI.TXWI_O.BW; if (pATEInfo->txSoundingMode == 3) pTxWI->TXWI_O.NDPSndRate = 2; else if (pATEInfo->txSoundingMode == 2) pTxWI->TXWI_O.NDPSndRate = 1; else pTxWI->TXWI_O.NDPSndRate = 0; } #endif #ifdef RLT_MAC if (IS_MT76x2(pAd)) { pTxWI->TXWI_N.Rsv4 = 0; pTxWI->TXWI_N.iTxBF = pATEInfo->TxWI.TXWI_N.iTxBF; pTxWI->TXWI_N.Sounding = (pATEInfo->txSoundingMode == 1 ? 1 : 0); pTxWI->TXWI_N.eTxBF = pATEInfo->TxWI.TXWI_N.eTxBF; //pTxWI->TXWI_N.Autofallback = pATEInfo->TxWI.TXWI_N.Autofallback; pTxWI->TXWI_N.NDPSndBW = pATEInfo->TxWI.TXWI_N.BW; if (pATEInfo->txSoundingMode == 3) pTxWI->TXWI_N.NDPSndRate = 2; else if (pATEInfo->txSoundingMode == 2) pTxWI->TXWI_N.NDPSndRate = 1; else pTxWI->TXWI_N.NDPSndRate = 0; pTxWI->TXWI_N.TXBF_PT_SCA = pATEInfo->TxWI.TXWI_N.TXBF_PT_SCA; } #endif } #endif /* TXBF_SUPPORT */ } /* fill 802.11 header */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { NdisMoveMemory(pDMAHeaderBufVA + TXWISize, pATEInfo->Header, pATEInfo->HLen); } else #endif /* RALINK_QA */ { buf = (pDMAHeaderBufVA + TXWISize); vht_ndpa = (VHT_NDPA_FRAME *)buf; pATEInfo->HLen = sizeof(VHT_NDPA_FRAME); vht_ndpa->fc.Type = FC_TYPE_CNTL; vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; COPY_MAC_ADDR(vht_ndpa->ra, pATEInfo->Addr1); COPY_MAC_ADDR(vht_ndpa->ta, pATEInfo->Addr3); hex_dump("NDPA Frame",buf,pATEInfo->HLen); /* Currnetly we only support 1 STA for a VHT DNPA */ sta_info = vht_ndpa->sta_info; sta_info->aid12 = 1; sta_info->fb_type = SNDING_FB_SU; sta_info->nc_idx = 0; vht_ndpa->token.token_num = 0; vht_ndpa->duration = 100; } #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); #endif /* RT_BIG_ENDIAN */ /* alloc buffer for payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->DLen + 0x100, FALSE, &AllocVa, &AllocPa); } else #endif /* RALINK_QA */ { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->TxLength, FALSE, &AllocVa, &AllocPa); } if (pPacket == NULL) { pATEInfo->TxCount = 0; DBGPRINT_ERR(("%s : fail to alloc packet space.\n", __FUNCTION__)); return -1; } pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket; pDest = (PUCHAR) AllocVa; #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { GET_OS_PKT_LEN(pPacket) = pATEInfo->DLen; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->DLen; #endif /* LIMUX */ } else #endif /* RALINK_QA */ { GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; #endif /* LINUX */ } /* prepare frame payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { /* copy pattern to payload */ if ((pATEInfo->PLen != 0)) { for (pos = 0; pos < pATEInfo->DLen; pos += pATEInfo->PLen) { memcpy(GET_OS_PKT_DATAPTR(pPacket) + pos, pATEInfo->Pattern, pATEInfo->PLen); } } } else #endif /* RALINK_QA */ { for (pos = 0; pos < GET_OS_PKT_LEN(pPacket); pos++) { pDest[pos] = 0x00; } } /* build Tx descriptor */ #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); #else pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); pTxD = (TXD_STRUC *)&tx_hw_info[0]; pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); #endif /* !RT_BIG_ENDIAN */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* prepare TxD */ NdisZeroMemory(pTxD, TXD_SIZE); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + pATEInfo->HLen; pTxD->SDPtr1 = AllocPa; pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec0 = (pTxD->SDLen1 == 0) ? 1 : 0; pTxD->LastSec1 = 1; ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); pDest = (PUCHAR)pTxWI; pDest += TXWISize; pHeader80211 = (PHEADER_802_11)pDest; /* modify sequence number... */ if (pATEInfo->TxDoneCount == 0) pATEInfo->seq = pHeader80211->Sequence; else pHeader80211->Sequence = ++pATEInfo->seq; } else #endif /* RALINK_QA */ { TX_BLK txblk; txblk.SrcBufLen = GET_OS_PKT_LEN(pPacket); txblk.pSrcBufData = AllocVa; NdisZeroMemory(pTxD, TXD_SIZE); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + pATEInfo->HLen /* LENGTH_802_11 */; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, &txblk, 0, 1, RTMP_PCI_DMA_TODEVICE); pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec0 = (pTxD->SDLen1 == 0) ? 1 : 0; pTxD->LastSec1 = 1; ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); } #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif /* RT_BIG_ENDIAN */ return 0; }