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