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