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