aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rt3070/common/cmm_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rt3070/common/cmm_data.c')
-rw-r--r--drivers/staging/rt3070/common/cmm_data.c2827
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
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)
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
331NDIS_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
353NDIS_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*/
611static 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
677BOOLEAN 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
803FillTxBlkErr:
804 return FALSE;
805}
806
807
808BOOLEAN 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*/
868VOID 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*/
1067USHORT 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*/
1130VOID 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
1236VOID 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
1359VOID 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*/
1461VOID 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
1486BOOLEAN 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*/
1525BOOLEAN 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*/
1572PQUEUE_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*/
1638VOID 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*/
1677VOID 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
1704UINT 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
1812UINT 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*/
1837MAC_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
1860MAC_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 */
2034BOOLEAN 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 */
2144VOID 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*/
2186VOID 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*/
2210VOID 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
2255BOOLEAN 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
2314BOOLEAN 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
2423VOID 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
2457VOID 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
2532VOID 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
2560VOID 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
2644PNDIS_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
2722done:
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
2754VOID 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
2766VOID 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
2793VOID 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