Staging: rt2870: remove dead QOS_DLS_SUPPORT code
[linux-2.6] / drivers / staging / rt2870 / common / action.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     Module Name:
28         action.c
29
30     Abstract:
31     Handle association related requests either from WSTA or from local MLME
32
33     Revision History:
34     Who         When          What
35     --------    ----------    ----------------------------------------------
36         Jan Lee         2006            created for rt2860
37  */
38
39 #include "../rt_config.h"
40 #include "action.h"
41
42
43 static VOID ReservedAction(
44         IN PRTMP_ADAPTER pAd,
45         IN MLME_QUEUE_ELEM *Elem);
46
47 /*
48     ==========================================================================
49     Description:
50         association state machine init, including state transition and timer init
51     Parameters:
52         S - pointer to the association state machine
53     Note:
54         The state machine looks like the following
55
56                                     ASSOC_IDLE
57         MT2_MLME_DISASSOC_REQ    mlme_disassoc_req_action
58         MT2_PEER_DISASSOC_REQ    peer_disassoc_action
59         MT2_PEER_ASSOC_REQ       drop
60         MT2_PEER_REASSOC_REQ     drop
61         MT2_CLS3ERR              cls3err_action
62     ==========================================================================
63  */
64 VOID ActionStateMachineInit(
65     IN  PRTMP_ADAPTER   pAd,
66     IN  STATE_MACHINE *S,
67     OUT STATE_MACHINE_FUNC Trans[])
68 {
69         StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE);
70
71         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction);
72         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction);
73
74         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction);
75
76 #ifdef DOT11_N_SUPPORT
77         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction);
78         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction);
79         StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction);
80         StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
81         StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
82 #endif // DOT11_N_SUPPORT //
83
84         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction);
85         StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction);
86
87         StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction);
88         StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction);
89         StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction);
90 }
91
92 #ifdef DOT11_N_SUPPORT
93 VOID MlmeADDBAAction(
94     IN PRTMP_ADAPTER pAd,
95     IN MLME_QUEUE_ELEM *Elem)
96
97 {
98         MLME_ADDBA_REQ_STRUCT *pInfo;
99         UCHAR           Addr[6];
100         PUCHAR         pOutBuffer = NULL;
101         NDIS_STATUS     NStatus;
102         ULONG           Idx;
103         FRAME_ADDBA_REQ  Frame;
104         ULONG           FrameLen;
105         BA_ORI_ENTRY                    *pBAEntry = NULL;
106
107         pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg;
108         NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ));
109
110         if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr))
111         {
112                 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
113                 if(NStatus != NDIS_STATUS_SUCCESS)
114                 {
115                         DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n"));
116                         return;
117                 }
118                 // 1. find entry
119                 Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
120                 if (Idx == 0)
121                 {
122                         MlmeFreeMemory(pAd, pOutBuffer);
123                         DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
124                         return;
125                 }
126                 else
127                 {
128                         pBAEntry =&pAd->BATable.BAOriEntry[Idx];
129                 }
130
131 #ifdef CONFIG_STA_SUPPORT
132                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
133                 {
134                         if (ADHOC_ON(pAd))
135                                 ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
136                         else
137                                 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr);
138                 }
139 #endif // CONFIG_STA_SUPPORT //
140
141                 Frame.Category = CATEGORY_BA;
142                 Frame.Action = ADDBA_REQ;
143                 Frame.BaParm.AMSDUSupported = 0;
144                 Frame.BaParm.BAPolicy = IMMED_BA;
145                 Frame.BaParm.TID = pInfo->TID;
146                 Frame.BaParm.BufSize = pInfo->BaBufSize;
147                 Frame.Token = pInfo->Token;
148                 Frame.TimeOutValue = pInfo->TimeOutValue;
149                 Frame.BaStartSeq.field.FragNum = 0;
150                 Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
151
152                 *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm));
153                 Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
154                 Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
155
156                 MakeOutgoingFrame(pOutBuffer,              &FrameLen,
157                               sizeof(FRAME_ADDBA_REQ), &Frame,
158                               END_OF_ARGS);
159                 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
160                 MlmeFreeMemory(pAd, pOutBuffer);
161
162                 DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x,  FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize));
163     }
164 }
165
166 /*
167     ==========================================================================
168     Description:
169         send DELBA and delete BaEntry if any
170     Parametrs:
171         Elem - MLME message MLME_DELBA_REQ_STRUCT
172
173         IRQL = DISPATCH_LEVEL
174
175     ==========================================================================
176  */
177 VOID MlmeDELBAAction(
178     IN PRTMP_ADAPTER pAd,
179     IN MLME_QUEUE_ELEM *Elem)
180 {
181         MLME_DELBA_REQ_STRUCT *pInfo;
182         PUCHAR         pOutBuffer = NULL;
183         PUCHAR             pOutBuffer2 = NULL;
184         NDIS_STATUS     NStatus;
185         ULONG           Idx;
186         FRAME_DELBA_REQ  Frame;
187         ULONG           FrameLen;
188         FRAME_BAR       FrameBar;
189
190         pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg;
191         // must send back DELBA
192         NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ));
193         DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
194
195         if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen))
196         {
197                 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
198                 if(NStatus != NDIS_STATUS_SUCCESS)
199                 {
200                         DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
201                         return;
202                 }
203
204                 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2);  //Get an unused nonpaged memory
205                 if(NStatus != NDIS_STATUS_SUCCESS)
206                 {
207                         MlmeFreeMemory(pAd, pOutBuffer);
208                         DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
209                         return;
210                 }
211
212                 // SEND BAR (Send BAR to refresh peer reordering buffer.)
213                 Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
214
215 #ifdef CONFIG_STA_SUPPORT
216                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
217                         BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress);
218 #endif // CONFIG_STA_SUPPORT //
219
220                 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton.
221                 FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton.
222                 FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton.
223                 FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton.
224                 FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton.
225                 FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton.
226
227                 MakeOutgoingFrame(pOutBuffer2,                          &FrameLen,
228                                           sizeof(FRAME_BAR),      &FrameBar,
229                                           END_OF_ARGS);
230                 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
231                 MlmeFreeMemory(pAd, pOutBuffer2);
232                 DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
233
234                 // SEND DELBA FRAME
235                 FrameLen = 0;
236 #ifdef CONFIG_STA_SUPPORT
237                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
238                 {
239                         if (ADHOC_ON(pAd))
240                                 ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
241                         else
242                                 ActHeaderInit(pAd, &Frame.Hdr,  pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr);
243                 }
244 #endif // CONFIG_STA_SUPPORT //
245                 Frame.Category = CATEGORY_BA;
246                 Frame.Action = DELBA;
247                 Frame.DelbaParm.Initiator = pInfo->Initiator;
248                 Frame.DelbaParm.TID = pInfo->TID;
249                 Frame.ReasonCode = 39; // Time Out
250                 *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm));
251                 Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
252
253                 MakeOutgoingFrame(pOutBuffer,               &FrameLen,
254                               sizeof(FRAME_DELBA_REQ),    &Frame,
255                               END_OF_ARGS);
256                 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
257                 MlmeFreeMemory(pAd, pOutBuffer);
258                 DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator));
259         }
260 }
261 #endif // DOT11_N_SUPPORT //
262
263 VOID MlmeQOSAction(
264     IN PRTMP_ADAPTER pAd,
265     IN MLME_QUEUE_ELEM *Elem)
266 {
267 }
268
269 VOID MlmeDLSAction(
270     IN PRTMP_ADAPTER pAd,
271     IN MLME_QUEUE_ELEM *Elem)
272 {
273 }
274
275 VOID MlmeInvalidAction(
276     IN PRTMP_ADAPTER pAd,
277     IN MLME_QUEUE_ELEM *Elem)
278 {
279         //PUCHAR                   pOutBuffer = NULL;
280         //Return the receiving frame except the MSB of category filed set to 1.  7.3.1.11
281 }
282
283 VOID PeerQOSAction(
284         IN PRTMP_ADAPTER pAd,
285         IN MLME_QUEUE_ELEM *Elem)
286 {
287 }
288
289 #ifdef DOT11_N_SUPPORT
290 VOID PeerBAAction(
291         IN PRTMP_ADAPTER pAd,
292         IN MLME_QUEUE_ELEM *Elem)
293 {
294         UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
295
296         switch(Action)
297         {
298                 case ADDBA_REQ:
299                         PeerAddBAReqAction(pAd,Elem);
300                         break;
301                 case ADDBA_RESP:
302                         PeerAddBARspAction(pAd,Elem);
303                         break;
304                 case DELBA:
305                         PeerDelBAAction(pAd,Elem);
306                         break;
307         }
308 }
309
310
311 #ifdef DOT11N_DRAFT3
312
313 #ifdef CONFIG_STA_SUPPORT
314 VOID StaPublicAction(
315         IN PRTMP_ADAPTER pAd,
316         IN UCHAR Bss2040Coexist)
317 {
318         BSS_2040_COEXIST_IE             BssCoexist;
319         MLME_SCAN_REQ_STRUCT                    ScanReq;
320
321         BssCoexist.word = Bss2040Coexist;
322         // AP asks Station to return a 20/40 BSS Coexistence mgmt frame.  So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame
323         if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)))
324         {
325                 // Clear record first.  After scan , will update those bit and send back to transmiter.
326                 pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
327                 pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0;
328                 pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0;
329                 // Fill out stuff for scan request
330                 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
331                 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
332                 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
333         }
334 }
335
336
337 /*
338 Description : Build Intolerant Channel Rerpot from Trigger event table.
339 return : how many bytes copied.
340 */
341 ULONG BuildIntolerantChannelRep(
342         IN      PRTMP_ADAPTER   pAd,
343         IN    PUCHAR  pDest)
344 {
345         ULONG                   FrameLen = 0;
346         ULONG                   ReadOffset = 0;
347         UCHAR                   i;
348         UCHAR                   LastRegClass = 0xff;
349         PUCHAR                  pLen;
350
351         for ( i = 0;i < MAX_TRIGGER_EVENT;i++)
352         {
353                 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE)
354                 {
355                         if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass)
356                         {
357                                 *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
358                                 *pLen++;
359                                 ReadOffset++;
360                                 FrameLen++;
361                         }
362                         else
363                         {
364                                 *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT;  // IE
365                                 *(pDest + ReadOffset + 1) = 2;  // Len = RegClass byte + channel byte.
366                                 pLen = pDest + ReadOffset + 1;
367                                 LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass;
368                                 *(pDest + ReadOffset + 2) = LastRegClass;       // Len = RegClass byte + channel byte.
369                                 *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
370                                 FrameLen += 4;
371                                 ReadOffset += 4;
372                         }
373
374                 }
375         }
376         return FrameLen;
377 }
378
379
380 /*
381 Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered.
382 */
383 VOID Send2040CoexistAction(
384         IN      PRTMP_ADAPTER   pAd,
385         IN    UCHAR  Wcid,
386         IN      BOOLEAN bAddIntolerantCha)
387 {
388         PUCHAR                  pOutBuffer = NULL;
389         NDIS_STATUS     NStatus;
390         FRAME_ACTION_HDR        Frame;
391         ULONG                   FrameLen;
392         ULONG                   IntolerantChaRepLen;
393
394         IntolerantChaRepLen = 0;
395         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
396         if(NStatus != NDIS_STATUS_SUCCESS)
397         {
398                 DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n"));
399                 return;
400         }
401         ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid);
402         Frame.Category = CATEGORY_PUBLIC;
403         Frame.Action = ACTION_BSS_2040_COEXIST;
404
405         MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
406                                   sizeof(FRAME_ACTION_HDR),       &Frame,
407                                   END_OF_ARGS);
408
409         *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word;
410         FrameLen++;
411
412         if (bAddIntolerantCha == TRUE)
413                 IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen);
414
415         MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen);
416         DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x )  \n", pAd->CommonCfg.BSSCoexist2040.word));
417
418 }
419
420
421 /*
422         ==========================================================================
423         Description:
424         After scan, Update 20/40 BSS Coexistence IE and send out.
425         According to 802.11n D3.03 11.14.10
426
427         Parameters:
428         ==========================================================================
429  */
430 VOID Update2040CoexistFrameAndNotify(
431         IN      PRTMP_ADAPTER   pAd,
432         IN    UCHAR  Wcid,
433         IN      BOOLEAN bAddIntolerantCha)
434 {
435         BSS_2040_COEXIST_IE     OldValue;
436
437         OldValue.word = pAd->CommonCfg.BSSCoexist2040.word;
438         if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0))
439                 pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1;
440
441         // Need to check !!!!
442         // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!!
443         // So Only check BSS20WidthReq change.
444         if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)
445         {
446                 Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha);
447         }
448 }
449 #endif // CONFIG_STA_SUPPORT //
450
451
452 BOOLEAN ChannelSwitchSanityCheck(
453         IN      PRTMP_ADAPTER   pAd,
454         IN    UCHAR  Wcid,
455         IN    UCHAR  NewChannel,
456         IN    UCHAR  Secondary)
457 {
458         UCHAR           i;
459
460         if (Wcid >= MAX_LEN_OF_MAC_TABLE)
461                 return FALSE;
462
463         if ((NewChannel > 7) && (Secondary == 1))
464                 return FALSE;
465
466         if ((NewChannel < 5) && (Secondary == 3))
467                 return FALSE;
468
469         // 0. Check if new channel is in the channellist.
470         for (i = 0;i < pAd->ChannelListNum;i++)
471         {
472                 if (pAd->ChannelList[i].Channel == NewChannel)
473                 {
474                         break;
475                 }
476         }
477
478         if (i == pAd->ChannelListNum)
479                 return FALSE;
480
481         return TRUE;
482 }
483
484
485 VOID ChannelSwitchAction(
486         IN      PRTMP_ADAPTER   pAd,
487         IN    UCHAR  Wcid,
488         IN    UCHAR  NewChannel,
489         IN    UCHAR  Secondary)
490 {
491         UCHAR           BBPValue = 0;
492         ULONG           MACValue;
493
494         DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d)  \n", NewChannel, Secondary));
495
496         if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE)
497                 return;
498
499         // 1.  Switches to BW = 20.
500         if (Secondary == 0)
501         {
502                 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
503                 BBPValue&= (~0x18);
504                 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
505                 if (pAd->MACVersion == 0x28600100)
506                 {
507                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
508                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
509                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
510                         DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
511                 }
512                 pAd->CommonCfg.BBPCurrentBW = BW_20;
513                 pAd->CommonCfg.Channel = NewChannel;
514                 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
515                 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE);
516                 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
517                 pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0;
518                 DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz   !!! \n" ));
519         }
520         // 1.  Switches to BW = 40 And Station supports BW = 40.
521         else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1))
522         {
523                 pAd->CommonCfg.Channel = NewChannel;
524
525                 if (Secondary == 1)
526                 {
527                         // Secondary above.
528                         pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
529                         RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
530                         MACValue &= 0xfe;
531                         RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
532                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
533                         BBPValue&= (~0x18);
534                         BBPValue|= (0x10);
535                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
536                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
537                         BBPValue&= (~0x20);
538                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
539                         DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
540                 }
541                 else
542                 {
543                         // Secondary below.
544                         pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
545                         RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
546                         MACValue &= 0xfe;
547                         MACValue |= 0x1;
548                         RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
549                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
550                         BBPValue&= (~0x18);
551                         BBPValue|= (0x10);
552                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
553                         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
554                         BBPValue&= (~0x20);
555                         BBPValue|= (0x20);
556                         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
557                         DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
558                 }
559                 pAd->CommonCfg.BBPCurrentBW = BW_40;
560                 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
561                 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
562                 pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1;
563         }
564 }
565 #endif // DOT11N_DRAFT3 //
566 #endif // DOT11_N_SUPPORT //
567
568 VOID PeerPublicAction(
569         IN PRTMP_ADAPTER pAd,
570         IN MLME_QUEUE_ELEM *Elem)
571 {
572 #ifdef DOT11N_DRAFT3
573         UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
574 #endif // DOT11N_DRAFT3 //
575
576         if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
577                 return;
578
579 #ifdef DOT11N_DRAFT3
580         switch(Action)
581         {
582                 case ACTION_BSS_2040_COEXIST:   // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03
583                         {
584                                 //UCHAR BssCoexist;
585                                 BSS_2040_COEXIST_ELEMENT                *pCoexistInfo;
586                                 BSS_2040_COEXIST_IE                     *pBssCoexistIe;
587                                 BSS_2040_INTOLERANT_CH_REPORT   *pIntolerantReport = NULL;
588
589                                 if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) )
590                                 {
591                                         DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen));
592                                         break;
593                                 }
594                                 DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n"));
595                                 hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen);
596
597
598                                 pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2];
599                                 //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));
600                                 if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT)))
601                                 {
602                                         pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT));
603                                 }
604                                 //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));
605
606                                 pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe);
607
608 #ifdef CONFIG_STA_SUPPORT
609                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
610                                 {
611                                         if (INFRA_ON(pAd))
612                                         {
613                                                 StaPublicAction(pAd, pCoexistInfo);
614                                         }
615                                 }
616 #endif // CONFIG_STA_SUPPORT //
617
618                         }
619                         break;
620         }
621
622 #endif // DOT11N_DRAFT3 //
623
624 }
625
626
627 static VOID ReservedAction(
628         IN PRTMP_ADAPTER pAd,
629         IN MLME_QUEUE_ELEM *Elem)
630 {
631         UCHAR Category;
632
633         if (Elem->MsgLen <= LENGTH_802_11)
634         {
635                 return;
636         }
637
638         Category = Elem->Msg[LENGTH_802_11];
639         DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category));
640         hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
641 }
642
643 VOID PeerRMAction(
644         IN PRTMP_ADAPTER pAd,
645         IN MLME_QUEUE_ELEM *Elem)
646
647 {
648         return;
649 }
650
651 #ifdef DOT11_N_SUPPORT
652 static VOID respond_ht_information_exchange_action(
653         IN PRTMP_ADAPTER pAd,
654         IN MLME_QUEUE_ELEM *Elem)
655 {
656         PUCHAR                  pOutBuffer = NULL;
657         NDIS_STATUS             NStatus;
658         ULONG                   FrameLen;
659         FRAME_HT_INFO   HTINFOframe, *pFrame;
660         UCHAR                   *pAddr;
661
662
663         // 2. Always send back ADDBA Response
664         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
665
666         if (NStatus != NDIS_STATUS_SUCCESS)
667         {
668                 DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
669                 return;
670         }
671
672         // get RA
673         pFrame = (FRAME_HT_INFO *) &Elem->Msg[0];
674         pAddr = pFrame->Hdr.Addr2;
675
676         NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO));
677         // 2-1. Prepare ADDBA Response frame.
678 #ifdef CONFIG_STA_SUPPORT
679         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
680         {
681                 if (ADHOC_ON(pAd))
682                         ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
683                 else
684                         ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
685         }
686 #endif // CONFIG_STA_SUPPORT //
687
688         HTINFOframe.Category = CATEGORY_HT;
689         HTINFOframe.Action = HT_INFO_EXCHANGE;
690         HTINFOframe.HT_Info.Request = 0;
691         HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
692         HTINFOframe.HT_Info.STA_Channel_Width    = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
693
694         MakeOutgoingFrame(pOutBuffer,                                   &FrameLen,
695                                           sizeof(FRAME_HT_INFO),        &HTINFOframe,
696                                           END_OF_ARGS);
697
698         MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
699         MlmeFreeMemory(pAd, pOutBuffer);
700 }
701
702
703 #ifdef DOT11N_DRAFT3
704 VOID SendNotifyBWActionFrame(
705         IN PRTMP_ADAPTER pAd,
706         IN UCHAR  Wcid,
707         IN UCHAR apidx)
708 {
709         PUCHAR                  pOutBuffer = NULL;
710         NDIS_STATUS     NStatus;
711         FRAME_ACTION_HDR        Frame;
712         ULONG                   FrameLen;
713         PUCHAR                  pAddr1;
714
715
716         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
717         if(NStatus != NDIS_STATUS_SUCCESS)
718         {
719                 DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n"));
720                 return;
721         }
722
723         if (Wcid == MCAST_WCID)
724                 pAddr1 = &BROADCAST_ADDR[0];
725         else
726                 pAddr1 = pAd->MacTab.Content[Wcid].Addr;
727         ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
728
729         Frame.Category = CATEGORY_HT;
730         Frame.Action = NOTIFY_BW_ACTION;
731
732         MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
733                                   sizeof(FRAME_ACTION_HDR),       &Frame,
734                                   END_OF_ARGS);
735
736         *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
737         FrameLen++;
738
739
740         MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
741         DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth));
742
743 }
744 #endif // DOT11N_DRAFT3 //
745
746
747 VOID PeerHTAction(
748         IN PRTMP_ADAPTER pAd,
749         IN MLME_QUEUE_ELEM *Elem)
750 {
751         UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
752
753         if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
754                 return;
755
756         switch(Action)
757         {
758                 case NOTIFY_BW_ACTION:
759                         DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n"));
760 #ifdef CONFIG_STA_SUPPORT
761                         if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
762                         {
763                                 // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps
764                                 // sending BW_Notify Action frame, and cause us to linkup and linkdown.
765                                 // In legacy mode, don't need to parse HT action frame.
766                                 DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
767                                                                 Elem->Msg[LENGTH_802_11+2] ));
768                                 break;
769                         }
770 #endif // CONFIG_STA_SUPPORT //
771
772                         if (Elem->Msg[LENGTH_802_11+2] == 0)    // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth.
773                                 pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0;
774
775                         break;
776
777                 case SMPS_ACTION:
778                         // 7.3.1.25
779                         DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n"));
780                         if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0))
781                         {
782                                 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE;
783                         }
784                         else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0))
785                         {
786                                 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC;
787                         }
788                         else
789                         {
790                                 pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC;
791                         }
792
793                         DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode));
794                         // rt2860c : add something for smps change.
795                         break;
796
797                 case SETPCO_ACTION:
798                         break;
799
800                 case MIMO_CHA_MEASURE_ACTION:
801                         break;
802
803                 case HT_INFO_EXCHANGE:
804                         {
805                                 HT_INFORMATION_OCTET    *pHT_info;
806
807                                 pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2];
808                                 // 7.4.8.10
809                                 DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n"));
810                                 if (pHT_info->Request)
811                                 {
812                                         respond_ht_information_exchange_action(pAd, Elem);
813                                 }
814                         }
815                         break;
816         }
817 }
818
819
820 /*
821         ==========================================================================
822         Description:
823                 Retry sending ADDBA Reqest.
824
825         IRQL = DISPATCH_LEVEL
826
827         Parametrs:
828         p8023Header: if this is already 802.3 format, p8023Header is NULL
829
830         Return  : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
831                                 FALSE , then continue indicaterx at this moment.
832         ==========================================================================
833  */
834 VOID ORIBATimerTimeout(
835         IN      PRTMP_ADAPTER   pAd)
836 {
837         MAC_TABLE_ENTRY *pEntry;
838         INT                     i, total;
839 //      FRAME_BAR                       FrameBar;
840 //      ULONG                   FrameLen;
841 //      NDIS_STATUS     NStatus;
842 //      PUCHAR                  pOutBuffer = NULL;
843 //      USHORT                  Sequence;
844         UCHAR                   TID;
845
846         total = pAd->MacTab.Size * NUM_OF_TID;
847
848         for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++)
849         {
850                 if  (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done)
851                 {
852                         pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid];
853                         TID = pAd->BATable.BAOriEntry[i].TID;
854
855                         ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE);
856                 }
857                 total --;
858         }
859 }
860
861
862 VOID SendRefreshBAR(
863         IN      PRTMP_ADAPTER   pAd,
864         IN      MAC_TABLE_ENTRY *pEntry)
865 {
866         FRAME_BAR               FrameBar;
867         ULONG                   FrameLen;
868         NDIS_STATUS     NStatus;
869         PUCHAR                  pOutBuffer = NULL;
870         USHORT                  Sequence;
871         UCHAR                   i, TID;
872         USHORT                  idx;
873         BA_ORI_ENTRY    *pBAEntry;
874
875         for (i = 0; i <NUM_OF_TID; i++)
876         {
877                 idx = pEntry->BAOriWcidArray[i];
878                 if (idx == 0)
879                 {
880                         continue;
881                 }
882                 pBAEntry = &pAd->BATable.BAOriEntry[idx];
883
884                 if  (pBAEntry->ORI_BA_Status == Originator_Done)
885                 {
886                         TID = pBAEntry->TID;
887
888                         ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
889
890                         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
891                         if(NStatus != NDIS_STATUS_SUCCESS)
892                         {
893                                 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
894                                 return;
895                         }
896
897                         Sequence = pEntry->TxSeq[TID];
898
899
900 #ifdef CONFIG_STA_SUPPORT
901                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
902                                 BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress);
903 #endif // CONFIG_STA_SUPPORT //
904
905                         FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
906                         FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton.
907                         FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton.
908
909                         MakeOutgoingFrame(pOutBuffer,                           &FrameLen,
910                                                           sizeof(FRAME_BAR),      &FrameBar,
911                                                           END_OF_ARGS);
912                         //if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))
913                         if (1)  // Now we always send BAR.
914                         {
915                                 //MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);
916                                 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
917                         }
918                         MlmeFreeMemory(pAd, pOutBuffer);
919                 }
920         }
921 }
922 #endif // DOT11_N_SUPPORT //
923
924 VOID ActHeaderInit(
925     IN  PRTMP_ADAPTER   pAd,
926     IN OUT PHEADER_802_11 pHdr80211,
927     IN PUCHAR Addr1,
928     IN PUCHAR Addr2,
929     IN PUCHAR Addr3)
930 {
931     NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
932     pHdr80211->FC.Type = BTYPE_MGMT;
933     pHdr80211->FC.SubType = SUBTYPE_ACTION;
934
935     COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
936         COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
937     COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
938 }
939
940 VOID BarHeaderInit(
941         IN      PRTMP_ADAPTER   pAd,
942         IN OUT PFRAME_BAR pCntlBar,
943         IN PUCHAR pDA,
944         IN PUCHAR pSA)
945 {
946 //      USHORT  Duration;
947
948         NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR));
949         pCntlBar->FC.Type = BTYPE_CNTL;
950         pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
951         pCntlBar->BarControl.MTID = 0;
952         pCntlBar->BarControl.Compressed = 1;
953         pCntlBar->BarControl.ACKPolicy = 0;
954
955
956         pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA));
957
958         COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
959         COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
960 }
961
962
963 /*
964         ==========================================================================
965         Description:
966                 Insert Category and action code into the action frame.
967
968         Parametrs:
969                 1. frame buffer pointer.
970                 2. frame length.
971                 3. category code of the frame.
972                 4. action code of the frame.
973
974         Return  : None.
975         ==========================================================================
976  */
977 VOID InsertActField(
978         IN PRTMP_ADAPTER pAd,
979         OUT PUCHAR pFrameBuf,
980         OUT PULONG pFrameLen,
981         IN UINT8 Category,
982         IN UINT8 ActCode)
983 {
984         ULONG TempLen;
985
986         MakeOutgoingFrame(      pFrameBuf,              &TempLen,
987                                                 1,                              &Category,
988                                                 1,                              &ActCode,
989                                                 END_OF_ARGS);
990
991         *pFrameLen = *pFrameLen + TempLen;
992
993         return;
994 }