Merge tag 'qcom-soc-for-3.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / staging / rtl8723au / core / rtw_wlan_util.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _RTW_WLAN_UTIL_C_
16
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <linux/ieee80211.h>
20 #include <wifi.h>
21
22 static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
23 static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
24
25 static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
26 static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
27
28 static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
29 static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
30 static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
31 static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
32 static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
33 static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
34
35 unsigned char REALTEK_96B_IE23A[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
36
37 #define R2T_PHY_DELAY   (0)
38
39 /* define WAIT_FOR_BCN_TO_MIN   (3000) */
40 #define WAIT_FOR_BCN_TO_MIN     (6000)
41 #define WAIT_FOR_BCN_TO_MAX     (20000)
42
43 static u8 rtw_basic_rate_cck[4] = {
44         IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
45         IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK
46 };
47
48 static u8 rtw_basic_rate_ofdm[3] = {
49         IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
50         IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
51 };
52
53 static u8 rtw_basic_rate_mix[7] = {
54         IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
55         IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK,
56         IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
57         IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
58 };
59
60 int cckrates_included23a(unsigned char *rate, int ratelen)
61 {
62         int     i;
63
64         for (i = 0; i < ratelen; i++) {
65                 if  ((((rate[i]) & 0x7f) == 2)  || (((rate[i]) & 0x7f) == 4) ||
66                      (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22))
67                         return true;
68         }
69
70         return false;
71 }
72
73 int cckratesonly_included23a(unsigned char *rate, int ratelen)
74 {
75         int     i;
76
77         for (i = 0; i < ratelen; i++) {
78                 if  ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
79                            (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22))
80                 return false;
81         }
82
83         return true;
84 }
85
86 unsigned char networktype_to_raid23a(unsigned char network_type)
87 {
88         unsigned char raid;
89
90         switch (network_type) {
91         case WIRELESS_11B:
92                 raid = RATR_INX_WIRELESS_B;
93                 break;
94         case WIRELESS_11A:
95         case WIRELESS_11G:
96                 raid = RATR_INX_WIRELESS_G;
97                 break;
98         case WIRELESS_11BG:
99                 raid = RATR_INX_WIRELESS_GB;
100                 break;
101         case WIRELESS_11_24N:
102         case WIRELESS_11_5N:
103                 raid = RATR_INX_WIRELESS_N;
104                 break;
105         case WIRELESS_11A_5N:
106         case WIRELESS_11G_24N:
107                 raid = RATR_INX_WIRELESS_NG;
108                 break;
109         case WIRELESS_11BG_24N:
110                 raid = RATR_INX_WIRELESS_NGB;
111                 break;
112         default:
113                 raid = RATR_INX_WIRELESS_GB;
114                 break;
115         }
116         return raid;
117 }
118
119 u8 judge_network_type23a(struct rtw_adapter *padapter, unsigned char *rate, int ratelen)
120 {
121         u8 network_type = 0;
122         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
123         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
124
125         if (pmlmeext->cur_channel > 14) {
126                 if (pmlmeinfo->HT_enable)
127                         network_type = WIRELESS_11_5N;
128                 network_type |= WIRELESS_11A;
129         } else {
130                 if (pmlmeinfo->HT_enable)
131                         network_type = WIRELESS_11_24N;
132
133                 if ((cckratesonly_included23a(rate, ratelen)) == true)
134                         network_type |= WIRELESS_11B;
135                 else if ((cckrates_included23a(rate, ratelen)) == true)
136                         network_type |= WIRELESS_11BG;
137                 else
138                         network_type |= WIRELESS_11G;
139         }
140         return  network_type;
141 }
142
143 unsigned char ratetbl_val_2wifirate(unsigned char rate)
144 {
145         unsigned char val = 0;
146
147         switch (rate & 0x7f) {
148         case 0:
149                 val = IEEE80211_CCK_RATE_1MB;
150                 break;
151         case 1:
152                 val = IEEE80211_CCK_RATE_2MB;
153                 break;
154         case 2:
155                 val = IEEE80211_CCK_RATE_5MB;
156                 break;
157         case 3:
158                 val = IEEE80211_CCK_RATE_11MB;
159                 break;
160         case 4:
161                 val = IEEE80211_OFDM_RATE_6MB;
162                 break;
163         case 5:
164                 val = IEEE80211_OFDM_RATE_9MB;
165                 break;
166         case 6:
167                 val = IEEE80211_OFDM_RATE_12MB;
168                 break;
169         case 7:
170                 val = IEEE80211_OFDM_RATE_18MB;
171                 break;
172         case 8:
173                 val = IEEE80211_OFDM_RATE_24MB;
174                 break;
175         case 9:
176                 val = IEEE80211_OFDM_RATE_36MB;
177                 break;
178         case 10:
179                 val = IEEE80211_OFDM_RATE_48MB;
180                 break;
181         case 11:
182                 val = IEEE80211_OFDM_RATE_54MB;
183                 break;
184         }
185         return val;
186 }
187
188 int is_basicrate(struct rtw_adapter *padapter, unsigned char rate)
189 {
190         int i;
191         unsigned char val;
192         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
193
194         for (i = 0; i < NumRates; i++) {
195                 val = pmlmeext->basicrate[i];
196
197                 if ((val != 0xff) && (val != 0xfe)) {
198                         if (rate == ratetbl_val_2wifirate(val))
199                                 return true;
200                 }
201         }
202
203         return false;
204 }
205
206 unsigned int ratetbl2rateset(struct rtw_adapter *padapter, unsigned char *rateset)
207 {
208         int i;
209         unsigned char rate;
210         unsigned int    len = 0;
211         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
212
213         for (i = 0; i < NumRates; i++) {
214                 rate = pmlmeext->datarate[i];
215
216                 switch (rate) {
217                 case 0xff:
218                         return len;
219                 case 0xfe:
220                         continue;
221                 default:
222                         rate = ratetbl_val_2wifirate(rate);
223
224                         if (is_basicrate(padapter, rate) == true)
225                                 rate |= IEEE80211_BASIC_RATE_MASK;
226
227                         rateset[len] = rate;
228                         len++;
229                         break;
230                 }
231         }
232         return len;
233 }
234
235 void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
236 {
237         unsigned char supportedrates[NumRates];
238
239         memset(supportedrates, 0, NumRates);
240         *bssrate_len = ratetbl2rateset(padapter, supportedrates);
241         memcpy(pbssrate, supportedrates, *bssrate_len);
242 }
243
244 void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS)
245 {
246         u8      i;
247         u8      rate;
248
249         /*  1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
250         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
251                 rate = mBratesOS[i] & 0x7f;
252                 switch (rate) {
253                 case IEEE80211_CCK_RATE_1MB:
254                 case IEEE80211_CCK_RATE_2MB:
255                 case IEEE80211_CCK_RATE_5MB:
256                 case IEEE80211_CCK_RATE_11MB:
257                 case IEEE80211_OFDM_RATE_6MB:
258                 case IEEE80211_OFDM_RATE_12MB:
259                 case IEEE80211_OFDM_RATE_24MB:
260                         mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
261                         break;
262                 default:
263                         break;
264                 }
265         }
266 }
267
268 void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen)
269 {
270         u8      i;
271         u8      rate;
272
273         for (i = 0; i < bssratelen; i++) {
274                 rate = bssrateset[i] & 0x7f;
275                 switch (rate) {
276                 case IEEE80211_CCK_RATE_1MB:
277                 case IEEE80211_CCK_RATE_2MB:
278                 case IEEE80211_CCK_RATE_5MB:
279                 case IEEE80211_CCK_RATE_11MB:
280                         bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
281                         break;
282                 }
283         }
284 }
285
286 void Save_DM_Func_Flag23a(struct rtw_adapter *padapter)
287 {
288         u8      bSaveFlag = true;
289
290         rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
291 }
292
293 void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter)
294 {
295         u8      bSaveFlag = false;
296         rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
297 }
298
299 void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable)
300 {
301         if (enable == true)
302                 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
303         else
304                 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
305 }
306
307 static void Set_NETYPE0_MSR(struct rtw_adapter *padapter, u8 type)
308 {
309         rtw_hal_set_hwreg23a(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
310 }
311
312 void Set_MSR23a(struct rtw_adapter *padapter, u8 type)
313 {
314                 Set_NETYPE0_MSR(padapter, type);
315 }
316
317 inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
318 {
319         return adapter_to_dvobj(adapter)->oper_channel;
320 }
321
322 inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch)
323 {
324         adapter_to_dvobj(adapter)->oper_channel = ch;
325 }
326
327 inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter)
328 {
329         return adapter_to_dvobj(adapter)->oper_bwmode;
330 }
331
332 inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw)
333 {
334         adapter_to_dvobj(adapter)->oper_bwmode = bw;
335 }
336
337 inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter)
338 {
339         return adapter_to_dvobj(adapter)->oper_ch_offset;
340 }
341
342 inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset)
343 {
344         adapter_to_dvobj(adapter)->oper_ch_offset = offset;
345 }
346
347 void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel)
348 {
349         mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
350
351         /* saved channel info */
352         rtw_set_oper_ch23a(padapter, channel);
353
354         rtw_hal_set_chan23a(padapter, channel);
355
356         mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
357 }
358
359 void SetBWMode23a(struct rtw_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
360 {
361         mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex);
362
363         /* saved bw info */
364         rtw_set_oper_bw23a(padapter, bwmode);
365         rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
366
367         rtw_hal_set_bwmode23a(padapter, (enum ht_channel_width)bwmode,
368                            channel_offset);
369
370         mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex);
371 }
372
373 void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel,
374                         unsigned char channel_offset, unsigned short bwmode)
375 {
376         u8 center_ch;
377
378         if (padapter->bNotifyChannelChange)
379                 DBG_8723A("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode);
380
381         if ((bwmode == HT_CHANNEL_WIDTH_20) ||
382             (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
383                 /* SelectChannel23a(padapter, channel); */
384                 center_ch = channel;
385         } else {
386                 /* switch to the proper channel */
387                 if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
388                         /* SelectChannel23a(padapter, channel + 2); */
389                         center_ch = channel + 2;
390                 } else {
391                         /* SelectChannel23a(padapter, channel - 2); */
392                         center_ch = channel - 2;
393                 }
394         }
395
396         /* set Channel */
397         mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
398
399         /* saved channel/bw info */
400         rtw_set_oper_ch23a(padapter, channel);
401         rtw_set_oper_bw23a(padapter, bwmode);
402         rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
403
404         rtw_hal_set_chan23a(padapter, center_ch); /*  set center channel */
405
406         mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
407
408         SetBWMode23a(padapter, bwmode, channel_offset);
409 }
410
411 int get_bsstype23a(unsigned short capability)
412 {
413         if (capability & BIT(0))
414                 return WIFI_FW_AP_STATE;
415         else if (capability & BIT(1))
416                 return WIFI_FW_ADHOC_STATE;
417         return 0;
418 }
419
420 inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork)
421 {
422         return pnetwork->MacAddress;
423 }
424
425 u16 get_beacon_interval23a(struct wlan_bssid_ex *bss)
426 {
427         unsigned short val;
428         memcpy((unsigned char *)&val, rtw_get_beacon_interval23a_from_ie(bss->IEs), 2);
429
430         return le16_to_cpu(val);
431 }
432
433 int is_client_associated_to_ap23a(struct rtw_adapter *padapter)
434 {
435         struct mlme_ext_priv    *pmlmeext;
436         struct mlme_ext_info    *pmlmeinfo;
437
438         if (!padapter)
439                 return _FAIL;
440
441         pmlmeext = &padapter->mlmeextpriv;
442         pmlmeinfo = &pmlmeext->mlmext_info;
443
444         if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
445                 return true;
446         else
447                 return _FAIL;
448 }
449
450 int is_client_associated_to_ibss23a(struct rtw_adapter *padapter)
451 {
452         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
453         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
454
455         if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
456             ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
457                 return true;
458         else
459                 return _FAIL;
460 }
461
462 int is_IBSS_empty23a(struct rtw_adapter *padapter)
463 {
464         unsigned int i;
465         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
466         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
467
468         for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
469                 if (pmlmeinfo->FW_sta_info[i].status == 1)
470                         return _FAIL;
471         }
472
473         return true;
474 }
475
476 unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)
477 {
478         if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
479                 return WAIT_FOR_BCN_TO_MIN;
480         else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
481                 return WAIT_FOR_BCN_TO_MAX;
482         else
483                 return bcn_interval << 2;
484 }
485
486 void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex)
487 {
488         rtw_hal_set_hwreg23a(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
489 }
490
491 void invalidate_cam_all23a(struct rtw_adapter *padapter)
492 {
493         rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
494 }
495
496 void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
497 {
498         unsigned int    i, val, addr;
499         int j;
500         u32     cam_val[2];
501
502         addr = entry << 3;
503
504         for (j = 5; j >= 0; j--) {
505                 switch (j) {
506                 case 0:
507                         val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
508                         break;
509                 case 1:
510                         val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
511                         break;
512                 default:
513                         i = (j - 2) << 2;
514                         val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
515                         break;
516                 }
517
518                 cam_val[0] = val;
519                 cam_val[1] = addr + (unsigned int)j;
520
521                 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
522
523                 /* rtw_write32(padapter, WCAMI, val); */
524
525                 /* cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); */
526                 /* rtw_write32(padapter, RWCAM, cmd); */
527
528                 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val); */
529
530         }
531 }
532
533 void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
534 {
535         unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
536
537         unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
538
539         write_cam23a(padapter, entry, 0, null_sta, null_key);
540 }
541
542 int allocate_fw_sta_entry23a(struct rtw_adapter *padapter)
543 {
544         unsigned int mac_id;
545         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
546         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
547
548         for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
549                 if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
550                         pmlmeinfo->FW_sta_info[mac_id].status = 1;
551                         pmlmeinfo->FW_sta_info[mac_id].retry = 0;
552                         break;
553                 }
554         }
555
556         return mac_id;
557 }
558
559 void flush_all_cam_entry23a(struct rtw_adapter *padapter)
560 {
561         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
562         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
563
564         rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
565
566         memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
567 }
568
569 #if defined(CONFIG_8723AU_P2P) && defined(CONFIG_8723AU_P2P)
570 int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
571 {
572         struct wifidirect_info  *pwdinfo;
573         u8      wfd_ie[MAX_WFD_IE_LEN] = {0x00};
574         u32     wfd_ielen = 0;
575
576         pwdinfo = &padapter->wdinfo;
577         if (rtw_get_wfd_ie((u8 *) pIE, pIE->Length, wfd_ie, &wfd_ielen)) {
578                 u8      attr_content[ 10 ] = { 0x00 };
579                 u32     attr_contentlen = 0;
580
581                 DBG_8723A("[%s] Found WFD IE\n", __func__);
582                 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
583                 if (attr_contentlen) {
584                         pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
585                         DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
586                         return true;
587                 }
588         } else {
589                 DBG_8723A("[%s] NO WFD IE\n", __func__);
590         }
591         return _FAIL;
592 }
593 #endif
594
595 int WMM_param_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies *     pIE)
596 {
597         /* struct registry_priv *pregpriv = &padapter->registrypriv; */
598         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
599         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
600         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
601
602         if (pmlmepriv->qospriv.qos_option == 0) {
603                 pmlmeinfo->WMM_enable = 0;
604                 return _FAIL;
605         }
606
607         pmlmeinfo->WMM_enable = 1;
608         memcpy(&pmlmeinfo->WMM_param, (pIE->data + 6),
609                sizeof(struct WMM_para_element));
610         return true;
611 }
612
613 void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
614 {
615         u8      ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
616         u8      acm_mask;
617         u16     TXOP;
618         u32     acParm, i;
619         u32     edca[4], inx[4];
620         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
621         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
622         struct xmit_priv                *pxmitpriv = &padapter->xmitpriv;
623         struct registry_priv    *pregpriv = &padapter->registrypriv;
624
625         if (pmlmeinfo->WMM_enable == 0) {
626                 padapter->mlmepriv.acm_mask = 0;
627                 return;
628         }
629
630         acm_mask = 0;
631
632         if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
633                 aSifsTime = 10;
634         else
635                 aSifsTime = 16;
636
637                 for (i = 0; i < 4; i++) {
638                 ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
639                 ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
640
641                 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
642                 AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
643
644                 ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
645                 ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
646                 TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
647
648                 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
649
650                 switch (ACI) {
651                 case 0x0:
652                         rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
653                         acm_mask |= (ACM? BIT(1):0);
654                         edca[XMIT_BE_QUEUE] = acParm;
655                         break;
656                 case 0x1:
657                         rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
658                         /* acm_mask |= (ACM? BIT(0):0); */
659                         edca[XMIT_BK_QUEUE] = acParm;
660                         break;
661                 case 0x2:
662                         rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
663                         acm_mask |= (ACM? BIT(2):0);
664                         edca[XMIT_VI_QUEUE] = acParm;
665                         break;
666                 case 0x3:
667                         rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
668                         acm_mask |= (ACM? BIT(3):0);
669                         edca[XMIT_VO_QUEUE] = acParm;
670                         break;
671                 }
672
673                 DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm);
674         }
675
676         if (padapter->registrypriv.acm_method == 1)
677                 rtw_hal_set_hwreg23a(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
678         else
679                 padapter->mlmepriv.acm_mask = acm_mask;
680
681         inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
682
683         if (pregpriv->wifi_spec == 1) {
684                 u32     j, tmp, change_inx = false;
685
686                 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
687                 for (i = 0; i < 4; i++) {
688                         for (j = i+1; j < 4; j++) {
689                                 /* compare CW and AIFS */
690                                 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
691                                         change_inx = true;
692                                 } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
693                                         /* compare TXOP */
694                                         if ((edca[j] >> 16) > (edca[i] >> 16))
695                                                 change_inx = true;
696                                 }
697
698                                 if (change_inx) {
699                                         tmp = edca[i];
700                                         edca[i] = edca[j];
701                                         edca[j] = tmp;
702
703                                         tmp = inx[i];
704                                         inx[i] = inx[j];
705                                         inx[j] = tmp;
706
707                                         change_inx = false;
708                                 }
709                         }
710                 }
711         }
712
713         for (i = 0; i<4; i++) {
714                 pxmitpriv->wmm_para_seq[i] = inx[i];
715                 DBG_8723A("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
716         }
717
718         return;
719 }
720
721 static void bwmode_update_check(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
722 {
723         struct HT_info_element   *pHT_info;
724         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
725         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
726         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
727         struct registry_priv *pregistrypriv = &padapter->registrypriv;
728         struct ht_priv  *phtpriv = &pmlmepriv->htpriv;
729         unsigned char    new_bwmode;
730         unsigned char  new_ch_offset;
731
732         if (!pIE)
733                 return;
734         if (!phtpriv->ht_option)
735                 return;
736         if (pIE->Length > sizeof(struct HT_info_element))
737                 return;
738
739         pHT_info = (struct HT_info_element *)pIE->data;
740
741         if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
742                 new_bwmode = HT_CHANNEL_WIDTH_40;
743
744                 switch (pHT_info->infos[0] & 0x3) {
745                 case 1:
746                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
747                         break;
748                 case 3:
749                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
750                         break;
751                 default:
752                         new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
753                         break;
754                 }
755         } else {
756                 new_bwmode = HT_CHANNEL_WIDTH_20;
757                 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
758         }
759
760         if ((new_bwmode!= pmlmeext->cur_bwmode) ||
761             (new_ch_offset!= pmlmeext->cur_ch_offset)) {
762                 pmlmeinfo->bwmode_updated = true;
763
764                 pmlmeext->cur_bwmode = new_bwmode;
765                 pmlmeext->cur_ch_offset = new_ch_offset;
766
767                 /* update HT info also */
768                 HT_info_handler23a(padapter, pIE);
769         } else {
770                 pmlmeinfo->bwmode_updated = false;
771         }
772
773         if (pmlmeinfo->bwmode_updated) {
774                 struct sta_info *psta;
775                 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
776                 struct sta_priv *pstapriv = &padapter->stapriv;
777
778                 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
779
780                 /* update ap's stainfo */
781                 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
782                 if (psta) {
783                         struct ht_priv  *phtpriv_sta = &psta->htpriv;
784
785                         if (phtpriv_sta->ht_option) {
786                                 /*  bwmode */
787                                 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
788                                 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
789                         } else {
790                                 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
791                                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
792                         }
793
794                 }
795         }
796 }
797
798 void HT_caps_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
799 {
800         unsigned int    i;
801         u8      rf_type;
802         u8      max_AMPDU_len, min_MPDU_spacing;
803         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
804         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
805         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
806         struct ht_priv                  *phtpriv = &pmlmepriv->htpriv;
807
808         if (pIE == NULL) return;
809
810         if (phtpriv->ht_option == false)        return;
811
812         pmlmeinfo->HT_caps_enable = 1;
813
814         for (i = 0; i < (pIE->Length); i++) {
815                 if (i != 2) {
816                         /*      Commented by Albert 2010/07/12 */
817                         /*      Got the endian issue here. */
818                         pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
819                 } else {
820                         /* modify from  fw by Thomas 2010/11/17 */
821                         if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
822                                 max_AMPDU_len = (pIE->data[i] & 0x3);
823                         else
824                                 max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
825
826                         if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
827                                 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
828                         else
829                                 min_MPDU_spacing = (pIE->data[i] & 0x1c);
830
831                         pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
832                 }
833         }
834
835         /*      Commented by Albert 2010/07/12 */
836         /*      Have to handle the endian issue after copying. */
837         /*      HT_ext_caps didn't be used yet. */
838         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
839         pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps);
840
841         rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
842
843         /* update the MCS rates */
844         for (i = 0; i < 16; i++) {
845                 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
846                         pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
847                 else
848                         pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
849         }
850         return;
851 }
852
853 void HT_info_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
854 {
855         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
856         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
857         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
858         struct ht_priv                  *phtpriv = &pmlmepriv->htpriv;
859
860         if (pIE == NULL) return;
861
862         if (phtpriv->ht_option == false)        return;
863
864         if (pIE->Length > sizeof(struct HT_info_element))
865                 return;
866
867         pmlmeinfo->HT_info_enable = 1;
868         memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length);
869         return;
870 }
871
872 void HTOnAssocRsp23a(struct rtw_adapter *padapter)
873 {
874         unsigned char           max_AMPDU_len;
875         unsigned char           min_MPDU_spacing;
876         /* struct registry_priv  *pregpriv = &padapter->registrypriv; */
877         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
878         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
879
880         DBG_8723A("%s\n", __func__);
881
882         if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
883                 pmlmeinfo->HT_enable = 1;
884         } else {
885                 pmlmeinfo->HT_enable = 0;
886                 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
887                 return;
888         }
889
890         /* handle A-MPDU parameter field */
891         /*
892                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
893                 AMPDU_para [4:2]:Min MPDU Start Spacing
894         */
895         max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
896
897         min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
898
899         rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
900
901         rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
902 }
903
904 void ERP_IE_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
905 {
906         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
907         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
908
909         if (pIE->Length>1)
910                 return;
911
912         pmlmeinfo->ERP_enable = 1;
913         memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length);
914 }
915
916 void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
917 {
918         struct registry_priv     *pregpriv = &padapter->registrypriv;
919         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
920         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
921
922         switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
923         case 0: /* off */
924                 psta->rtsen = 0;
925                 psta->cts2self = 0;
926                 break;
927         case 1: /* on */
928                 if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
929                         psta->rtsen = 1;
930                         psta->cts2self = 0;
931                 } else {
932                         psta->rtsen = 0;
933                         psta->cts2self = 1;
934                 }
935                 break;
936         case 2: /* auto */
937         default:
938                 if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
939                         if (pregpriv->vcs_type == 1) {
940                                 psta->rtsen = 1;
941                                 psta->cts2self = 0;
942                         } else {
943                                 psta->rtsen = 0;
944                                 psta->cts2self = 1;
945                         }
946                 } else {
947                         psta->rtsen = 0;
948                         psta->cts2self = 0;
949                 }
950                 break;
951         }
952 }
953
954 int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len)
955 {
956         unsigned int            len;
957         unsigned char           *p;
958         unsigned short  val16;
959         struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
960         u16 wpa_len = 0, rsn_len = 0;
961         u8 encryp_protocol = 0;
962         struct wlan_bssid_ex *bssid;
963         int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
964         unsigned char *pbuf;
965         u32 wpa_ielen = 0;
966         u32 hidden_ssid = 0;
967         struct HT_info_element *pht_info = NULL;
968         struct ieee80211_ht_cap *pht_cap = NULL;
969         u32 bcn_channel;
970         unsigned short  ht_cap_info;
971         unsigned char   ht_info_infos_0;
972         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
973         u8 *pbssid = hdr->addr3;
974
975         if (is_client_associated_to_ap23a(Adapter) == false)
976                 return true;
977
978         len = packet_len - sizeof(struct ieee80211_hdr_3addr);
979
980         if (len > MAX_IE_SZ) {
981                 DBG_8723A("%s IE too long for survey event\n", __func__);
982                 return _FAIL;
983         }
984
985         if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
986                 DBG_8723A("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
987                                 MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
988                 return true;
989         }
990
991         bssid = (struct wlan_bssid_ex *)kzalloc(sizeof(struct wlan_bssid_ex),
992                 GFP_ATOMIC);
993
994         if (ieee80211_is_beacon(hdr->frame_control))
995                 bssid->reserved = 1;
996
997         bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
998
999         /* below is to copy the information element */
1000         bssid->IELength = len;
1001         memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
1002
1003         /* check bw and channel offset */
1004         /* parsing HT_CAP_IE */
1005         p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1006         if (p && len>0) {
1007                         pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1008                         ht_cap_info = pht_cap->cap_info;
1009         } else {
1010                         ht_cap_info = 0;
1011         }
1012         /* parsing HT_INFO_IE */
1013         p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1014         if (p && len>0) {
1015                         pht_info = (struct HT_info_element *)(p + 2);
1016                         ht_info_infos_0 = pht_info->infos[0];
1017         } else {
1018                         ht_info_infos_0 = 0;
1019         }
1020         if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
1021                 ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
1022                         DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1023                                                         ht_cap_info, ht_info_infos_0);
1024                         DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1025                                                         cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
1026                         DBG_8723A("%s bw mode change, disconnect\n", __func__);
1027                         /* bcn_info_update */
1028                         cur_network->BcnInfo.ht_cap_info = ht_cap_info;
1029                         cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
1030                         /* to do : need to check that whether modify related register of BB or not */
1031         }
1032
1033         /* Checking for channel */
1034         p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1035         if (p) {
1036                         bcn_channel = *(p + 2);
1037         } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
1038                         p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1039                         if (pht_info) {
1040                                         bcn_channel = pht_info->primary_channel;
1041                         } else { /* we don't find channel IE, so don't check it */
1042                                         DBG_8723A("Oops: %s we don't find channel IE, so don't check it\n", __func__);
1043                                         bcn_channel = Adapter->mlmeextpriv.cur_channel;
1044                         }
1045         }
1046         if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
1047                         DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
1048                                                    bcn_channel, Adapter->mlmeextpriv.cur_channel);
1049                         goto _mismatch;
1050         }
1051
1052         /* checking SSID */
1053         if ((p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_)) == NULL) {
1054                 DBG_8723A("%s marc: cannot find SSID for survey event\n", __func__);
1055                 hidden_ssid = true;
1056         } else {
1057                 hidden_ssid = false;
1058         }
1059
1060         if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
1061                 memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
1062                 bssid->Ssid.ssid_len = *(p + 1);
1063         } else {
1064                 bssid->Ssid.ssid_len = 0;
1065                 bssid->Ssid.ssid[0] = '\0';
1066         }
1067
1068         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1069                  ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
1070                   "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
1071                   bssid->Ssid.ssid, bssid->Ssid.ssid_len,
1072                   cur_network->network.Ssid.ssid,
1073                   cur_network->network.Ssid.ssid_len));
1074
1075         if (memcmp(bssid->Ssid.ssid, cur_network->network.Ssid.ssid, 32) ||
1076             bssid->Ssid.ssid_len != cur_network->network.Ssid.ssid_len) {
1077                 if (bssid->Ssid.ssid[0] != '\0' &&
1078                     bssid->Ssid.ssid_len != 0) { /* not hidden ssid */
1079                         DBG_8723A("%s(), SSID is not match return FAIL\n",
1080                                   __func__);
1081                         goto _mismatch;
1082                 }
1083         }
1084
1085         /* check encryption info */
1086         val16 = rtw_get_capability23a((struct wlan_bssid_ex *)bssid);
1087
1088         if (val16 & BIT(4))
1089                 bssid->Privacy = 1;
1090         else
1091                 bssid->Privacy = 0;
1092
1093         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1094                         ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
1095                          __func__, cur_network->network.Privacy, bssid->Privacy));
1096         if (cur_network->network.Privacy != bssid->Privacy) {
1097                 DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
1098                 goto _mismatch;
1099         }
1100
1101         rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL,&rsn_len, NULL,&wpa_len);
1102
1103         if (rsn_len > 0) {
1104                 encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1105         } else if (wpa_len > 0) {
1106                 encryp_protocol = ENCRYP_PROTOCOL_WPA;
1107         } else {
1108                 if (bssid->Privacy)
1109                         encryp_protocol = ENCRYP_PROTOCOL_WEP;
1110         }
1111
1112         if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
1113                 DBG_8723A("%s(): enctyp is not match , return FAIL\n", __func__);
1114                 goto _mismatch;
1115         }
1116
1117         if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
1118                 pbuf = rtw_get_wpa_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1119                 if (pbuf && (wpa_ielen>0)) {
1120                         if (_SUCCESS == rtw_parse_wpa_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1121                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1122                                                 ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
1123                                                  pairwise_cipher, group_cipher, is_8021x));
1124                         }
1125                 } else {
1126                         pbuf = rtw_get_wpa2_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1127
1128                         if (pbuf && (wpa_ielen>0)) {
1129                                 if (_SUCCESS == rtw_parse_wpa2_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1130                                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1131                                                         ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
1132                                                          __func__, pairwise_cipher, group_cipher, is_8021x));
1133                                 }
1134                         }
1135                 }
1136
1137                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1138                                 ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
1139                 if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
1140                         DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
1141                                         pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
1142                                         group_cipher, cur_network->BcnInfo.group_cipher);
1143                         goto _mismatch;
1144                 }
1145
1146                 if (is_8021x != cur_network->BcnInfo.is_8021x) {
1147                         DBG_8723A("%s authentication is not match , return FAIL\n", __func__);
1148                         goto _mismatch;
1149                 }
1150         }
1151
1152         kfree(bssid);
1153         return _SUCCESS;
1154
1155 _mismatch:
1156         kfree(bssid);
1157
1158         return _FAIL;
1159 }
1160
1161 void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
1162 {
1163         unsigned int i;
1164         unsigned int len;
1165         struct ndis_802_11_var_ies *    pIE;
1166
1167         len = pkt_len -
1168                 (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr));
1169
1170         for (i = 0; i < len;) {
1171                 pIE = (struct ndis_802_11_var_ies *)(pframe + (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr)) + i);
1172
1173                 switch (pIE->ElementID) {
1174                 case _HT_EXTRA_INFO_IE_:        /* HT info */
1175                         /* HT_info_handler23a(padapter, pIE); */
1176                         bwmode_update_check(padapter, pIE);
1177                         break;
1178                 case _ERPINFO_IE_:
1179                         ERP_IE_handler23a(padapter, pIE);
1180                         VCS_update23a(padapter, psta);
1181                         break;
1182                 default:
1183                         break;
1184                 }
1185                 i += (pIE->Length + 2);
1186         }
1187 }
1188
1189 unsigned int is_ap_in_tkip23a(struct rtw_adapter *padapter)
1190 {
1191         u32 i;
1192         struct ndis_802_11_var_ies *    pIE;
1193         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1194         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1195         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1196
1197         if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1198                 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1199                         pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1200
1201                         switch (pIE->ElementID) {
1202                         case _VENDOR_SPECIFIC_IE_:
1203                                 if ((!memcmp(pIE->data, RTW_WPA_OUI23A, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER23A, 4)))
1204                                         return true;
1205                                 break;
1206                         case _RSN_IE_2_:
1207                                 if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER23A, 4))
1208                                         return true;
1209                                 break;
1210                         default:
1211                                 break;
1212                         }
1213                         i += (pIE->Length + 2);
1214                 }
1215                 return false;
1216         } else {
1217                 return false;
1218         }
1219 }
1220
1221 unsigned int should_forbid_n_rate23a(struct rtw_adapter * padapter)
1222 {
1223         u32 i;
1224         struct ndis_802_11_var_ies *    pIE;
1225         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1226         struct wlan_bssid_ex  *cur_network = &pmlmepriv->cur_network.network;
1227
1228         if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1229                 for (i = sizeof(struct ndis_802_11_fixed_ies); i < cur_network->IELength;) {
1230                         pIE = (struct ndis_802_11_var_ies *)(cur_network->IEs + i);
1231
1232                         switch (pIE->ElementID) {
1233                         case _VENDOR_SPECIFIC_IE_:
1234                                 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) &&
1235                                         ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP23A, 4)) ||
1236                                           (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP23A, 4))))
1237                                         return false;
1238                                 break;
1239                         case _RSN_IE_2_:
1240                                 if  ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP23A, 4))  ||
1241                                        (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP23A, 4)))
1242                                 return false;
1243                         default:
1244                                 break;
1245                         }
1246
1247                         i += (pIE->Length + 2);
1248                 }
1249                 return true;
1250         } else {
1251                 return false;
1252         }
1253 }
1254
1255 unsigned int is_ap_in_wep23a(struct rtw_adapter *padapter)
1256 {
1257         u32 i;
1258         struct ndis_802_11_var_ies *    pIE;
1259         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1260         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1261         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1262
1263         if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1264                 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1265                         pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1266
1267                         switch (pIE->ElementID) {
1268                         case _VENDOR_SPECIFIC_IE_:
1269                                 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4))
1270                                         return false;
1271                                 break;
1272                         case _RSN_IE_2_:
1273                                 return false;
1274
1275                         default:
1276                                 break;
1277                         }
1278
1279                         i += (pIE->Length + 2);
1280                 }
1281
1282                 return true;
1283         } else {
1284                 return false;
1285         }
1286 }
1287
1288 int wifirate2_ratetbl_inx23a(unsigned char rate)
1289 {
1290         int     inx = 0;
1291         rate = rate & 0x7f;
1292
1293         switch (rate) {
1294         case 54*2:
1295                 inx = 11;
1296                 break;
1297         case 48*2:
1298                 inx = 10;
1299                 break;
1300         case 36*2:
1301                 inx = 9;
1302                 break;
1303         case 24*2:
1304                 inx = 8;
1305                 break;
1306         case 18*2:
1307                 inx = 7;
1308                 break;
1309         case 12*2:
1310                 inx = 6;
1311                 break;
1312         case 9*2:
1313                 inx = 5;
1314                 break;
1315         case 6*2:
1316                 inx = 4;
1317                 break;
1318         case 11*2:
1319                 inx = 3;
1320                 break;
1321         case 11:
1322                 inx = 2;
1323                 break;
1324         case 2*2:
1325                 inx = 1;
1326                 break;
1327         case 1*2:
1328                 inx = 0;
1329                 break;
1330         }
1331         return inx;
1332 }
1333
1334 unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1335 {
1336         unsigned int i, num_of_rate;
1337         unsigned int mask = 0;
1338
1339         num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1340
1341         for (i = 0; i < num_of_rate; i++) {
1342                 if ((*(ptn + i)) & 0x80)
1343                         mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1344         }
1345         return mask;
1346 }
1347
1348 unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1349 {
1350         unsigned int i, num_of_rate;
1351         unsigned int mask = 0;
1352
1353         num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1354
1355         for (i = 0; i < num_of_rate; i++)
1356                 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1357         return mask;
1358 }
1359
1360 unsigned int update_MSC_rate23a(struct HT_caps_element *pHT_caps)
1361 {
1362         unsigned int mask = 0;
1363
1364         mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
1365
1366         return mask;
1367 }
1368
1369 int support_short_GI23a(struct rtw_adapter *padapter,
1370                      struct HT_caps_element *pHT_caps)
1371 {
1372         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1373         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1374         unsigned char bit_offset;
1375
1376         if (!(pmlmeinfo->HT_enable))
1377                 return _FAIL;
1378         if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK))
1379                 return _FAIL;
1380         bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
1381
1382         if (pHT_caps->u.HT_cap_element.HT_caps_info & (0x1 << bit_offset))
1383                 return _SUCCESS;
1384         else
1385                 return _FAIL;
1386 }
1387
1388 unsigned char get_highest_rate_idx23a(u32 mask)
1389 {
1390         int i;
1391         unsigned char rate_idx = 0;
1392
1393         for (i = 27; i >= 0; i--) {
1394                 if (mask & BIT(i)) {
1395                         rate_idx = i;
1396                         break;
1397                 }
1398         }
1399         return rate_idx;
1400 }
1401
1402 unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps)
1403 {
1404         int i, mcs_rate;
1405
1406         mcs_rate = (pHT_caps->u.HT_cap_element.MCS_rate[0] | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 8));
1407
1408         for (i = 15; i >= 0; i--) {
1409                 if (mcs_rate & (0x1 << i))
1410                         break;
1411         }
1412         return i;
1413 }
1414
1415 void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta)
1416 {
1417         rtw_hal_update_ra_mask23a(psta, 0);
1418 }
1419
1420 void enable_rate_adaptive(struct rtw_adapter *padapter, struct sta_info *psta)
1421 {
1422         Update_RA_Entry23a(padapter, psta);
1423 }
1424
1425 void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
1426 {
1427         /* rate adaptive */
1428         enable_rate_adaptive(padapter, psta);
1429 }
1430
1431 /*  Update RRSR and Rate for USERATE */
1432 void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
1433 {
1434         unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1435 #ifdef CONFIG_8723AU_P2P
1436         struct wifidirect_info* pwdinfo = &padapter->wdinfo;
1437
1438         /*      Added by Albert 2011/03/22 */
1439         /*      In the P2P mode, the driver should not support the b mode. */
1440         /*      So, the Tx packet shouldn't use the CCK rate */
1441         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1442                 return;
1443 #endif /* CONFIG_8723AU_P2P */
1444
1445         memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1446
1447         if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
1448                 memcpy(supported_rates, rtw_basic_rate_cck, 4);
1449         } else if (wirelessmode & WIRELESS_11B) {
1450                 memcpy(supported_rates, rtw_basic_rate_mix, 7);
1451         } else {
1452                 memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1453         }
1454
1455         if (wirelessmode & WIRELESS_11B)
1456                 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1457         else
1458                 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1459
1460         rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, supported_rates);
1461 }
1462
1463 unsigned char check_assoc_AP23a(u8 *pframe, uint len)
1464 {
1465         unsigned int    i;
1466         struct ndis_802_11_var_ies *    pIE;
1467         u8      epigram_vendor_flag;
1468         u8      ralink_vendor_flag;
1469         epigram_vendor_flag = 0;
1470         ralink_vendor_flag = 0;
1471
1472         for (i = sizeof(struct ndis_802_11_fixed_ies); i < len;) {
1473                 pIE = (struct ndis_802_11_var_ies *)(pframe + i);
1474
1475                 switch (pIE->ElementID) {
1476                 case _VENDOR_SPECIFIC_IE_:
1477                         if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
1478                             (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
1479                                 DBG_8723A("link to Artheros AP\n");
1480                                 return HT_IOT_PEER_ATHEROS;
1481                         } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
1482                                    !memcmp(pIE->data, BROADCOM_OUI2, 3) ||
1483                                    !memcmp(pIE->data, BROADCOM_OUI2, 3)) {
1484                                 DBG_8723A("link to Broadcom AP\n");
1485                                 return HT_IOT_PEER_BROADCOM;
1486                         } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
1487                                 DBG_8723A("link to Marvell AP\n");
1488                                 return HT_IOT_PEER_MARVELL;
1489                         } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
1490                                 if (!ralink_vendor_flag) {
1491                                         ralink_vendor_flag = 1;
1492                                 } else {
1493                                         DBG_8723A("link to Ralink AP\n");
1494                                         return HT_IOT_PEER_RALINK;
1495                                 }
1496                         } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
1497                                 DBG_8723A("link to Cisco AP\n");
1498                                 return HT_IOT_PEER_CISCO;
1499                         } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
1500                                 DBG_8723A("link to Realtek 96B\n");
1501                                 return HT_IOT_PEER_REALTEK;
1502                         } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
1503                                 DBG_8723A("link to Airgo Cap\n");
1504                                 return HT_IOT_PEER_AIRGO;
1505                         } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
1506                                 epigram_vendor_flag = 1;
1507                                 if (ralink_vendor_flag) {
1508                                         DBG_8723A("link to Tenda W311R AP\n");
1509                                         return HT_IOT_PEER_TENDA;
1510                                 } else {
1511                                         DBG_8723A("Capture EPIGRAM_OUI\n");
1512                                 }
1513                         } else {
1514                                 break;
1515                         }
1516                 default:
1517                         break;
1518                 }
1519
1520                 i += (pIE->Length + 2);
1521         }
1522
1523         if (ralink_vendor_flag && !epigram_vendor_flag) {
1524                 DBG_8723A("link to Ralink AP\n");
1525                 return HT_IOT_PEER_RALINK;
1526         } else if (ralink_vendor_flag && epigram_vendor_flag) {
1527                 DBG_8723A("link to Tenda W311R AP\n");
1528                 return HT_IOT_PEER_TENDA;
1529         } else {
1530                 DBG_8723A("link to new AP\n");
1531                 return HT_IOT_PEER_UNKNOWN;
1532         }
1533 }
1534
1535 void update_IOT_info23a(struct rtw_adapter *padapter)
1536 {
1537         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1538         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1539
1540         switch (pmlmeinfo->assoc_AP_vendor) {
1541         case HT_IOT_PEER_MARVELL:
1542                 pmlmeinfo->turboMode_cts2self = 1;
1543                 pmlmeinfo->turboMode_rtsen = 0;
1544                 break;
1545         case HT_IOT_PEER_RALINK:
1546                 pmlmeinfo->turboMode_cts2self = 0;
1547                 pmlmeinfo->turboMode_rtsen = 1;
1548                 /* disable high power */
1549                 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1550                                false);
1551                 break;
1552         case HT_IOT_PEER_REALTEK:
1553                 /* rtw_write16(padapter, 0x4cc, 0xffff); */
1554                 /* rtw_write16(padapter, 0x546, 0x01c0); */
1555                 /* disable high power */
1556                 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1557                                false);
1558                 break;
1559         default:
1560                 pmlmeinfo->turboMode_cts2self = 0;
1561                 pmlmeinfo->turboMode_rtsen = 1;
1562                 break;
1563         }
1564 }
1565
1566 void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
1567 {
1568         struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;
1569         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1570         bool            ShortPreamble;
1571
1572         if (updateCap & cShortPreamble) {
1573                 /*  Short Preamble */
1574                 if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
1575                         /*  PREAMBLE_LONG or PREAMBLE_AUTO */
1576                         ShortPreamble = true;
1577                         pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1578                         rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1579                 }
1580         } else { /*  Long Preamble */
1581                 if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
1582                         /*  PREAMBLE_SHORT or PREAMBLE_AUTO */
1583                         ShortPreamble = false;
1584                         pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1585                         rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1586                 }
1587         }
1588         if (updateCap & cIBSS) {
1589                 /* Filen: See 802.11-2007 p.91 */
1590                 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1591         } else {
1592                 /* Filen: See 802.11-2007 p.90 */
1593                 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) {
1594                         if (updateCap & cShortSlotTime) { /*  Short Slot Time */
1595                                 if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1596                                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1597                         } else { /*  Long Slot Time */
1598                                 if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1599                                         pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1600                         }
1601                 } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
1602                         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1603                 } else {
1604                         /* B Mode */
1605                         pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1606                 }
1607         }
1608         rtw_hal_set_hwreg23a(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
1609 }
1610
1611 void update_wireless_mode23a(struct rtw_adapter *padapter)
1612 {
1613         int ratelen, network_type = 0;
1614         u32 SIFS_Timer;
1615         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1616         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1617         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1618         unsigned char                   *rate = cur_network->SupportedRates;
1619
1620         ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates);
1621
1622         if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1623                 pmlmeinfo->HT_enable = 1;
1624
1625         if (pmlmeext->cur_channel > 14) {
1626                 if (pmlmeinfo->HT_enable)
1627                         network_type = WIRELESS_11_5N;
1628                 network_type |= WIRELESS_11A;
1629         } else {
1630                 if (pmlmeinfo->HT_enable)
1631                         network_type = WIRELESS_11_24N;
1632
1633                 if ((cckratesonly_included23a(rate, ratelen)) == true)
1634                         network_type |= WIRELESS_11B;
1635                 else if ((cckrates_included23a(rate, ratelen)) == true)
1636                         network_type |= WIRELESS_11BG;
1637                 else
1638                         network_type |= WIRELESS_11G;
1639         }
1640
1641         pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
1642
1643         SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1644                              /* change this value if having IOT issues. */
1645
1646         padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS,  (u8 *)&SIFS_Timer);
1647
1648         if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1649                 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1650          else
1651                 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1652 }
1653
1654 void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
1655 {
1656         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1657         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1658
1659         if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1660                 /*  Only B, B/G, and B/G/N AP could use CCK rate */
1661                 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4);
1662         } else {
1663                 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 4);
1664         }
1665 }
1666
1667 int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
1668 {
1669         unsigned int    ie_len;
1670         struct ndis_802_11_var_ies *pIE;
1671         int     supportRateNum = 0;
1672         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1673         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1674
1675         pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1676         if (pIE == NULL)
1677                 return _FAIL;
1678
1679         memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
1680         supportRateNum = ie_len;
1681
1682         pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1683         if (pIE)
1684                 memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
1685         return _SUCCESS;
1686 }
1687
1688 void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr)
1689 {
1690         struct sta_info *psta;
1691         u16 tid, start_seq, param;
1692         struct recv_reorder_ctrl *preorder_ctrl;
1693         struct sta_priv *pstapriv = &padapter->stapriv;
1694         struct ADDBA_request    *preq = (struct ADDBA_request*)paddba_req;
1695         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1696         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1697
1698         psta = rtw_get_stainfo23a(pstapriv, addr);
1699
1700         if (psta) {
1701                 start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
1702
1703                 param = le16_to_cpu(preq->BA_para_set);
1704                 tid = (param>>2)&0x0f;
1705
1706                 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1707
1708                 preorder_ctrl->indicate_seq = 0xffff;
1709
1710                 preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true)? true :false;
1711         }
1712 }
1713
1714 void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1715 {
1716         u8 *pIE;
1717         u32 *pbuf;
1718
1719         pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1720         pbuf = (u32 *)pIE;
1721
1722         pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
1723
1724         pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
1725
1726         pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
1727 }
1728
1729 void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext)
1730 {
1731         rtw_hal_set_hwreg23a(padapter, HW_VAR_CORRECT_TSF, NULL);
1732 }
1733
1734 void beacon_timing_control23a(struct rtw_adapter *padapter)
1735 {
1736         rtw_hal_bcn_related_reg_setting23a(padapter);
1737 }
1738
1739 static struct rtw_adapter *pbuddy_padapter;
1740
1741 int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init)
1742 {
1743         int status = _SUCCESS;
1744
1745         if (init) {
1746                 if (pbuddy_padapter == NULL) {
1747                         pbuddy_padapter = adapter;
1748                         DBG_8723A("%s(): pbuddy_padapter == NULL, Set pbuddy_padapter\n", __func__);
1749                 } else {
1750                         adapter->pbuddy_adapter = pbuddy_padapter;
1751                         pbuddy_padapter->pbuddy_adapter = adapter;
1752                         /*  clear global value */
1753                         pbuddy_padapter = NULL;
1754                         DBG_8723A("%s(): pbuddy_padapter exist, Exchange Information\n", __func__);
1755                 }
1756           } else {
1757                 pbuddy_padapter = NULL;
1758         }
1759         return status;
1760 }