e9739b45ba373cf2e7d4f50f5375d55a561b5b55
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / cmm_data_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 /*
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
36 USHORT RtmpPCI_WriteTxResource(
37         IN      PRTMP_ADAPTER   pAd,
38         IN      TX_BLK                  *pTxBlk,
39         IN      BOOLEAN                 bIsLast,
40         OUT     USHORT                  *FreeNumber)
41 {
42
43         UCHAR                   *pDMAHeaderBufVA;
44         USHORT                  TxIdx, RetTxIdx;
45         PTXD_STRUC              pTxD;
46         UINT32                  BufBasePaLow;
47         PRTMP_TX_RING   pTxRing;
48         USHORT                  hwHeaderLen;
49
50         //
51         // get Tx Ring Resource
52         //
53         pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
54         TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
55         pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
56         BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
57
58         // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
59         if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
60         {
61                 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
62                 hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
63         }
64         else
65         {
66                 //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
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 = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
127         hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
128
129         NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
130
131         pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
132         pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
133
134         //
135         // build Tx Descriptor
136         //
137         pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
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         NdisZeroMemory(pTxD, TXD_SIZE);
217
218         pTxD->SDPtr0 = BufBasePaLow;
219         pTxD->SDLen0 = firstDMALen; // include padding
220         pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
221         pTxD->SDLen1 = pTxBlk->SrcBufLen;
222         pTxD->LastSec0 = 0;
223         pTxD->LastSec1 = (bIsLast) ? 1 : 0;
224
225         RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
226
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
262 VOID RtmpPCIDataLastTxIdx(
263         IN      PRTMP_ADAPTER   pAd,
264         IN      UCHAR                   QueIdx,
265         IN      USHORT                  LastTxIdx)
266 {
267         PTXD_STRUC              pTxD;
268         PRTMP_TX_RING   pTxRing;
269
270         //
271         // get Tx Ring Resource
272         //
273         pTxRing = &pAd->TxRing[QueIdx];
274
275         //
276         // build Tx Descriptor
277         //
278         pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
279
280         pTxD->LastSec1 = 1;
281
282
283 }
284
285
286 USHORT  RtmpPCI_WriteFragTxResource(
287         IN      PRTMP_ADAPTER   pAd,
288         IN      TX_BLK                  *pTxBlk,
289         IN      UCHAR                   fragNum,
290         OUT     USHORT                  *FreeNumber)
291 {
292         UCHAR                   *pDMAHeaderBufVA;
293         USHORT                  TxIdx, RetTxIdx;
294         PTXD_STRUC              pTxD;
295         UINT32                  BufBasePaLow;
296         PRTMP_TX_RING   pTxRing;
297         USHORT                  hwHeaderLen;
298         UINT32                  firstDMALen;
299
300         //
301         // Get Tx Ring Resource
302         //
303         pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
304         TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
305         pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
306         BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
307
308         //
309         // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
310         //
311         //hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
312         hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
313
314         firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
315         NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
316
317
318         //
319         // Build Tx Descriptor
320         //
321         pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
322         NdisZeroMemory(pTxD, TXD_SIZE);
323
324         if (fragNum == pTxBlk->TotalFragNum)
325         {
326                 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
327                 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
328         }
329
330         pTxD->SDPtr0 = BufBasePaLow;
331         pTxD->SDLen0 = firstDMALen; // include padding
332         pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
333         pTxD->SDLen1 = pTxBlk->SrcBufLen;
334         pTxD->LastSec0 = 0;
335         pTxD->LastSec1 = 1;
336
337         RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
338
339
340         RetTxIdx = TxIdx;
341         pTxBlk->Priv += pTxBlk->SrcBufLen;
342
343         //
344         // Update Tx index
345         //
346         INC_RING_INDEX(TxIdx, TX_RING_SIZE);
347         pTxRing->TxCpuIdx = TxIdx;
348
349         *FreeNumber -= 1;
350
351         return RetTxIdx;
352
353 }
354
355
356 /*
357         Must be run in Interrupt context
358         This function handle PCI specific TxDesc and cpu index update and kick the packet out.
359  */
360 int RtmpPCIMgmtKickOut(
361         IN RTMP_ADAPTER         *pAd,
362         IN UCHAR                        QueIdx,
363         IN PNDIS_PACKET         pPacket,
364         IN PUCHAR                       pSrcBufVA,
365         IN UINT                         SrcBufLen)
366 {
367         PTXD_STRUC              pTxD;
368         ULONG                   SwIdx = pAd->MgmtRing.TxCpuIdx;
369
370         pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
371
372         pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
373         pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
374
375         RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
376         pTxD->LastSec0 = 1;
377         pTxD->LastSec1 = 1;
378         pTxD->DMADONE = 0;
379         pTxD->SDLen1 = 0;
380         pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
381         pTxD->SDLen0 = SrcBufLen;
382
383
384 //==================================================================
385 /*      DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n"));
386         for (i = 0; i < (TXWI_SIZE+24); i++)
387         {
388
389                 DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i)));
390                 if ( i%4 == 3)
391                         DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: "));
392                 if ( i%16 == 15)
393                         DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n      "));
394         }
395         DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n      "));*/
396 //=======================================================================
397
398         pAd->RalinkCounters.KickTxCount++;
399         pAd->RalinkCounters.OneSecTxDoneCount++;
400
401         // Increase TX_CTX_IDX, but write to register later.
402         INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
403
404         RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX,  pAd->MgmtRing.TxCpuIdx);
405
406         return 0;
407 }
408
409
410 /*
411         ========================================================================
412
413         Routine Description:
414                 Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
415
416         Arguments:
417                 pRxD            Pointer to the Rx descriptor
418
419         Return Value:
420                 NDIS_STATUS_SUCCESS     No err
421                 NDIS_STATUS_FAILURE     Error
422
423         Note:
424
425         ========================================================================
426 */
427 NDIS_STATUS RTMPCheckRxError(
428         IN      PRTMP_ADAPTER           pAd,
429         IN      PHEADER_802_11          pHeader,
430         IN      PRXWI_STRUC             pRxWI,
431         IN  PRT28XX_RXD_STRUC   pRxD)
432 {
433         PCIPHER_KEY pWpaKey;
434         INT dBm;
435
436         // Phy errors & CRC errors
437         if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
438         {
439                 // Check RSSI for Noise Hist statistic collection.
440                 dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
441                 if (dBm <= -87)
442                         pAd->StaCfg.RPIDensity[0] += 1;
443                 else if (dBm <= -82)
444                         pAd->StaCfg.RPIDensity[1] += 1;
445                 else if (dBm <= -77)
446                         pAd->StaCfg.RPIDensity[2] += 1;
447                 else if (dBm <= -72)
448                         pAd->StaCfg.RPIDensity[3] += 1;
449                 else if (dBm <= -67)
450                         pAd->StaCfg.RPIDensity[4] += 1;
451                 else if (dBm <= -62)
452                         pAd->StaCfg.RPIDensity[5] += 1;
453                 else if (dBm <= -57)
454                         pAd->StaCfg.RPIDensity[6] += 1;
455                 else if (dBm > -57)
456                         pAd->StaCfg.RPIDensity[7] += 1;
457
458                 return(NDIS_STATUS_FAILURE);
459         }
460
461         // Add Rx size to channel load counter, we should ignore error counts
462         pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
463
464         // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
465         if (pHeader != NULL)
466         {
467                 if (pHeader->FC.ToDs)
468                 {
469                         return(NDIS_STATUS_FAILURE);
470                 }
471         }
472
473         // Drop not U2M frames, cant's drop here because we will drop beacon in this case
474         // I am kind of doubting the U2M bit operation
475         // if (pRxD->U2M == 0)
476         //      return(NDIS_STATUS_FAILURE);
477
478         // drop decyption fail frame
479         if (pRxD->CipherErr)
480         {
481                 if (pRxD->CipherErr == 2)
482                         {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
483                 else if (pRxD->CipherErr == 1)
484                         {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
485                 else if (pRxD->CipherErr == 3)
486                         DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
487
488         if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
489             RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
490
491                 DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
492                         pRxD->CipherErr,
493                         pRxD->SDL0,
494                         pRxD->Mcast | pRxD->Bcast,
495                         pRxD->MyBss,
496                         pRxWI->WirelessCliID,
497 //                      CipherName[pRxD->CipherAlg],
498                         pRxWI->KeyIndex));
499
500                 //
501                 // MIC Error
502                 //
503                 if (pRxD->CipherErr == 2)
504                 {
505                         pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
506             if (pAd->StaCfg.WpaSupplicantUP)
507                 WpaSendMicFailureToWpaSupplicant(pAd,
508                                    (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
509             else
510                             RTMPReportMicError(pAd, pWpaKey);
511
512             if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
513                 RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
514
515                         DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
516                 }
517
518                 if (pHeader == NULL)
519                         return(NDIS_STATUS_SUCCESS);
520                 /*if ((pRxD->CipherAlg == CIPHER_AES) &&
521                         (pHeader->Sequence == pAd->FragFrame.Sequence))
522                 {
523                         //
524                         // Acceptable since the First FragFrame no CipherErr problem.
525                         //
526                         return(NDIS_STATUS_SUCCESS);
527                 }*/
528
529                 return(NDIS_STATUS_FAILURE);
530         }
531
532         return(NDIS_STATUS_SUCCESS);
533 }
534
535
536 BOOLEAN  RTMPFreeTXDUponTxDmaDone(
537         IN PRTMP_ADAPTER        pAd,
538         IN UCHAR                        QueIdx)
539 {
540         PRTMP_TX_RING pTxRing;
541         PTXD_STRUC        pTxD;
542         PNDIS_PACKET  pPacket;
543         UCHAR   FREE = 0;
544         TXD_STRUC       TxD, *pOriTxD;
545         //ULONG         IrqFlags;
546         BOOLEAN                 bReschedule = FALSE;
547
548
549         ASSERT(QueIdx < NUM_OF_TX_RING);
550         pTxRing = &pAd->TxRing[QueIdx];
551
552         RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
553         while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
554         {
555 //              RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
556
557                 // static rate also need NICUpdateFifoStaCounters() function.
558                 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
559                         NICUpdateFifoStaCounters(pAd);
560
561                 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
562                 FREE++;
563                 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
564                 pOriTxD = pTxD;
565                 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
566                 pTxD = &TxD;
567
568                 pTxD->DMADONE = 0;
569
570
571                 {
572                         pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
573                         if (pPacket)
574                         {
575                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
576                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
577                         }
578                         //Always assign pNdisPacket as NULL after clear
579                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
580
581                         pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
582
583                         ASSERT(pPacket == NULL);
584                         if (pPacket)
585                         {
586                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
587                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
588                         }
589                         //Always assign pNextNdisPacket as NULL after clear
590                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
591                 }
592
593                 pAd->RalinkCounters.TransmittedByteCount +=  (pTxD->SDLen1 + pTxD->SDLen0);
594                 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
595                 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
596                 /* get tx_tdx_idx again */
597                 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF ,  &pTxRing->TxDmaIdx);
598         NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
599
600 //         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
601         }
602
603
604         return  bReschedule;
605
606 }
607
608
609 /*
610         ========================================================================
611
612         Routine Description:
613                 Process TX Rings DMA Done interrupt, running in DPC level
614
615         Arguments:
616                 Adapter         Pointer to our adapter
617
618         Return Value:
619                 None
620
621         IRQL = DISPATCH_LEVEL
622
623         ========================================================================
624 */
625 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
626         IN      PRTMP_ADAPTER   pAd,
627         IN      INT_SOURCE_CSR_STRUC TxRingBitmap)
628 {
629 //      UCHAR                   Count = 0;
630     unsigned long       IrqFlags;
631         BOOLEAN                 bReschedule = FALSE;
632
633         // Make sure Tx ring resource won't be used by other threads
634         //NdisAcquireSpinLock(&pAd->TxRingLock);
635
636         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
637
638         if (TxRingBitmap.field.Ac0DmaDone)
639                 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
640
641         if (TxRingBitmap.field.Ac3DmaDone)
642                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
643
644         if (TxRingBitmap.field.Ac2DmaDone)
645                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
646
647         if (TxRingBitmap.field.Ac1DmaDone)
648                 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
649
650         // Make sure to release Tx ring resource
651         //NdisReleaseSpinLock(&pAd->TxRingLock);
652         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
653
654         // Dequeue outgoing frames from TxSwQueue[] and process it
655         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
656
657         return  bReschedule;
658 }
659
660
661 /*
662         ========================================================================
663
664         Routine Description:
665                 Process MGMT ring DMA done interrupt, running in DPC level
666
667         Arguments:
668                 pAd     Pointer to our adapter
669
670         Return Value:
671                 None
672
673         IRQL = DISPATCH_LEVEL
674
675         Note:
676
677         ========================================================================
678 */
679 VOID    RTMPHandleMgmtRingDmaDoneInterrupt(
680         IN      PRTMP_ADAPTER   pAd)
681 {
682         PTXD_STRUC       pTxD;
683         PNDIS_PACKET pPacket;
684 //      int              i;
685         UCHAR   FREE = 0;
686         PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
687
688         NdisAcquireSpinLock(&pAd->MgmtRingLock);
689
690         RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
691         while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
692         {
693                 FREE++;
694                 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
695                 pTxD->DMADONE = 0;
696                 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
697
698
699                 if (pPacket)
700                 {
701                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
702                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
703                 }
704                 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
705
706                 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
707                 if (pPacket)
708                 {
709                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
710                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
711                 }
712                 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
713                 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
714
715         }
716         NdisReleaseSpinLock(&pAd->MgmtRingLock);
717
718 }
719
720
721 /*
722         ========================================================================
723
724         Routine Description:
725         Arguments:
726                 Adapter         Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
727
728         IRQL = DISPATCH_LEVEL
729
730         ========================================================================
731 */
732 VOID    RTMPHandleTBTTInterrupt(
733         IN PRTMP_ADAPTER pAd)
734 {
735         {
736                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
737                 {
738                 }
739         }
740 }
741
742
743 /*
744         ========================================================================
745
746         Routine Description:
747         Arguments:
748                 pAd             Pointer to our adapter. Rewrite beacon content before next send-out.
749
750         IRQL = DISPATCH_LEVEL
751
752         ========================================================================
753 */
754 VOID    RTMPHandlePreTBTTInterrupt(
755         IN PRTMP_ADAPTER pAd)
756 {
757         {
758                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
759                 {
760                         DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
761                 }
762         }
763
764
765 }
766
767 VOID    RTMPHandleRxCoherentInterrupt(
768         IN      PRTMP_ADAPTER   pAd)
769 {
770         WPDMA_GLO_CFG_STRUC     GloCfg;
771
772         if (pAd == NULL)
773         {
774                 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
775                 return;
776         }
777
778         DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
779
780         RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
781
782         GloCfg.field.EnTXWriteBackDDONE = 0;
783         GloCfg.field.EnableRxDMA = 0;
784         GloCfg.field.EnableTxDMA = 0;
785         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
786
787         RTMPRingCleanUp(pAd, QID_AC_BE);
788         RTMPRingCleanUp(pAd, QID_AC_BK);
789         RTMPRingCleanUp(pAd, QID_AC_VI);
790         RTMPRingCleanUp(pAd, QID_AC_VO);
791         RTMPRingCleanUp(pAd, QID_MGMT);
792         RTMPRingCleanUp(pAd, QID_RX);
793
794         RTMPEnableRxTx(pAd);
795
796         DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
797 }
798
799 PNDIS_PACKET GetPacketFromRxRing(
800         IN              PRTMP_ADAPTER   pAd,
801         OUT             PRT28XX_RXD_STRUC       pSaveRxD,
802         OUT             BOOLEAN                 *pbReschedule,
803         IN OUT  UINT32                  *pRxPending)
804 {
805         PRXD_STRUC                              pRxD;
806         PNDIS_PACKET                    pRxPacket = NULL;
807         PNDIS_PACKET                    pNewPacket;
808         PVOID                                   AllocVa;
809         NDIS_PHYSICAL_ADDRESS   AllocPa;
810         BOOLEAN                                 bReschedule = FALSE;
811         RTMP_DMACB                              *pRxCell;
812
813         RTMP_SEM_LOCK(&pAd->RxRingLock);
814
815         if (*pRxPending == 0)
816         {
817                 // Get how may packets had been received
818                 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
819
820                 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
821                 {
822                         // no more rx packets
823                         bReschedule = FALSE;
824                         goto done;
825                 }
826
827                 // get rx pending count
828                 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
829                         *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
830                 else
831                         *pRxPending     = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
832
833         }
834
835         pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx];
836
837         // Point to Rx indexed rx ring descriptor
838         pRxD = (PRXD_STRUC) pRxCell->AllocVa;
839
840         if (pRxD->DDONE == 0)
841         {
842                 *pRxPending = 0;
843                 // DMAIndx had done but DDONE bit not ready
844                 bReschedule = TRUE;
845                 goto done;
846         }
847
848
849         // return rx descriptor
850         NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
851
852         pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
853
854         if (pNewPacket)
855         {
856                 // unmap the rx buffer
857                 PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa,
858                                          pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
859                 pRxPacket = pRxCell->pNdisPacket;
860
861                 pRxCell->DmaBuf.AllocSize       = RX_BUFFER_AGGRESIZE;
862                 pRxCell->pNdisPacket            = (PNDIS_PACKET) pNewPacket;
863                 pRxCell->DmaBuf.AllocVa = AllocVa;
864                 pRxCell->DmaBuf.AllocPa = AllocPa;
865                 /* update SDP0 to new buffer of rx packet */
866                 pRxD->SDP0 = AllocPa;
867         }
868         else
869         {
870                 //DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n"));
871                 pRxPacket = NULL;
872                 bReschedule = TRUE;
873         }
874
875         pRxD->DDONE = 0;
876
877         // had handled one rx packet
878         *pRxPending = *pRxPending - 1;
879
880         // update rx descriptor and kick rx
881         INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
882
883         pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
884         RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
885
886 done:
887         RTMP_SEM_UNLOCK(&pAd->RxRingLock);
888         *pbReschedule = bReschedule;
889         return pRxPacket;
890 }
891
892
893 NDIS_STATUS MlmeHardTransmitTxRing(
894         IN      PRTMP_ADAPTER   pAd,
895         IN      UCHAR   QueIdx,
896         IN      PNDIS_PACKET    pPacket)
897 {
898         PACKET_INFO     PacketInfo;
899         PUCHAR                  pSrcBufVA;
900         UINT                    SrcBufLen;
901         PTXD_STRUC              pTxD;
902         PHEADER_802_11  pHeader_802_11;
903         BOOLEAN                 bAckRequired, bInsertTimestamp;
904         ULONG                   SrcBufPA;
905         //UCHAR                 TxBufIdx;
906         UCHAR                   MlmeRate;
907         ULONG                   SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
908         PTXWI_STRUC     pFirstTxWI;
909         //ULONG i;
910         //HTTRANSMIT_SETTING    MlmeTransmit;   //Rate for this MGMT frame.
911         ULONG    FreeNum;
912         MAC_TABLE_ENTRY *pMacEntry = NULL;
913
914
915         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
916
917
918         if (pSrcBufVA == NULL)
919         {
920                 // The buffer shouldn't be NULL
921                 return NDIS_STATUS_FAILURE;
922         }
923
924         // Make sure MGMT ring resource won't be used by other threads
925         //NdisAcquireSpinLock(&pAd->TxRingLock);
926
927         FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
928
929         if (FreeNum == 0)
930         {
931                 //NdisReleaseSpinLock(&pAd->TxRingLock);
932                 return NDIS_STATUS_FAILURE;
933         }
934
935         SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
936
937         pTxD  = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
938
939         if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
940         {
941                 DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n"));
942                 //NdisReleaseSpinLock(&pAd->TxRingLock);
943                 return NDIS_STATUS_FAILURE;
944         }
945
946         {
947                 // outgoing frame always wakeup PHY to prevent frame lost
948                 // if (pAd->StaCfg.Psm == PWR_SAVE)
949                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
950                         AsicForceWakeup(pAd, TRUE);
951         }
952         pFirstTxWI      =(PTXWI_STRUC)pSrcBufVA;
953
954         pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
955         if (pHeader_802_11->Addr1[0] & 0x01)
956         {
957                 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
958         }
959         else
960         {
961                 MlmeRate = pAd->CommonCfg.MlmeRate;
962         }
963
964         if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
965                 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
966         {
967                 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
968         }
969
970         // Verify Mlme rate for a / g bands.
971         if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
972                 MlmeRate = RATE_6;
973
974         //
975         // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
976         // Snice it's been set to 0 while on MgtMacHeaderInit
977         // By the way this will cause frame to be send on PWR_SAVE failed.
978         //
979         //
980         // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
981     // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
982         if (pHeader_802_11->FC.Type != BTYPE_DATA)
983     {
984         if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
985         {
986                 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
987         }
988         else
989         {
990                 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
991         }
992     }
993
994         bInsertTimestamp = FALSE;
995         if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
996         {
997                 bAckRequired = FALSE;
998         }
999         else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
1000         {
1001                 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
1002                 {
1003                         bAckRequired = FALSE;
1004                         pHeader_802_11->Duration = 0;
1005                 }
1006                 else
1007                 {
1008                         bAckRequired = TRUE;
1009                         pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
1010                         if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
1011                         {
1012                                 bInsertTimestamp = TRUE;
1013                         }
1014                 }
1015         }
1016         pHeader_802_11->Sequence = pAd->Sequence++;
1017         if (pAd->Sequence > 0xfff)
1018                 pAd->Sequence = 0;
1019         // Before radar detection done, mgmt frame can not be sent but probe req
1020         // Because we need to use probe req to trigger driver to send probe req in passive scan
1021         if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
1022                 && (pAd->CommonCfg.bIEEE80211H == 1)
1023                 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
1024         {
1025                 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
1026                 //NdisReleaseSpinLock(&pAd->TxRingLock);
1027                 return (NDIS_STATUS_FAILURE);
1028         }
1029
1030         //
1031         // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
1032         // should always has only one ohysical buffer, and the whole frame size equals
1033         // to the first scatter buffer size
1034         //
1035
1036         // Initialize TX Descriptor
1037         // For inter-frame gap, the number is for this frame and next frame
1038         // For MLME rate, we will fix as 2Mb to match other vendor's implement
1039 //      pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
1040
1041 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
1042         // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
1043         if (pMacEntry == NULL)
1044         {
1045         RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
1046                 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0,  (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
1047         }
1048         else
1049         {
1050                 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
1051                                         bInsertTimestamp, FALSE, bAckRequired, FALSE,
1052                                         0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
1053                                         pMacEntry->MaxHTPhyMode.field.MCS, 0,
1054                                         (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
1055                                         IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
1056         }
1057
1058         pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
1059         pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
1060 //      pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE;
1061         SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
1062
1063
1064         RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
1065         pTxD->LastSec0 = 1;
1066         pTxD->LastSec1 = 1;
1067         pTxD->SDLen0 = SrcBufLen;
1068         pTxD->SDLen1 = 0;
1069         pTxD->SDPtr0 = SrcBufPA;
1070         pTxD->DMADONE = 0;
1071
1072
1073         pAd->RalinkCounters.KickTxCount++;
1074         pAd->RalinkCounters.OneSecTxDoneCount++;
1075
1076         // Increase TX_CTX_IDX, but write to register later.
1077         INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1078
1079         RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10,  pAd->TxRing[QueIdx].TxCpuIdx);
1080
1081         // Make sure to release MGMT ring resource
1082 //      NdisReleaseSpinLock(&pAd->TxRingLock);
1083
1084         return NDIS_STATUS_SUCCESS;
1085 }
1086
1087
1088 NDIS_STATUS MlmeDataHardTransmit(
1089         IN      PRTMP_ADAPTER   pAd,
1090         IN      UCHAR   QueIdx,
1091         IN      PNDIS_PACKET    pPacket)
1092 {
1093         if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1094                 )
1095         {
1096                 return NDIS_STATUS_FAILURE;
1097         }
1098
1099         return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
1100 }
1101
1102
1103 /*
1104         ========================================================================
1105
1106         Routine Description:
1107                 Calculates the duration which is required to transmit out frames
1108         with given size and specified rate.
1109
1110         Arguments:
1111                 pTxD            Pointer to transmit descriptor
1112                 Ack             Setting for Ack requirement bit
1113                 Fragment        Setting for Fragment bit
1114                 RetryMode       Setting for retry mode
1115                 Ifs             Setting for IFS gap
1116                 Rate            Setting for transmit rate
1117                 Service         Setting for service
1118                 Length          Frame length
1119                 TxPreamble      Short or Long preamble when using CCK rates
1120                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1121
1122         Return Value:
1123                 None
1124
1125         IRQL = PASSIVE_LEVEL
1126         IRQL = DISPATCH_LEVEL
1127
1128         ========================================================================
1129 */
1130 VOID RTMPWriteTxDescriptor(
1131         IN      PRTMP_ADAPTER   pAd,
1132         IN      PTXD_STRUC              pTxD,
1133         IN      BOOLEAN                 bWIV,
1134         IN      UCHAR                   QueueSEL)
1135 {
1136         //
1137         // Always use Long preamble before verifiation short preamble functionality works well.
1138         // Todo: remove the following line if short preamble functionality works
1139         //
1140         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1141
1142         pTxD->WIV       = (bWIV) ? 1: 0;
1143         pTxD->QSEL= (QueueSEL);
1144         //RT2860c??  fixed using EDCA queue for test...  We doubt Queue1 has problem.  2006-09-26 Jan
1145         //pTxD->QSEL= FIFO_EDCA;
1146         pTxD->DMADONE = 0;
1147 }