VOID asic_write_bcn_buf(RTMP_ADAPTER *pAd, UCHAR *tmac_info, INT info_len, UCHAR *bcn_buf, INT buf_len, UINT32 hw_addr) { INT i; UCHAR *ptr = tmac_info; UINT32 longValue, reg_base = hw_addr; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); #endif for (i = 0; i < info_len; i += 4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = bcn_buf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = hw_addr + info_len; for (i= 0; i< buf_len; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } }
VOID RtmpUSBNullFrameKickOut( IN RTMP_ADAPTER *pAd, IN UCHAR QueIdx, IN UCHAR *pNullFrame, IN UINT32 frameLen) { if (pAd->NullContext.InUse == FALSE) { PTX_CONTEXT pNullContext; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UCHAR *pWirelessPkt; UINT8 TXWISize = pAd->chipCap.TXWISize; pNullContext = &(pAd->NullContext); /* Set the in use bit*/ pNullContext->InUse = TRUE; pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0]; RTMPZeroMemory(&pWirelessPkt[0], 100); pTxInfo = (TXINFO_STRUC *)&pWirelessPkt[0]; rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(frameLen + TXWISize + TSO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); pTxInfo->TxInfoQSEL = FIFO_EDCA; pTxWI = (TXWI_STRUC *)&pWirelessPkt[TXINFO_SIZE]; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, frameLen, 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); #endif /* RT_BIG_ENDIAN */ RTMPMoveMemory(&pWirelessPkt[TXWISize + TXINFO_SIZE + TSO_SIZE], pNullFrame, frameLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWISize + TSO_SIZE], DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWISize + TSO_SIZE + frameLen + 4; pAd->NullContext.BulkOutSize = ( pAd->NullContext.BulkOutSize + 3) & (~3); /* Fill out frame length information for global Bulk out arbitor*/ /*pNullContext->BulkOutSize = TransferBufferLength;*/ DBGPRINT(RT_DEBUG_TRACE, ("%s - Send NULL Frame @%d Mbps...\n", __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate])); RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* Kick bulk out */ RTUSBKickBulkOut(pAd); } }
VOID RtmpUSBNullFrameKickOut( IN RTMP_ADAPTER *pAd, IN UCHAR QueIdx, IN UCHAR *pNullFrame, IN UINT32 frameLen) { if (pAd->NullContext.InUse == FALSE) { PTX_CONTEXT pNullContext; PTXINFO_STRUC pTxInfo; PTXWI_STRUC pTxWI; PUCHAR pWirelessPkt; pNullContext = &(pAd->NullContext); // Set the in use bit pNullContext->InUse = TRUE; pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0]; RTMPZeroMemory(&pWirelessPkt[0], 100); pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0]; RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); pTxInfo->QSEL = FIFO_EDCA; pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE]; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)), 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); #endif // RT_BIG_ENDIAN // RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWI_SIZE], DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; // Fill out frame length information for global Bulk out arbitor //pNullContext->BulkOutSize = TransferBufferLength; DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate])); RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); // Kick bulk out RTUSBKickBulkOut(pAd); } }
VOID asic_write_bcn_buf(RTMP_ADAPTER *pAd, UCHAR *tmac_info, INT info_len, UCHAR *bcn_buf, INT buf_len, UINT32 hw_addr) { UCHAR *ptr; #ifdef RT_BIG_ENDIAN #if defined(RTMP_MAC) || defined(RLT_MAC) if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) { RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); } #endif #endif /* update BEACON frame content. start right after the TXWI field. */ ptr = bcn_buf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif // TODO: shiang-MT7603, Send to ASIC! }
/* ========================================================================== 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; }
USHORT RtmpUSB_WriteSingleTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UCHAR *pWirelessPacket, *buf; UCHAR QueIdx; unsigned long IrqFlags; NDIS_STATUS Status; UINT32 hdr_copy_len, hdr_len, dma_len = 0, padding; #ifndef USB_BULK_BUF_ALIGMENT BOOLEAN bTxQLastRound = FALSE; #endif /* USB_BULK_BUF_ALIGMENT */ UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; /* Check ring full */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if(Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; buf = &pTxBlk->HeaderBuf[0]; pTxInfo = (TXINFO_STRUC *)buf; pTxWI= (TXWI_STRUC *)&buf[TXINFO_SIZE]; #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* Build our URB for USBD */ hdr_len = TXWISize + TSO_SIZE + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; hdr_copy_len = TXINFO_SIZE + hdr_len; dma_len = hdr_len + pTxBlk->SrcBufLen; padding = (4 - (dma_len % 4)) & 0x03; /* round up to 4 byte alignment*/ dma_len += padding; pTxBlk->Priv = (TXINFO_SIZE + dma_len); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + TSO_SIZE + 802.11 header + payload */ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); #ifndef USB_BULK_BUF_ALIGMENT if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->TxInfoSwLstRnd = 1; bTxQLastRound = TRUE; } #endif /* USB_BULK_BUF_ALIGMENT */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, hdr_copy_len); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize + TSO_SIZE), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pWirelessPacket += (hdr_copy_len); /* We unlock it here to prevent the first 8 bytes maybe over-writed issue.*/ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.*/ /* 2. An interrupt break our routine and handle bulk-out complete.*/ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,*/ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.*/ /* 4. Interrupt complete.*/ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.*/ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.*/ /* and the packet will wrong.*/ pHTTXContext->CurWriteRealPos += hdr_copy_len; #ifndef USB_BULK_BUF_ALIGMENT RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); #endif /* USB_BULK_BUF_ALIGMENT */ #ifdef TX_PKT_SG if (pTxBlk->pkt_info.BufferCount > 1) { INT i, len; void *data; PKT_SG_T *sg = &pTxBlk->pkt_info.sg_list[0]; for (i = 0 ; i < pTxBlk->pkt_info.BufferCount; i++) { data = sg[i].data; len = sg[i].len; if (i == 0) { len -= ((ULONG)pTxBlk->pSrcBufData - (ULONG)sg[i].data); data = pTxBlk->pSrcBufData; } //DBGPRINT(RT_DEBUG_TRACE, ("%s:sg[%d]=0x%x, len=%d\n", __FUNCTION__, i, data, len)); if (len <= 0) { DBGPRINT(RT_DEBUG_ERROR, ("%s():sg[%d] info error, sg.data=0x%x, sg.len=%d, pTxBlk->pSrcBufData=0x%x, pTxBlk->SrcBufLen=%d, data=0x%x, len=%d\n", __FUNCTION__, i, sg[i].data, sg[i].len, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, data, len)); break; } NdisMoveMemory(pWirelessPacket, data, len); pWirelessPacket += len; } } else #endif /* TX_PKT_SG */ { NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; } #ifndef USB_BULK_BUF_ALIGMENT NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWritePosition += pTxBlk->Priv; #ifdef UAPSD_SUPPORT #endif /* UAPSD_SUPPORT */ #ifdef USB_BULK_BUF_ALIGMENT /* when CurWritePosition > 0x6000 mean that it is at the max bulk out size, we CurWriteIdx must move to the next alignment section. Otherwirse, CurWriteIdx will be moved to the next section at databulkout. Writingflag = TRUE ,mean that when we writing resource ,and databulkout happen, So we bulk out when this packet finish. */ if ( (pHTTXContext->CurWritePosition & 0x00006000) == 0x00006000) { pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000); } #else if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx) { PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD; #ifdef RT_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_QA PHEADER_802_11 pHeader80211; if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == QueIdx) { pAd->ate.TxDoneCount++; pAd->RalinkCounters.KickTxCount++; /* always use QID_AC_BE and FIFO_EDCA */ ASSERT(pAd->ate.QID == 0); pAd->ate.TxAc0++; FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); #endif pHeader80211->Sequence = ++pAd->ate.seq; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); #endif if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) { pAd->RalinkCounters.TransmittedByteCount.QuadPart += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); /* get TX_DTX_IDX again */ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); goto kick_out; } else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) { DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); // Tx status enters idle mode. pAd->ate.TxStatus = 0; } else if (!(pAd->ate.Mode & ATE_TXFRAME)) { /* not complete sending yet, but someone press the Stop TX botton */ DBGPRINT(RT_DEBUG_INFO,("not complete sending yet, but someone pressed the Stop TX bottom\n")); DBGPRINT(RT_DEBUG_INFO,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); } else { DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); } #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif // RT_BIG_ENDIAN // INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); continue; } } #endif // RALINK_QA // #endif // RALINK_ATE // // static rate also need NICUpdateFifoStaCounters() function. //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) #ifdef VENDOR_FEATURE1_SUPPORT /* Note: Can not take off the NICUpdateFifoStaCounters(); Or the FIFO overflow rate will be high, i.e. > 3% (see the rate by "iwpriv ra0 show stainfo") Based on different platform, try to find the best value to replace '4' here (overflow rate target is about 0%). */ if (++pAd->FifoUpdateRx >= 4) { NICUpdateFifoStaCounters(pAd); pAd->FifoUpdateRx = 0; } #else NICUpdateFifoStaCounters(pAd); #endif // VENDOR_FEATURE1_SUPPORT // /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifdef CONFIG_AP_SUPPORT #ifdef UAPSD_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { UAPSD_SP_PacketCheck(pAd, pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, ((UCHAR *)pTxRing->Cell[\ pTxRing->TxSwFreeIdx].DmaBuf.AllocVa)+TXWI_SIZE); } #endif // UAPSD_AP_SUPPORT // #endif // CONFIG_AP_SUPPORT // #ifdef RALINK_ATE /* Execution of this block is not allowed when ATE is running. */ if (!(ATE_ON(pAd))) #endif // RALINK_ATE // { pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif // CONFIG_5VT_ENHANCE // PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } //Always assign pNdisPacket as NULL after clear pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif // CONFIG_5VT_ENHANCE // PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } //Always assign pNextNdisPacket as NULL after clear pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } pAd->RalinkCounters.TransmittedByteCount.QuadPart += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); /* get tx_tdx_idx again */ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #else NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #endif #ifdef RALINK_ATE #ifdef RALINK_QA kick_out: #endif // RALINK_QA // /* ATE_TXCONT mode also need to send some normal frames, so let it in. ATE_STOP must be changed not to be 0xff to prevent it from running into this block. */ if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) { // TxDoneCount++ has been done if QA is used. if (pAd->ate.bQATxStart == FALSE) { pAd->ate.TxDoneCount++; } if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) { /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */ INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif // kick Tx-Ring RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); pAd->RalinkCounters.KickTxCount++; } } #endif // RALINK_ATE // // RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } return bReschedule; }
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 RtmpUSB_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { // Check if we have enough space for this bulk-out batch. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); // Zero the last padding. pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; // Finally, set bCurWriting as FALSE pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
USHORT RtmpUSB_WriteSingleTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket; UCHAR QueIdx; unsigned long IrqFlags; NDIS_STATUS Status; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN bTxQLastRound = FALSE; // For USB, didn't need PCI_MAP_SINGLE() //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; // Check ring full. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if(Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; bTxQLastRound = TRUE; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); // We unlock it here to prevent the first 8 bytes maybe over-writed issue. // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. // 2. An interrupt break our routine and handle bulk-out complete. // 3. In the bulk-out compllete, it need to do another bulk-out, // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. // 4. Interrupt complete. // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. // and the packet will wrong. pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
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_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 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; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon( IN PRTMP_ADAPTER pAd, IN INT apidx) { UCHAR DsLen = 1, SsidLen;/*, TimLen = 4, */ /*BitmapControl = 0, VirtualBitmap = 0, EmptySsidLen = 0, SsidLen; */ /* UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; */ HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; #ifdef SPECIFIC_BCN_BUF_SUPPORT unsigned long irqFlag = 0; #endif /* SPECIFIC_BCN_BUF_SUPPORT */ if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) return; PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (pAd->ApCfg.MBSSID[apidx].bHideSsid) SsidLen = 0; else SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, #ifdef P2P_SUPPORT pAd->ApCfg.MBSSID[apidx].Bssid, #endif /* P2P_SUPPORT */ pAd->ApCfg.MBSSID[apidx].Bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == PHY_11B) SupRateLen = 4; #ifdef P2P_SUPPORT if (P2P_GO_ON(pAd)) { UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateIe = IE_SUPP_RATES; UCHAR SupRateLen = 0; SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */ SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */ SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */ SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */ SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */ SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */ SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */ SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */ SupRateLen = 8; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, &SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); } else #endif /* P2P_SUPPORT */ MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != PHY_11B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; /* UCHAR TmpFrame[256]; */ UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J */ /* USA */ /* regulatory class 32, channel set 1~7 */ /* regulatory class 33, channel set 5-11 */ UCHAR rclass32[]= {32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]= {33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == PHY_11BGN_MIXED) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); /* */ /* step 6. move BEACON TXD and frame content to on-chip memory */ /* */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (higher 8KB shared memory) */ RTMP_MAC_SHR_MSEL_LOCK(pAd, HIGHER_SHRMEM, irqFlag); #endif /* SPECIFIC_BCN_BUF_SUPPORT */ for (i=0; i<TXWI_SIZE; i+=4) /* 16-byte TXWI field */ { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + i, longValue); ptr += 4; } /* update BEACON frame content. start right after the 16-byte TXWI field. */ ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWI_SIZE + i, longValue); ptr += 4; } #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (lower 16KB shared memory) */ RTMP_MAC_SHR_MSEL_UNLOCK(pAd, LOWER_SHRMEM, irqFlag); #endif /* SPECIFIC_BCN_BUF_SUPPORT */ pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) UINT i; #endif /* defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) */ HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; PhyMode = pMbss->wdev.PhyMode; if (pMbss->bHideSsid) SsidLen = 0; else SsidLen = pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx) && (pAd->CommonCfg.RegulatoryClass[0] != 0)) { TmpLen2 = 0; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); } #endif /* DOT11K_RRM_SUPPORT */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx)) { InsertTpcReportIE(pAd, pBeaconFrame+FrameLen, &FrameLen, RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); RRM_InsertRRMEnCapIE(pAd, pBeaconFrame+FrameLen, &FrameLen, apidx); } #endif /* DOT11K_RRM_SUPPORT */ #ifdef DOT11_N_SUPPORT /* AP Channel Report */ #ifdef DOT11K_RRM_SUPPORT for (i=0; i<MAX_NUM_OF_REGULATORY_CLASS; i++) { if (pAd->CommonCfg.RegulatoryClass[i] == 0) break; InsertChannelRepIE(pAd, pBeaconFrame+FrameLen, &FrameLen, (PSTRING)pAd->CommonCfg.CountryCode, pAd->CommonCfg.RegulatoryClass[i]); } #else { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif #endif /* DOT11_N_SUPPORT */ #ifdef DOT11R_FT_SUPPORT /* The Mobility Domain information element (MDIE) is present in Beacon ** frame when dot11FastBssTransitionEnable is set to true. */ if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) { PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; FT_CAP_AND_POLICY FtCap; NdisZeroMemory(&FtCap, sizeof(FT_CAP_AND_POLICY)); FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; FT_InsertMdIE(pAd, pBeaconFrame + FrameLen, &FrameLen, pFtCfg->FtMdId, FtCap); } #endif /* DOT11R_FT_SUPPORT */ BeaconTransmit.word = 0; #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 6. move BEACON TXD and frame content to on-chip memory */ updateAllBeacon(pAd, apidx, FrameLen); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } void updateAllBeacon(RTMP_ADAPTER *pAd, INT apidx, ULONG FrameLen) { UCHAR *ptr = NULL; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; UINT32 longValue, reg_base; UINT i = 0; UINT8 TXWISize = pAd->chipCap.TXWISize; ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pMbss->BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } }
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; }
BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx) { PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; #endif PNDIS_PACKET pPacket; UCHAR FREE = 0; TXD_STRUC TxD, *pOriTxD; 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) { #ifdef RALINK_ATE #ifdef RALINK_28xx_QA PHEADER_802_11 pHeader80211; if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == QueIdx) { pAd->ate.TxDoneCount++; pAd->RalinkCounters.KickTxCount++; ASSERT(pAd->ate.QID == 0); pAd->ate.TxAc0++; FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); #endif pHeader80211->Sequence = ++pAd->ate.seq; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); #endif if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) { pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); goto kick_out; } else if ((pAd->ate.TxStatus == 1) && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) { DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); pAd->ate.TxStatus = 0; } else if (!(pAd->ate.Mode & ATE_TXFRAME)) { DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n")); DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); } else { DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); } #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); continue; } } #endif #endif NICUpdateFifoStaCounters(pAd); FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifdef RALINK_ATE if (!(ATE_ON(pAd))) #endif { pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; ASSERT(pPacket == NULL); if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #else NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #endif #ifdef RALINK_ATE #ifdef RALINK_28xx_QA kick_out: #endif if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) { if (pAd->ate.bQATxStart == FALSE) { pAd->ate.TxDoneCount++; } if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) { INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); pAd->RalinkCounters.KickTxCount++; } } #endif } return bReschedule; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue, reg_base; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; PhyMode = pMbss->wdev.PhyMode; if (pMbss->bHideSsid) SsidLen = 0; else SsidLen = pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 6. move BEACON TXD and frame content to on-chip memory */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pMbss->BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); #endif /* AP_QLOAD_SUPPORT */ #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { ULONG TmpLen; UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; UINT8 ie_len; VHT_TXPWR_ENV_IE txpwr_env; ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &vht_txpwr_env_ie, 1, &ie_len, ie_len, &txpwr_env, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11_VHT_AC */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); }
/* REF: ap_connect.c ApMakeBssBeacon */ BOOLEAN CFG80211DRV_OpsBeaconSet( VOID *pAdOrg, VOID *pData, BOOLEAN isAdd) { CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> %d\n", isAdd)); PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ BCN_TIME_CFG_STRUC csr9; UCHAR *ptr; UINT i; UINT32 longValue; UINT8 TXWISize = pAd->chipCap.TXWISize; UINT32 rx_filter_flag; BOOLEAN TxPreamble, SpectrumMgmt = FALSE; BOOLEAN bWmmCapable = FALSE; UCHAR BBPR1 = 0, BBPR3 = 0; INT idx; ULONG offset; CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> \n")); pBeacon = (CMD_RTPRIV_IOCTL_80211_BEACON *)pData; #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) { ULONG TmpLen, WfdIeBitmap; ptr = pBeacon->beacon + pBeacon->beacon_len; WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO); WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &TmpLen); pBeacon->beacon_len += TmpLen; } #endif /* WFD_SUPPORT */ if (isAdd) { rx_filter_flag = APNORMAL; RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ pAd->ApCfg.BssidNum = 1; pAd->MacTab.MsduLifeTime = 20; /* default 5 seconds */ pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; #ifdef INF_AMAZON_SE printk("YF DEBUG: INF_AMAZON_SE\n"); for (i = 0; i < NUM_OF_TX_RING; i++) { pAd->BulkOutDataSizeLimit[i]=24576; } #endif /* INF_AMAZON_SE */ AsicDisableSync(pAd); if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11AN_MIXED; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; } else { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11A; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BG_MIXED; } TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); } PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; const UCHAR *ssid_ie = NULL; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, pBeacon->beacon+36, pBeacon->beacon_len-36); #endif NdisZeroMemory(pMbss->Ssid, pMbss->SsidLen); if (ssid_ie == NULL) { printk("YF Debug: SSID Not Found In Packet\n"); NdisMoveMemory(pMbss->Ssid, "P2P_Linux_AP", 12); pMbss->SsidLen = 12; } else { pMbss->SsidLen = ssid_ie[1]; NdisCopyMemory(pMbss->Ssid, ssid_ie+2, pMbss->SsidLen); printk("YF Debug: SSID: %s, %d\n", pMbss->Ssid, pMbss->SsidLen); } if (isAdd) { //if (pMbss->bWmmCapable) //{ bWmmCapable = FALSE; pMbss->bWmmCapable = FALSE; //} pMbss->MSSIDDev = pAd->net_dev; COPY_MAC_ADDR(pMbss->Bssid, pAd->CurrentAddress); printk("AP BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pAd->CurrentAddress)); /* GO always use WPA2PSK / AES */ pMbss->AuthMode = Ndis802_11AuthModeWPA2PSK; pMbss->WepStatus = Ndis802_11Encryption3Enabled; pMbss->WscSecurityMode = WPA2PSKAES; pMbss->GroupKeyWepStatus = pMbss->WepStatus; pMbss->CapabilityInfo = CAP_GENERATE(1, 0, (pMbss->WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, SpectrumMgmt); RTMPMakeRSNIE(pAd, Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled, MAIN_MBSSID); #ifdef DOT11_N_SUPPORT RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); SetCommonHT(pAd); if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); BBPR1 |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } else #endif /* DOT11_N_SUPPORT */ { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } /* Receiver Antenna selection, write to BBP R3(bit4:3) */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); BBPR3 &= (~0x18); if(pAd->Antenna.field.RxPath == 3) { BBPR3 |= (0x10); } else if(pAd->Antenna.field.RxPath == 2) { BBPR3 |= (0x8); } else if(pAd->Antenna.field.RxPath == 1) { BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { if ((pAd->CommonCfg.PhyMode > PHY_11G) || bWmmCapable) { /* EDCA parameters used for AP's own transmission */ pAd->CommonCfg.APEdcaParm.bValid = TRUE; pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; pAd->CommonCfg.APEdcaParm.Txop[0] = 0; pAd->CommonCfg.APEdcaParm.Txop[1] = 0; pAd->CommonCfg.APEdcaParm.Txop[2] = 94; /*96; */ pAd->CommonCfg.APEdcaParm.Txop[3] = 47; /*48; */ AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ pAd->ApCfg.BssEdcaParm.bValid = TRUE; pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3; pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7; pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2; pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3; pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4; pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3; pAd->ApCfg.BssEdcaParm.Txop[0] = 0; pAd->ApCfg.BssEdcaParm.Txop[1] = 0; pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */ pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */ } else { AsicSetEdcaParm(pAd, NULL); } } #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) { /* Patch UI */ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; } /* init */ if (pAd->CommonCfg.bRdg) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicEnableRDG(pAd); } else { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicDisableRDG(pAd); } #endif /* DOT11_N_SUPPORT */ //AsicSetBssid(pAd, pAd->CurrentAddress); AsicSetMcastWC(pAd); /* In AP mode, First WCID Table in ASIC will never be used. To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */ /* p.s ASIC use all 0xff as termination of WCID table search. */ RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); RTMP_IO_WRITE32(pAd, MAC_WCID_BASE+4, 0x0); /* reset WCID table */ for (idx=2; idx<255; idx++) { offset = MAC_WCID_BASE + (idx * HW_WCID_ENTRY_SIZE); RTMP_IO_WRITE32(pAd, offset, 0x0); RTMP_IO_WRITE32(pAd, offset+4, 0x0); } pAd->MacTab.Content[0].Addr[0] = 0x01; pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; pAd->MacTab.Content[0].HTPhyMode.field.MCS = 3; AsicBBPAdjust(pAd); //MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); { ULONG Addr4; UINT32 regValue; PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; Addr4 = (ULONG)(pP2PBssid[0]) | (ULONG)(pP2PBssid[1] << 8) | (ULONG)(pP2PBssid[2] << 16) | (ULONG)(pP2PBssid[3] << 24); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); Addr4 = 0; Addr4 = (ULONG)(pP2PBssid[4]) | (ULONG)(pP2PBssid[5] << 8); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); regValue &= 0x0000FFFF; regValue |= (1 << 16); if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) regValue |= (1 << 21); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); } #ifdef RTMP_MAC_USB printk("YF DEBUG: RTUSBBssBeaconInit\n"); RTUSBBssBeaconInit(pAd); #endif /* RTMP_MAC_USB */ } UCHAR apcliIdx, apidx = MAIN_MBSSID; //pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; printk("YF DEBUG: Beacon Len %d\n", pBeacon->beacon_len); printk("YF DEBUG: Beacon Interval %d\n", pBeacon->interval); BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, pBeacon->beacon_len, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif for (i=0; i<TXWISize; i+=4) /* 16-byte TXWI field */ { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[0] + i, longValue); ptr += 4; } /* update BEACON frame content. start right after the 16-byte TXWI field. */ ptr = pBeacon->beacon; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< pBeacon->beacon_len; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[0] + TXWISize + i, longValue); ptr += 4; } if (isAdd) { /* Enable Bss Sync*/ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); csr9.field.BeaconInterval = (pBeacon->interval) << 4; /* ASIC register in units of 1/16 TU*/ csr9.field.bTsfTicking = 1; csr9.field.TsfSyncMode = 3; csr9.field.bTBTTEnable = 1; csr9.field.bBeaconGen = 1; RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); pAd->P2pCfg.bSentProbeRSP = TRUE; #ifdef RTMP_MAC_USB /* * Support multiple BulkIn IRP, * the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. */ UCHAR num_idx; for(num_idx=0; num_idx < pAd->CommonCfg.NumOfBulkInIRP; num_idx++) { RTUSBBulkReceive(pAd); printk("RTUSBBulkReceive!\n" ); } #endif /* RTMP_MAC_USB */ } #ifdef WFD_SUPPORT pAd->StaCfg.WfdCfg.bSuppGoOn = TRUE; #endif /* WFD_SUPPORT */ return TRUE; }
/* ========================================================================== 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; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PNDIS_PACKET pPacket=NULL; PUCHAR pDest=NULL; PVOID AllocVa=NULL; NDIS_PHYSICAL_ADDRESS AllocPa; HTTRANSMIT_SETTING TxHTPhyMode; PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; PTXWI_STRUC pTxWI = (PTXWI_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 */ /* fill TxWI */ TxHTPhyMode.field.BW = pATEInfo->TxWI.BW; TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.ShortGI; TxHTPhyMode.field.STBC = pATEInfo->TxWI.STBC; TxHTPhyMode.field.MCS = pATEInfo->TxWI.MCS; TxHTPhyMode.field.MODE = pATEInfo->TxWI.PHYMODE; if (pATEInfo->bQATxStart == TRUE) { /* always use QID_AC_BE and FIFO_EDCA */ ATEWriteTxWI(pAd, pTxWI, pATEInfo->TxWI.FRAG, pATEInfo->TxWI.CFACK, pATEInfo->TxWI.TS, pATEInfo->TxWI.AMPDU, pATEInfo->TxWI.ACK, pATEInfo->TxWI.NSEQ, pATEInfo->TxWI.BAWinSize, 0, pATEInfo->TxWI.MPDUtotalByteCount, pATEInfo->TxWI.PacketId, 0, 0, pATEInfo->TxWI.txop/*IFS_HTTXOP*/, pATEInfo->TxWI.CFACK/*FALSE*/, &TxHTPhyMode); } 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; NdisMoveMemory(pDMAHeaderBufVA + TXWISize, TemplateFrame, pATEInfo->HLen); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, pATEInfo->Addr1, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, ETH_LENGTH_OF_ADDRESS); } #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; GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->DLen; } else #endif /* RALINK_QA */ { GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; } /* 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++) { /* default payload is 0xA5 */ pDest[pos] = pATEInfo->Payload; } } /* 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 /* !RT_BIG_ENDIAN */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* prepare TxD */ NdisZeroMemory(pTxD, TXD_SIZE); RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); /* 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; 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 */ { NdisZeroMemory(pTxD, TXD_SIZE); RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + LENGTH_802_11; pTxD->LastSec0 = 0; pTxD->SDPtr1 = AllocPa; pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec1 = 1; } #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; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon( IN PRTMP_ADAPTER pAd, IN INT apidx) { UCHAR DsLen = 1, SsidLen;//, TimLen = 4, //BitmapControl = 0, VirtualBitmap = 0, EmptySsidLen = 0, SsidLen; // UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue; HTTRANSMIT_SETTING BeaconTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. UCHAR PhyMode, SupRateLen; #ifdef SPECIFIC_BCN_BUF_SUPPORT unsigned long irqFlag = 0; #endif // SPECIFIC_BCN_BUF_SUPPORT // BOOLEAN bHasWpsIE = FALSE; if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) return; PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (pAd->ApCfg.MBSSID[apidx].bHideSsid) SsidLen = 0; else SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[apidx].Bssid); // for update framelen to TxWI later. SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == PHY_11B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != PHY_11B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } // add country IE, power constraint IE if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); // prepare channel information #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif // EXT_BUILD_CHANNEL_LIST // // need to do the padding bit check, and concatenate it if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; } #ifdef DOT11_N_SUPPORT // AP Channel Report { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; // 802.11n D2.0 Annex J // USA // regulatory class 32, channel set 1~7 // regulatory class 33, channel set 5-11 UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; //sizeof(rclass32); if (PhyMode == PHY_11BGN_MIXED) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif // DOT11_N_SUPPORT // #ifdef WSC_AP_SUPPORT // add Simple Config Information Element if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) { bHasWpsIE = TRUE; } if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif // DOT1X_SUPPORT // (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif // WSC_AP_SUPPORT // BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); // // step 6. move BEACON TXD and frame content to on-chip memory // ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (higher 8KB shared memory) */ if (pAd->BcnCB.bHighShareMemSupport == 1) RTMP_MAC_SHR_MSEL_LOCK(pAd, HIGHER_SHRMEM, irqFlag); #endif // SPECIFIC_BCN_BUF_SUPPORT // for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + i, longValue); ptr += 4; } // update BEACON frame content. start right after the 16-byte TXWI field. ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWI_SIZE + i, longValue); ptr += 4; } #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (lower 16KB shared memory) */ if (pAd->BcnCB.bHighShareMemSupport == 1) RTMP_MAC_SHR_MSEL_UNLOCK(pAd, LOWER_SHRMEM, irqFlag); #endif // SPECIFIC_BCN_BUF_SUPPORT // pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; }
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; }
/* ========================================================================== 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; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PNDIS_PACKET pPacket=NULL; PUCHAR pDest=NULL; PVOID AllocVa=NULL; NDIS_PHYSICAL_ADDRESS AllocPa; HTTRANSMIT_SETTING TxHTPhyMode; PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; PTXWI_STRUC pTxWI = (PTXWI_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 */ /* fill TxWI */ TxHTPhyMode.field.BW = pATEInfo->TxWI.BW; TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.ShortGI; TxHTPhyMode.field.STBC = pATEInfo->TxWI.STBC; TxHTPhyMode.field.MCS = pATEInfo->TxWI.MCS; TxHTPhyMode.field.MODE = pATEInfo->TxWI.PHYMODE; if (pATEInfo->bQATxStart == TRUE) { /* always use QID_AC_BE and FIFO_EDCA */ ATEWriteTxWI(pAd, pTxWI, pATEInfo->TxWI.FRAG, pATEInfo->TxWI.CFACK, pATEInfo->TxWI.TS, pATEInfo->TxWI.AMPDU, pATEInfo->TxWI.ACK, pATEInfo->TxWI.NSEQ, pATEInfo->TxWI.BAWinSize, 0, pATEInfo->TxWI.MPDUtotalByteCount, pATEInfo->TxWI.PacketId, 0, 0, pATEInfo->TxWI.txop/*IFS_HTTXOP*/, pATEInfo->TxWI.CFACK/*FALSE*/, &TxHTPhyMode); #ifdef TXBF_SUPPORT if (IS_RT2883(pAd) || IS_RT3883(pAd)) { /* Must copy rsv bits to actual TxWI */ pTxWI->rsv = pATEInfo->TxWI.rsv; pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; pTxWI->Sounding = pATEInfo->TxWI.Sounding; pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; pTxWI->NDPSndBW = pATEInfo->TxWI.NDPSndBW; pTxWI->NDPSndRate = pATEInfo->TxWI.NDPSndRate; } #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) { if (IS_RT2883(pAd) || IS_RT3883(pAd)) { pTxWI->rsv = 0; pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; pTxWI->Sounding = (pATEInfo->txSoundingMode == 1 ? 1 : 0); pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; pTxWI->NDPSndBW = pATEInfo->TxWI.BW; if (pATEInfo->txSoundingMode == 3) pTxWI->NDPSndRate = 2; else if (pATEInfo->txSoundingMode == 2) pTxWI->NDPSndRate = 1; else pTxWI->NDPSndRate = 0; } } #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 */ { 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, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, ETH_LENGTH_OF_ADDRESS); } #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 - LENGTH_802_11; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; #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++) { /* default payload is 0xA5 */ pDest[pos] = pATEInfo->Payload; } } /* 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 /* !RT_BIG_ENDIAN */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* prepare TxD */ NdisZeroMemory(pTxD, TXD_SIZE); RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); /* 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; 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 */ { NdisZeroMemory(pTxD, TXD_SIZE); RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + LENGTH_802_11; pTxD->LastSec0 = 0; pTxD->SDPtr1 = AllocPa; pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec1 = 1; } #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; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue, reg_base; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) return; PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (pAd->ApCfg.MBSSID[apidx].bHideSsid) SsidLen = 0; else SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[apidx].Bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); /* step 6. move BEACON TXD and frame content to on-chip memory */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; ULONG FrameLen = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; ULONG UpdatePos = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ pMbss = &pAd->ApCfg.MBSSID[apidx]; pComCfg = &pAd->CommonCfg; PhyMode = pMbss->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); #ifdef HOSTAPD_SUPPORT if ( pAd->ApCfg.MBSSID[apidx].HostapdWPS && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) { bHasWpsIE = TRUE; } #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ #if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) */ if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pMbss->AuthMode == Ndis802_11AuthModeWPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pMbss->AuthMode == Ndis802_11AuthModeWAICERT) || (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (pMbss->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (pMbss->bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2;*/ /* no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, PID_MGMT, QID_MGMT, 0, IFS_HTTXOP, FALSE, &BeaconTransmit); /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); }
INT ATESetUpFrame( IN PRTMP_ADAPTER pAd, IN UINT32 TxIdx) { PATE_INFO pATEInfo = &(pAd->ate); UINT pos = 0; PTX_CONTEXT pNullContext; PUCHAR pDest; HTTRANSMIT_SETTING TxHTPhyMode; TXWI_STRUC *pTxWI; TXINFO_STRUC *pTxInfo; UINT32 TransferBufferLength, OrgBufferLength = 0; UCHAR padLen = 0; UINT8 TXWISize = pAd->chipCap.TXWISize; #ifdef RALINK_QA PHEADER_802_11 pHeader80211 = NULL; #endif /* RALINK_QA */ if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { return -1; } /* We always use QID_AC_BE and FIFO_EDCA in ATE mode. */ pNullContext = &(pAd->NullContext); ASSERT(pNullContext != NULL); if (pNullContext->InUse == FALSE) { /* set the in use bit */ pNullContext->InUse = TRUE; NdisZeroMemory(&(pAd->NullFrame), sizeof(HEADER_802_11)); /* fill 802.11 header */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { pHeader80211 = NdisMoveMemory(&(pAd->NullFrame), pATEInfo->Header, pATEInfo->HLen); } else #endif /* RALINK_QA */ { NdisMoveMemory(&(pAd->NullFrame), TemplateFrame, sizeof(HEADER_802_11)); } #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)&(pAd->NullFrame), DIR_READ, FALSE); #endif /* RT_BIG_ENDIAN */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* modify sequence number... */ if (pATEInfo->TxDoneCount == 0) { pATEInfo->seq = pHeader80211->Sequence; } else { pHeader80211->Sequence = ++pATEInfo->seq; } /* We already got all the address fields from QA GUI. */ } else #endif /* RALINK_QA */ { COPY_MAC_ADDR(pAd->NullFrame.Addr1, pATEInfo->Addr1); COPY_MAC_ADDR(pAd->NullFrame.Addr2, pATEInfo->Addr2); COPY_MAC_ADDR(pAd->NullFrame.Addr3, pATEInfo->Addr3); } RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], TX_BUFFER_NORMSIZE); pTxInfo = (TXINFO_STRUC *)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0]; #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* Avoid to exceed the range of WirelessPacket[]. */ ASSERT(pATEInfo->TxInfo.TxInfoPktLen <= (MAX_FRAME_SIZE - 34/* == 2312 */)); NdisMoveMemory(pTxInfo, &(pATEInfo->TxInfo), sizeof(pATEInfo->TxInfo)); } else #endif /* RALINK_QA */ { /* Avoid to exceed the range of WirelessPacket[]. */ ASSERT(pATEInfo->TxLength <= (MAX_FRAME_SIZE - 34/* == 2312 */)); /* pTxInfo->TxInfoPktLen will be updated to include padding later */ ATEWriteTxInfo(pAd, pTxInfo, (USHORT)(TXWISize + pATEInfo->TxLength) , TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); pTxInfo->TxInfoQSEL = FIFO_EDCA; } pTxWI = (TXWI_STRUC *)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; /* fill TxWI */ if (pATEInfo->bQATxStart == TRUE) { TxHTPhyMode.field.BW = pATEInfo->TxWI.TxWIBW; TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.TxWIShortGI; TxHTPhyMode.field.STBC = pATEInfo->TxWI.TxWISTBC; TxHTPhyMode.field.MCS = pATEInfo->TxWI.TxWIMCS; TxHTPhyMode.field.MODE = pATEInfo->TxWI.TxWIPHYMODE; ATEWriteTxWI(pAd, pTxWI, pATEInfo->TxWI.TxWIFRAG, pATEInfo->TxWI.TxWITS, pATEInfo->TxWI.TxWIAMPDU, pATEInfo->TxWI.TxWIACK, pATEInfo->TxWI.TxWINSEQ, pATEInfo->TxWI.TxWIBAWinSize, BSSID_WCID, pATEInfo->TxWI.TxWIMPDUByteCnt/* include 802.11 header */, pATEInfo->TxWI.TxWIPacketId, 0, pATEInfo->TxWI.TxWITXOP/*IFS_HTTXOP*/, pATEInfo->TxWI.TxWICFACK /*FALSE*/, TxHTPhyMode); } else { TxHTPhyMode.field.BW = pATEInfo->TxWI.TxWIBW; TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.TxWIShortGI; TxHTPhyMode.field.STBC = 0; TxHTPhyMode.field.MCS = pATEInfo->TxWI.TxWIMCS; TxHTPhyMode.field.MODE = pATEInfo->TxWI.TxWIPHYMODE; ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE /* No ack required. */, FALSE, 0, BSSID_WCID, pATEInfo->TxLength, 0, 0, IFS_HTTXOP, FALSE, TxHTPhyMode); } hex_dump("ATE", pAd->NullContext.TransferBuffer->field.WirelessPacket, 24); dump_txinfo(pAd, pTxInfo); dumpTxWI(pAd, pTxWI); RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE + TXWISize], &pAd->NullFrame, sizeof(HEADER_802_11)); pDest = &(pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE + TXWISize + sizeof(HEADER_802_11)]); /* prepare frame payload */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* copy the pattern one by one to the frame payload */ if ((pATEInfo->PLen != 0) && (pATEInfo->DLen != 0)) { for (pos = 0; pos < pATEInfo->DLen; pos += pATEInfo->PLen) { RTMPMoveMemory(pDest, pATEInfo->Pattern, pATEInfo->PLen); pDest += pATEInfo->PLen; } } TransferBufferLength = TXINFO_SIZE + TXWISize + pATEInfo->TxWI.TxWIMPDUByteCnt; } else #endif /* RALINK_QA */ { for (pos = 0; pos < (pATEInfo->TxLength - sizeof(HEADER_802_11)); pos++) { /* default payload is 0xA5 */ *pDest = pATEInfo->Payload; pDest += 1; } TransferBufferLength = TXINFO_SIZE + TXWISize + pATEInfo->TxLength; } OrgBufferLength = TransferBufferLength; TransferBufferLength = (TransferBufferLength + 3) & (~3); /* Always add 4 extra bytes at every packet. */ padLen = TransferBufferLength - OrgBufferLength + 4;/* 4 == last packet padding */ /* RTMP_PKT_TAIL_PADDING == 11. [11 == 3(max 4 byte padding) + 4(last packet padding) + 4(MaxBulkOutsize align padding)] */ ASSERT((padLen <= (RTMP_PKT_TAIL_PADDING - 4/* 4 == MaxBulkOutsize alignment padding */))); /* Now memzero all extra padding bytes. */ NdisZeroMemory(pDest, padLen); pDest += padLen; /* Update pTxInfo->TxInfoPktLen to include padding. */ pTxInfo->TxInfoPktLen = TransferBufferLength - TXINFO_SIZE; TransferBufferLength += 4; /* If TransferBufferLength is multiple of 64, add extra 4 bytes again. */ if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0) { NdisZeroMemory(pDest, 4); TransferBufferLength += 4; } /* Fill out frame length information for global Bulk out arbitor. */ pAd->NullContext.BulkOutSize = TransferBufferLength; } #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); RTMPFrameEndianChange(pAd, (((PUCHAR)pTxInfo) + TXWISize + TXINFO_SIZE), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); #endif /* RT_BIG_ENDIAN */ hex_dump("ATE TX", &pAd->NullContext.TransferBuffer->field.WirelessPacket[0], TXWISize + TXINFO_SIZE); return 0; }
USHORT RtmpUSB_WriteFragTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/ UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; #ifdef USB_BULK_BUF_ALIGMENT BOOLEAN bLasAlignmentsectiontRound = FALSE; #else BOOLEAN TxQLastRound = FALSE; #endif /* USB_BULK_BUF_ALIGMENT */ UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { /* Check if we have enough space for this bulk-out batch.*/ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]); pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer*/ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD*/ DMAHdrLen = TXWISize + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment*/ USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload*/ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->TxInfoUDMATxburst = 0; #ifdef USB_BULK_BUF_ALIGMENT /* when CurWritePosition > 0x6000 mean that it is at the max bulk out size, we CurWriteIdx must move to the next alignment section. Otherwirse, CurWriteIdx will be moved to the next section at databulkout. (((pHTTXContext->CurWritePosition + 3906)& 0x00007fff) & 0xffff6000) == 0x00006000) we must make sure that the last fragNun packet just over the 0x6000 otherwise it will error because the last frag packet will at the section but will not bulk out. ex: when secoend packet writeresouce and it > 0x6000 And the last packet writesource and it also > 0x6000 at this time CurWriteIdx++ but when data bulk out , because at second packet it will > 0x6000 , the last packet will not bulk out. */ if ( ((pHTTXContext->CurWritePosition + 3906) & 0x00006000) == 0x00006000) { bLasAlignmentsectiontRound = TRUE; pTxInfo->bFragLasAlignmentsectiontRound = 1; } #else if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->TxInfoSwLstRnd = 1; TxQLastRound = TRUE; } #endif /* USB_BULK_BUF_ALIGMENT */ } else { pTxInfo->TxInfoUDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWISize + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pWirelessPacket += (TXINFO_SIZE + TXWISize + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWISize + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); /* Zero the last padding.*/ pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.*/ pHTTXContext->CurWritePosition += pTxBlk->Priv; #ifndef USB_BULK_BUF_ALIGMENT if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; #endif /* USB_BULK_BUF_ALIGMENT */ #ifdef USB_BULK_BUF_ALIGMENT if(bLasAlignmentsectiontRound == TRUE) { pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000); } #endif /* USB_BULK_BUF_ALIGMENT */ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; #ifdef UAPSD_SUPPORT #endif /* UAPSD_SUPPORT */ /* Finally, set bCurWriting as FALSE*/ pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
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 RtmpUSB_WriteMultiTxResource( IN RTMP_ADAPTER *pAd, IN TX_BLK *pTxBlk, IN UCHAR frmNum, OUT USHORT *freeCnt) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/ UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UCHAR *pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT8 TXWISize = pAd->chipCap.TXWISize; /* get Tx Ring Resource & Dma Buffer address*/ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if(frmNum == 0) { /* Check if we have enough space for this bulk-out batch.*/ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]); pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); #ifndef USB_BULK_BUF_ALIGMENT /* Reserve space for 8 bytes padding.*/ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } #endif /* USB_BULK_BUF_ALIGMENT */ fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* 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; /* Update the pTxBlk->Priv.*/ pTxBlk->Priv = TXINFO_SIZE + TXWISize + hwHdrLen; /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter.*/ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); /* Copy it.*/ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE); #endif /* RT_BIG_ENDIAN */ pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /*hwHdrLen = pTxBlk->MpduHeaderLen;*/ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { /* It should not happened now unless we are going to shutdown.*/ DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } /* We unlock it here to prevent the first 8 bytes maybe over-write issue. 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. 2. An interrupt break our routine and handle bulk-out complete. 3. In the bulk-out compllete, it need to do another bulk-out, if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. 4. Interrupt complete. 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. and the packet will wrong. */ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } /* Copy the frame content into DMA buffer and update the pTxBlk->Priv*/ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: /* Release the skb buffer here*/ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
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; }