]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt3090/common/cmm_mac_pci.c
8e1636315a8b332edc8522a77a4c66d03bf92fb1
[net-next-2.6.git] / drivers / staging / rt3090 / common / cmm_mac_pci.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
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.                                   *
14  *                                                                       *
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.                          *
19  *                                                                       *
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.             *
24  *                                                                       *
25  *************************************************************************
26 */
27
28 #ifdef RTMP_MAC_PCI
29
30 #include "../rt_config.h"
31
32
33 /*
34         ========================================================================
35
36         Routine Description:
37                 Allocate DMA memory blocks for send, receive
38
39         Arguments:
40                 Adapter         Pointer to our adapter
41
42         Return Value:
43                 NDIS_STATUS_SUCCESS
44                 NDIS_STATUS_FAILURE
45                 NDIS_STATUS_RESOURCES
46
47         IRQL = PASSIVE_LEVEL
48
49         Note:
50
51         ========================================================================
52 */
53 NDIS_STATUS     RTMPAllocTxRxRingMemory(
54         IN      PRTMP_ADAPTER   pAd)
55 {
56         NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
57         ULONG                   RingBasePaHigh;
58         ULONG                   RingBasePaLow;
59         PVOID                   RingBaseVa;
60         INT                             index, num;
61         PTXD_STRUC              pTxD;
62         PRXD_STRUC              pRxD;
63         ULONG                   ErrorValue = 0;
64         PRTMP_TX_RING   pTxRing;
65         PRTMP_DMABUF    pDmaBuf;
66         PNDIS_PACKET    pPacket;
67 //      PRTMP_REORDERBUF        pReorderBuf;
68
69         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
70         do
71         {
72                 //
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.
76                 //
77                 for (num=0; num<NUM_OF_TX_RING; num++)
78                 {
79                         ULONG  BufBasePaHigh;
80                         ULONG  BufBasePaLow;
81                         PVOID  BufBaseVa;
82
83                         //
84                         // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
85                         //
86                         pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
87                         RTMP_AllocateTxDescMemory(
88                                 pAd,
89                                 num,
90                                 pAd->TxDescRing[num].AllocSize,
91                                 FALSE,
92                                 &pAd->TxDescRing[num].AllocVa,
93                                 &pAd->TxDescRing[num].AllocPa);
94
95                         if (pAd->TxDescRing[num].AllocVa == NULL)
96                         {
97                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
98                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
99                                 Status = NDIS_STATUS_RESOURCES;
100                                 break;
101                         }
102
103                         // Zero init this memory block
104                         NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
105
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;
110
111                         //
112                         // Allocate all 1st TXBuf's memory for this TxRing
113                         //
114                         pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
115                         RTMP_AllocateFirstTxBuffer(
116                                 pAd,
117                                 num,
118                                 pAd->TxBufSpace[num].AllocSize,
119                                 FALSE,
120                                 &pAd->TxBufSpace[num].AllocVa,
121                                 &pAd->TxBufSpace[num].AllocPa);
122
123                         if (pAd->TxBufSpace[num].AllocVa == NULL)
124                         {
125                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
126                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
127                                 Status = NDIS_STATUS_RESOURCES;
128                                 break;
129                         }
130
131                         // Zero init this memory block
132                         NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
133
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;
138
139                         //
140                         // Initialize Tx Ring Descriptor and associated buffer memory
141                         //
142                         pTxRing = &pAd->TxRing[num];
143                         for (index = 0; index < TX_RING_SIZE; index++)
144                         {
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);
152
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);
159
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
164                                 pTxD->DMADONE = 1;
165 #ifdef RT_BIG_ENDIAN
166                                 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
167 #endif
168                                 RingBasePaLow += TXD_SIZE;
169                                 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
170
171                                 // advance to next TxBuf address
172                                 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
173                                 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
174                         }
175                         DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
176                 }
177                 if (Status == NDIS_STATUS_RESOURCES)
178                         break;
179
180                 //
181                 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
182                 //
183                 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
184                 RTMP_AllocateMgmtDescMemory(
185                         pAd,
186                         pAd->MgmtDescRing.AllocSize,
187                         FALSE,
188                         &pAd->MgmtDescRing.AllocVa,
189                         &pAd->MgmtDescRing.AllocPa);
190
191                 if (pAd->MgmtDescRing.AllocVa == NULL)
192                 {
193                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
194                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
195                         Status = NDIS_STATUS_RESOURCES;
196                         break;
197                 }
198
199                 // Zero init this memory block
200                 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
201
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;
206
207                 //
208                 // Initialize MGMT Ring and associated buffer memory
209                 //
210                 for (index = 0; index < MGMT_RING_SIZE; index++)
211                 {
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);
219
220                         // Offset to next ring descriptor address
221                         RingBasePaLow += TXD_SIZE;
222                         RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
223
224                         // link the pre-allocated TxBuf to TXD
225                         pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
226                         pTxD->DMADONE = 1;
227
228 #ifdef RT_BIG_ENDIAN
229                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
230 #endif
231                         // no pre-allocated buffer required in MgmtRing for scatter-gather case
232                 }
233                 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
234
235                 //
236                 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
237                 //
238                 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
239                 RTMP_AllocateRxDescMemory(
240                         pAd,
241                         pAd->RxDescRing.AllocSize,
242                         FALSE,
243                         &pAd->RxDescRing.AllocVa,
244                         &pAd->RxDescRing.AllocPa);
245
246                 if (pAd->RxDescRing.AllocVa == NULL)
247                 {
248                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
249                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
250                         Status = NDIS_STATUS_RESOURCES;
251                         break;
252                 }
253
254                 // Zero init this memory block
255                 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
256
257
258                 DBGPRINT(RT_DEBUG_OFF,
259                                         ("RX DESC %p  size = %ld\n", pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize));
260
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;
265
266                 //
267                 // Initialize Rx Ring and associated buffer memory
268                 //
269                 for (index = 0; index < RX_RING_SIZE; index++)
270                 {
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);
276
277                         //NdisZeroMemory(RingBaseVa, RXD_SIZE);
278
279                         // Offset to next ring descriptor address
280                         RingBasePaLow += RXD_SIZE;
281                         RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
282
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(
287                                 pAd,
288                                 pDmaBuf->AllocSize,
289                                 FALSE,
290                                 &pDmaBuf->AllocVa,
291                                 &pDmaBuf->AllocPa);
292
293                         /* keep allocated rx packet */
294                         pAd->RxRing.Cell[index].pNdisPacket = pPacket;
295
296                         // Error handling
297                         if (pDmaBuf->AllocVa == NULL)
298                         {
299                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
300                                 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
301                                 Status = NDIS_STATUS_RESOURCES;
302                                 break;
303                         }
304
305                         // Zero init this memory block
306                         NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
307
308                         // Write RxD buffer address & allocated buffer length
309                         pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
310                         pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
311                         pRxD->DDONE = 0;
312
313 #ifdef RT_BIG_ENDIAN
314                         RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
315 #endif
316                 }
317
318                 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
319
320         }       while (FALSE);
321
322
323         NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
324         pAd->FragFrame.pFragPacket =  RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
325
326         if (pAd->FragFrame.pFragPacket == NULL)
327         {
328                 Status = NDIS_STATUS_RESOURCES;
329         }
330
331         if (Status != NDIS_STATUS_SUCCESS)
332         {
333                 // Log error inforamtion
334                 NdisWriteErrorLogEntry(
335                         pAd->AdapterHandle,
336                         NDIS_ERROR_CODE_OUT_OF_RESOURCES,
337                         1,
338                         ErrorValue);
339         }
340
341         // Following code segment get from original func:NICInitTxRxRingAndBacklogQueue(), now should integrate it to here.
342         {
343                 DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTxRxRingAndBacklogQueue\n"));
344
345 /*
346                 // Disable DMA.
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);
351 */
352
353                 // Initialize all transmit related software queues
354                 for(index = 0; index < NUM_OF_TX_RING; index++)
355                 {
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);
361                 }
362
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);
367
368
369                 // init MGMT ring index pointer
370                 pAd->MgmtRing.TxSwFreeIdx = 0;
371                 pAd->MgmtRing.TxCpuIdx = 0;
372
373                 pAd->PrivateInfo.TxRingFullCnt = 0;
374
375                 DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTxRxRingAndBacklogQueue\n"));
376         }
377
378         DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
379         return Status;
380 }
381
382
383
384
385 /*
386         ========================================================================
387
388         Routine Description:
389                 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
390
391         Arguments:
392                 Adapter                                         Pointer to our adapter
393
394         Return Value:
395                 None
396
397         IRQL = PASSIVE_LEVEL
398         IRQL = DISPATCH_LEVEL
399
400         Note:
401                 Reset NIC to initial state AS IS system boot up time.
402
403         ========================================================================
404 */
405 VOID    RTMPRingCleanUp(
406         IN      PRTMP_ADAPTER   pAd,
407         IN      UCHAR                   RingType)
408 {
409         PTXD_STRUC              pTxD;
410         PRXD_STRUC              pRxD;
411         PQUEUE_ENTRY    pEntry;
412         PNDIS_PACKET    pPacket;
413         int                             i;
414         PRTMP_TX_RING   pTxRing;
415         unsigned long   IrqFlags;
416         //UINT32                        RxSwReadIdx;
417
418
419         DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
420         switch (RingType)
421         {
422                 case QID_AC_BK:
423                 case QID_AC_BE:
424                 case QID_AC_VI:
425                 case QID_AC_VO:
426                 /*case QID_HCCA:*/
427
428                         pTxRing = &pAd->TxRing[RingType];
429
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
433                         {
434                                 pTxD  = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
435
436                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
437                                 // release scatter-and-gather NDIS_PACKET
438                                 if (pPacket)
439                                 {
440                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
441                                         pTxRing->Cell[i].pNdisPacket = NULL;
442                                 }
443
444                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
445                                 // release scatter-and-gather NDIS_PACKET
446                                 if (pPacket)
447                                 {
448                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
449                                         pTxRing->Cell[i].pNextNdisPacket = NULL;
450                                 }
451                         }
452
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);
457
458                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
459
460                         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
461                         while (pAd->TxSwQueue[RingType].Head != NULL)
462                         {
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"));
467                         }
468                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
469                         break;
470
471                 case QID_MGMT:
472                         // We have to clean all descriptors in case some error happened with reset
473                         NdisAcquireSpinLock(&pAd->MgmtRingLock);
474
475                         for (i=0; i<MGMT_RING_SIZE; i++)
476                         {
477                                 pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
478
479                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
480                                 // rlease scatter-and-gather NDIS_PACKET
481                                 if (pPacket)
482                                 {
483                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
484                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
485                                 }
486                                 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
487
488                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
489                                 // release scatter-and-gather NDIS_PACKET
490                                 if (pPacket)
491                                 {
492                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
493                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
494                         }
495                                 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
496
497                         }
498
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);
503
504                         NdisReleaseSpinLock(&pAd->MgmtRingLock);
505                         pAd->RalinkCounters.MgmtRingFullCount = 0;
506                         break;
507
508                 case QID_RX:
509                         // We have to clean all descriptors in case some error happened with reset
510                         NdisAcquireSpinLock(&pAd->RxRingLock);
511
512                         for (i=0; i<RX_RING_SIZE; i++)
513                         {
514                                 pRxD  = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
515                 pRxD->DDONE = 0 ;
516                         }
517
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);
522
523                         NdisReleaseSpinLock(&pAd->RxRingLock);
524                         break;
525
526                 default:
527                         break;
528         }
529 }
530
531
532 VOID RTMPFreeTxRxRingMemory(
533     IN  PRTMP_ADAPTER   pAd)
534 {
535         int index, num , j;
536         PRTMP_TX_RING pTxRing;
537         PTXD_STRUC        pTxD;
538         PNDIS_PACKET  pPacket;
539         unsigned int  IrqFlags;
540
541         //POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
542
543         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
544
545         // Free TxSwQueue Packet
546         for (index=0; index <NUM_OF_TX_RING; index++)
547         {
548                 PQUEUE_ENTRY pEntry;
549                 PNDIS_PACKET pPacket;
550                 PQUEUE_HEADER   pQueue;
551
552                 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
553                 pQueue = &pAd->TxSwQueue[index];
554                 while (pQueue->Head)
555                 {
556                         pEntry = RemoveHeadQueue(pQueue);
557                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
558                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
559                 }
560                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
561         }
562
563         // Free Tx Ring Packet
564         for (index=0;index< NUM_OF_TX_RING;index++)
565         {
566                 pTxRing = &pAd->TxRing[index];
567
568                 for (j=0; j< TX_RING_SIZE; j++)
569                 {
570                         pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
571                         pPacket = pTxRing->Cell[j].pNdisPacket;
572
573                         if (pPacket)
574                         {
575                                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
576                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
577                         }
578                         //Always assign pNdisPacket as NULL after clear
579                         pTxRing->Cell[j].pNdisPacket = NULL;
580
581                         pPacket = pTxRing->Cell[j].pNextNdisPacket;
582
583                         if (pPacket)
584                         {
585                                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
586                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
587                         }
588                         //Always assign pNextNdisPacket as NULL after clear
589                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
590
591                 }
592         }
593
594         for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
595         {
596                 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
597                 {
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);
600                 }
601         }
602         NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
603
604         if (pAd->RxDescRing.AllocVa)
605     {
606                 RTMP_FreeDescMemory(pAd, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
607     }
608     NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
609
610         if (pAd->MgmtDescRing.AllocVa)
611         {
612                 RTMP_FreeDescMemory(pAd, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
613         }
614         NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
615
616         for (num = 0; num < NUM_OF_TX_RING; num++)
617         {
618         if (pAd->TxBufSpace[num].AllocVa)
619                 {
620                         RTMP_FreeFirstTxBuffer(pAd, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
621             }
622             NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
623
624         if (pAd->TxDescRing[num].AllocVa)
625                 {
626                         RTMP_FreeDescMemory(pAd, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
627             }
628             NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
629         }
630
631         if (pAd->FragFrame.pFragPacket)
632                 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
633
634         DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
635 }
636
637
638 /***************************************************************************
639   *
640   *     register related procedures.
641   *
642   **************************************************************************/
643 /*
644 ========================================================================
645 Routine Description:
646     Disable DMA.
647
648 Arguments:
649         *pAd                            the raxx interface data pointer
650
651 Return Value:
652         None
653
654 Note:
655 ========================================================================
656 */
657 VOID RT28XXDMADisable(
658         IN RTMP_ADAPTER                 *pAd)
659 {
660         WPDMA_GLO_CFG_STRUC     GloCfg;
661
662
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);
667 }
668
669
670 /*
671 ========================================================================
672 Routine Description:
673     Enable DMA.
674
675 Arguments:
676         *pAd                            the raxx interface data pointer
677
678 Return Value:
679         None
680
681 Note:
682 ========================================================================
683 */
684 VOID RT28XXDMAEnable(
685         IN RTMP_ADAPTER                 *pAd)
686 {
687         WPDMA_GLO_CFG_STRUC     GloCfg;
688         int i = 0;
689
690         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
691         do
692         {
693                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
694                 if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
695                         break;
696
697                 DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
698                 RTMPusecDelay(1000);
699                 i++;
700         }while ( i <200);
701
702         RTMPusecDelay(50);
703
704         GloCfg.field.EnTXWriteBackDDONE = 1;
705         GloCfg.field.WPDMABurstSIZE = 2;
706         GloCfg.field.EnableRxDMA = 1;
707         GloCfg.field.EnableTxDMA = 1;
708
709         DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
710         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
711
712 }
713
714
715 BOOLEAN AsicCheckCommanOk(
716         IN PRTMP_ADAPTER pAd,
717         IN UCHAR                 Command)
718 {
719         UINT32  CmdStatus = 0, CID = 0, i;
720         UINT32  ThisCIDMask = 0;
721
722         i = 0;
723         do
724         {
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)
728                 {
729                         ThisCIDMask = CID0MASK;
730                         break;
731                 }
732                 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
733                 {
734                         ThisCIDMask = CID1MASK;
735                         break;
736                 }
737                 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
738                 {
739                         ThisCIDMask = CID2MASK;
740                         break;
741                 }
742                 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
743                 {
744                         ThisCIDMask = CID3MASK;
745                         break;
746                 }
747
748                 RTMPusecDelay(100);
749                 i++;
750         }while (i < 200);
751
752         // Get CommandStatus Value
753         RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
754
755         // This command's status is at the same position as command. So AND command position's bitmask to read status.
756         if (i < 200)
757         {
758                 // If Status is 1, the comamnd is success.
759                 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
760                         || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
761                 {
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);
765                         return TRUE;
766                 }
767                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
768         }
769         else
770         {
771                 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
772         }
773         // Clear Command and Status.
774         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
775         RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
776
777         return FALSE;
778 }
779
780
781 /*
782 ========================================================================
783 Routine Description:
784     Write Beacon buffer to Asic.
785
786 Arguments:
787         *pAd                            the raxx interface data pointer
788
789 Return Value:
790         None
791
792 Note:
793 ========================================================================
794 */
795 VOID RT28xx_UpdateBeaconToAsic(
796         IN RTMP_ADAPTER         *pAd,
797         IN INT                          apidx,
798         IN ULONG                        FrameLen,
799         IN ULONG                        UpdatePos)
800 {
801         ULONG                           CapInfoPos = 0;
802         UCHAR                   *ptr, *ptr_update, *ptr_capinfo;
803         UINT                    i;
804         BOOLEAN                 bBcnReq = FALSE;
805         UCHAR                   bcn_idx = 0;
806
807
808         {
809                 DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __FUNCTION__));
810                 return;
811         }
812
813         //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE)
814         //      || ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL)
815         //              || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
816         //      )
817         if (bBcnReq == FALSE)
818         {
819                 /* when the ra interface is down, do not send its beacon frame */
820                 /* clear all zero */
821                 for(i=0; i<TXWI_SIZE; i+=4)
822                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
823         }
824         else
825         {
826                 ptr = (PUCHAR)&pAd->BeaconTxWI;
827 #ifdef RT_BIG_ENDIAN
828                 RTMPWIEndianChange(ptr, TYPE_TXWI);
829 #endif
830                 for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
831                 {
832                         UINT32 longptr =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
833                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr);
834                         ptr += 4;
835                 }
836
837                 // Update CapabilityInfo in Beacon
838                 for (i = CapInfoPos; i < (CapInfoPos+2); i++)
839                 {
840                         RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo);
841                         ptr_capinfo ++;
842                 }
843
844                 if (FrameLen > UpdatePos)
845                 {
846                         for (i= UpdatePos; i< (FrameLen); i++)
847                         {
848                                 RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update);
849                                 ptr_update ++;
850                         }
851                 }
852
853         }
854
855 }
856
857
858 #ifdef CONFIG_STA_SUPPORT
859 VOID RT28xxPciStaAsicForceWakeup(
860         IN PRTMP_ADAPTER pAd,
861         IN BOOLEAN       bFromTx)
862 {
863     AUTO_WAKEUP_STRUC   AutoWakeupCfg;
864
865     if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
866         return;
867
868     if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
869     {
870         DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
871         return;
872     }
873
874     OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
875
876     RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
877
878     if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
879                 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
880     {
881         // Support PCIe Advance Power Save
882         if (bFromTx == TRUE
883                         &&(pAd->Mlme.bPsPollTimerRunning == TRUE))
884         {
885             pAd->Mlme.bPsPollTimerRunning = FALSE;
886                 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
887                 RTMPusecDelay(3000);
888             DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
889         }
890
891                 AutoWakeupCfg.word = 0;
892                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
893
894         if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
895         {
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))
899                         {
900                                 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
901
902                                 if (pChipOps->AsicReverseRfFromSleepMode)
903                                         pChipOps->AsicReverseRfFromSleepMode(pAd);
904                         }
905                         else
906 #endif // PCIE_PS_SUPPORT //
907                         {
908                         // end johnli
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))
912                                 {
913                                         // Must using 40MHz.
914                                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
915                                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
916                                 }
917                                 else
918                                 {
919                                         // Must using 20MHz.
920                                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
921                                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
922                                 }
923                         }
924         }
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))
931                         {
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);
936                         }
937 #endif // PCIE_PS_SUPPORT //
938     }
939     else
940     {
941         // PCI, 2860-PCIe
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);
946     }
947
948     OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
949     OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
950     DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
951 }
952
953
954 VOID RT28xxPciStaAsicSleepThenAutoWakeup(
955         IN PRTMP_ADAPTER pAd,
956         IN USHORT TbttNumToNextWakeUp)
957 {
958         BOOLEAN brc;
959
960         if (pAd->StaCfg.bRadio == FALSE)
961         {
962                 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
963                 return;
964         }
965         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
966                 &&pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
967         {
968                 ULONG   Now = 0;
969                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
970                 {
971                         DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
972                         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
973                         return;
974                 }
975
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))
980                 {
981                         DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu :  RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
982                         return;
983                 }
984                 else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
985                 {
986                         DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime,  pAd->RalinkCounters.RxCountSinceLastNULL));
987                         return;
988                 }
989
990                 brc = RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
991                 if (brc==TRUE)
992                         OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
993         }
994         else
995         {
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;
1000
1001                 //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
1002
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));
1012         }
1013
1014 }
1015
1016
1017 VOID PsPollWakeExec(
1018         IN PVOID SystemSpecific1,
1019         IN PVOID FunctionContext,
1020         IN PVOID SystemSpecific2,
1021         IN PVOID SystemSpecific3)
1022 {
1023         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1024         unsigned long flags;
1025
1026     DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
1027
1028         RTMP_INT_LOCK(&pAd->irq_lock, flags);
1029     if (pAd->Mlme.bPsPollTimerRunning)
1030     {
1031             RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1032     }
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))
1041         {
1042                 DBGPRINT(RT_DEBUG_TRACE,("<--PsPollWakeExec::3090 calls AsicForceWakeup(pAd, DOT11POWERSAVE) in advance \n"));
1043                 AsicForceWakeup(pAd, DOT11POWERSAVE);
1044         }
1045
1046 #endif // PCIE_PS_SUPPORT //
1047 }
1048
1049 VOID  RadioOnExec(
1050         IN PVOID SystemSpecific1,
1051         IN PVOID FunctionContext,
1052         IN PVOID SystemSpecific2,
1053         IN PVOID SystemSpecific3)
1054 {
1055         RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1056         RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1057         WPDMA_GLO_CFG_STRUC     DmaCfg;
1058         BOOLEAN                         Cancelled;
1059
1060         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1061         {
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 //
1069                 return;
1070         }
1071
1072         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1073         {
1074                 DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
1075
1076
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 //
1082                 return;
1083         }
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)
1088         {
1089         pAd->Mlme.bPsPollTimerRunning = FALSE;
1090         RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1091         }
1092 #endif // RTMP_PCI_SUPPORT //
1093         if (pAd->StaCfg.bRadio == TRUE)
1094         {
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);
1103
1104                 // 2. Send wake up command.
1105                 AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1106                 // 2-1. wait command ok.
1107                 AsicCheckCommanOk(pAd, PowerWakeCID);
1108
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);
1112
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);
1117
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))
1121                 {
1122                         // Must using 40MHz.
1123                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1124                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1125                 }
1126                 else
1127                 {
1128                         // Must using 20MHz.
1129                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1130                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1131                 }
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))
1142         {
1143         RTMP_SEM_LOCK(&pAd->McuCmdLock);
1144         pAd->brt30xxBanMcuCmd = FALSE;
1145         RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1146         }
1147 #endif // CONFIG_STA_SUPPORT //
1148 #endif // PCIE_PS_SUPPORT //
1149                 // Clear Radio off flag
1150                 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1151
1152                 // Set LED
1153                 RTMPSetLED(pAd, LED_RADIO_ON);
1154
1155         if (pAd->StaCfg.Psm == PWR_ACTIVE)
1156         {
1157                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1158         }
1159         }
1160         else
1161         {
1162                 RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1163         }
1164 }
1165 #endif // CONFIG_STA_SUPPORT //
1166
1167
1168 /*
1169         ==========================================================================
1170         Description:
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.
1173         Input:
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.
1176
1177         ==========================================================================
1178  */
1179 BOOLEAN RT28xxPciAsicRadioOn(
1180         IN PRTMP_ADAPTER pAd,
1181         IN UCHAR     Level)
1182 {
1183     //WPDMA_GLO_CFG_STRUC       DmaCfg;
1184 #ifdef CONFIG_STA_SUPPORT
1185         BOOLEAN                         Cancelled;
1186 #endif // CONFIG_STA_SUPPORT //
1187     //UINT32                        MACValue;
1188
1189         if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1190                 return FALSE;
1191
1192 #ifdef CONFIG_STA_SUPPORT
1193         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1194         {
1195                 if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1196                 {
1197             pAd->Mlme.bPsPollTimerRunning = FALSE;
1198                 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1199                 }
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)))
1203                 {
1204                         // Some chips don't need to delay 6ms, so copy RTMPPCIePowerLinkCtrlRestore
1205                         // return condition here.
1206                         /*
1207                         if (((pAd->MACVersion&0xffff0000) != 0x28600000)
1208                                 && ((pAd->DeviceID == NIC2860_PCIe_DEVICE_ID)
1209                                 ||(pAd->DeviceID == NIC2790_PCIe_DEVICE_ID)))
1210                         */
1211                 {
1212                         DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
1213                         // 1. Set PCI Link Control in Configuration Space.
1214                         RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1215                         RTMPusecDelay(6000);
1216                 }
1217         }
1218         }
1219
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 //
1225         {
1226     pAd->bPCIclkOff = FALSE;
1227                 DBGPRINT(RT_DEBUG_TRACE, ("PSM :309xbPCIclkOff == %d\n", pAd->bPCIclkOff));
1228
1229         }
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);
1237
1238
1239         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1240         if (Level == GUI_IDLE_POWER_SAVE)
1241         {
1242 #ifdef  PCIE_PS_SUPPORT
1243
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)))
1246                         {
1247                                 RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
1248
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))
1257                                         {
1258                                                 RTMP_SEM_LOCK(&pAd->McuCmdLock);
1259                                                 pAd->brt30xxBanMcuCmd = FALSE;
1260                                                 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
1261                                         }
1262 #endif // CONFIG_STA_SUPPORT //
1263                         }
1264                         else
1265                         // end johnli
1266 #endif // PCIE_PS_SUPPORT //
1267                         {
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)
1271                                 {
1272                                 if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1273                                         && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1274                                 {
1275                                         // Must using 40MHz.
1276                                         AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1277                                         AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1278                                 }
1279                                 else
1280                                 {
1281                                         // Must using 20MHz.
1282                                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1283                                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1284                                 }
1285                                 }
1286 #endif // CONFIG_STA_SUPPORT //
1287                         }
1288         }
1289         return TRUE;
1290
1291 }
1292
1293
1294 /*
1295         ==========================================================================
1296         Description:
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.
1299         Input:
1300                 Level = GUIRADIO_OFF  : GUI Radio Off mode
1301                 Level = DOT11POWERSAVE  : 802.11 power save mode
1302                 Level = RTMP_HALT  : When Disable device.
1303
1304         ==========================================================================
1305  */
1306 BOOLEAN RT28xxPciAsicRadioOff(
1307         IN PRTMP_ADAPTER    pAd,
1308         IN UCHAR            Level,
1309         IN USHORT           TbttNumToNextWakeUp)
1310 {
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));
1321
1322         if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE)
1323                 return FALSE;
1324
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))
1329         {
1330                 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d ,  RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
1331                 return FALSE;
1332         }
1333         else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
1334         {
1335                 DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2.  RxCpuIdx = %d. RxDmaIdx = %d ,  \n", RxCpuIdx, RxDmaIdx));
1336                 return FALSE;
1337         }
1338
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 //
1347                 )
1348         {
1349
1350             RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
1351             RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
1352
1353             if (Level == DOT11POWERSAVE)
1354                 {
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))
1360                         {
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);
1365                                 return FALSE;
1366                         }
1367                         else
1368                         {
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))
1375                                 {
1376                                                         PsPollTime -= 5;
1377                                 }
1378                                 else
1379 #endif // CONFIG_STA_SUPPORT //
1380 #endif // PCIE_PS_SUPPORT //
1381                                 PsPollTime -= 3;
1382
1383                     BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
1384                                 if (TbttNumToNextWakeUp > 0)
1385                                         PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
1386
1387                     pAd->Mlme.bPsPollTimerRunning = TRUE;
1388                                 RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
1389                         }
1390                 }
1391         }
1392         else
1393         {
1394                 DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOff::Level!=DOT11POWERSAVE \n"));
1395         }
1396
1397         pAd->bPCIclkOffDisableTx = FALSE;
1398     RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1399
1400 #ifdef CONFIG_STA_SUPPORT
1401     // Set to 1R.
1402         if (pAd->Antenna.field.RxPath > 1 && pAd->OpMode == OPMODE_STA)
1403         {
1404     tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
1405         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
1406         }
1407 #endif // CONFIG_STA_SUPPORT //
1408
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))
1412         {
1413                 // Must using 40MHz.
1414                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1415         }
1416         else
1417         {
1418                 // Must using 20MHz.
1419                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1420         }
1421
1422         if (Level != RTMP_HALT)
1423         {
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);
1427         }
1428         else
1429         {
1430                 RTMP_ASIC_INTERRUPT_DISABLE(pAd);
1431         }
1432
1433
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);
1443
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))
1447         {
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);
1451         }
1452         else if (brc == TRUE)
1453         {
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);
1457         }
1458
1459 #ifdef CONFIG_STA_SUPPORT
1460         // 1. Wait DMA not busy
1461         i = 0;
1462         do
1463         {
1464                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1465                 if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
1466                         break;
1467                 RTMPusecDelay(20);
1468                 i++;
1469         }while(i < 50);
1470
1471         /*
1472         if (i >= 50)
1473         {
1474                 pAd->CheckDmaBusyCount++;
1475                 DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy.  return on AsicRadioOff () CheckDmaBusyCount = %d \n", pAd->CheckDmaBusyCount));
1476         }
1477         else
1478         {
1479                 pAd->CheckDmaBusyCount = 0;
1480         }
1481         */
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);
1487
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))
1493         {
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.
1498         return brc;
1499         }
1500 #endif // CONFIG_STA_SUPPORT //
1501 #endif // PCIE_PS_SUPPORT //
1502         if (Level == DOT11POWERSAVE)
1503         {
1504                 AUTO_WAKEUP_STRUC       AutoWakeupCfg;
1505                 //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
1506
1507                 // we have decided to SLEEP, so at least do it for a BEACON period.
1508                 if (TbttNumToNextWakeUp == 0)
1509                         TbttNumToNextWakeUp = 1;
1510
1511                 AutoWakeupCfg.word = 0;
1512                 RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1513
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);
1519         }
1520
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)
1524         {
1525                 if ((brc == TRUE) && (i < 50))
1526                         RTMPPCIeLinkCtrlSetting(pAd, 1);
1527         }
1528         //  4. Set PCI configuration Space Link Comtrol fields.  Only Radio Off needs to call this function
1529         else if (pAd->OpMode == OPMODE_STA)
1530         {
1531                 if ((brc == TRUE) && (i < 50))
1532                         RTMPPCIeLinkCtrlSetting(pAd, 3);
1533         }
1534 #endif // CONFIG_STA_SUPPORT //
1535
1536         //pAd->bPCIclkOffDisableTx = FALSE;
1537         RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
1538         return TRUE;
1539 }
1540
1541
1542
1543
1544 VOID RT28xxPciMlmeRadioOn(
1545         IN PRTMP_ADAPTER pAd)
1546 {
1547     if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1548                 return;
1549
1550     DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1551
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 //
1558         )))
1559     {
1560         RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1561         //NICResetFromError(pAd);
1562
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);
1570
1571         // Enable Tx/Rx
1572         RTMPEnableRxTx(pAd);
1573
1574         // Clear Radio off flag
1575         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1576         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
1577             // Set LED
1578             RTMPSetLED(pAd, LED_RADIO_ON);
1579     }
1580
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))
1585     {
1586         BOOLEAN         Cancelled;
1587
1588         RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1589
1590         pAd->Mlme.bPsPollTimerRunning = FALSE;
1591         RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1592         RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1593         RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 40);
1594     }
1595 #endif // CONFIG_STA_SUPPORT //
1596 }
1597
1598
1599 VOID RT28xxPciMlmeRadioOFF(
1600         IN PRTMP_ADAPTER pAd)
1601 {
1602         BOOLEAN brc=TRUE;
1603
1604     if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1605         return;
1606
1607 #ifdef CONFIG_STA_SUPPORT
1608         // Link down first if any association exists
1609         if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
1610         {
1611                 if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1612                 {
1613                         MLME_DISASSOC_REQ_STRUCT DisReq;
1614                         MLME_QUEUE_ELEM *pMsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1615
1616                         if (pMsgElem)
1617                         {
1618                                 COPY_MAC_ADDR(&DisReq.Addr, pAd->CommonCfg.Bssid);
1619                                 DisReq.Reason =  REASON_DISASSOC_STA_LEAVING;
1620
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));
1625
1626                                 MlmeDisassocReqAction(pAd, pMsgElem);
1627                                 kfree(pMsgElem);
1628
1629                                 RTMPusecDelay(1000);
1630                         }
1631                 }
1632         }
1633 #endif // CONFIG_STA_SUPPORT //
1634
1635     DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__));
1636
1637         // Set LED
1638         //RTMPSetLED(pAd, LED_RADIO_OFF);
1639         // Set Radio off flag
1640         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1641
1642 #ifdef CONFIG_STA_SUPPORT
1643         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1644     {
1645         BOOLEAN         Cancelled;
1646         if (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
1647                 {
1648         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1649         {
1650                         RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1651                         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1652         }
1653                         // If during power safe mode.
1654                         if (pAd->StaCfg.bRadio == TRUE)
1655                         {
1656                                 DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1657                                 return;
1658                         }
1659                         // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
1660                         if (IDLE_ON(pAd) &&
1661                                 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1662                         {
1663                                 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1664                         }
1665                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1666         {
1667             BOOLEAN Cancelled;
1668             pAd->Mlme.bPsPollTimerRunning = FALSE;
1669             RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
1670                 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1671         }
1672                 }
1673
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);
1681
1682         /*
1683         if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE))
1684         {
1685             RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1686             return;
1687         }
1688         */
1689     }
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);
1693
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)
1701         {
1702         RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1703         }
1704 else
1705 #endif // CONFIG_STA_SUPPORT //
1706 {
1707
1708
1709         brc=RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1710
1711         if (brc==FALSE)
1712         {
1713                 DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__));
1714         }
1715 }
1716 /*
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
1722
1723
1724         // MAC_SYS_CTRL => value = 0x0 => 40mA
1725         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
1726
1727         // PWR_PIN_CFG => value = 0x0 => 40mA
1728         RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
1729
1730         // TX_PIN_CFG => value = 0x0 => 20mA
1731         RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
1732
1733         if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1734         {
1735                 // Must using 40MHz.
1736                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1737         }
1738         else
1739         {
1740                 // Must using 20MHz.
1741                 AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1742         }
1743
1744         // Waiting for DMA idle
1745         i = 0;
1746         do
1747         {
1748                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1749                 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1750                         break;
1751
1752                 RTMPusecDelay(1000);
1753         }while (i++ < 100);
1754 */
1755 }
1756
1757 #endif // RTMP_MAC_PCI //