]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8192e/r8192E_dm.c
staging: rtl8192e: Remove RTL8192P and RTL8192U ifdefs
[~andy/linux] / drivers / staging / rtl8192e / r8192E_dm.c
1 /*++
2 Copyright-c Realtek Semiconductor Corp. All rights reserved.
3
4 Module Name:
5         r8192U_dm.c
6
7 Abstract:
8         HW dynamic mechanism.
9
10 Major Change History:
11         When            Who                             What
12         ----------      --------------- -------------------------------
13         2008-05-14      amy                     create version 0 porting from windows code.
14
15 --*/
16 #include "r8192E.h"
17 #include "r8192E_dm.h"
18 #include "r8192E_hw.h"
19 #include "r819xE_phy.h"
20 #include "r819xE_phyreg.h"
21 #include "r8190_rtl8256.h"
22
23 #define DRV_NAME "rtl819xE"
24
25 //
26 // Indicate different AP vendor for IOT issue.
27 //
28 static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
29 { 0x5e4322,     0x5e4322,       0x5e4322,       0x604322,       0xa44f,         0x5e4322,       0x5e4322};
30 static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
31 { 0x5e4322,     0xa44f,         0x5e4322,       0x604322,       0x5e4322,       0x5e4322,       0x5e4322};
32
33 #define RTK_UL_EDCA 0xa44f
34 #define RTK_DL_EDCA 0x5e4322
35
36
37 dig_t   dm_digtable;
38 // For Dynamic Rx Path Selection by Signal Strength
39 DRxPathSel      DM_RxPathSelTable;
40
41
42 /*--------------------Define export function prototype-----------------------*/
43 extern  void    init_hal_dm(struct net_device *dev);
44 extern  void deinit_hal_dm(struct net_device *dev);
45
46 extern void hal_dm_watchdog(struct net_device *dev);
47
48
49 extern  void    init_rate_adaptive(struct net_device *dev);
50 extern  void    dm_txpower_trackingcallback(struct work_struct *work);
51
52 extern  void    dm_cck_txpower_adjust(struct net_device *dev,bool  binch14);
53 extern  void    dm_restore_dynamic_mechanism_state(struct net_device *dev);
54 extern  void    dm_backup_dynamic_mechanism_state(struct net_device *dev);
55 extern  void    dm_change_dynamic_initgain_thresh(struct net_device *dev,
56                                                                 u32             dm_type,
57                                                                 u32             dm_value);
58 extern  void    DM_ChangeFsyncSetting(struct net_device *dev,
59                                                                                                 s32             DM_Type,
60                                                                                                 s32             DM_Value);
61 extern  void dm_force_tx_fw_info(struct net_device *dev,
62                                                                                 u32             force_type,
63                                                                                 u32             force_value);
64 extern  void    dm_init_edca_turbo(struct net_device *dev);
65 extern  void    dm_rf_operation_test_callback(unsigned long data);
66 extern  void    dm_rf_pathcheck_workitemcallback(struct work_struct *work);
67 extern  void dm_fsync_timer_callback(unsigned long data);
68 extern  void dm_check_fsync(struct net_device *dev);
69 extern  void dm_initialize_txpower_tracking(struct net_device *dev);
70
71 extern  void    dm_gpio_change_rf_callback(struct work_struct *work);
72
73
74 // DM --> Rate Adaptive
75 static  void    dm_check_rate_adaptive(struct net_device *dev);
76
77 // DM --> Bandwidth switch
78 static  void    dm_init_bandwidth_autoswitch(struct net_device *dev);
79 static  void    dm_bandwidth_autoswitch(        struct net_device *dev);
80
81 // DM --> TX power control
82 static  void    dm_check_txpower_tracking(struct net_device *dev);
83
84 // DM --> Dynamic Init Gain by RSSI
85 static  void    dm_dig_init(struct net_device *dev);
86 static  void    dm_ctrl_initgain_byrssi(struct net_device *dev);
87 static  void    dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev);
88 static  void    dm_ctrl_initgain_byrssi_by_driverrssi(  struct net_device *dev);
89 static  void    dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev);
90 static  void    dm_initial_gain(struct net_device *dev);
91 static  void    dm_pd_th(struct net_device *dev);
92 static  void    dm_cs_ratio(struct net_device *dev);
93
94 static  void dm_init_ctstoself(struct net_device *dev);
95 // DM --> EDCA turboe mode control
96 static  void    dm_check_edca_turbo(struct net_device *dev);
97
98 // DM --> HW RF control
99 static  void    dm_check_rfctrl_gpio(struct net_device *dev);
100
101 // DM --> Check PBC
102 static  void dm_check_pbc_gpio(struct net_device *dev);
103
104 // DM --> Check current RX RF path state
105 static  void    dm_check_rx_path_selection(struct net_device *dev);
106 static  void dm_init_rxpath_selection(struct net_device *dev);
107 static  void dm_rxpath_sel_byrssi(struct net_device *dev);
108
109 // DM --> Fsync for broadcom ap
110 static void dm_init_fsync(struct net_device *dev);
111 static void dm_deInit_fsync(struct net_device *dev);
112
113 static  void    dm_check_txrateandretrycount(struct net_device *dev);
114
115
116 /*---------------------Define of Tx Power Control For Near/Far Range --------*/   //Add by Jacken 2008/02/18
117 static  void    dm_init_dynamic_txpower(struct net_device *dev);
118 static  void    dm_dynamic_txpower(struct net_device *dev);
119
120 // DM --> For rate adaptive and DIG, we must send RSSI to firmware
121 static  void dm_send_rssi_tofw(struct net_device *dev);
122 static  void    dm_ctstoself(struct net_device *dev);
123
124 /*
125  * Prepare SW resource for HW dynamic mechanism.
126  * This function is only invoked at driver intialization once.
127  */
128 void init_hal_dm(struct net_device *dev)
129 {
130         struct r8192_priv *priv = ieee80211_priv(dev);
131
132         // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism.
133         priv->undecorated_smoothed_pwdb = -1;
134
135         //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
136         dm_init_dynamic_txpower(dev);
137         init_rate_adaptive(dev);
138         //dm_initialize_txpower_tracking(dev);
139         dm_dig_init(dev);
140         dm_init_edca_turbo(dev);
141         dm_init_bandwidth_autoswitch(dev);
142         dm_init_fsync(dev);
143         dm_init_rxpath_selection(dev);
144         dm_init_ctstoself(dev);
145         INIT_DELAYED_WORK(&priv->gpio_change_rf_wq,  dm_gpio_change_rf_callback);
146
147 }
148
149 void deinit_hal_dm(struct net_device *dev)
150 {
151
152         dm_deInit_fsync(dev);
153
154 }
155
156
157 #ifdef USB_RX_AGGREGATION_SUPPORT
158 void dm_CheckRxAggregation(struct net_device *dev) {
159         struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
160         PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
161         static unsigned long    lastTxOkCnt = 0;
162         static unsigned long    lastRxOkCnt = 0;
163         unsigned long           curTxOkCnt = 0;
164         unsigned long           curRxOkCnt = 0;
165
166         curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
167         curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
168
169         if((curTxOkCnt + curRxOkCnt) < 15000000) {
170                 return;
171         }
172
173         if(curTxOkCnt > 4*curRxOkCnt) {
174                 if (priv->bCurrentRxAggrEnable) {
175                         write_nic_dword(priv, 0x1a8, 0);
176                         priv->bCurrentRxAggrEnable = false;
177                 }
178         }else{
179                 if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) {
180                         u32 ulValue;
181                         ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
182                                 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
183                         /*
184                          * If usb rx firmware aggregation is enabled,
185                          * when anyone of three threshold conditions above is reached,
186                          * firmware will send aggregated packet to driver.
187                          */
188                         write_nic_dword(priv, 0x1a8, ulValue);
189                         priv->bCurrentRxAggrEnable = true;
190                 }
191         }
192
193         lastTxOkCnt = priv->stats.txbytesunicast;
194         lastRxOkCnt = priv->stats.rxbytesunicast;
195 }
196 #endif
197
198
199 // call the script file to enable
200 void dm_check_ac_dc_power(struct net_device *dev)
201 {
202         struct r8192_priv *priv = ieee80211_priv(dev);
203         static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
204         char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
205         static char *envp[] = {"HOME=/",
206                         "TERM=linux",
207                         "PATH=/usr/bin:/bin",
208                          NULL};
209
210         if(priv->ResetProgress == RESET_TYPE_SILENT)
211         {
212                 RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
213                 return;
214         }
215
216         if(priv->ieee80211->state != IEEE80211_LINKED) {
217                 return;
218         }
219         call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
220 }
221
222 void hal_dm_watchdog(struct net_device *dev)
223 {
224         dm_check_ac_dc_power(dev);
225
226         /*Add by amy 2008/05/15 ,porting from windows code.*/
227         dm_check_rate_adaptive(dev);
228         dm_dynamic_txpower(dev);
229         dm_check_txrateandretrycount(dev);
230
231         dm_check_txpower_tracking(dev);
232
233         dm_ctrl_initgain_byrssi(dev);
234         dm_check_edca_turbo(dev);
235         dm_bandwidth_autoswitch(dev);
236
237         dm_check_rfctrl_gpio(dev);
238         dm_check_rx_path_selection(dev);
239         dm_check_fsync(dev);
240
241         // Add by amy 2008-05-15 porting from windows code.
242         dm_check_pbc_gpio(dev);
243         dm_send_rssi_tofw(dev);
244         dm_ctstoself(dev);
245
246 #ifdef USB_RX_AGGREGATION_SUPPORT
247         dm_CheckRxAggregation(dev);
248 #endif
249 }
250
251
252 /*
253   * Decide Rate Adaptive Set according to distance (signal strength)
254   *     01/11/2008      MHC             Modify input arguments and RATR table level.
255   *     01/16/2008      MHC             RF_Type is assigned in ReadAdapterInfo(). We must call
256   *                                             the function after making sure RF_Type.
257   */
258 void init_rate_adaptive(struct net_device * dev)
259 {
260
261         struct r8192_priv *priv = ieee80211_priv(dev);
262         prate_adaptive                  pra = (prate_adaptive)&priv->rate_adaptive;
263
264         pra->ratr_state = DM_RATR_STA_MAX;
265         pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
266         pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
267         pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
268
269         pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
270         pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
271         pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
272
273         if(priv->CustomerID == RT_CID_819x_Netcore)
274                 pra->ping_rssi_enable = 1;
275         else
276                 pra->ping_rssi_enable = 0;
277         pra->ping_rssi_thresh_for_ra = 15;
278
279
280         if (priv->rf_type == RF_2T4R)
281         {
282                 // 07/10/08 MH Modify for RA smooth scheme.
283                 /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/
284                 pra->upper_rssi_threshold_ratr          =       0x8f0f0000;
285                 pra->middle_rssi_threshold_ratr         =       0x8f0ff000;
286                 pra->low_rssi_threshold_ratr            =       0x8f0ff001;
287                 pra->low_rssi_threshold_ratr_40M        =       0x8f0ff005;
288                 pra->low_rssi_threshold_ratr_20M        =       0x8f0ff001;
289                 pra->ping_rssi_ratr     =       0x0000000d;//cosa add for test
290         }
291         else if (priv->rf_type == RF_1T2R)
292         {
293                 pra->upper_rssi_threshold_ratr          =       0x000f0000;
294                 pra->middle_rssi_threshold_ratr         =       0x000ff000;
295                 pra->low_rssi_threshold_ratr            =       0x000ff001;
296                 pra->low_rssi_threshold_ratr_40M        =       0x000ff005;
297                 pra->low_rssi_threshold_ratr_20M        =       0x000ff001;
298                 pra->ping_rssi_ratr     =       0x0000000d;//cosa add for test
299         }
300
301 }
302
303
304 static void dm_check_rate_adaptive(struct net_device * dev)
305 {
306         struct r8192_priv *priv = ieee80211_priv(dev);
307         PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
308         prate_adaptive                  pra = (prate_adaptive)&priv->rate_adaptive;
309         u32                                             currentRATR, targetRATR = 0;
310         u32                                             LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
311         bool                                            bshort_gi_enabled = false;
312         static u8                                       ping_rssi_state=0;
313
314
315         if(!priv->up)
316         {
317                 RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
318                 return;
319         }
320
321         if(pra->rate_adaptive_disabled)//this variable is set by ioctl.
322                 return;
323
324         // TODO: Only 11n mode is implemented currently,
325         if( !(priv->ieee80211->mode == WIRELESS_MODE_N_24G ||
326                  priv->ieee80211->mode == WIRELESS_MODE_N_5G))
327                  return;
328
329         if( priv->ieee80211->state == IEEE80211_LINKED )
330         {
331         //      RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");
332
333                 //
334                 // Check whether Short GI is enabled
335                 //
336                 bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
337                         (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
338
339
340                 pra->upper_rssi_threshold_ratr =
341                                 (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
342
343                 pra->middle_rssi_threshold_ratr =
344                                 (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
345
346                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
347                 {
348                         pra->low_rssi_threshold_ratr =
349                                 (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
350                 }
351                 else
352                 {
353                         pra->low_rssi_threshold_ratr =
354                         (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
355                 }
356                 //cosa add for test
357                 pra->ping_rssi_ratr =
358                                 (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
359
360                 /* 2007/10/08 MH We support RA smooth scheme now. When it is the first
361                    time to link with AP. We will not change upper/lower threshold. If
362                    STA stay in high or low level, we must change two different threshold
363                    to prevent jumping frequently. */
364                 if (pra->ratr_state == DM_RATR_STA_HIGH)
365                 {
366                         HighRSSIThreshForRA     = pra->high2low_rssi_thresh_for_ra;
367                         LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
368                                         (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
369                 }
370                 else if (pra->ratr_state == DM_RATR_STA_LOW)
371                 {
372                         HighRSSIThreshForRA     = pra->high_rssi_thresh_for_ra;
373                         LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
374                                         (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M);
375                 }
376                 else
377                 {
378                         HighRSSIThreshForRA     = pra->high_rssi_thresh_for_ra;
379                         LowRSSIThreshForRA      = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
380                                         (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
381                 }
382
383                 if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA)
384                 {
385                         pra->ratr_state = DM_RATR_STA_HIGH;
386                         targetRATR = pra->upper_rssi_threshold_ratr;
387                 }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA)
388                 {
389                         pra->ratr_state = DM_RATR_STA_MIDDLE;
390                         targetRATR = pra->middle_rssi_threshold_ratr;
391                 }else
392                 {
393                         pra->ratr_state = DM_RATR_STA_LOW;
394                         targetRATR = pra->low_rssi_threshold_ratr;
395                 }
396
397                         //cosa add for test
398                 if(pra->ping_rssi_enable)
399                 {
400                         //pHalData->UndecoratedSmoothedPWDB = 19;
401                         if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5))
402                         {
403                                 if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
404                                         ping_rssi_state )
405                                 {
406                                         pra->ratr_state = DM_RATR_STA_LOW;
407                                         targetRATR = pra->ping_rssi_ratr;
408                                         ping_rssi_state = 1;
409                                 }
410                         }
411                         else
412                         {
413                                 ping_rssi_state = 0;
414                         }
415                 }
416
417                 // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
418                 if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev))
419                         targetRATR &=  0xf00fffff;
420
421                 //
422                 // Check whether updating of RATR0 is required
423                 //
424                 currentRATR = read_nic_dword(priv, RATR0);
425                 if( targetRATR !=  currentRATR )
426                 {
427                         u32 ratr_value;
428                         ratr_value = targetRATR;
429                         RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);
430                         if(priv->rf_type == RF_1T2R)
431                         {
432                                 ratr_value &= ~(RATE_ALL_OFDM_2SS);
433                         }
434                         write_nic_dword(priv, RATR0, ratr_value);
435                         write_nic_byte(priv, UFWP, 1);
436
437                         pra->last_ratr = targetRATR;
438                 }
439
440         }
441         else
442         {
443                 pra->ratr_state = DM_RATR_STA_MAX;
444         }
445
446 }
447
448
449 static void dm_init_bandwidth_autoswitch(struct net_device * dev)
450 {
451         struct r8192_priv *priv = ieee80211_priv(dev);
452
453         priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
454         priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
455         priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
456         priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false;
457
458 }
459
460
461 static void dm_bandwidth_autoswitch(struct net_device * dev)
462 {
463         struct r8192_priv *priv = ieee80211_priv(dev);
464
465         if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){
466                 return;
467         }else{
468                 if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40
469                         if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
470                                 priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
471                 }else{//in force send packets in 20 Mhz in 20/40
472                         if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
473                                 priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
474
475                 }
476         }
477 }
478
479 //OFDM default at 0db, index=6.
480 static const u32 OFDMSwingTable[OFDM_Table_Length] = {
481         0x7f8001fe,     // 0, +6db
482         0x71c001c7,     // 1, +5db
483         0x65400195,     // 2, +4db
484         0x5a400169,     // 3, +3db
485         0x50800142,     // 4, +2db
486         0x47c0011f,     // 5, +1db
487         0x40000100,     // 6, +0db ===> default, upper for higher temperature, lower for low temperature
488         0x390000e4,     // 7, -1db
489         0x32c000cb,     // 8, -2db
490         0x2d4000b5,     // 9, -3db
491         0x288000a2,     // 10, -4db
492         0x24000090,     // 11, -5db
493         0x20000080,     // 12, -6db
494         0x1c800072,     // 13, -7db
495         0x19800066,     // 14, -8db
496         0x26c0005b,     // 15, -9db
497         0x24400051,     // 16, -10db
498         0x12000048,     // 17, -11db
499         0x10000040      // 18, -12db
500 };
501 static const u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
502         {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},       // 0, +0db ===> CCK40M default
503         {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},       // 1, -1db
504         {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},       // 2, -2db
505         {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},       // 3, -3db
506         {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},       // 4, -4db
507         {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},       // 5, -5db
508         {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},       // 6, -6db ===> CCK20M default
509         {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},       // 7, -7db
510         {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},       // 8, -8db
511         {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},       // 9, -9db
512         {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},       // 10, -10db
513         {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}        // 11, -11db
514 };
515
516 static const u8 CCKSwingTable_Ch14[CCK_Table_length][8] = {
517         {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},       // 0, +0db  ===> CCK40M default
518         {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},       // 1, -1db
519         {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},       // 2, -2db
520         {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},       // 3, -3db
521         {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},       // 4, -4db
522         {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},       // 5, -5db
523         {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},       // 6, -6db  ===> CCK20M default
524         {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},       // 7, -7db
525         {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},       // 8, -8db
526         {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},       // 9, -9db
527         {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},       // 10, -10db
528         {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}        // 11, -11db
529 };
530
531 #define         Pw_Track_Flag                           0x11d
532 #define         Tssi_Mea_Value                          0x13c
533 #define         Tssi_Report_Value1                      0x134
534 #define         Tssi_Report_Value2                      0x13e
535 #define         FW_Busy_Flag                            0x13f
536 static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
537         {
538         struct r8192_priv *priv = ieee80211_priv(dev);
539         bool                                            bHighpowerstate, viviflag = FALSE;
540         DCMD_TXCMD_T                    tx_cmd;
541         u8                                      powerlevelOFDM24G;
542         int                                     i =0, j = 0, k = 0;
543         u8                                              RF_Type, tmp_report[5]={0, 0, 0, 0, 0};
544         u32                                             Value;
545         u8                                              Pwr_Flag;
546         u16                                     Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0;
547 //      bool rtStatus = true;
548         u32                                             delta=0;
549         RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
550 //      write_nic_byte(priv, 0x1ba, 0);
551         write_nic_byte(priv, Pw_Track_Flag, 0);
552         write_nic_byte(priv, FW_Busy_Flag, 0);
553         priv->ieee80211->bdynamic_txpower_enable = false;
554         bHighpowerstate = priv->bDynamicTxHighPower;
555
556         powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24);
557         RF_Type = priv->rf_type;
558         Value = (RF_Type<<8) | powerlevelOFDM24G;
559
560         RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G);
561
562         for(j = 0; j<=30; j++)
563 {       //fill tx_cmd
564
565         tx_cmd.Op               = TXCMD_SET_TX_PWR_TRACKING;
566         tx_cmd.Length   = 4;
567         tx_cmd.Value            = Value;
568         cmpk_message_handle_tx(dev, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
569         mdelay(1);
570
571         for(i = 0;i <= 30; i++)
572         {
573                 Pwr_Flag = read_nic_byte(priv, Pw_Track_Flag);
574
575                 if (Pwr_Flag == 0)
576                 {
577                         mdelay(1);
578                         continue;
579                 }
580
581                 Avg_TSSI_Meas = read_nic_word(priv, Tssi_Mea_Value);
582
583                 if(Avg_TSSI_Meas == 0)
584                 {
585                         write_nic_byte(priv, Pw_Track_Flag, 0);
586                         write_nic_byte(priv, FW_Busy_Flag, 0);
587                         return;
588                 }
589
590                 for(k = 0;k < 5; k++)
591                 {
592                         if(k !=4)
593                                 tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value1+k);
594                         else
595                                 tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value2);
596
597                         RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
598                 }
599
600                 //check if the report value is right
601                 for(k = 0;k < 5; k++)
602                 {
603                         if(tmp_report[k] <= 20)
604                         {
605                                 viviflag =TRUE;
606                                 break;
607                         }
608                 }
609                 if(viviflag ==TRUE)
610                 {
611                         write_nic_byte(priv, Pw_Track_Flag, 0);
612                         viviflag = FALSE;
613                         RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
614                         for(k = 0;k < 5; k++)
615                                 tmp_report[k] = 0;
616                         break;
617                 }
618
619                 for(k = 0;k < 5; k++)
620                 {
621                         Avg_TSSI_Meas_from_driver += tmp_report[k];
622                 }
623
624                 Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
625                 RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver);
626                 TSSI_13dBm = priv->TSSI_13dBm;
627                 RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
628
629                 //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)
630                 // For MacOS-compatible
631                 if(Avg_TSSI_Meas_from_driver > TSSI_13dBm)
632                         delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
633                 else
634                         delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
635
636                 if(delta <= E_FOR_TX_POWER_TRACK)
637                 {
638                         priv->ieee80211->bdynamic_txpower_enable = TRUE;
639                         write_nic_byte(priv, Pw_Track_Flag, 0);
640                         write_nic_byte(priv, FW_Busy_Flag, 0);
641                         RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
642                         RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
643                         RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
644                         RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
645                         RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
646                         return;
647                 }
648                 else
649                 {
650                         if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
651                         {
652                                 if (RF_Type == RF_2T4R)
653                                 {
654
655                                                 if((priv->rfa_txpowertrackingindex > 0) &&(priv->rfc_txpowertrackingindex > 0))
656                                 {
657                                         priv->rfa_txpowertrackingindex--;
658                                         if(priv->rfa_txpowertrackingindex_real > 4)
659                                         {
660                                                 priv->rfa_txpowertrackingindex_real--;
661                                                 rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
662                                         }
663
664                                         priv->rfc_txpowertrackingindex--;
665                                         if(priv->rfc_txpowertrackingindex_real > 4)
666                                         {
667                                                 priv->rfc_txpowertrackingindex_real--;
668                                                 rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
669                                         }
670                                                 }
671                                                 else
672                                                 {
673                                                                 rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
674                                                                 rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
675                                 }
676                         }
677                         else
678                         {
679                                                 if(priv->rfc_txpowertrackingindex > 0)
680                                                 {
681                                                         priv->rfc_txpowertrackingindex--;
682                                                         if(priv->rfc_txpowertrackingindex_real > 4)
683                                                         {
684                                                                 priv->rfc_txpowertrackingindex_real--;
685                                                                 rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
686                                                         }
687                                                 }
688                                                 else
689                                                         rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
690                                 }
691                         }
692                         else
693                         {
694                                 if (RF_Type == RF_2T4R)
695                                 {
696                                         if((priv->rfa_txpowertrackingindex < TxBBGainTableLength - 1) &&(priv->rfc_txpowertrackingindex < TxBBGainTableLength - 1))
697                                 {
698                                         priv->rfa_txpowertrackingindex++;
699                                         priv->rfa_txpowertrackingindex_real++;
700                                         rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
701                                         priv->rfc_txpowertrackingindex++;
702                                         priv->rfc_txpowertrackingindex_real++;
703                                         rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
704                                 }
705                                         else
706                                         {
707                                                 rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
708                                                 rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
709                         }
710                                 }
711                                 else
712                                 {
713                                         if(priv->rfc_txpowertrackingindex < (TxBBGainTableLength - 1))
714                                         {
715                                                         priv->rfc_txpowertrackingindex++;
716                                                         priv->rfc_txpowertrackingindex_real++;
717                                                         rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
718                                         }
719                                         else
720                                                         rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
721                                 }
722                         }
723                         if (RF_Type == RF_2T4R)
724                         priv->CCKPresentAttentuation_difference
725                                 = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
726                         else
727                                 priv->CCKPresentAttentuation_difference
728                                         = priv->rfc_txpowertrackingindex - priv->rfc_txpowertracking_default;
729
730                         if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
731                                 priv->CCKPresentAttentuation
732                                 = priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference;
733                         else
734                                 priv->CCKPresentAttentuation
735                                 = priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference;
736
737                         if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
738                                         priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
739                         if(priv->CCKPresentAttentuation < 0)
740                                         priv->CCKPresentAttentuation = 0;
741
742                         if(1)
743                         {
744                                 if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
745                                 {
746                                         priv->bcck_in_ch14 = TRUE;
747                                         dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
748                                 }
749                                 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
750                                 {
751                                         priv->bcck_in_ch14 = FALSE;
752                                         dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
753                                 }
754                                 else
755                                         dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
756                         }
757                 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
758                 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
759                 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
760                 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
761
762                 if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24)
763                 {
764                         priv->ieee80211->bdynamic_txpower_enable = TRUE;
765                         write_nic_byte(priv, Pw_Track_Flag, 0);
766                         write_nic_byte(priv, FW_Busy_Flag, 0);
767                         RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
768                         return;
769                 }
770
771
772         }
773                 write_nic_byte(priv, Pw_Track_Flag, 0);
774                 Avg_TSSI_Meas_from_driver = 0;
775                 for(k = 0;k < 5; k++)
776                         tmp_report[k] = 0;
777                 break;
778         }
779         write_nic_byte(priv, FW_Busy_Flag, 0);
780 }
781                 priv->ieee80211->bdynamic_txpower_enable = TRUE;
782                 write_nic_byte(priv, Pw_Track_Flag, 0);
783 }
784
785 static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
786 {
787 #define ThermalMeterVal 9
788         struct r8192_priv *priv = ieee80211_priv(dev);
789         u32 tmpRegA, TempCCk;
790         u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
791         int i =0, CCKSwingNeedUpdate=0;
792
793         if(!priv->btxpower_trackingInit)
794         {
795                 //Query OFDM default setting
796                 tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
797                 for(i=0; i<OFDM_Table_Length; i++)      //find the index
798                 {
799                         if(tmpRegA == OFDMSwingTable[i])
800                         {
801                                 priv->OFDM_index= (u8)i;
802                                 RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n",
803                                         rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index);
804                         }
805                 }
806
807                 //Query CCK default setting From 0xa22
808                 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
809                 for(i=0 ; i<CCK_Table_length ; i++)
810                 {
811                         if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0])
812                         {
813                                 priv->CCK_index =(u8) i;
814                                 RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n",
815                                         rCCK0_TxFilter1, TempCCk, priv->CCK_index);
816                                 break;
817                         }
818                 }
819                 priv->btxpower_trackingInit = TRUE;
820                 //pHalData->TXPowercount = 0;
821                 return;
822         }
823
824         // read and filter out unreasonable value
825         tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);        // 0x12: RF Reg[10:7]
826         RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA);
827         if(tmpRegA < 3 || tmpRegA > 13)
828                 return;
829         if(tmpRegA >= 12)       // if over 12, TP will be bad when high temperature
830                 tmpRegA = 12;
831         RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA);
832         priv->ThermalMeter[0] = ThermalMeterVal;        //We use fixed value by Bryant's suggestion
833         priv->ThermalMeter[1] = ThermalMeterVal;        //We use fixed value by Bryant's suggestion
834
835         //Get current RF-A temperature index
836         if(priv->ThermalMeter[0] >= (u8)tmpRegA)        //lower temperature
837         {
838                 tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
839                 tmpCCK40Mindex = tmpCCK20Mindex - 6;
840                 if(tmpOFDMindex >= OFDM_Table_Length)
841                         tmpOFDMindex = OFDM_Table_Length-1;
842                 if(tmpCCK20Mindex >= CCK_Table_length)
843                         tmpCCK20Mindex = CCK_Table_length-1;
844                 if(tmpCCK40Mindex >= CCK_Table_length)
845                         tmpCCK40Mindex = CCK_Table_length-1;
846         }
847         else
848         {
849                 tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
850                 if(tmpval >= 6)                                                         // higher temperature
851                         tmpOFDMindex = tmpCCK20Mindex = 0;              // max to +6dB
852                 else
853                         tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
854                 tmpCCK40Mindex = 0;
855         }
856
857         if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)       //40M
858                 tmpCCKindex = tmpCCK40Mindex;
859         else
860                 tmpCCKindex = tmpCCK20Mindex;
861
862         //record for bandwidth swith
863         priv->Record_CCK_20Mindex = tmpCCK20Mindex;
864         priv->Record_CCK_40Mindex = tmpCCK40Mindex;
865         RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n",
866                 priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
867
868         if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
869         {
870                 priv->bcck_in_ch14 = TRUE;
871                 CCKSwingNeedUpdate = 1;
872         }
873         else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
874         {
875                 priv->bcck_in_ch14 = FALSE;
876                 CCKSwingNeedUpdate = 1;
877         }
878
879         if(priv->CCK_index != tmpCCKindex)
880 {
881                 priv->CCK_index = tmpCCKindex;
882                 CCKSwingNeedUpdate = 1;
883         }
884
885         if(CCKSwingNeedUpdate)
886         {
887                 dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
888         }
889         if(priv->OFDM_index != tmpOFDMindex)
890         {
891                 priv->OFDM_index = tmpOFDMindex;
892                 rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
893                 RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
894                         priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
895         }
896         priv->txpower_count = 0;
897 }
898
899 void dm_txpower_trackingcallback(struct work_struct *work)
900 {
901         struct delayed_work *dwork = container_of(work,struct delayed_work,work);
902        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
903        struct net_device *dev = priv->ieee80211->dev;
904
905         if(priv->IC_Cut >= IC_VersionCut_D)
906                 dm_TXPowerTrackingCallback_TSSI(dev);
907         else
908                 dm_TXPowerTrackingCallback_ThermalMeter(dev);
909 }
910
911
912 static const txbbgain_struct rtl8192_txbbgain_table[] = {
913         { 12,   0x7f8001fe },
914         { 11,   0x788001e2 },
915         { 10,   0x71c001c7 },
916         { 9,    0x6b8001ae },
917         { 8,    0x65400195 },
918         { 7,    0x5fc0017f },
919         { 6,    0x5a400169 },
920         { 5,    0x55400155 },
921         { 4,    0x50800142 },
922         { 3,    0x4c000130 },
923         { 2,    0x47c0011f },
924         { 1,    0x43c0010f },
925         { 0,    0x40000100 },
926         { -1,   0x3c8000f2 },
927         { -2,   0x390000e4 },
928         { -3,   0x35c000d7 },
929         { -4,   0x32c000cb },
930         { -5,   0x300000c0 },
931         { -6,   0x2d4000b5 },
932         { -7,   0x2ac000ab },
933         { -8,   0x288000a2 },
934         { -9,   0x26000098 },
935         { -10,  0x24000090 },
936         { -11,  0x22000088 },
937         { -12,  0x20000080 },
938         { -13,  0x1a00006c },
939         { -14,  0x1c800072 },
940         { -15,  0x18000060 },
941         { -16,  0x19800066 },
942         { -17,  0x15800056 },
943         { -18,  0x26c0005b },
944         { -19,  0x14400051 },
945         { -20,  0x24400051 },
946         { -21,  0x1300004c },
947         { -22,  0x12000048 },
948         { -23,  0x11000044 },
949         { -24,  0x10000040 },
950 };
951
952 /*
953  * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
954  * This Table is for CH1~CH13
955  */
956 static const ccktxbbgain_struct rtl8192_cck_txbbgain_table[] = {
957         {{ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 }},
958         {{ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 }},
959         {{ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03 }},
960         {{ 0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03 }},
961         {{ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 }},
962         {{ 0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03 }},
963         {{ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }},
964         {{ 0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03 }},
965         {{ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02 }},
966         {{ 0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02 }},
967         {{ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02 }},
968         {{ 0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02 }},
969         {{ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02 }},
970         {{ 0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02 }},
971         {{ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02 }},
972         {{ 0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02 }},
973         {{ 0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01 }},
974         {{ 0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02 }},
975         {{ 0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01 }},
976         {{ 0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
977         {{ 0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
978         {{ 0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
979         {{ 0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
980 };
981
982 /*
983  * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
984  * This Table is for CH14
985  */
986 static const ccktxbbgain_struct rtl8192_cck_txbbgain_ch14_table[] = {
987         {{ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 }},
988         {{ 0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00 }},
989         {{ 0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00 }},
990         {{ 0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00 }},
991         {{ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 }},
992         {{ 0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00 }},
993         {{ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00 }},
994         {{ 0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00 }},
995         {{ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00 }},
996         {{ 0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00 }},
997         {{ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
998         {{ 0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
999         {{ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
1000         {{ 0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00 }},
1001         {{ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
1002         {{ 0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
1003         {{ 0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
1004         {{ 0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
1005         {{ 0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
1006         {{ 0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
1007         {{ 0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
1008         {{ 0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00 }},
1009         {{ 0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00 }},
1010 };
1011
1012 static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
1013 {
1014         struct r8192_priv *priv = ieee80211_priv(dev);
1015
1016         priv->txbbgain_table = rtl8192_txbbgain_table;
1017         priv->cck_txbbgain_table = rtl8192_cck_txbbgain_table;
1018         priv->cck_txbbgain_ch14_table = rtl8192_cck_txbbgain_ch14_table;
1019
1020         priv->btxpower_tracking = TRUE;
1021         priv->txpower_count       = 0;
1022         priv->btxpower_trackingInit = FALSE;
1023
1024 }
1025
1026 static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
1027 {
1028         struct r8192_priv *priv = ieee80211_priv(dev);
1029
1030         // Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism
1031         // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
1032         // 3-wire by driver cause RF goes into wrong state.
1033         if(priv->ieee80211->FwRWRF)
1034                 priv->btxpower_tracking = TRUE;
1035         else
1036                 priv->btxpower_tracking = FALSE;
1037         priv->txpower_count       = 0;
1038         priv->btxpower_trackingInit = FALSE;
1039 }
1040
1041 void dm_initialize_txpower_tracking(struct net_device *dev)
1042 {
1043         struct r8192_priv *priv = ieee80211_priv(dev);
1044
1045         if(priv->IC_Cut >= IC_VersionCut_D)
1046                 dm_InitializeTXPowerTracking_TSSI(dev);
1047         else
1048                 dm_InitializeTXPowerTracking_ThermalMeter(dev);
1049 }
1050
1051
1052 static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
1053 {
1054         struct r8192_priv *priv = ieee80211_priv(dev);
1055         static u32 tx_power_track_counter = 0;
1056         RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
1057         if(read_nic_byte(priv, 0x11e) ==1)
1058                 return;
1059         if(!priv->btxpower_tracking)
1060                 return;
1061         tx_power_track_counter++;
1062
1063         if (tx_power_track_counter > 90) {
1064                 queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
1065                 tx_power_track_counter =0;
1066         }
1067 }
1068
1069 static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
1070 {
1071         struct r8192_priv *priv = ieee80211_priv(dev);
1072         static u8       TM_Trigger=0;
1073
1074         if(!priv->btxpower_tracking)
1075                 return;
1076         else
1077         {
1078                 if(priv->txpower_count  <= 2)
1079                 {
1080                         priv->txpower_count++;
1081                         return;
1082                 }
1083         }
1084
1085         if(!TM_Trigger)
1086         {
1087                 //Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash
1088                 //actually write reg0x02 bit1=0, then bit1=1.
1089                 rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
1090                 rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
1091                 rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
1092                 rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
1093                 TM_Trigger = 1;
1094                 return;
1095         }
1096         else {
1097                 queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
1098                 TM_Trigger = 0;
1099         }
1100 }
1101
1102 static void dm_check_txpower_tracking(struct net_device *dev)
1103 {
1104         struct r8192_priv *priv = ieee80211_priv(dev);
1105
1106         if(priv->IC_Cut >= IC_VersionCut_D)
1107                 dm_CheckTXPowerTracking_TSSI(dev);
1108         else
1109                 dm_CheckTXPowerTracking_ThermalMeter(dev);
1110 }
1111
1112
1113 static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
1114 {
1115         u32 TempVal;
1116         struct r8192_priv *priv = ieee80211_priv(dev);
1117         //Write 0xa22 0xa23
1118         TempVal = 0;
1119         if(!bInCH14){
1120                 //Write 0xa22 0xa23
1121                 TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
1122                                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
1123
1124                 rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
1125                 //Write 0xa24 ~ 0xa27
1126                 TempVal = 0;
1127                 TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1128                                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1129                                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1130                                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1131                 rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
1132                 //Write 0xa28  0xa29
1133                 TempVal = 0;
1134                 TempVal =       (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1135                                         (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1136
1137                 rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
1138         }
1139         else
1140         {
1141                 TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
1142                                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
1143
1144                 rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
1145                 //Write 0xa24 ~ 0xa27
1146                 TempVal = 0;
1147                 TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1148                                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1149                                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1150                                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1151                 rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
1152                 //Write 0xa28  0xa29
1153                 TempVal = 0;
1154                 TempVal =       (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1155                                         (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1156
1157                 rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
1158         }
1159
1160
1161 }
1162
1163 static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,    bool  bInCH14)
1164 {
1165         u32 TempVal;
1166         struct r8192_priv *priv = ieee80211_priv(dev);
1167
1168         TempVal = 0;
1169         if(!bInCH14)
1170         {
1171                 //Write 0xa22 0xa23
1172                 TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
1173                                         (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
1174                 rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1175                 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1176                         rCCK0_TxFilter1, TempVal);
1177                 //Write 0xa24 ~ 0xa27
1178                 TempVal = 0;
1179                 TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
1180                                         (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
1181                                         (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+
1182                                         (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
1183                 rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1184                 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1185                         rCCK0_TxFilter2, TempVal);
1186                 //Write 0xa28  0xa29
1187                 TempVal = 0;
1188                 TempVal =       CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
1189                                         (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ;
1190
1191                 rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1192                 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1193                         rCCK0_DebugPort, TempVal);
1194         }
1195         else
1196         {
1197 //              priv->CCKTxPowerAdjustCntNotCh14++;     //cosa add for debug.
1198                 //Write 0xa22 0xa23
1199                 TempVal =       CCKSwingTable_Ch14[priv->CCK_index][0] +
1200                                         (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
1201
1202                 rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
1203                 RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1204                         rCCK0_TxFilter1, TempVal);
1205                 //Write 0xa24 ~ 0xa27
1206                 TempVal = 0;
1207                 TempVal =       CCKSwingTable_Ch14[priv->CCK_index][2] +
1208                                         (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
1209                                         (CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+
1210                                         (CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
1211                 rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
1212                 RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1213                         rCCK0_TxFilter2, TempVal);
1214                 //Write 0xa28  0xa29
1215                 TempVal = 0;
1216                 TempVal =       CCKSwingTable_Ch14[priv->CCK_index][6] +
1217                                         (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ;
1218
1219                 rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
1220                 RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n",
1221                         rCCK0_DebugPort, TempVal);
1222         }
1223 }
1224
1225 void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
1226 {
1227         struct r8192_priv *priv = ieee80211_priv(dev);
1228
1229         if(priv->IC_Cut >= IC_VersionCut_D)
1230                 dm_CCKTxPowerAdjust_TSSI(dev, binch14);
1231         else
1232                 dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
1233 }
1234
1235
1236 void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type, u32 dm_value)
1237 {
1238         if (dm_type == DIG_TYPE_THRESH_HIGH)
1239         {
1240                 dm_digtable.rssi_high_thresh = dm_value;
1241         }
1242         else if (dm_type == DIG_TYPE_THRESH_LOW)
1243         {
1244                 dm_digtable.rssi_low_thresh = dm_value;
1245         }
1246         else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
1247         {
1248                 dm_digtable.rssi_high_power_highthresh = dm_value;
1249         }
1250         else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
1251         {
1252                 dm_digtable.rssi_high_power_highthresh = dm_value;
1253         }
1254         else if (dm_type == DIG_TYPE_ENABLE)
1255         {
1256                 dm_digtable.dig_state           = DM_STA_DIG_MAX;
1257                 dm_digtable.dig_enable_flag     = true;
1258         }
1259         else if (dm_type == DIG_TYPE_DISABLE)
1260         {
1261                 dm_digtable.dig_state           = DM_STA_DIG_MAX;
1262                 dm_digtable.dig_enable_flag     = false;
1263         }
1264         else if (dm_type == DIG_TYPE_DBG_MODE)
1265         {
1266                 if(dm_value >= DM_DBG_MAX)
1267                         dm_value = DM_DBG_OFF;
1268                 dm_digtable.dbg_mode            = (u8)dm_value;
1269         }
1270         else if (dm_type == DIG_TYPE_RSSI)
1271         {
1272                 if(dm_value > 100)
1273                         dm_value = 30;
1274                 dm_digtable.rssi_val                    = (long)dm_value;
1275         }
1276         else if (dm_type == DIG_TYPE_ALGORITHM)
1277         {
1278                 if (dm_value >= DIG_ALGO_MAX)
1279                         dm_value = DIG_ALGO_BY_FALSE_ALARM;
1280                 if(dm_digtable.dig_algorithm != (u8)dm_value)
1281                         dm_digtable.dig_algorithm_switch = 1;
1282                 dm_digtable.dig_algorithm       = (u8)dm_value;
1283         }
1284         else if (dm_type == DIG_TYPE_BACKOFF)
1285         {
1286                 if(dm_value > 30)
1287                         dm_value = 30;
1288                 dm_digtable.backoff_val         = (u8)dm_value;
1289         }
1290         else if(dm_type == DIG_TYPE_RX_GAIN_MIN)
1291         {
1292                 if(dm_value == 0)
1293                         dm_value = 0x1;
1294                 dm_digtable.rx_gain_range_min = (u8)dm_value;
1295         }
1296         else if(dm_type == DIG_TYPE_RX_GAIN_MAX)
1297         {
1298                 if(dm_value > 0x50)
1299                         dm_value = 0x50;
1300                 dm_digtable.rx_gain_range_max = (u8)dm_value;
1301         }
1302 }
1303
1304
1305 /* Set DIG scheme init value. */
1306 static void dm_dig_init(struct net_device *dev)
1307 {
1308         struct r8192_priv *priv = ieee80211_priv(dev);
1309         /* 2007/10/05 MH Disable DIG scheme now. Not tested. */
1310         dm_digtable.dig_enable_flag     = true;
1311         dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
1312         dm_digtable.dbg_mode = DM_DBG_OFF;      //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig
1313         dm_digtable.dig_algorithm_switch = 0;
1314
1315         /* 2007/10/04 MH Define init gain threshold. */
1316         dm_digtable.dig_state           = DM_STA_DIG_MAX;
1317         dm_digtable.dig_highpwr_state   = DM_STA_DIG_MAX;
1318         dm_digtable.initialgain_lowerbound_state = false;
1319
1320         dm_digtable.rssi_low_thresh     = DM_DIG_THRESH_LOW;
1321         dm_digtable.rssi_high_thresh    = DM_DIG_THRESH_HIGH;
1322
1323         dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
1324         dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
1325
1326         dm_digtable.rssi_val = 50;      //for new dig debug rssi value
1327         dm_digtable.backoff_val = DM_DIG_BACKOFF;
1328         dm_digtable.rx_gain_range_max = DM_DIG_MAX;
1329         if(priv->CustomerID == RT_CID_819x_Netcore)
1330                 dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;
1331         else
1332                 dm_digtable.rx_gain_range_min = DM_DIG_MIN;
1333
1334 }
1335
1336
1337 /*
1338  * Driver must monitor RSSI and notify firmware to change initial
1339  * gain according to different threshold. BB team provide the
1340  * suggested solution.
1341  */
1342 static void dm_ctrl_initgain_byrssi(struct net_device *dev)
1343 {
1344
1345         if (dm_digtable.dig_enable_flag == false)
1346                 return;
1347
1348         if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
1349                 dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev);
1350         else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1351                 dm_ctrl_initgain_byrssi_by_driverrssi(dev);
1352 }
1353
1354
1355 static void dm_ctrl_initgain_byrssi_by_driverrssi(
1356         struct net_device *dev)
1357 {
1358         struct r8192_priv *priv = ieee80211_priv(dev);
1359         u8 i;
1360         static u8       fw_dig=0;
1361
1362         if (dm_digtable.dig_enable_flag == false)
1363                 return;
1364
1365         if(dm_digtable.dig_algorithm_switch)    // if swithed algorithm, we have to disable FW Dig.
1366                 fw_dig = 0;
1367         if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled
1368         {// FW DIG Off
1369                 for(i=0; i<3; i++)
1370                         rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);   // Only clear byte 1 and rewrite.
1371                 fw_dig++;
1372                 dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off.
1373         }
1374
1375         if(priv->ieee80211->state == IEEE80211_LINKED)
1376                 dm_digtable.cur_connect_state = DIG_CONNECT;
1377         else
1378                 dm_digtable.cur_connect_state = DIG_DISCONNECT;
1379
1380         if(dm_digtable.dbg_mode == DM_DBG_OFF)
1381                 dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
1382
1383         dm_initial_gain(dev);
1384         dm_pd_th(dev);
1385         dm_cs_ratio(dev);
1386         if(dm_digtable.dig_algorithm_switch)
1387                 dm_digtable.dig_algorithm_switch = 0;
1388         dm_digtable.pre_connect_state = dm_digtable.cur_connect_state;
1389
1390 }
1391
1392 static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
1393         struct net_device *dev)
1394 {
1395         struct r8192_priv *priv = ieee80211_priv(dev);
1396         static u32 reset_cnt = 0;
1397         u8 i;
1398
1399         if (dm_digtable.dig_enable_flag == false)
1400                 return;
1401
1402         if(dm_digtable.dig_algorithm_switch)
1403         {
1404                 dm_digtable.dig_state = DM_STA_DIG_MAX;
1405                 // Fw DIG On.
1406                 for(i=0; i<3; i++)
1407                         rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);   // Only clear byte 1 and rewrite.
1408                 dm_digtable.dig_algorithm_switch = 0;
1409         }
1410
1411         if (priv->ieee80211->state != IEEE80211_LINKED)
1412                 return;
1413
1414         // For smooth, we can not change DIG state.
1415         if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
1416                 (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
1417         {
1418                 return;
1419         }
1420
1421         /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
1422                   and then execute below step. */
1423         if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
1424         {
1425                 /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters
1426                    will be reset to init value. We must prevent the condition. */
1427                 if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
1428                         (priv->reset_count == reset_cnt))
1429                 {
1430                         return;
1431                 }
1432                 else
1433                 {
1434                         reset_cnt = priv->reset_count;
1435                 }
1436
1437                 // If DIG is off, DIG high power state must reset.
1438                 dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
1439                 dm_digtable.dig_state = DM_STA_DIG_OFF;
1440
1441                 // 1.1 DIG Off.
1442                 rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);   // Only clear byte 1 and rewrite.
1443
1444                 // 1.2 Set initial gain.
1445                 write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x17);
1446                 write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x17);
1447                 write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x17);
1448                 write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x17);
1449
1450                 // 1.3 Lower PD_TH for OFDM.
1451                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1452                 {
1453                         /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1454                         // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1455                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1456                 }
1457                 else
1458                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1459
1460                 // 1.4 Lower CS ratio for CCK.
1461                 write_nic_byte(priv, 0xa0a, 0x08);
1462
1463                 // 1.5 Higher EDCCA.
1464                 //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);
1465                 return;
1466
1467         }
1468
1469         /* 2. When RSSI increase, We have to judge if it is larger than a threshold
1470                   and then execute below step.  */
1471         if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) )
1472         {
1473                 u8 reset_flag = 0;
1474
1475                 if (dm_digtable.dig_state == DM_STA_DIG_ON &&
1476                         (priv->reset_count == reset_cnt))
1477                 {
1478                         dm_ctrl_initgain_byrssi_highpwr(dev);
1479                         return;
1480                 }
1481                 else
1482                 {
1483                         if (priv->reset_count != reset_cnt)
1484                                 reset_flag = 1;
1485
1486                         reset_cnt = priv->reset_count;
1487                 }
1488
1489                 dm_digtable.dig_state = DM_STA_DIG_ON;
1490
1491                 // 2.1 Set initial gain.
1492                 // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment.
1493                 if (reset_flag == 1)
1494                 {
1495                         write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x2c);
1496                         write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x2c);
1497                         write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x2c);
1498                         write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x2c);
1499                 }
1500                 else
1501                 {
1502                         write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x20);
1503                         write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x20);
1504                         write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x20);
1505                         write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x20);
1506                 }
1507
1508                 // 2.2 Higher PD_TH for OFDM.
1509                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1510                 {
1511                         /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1512                         // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1513                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1514                 }
1515                 else
1516                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1517
1518                 // 2.3 Higher CS ratio for CCK.
1519                 write_nic_byte(priv, 0xa0a, 0xcd);
1520
1521                 // 2.4 Lower EDCCA.
1522                 /* 2008/01/11 MH 90/92 series are the same. */
1523                 //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);
1524
1525                 // 2.5 DIG On.
1526                 rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);   // Only clear byte 1 and rewrite.
1527
1528         }
1529
1530         dm_ctrl_initgain_byrssi_highpwr(dev);
1531
1532 }
1533
1534 static void dm_ctrl_initgain_byrssi_highpwr(
1535         struct net_device * dev)
1536 {
1537         struct r8192_priv *priv = ieee80211_priv(dev);
1538         static u32 reset_cnt_highpwr = 0;
1539
1540         // For smooth, we can not change high power DIG state in the range.
1541         if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
1542                 (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
1543         {
1544                 return;
1545         }
1546
1547         /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if
1548                   it is larger than a threshold and then execute below step.  */
1549         // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue.
1550         if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh)
1551         {
1552                 if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
1553                         (priv->reset_count == reset_cnt_highpwr))
1554                         return;
1555                 else
1556                         dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
1557
1558                 // 3.1 Higher PD_TH for OFDM for high power state.
1559                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1560                 {
1561                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1562                 }
1563                 else
1564                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1565         }
1566         else
1567         {
1568                 if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&&
1569                         (priv->reset_count == reset_cnt_highpwr))
1570                         return;
1571                 else
1572                         dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
1573
1574                 if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
1575                          priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)
1576                 {
1577                         // 3.2 Recover PD_TH for OFDM for normal power region.
1578                         if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1579                         {
1580                                 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1581                         }
1582                         else
1583                                 write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1584                 }
1585         }
1586
1587         reset_cnt_highpwr = priv->reset_count;
1588
1589 }
1590
1591
1592 static void dm_initial_gain(
1593         struct net_device * dev)
1594 {
1595         struct r8192_priv *priv = ieee80211_priv(dev);
1596         u8                                      initial_gain=0;
1597         static u8                               initialized=0, force_write=0;
1598         static u32                      reset_cnt=0;
1599
1600         if(dm_digtable.dig_algorithm_switch)
1601         {
1602                 initialized = 0;
1603                 reset_cnt = 0;
1604         }
1605
1606         if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1607         {
1608                 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1609                 {
1610                         if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
1611                                 dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
1612                         else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
1613                                 dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
1614                         else
1615                                 dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
1616                 }
1617                 else            //current state is disconnected
1618                 {
1619                         if(dm_digtable.cur_ig_value == 0)
1620                                 dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1621                         else
1622                                 dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
1623                 }
1624         }
1625         else    // disconnected -> connected or connected -> disconnected
1626         {
1627                 dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1628                 dm_digtable.pre_ig_value = 0;
1629         }
1630
1631         // if silent reset happened, we should rewrite the values back
1632         if(priv->reset_count != reset_cnt)
1633         {
1634                 force_write = 1;
1635                 reset_cnt = priv->reset_count;
1636         }
1637
1638         if(dm_digtable.pre_ig_value != read_nic_byte(priv, rOFDM0_XAAGCCore1))
1639                 force_write = 1;
1640
1641         {
1642                 if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
1643                         || !initialized || force_write)
1644                 {
1645                         initial_gain = (u8)dm_digtable.cur_ig_value;
1646                         // Set initial gain.
1647                         write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
1648                         write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
1649                         write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
1650                         write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
1651                         dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
1652                         initialized = 1;
1653                         force_write = 0;
1654                 }
1655         }
1656 }
1657
1658 static void dm_pd_th(
1659         struct net_device * dev)
1660 {
1661         struct r8192_priv *priv = ieee80211_priv(dev);
1662         static u8                               initialized=0, force_write=0;
1663         static u32                      reset_cnt = 0;
1664
1665         if(dm_digtable.dig_algorithm_switch)
1666         {
1667                 initialized = 0;
1668                 reset_cnt = 0;
1669         }
1670
1671         if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1672         {
1673                 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1674                 {
1675                         if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
1676                                 dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
1677                         else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1678                                 dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1679                         else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
1680                                         (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
1681                                 dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
1682                         else
1683                                 dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
1684                 }
1685                 else
1686                 {
1687                         dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1688                 }
1689         }
1690         else    // disconnected -> connected or connected -> disconnected
1691         {
1692                 dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1693         }
1694
1695         // if silent reset happened, we should rewrite the values back
1696         if(priv->reset_count != reset_cnt)
1697         {
1698                 force_write = 1;
1699                 reset_cnt = priv->reset_count;
1700         }
1701
1702         {
1703                 if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
1704                         (initialized<=3) || force_write)
1705                 {
1706                         if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER)
1707                         {
1708                                 // Lower PD_TH for OFDM.
1709                                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1710                                 {
1711                                         /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1712                                         // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1713                                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1714                                 }
1715                                 else
1716                                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1717                         }
1718                         else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER)
1719                         {
1720                                 // Higher PD_TH for OFDM.
1721                                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1722                                 {
1723                                         /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1724                                         // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1725                                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1726                                 }
1727                                 else
1728                                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1729                         }
1730                         else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER)
1731                         {
1732                                 // Higher PD_TH for OFDM for high power state.
1733                                 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1734                                 {
1735                                         write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1736                                 }
1737                                 else
1738                                         write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1739                         }
1740                         dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
1741                         if(initialized <= 3)
1742                                 initialized++;
1743                         force_write = 0;
1744                 }
1745         }
1746 }
1747
1748 static  void dm_cs_ratio(
1749         struct net_device * dev)
1750 {
1751         struct r8192_priv *priv = ieee80211_priv(dev);
1752         static u8                               initialized=0,force_write=0;
1753         static u32                      reset_cnt = 0;
1754
1755         if(dm_digtable.dig_algorithm_switch)
1756         {
1757                 initialized = 0;
1758                 reset_cnt = 0;
1759         }
1760
1761         if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1762         {
1763                 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1764                 {
1765                         if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1766                                 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1767                         else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) )
1768                                 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
1769                         else
1770                                 dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
1771                 }
1772                 else
1773                 {
1774                         dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1775                 }
1776         }
1777         else    // disconnected -> connected or connected -> disconnected
1778         {
1779                 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1780         }
1781
1782         // if silent reset happened, we should rewrite the values back
1783         if(priv->reset_count != reset_cnt)
1784         {
1785                 force_write = 1;
1786                 reset_cnt = priv->reset_count;
1787         }
1788
1789
1790         if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
1791                 !initialized || force_write)
1792         {
1793                 if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
1794                 {
1795                         // Lower CS ratio for CCK.
1796                         write_nic_byte(priv, 0xa0a, 0x08);
1797                 }
1798                 else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
1799                 {
1800                         // Higher CS ratio for CCK.
1801                         write_nic_byte(priv, 0xa0a, 0xcd);
1802                 }
1803                 dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
1804                 initialized = 1;
1805                 force_write = 0;
1806         }
1807 }
1808
1809 void dm_init_edca_turbo(struct net_device *dev)
1810 {
1811         struct r8192_priv *priv = ieee80211_priv(dev);
1812
1813         priv->bcurrent_turbo_EDCA = false;
1814         priv->ieee80211->bis_any_nonbepkts = false;
1815         priv->bis_cur_rdlstate = false;
1816 }
1817
1818 static void dm_check_edca_turbo(
1819         struct net_device * dev)
1820 {
1821         struct r8192_priv *priv = ieee80211_priv(dev);
1822         PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
1823         //PSTA_QOS                      pStaQos = pMgntInfo->pStaQos;
1824
1825         // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.
1826         static unsigned long                    lastTxOkCnt = 0;
1827         static unsigned long                    lastRxOkCnt = 0;
1828         unsigned long                           curTxOkCnt = 0;
1829         unsigned long                           curRxOkCnt = 0;
1830
1831         //
1832         // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters
1833         // should follow the settings from QAP. By Bruce, 2007-12-07.
1834         //
1835         if(priv->ieee80211->state != IEEE80211_LINKED)
1836                 goto dm_CheckEdcaTurbo_EXIT;
1837         // We do not turn on EDCA turbo mode for some AP that has IOT issue
1838         if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
1839                 goto dm_CheckEdcaTurbo_EXIT;
1840
1841         // Check the status for current condition.
1842         if(!priv->ieee80211->bis_any_nonbepkts)
1843         {
1844                 curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1845                 curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1846                 // For RT-AP, we needs to turn it on when Rx>Tx
1847                 if(curRxOkCnt > 4*curTxOkCnt)
1848                 {
1849                         if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1850                         {
1851                                 write_nic_dword(priv, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
1852                                 priv->bis_cur_rdlstate = true;
1853                         }
1854                 }
1855                 else
1856                 {
1857                         if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1858                         {
1859                                 write_nic_dword(priv, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
1860                                 priv->bis_cur_rdlstate = false;
1861                         }
1862
1863                 }
1864
1865                 priv->bcurrent_turbo_EDCA = true;
1866         }
1867         else
1868         {
1869                 //
1870                 // Turn Off EDCA turbo here.
1871                 // Restore original EDCA according to the declaration of AP.
1872                 //
1873                  if(priv->bcurrent_turbo_EDCA)
1874                 {
1875
1876                         {
1877                                 u8              u1bAIFS;
1878                                 u32             u4bAcParam;
1879                                 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
1880                                 u8 mode = priv->ieee80211->mode;
1881
1882                         // For Each time updating EDCA parameter, reset EDCA turbo mode status.
1883                                 dm_init_edca_turbo(dev);
1884                                 u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
1885                                 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
1886                                         (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)|
1887                                         (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)|
1888                                         ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
1889                                 printk("===>u4bAcParam:%x, ", u4bAcParam);
1890                         //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
1891                                 write_nic_dword(priv, EDCAPARA_BE,  u4bAcParam);
1892
1893                         // Check ACM bit.
1894                         // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
1895                                 {
1896                         // TODO:  Modified this part and try to set acm control in only 1 IO processing!!
1897
1898                                         PACI_AIFSN      pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
1899                                         u8              AcmCtrl = read_nic_byte(priv, AcmHwCtrl );
1900                                         if( pAciAifsn->f.ACM )
1901                                         { // ACM bit is 1.
1902                                                 AcmCtrl |= AcmHw_BeqEn;
1903                                         }
1904                                         else
1905                                         { // ACM bit is 0.
1906                                                 AcmCtrl &= (~AcmHw_BeqEn);
1907                                         }
1908
1909                                         RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ;
1910                                         write_nic_byte(priv, AcmHwCtrl, AcmCtrl );
1911                                 }
1912                         }
1913                         priv->bcurrent_turbo_EDCA = false;
1914                 }
1915         }
1916
1917
1918 dm_CheckEdcaTurbo_EXIT:
1919         // Set variables for next time.
1920         priv->ieee80211->bis_any_nonbepkts = false;
1921         lastTxOkCnt = priv->stats.txbytesunicast;
1922         lastRxOkCnt = priv->stats.rxbytesunicast;
1923 }
1924
1925 static void dm_init_ctstoself(struct net_device * dev)
1926 {
1927         struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
1928
1929         priv->ieee80211->bCTSToSelfEnable = TRUE;
1930         priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
1931 }
1932
1933 static void dm_ctstoself(struct net_device *dev)
1934 {
1935         struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
1936         PRT_HIGH_THROUGHPUT     pHTInfo = priv->ieee80211->pHTInfo;
1937         static unsigned long                            lastTxOkCnt = 0;
1938         static unsigned long                            lastRxOkCnt = 0;
1939         unsigned long                                           curTxOkCnt = 0;
1940         unsigned long                                           curRxOkCnt = 0;
1941
1942         if(priv->ieee80211->bCTSToSelfEnable != TRUE)
1943         {
1944                 pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1945                 return;
1946         }
1947         /*
1948         1. Uplink
1949         2. Linksys350/Linksys300N
1950         3. <50 disable, >55 enable
1951         */
1952
1953         if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
1954         {
1955                 curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1956                 curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1957                 if(curRxOkCnt > 4*curTxOkCnt)   //downlink, disable CTS to self
1958                 {
1959                         pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1960                 }
1961                 else    //uplink
1962                 {
1963                         pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
1964                 }
1965
1966                 lastTxOkCnt = priv->stats.txbytesunicast;
1967                 lastRxOkCnt = priv->stats.rxbytesunicast;
1968         }
1969 }
1970
1971
1972
1973 /* Copy 8187B template for 9xseries */
1974 static void dm_check_rfctrl_gpio(struct net_device * dev)
1975 {
1976         struct r8192_priv *priv = ieee80211_priv(dev);
1977
1978         // Walk around for DTM test, we will not enable HW - radio on/off because r/w
1979         // page 1 register before Lextra bus is enabled cause system fails when resuming
1980         // from S4. 20080218, Emily
1981
1982         // Stop to execute workitem to prevent S3/S4 bug.
1983         queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
1984 }
1985
1986 /* Check if PBC button is pressed. */
1987 static  void    dm_check_pbc_gpio(struct net_device *dev)
1988 {
1989 }
1990
1991 /* PCI will not support workitem call back HW radio on-off control. */
1992 void dm_gpio_change_rf_callback(struct work_struct *work)
1993 {
1994         struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1995         struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
1996         struct net_device *dev = priv->ieee80211->dev;
1997         u8 tmp1byte;
1998         RT_RF_POWER_STATE       eRfPowerStateToSet;
1999         bool bActuallySet = false;
2000
2001         if (!priv->up) {
2002                 RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n");
2003         } else {
2004                 // 0x108 GPIO input register is read only
2005                 //set 0x108 B1= 1: RF-ON; 0: RF-OFF.
2006                 tmp1byte = read_nic_byte(priv, GPI);
2007
2008                 eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
2009
2010                 if (priv->bHwRadioOff && (eRfPowerStateToSet == eRfOn)) {
2011                         RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio ON\n");
2012
2013                         priv->bHwRadioOff = false;
2014                         bActuallySet = true;
2015                 } else if ((!priv->bHwRadioOff) && (eRfPowerStateToSet == eRfOff)) {
2016                         RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio OFF\n");
2017                         priv->bHwRadioOff = true;
2018                         bActuallySet = true;
2019                 }
2020
2021                 if (bActuallySet) {
2022                         priv->bHwRfOffAction = 1;
2023                         MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
2024                         //DrvIFIndicateCurrentPhyStatus(pAdapter);
2025                 } else {
2026                         msleep(2000);
2027                 }
2028         }
2029 }
2030
2031 /* Check if Current RF RX path is enabled */
2032 void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
2033 {
2034         struct delayed_work *dwork = container_of(work,struct delayed_work,work);
2035         struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq);
2036         struct net_device *dev =priv->ieee80211->dev;
2037         //bool bactually_set = false;
2038         u8 rfpath = 0, i;
2039
2040
2041         /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will
2042            always be the same. We only read 0xc04 now. */
2043         rfpath = read_nic_byte(priv, 0xc04);
2044
2045         // Check Bit 0-3, it means if RF A-D is enabled.
2046         for (i = 0; i < RF90_PATH_MAX; i++)
2047         {
2048                 if (rfpath & (0x01<<i))
2049                         priv->brfpath_rxenable[i] = 1;
2050                 else
2051                         priv->brfpath_rxenable[i] = 0;
2052         }
2053         if(!DM_RxPathSelTable.Enable)
2054                 return;
2055
2056         dm_rxpath_sel_byrssi(dev);
2057 }
2058
2059 static void dm_init_rxpath_selection(struct net_device * dev)
2060 {
2061         u8 i;
2062         struct r8192_priv *priv = ieee80211_priv(dev);
2063         DM_RxPathSelTable.Enable = 1;   //default enabled
2064         DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
2065         DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
2066         if(priv->CustomerID == RT_CID_819x_Netcore)
2067                 DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
2068         else
2069                 DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
2070         DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
2071         DM_RxPathSelTable.disabledRF = 0;
2072         for(i=0; i<4; i++)
2073         {
2074                 DM_RxPathSelTable.rf_rssi[i] = 50;
2075                 DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
2076                 DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2077         }
2078 }
2079
2080 static void dm_rxpath_sel_byrssi(struct net_device * dev)
2081 {
2082         struct r8192_priv *priv = ieee80211_priv(dev);
2083         u8                              i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0;
2084         u8                              tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0;
2085         u8                              cck_default_Rx=0x2;     //RF-C
2086         u8                              cck_optional_Rx=0x3;//RF-D
2087         long                            tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0;
2088         u8                              cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0;
2089         u8                              cur_rf_rssi;
2090         long                            cur_cck_pwdb;
2091         static u8                       disabled_rf_cnt=0, cck_Rx_Path_initialized=0;
2092         u8                              update_cck_rx_path;
2093
2094         if(priv->rf_type != RF_2T4R)
2095                 return;
2096
2097         if(!cck_Rx_Path_initialized)
2098         {
2099                 DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(priv, 0xa07)&0xf);
2100                 cck_Rx_Path_initialized = 1;
2101         }
2102
2103         DM_RxPathSelTable.disabledRF = 0xf;
2104         DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(priv, 0xc04));
2105
2106         if(priv->ieee80211->mode == WIRELESS_MODE_B)
2107         {
2108                 DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;        //pure B mode, fixed cck version2
2109         }
2110
2111         //decide max/sec/min rssi index
2112         for (i=0; i<RF90_PATH_MAX; i++)
2113         {
2114                 if(!DM_RxPathSelTable.DbgMode)
2115                         DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
2116
2117                 if(priv->brfpath_rxenable[i])
2118                 {
2119                         rf_num++;
2120                         cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
2121
2122                         if(rf_num == 1) // find first enabled rf path and the rssi values
2123                         {       //initialize, set all rssi index to the same one
2124                                 max_rssi_index = min_rssi_index = sec_rssi_index = i;
2125                                 tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
2126                         }
2127                         else if(rf_num == 2)
2128                         {       // we pick up the max index first, and let sec and min to be the same one
2129                                 if(cur_rf_rssi >= tmp_max_rssi)
2130                                 {
2131                                         tmp_max_rssi = cur_rf_rssi;
2132                                         max_rssi_index = i;
2133                                 }
2134                                 else
2135                                 {
2136                                         tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
2137                                         sec_rssi_index = min_rssi_index = i;
2138                                 }
2139                         }
2140                         else
2141                         {
2142                                 if(cur_rf_rssi > tmp_max_rssi)
2143                                 {
2144                                         tmp_sec_rssi = tmp_max_rssi;
2145                                         sec_rssi_index = max_rssi_index;
2146                                         tmp_max_rssi = cur_rf_rssi;
2147                                         max_rssi_index = i;
2148                                 }
2149                                 else if(cur_rf_rssi == tmp_max_rssi)
2150                                 {       // let sec and min point to the different index
2151                                         tmp_sec_rssi = cur_rf_rssi;
2152                                         sec_rssi_index = i;
2153                                 }
2154                                 else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi))
2155                                 {
2156                                         tmp_sec_rssi = cur_rf_rssi;
2157                                         sec_rssi_index = i;
2158                                 }
2159                                 else if(cur_rf_rssi == tmp_sec_rssi)
2160                                 {
2161                                         if(tmp_sec_rssi == tmp_min_rssi)
2162                                         {       // let sec and min point to the different index
2163                                                 tmp_sec_rssi = cur_rf_rssi;
2164                                                 sec_rssi_index = i;
2165                                         }
2166                                         else
2167                                         {
2168                                                 // This case we don't need to set any index
2169                                         }
2170                                 }
2171                                 else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi))
2172                                 {
2173                                         // This case we don't need to set any index
2174                                 }
2175                                 else if(cur_rf_rssi == tmp_min_rssi)
2176                                 {
2177                                         if(tmp_sec_rssi == tmp_min_rssi)
2178                                         {       // let sec and min point to the different index
2179                                                 tmp_min_rssi = cur_rf_rssi;
2180                                                 min_rssi_index = i;
2181                                         }
2182                                         else
2183                                         {
2184                                                 // This case we don't need to set any index
2185                                         }
2186                                 }
2187                                 else if(cur_rf_rssi < tmp_min_rssi)
2188                                 {
2189                                         tmp_min_rssi = cur_rf_rssi;
2190                                         min_rssi_index = i;
2191                                 }
2192                         }
2193                 }
2194         }
2195
2196         rf_num = 0;
2197         // decide max/sec/min cck pwdb index
2198         if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
2199         {
2200                 for (i=0; i<RF90_PATH_MAX; i++)
2201                 {
2202                         if(priv->brfpath_rxenable[i])
2203                         {
2204                                 rf_num++;
2205                                 cur_cck_pwdb =  DM_RxPathSelTable.cck_pwdb_sta[i];
2206
2207                                 if(rf_num == 1) // find first enabled rf path and the rssi values
2208                                 {       //initialize, set all rssi index to the same one
2209                                         cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i;
2210                                         tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb;
2211                                 }
2212                                 else if(rf_num == 2)
2213                                 {       // we pick up the max index first, and let sec and min to be the same one
2214                                         if(cur_cck_pwdb >= tmp_cck_max_pwdb)
2215                                         {
2216                                                 tmp_cck_max_pwdb = cur_cck_pwdb;
2217                                                 cck_rx_ver2_max_index = i;
2218                                         }
2219                                         else
2220                                         {
2221                                                 tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb;
2222                                                 cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i;
2223                                         }
2224                                 }
2225                                 else
2226                                 {
2227                                         if(cur_cck_pwdb > tmp_cck_max_pwdb)
2228                                         {
2229                                                 tmp_cck_sec_pwdb = tmp_cck_max_pwdb;
2230                                                 cck_rx_ver2_sec_index = cck_rx_ver2_max_index;
2231                                                 tmp_cck_max_pwdb = cur_cck_pwdb;
2232                                                 cck_rx_ver2_max_index = i;
2233                                         }
2234                                         else if(cur_cck_pwdb == tmp_cck_max_pwdb)
2235                                         {       // let sec and min point to the different index
2236                                                 tmp_cck_sec_pwdb = cur_cck_pwdb;
2237                                                 cck_rx_ver2_sec_index = i;
2238                                         }
2239                                         else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb))
2240                                         {
2241                                                 tmp_cck_sec_pwdb = cur_cck_pwdb;
2242                                                 cck_rx_ver2_sec_index = i;
2243                                         }
2244                                         else if(cur_cck_pwdb == tmp_cck_sec_pwdb)
2245                                         {
2246                                                 if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2247                                                 {       // let sec and min point to the different index
2248                                                         tmp_cck_sec_pwdb = cur_cck_pwdb;
2249                                                         cck_rx_ver2_sec_index = i;
2250                                                 }
2251                                                 else
2252                                                 {
2253                                                         // This case we don't need to set any index
2254                                                 }
2255                                         }
2256                                         else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb))
2257                                         {
2258                                                 // This case we don't need to set any index
2259                                         }
2260                                         else if(cur_cck_pwdb == tmp_cck_min_pwdb)
2261                                         {
2262                                                 if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2263                                                 {       // let sec and min point to the different index
2264                                                         tmp_cck_min_pwdb = cur_cck_pwdb;
2265                                                         cck_rx_ver2_min_index = i;
2266                                                 }
2267                                                 else
2268                                                 {
2269                                                         // This case we don't need to set any index
2270                                                 }
2271                                         }
2272                                         else if(cur_cck_pwdb < tmp_cck_min_pwdb)
2273                                         {
2274                                                 tmp_cck_min_pwdb = cur_cck_pwdb;
2275                                                 cck_rx_ver2_min_index = i;
2276                                         }
2277                                 }
2278
2279                         }
2280                 }
2281         }
2282
2283
2284         // Set CCK Rx path
2285         // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path.
2286         update_cck_rx_path = 0;
2287         if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
2288         {
2289                 cck_default_Rx = cck_rx_ver2_max_index;
2290                 cck_optional_Rx = cck_rx_ver2_sec_index;
2291                 if(tmp_cck_max_pwdb != -64)
2292                         update_cck_rx_path = 1;
2293         }
2294
2295         if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2)
2296         {
2297                 if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH)
2298                 {
2299                         //record the enabled rssi threshold
2300                         DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
2301                         //disable the BB Rx path, OFDM
2302                         rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0);  // 0xc04[3:0]
2303                         rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0);  // 0xd04[3:0]
2304                         disabled_rf_cnt++;
2305                 }
2306                 if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1)
2307                 {
2308                         cck_default_Rx = max_rssi_index;
2309                         cck_optional_Rx = sec_rssi_index;
2310                         if(tmp_max_rssi)
2311                                 update_cck_rx_path = 1;
2312                 }
2313         }
2314
2315         if(update_cck_rx_path)
2316         {
2317                 DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
2318                 rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
2319         }
2320
2321         if(DM_RxPathSelTable.disabledRF)
2322         {
2323                 for(i=0; i<4; i++)
2324                 {
2325                         if((DM_RxPathSelTable.disabledRF>>i) & 0x1)     //disabled rf
2326                         {
2327                                 if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i])
2328                                 {
2329                                         //enable the BB Rx path
2330                                         rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);       // 0xc04[3:0]
2331                                         rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);       // 0xd04[3:0]
2332                                         DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2333                                         disabled_rf_cnt--;
2334                                 }
2335                         }
2336                 }
2337         }
2338 }
2339
2340 /*
2341  * Call a workitem to check current RXRF path and Rx Path selection by RSSI.
2342  */
2343 static void dm_check_rx_path_selection(struct net_device *dev)
2344 {
2345         struct r8192_priv *priv = ieee80211_priv(dev);
2346         queue_delayed_work(priv->priv_wq,&priv->rfpath_check_wq,0);
2347 }
2348
2349 static void dm_init_fsync (struct net_device *dev)
2350 {
2351         struct r8192_priv *priv = ieee80211_priv(dev);
2352
2353         priv->ieee80211->fsync_time_interval = 500;
2354         priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
2355         priv->ieee80211->fsync_rssi_threshold = 30;
2356         priv->ieee80211->bfsync_enable = false;
2357         priv->ieee80211->fsync_multiple_timeinterval = 3;
2358         priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
2359         priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
2360         priv->ieee80211->fsync_state = Default_Fsync;
2361         priv->framesyncMonitor = 1;     // current default 0xc38 monitor on
2362
2363         init_timer(&priv->fsync_timer);
2364         priv->fsync_timer.data = (unsigned long)dev;
2365         priv->fsync_timer.function = dm_fsync_timer_callback;
2366 }
2367
2368
2369 static void dm_deInit_fsync(struct net_device *dev)
2370 {
2371         struct r8192_priv *priv = ieee80211_priv(dev);
2372         del_timer_sync(&priv->fsync_timer);
2373 }
2374
2375 void dm_fsync_timer_callback(unsigned long data)
2376 {
2377         struct r8192_priv *priv = ieee80211_priv((struct net_device *)data);
2378         u32 rate_index, rate_count = 0, rate_count_diff=0;
2379         bool            bSwitchFromCountDiff = false;
2380         bool            bDoubleTimeInterval = false;
2381
2382         if(     priv->ieee80211->state == IEEE80211_LINKED &&
2383                 priv->ieee80211->bfsync_enable &&
2384                 (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2385         {
2386                  // Count rate 54, MCS [7], [12, 13, 14, 15]
2387                 u32 rate_bitmap;
2388                 for(rate_index = 0; rate_index <= 27; rate_index++)
2389                 {
2390                         rate_bitmap  = 1 << rate_index;
2391                         if(priv->ieee80211->fsync_rate_bitmap &  rate_bitmap)
2392                                 rate_count+= priv->stats.received_rate_histogram[1][rate_index];
2393                 }
2394
2395                 if(rate_count < priv->rate_record)
2396                         rate_count_diff = 0xffffffff - rate_count + priv->rate_record;
2397                 else
2398                         rate_count_diff = rate_count - priv->rate_record;
2399                 if(rate_count_diff < priv->rateCountDiffRecord)
2400                 {
2401
2402                         u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
2403                         // Contiune count
2404                         if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold)
2405                                 priv->ContiuneDiffCount++;
2406                         else
2407                                 priv->ContiuneDiffCount = 0;
2408
2409                         // Contiune count over
2410                         if(priv->ContiuneDiffCount >=2)
2411                         {
2412                                 bSwitchFromCountDiff = true;
2413                                 priv->ContiuneDiffCount = 0;
2414                         }
2415                 }
2416                 else
2417                 {
2418                         // Stop contiune count
2419                         priv->ContiuneDiffCount = 0;
2420                 }
2421
2422                 //If Count diff <= FsyncRateCountThreshold
2423                 if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold)
2424                 {
2425                         bSwitchFromCountDiff = true;
2426                         priv->ContiuneDiffCount = 0;
2427                 }
2428                 priv->rate_record = rate_count;
2429                 priv->rateCountDiffRecord = rate_count_diff;
2430                 RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2431                 // if we never receive those mcs rate and rssi > 30 % then switch fsyn
2432                 if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff)
2433                 {
2434                         bDoubleTimeInterval = true;
2435                         priv->bswitch_fsync = !priv->bswitch_fsync;
2436                         if(priv->bswitch_fsync)
2437                         {
2438                                 write_nic_byte(priv,0xC36, 0x1c);
2439                                 write_nic_byte(priv, 0xC3e, 0x90);
2440                         }
2441                         else
2442                         {
2443                                 write_nic_byte(priv, 0xC36, 0x5c);
2444                                 write_nic_byte(priv, 0xC3e, 0x96);
2445                         }
2446                 }
2447                 else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold)
2448                 {
2449                         if(priv->bswitch_fsync)
2450                         {
2451                                 priv->bswitch_fsync  = false;
2452                                 write_nic_byte(priv, 0xC36, 0x5c);
2453                                 write_nic_byte(priv, 0xC3e, 0x96);
2454                         }
2455                 }
2456                 if(bDoubleTimeInterval){
2457                         if(timer_pending(&priv->fsync_timer))
2458                                 del_timer_sync(&priv->fsync_timer);
2459                         priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval);
2460                         add_timer(&priv->fsync_timer);
2461                 }
2462                 else{
2463                         if(timer_pending(&priv->fsync_timer))
2464                                 del_timer_sync(&priv->fsync_timer);
2465                         priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2466                         add_timer(&priv->fsync_timer);
2467                 }
2468         }
2469         else
2470         {
2471                 // Let Register return to default value;
2472                 if(priv->bswitch_fsync)
2473                 {
2474                         priv->bswitch_fsync  = false;
2475                         write_nic_byte(priv, 0xC36, 0x5c);
2476                         write_nic_byte(priv, 0xC3e, 0x96);
2477                 }
2478                 priv->ContiuneDiffCount = 0;
2479                 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2480         }
2481         RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
2482         RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2483 }
2484
2485 static void dm_StartHWFsync(struct net_device *dev)
2486 {
2487         struct r8192_priv *priv = ieee80211_priv(dev);
2488
2489         RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2490         write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cf);
2491         write_nic_byte(priv, 0xc3b, 0x41);
2492 }
2493
2494 static void dm_EndSWFsync(struct net_device *dev)
2495 {
2496         struct r8192_priv *priv = ieee80211_priv(dev);
2497
2498         RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2499         del_timer_sync(&(priv->fsync_timer));
2500
2501         // Let Register return to default value;
2502         if(priv->bswitch_fsync)
2503         {
2504                 priv->bswitch_fsync  = false;
2505
2506                 write_nic_byte(priv, 0xC36, 0x40);
2507
2508                 write_nic_byte(priv, 0xC3e, 0x96);
2509         }
2510
2511         priv->ContiuneDiffCount = 0;
2512
2513         write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2514 }
2515
2516 static void dm_StartSWFsync(struct net_device *dev)
2517 {
2518         struct r8192_priv *priv = ieee80211_priv(dev);
2519         u32                     rateIndex;
2520         u32                     rateBitmap;
2521
2522         RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2523         // Initial rate record to zero, start to record.
2524         priv->rate_record = 0;
2525         // Initial contiune diff count to zero, start to record.
2526         priv->ContiuneDiffCount = 0;
2527         priv->rateCountDiffRecord = 0;
2528         priv->bswitch_fsync  = false;
2529
2530         if(priv->ieee80211->mode == WIRELESS_MODE_N_24G)
2531         {
2532                 priv->ieee80211->fsync_firstdiff_ratethreshold= 600;
2533                 priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff;
2534         }
2535         else
2536         {
2537                 priv->ieee80211->fsync_firstdiff_ratethreshold= 200;
2538                 priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
2539         }
2540         for(rateIndex = 0; rateIndex <= 27; rateIndex++)
2541         {
2542                 rateBitmap  = 1 << rateIndex;
2543                 if(priv->ieee80211->fsync_rate_bitmap &  rateBitmap)
2544                         priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
2545         }
2546         if(timer_pending(&priv->fsync_timer))
2547                 del_timer_sync(&priv->fsync_timer);
2548         priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2549         add_timer(&priv->fsync_timer);
2550
2551         write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cd);
2552 }
2553
2554 static void dm_EndHWFsync(struct net_device *dev)
2555 {
2556         struct r8192_priv *priv = ieee80211_priv(dev);
2557
2558         RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2559         write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2560         write_nic_byte(priv, 0xc3b, 0x49);
2561 }
2562
2563 void dm_check_fsync(struct net_device *dev)
2564 {
2565 #define RegC38_Default                          0
2566 #define RegC38_NonFsync_Other_AP        1
2567 #define RegC38_Fsync_AP_BCM             2
2568         struct r8192_priv *priv = ieee80211_priv(dev);
2569         //u32                   framesyncC34;
2570         static u8               reg_c38_State=RegC38_Default;
2571         static u32      reset_cnt=0;
2572
2573         RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval);
2574         RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold);
2575
2576         if(     priv->ieee80211->state == IEEE80211_LINKED &&
2577                 (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2578         {
2579                 if(priv->ieee80211->bfsync_enable == 0)
2580                 {
2581                         switch(priv->ieee80211->fsync_state)
2582                         {
2583                                 case Default_Fsync:
2584                                         dm_StartHWFsync(dev);
2585                                         priv->ieee80211->fsync_state = HW_Fsync;
2586                                         break;
2587                                 case SW_Fsync:
2588                                         dm_EndSWFsync(dev);
2589                                         dm_StartHWFsync(dev);
2590                                         priv->ieee80211->fsync_state = HW_Fsync;
2591                                         break;
2592                                 case HW_Fsync:
2593                                 default:
2594                                         break;
2595                         }
2596                 }
2597                 else
2598                 {
2599                         switch(priv->ieee80211->fsync_state)
2600                         {
2601                                 case Default_Fsync:
2602                                         dm_StartSWFsync(dev);
2603                                         priv->ieee80211->fsync_state = SW_Fsync;
2604                                         break;
2605                                 case HW_Fsync:
2606                                         dm_EndHWFsync(dev);
2607                                         dm_StartSWFsync(dev);
2608                                         priv->ieee80211->fsync_state = SW_Fsync;
2609                                         break;
2610                                 case SW_Fsync:
2611                                 default:
2612                                         break;
2613
2614                         }
2615                 }
2616                 if(priv->framesyncMonitor)
2617                 {
2618                         if(reg_c38_State != RegC38_Fsync_AP_BCM)
2619                         {       //For broadcom AP we write different default value
2620                                 write_nic_byte(priv, rOFDM0_RxDetector3, 0x95);
2621
2622                                 reg_c38_State = RegC38_Fsync_AP_BCM;
2623                         }
2624                 }
2625         }
2626         else
2627         {
2628                 switch(priv->ieee80211->fsync_state)
2629                 {
2630                         case HW_Fsync:
2631                                 dm_EndHWFsync(dev);
2632                                 priv->ieee80211->fsync_state = Default_Fsync;
2633                                 break;
2634                         case SW_Fsync:
2635                                 dm_EndSWFsync(dev);
2636                                 priv->ieee80211->fsync_state = Default_Fsync;
2637                                 break;
2638                         case Default_Fsync:
2639                         default:
2640                                 break;
2641                 }
2642
2643                 if(priv->framesyncMonitor)
2644                 {
2645                         if(priv->ieee80211->state == IEEE80211_LINKED)
2646                         {
2647                                 if(priv->undecorated_smoothed_pwdb <= RegC38_TH)
2648                                 {
2649                                         if(reg_c38_State != RegC38_NonFsync_Other_AP)
2650                                         {
2651                                                 write_nic_byte(priv, rOFDM0_RxDetector3, 0x90);
2652
2653                                                 reg_c38_State = RegC38_NonFsync_Other_AP;
2654                                         }
2655                                 }
2656                                 else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5))
2657                                 {
2658                                         if(reg_c38_State)
2659                                         {
2660                                                 write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2661                                                 reg_c38_State = RegC38_Default;
2662                                         }
2663                                 }
2664                         }
2665                         else
2666                         {
2667                                 if(reg_c38_State)
2668                                 {
2669                                         write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2670                                         reg_c38_State = RegC38_Default;
2671                                 }
2672                         }
2673                 }
2674         }
2675         if(priv->framesyncMonitor)
2676         {
2677                 if(priv->reset_count != reset_cnt)
2678                 {       //After silent reset, the reg_c38_State will be returned to default value
2679                         write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2680                         reg_c38_State = RegC38_Default;
2681                         reset_cnt = priv->reset_count;
2682                 }
2683         }
2684         else
2685         {
2686                 if(reg_c38_State)
2687                 {
2688                         write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2689                         reg_c38_State = RegC38_Default;
2690                 }
2691         }
2692 }
2693
2694 /*
2695  * Detect Signal strength to control TX Registry
2696  * Tx Power Control For Near/Far Range
2697  */
2698 static void dm_init_dynamic_txpower(struct net_device *dev)
2699 {
2700         struct r8192_priv *priv = ieee80211_priv(dev);
2701
2702         //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
2703         priv->ieee80211->bdynamic_txpower_enable = true;    //Default to enable Tx Power Control
2704         priv->bLastDTPFlag_High = false;
2705         priv->bLastDTPFlag_Low = false;
2706         priv->bDynamicTxHighPower = false;
2707         priv->bDynamicTxLowPower = false;
2708 }
2709
2710 static void dm_dynamic_txpower(struct net_device *dev)
2711 {
2712         struct r8192_priv *priv = ieee80211_priv(dev);
2713         unsigned int txhipower_threshhold=0;
2714         unsigned int txlowpower_threshold=0;
2715         if(priv->ieee80211->bdynamic_txpower_enable != true)
2716         {
2717                 priv->bDynamicTxHighPower = false;
2718                 priv->bDynamicTxLowPower = false;
2719                 return;
2720         }
2721         if((priv->ieee80211->current_network.atheros_cap_exist ) && (priv->ieee80211->mode == IEEE_G)){
2722                 txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
2723                 txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
2724         }
2725         else
2726         {
2727                 txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
2728                 txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
2729         }
2730
2731         RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb);
2732
2733         if(priv->ieee80211->state == IEEE80211_LINKED)
2734         {
2735                 if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold)
2736                 {
2737                         priv->bDynamicTxHighPower = true;
2738                         priv->bDynamicTxLowPower = false;
2739                 }
2740                 else
2741                 {
2742                         // high power state check
2743                         if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true)
2744                         {
2745                                 priv->bDynamicTxHighPower = false;
2746                         }
2747                         // low power state check
2748                         if(priv->undecorated_smoothed_pwdb < 35)
2749                         {
2750                                 priv->bDynamicTxLowPower = true;
2751                         }
2752                         else if(priv->undecorated_smoothed_pwdb >= 40)
2753                         {
2754                                 priv->bDynamicTxLowPower = false;
2755                         }
2756                 }
2757         }
2758         else
2759         {
2760                 //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;
2761                 priv->bDynamicTxHighPower = false;
2762                 priv->bDynamicTxLowPower = false;
2763         }
2764
2765         if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) ||
2766                 (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) )
2767         {
2768                 RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190()  channel = %d \n" , priv->ieee80211->current_network.channel);
2769
2770
2771                 rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel);
2772
2773         }
2774         priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
2775         priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
2776
2777 }
2778
2779 //added by vivi, for read tx rate and retrycount
2780 static void dm_check_txrateandretrycount(struct net_device * dev)
2781 {
2782         struct r8192_priv *priv = ieee80211_priv(dev);
2783         struct ieee80211_device* ieee = priv->ieee80211;
2784         //for initial tx rate
2785         ieee->softmac_stats.last_packet_rate = read_nic_byte(priv ,Initial_Tx_Rate_Reg);
2786         //for tx tx retry count
2787         ieee->softmac_stats.txretrycount = read_nic_dword(priv, Tx_Retry_Count_Reg);
2788 }
2789
2790 static void dm_send_rssi_tofw(struct net_device *dev)
2791 {
2792         struct r8192_priv *priv = ieee80211_priv(dev);
2793
2794         // If we test chariot, we should stop the TX command ?
2795         // Because 92E will always silent reset when we send tx command. We use register
2796         // 0x1e0(byte) to botify driver.
2797         write_nic_byte(priv, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
2798         return;
2799 }
2800