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"
35 extern RTMP_RF_REGS RF2850RegTable[];
36 extern UCHAR NUM_OF_2850_CHNL;
38 USHORT RtmpPCI_WriteTxResource(
42 OUT USHORT *FreeNumber)
45 UCHAR *pDMAHeaderBufVA;
46 USHORT TxIdx, RetTxIdx;
49 PRTMP_TX_RING pTxRing;
53 // get Tx Ring Resource
55 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
56 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
57 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
58 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
60 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
61 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
63 hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
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 = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
132 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
134 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
135 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
138 // build Tx Descriptor
140 #ifndef RT_BIG_ENDIAN
141 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
143 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
147 NdisZeroMemory(pTxD, TXD_SIZE);
149 pTxD->SDPtr0 = BufBasePaLow;
150 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
151 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
152 pTxD->SDLen1 = pTxBlk->SrcBufLen;
154 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
156 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
158 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
159 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
160 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
161 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
162 #endif // RT_BIG_ENDIAN //
168 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
169 pTxRing->TxCpuIdx = TxIdx;
177 USHORT RtmpPCI_WriteMultiTxResource(
178 IN PRTMP_ADAPTER pAd,
181 OUT USHORT *FreeNumber)
184 UCHAR *pDMAHeaderBufVA;
185 USHORT TxIdx, RetTxIdx;
192 PRTMP_TX_RING pTxRing;
196 bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
199 // get Tx Ring Resource
201 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
202 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
203 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
204 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
208 // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
209 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
210 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
211 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
212 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
213 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
214 hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
216 //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
217 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
219 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
223 firstDMALen = pTxBlk->MpduHeaderLen;
226 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
228 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
229 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
232 // build Tx Descriptor
234 #ifndef RT_BIG_ENDIAN
235 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
237 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
241 NdisZeroMemory(pTxD, TXD_SIZE);
243 pTxD->SDPtr0 = BufBasePaLow;
244 pTxD->SDLen0 = firstDMALen; // include padding
245 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
246 pTxD->SDLen1 = pTxBlk->SrcBufLen;
248 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
250 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
254 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
257 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
259 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
260 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
261 #endif // RT_BIG_ENDIAN //
267 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
268 pTxRing->TxCpuIdx = TxIdx;
277 VOID RtmpPCI_FinalWriteTxResource(
278 IN PRTMP_ADAPTER pAd,
280 IN USHORT totalMPDUSize,
281 IN USHORT FirstTxIdx)
285 PRTMP_TX_RING pTxRing;
288 // get Tx Ring Resource
290 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
291 pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
292 pTxWI->MPDUtotalByteCount = totalMPDUSize;
294 RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
295 #endif // RT_BIG_ENDIAN //
300 VOID RtmpPCIDataLastTxIdx(
301 IN PRTMP_ADAPTER pAd,
310 PRTMP_TX_RING pTxRing;
313 // get Tx Ring Resource
315 pTxRing = &pAd->TxRing[QueIdx];
318 // build Tx Descriptor
320 #ifndef RT_BIG_ENDIAN
321 pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
323 pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
331 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
332 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
333 #endif // RT_BIG_ENDIAN //
338 USHORT RtmpPCI_WriteFragTxResource(
339 IN PRTMP_ADAPTER pAd,
342 OUT USHORT *FreeNumber)
344 UCHAR *pDMAHeaderBufVA;
345 USHORT TxIdx, RetTxIdx;
352 PRTMP_TX_RING pTxRing;
357 // Get Tx Ring Resource
359 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
360 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
361 pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
362 BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
365 // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
367 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
369 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
370 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
374 // Build Tx Descriptor
376 #ifndef RT_BIG_ENDIAN
377 pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
379 pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
383 NdisZeroMemory(pTxD, TXD_SIZE);
385 if (fragNum == pTxBlk->TotalFragNum)
387 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
388 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
391 pTxD->SDPtr0 = BufBasePaLow;
392 pTxD->SDLen0 = firstDMALen; // include padding
393 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
394 pTxD->SDLen1 = pTxBlk->SrcBufLen;
398 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
401 RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
402 RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
403 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
404 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
405 #endif // RT_BIG_ENDIAN //
408 pTxBlk->Priv += pTxBlk->SrcBufLen;
413 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
414 pTxRing->TxCpuIdx = TxIdx;
423 Must be run in Interrupt context
424 This function handle PCI specific TxDesc and cpu index update and kick the packet out.
426 int RtmpPCIMgmtKickOut(
427 IN RTMP_ADAPTER *pAd,
429 IN PNDIS_PACKET pPacket,
438 ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
441 pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa;
444 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
446 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
449 pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
450 pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
452 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
457 pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);;
458 pTxD->SDLen0 = SrcBufLen;
461 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
462 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
465 pAd->RalinkCounters.KickTxCount++;
466 pAd->RalinkCounters.OneSecTxDoneCount++;
468 // Increase TX_CTX_IDX, but write to register later.
469 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
471 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
477 #ifdef CONFIG_STA_SUPPORT
479 ========================================================================
482 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
485 pRxD Pointer to the Rx descriptor
488 NDIS_STATUS_SUCCESS No err
489 NDIS_STATUS_FAILURE Error
493 ========================================================================
495 NDIS_STATUS RTMPCheckRxError(
496 IN PRTMP_ADAPTER pAd,
497 IN PHEADER_802_11 pHeader,
498 IN PRXWI_STRUC pRxWI,
499 IN PRT28XX_RXD_STRUC pRxD)
504 // Phy errors & CRC errors
505 if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
507 // Check RSSI for Noise Hist statistic collection.
508 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
510 pAd->StaCfg.RPIDensity[0] += 1;
512 pAd->StaCfg.RPIDensity[1] += 1;
514 pAd->StaCfg.RPIDensity[2] += 1;
516 pAd->StaCfg.RPIDensity[3] += 1;
518 pAd->StaCfg.RPIDensity[4] += 1;
520 pAd->StaCfg.RPIDensity[5] += 1;
522 pAd->StaCfg.RPIDensity[6] += 1;
524 pAd->StaCfg.RPIDensity[7] += 1;
526 return(NDIS_STATUS_FAILURE);
529 // Add Rx size to channel load counter, we should ignore error counts
530 pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
532 // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
535 if (pHeader->FC.ToDs)
537 return(NDIS_STATUS_FAILURE);
541 // Drop not U2M frames, cant's drop here because we will drop beacon in this case
542 // I am kind of doubting the U2M bit operation
543 // if (pRxD->U2M == 0)
544 // return(NDIS_STATUS_FAILURE);
546 // drop decyption fail frame
549 if (pRxD->CipherErr == 2)
550 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
551 else if (pRxD->CipherErr == 1)
552 {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
553 else if (pRxD->CipherErr == 3)
554 DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
556 if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
557 RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
559 DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
562 pRxD->Mcast | pRxD->Bcast,
564 pRxWI->WirelessCliID,
570 if (pRxD->CipherErr == 2)
572 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
573 #ifdef WPA_SUPPLICANT_SUPPORT
574 if (pAd->StaCfg.WpaSupplicantUP)
575 WpaSendMicFailureToWpaSupplicant(pAd,
576 (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
578 #endif // WPA_SUPPLICANT_SUPPORT //
579 RTMPReportMicError(pAd, pWpaKey);
581 if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
582 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
584 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
588 return(NDIS_STATUS_SUCCESS);
590 return(NDIS_STATUS_FAILURE);
593 return(NDIS_STATUS_SUCCESS);
597 ==========================================================================
599 This routine sends command to firmware and turn our chip to power save mode.
600 Both RadioOff and .11 power save function needs to call this routine.
602 Level = GUIRADIO_OFF : GUI Radio Off mode
603 Level = DOT11POWERSAVE : 802.11 power save mode
604 Level = RTMP_HALT : When Disable device.
606 ==========================================================================
608 VOID RT28xxPciAsicRadioOff(
609 IN PRTMP_ADAPTER pAd,
611 IN USHORT TbttNumToNextWakeUp)
613 WPDMA_GLO_CFG_STRUC DmaCfg;
614 UCHAR i, tempBBP_R3 = 0;
615 BOOLEAN brc = FALSE, Cancelled;
617 UINT32 PsPollTime = 0, MACValue;
618 ULONG BeaconPeriodTime;
619 UINT32 RxDmaIdx, RxCpuIdx;
620 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
622 // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
623 RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
624 RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
625 if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
627 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
630 else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
632 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx));
636 // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
637 pAd->bPCIclkOffDisableTx = TRUE;
639 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
641 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
642 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
644 if (Level == DOT11POWERSAVE)
646 RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
648 // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
649 // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
650 if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
652 DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
653 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
654 pAd->bPCIclkOffDisableTx = FALSE;
659 PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
662 BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
663 if (TbttNumToNextWakeUp > 0)
664 PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
666 pAd->Mlme.bPsPollTimerRunning = TRUE;
667 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
672 // 0. Disable Tx DMA.
673 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
674 DmaCfg.field.EnableTxDMA = 0;
675 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
677 // 1. Wait DMA not busy
681 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
682 if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0))
690 DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n"));
691 pAd->bPCIclkOffDisableTx = FALSE;
692 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
693 DmaCfg.field.EnableTxDMA = 1;
694 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
698 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
701 tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
702 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
704 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
705 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
706 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
709 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
714 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
717 // When PCI clock is off, don't want to service interrupt.
718 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
720 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
722 RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
724 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
726 // 2. Send Sleep command
727 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
728 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
729 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us.
730 // 2-1. Wait command success
731 // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
732 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
737 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us.
738 //RTMPusecDelay(200);
739 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
742 // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
743 // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
744 if ((Level == DOT11POWERSAVE) && (brc == TRUE))
746 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
747 // 3-1. Wait command success
748 AsicCheckCommanOk(pAd, PowerRadioOffCID);
750 else if (brc == TRUE)
752 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
753 // 3-1. Wait command success
754 AsicCheckCommanOk(pAd, PowerRadioOffCID);
761 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
762 if (DmaCfg.field.RxDMABusy == 0)
770 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n"));
774 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
775 DmaCfg.field.EnableRxDMA = 0;
776 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
779 if (Level == DOT11POWERSAVE)
781 AUTO_WAKEUP_STRUC AutoWakeupCfg;
782 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
784 // we have decided to SLEEP, so at least do it for a BEACON period.
785 if (TbttNumToNextWakeUp == 0)
786 TbttNumToNextWakeUp = 1;
788 AutoWakeupCfg.word = 0;
789 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
791 // 1. Set auto wake up timer.
792 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
793 AutoWakeupCfg.field.EnableAutoWakeup = 1;
794 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
795 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
798 // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
799 if (Level == RTMP_HALT)
801 if ((brc == TRUE) && (i < 50))
802 RTMPPCIeLinkCtrlSetting(pAd, 1);
804 // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function
807 if ((brc == TRUE) && (i < 50))
808 RTMPPCIeLinkCtrlSetting(pAd, 3);
811 pAd->bPCIclkOffDisableTx = FALSE;
816 ==========================================================================
818 This routine sends command to firmware and turn our chip to wake up mode from power save mode.
819 Both RadioOn and .11 power save function needs to call this routine.
821 Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value.
822 Level = other value : normal wake up function.
824 ==========================================================================
826 BOOLEAN RT28xxPciAsicRadioOn(
827 IN PRTMP_ADAPTER pAd,
830 WPDMA_GLO_CFG_STRUC DmaCfg;
831 BOOLEAN Cancelled, brv = TRUE;
834 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
836 pAd->Mlme.bPsPollTimerRunning = FALSE;
837 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
838 if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE))
840 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
841 // 1. Set PCI Link Control in Configuration Space.
842 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
847 pAd->bPCIclkOff = FALSE;
849 // 2. Send wake up command.
850 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00);
852 // 2-1. wait command ok.
853 brv = AsicCheckCommanOk(pAd, PowerWakeCID);
856 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT));
857 NICEnableInterrupt(pAd);
860 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
861 DmaCfg.field.EnableTxDMA = 1;
862 DmaCfg.field.EnableRxDMA = 1;
863 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
866 RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
868 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
870 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
871 if (Level == GUI_IDLE_POWER_SAVE)
873 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
874 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
875 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
878 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
879 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
884 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
885 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
894 VOID RT28xxPciStaAsicForceWakeup(
895 IN PRTMP_ADAPTER pAd,
898 AUTO_WAKEUP_STRUC AutoWakeupCfg;
900 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
903 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
905 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
909 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
911 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
913 // Support PCIe Advance Power Save
916 pAd->Mlme.bPsPollTimerRunning = FALSE;
917 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
919 DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
922 AutoWakeupCfg.word = 0;
923 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
925 if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
927 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
928 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
929 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
932 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
933 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
938 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
939 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
946 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
947 AutoWakeupCfg.word = 0;
948 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
951 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
952 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
953 DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
956 VOID RT28xxPciStaAsicSleepThenAutoWakeup(
957 IN PRTMP_ADAPTER pAd,
958 IN USHORT TbttNumToNextWakeUp)
960 if (pAd->StaCfg.bRadio == FALSE)
962 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
965 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
968 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
970 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
971 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
975 NdisGetSystemUpTime(&Now);
976 // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
977 // Because Some AP can't queuing outgoing frames immediately.
978 if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
980 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
983 else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
985 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
989 RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
993 AUTO_WAKEUP_STRUC AutoWakeupCfg;
994 // we have decided to SLEEP, so at least do it for a BEACON period.
995 if (TbttNumToNextWakeUp == 0)
996 TbttNumToNextWakeUp = 1;
998 AutoWakeupCfg.word = 0;
999 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1000 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1001 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1002 AutoWakeupCfg.field.AutoLeadTime = 5;
1003 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1004 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us.
1005 DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __FUNCTION__, TbttNumToNextWakeUp));
1007 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
1010 VOID PsPollWakeExec(
1011 IN PVOID SystemSpecific1,
1012 IN PVOID FunctionContext,
1013 IN PVOID SystemSpecific2,
1014 IN PVOID SystemSpecific3)
1016 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1017 unsigned long flags;
1019 DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
1020 RTMP_INT_LOCK(&pAd->irq_lock, flags);
1021 if (pAd->Mlme.bPsPollTimerRunning)
1023 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1025 pAd->Mlme.bPsPollTimerRunning = FALSE;
1026 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
1030 IN PVOID SystemSpecific1,
1031 IN PVOID FunctionContext,
1032 IN PVOID SystemSpecific2,
1033 IN PVOID SystemSpecific3)
1035 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1036 WPDMA_GLO_CFG_STRUC DmaCfg;
1039 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1041 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
1042 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1046 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1048 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
1049 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1052 pAd->Mlme.bPsPollTimerRunning = FALSE;
1053 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1054 if (pAd->StaCfg.bRadio == TRUE)
1056 pAd->bPCIclkOff = FALSE;
1057 RTMPRingCleanUp(pAd, QID_AC_BK);
1058 RTMPRingCleanUp(pAd, QID_AC_BE);
1059 RTMPRingCleanUp(pAd, QID_AC_VI);
1060 RTMPRingCleanUp(pAd, QID_AC_VO);
1061 RTMPRingCleanUp(pAd, QID_HCCA);
1062 RTMPRingCleanUp(pAd, QID_MGMT);
1063 RTMPRingCleanUp(pAd, QID_RX);
1065 // 2. Send wake up command.
1066 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1067 // 2-1. wait command ok.
1068 AsicCheckCommanOk(pAd, PowerWakeCID);
1070 // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
1071 NICEnableInterrupt(pAd);
1073 // 3. Enable Tx DMA.
1074 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1075 DmaCfg.field.EnableTxDMA = 1;
1076 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
1078 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1079 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1080 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1082 // Must using 40MHz.
1083 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1084 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1088 // Must using 20MHz.
1089 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1090 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1093 // Clear Radio off flag
1094 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1097 RTMPSetLED(pAd, LED_RADIO_ON);
1099 if (pAd->StaCfg.Psm == PWR_ACTIVE)
1101 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1106 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1110 #endif // CONFIG_STA_SUPPORT //
1112 VOID RT28xxPciMlmeRadioOn(
1113 IN PRTMP_ADAPTER pAd)
1115 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1118 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1120 if ((pAd->OpMode == OPMODE_AP) ||
1121 ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))))
1123 NICResetFromError(pAd);
1125 RTMPRingCleanUp(pAd, QID_AC_BK);
1126 RTMPRingCleanUp(pAd, QID_AC_BE);
1127 RTMPRingCleanUp(pAd, QID_AC_VI);
1128 RTMPRingCleanUp(pAd, QID_AC_VO);
1129 RTMPRingCleanUp(pAd, QID_HCCA);
1130 RTMPRingCleanUp(pAd, QID_MGMT);
1131 RTMPRingCleanUp(pAd, QID_RX);
1134 RTMPEnableRxTx(pAd);
1136 // Clear Radio off flag
1137 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1140 RTMPSetLED(pAd, LED_RADIO_ON);
1143 #ifdef CONFIG_STA_SUPPORT
1144 if ((pAd->OpMode == OPMODE_STA) &&
1145 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))
1149 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1151 pAd->Mlme.bPsPollTimerRunning = FALSE;
1152 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1153 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1154 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1156 #endif // CONFIG_STA_SUPPORT //
1159 VOID RT28xxPciMlmeRadioOFF(
1160 IN PRTMP_ADAPTER pAd)
1162 WPDMA_GLO_CFG_STRUC GloCfg;
1165 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1168 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1171 RTMPSetLED(pAd, LED_RADIO_OFF);
1172 // Set Radio off flag
1173 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1175 #ifdef CONFIG_STA_SUPPORT
1176 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1179 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1181 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1182 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1185 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1188 pAd->Mlme.bPsPollTimerRunning = FALSE;
1189 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1190 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1193 // Link down first if any association exists
1194 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1195 LinkDown(pAd, FALSE);
1196 RTMPusecDelay(10000);
1197 //==========================================
1198 // Clean up old bss table
1199 BssTableInit(&pAd->ScanTab);
1201 #endif // CONFIG_STA_SUPPORT //
1203 // Disable Tx/Rx DMA
1204 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
1205 GloCfg.field.EnableTxDMA = 0;
1206 GloCfg.field.EnableRxDMA = 0;
1207 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
1210 // MAC_SYS_CTRL => value = 0x0 => 40mA
1211 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
1213 // PWR_PIN_CFG => value = 0x0 => 40mA
1214 RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
1216 // TX_PIN_CFG => value = 0x0 => 20mA
1217 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
1219 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1221 // Must using 40MHz.
1222 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1226 // Must using 20MHz.
1227 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1230 // Waiting for DMA idle
1234 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1235 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1238 RTMPusecDelay(1000);