blob: f01a51c381f1d9e218b65ff79724bfb966250050 [file] [log] [blame]
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001/*
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
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080035u16 RtmpPCI_WriteTxResource(struct rt_rtmp_adapter *pAd,
36 struct rt_tx_blk *pTxBlk,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080037 IN BOOLEAN bIsLast, u16 * FreeNumber)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020038{
39
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080040 u8 *pDMAHeaderBufVA;
41 u16 TxIdx, RetTxIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080042 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080043 u32 BufBasePaLow;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080044 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080045 u16 hwHeaderLen;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020046
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080047 /* */
48 /* get Tx Ring Resource */
49 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020050 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
51 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -080052 pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080053 BufBasePaLow =
54 RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020055
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080056 /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080057 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080058 /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080059 hwHeaderLen =
60 pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD +
61 pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
62 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080063 /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020064 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
65 }
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -080066 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf,
67 TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020068
69 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
70 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
71
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080072 /* */
73 /* build Tx Descriptor */
74 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020075
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -080076 pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020077 NdisZeroMemory(pTxD, TXD_SIZE);
78
79 pTxD->SDPtr0 = BufBasePaLow;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080080 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020081 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;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -080089 /* */
90 /* Update Tx index */
91 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +020092 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
93 pTxRing->TxCpuIdx = TxIdx;
94
95 *FreeNumber -= 1;
96
97 return RetTxIdx;
98}
99
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800100u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd,
101 struct rt_tx_blk *pTxBlk,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800102 IN BOOLEAN bIsLast,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800103 u16 * FreeNumber)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200104{
105
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800106 u8 *pDMAHeaderBufVA;
107 u16 TxIdx, RetTxIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800108 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800109 u32 BufBasePaLow;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800110 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800111 u16 hwHeaderLen;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200112
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800113 /* */
114 /* get Tx Ring Resource */
115 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200116 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
117 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800118 pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800119 BufBasePaLow =
120 RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200121
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800122 /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
123 /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200124 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
125
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800126 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf,
127 TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200128
129 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
130 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
131
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800132 /* */
133 /* build Tx Descriptor */
134 /* */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800135 pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200136 NdisZeroMemory(pTxD, TXD_SIZE);
137
138 pTxD->SDPtr0 = BufBasePaLow;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800139 pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */
Joe Perches859171c2010-11-14 19:04:48 -0800140 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200141 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;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800148 /* */
149 /* Update Tx index */
150 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200151 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
152 pTxRing->TxCpuIdx = TxIdx;
153
154 *FreeNumber -= 1;
155
156 return RetTxIdx;
157}
158
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800159u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd,
160 struct rt_tx_blk *pTxBlk,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800161 u8 frameNum, u16 * FreeNumber)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200162{
163 BOOLEAN bIsLast;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800164 u8 *pDMAHeaderBufVA;
165 u16 TxIdx, RetTxIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800166 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800167 u32 BufBasePaLow;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800168 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800169 u16 hwHdrLen;
170 u32 firstDMALen;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200171
172 bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
173
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800174 /* */
175 /* get Tx Ring Resource */
176 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200177 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
178 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800179 pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800180 BufBasePaLow =
181 RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200182
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800183 if (frameNum == 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800184 /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200185 if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800186 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800187 hwHdrLen =
188 pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD +
189 pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200190 else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800191 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800192 hwHdrLen =
193 pTxBlk->MpduHeaderLen -
194 LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen +
195 LENGTH_ARALINK_HEADER_FIELD;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200196 else
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800197 /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200198 hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
199
200 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800201 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200202 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
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800210 /* */
211 /* build Tx Descriptor */
212 /* */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800213 pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200214 NdisZeroMemory(pTxD, TXD_SIZE);
215
216 pTxD->SDPtr0 = BufBasePaLow;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800217 pTxD->SDLen0 = firstDMALen; /* include padding */
Joe Perches859171c2010-11-14 19:04:48 -0800218 pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200219 pTxD->SDLen1 = pTxBlk->SrcBufLen;
220 pTxD->LastSec0 = 0;
221 pTxD->LastSec1 = (bIsLast) ? 1 : 0;
222
223 RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
224
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200225 RetTxIdx = TxIdx;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800226 /* */
227 /* Update Tx index */
228 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200229 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
230 pTxRing->TxCpuIdx = TxIdx;
231
232 *FreeNumber -= 1;
233
234 return RetTxIdx;
235
236}
237
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800238void RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter *pAd,
239 struct rt_tx_blk *pTxBlk,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800240 u16 totalMPDUSize, u16 FirstTxIdx)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200241{
242
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800243 struct rt_txwi * pTxWI;
244 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200245
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800246 /* */
247 /* get Tx Ring Resource */
248 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200249 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800250 pTxWI = (struct rt_txwi *) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200251 pTxWI->MPDUtotalByteCount = totalMPDUSize;
252
253}
254
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800255void RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800256 u8 QueIdx, u16 LastTxIdx)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200257{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800258 struct rt_txd * pTxD;
259 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200260
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800261 /* */
262 /* get Tx Ring Resource */
263 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200264 pTxRing = &pAd->TxRing[QueIdx];
265
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800266 /* */
267 /* build Tx Descriptor */
268 /* */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800269 pTxD = (struct rt_txd *) pTxRing->Cell[LastTxIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200270
271 pTxD->LastSec1 = 1;
272
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200273}
274
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800275u16 RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter *pAd,
276 struct rt_tx_blk *pTxBlk,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800277 u8 fragNum, u16 * FreeNumber)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200278{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800279 u8 *pDMAHeaderBufVA;
280 u16 TxIdx, RetTxIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800281 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800282 u32 BufBasePaLow;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800283 struct rt_rtmp_tx_ring *pTxRing;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800284 u16 hwHeaderLen;
285 u32 firstDMALen;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200286
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800287 /* */
288 /* Get Tx Ring Resource */
289 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200290 pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
291 TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800292 pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800293 BufBasePaLow =
294 RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200295
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800296 /* */
297 /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
298 /* */
299 /*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200300 hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
301
302 firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
303 NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
304
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800305 /* */
306 /* Build Tx Descriptor */
307 /* */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800308 pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200309 NdisZeroMemory(pTxD, TXD_SIZE);
310
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800311 if (fragNum == pTxBlk->TotalFragNum) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200312 pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
313 pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
314 }
315
316 pTxD->SDPtr0 = BufBasePaLow;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800317 pTxD->SDLen0 = firstDMALen; /* include padding */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200318 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
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200325 RetTxIdx = TxIdx;
326 pTxBlk->Priv += pTxBlk->SrcBufLen;
327
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800328 /* */
329 /* Update Tx index */
330 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200331 INC_RING_INDEX(TxIdx, TX_RING_SIZE);
332 pTxRing->TxCpuIdx = TxIdx;
333
334 *FreeNumber -= 1;
335
336 return RetTxIdx;
337
338}
339
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200340/*
341 Must be run in Interrupt context
342 This function handle PCI specific TxDesc and cpu index update and kick the packet out.
343 */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800344int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800345 u8 QueIdx,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800346 void *pPacket,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800347 u8 *pSrcBufVA, u32 SrcBufLen)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200348{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800349 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800350 unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200351
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800352 pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[SwIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200353
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;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800362 pTxD->SDPtr0 =
363 PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200364 pTxD->SDLen0 = SrcBufLen;
365
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800366/*================================================================== */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200367/* 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 "));*/
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800378/*======================================================================= */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200379
380 pAd->RalinkCounters.KickTxCount++;
381 pAd->RalinkCounters.OneSecTxDoneCount++;
382
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800383 /* Increase TX_CTX_IDX, but write to register later. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200384 INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
385
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800386 RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200387
388 return 0;
389}
390
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200391/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800408int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
409 struct rt_header_802_11 * pHeader,
410 struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxD)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200411{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800412 struct rt_cipher_key *pWpaKey;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800413 int dBm;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200414
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800415 /* Phy errors & CRC errors */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800416 if ( /*(pRxD->PhyErr) || */ (pRxD->Crc)) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800417 /* Check RSSI for Noise Hist statistic collection. */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800418 dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200419 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
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800436 return (NDIS_STATUS_FAILURE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200437 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800438 /* Add Rx size to channel load counter, we should ignore error counts */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200439 pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
440
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300441 /* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800442 if (pHeader != NULL) {
443 if (pHeader->FC.ToDs) {
444 return (NDIS_STATUS_FAILURE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200445 }
446 }
Lucas De Marchie9c54992011-04-26 23:28:26 -0700447 /* Drop not U2M frames, can't drop here because we will drop beacon in this case */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800448 /* I am kind of doubting the U2M bit operation */
449 /* if (pRxD->U2M == 0) */
450 /* return(NDIS_STATUS_FAILURE); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200451
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800452 /* drop decyption fail frame */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800453 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 "));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200462
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800463 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);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200468
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800469 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,
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800474/* CipherName[pRxD->CipherAlg], */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800475 pRxWI->KeyIndex));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200476
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800477 /* */
478 /* MIC Error */
479 /* */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800480 if (pRxD->CipherErr == 2) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200481 pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800482 if (pAd->StaCfg.WpaSupplicantUP)
483 WpaSendMicFailureToWpaSupplicant(pAd,
484 (pWpaKey->
485 Type ==
486 PAIRWISEKEY) ?
487 TRUE : FALSE);
488 else
489 RTMPReportMicError(pAd, pWpaKey);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200490
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800491 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);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200498
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800499 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200500 }
501
502 if (pHeader == NULL)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800503 return (NDIS_STATUS_SUCCESS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200504 /*if ((pRxD->CipherAlg == CIPHER_AES) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800505 (pHeader->Sequence == pAd->FragFrame.Sequence))
506 {
507 //
508 // Acceptable since the First FragFrame no CipherErr problem.
509 //
510 return(NDIS_STATUS_SUCCESS);
511 } */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200512
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800513 return (NDIS_STATUS_FAILURE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200514 }
515
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800516 return (NDIS_STATUS_SUCCESS);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200517}
518
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800519BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200520{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800521 struct rt_rtmp_tx_ring *pTxRing;
522 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800523 void *pPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800524 u8 FREE = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800525 struct rt_txd TxD, *pOriTxD;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800526 /*unsigned long IrqFlags; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800527 BOOLEAN bReschedule = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200528
529 ASSERT(QueIdx < NUM_OF_TX_RING);
530 pTxRing = &pAd->TxRing[QueIdx];
531
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800532 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF,
533 &pTxRing->TxDmaIdx);
534 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800535/* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200536
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800537 /* static rate also need NICUpdateFifoStaCounters() function. */
538 /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800539 NICUpdateFifoStaCounters(pAd);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200540
541 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
542 FREE++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800543 pTxD =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800544 (struct rt_txd *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200545 pOriTxD = pTxD;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800546 NdisMoveMemory(&TxD, pTxD, sizeof(struct rt_txd));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200547 pTxD = &TxD;
548
549 pTxD->DMADONE = 0;
550
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200551 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800552 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);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200560 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800561 /*Always assign pNdisPacket as NULL after clear */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200562 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
563
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800564 pPacket =
565 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200566
567 ASSERT(pPacket == NULL);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800568 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);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200574 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800575 /*Always assign pNextNdisPacket as NULL after clear */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800576 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket =
577 NULL;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200578 }
579
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800580 pAd->RalinkCounters.TransmittedByteCount +=
581 (pTxD->SDLen1 + pTxD->SDLen0);
582 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200583 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
584 /* get tx_tdx_idx again */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800585 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF,
586 &pTxRing->TxDmaIdx);
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800587 NdisMoveMemory(pOriTxD, pTxD, sizeof(struct rt_txd));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200588
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800589/* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200590 }
591
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800592 return bReschedule;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200593
594}
595
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200596/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800612BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800613 INT_SOURCE_CSR_STRUC TxRingBitmap)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200614{
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800615/* u8 Count = 0; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800616 unsigned long IrqFlags;
617 BOOLEAN bReschedule = FALSE;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200618
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800619 /* Make sure Tx ring resource won't be used by other threads */
620 /*NdisAcquireSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200621
622 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
623
624 if (TxRingBitmap.field.Ac0DmaDone)
625 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
626
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200627 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
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800636 /* Make sure to release Tx ring resource */
637 /*NdisReleaseSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200638 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
639
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800640 /* Dequeue outgoing frames from TxSwQueue[] and process it */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200641 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
642
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800643 return bReschedule;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200644}
645
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200646/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800664void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200665{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800666 struct rt_txd * pTxD;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800667 void *pPacket;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800668/* int i; */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800669 u8 FREE = 0;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800670 struct rt_rtmp_mgmt_ring *pMgmtRing = &pAd->MgmtRing;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200671
672 NdisAcquireSpinLock(&pAd->MgmtRingLock);
673
674 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800675 while (pMgmtRing->TxSwFreeIdx != pMgmtRing->TxDmaIdx) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200676 FREE++;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800677 pTxD =
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800678 (struct rt_txd *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800679 AllocVa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200680 pTxD->DMADONE = 0;
681 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
682
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800683 if (pPacket) {
684 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0,
685 PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200686 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
687 }
688 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
689
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800690 pPacket =
691 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
692 if (pPacket) {
693 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1,
694 PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200695 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
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200705/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800716void RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200717{
718 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800719 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200720 }
721 }
722}
723
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200724/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800735void RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200736{
737 {
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800738 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
739 DBGPRINT(RT_DEBUG_TRACE,
740 ("RTMPHandlePreTBTTInterrupt...\n"));
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200741 }
742 }
743
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200744}
745
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800746void RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter *pAd)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200747{
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800748 WPDMA_GLO_CFG_STRUC GloCfg;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200749
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800750 if (pAd == NULL) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200751 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
752 return;
753 }
754
755 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
756
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800757 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200758
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);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200768 RTMPRingCleanUp(pAd, QID_MGMT);
769 RTMPRingCleanUp(pAd, QID_RX);
770
771 RTMPEnableRxTx(pAd);
772
773 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
774}
775
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800776void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800777 OUT PRT28XX_RXD_STRUC pSaveRxD,
778 OUT BOOLEAN * pbReschedule,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800779 IN u32 * pRxPending)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200780{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800781 struct rt_rxd * pRxD;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800782 void *pRxPacket = NULL;
783 void *pNewPacket;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800784 void *AllocVa;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800785 dma_addr_t AllocPa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800786 BOOLEAN bReschedule = FALSE;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800787 struct rt_rtmp_dmacb *pRxCell;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200788
789 RTMP_SEM_LOCK(&pAd->RxRingLock);
790
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800791 if (*pRxPending == 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800792 /* Get how may packets had been received */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800793 RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200794
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800795 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800796 /* no more rx packets */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200797 bReschedule = FALSE;
798 goto done;
799 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800800 /* get rx pending count */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200801 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800802 *pRxPending =
803 pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200804 else
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800805 *pRxPending =
806 pAd->RxRing.RxDmaIdx + RX_RING_SIZE -
807 pAd->RxRing.RxSwReadIdx;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200808
809 }
810
811 pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx];
812
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800813 /* Point to Rx indexed rx ring descriptor */
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800814 pRxD = (struct rt_rxd *) pRxCell->AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200815
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800816 if (pRxD->DDONE == 0) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200817 *pRxPending = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800818 /* DMAIndx had done but DDONE bit not ready */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200819 bReschedule = TRUE;
820 goto done;
821 }
822
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800823 /* return rx descriptor */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200824 NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
825
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800826 pNewPacket =
827 RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE,
828 &AllocVa, &AllocPa);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200829
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800830 if (pNewPacket) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800831 /* unmap the rx buffer */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200832 PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800833 pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200834 pRxPacket = pRxCell->pNdisPacket;
835
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800836 pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800837 pRxCell->pNdisPacket = (void *)pNewPacket;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800838 pRxCell->DmaBuf.AllocVa = AllocVa;
839 pRxCell->DmaBuf.AllocPa = AllocPa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200840 /* update SDP0 to new buffer of rx packet */
841 pRxD->SDP0 = AllocPa;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800842 } else {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800843 /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200844 pRxPacket = NULL;
845 bReschedule = TRUE;
846 }
847
848 pRxD->DDONE = 0;
849
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800850 /* had handled one rx packet */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200851 *pRxPending = *pRxPending - 1;
852
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800853 /* update rx descriptor and kick rx */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200854 INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
855
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800856 pAd->RxRing.RxCpuIdx =
857 (pAd->RxRing.RxSwReadIdx ==
858 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxSwReadIdx - 1);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200859 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
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800867int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -0800868 u8 QueIdx, void *pPacket)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200869{
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800870 struct rt_packet_info PacketInfo;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800871 u8 *pSrcBufVA;
872 u32 SrcBufLen;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800873 struct rt_txd * pTxD;
874 struct rt_header_802_11 * pHeader_802_11;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800875 BOOLEAN bAckRequired, bInsertTimestamp;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800876 unsigned long SrcBufPA;
877 /*u8 TxBufIdx; */
878 u8 MlmeRate;
879 unsigned long SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800880 struct rt_txwi * pFirstTxWI;
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800881 /*unsigned long i; */
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800882 /*HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. */
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -0800883 unsigned long FreeNum;
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800884 struct rt_mac_table_entry *pMacEntry = NULL;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200885
886 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
887
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800888 if (pSrcBufVA == NULL) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800889 /* The buffer shouldn't be NULL */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200890 return NDIS_STATUS_FAILURE;
891 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800892 /* Make sure MGMT ring resource won't be used by other threads */
893 /*NdisAcquireSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200894
895 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
896
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800897 if (FreeNum == 0) {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800898 /*NdisReleaseSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200899 return NDIS_STATUS_FAILURE;
900 }
901
902 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
903
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800904 pTxD = (struct rt_txd *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200905
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800906 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200907 DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800908 /*NdisReleaseSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200909 return NDIS_STATUS_FAILURE;
910 }
911
912 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800913 /* outgoing frame always wakeup PHY to prevent frame lost */
914 /* if (pAd->StaCfg.Psm == PWR_SAVE) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200915 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
916 AsicForceWakeup(pAd, TRUE);
917 }
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800918 pFirstTxWI = (struct rt_txwi *) pSrcBufVA;
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200919
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -0800920 pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXWI_SIZE);
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800921 if (pHeader_802_11->Addr1[0] & 0x01) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200922 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800923 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200924 MlmeRate = pAd->CommonCfg.MlmeRate;
925 }
926
927 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800928 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200929 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
930 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800931 /* Verify Mlme rate for a / g bands. */
932 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200933 MlmeRate = RATE_6;
934
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800935 /* */
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 */
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300942 /* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800943 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 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200952 }
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200953
954 bInsertTimestamp = FALSE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800955 if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200956 {
957 bAckRequired = FALSE;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800958 } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200959 {
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800960 if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200961 {
962 bAckRequired = FALSE;
963 pHeader_802_11->Duration = 0;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800964 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200965 bAckRequired = TRUE;
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800966 pHeader_802_11->Duration =
967 RTMPCalcDuration(pAd, MlmeRate, 14);
968 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200969 bInsertTimestamp = TRUE;
970 }
971 }
972 }
973 pHeader_802_11->Sequence = pAd->Sequence++;
974 if (pAd->Sequence > 0xfff)
975 pAd->Sequence = 0;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800976 /* 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 */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200978 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800979 && (pAd->CommonCfg.bIEEE80211H == 1)
980 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
981 DBGPRINT(RT_DEBUG_ERROR,
Sebastian Dalfuß06aea992009-11-07 17:31:12 +0100982 ("MlmeHardTransmit --> radar detect not in normal mode!\n"));
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800983 /*NdisReleaseSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200984 return (NDIS_STATUS_FAILURE);
985 }
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800986 /* */
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 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200991
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800992 /* 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; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +0200996
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -0800997/* 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. */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -0800999 if (pMacEntry == NULL) {
1000 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
1001 FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
1002 (SrcBufLen - TXWI_SIZE), PID_MGMT, 0,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001003 (u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001004 IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
1005 } else {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001006 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001007 bInsertTimestamp, FALSE, bAckRequired, FALSE,
1008 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
1009 pMacEntry->MaxHTPhyMode.field.MCS, 0,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001010 (u8)pMacEntry->MaxHTPhyMode.field.MCS,
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001011 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001012 }
1013
1014 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
1015 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001016/* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; */
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001017 SrcBufPA =
1018 PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001019
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
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001028 pAd->RalinkCounters.KickTxCount++;
1029 pAd->RalinkCounters.OneSecTxDoneCount++;
1030
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001031 /* Increase TX_CTX_IDX, but write to register later. */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001032 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1033
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001034 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * 0x10,
1035 pAd->TxRing[QueIdx].TxCpuIdx);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001036
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001037 /* Make sure to release MGMT ring resource */
1038/* NdisReleaseSpinLock(&pAd->TxRingLock); */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001039
1040 return NDIS_STATUS_SUCCESS;
1041}
1042
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001043int MlmeDataHardTransmit(struct rt_rtmp_adapter *pAd,
Bartlomiej Zolnierkiewicz8a10a542009-12-11 12:23:15 -08001044 u8 QueIdx, void *pPacket)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001045{
1046 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001047 ) {
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001048 return NDIS_STATUS_FAILURE;
1049 }
1050
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001051 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001052}
1053
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001054/*
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*/
Bartlomiej Zolnierkiewicz62eb7342009-12-11 12:23:16 -08001081void RTMPWriteTxDescriptor(struct rt_rtmp_adapter *pAd,
1082 struct rt_txd * pTxD,
Bartlomiej Zolnierkiewicz51126de2009-12-11 12:23:15 -08001083 IN BOOLEAN bWIV, u8 QueueSEL)
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001084{
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001085 /* */
1086 /* Always use Long preamble before verifiation short preamble functionality works well. */
1087 /* Todo: remove the following line if short preamble functionality works */
1088 /* */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001089 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1090
Bartlomiej Zolnierkiewicz96b3c83d2009-12-11 12:23:13 -08001091 pTxD->WIV = (bWIV) ? 1 : 0;
1092 pTxD->QSEL = (QueueSEL);
Bartlomiej Zolnierkiewiczec278fa2009-12-11 12:23:15 -08001093 /*RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan */
1094 /*pTxD->QSEL= FIFO_EDCA; */
Bartlomiej Zolnierkiewiczca97b832009-09-22 20:44:07 +02001095 pTxD->DMADONE = 0;
1096}