2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
29 All functions in this file must be PCI-depended, or you should out your function
33 #include "../rt_config.h"
36 USHORT RtmpPCI_WriteTxResource(
40 OUT USHORT *FreeNumber)
43 UCHAR *pDMAHeaderBufVA;
44 USHORT TxIdx, RetTxIdx;
47 PRTMP_TX_RING pTxRing;
51 // get Tx Ring Resource
53 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
54 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
55 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
56 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
58 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
59 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
61 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
62 hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
66 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
67 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
69 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
71 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
72 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
75 // build Tx Descriptor
78 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
79 NdisZeroMemory(pTxD, TXD_SIZE);
81 pTxD->SDPtr0 = BufBasePaLow;
82 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
83 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
84 pTxD->SDLen1 = pTxBlk->SrcBufLen;
86 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
88 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
94 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
95 pTxRing->TxCpuIdx = TxIdx;
103 USHORT RtmpPCI_WriteSingleTxResource(
104 IN PRTMP_ADAPTER pAd,
107 OUT USHORT *FreeNumber)
110 UCHAR *pDMAHeaderBufVA;
111 USHORT TxIdx, RetTxIdx;
118 PRTMP_TX_RING pTxRing;
122 // get Tx Ring Resource
124 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
125 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
126 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
127 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
129 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
130 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
131 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
133 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
135 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
136 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
139 // build Tx Descriptor
141 #ifndef RT_BIG_ENDIAN
142 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
144 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
148 NdisZeroMemory(pTxD, TXD_SIZE);
150 pTxD->SDPtr0 = BufBasePaLow;
151 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
152 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
153 pTxD->SDLen1 = pTxBlk->SrcBufLen;
155 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
157 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
159 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
160 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
161 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
162 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
163 #endif // RT_BIG_ENDIAN //
169 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
170 pTxRing->TxCpuIdx = TxIdx;
178 USHORT RtmpPCI_WriteMultiTxResource(
179 IN PRTMP_ADAPTER pAd,
182 OUT USHORT *FreeNumber)
185 UCHAR *pDMAHeaderBufVA;
186 USHORT TxIdx, RetTxIdx;
193 PRTMP_TX_RING pTxRing;
197 bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
200 // get Tx Ring Resource
202 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
203 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
204 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
205 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
209 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
210 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
211 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
212 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
213 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
214 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
215 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
217 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
218 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
220 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
224 firstDMALen = pTxBlk->MpduHeaderLen;
227 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
229 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
230 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
233 // build Tx Descriptor
235 #ifndef RT_BIG_ENDIAN
236 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
238 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
242 NdisZeroMemory(pTxD, TXD_SIZE);
244 pTxD->SDPtr0 = BufBasePaLow;
245 pTxD->SDLen0 = firstDMALen; // include padding
246 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
247 pTxD->SDLen1 = pTxBlk->SrcBufLen;
249 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
251 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
255 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
258 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
260 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
261 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
262 #endif // RT_BIG_ENDIAN //
268 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
269 pTxRing->TxCpuIdx = TxIdx;
278 VOID RtmpPCI_FinalWriteTxResource(
279 IN PRTMP_ADAPTER pAd,
281 IN USHORT totalMPDUSize,
282 IN USHORT FirstTxIdx)
286 PRTMP_TX_RING pTxRing;
289 // get Tx Ring Resource
291 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
292 pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
293 pTxWI->MPDUtotalByteCount = totalMPDUSize;
295 RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
296 #endif // RT_BIG_ENDIAN //
301 VOID RtmpPCIDataLastTxIdx(
302 IN PRTMP_ADAPTER pAd,
311 PRTMP_TX_RING pTxRing;
314 // get Tx Ring Resource
316 pTxRing = &pAd->TxRing[QueIdx];
319 // build Tx Descriptor
321 #ifndef RT_BIG_ENDIAN
322 pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
324 pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
332 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
333 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
334 #endif // RT_BIG_ENDIAN //
339 USHORT RtmpPCI_WriteFragTxResource(
340 IN PRTMP_ADAPTER pAd,
343 OUT USHORT *FreeNumber)
345 UCHAR *pDMAHeaderBufVA;
346 USHORT TxIdx, RetTxIdx;
353 PRTMP_TX_RING pTxRing;
358 // Get Tx Ring Resource
360 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
361 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
362 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
363 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
366 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
368 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
369 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
371 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
372 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
376 // Build Tx Descriptor
378 #ifndef RT_BIG_ENDIAN
379 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
381 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
385 NdisZeroMemory(pTxD, TXD_SIZE);
387 if (fragNum == pTxBlk->TotalFragNum)
389 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
390 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
393 pTxD->SDPtr0 = BufBasePaLow;
394 pTxD->SDLen0 = firstDMALen; // include padding
395 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
396 pTxD->SDLen1 = pTxBlk->SrcBufLen;
400 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
403 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
404 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
405 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
406 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
407 #endif // RT_BIG_ENDIAN //
410 pTxBlk->Priv += pTxBlk->SrcBufLen;
415 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
416 pTxRing->TxCpuIdx = TxIdx;
426 Must be run in Interrupt context
427 This function handle PCI specific TxDesc and cpu index update and kick the packet out.
429 int RtmpPCIMgmtKickOut(
430 IN RTMP_ADAPTER *pAd,
432 IN PNDIS_PACKET pPacket,
441 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
444 pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa;
447 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
449 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
452 pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
453 pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
455 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
460 pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
461 pTxD->SDLen0 = SrcBufLen;
464 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
465 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
468 //==================================================================
469 /* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n"));
470 for (i = 0; i < (TXWI_SIZE+24); i++)
473 DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i)));
475 DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: "));
477 DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));
479 DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/
480 //=======================================================================
482 pAd->RalinkCounters.KickTxCount++;
483 pAd->RalinkCounters.OneSecTxDoneCount++;
485 // Increase TX_CTX_IDX, but write to register later.
486 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
488 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
494 #ifdef CONFIG_STA_SUPPORT
496 ========================================================================
499 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
502 pRxD Pointer to the Rx descriptor
505 NDIS_STATUS_SUCCESS No err
506 NDIS_STATUS_FAILURE Error
510 ========================================================================
512 NDIS_STATUS RTMPCheckRxError(
513 IN PRTMP_ADAPTER pAd,
514 IN PHEADER_802_11 pHeader,
515 IN PRXWI_STRUC pRxWI,
516 IN PRT28XX_RXD_STRUC pRxD)
521 // Phy errors & CRC errors
522 if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
524 // Check RSSI for Noise Hist statistic collection.
525 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
527 pAd->StaCfg.RPIDensity[0] += 1;
529 pAd->StaCfg.RPIDensity[1] += 1;
531 pAd->StaCfg.RPIDensity[2] += 1;
533 pAd->StaCfg.RPIDensity[3] += 1;
535 pAd->StaCfg.RPIDensity[4] += 1;
537 pAd->StaCfg.RPIDensity[5] += 1;
539 pAd->StaCfg.RPIDensity[6] += 1;
541 pAd->StaCfg.RPIDensity[7] += 1;
543 return(NDIS_STATUS_FAILURE);
546 // Add Rx size to channel load counter, we should ignore error counts
547 pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
549 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
552 if (pHeader->FC.ToDs)
554 return(NDIS_STATUS_FAILURE);
558 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
559 // I am kind of doubting the U2M bit operation
560 // if (pRxD->U2M == 0)
561 // return(NDIS_STATUS_FAILURE);
563 // drop decyption fail frame
566 if (pRxD->CipherErr == 2)
567 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
568 else if (pRxD->CipherErr == 1)
569 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
570 else if (pRxD->CipherErr == 3)
571 DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
573 if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
574 RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
576 DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
579 pRxD->Mcast | pRxD->Bcast,
581 pRxWI->WirelessCliID,
582 // CipherName[pRxD->CipherAlg],
588 if (pRxD->CipherErr == 2)
590 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
591 #ifdef WPA_SUPPLICANT_SUPPORT
592 if (pAd->StaCfg.WpaSupplicantUP)
593 WpaSendMicFailureToWpaSupplicant(pAd,
594 (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
596 #endif // WPA_SUPPLICANT_SUPPORT //
597 RTMPReportMicError(pAd, pWpaKey);
599 if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
600 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
602 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
606 return(NDIS_STATUS_SUCCESS);
607 /*if ((pRxD->CipherAlg == CIPHER_AES) &&
608 (pHeader->Sequence == pAd->FragFrame.Sequence))
611 // Acceptable since the First FragFrame no CipherErr problem.
613 return(NDIS_STATUS_SUCCESS);
616 return(NDIS_STATUS_FAILURE);
619 return(NDIS_STATUS_SUCCESS);
621 #endif // CONFIG_STA_SUPPORT //
624 BOOLEAN RTMPFreeTXDUponTxDmaDone(
625 IN PRTMP_ADAPTER pAd,
628 PRTMP_TX_RING pTxRing;
633 PNDIS_PACKET pPacket;
635 TXD_STRUC TxD, *pOriTxD;
637 BOOLEAN bReschedule = FALSE;
640 ASSERT(QueIdx < NUM_OF_TX_RING);
641 pTxRing = &pAd->TxRing[QueIdx];
643 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
644 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
646 // RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
648 #ifdef RALINK_28xx_QA
649 PHEADER_802_11 pHeader80211;
651 if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
653 if (pAd->ate.QID == QueIdx)
655 pAd->ate.TxDoneCount++;
656 pAd->RalinkCounters.KickTxCount++;
658 /* always use QID_AC_BE and FIFO_EDCA */
659 ASSERT(pAd->ate.QID == 0);
663 #ifndef RT_BIG_ENDIAN
664 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
666 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
669 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
673 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
677 pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
679 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE);
681 pHeader80211->Sequence = ++pAd->ate.seq;
683 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
686 if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount))
688 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
689 pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
690 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
691 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
693 /* get TX_DTX_IDX again */
694 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
697 else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))
699 DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n"));
701 // Tx status enters idle mode.
702 pAd->ate.TxStatus = 0;
704 else if (!(pAd->ate.Mode & ATE_TXFRAME))
706 /* not complete sending yet, but someone press the Stop TX botton */
707 DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n"));
708 DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode));
712 DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx));
715 #ifndef RT_BIG_ENDIAN
716 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
718 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
720 #endif // RT_BIG_ENDIAN //
722 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
726 #endif // RALINK_28xx_QA //
727 #endif // RALINK_ATE //
729 // static rate also need NICUpdateFifoStaCounters() function.
730 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
731 NICUpdateFifoStaCounters(pAd);
733 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
735 #ifndef RT_BIG_ENDIAN
736 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
738 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
741 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
745 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
752 /* Execution of this block is not allowed when ATE is running. */
754 #endif // RALINK_ATE //
756 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
759 #ifdef CONFIG_5VT_ENHANCE
760 if (RTMP_GET_PACKET_5VT(pPacket))
761 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
763 #endif // CONFIG_5VT_ENHANCE //
764 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
765 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
767 //Always assign pNdisPacket as NULL after clear
768 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
770 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
772 ASSERT(pPacket == NULL);
775 #ifdef CONFIG_5VT_ENHANCE
776 if (RTMP_GET_PACKET_5VT(pPacket))
777 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
779 #endif // CONFIG_5VT_ENHANCE //
780 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
781 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
783 //Always assign pNextNdisPacket as NULL after clear
784 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
787 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
788 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
789 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
790 /* get tx_tdx_idx again */
791 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
793 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
796 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
800 #ifdef RALINK_28xx_QA
802 #endif // RALINK_28xx_QA //
805 ATE_TXCONT mode also need to send some normal frames, so let it in.
806 ATE_STOP must be changed not to be 0xff
807 to prevent it from running into this block.
809 if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx))
811 // TxDoneCount++ has been done if QA is used.
812 if (pAd->ate.bQATxStart == FALSE)
814 pAd->ate.TxDoneCount++;
816 if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE))
818 /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */
819 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
820 #ifndef RT_BIG_ENDIAN
821 pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
823 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
826 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
830 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
833 #ifndef RT_BIG_ENDIAN
834 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
836 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
840 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx);
841 pAd->RalinkCounters.KickTxCount++;
844 #endif // RALINK_ATE //
845 // RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
855 ========================================================================
858 Process TX Rings DMA Done interrupt, running in DPC level
861 Adapter Pointer to our adapter
866 IRQL = DISPATCH_LEVEL
868 ========================================================================
870 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
871 IN PRTMP_ADAPTER pAd,
872 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
875 unsigned long IrqFlags;
876 BOOLEAN bReschedule = FALSE;
878 // Make sure Tx ring resource won't be used by other threads
879 //NdisAcquireSpinLock(&pAd->TxRingLock);
881 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
883 if (TxRingBitmap.field.Ac0DmaDone)
884 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
886 if (TxRingBitmap.field.HccaDmaDone)
887 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
890 if (TxRingBitmap.field.Ac3DmaDone)
891 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
893 if (TxRingBitmap.field.Ac2DmaDone)
894 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
896 if (TxRingBitmap.field.Ac1DmaDone)
897 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
899 // Make sure to release Tx ring resource
900 //NdisReleaseSpinLock(&pAd->TxRingLock);
901 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
903 // Dequeue outgoing frames from TxSwQueue[] and process it
904 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
911 ========================================================================
914 Process MGMT ring DMA done interrupt, running in DPC level
917 pAd Pointer to our adapter
922 IRQL = DISPATCH_LEVEL
926 ========================================================================
928 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
929 IN PRTMP_ADAPTER pAd)
936 PNDIS_PACKET pPacket;
939 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
941 NdisAcquireSpinLock(&pAd->MgmtRingLock);
943 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
944 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
948 pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
951 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
953 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
956 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
961 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
962 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
964 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
966 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
969 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
970 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
972 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
973 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
976 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
977 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD);
980 NdisReleaseSpinLock(&pAd->MgmtRingLock);
982 #ifdef CONFIG_STA_SUPPORT
983 #endif // CONFIG_STA_SUPPORT //
988 ========================================================================
992 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
994 IRQL = DISPATCH_LEVEL
996 ========================================================================
998 VOID RTMPHandleTBTTInterrupt(
999 IN PRTMP_ADAPTER pAd)
1002 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1010 ========================================================================
1012 Routine Description:
1014 pAd Pointer to our adapter. Rewrite beacon content before next send-out.
1016 IRQL = DISPATCH_LEVEL
1018 ========================================================================
1020 VOID RTMPHandlePreTBTTInterrupt(
1021 IN PRTMP_ADAPTER pAd)
1024 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1026 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
1033 VOID RTMPHandleRxCoherentInterrupt(
1034 IN PRTMP_ADAPTER pAd)
1036 WPDMA_GLO_CFG_STRUC GloCfg;
1040 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
1044 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
1046 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
1048 GloCfg.field.EnTXWriteBackDDONE = 0;
1049 GloCfg.field.EnableRxDMA = 0;
1050 GloCfg.field.EnableTxDMA = 0;
1051 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1053 RTMPRingCleanUp(pAd, QID_AC_BE);
1054 RTMPRingCleanUp(pAd, QID_AC_BK);
1055 RTMPRingCleanUp(pAd, QID_AC_VI);
1056 RTMPRingCleanUp(pAd, QID_AC_VO);
1057 /*RTMPRingCleanUp(pAd, QID_HCCA);*/
1058 RTMPRingCleanUp(pAd, QID_MGMT);
1059 RTMPRingCleanUp(pAd, QID_RX);
1061 RTMPEnableRxTx(pAd);
1063 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
1069 VOID DBGPRINT_TX_RING(
1070 IN PRTMP_ADAPTER pAd,
1074 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
1079 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
1083 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
1084 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
1085 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
1086 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
1087 for (i=0;i<TX_RING_SIZE;i++)
1089 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
1090 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1092 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1095 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
1096 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
1097 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
1098 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
1099 for (i=0;i<TX_RING_SIZE;i++)
1101 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
1102 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1104 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1107 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
1108 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
1109 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
1110 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
1111 for (i=0;i<TX_RING_SIZE;i++)
1113 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
1114 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1116 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1119 RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
1120 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
1121 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
1122 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
1123 for (i=0;i<TX_RING_SIZE;i++)
1125 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
1126 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1128 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1131 RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
1132 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
1133 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
1134 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
1135 for (i=0;i<MGMT_RING_SIZE;i++)
1137 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
1138 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1140 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1144 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
1147 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
1149 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
1150 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
1151 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
1157 VOID DBGPRINT_RX_RING(
1158 IN PRTMP_ADAPTER pAd)
1161 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
1167 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
1168 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
1169 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
1170 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
1171 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
1173 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
1174 for (i=0;i<RX_RING_SIZE;i++)
1176 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
1177 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1179 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
1180 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
1181 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
1185 PNDIS_PACKET GetPacketFromRxRing(
1186 IN PRTMP_ADAPTER pAd,
1187 OUT PRT28XX_RXD_STRUC pSaveRxD,
1188 OUT BOOLEAN *pbReschedule,
1189 IN OUT UINT32 *pRxPending)
1192 #ifdef RT_BIG_ENDIAN
1193 PRXD_STRUC pDestRxD;
1196 PNDIS_PACKET pRxPacket = NULL;
1197 PNDIS_PACKET pNewPacket;
1199 NDIS_PHYSICAL_ADDRESS AllocPa;
1200 BOOLEAN bReschedule = FALSE;
1202 RTMP_SEM_LOCK(&pAd->RxRingLock);
1204 if (*pRxPending == 0)
1206 // Get how may packets had been received
1207 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
1209 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
1211 // no more rx packets
1212 bReschedule = FALSE;
1216 // get rx pending count
1217 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
1218 *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
1220 *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
1224 #ifdef RT_BIG_ENDIAN
1225 pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
1228 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
1230 // Point to Rx indexed rx ring descriptor
1231 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
1234 if (pRxD->DDONE == 0)
1237 // DMAIndx had done but DDONE bit not ready
1243 // return rx descriptor
1244 NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
1246 pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
1250 // unmap the rx buffer
1251 PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa,
1252 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
1253 pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket;
1255 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
1256 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket;
1257 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa;
1258 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa;
1259 /* update SDP0 to new buffer of rx packet */
1260 pRxD->SDP0 = AllocPa;
1264 //DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n"));
1271 // had handled one rx packet
1272 *pRxPending = *pRxPending - 1;
1274 // update rx descriptor and kick rx
1275 #ifdef RT_BIG_ENDIAN
1276 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
1277 WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD);
1279 INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
1281 pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
1282 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
1285 RTMP_SEM_UNLOCK(&pAd->RxRingLock);
1286 *pbReschedule = bReschedule;
1291 NDIS_STATUS MlmeHardTransmitTxRing(
1292 IN PRTMP_ADAPTER pAd,
1294 IN PNDIS_PACKET pPacket)
1296 PACKET_INFO PacketInfo;
1300 #ifdef RT_BIG_ENDIAN
1301 PTXD_STRUC pDestTxD;
1304 PHEADER_802_11 pHeader_802_11;
1305 BOOLEAN bAckRequired, bInsertTimestamp;
1309 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
1310 PTXWI_STRUC pFirstTxWI;
1312 //HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame.
1314 MAC_TABLE_ENTRY *pMacEntry = NULL;
1317 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
1320 if (pSrcBufVA == NULL)
1322 // The buffer shouldn't be NULL
1323 return NDIS_STATUS_FAILURE;
1326 // Make sure MGMT ring resource won't be used by other threads
1327 //NdisAcquireSpinLock(&pAd->TxRingLock);
1329 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
1333 //NdisReleaseSpinLock(&pAd->TxRingLock);
1334 return NDIS_STATUS_FAILURE;
1337 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
1339 #ifndef RT_BIG_ENDIAN
1340 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
1342 pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
1345 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1348 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
1350 DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n"));
1351 //NdisReleaseSpinLock(&pAd->TxRingLock);
1352 return NDIS_STATUS_FAILURE;
1356 #ifdef CONFIG_STA_SUPPORT
1357 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1359 // outgoing frame always wakeup PHY to prevent frame lost
1360 // if (pAd->StaCfg.Psm == PWR_SAVE)
1361 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1362 AsicForceWakeup(pAd, TRUE);
1364 #endif // CONFIG_STA_SUPPORT //
1365 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
1367 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
1368 if (pHeader_802_11->Addr1[0] & 0x01)
1370 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
1374 MlmeRate = pAd->CommonCfg.MlmeRate;
1377 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
1378 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
1380 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
1383 // Verify Mlme rate for a / g bands.
1384 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
1388 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
1389 // Snice it's been set to 0 while on MgtMacHeaderInit
1390 // By the way this will cause frame to be send on PWR_SAVE failed.
1393 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
1394 #ifdef CONFIG_STA_SUPPORT
1395 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
1396 if (pHeader_802_11->FC.Type != BTYPE_DATA)
1398 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
1400 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
1404 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
1407 #endif // CONFIG_STA_SUPPORT //
1409 bInsertTimestamp = FALSE;
1410 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
1412 bAckRequired = FALSE;
1414 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
1416 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
1418 bAckRequired = FALSE;
1419 pHeader_802_11->Duration = 0;
1423 bAckRequired = TRUE;
1424 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
1425 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
1427 bInsertTimestamp = TRUE;
1431 pHeader_802_11->Sequence = pAd->Sequence++;
1432 if (pAd->Sequence > 0xfff)
1434 // Before radar detection done, mgmt frame can not be sent but probe req
1435 // Because we need to use probe req to trigger driver to send probe req in passive scan
1436 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
1437 && (pAd->CommonCfg.bIEEE80211H == 1)
1438 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
1440 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
1441 //NdisReleaseSpinLock(&pAd->TxRingLock);
1442 return (NDIS_STATUS_FAILURE);
1445 #ifdef RT_BIG_ENDIAN
1446 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
1449 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
1450 // should always has only one ohysical buffer, and the whole frame size equals
1451 // to the first scatter buffer size
1454 // Initialize TX Descriptor
1455 // For inter-frame gap, the number is for this frame and next frame
1456 // For MLME rate, we will fix as 2Mb to match other vendor's implement
1457 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
1459 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
1460 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
1461 if (pMacEntry == NULL)
1463 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
1464 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
1468 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
1469 bInsertTimestamp, FALSE, bAckRequired, FALSE,
1470 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
1471 pMacEntry->MaxHTPhyMode.field.MCS, 0,
1472 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
1473 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
1476 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
1477 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
1478 // pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;
1479 #ifdef RT_BIG_ENDIAN
1480 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
1482 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
1485 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
1488 pTxD->SDLen0 = SrcBufLen;
1490 pTxD->SDPtr0 = SrcBufPA;
1493 #ifdef RT_BIG_ENDIAN
1494 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1495 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
1498 pAd->RalinkCounters.KickTxCount++;
1499 pAd->RalinkCounters.OneSecTxDoneCount++;
1501 // Increase TX_CTX_IDX, but write to register later.
1502 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1504 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
1506 // Make sure to release MGMT ring resource
1507 // NdisReleaseSpinLock(&pAd->TxRingLock);
1509 return NDIS_STATUS_SUCCESS;
1513 NDIS_STATUS MlmeDataHardTransmit(
1514 IN PRTMP_ADAPTER pAd,
1516 IN PNDIS_PACKET pPacket)
1518 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1521 return NDIS_STATUS_FAILURE;
1524 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
1529 ========================================================================
1531 Routine Description:
1532 Calculates the duration which is required to transmit out frames
1533 with given size and specified rate.
1536 pTxD Pointer to transmit descriptor
1537 Ack Setting for Ack requirement bit
1538 Fragment Setting for Fragment bit
1539 RetryMode Setting for retry mode
1540 Ifs Setting for IFS gap
1541 Rate Setting for transmit rate
1542 Service Setting for service
1544 TxPreamble Short or Long preamble when using CCK rates
1545 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1550 IRQL = PASSIVE_LEVEL
1551 IRQL = DISPATCH_LEVEL
1553 ========================================================================
1555 VOID RTMPWriteTxDescriptor(
1556 IN PRTMP_ADAPTER pAd,
1562 // Always use Long preamble before verifiation short preamble functionality works well.
1563 // Todo: remove the following line if short preamble functionality works
1565 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1567 pTxD->WIV = (bWIV) ? 1: 0;
1568 pTxD->QSEL= (QueueSEL);
1569 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1570 //pTxD->QSEL= FIFO_EDCA;
1572 if (pAd->bGenOneHCCA == TRUE)
1573 pTxD->QSEL= FIFO_HCCA;