• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rt2860/common/
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	Fonchi Wu    2008	  	   created for 802.11h
37 */
38
39#include "../rt_config.h"
40#include "action.h"
41
42/* The regulatory information in the USA (US) */
43struct rt_dot11_regulatory_information USARegulatoryInfo[] = {
44/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
45	{0, {0, 0, {0}
46	     }
47	 }
48	,			/* Invlid entry */
49	{1, {4, 16, {36, 40, 44, 48}
50	     }
51	 }
52	,
53	{2, {4, 23, {52, 56, 60, 64}
54	     }
55	 }
56	,
57	{3, {4, 29, {149, 153, 157, 161}
58	     }
59	 }
60	,
61	{4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
62	     }
63	 }
64	,
65	{5, {5, 30, {149, 153, 157, 161, 165}
66	     }
67	 }
68	,
69	{6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
70	     }
71	 }
72	,
73	{7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
74	     }
75	 }
76	,
77	{8, {5, 17, {11, 13, 15, 17, 19}
78	     }
79	 }
80	,
81	{9, {5, 30, {11, 13, 15, 17, 19}
82	     }
83	 }
84	,
85	{10, {2, 20, {21, 25}
86	      }
87	 }
88	,
89	{11, {2, 33, {21, 25}
90	      }
91	 }
92	,
93	{12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
94	      }
95	 }
96};
97
98#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
99
100/* The regulatory information in Europe */
101struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = {
102/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
103	{0, {0, 0, {0}
104	     }
105	 }
106	,			/* Invalid entry */
107	{1, {4, 20, {36, 40, 44, 48}
108	     }
109	 }
110	,
111	{2, {4, 20, {52, 56, 60, 64}
112	     }
113	 }
114	,
115	{3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
116	     }
117	 }
118	,
119	{4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
120	     }
121	 }
122};
123
124#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
125
126/* The regulatory information in Japan */
127struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = {
128/*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
129	{0, {0, 0, {0}
130	     }
131	 }
132	,			/* Invalid entry */
133	{1, {4, 22, {34, 38, 42, 46}
134	     }
135	 }
136	,
137	{2, {3, 24, {8, 12, 16}
138	     }
139	 }
140	,
141	{3, {3, 24, {8, 12, 16}
142	     }
143	 }
144	,
145	{4, {3, 24, {8, 12, 16}
146	     }
147	 }
148	,
149	{5, {3, 24, {8, 12, 16}
150	     }
151	 }
152	,
153	{6, {3, 22, {8, 12, 16}
154	     }
155	 }
156	,
157	{7, {4, 24, {184, 188, 192, 196}
158	     }
159	 }
160	,
161	{8, {4, 24, {184, 188, 192, 196}
162	     }
163	 }
164	,
165	{9, {4, 24, {184, 188, 192, 196}
166	     }
167	 }
168	,
169	{10, {4, 24, {184, 188, 192, 196}
170	      }
171	 }
172	,
173	{11, {4, 22, {184, 188, 192, 196}
174	      }
175	 }
176	,
177	{12, {4, 24, {7, 8, 9, 11}
178	      }
179	 }
180	,
181	{13, {4, 24, {7, 8, 9, 11}
182	      }
183	 }
184	,
185	{14, {4, 24, {7, 8, 9, 11}
186	      }
187	 }
188	,
189	{15, {4, 24, {7, 8, 9, 11}
190	      }
191	 }
192	,
193	{16, {6, 24, {183, 184, 185, 187, 188, 189}
194	      }
195	 }
196	,
197	{17, {6, 24, {183, 184, 185, 187, 188, 189}
198	      }
199	 }
200	,
201	{18, {6, 24, {183, 184, 185, 187, 188, 189}
202	      }
203	 }
204	,
205	{19, {6, 24, {183, 184, 185, 187, 188, 189}
206	      }
207	 }
208	,
209	{20, {6, 17, {183, 184, 185, 187, 188, 189}
210	      }
211	 }
212	,
213	{21, {6, 24, {6, 7, 8, 9, 10, 11}
214	      }
215	 }
216	,
217	{22, {6, 24, {6, 7, 8, 9, 10, 11}
218	      }
219	 }
220	,
221	{23, {6, 24, {6, 7, 8, 9, 10, 11}
222	      }
223	 }
224	,
225	{24, {6, 24, {6, 7, 8, 9, 10, 11}
226	      }
227	 }
228	,
229	{25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
230	      }
231	 }
232	,
233	{26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
234	      }
235	 }
236	,
237	{27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
238	      }
239	 }
240	,
241	{28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
242	      }
243	 }
244	,
245	{29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}
246	      }
247	 }
248	,
249	{30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
250	      }
251	 }
252	,
253	{31, {1, 23, {14}
254	      }
255	 }
256	,
257	{32, {4, 22, {52, 56, 60, 64}
258	      }
259	 }
260};
261
262#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
263
264char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode)
265{
266	struct tx_pwr_cfg {
267		u8 Mode;
268		u8 MCS;
269		u16 req;
270		u8 shift;
271		u32 BitMask;
272	};
273
274	u32 Value;
275	int Idx;
276	u8 PhyMode;
277	char CurTxPwr;
278	u8 TxPwrRef = 0;
279	char DaltaPwr;
280	unsigned long TxPwr[5];
281
282	struct tx_pwr_cfg TxPwrCfg[] = {
283		{MODE_CCK, 0, 0, 4, 0x000000f0},
284		{MODE_CCK, 1, 0, 0, 0x0000000f},
285		{MODE_CCK, 2, 0, 12, 0x0000f000},
286		{MODE_CCK, 3, 0, 8, 0x00000f00},
287
288		{MODE_OFDM, 0, 0, 20, 0x00f00000},
289		{MODE_OFDM, 1, 0, 16, 0x000f0000},
290		{MODE_OFDM, 2, 0, 28, 0xf0000000},
291		{MODE_OFDM, 3, 0, 24, 0x0f000000},
292		{MODE_OFDM, 4, 1, 4, 0x000000f0},
293		{MODE_OFDM, 5, 1, 0, 0x0000000f},
294		{MODE_OFDM, 6, 1, 12, 0x0000f000},
295		{MODE_OFDM, 7, 1, 8, 0x00000f00}
296		, {MODE_HTMIX, 0, 1, 20, 0x00f00000},
297		{MODE_HTMIX, 1, 1, 16, 0x000f0000},
298		{MODE_HTMIX, 2, 1, 28, 0xf0000000},
299		{MODE_HTMIX, 3, 1, 24, 0x0f000000},
300		{MODE_HTMIX, 4, 2, 4, 0x000000f0},
301		{MODE_HTMIX, 5, 2, 0, 0x0000000f},
302		{MODE_HTMIX, 6, 2, 12, 0x0000f000},
303		{MODE_HTMIX, 7, 2, 8, 0x00000f00},
304		{MODE_HTMIX, 8, 2, 20, 0x00f00000},
305		{MODE_HTMIX, 9, 2, 16, 0x000f0000},
306		{MODE_HTMIX, 10, 2, 28, 0xf0000000},
307		{MODE_HTMIX, 11, 2, 24, 0x0f000000},
308		{MODE_HTMIX, 12, 3, 4, 0x000000f0},
309		{MODE_HTMIX, 13, 3, 0, 0x0000000f},
310		{MODE_HTMIX, 14, 3, 12, 0x0000f000},
311		{MODE_HTMIX, 15, 3, 8, 0x00000f00}
312	};
313#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg))
314
315	CurTxPwr = 19;
316
317	/* check Tx Power setting from UI. */
318	if (pAd->CommonCfg.TxPowerPercentage > 90) ;
319	else if (pAd->CommonCfg.TxPowerPercentage > 60)	/* reduce Pwr for 1 dB. */
320		CurTxPwr -= 1;
321	else if (pAd->CommonCfg.TxPowerPercentage > 30)	/* reduce Pwr for 3 dB. */
322		CurTxPwr -= 3;
323	else if (pAd->CommonCfg.TxPowerPercentage > 15)	/* reduce Pwr for 6 dB. */
324		CurTxPwr -= 6;
325	else if (pAd->CommonCfg.TxPowerPercentage > 9)	/* reduce Pwr for 9 dB. */
326		CurTxPwr -= 9;
327	else			/* reduce Pwr for 12 dB. */
328		CurTxPwr -= 12;
329
330	if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
331		if (pAd->CommonCfg.CentralChannel > 14) {
332			TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
333			TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
334			TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
335			TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
336			TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
337		} else {
338			TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
339			TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
340			TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
341			TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
342			TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
343		}
344	} else {
345		if (pAd->CommonCfg.Channel > 14) {
346			TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
347			TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
348			TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
349			TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
350			TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
351		} else {
352			TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
353			TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
354			TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
355			TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
356			TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
357		}
358	}
359
360	switch (HTTxMode.field.MODE) {
361	case MODE_CCK:
362	case MODE_OFDM:
363		Value = TxPwr[1];
364		TxPwrRef = (Value & 0x00000f00) >> 8;
365
366		break;
367
368	case MODE_HTMIX:
369	case MODE_HTGREENFIELD:
370		if (pAd->CommonCfg.TxStream == 1) {
371			Value = TxPwr[2];
372			TxPwrRef = (Value & 0x00000f00) >> 8;
373		} else if (pAd->CommonCfg.TxStream == 2) {
374			Value = TxPwr[3];
375			TxPwrRef = (Value & 0x00000f00) >> 8;
376		}
377		break;
378	}
379
380	PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD)
381	    ? MODE_HTMIX : HTTxMode.field.MODE;
382
383	for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) {
384		if ((TxPwrCfg[Idx].Mode == PhyMode)
385		    && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) {
386			Value = TxPwr[TxPwrCfg[Idx].req];
387			DaltaPwr =
388			    TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask)
389					       >> TxPwrCfg[Idx].shift);
390			CurTxPwr -= DaltaPwr;
391			break;
392		}
393	}
394
395	return CurTxPwr;
396}
397
398void MeasureReqTabInit(struct rt_rtmp_adapter *pAd)
399{
400	NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
401
402	pAd->CommonCfg.pMeasureReqTab =
403	    kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC);
404	if (pAd->CommonCfg.pMeasureReqTab)
405		NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
406			       sizeof(struct rt_measure_req_tab));
407	else
408		DBGPRINT(RT_DEBUG_ERROR,
409			 ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
410			  __func__));
411
412	return;
413}
414
415void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
416{
417	NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
418
419	if (pAd->CommonCfg.pMeasureReqTab)
420		kfree(pAd->CommonCfg.pMeasureReqTab);
421	pAd->CommonCfg.pMeasureReqTab = NULL;
422
423	return;
424}
425
426struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
427{
428	u32 HashIdx;
429	struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
430	struct rt_measure_req_entry *pEntry = NULL;
431	struct rt_measure_req_entry *pPrevEntry = NULL;
432
433	if (pTab == NULL) {
434		DBGPRINT(RT_DEBUG_ERROR,
435			 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
436		return NULL;
437	}
438
439	RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
440
441	HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
442	pEntry = pTab->Hash[HashIdx];
443
444	while (pEntry) {
445		if (pEntry->DialogToken == DialogToken)
446			break;
447		else {
448			pPrevEntry = pEntry;
449			pEntry = pEntry->pNext;
450		}
451	}
452
453	RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
454
455	return pEntry;
456}
457
458struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
459{
460	int i;
461	unsigned long HashIdx;
462	struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
463	struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry;
464	unsigned long Now;
465
466	if (pTab == NULL) {
467		DBGPRINT(RT_DEBUG_ERROR,
468			 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
469		return NULL;
470	}
471
472	pEntry = MeasureReqLookUp(pAd, DialogToken);
473	if (pEntry == NULL) {
474		RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
475		for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
476			NdisGetSystemUpTime(&Now);
477			pEntry = &pTab->Content[i];
478
479			if ((pEntry->Valid == TRUE)
480			    && RTMP_TIME_AFTER((unsigned long)Now,
481					       (unsigned long)(pEntry->
482							       lastTime +
483							       MQ_REQ_AGE_OUT)))
484			{
485				struct rt_measure_req_entry *pPrevEntry = NULL;
486				unsigned long HashIdx =
487				    MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
488							      DialogToken);
489				struct rt_measure_req_entry *pProbeEntry =
490				    pTab->Hash[HashIdx];
491
492				/* update Hash list */
493				do {
494					if (pProbeEntry == pEntry) {
495						if (pPrevEntry == NULL) {
496							pTab->Hash[HashIdx] =
497							    pEntry->pNext;
498						} else {
499							pPrevEntry->pNext =
500							    pEntry->pNext;
501						}
502						break;
503					}
504
505					pPrevEntry = pProbeEntry;
506					pProbeEntry = pProbeEntry->pNext;
507				} while (pProbeEntry);
508
509				NdisZeroMemory(pEntry,
510					       sizeof(struct rt_measure_req_entry));
511				pTab->Size--;
512
513				break;
514			}
515
516			if (pEntry->Valid == FALSE)
517				break;
518		}
519
520		if (i < MAX_MEASURE_REQ_TAB_SIZE) {
521			NdisGetSystemUpTime(&Now);
522			pEntry->lastTime = Now;
523			pEntry->Valid = TRUE;
524			pEntry->DialogToken = DialogToken;
525			pTab->Size++;
526		} else {
527			pEntry = NULL;
528			DBGPRINT(RT_DEBUG_ERROR,
529				 ("%s: pMeasureReqTab tab full.\n", __func__));
530		}
531
532		/* add this Neighbor entry into HASH table */
533		if (pEntry) {
534			HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
535			if (pTab->Hash[HashIdx] == NULL) {
536				pTab->Hash[HashIdx] = pEntry;
537			} else {
538				pCurrEntry = pTab->Hash[HashIdx];
539				while (pCurrEntry->pNext != NULL)
540					pCurrEntry = pCurrEntry->pNext;
541				pCurrEntry->pNext = pEntry;
542			}
543		}
544
545		RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
546	}
547
548	return pEntry;
549}
550
551void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
552{
553	struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
554	struct rt_measure_req_entry *pEntry = NULL;
555
556	if (pTab == NULL) {
557		DBGPRINT(RT_DEBUG_ERROR,
558			 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
559		return;
560	}
561	/* if empty, return */
562	if (pTab->Size == 0) {
563		DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
564		return;
565	}
566
567	pEntry = MeasureReqLookUp(pAd, DialogToken);
568	if (pEntry != NULL) {
569		struct rt_measure_req_entry *pPrevEntry = NULL;
570		unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
571		struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx];
572
573		RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
574		/* update Hash list */
575		do {
576			if (pProbeEntry == pEntry) {
577				if (pPrevEntry == NULL) {
578					pTab->Hash[HashIdx] = pEntry->pNext;
579				} else {
580					pPrevEntry->pNext = pEntry->pNext;
581				}
582				break;
583			}
584
585			pPrevEntry = pProbeEntry;
586			pProbeEntry = pProbeEntry->pNext;
587		} while (pProbeEntry);
588
589		NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry));
590		pTab->Size--;
591
592		RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
593	}
594
595	return;
596}
597
598void TpcReqTabInit(struct rt_rtmp_adapter *pAd)
599{
600	NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
601
602	pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC);
603	if (pAd->CommonCfg.pTpcReqTab)
604		NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab));
605	else
606		DBGPRINT(RT_DEBUG_ERROR,
607			 ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
608			  __func__));
609
610	return;
611}
612
613void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
614{
615	NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
616
617	if (pAd->CommonCfg.pTpcReqTab)
618		kfree(pAd->CommonCfg.pTpcReqTab);
619	pAd->CommonCfg.pTpcReqTab = NULL;
620
621	return;
622}
623
624static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
625{
626	u32 HashIdx;
627	struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
628	struct rt_tpc_req_entry *pEntry = NULL;
629	struct rt_tpc_req_entry *pPrevEntry = NULL;
630
631	if (pTab == NULL) {
632		DBGPRINT(RT_DEBUG_ERROR,
633			 ("%s: pTpcReqTab doesn't exist.\n", __func__));
634		return NULL;
635	}
636
637	RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
638
639	HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
640	pEntry = pTab->Hash[HashIdx];
641
642	while (pEntry) {
643		if (pEntry->DialogToken == DialogToken)
644			break;
645		else {
646			pPrevEntry = pEntry;
647			pEntry = pEntry->pNext;
648		}
649	}
650
651	RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
652
653	return pEntry;
654}
655
656static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
657{
658	int i;
659	unsigned long HashIdx;
660	struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
661	struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry;
662	unsigned long Now;
663
664	if (pTab == NULL) {
665		DBGPRINT(RT_DEBUG_ERROR,
666			 ("%s: pTpcReqTab doesn't exist.\n", __func__));
667		return NULL;
668	}
669
670	pEntry = TpcReqLookUp(pAd, DialogToken);
671	if (pEntry == NULL) {
672		RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
673		for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
674			NdisGetSystemUpTime(&Now);
675			pEntry = &pTab->Content[i];
676
677			if ((pEntry->Valid == TRUE)
678			    && RTMP_TIME_AFTER((unsigned long)Now,
679					       (unsigned long)(pEntry->
680							       lastTime +
681							       TPC_REQ_AGE_OUT)))
682			{
683				struct rt_tpc_req_entry *pPrevEntry = NULL;
684				unsigned long HashIdx =
685				    TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
686							       DialogToken);
687				struct rt_tpc_req_entry *pProbeEntry =
688				    pTab->Hash[HashIdx];
689
690				/* update Hash list */
691				do {
692					if (pProbeEntry == pEntry) {
693						if (pPrevEntry == NULL) {
694							pTab->Hash[HashIdx] =
695							    pEntry->pNext;
696						} else {
697							pPrevEntry->pNext =
698							    pEntry->pNext;
699						}
700						break;
701					}
702
703					pPrevEntry = pProbeEntry;
704					pProbeEntry = pProbeEntry->pNext;
705				} while (pProbeEntry);
706
707				NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
708				pTab->Size--;
709
710				break;
711			}
712
713			if (pEntry->Valid == FALSE)
714				break;
715		}
716
717		if (i < MAX_TPC_REQ_TAB_SIZE) {
718			NdisGetSystemUpTime(&Now);
719			pEntry->lastTime = Now;
720			pEntry->Valid = TRUE;
721			pEntry->DialogToken = DialogToken;
722			pTab->Size++;
723		} else {
724			pEntry = NULL;
725			DBGPRINT(RT_DEBUG_ERROR,
726				 ("%s: pTpcReqTab tab full.\n", __func__));
727		}
728
729		/* add this Neighbor entry into HASH table */
730		if (pEntry) {
731			HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
732			if (pTab->Hash[HashIdx] == NULL) {
733				pTab->Hash[HashIdx] = pEntry;
734			} else {
735				pCurrEntry = pTab->Hash[HashIdx];
736				while (pCurrEntry->pNext != NULL)
737					pCurrEntry = pCurrEntry->pNext;
738				pCurrEntry->pNext = pEntry;
739			}
740		}
741
742		RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
743	}
744
745	return pEntry;
746}
747
748static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
749{
750	struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
751	struct rt_tpc_req_entry *pEntry = NULL;
752
753	if (pTab == NULL) {
754		DBGPRINT(RT_DEBUG_ERROR,
755			 ("%s: pTpcReqTab doesn't exist.\n", __func__));
756		return;
757	}
758	/* if empty, return */
759	if (pTab->Size == 0) {
760		DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
761		return;
762	}
763
764	pEntry = TpcReqLookUp(pAd, DialogToken);
765	if (pEntry != NULL) {
766		struct rt_tpc_req_entry *pPrevEntry = NULL;
767		unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
768		struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx];
769
770		RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
771		/* update Hash list */
772		do {
773			if (pProbeEntry == pEntry) {
774				if (pPrevEntry == NULL) {
775					pTab->Hash[HashIdx] = pEntry->pNext;
776				} else {
777					pPrevEntry->pNext = pEntry->pNext;
778				}
779				break;
780			}
781
782			pPrevEntry = pProbeEntry;
783			pProbeEntry = pProbeEntry->pNext;
784		} while (pProbeEntry);
785
786		NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
787		pTab->Size--;
788
789		RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
790	}
791
792	return;
793}
794
795/*
796	==========================================================================
797	Description:
798		Get Current TimeS tamp.
799
800	Parametrs:
801
802	Return	: Current Time Stamp.
803	==========================================================================
804 */
805static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd)
806{
807	/* get current time stamp. */
808	return 0;
809}
810
811/*
812	==========================================================================
813	Description:
814		Get Current Transmit Power.
815
816	Parametrs:
817
818	Return	: Current Time Stamp.
819	==========================================================================
820 */
821static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid)
822{
823	return 16;		/* 16 dBm */
824}
825
826/*
827	==========================================================================
828	Description:
829		Get Current Transmit Power.
830
831	Parametrs:
832
833	Return	: Current Time Stamp.
834	==========================================================================
835 */
836void InsertChannelRepIE(struct rt_rtmp_adapter *pAd,
837			u8 *pFrameBuf,
838			unsigned long *pFrameLen,
839			char *pCountry, u8 RegulatoryClass)
840{
841	unsigned long TempLen;
842	u8 Len;
843	u8 IEId = IE_AP_CHANNEL_REPORT;
844	u8 *pChListPtr = NULL;
845
846	Len = 1;
847	if (strncmp(pCountry, "US", 2) == 0) {
848		if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) {
849			DBGPRINT(RT_DEBUG_ERROR,
850				 ("%s: USA Unknow Requlatory class (%d)\n",
851				  __func__, RegulatoryClass));
852			return;
853		}
854
855		Len +=
856		    USARegulatoryInfo[RegulatoryClass].ChannelSet.
857		    NumberOfChannels;
858		pChListPtr =
859		    USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
860	} else if (strncmp(pCountry, "JP", 2) == 0) {
861		if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) {
862			DBGPRINT(RT_DEBUG_ERROR,
863				 ("%s: JP Unknow Requlatory class (%d)\n",
864				  __func__, RegulatoryClass));
865			return;
866		}
867
868		Len +=
869		    JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
870		    NumberOfChannels;
871		pChListPtr =
872		    JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
873	} else {
874		DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
875					  __func__, pCountry));
876		return;
877	}
878
879	MakeOutgoingFrame(pFrameBuf, &TempLen,
880			  1, &IEId,
881			  1, &Len,
882			  1, &RegulatoryClass,
883			  Len - 1, pChListPtr, END_OF_ARGS);
884
885	*pFrameLen = *pFrameLen + TempLen;
886
887	return;
888}
889
890/*
891	==========================================================================
892	Description:
893		Insert Dialog Token into frame.
894
895	Parametrs:
896		1. frame buffer pointer.
897		2. frame length.
898		3. Dialog token.
899
900	Return	: None.
901	==========================================================================
902 */
903void InsertDialogToken(struct rt_rtmp_adapter *pAd,
904		       u8 *pFrameBuf,
905		       unsigned long *pFrameLen, u8 DialogToken)
906{
907	unsigned long TempLen;
908	MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
909
910	*pFrameLen = *pFrameLen + TempLen;
911
912	return;
913}
914
915/*
916	==========================================================================
917	Description:
918		Insert TPC Request IE into frame.
919
920	Parametrs:
921		1. frame buffer pointer.
922		2. frame length.
923
924	Return	: None.
925	==========================================================================
926 */
927static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd,
928			   u8 *pFrameBuf, unsigned long *pFrameLen)
929{
930	unsigned long TempLen;
931	unsigned long Len = 0;
932	u8 ElementID = IE_TPC_REQUEST;
933
934	MakeOutgoingFrame(pFrameBuf, &TempLen,
935			  1, &ElementID, 1, &Len, END_OF_ARGS);
936
937	*pFrameLen = *pFrameLen + TempLen;
938
939	return;
940}
941
942/*
943	==========================================================================
944	Description:
945		Insert TPC Report IE into frame.
946
947	Parametrs:
948		1. frame buffer pointer.
949		2. frame length.
950		3. Transmit Power.
951		4. Link Margin.
952
953	Return	: None.
954	==========================================================================
955 */
956void InsertTpcReportIE(struct rt_rtmp_adapter *pAd,
957		       u8 *pFrameBuf,
958		       unsigned long *pFrameLen,
959		       u8 TxPwr, u8 LinkMargin)
960{
961	unsigned long TempLen;
962	unsigned long Len = sizeof(struct rt_tpc_report_info);
963	u8 ElementID = IE_TPC_REPORT;
964	struct rt_tpc_report_info TpcReportIE;
965
966	TpcReportIE.TxPwr = TxPwr;
967	TpcReportIE.LinkMargin = LinkMargin;
968
969	MakeOutgoingFrame(pFrameBuf, &TempLen,
970			  1, &ElementID,
971			  1, &Len, Len, &TpcReportIE, END_OF_ARGS);
972
973	*pFrameLen = *pFrameLen + TempLen;
974
975	return;
976}
977
978/*
979	==========================================================================
980	Description:
981		Insert Channel Switch Announcement IE into frame.
982
983	Parametrs:
984		1. frame buffer pointer.
985		2. frame length.
986		3. channel switch announcement mode.
987		4. new selected channel.
988		5. channel switch announcement count.
989
990	Return	: None.
991	==========================================================================
992 */
993static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd,
994			    u8 *pFrameBuf,
995			    unsigned long *pFrameLen,
996			    u8 ChSwMode,
997			    u8 NewChannel, u8 ChSwCnt)
998{
999	unsigned long TempLen;
1000	unsigned long Len = sizeof(struct rt_ch_sw_ann_info);
1001	u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
1002	struct rt_ch_sw_ann_info ChSwAnnIE;
1003
1004	ChSwAnnIE.ChSwMode = ChSwMode;
1005	ChSwAnnIE.Channel = NewChannel;
1006	ChSwAnnIE.ChSwCnt = ChSwCnt;
1007
1008	MakeOutgoingFrame(pFrameBuf, &TempLen,
1009			  1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
1010
1011	*pFrameLen = *pFrameLen + TempLen;
1012
1013	return;
1014}
1015
1016/*
1017	==========================================================================
1018	Description:
1019		Insert Measure Request IE into frame.
1020
1021	Parametrs:
1022		1. frame buffer pointer.
1023		2. frame length.
1024		3. Measure Token.
1025		4. Measure Request Mode.
1026		5. Measure Request Type.
1027		6. Measure Channel.
1028		7. Measure Start time.
1029		8. Measure Duration.
1030
1031	Return	: None.
1032	==========================================================================
1033 */
1034static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd,
1035			       u8 *pFrameBuf,
1036			       unsigned long *pFrameLen,
1037			       u8 Len, struct rt_measure_req_info * pMeasureReqIE)
1038{
1039	unsigned long TempLen;
1040	u8 ElementID = IE_MEASUREMENT_REQUEST;
1041
1042	MakeOutgoingFrame(pFrameBuf, &TempLen,
1043			  1, &ElementID,
1044			  1, &Len,
1045			  sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS);
1046
1047	*pFrameLen = *pFrameLen + TempLen;
1048
1049	return;
1050}
1051
1052/*
1053	==========================================================================
1054	Description:
1055		Insert Measure Report IE into frame.
1056
1057	Parametrs:
1058		1. frame buffer pointer.
1059		2. frame length.
1060		3. Measure Token.
1061		4. Measure Request Mode.
1062		5. Measure Request Type.
1063		6. Length of Report Infomation
1064		7. Pointer of Report Infomation Buffer.
1065
1066	Return	: None.
1067	==========================================================================
1068 */
1069static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd,
1070				  u8 *pFrameBuf,
1071				  unsigned long *pFrameLen,
1072				  struct rt_measure_report_info * pMeasureReportIE,
1073				  u8 ReportLnfoLen, u8 *pReportInfo)
1074{
1075	unsigned long TempLen;
1076	unsigned long Len;
1077	u8 ElementID = IE_MEASUREMENT_REPORT;
1078
1079	Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen;
1080
1081	MakeOutgoingFrame(pFrameBuf, &TempLen,
1082			  1, &ElementID,
1083			  1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
1084
1085	*pFrameLen = *pFrameLen + TempLen;
1086
1087	if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1088		MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1089				  ReportLnfoLen, pReportInfo, END_OF_ARGS);
1090
1091		*pFrameLen = *pFrameLen + TempLen;
1092	}
1093	return;
1094}
1095
1096/*
1097	==========================================================================
1098	Description:
1099		Prepare Measurement request action frame and enqueue it into
1100		management queue waiting for transmition.
1101
1102	Parametrs:
1103		1. the destination mac address of the frame.
1104
1105	Return	: None.
1106	==========================================================================
1107 */
1108void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd,
1109			     u8 *pOutBuffer,
1110			     unsigned long *pFrameLen,
1111			     u8 TotalLen,
1112			     u8 Category,
1113			     u8 Action,
1114			     u8 MeasureToken,
1115			     u8 MeasureReqMode,
1116			     u8 MeasureReqType, u8 NumOfRepetitions)
1117{
1118	unsigned long TempLen;
1119	struct rt_measure_req_info MeasureReqIE;
1120
1121	InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1122		       Action);
1123
1124	/* fill Dialog Token */
1125	InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1126			  MeasureToken);
1127
1128	/* fill Number of repetitions. */
1129	if (Category == CATEGORY_RM) {
1130		MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1131				  2, &NumOfRepetitions, END_OF_ARGS);
1132
1133		*pFrameLen += TempLen;
1134	}
1135	/* prepare Measurement IE. */
1136	NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info));
1137	MeasureReqIE.Token = MeasureToken;
1138	MeasureReqIE.ReqMode.word = MeasureReqMode;
1139	MeasureReqIE.ReqType = MeasureReqType;
1140	InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1141			   TotalLen, &MeasureReqIE);
1142
1143	return;
1144}
1145
1146/*
1147	==========================================================================
1148	Description:
1149		Prepare Measurement report action frame and enqueue it into
1150		management queue waiting for transmition.
1151
1152	Parametrs:
1153		1. the destination mac address of the frame.
1154
1155	Return	: None.
1156	==========================================================================
1157 */
1158void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd,
1159			   u8 *pDA,
1160			   u8 DialogToken,
1161			   u8 MeasureToken,
1162			   u8 MeasureReqMode,
1163			   u8 MeasureReqType,
1164			   u8 ReportInfoLen, u8 *pReportInfo)
1165{
1166	u8 *pOutBuffer = NULL;
1167	int NStatus;
1168	unsigned long FrameLen;
1169	struct rt_header_802_11 ActHdr;
1170	struct rt_measure_report_info MeasureRepIE;
1171
1172	/* build action frame header. */
1173	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1174			 pAd->CurrentAddress);
1175
1176	NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);	/*Get an unused nonpaged memory */
1177	if (NStatus != NDIS_STATUS_SUCCESS) {
1178		DBGPRINT(RT_DEBUG_TRACE,
1179			 ("%s() allocate memory failed \n", __func__));
1180		return;
1181	}
1182	NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1183	FrameLen = sizeof(struct rt_header_802_11);
1184
1185	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1186		       CATEGORY_SPECTRUM, SPEC_MRP);
1187
1188	/* fill Dialog Token */
1189	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1190
1191	/* prepare Measurement IE. */
1192	NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info));
1193	MeasureRepIE.Token = MeasureToken;
1194	MeasureRepIE.ReportMode = MeasureReqMode;
1195	MeasureRepIE.ReportType = MeasureReqType;
1196	InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1197			      &MeasureRepIE, ReportInfoLen, pReportInfo);
1198
1199	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1200	MlmeFreeMemory(pAd, pOutBuffer);
1201
1202	return;
1203}
1204
1205/*
1206	==========================================================================
1207	Description:
1208		Prepare TPC Request action frame and enqueue it into
1209		management queue waiting for transmition.
1210
1211	Parametrs:
1212		1. the destination mac address of the frame.
1213
1214	Return	: None.
1215	==========================================================================
1216 */
1217void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken)
1218{
1219	u8 *pOutBuffer = NULL;
1220	int NStatus;
1221	unsigned long FrameLen;
1222
1223	struct rt_header_802_11 ActHdr;
1224
1225	/* build action frame header. */
1226	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1227			 pAd->CurrentAddress);
1228
1229	NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);	/*Get an unused nonpaged memory */
1230	if (NStatus != NDIS_STATUS_SUCCESS) {
1231		DBGPRINT(RT_DEBUG_TRACE,
1232			 ("%s() allocate memory failed \n", __func__));
1233		return;
1234	}
1235	NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1236	FrameLen = sizeof(struct rt_header_802_11);
1237
1238	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1239		       CATEGORY_SPECTRUM, SPEC_TPCRQ);
1240
1241	/* fill Dialog Token */
1242	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1243
1244	/* Insert TPC Request IE. */
1245	InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1246
1247	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1248	MlmeFreeMemory(pAd, pOutBuffer);
1249
1250	return;
1251}
1252
1253/*
1254	==========================================================================
1255	Description:
1256		Prepare TPC Report action frame and enqueue it into
1257		management queue waiting for transmition.
1258
1259	Parametrs:
1260		1. the destination mac address of the frame.
1261
1262	Return	: None.
1263	==========================================================================
1264 */
1265void EnqueueTPCRep(struct rt_rtmp_adapter *pAd,
1266		   u8 *pDA,
1267		   u8 DialogToken, u8 TxPwr, u8 LinkMargin)
1268{
1269	u8 *pOutBuffer = NULL;
1270	int NStatus;
1271	unsigned long FrameLen;
1272
1273	struct rt_header_802_11 ActHdr;
1274
1275	/* build action frame header. */
1276	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1277			 pAd->CurrentAddress);
1278
1279	NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);	/*Get an unused nonpaged memory */
1280	if (NStatus != NDIS_STATUS_SUCCESS) {
1281		DBGPRINT(RT_DEBUG_TRACE,
1282			 ("%s() allocate memory failed \n", __func__));
1283		return;
1284	}
1285	NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1286	FrameLen = sizeof(struct rt_header_802_11);
1287
1288	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1289		       CATEGORY_SPECTRUM, SPEC_TPCRP);
1290
1291	/* fill Dialog Token */
1292	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1293
1294	/* Insert TPC Request IE. */
1295	InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1296			  LinkMargin);
1297
1298	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1299	MlmeFreeMemory(pAd, pOutBuffer);
1300
1301	return;
1302}
1303
1304/*
1305	==========================================================================
1306	Description:
1307		Prepare Channel Switch Announcement action frame and enqueue it into
1308		management queue waiting for transmition.
1309
1310	Parametrs:
1311		1. the destination mac address of the frame.
1312		2. Channel switch announcement mode.
1313		2. a New selected channel.
1314
1315	Return	: None.
1316	==========================================================================
1317 */
1318void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd,
1319		    u8 *pDA, u8 ChSwMode, u8 NewCh)
1320{
1321	u8 *pOutBuffer = NULL;
1322	int NStatus;
1323	unsigned long FrameLen;
1324
1325	struct rt_header_802_11 ActHdr;
1326
1327	/* build action frame header. */
1328	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1329			 pAd->CurrentAddress);
1330
1331	NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);	/*Get an unused nonpaged memory */
1332	if (NStatus != NDIS_STATUS_SUCCESS) {
1333		DBGPRINT(RT_DEBUG_TRACE,
1334			 ("%s() allocate memory failed \n", __func__));
1335		return;
1336	}
1337	NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1338	FrameLen = sizeof(struct rt_header_802_11);
1339
1340	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1341		       CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1342
1343	InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1344			NewCh, 0);
1345
1346	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1347	MlmeFreeMemory(pAd, pOutBuffer);
1348
1349	return;
1350}
1351
1352static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel)
1353{
1354	BOOLEAN Result = FALSE;
1355	int i;
1356
1357	do {
1358		/* check DFS procedure is running. */
1359		/* make sure DFS procedure won't start twice. */
1360		if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
1361			Result = FALSE;
1362			break;
1363		}
1364		/* check the new channel carried from Channel Switch Announcemnet is valid. */
1365		for (i = 0; i < pAd->ChannelListNum; i++) {
1366			if ((Channel == pAd->ChannelList[i].Channel)
1367			    && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
1368				/* found radar signal in the channel. the channel can't use at least for 30 minutes. */
1369				pAd->ChannelList[i].RemainingTimeForUse = 1800;	/*30 min = 1800 sec */
1370				Result = TRUE;
1371				break;
1372			}
1373		}
1374	} while (FALSE);
1375
1376	return Result;
1377}
1378
1379void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd,
1380			    u8 *pRA,
1381			    u8 *pTA, u8 ChSwMode, u8 Channel)
1382{
1383}
1384
1385static void StartDFSProcedure(struct rt_rtmp_adapter *pAd,
1386			      u8 Channel, u8 ChSwMode)
1387{
1388	/* start DFS procedure */
1389	pAd->CommonCfg.Channel = Channel;
1390
1391	N_ChannelCheck(pAd);
1392
1393	pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1394	pAd->CommonCfg.RadarDetect.CSCount = 0;
1395}
1396
1397/*
1398	==========================================================================
1399	Description:
1400		Channel Switch Announcement action frame sanity check.
1401
1402	Parametrs:
1403		1. MLME message containing the received frame
1404		2. message length.
1405		3. Channel switch announcement infomation buffer.
1406
1407	Return	: None.
1408	==========================================================================
1409 */
1410
1411/*
1412  Channel Switch Announcement IE.
1413  +----+-----+-----------+------------+-----------+
1414  | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1415  +----+-----+-----------+------------+-----------+
1416    1    1        1           1            1
1417*/
1418static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd,
1419				 void * pMsg,
1420				 unsigned long MsgLen,
1421				 struct rt_ch_sw_ann_info * pChSwAnnInfo)
1422{
1423	struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1424	u8 *pFramePtr = Fr->Octet;
1425	BOOLEAN result = FALSE;
1426	struct rt_eid * eid_ptr;
1427
1428	/* skip 802.11 header. */
1429	MsgLen -= sizeof(struct rt_header_802_11);
1430
1431	/* skip category and action code. */
1432	pFramePtr += 2;
1433	MsgLen -= 2;
1434
1435	if (pChSwAnnInfo == NULL)
1436		return result;
1437
1438	eid_ptr = (struct rt_eid *) pFramePtr;
1439	while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1440	       ((u8 *)pFramePtr + MsgLen)) {
1441		switch (eid_ptr->Eid) {
1442		case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1443			NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet,
1444				       1);
1445			NdisMoveMemory(&pChSwAnnInfo->Channel,
1446				       eid_ptr->Octet + 1, 1);
1447			NdisMoveMemory(&pChSwAnnInfo->ChSwCnt,
1448				       eid_ptr->Octet + 2, 1);
1449
1450			result = TRUE;
1451			break;
1452
1453		default:
1454			break;
1455		}
1456		eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1457	}
1458
1459	return result;
1460}
1461
1462/*
1463	==========================================================================
1464	Description:
1465		Measurement request action frame sanity check.
1466
1467	Parametrs:
1468		1. MLME message containing the received frame
1469		2. message length.
1470		3. Measurement request infomation buffer.
1471
1472	Return	: None.
1473	==========================================================================
1474 */
1475static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd,
1476				    void * pMsg,
1477				    unsigned long MsgLen,
1478				    u8 *pDialogToken,
1479				    struct rt_measure_req_info * pMeasureReqInfo,
1480				    struct rt_measure_req * pMeasureReq)
1481{
1482	struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1483	u8 *pFramePtr = Fr->Octet;
1484	BOOLEAN result = FALSE;
1485	struct rt_eid * eid_ptr;
1486	u8 *ptr;
1487	u64 MeasureStartTime;
1488	u16 MeasureDuration;
1489
1490	/* skip 802.11 header. */
1491	MsgLen -= sizeof(struct rt_header_802_11);
1492
1493	/* skip category and action code. */
1494	pFramePtr += 2;
1495	MsgLen -= 2;
1496
1497	if (pMeasureReqInfo == NULL)
1498		return result;
1499
1500	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1501	pFramePtr += 1;
1502	MsgLen -= 1;
1503
1504	eid_ptr = (struct rt_eid *) pFramePtr;
1505	while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1506	       ((u8 *)pFramePtr + MsgLen)) {
1507		switch (eid_ptr->Eid) {
1508		case IE_MEASUREMENT_REQUEST:
1509			NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet,
1510				       1);
1511			NdisMoveMemory(&pMeasureReqInfo->ReqMode.word,
1512				       eid_ptr->Octet + 1, 1);
1513			NdisMoveMemory(&pMeasureReqInfo->ReqType,
1514				       eid_ptr->Octet + 2, 1);
1515			ptr = (u8 *)(eid_ptr->Octet + 3);
1516			NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1517			NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1518			pMeasureReq->MeasureStartTime =
1519			    SWAP64(MeasureStartTime);
1520			NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1521			pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1522
1523			result = TRUE;
1524			break;
1525
1526		default:
1527			break;
1528		}
1529		eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1530	}
1531
1532	return result;
1533}
1534
1535/*
1536	==========================================================================
1537	Description:
1538		Measurement report action frame sanity check.
1539
1540	Parametrs:
1541		1. MLME message containing the received frame
1542		2. message length.
1543		3. Measurement report infomation buffer.
1544		4. basic report infomation buffer.
1545
1546	Return	: None.
1547	==========================================================================
1548 */
1549
1550/*
1551  Measurement Report IE.
1552  +----+-----+-------+-------------+--------------+----------------+
1553  | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1554  +----+-----+-------+-------------+--------------+----------------+
1555    1     1      1          1             1            variable
1556
1557  Basic Report.
1558  +--------+------------+----------+-----+
1559  | Ch Num | Start Time | Duration | Map |
1560  +--------+------------+----------+-----+
1561      1          8           2        1
1562
1563  Map Field Bit Format.
1564  +-----+---------------+---------------------+-------+------------+----------+
1565  | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1566  +-----+---------------+---------------------+-------+------------+----------+
1567     0          1                  2              3         4          5-7
1568*/
1569static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd,
1570				       void * pMsg,
1571				       unsigned long MsgLen,
1572				       u8 *pDialogToken,
1573				       struct rt_measure_report_info *
1574				       pMeasureReportInfo,
1575				       u8 *pReportBuf)
1576{
1577	struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1578	u8 *pFramePtr = Fr->Octet;
1579	BOOLEAN result = FALSE;
1580	struct rt_eid * eid_ptr;
1581	u8 *ptr;
1582
1583	/* skip 802.11 header. */
1584	MsgLen -= sizeof(struct rt_header_802_11);
1585
1586	/* skip category and action code. */
1587	pFramePtr += 2;
1588	MsgLen -= 2;
1589
1590	if (pMeasureReportInfo == NULL)
1591		return result;
1592
1593	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1594	pFramePtr += 1;
1595	MsgLen -= 1;
1596
1597	eid_ptr = (struct rt_eid *) pFramePtr;
1598	while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1599	       ((u8 *)pFramePtr + MsgLen)) {
1600		switch (eid_ptr->Eid) {
1601		case IE_MEASUREMENT_REPORT:
1602			NdisMoveMemory(&pMeasureReportInfo->Token,
1603				       eid_ptr->Octet, 1);
1604			NdisMoveMemory(&pMeasureReportInfo->ReportMode,
1605				       eid_ptr->Octet + 1, 1);
1606			NdisMoveMemory(&pMeasureReportInfo->ReportType,
1607				       eid_ptr->Octet + 2, 1);
1608			if (pMeasureReportInfo->ReportType == RM_BASIC) {
1609				struct rt_measure_basic_report * pReport =
1610				    (struct rt_measure_basic_report *) pReportBuf;
1611				ptr = (u8 *)(eid_ptr->Octet + 3);
1612				NdisMoveMemory(&pReport->ChNum, ptr, 1);
1613				NdisMoveMemory(&pReport->MeasureStartTime,
1614					       ptr + 1, 8);
1615				NdisMoveMemory(&pReport->MeasureDuration,
1616					       ptr + 9, 2);
1617				NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1618
1619			} else if (pMeasureReportInfo->ReportType == RM_CCA) {
1620				struct rt_measure_cca_report * pReport =
1621				    (struct rt_measure_cca_report *) pReportBuf;
1622				ptr = (u8 *)(eid_ptr->Octet + 3);
1623				NdisMoveMemory(&pReport->ChNum, ptr, 1);
1624				NdisMoveMemory(&pReport->MeasureStartTime,
1625					       ptr + 1, 8);
1626				NdisMoveMemory(&pReport->MeasureDuration,
1627					       ptr + 9, 2);
1628				NdisMoveMemory(&pReport->CCA_Busy_Fraction,
1629					       ptr + 11, 1);
1630
1631			} else if (pMeasureReportInfo->ReportType ==
1632				   RM_RPI_HISTOGRAM) {
1633				struct rt_measure_rpi_report * pReport =
1634				    (struct rt_measure_rpi_report *) pReportBuf;
1635				ptr = (u8 *)(eid_ptr->Octet + 3);
1636				NdisMoveMemory(&pReport->ChNum, ptr, 1);
1637				NdisMoveMemory(&pReport->MeasureStartTime,
1638					       ptr + 1, 8);
1639				NdisMoveMemory(&pReport->MeasureDuration,
1640					       ptr + 9, 2);
1641				NdisMoveMemory(&pReport->RPI_Density, ptr + 11,
1642					       8);
1643			}
1644			result = TRUE;
1645			break;
1646
1647		default:
1648			break;
1649		}
1650		eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1651	}
1652
1653	return result;
1654}
1655
1656/*
1657	==========================================================================
1658	Description:
1659		TPC Request action frame sanity check.
1660
1661	Parametrs:
1662		1. MLME message containing the received frame
1663		2. message length.
1664		3. Dialog Token.
1665
1666	Return	: None.
1667	==========================================================================
1668 */
1669static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd,
1670				void * pMsg,
1671				unsigned long MsgLen, u8 *pDialogToken)
1672{
1673	struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1674	u8 *pFramePtr = Fr->Octet;
1675	BOOLEAN result = FALSE;
1676	struct rt_eid * eid_ptr;
1677
1678	MsgLen -= sizeof(struct rt_header_802_11);
1679
1680	/* skip category and action code. */
1681	pFramePtr += 2;
1682	MsgLen -= 2;
1683
1684	if (pDialogToken == NULL)
1685		return result;
1686
1687	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1688	pFramePtr += 1;
1689	MsgLen -= 1;
1690
1691	eid_ptr = (struct rt_eid *) pFramePtr;
1692	while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1693	       ((u8 *)pFramePtr + MsgLen)) {
1694		switch (eid_ptr->Eid) {
1695		case IE_TPC_REQUEST:
1696			result = TRUE;
1697			break;
1698
1699		default:
1700			break;
1701		}
1702		eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1703	}
1704
1705	return result;
1706}
1707
1708/*
1709	==========================================================================
1710	Description:
1711		TPC Report action frame sanity check.
1712
1713	Parametrs:
1714		1. MLME message containing the received frame
1715		2. message length.
1716		3. Dialog Token.
1717		4. TPC Report IE.
1718
1719	Return	: None.
1720	==========================================================================
1721 */
1722static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd,
1723				void * pMsg,
1724				unsigned long MsgLen,
1725				u8 *pDialogToken,
1726				struct rt_tpc_report_info * pTpcRepInfo)
1727{
1728	struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1729	u8 *pFramePtr = Fr->Octet;
1730	BOOLEAN result = FALSE;
1731	struct rt_eid * eid_ptr;
1732
1733	MsgLen -= sizeof(struct rt_header_802_11);
1734
1735	/* skip category and action code. */
1736	pFramePtr += 2;
1737	MsgLen -= 2;
1738
1739	if (pDialogToken == NULL)
1740		return result;
1741
1742	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1743	pFramePtr += 1;
1744	MsgLen -= 1;
1745
1746	eid_ptr = (struct rt_eid *) pFramePtr;
1747	while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1748	       ((u8 *)pFramePtr + MsgLen)) {
1749		switch (eid_ptr->Eid) {
1750		case IE_TPC_REPORT:
1751			NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1752			NdisMoveMemory(&pTpcRepInfo->LinkMargin,
1753				       eid_ptr->Octet + 1, 1);
1754			result = TRUE;
1755			break;
1756
1757		default:
1758			break;
1759		}
1760		eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1761	}
1762
1763	return result;
1764}
1765
1766/*
1767	==========================================================================
1768	Description:
1769		Channel Switch Announcement action frame handler.
1770
1771	Parametrs:
1772		Elme - MLME message containing the received frame
1773
1774	Return	: None.
1775	==========================================================================
1776 */
1777static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1778{
1779	struct rt_ch_sw_ann_info ChSwAnnInfo;
1780	struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1781	u8 index = 0, Channel = 0, NewChannel = 0;
1782	unsigned long Bssidx = 0;
1783
1784	NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info));
1785	if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1786		DBGPRINT(RT_DEBUG_TRACE,
1787			 ("Invalid Channel Switch Action Frame.\n"));
1788		return;
1789	}
1790
1791	if (pAd->OpMode == OPMODE_STA) {
1792		Bssidx =
1793		    BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3,
1794				   pAd->CommonCfg.Channel);
1795		if (Bssidx == BSS_NOT_FOUND) {
1796			DBGPRINT(RT_DEBUG_TRACE,
1797				 ("PeerChSwAnnAction - Bssidx is not found\n"));
1798			return;
1799		}
1800
1801		DBGPRINT(RT_DEBUG_TRACE,
1802			 ("\n****Bssidx is %d, Channel = %d\n", index,
1803			  pAd->ScanTab.BssEntry[Bssidx].Channel));
1804		hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6);
1805
1806		Channel = pAd->CommonCfg.Channel;
1807		NewChannel = ChSwAnnInfo.Channel;
1808
1809		if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1810		    && (Channel != NewChannel)) {
1811			/* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1812			/* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
1813			AsicSwitchChannel(pAd, 1, FALSE);
1814			AsicLockChannel(pAd, 1);
1815			LinkDown(pAd, FALSE);
1816			MlmeQueueInit(&pAd->Mlme.Queue);
1817			BssTableInit(&pAd->ScanTab);
1818			RTMPusecDelay(1000000);	/* use delay to prevent STA do reassoc */
1819
1820			/* channel sanity check */
1821			for (index = 0; index < pAd->ChannelListNum; index++) {
1822				if (pAd->ChannelList[index].Channel ==
1823				    NewChannel) {
1824					pAd->ScanTab.BssEntry[Bssidx].Channel =
1825					    NewChannel;
1826					pAd->CommonCfg.Channel = NewChannel;
1827					AsicSwitchChannel(pAd,
1828							  pAd->CommonCfg.
1829							  Channel, FALSE);
1830					AsicLockChannel(pAd,
1831							pAd->CommonCfg.Channel);
1832					DBGPRINT(RT_DEBUG_TRACE,
1833						 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n",
1834						  NewChannel));
1835					break;
1836				}
1837			}
1838
1839			if (index >= pAd->ChannelListNum) {
1840				DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1841			}
1842		}
1843	}
1844
1845	return;
1846}
1847
1848/*
1849	==========================================================================
1850	Description:
1851		Measurement Request action frame handler.
1852
1853	Parametrs:
1854		Elme - MLME message containing the received frame
1855
1856	Return	: None.
1857	==========================================================================
1858 */
1859static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd,
1860				 struct rt_mlme_queue_elem *Elem)
1861{
1862	struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1863	u8 DialogToken;
1864	struct rt_measure_req_info MeasureReqInfo;
1865	struct rt_measure_req MeasureReq;
1866	MEASURE_REPORT_MODE ReportMode;
1867
1868	if (PeerMeasureReqSanity
1869	    (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1870	     &MeasureReq)) {
1871		ReportMode.word = 0;
1872		ReportMode.field.Incapable = 1;
1873		EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1874				      MeasureReqInfo.Token, ReportMode.word,
1875				      MeasureReqInfo.ReqType, 0, NULL);
1876	}
1877
1878	return;
1879}
1880
1881/*
1882	==========================================================================
1883	Description:
1884		Measurement Report action frame handler.
1885
1886	Parametrs:
1887		Elme - MLME message containing the received frame
1888
1889	Return	: None.
1890	==========================================================================
1891 */
1892static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd,
1893				    struct rt_mlme_queue_elem *Elem)
1894{
1895	struct rt_measure_report_info MeasureReportInfo;
1896	struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1897	u8 DialogToken;
1898	u8 *pMeasureReportInfo;
1899
1900/*      if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1901/*              return; */
1902
1903	pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC);
1904	if (pMeasureReportInfo == NULL) {
1905		DBGPRINT(RT_DEBUG_ERROR,
1906			 ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1907			  __func__, sizeof(struct rt_measure_rpi_report)));
1908		return;
1909	}
1910
1911	NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info));
1912	NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report));
1913	if (PeerMeasureReportSanity
1914	    (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1915	     pMeasureReportInfo)) {
1916		do {
1917			struct rt_measure_req_entry *pEntry = NULL;
1918
1919			/* Not a autonomous measure report. */
1920			/* check the dialog token field. drop it if the dialog token doesn't match. */
1921			if ((DialogToken != 0)
1922			    && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1923				NULL))
1924				break;
1925
1926			if (pEntry != NULL)
1927				MeasureReqDelete(pAd, pEntry->DialogToken);
1928
1929			if (MeasureReportInfo.ReportType == RM_BASIC) {
1930				struct rt_measure_basic_report * pBasicReport =
1931				    (struct rt_measure_basic_report *) pMeasureReportInfo;
1932				if ((pBasicReport->Map.field.Radar)
1933				    &&
1934				    (DfsRequirementCheck
1935				     (pAd, pBasicReport->ChNum) == TRUE)) {
1936					NotifyChSwAnnToPeerAPs(pAd,
1937							       pFr->Hdr.Addr1,
1938							       pFr->Hdr.Addr2,
1939							       1,
1940							       pBasicReport->
1941							       ChNum);
1942					StartDFSProcedure(pAd,
1943							  pBasicReport->ChNum,
1944							  1);
1945				}
1946			}
1947		} while (FALSE);
1948	} else
1949		DBGPRINT(RT_DEBUG_TRACE,
1950			 ("Invalid Measurement Report Frame.\n"));
1951
1952	kfree(pMeasureReportInfo);
1953
1954	return;
1955}
1956
1957/*
1958	==========================================================================
1959	Description:
1960		TPC Request action frame handler.
1961
1962	Parametrs:
1963		Elme - MLME message containing the received frame
1964
1965	Return	: None.
1966	==========================================================================
1967 */
1968static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1969{
1970	struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1971	u8 *pFramePtr = pFr->Octet;
1972	u8 DialogToken;
1973	u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1974	u8 LinkMargin = 0;
1975	char RealRssi;
1976
1977	/* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */
1978	/*                              STA may incorporate rate information and channel conditions, including interference, into its computation */
1979	/*                              of link margin. */
1980
1981	RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1982			       ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1983			       ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1984
1985	/* skip Category and action code. */
1986	pFramePtr += 2;
1987
1988	/* Dialog token. */
1989	NdisMoveMemory(&DialogToken, pFramePtr, 1);
1990
1991	LinkMargin = (RealRssi / MIN_RCV_PWR);
1992	if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1993		EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
1994			      LinkMargin);
1995
1996	return;
1997}
1998
1999/*
2000	==========================================================================
2001	Description:
2002		TPC Report action frame handler.
2003
2004	Parametrs:
2005		Elme - MLME message containing the received frame
2006
2007	Return	: None.
2008	==========================================================================
2009 */
2010static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2011{
2012	u8 DialogToken;
2013	struct rt_tpc_report_info TpcRepInfo;
2014	struct rt_tpc_req_entry *pEntry = NULL;
2015
2016	NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info));
2017	if (PeerTpcRepSanity
2018	    (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2019		pEntry = TpcReqLookUp(pAd, DialogToken);
2020		if (pEntry != NULL) {
2021			TpcReqDelete(pAd, pEntry->DialogToken);
2022			DBGPRINT(RT_DEBUG_TRACE,
2023				 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2024				  __func__, DialogToken, TpcRepInfo.TxPwr,
2025				  TpcRepInfo.LinkMargin));
2026		}
2027	}
2028
2029	return;
2030}
2031
2032/*
2033	==========================================================================
2034	Description:
2035		Spectrun action frames Handler such as channel switch annoucement,
2036		measurement report, measurement request actions frames.
2037
2038	Parametrs:
2039		Elme - MLME message containing the received frame
2040
2041	Return	: None.
2042	==========================================================================
2043 */
2044void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2045{
2046
2047	u8 Action = Elem->Msg[LENGTH_802_11 + 1];
2048
2049	if (pAd->CommonCfg.bIEEE80211H != TRUE)
2050		return;
2051
2052	switch (Action) {
2053	case SPEC_MRQ:
2054		/* current rt2860 unable do such measure specified in Measurement Request. */
2055		/* reject all measurement request. */
2056		PeerMeasureReqAction(pAd, Elem);
2057		break;
2058
2059	case SPEC_MRP:
2060		PeerMeasureReportAction(pAd, Elem);
2061		break;
2062
2063	case SPEC_TPCRQ:
2064		PeerTpcReqAction(pAd, Elem);
2065		break;
2066
2067	case SPEC_TPCRP:
2068		PeerTpcRepAction(pAd, Elem);
2069		break;
2070
2071	case SPEC_CHANNEL_SWITCH:
2072
2073		PeerChSwAnnAction(pAd, Elem);
2074		break;
2075	}
2076
2077	return;
2078}
2079
2080/*
2081	==========================================================================
2082	Description:
2083
2084	Parametrs:
2085
2086	Return	: None.
2087	==========================================================================
2088 */
2089int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2090{
2091	u32 Aid = 1;
2092	u32 ArgIdx;
2093	char *thisChar;
2094
2095	MEASURE_REQ_MODE MeasureReqMode;
2096	u8 MeasureReqToken = RandomByte(pAd);
2097	u8 MeasureReqType = RM_BASIC;
2098	u8 MeasureCh = 1;
2099	u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2100	struct rt_measure_req MeasureReq;
2101	u8 TotalLen;
2102
2103	struct rt_header_802_11 ActHdr;
2104	u8 *pOutBuffer = NULL;
2105	int NStatus;
2106	unsigned long FrameLen;
2107
2108	NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);	/*Get an unused nonpaged memory */
2109	if (NStatus != NDIS_STATUS_SUCCESS) {
2110		DBGPRINT(RT_DEBUG_TRACE,
2111			 ("%s() allocate memory failed \n", __func__));
2112		goto END_OF_MEASURE_REQ;
2113	}
2114
2115	ArgIdx = 1;
2116	while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2117		switch (ArgIdx) {
2118		case 1:	/* Aid. */
2119			Aid = (u8)simple_strtol(thisChar, 0, 16);
2120			break;
2121
2122		case 2:	/* Measurement Request Type. */
2123			MeasureReqType = simple_strtol(thisChar, 0, 16);
2124			if (MeasureReqType > 3) {
2125				DBGPRINT(RT_DEBUG_ERROR,
2126					 ("%s: unknow MeasureReqType(%d)\n",
2127					  __func__, MeasureReqType));
2128				goto END_OF_MEASURE_REQ;
2129			}
2130			break;
2131
2132		case 3:	/* Measurement channel. */
2133			MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
2134			break;
2135		}
2136		ArgIdx++;
2137	}
2138
2139	DBGPRINT(RT_DEBUG_TRACE,
2140		 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2141		  Aid, MeasureReqType, MeasureCh));
2142	if (!VALID_WCID(Aid)) {
2143		DBGPRINT(RT_DEBUG_ERROR,
2144			 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2145		goto END_OF_MEASURE_REQ;
2146	}
2147
2148	MeasureReqMode.word = 0;
2149	MeasureReqMode.field.Enable = 1;
2150
2151	MeasureReqInsert(pAd, MeasureReqToken);
2152
2153	/* build action frame header. */
2154	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2155			 pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
2156
2157	NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
2158	FrameLen = sizeof(struct rt_header_802_11);
2159
2160	TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req);
2161
2162	MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2163				sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC,
2164				MeasureReqToken, MeasureReqMode.word,
2165				MeasureReqType, 0);
2166
2167	MeasureReq.ChNum = MeasureCh;
2168	MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2169	MeasureReq.MeasureDuration = cpu2le16(2000);
2170
2171	{
2172		unsigned long TempLen;
2173		MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2174				  sizeof(struct rt_measure_req), &MeasureReq,
2175				  END_OF_ARGS);
2176		FrameLen += TempLen;
2177	}
2178
2179	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
2180
2181END_OF_MEASURE_REQ:
2182	MlmeFreeMemory(pAd, pOutBuffer);
2183
2184	return TRUE;
2185}
2186
2187int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2188{
2189	u32 Aid;
2190
2191	u8 TpcReqToken = RandomByte(pAd);
2192
2193	Aid = (u32)simple_strtol(arg, 0, 16);
2194
2195	DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2196	if (!VALID_WCID(Aid)) {
2197		DBGPRINT(RT_DEBUG_ERROR,
2198			 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2199		return TRUE;
2200	}
2201
2202	TpcReqInsert(pAd, TpcReqToken);
2203
2204	EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2205
2206	return TRUE;
2207}
2208