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 static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
43 
44 /*
45     ==========================================================================
46     Description:
47         association state machine init, including state transition and timer init
48     Parameters:
49         S - pointer to the association state machine
50     Note:
51         The state machine looks like the following
52 
53                                     ASSOC_IDLE
54         MT2_MLME_DISASSOC_REQ    mlme_disassoc_req_action
55         MT2_PEER_DISASSOC_REQ    peer_disassoc_action
56         MT2_PEER_ASSOC_REQ       drop
57         MT2_PEER_REASSOC_REQ     drop
58         MT2_CLS3ERR              cls3err_action
59     ==========================================================================
60  */
ActionStateMachineInit(struct rt_rtmp_adapter * pAd,struct rt_state_machine * S,OUT STATE_MACHINE_FUNC Trans[])61 void ActionStateMachineInit(struct rt_rtmp_adapter *pAd,
62 			    struct rt_state_machine *S,
63 			    OUT STATE_MACHINE_FUNC Trans[])
64 {
65 	StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_ACT_STATE,
66 			 MAX_ACT_MSG, (STATE_MACHINE_FUNC) Drop, ACT_IDLE,
67 			 ACT_MACHINE_BASE);
68 
69 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE,
70 			      (STATE_MACHINE_FUNC) PeerSpectrumAction);
71 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE,
72 			      (STATE_MACHINE_FUNC) PeerQOSAction);
73 
74 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE,
75 			      (STATE_MACHINE_FUNC) ReservedAction);
76 
77 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE,
78 			      (STATE_MACHINE_FUNC) PeerBAAction);
79 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE,
80 			      (STATE_MACHINE_FUNC) PeerHTAction);
81 	StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE,
82 			      (STATE_MACHINE_FUNC) MlmeADDBAAction);
83 	StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE,
84 			      (STATE_MACHINE_FUNC) MlmeDELBAAction);
85 	StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE,
86 			      (STATE_MACHINE_FUNC) MlmeDELBAAction);
87 
88 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE,
89 			      (STATE_MACHINE_FUNC) PeerPublicAction);
90 	StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE,
91 			      (STATE_MACHINE_FUNC) PeerRMAction);
92 
93 	StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE,
94 			      (STATE_MACHINE_FUNC) MlmeQOSAction);
95 	StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE,
96 			      (STATE_MACHINE_FUNC) MlmeDLSAction);
97 	StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID,
98 			      (STATE_MACHINE_FUNC) MlmeInvalidAction);
99 }
100 
MlmeADDBAAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)101 void MlmeADDBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
102 {
103 	struct rt_mlme_addba_req *pInfo;
104 	u8 Addr[6];
105 	u8 *pOutBuffer = NULL;
106 	int NStatus;
107 	unsigned long Idx;
108 	struct rt_frame_addba_req Frame;
109 	unsigned long FrameLen;
110 	struct rt_ba_ori_entry *pBAEntry = NULL;
111 
112 	pInfo = (struct rt_mlme_addba_req *)Elem->Msg;
113 	NdisZeroMemory(&Frame, sizeof(struct rt_frame_addba_req));
114 
115 	if (MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) {
116 		NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
117 		if (NStatus != NDIS_STATUS_SUCCESS) {
118 			DBGPRINT(RT_DEBUG_TRACE,
119 				 ("BA - MlmeADDBAAction() allocate memory failed \n"));
120 			return;
121 		}
122 		/* 1. find entry */
123 		Idx =
124 		    pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
125 		if (Idx == 0) {
126 			MlmeFreeMemory(pAd, pOutBuffer);
127 			DBGPRINT(RT_DEBUG_ERROR,
128 				 ("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
129 			return;
130 		} else {
131 			pBAEntry = &pAd->BATable.BAOriEntry[Idx];
132 		}
133 
134 		{
135 			if (ADHOC_ON(pAd))
136 				ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr,
137 					      pAd->CurrentAddress,
138 					      pAd->CommonCfg.Bssid);
139 			else
140 				ActHeaderInit(pAd, &Frame.Hdr,
141 					      pAd->CommonCfg.Bssid,
142 					      pAd->CurrentAddress,
143 					      pInfo->pAddr);
144 		}
145 
146 		Frame.Category = CATEGORY_BA;
147 		Frame.Action = ADDBA_REQ;
148 		Frame.BaParm.AMSDUSupported = 0;
149 		Frame.BaParm.BAPolicy = IMMED_BA;
150 		Frame.BaParm.TID = pInfo->TID;
151 		Frame.BaParm.BufSize = pInfo->BaBufSize;
152 		Frame.Token = pInfo->Token;
153 		Frame.TimeOutValue = pInfo->TimeOutValue;
154 		Frame.BaStartSeq.field.FragNum = 0;
155 		Frame.BaStartSeq.field.StartSeq =
156 		    pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
157 
158 		*(u16 *) (&Frame.BaParm) =
159 		    cpu2le16(*(u16 *) (&Frame.BaParm));
160 		Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
161 		Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
162 
163 		MakeOutgoingFrame(pOutBuffer, &FrameLen,
164 				  sizeof(struct rt_frame_addba_req), &Frame, END_OF_ARGS);
165 
166 		MiniportMMRequest(pAd,
167 				  (MGMT_USE_QUEUE_FLAG |
168 				   MapUserPriorityToAccessCategory[pInfo->TID]),
169 				  pOutBuffer, FrameLen);
170 
171 		MlmeFreeMemory(pAd, pOutBuffer);
172 
173 		DBGPRINT(RT_DEBUG_TRACE,
174 			 ("BA - Send ADDBA request. StartSeq = %x,  FrameLen = %ld. BufSize = %d\n",
175 			  Frame.BaStartSeq.field.StartSeq, FrameLen,
176 			  Frame.BaParm.BufSize));
177 	}
178 }
179 
180 /*
181     ==========================================================================
182     Description:
183         send DELBA and delete BaEntry if any
184     Parametrs:
185         Elem - MLME message struct rt_mlme_delba_req
186 
187 	IRQL = DISPATCH_LEVEL
188 
189     ==========================================================================
190  */
MlmeDELBAAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)191 void MlmeDELBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
192 {
193 	struct rt_mlme_delba_req *pInfo;
194 	u8 *pOutBuffer = NULL;
195 	u8 *pOutBuffer2 = NULL;
196 	int NStatus;
197 	unsigned long Idx;
198 	struct rt_frame_delba_req Frame;
199 	unsigned long FrameLen;
200 	struct rt_frame_bar FrameBar;
201 
202 	pInfo = (struct rt_mlme_delba_req *)Elem->Msg;
203 	/* must send back DELBA */
204 	NdisZeroMemory(&Frame, sizeof(struct rt_frame_delba_req));
205 	DBGPRINT(RT_DEBUG_TRACE,
206 		 ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
207 
208 	if (MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) {
209 		NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
210 		if (NStatus != NDIS_STATUS_SUCCESS) {
211 			DBGPRINT(RT_DEBUG_ERROR,
212 				 ("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
213 			return;
214 		}
215 
216 		NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2);	/*Get an unused nonpaged memory */
217 		if (NStatus != NDIS_STATUS_SUCCESS) {
218 			MlmeFreeMemory(pAd, pOutBuffer);
219 			DBGPRINT(RT_DEBUG_ERROR,
220 				 ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
221 			return;
222 		}
223 		/* SEND BAR (Send BAR to refresh peer reordering buffer.) */
224 		Idx =
225 		    pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
226 
227 		BarHeaderInit(pAd, &FrameBar,
228 			      pAd->MacTab.Content[pInfo->Wcid].Addr,
229 			      pAd->CurrentAddress);
230 
231 		FrameBar.StartingSeq.field.FragNum = 0;	/* make sure sequence not clear in DEL funciton. */
232 		FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];	/* make sure sequence not clear in DEL funciton. */
233 		FrameBar.BarControl.TID = pInfo->TID;	/* make sure sequence not clear in DEL funciton. */
234 		FrameBar.BarControl.ACKPolicy = IMMED_BA;	/* make sure sequence not clear in DEL funciton. */
235 		FrameBar.BarControl.Compressed = 1;	/* make sure sequence not clear in DEL funciton. */
236 		FrameBar.BarControl.MTID = 0;	/* make sure sequence not clear in DEL funciton. */
237 
238 		MakeOutgoingFrame(pOutBuffer2, &FrameLen,
239 				  sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS);
240 		MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
241 		MlmeFreeMemory(pAd, pOutBuffer2);
242 		DBGPRINT(RT_DEBUG_TRACE,
243 			 ("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
244 
245 		/* SEND DELBA FRAME */
246 		FrameLen = 0;
247 
248 		{
249 			if (ADHOC_ON(pAd))
250 				ActHeaderInit(pAd, &Frame.Hdr,
251 					      pAd->MacTab.Content[pInfo->Wcid].
252 					      Addr, pAd->CurrentAddress,
253 					      pAd->CommonCfg.Bssid);
254 			else
255 				ActHeaderInit(pAd, &Frame.Hdr,
256 					      pAd->CommonCfg.Bssid,
257 					      pAd->CurrentAddress,
258 					      pAd->MacTab.Content[pInfo->Wcid].
259 					      Addr);
260 		}
261 
262 		Frame.Category = CATEGORY_BA;
263 		Frame.Action = DELBA;
264 		Frame.DelbaParm.Initiator = pInfo->Initiator;
265 		Frame.DelbaParm.TID = pInfo->TID;
266 		Frame.ReasonCode = 39;	/* Time Out */
267 		*(u16 *) (&Frame.DelbaParm) =
268 		    cpu2le16(*(u16 *) (&Frame.DelbaParm));
269 		Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
270 
271 		MakeOutgoingFrame(pOutBuffer, &FrameLen,
272 				  sizeof(struct rt_frame_delba_req), &Frame, END_OF_ARGS);
273 		MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
274 		MlmeFreeMemory(pAd, pOutBuffer);
275 		DBGPRINT(RT_DEBUG_TRACE,
276 			 ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n",
277 			  pInfo->Initiator));
278 	}
279 }
280 
MlmeQOSAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)281 void MlmeQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
282 {
283 }
284 
MlmeDLSAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)285 void MlmeDLSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
286 {
287 }
288 
MlmeInvalidAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)289 void MlmeInvalidAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
290 {
291 	/*u8 *                  pOutBuffer = NULL; */
292 	/*Return the receiving frame except the MSB of category filed set to 1.  7.3.1.11 */
293 }
294 
PeerQOSAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)295 void PeerQOSAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
296 {
297 }
298 
PeerBAAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)299 void PeerBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
300 {
301 	u8 Action = Elem->Msg[LENGTH_802_11 + 1];
302 
303 	switch (Action) {
304 	case ADDBA_REQ:
305 		PeerAddBAReqAction(pAd, Elem);
306 		break;
307 	case ADDBA_RESP:
308 		PeerAddBARspAction(pAd, Elem);
309 		break;
310 	case DELBA:
311 		PeerDelBAAction(pAd, Elem);
312 		break;
313 	}
314 }
315 
PeerPublicAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)316 void PeerPublicAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
317 {
318 	if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
319 		return;
320 }
321 
ReservedAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)322 static void ReservedAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
323 {
324 	u8 Category;
325 
326 	if (Elem->MsgLen <= LENGTH_802_11) {
327 		return;
328 	}
329 
330 	Category = Elem->Msg[LENGTH_802_11];
331 	DBGPRINT(RT_DEBUG_TRACE,
332 		 ("Rcv reserved category(%d) Action Frame\n", Category));
333 	hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
334 }
335 
PeerRMAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)336 void PeerRMAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
337 {
338 	return;
339 }
340 
respond_ht_information_exchange_action(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)341 static void respond_ht_information_exchange_action(struct rt_rtmp_adapter *pAd,
342 						   struct rt_mlme_queue_elem *Elem)
343 {
344 	u8 *pOutBuffer = NULL;
345 	int NStatus;
346 	unsigned long FrameLen;
347 	struct rt_frame_ht_info HTINFOframe, *pFrame;
348 	u8 *pAddr;
349 
350 	/* 2. Always send back ADDBA Response */
351 	NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
352 
353 	if (NStatus != NDIS_STATUS_SUCCESS) {
354 		DBGPRINT(RT_DEBUG_TRACE,
355 			 ("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
356 		return;
357 	}
358 	/* get RA */
359 	pFrame = (struct rt_frame_ht_info *) & Elem->Msg[0];
360 	pAddr = pFrame->Hdr.Addr2;
361 
362 	NdisZeroMemory(&HTINFOframe, sizeof(struct rt_frame_ht_info));
363 	/* 2-1. Prepare ADDBA Response frame. */
364 	{
365 		if (ADHOC_ON(pAd))
366 			ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr,
367 				      pAd->CurrentAddress,
368 				      pAd->CommonCfg.Bssid);
369 		else
370 			ActHeaderInit(pAd, &HTINFOframe.Hdr,
371 				      pAd->CommonCfg.Bssid, pAd->CurrentAddress,
372 				      pAddr);
373 	}
374 
375 	HTINFOframe.Category = CATEGORY_HT;
376 	HTINFOframe.Action = HT_INFO_EXCHANGE;
377 	HTINFOframe.HT_Info.Request = 0;
378 	HTINFOframe.HT_Info.Forty_MHz_Intolerant =
379 	    pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
380 	HTINFOframe.HT_Info.STA_Channel_Width =
381 	    pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
382 
383 	MakeOutgoingFrame(pOutBuffer, &FrameLen,
384 			  sizeof(struct rt_frame_ht_info), &HTINFOframe, END_OF_ARGS);
385 
386 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
387 	MlmeFreeMemory(pAd, pOutBuffer);
388 }
389 
PeerHTAction(struct rt_rtmp_adapter * pAd,struct rt_mlme_queue_elem * Elem)390 void PeerHTAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
391 {
392 	u8 Action = Elem->Msg[LENGTH_802_11 + 1];
393 
394 	if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
395 		return;
396 
397 	switch (Action) {
398 	case NOTIFY_BW_ACTION:
399 		DBGPRINT(RT_DEBUG_TRACE,
400 			 ("ACTION - HT Notify Channel bandwidth action----> \n"));
401 
402 		if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) {
403 			/* Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps */
404 			/* sending BW_Notify Action frame, and cause us to linkup and linkdown. */
405 			/* In legacy mode, don't need to parse HT action frame. */
406 			DBGPRINT(RT_DEBUG_TRACE,
407 				 ("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
408 				  Elem->Msg[LENGTH_802_11 + 2]));
409 			break;
410 		}
411 
412 		if (Elem->Msg[LENGTH_802_11 + 2] == 0)	/* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */
413 			pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0;
414 
415 		break;
416 	case SMPS_ACTION:
417 		/* 7.3.1.25 */
418 		DBGPRINT(RT_DEBUG_TRACE, ("ACTION - SMPS action----> \n"));
419 		if (((Elem->Msg[LENGTH_802_11 + 2] & 0x1) == 0)) {
420 			pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE;
421 		} else if (((Elem->Msg[LENGTH_802_11 + 2] & 0x2) == 0)) {
422 			pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC;
423 		} else {
424 			pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC;
425 		}
426 
427 		DBGPRINT(RT_DEBUG_TRACE,
428 			 ("Aid(%d) MIMO PS = %d\n", Elem->Wcid,
429 			  pAd->MacTab.Content[Elem->Wcid].MmpsMode));
430 		/* rt2860c : add something for smps change. */
431 		break;
432 
433 	case SETPCO_ACTION:
434 		break;
435 	case MIMO_CHA_MEASURE_ACTION:
436 		break;
437 	case HT_INFO_EXCHANGE:
438 		{
439 			struct rt_ht_information_octet *pHT_info;
440 
441 			pHT_info =
442 			    (struct rt_ht_information_octet *) & Elem->Msg[LENGTH_802_11 +
443 								 2];
444 			/* 7.4.8.10 */
445 			DBGPRINT(RT_DEBUG_TRACE,
446 				 ("ACTION - HT Information Exchange action----> \n"));
447 			if (pHT_info->Request) {
448 				respond_ht_information_exchange_action(pAd,
449 								       Elem);
450 			}
451 		}
452 		break;
453 	}
454 }
455 
456 /*
457 	==========================================================================
458 	Description:
459 		Retry sending ADDBA Reqest.
460 
461 	IRQL = DISPATCH_LEVEL
462 
463 	Parametrs:
464 	p8023Header: if this is already 802.3 format, p8023Header is NULL
465 
466 	Return	: TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
467 				FALSE , then continue indicaterx at this moment.
468 	==========================================================================
469  */
ORIBATimerTimeout(struct rt_rtmp_adapter * pAd)470 void ORIBATimerTimeout(struct rt_rtmp_adapter *pAd)
471 {
472 	struct rt_mac_table_entry *pEntry;
473 	int i, total;
474 	u8 TID;
475 
476 	total = pAd->MacTab.Size * NUM_OF_TID;
477 
478 	for (i = 1; ((i < MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)); i++) {
479 		if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) {
480 			pEntry =
481 			    &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].
482 						 Wcid];
483 			TID = pAd->BATable.BAOriEntry[i].TID;
484 
485 			ASSERT(pAd->BATable.BAOriEntry[i].Wcid <
486 			       MAX_LEN_OF_MAC_TABLE);
487 		}
488 		total--;
489 	}
490 }
491 
SendRefreshBAR(struct rt_rtmp_adapter * pAd,struct rt_mac_table_entry * pEntry)492 void SendRefreshBAR(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
493 {
494 	struct rt_frame_bar FrameBar;
495 	unsigned long FrameLen;
496 	int NStatus;
497 	u8 *pOutBuffer = NULL;
498 	u16 Sequence;
499 	u8 i, TID;
500 	u16 idx;
501 	struct rt_ba_ori_entry *pBAEntry;
502 
503 	for (i = 0; i < NUM_OF_TID; i++) {
504 		idx = pEntry->BAOriWcidArray[i];
505 		if (idx == 0) {
506 			continue;
507 		}
508 		pBAEntry = &pAd->BATable.BAOriEntry[idx];
509 
510 		if (pBAEntry->ORI_BA_Status == Originator_Done) {
511 			TID = pBAEntry->TID;
512 
513 			ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
514 
515 			NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
516 			if (NStatus != NDIS_STATUS_SUCCESS) {
517 				DBGPRINT(RT_DEBUG_ERROR,
518 					 ("BA - MlmeADDBAAction() allocate memory failed \n"));
519 				return;
520 			}
521 
522 			Sequence = pEntry->TxSeq[TID];
523 
524 			BarHeaderInit(pAd, &FrameBar, pEntry->Addr,
525 				      pAd->CurrentAddress);
526 
527 			FrameBar.StartingSeq.field.FragNum = 0;	/* make sure sequence not clear in DEL function. */
528 			FrameBar.StartingSeq.field.StartSeq = Sequence;	/* make sure sequence not clear in DEL funciton. */
529 			FrameBar.BarControl.TID = TID;	/* make sure sequence not clear in DEL funciton. */
530 
531 			MakeOutgoingFrame(pOutBuffer, &FrameLen,
532 					  sizeof(struct rt_frame_bar), &FrameBar,
533 					  END_OF_ARGS);
534 			/*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) */
535 			if (1)	/* Now we always send BAR. */
536 			{
537 				/*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen); */
538 				MiniportMMRequest(pAd,
539 						  (MGMT_USE_QUEUE_FLAG |
540 						   MapUserPriorityToAccessCategory
541 						   [TID]), pOutBuffer,
542 						  FrameLen);
543 
544 			}
545 			MlmeFreeMemory(pAd, pOutBuffer);
546 		}
547 	}
548 }
549 
ActHeaderInit(struct rt_rtmp_adapter * pAd,struct rt_header_802_11 * pHdr80211,u8 * Addr1,u8 * Addr2,u8 * Addr3)550 void ActHeaderInit(struct rt_rtmp_adapter *pAd,
551 		   struct rt_header_802_11 * pHdr80211,
552 		   u8 *Addr1, u8 *Addr2, u8 *Addr3)
553 {
554 	NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
555 	pHdr80211->FC.Type = BTYPE_MGMT;
556 	pHdr80211->FC.SubType = SUBTYPE_ACTION;
557 
558 	COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
559 	COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
560 	COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
561 }
562 
BarHeaderInit(struct rt_rtmp_adapter * pAd,struct rt_frame_bar * pCntlBar,u8 * pDA,u8 * pSA)563 void BarHeaderInit(struct rt_rtmp_adapter *pAd,
564 		   struct rt_frame_bar * pCntlBar, u8 *pDA, u8 *pSA)
565 {
566 	NdisZeroMemory(pCntlBar, sizeof(struct rt_frame_bar));
567 	pCntlBar->FC.Type = BTYPE_CNTL;
568 	pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
569 	pCntlBar->BarControl.MTID = 0;
570 	pCntlBar->BarControl.Compressed = 1;
571 	pCntlBar->BarControl.ACKPolicy = 0;
572 
573 	pCntlBar->Duration =
574 	    16 + RTMPCalcDuration(pAd, RATE_1, sizeof(struct rt_frame_ba));
575 
576 	COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
577 	COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
578 }
579 
580 /*
581 	==========================================================================
582 	Description:
583 		Insert Category and action code into the action frame.
584 
585 	Parametrs:
586 		1. frame buffer pointer.
587 		2. frame length.
588 		3. category code of the frame.
589 		4. action code of the frame.
590 
591 	Return	: None.
592 	==========================================================================
593  */
InsertActField(struct rt_rtmp_adapter * pAd,u8 * pFrameBuf,unsigned long * pFrameLen,u8 Category,u8 ActCode)594 void InsertActField(struct rt_rtmp_adapter *pAd,
595 		    u8 *pFrameBuf,
596 		    unsigned long *pFrameLen, u8 Category, u8 ActCode)
597 {
598 	unsigned long TempLen;
599 
600 	MakeOutgoingFrame(pFrameBuf, &TempLen,
601 			  1, &Category, 1, &ActCode, END_OF_ARGS);
602 
603 	*pFrameLen = *pFrameLen + TempLen;
604 
605 	return;
606 }
607