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 
RtmpPCI_WriteTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,IN BOOLEAN bIsLast,u16 * FreeNumber)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 
RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,IN BOOLEAN bIsLast,u16 * FreeNumber)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 
RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u8 frameNum,u16 * FreeNumber)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 
RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u16 totalMPDUSize,u16 FirstTxIdx)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 
RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter * pAd,u8 QueIdx,u16 LastTxIdx)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 
RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter * pAd,struct rt_tx_blk * pTxBlk,u8 fragNum,u16 * FreeNumber)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  */
RtmpPCIMgmtKickOut(struct rt_rtmp_adapter * pAd,u8 QueIdx,void * pPacket,u8 * pSrcBufVA,u32 SrcBufLen)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 */
RTMPCheckRxError(struct rt_rtmp_adapter * pAd,struct rt_header_802_11 * pHeader,struct rt_rxwi * pRxWI,IN PRT28XX_RXD_STRUC pRxD)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 
RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter * pAd,u8 QueIdx)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 */
RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter * pAd,INT_SOURCE_CSR_STRUC TxRingBitmap)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 */
RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter * pAd)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 */
RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter * pAd)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 */
RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter * pAd)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 
RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter * pAd)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 
GetPacketFromRxRing(struct rt_rtmp_adapter * pAd,OUT PRT28XX_RXD_STRUC pSaveRxD,OUT BOOLEAN * pbReschedule,IN u32 * pRxPending)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 
MlmeHardTransmitTxRing(struct rt_rtmp_adapter * pAd,u8 QueIdx,void * pPacket)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 
MlmeDataHardTransmit(struct rt_rtmp_adapter * pAd,u8 QueIdx,void * pPacket)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 */
RTMPWriteTxDescriptor(struct rt_rtmp_adapter * pAd,struct rt_txd * pTxD,IN BOOLEAN bWIV,u8 QueueSEL)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 }
1097