diff options
Diffstat (limited to 'drivers/staging/rt3070/common/cmm_data.c')
-rw-r--r-- | drivers/staging/rt3070/common/cmm_data.c | 2827 |
1 files changed, 2827 insertions, 0 deletions
diff --git a/drivers/staging/rt3070/common/cmm_data.c b/drivers/staging/rt3070/common/cmm_data.c new file mode 100644 index 00000000000..85f92b9f83d --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_data.c | |||
@@ -0,0 +1,2827 @@ | |||
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 | #include "../rt_config.h" | ||
29 | |||
30 | #define MAX_TX_IN_TBTT (16) | ||
31 | |||
32 | |||
33 | UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
34 | UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; | ||
35 | // Add Cisco Aironet SNAP heade for CCX2 support | ||
36 | UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; | ||
37 | UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; | ||
38 | UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; | ||
39 | UCHAR EAPOL[] = {0x88, 0x8e}; | ||
40 | UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ | ||
41 | |||
42 | UCHAR IPX[] = {0x81, 0x37}; | ||
43 | UCHAR APPLE_TALK[] = {0x80, 0xf3}; | ||
44 | UCHAR RateIdToPlcpSignal[12] = { | ||
45 | 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec | ||
46 | 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 | ||
47 | 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 | ||
48 | |||
49 | UCHAR OfdmSignalToRateId[16] = { | ||
50 | RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively | ||
51 | RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively | ||
52 | RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively | ||
53 | RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively | ||
54 | }; | ||
55 | |||
56 | UCHAR OfdmRateToRxwiMCS[12] = { | ||
57 | 0, 0, 0, 0, | ||
58 | 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 | ||
59 | 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 | ||
60 | }; | ||
61 | UCHAR RxwiMCSToOfdmRate[12] = { | ||
62 | RATE_6, RATE_9, RATE_12, RATE_18, | ||
63 | RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 | ||
64 | 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 | ||
65 | }; | ||
66 | |||
67 | char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; | ||
68 | |||
69 | UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; | ||
70 | //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; | ||
71 | UCHAR default_sta_aifsn[]={3,7,2,2}; | ||
72 | |||
73 | UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; | ||
74 | |||
75 | |||
76 | /* | ||
77 | ======================================================================== | ||
78 | |||
79 | Routine Description: | ||
80 | API for MLME to transmit management frame to AP (BSS Mode) | ||
81 | or station (IBSS Mode) | ||
82 | |||
83 | Arguments: | ||
84 | pAd Pointer to our adapter | ||
85 | pData Pointer to the outgoing 802.11 frame | ||
86 | Length Size of outgoing management frame | ||
87 | |||
88 | Return Value: | ||
89 | NDIS_STATUS_FAILURE | ||
90 | NDIS_STATUS_PENDING | ||
91 | NDIS_STATUS_SUCCESS | ||
92 | |||
93 | IRQL = PASSIVE_LEVEL | ||
94 | IRQL = DISPATCH_LEVEL | ||
95 | |||
96 | Note: | ||
97 | |||
98 | ======================================================================== | ||
99 | */ | ||
100 | NDIS_STATUS MiniportMMRequest( | ||
101 | IN PRTMP_ADAPTER pAd, | ||
102 | IN UCHAR QueIdx, | ||
103 | IN PUCHAR pData, | ||
104 | IN UINT Length) | ||
105 | { | ||
106 | PNDIS_PACKET pPacket; | ||
107 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | ||
108 | ULONG FreeNum; | ||
109 | UCHAR IrqState; | ||
110 | UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; | ||
111 | |||
112 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | ||
113 | |||
114 | QueIdx=3; | ||
115 | |||
116 | // 2860C use Tx Ring | ||
117 | |||
118 | IrqState = pAd->irq_disabled; | ||
119 | |||
120 | do | ||
121 | { | ||
122 | // Reset is in progress, stop immediately | ||
123 | if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | ||
124 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| | ||
125 | !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) | ||
126 | { | ||
127 | Status = NDIS_STATUS_FAILURE; | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | // Check Free priority queue | ||
132 | // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. | ||
133 | |||
134 | // 2860C use Tx Ring | ||
135 | if (pAd->MACVersion == 0x28600100) | ||
136 | { | ||
137 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | FreeNum = GET_MGMTRING_FREENO(pAd); | ||
142 | } | ||
143 | |||
144 | if ((FreeNum > 0)) | ||
145 | { | ||
146 | // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 | ||
147 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); | ||
148 | Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); | ||
149 | if (Status != NDIS_STATUS_SUCCESS) | ||
150 | { | ||
151 | DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); | ||
152 | break; | ||
153 | } | ||
154 | |||
155 | //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | ||
156 | //pAd->CommonCfg.MlmeRate = RATE_2; | ||
157 | |||
158 | |||
159 | Status = MlmeHardTransmit(pAd, QueIdx, pPacket); | ||
160 | if (Status != NDIS_STATUS_SUCCESS) | ||
161 | RTMPFreeNdisPacket(pAd, pPacket); | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | pAd->RalinkCounters.MgmtRingFullCount++; | ||
166 | DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", | ||
167 | QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); | ||
168 | } | ||
169 | |||
170 | } while (FALSE); | ||
171 | |||
172 | |||
173 | return Status; | ||
174 | } | ||
175 | |||
176 | |||
177 | |||
178 | NDIS_STATUS MlmeDataHardTransmit( | ||
179 | IN PRTMP_ADAPTER pAd, | ||
180 | IN UCHAR QueIdx, | ||
181 | IN PNDIS_PACKET pPacket); | ||
182 | |||
183 | #define MAX_DATAMM_RETRY 3 | ||
184 | /* | ||
185 | ======================================================================== | ||
186 | |||
187 | Routine Description: | ||
188 | API for MLME to transmit management frame to AP (BSS Mode) | ||
189 | or station (IBSS Mode) | ||
190 | |||
191 | Arguments: | ||
192 | pAd Pointer to our adapter | ||
193 | pData Pointer to the outgoing 802.11 frame | ||
194 | Length Size of outgoing management frame | ||
195 | |||
196 | Return Value: | ||
197 | NDIS_STATUS_FAILURE | ||
198 | NDIS_STATUS_PENDING | ||
199 | NDIS_STATUS_SUCCESS | ||
200 | |||
201 | IRQL = PASSIVE_LEVEL | ||
202 | IRQL = DISPATCH_LEVEL | ||
203 | |||
204 | Note: | ||
205 | |||
206 | ======================================================================== | ||
207 | */ | ||
208 | NDIS_STATUS MiniportDataMMRequest( | ||
209 | IN PRTMP_ADAPTER pAd, | ||
210 | IN UCHAR QueIdx, | ||
211 | IN PUCHAR pData, | ||
212 | IN UINT Length) | ||
213 | { | ||
214 | PNDIS_PACKET pPacket; | ||
215 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | ||
216 | ULONG FreeNum; | ||
217 | int retry = 0; | ||
218 | UCHAR IrqState; | ||
219 | UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; | ||
220 | |||
221 | ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); | ||
222 | |||
223 | // 2860C use Tx Ring | ||
224 | IrqState = pAd->irq_disabled; | ||
225 | |||
226 | do | ||
227 | { | ||
228 | // Reset is in progress, stop immediately | ||
229 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || | ||
230 | RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| | ||
231 | !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) | ||
232 | { | ||
233 | Status = NDIS_STATUS_FAILURE; | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | // Check Free priority queue | ||
238 | // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. | ||
239 | |||
240 | // 2860C use Tx Ring | ||
241 | |||
242 | // free Tx(QueIdx) resources | ||
243 | FreeNum = GET_TXRING_FREENO(pAd, QueIdx); | ||
244 | |||
245 | if ((FreeNum > 0)) | ||
246 | { | ||
247 | // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 | ||
248 | NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); | ||
249 | Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); | ||
250 | if (Status != NDIS_STATUS_SUCCESS) | ||
251 | { | ||
252 | DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; | ||
257 | //pAd->CommonCfg.MlmeRate = RATE_2; | ||
258 | |||
259 | |||
260 | Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket); | ||
261 | if (Status != NDIS_STATUS_SUCCESS) | ||
262 | RTMPFreeNdisPacket(pAd, pPacket); | ||
263 | retry = MAX_DATAMM_RETRY; | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | retry ++; | ||
268 | |||
269 | printk("retry %d\n", retry); | ||
270 | pAd->RalinkCounters.MgmtRingFullCount++; | ||
271 | |||
272 | if (retry >= MAX_DATAMM_RETRY) | ||
273 | { | ||
274 | DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", | ||
275 | QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | } while (retry < MAX_DATAMM_RETRY); | ||
280 | |||
281 | |||
282 | return Status; | ||
283 | } | ||
284 | |||
285 | |||
286 | |||
287 | |||
288 | |||
289 | |||
290 | /* | ||
291 | ======================================================================== | ||
292 | |||
293 | Routine Description: | ||
294 | Copy frame from waiting queue into relative ring buffer and set | ||
295 | appropriate ASIC register to kick hardware transmit function | ||
296 | |||
297 | Arguments: | ||
298 | pAd Pointer to our adapter | ||
299 | pBuffer Pointer to memory of outgoing frame | ||
300 | Length Size of outgoing management frame | ||
301 | |||
302 | Return Value: | ||
303 | NDIS_STATUS_FAILURE | ||
304 | NDIS_STATUS_PENDING | ||
305 | NDIS_STATUS_SUCCESS | ||
306 | |||
307 | IRQL = PASSIVE_LEVEL | ||
308 | IRQL = DISPATCH_LEVEL | ||
309 | |||
310 | Note: | ||
311 | |||
312 | ======================================================================== | ||
313 | */ | ||
314 | NDIS_STATUS MlmeHardTransmit( | ||
315 | IN PRTMP_ADAPTER pAd, | ||
316 | IN UCHAR QueIdx, | ||
317 | IN PNDIS_PACKET pPacket) | ||
318 | { | ||
319 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | ||
320 | #ifdef CARRIER_DETECTION_SUPPORT | ||
321 | #endif // CARRIER_DETECTION_SUPPORT // | ||
322 | ) | ||
323 | { | ||
324 | return NDIS_STATUS_FAILURE; | ||
325 | } | ||
326 | |||
327 | return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); | ||
328 | |||
329 | } | ||
330 | |||
331 | NDIS_STATUS MlmeDataHardTransmit( | ||
332 | IN PRTMP_ADAPTER pAd, | ||
333 | IN UCHAR QueIdx, | ||
334 | IN PNDIS_PACKET pPacket) | ||
335 | { | ||
336 | if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) | ||
337 | #ifdef CARRIER_DETECTION_SUPPORT | ||
338 | #endif // CARRIER_DETECTION_SUPPORT // | ||
339 | ) | ||
340 | { | ||
341 | return NDIS_STATUS_FAILURE; | ||
342 | } | ||
343 | |||
344 | #ifdef RT2870 | ||
345 | return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); | ||
346 | #endif // RT2870 // | ||
347 | } | ||
348 | |||
349 | |||
350 | |||
351 | |||
352 | |||
353 | NDIS_STATUS MlmeHardTransmitMgmtRing( | ||
354 | IN PRTMP_ADAPTER pAd, | ||
355 | IN UCHAR QueIdx, | ||
356 | IN PNDIS_PACKET pPacket) | ||
357 | { | ||
358 | PACKET_INFO PacketInfo; | ||
359 | PUCHAR pSrcBufVA; | ||
360 | UINT SrcBufLen; | ||
361 | PHEADER_802_11 pHeader_802_11; | ||
362 | BOOLEAN bAckRequired, bInsertTimestamp; | ||
363 | UCHAR MlmeRate; | ||
364 | PTXWI_STRUC pFirstTxWI; | ||
365 | MAC_TABLE_ENTRY *pMacEntry = NULL; | ||
366 | |||
367 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); | ||
368 | |||
369 | // Make sure MGMT ring resource won't be used by other threads | ||
370 | // sample, for IRQ LOCK -> SEM LOCK | ||
371 | // IrqState = pAd->irq_disabled; | ||
372 | // if (!IrqState) | ||
373 | RTMP_SEM_LOCK(&pAd->MgmtRingLock); | ||
374 | |||
375 | |||
376 | if (pSrcBufVA == NULL) | ||
377 | { | ||
378 | // The buffer shouldn't be NULL | ||
379 | // if (!IrqState) | ||
380 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
381 | return NDIS_STATUS_FAILURE; | ||
382 | } | ||
383 | |||
384 | #ifdef CONFIG_STA_SUPPORT | ||
385 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
386 | { | ||
387 | // outgoing frame always wakeup PHY to prevent frame lost | ||
388 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) | ||
389 | AsicForceWakeup(pAd, TRUE); | ||
390 | } | ||
391 | #endif // CONFIG_STA_SUPPORT // | ||
392 | |||
393 | pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); | ||
394 | pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); | ||
395 | |||
396 | if (pHeader_802_11->Addr1[0] & 0x01) | ||
397 | { | ||
398 | MlmeRate = pAd->CommonCfg.BasicMlmeRate; | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | MlmeRate = pAd->CommonCfg.MlmeRate; | ||
403 | } | ||
404 | |||
405 | // Verify Mlme rate for a / g bands. | ||
406 | if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band | ||
407 | MlmeRate = RATE_6; | ||
408 | |||
409 | if ((pHeader_802_11->FC.Type == BTYPE_DATA) && | ||
410 | (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) | ||
411 | { | ||
412 | pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); | ||
413 | } | ||
414 | |||
415 | #ifdef CONFIG_STA_SUPPORT | ||
416 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
417 | { | ||
418 | // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. | ||
419 | if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED | ||
420 | #ifdef DOT11_N_SUPPORT | ||
421 | || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED | ||
422 | #endif // DOT11_N_SUPPORT // | ||
423 | ) | ||
424 | { | ||
425 | if (pAd->LatchRfRegs.Channel > 14) | ||
426 | pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | ||
427 | else | ||
428 | pAd->CommonCfg.MlmeTransmit.field.MODE = 0; | ||
429 | } | ||
430 | } | ||
431 | #endif // CONFIG_STA_SUPPORT // | ||
432 | |||
433 | // | ||
434 | // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) | ||
435 | // Snice it's been set to 0 while on MgtMacHeaderInit | ||
436 | // By the way this will cause frame to be send on PWR_SAVE failed. | ||
437 | // | ||
438 | // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); | ||
439 | // | ||
440 | // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame | ||
441 | #ifdef CONFIG_STA_SUPPORT | ||
442 | // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD | ||
443 | if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) | ||
444 | { | ||
445 | if ((pAd->StaCfg.Psm == PWR_SAVE) && | ||
446 | (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) | ||
447 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | ||
448 | else | ||
449 | pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; | ||
450 | } | ||
451 | #endif // CONFIG_STA_SUPPORT // | ||
452 | |||
453 | bInsertTimestamp = FALSE; | ||
454 | if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL | ||
455 | { | ||
456 | #ifdef CONFIG_STA_SUPPORT | ||
457 | //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. | ||
458 | if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) | ||
459 | { | ||
460 | pHeader_802_11->FC.PwrMgmt = PWR_SAVE; | ||
461 | } | ||
462 | #endif // CONFIG_STA_SUPPORT // | ||
463 | bAckRequired = FALSE; | ||
464 | } | ||
465 | else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) | ||
466 | { | ||
467 | //pAd->Sequence++; | ||
468 | //pHeader_802_11->Sequence = pAd->Sequence; | ||
469 | |||
470 | if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST | ||
471 | { | ||
472 | bAckRequired = FALSE; | ||
473 | pHeader_802_11->Duration = 0; | ||
474 | } | ||
475 | else | ||
476 | { | ||
477 | bAckRequired = TRUE; | ||
478 | pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); | ||
479 | if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) | ||
480 | { | ||
481 | bInsertTimestamp = TRUE; | ||
482 | } | ||
483 | } | ||
484 | } | ||
485 | |||
486 | pHeader_802_11->Sequence = pAd->Sequence++; | ||
487 | if (pAd->Sequence >0xfff) | ||
488 | pAd->Sequence = 0; | ||
489 | |||
490 | // Before radar detection done, mgmt frame can not be sent but probe req | ||
491 | // Because we need to use probe req to trigger driver to send probe req in passive scan | ||
492 | if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) | ||
493 | && (pAd->CommonCfg.bIEEE80211H == 1) | ||
494 | && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) | ||
495 | { | ||
496 | DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); | ||
497 | // if (!IrqState) | ||
498 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
499 | return (NDIS_STATUS_FAILURE); | ||
500 | } | ||
501 | |||
502 | #ifdef RT_BIG_ENDIAN | ||
503 | RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); | ||
504 | #endif | ||
505 | |||
506 | // | ||
507 | // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET | ||
508 | // should always has only one ohysical buffer, and the whole frame size equals | ||
509 | // to the first scatter buffer size | ||
510 | // | ||
511 | |||
512 | // Initialize TX Descriptor | ||
513 | // For inter-frame gap, the number is for this frame and next frame | ||
514 | // For MLME rate, we will fix as 2Mb to match other vendor's implement | ||
515 | // pAd->CommonCfg.MlmeTransmit.field.MODE = 1; | ||
516 | |||
517 | // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. | ||
518 | if (pMacEntry == NULL) | ||
519 | { | ||
520 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, | ||
521 | 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); | ||
522 | } | ||
523 | else | ||
524 | { | ||
525 | RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, | ||
526 | bInsertTimestamp, FALSE, bAckRequired, FALSE, | ||
527 | 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), | ||
528 | pMacEntry->MaxHTPhyMode.field.MCS, 0, | ||
529 | (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, | ||
530 | IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); | ||
531 | } | ||
532 | |||
533 | #ifdef RT_BIG_ENDIAN | ||
534 | RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); | ||
535 | #endif | ||
536 | |||
537 | // Now do hardware-depened kick out. | ||
538 | HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); | ||
539 | |||
540 | // Make sure to release MGMT ring resource | ||
541 | // if (!IrqState) | ||
542 | RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); | ||
543 | return NDIS_STATUS_SUCCESS; | ||
544 | } | ||
545 | |||
546 | |||
547 | /******************************************************************************** | ||
548 | |||
549 | New DeQueue Procedures. | ||
550 | |||
551 | ********************************************************************************/ | ||
552 | |||
553 | #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ | ||
554 | do{ \ | ||
555 | if (bIntContext == FALSE) \ | ||
556 | RTMP_IRQ_LOCK((lock), IrqFlags); \ | ||
557 | }while(0) | ||
558 | |||
559 | #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ | ||
560 | do{ \ | ||
561 | if (bIntContext == FALSE) \ | ||
562 | RTMP_IRQ_UNLOCK((lock), IrqFlags); \ | ||
563 | }while(0) | ||
564 | |||
565 | |||
566 | /* | ||
567 | ======================================================================== | ||
568 | Tx Path design algorithm: | ||
569 | Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), | ||
570 | Specific Packet Type. Following show the classification rule and policy for each kinds of packets. | ||
571 | Classification Rule=> | ||
572 | Multicast: (*addr1 & 0x01) == 0x01 | ||
573 | Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. | ||
574 | 11N Rate : If peer support HT | ||
575 | (1).AMPDU -- If TXBA is negotiated. | ||
576 | (2).AMSDU -- If AMSDU is capable for both peer and ourself. | ||
577 | *). AMSDU can embedded in a AMPDU, but now we didn't support it. | ||
578 | (3).Normal -- Other packets which send as 11n rate. | ||
579 | |||
580 | B/G Rate : If peer is b/g only. | ||
581 | (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 | ||
582 | (2).Normal -- Other packets which send as b/g rate. | ||
583 | Fragment: | ||
584 | The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. | ||
585 | |||
586 | Classified Packet Handle Rule=> | ||
587 | Multicast: | ||
588 | No ACK, //pTxBlk->bAckRequired = FALSE; | ||
589 | No WMM, //pTxBlk->bWMM = FALSE; | ||
590 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | ||
591 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | ||
592 | Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use | ||
593 | the same policy to handle it. | ||
594 | Force LowRate, //pTxBlk->bForceLowRate = TRUE; | ||
595 | |||
596 | 11N Rate : | ||
597 | No piggyback, //pTxBlk->bPiggyBack = FALSE; | ||
598 | |||
599 | (1).AMSDU | ||
600 | pTxBlk->bWMM = TRUE; | ||
601 | (2).AMPDU | ||
602 | pTxBlk->bWMM = TRUE; | ||
603 | (3).Normal | ||
604 | |||
605 | B/G Rate : | ||
606 | (1).ARALINK | ||
607 | |||
608 | (2).Normal | ||
609 | ======================================================================== | ||
610 | */ | ||
611 | static UCHAR TxPktClassification( | ||
612 | IN RTMP_ADAPTER *pAd, | ||
613 | IN PNDIS_PACKET pPacket) | ||
614 | { | ||
615 | UCHAR TxFrameType = TX_UNKOWN_FRAME; | ||
616 | UCHAR Wcid; | ||
617 | MAC_TABLE_ENTRY *pMacEntry = NULL; | ||
618 | #ifdef DOT11_N_SUPPORT | ||
619 | BOOLEAN bHTRate = FALSE; | ||
620 | #endif // DOT11_N_SUPPORT // | ||
621 | |||
622 | Wcid = RTMP_GET_PACKET_WCID(pPacket); | ||
623 | if (Wcid == MCAST_WCID) | ||
624 | { // Handle for RA is Broadcast/Multicast Address. | ||
625 | return TX_MCAST_FRAME; | ||
626 | } | ||
627 | |||
628 | // Handle for unicast packets | ||
629 | pMacEntry = &pAd->MacTab.Content[Wcid]; | ||
630 | if (RTMP_GET_PACKET_LOWRATE(pPacket)) | ||
631 | { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame | ||
632 | TxFrameType = TX_LEGACY_FRAME; | ||
633 | } | ||
634 | #ifdef DOT11_N_SUPPORT | ||
635 | else if (IS_HT_RATE(pMacEntry)) | ||
636 | { // it's a 11n capable packet | ||
637 | |||
638 | // Depends on HTPhyMode to check if the peer support the HTRate transmission. | ||
639 | // Currently didn't support A-MSDU embedded in A-MPDU | ||
640 | bHTRate = TRUE; | ||
641 | if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) | ||
642 | TxFrameType = TX_LEGACY_FRAME; | ||
643 | #ifdef UAPSD_AP_SUPPORT | ||
644 | else if (RTMP_GET_PACKET_EOSP(pPacket)) | ||
645 | TxFrameType = TX_LEGACY_FRAME; | ||
646 | #endif // UAPSD_AP_SUPPORT // | ||
647 | else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) | ||
648 | return TX_AMPDU_FRAME; | ||
649 | else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) | ||
650 | return TX_AMSDU_FRAME; | ||
651 | else | ||
652 | TxFrameType = TX_LEGACY_FRAME; | ||
653 | } | ||
654 | #endif // DOT11_N_SUPPORT // | ||
655 | else | ||
656 | { // it's a legacy b/g packet. | ||
657 | if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && | ||
658 | (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && | ||
659 | (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) | ||
660 | { // if peer support Ralink Aggregation, we use it. | ||
661 | TxFrameType = TX_RALINK_FRAME; | ||
662 | } | ||
663 | else | ||
664 | { | ||
665 | TxFrameType = TX_LEGACY_FRAME; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. | ||
670 | if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) | ||
671 | TxFrameType = TX_FRAG_FRAME; | ||
672 | |||
673 | return TxFrameType; | ||
674 | } | ||
675 | |||
676 | |||
677 | BOOLEAN RTMP_FillTxBlkInfo( | ||
678 | IN RTMP_ADAPTER *pAd, | ||
679 | IN TX_BLK *pTxBlk) | ||
680 | { | ||
681 | PACKET_INFO PacketInfo; | ||
682 | PNDIS_PACKET pPacket; | ||
683 | PMAC_TABLE_ENTRY pMacEntry = NULL; | ||
684 | |||
685 | pPacket = pTxBlk->pPacket; | ||
686 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); | ||
687 | |||
688 | pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); | ||
689 | pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); | ||
690 | pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); | ||
691 | pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap | ||
692 | |||
693 | if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) | ||
694 | TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); | ||
695 | else | ||
696 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); | ||
697 | |||
698 | // Default to clear this flag | ||
699 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); | ||
700 | |||
701 | |||
702 | if (pTxBlk->Wcid == MCAST_WCID) | ||
703 | { | ||
704 | pTxBlk->pMacEntry = NULL; | ||
705 | { | ||
706 | #ifdef MCAST_RATE_SPECIFIC | ||
707 | PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); | ||
708 | if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) | ||
709 | pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; | ||
710 | else | ||
711 | #endif // MCAST_RATE_SPECIFIC // | ||
712 | pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | ||
713 | } | ||
714 | |||
715 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. | ||
716 | //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); | ||
717 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); | ||
718 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | ||
719 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) | ||
720 | { | ||
721 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | ||
722 | } | ||
723 | |||
724 | } | ||
725 | else | ||
726 | { | ||
727 | pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; | ||
728 | pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; | ||
729 | |||
730 | pMacEntry = pTxBlk->pMacEntry; | ||
731 | |||
732 | |||
733 | // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. | ||
734 | if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) | ||
735 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); | ||
736 | else | ||
737 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); | ||
738 | |||
739 | { | ||
740 | |||
741 | #ifdef CONFIG_STA_SUPPORT | ||
742 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
743 | { | ||
744 | |||
745 | // If support WMM, enable it. | ||
746 | if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && | ||
747 | CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) | ||
748 | TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); | ||
749 | |||
750 | // if (pAd->StaCfg.bAutoTxRateSwitch) | ||
751 | // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); | ||
752 | } | ||
753 | #endif // CONFIG_STA_SUPPORT // | ||
754 | } | ||
755 | |||
756 | if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) | ||
757 | { | ||
758 | if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || | ||
759 | ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) | ||
760 | { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. | ||
761 | pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; | ||
762 | #ifdef DOT11_N_SUPPORT | ||
763 | // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? | ||
764 | if (IS_HT_STA(pTxBlk->pMacEntry) && | ||
765 | (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && | ||
766 | ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) | ||
767 | { | ||
768 | TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); | ||
769 | TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); | ||
770 | } | ||
771 | #endif // DOT11_N_SUPPORT // | ||
772 | } | ||
773 | |||
774 | #ifdef DOT11_N_SUPPORT | ||
775 | if ( (IS_HT_RATE(pMacEntry) == FALSE) && | ||
776 | (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) | ||
777 | { // Currently piggy-back only support when peer is operate in b/g mode. | ||
778 | TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); | ||
779 | } | ||
780 | #endif // DOT11_N_SUPPORT // | ||
781 | |||
782 | if (RTMP_GET_PACKET_MOREDATA(pPacket)) | ||
783 | { | ||
784 | TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); | ||
785 | } | ||
786 | #ifdef UAPSD_AP_SUPPORT | ||
787 | if (RTMP_GET_PACKET_EOSP(pPacket)) | ||
788 | { | ||
789 | TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); | ||
790 | } | ||
791 | #endif // UAPSD_AP_SUPPORT // | ||
792 | } | ||
793 | else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) | ||
794 | { | ||
795 | TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); | ||
796 | } | ||
797 | |||
798 | pMacEntry->DebugTxCount++; | ||
799 | } | ||
800 | |||
801 | return TRUE; | ||
802 | |||
803 | FillTxBlkErr: | ||
804 | return FALSE; | ||
805 | } | ||
806 | |||
807 | |||
808 | BOOLEAN CanDoAggregateTransmit( | ||
809 | IN RTMP_ADAPTER *pAd, | ||
810 | IN NDIS_PACKET *pPacket, | ||
811 | IN TX_BLK *pTxBlk) | ||
812 | { | ||
813 | |||
814 | //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType); | ||
815 | |||
816 | if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) | ||
817 | return FALSE; | ||
818 | |||
819 | if (RTMP_GET_PACKET_DHCP(pPacket) || | ||
820 | RTMP_GET_PACKET_EAPOL(pPacket) || | ||
821 | RTMP_GET_PACKET_WAI(pPacket)) | ||
822 | return FALSE; | ||
823 | |||
824 | if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && | ||
825 | ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) | ||
826 | { // For AMSDU, allow the packets with total length < max-amsdu size | ||
827 | return FALSE; | ||
828 | } | ||
829 | |||
830 | if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && | ||
831 | (pTxBlk->TxPacketList.Number == 2)) | ||
832 | { // For RALINK-Aggregation, allow two frames in one batch. | ||
833 | return FALSE; | ||
834 | } | ||
835 | |||
836 | #ifdef CONFIG_STA_SUPPORT | ||
837 | if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP | ||
838 | return TRUE; | ||
839 | else | ||
840 | #endif // CONFIG_STA_SUPPORT // | ||
841 | return FALSE; | ||
842 | |||
843 | } | ||
844 | |||
845 | |||
846 | /* | ||
847 | ======================================================================== | ||
848 | |||
849 | Routine Description: | ||
850 | To do the enqueue operation and extract the first item of waiting | ||
851 | list. If a number of available shared memory segments could meet | ||
852 | the request of extracted item, the extracted item will be fragmented | ||
853 | into shared memory segments. | ||
854 | |||
855 | Arguments: | ||
856 | pAd Pointer to our adapter | ||
857 | pQueue Pointer to Waiting Queue | ||
858 | |||
859 | Return Value: | ||
860 | None | ||
861 | |||
862 | IRQL = DISPATCH_LEVEL | ||
863 | |||
864 | Note: | ||
865 | |||
866 | ======================================================================== | ||
867 | */ | ||
868 | VOID RTMPDeQueuePacket( | ||
869 | IN PRTMP_ADAPTER pAd, | ||
870 | IN BOOLEAN bIntContext, | ||
871 | IN UCHAR QIdx, /* BulkOutPipeId */ | ||
872 | IN UCHAR Max_Tx_Packets) | ||
873 | { | ||
874 | PQUEUE_ENTRY pEntry = NULL; | ||
875 | PNDIS_PACKET pPacket; | ||
876 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS; | ||
877 | UCHAR Count=0; | ||
878 | PQUEUE_HEADER pQueue; | ||
879 | ULONG FreeNumber[NUM_OF_TX_RING]; | ||
880 | UCHAR QueIdx, sQIdx, eQIdx; | ||
881 | unsigned long IrqFlags = 0; | ||
882 | BOOLEAN hasTxDesc = FALSE; | ||
883 | TX_BLK TxBlk; | ||
884 | TX_BLK *pTxBlk; | ||
885 | |||
886 | #ifdef DBG_DIAGNOSE | ||
887 | BOOLEAN firstRound; | ||
888 | RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; | ||
889 | #endif | ||
890 | |||
891 | |||
892 | if (QIdx == NUM_OF_TX_RING) | ||
893 | { | ||
894 | sQIdx = 0; | ||
895 | //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) | ||
896 | #ifdef CONFIG_STA_SUPPORT | ||
897 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
898 | eQIdx = 3; // 4 ACs, start from 0. | ||
899 | #endif // CONFIG_STA_SUPPORT // | ||
900 | } | ||
901 | else | ||
902 | { | ||
903 | sQIdx = eQIdx = QIdx; | ||
904 | } | ||
905 | |||
906 | for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) | ||
907 | { | ||
908 | Count=0; | ||
909 | |||
910 | RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
911 | |||
912 | #ifdef DBG_DIAGNOSE | ||
913 | firstRound = ((QueIdx == 0) ? TRUE : FALSE); | ||
914 | #endif // DBG_DIAGNOSE // | ||
915 | |||
916 | while (1) | ||
917 | { | ||
918 | if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | | ||
919 | fRTMP_ADAPTER_RADIO_OFF | | ||
920 | fRTMP_ADAPTER_RESET_IN_PROGRESS | | ||
921 | fRTMP_ADAPTER_HALT_IN_PROGRESS | | ||
922 | fRTMP_ADAPTER_NIC_NOT_EXIST)))) | ||
923 | { | ||
924 | RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
925 | return; | ||
926 | } | ||
927 | |||
928 | if (Count >= Max_Tx_Packets) | ||
929 | break; | ||
930 | |||
931 | DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
932 | if (&pAd->TxSwQueue[QueIdx] == NULL) | ||
933 | { | ||
934 | #ifdef DBG_DIAGNOSE | ||
935 | if (firstRound == TRUE) | ||
936 | pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; | ||
937 | #endif // DBG_DIAGNOSE // | ||
938 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
939 | break; | ||
940 | } | ||
941 | |||
942 | |||
943 | // probe the Queue Head | ||
944 | pQueue = &pAd->TxSwQueue[QueIdx]; | ||
945 | if ((pEntry = pQueue->Head) == NULL) | ||
946 | { | ||
947 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
948 | break; | ||
949 | } | ||
950 | |||
951 | pTxBlk = &TxBlk; | ||
952 | NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); | ||
953 | //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. | ||
954 | pTxBlk->QueIdx = QueIdx; | ||
955 | |||
956 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | ||
957 | |||
958 | // Early check to make sure we have enoguh Tx Resource. | ||
959 | hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); | ||
960 | if (!hasTxDesc) | ||
961 | { | ||
962 | pAd->PrivateInfo.TxRingFullCnt++; | ||
963 | |||
964 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
965 | |||
966 | break; | ||
967 | } | ||
968 | |||
969 | pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); | ||
970 | pEntry = RemoveHeadQueue(pQueue); | ||
971 | pTxBlk->TotalFrameNum++; | ||
972 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary | ||
973 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); | ||
974 | pTxBlk->pPacket = pPacket; | ||
975 | InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); | ||
976 | |||
977 | if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) | ||
978 | { | ||
979 | // Enhance SW Aggregation Mechanism | ||
980 | if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) | ||
981 | { | ||
982 | InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); | ||
983 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
984 | break; | ||
985 | } | ||
986 | |||
987 | do{ | ||
988 | if((pEntry = pQueue->Head) == NULL) | ||
989 | break; | ||
990 | |||
991 | // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. | ||
992 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | ||
993 | FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); | ||
994 | hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); | ||
995 | if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) | ||
996 | break; | ||
997 | |||
998 | //Remove the packet from the TxSwQueue and insert into pTxBlk | ||
999 | pEntry = RemoveHeadQueue(pQueue); | ||
1000 | ASSERT(pEntry); | ||
1001 | pPacket = QUEUE_ENTRY_TO_PKT(pEntry); | ||
1002 | pTxBlk->TotalFrameNum++; | ||
1003 | pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary | ||
1004 | pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); | ||
1005 | InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); | ||
1006 | }while(1); | ||
1007 | |||
1008 | if (pTxBlk->TxPacketList.Number == 1) | ||
1009 | pTxBlk->TxFrameType = TX_LEGACY_FRAME; | ||
1010 | } | ||
1011 | |||
1012 | #ifdef RT2870 | ||
1013 | DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); | ||
1014 | #endif // RT2870 // | ||
1015 | |||
1016 | Count += pTxBlk->TxPacketList.Number; | ||
1017 | |||
1018 | // Do HardTransmit now. | ||
1019 | #ifdef CONFIG_STA_SUPPORT | ||
1020 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1021 | Status = STAHardTransmit(pAd, pTxBlk, QueIdx); | ||
1022 | #endif // CONFIG_STA_SUPPORT // | ||
1023 | } | ||
1024 | |||
1025 | RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); | ||
1026 | |||
1027 | #ifdef RT2870 | ||
1028 | if (!hasTxDesc) | ||
1029 | RTUSBKickBulkOut(pAd); | ||
1030 | #endif // RT2870 // | ||
1031 | |||
1032 | #ifdef BLOCK_NET_IF | ||
1033 | if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) | ||
1034 | && (pAd->TxSwQueue[QueIdx].Number < 1)) | ||
1035 | { | ||
1036 | releaseNetIf(&pAd->blockQueueTab[QueIdx]); | ||
1037 | } | ||
1038 | #endif // BLOCK_NET_IF // | ||
1039 | |||
1040 | } | ||
1041 | |||
1042 | } | ||
1043 | |||
1044 | |||
1045 | /* | ||
1046 | ======================================================================== | ||
1047 | |||
1048 | Routine Description: | ||
1049 | Calculates the duration which is required to transmit out frames | ||
1050 | with given size and specified rate. | ||
1051 | |||
1052 | Arguments: | ||
1053 | pAd Pointer to our adapter | ||
1054 | Rate Transmit rate | ||
1055 | Size Frame size in units of byte | ||
1056 | |||
1057 | Return Value: | ||
1058 | Duration number in units of usec | ||
1059 | |||
1060 | IRQL = PASSIVE_LEVEL | ||
1061 | IRQL = DISPATCH_LEVEL | ||
1062 | |||
1063 | Note: | ||
1064 | |||
1065 | ======================================================================== | ||
1066 | */ | ||
1067 | USHORT RTMPCalcDuration( | ||
1068 | IN PRTMP_ADAPTER pAd, | ||
1069 | IN UCHAR Rate, | ||
1070 | IN ULONG Size) | ||
1071 | { | ||
1072 | ULONG Duration = 0; | ||
1073 | |||
1074 | if (Rate < RATE_FIRST_OFDM_RATE) // CCK | ||
1075 | { | ||
1076 | if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) | ||
1077 | Duration = 96; // 72+24 preamble+plcp | ||
1078 | else | ||
1079 | Duration = 192; // 144+48 preamble+plcp | ||
1080 | |||
1081 | Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); | ||
1082 | if ((Size << 4) % RateIdTo500Kbps[Rate]) | ||
1083 | Duration ++; | ||
1084 | } | ||
1085 | else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates | ||
1086 | { | ||
1087 | Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension | ||
1088 | Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); | ||
1089 | if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) | ||
1090 | Duration += 4; | ||
1091 | } | ||
1092 | else //mimo rate | ||
1093 | { | ||
1094 | Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension | ||
1095 | } | ||
1096 | |||
1097 | return (USHORT)Duration; | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /* | ||
1102 | ======================================================================== | ||
1103 | |||
1104 | Routine Description: | ||
1105 | Calculates the duration which is required to transmit out frames | ||
1106 | with given size and specified rate. | ||
1107 | |||
1108 | Arguments: | ||
1109 | pTxWI Pointer to head of each MPDU to HW. | ||
1110 | Ack Setting for Ack requirement bit | ||
1111 | Fragment Setting for Fragment bit | ||
1112 | RetryMode Setting for retry mode | ||
1113 | Ifs Setting for IFS gap | ||
1114 | Rate Setting for transmit rate | ||
1115 | Service Setting for service | ||
1116 | Length Frame length | ||
1117 | TxPreamble Short or Long preamble when using CCK rates | ||
1118 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | ||
1119 | |||
1120 | Return Value: | ||
1121 | None | ||
1122 | |||
1123 | IRQL = PASSIVE_LEVEL | ||
1124 | IRQL = DISPATCH_LEVEL | ||
1125 | |||
1126 | See also : BASmartHardTransmit() !!! | ||
1127 | |||
1128 | ======================================================================== | ||
1129 | */ | ||
1130 | VOID RTMPWriteTxWI( | ||
1131 | IN PRTMP_ADAPTER pAd, | ||
1132 | IN PTXWI_STRUC pOutTxWI, | ||
1133 | IN BOOLEAN FRAG, | ||
1134 | IN BOOLEAN CFACK, | ||
1135 | IN BOOLEAN InsTimestamp, | ||
1136 | IN BOOLEAN AMPDU, | ||
1137 | IN BOOLEAN Ack, | ||
1138 | IN BOOLEAN NSeq, // HW new a sequence. | ||
1139 | IN UCHAR BASize, | ||
1140 | IN UCHAR WCID, | ||
1141 | IN ULONG Length, | ||
1142 | IN UCHAR PID, | ||
1143 | IN UCHAR TID, | ||
1144 | IN UCHAR TxRate, | ||
1145 | IN UCHAR Txopmode, | ||
1146 | IN BOOLEAN CfAck, | ||
1147 | IN HTTRANSMIT_SETTING *pTransmit) | ||
1148 | { | ||
1149 | PMAC_TABLE_ENTRY pMac = NULL; | ||
1150 | TXWI_STRUC TxWI; | ||
1151 | PTXWI_STRUC pTxWI; | ||
1152 | |||
1153 | if (WCID < MAX_LEN_OF_MAC_TABLE) | ||
1154 | pMac = &pAd->MacTab.Content[WCID]; | ||
1155 | |||
1156 | // | ||
1157 | // Always use Long preamble before verifiation short preamble functionality works well. | ||
1158 | // Todo: remove the following line if short preamble functionality works | ||
1159 | // | ||
1160 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
1161 | NdisZeroMemory(&TxWI, TXWI_SIZE); | ||
1162 | pTxWI = &TxWI; | ||
1163 | |||
1164 | pTxWI->FRAG= FRAG; | ||
1165 | |||
1166 | pTxWI->CFACK = CFACK; | ||
1167 | pTxWI->TS= InsTimestamp; | ||
1168 | pTxWI->AMPDU = AMPDU; | ||
1169 | pTxWI->ACK = Ack; | ||
1170 | pTxWI->txop= Txopmode; | ||
1171 | |||
1172 | pTxWI->NSEQ = NSeq; | ||
1173 | // John tune the performace with Intel Client in 20 MHz performance | ||
1174 | #ifdef DOT11_N_SUPPORT | ||
1175 | BASize = pAd->CommonCfg.TxBASize; | ||
1176 | |||
1177 | if( BASize >7 ) | ||
1178 | BASize =7; | ||
1179 | pTxWI->BAWinSize = BASize; | ||
1180 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1181 | pTxWI->STBC = pTransmit->field.STBC; | ||
1182 | #endif // DOT11_N_SUPPORT // | ||
1183 | |||
1184 | pTxWI->WirelessCliID = WCID; | ||
1185 | pTxWI->MPDUtotalByteCount = Length; | ||
1186 | pTxWI->PacketId = PID; | ||
1187 | |||
1188 | // If CCK or OFDM, BW must be 20 | ||
1189 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1190 | #ifdef DOT11N_DRAFT3 | ||
1191 | if (pTxWI->BW) | ||
1192 | pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); | ||
1193 | #endif // DOT11N_DRAFT3 // | ||
1194 | |||
1195 | pTxWI->MCS = pTransmit->field.MCS; | ||
1196 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1197 | pTxWI->CFACK = CfAck; | ||
1198 | |||
1199 | #ifdef DOT11_N_SUPPORT | ||
1200 | if (pMac) | ||
1201 | { | ||
1202 | if (pAd->CommonCfg.bMIMOPSEnable) | ||
1203 | { | ||
1204 | if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | ||
1205 | { | ||
1206 | // Dynamic MIMO Power Save Mode | ||
1207 | pTxWI->MIMOps = 1; | ||
1208 | } | ||
1209 | else if (pMac->MmpsMode == MMPS_STATIC) | ||
1210 | { | ||
1211 | // Static MIMO Power Save Mode | ||
1212 | if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) | ||
1213 | { | ||
1214 | pTxWI->MCS = 7; | ||
1215 | pTxWI->MIMOps = 0; | ||
1216 | } | ||
1217 | } | ||
1218 | } | ||
1219 | //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; | ||
1220 | if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) | ||
1221 | { | ||
1222 | pTxWI->MpduDensity = 7; | ||
1223 | } | ||
1224 | else | ||
1225 | { | ||
1226 | pTxWI->MpduDensity = pMac->MpduDensity; | ||
1227 | } | ||
1228 | } | ||
1229 | #endif // DOT11_N_SUPPORT // | ||
1230 | |||
1231 | pTxWI->PacketId = pTxWI->MCS; | ||
1232 | NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); | ||
1233 | } | ||
1234 | |||
1235 | |||
1236 | VOID RTMPWriteTxWI_Data( | ||
1237 | IN PRTMP_ADAPTER pAd, | ||
1238 | IN OUT PTXWI_STRUC pTxWI, | ||
1239 | IN TX_BLK *pTxBlk) | ||
1240 | { | ||
1241 | HTTRANSMIT_SETTING *pTransmit; | ||
1242 | PMAC_TABLE_ENTRY pMacEntry; | ||
1243 | #ifdef DOT11_N_SUPPORT | ||
1244 | UCHAR BASize; | ||
1245 | #endif // DOT11_N_SUPPORT // | ||
1246 | |||
1247 | |||
1248 | ASSERT(pTxWI); | ||
1249 | |||
1250 | pTransmit = pTxBlk->pTransmit; | ||
1251 | pMacEntry = pTxBlk->pMacEntry; | ||
1252 | |||
1253 | |||
1254 | // | ||
1255 | // Always use Long preamble before verifiation short preamble functionality works well. | ||
1256 | // Todo: remove the following line if short preamble functionality works | ||
1257 | // | ||
1258 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
1259 | NdisZeroMemory(pTxWI, TXWI_SIZE); | ||
1260 | |||
1261 | pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); | ||
1262 | pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); | ||
1263 | pTxWI->txop = pTxBlk->FrameGap; | ||
1264 | |||
1265 | #ifdef CONFIG_STA_SUPPORT | ||
1266 | #ifdef QOS_DLS_SUPPORT | ||
1267 | if (pMacEntry && | ||
1268 | (pAd->StaCfg.BssType == BSS_INFRA) && | ||
1269 | (pMacEntry->ValidAsDls == TRUE)) | ||
1270 | pTxWI->WirelessCliID = BSSID_WCID; | ||
1271 | else | ||
1272 | #endif // QOS_DLS_SUPPORT // | ||
1273 | #endif // CONFIG_STA_SUPPORT // | ||
1274 | pTxWI->WirelessCliID = pTxBlk->Wcid; | ||
1275 | |||
1276 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | ||
1277 | pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); | ||
1278 | |||
1279 | // If CCK or OFDM, BW must be 20 | ||
1280 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1281 | #ifdef DOT11_N_SUPPORT | ||
1282 | #ifdef DOT11N_DRAFT3 | ||
1283 | if (pTxWI->BW) | ||
1284 | pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); | ||
1285 | #endif // DOT11N_DRAFT3 // | ||
1286 | pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); | ||
1287 | |||
1288 | // John tune the performace with Intel Client in 20 MHz performance | ||
1289 | BASize = pAd->CommonCfg.TxBASize; | ||
1290 | if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) | ||
1291 | { | ||
1292 | UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. | ||
1293 | |||
1294 | RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; | ||
1295 | BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; | ||
1296 | } | ||
1297 | |||
1298 | pTxWI->TxBF = pTransmit->field.TxBF; | ||
1299 | pTxWI->BAWinSize = BASize; | ||
1300 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1301 | pTxWI->STBC = pTransmit->field.STBC; | ||
1302 | #endif // DOT11_N_SUPPORT // | ||
1303 | |||
1304 | pTxWI->MCS = pTransmit->field.MCS; | ||
1305 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1306 | |||
1307 | #ifdef DOT11_N_SUPPORT | ||
1308 | if (pMacEntry) | ||
1309 | { | ||
1310 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | ||
1311 | { | ||
1312 | // Dynamic MIMO Power Save Mode | ||
1313 | pTxWI->MIMOps = 1; | ||
1314 | } | ||
1315 | else if (pMacEntry->MmpsMode == MMPS_STATIC) | ||
1316 | { | ||
1317 | // Static MIMO Power Save Mode | ||
1318 | if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) | ||
1319 | { | ||
1320 | pTxWI->MCS = 7; | ||
1321 | pTxWI->MIMOps = 0; | ||
1322 | } | ||
1323 | } | ||
1324 | |||
1325 | if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) | ||
1326 | { | ||
1327 | pTxWI->MpduDensity = 7; | ||
1328 | } | ||
1329 | else | ||
1330 | { | ||
1331 | pTxWI->MpduDensity = pMacEntry->MpduDensity; | ||
1332 | } | ||
1333 | } | ||
1334 | #endif // DOT11_N_SUPPORT // | ||
1335 | |||
1336 | #ifdef DBG_DIAGNOSE | ||
1337 | if (pTxBlk->QueIdx== 0) | ||
1338 | { | ||
1339 | pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; | ||
1340 | pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; | ||
1341 | } | ||
1342 | #endif // DBG_DIAGNOSE // | ||
1343 | |||
1344 | // for rate adapation | ||
1345 | pTxWI->PacketId = pTxWI->MCS; | ||
1346 | #ifdef INF_AMAZON_SE | ||
1347 | /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ | ||
1348 | if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket)) | ||
1349 | { | ||
1350 | if(pTxWI->PHYMODE == MODE_CCK) | ||
1351 | { | ||
1352 | pTxWI->PacketId = 6; | ||
1353 | } | ||
1354 | } | ||
1355 | #endif // INF_AMAZON_SE // | ||
1356 | } | ||
1357 | |||
1358 | |||
1359 | VOID RTMPWriteTxWI_Cache( | ||
1360 | IN PRTMP_ADAPTER pAd, | ||
1361 | IN OUT PTXWI_STRUC pTxWI, | ||
1362 | IN TX_BLK *pTxBlk) | ||
1363 | { | ||
1364 | PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit; | ||
1365 | PMAC_TABLE_ENTRY pMacEntry; | ||
1366 | |||
1367 | // | ||
1368 | // update TXWI | ||
1369 | // | ||
1370 | pMacEntry = pTxBlk->pMacEntry; | ||
1371 | pTransmit = pTxBlk->pTransmit; | ||
1372 | |||
1373 | //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) | ||
1374 | //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) | ||
1375 | //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) | ||
1376 | if (pMacEntry->bAutoTxRateSwitch) | ||
1377 | { | ||
1378 | pTxWI->txop = IFS_HTTXOP; | ||
1379 | |||
1380 | // If CCK or OFDM, BW must be 20 | ||
1381 | pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); | ||
1382 | pTxWI->ShortGI = pTransmit->field.ShortGI; | ||
1383 | pTxWI->STBC = pTransmit->field.STBC; | ||
1384 | |||
1385 | pTxWI->MCS = pTransmit->field.MCS; | ||
1386 | pTxWI->PHYMODE = pTransmit->field.MODE; | ||
1387 | |||
1388 | // set PID for TxRateSwitching | ||
1389 | pTxWI->PacketId = pTransmit->field.MCS; | ||
1390 | } | ||
1391 | |||
1392 | #ifdef DOT11_N_SUPPORT | ||
1393 | pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); | ||
1394 | pTxWI->MIMOps = 0; | ||
1395 | |||
1396 | #ifdef DOT11N_DRAFT3 | ||
1397 | if (pTxWI->BW) | ||
1398 | pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); | ||
1399 | #endif // DOT11N_DRAFT3 // | ||
1400 | |||
1401 | if (pAd->CommonCfg.bMIMOPSEnable) | ||
1402 | { | ||
1403 | // MIMO Power Save Mode | ||
1404 | if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) | ||
1405 | { | ||
1406 | // Dynamic MIMO Power Save Mode | ||
1407 | pTxWI->MIMOps = 1; | ||
1408 | } | ||
1409 | else if (pMacEntry->MmpsMode == MMPS_STATIC) | ||
1410 | { | ||
1411 | // Static MIMO Power Save Mode | ||
1412 | if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) | ||
1413 | { | ||
1414 | pTxWI->MCS = 7; | ||
1415 | pTxWI->MIMOps = 0; | ||
1416 | } | ||
1417 | } | ||
1418 | } | ||
1419 | #endif // DOT11_N_SUPPORT // | ||
1420 | |||
1421 | #ifdef DBG_DIAGNOSE | ||
1422 | if (pTxBlk->QueIdx== 0) | ||
1423 | { | ||
1424 | pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; | ||
1425 | pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; | ||
1426 | } | ||
1427 | #endif // DBG_DIAGNOSE // | ||
1428 | |||
1429 | pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; | ||
1430 | |||
1431 | } | ||
1432 | |||
1433 | |||
1434 | /* | ||
1435 | ======================================================================== | ||
1436 | |||
1437 | Routine Description: | ||
1438 | Calculates the duration which is required to transmit out frames | ||
1439 | with given size and specified rate. | ||
1440 | |||
1441 | Arguments: | ||
1442 | pTxD Pointer to transmit descriptor | ||
1443 | Ack Setting for Ack requirement bit | ||
1444 | Fragment Setting for Fragment bit | ||
1445 | RetryMode Setting for retry mode | ||
1446 | Ifs Setting for IFS gap | ||
1447 | Rate Setting for transmit rate | ||
1448 | Service Setting for service | ||
1449 | Length Frame length | ||
1450 | TxPreamble Short or Long preamble when using CCK rates | ||
1451 | QueIdx - 0-3, according to 802.11e/d4.4 June/2003 | ||
1452 | |||
1453 | Return Value: | ||
1454 | None | ||
1455 | |||
1456 | IRQL = PASSIVE_LEVEL | ||
1457 | IRQL = DISPATCH_LEVEL | ||
1458 | |||
1459 | ======================================================================== | ||
1460 | */ | ||
1461 | VOID RTMPWriteTxDescriptor( | ||
1462 | IN PRTMP_ADAPTER pAd, | ||
1463 | IN PTXD_STRUC pTxD, | ||
1464 | IN BOOLEAN bWIV, | ||
1465 | IN UCHAR QueueSEL) | ||
1466 | { | ||
1467 | // | ||
1468 | // Always use Long preamble before verifiation short preamble functionality works well. | ||
1469 | // Todo: remove the following line if short preamble functionality works | ||
1470 | // | ||
1471 | OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); | ||
1472 | |||
1473 | pTxD->WIV = (bWIV) ? 1: 0; | ||
1474 | pTxD->QSEL= (QueueSEL); | ||
1475 | if (pAd->bGenOneHCCA == TRUE) | ||
1476 | pTxD->QSEL= FIFO_HCCA; | ||
1477 | pTxD->DMADONE = 0; | ||
1478 | } | ||
1479 | |||
1480 | |||
1481 | // should be called only when - | ||
1482 | // 1. MEADIA_CONNECTED | ||
1483 | // 2. AGGREGATION_IN_USED | ||
1484 | // 3. Fragmentation not in used | ||
1485 | // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible | ||
1486 | BOOLEAN TxFrameIsAggregatible( | ||
1487 | IN PRTMP_ADAPTER pAd, | ||
1488 | IN PUCHAR pPrevAddr1, | ||
1489 | IN PUCHAR p8023hdr) | ||
1490 | { | ||
1491 | |||
1492 | // can't aggregate EAPOL (802.1x) frame | ||
1493 | if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) | ||
1494 | return FALSE; | ||
1495 | |||
1496 | // can't aggregate multicast/broadcast frame | ||
1497 | if (p8023hdr[0] & 0x01) | ||
1498 | return FALSE; | ||
1499 | |||
1500 | if (INFRA_ON(pAd)) // must be unicast to AP | ||
1501 | return TRUE; | ||
1502 | else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA | ||
1503 | return TRUE; | ||
1504 | else | ||
1505 | return FALSE; | ||
1506 | } | ||
1507 | |||
1508 | |||
1509 | /* | ||
1510 | ======================================================================== | ||
1511 | |||
1512 | Routine Description: | ||
1513 | Check the MSDU Aggregation policy | ||
1514 | 1.HT aggregation is A-MSDU | ||
1515 | 2.legaacy rate aggregation is software aggregation by Ralink. | ||
1516 | |||
1517 | Arguments: | ||
1518 | |||
1519 | Return Value: | ||
1520 | |||
1521 | Note: | ||
1522 | |||
1523 | ======================================================================== | ||
1524 | */ | ||
1525 | BOOLEAN PeerIsAggreOn( | ||
1526 | IN PRTMP_ADAPTER pAd, | ||
1527 | IN ULONG TxRate, | ||
1528 | IN PMAC_TABLE_ENTRY pMacEntry) | ||
1529 | { | ||
1530 | ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); | ||
1531 | |||
1532 | if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) | ||
1533 | { | ||
1534 | #ifdef DOT11_N_SUPPORT | ||
1535 | if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) | ||
1536 | { | ||
1537 | return TRUE; | ||
1538 | } | ||
1539 | #endif // DOT11_N_SUPPORT // | ||
1540 | |||
1541 | #ifdef AGGREGATION_SUPPORT | ||
1542 | if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) | ||
1543 | { // legacy Ralink Aggregation support | ||
1544 | return TRUE; | ||
1545 | } | ||
1546 | #endif // AGGREGATION_SUPPORT // | ||
1547 | } | ||
1548 | |||
1549 | return FALSE; | ||
1550 | |||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /* | ||
1555 | ======================================================================== | ||
1556 | |||
1557 | Routine Description: | ||
1558 | Check and fine the packet waiting in SW queue with highest priority | ||
1559 | |||
1560 | Arguments: | ||
1561 | pAd Pointer to our adapter | ||
1562 | |||
1563 | Return Value: | ||
1564 | pQueue Pointer to Waiting Queue | ||
1565 | |||
1566 | IRQL = DISPATCH_LEVEL | ||
1567 | |||
1568 | Note: | ||
1569 | |||
1570 | ======================================================================== | ||
1571 | */ | ||
1572 | PQUEUE_HEADER RTMPCheckTxSwQueue( | ||
1573 | IN PRTMP_ADAPTER pAd, | ||
1574 | OUT PUCHAR pQueIdx) | ||
1575 | { | ||
1576 | |||
1577 | ULONG Number; | ||
1578 | // 2004-11-15 to be removed. test aggregation only | ||
1579 | // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) | ||
1580 | // return NULL; | ||
1581 | |||
1582 | Number = pAd->TxSwQueue[QID_AC_BK].Number | ||
1583 | + pAd->TxSwQueue[QID_AC_BE].Number | ||
1584 | + pAd->TxSwQueue[QID_AC_VI].Number | ||
1585 | + pAd->TxSwQueue[QID_AC_VO].Number | ||
1586 | + pAd->TxSwQueue[QID_HCCA].Number; | ||
1587 | |||
1588 | if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) | ||
1589 | { | ||
1590 | *pQueIdx = QID_AC_VO; | ||
1591 | return (&pAd->TxSwQueue[QID_AC_VO]); | ||
1592 | } | ||
1593 | else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) | ||
1594 | { | ||
1595 | *pQueIdx = QID_AC_VI; | ||
1596 | return (&pAd->TxSwQueue[QID_AC_VI]); | ||
1597 | } | ||
1598 | else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) | ||
1599 | { | ||
1600 | *pQueIdx = QID_AC_BE; | ||
1601 | return (&pAd->TxSwQueue[QID_AC_BE]); | ||
1602 | } | ||
1603 | else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) | ||
1604 | { | ||
1605 | *pQueIdx = QID_AC_BK; | ||
1606 | return (&pAd->TxSwQueue[QID_AC_BK]); | ||
1607 | } | ||
1608 | else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) | ||
1609 | { | ||
1610 | *pQueIdx = QID_HCCA; | ||
1611 | return (&pAd->TxSwQueue[QID_HCCA]); | ||
1612 | } | ||
1613 | |||
1614 | // No packet pending in Tx Sw queue | ||
1615 | *pQueIdx = QID_AC_BK; | ||
1616 | |||
1617 | return (NULL); | ||
1618 | } | ||
1619 | |||
1620 | |||
1621 | |||
1622 | /* | ||
1623 | ======================================================================== | ||
1624 | |||
1625 | Routine Description: | ||
1626 | Suspend MSDU transmission | ||
1627 | |||
1628 | Arguments: | ||
1629 | pAd Pointer to our adapter | ||
1630 | |||
1631 | Return Value: | ||
1632 | None | ||
1633 | |||
1634 | Note: | ||
1635 | |||
1636 | ======================================================================== | ||
1637 | */ | ||
1638 | VOID RTMPSuspendMsduTransmission( | ||
1639 | IN PRTMP_ADAPTER pAd) | ||
1640 | { | ||
1641 | DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); | ||
1642 | |||
1643 | |||
1644 | // | ||
1645 | // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and | ||
1646 | // use Lowbound as R66 value on ScanNextChannel(...) | ||
1647 | // | ||
1648 | RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); | ||
1649 | |||
1650 | // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) | ||
1651 | //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); | ||
1652 | RTMPSetAGCInitValue(pAd, BW_20); | ||
1653 | |||
1654 | RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
1655 | //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings | ||
1656 | } | ||
1657 | |||
1658 | |||
1659 | /* | ||
1660 | ======================================================================== | ||
1661 | |||
1662 | Routine Description: | ||
1663 | Resume MSDU transmission | ||
1664 | |||
1665 | Arguments: | ||
1666 | pAd Pointer to our adapter | ||
1667 | |||
1668 | Return Value: | ||
1669 | None | ||
1670 | |||
1671 | IRQL = DISPATCH_LEVEL | ||
1672 | |||
1673 | Note: | ||
1674 | |||
1675 | ======================================================================== | ||
1676 | */ | ||
1677 | VOID RTMPResumeMsduTransmission( | ||
1678 | IN PRTMP_ADAPTER pAd) | ||
1679 | { | ||
1680 | // UCHAR IrqState; | ||
1681 | |||
1682 | DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); | ||
1683 | |||
1684 | |||
1685 | // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value | ||
1686 | // R66 should not be 0 | ||
1687 | if (pAd->BbpTuning.R66CurrentValue == 0) | ||
1688 | { | ||
1689 | pAd->BbpTuning.R66CurrentValue = 0x38; | ||
1690 | DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); | ||
1691 | } | ||
1692 | RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); | ||
1693 | |||
1694 | RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); | ||
1695 | // sample, for IRQ LOCK to SEM LOCK | ||
1696 | // IrqState = pAd->irq_disabled; | ||
1697 | // if (IrqState) | ||
1698 | // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); | ||
1699 | // else | ||
1700 | RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); | ||
1701 | } | ||
1702 | |||
1703 | |||
1704 | UINT deaggregate_AMSDU_announce( | ||
1705 | IN PRTMP_ADAPTER pAd, | ||
1706 | PNDIS_PACKET pPacket, | ||
1707 | IN PUCHAR pData, | ||
1708 | IN ULONG DataSize) | ||
1709 | { | ||
1710 | USHORT PayloadSize; | ||
1711 | USHORT SubFrameSize; | ||
1712 | PHEADER_802_3 pAMSDUsubheader; | ||
1713 | UINT nMSDU; | ||
1714 | UCHAR Header802_3[14]; | ||
1715 | |||
1716 | PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; | ||
1717 | PNDIS_PACKET pClonePacket; | ||
1718 | |||
1719 | |||
1720 | |||
1721 | nMSDU = 0; | ||
1722 | |||
1723 | while (DataSize > LENGTH_802_3) | ||
1724 | { | ||
1725 | |||
1726 | nMSDU++; | ||
1727 | |||
1728 | //hex_dump("subheader", pData, 64); | ||
1729 | pAMSDUsubheader = (PHEADER_802_3)pData; | ||
1730 | //pData += LENGTH_802_3; | ||
1731 | PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); | ||
1732 | SubFrameSize = PayloadSize + LENGTH_802_3; | ||
1733 | |||
1734 | |||
1735 | if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) | ||
1736 | { | ||
1737 | break; | ||
1738 | } | ||
1739 | |||
1740 | //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize); | ||
1741 | |||
1742 | pPayload = pData + LENGTH_802_3; | ||
1743 | pDA = pData; | ||
1744 | pSA = pData + MAC_ADDR_LEN; | ||
1745 | |||
1746 | // convert to 802.3 header | ||
1747 | CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); | ||
1748 | |||
1749 | #ifdef CONFIG_STA_SUPPORT | ||
1750 | if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) | ||
1751 | { | ||
1752 | // avoid local heap overflow, use dyanamic allocation | ||
1753 | MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); | ||
1754 | memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); | ||
1755 | Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; | ||
1756 | WpaEAPOLKeyAction(pAd, Elem); | ||
1757 | kfree(Elem); | ||
1758 | } | ||
1759 | #endif // CONFIG_STA_SUPPORT // | ||
1760 | |||
1761 | #ifdef CONFIG_STA_SUPPORT | ||
1762 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1763 | { | ||
1764 | if (pRemovedLLCSNAP) | ||
1765 | { | ||
1766 | pPayload -= LENGTH_802_3; | ||
1767 | PayloadSize += LENGTH_802_3; | ||
1768 | NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); | ||
1769 | } | ||
1770 | } | ||
1771 | #endif // CONFIG_STA_SUPPORT // | ||
1772 | |||
1773 | pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); | ||
1774 | if (pClonePacket) | ||
1775 | { | ||
1776 | #ifdef CONFIG_STA_SUPPORT | ||
1777 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1778 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); | ||
1779 | #endif // CONFIG_STA_SUPPORT // | ||
1780 | } | ||
1781 | |||
1782 | |||
1783 | // A-MSDU has padding to multiple of 4 including subframe header. | ||
1784 | // align SubFrameSize up to multiple of 4 | ||
1785 | SubFrameSize = (SubFrameSize+3)&(~0x3); | ||
1786 | |||
1787 | |||
1788 | if (SubFrameSize > 1528 || SubFrameSize < 32) | ||
1789 | { | ||
1790 | break; | ||
1791 | } | ||
1792 | |||
1793 | if (DataSize > SubFrameSize) | ||
1794 | { | ||
1795 | pData += SubFrameSize; | ||
1796 | DataSize -= SubFrameSize; | ||
1797 | } | ||
1798 | else | ||
1799 | { | ||
1800 | // end of A-MSDU | ||
1801 | DataSize = 0; | ||
1802 | } | ||
1803 | } | ||
1804 | |||
1805 | // finally release original rx packet | ||
1806 | RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); | ||
1807 | |||
1808 | return nMSDU; | ||
1809 | } | ||
1810 | |||
1811 | |||
1812 | UINT BA_Reorder_AMSDU_Annnounce( | ||
1813 | IN PRTMP_ADAPTER pAd, | ||
1814 | IN PNDIS_PACKET pPacket) | ||
1815 | { | ||
1816 | PUCHAR pData; | ||
1817 | USHORT DataSize; | ||
1818 | UINT nMSDU = 0; | ||
1819 | |||
1820 | pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); | ||
1821 | DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); | ||
1822 | |||
1823 | nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); | ||
1824 | |||
1825 | return nMSDU; | ||
1826 | } | ||
1827 | |||
1828 | |||
1829 | /* | ||
1830 | ========================================================================== | ||
1831 | Description: | ||
1832 | Look up the MAC address in the MAC table. Return NULL if not found. | ||
1833 | Return: | ||
1834 | pEntry - pointer to the MAC entry; NULL is not found | ||
1835 | ========================================================================== | ||
1836 | */ | ||
1837 | MAC_TABLE_ENTRY *MacTableLookup( | ||
1838 | IN PRTMP_ADAPTER pAd, | ||
1839 | PUCHAR pAddr) | ||
1840 | { | ||
1841 | ULONG HashIdx; | ||
1842 | MAC_TABLE_ENTRY *pEntry = NULL; | ||
1843 | |||
1844 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
1845 | pEntry = pAd->MacTab.Hash[HashIdx]; | ||
1846 | |||
1847 | while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) | ||
1848 | { | ||
1849 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) | ||
1850 | { | ||
1851 | break; | ||
1852 | } | ||
1853 | else | ||
1854 | pEntry = pEntry->pNext; | ||
1855 | } | ||
1856 | |||
1857 | return pEntry; | ||
1858 | } | ||
1859 | |||
1860 | MAC_TABLE_ENTRY *MacTableInsertEntry( | ||
1861 | IN PRTMP_ADAPTER pAd, | ||
1862 | IN PUCHAR pAddr, | ||
1863 | IN UCHAR apidx, | ||
1864 | IN BOOLEAN CleanAll) | ||
1865 | { | ||
1866 | UCHAR HashIdx; | ||
1867 | int i, FirstWcid; | ||
1868 | MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; | ||
1869 | // USHORT offset; | ||
1870 | // ULONG addr; | ||
1871 | |||
1872 | // if FULL, return | ||
1873 | if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) | ||
1874 | return NULL; | ||
1875 | |||
1876 | FirstWcid = 1; | ||
1877 | #ifdef CONFIG_STA_SUPPORT | ||
1878 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1879 | if (pAd->StaCfg.BssType == BSS_INFRA) | ||
1880 | FirstWcid = 2; | ||
1881 | #endif // CONFIG_STA_SUPPORT // | ||
1882 | |||
1883 | // allocate one MAC entry | ||
1884 | NdisAcquireSpinLock(&pAd->MacTabLock); | ||
1885 | for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup | ||
1886 | { | ||
1887 | // pick up the first available vacancy | ||
1888 | if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && | ||
1889 | (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && | ||
1890 | (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && | ||
1891 | (pAd->MacTab.Content[i].ValidAsMesh == FALSE) | ||
1892 | #ifdef CONFIG_STA_SUPPORT | ||
1893 | #ifdef QOS_DLS_SUPPORT | ||
1894 | && (pAd->MacTab.Content[i].ValidAsDls == FALSE) | ||
1895 | #endif // QOS_DLS_SUPPORT // | ||
1896 | #endif // CONFIG_STA_SUPPORT // | ||
1897 | ) | ||
1898 | { | ||
1899 | pEntry = &pAd->MacTab.Content[i]; | ||
1900 | if (CleanAll == TRUE) | ||
1901 | { | ||
1902 | pEntry->MaxSupportedRate = RATE_11; | ||
1903 | pEntry->CurrTxRate = RATE_11; | ||
1904 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); | ||
1905 | pEntry->PairwiseKey.KeyLen = 0; | ||
1906 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | ||
1907 | } | ||
1908 | #ifdef CONFIG_STA_SUPPORT | ||
1909 | #ifdef QOS_DLS_SUPPORT | ||
1910 | if (apidx >= MIN_NET_DEVICE_FOR_DLS) | ||
1911 | { | ||
1912 | pEntry->ValidAsCLI = FALSE; | ||
1913 | pEntry->ValidAsWDS = FALSE; | ||
1914 | pEntry->ValidAsApCli = FALSE; | ||
1915 | pEntry->ValidAsMesh = FALSE; | ||
1916 | pEntry->ValidAsDls = TRUE; | ||
1917 | pEntry->isCached = FALSE; | ||
1918 | } | ||
1919 | else | ||
1920 | #endif // QOS_DLS_SUPPORT // | ||
1921 | #endif // CONFIG_STA_SUPPORT // | ||
1922 | { | ||
1923 | |||
1924 | #ifdef CONFIG_STA_SUPPORT | ||
1925 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1926 | { | ||
1927 | pEntry->ValidAsCLI = TRUE; | ||
1928 | pEntry->ValidAsWDS = FALSE; | ||
1929 | pEntry->ValidAsApCli = FALSE; | ||
1930 | pEntry->ValidAsMesh = FALSE; | ||
1931 | pEntry->ValidAsDls = FALSE; | ||
1932 | } | ||
1933 | #endif // CONFIG_STA_SUPPORT // | ||
1934 | } | ||
1935 | |||
1936 | pEntry->bIAmBadAtheros = FALSE; | ||
1937 | pEntry->pAd = pAd; | ||
1938 | pEntry->CMTimerRunning = FALSE; | ||
1939 | pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; | ||
1940 | pEntry->RSNIE_Len = 0; | ||
1941 | NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); | ||
1942 | pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; | ||
1943 | |||
1944 | if (pEntry->ValidAsMesh) | ||
1945 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); | ||
1946 | else if (pEntry->ValidAsApCli) | ||
1947 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); | ||
1948 | else if (pEntry->ValidAsWDS) | ||
1949 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); | ||
1950 | #ifdef CONFIG_STA_SUPPORT | ||
1951 | #ifdef QOS_DLS_SUPPORT | ||
1952 | else if (pEntry->ValidAsDls) | ||
1953 | pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS); | ||
1954 | #endif // QOS_DLS_SUPPORT // | ||
1955 | #endif // CONFIG_STA_SUPPORT // | ||
1956 | else | ||
1957 | pEntry->apidx = apidx; | ||
1958 | |||
1959 | { | ||
1960 | |||
1961 | #ifdef CONFIG_STA_SUPPORT | ||
1962 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
1963 | { | ||
1964 | pEntry->AuthMode = pAd->StaCfg.AuthMode; | ||
1965 | pEntry->WepStatus = pAd->StaCfg.WepStatus; | ||
1966 | pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; | ||
1967 | } | ||
1968 | #endif // CONFIG_STA_SUPPORT // | ||
1969 | } | ||
1970 | |||
1971 | pEntry->GTKState = REKEY_NEGOTIATING; | ||
1972 | pEntry->PairwiseKey.KeyLen = 0; | ||
1973 | pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; | ||
1974 | #ifdef CONFIG_STA_SUPPORT | ||
1975 | #ifdef QOS_DLS_SUPPORT | ||
1976 | if (pEntry->ValidAsDls == TRUE) | ||
1977 | pEntry->PortSecured = WPA_802_1X_PORT_SECURED; | ||
1978 | else | ||
1979 | #endif //QOS_DLS_SUPPORT | ||
1980 | #endif // CONFIG_STA_SUPPORT // | ||
1981 | pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; | ||
1982 | pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; | ||
1983 | COPY_MAC_ADDR(pEntry->Addr, pAddr); | ||
1984 | pEntry->Sst = SST_NOT_AUTH; | ||
1985 | pEntry->AuthState = AS_NOT_AUTH; | ||
1986 | pEntry->Aid = (USHORT)i; //0; | ||
1987 | pEntry->CapabilityInfo = 0; | ||
1988 | pEntry->PsMode = PWR_ACTIVE; | ||
1989 | pEntry->PsQIdleCount = 0; | ||
1990 | pEntry->NoDataIdleCount = 0; | ||
1991 | pEntry->ContinueTxFailCnt = 0; | ||
1992 | InitializeQueueHeader(&pEntry->PsQueue); | ||
1993 | |||
1994 | |||
1995 | pAd->MacTab.Size ++; | ||
1996 | |||
1997 | // Add this entry into ASIC RX WCID search table | ||
1998 | RT28XX_STA_ENTRY_ADD(pAd, pEntry); | ||
1999 | |||
2000 | |||
2001 | |||
2002 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); | ||
2003 | break; | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | // add this MAC entry into HASH table | ||
2008 | if (pEntry) | ||
2009 | { | ||
2010 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
2011 | if (pAd->MacTab.Hash[HashIdx] == NULL) | ||
2012 | { | ||
2013 | pAd->MacTab.Hash[HashIdx] = pEntry; | ||
2014 | } | ||
2015 | else | ||
2016 | { | ||
2017 | pCurrEntry = pAd->MacTab.Hash[HashIdx]; | ||
2018 | while (pCurrEntry->pNext != NULL) | ||
2019 | pCurrEntry = pCurrEntry->pNext; | ||
2020 | pCurrEntry->pNext = pEntry; | ||
2021 | } | ||
2022 | } | ||
2023 | |||
2024 | NdisReleaseSpinLock(&pAd->MacTabLock); | ||
2025 | return pEntry; | ||
2026 | } | ||
2027 | |||
2028 | /* | ||
2029 | ========================================================================== | ||
2030 | Description: | ||
2031 | Delete a specified client from MAC table | ||
2032 | ========================================================================== | ||
2033 | */ | ||
2034 | BOOLEAN MacTableDeleteEntry( | ||
2035 | IN PRTMP_ADAPTER pAd, | ||
2036 | IN USHORT wcid, | ||
2037 | IN PUCHAR pAddr) | ||
2038 | { | ||
2039 | USHORT HashIdx; | ||
2040 | MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; | ||
2041 | BOOLEAN Cancelled; | ||
2042 | //USHORT offset; // unused variable | ||
2043 | //UCHAR j; // unused variable | ||
2044 | |||
2045 | if (wcid >= MAX_LEN_OF_MAC_TABLE) | ||
2046 | return FALSE; | ||
2047 | |||
2048 | NdisAcquireSpinLock(&pAd->MacTabLock); | ||
2049 | |||
2050 | HashIdx = MAC_ADDR_HASH_INDEX(pAddr); | ||
2051 | //pEntry = pAd->MacTab.Hash[HashIdx]; | ||
2052 | pEntry = &pAd->MacTab.Content[wcid]; | ||
2053 | |||
2054 | if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh | ||
2055 | #ifdef CONFIG_STA_SUPPORT | ||
2056 | #ifdef QOS_DLS_SUPPORT | ||
2057 | || pEntry->ValidAsDls | ||
2058 | #endif // QOS_DLS_SUPPORT // | ||
2059 | #endif // CONFIG_STA_SUPPORT // | ||
2060 | )) | ||
2061 | { | ||
2062 | if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) | ||
2063 | { | ||
2064 | |||
2065 | // Delete this entry from ASIC on-chip WCID Table | ||
2066 | RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid); | ||
2067 | |||
2068 | #ifdef DOT11_N_SUPPORT | ||
2069 | // free resources of BA | ||
2070 | BASessionTearDownALL(pAd, pEntry->Aid); | ||
2071 | #endif // DOT11_N_SUPPORT // | ||
2072 | |||
2073 | |||
2074 | pPrevEntry = NULL; | ||
2075 | pProbeEntry = pAd->MacTab.Hash[HashIdx]; | ||
2076 | ASSERT(pProbeEntry); | ||
2077 | |||
2078 | // update Hash list | ||
2079 | do | ||
2080 | { | ||
2081 | if (pProbeEntry == pEntry) | ||
2082 | { | ||
2083 | if (pPrevEntry == NULL) | ||
2084 | { | ||
2085 | pAd->MacTab.Hash[HashIdx] = pEntry->pNext; | ||
2086 | } | ||
2087 | else | ||
2088 | { | ||
2089 | pPrevEntry->pNext = pEntry->pNext; | ||
2090 | } | ||
2091 | break; | ||
2092 | } | ||
2093 | |||
2094 | pPrevEntry = pProbeEntry; | ||
2095 | pProbeEntry = pProbeEntry->pNext; | ||
2096 | } while (pProbeEntry); | ||
2097 | |||
2098 | // not found !!! | ||
2099 | ASSERT(pProbeEntry != NULL); | ||
2100 | |||
2101 | RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); | ||
2102 | |||
2103 | |||
2104 | if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) | ||
2105 | { | ||
2106 | RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); | ||
2107 | pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; | ||
2108 | } | ||
2109 | |||
2110 | |||
2111 | NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); | ||
2112 | pAd->MacTab.Size --; | ||
2113 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); | ||
2114 | } | ||
2115 | else | ||
2116 | { | ||
2117 | printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid); | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | NdisReleaseSpinLock(&pAd->MacTabLock); | ||
2122 | |||
2123 | //Reset operating mode when no Sta. | ||
2124 | if (pAd->MacTab.Size == 0) | ||
2125 | { | ||
2126 | #ifdef DOT11_N_SUPPORT | ||
2127 | pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; | ||
2128 | #endif // DOT11_N_SUPPORT // | ||
2129 | //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); | ||
2130 | RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet | ||
2131 | } | ||
2132 | |||
2133 | return TRUE; | ||
2134 | } | ||
2135 | |||
2136 | |||
2137 | /* | ||
2138 | ========================================================================== | ||
2139 | Description: | ||
2140 | This routine reset the entire MAC table. All packets pending in | ||
2141 | the power-saving queues are freed here. | ||
2142 | ========================================================================== | ||
2143 | */ | ||
2144 | VOID MacTableReset( | ||
2145 | IN PRTMP_ADAPTER pAd) | ||
2146 | { | ||
2147 | int i; | ||
2148 | |||
2149 | DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); | ||
2150 | //NdisAcquireSpinLock(&pAd->MacTabLock); | ||
2151 | |||
2152 | for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++) | ||
2153 | { | ||
2154 | if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) | ||
2155 | { | ||
2156 | |||
2157 | #ifdef DOT11_N_SUPPORT | ||
2158 | // free resources of BA | ||
2159 | BASessionTearDownALL(pAd, i); | ||
2160 | #endif // DOT11_N_SUPPORT // | ||
2161 | |||
2162 | pAd->MacTab.Content[i].ValidAsCLI = FALSE; | ||
2163 | |||
2164 | |||
2165 | |||
2166 | #ifdef RT2870 | ||
2167 | NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); | ||
2168 | RT28XX_STA_ENTRY_MAC_RESET(pAd, i); | ||
2169 | #endif // RT2870 // | ||
2170 | |||
2171 | //AsicDelWcidTab(pAd, i); | ||
2172 | } | ||
2173 | } | ||
2174 | |||
2175 | return; | ||
2176 | } | ||
2177 | |||
2178 | /* | ||
2179 | ========================================================================== | ||
2180 | Description: | ||
2181 | |||
2182 | IRQL = DISPATCH_LEVEL | ||
2183 | |||
2184 | ========================================================================== | ||
2185 | */ | ||
2186 | VOID AssocParmFill( | ||
2187 | IN PRTMP_ADAPTER pAd, | ||
2188 | IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, | ||
2189 | IN PUCHAR pAddr, | ||
2190 | IN USHORT CapabilityInfo, | ||
2191 | IN ULONG Timeout, | ||
2192 | IN USHORT ListenIntv) | ||
2193 | { | ||
2194 | COPY_MAC_ADDR(AssocReq->Addr, pAddr); | ||
2195 | // Add mask to support 802.11b mode only | ||
2196 | AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request | ||
2197 | AssocReq->Timeout = Timeout; | ||
2198 | AssocReq->ListenIntv = ListenIntv; | ||
2199 | } | ||
2200 | |||
2201 | |||
2202 | /* | ||
2203 | ========================================================================== | ||
2204 | Description: | ||
2205 | |||
2206 | IRQL = DISPATCH_LEVEL | ||
2207 | |||
2208 | ========================================================================== | ||
2209 | */ | ||
2210 | VOID DisassocParmFill( | ||
2211 | IN PRTMP_ADAPTER pAd, | ||
2212 | IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, | ||
2213 | IN PUCHAR pAddr, | ||
2214 | IN USHORT Reason) | ||
2215 | { | ||
2216 | COPY_MAC_ADDR(DisassocReq->Addr, pAddr); | ||
2217 | DisassocReq->Reason = Reason; | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | /* | ||
2222 | ======================================================================== | ||
2223 | |||
2224 | Routine Description: | ||
2225 | Check the out going frame, if this is an DHCP or ARP datagram | ||
2226 | will be duplicate another frame at low data rate transmit. | ||
2227 | |||
2228 | Arguments: | ||
2229 | pAd Pointer to our adapter | ||
2230 | pPacket Pointer to outgoing Ndis frame | ||
2231 | |||
2232 | Return Value: | ||
2233 | TRUE To be duplicate at Low data rate transmit. (1mb) | ||
2234 | FALSE Do nothing. | ||
2235 | |||
2236 | IRQL = DISPATCH_LEVEL | ||
2237 | |||
2238 | Note: | ||
2239 | |||
2240 | MAC header + IP Header + UDP Header | ||
2241 | 14 Bytes 20 Bytes | ||
2242 | |||
2243 | UDP Header | ||
2244 | 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| | ||
2245 | Source Port | ||
2246 | 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| | ||
2247 | Destination Port | ||
2248 | |||
2249 | port 0x43 means Bootstrap Protocol, server. | ||
2250 | Port 0x44 means Bootstrap Protocol, client. | ||
2251 | |||
2252 | ======================================================================== | ||
2253 | */ | ||
2254 | |||
2255 | BOOLEAN RTMPCheckDHCPFrame( | ||
2256 | IN PRTMP_ADAPTER pAd, | ||
2257 | IN PNDIS_PACKET pPacket) | ||
2258 | { | ||
2259 | PACKET_INFO PacketInfo; | ||
2260 | ULONG NumberOfBytesRead = 0; | ||
2261 | ULONG CurrentOffset = 0; | ||
2262 | PVOID pVirtualAddress = NULL; | ||
2263 | UINT NdisBufferLength; | ||
2264 | PUCHAR pSrc; | ||
2265 | USHORT Protocol; | ||
2266 | UCHAR ByteOffset36 = 0; | ||
2267 | UCHAR ByteOffset38 = 0; | ||
2268 | BOOLEAN ReadFirstParm = TRUE; | ||
2269 | |||
2270 | RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); | ||
2271 | |||
2272 | NumberOfBytesRead += NdisBufferLength; | ||
2273 | pSrc = (PUCHAR) pVirtualAddress; | ||
2274 | Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); | ||
2275 | |||
2276 | // | ||
2277 | // Check DHCP & BOOTP protocol | ||
2278 | // | ||
2279 | while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) | ||
2280 | { | ||
2281 | if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) | ||
2282 | { | ||
2283 | CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); | ||
2284 | ByteOffset36 = *(pSrc + CurrentOffset); | ||
2285 | ReadFirstParm = FALSE; | ||
2286 | } | ||
2287 | |||
2288 | if (NumberOfBytesRead >= 37) | ||
2289 | { | ||
2290 | CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); | ||
2291 | ByteOffset38 = *(pSrc + CurrentOffset); | ||
2292 | //End of Read | ||
2293 | break; | ||
2294 | } | ||
2295 | return FALSE; | ||
2296 | } | ||
2297 | |||
2298 | // Check for DHCP & BOOTP protocol | ||
2299 | if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) | ||
2300 | { | ||
2301 | // | ||
2302 | // 2054 (hex 0806) for ARP datagrams | ||
2303 | // if this packet is not ARP datagrams, then do nothing | ||
2304 | // ARP datagrams will also be duplicate at 1mb broadcast frames | ||
2305 | // | ||
2306 | if (Protocol != 0x0806 ) | ||
2307 | return FALSE; | ||
2308 | } | ||
2309 | |||
2310 | return TRUE; | ||
2311 | } | ||
2312 | |||
2313 | |||
2314 | BOOLEAN RTMPCheckEtherType( | ||
2315 | IN PRTMP_ADAPTER pAd, | ||
2316 | IN PNDIS_PACKET pPacket) | ||
2317 | { | ||
2318 | USHORT TypeLen; | ||
2319 | UCHAR Byte0, Byte1; | ||
2320 | PUCHAR pSrcBuf; | ||
2321 | UINT32 pktLen; | ||
2322 | UINT16 srcPort, dstPort; | ||
2323 | BOOLEAN status = TRUE; | ||
2324 | |||
2325 | |||
2326 | pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); | ||
2327 | pktLen = GET_OS_PKT_LEN(pPacket); | ||
2328 | |||
2329 | ASSERT(pSrcBuf); | ||
2330 | |||
2331 | RTMP_SET_PACKET_SPECIFIC(pPacket, 0); | ||
2332 | |||
2333 | // get Ethernet protocol field | ||
2334 | TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; | ||
2335 | |||
2336 | pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. | ||
2337 | |||
2338 | if (TypeLen <= 1500) | ||
2339 | { // 802.3, 802.3 LLC | ||
2340 | /* | ||
2341 | DestMAC(6) + SrcMAC(6) + Lenght(2) + | ||
2342 | DSAP(1) + SSAP(1) + Control(1) + | ||
2343 | if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. | ||
2344 | => + SNAP (5, OriginationID(3) + etherType(2)) | ||
2345 | */ | ||
2346 | if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) | ||
2347 | { | ||
2348 | Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1); | ||
2349 | RTMP_SET_PACKET_LLCSNAP(pPacket, 1); | ||
2350 | TypeLen = (USHORT)((Byte0 << 8) + Byte1); | ||
2351 | pSrcBuf += 8; // Skip this LLC/SNAP header | ||
2352 | } | ||
2353 | else | ||
2354 | { | ||
2355 | //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. | ||
2356 | } | ||
2357 | } | ||
2358 | |||
2359 | // If it's a VLAN packet, get the real Type/Length field. | ||
2360 | if (TypeLen == 0x8100) | ||
2361 | { | ||
2362 | /* 0x8100 means VLAN packets */ | ||
2363 | |||
2364 | /* Dest. MAC Address (6-bytes) + | ||
2365 | Source MAC Address (6-bytes) + | ||
2366 | Length/Type = 802.1Q Tag Type (2-byte) + | ||
2367 | Tag Control Information (2-bytes) + | ||
2368 | Length / Type (2-bytes) + | ||
2369 | data payload (0-n bytes) + | ||
2370 | Pad (0-p bytes) + | ||
2371 | Frame Check Sequence (4-bytes) */ | ||
2372 | |||
2373 | RTMP_SET_PACKET_VLAN(pPacket, 1); | ||
2374 | Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1); | ||
2375 | TypeLen = (USHORT)((Byte0 << 8) + Byte1); | ||
2376 | |||
2377 | pSrcBuf += 4; // Skip the VLAN Header. | ||
2378 | } | ||
2379 | |||
2380 | switch (TypeLen) | ||
2381 | { | ||
2382 | case 0x0800: | ||
2383 | { | ||
2384 | ASSERT((pktLen > 34)); | ||
2385 | if (*(pSrcBuf + 9) == 0x11) | ||
2386 | { // udp packet | ||
2387 | ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header | ||
2388 | |||
2389 | pSrcBuf += 20; // Skip the IP header | ||
2390 | srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf)); | ||
2391 | dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2))); | ||
2392 | |||
2393 | if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) | ||
2394 | { //It's a BOOTP/DHCP packet | ||
2395 | RTMP_SET_PACKET_DHCP(pPacket, 1); | ||
2396 | } | ||
2397 | } | ||
2398 | } | ||
2399 | break; | ||
2400 | case 0x0806: | ||
2401 | { | ||
2402 | //ARP Packet. | ||
2403 | RTMP_SET_PACKET_DHCP(pPacket, 1); | ||
2404 | } | ||
2405 | break; | ||
2406 | case 0x888e: | ||
2407 | { | ||
2408 | // EAPOL Packet. | ||
2409 | RTMP_SET_PACKET_EAPOL(pPacket, 1); | ||
2410 | } | ||
2411 | break; | ||
2412 | default: | ||
2413 | status = FALSE; | ||
2414 | break; | ||
2415 | } | ||
2416 | |||
2417 | return status; | ||
2418 | |||
2419 | } | ||
2420 | |||
2421 | |||
2422 | |||
2423 | VOID Update_Rssi_Sample( | ||
2424 | IN PRTMP_ADAPTER pAd, | ||
2425 | IN RSSI_SAMPLE *pRssi, | ||
2426 | IN PRXWI_STRUC pRxWI) | ||
2427 | { | ||
2428 | CHAR rssi0 = pRxWI->RSSI0; | ||
2429 | CHAR rssi1 = pRxWI->RSSI1; | ||
2430 | CHAR rssi2 = pRxWI->RSSI2; | ||
2431 | |||
2432 | if (rssi0 != 0) | ||
2433 | { | ||
2434 | pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); | ||
2435 | pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; | ||
2436 | pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; | ||
2437 | } | ||
2438 | |||
2439 | if (rssi1 != 0) | ||
2440 | { | ||
2441 | pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); | ||
2442 | pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; | ||
2443 | pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; | ||
2444 | } | ||
2445 | |||
2446 | if (rssi2 != 0) | ||
2447 | { | ||
2448 | pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); | ||
2449 | pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; | ||
2450 | pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; | ||
2451 | } | ||
2452 | } | ||
2453 | |||
2454 | |||
2455 | |||
2456 | // Normal legacy Rx packet indication | ||
2457 | VOID Indicate_Legacy_Packet( | ||
2458 | IN PRTMP_ADAPTER pAd, | ||
2459 | IN RX_BLK *pRxBlk, | ||
2460 | IN UCHAR FromWhichBSSID) | ||
2461 | { | ||
2462 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; | ||
2463 | UCHAR Header802_3[LENGTH_802_3]; | ||
2464 | |||
2465 | // 1. get 802.3 Header | ||
2466 | // 2. remove LLC | ||
2467 | // a. pointer pRxBlk->pData to payload | ||
2468 | // b. modify pRxBlk->DataSize | ||
2469 | #ifdef CONFIG_STA_SUPPORT | ||
2470 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2471 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | ||
2472 | #endif // CONFIG_STA_SUPPORT // | ||
2473 | |||
2474 | if (pRxBlk->DataSize > MAX_RX_PKT_LEN) | ||
2475 | { | ||
2476 | // release packet | ||
2477 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | ||
2478 | return; | ||
2479 | } | ||
2480 | |||
2481 | |||
2482 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); | ||
2483 | |||
2484 | #ifdef RT2870 | ||
2485 | #ifdef DOT11_N_SUPPORT | ||
2486 | if (pAd->CommonCfg.bDisableReordering == 0) | ||
2487 | { | ||
2488 | PBA_REC_ENTRY pBAEntry; | ||
2489 | ULONG Now32; | ||
2490 | UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; | ||
2491 | UCHAR TID = pRxBlk->pRxWI->TID; | ||
2492 | USHORT Idx; | ||
2493 | |||
2494 | #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms | ||
2495 | |||
2496 | if (Wcid < MAX_LEN_OF_MAC_TABLE) | ||
2497 | { | ||
2498 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | ||
2499 | if (Idx != 0) | ||
2500 | { | ||
2501 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | ||
2502 | // update last rx time | ||
2503 | NdisGetSystemUpTime(&Now32); | ||
2504 | if ((pBAEntry->list.qlen > 0) && | ||
2505 | RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) | ||
2506 | ) | ||
2507 | { | ||
2508 | printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU); | ||
2509 | hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64); | ||
2510 | ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); | ||
2511 | } | ||
2512 | } | ||
2513 | } | ||
2514 | } | ||
2515 | #endif // DOT11_N_SUPPORT // | ||
2516 | #endif // RT2870 // | ||
2517 | |||
2518 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | ||
2519 | |||
2520 | // | ||
2521 | // pass this 802.3 packet to upper layer or forward this packet to WM directly | ||
2522 | // | ||
2523 | #ifdef CONFIG_STA_SUPPORT | ||
2524 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2525 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); | ||
2526 | #endif // CONFIG_STA_SUPPORT // | ||
2527 | |||
2528 | } | ||
2529 | |||
2530 | |||
2531 | // Normal, AMPDU or AMSDU | ||
2532 | VOID CmmRxnonRalinkFrameIndicate( | ||
2533 | IN PRTMP_ADAPTER pAd, | ||
2534 | IN RX_BLK *pRxBlk, | ||
2535 | IN UCHAR FromWhichBSSID) | ||
2536 | { | ||
2537 | #ifdef DOT11_N_SUPPORT | ||
2538 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) | ||
2539 | { | ||
2540 | Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2541 | } | ||
2542 | else | ||
2543 | #endif // DOT11_N_SUPPORT // | ||
2544 | { | ||
2545 | #ifdef DOT11_N_SUPPORT | ||
2546 | if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) | ||
2547 | { | ||
2548 | // handle A-MSDU | ||
2549 | Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2550 | } | ||
2551 | else | ||
2552 | #endif // DOT11_N_SUPPORT // | ||
2553 | { | ||
2554 | Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); | ||
2555 | } | ||
2556 | } | ||
2557 | } | ||
2558 | |||
2559 | |||
2560 | VOID CmmRxRalinkFrameIndicate( | ||
2561 | IN PRTMP_ADAPTER pAd, | ||
2562 | IN MAC_TABLE_ENTRY *pEntry, | ||
2563 | IN RX_BLK *pRxBlk, | ||
2564 | IN UCHAR FromWhichBSSID) | ||
2565 | { | ||
2566 | UCHAR Header802_3[LENGTH_802_3]; | ||
2567 | UINT16 Msdu2Size; | ||
2568 | UINT16 Payload1Size, Payload2Size; | ||
2569 | PUCHAR pData2; | ||
2570 | PNDIS_PACKET pPacket2 = NULL; | ||
2571 | |||
2572 | |||
2573 | |||
2574 | Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); | ||
2575 | |||
2576 | if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) | ||
2577 | { | ||
2578 | /* skip two byte MSDU2 len */ | ||
2579 | pRxBlk->pData += 2; | ||
2580 | pRxBlk->DataSize -= 2; | ||
2581 | } | ||
2582 | else | ||
2583 | { | ||
2584 | // release packet | ||
2585 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | ||
2586 | return; | ||
2587 | } | ||
2588 | |||
2589 | // get 802.3 Header and remove LLC | ||
2590 | #ifdef CONFIG_STA_SUPPORT | ||
2591 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2592 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | ||
2593 | #endif // CONFIG_STA_SUPPORT // | ||
2594 | |||
2595 | |||
2596 | ASSERT(pRxBlk->pRxPacket); | ||
2597 | |||
2598 | // Ralink Aggregation frame | ||
2599 | pAd->RalinkCounters.OneSecRxAggregationCount ++; | ||
2600 | Payload1Size = pRxBlk->DataSize - Msdu2Size; | ||
2601 | Payload2Size = Msdu2Size - LENGTH_802_3; | ||
2602 | |||
2603 | pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; | ||
2604 | #ifdef CONFIG_STA_SUPPORT | ||
2605 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2606 | pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); | ||
2607 | #endif // CONFIG_STA_SUPPORT // | ||
2608 | |||
2609 | if (!pPacket2) | ||
2610 | { | ||
2611 | // release packet | ||
2612 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | ||
2613 | return; | ||
2614 | } | ||
2615 | |||
2616 | // update payload size of 1st packet | ||
2617 | pRxBlk->DataSize = Payload1Size; | ||
2618 | wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); | ||
2619 | |||
2620 | #ifdef CONFIG_STA_SUPPORT | ||
2621 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2622 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); | ||
2623 | #endif // CONFIG_STA_SUPPORT // | ||
2624 | |||
2625 | if (pPacket2) | ||
2626 | { | ||
2627 | #ifdef CONFIG_STA_SUPPORT | ||
2628 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2629 | ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); | ||
2630 | #endif // CONFIG_STA_SUPPORT // | ||
2631 | } | ||
2632 | } | ||
2633 | |||
2634 | |||
2635 | #define RESET_FRAGFRAME(_fragFrame) \ | ||
2636 | { \ | ||
2637 | _fragFrame.RxSize = 0; \ | ||
2638 | _fragFrame.Sequence = 0; \ | ||
2639 | _fragFrame.LastFrag = 0; \ | ||
2640 | _fragFrame.Flags = 0; \ | ||
2641 | } | ||
2642 | |||
2643 | |||
2644 | PNDIS_PACKET RTMPDeFragmentDataFrame( | ||
2645 | IN PRTMP_ADAPTER pAd, | ||
2646 | IN RX_BLK *pRxBlk) | ||
2647 | { | ||
2648 | PHEADER_802_11 pHeader = pRxBlk->pHeader; | ||
2649 | PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; | ||
2650 | UCHAR *pData = pRxBlk->pData; | ||
2651 | USHORT DataSize = pRxBlk->DataSize; | ||
2652 | PNDIS_PACKET pRetPacket = NULL; | ||
2653 | UCHAR *pFragBuffer = NULL; | ||
2654 | BOOLEAN bReassDone = FALSE; | ||
2655 | UCHAR HeaderRoom = 0; | ||
2656 | |||
2657 | |||
2658 | ASSERT(pHeader); | ||
2659 | |||
2660 | HeaderRoom = pData - (UCHAR *)pHeader; | ||
2661 | |||
2662 | // Re-assemble the fragmented packets | ||
2663 | if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt | ||
2664 | { | ||
2665 | // the first pkt of fragment, record it. | ||
2666 | if (pHeader->FC.MoreFrag) | ||
2667 | { | ||
2668 | ASSERT(pAd->FragFrame.pFragPacket); | ||
2669 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | ||
2670 | pAd->FragFrame.RxSize = DataSize + HeaderRoom; | ||
2671 | NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); | ||
2672 | pAd->FragFrame.Sequence = pHeader->Sequence; | ||
2673 | pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 | ||
2674 | ASSERT(pAd->FragFrame.LastFrag == 0); | ||
2675 | goto done; // end of processing this frame | ||
2676 | } | ||
2677 | } | ||
2678 | else //Middle & End of fragment | ||
2679 | { | ||
2680 | if ((pHeader->Sequence != pAd->FragFrame.Sequence) || | ||
2681 | (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) | ||
2682 | { | ||
2683 | // Fragment is not the same sequence or out of fragment number order | ||
2684 | // Reset Fragment control blk | ||
2685 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2686 | DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); | ||
2687 | goto done; // give up this frame | ||
2688 | } | ||
2689 | else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) | ||
2690 | { | ||
2691 | // Fragment frame is too large, it exeeds the maximum frame size. | ||
2692 | // Reset Fragment control blk | ||
2693 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2694 | DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); | ||
2695 | goto done; // give up this frame | ||
2696 | } | ||
2697 | |||
2698 | // | ||
2699 | // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. | ||
2700 | // In this case, we will dropt it. | ||
2701 | // | ||
2702 | if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) | ||
2703 | { | ||
2704 | DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); | ||
2705 | goto done; // give up this frame | ||
2706 | } | ||
2707 | |||
2708 | pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); | ||
2709 | |||
2710 | // concatenate this fragment into the re-assembly buffer | ||
2711 | NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); | ||
2712 | pAd->FragFrame.RxSize += DataSize; | ||
2713 | pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number | ||
2714 | |||
2715 | // Last fragment | ||
2716 | if (pHeader->FC.MoreFrag == FALSE) | ||
2717 | { | ||
2718 | bReassDone = TRUE; | ||
2719 | } | ||
2720 | } | ||
2721 | |||
2722 | done: | ||
2723 | // always release rx fragmented packet | ||
2724 | RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); | ||
2725 | |||
2726 | // return defragmented packet if packet is reassembled completely | ||
2727 | // otherwise return NULL | ||
2728 | if (bReassDone) | ||
2729 | { | ||
2730 | PNDIS_PACKET pNewFragPacket; | ||
2731 | |||
2732 | // allocate a new packet buffer for fragment | ||
2733 | pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); | ||
2734 | if (pNewFragPacket) | ||
2735 | { | ||
2736 | // update RxBlk | ||
2737 | pRetPacket = pAd->FragFrame.pFragPacket; | ||
2738 | pAd->FragFrame.pFragPacket = pNewFragPacket; | ||
2739 | pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); | ||
2740 | pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; | ||
2741 | pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; | ||
2742 | pRxBlk->pRxPacket = pRetPacket; | ||
2743 | } | ||
2744 | else | ||
2745 | { | ||
2746 | RESET_FRAGFRAME(pAd->FragFrame); | ||
2747 | } | ||
2748 | } | ||
2749 | |||
2750 | return pRetPacket; | ||
2751 | } | ||
2752 | |||
2753 | |||
2754 | VOID Indicate_AMSDU_Packet( | ||
2755 | IN PRTMP_ADAPTER pAd, | ||
2756 | IN RX_BLK *pRxBlk, | ||
2757 | IN UCHAR FromWhichBSSID) | ||
2758 | { | ||
2759 | UINT nMSDU; | ||
2760 | |||
2761 | update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); | ||
2762 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | ||
2763 | nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); | ||
2764 | } | ||
2765 | |||
2766 | VOID Indicate_EAPOL_Packet( | ||
2767 | IN PRTMP_ADAPTER pAd, | ||
2768 | IN RX_BLK *pRxBlk, | ||
2769 | IN UCHAR FromWhichBSSID) | ||
2770 | { | ||
2771 | MAC_TABLE_ENTRY *pEntry = NULL; | ||
2772 | |||
2773 | |||
2774 | #ifdef CONFIG_STA_SUPPORT | ||
2775 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | ||
2776 | { | ||
2777 | pEntry = &pAd->MacTab.Content[BSSID_WCID]; | ||
2778 | STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); | ||
2779 | return; | ||
2780 | } | ||
2781 | #endif // CONFIG_STA_SUPPORT // | ||
2782 | |||
2783 | if (pEntry == NULL) | ||
2784 | { | ||
2785 | DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); | ||
2786 | // release packet | ||
2787 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | ||
2788 | return; | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2792 | #define BCN_TBTT_OFFSET 64 //defer 64 us | ||
2793 | VOID ReSyncBeaconTime( | ||
2794 | IN PRTMP_ADAPTER pAd) | ||
2795 | { | ||
2796 | |||
2797 | UINT32 Offset; | ||
2798 | |||
2799 | |||
2800 | Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); | ||
2801 | |||
2802 | pAd->TbttTickCount++; | ||
2803 | |||
2804 | // | ||
2805 | // The updated BeaconInterval Value will affect Beacon Interval after two TBTT | ||
2806 | // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER | ||
2807 | // | ||
2808 | if (Offset == (BCN_TBTT_OFFSET-2)) | ||
2809 | { | ||
2810 | BCN_TIME_CFG_STRUC csr; | ||
2811 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
2812 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us | ||
2813 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
2814 | } | ||
2815 | else | ||
2816 | { | ||
2817 | if (Offset == (BCN_TBTT_OFFSET-1)) | ||
2818 | { | ||
2819 | BCN_TIME_CFG_STRUC csr; | ||
2820 | |||
2821 | RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); | ||
2822 | csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU | ||
2823 | RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); | ||
2824 | } | ||
2825 | } | ||
2826 | } | ||
2827 | |||