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