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 *************************************************************************
30 #include "../rt_config.h"
34 ========================================================================
37 Allocate DMA memory blocks for send, receive
40 Adapter Pointer to our adapter
51 ========================================================================
53 NDIS_STATUS RTMPAllocTxRxRingMemory(
56 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
64 PRTMP_TX_RING pTxRing;
67 // PRTMP_REORDERBUF pReorderBuf;
69 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
73 // Allocate all ring descriptors, include TxD, RxD, MgmtD.
74 // Although each size is different, to prevent cacheline and alignment
75 // issue, I intentional set them all to 64 bytes.
77 for (num=0; num<NUM_OF_TX_RING; num++)
84 // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
86 pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
87 RTMP_AllocateTxDescMemory(
90 pAd->TxDescRing[num].AllocSize,
92 &pAd->TxDescRing[num].AllocVa,
93 &pAd->TxDescRing[num].AllocPa);
95 if (pAd->TxDescRing[num].AllocVa == NULL)
97 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
98 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
99 Status = NDIS_STATUS_RESOURCES;
103 // Zero init this memory block
104 NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
106 // Save PA & VA for further operation
107 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa);
108 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa);
109 RingBaseVa = pAd->TxDescRing[num].AllocVa;
112 // Allocate all 1st TXBuf's memory for this TxRing
114 pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
115 RTMP_AllocateFirstTxBuffer(
118 pAd->TxBufSpace[num].AllocSize,
120 &pAd->TxBufSpace[num].AllocVa,
121 &pAd->TxBufSpace[num].AllocPa);
123 if (pAd->TxBufSpace[num].AllocVa == NULL)
125 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
126 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
127 Status = NDIS_STATUS_RESOURCES;
131 // Zero init this memory block
132 NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
134 // Save PA & VA for further operation
135 BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa);
136 BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa);
137 BufBaseVa = pAd->TxBufSpace[num].AllocVa;
140 // Initialize Tx Ring Descriptor and associated buffer memory
142 pTxRing = &pAd->TxRing[num];
143 for (index = 0; index < TX_RING_SIZE; index++)
145 pTxRing->Cell[index].pNdisPacket = NULL;
146 pTxRing->Cell[index].pNextNdisPacket = NULL;
147 // Init Tx Ring Size, Va, Pa variables
148 pTxRing->Cell[index].AllocSize = TXD_SIZE;
149 pTxRing->Cell[index].AllocVa = RingBaseVa;
150 RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh);
151 RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow);
153 // Setup Tx Buffer size & address. only 802.11 header will store in this space
154 pDmaBuf = &pTxRing->Cell[index].DmaBuf;
155 pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE;
156 pDmaBuf->AllocVa = BufBaseVa;
157 RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh);
158 RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow);
160 // link the pre-allocated TxBuf to TXD
161 pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa;
162 pTxD->SDPtr0 = BufBasePaLow;
163 // advance to next ring descriptor address
166 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
168 RingBasePaLow += TXD_SIZE;
169 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
171 // advance to next TxBuf address
172 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
173 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
175 DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
177 if (Status == NDIS_STATUS_RESOURCES)
181 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
183 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
184 RTMP_AllocateMgmtDescMemory(
186 pAd->MgmtDescRing.AllocSize,
188 &pAd->MgmtDescRing.AllocVa,
189 &pAd->MgmtDescRing.AllocPa);
191 if (pAd->MgmtDescRing.AllocVa == NULL)
193 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
194 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
195 Status = NDIS_STATUS_RESOURCES;
199 // Zero init this memory block
200 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
202 // Save PA & VA for further operation
203 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
204 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
205 RingBaseVa = pAd->MgmtDescRing.AllocVa;
208 // Initialize MGMT Ring and associated buffer memory
210 for (index = 0; index < MGMT_RING_SIZE; index++)
212 pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
213 pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
214 // Init MGMT Ring Size, Va, Pa variables
215 pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
216 pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
217 RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
218 RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
220 // Offset to next ring descriptor address
221 RingBasePaLow += TXD_SIZE;
222 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
224 // link the pre-allocated TxBuf to TXD
225 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
229 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
231 // no pre-allocated buffer required in MgmtRing for scatter-gather case
233 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
236 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
238 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
239 RTMP_AllocateRxDescMemory(
241 pAd->RxDescRing.AllocSize,
243 &pAd->RxDescRing.AllocVa,
244 &pAd->RxDescRing.AllocPa);
246 if (pAd->RxDescRing.AllocVa == NULL)
248 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
249 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
250 Status = NDIS_STATUS_RESOURCES;
254 // Zero init this memory block
255 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
258 DBGPRINT(RT_DEBUG_OFF,
259 ("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize));
261 // Save PA & VA for further operation
262 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
263 RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
264 RingBaseVa = pAd->RxDescRing.AllocVa;
267 // Initialize Rx Ring and associated buffer memory
269 for (index = 0; index < RX_RING_SIZE; index++)
271 // Init RX Ring Size, Va, Pa variables
272 pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
273 pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
274 RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
275 RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
277 //NdisZeroMemory(RingBaseVa, RXD_SIZE);
279 // Offset to next ring descriptor address
280 RingBasePaLow += RXD_SIZE;
281 RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
283 // Setup Rx associated Buffer size & allocate share memory
284 pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
285 pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
286 pPacket = RTMP_AllocateRxPacketBuffer(
293 /* keep allocated rx packet */
294 pAd->RxRing.Cell[index].pNdisPacket = pPacket;
297 if (pDmaBuf->AllocVa == NULL)
299 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
300 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
301 Status = NDIS_STATUS_RESOURCES;
305 // Zero init this memory block
306 NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
308 // Write RxD buffer address & allocated buffer length
309 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
310 pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
314 RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
318 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
323 NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
324 pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
326 if (pAd->FragFrame.pFragPacket == NULL)
328 Status = NDIS_STATUS_RESOURCES;
331 if (Status != NDIS_STATUS_SUCCESS)
333 // Log error inforamtion
334 NdisWriteErrorLogEntry(
336 NDIS_ERROR_CODE_OUT_OF_RESOURCES,
341 // Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here.
343 DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n"));
347 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
348 GloCfg.word &= 0xff0;
349 GloCfg.field.EnTXWriteBackDDONE =1;
350 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
353 // Initialize all transmit related software queues
354 for(index = 0; index < NUM_OF_TX_RING; index++)
356 InitializeQueueHeader(&pAd->TxSwQueue[index]);
357 // Init TX rings index pointer
358 pAd->TxRing[index].TxSwFreeIdx = 0;
359 pAd->TxRing[index].TxCpuIdx = 0;
360 //RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TX_CTX_IDX);
363 // Init RX Ring index pointer
364 pAd->RxRing.RxSwReadIdx = 0;
365 pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
366 //RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RX_CRX_IDX0);
369 // init MGMT ring index pointer
370 pAd->MgmtRing.TxSwFreeIdx = 0;
371 pAd->MgmtRing.TxCpuIdx = 0;
373 pAd->PrivateInfo.TxRingFullCnt = 0;
375 DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n"));
378 DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
386 ========================================================================
389 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
392 Adapter Pointer to our adapter
398 IRQL = DISPATCH_LEVEL
401 Reset NIC to initial state AS IS system boot up time.
403 ========================================================================
405 VOID RTMPRingCleanUp(
406 IN PRTMP_ADAPTER pAd,
412 PNDIS_PACKET pPacket;
414 PRTMP_TX_RING pTxRing;
415 unsigned long IrqFlags;
416 //UINT32 RxSwReadIdx;
419 DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
428 pTxRing = &pAd->TxRing[RingType];
430 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
431 // We have to clean all descriptors in case some error happened with reset
432 for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
434 pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
436 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
437 // release scatter-and-gather NDIS_PACKET
440 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
441 pTxRing->Cell[i].pNdisPacket = NULL;
444 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
445 // release scatter-and-gather NDIS_PACKET
448 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
449 pTxRing->Cell[i].pNextNdisPacket = NULL;
453 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
454 pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
455 pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
456 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
458 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
460 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
461 while (pAd->TxSwQueue[RingType].Head != NULL)
463 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
464 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
465 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
466 DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
468 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
472 // We have to clean all descriptors in case some error happened with reset
473 NdisAcquireSpinLock(&pAd->MgmtRingLock);
475 for (i=0; i<MGMT_RING_SIZE; i++)
477 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
479 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
480 // rlease scatter-and-gather NDIS_PACKET
483 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
484 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
486 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
488 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
489 // release scatter-and-gather NDIS_PACKET
492 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
493 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
495 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
499 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
500 pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
501 pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
502 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
504 NdisReleaseSpinLock(&pAd->MgmtRingLock);
505 pAd->RalinkCounters.MgmtRingFullCount = 0;
509 // We have to clean all descriptors in case some error happened with reset
510 NdisAcquireSpinLock(&pAd->RxRingLock);
512 for (i=0; i<RX_RING_SIZE; i++)
514 pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
518 RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
519 pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
520 pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
521 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
523 NdisReleaseSpinLock(&pAd->RxRingLock);
532 VOID RTMPFreeTxRxRingMemory(
533 IN PRTMP_ADAPTER pAd)
536 PRTMP_TX_RING pTxRing;
538 PNDIS_PACKET pPacket;
539 unsigned int IrqFlags;
541 //POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
543 DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
545 // Free TxSwQueue Packet
546 for (index=0; index <NUM_OF_TX_RING; index++)
549 PNDIS_PACKET pPacket;
550 PQUEUE_HEADER pQueue;
552 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
553 pQueue = &pAd->TxSwQueue[index];
556 pEntry = RemoveHeadQueue(pQueue);
557 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
558 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
560 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
563 // Free Tx Ring Packet
564 for (index=0;index< NUM_OF_TX_RING;index++)
566 pTxRing = &pAd->TxRing[index];
568 for (j=0; j< TX_RING_SIZE; j++)
570 pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
571 pPacket = pTxRing->Cell[j].pNdisPacket;
575 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
576 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
578 //Always assign pNdisPacket as NULL after clear
579 pTxRing->Cell[j].pNdisPacket = NULL;
581 pPacket = pTxRing->Cell[j].pNextNdisPacket;
585 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
586 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
588 //Always assign pNextNdisPacket as NULL after clear
589 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
594 for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
596 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
598 PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
599 RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
602 NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
604 if (pAd->RxDescRing.AllocVa)
606 RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
608 NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
610 if (pAd->MgmtDescRing.AllocVa)
612 RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
614 NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
616 for (num = 0; num < NUM_OF_TX_RING; num++)
618 if (pAd->TxBufSpace[num].AllocVa)
620 RTMP_FreeFirstTxBuffer(pAd, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
622 NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
624 if (pAd->TxDescRing[num].AllocVa)
626 RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
628 NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
631 if (pAd->FragFrame.pFragPacket)
632 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
634 DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
638 /***************************************************************************
640 * register related procedures.
642 **************************************************************************/
644 ========================================================================
649 *pAd the raxx interface data pointer
655 ========================================================================
657 VOID RT28XXDMADisable(
658 IN RTMP_ADAPTER *pAd)
660 WPDMA_GLO_CFG_STRUC GloCfg;
663 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
664 GloCfg.word &= 0xff0;
665 GloCfg.field.EnTXWriteBackDDONE =1;
666 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
671 ========================================================================
676 *pAd the raxx interface data pointer
682 ========================================================================
684 VOID RT28XXDMAEnable(
685 IN RTMP_ADAPTER *pAd)
687 WPDMA_GLO_CFG_STRUC GloCfg;
690 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
693 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
694 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
697 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
704 GloCfg.field.EnTXWriteBackDDONE = 1;
705 GloCfg.field.WPDMABurstSIZE = 2;
706 GloCfg.field.EnableRxDMA = 1;
707 GloCfg.field.EnableTxDMA = 1;
709 DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
710 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
715 BOOLEAN AsicCheckCommanOk(
716 IN PRTMP_ADAPTER pAd,
719 UINT32 CmdStatus = 0, CID = 0, i;
720 UINT32 ThisCIDMask = 0;
725 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
726 // Find where the command is. Because this is randomly specified by firmware.
727 if ((CID & CID0MASK) == Command)
729 ThisCIDMask = CID0MASK;
732 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
734 ThisCIDMask = CID1MASK;
737 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
739 ThisCIDMask = CID2MASK;
742 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
744 ThisCIDMask = CID3MASK;
752 // Get CommandStatus Value
753 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
755 // This command's status is at the same position as command. So AND command position's bitmask to read status.
758 // If Status is 1, the comamnd is success.
759 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
760 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
762 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
763 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
764 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
767 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
771 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
773 // Clear Command and Status.
774 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
775 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
782 ========================================================================
784 Write Beacon buffer to Asic.
787 *pAd the raxx interface data pointer
793 ========================================================================
795 VOID RT28xx_UpdateBeaconToAsic(
796 IN RTMP_ADAPTER *pAd,
801 ULONG CapInfoPos = 0;
802 UCHAR *ptr, *ptr_update, *ptr_capinfo;
804 BOOLEAN bBcnReq = FALSE;
809 DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __FUNCTION__));
813 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE)
814 // || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL)
815 // || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
817 if (bBcnReq == FALSE)
819 /* when the ra interface is down, do not send its beacon frame */
821 for(i=0; i<TXWI_SIZE; i+=4)
822 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
826 ptr = (PUCHAR)&pAd->BeaconTxWI;
828 RTMPWIEndianChange(ptr, TYPE_TXWI);
830 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
832 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
833 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr);
837 // Update CapabilityInfo in Beacon
838 for (i = CapInfoPos; i < (CapInfoPos+2); i++)
840 RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo);
844 if (FrameLen > UpdatePos)
846 for (i= UpdatePos; i< (FrameLen); i++)
848 RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update);
858 #ifdef CONFIG_STA_SUPPORT
859 VOID RT28xxPciStaAsicForceWakeup(
860 IN PRTMP_ADAPTER pAd,
863 AUTO_WAKEUP_STRUC AutoWakeupCfg;
865 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
868 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
870 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
874 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
876 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
878 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
879 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
881 // Support PCIe Advance Power Save
883 &&(pAd->Mlme.bPsPollTimerRunning == TRUE))
885 pAd->Mlme.bPsPollTimerRunning = FALSE;
886 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
888 DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
891 AutoWakeupCfg.word = 0;
892 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
894 if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
896 #ifdef PCIE_PS_SUPPORT
897 // add by johnli, RF power sequence setup, load RF normal operation-mode setup
898 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd))
900 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
902 if (pChipOps->AsicReverseRfFromSleepMode)
903 pChipOps->AsicReverseRfFromSleepMode(pAd);
906 #endif // PCIE_PS_SUPPORT //
909 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
910 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
911 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
914 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
915 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
920 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
921 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
925 #ifdef PCIE_PS_SUPPORT
926 // 3090 MCU Wakeup command needs more time to be stable.
927 // Before stable, don't issue other MCU command to prevent from firmware error.
928 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
929 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
930 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
932 DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Release the MCU Lock(3090)\n"));
933 RTMP_SEM_LOCK(&pAd->McuCmdLock);
934 pAd->brt30xxBanMcuCmd = FALSE;
935 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
937 #endif // PCIE_PS_SUPPORT //
942 DBGPRINT(RT_DEBUG_TRACE, ("<==RT28xxPciStaAsicForceWakeup::Original PCI Power Saving\n"));
943 AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02);
944 AutoWakeupCfg.word = 0;
945 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
948 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
949 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
950 DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
954 VOID RT28xxPciStaAsicSleepThenAutoWakeup(
955 IN PRTMP_ADAPTER pAd,
956 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_PCIE_DEVICE)
966 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
969 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
971 DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
972 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
976 NdisGetSystemUpTime(&Now);
977 // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
978 // Because Some AP can't queuing outgoing frames immediately.
979 if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
981 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
984 else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
986 DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
990 brc = RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
992 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
996 AUTO_WAKEUP_STRUC AutoWakeupCfg;
997 // we have decided to SLEEP, so at least do it for a BEACON period.
998 if (TbttNumToNextWakeUp == 0)
999 TbttNumToNextWakeUp = 1;
1001 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
1003 AutoWakeupCfg.word = 0;
1004 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1005 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1006 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1007 AutoWakeupCfg.field.AutoLeadTime = 5;
1008 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1009 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us.
1010 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
1011 DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __FUNCTION__, TbttNumToNextWakeUp));
1017 VOID PsPollWakeExec(
1018 IN PVOID SystemSpecific1,
1019 IN PVOID FunctionContext,
1020 IN PVOID SystemSpecific2,
1021 IN PVOID SystemSpecific3)
1023 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1024 unsigned long flags;
1026 DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
1028 RTMP_INT_LOCK(&pAd->irq_lock, flags);
1029 if (pAd->Mlme.bPsPollTimerRunning)
1031 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1033 pAd->Mlme.bPsPollTimerRunning = FALSE;
1034 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
1035 #ifdef PCIE_PS_SUPPORT
1036 // For rt30xx power solution 3, Use software timer to wake up in psm. So call
1037 // AsicForceWakeup here instead of handling twakeup interrupt.
1038 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd))
1039 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1040 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1042 DBGPRINT(RT_DEBUG_TRACE,("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n"));
1043 AsicForceWakeup(pAd, DOT11POWERSAVE);
1046 #endif // PCIE_PS_SUPPORT //
1050 IN PVOID SystemSpecific1,
1051 IN PVOID FunctionContext,
1052 IN PVOID SystemSpecific2,
1053 IN PVOID SystemSpecific3)
1055 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1056 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1057 WPDMA_GLO_CFG_STRUC DmaCfg;
1060 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1062 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
1063 //KH Debug: Add the compile flag "RT2860 and condition
1064 #ifdef RTMP_PCI_SUPPORT
1065 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1066 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1067 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1068 #endif // RTMP_PCI_SUPPORT //
1072 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1074 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
1077 #ifdef RTMP_PCI_SUPPORT
1078 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1079 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1080 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1081 #endif // RTMP_PCI_SUPPORT //
1084 //KH Debug: need to check. I add the compile flag "CONFIG_STA_SUPPORT" to enclose the following codes.
1085 #ifdef RTMP_PCI_SUPPORT
1086 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1087 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1089 pAd->Mlme.bPsPollTimerRunning = FALSE;
1090 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1092 #endif // RTMP_PCI_SUPPORT //
1093 if (pAd->StaCfg.bRadio == TRUE)
1095 pAd->bPCIclkOff = FALSE;
1096 RTMPRingCleanUp(pAd, QID_AC_BK);
1097 RTMPRingCleanUp(pAd, QID_AC_BE);
1098 RTMPRingCleanUp(pAd, QID_AC_VI);
1099 RTMPRingCleanUp(pAd, QID_AC_VO);
1100 /*RTMPRingCleanUp(pAd, QID_HCCA);*/
1101 RTMPRingCleanUp(pAd, QID_MGMT);
1102 RTMPRingCleanUp(pAd, QID_RX);
1104 // 2. Send wake up command.
1105 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1106 // 2-1. wait command ok.
1107 AsicCheckCommanOk(pAd, PowerWakeCID);
1109 // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
1110 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT));
1111 RTMP_ASIC_INTERRUPT_ENABLE(pAd);
1113 // 3. Enable Tx DMA.
1114 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1115 DmaCfg.field.EnableTxDMA = 1;
1116 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
1118 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1119 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1120 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1122 // Must using 40MHz.
1123 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1124 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1128 // Must using 20MHz.
1129 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1130 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1132 //KH Debug:The following codes should be enclosed by RT3090 compile flag
1133 if (pChipOps->AsicReverseRfFromSleepMode)
1134 pChipOps->AsicReverseRfFromSleepMode(pAd);
1135 #ifdef PCIE_PS_SUPPORT
1136 #ifdef CONFIG_STA_SUPPORT
1137 // 3090 MCU Wakeup command needs more time to be stable.
1138 // Before stable, don't issue other MCU command to prevent from firmware error.
1139 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1140 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1141 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1143 RTMP_SEM_LOCK(&pAd->McuCmdLock);
1144 pAd->brt30xxBanMcuCmd = FALSE;
1145 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1147 #endif // CONFIG_STA_SUPPORT //
1148 #endif // PCIE_PS_SUPPORT //
1149 // Clear Radio off flag
1150 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1153 RTMPSetLED(pAd, LED_RADIO_ON);
1155 if (pAd->StaCfg.Psm == PWR_ACTIVE)
1157 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1162 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1165 #endif // CONFIG_STA_SUPPORT //
1169 ==========================================================================
1171 This routine sends command to firmware and turn our chip to wake up mode from power save mode.
1172 Both RadioOn and .11 power save function needs to call this routine.
1174 Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value.
1175 Level = other value : normal wake up function.
1177 ==========================================================================
1179 BOOLEAN RT28xxPciAsicRadioOn(
1180 IN PRTMP_ADAPTER pAd,
1183 //WPDMA_GLO_CFG_STRUC DmaCfg;
1184 #ifdef CONFIG_STA_SUPPORT
1186 #endif // CONFIG_STA_SUPPORT //
1189 if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1192 #ifdef CONFIG_STA_SUPPORT
1193 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1195 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1197 pAd->Mlme.bPsPollTimerRunning = FALSE;
1198 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1200 if ((pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)&&
1201 ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE))
1202 ||(RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)))
1204 // Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore
1205 // return condition here.
1207 if (((pAd->MACVersion&0xffff0000) != 0x28600000)
1208 && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID)
1209 ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID)))
1212 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
1213 // 1. Set PCI Link Control in Configuration Space.
1214 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1215 RTMPusecDelay(6000);
1220 #ifdef PCIE_PS_SUPPORT
1221 if (!(((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1222 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1223 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))))
1224 #endif // PCIE_PS_SUPPORT //
1226 pAd->bPCIclkOff = FALSE;
1227 DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff));
1230 #endif // CONFIG_STA_SUPPORT //
1231 // 2. Send wake up command.
1232 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1233 pAd->bPCIclkOff = FALSE;
1234 // 2-1. wait command ok.
1235 AsicCheckCommanOk(pAd, PowerWakeCID);
1236 RTMP_ASIC_INTERRUPT_ENABLE(pAd);
1239 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1240 if (Level == GUI_IDLE_POWER_SAVE)
1242 #ifdef PCIE_PS_SUPPORT
1244 // add by johnli, RF power sequence setup, load RF normal operation-mode setup
1245 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
1247 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1249 if (pChipOps->AsicReverseRfFromSleepMode)
1250 pChipOps->AsicReverseRfFromSleepMode(pAd);
1251 #ifdef CONFIG_STA_SUPPORT
1252 // 3090 MCU Wakeup command needs more time to be stable.
1253 // Before stable, don't issue other MCU command to prevent from firmware error.
1254 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1255 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1256 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1258 RTMP_SEM_LOCK(&pAd->McuCmdLock);
1259 pAd->brt30xxBanMcuCmd = FALSE;
1260 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1262 #endif // CONFIG_STA_SUPPORT //
1266 #endif // PCIE_PS_SUPPORT //
1268 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1269 #ifdef CONFIG_STA_SUPPORT
1270 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1272 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1273 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1275 // Must using 40MHz.
1276 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1277 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1281 // Must using 20MHz.
1282 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1283 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1286 #endif // CONFIG_STA_SUPPORT //
1295 ==========================================================================
1297 This routine sends command to firmware and turn our chip to power save mode.
1298 Both RadioOff and .11 power save function needs to call this routine.
1300 Level = GUIRADIO_OFF : GUI Radio Off mode
1301 Level = DOT11POWERSAVE : 802.11 power save mode
1302 Level = RTMP_HALT : When Disable device.
1304 ==========================================================================
1306 BOOLEAN RT28xxPciAsicRadioOff(
1307 IN PRTMP_ADAPTER pAd,
1309 IN USHORT TbttNumToNextWakeUp)
1311 #ifdef CONFIG_STA_SUPPORT
1312 WPDMA_GLO_CFG_STRUC DmaCfg;
1313 UCHAR i, tempBBP_R3 = 0;
1314 #endif // CONFIG_STA_SUPPORT //
1315 BOOLEAN brc = FALSE, Cancelled;
1316 UINT32 TbTTTime = 0;
1317 UINT32 PsPollTime = 0/*, MACValue*/;
1318 ULONG BeaconPeriodTime;
1319 UINT32 RxDmaIdx, RxCpuIdx;
1320 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", Level,pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
1322 if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1325 // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
1326 RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
1327 RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
1328 if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
1330 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
1333 else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
1335 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx));
1339 // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
1340 //pAd->bPCIclkOffDisableTx = TRUE;
1341 RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1342 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1343 && pAd->OpMode == OPMODE_STA
1344 #ifdef CONFIG_STA_SUPPORT
1345 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE
1346 #endif // CONFIG_STA_SUPPORT //
1350 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1351 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1353 if (Level == DOT11POWERSAVE)
1355 RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
1356 TbTTTime &= 0x1ffff;
1357 // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
1358 // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
1359 if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
1361 DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
1362 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
1363 //pAd->bPCIclkOffDisableTx = FALSE;
1364 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1369 PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
1370 #ifdef PCIE_PS_SUPPORT
1371 #ifdef CONFIG_STA_SUPPORT
1372 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1373 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1374 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1379 #endif // CONFIG_STA_SUPPORT //
1380 #endif // PCIE_PS_SUPPORT //
1383 BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
1384 if (TbttNumToNextWakeUp > 0)
1385 PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
1387 pAd->Mlme.bPsPollTimerRunning = TRUE;
1388 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
1394 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n"));
1397 pAd->bPCIclkOffDisableTx = FALSE;
1398 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1400 #ifdef CONFIG_STA_SUPPORT
1402 if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA)
1404 tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
1405 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
1407 #endif // CONFIG_STA_SUPPORT //
1409 // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1410 if ((INFRA_ON(pAd) || pAd->OpMode == OPMODE_AP) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1411 && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1413 // Must using 40MHz.
1414 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1418 // Must using 20MHz.
1419 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1422 if (Level != RTMP_HALT)
1424 // Change Interrupt bitmask.
1425 // When PCI clock is off, don't want to service interrupt.
1426 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
1430 RTMP_ASIC_INTERRUPT_DISABLE(pAd);
1434 RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
1435 // 2. Send Sleep command
1436 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
1437 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
1438 // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power
1439 AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1);
1440 // 2-1. Wait command success
1441 // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
1442 brc = AsicCheckCommanOk(pAd, PowerSafeCID);
1444 // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
1445 // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
1446 if ((Level == DOT11POWERSAVE) && (brc == TRUE))
1448 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
1449 // 3-1. Wait command success
1450 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1452 else if (brc == TRUE)
1454 AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
1455 // 3-1. Wait command success
1456 AsicCheckCommanOk(pAd, PowerRadioOffCID);
1459 #ifdef CONFIG_STA_SUPPORT
1460 // 1. Wait DMA not busy
1464 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1465 if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
1474 pAd->CheckDmaBusyCount++;
1475 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount));
1479 pAd->CheckDmaBusyCount = 0;
1482 #endif // CONFIG_STA_SUPPORT //
1483 //KH Debug:My original codes have the follwoing codes, but currecnt codes do not have it.
1484 // Disable for stability. If PCIE Link Control is modified for advance power save, re-covery this code segment.
1485 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x1280);
1486 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_CLKSELECT_40MHZ);
1488 #ifdef PCIE_PS_SUPPORT
1489 #ifdef CONFIG_STA_SUPPORT
1490 if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) && IS_VERSION_AFTER_F(pAd)
1491 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
1492 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1494 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::3090 return to skip the following TbttNumToNextWakeUp setting for 279x\n"));
1495 pAd->bPCIclkOff = TRUE;
1496 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1497 // For this case, doesn't need to below actions, so return here.
1500 #endif // CONFIG_STA_SUPPORT //
1501 #endif // PCIE_PS_SUPPORT //
1502 if (Level == DOT11POWERSAVE)
1504 AUTO_WAKEUP_STRUC AutoWakeupCfg;
1505 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
1507 // we have decided to SLEEP, so at least do it for a BEACON period.
1508 if (TbttNumToNextWakeUp == 0)
1509 TbttNumToNextWakeUp = 1;
1511 AutoWakeupCfg.word = 0;
1512 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1514 // 1. Set auto wake up timer.
1515 AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
1516 AutoWakeupCfg.field.EnableAutoWakeup = 1;
1517 AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
1518 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1521 #ifdef CONFIG_STA_SUPPORT
1522 // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
1523 if (Level == RTMP_HALT && pAd->OpMode == OPMODE_STA)
1525 if ((brc == TRUE) && (i < 50))
1526 RTMPPCIeLinkCtrlSetting(pAd, 1);
1528 // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function
1529 else if (pAd->OpMode == OPMODE_STA)
1531 if ((brc == TRUE) && (i < 50))
1532 RTMPPCIeLinkCtrlSetting(pAd, 3);
1534 #endif // CONFIG_STA_SUPPORT //
1536 //pAd->bPCIclkOffDisableTx = FALSE;
1537 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1544 VOID RT28xxPciMlmeRadioOn(
1545 IN PRTMP_ADAPTER pAd)
1547 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1550 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1552 if ((pAd->OpMode == OPMODE_AP) ||
1553 ((pAd->OpMode == OPMODE_STA)
1554 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
1555 #ifdef CONFIG_STA_SUPPORT
1556 ||pAd->StaCfg.PSControl.field.EnableNewPS == FALSE
1557 #endif // CONFIG_STA_SUPPORT //
1560 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1561 //NICResetFromError(pAd);
1563 RTMPRingCleanUp(pAd, QID_AC_BK);
1564 RTMPRingCleanUp(pAd, QID_AC_BE);
1565 RTMPRingCleanUp(pAd, QID_AC_VI);
1566 RTMPRingCleanUp(pAd, QID_AC_VO);
1567 /*RTMPRingCleanUp(pAd, QID_HCCA);*/
1568 RTMPRingCleanUp(pAd, QID_MGMT);
1569 RTMPRingCleanUp(pAd, QID_RX);
1572 RTMPEnableRxTx(pAd);
1574 // Clear Radio off flag
1575 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1576 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1578 RTMPSetLED(pAd, LED_RADIO_ON);
1581 #ifdef CONFIG_STA_SUPPORT
1582 if ((pAd->OpMode == OPMODE_STA) &&
1583 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1584 &&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
1588 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1590 pAd->Mlme.bPsPollTimerRunning = FALSE;
1591 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1592 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1593 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40);
1595 #endif // CONFIG_STA_SUPPORT //
1599 VOID RT28xxPciMlmeRadioOFF(
1600 IN PRTMP_ADAPTER pAd)
1604 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1607 #ifdef CONFIG_STA_SUPPORT
1608 // Link down first if any association exists
1609 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
1611 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1613 MLME_DISASSOC_REQ_STRUCT DisReq;
1614 MLME_QUEUE_ELEM *pMsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1618 COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid);
1619 DisReq.Reason = REASON_DISASSOC_STA_LEAVING;
1621 pMsgElem->Machine = ASSOC_STATE_MACHINE;
1622 pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
1623 pMsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
1624 NdisMoveMemory(pMsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
1626 MlmeDisassocReqAction(pAd, pMsgElem);
1629 RTMPusecDelay(1000);
1633 #endif // CONFIG_STA_SUPPORT //
1635 DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1638 //RTMPSetLED(pAd, LED_RADIO_OFF);
1639 // Set Radio off flag
1640 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1642 #ifdef CONFIG_STA_SUPPORT
1643 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1646 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1648 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1650 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1651 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1653 // If during power safe mode.
1654 if (pAd->StaCfg.bRadio == TRUE)
1656 DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1659 // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
1661 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1663 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1665 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1668 pAd->Mlme.bPsPollTimerRunning = FALSE;
1669 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1670 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1674 // Link down first if any association exists
1675 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1676 LinkDown(pAd, FALSE);
1677 RTMPusecDelay(10000);
1678 //==========================================
1679 // Clean up old bss table
1680 BssTableInit(&pAd->ScanTab);
1683 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1685 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1690 #endif // CONFIG_STA_SUPPORT //
1691 // Set LED.Move to here for fixing LED bug. This flag must be called after LinkDown
1692 RTMPSetLED(pAd, LED_RADIO_OFF);
1694 #ifdef CONFIG_STA_SUPPORT
1695 //KH Debug:All PCIe devices need to use timer to execute radio off function, or the PCIe&&EnableNewPS needs.
1696 //KH Ans:It is right, because only when the PCIe and EnableNewPs is true, we need to delay the RadioOffTimer
1697 //to avoid the deadlock with PCIe Power saving function.
1698 if (pAd->OpMode == OPMODE_STA&&
1699 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)&&
1700 pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1702 RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1705 #endif // CONFIG_STA_SUPPORT //
1709 brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1713 DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__));
1717 // Disable Tx/Rx DMA
1718 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
1719 GloCfg.field.EnableTxDMA = 0;
1720 GloCfg.field.EnableRxDMA = 0;
1721 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
1724 // MAC_SYS_CTRL => value = 0x0 => 40mA
1725 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
1727 // PWR_PIN_CFG => value = 0x0 => 40mA
1728 RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
1730 // TX_PIN_CFG => value = 0x0 => 20mA
1731 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
1733 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1735 // Must using 40MHz.
1736 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1740 // Must using 20MHz.
1741 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1744 // Waiting for DMA idle
1748 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1749 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1752 RTMPusecDelay(1000);
1757 #endif // RTMP_MAC_PCI //