• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rt2860/common/
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
35u16 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
100u16 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
159u16 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
238void 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
255void 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
275u16 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 */
344int 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*/
408int 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 promiscous 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, cant's 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
519BOOLEAN 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*/
612BOOLEAN 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*/
664void 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*/
716void 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*/
735void 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
746void 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
776void *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
861done:
862	RTMP_SEM_UNLOCK(&pAd->RxRingLock);
863	*pbReschedule = bReschedule;
864	return pRxPacket;
865}
866
867int 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 alse 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
1043int 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*/
1081void 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}
1097