These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8712 / rtl871x_mp_ioctl.c
1 /******************************************************************************
2  * rtl871x_mp_ioctl.c
3  *
4  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5  * Linux device driver for RTL8192SU
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * Modifications for inclusion into the Linux staging tree are
21  * Copyright(c) 2010 Larry Finger. All rights reserved.
22  *
23  * Contact information:
24  * WLAN FAE <wlanfae@realtek.com>
25  * Larry Finger <Larry.Finger@lwfinger.net>
26  *
27  ******************************************************************************/
28
29 #include <linux/rndis.h>
30 #include "osdep_service.h"
31 #include "drv_types.h"
32 #include "mlme_osdep.h"
33 #include "rtl871x_mp.h"
34 #include "rtl871x_mp_ioctl.h"
35
36 uint oid_null_function(struct oid_par_priv *poid_par_priv)
37 {
38         return RNDIS_STATUS_SUCCESS;
39 }
40
41 uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
42 {
43         uint status = RNDIS_STATUS_SUCCESS;
44         struct _adapter *Adapter = (struct _adapter *)
45                                    (poid_par_priv->adapter_context);
46
47         if (poid_par_priv->type_of_oid == SET_OID) {
48                 if (poid_par_priv->information_buf_len >= sizeof(u8))
49                         Adapter->registrypriv.wireless_mode =
50                                         *(u8 *)poid_par_priv->information_buf;
51                 else
52                         status = RNDIS_STATUS_INVALID_LENGTH;
53         } else if (poid_par_priv->type_of_oid == QUERY_OID) {
54                 if (poid_par_priv->information_buf_len >= sizeof(u8)) {
55                         *(u8 *)poid_par_priv->information_buf =
56                                          Adapter->registrypriv.wireless_mode;
57                         *poid_par_priv->bytes_rw =
58                                         poid_par_priv->information_buf_len;
59                 } else {
60                         status = RNDIS_STATUS_INVALID_LENGTH;
61                 }
62         } else {
63                 status = RNDIS_STATUS_NOT_ACCEPTED;
64         }
65         return status;
66 }
67
68 uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
69 {
70         struct _adapter *Adapter = (struct _adapter *)
71                                    (poid_par_priv->adapter_context);
72         struct bb_reg_param *pbbreg;
73         u16 offset;
74         u32 value;
75
76         if (poid_par_priv->type_of_oid != SET_OID)
77                 return RNDIS_STATUS_NOT_ACCEPTED;
78         if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
79                 return RNDIS_STATUS_INVALID_LENGTH;
80         pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
81         offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
82         if (offset < BB_REG_BASE_ADDR)
83                 offset |= BB_REG_BASE_ADDR;
84         value = pbbreg->value;
85         r8712_bb_reg_write(Adapter, offset, value);
86         return RNDIS_STATUS_SUCCESS;
87 }
88
89 uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
90 {
91         struct _adapter *Adapter = (struct _adapter *)
92                                    (poid_par_priv->adapter_context);
93         struct bb_reg_param *pbbreg;
94         u16 offset;
95         u32 value;
96
97         if (poid_par_priv->type_of_oid != QUERY_OID)
98                 return RNDIS_STATUS_NOT_ACCEPTED;
99         if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
100                 return RNDIS_STATUS_INVALID_LENGTH;
101         pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
102         offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
103         if (offset < BB_REG_BASE_ADDR)
104                 offset |= BB_REG_BASE_ADDR;
105         value = r8712_bb_reg_read(Adapter, offset);
106         pbbreg->value = value;
107         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
108         return RNDIS_STATUS_SUCCESS;
109 }
110
111 uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
112 {
113         struct _adapter *Adapter = (struct _adapter *)
114                                    (poid_par_priv->adapter_context);
115         struct rf_reg_param *pbbreg;
116         u8 path;
117         u8 offset;
118         u32 value;
119
120         if (poid_par_priv->type_of_oid != SET_OID)
121                 return RNDIS_STATUS_NOT_ACCEPTED;
122         if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
123                 return RNDIS_STATUS_INVALID_LENGTH;
124         pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
125         path = (u8)pbbreg->path;
126         if (path > RF_PATH_B)
127                 return RNDIS_STATUS_NOT_ACCEPTED;
128         offset = (u8)pbbreg->offset;
129         value = pbbreg->value;
130         r8712_rf_reg_write(Adapter, path, offset, value);
131         return RNDIS_STATUS_SUCCESS;
132 }
133
134 uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
135 {
136         struct _adapter *Adapter = (struct _adapter *)
137                                    (poid_par_priv->adapter_context);
138         struct rf_reg_param *pbbreg;
139         u8 path;
140         u8 offset;
141         u32 value;
142
143         if (poid_par_priv->type_of_oid != QUERY_OID)
144                 return RNDIS_STATUS_NOT_ACCEPTED;
145         if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
146                 return RNDIS_STATUS_INVALID_LENGTH;
147         pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
148         path = (u8)pbbreg->path;
149         if (path > RF_PATH_B) /* 1T2R  path_a /path_b */
150                 return RNDIS_STATUS_NOT_ACCEPTED;
151         offset = (u8)pbbreg->offset;
152         value = r8712_rf_reg_read(Adapter, path, offset);
153         pbbreg->value = value;
154         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
155         return RNDIS_STATUS_SUCCESS;
156 }
157
158 /*This function initializes the DUT to the MP test mode*/
159 static int mp_start_test(struct _adapter *padapter)
160 {
161         struct mp_priv *pmppriv = &padapter->mppriv;
162         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
163         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
164         struct wlan_bssid_ex bssid;
165         struct sta_info *psta;
166         unsigned long length;
167         unsigned long irqL;
168         int res = _SUCCESS;
169
170         /* 3 1. initialize a new struct wlan_bssid_ex */
171         memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
172         bssid.Ssid.SsidLength = 16;
173         memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
174                 bssid.Ssid.SsidLength);
175         bssid.InfrastructureMode = Ndis802_11IBSS;
176         bssid.NetworkTypeInUse = Ndis802_11DS;
177         bssid.IELength = 0;
178         length = r8712_get_wlan_bssid_ex_sz(&bssid);
179         if (length % 4) {
180                 /*round up to multiple of 4 bytes.*/
181                 bssid.Length = ((length >> 2) + 1) << 2;
182         } else {
183                 bssid.Length = length;
184         }
185         spin_lock_irqsave(&pmlmepriv->lock, irqL);
186         if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
187                 goto end_of_mp_start_test;
188         /*init mp_start_test status*/
189         pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
190         pmlmepriv->fw_state = WIFI_MP_STATE;
191         if (pmppriv->mode == _LOOPBOOK_MODE_)
192                 set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/
193         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
194         /* 3 2. create a new psta for mp driver */
195         /* clear psta in the cur_network, if any */
196         psta = r8712_get_stainfo(&padapter->stapriv,
197                                  tgt_network->network.MacAddress);
198         if (psta)
199                 r8712_free_stainfo(padapter, psta);
200         psta = r8712_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
201         if (psta == NULL) {
202                 res = _FAIL;
203                 goto end_of_mp_start_test;
204         }
205         /* 3 3. join psudo AdHoc */
206         tgt_network->join_res = 1;
207         tgt_network->aid = psta->aid = 1;
208         memcpy(&tgt_network->network, &bssid, length);
209         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
210         r8712_os_indicate_connect(padapter);
211         /* Set to LINKED STATE for MP TRX Testing */
212         set_fwstate(pmlmepriv, _FW_LINKED);
213 end_of_mp_start_test:
214         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
215         return res;
216 }
217
218 /*This function change the DUT from the MP test mode into normal mode */
219 static int mp_stop_test(struct _adapter *padapter)
220 {
221         struct mp_priv *pmppriv = &padapter->mppriv;
222         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
223         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
224         struct sta_info *psta;
225         unsigned long irqL;
226
227         spin_lock_irqsave(&pmlmepriv->lock, irqL);
228         if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
229                 goto end_of_mp_stop_test;
230         /* 3 1. disconnect psudo AdHoc */
231         r8712_os_indicate_disconnect(padapter);
232         /* 3 2. clear psta used in mp test mode. */
233         psta = r8712_get_stainfo(&padapter->stapriv,
234                                  tgt_network->network.MacAddress);
235         if (psta)
236                 r8712_free_stainfo(padapter, psta);
237         /* 3 3. return to normal state (default:station mode) */
238         pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE;*/
239         /*flush the cur_network*/
240         memset(tgt_network, 0, sizeof(struct wlan_network));
241 end_of_mp_stop_test:
242         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
243         return _SUCCESS;
244 }
245
246 int mp_start_joinbss(struct _adapter *padapter, struct ndis_802_11_ssid *pssid)
247 {
248         struct mp_priv *pmppriv = &padapter->mppriv;
249         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
250         unsigned char res = _SUCCESS;
251
252         if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
253                 return _FAIL;
254         if (!check_fwstate(pmlmepriv, _FW_LINKED))
255                 return _FAIL;
256         _clr_fwstate_(pmlmepriv, _FW_LINKED);
257         res = r8712_setassocsta_cmd(padapter, pmppriv->network_macaddr);
258         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
259         return res;
260 }
261
262 uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv
263                                          *poid_par_priv)
264 {
265         struct _adapter *Adapter = (struct _adapter *)
266                                    (poid_par_priv->adapter_context);
267         u32 ratevalue;
268
269         if (poid_par_priv->type_of_oid != SET_OID)
270                 return RNDIS_STATUS_NOT_ACCEPTED;
271         if (poid_par_priv->information_buf_len != sizeof(u32))
272                 return RNDIS_STATUS_INVALID_LENGTH;
273         ratevalue = *((u32 *)poid_par_priv->information_buf);
274         if (ratevalue >= MPT_RATE_LAST)
275                 return RNDIS_STATUS_INVALID_DATA;
276         Adapter->mppriv.curr_rateidx = ratevalue;
277         r8712_SetDataRate(Adapter);
278         return RNDIS_STATUS_SUCCESS;
279 }
280
281 uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
282 {
283         struct _adapter *Adapter = (struct _adapter *)
284                                    (poid_par_priv->adapter_context);
285         uint status = RNDIS_STATUS_SUCCESS;
286         u32 mode;
287         u8 val8;
288
289         if (poid_par_priv->type_of_oid != SET_OID)
290                 return  RNDIS_STATUS_NOT_ACCEPTED;
291         mode = *((u32 *)poid_par_priv->information_buf);
292         Adapter->mppriv.mode = mode;/* 1 for loopback*/
293         if (mp_start_test(Adapter) == _FAIL)
294                 status = RNDIS_STATUS_NOT_ACCEPTED;
295         r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */
296         r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */
297         /* RCR disable Check BSSID, 0x1025004a */
298         r8712_write8(Adapter, RCR + 2, 0x57);
299         /* disable RX filter map , mgt frames will put in RX FIFO 0 */
300         r8712_write16(Adapter, RXFLTMAP0, 0x0);
301         val8 = r8712_read8(Adapter, EE_9346CR);
302         if (!(val8 & _9356SEL)) { /*boot from EFUSE*/
303                 r8712_efuse_reg_init(Adapter);
304                 r8712_efuse_change_max_size(Adapter);
305                 r8712_efuse_reg_uninit(Adapter);
306         }
307         return status;
308 }
309
310 uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
311 {
312         struct _adapter *Adapter = (struct _adapter *)
313                                    (poid_par_priv->adapter_context);
314         uint status = RNDIS_STATUS_SUCCESS;
315
316         if (poid_par_priv->type_of_oid != SET_OID)
317                 return RNDIS_STATUS_NOT_ACCEPTED;
318         if (mp_stop_test(Adapter) == _FAIL)
319                 status = RNDIS_STATUS_NOT_ACCEPTED;
320         return status;
321 }
322
323 uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv
324                                                    *poid_par_priv)
325 {
326         struct _adapter *Adapter = (struct _adapter *)
327                                    (poid_par_priv->adapter_context);
328         u32             Channel;
329
330         if (poid_par_priv->type_of_oid != SET_OID)
331                 return RNDIS_STATUS_NOT_ACCEPTED;
332         if (poid_par_priv->information_buf_len != sizeof(u32))
333                 return RNDIS_STATUS_INVALID_LENGTH;
334         Channel = *((u32 *)poid_par_priv->information_buf);
335         if (Channel > 14)
336                 return RNDIS_STATUS_NOT_ACCEPTED;
337         Adapter->mppriv.curr_ch = Channel;
338         r8712_SetChannel(Adapter);
339         return RNDIS_STATUS_SUCCESS;
340 }
341
342 uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
343 {
344         struct _adapter *Adapter = (struct _adapter *)
345                                    (poid_par_priv->adapter_context);
346         u32 antenna;
347
348         if (poid_par_priv->type_of_oid != SET_OID)
349                 return RNDIS_STATUS_NOT_ACCEPTED;
350         if (poid_par_priv->information_buf_len != sizeof(u32))
351                 return RNDIS_STATUS_INVALID_LENGTH;
352         antenna = *((u32 *)poid_par_priv->information_buf);
353         Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
354         Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
355         r8712_SwitchAntenna(Adapter);
356         return RNDIS_STATUS_SUCCESS;
357 }
358
359 uint oid_rt_pro_set_tx_power_control_hdl(
360                                         struct oid_par_priv *poid_par_priv)
361 {
362         struct _adapter *Adapter = (struct _adapter *)
363                                    (poid_par_priv->adapter_context);
364         u32 tx_pwr_idx;
365
366         if (poid_par_priv->type_of_oid != SET_OID)
367                 return RNDIS_STATUS_NOT_ACCEPTED;
368         if (poid_par_priv->information_buf_len != sizeof(u32))
369                 return RNDIS_STATUS_INVALID_LENGTH;
370         tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
371         if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
372                 return RNDIS_STATUS_NOT_ACCEPTED;
373         Adapter->mppriv.curr_txpoweridx = (u8)tx_pwr_idx;
374         r8712_SetTxPower(Adapter);
375         return RNDIS_STATUS_SUCCESS;
376 }
377
378 uint oid_rt_pro_query_tx_packet_sent_hdl(
379                                         struct oid_par_priv *poid_par_priv)
380 {
381         uint status = RNDIS_STATUS_SUCCESS;
382         struct _adapter *Adapter = (struct _adapter *)
383                                    (poid_par_priv->adapter_context);
384
385         if (poid_par_priv->type_of_oid != QUERY_OID) {
386                 status = RNDIS_STATUS_NOT_ACCEPTED;
387                 return status;
388         }
389         if (poid_par_priv->information_buf_len == sizeof(u32)) {
390                 *(u32 *)poid_par_priv->information_buf =
391                                         Adapter->mppriv.tx_pktcount;
392                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
393         } else {
394                 status = RNDIS_STATUS_INVALID_LENGTH;
395         }
396         return status;
397 }
398
399 uint oid_rt_pro_query_rx_packet_received_hdl(
400                                         struct oid_par_priv *poid_par_priv)
401 {
402         uint status = RNDIS_STATUS_SUCCESS;
403         struct _adapter *Adapter = (struct _adapter *)
404                                    (poid_par_priv->adapter_context);
405
406         if (poid_par_priv->type_of_oid != QUERY_OID) {
407                 status = RNDIS_STATUS_NOT_ACCEPTED;
408                 return status;
409         }
410         if (poid_par_priv->information_buf_len == sizeof(u32)) {
411                 *(u32 *)poid_par_priv->information_buf =
412                                         Adapter->mppriv.rx_pktcount;
413                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
414         } else {
415                 status = RNDIS_STATUS_INVALID_LENGTH;
416         }
417         return status;
418 }
419
420 uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
421                                         struct oid_par_priv *poid_par_priv)
422 {
423         uint status = RNDIS_STATUS_SUCCESS;
424         struct _adapter *Adapter = (struct _adapter *)
425                                    (poid_par_priv->adapter_context);
426
427         if (poid_par_priv->type_of_oid != QUERY_OID) {
428                 status = RNDIS_STATUS_NOT_ACCEPTED;
429                 return status;
430         }
431         if (poid_par_priv->information_buf_len == sizeof(u32)) {
432                 *(u32 *)poid_par_priv->information_buf =
433                                         Adapter->mppriv.rx_crcerrpktcount;
434                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
435         } else {
436                 status = RNDIS_STATUS_INVALID_LENGTH;
437         }
438         return status;
439 }
440
441 uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv
442                                                 *poid_par_priv)
443 {
444         struct _adapter *Adapter = (struct _adapter *)
445                                    (poid_par_priv->adapter_context);
446
447         if (poid_par_priv->type_of_oid != SET_OID)
448                 return RNDIS_STATUS_NOT_ACCEPTED;
449         Adapter->mppriv.tx_pktcount = 0;
450         return RNDIS_STATUS_SUCCESS;
451 }
452
453 uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv
454                                                     *poid_par_priv)
455 {
456         uint status = RNDIS_STATUS_SUCCESS;
457         struct _adapter *Adapter = (struct _adapter *)
458                                    (poid_par_priv->adapter_context);
459
460         if (poid_par_priv->type_of_oid != SET_OID)
461                 return RNDIS_STATUS_NOT_ACCEPTED;
462         if (poid_par_priv->information_buf_len == sizeof(u32)) {
463                 Adapter->mppriv.rx_pktcount = 0;
464                 Adapter->mppriv.rx_crcerrpktcount = 0;
465         } else {
466                 status = RNDIS_STATUS_INVALID_LENGTH;
467         }
468         return status;
469 }
470
471 uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv
472                                                  *poid_par_priv)
473 {
474         struct _adapter *Adapter = (struct _adapter *)
475                                    (poid_par_priv->adapter_context);
476
477         if (poid_par_priv->type_of_oid != SET_OID)
478                 return RNDIS_STATUS_NOT_ACCEPTED;
479         r8712_ResetPhyRxPktCount(Adapter);
480         return RNDIS_STATUS_SUCCESS;
481 }
482
483 uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv
484                                                   *poid_par_priv)
485 {
486         struct _adapter *Adapter = (struct _adapter *)
487                                    (poid_par_priv->adapter_context);
488
489         if (poid_par_priv->type_of_oid != QUERY_OID)
490                 return RNDIS_STATUS_NOT_ACCEPTED;
491         if (poid_par_priv->information_buf_len != sizeof(u32))
492                 return RNDIS_STATUS_INVALID_LENGTH;
493         *(u32 *)poid_par_priv->information_buf =
494                                          r8712_GetPhyRxPktReceived(Adapter);
495         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
496         return RNDIS_STATUS_SUCCESS;
497 }
498
499 uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv
500                                                      *poid_par_priv)
501 {
502         struct _adapter *Adapter = (struct _adapter *)
503                                    (poid_par_priv->adapter_context);
504
505         if (poid_par_priv->type_of_oid != QUERY_OID)
506                 return RNDIS_STATUS_NOT_ACCEPTED;
507         if (poid_par_priv->information_buf_len != sizeof(u32))
508                 return RNDIS_STATUS_INVALID_LENGTH;
509         *(u32 *)poid_par_priv->information_buf =
510                                          r8712_GetPhyRxPktCRC32Error(Adapter);
511         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
512         return RNDIS_STATUS_SUCCESS;
513 }
514
515 uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv
516                                           *poid_par_priv)
517 {
518         struct _adapter *Adapter = (struct _adapter *)
519                                    (poid_par_priv->adapter_context);
520
521         if (poid_par_priv->type_of_oid != SET_OID)
522                 return RNDIS_STATUS_NOT_ACCEPTED;
523
524         Adapter->mppriv.curr_modem = *((u8 *)poid_par_priv->information_buf);
525         return RNDIS_STATUS_SUCCESS;
526 }
527
528 uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv
529                                              *poid_par_priv)
530 {
531         struct _adapter *Adapter = (struct _adapter *)
532                                    (poid_par_priv->adapter_context);
533         u32             bStartTest;
534
535         if (poid_par_priv->type_of_oid != SET_OID)
536                 return RNDIS_STATUS_NOT_ACCEPTED;
537         bStartTest = *((u32 *)poid_par_priv->information_buf);
538         r8712_SetContinuousTx(Adapter, (u8)bStartTest);
539         return RNDIS_STATUS_SUCCESS;
540 }
541
542 uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv
543                                                  *poid_par_priv)
544 {
545         struct _adapter *Adapter = (struct _adapter *)
546                                    (poid_par_priv->adapter_context);
547         u32             bStartTest;
548
549         if (poid_par_priv->type_of_oid != SET_OID)
550                 return RNDIS_STATUS_NOT_ACCEPTED;
551         bStartTest = *((u32 *)poid_par_priv->information_buf);
552         r8712_SetSingleCarrierTx(Adapter, (u8)bStartTest);
553         return RNDIS_STATUS_SUCCESS;
554 }
555
556 uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv
557                                                       *poid_par_priv)
558 {
559         struct _adapter *Adapter = (struct _adapter *)
560                                    (poid_par_priv->adapter_context);
561         u32             bStartTest;
562
563         if (poid_par_priv->type_of_oid != SET_OID)
564                 return RNDIS_STATUS_NOT_ACCEPTED;
565         bStartTest = *((u32 *)poid_par_priv->information_buf);
566         r8712_SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
567         return RNDIS_STATUS_SUCCESS;
568 }
569
570 uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv
571                                               *poid_par_priv)
572 {
573         struct _adapter *Adapter = (struct _adapter *)
574                                    (poid_par_priv->adapter_context);
575         u32             bStartTest;
576
577         if (poid_par_priv->type_of_oid != SET_OID)
578                 return RNDIS_STATUS_NOT_ACCEPTED;
579         bStartTest = *((u32 *)poid_par_priv->information_buf);
580         r8712_SetSingleToneTx(Adapter, (u8)bStartTest);
581         return RNDIS_STATUS_SUCCESS;
582 }
583
584 uint oid_rt_pro_read_register_hdl(struct oid_par_priv
585                                          *poid_par_priv)
586 {
587         struct _adapter *Adapter = (struct _adapter *)
588                                    (poid_par_priv->adapter_context);
589         uint status = RNDIS_STATUS_SUCCESS;
590         struct mp_rw_reg *RegRWStruct;
591         u16             offset;
592
593         if (poid_par_priv->type_of_oid != QUERY_OID)
594                 return RNDIS_STATUS_NOT_ACCEPTED;
595         RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
596         if ((RegRWStruct->offset >= 0x10250800) &&
597             (RegRWStruct->offset <= 0x10250FFF)) {
598                 /*baseband register*/
599                 /*0ffset :0x800~0xfff*/
600                 offset = (u16)(RegRWStruct->offset) & 0xFFF;
601                 RegRWStruct->value = r8712_bb_reg_read(Adapter, offset);
602         } else {
603                 switch (RegRWStruct->width) {
604                 case 1:
605                         RegRWStruct->value = r8712_read8(Adapter,
606                                                    RegRWStruct->offset);
607                         break;
608                 case 2:
609                         RegRWStruct->value = r8712_read16(Adapter,
610                                                     RegRWStruct->offset);
611                         break;
612                 case 4:
613                         RegRWStruct->value = r8712_read32(Adapter,
614                                                     RegRWStruct->offset);
615                         break;
616                 default:
617                         status = RNDIS_STATUS_NOT_ACCEPTED;
618                         break;
619                 }
620         }
621         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
622         return status;
623 }
624
625 uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
626 {
627         struct _adapter *Adapter = (struct _adapter *)
628                                    (poid_par_priv->adapter_context);
629         uint status = RNDIS_STATUS_SUCCESS;
630         struct mp_rw_reg *RegRWStruct;
631         u16             offset;
632         u32             value;
633         u32 oldValue = 0;
634
635         if (poid_par_priv->type_of_oid != SET_OID)
636                 return RNDIS_STATUS_NOT_ACCEPTED;
637         RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
638         if ((RegRWStruct->offset >= 0x10250800) &&
639             (RegRWStruct->offset <= 0x10250FFF)) {
640                 /*baseband register*/
641                 offset = (u16)(RegRWStruct->offset) & 0xFFF;
642                 value = RegRWStruct->value;
643                 switch (RegRWStruct->width) {
644                 case 1:
645                         oldValue = r8712_bb_reg_read(Adapter, offset);
646                         oldValue &= 0xFFFFFF00;
647                         value &= 0x000000FF;
648                         value |= oldValue;
649                         break;
650                 case 2:
651                         oldValue = r8712_bb_reg_read(Adapter, offset);
652                         oldValue &= 0xFFFF0000;
653                         value &= 0x0000FFFF;
654                         value |= oldValue;
655                         break;
656                 }
657                 r8712_bb_reg_write(Adapter, offset, value);
658         } else {
659                 switch (RegRWStruct->width) {
660                 case 1:
661                         r8712_write8(Adapter, RegRWStruct->offset,
662                                (unsigned char)RegRWStruct->value);
663                         break;
664                 case 2:
665                         r8712_write16(Adapter, RegRWStruct->offset,
666                                 (unsigned short)RegRWStruct->value);
667                         break;
668                 case 4:
669                         r8712_write32(Adapter, RegRWStruct->offset,
670                                 (unsigned int)RegRWStruct->value);
671                         break;
672                 default:
673                         status = RNDIS_STATUS_NOT_ACCEPTED;
674                         break;
675                 }
676
677                 if ((status == RNDIS_STATUS_SUCCESS) &&
678                     (RegRWStruct->offset == HIMR) &&
679                     (RegRWStruct->width == 4))
680                         Adapter->ImrContent = RegRWStruct->value;
681         }
682         return status;
683 }
684
685 uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
686 {
687         struct _adapter *Adapter = (struct _adapter *)
688                                    (poid_par_priv->adapter_context);
689
690         if (poid_par_priv->type_of_oid != QUERY_OID)
691                 return RNDIS_STATUS_NOT_ACCEPTED;
692
693         if (Adapter->mppriv.act_in_progress)
694                 return RNDIS_STATUS_NOT_ACCEPTED;
695
696         if (poid_par_priv->information_buf_len < sizeof(u8))
697                 return RNDIS_STATUS_INVALID_LENGTH;
698         /*init workparam*/
699         Adapter->mppriv.act_in_progress = true;
700         Adapter->mppriv.workparam.bcompleted = false;
701         Adapter->mppriv.workparam.act_type = MPT_GET_THERMAL_METER;
702         Adapter->mppriv.workparam.io_offset = 0;
703         Adapter->mppriv.workparam.io_value = 0xFFFFFFFF;
704         r8712_GetThermalMeter(Adapter, &Adapter->mppriv.workparam.io_value);
705         Adapter->mppriv.workparam.bcompleted = true;
706         Adapter->mppriv.act_in_progress = false;
707         *(u32 *)poid_par_priv->information_buf =
708                                  Adapter->mppriv.workparam.io_value;
709         *poid_par_priv->bytes_rw = sizeof(u32);
710         return RNDIS_STATUS_SUCCESS;
711 }
712
713 uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
714 {
715         struct _adapter *Adapter = (struct _adapter *)
716                                    (poid_par_priv->adapter_context);
717
718         uint status = RNDIS_STATUS_SUCCESS;
719
720         struct EFUSE_ACCESS_STRUCT *pefuse;
721         u8 *data;
722         u16 addr = 0, cnts = 0;
723
724         if (poid_par_priv->type_of_oid != QUERY_OID)
725                 return RNDIS_STATUS_NOT_ACCEPTED;
726         if (poid_par_priv->information_buf_len <
727             sizeof(struct EFUSE_ACCESS_STRUCT))
728                 return RNDIS_STATUS_INVALID_LENGTH;
729         pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
730         addr = pefuse->start_addr;
731         cnts = pefuse->cnts;
732         data = pefuse->data;
733         memset(data, 0xFF, cnts);
734         if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) >
735              EFUSE_MAX_SIZE)
736                 return RNDIS_STATUS_NOT_ACCEPTED;
737         if (!r8712_efuse_access(Adapter, true, addr, cnts, data))
738                 status = RNDIS_STATUS_FAILURE;
739         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
740         return status;
741 }
742 /*------------------------------------------------------------------------*/
743 uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
744 {
745         struct _adapter *Adapter = (struct _adapter *)
746                                    (poid_par_priv->adapter_context);
747
748         uint status = RNDIS_STATUS_SUCCESS;
749
750         struct EFUSE_ACCESS_STRUCT *pefuse;
751         u8 *data;
752         u16 addr = 0, cnts = 0;
753
754         if (poid_par_priv->type_of_oid != SET_OID)
755                 return RNDIS_STATUS_NOT_ACCEPTED;
756
757         pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
758         addr = pefuse->start_addr;
759         cnts = pefuse->cnts;
760         data = pefuse->data;
761
762         if ((addr > 511) || (cnts < 1) || (cnts > 512) ||
763             (addr + cnts) > r8712_efuse_get_max_size(Adapter))
764                 return RNDIS_STATUS_NOT_ACCEPTED;
765         if (!r8712_efuse_access(Adapter, false, addr, cnts, data))
766                 status = RNDIS_STATUS_FAILURE;
767         return status;
768 }
769 /*----------------------------------------------------------------------*/
770
771 uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv
772                                               *poid_par_priv)
773 {
774         struct _adapter *Adapter = (struct _adapter *)
775                                    (poid_par_priv->adapter_context);
776
777         if (poid_par_priv->type_of_oid != QUERY_OID)
778                 return RNDIS_STATUS_NOT_ACCEPTED;
779         if (poid_par_priv->information_buf_len < sizeof(int))
780                 return RNDIS_STATUS_INVALID_LENGTH;
781         r8712_efuse_reg_init(Adapter);
782         *(int *)poid_par_priv->information_buf =
783                                  r8712_efuse_get_current_size(Adapter);
784         r8712_efuse_reg_uninit(Adapter);
785         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
786         return RNDIS_STATUS_SUCCESS;
787 }
788
789 uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
790 {
791         struct _adapter *Adapter = (struct _adapter *)
792                                    (poid_par_priv->adapter_context);
793
794         if (poid_par_priv->type_of_oid != QUERY_OID)
795                 return RNDIS_STATUS_NOT_ACCEPTED;
796         if (poid_par_priv->information_buf_len < sizeof(u32))
797                 return RNDIS_STATUS_INVALID_LENGTH;
798         *(int *)poid_par_priv->information_buf =
799                                          r8712_efuse_get_max_size(Adapter);
800         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
801         return RNDIS_STATUS_SUCCESS;
802 }
803
804 uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
805 {
806         uint status = RNDIS_STATUS_SUCCESS;
807
808         if (poid_par_priv->type_of_oid == QUERY_OID)
809                 status = oid_rt_pro_read_efuse_hdl(poid_par_priv);
810         else
811                 status = oid_rt_pro_write_efuse_hdl(poid_par_priv);
812         return status;
813 }
814
815 uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
816 {
817         struct _adapter *Adapter = (struct _adapter *)
818                                    (poid_par_priv->adapter_context);
819         uint status = RNDIS_STATUS_SUCCESS;
820         u8              *data;
821
822         *poid_par_priv->bytes_rw = 0;
823         if (poid_par_priv->information_buf_len < EFUSE_MAP_MAX_SIZE)
824                 return RNDIS_STATUS_INVALID_LENGTH;
825         data = (u8 *)poid_par_priv->information_buf;
826         if (poid_par_priv->type_of_oid == QUERY_OID) {
827                 if (r8712_efuse_map_read(Adapter, 0, EFUSE_MAP_MAX_SIZE, data))
828                         *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
829                 else
830                         status = RNDIS_STATUS_FAILURE;
831         } else {
832                 /* SET_OID */
833                 if (r8712_efuse_reg_init(Adapter)) {
834                         if (r8712_efuse_map_write(Adapter, 0,
835                             EFUSE_MAP_MAX_SIZE, data))
836                                 *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
837                         else
838                                 status = RNDIS_STATUS_FAILURE;
839                         r8712_efuse_reg_uninit(Adapter);
840                 } else {
841                         status = RNDIS_STATUS_FAILURE;
842                 }
843         }
844         return status;
845 }
846
847 uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
848 {
849         struct _adapter *Adapter = (struct _adapter *)
850                                    (poid_par_priv->adapter_context);
851         u32             bandwidth;
852
853         if (poid_par_priv->type_of_oid != SET_OID)
854                 return RNDIS_STATUS_NOT_ACCEPTED;
855         if (poid_par_priv->information_buf_len < sizeof(u32))
856                 return RNDIS_STATUS_INVALID_LENGTH;
857         bandwidth = *((u32 *)poid_par_priv->information_buf);/*4*/
858         if (bandwidth != HT_CHANNEL_WIDTH_20)
859                 bandwidth = HT_CHANNEL_WIDTH_40;
860         Adapter->mppriv.curr_bandwidth = (u8)bandwidth;
861         r8712_SwitchBandwidth(Adapter);
862         return RNDIS_STATUS_SUCCESS;
863 }
864
865 uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv
866                                            *poid_par_priv)
867 {
868         struct _adapter *Adapter = (struct _adapter *)
869                                    (poid_par_priv->adapter_context);
870         u8              rx_pkt_type;
871         u32             rcr_val32;
872
873         if (poid_par_priv->type_of_oid != SET_OID)
874                 return RNDIS_STATUS_NOT_ACCEPTED;
875         if (poid_par_priv->information_buf_len < sizeof(u8))
876                 return RNDIS_STATUS_INVALID_LENGTH;
877         rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/*4*/
878         rcr_val32 = r8712_read32(Adapter, RCR);/*RCR = 0x10250048*/
879         rcr_val32 &= ~(RCR_CBSSID | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
880         switch (rx_pkt_type) {
881         case RX_PKT_BROADCAST:
882                 rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
883                 break;
884         case RX_PKT_DEST_ADDR:
885                 rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
886                 break;
887         case RX_PKT_PHY_MATCH:
888                 rcr_val32 |= (RCR_APM | RCR_ACRC32);
889                 break;
890         default:
891                 rcr_val32 &= ~(RCR_AAP |
892                                RCR_APM |
893                                RCR_AM |
894                                RCR_AB |
895                                RCR_ACRC32);
896                 break;
897         }
898         if (rx_pkt_type == RX_PKT_DEST_ADDR)
899                 Adapter->mppriv.check_mp_pkt = 1;
900         else
901                 Adapter->mppriv.check_mp_pkt = 0;
902         r8712_write32(Adapter, RCR, rcr_val32);
903         return RNDIS_STATUS_SUCCESS;
904 }
905
906 /*--------------------------------------------------------------------------*/
907 /*Linux*/
908 unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
909 {
910         return _SUCCESS;
911 }
912 /*-------------------------------------------------------------------------*/
913 uint oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
914 {
915         if (poid_par_priv->type_of_oid != SET_OID)
916                 return RNDIS_STATUS_NOT_ACCEPTED;
917         /*CALL  the power_down function*/
918         return RNDIS_STATUS_SUCCESS;
919 }
920
921 /*-------------------------------------------------------------------------- */
922 uint oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
923 {
924         struct _adapter *Adapter = (struct _adapter *)
925                                    (poid_par_priv->adapter_context);
926
927         if (poid_par_priv->type_of_oid != QUERY_OID)
928                 return RNDIS_STATUS_NOT_ACCEPTED;
929         if (poid_par_priv->information_buf_len < sizeof(u32))
930                 return RNDIS_STATUS_INVALID_LENGTH;
931         *(int *)poid_par_priv->information_buf =
932                  Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL;
933         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
934         return RNDIS_STATUS_SUCCESS;
935 }