Merge branch 'vhost-net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mst...
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rtl8192e / r8190_rtl8256.c
1 /*
2   This is part of the rtl8192 driver
3   released under the GPL (See file COPYING for details).
4
5   This files contains programming code for the rtl8256
6   radio frontend.
7
8   *Many* thanks to Realtek Corp. for their great support!
9
10 */
11
12 #include "r8192E.h"
13 #include "r8192E_hw.h"
14 #include "r819xE_phyreg.h"
15 #include "r819xE_phy.h"
16 #include "r8190_rtl8256.h"
17
18 /*--------------------------------------------------------------------------
19  * Overview:    set RF band width (20M or 40M)
20  * Input:       struct net_device*      dev
21  *              WIRELESS_BANDWIDTH_E    Bandwidth       //20M or 40M
22  * Output:      NONE
23  * Return:      NONE
24  * Note:        8226 support both 20M  and 40 MHz
25  *---------------------------------------------------------------------------*/
26 void PHY_SetRF8256Bandwidth(struct r8192_priv *priv, HT_CHANNEL_WIDTH Bandwidth)        //20M or 40M
27 {
28         u8      eRFPath;
29
30         //for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
31         for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
32         {
33                 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
34                                 continue;
35
36                 switch(Bandwidth)
37                 {
38                         case HT_CHANNEL_WIDTH_20:
39                                 if(priv->card_8192_version == VERSION_8190_BD || priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
40                                 {
41                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
42                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
43                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
44
45                                         //cosa add for sd3's request 01/23/2008
46                                         //rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
47                                 }
48                                 else
49                                 {
50                                         RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
51                                 }
52
53                                 break;
54                         case HT_CHANNEL_WIDTH_20_40:
55                                 if(priv->card_8192_version == VERSION_8190_BD ||priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
56                                 {
57                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
58                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3ff);
59                                         rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0e1);
60
61                                 }
62                                 else
63                                 {
64                                         RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
65                                 }
66
67
68                                 break;
69                         default:
70                                 RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth );
71                                 break;
72
73                 }
74         }
75 }
76 /*--------------------------------------------------------------------------
77  * Overview:    Interface to config 8256
78  * Input:       struct net_device*      dev
79  * Output:      NONE
80  * Return:      NONE
81  *---------------------------------------------------------------------------*/
82 RT_STATUS PHY_RF8256_Config(struct r8192_priv *priv)
83 {
84         // Initialize general global value
85         //
86         RT_STATUS rtStatus = RT_STATUS_SUCCESS;
87         // TODO: Extend RF_PATH_C and RF_PATH_D in the future
88         priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
89         // Config BB and RF
90         rtStatus = phy_RF8256_Config_ParaFile(priv);
91
92         return rtStatus;
93 }
94
95 /*--------------------------------------------------------------------------
96  * Overview:    Interface to config 8256
97  * Input:       struct net_device*      dev
98  * Output:      NONE
99  * Return:      NONE
100  *---------------------------------------------------------------------------*/
101 RT_STATUS phy_RF8256_Config_ParaFile(struct r8192_priv *priv)
102 {
103         u32     u4RegValue = 0;
104         u8      eRFPath;
105         RT_STATUS                               rtStatus = RT_STATUS_SUCCESS;
106         BB_REGISTER_DEFINITION_T        *pPhyReg;
107         u32     RegOffSetToBeCheck = 0x3;
108         u32     RegValueToBeCheck = 0x7f1;
109         u32     RF3_Final_Value = 0;
110         u8      ConstRetryTimes = 5, RetryTimes = 5;
111         u8 ret = 0;
112
113         //3//-----------------------------------------------------------------
114         //3// <2> Initialize RF
115         //3//-----------------------------------------------------------------
116         for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath <priv->NumTotalRFPath; eRFPath++)
117         {
118                 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
119                                 continue;
120
121                 pPhyReg = &priv->PHYRegDef[eRFPath];
122
123                 /*----Store original RFENV control type----*/
124                 switch(eRFPath)
125                 {
126                 case RF90_PATH_A:
127                 case RF90_PATH_C:
128                         u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV);
129                         break;
130                 case RF90_PATH_B :
131                 case RF90_PATH_D:
132                         u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16);
133                         break;
134                 }
135
136                 /*----Set RF_ENV enable----*/
137                 rtl8192_setBBreg(priv, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
138
139                 /*----Set RF_ENV output high----*/
140                 rtl8192_setBBreg(priv, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
141
142                 /* Set bit number of Address and Data for RF register */
143                 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0);         // Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
144                 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0);    // Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
145
146                 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf);
147
148                 /*----Check RF block (for FPGA platform only)----*/
149                 // TODO: this function should be removed on ASIC , Emily 2007.2.2
150                 rtStatus = rtl8192_phy_checkBBAndRF(priv, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath);
151                 if(rtStatus!= RT_STATUS_SUCCESS)
152                 {
153                         RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath);
154                         goto phy_RF8256_Config_ParaFile_Fail;
155                 }
156
157                 RetryTimes = ConstRetryTimes;
158                 RF3_Final_Value = 0;
159                 /*----Initialize RF fom connfiguration file----*/
160                 switch(eRFPath)
161                 {
162                 case RF90_PATH_A:
163                         while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
164                         {
165                                 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
166                                 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
167                                 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
168                                 RetryTimes--;
169                         }
170                         break;
171                 case RF90_PATH_B:
172                         while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
173                         {
174                                 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
175                                 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
176                                 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
177                                 RetryTimes--;
178                         }
179                         break;
180                 case RF90_PATH_C:
181                         while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
182                         {
183                                 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
184                                 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
185                                 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
186                                 RetryTimes--;
187                         }
188                         break;
189                 case RF90_PATH_D:
190                         while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
191                         {
192                                 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
193                                 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
194                                 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
195                                 RetryTimes--;
196                         }
197                         break;
198                 }
199
200                 /*----Restore RFENV control type----*/;
201                 switch(eRFPath)
202                 {
203                 case RF90_PATH_A:
204                 case RF90_PATH_C:
205                         rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
206                         break;
207                 case RF90_PATH_B :
208                 case RF90_PATH_D:
209                         rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
210                         break;
211                 }
212
213                 if(ret){
214                         RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath);
215                         goto phy_RF8256_Config_ParaFile_Fail;
216                 }
217
218         }
219
220         RT_TRACE(COMP_PHY, "PHY Initialization Success\n") ;
221         return RT_STATUS_SUCCESS;
222
223 phy_RF8256_Config_ParaFile_Fail:
224         RT_TRACE(COMP_ERR, "PHY Initialization failed\n") ;
225         return RT_STATUS_FAILURE;
226 }
227
228
229 void PHY_SetRF8256CCKTxPower(struct r8192_priv *priv, u8 powerlevel)
230 {
231         u32     TxAGC=0;
232
233         TxAGC = powerlevel;
234         if(priv->bDynamicTxLowPower == true)//cosa 04282008 for cck long range
235         {
236                 if(priv->CustomerID == RT_CID_819x_Netcore)
237                 TxAGC = 0x22;
238         else
239                 TxAGC += priv->CckPwEnl;
240         }
241         if(TxAGC > 0x24)
242                 TxAGC = 0x24;
243         rtl8192_setBBreg(priv, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
244 }
245
246
247 void PHY_SetRF8256OFDMTxPower(struct r8192_priv *priv, u8 powerlevel)
248 {
249
250         u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
251         u8 index = 0;
252         u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
253         u8 byte0, byte1, byte2, byte3;
254
255         powerBase0 = powerlevel + priv->LegacyHTTxPowerDiff;    //OFDM rates
256         powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
257         powerBase1 = powerlevel;                                                        //MCS rates
258         powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
259
260         for(index=0; index<6; index++)
261         {
262                 writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index<2)?powerBase0:powerBase1);
263                 byte0 = (u8)(writeVal & 0x7f);
264                 byte1 = (u8)((writeVal & 0x7f00)>>8);
265                 byte2 = (u8)((writeVal & 0x7f0000)>>16);
266                 byte3 = (u8)((writeVal & 0x7f000000)>>24);
267                 if(byte0 > 0x24)        // Max power index = 0x24
268                         byte0 = 0x24;
269                 if(byte1 > 0x24)
270                         byte1 = 0x24;
271                 if(byte2 > 0x24)
272                         byte2 = 0x24;
273                 if(byte3 > 0x24)
274                         byte3 = 0x24;
275
276                 if(index == 3)
277                 {
278                         writeVal_tmp = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
279                         priv->Pwr_Track = writeVal_tmp;
280                 }
281
282                 if(priv->bDynamicTxHighPower == true)     //Add by Jacken 2008/03/06  //when DM implement, add this
283                 {
284                         writeVal = 0x03030303;
285                 }
286                 else
287                 {
288                         writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
289                 }
290                 rtl8192_setBBreg(priv, RegOffset[index], 0x7f7f7f7f, writeVal);
291         }
292 }
293
294 #define MAX_DOZE_WAITING_TIMES_9x 64
295 static void r8192e_drain_tx_queues(struct r8192_priv *priv)
296 {
297         u8 i, QueueID;
298
299         for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
300         {
301                 struct rtl8192_tx_ring *ring = &priv->tx_ring[QueueID];
302
303                 if(skb_queue_len(&ring->queue) == 0)
304                 {
305                         QueueID++;
306                         continue;
307                 }
308
309                 udelay(10);
310                 i++;
311
312                 if (i >= MAX_DOZE_WAITING_TIMES_9x)
313                 {
314                         RT_TRACE(COMP_POWER, "r8192e_drain_tx_queues() timeout queue %d\n", QueueID);
315                         break;
316                 }
317         }
318 }
319
320 static bool SetRFPowerState8190(struct r8192_priv *priv,
321                                 RT_RF_POWER_STATE eRFPowerState)
322 {
323         PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
324         bool bResult = true;
325
326         if (eRFPowerState == priv->eRFPowerState &&
327             priv->bHwRfOffAction == 0) {
328                 bResult = false;
329                 goto out;
330         }
331
332         switch( eRFPowerState )
333         {
334         case eRfOn:
335
336                 // turn on RF
337                 if ((priv->eRFPowerState == eRfOff) &&
338                     RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
339                 {
340                         /*
341                          * The current RF state is OFF and the RF OFF level
342                          * is halting the NIC, re-initialize the NIC.
343                          */
344                         if (!NicIFEnableNIC(priv)) {
345                                 RT_TRACE(COMP_ERR, "%s(): NicIFEnableNIC failed\n",__FUNCTION__);
346                                 bResult = false;
347                                 goto out;
348                         }
349
350                         RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
351                 } else {
352                         write_nic_byte(priv, ANAPAR, 0x37);//160MHz
353                         mdelay(1);
354                         //enable clock 80/88 MHz
355                         rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
356                         priv->bHwRfOffAction = 0;
357
358                         //RF-A, RF-B
359                         //enable RF-Chip A/B
360                         rtl8192_setBBreg(priv, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);             // 0x860[4]
361                         //analog to digital on
362                         rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
363                         //digital to analog on
364                         rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
365                         //rx antenna on
366                         rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
367                         //rx antenna on
368                         rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
369                         //analog to digital part2 on
370                         rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x60, 0x3);     // 0x880[6:5]
371
372                 }
373
374                 break;
375
376         //
377         // In current solution, RFSleep=RFOff in order to save power under 802.11 power save.
378         // By Bruce, 2008-01-16.
379         //
380         case eRfSleep:
381
382                 // HW setting had been configured with deeper mode.
383                 if(priv->eRFPowerState == eRfOff)
384                         break;
385
386                 r8192e_drain_tx_queues(priv);
387
388                 PHY_SetRtl8192eRfOff(priv);
389
390                 break;
391
392         case eRfOff:
393
394                 //
395                 // Disconnect with Any AP or STA.
396                 //
397                 r8192e_drain_tx_queues(priv);
398
399
400                 if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
401                 {
402                         /* Disable all components. */
403                         NicIFDisableNIC(priv);
404                         RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
405                 }
406                 else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
407                 {
408                         /* Normal case - IPS should go to this. */
409                         PHY_SetRtl8192eRfOff(priv);
410                 }
411                 break;
412
413         default:
414                 bResult = false;
415                 RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
416                 break;
417         }
418
419         if(bResult)
420         {
421                 // Update current RF state variable.
422                 priv->eRFPowerState = eRFPowerState;
423         }
424
425 out:
426         return bResult;
427 }
428
429
430
431
432
433 static void MgntDisconnectIBSS(struct r8192_priv *priv)
434 {
435         u8                      i;
436         bool    bFilterOutNonAssociatedBSSID = false;
437
438         priv->ieee80211->state = IEEE80211_NOLINK;
439
440         for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i]= 0x55;
441         priv->OpMode = RT_OP_MODE_NO_LINK;
442         write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
443         write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
444         {
445                         RT_OP_MODE      OpMode = priv->OpMode;
446                         u8      btMsr = read_nic_byte(priv, MSR);
447
448                         btMsr &= 0xfc;
449
450                         switch(OpMode)
451                         {
452                         case RT_OP_MODE_INFRASTRUCTURE:
453                                 btMsr |= MSR_LINK_MANAGED;
454                                 break;
455
456                         case RT_OP_MODE_IBSS:
457                                 btMsr |= MSR_LINK_ADHOC;
458                                 // led link set separate
459                                 break;
460
461                         case RT_OP_MODE_AP:
462                                 btMsr |= MSR_LINK_MASTER;
463                                 break;
464
465                         default:
466                                 btMsr |= MSR_LINK_NONE;
467                                 break;
468                         }
469
470                         write_nic_byte(priv, MSR, btMsr);
471         }
472         ieee80211_stop_send_beacons(priv->ieee80211);
473
474         // If disconnect, clear RCR CBSSID bit
475         bFilterOutNonAssociatedBSSID = false;
476         {
477                         u32 RegRCR, Type;
478                         Type = bFilterOutNonAssociatedBSSID;
479                         RegRCR = read_nic_dword(priv, RCR);
480                         priv->ReceiveConfig = RegRCR;
481                         if (Type == true)
482                                 RegRCR |= (RCR_CBSSID);
483                         else if (Type == false)
484                                 RegRCR &= (~RCR_CBSSID);
485
486                         {
487                                 write_nic_dword(priv, RCR, RegRCR);
488                                 priv->ReceiveConfig = RegRCR;
489                         }
490
491                 }
492         notify_wx_assoc_event(priv->ieee80211);
493
494 }
495
496 static void MlmeDisassociateRequest(struct r8192_priv *priv, u8 *asSta,
497                                     u8 asRsn)
498 {
499         u8 i;
500
501         RemovePeerTS(priv->ieee80211, asSta);
502
503         SendDisassociation( priv->ieee80211, asSta, asRsn );
504
505         if(memcpy(priv->ieee80211->current_network.bssid,asSta,6) == NULL)
506         {
507                 //ShuChen TODO: change media status.
508                 //ShuChen TODO: What to do when disassociate.
509                 priv->ieee80211->state = IEEE80211_NOLINK;
510                 for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i] = 0x22;
511                 priv->OpMode = RT_OP_MODE_NO_LINK;
512                 {
513                         RT_OP_MODE      OpMode = priv->OpMode;
514                         u8 btMsr = read_nic_byte(priv, MSR);
515
516                         btMsr &= 0xfc;
517
518                         switch(OpMode)
519                         {
520                         case RT_OP_MODE_INFRASTRUCTURE:
521                                 btMsr |= MSR_LINK_MANAGED;
522                                 break;
523
524                         case RT_OP_MODE_IBSS:
525                                 btMsr |= MSR_LINK_ADHOC;
526                                 // led link set separate
527                                 break;
528
529                         case RT_OP_MODE_AP:
530                                 btMsr |= MSR_LINK_MASTER;
531                                 break;
532
533                         default:
534                                 btMsr |= MSR_LINK_NONE;
535                                 break;
536                         }
537
538                         write_nic_byte(priv, MSR, btMsr);
539                 }
540                 ieee80211_disassociate(priv->ieee80211);
541
542                 write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
543                 write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
544
545         }
546
547 }
548
549
550 static void MgntDisconnectAP(struct r8192_priv *priv, u8 asRsn)
551 {
552         bool bFilterOutNonAssociatedBSSID = false;
553         u32 RegRCR, Type;
554
555         /* If disconnect, clear RCR CBSSID bit */
556         bFilterOutNonAssociatedBSSID = false;
557
558         Type = bFilterOutNonAssociatedBSSID;
559         RegRCR = read_nic_dword(priv, RCR);
560         priv->ReceiveConfig = RegRCR;
561
562         if (Type == true)
563                 RegRCR |= (RCR_CBSSID);
564         else if (Type == false)
565                 RegRCR &= (~RCR_CBSSID);
566
567         write_nic_dword(priv, RCR, RegRCR);
568         priv->ReceiveConfig = RegRCR;
569
570         MlmeDisassociateRequest(priv, priv->ieee80211->current_network.bssid, asRsn);
571
572         priv->ieee80211->state = IEEE80211_NOLINK;
573 }
574
575
576 static bool MgntDisconnect(struct r8192_priv *priv, u8 asRsn)
577 {
578         // In adhoc mode, update beacon frame.
579         if( priv->ieee80211->state == IEEE80211_LINKED )
580         {
581                 if( priv->ieee80211->iw_mode == IW_MODE_ADHOC )
582                 {
583                         MgntDisconnectIBSS(priv);
584                 }
585                 if( priv->ieee80211->iw_mode == IW_MODE_INFRA )
586                 {
587                         // We clear key here instead of MgntDisconnectAP() because that
588                         // MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
589                         // e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
590                         // used to handle disassociation related things to AP, e.g. send Disassoc
591                         // frame to AP.  2005.01.27, by rcnjko.
592                         MgntDisconnectAP(priv, asRsn);
593                 }
594         }
595
596         return true;
597 }
598
599 //
600 //      Description:
601 //              Chang RF Power State.
602 //              Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
603 //
604 //      Assumption:
605 //              PASSIVE LEVEL.
606 //
607 bool MgntActSet_RF_State(struct r8192_priv *priv, RT_RF_POWER_STATE StateToSet,
608                          RT_RF_CHANGE_SOURCE ChangeSource)
609 {
610         bool                    bActionAllowed = false;
611         bool                    bConnectBySSID = false;
612         RT_RF_POWER_STATE       rtState;
613
614         RT_TRACE(COMP_POWER, "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet);
615
616         spin_lock(&priv->rf_ps_lock);
617
618         rtState = priv->eRFPowerState;
619
620         switch(StateToSet)
621         {
622         case eRfOn:
623                 priv->RfOffReason &= (~ChangeSource);
624
625                 if (!priv->RfOffReason)
626                 {
627                         priv->RfOffReason = 0;
628                         bActionAllowed = true;
629
630
631                         if(rtState == eRfOff && ChangeSource >=RF_CHANGE_BY_HW )
632                         {
633                                 bConnectBySSID = true;
634                         }
635                 }
636                 else
637                         RT_TRACE(COMP_POWER, "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->RfOffReason, ChangeSource);
638
639                 break;
640
641         case eRfOff:
642
643                 if (priv->RfOffReason > RF_CHANGE_BY_IPS)
644                 {
645                         // Disconnect to current BSS when radio off. Asked by QuanTa.
646                         MgntDisconnect(priv, disas_lv_ss);
647                 }
648
649                 priv->RfOffReason |= ChangeSource;
650                 bActionAllowed = true;
651                 break;
652
653         case eRfSleep:
654                 priv->RfOffReason |= ChangeSource;
655                 bActionAllowed = true;
656                 break;
657         }
658
659         if (bActionAllowed)
660         {
661                 RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason);
662                 // Config HW to the specified mode.
663                 SetRFPowerState8190(priv, StateToSet);
664         }
665         else
666         {
667                 RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->RfOffReason);
668         }
669
670         // Release RF spinlock
671         spin_unlock(&priv->rf_ps_lock);
672
673         RT_TRACE(COMP_POWER, "<===MgntActSet_RF_State()\n");
674         return bActionAllowed;
675 }
676
677