~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/rt2860/common/cmm_data_2860.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
/*
29
 
   All functions in this file must be PCI-depended, or you should out your function
30
 
        in other files.
31
 
 
32
 
*/
33
 
#include "../rt_config.h"
34
 
 
35
 
extern RTMP_RF_REGS RF2850RegTable[];
36
 
extern UCHAR    NUM_OF_2850_CHNL;
37
 
 
38
 
USHORT RtmpPCI_WriteTxResource(
39
 
        IN      PRTMP_ADAPTER   pAd,
40
 
        IN      TX_BLK                  *pTxBlk,
41
 
        IN      BOOLEAN                 bIsLast,
42
 
        OUT     USHORT                  *FreeNumber)
43
 
{
44
 
 
45
 
        UCHAR                   *pDMAHeaderBufVA;
46
 
        USHORT                  TxIdx, RetTxIdx;
47
 
        PTXD_STRUC              pTxD;
48
 
        UINT32                  BufBasePaLow;
49
 
        PRTMP_TX_RING   pTxRing;
50
 
        USHORT                  hwHeaderLen;
51
 
 
52
 
        //
53
 
        // get Tx Ring Resource
54
 
        //
55
 
        pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
56
 
        TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
57
 
        pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
58
 
        BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
59
 
 
60
 
        // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
61
 
        if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
62
 
        {
63
 
                hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
64
 
        }
65
 
        else
66
 
        {
67
 
                hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
68
 
        }
69
 
        NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
70
 
 
71
 
        pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
72
 
        pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
73
 
 
74
 
        //
75
 
        // build Tx Descriptor
76
 
        //
77
 
 
78
 
        pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
79
 
        NdisZeroMemory(pTxD, TXD_SIZE);
80
 
 
81
 
        pTxD->SDPtr0 = BufBasePaLow;
82
 
        pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
83
 
        pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
84
 
        pTxD->SDLen1 = pTxBlk->SrcBufLen;
85
 
        pTxD->LastSec0 = 0;
86
 
        pTxD->LastSec1 = (bIsLast) ? 1 : 0;
87
 
 
88
 
        RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
89
 
 
90
 
        RetTxIdx = TxIdx;
91
 
        //
92
 
        // Update Tx index
93
 
        //
94
 
        INC_RING_INDEX(TxIdx, TX_RING_SIZE);
95
 
        pTxRing->TxCpuIdx = TxIdx;
96
 
 
97
 
        *FreeNumber -= 1;
98
 
 
99
 
        return RetTxIdx;
100
 
}
101
 
 
102
 
 
103
 
USHORT RtmpPCI_WriteSingleTxResource(
104
 
        IN      PRTMP_ADAPTER   pAd,
105
 
        IN      TX_BLK                  *pTxBlk,
106
 
        IN      BOOLEAN                 bIsLast,
107
 
        OUT     USHORT                  *FreeNumber)
108
 
{
109
 
 
110
 
        UCHAR                   *pDMAHeaderBufVA;
111
 
        USHORT                  TxIdx, RetTxIdx;
112
 
        PTXD_STRUC              pTxD;
113
 
        UINT32                  BufBasePaLow;
114
 
        PRTMP_TX_RING   pTxRing;
115
 
        USHORT                  hwHeaderLen;
116
 
 
117
 
        //
118
 
        // get Tx Ring Resource
119
 
        //
120
 
        pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
121
 
        TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
122
 
        pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
123
 
        BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
124
 
 
125
 
        // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
126
 
        hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
127
 
 
128
 
        NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
129
 
 
130
 
        pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
131
 
        pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
132
 
 
133
 
        //
134
 
        // build Tx Descriptor
135
 
        //
136
 
        pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
137
 
 
138
 
        NdisZeroMemory(pTxD, TXD_SIZE);
139
 
 
140
 
        pTxD->SDPtr0 = BufBasePaLow;
141
 
        pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
142
 
        pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
143
 
        pTxD->SDLen1 = pTxBlk->SrcBufLen;
144
 
        pTxD->LastSec0 = 0;
145
 
        pTxD->LastSec1 = (bIsLast) ? 1 : 0;
146
 
 
147
 
        RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
148
 
 
149
 
        RetTxIdx = TxIdx;
150
 
        //
151
 
        // Update Tx index
152
 
        //
153
 
        INC_RING_INDEX(TxIdx, TX_RING_SIZE);
154
 
        pTxRing->TxCpuIdx = TxIdx;
155
 
 
156
 
        *FreeNumber -= 1;
157
 
 
158
 
        return RetTxIdx;
159
 
}
160
 
 
161
 
 
162
 
USHORT RtmpPCI_WriteMultiTxResource(
163
 
        IN      PRTMP_ADAPTER   pAd,
164
 
        IN      TX_BLK                  *pTxBlk,
165
 
        IN      UCHAR                   frameNum,
166
 
        OUT     USHORT                  *FreeNumber)
167
 
{
168
 
        BOOLEAN bIsLast;
169
 
        UCHAR                   *pDMAHeaderBufVA;
170
 
        USHORT                  TxIdx, RetTxIdx;
171
 
        PTXD_STRUC              pTxD;
172
 
        UINT32                  BufBasePaLow;
173
 
        PRTMP_TX_RING   pTxRing;
174
 
        USHORT                  hwHdrLen;
175
 
        UINT32                  firstDMALen;
176
 
 
177
 
        bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
178
 
 
179
 
        //
180
 
        // get Tx Ring Resource
181
 
        //
182
 
        pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
183
 
        TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
184
 
        pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
185
 
        BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
186
 
 
187
 
        if (frameNum == 0)
188
 
        {
189
 
                // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
190
 
                if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
191
 
                        //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
192
 
                        hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
193
 
                else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
194
 
                        //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
195
 
                        hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
196
 
                else
197
 
                        //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
198
 
                        hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
199
 
 
200
 
                firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
201
 
        }
202
 
        else
203
 
        {
204
 
                firstDMALen = pTxBlk->MpduHeaderLen;
205
 
        }
206
 
 
207
 
        NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
208
 
 
209
 
        pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
210
 
        pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
211
 
 
212
 
        //
213
 
        // build Tx Descriptor
214
 
        //
215
 
        pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
216
 
 
217
 
        NdisZeroMemory(pTxD, TXD_SIZE);
218
 
 
219
 
        pTxD->SDPtr0 = BufBasePaLow;
220
 
        pTxD->SDLen0 = firstDMALen; // include padding
221
 
        pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
222
 
        pTxD->SDLen1 = pTxBlk->SrcBufLen;
223
 
        pTxD->LastSec0 = 0;
224
 
        pTxD->LastSec1 = (bIsLast) ? 1 : 0;
225
 
 
226
 
        RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
227
 
 
228
 
        RetTxIdx = TxIdx;
229
 
        //
230
 
        // Update Tx index
231
 
        //
232
 
        INC_RING_INDEX(TxIdx, TX_RING_SIZE);
233
 
        pTxRing->TxCpuIdx = TxIdx;
234
 
 
235
 
        *FreeNumber -= 1;
236
 
 
237
 
        return RetTxIdx;
238
 
 
239
 
}
240
 
 
241
 
 
242
 
VOID RtmpPCI_FinalWriteTxResource(
243
 
        IN      PRTMP_ADAPTER   pAd,
244
 
        IN      TX_BLK                  *pTxBlk,
245
 
        IN      USHORT                  totalMPDUSize,
246
 
        IN      USHORT                  FirstTxIdx)
247
 
{
248
 
 
249
 
        PTXWI_STRUC             pTxWI;
250
 
        PRTMP_TX_RING   pTxRing;
251
 
 
252
 
        //
253
 
        // get Tx Ring Resource
254
 
        //
255
 
        pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
256
 
        pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
257
 
        pTxWI->MPDUtotalByteCount = totalMPDUSize;
258
 
}
259
 
 
260
 
 
261
 
VOID RtmpPCIDataLastTxIdx(
262
 
        IN      PRTMP_ADAPTER   pAd,
263
 
        IN      UCHAR                   QueIdx,
264
 
        IN      USHORT                  LastTxIdx)
265
 
{
266
 
        PTXD_STRUC              pTxD;
267
 
        PRTMP_TX_RING   pTxRing;
268
 
 
269
 
        //
270
 
        // get Tx Ring Resource
271
 
        //
272
 
        pTxRing = &pAd->TxRing[QueIdx];
273
 
 
274
 
        //
275
 
        // build Tx Descriptor
276
 
        //
277
 
        pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
278
 
 
279
 
        pTxD->LastSec1 = 1;
280
 
}
281
 
 
282
 
 
283
 
USHORT  RtmpPCI_WriteFragTxResource(
284
 
        IN      PRTMP_ADAPTER   pAd,
285
 
        IN      TX_BLK                  *pTxBlk,
286
 
        IN      UCHAR                   fragNum,
287
 
        OUT     USHORT                  *FreeNumber)
288
 
{
289
 
        UCHAR                   *pDMAHeaderBufVA;
290
 
        USHORT                  TxIdx, RetTxIdx;
291
 
        PTXD_STRUC              pTxD;
292
 
        UINT32                  BufBasePaLow;
293
 
        PRTMP_TX_RING   pTxRing;
294
 
        USHORT                  hwHeaderLen;
295
 
        UINT32                  firstDMALen;
296
 
 
297
 
        //
298
 
        // Get Tx Ring Resource
299
 
        //
300
 
        pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
301
 
        TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
302
 
        pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
303
 
        BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
304
 
 
305
 
        //
306
 
        // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
307
 
        //
308
 
        hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
309
 
 
310
 
        firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
311
 
        NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
312
 
 
313
 
 
314
 
        //
315
 
        // Build Tx Descriptor
316
 
        //
317
 
        pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
318
 
 
319
 
        NdisZeroMemory(pTxD, TXD_SIZE);
320
 
 
321
 
        if (fragNum == pTxBlk->TotalFragNum)
322
 
        {
323
 
                pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
324
 
                pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
325
 
        }
326
 
 
327
 
        pTxD->SDPtr0 = BufBasePaLow;
328
 
        pTxD->SDLen0 = firstDMALen; // include padding
329
 
        pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
330
 
        pTxD->SDLen1 = pTxBlk->SrcBufLen;
331
 
        pTxD->LastSec0 = 0;
332
 
        pTxD->LastSec1 = 1;
333
 
 
334
 
        RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
335
 
 
336
 
        RetTxIdx = TxIdx;
337
 
        pTxBlk->Priv += pTxBlk->SrcBufLen;
338
 
 
339
 
        //
340
 
        // Update Tx index
341
 
        //
342
 
        INC_RING_INDEX(TxIdx, TX_RING_SIZE);
343
 
        pTxRing->TxCpuIdx = TxIdx;
344
 
 
345
 
        *FreeNumber -= 1;
346
 
 
347
 
        return RetTxIdx;
348
 
 
349
 
}
350
 
 
351
 
/*
352
 
        Must be run in Interrupt context
353
 
        This function handle PCI specific TxDesc and cpu index update and kick the packet out.
354
 
 */
355
 
int RtmpPCIMgmtKickOut(
356
 
        IN RTMP_ADAPTER         *pAd,
357
 
        IN UCHAR                        QueIdx,
358
 
        IN PNDIS_PACKET         pPacket,
359
 
        IN PUCHAR                       pSrcBufVA,
360
 
        IN UINT                         SrcBufLen)
361
 
{
362
 
        PTXD_STRUC              pTxD;
363
 
        ULONG                   SwIdx = pAd->MgmtRing.TxCpuIdx;
364
 
 
365
 
        pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
366
 
        if (!pTxD)
367
 
                return 0;
368
 
 
369
 
        pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
370
 
        pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
371
 
 
372
 
        RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
373
 
        pTxD->LastSec0 = 1;
374
 
        pTxD->LastSec1 = 1;
375
 
        pTxD->DMADONE = 0;
376
 
        pTxD->SDLen1 = 0;
377
 
        pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);;
378
 
        pTxD->SDLen0 = SrcBufLen;
379
 
 
380
 
        pAd->RalinkCounters.KickTxCount++;
381
 
        pAd->RalinkCounters.OneSecTxDoneCount++;
382
 
 
383
 
        // Increase TX_CTX_IDX, but write to register later.
384
 
        INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
385
 
 
386
 
        RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX,  pAd->MgmtRing.TxCpuIdx);
387
 
 
388
 
        return 0;
389
 
}
390
 
 
391
 
/*
392
 
        ========================================================================
393
 
 
394
 
        Routine Description:
395
 
                Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
396
 
 
397
 
        Arguments:
398
 
                pRxD            Pointer to the Rx descriptor
399
 
 
400
 
        Return Value:
401
 
                NDIS_STATUS_SUCCESS     No err
402
 
                NDIS_STATUS_FAILURE     Error
403
 
 
404
 
        Note:
405
 
 
406
 
        ========================================================================
407
 
*/
408
 
NDIS_STATUS RTMPCheckRxError(
409
 
        IN      PRTMP_ADAPTER           pAd,
410
 
        IN      PHEADER_802_11          pHeader,
411
 
        IN      PRXWI_STRUC             pRxWI,
412
 
        IN  PRT28XX_RXD_STRUC   pRxD)
413
 
{
414
 
        PCIPHER_KEY pWpaKey;
415
 
        INT dBm;
416
 
 
417
 
        // Phy errors & CRC errors
418
 
        if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
419
 
        {
420
 
                // Check RSSI for Noise Hist statistic collection.
421
 
                dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
422
 
                if (dBm <= -87)
423
 
                        pAd->StaCfg.RPIDensity[0] += 1;
424
 
                else if (dBm <= -82)
425
 
                        pAd->StaCfg.RPIDensity[1] += 1;
426
 
                else if (dBm <= -77)
427
 
                        pAd->StaCfg.RPIDensity[2] += 1;
428
 
                else if (dBm <= -72)
429
 
                        pAd->StaCfg.RPIDensity[3] += 1;
430
 
                else if (dBm <= -67)
431
 
                        pAd->StaCfg.RPIDensity[4] += 1;
432
 
                else if (dBm <= -62)
433
 
                        pAd->StaCfg.RPIDensity[5] += 1;
434
 
                else if (dBm <= -57)
435
 
                        pAd->StaCfg.RPIDensity[6] += 1;
436
 
                else if (dBm > -57)
437
 
                        pAd->StaCfg.RPIDensity[7] += 1;
438
 
 
439
 
                return(NDIS_STATUS_FAILURE);
440
 
        }
441
 
 
442
 
        // Add Rx size to channel load counter, we should ignore error counts
443
 
        pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
444
 
 
445
 
        // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
446
 
        if (pHeader != NULL)
447
 
        {
448
 
                if (pHeader->FC.ToDs)
449
 
                {
450
 
                        return(NDIS_STATUS_FAILURE);
451
 
                }
452
 
        }
453
 
 
454
 
        // Drop not U2M frames, cant's drop here because we will drop beacon in this case
455
 
        // I am kind of doubting the U2M bit operation
456
 
        // if (pRxD->U2M == 0)
457
 
        //      return(NDIS_STATUS_FAILURE);
458
 
 
459
 
        // drop decyption fail frame
460
 
        if (pRxD->CipherErr)
461
 
        {
462
 
                if (pRxD->CipherErr == 2)
463
 
                        {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
464
 
                else if (pRxD->CipherErr == 1)
465
 
                        {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
466
 
                else if (pRxD->CipherErr == 3)
467
 
                        DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
468
 
 
469
 
        if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
470
 
            RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
471
 
 
472
 
                DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
473
 
                        pRxD->CipherErr,
474
 
                        pRxD->SDL0,
475
 
                        pRxD->Mcast | pRxD->Bcast,
476
 
                        pRxD->MyBss,
477
 
                        pRxWI->WirelessCliID,
478
 
                        pRxWI->KeyIndex));
479
 
 
480
 
                //
481
 
                // MIC Error
482
 
                //
483
 
                if (pRxD->CipherErr == 2)
484
 
                {
485
 
                        pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
486
 
 
487
 
            if (pAd->StaCfg.WpaSupplicantUP)
488
 
                WpaSendMicFailureToWpaSupplicant(pAd,
489
 
                                   (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
490
 
            else
491
 
                            RTMPReportMicError(pAd, pWpaKey);
492
 
 
493
 
            if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
494
 
                RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
495
 
 
496
 
                        DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
497
 
                }
498
 
 
499
 
                if (pHeader == NULL)
500
 
                        return(NDIS_STATUS_SUCCESS);
501
 
 
502
 
                return(NDIS_STATUS_FAILURE);
503
 
        }
504
 
 
505
 
        return(NDIS_STATUS_SUCCESS);
506
 
}
507
 
 
508
 
/*
509
 
        ==========================================================================
510
 
        Description:
511
 
                This routine sends command to firmware and turn our chip to power save mode.
512
 
                Both RadioOff and .11 power save function needs to call this routine.
513
 
        Input:
514
 
                Level = GUIRADIO_OFF  : GUI Radio Off mode
515
 
                Level = DOT11POWERSAVE  : 802.11 power save mode
516
 
                Level = RTMP_HALT  : When Disable device.
517
 
 
518
 
        ==========================================================================
519
 
 */
520
 
VOID RT28xxPciAsicRadioOff(
521
 
        IN PRTMP_ADAPTER    pAd,
522
 
        IN UCHAR            Level,
523
 
        IN USHORT           TbttNumToNextWakeUp)
524
 
{
525
 
        WPDMA_GLO_CFG_STRUC     DmaCfg;
526
 
        UCHAR           i, tempBBP_R3 = 0;
527
 
        BOOLEAN         brc = FALSE, Cancelled;
528
 
    UINT32              TbTTTime = 0;
529
 
        UINT32          PsPollTime = 0, MACValue;
530
 
    ULONG               BeaconPeriodTime;
531
 
    UINT32              RxDmaIdx, RxCpuIdx;
532
 
        DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
533
 
 
534
 
    // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
535
 
        RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
536
 
        RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
537
 
        if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
538
 
        {
539
 
                DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d ,  RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
540
 
                return;
541
 
        }
542
 
        else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
543
 
        {
544
 
                DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2.  RxCpuIdx = %d. RxDmaIdx = %d ,  \n", RxCpuIdx, RxDmaIdx));
545
 
                return;
546
 
        }
547
 
 
548
 
    // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
549
 
        RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
550
 
 
551
 
        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
552
 
        {
553
 
            RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
554
 
            RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
555
 
 
556
 
            if (Level == DOT11POWERSAVE)
557
 
                {
558
 
                        RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
559
 
                        TbTTTime &= 0x1ffff;
560
 
                        // 00. check if need to do sleep in this DTIM period.   If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
561
 
                        // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
562
 
                if  (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
563
 
                        {
564
 
                                DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
565
 
                    OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
566
 
                                RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
567
 
                                return;
568
 
                        }
569
 
                        else
570
 
                        {
571
 
                                PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
572
 
                                PsPollTime -= 3;
573
 
 
574
 
                    BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
575
 
                                if (TbttNumToNextWakeUp > 0)
576
 
                                        PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
577
 
 
578
 
                    pAd->Mlme.bPsPollTimerRunning = TRUE;
579
 
                                RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
580
 
                        }
581
 
                }
582
 
        }
583
 
 
584
 
    // 0. Disable Tx DMA.
585
 
        RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
586
 
        DmaCfg.field.EnableTxDMA = 0;
587
 
        RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
588
 
 
589
 
        // 1. Wait DMA not busy
590
 
        i = 0;
591
 
        do
592
 
        {
593
 
                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
594
 
                if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0))
595
 
                        break;
596
 
                RTMPusecDelay(20);
597
 
                i++;
598
 
        }while(i < 50);
599
 
 
600
 
        if (i >= 50)
601
 
        {
602
 
                DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy.  return on RT28xxPciAsicRadioOff ()\n"));
603
 
                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
604
 
                DmaCfg.field.EnableTxDMA = 1;
605
 
                RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
606
 
                pAd->CheckDmaBusyCount++;
607
 
                return;
608
 
        }
609
 
        else
610
 
        {
611
 
                pAd->CheckDmaBusyCount = 0;
612
 
        }
613
 
 
614
 
    RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
615
 
 
616
 
    // Set to 1R.
617
 
        if (pAd->Antenna.field.RxPath > 1)
618
 
        {
619
 
                tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
620
 
                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
621
 
        }
622
 
 
623
 
        // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
624
 
        if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
625
 
                && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
626
 
        {
627
 
                // Must using 40MHz.
628
 
                AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
629
 
        }
630
 
        else
631
 
        {
632
 
                // Must using 20MHz.
633
 
                AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
634
 
        }
635
 
 
636
 
        if (Level != RTMP_HALT)
637
 
        {
638
 
                // Change Interrupt bitmask.
639
 
                RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
640
 
        }
641
 
        else
642
 
        {
643
 
                NICDisableInterrupt(pAd);
644
 
        }
645
 
 
646
 
    RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
647
 
        // Disable MAC Rx
648
 
        RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
649
 
        MACValue &= 0xf7;
650
 
        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
651
 
 
652
 
        //  2. Send Sleep command
653
 
        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
654
 
        RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
655
 
        // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power
656
 
        AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1);
657
 
        //  2-1. Wait command success
658
 
        // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
659
 
        brc = AsicCheckCommanOk(pAd, PowerSafeCID);
660
 
 
661
 
    if (brc == FALSE)
662
 
    {
663
 
        // try again
664
 
        AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x01);   // send POWER-SAVE command to MCU. Timeout unit:40us.
665
 
        //RTMPusecDelay(200);
666
 
        brc = AsicCheckCommanOk(pAd, PowerSafeCID);
667
 
    }
668
 
 
669
 
        //  3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
670
 
        // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
671
 
        if ((Level == DOT11POWERSAVE) && (brc == TRUE))
672
 
        {
673
 
                AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00);     // lowbyte = 0 means to do power safe, NOT turn off radio.
674
 
                //  3-1. Wait command success
675
 
                AsicCheckCommanOk(pAd, PowerRadioOffCID);
676
 
        }
677
 
        else if (brc == TRUE)
678
 
        {
679
 
                AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00);     // lowbyte = 0 means to do power safe, NOT turn off radio.
680
 
                //  3-1. Wait command success
681
 
                AsicCheckCommanOk(pAd, PowerRadioOffCID);
682
 
        }
683
 
 
684
 
    // Wait DMA not busy
685
 
        i = 0;
686
 
        do
687
 
        {
688
 
                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
689
 
                if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0))
690
 
                        break;
691
 
                RTMPusecDelay(20);
692
 
                i++;
693
 
        }while(i < 50);
694
 
 
695
 
        if (i >= 50)
696
 
        {
697
 
                pAd->CheckDmaBusyCount++;
698
 
                DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy.  on RT28xxPciAsicRadioOff ()\n"));
699
 
        }
700
 
        else
701
 
        {
702
 
                pAd->CheckDmaBusyCount = 0;
703
 
        }
704
 
 
705
 
        if (Level == DOT11POWERSAVE)
706
 
        {
707
 
                AUTO_WAKEUP_STRUC       AutoWakeupCfg;
708
 
                //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
709
 
 
710
 
                // we have decided to SLEEP, so at least do it for a BEACON period.
711
 
                if (TbttNumToNextWakeUp == 0)
712
 
                        TbttNumToNextWakeUp = 1;
713
 
 
714
 
                AutoWakeupCfg.word = 0;
715
 
                RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
716
 
 
717
 
                // 1. Set auto wake up timer.
718
 
                AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
719
 
                AutoWakeupCfg.field.EnableAutoWakeup = 1;
720
 
                AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
721
 
                RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
722
 
        }
723
 
 
724
 
        //  4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
725
 
        if (Level == RTMP_HALT)
726
 
        {
727
 
                if ((brc == TRUE) && (i < 50))
728
 
                        RTMPPCIeLinkCtrlSetting(pAd, 0);
729
 
        }
730
 
        //  4. Set PCI configuration Space Link Comtrol fields.  Only Radio Off needs to call this function
731
 
        else
732
 
        {
733
 
                if ((brc == TRUE) && (i < 50))
734
 
                        RTMPPCIeLinkCtrlSetting(pAd, 3);
735
 
        }
736
 
 
737
 
        RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX);
738
 
}
739
 
 
740
 
 
741
 
/*
742
 
        ==========================================================================
743
 
        Description:
744
 
                This routine sends command to firmware and turn our chip to wake up mode from power save mode.
745
 
                Both RadioOn and .11 power save function needs to call this routine.
746
 
        Input:
747
 
                Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On.  Need to restore PCI host value.
748
 
                Level = other value : normal wake up function.
749
 
 
750
 
        ==========================================================================
751
 
 */
752
 
BOOLEAN RT28xxPciAsicRadioOn(
753
 
        IN PRTMP_ADAPTER pAd,
754
 
        IN UCHAR     Level)
755
 
{
756
 
    WPDMA_GLO_CFG_STRUC DmaCfg;
757
 
        BOOLEAN                         Cancelled, brv = TRUE;
758
 
    UINT32                          MACValue;
759
 
 
760
 
        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
761
 
        {
762
 
            pAd->Mlme.bPsPollTimerRunning = FALSE;
763
 
                RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
764
 
                if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)
765
 
                || (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)))
766
 
                {
767
 
                        DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
768
 
                        // 1. Set PCI Link Control in Configuration Space.
769
 
                        RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
770
 
                        RTMPusecDelay(6000);
771
 
                }
772
 
        }
773
 
 
774
 
    pAd->bPCIclkOff = FALSE;
775
 
        RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x3a80);
776
 
        // 2. Send wake up command.
777
 
        AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
778
 
 
779
 
        // 2-1. wait command ok.
780
 
        brv = AsicCheckCommanOk(pAd, PowerWakeCID);
781
 
    if (brv)
782
 
    {
783
 
        NICEnableInterrupt(pAd);
784
 
 
785
 
        // 3. Enable Tx DMA.
786
 
        RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
787
 
        DmaCfg.field.EnableTxDMA = 1;
788
 
        DmaCfg.field.EnableRxDMA = 1;
789
 
        RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
790
 
 
791
 
        // Eable MAC Rx
792
 
        RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
793
 
        MACValue |= 0x8;
794
 
        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
795
 
 
796
 
        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
797
 
        if (Level == GUI_IDLE_POWER_SAVE)
798
 
        {
799
 
                // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
800
 
                if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
801
 
                        && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
802
 
                {
803
 
                        // Must using 40MHz.
804
 
                        AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
805
 
                        AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
806
 
                }
807
 
                else
808
 
                {
809
 
                        // Must using 20MHz.
810
 
                        AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
811
 
                        AsicLockChannel(pAd, pAd->CommonCfg.Channel);
812
 
                }
813
 
        }
814
 
        return TRUE;
815
 
    }
816
 
    else
817
 
        return FALSE;
818
 
}
819
 
 
820
 
VOID RT28xxPciStaAsicForceWakeup(
821
 
        IN PRTMP_ADAPTER pAd,
822
 
        IN UCHAR         Level)
823
 
{
824
 
    AUTO_WAKEUP_STRUC   AutoWakeupCfg;
825
 
 
826
 
    if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
827
 
    {
828
 
        DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
829
 
        return;
830
 
    }
831
 
 
832
 
    OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
833
 
        RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
834
 
 
835
 
    if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
836
 
    {
837
 
        // Support PCIe Advance Power Save
838
 
        if (((Level == FROM_TX) && (pAd->Mlme.bPsPollTimerRunning == TRUE)) ||
839
 
                        (Level == RTMP_HALT))
840
 
        {
841
 
            pAd->Mlme.bPsPollTimerRunning = FALSE;
842
 
                RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
843
 
                RTMPusecDelay(5000);
844
 
            DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
845
 
        }
846
 
 
847
 
                AutoWakeupCfg.word = 0;
848
 
                RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
849
 
 
850
 
                // If this is called from Halt. ALWAYS force wakeup!!!
851
 
                if (Level == RTMP_HALT)
852
 
                {
853
 
                        RT28xxPciAsicRadioOn(pAd, RTMP_HALT);
854
 
                }
855
 
                else
856
 
                {
857
 
                        if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
858
 
                        {
859
 
                                // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
860
 
                                if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
861
 
                                        && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
862
 
                                {
863
 
                                        // Must using 40MHz.
864
 
                                        AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
865
 
                                        AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
866
 
                                }
867
 
                                else
868
 
                                {
869
 
                                        // Must using 20MHz.
870
 
                                        AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
871
 
                                        AsicLockChannel(pAd, pAd->CommonCfg.Channel);
872
 
                                }
873
 
                        }
874
 
                }
875
 
    }
876
 
    else
877
 
    {
878
 
        // PCI, 2860-PCIe
879
 
        AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
880
 
                AutoWakeupCfg.word = 0;
881
 
                RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
882
 
    }
883
 
 
884
 
    OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
885
 
    OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
886
 
    DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
887
 
}
888
 
 
889
 
VOID RT28xxPciStaAsicSleepThenAutoWakeup(
890
 
        IN PRTMP_ADAPTER pAd,
891
 
        IN USHORT TbttNumToNextWakeUp)
892
 
{
893
 
    if (pAd->StaCfg.bRadio == FALSE)
894
 
        {
895
 
                OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
896
 
                return;
897
 
        }
898
 
    if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
899
 
    {
900
 
        ULONG   Now = 0;
901
 
        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
902
 
        {
903
 
            DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
904
 
            OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
905
 
            return;
906
 
        }
907
 
 
908
 
                NdisGetSystemUpTime(&Now);
909
 
                // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
910
 
                // Because Some AP can't queuing outgoing frames immediately.
911
 
                if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
912
 
                {
913
 
                        DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu :  RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
914
 
                        return;
915
 
                }
916
 
                else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
917
 
                {
918
 
                        DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime,  pAd->RalinkCounters.RxCountSinceLastNULL));
919
 
                        return;
920
 
                }
921
 
 
922
 
        RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
923
 
    }
924
 
    else
925
 
    {
926
 
        AUTO_WAKEUP_STRUC       AutoWakeupCfg;
927
 
        // we have decided to SLEEP, so at least do it for a BEACON period.
928
 
        if (TbttNumToNextWakeUp == 0)
929
 
            TbttNumToNextWakeUp = 1;
930
 
 
931
 
        AutoWakeupCfg.word = 0;
932
 
        RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
933
 
        AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
934
 
        AutoWakeupCfg.field.EnableAutoWakeup = 1;
935
 
        AutoWakeupCfg.field.AutoLeadTime = 5;
936
 
        RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
937
 
        AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00);   // send POWER-SAVE command to MCU. Timeout 40us.
938
 
        DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, TbttNumToNextWakeUp));
939
 
    }
940
 
    OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
941
 
}
942
 
 
943
 
VOID PsPollWakeExec(
944
 
        IN PVOID SystemSpecific1,
945
 
        IN PVOID FunctionContext,
946
 
        IN PVOID SystemSpecific2,
947
 
        IN PVOID SystemSpecific3)
948
 
{
949
 
        RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
950
 
        unsigned long flags;
951
 
 
952
 
    DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
953
 
        RTMP_INT_LOCK(&pAd->irq_lock, flags);
954
 
    if (pAd->Mlme.bPsPollTimerRunning)
955
 
    {
956
 
            RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
957
 
    }
958
 
    pAd->Mlme.bPsPollTimerRunning = FALSE;
959
 
        RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
960
 
}
961
 
 
962
 
VOID  RadioOnExec(
963
 
        IN PVOID SystemSpecific1,
964
 
        IN PVOID FunctionContext,
965
 
        IN PVOID SystemSpecific2,
966
 
        IN PVOID SystemSpecific3)
967
 
{
968
 
        RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
969
 
        WPDMA_GLO_CFG_STRUC     DmaCfg;
970
 
        BOOLEAN                         Cancelled;
971
 
 
972
 
        if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
973
 
        {
974
 
                DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
975
 
                RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
976
 
                return;
977
 
        }
978
 
 
979
 
        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
980
 
        {
981
 
                DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
982
 
                RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
983
 
                return;
984
 
        }
985
 
    pAd->Mlme.bPsPollTimerRunning = FALSE;
986
 
        RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
987
 
        if (pAd->StaCfg.bRadio == TRUE)
988
 
        {
989
 
                pAd->bPCIclkOff = FALSE;
990
 
        RTMPRingCleanUp(pAd, QID_AC_BK);
991
 
                RTMPRingCleanUp(pAd, QID_AC_BE);
992
 
                RTMPRingCleanUp(pAd, QID_AC_VI);
993
 
                RTMPRingCleanUp(pAd, QID_AC_VO);
994
 
                RTMPRingCleanUp(pAd, QID_HCCA);
995
 
                RTMPRingCleanUp(pAd, QID_MGMT);
996
 
                RTMPRingCleanUp(pAd, QID_RX);
997
 
 
998
 
                // 2. Send wake up command.
999
 
                AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
1000
 
                // 2-1. wait command ok.
1001
 
                AsicCheckCommanOk(pAd, PowerWakeCID);
1002
 
 
1003
 
                // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
1004
 
                NICEnableInterrupt(pAd);
1005
 
 
1006
 
                // 3. Enable Tx DMA.
1007
 
                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
1008
 
                DmaCfg.field.EnableTxDMA = 1;
1009
 
                RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
1010
 
 
1011
 
                // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
1012
 
                if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
1013
 
                        && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1014
 
                {
1015
 
                        // Must using 40MHz.
1016
 
                        AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1017
 
                        AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1018
 
                }
1019
 
                else
1020
 
                {
1021
 
                        // Must using 20MHz.
1022
 
                        AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1023
 
                        AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1024
 
                }
1025
 
 
1026
 
                // Clear Radio off flag
1027
 
                RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1028
 
 
1029
 
                // Set LED
1030
 
                RTMPSetLED(pAd, LED_RADIO_ON);
1031
 
 
1032
 
        if (pAd->StaCfg.Psm == PWR_ACTIVE)
1033
 
        {
1034
 
                RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1035
 
        }
1036
 
        }
1037
 
        else
1038
 
        {
1039
 
                RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
1040
 
        }
1041
 
}
1042
 
 
1043
 
VOID RT28xxPciMlmeRadioOn(
1044
 
        IN PRTMP_ADAPTER pAd)
1045
 
{
1046
 
    if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1047
 
                return;
1048
 
 
1049
 
    DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1050
 
 
1051
 
    if ((pAd->OpMode == OPMODE_AP) ||
1052
 
        ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))))
1053
 
    {
1054
 
        NICResetFromError(pAd);
1055
 
 
1056
 
        /*
1057
 
        RTMPRingCleanUp(pAd, QID_AC_BK);
1058
 
        RTMPRingCleanUp(pAd, QID_AC_BE);
1059
 
        RTMPRingCleanUp(pAd, QID_AC_VI);
1060
 
        RTMPRingCleanUp(pAd, QID_AC_VO);
1061
 
        RTMPRingCleanUp(pAd, QID_HCCA);
1062
 
        RTMPRingCleanUp(pAd, QID_MGMT);
1063
 
        RTMPRingCleanUp(pAd, QID_RX);
1064
 
                */
1065
 
 
1066
 
        // Enable Tx/Rx
1067
 
        RTMPEnableRxTx(pAd);
1068
 
 
1069
 
        // Clear Radio off flag
1070
 
        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1071
 
 
1072
 
            // Set LED
1073
 
            RTMPSetLED(pAd, LED_RADIO_ON);
1074
 
    }
1075
 
 
1076
 
    if ((pAd->OpMode == OPMODE_STA) &&
1077
 
        (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))
1078
 
    {
1079
 
        BOOLEAN         Cancelled;
1080
 
 
1081
 
        RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
1082
 
 
1083
 
        pAd->Mlme.bPsPollTimerRunning = FALSE;
1084
 
        RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1085
 
        RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1086
 
        RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
1087
 
    }
1088
 
}
1089
 
 
1090
 
VOID RT28xxPciMlmeRadioOFF(
1091
 
        IN PRTMP_ADAPTER pAd)
1092
 
{
1093
 
    WPDMA_GLO_CFG_STRUC GloCfg;
1094
 
        UINT32  i;
1095
 
 
1096
 
        if (pAd->StaCfg.bRadio == TRUE)
1097
 
        {
1098
 
                DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n"));
1099
 
                return;
1100
 
        }
1101
 
 
1102
 
    if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
1103
 
        return;
1104
 
 
1105
 
    DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
1106
 
 
1107
 
        // Set LED
1108
 
        RTMPSetLED(pAd, LED_RADIO_OFF);
1109
 
 
1110
 
    {
1111
 
        BOOLEAN         Cancelled;
1112
 
 
1113
 
        if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1114
 
        {
1115
 
                        RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
1116
 
                        RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1117
 
        }
1118
 
 
1119
 
                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1120
 
        {
1121
 
            BOOLEAN Cancelled;
1122
 
 
1123
 
                        // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF).
1124
 
                        if ((pAd->OpMode == OPMODE_STA) && 
1125
 
                             (IDLE_ON(pAd)) && 
1126
 
                             (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1127
 
                        {
1128
 
                                RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
1129
 
                        }
1130
 
 
1131
 
            pAd->Mlme.bPsPollTimerRunning = FALSE;
1132
 
            RTMPCancelTimer(&pAd->Mlme.PsPollTimer,     &Cancelled);
1133
 
                RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer,     &Cancelled);
1134
 
        }
1135
 
 
1136
 
        // Link down first if any association exists
1137
 
        if (INFRA_ON(pAd) || ADHOC_ON(pAd))
1138
 
            LinkDown(pAd, FALSE);
1139
 
        RTMPusecDelay(10000);
1140
 
        //==========================================
1141
 
        // Clean up old bss table
1142
 
        BssTableInit(&pAd->ScanTab);
1143
 
 
1144
 
                RTMPRingCleanUp(pAd, QID_AC_BK);
1145
 
        RTMPRingCleanUp(pAd, QID_AC_BE);
1146
 
        RTMPRingCleanUp(pAd, QID_AC_VI);
1147
 
        RTMPRingCleanUp(pAd, QID_AC_VO);
1148
 
        RTMPRingCleanUp(pAd, QID_HCCA);
1149
 
        RTMPRingCleanUp(pAd, QID_MGMT);
1150
 
        RTMPRingCleanUp(pAd, QID_RX);
1151
 
 
1152
 
                if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1153
 
                {
1154
 
                        RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 500);
1155
 
                        return;
1156
 
                }
1157
 
    }
1158
 
 
1159
 
        // Set Radio off flag
1160
 
        RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
1161
 
 
1162
 
        // Disable Tx/Rx DMA
1163
 
        RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);          // disable DMA
1164
 
        GloCfg.field.EnableTxDMA = 0;
1165
 
        GloCfg.field.EnableRxDMA = 0;
1166
 
        RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);          // abort all TX rings
1167
 
 
1168
 
 
1169
 
        // MAC_SYS_CTRL => value = 0x0 => 40mA
1170
 
        RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
1171
 
 
1172
 
        // PWR_PIN_CFG => value = 0x0 => 40mA
1173
 
        RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
1174
 
 
1175
 
        // TX_PIN_CFG => value = 0x0 => 20mA
1176
 
        RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
1177
 
 
1178
 
        if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1179
 
        {
1180
 
                // Must using 40MHz.
1181
 
                AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
1182
 
        }
1183
 
        else
1184
 
        {
1185
 
                // Must using 20MHz.
1186
 
                AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
1187
 
        }
1188
 
 
1189
 
        // Waiting for DMA idle
1190
 
        i = 0;
1191
 
        do
1192
 
        {
1193
 
                RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1194
 
                if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1195
 
                        break;
1196
 
 
1197
 
                RTMPusecDelay(1000);
1198
 
        }while (i++ < 100);
1199
 
}