Commit | Line | Data |
---|---|---|
7b464c9f LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | *published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * | |
19 | ******************************************************************************/ | |
20 | #define _RTW_MP_C_ | |
21 | ||
22 | #include <drv_types.h> | |
23 | ||
24 | #include "odm_precomp.h" | |
25 | #include "rtl8188e_hal.h" | |
26 | ||
27 | u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz) | |
28 | { | |
29 | u32 val = 0; | |
30 | ||
31 | switch (sz) { | |
32 | case 1: | |
33 | val = rtw_read8(padapter, addr); | |
34 | break; | |
35 | case 2: | |
36 | val = rtw_read16(padapter, addr); | |
37 | break; | |
38 | case 4: | |
39 | val = rtw_read32(padapter, addr); | |
40 | break; | |
41 | default: | |
42 | val = 0xffffffff; | |
43 | break; | |
44 | } | |
45 | ||
46 | return val; | |
47 | } | |
48 | ||
49 | void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz) | |
50 | { | |
51 | switch (sz) { | |
52 | case 1: | |
53 | rtw_write8(padapter, addr, (u8)val); | |
54 | break; | |
55 | case 2: | |
56 | rtw_write16(padapter, addr, (u16)val); | |
57 | break; | |
58 | case 4: | |
59 | rtw_write32(padapter, addr, val); | |
60 | break; | |
61 | default: | |
62 | break; | |
63 | } | |
64 | } | |
65 | ||
66 | u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask) | |
67 | { | |
68 | return rtw_hal_read_bbreg(padapter, addr, bitmask); | |
69 | } | |
70 | ||
71 | void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val) | |
72 | { | |
73 | rtw_hal_write_bbreg(padapter, addr, bitmask, val); | |
74 | } | |
75 | ||
76 | u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask) | |
77 | { | |
78 | return rtw_hal_read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask); | |
79 | } | |
80 | ||
81 | void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val) | |
82 | { | |
83 | rtw_hal_write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bitmask, val); | |
84 | } | |
85 | ||
86 | u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr) | |
87 | { | |
88 | return _read_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask); | |
89 | } | |
90 | ||
91 | void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val) | |
92 | { | |
93 | _write_rfreg(padapter, (enum rf_radio_path)rfpath, addr, bRFRegOffsetMask, val); | |
94 | } | |
95 | ||
96 | static void _init_mp_priv_(struct mp_priv *pmp_priv) | |
97 | { | |
98 | struct wlan_bssid_ex *pnetwork; | |
99 | ||
100 | _rtw_memset(pmp_priv, 0, sizeof(struct mp_priv)); | |
101 | ||
102 | pmp_priv->mode = MP_OFF; | |
103 | ||
104 | pmp_priv->channel = 1; | |
105 | pmp_priv->bandwidth = HT_CHANNEL_WIDTH_20; | |
106 | pmp_priv->prime_channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; | |
107 | pmp_priv->rateidx = MPT_RATE_1M; | |
108 | pmp_priv->txpoweridx = 0x2A; | |
109 | ||
110 | pmp_priv->antenna_tx = ANTENNA_A; | |
111 | pmp_priv->antenna_rx = ANTENNA_AB; | |
112 | ||
113 | pmp_priv->check_mp_pkt = 0; | |
114 | ||
115 | pmp_priv->tx_pktcount = 0; | |
116 | ||
117 | pmp_priv->rx_pktcount = 0; | |
118 | pmp_priv->rx_crcerrpktcount = 0; | |
119 | ||
120 | pmp_priv->network_macaddr[0] = 0x00; | |
121 | pmp_priv->network_macaddr[1] = 0xE0; | |
122 | pmp_priv->network_macaddr[2] = 0x4C; | |
123 | pmp_priv->network_macaddr[3] = 0x87; | |
124 | pmp_priv->network_macaddr[4] = 0x66; | |
125 | pmp_priv->network_macaddr[5] = 0x55; | |
126 | ||
127 | pnetwork = &pmp_priv->mp_network.network; | |
128 | memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN); | |
129 | ||
130 | pnetwork->Ssid.SsidLength = 8; | |
131 | memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength); | |
132 | } | |
133 | ||
134 | static void mp_init_xmit_attrib(struct mp_tx *pmptx, struct adapter *padapter) | |
135 | { | |
136 | struct pkt_attrib *pattrib; | |
137 | struct tx_desc *desc; | |
138 | ||
139 | /* init xmitframe attribute */ | |
140 | pattrib = &pmptx->attrib; | |
141 | _rtw_memset(pattrib, 0, sizeof(struct pkt_attrib)); | |
142 | desc = &pmptx->desc; | |
143 | _rtw_memset(desc, 0, TXDESC_SIZE); | |
144 | ||
145 | pattrib->ether_type = 0x8712; | |
146 | _rtw_memset(pattrib->dst, 0xFF, ETH_ALEN); | |
147 | pattrib->ack_policy = 0; | |
148 | pattrib->hdrlen = WLAN_HDR_A3_LEN; | |
149 | pattrib->subtype = WIFI_DATA; | |
150 | pattrib->priority = 0; | |
151 | pattrib->qsel = pattrib->priority; | |
152 | pattrib->nr_frags = 1; | |
153 | pattrib->encrypt = 0; | |
154 | pattrib->bswenc = false; | |
155 | pattrib->qos_en = false; | |
156 | } | |
157 | ||
158 | s32 init_mp_priv(struct adapter *padapter) | |
159 | { | |
160 | struct mp_priv *pmppriv = &padapter->mppriv; | |
161 | ||
162 | _init_mp_priv_(pmppriv); | |
163 | pmppriv->papdater = padapter; | |
164 | ||
165 | pmppriv->tx.stop = 1; | |
166 | mp_init_xmit_attrib(&pmppriv->tx, padapter); | |
167 | ||
168 | switch (padapter->registrypriv.rf_config) { | |
169 | case RF_1T1R: | |
170 | pmppriv->antenna_tx = ANTENNA_A; | |
171 | pmppriv->antenna_rx = ANTENNA_A; | |
172 | break; | |
173 | case RF_1T2R: | |
174 | default: | |
175 | pmppriv->antenna_tx = ANTENNA_A; | |
176 | pmppriv->antenna_rx = ANTENNA_AB; | |
177 | break; | |
178 | case RF_2T2R: | |
179 | case RF_2T2R_GREEN: | |
180 | pmppriv->antenna_tx = ANTENNA_AB; | |
181 | pmppriv->antenna_rx = ANTENNA_AB; | |
182 | break; | |
183 | case RF_2T4R: | |
184 | pmppriv->antenna_tx = ANTENNA_AB; | |
185 | pmppriv->antenna_rx = ANTENNA_ABCD; | |
186 | break; | |
187 | } | |
188 | ||
189 | return _SUCCESS; | |
190 | } | |
191 | ||
192 | void free_mp_priv(struct mp_priv *pmp_priv) | |
193 | { | |
194 | kfree(pmp_priv->pallocated_mp_xmitframe_buf); | |
195 | pmp_priv->pallocated_mp_xmitframe_buf = NULL; | |
196 | pmp_priv->pmp_xmtframe_buf = NULL; | |
197 | } | |
198 | ||
199 | #define PHY_IQCalibrate(a, b) PHY_IQCalibrate_8188E(a, b) | |
200 | #define PHY_LCCalibrate(a) PHY_LCCalibrate_8188E(a) | |
201 | #define PHY_SetRFPathSwitch(a, b) PHY_SetRFPathSwitch_8188E(a, b) | |
202 | ||
203 | s32 MPT_InitializeAdapter(struct adapter *pAdapter, u8 Channel) | |
204 | { | |
205 | struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); | |
206 | s32 rtStatus = _SUCCESS; | |
207 | struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx; | |
208 | struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; | |
209 | ||
210 | /* HW Initialization for 8190 MPT. */ | |
211 | /* SW Initialization for 8190 MP. */ | |
212 | pMptCtx->bMptDrvUnload = false; | |
213 | pMptCtx->bMassProdTest = false; | |
214 | pMptCtx->bMptIndexEven = true; /* default gain index is -6.0db */ | |
215 | pMptCtx->h2cReqNum = 0x0; | |
216 | /* Init mpt event. */ | |
217 | /* init for BT MP */ | |
218 | ||
219 | pMptCtx->bMptWorkItemInProgress = false; | |
220 | pMptCtx->CurrMptAct = NULL; | |
221 | /* */ | |
222 | ||
223 | /* Don't accept any packets */ | |
224 | rtw_write32(pAdapter, REG_RCR, 0); | |
225 | ||
226 | PHY_IQCalibrate(pAdapter, false); | |
227 | dm_CheckTXPowerTracking(&pHalData->odmpriv); /* trigger thermal meter */ | |
228 | PHY_LCCalibrate(pAdapter); | |
229 | ||
230 | pMptCtx->backup0xc50 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XAAGCCore1, bMaskByte0); | |
231 | pMptCtx->backup0xc58 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_XBAGCCore1, bMaskByte0); | |
232 | pMptCtx->backup0xc30 = (u8)PHY_QueryBBReg(pAdapter, rOFDM0_RxDetector1, bMaskByte0); | |
233 | pMptCtx->backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0); | |
234 | pMptCtx->backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0); | |
235 | ||
236 | /* set ant to wifi side in mp mode */ | |
237 | rtw_write16(pAdapter, 0x870, 0x300); | |
238 | rtw_write16(pAdapter, 0x860, 0x110); | |
239 | ||
240 | if (pAdapter->registrypriv.mp_mode == 1) | |
241 | pmlmepriv->fw_state = WIFI_MP_STATE; | |
242 | ||
243 | return rtStatus; | |
244 | } | |
245 | ||
246 | /*----------------------------------------------------------------------------- | |
247 | * Function: MPT_DeInitAdapter() | |
248 | * | |
249 | * Overview: Extra DeInitialization for Mass Production Test. | |
250 | * | |
251 | * Input: struct adapter * pAdapter | |
252 | * | |
253 | * Output: NONE | |
254 | * | |
255 | * Return: NONE | |
256 | * | |
257 | * Revised History: | |
258 | * When Who Remark | |
259 | * 05/08/2007 MHC Create Version 0. | |
260 | * 05/18/2007 MHC Add normal driver MPHalt code. | |
261 | * | |
262 | *---------------------------------------------------------------------------*/ | |
263 | void MPT_DeInitAdapter(struct adapter *pAdapter) | |
264 | { | |
265 | struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx; | |
266 | ||
267 | pMptCtx->bMptDrvUnload = true; | |
268 | } | |
269 | ||
270 | static u8 mpt_ProStartTest(struct adapter *padapter) | |
271 | { | |
272 | struct mpt_context *pMptCtx = &padapter->mppriv.MptCtx; | |
273 | ||
274 | pMptCtx->bMassProdTest = true; | |
275 | pMptCtx->bStartContTx = false; | |
276 | pMptCtx->bCckContTx = false; | |
277 | pMptCtx->bOfdmContTx = false; | |
278 | pMptCtx->bSingleCarrier = false; | |
279 | pMptCtx->bCarrierSuppression = false; | |
280 | pMptCtx->bSingleTone = false; | |
281 | ||
282 | return _SUCCESS; | |
283 | } | |
284 | ||
285 | /* | |
286 | * General use | |
287 | */ | |
288 | s32 SetPowerTracking(struct adapter *padapter, u8 enable) | |
289 | { | |
290 | Hal_SetPowerTracking(padapter, enable); | |
291 | return 0; | |
292 | } | |
293 | ||
294 | void GetPowerTracking(struct adapter *padapter, u8 *enable) | |
295 | { | |
296 | Hal_GetPowerTracking(padapter, enable); | |
297 | } | |
298 | ||
299 | static void disable_dm(struct adapter *padapter) | |
300 | { | |
301 | u8 v8; | |
302 | ||
303 | /* 3 1. disable firmware dynamic mechanism */ | |
304 | /* disable Power Training, Rate Adaptive */ | |
305 | v8 = rtw_read8(padapter, REG_BCN_CTRL); | |
306 | v8 &= ~EN_BCN_FUNCTION; | |
307 | rtw_write8(padapter, REG_BCN_CTRL, v8); | |
308 | ||
309 | /* 3 2. disable driver dynamic mechanism */ | |
310 | /* disable Dynamic Initial Gain */ | |
311 | /* disable High Power */ | |
312 | /* disable Power Tracking */ | |
313 | Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); | |
314 | ||
315 | /* enable APK, LCK and IQK but disable power tracking */ | |
316 | Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, true); | |
317 | } | |
318 | ||
319 | /* This function initializes the DUT to the MP test mode */ | |
320 | s32 mp_start_test(struct adapter *padapter) | |
321 | { | |
322 | struct wlan_bssid_ex bssid; | |
323 | struct sta_info *psta; | |
324 | u32 length; | |
325 | u8 val8; | |
326 | ||
327 | unsigned long irqL; | |
328 | s32 res = _SUCCESS; | |
329 | ||
330 | struct mp_priv *pmppriv = &padapter->mppriv; | |
331 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
332 | struct wlan_network *tgt_network = &pmlmepriv->cur_network; | |
333 | ||
334 | padapter->registrypriv.mp_mode = 1; | |
335 | pmppriv->bSetTxPower = 0; /* for manually set tx power */ | |
336 | ||
337 | /* 3 disable dynamic mechanism */ | |
338 | disable_dm(padapter); | |
339 | ||
340 | /* 3 0. update mp_priv */ | |
341 | ||
342 | if (padapter->registrypriv.rf_config == RF_819X_MAX_TYPE) { | |
343 | switch (GET_RF_TYPE(padapter)) { | |
344 | case RF_1T1R: | |
345 | pmppriv->antenna_tx = ANTENNA_A; | |
346 | pmppriv->antenna_rx = ANTENNA_A; | |
347 | break; | |
348 | case RF_1T2R: | |
349 | default: | |
350 | pmppriv->antenna_tx = ANTENNA_A; | |
351 | pmppriv->antenna_rx = ANTENNA_AB; | |
352 | break; | |
353 | case RF_2T2R: | |
354 | case RF_2T2R_GREEN: | |
355 | pmppriv->antenna_tx = ANTENNA_AB; | |
356 | pmppriv->antenna_rx = ANTENNA_AB; | |
357 | break; | |
358 | case RF_2T4R: | |
359 | pmppriv->antenna_tx = ANTENNA_AB; | |
360 | pmppriv->antenna_rx = ANTENNA_ABCD; | |
361 | break; | |
362 | } | |
363 | } | |
364 | ||
365 | mpt_ProStartTest(padapter); | |
366 | ||
367 | /* 3 1. initialize a new struct wlan_bssid_ex */ | |
368 | /* _rtw_memset(&bssid, 0, sizeof(struct wlan_bssid_ex)); */ | |
369 | memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN); | |
370 | bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc"); | |
371 | memcpy(bssid.Ssid.Ssid, (u8 *)"mp_pseudo_adhoc", bssid.Ssid.SsidLength); | |
372 | bssid.InfrastructureMode = Ndis802_11IBSS; | |
373 | bssid.NetworkTypeInUse = Ndis802_11DS; | |
374 | bssid.IELength = 0; | |
375 | ||
376 | length = get_wlan_bssid_ex_sz(&bssid); | |
377 | if (length % 4) | |
378 | bssid.Length = ((length >> 2) + 1) << 2; /* round up to multiple of 4 bytes. */ | |
379 | else | |
380 | bssid.Length = length; | |
381 | ||
382 | _enter_critical_bh(&pmlmepriv->lock, &irqL); | |
383 | ||
384 | if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) | |
385 | goto end_of_mp_start_test; | |
386 | ||
387 | /* init mp_start_test status */ | |
388 | if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { | |
389 | rtw_disassoc_cmd(padapter, 500, true); | |
390 | rtw_indicate_disconnect(padapter); | |
391 | rtw_free_assoc_resources(padapter, 1); | |
392 | } | |
393 | pmppriv->prev_fw_state = get_fwstate(pmlmepriv); | |
394 | if (padapter->registrypriv.mp_mode == 1) | |
395 | pmlmepriv->fw_state = WIFI_MP_STATE; | |
396 | set_fwstate(pmlmepriv, _FW_UNDER_LINKING); | |
397 | ||
398 | /* 3 2. create a new psta for mp driver */ | |
399 | /* clear psta in the cur_network, if any */ | |
400 | psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress); | |
401 | if (psta) | |
402 | rtw_free_stainfo(padapter, psta); | |
403 | ||
404 | psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress); | |
405 | if (psta == NULL) { | |
406 | RT_TRACE(_module_mp_, _drv_err_, ("mp_start_test: Can't alloc sta_info!\n")); | |
407 | pmlmepriv->fw_state = pmppriv->prev_fw_state; | |
408 | res = _FAIL; | |
409 | goto end_of_mp_start_test; | |
410 | } | |
411 | ||
412 | /* 3 3. join psudo AdHoc */ | |
413 | tgt_network->join_res = 1; | |
414 | tgt_network->aid = 1; | |
415 | psta->aid = 1; | |
416 | memcpy(&tgt_network->network, &bssid, length); | |
417 | ||
418 | rtw_indicate_connect(padapter); | |
419 | _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); | |
420 | ||
421 | end_of_mp_start_test: | |
422 | ||
423 | _exit_critical_bh(&pmlmepriv->lock, &irqL); | |
424 | ||
425 | if (res == _SUCCESS) { | |
426 | /* set MSR to WIFI_FW_ADHOC_STATE */ | |
427 | val8 = rtw_read8(padapter, MSR) & 0xFC; /* 0x0102 */ | |
428 | val8 |= WIFI_FW_ADHOC_STATE; | |
429 | rtw_write8(padapter, MSR, val8); /* Link in ad hoc network */ | |
430 | } | |
431 | return res; | |
432 | } | |
433 | /* */ | |
434 | /* This function change the DUT from the MP test mode into normal mode */ | |
435 | void mp_stop_test(struct adapter *padapter) | |
436 | { | |
437 | struct mp_priv *pmppriv = &padapter->mppriv; | |
438 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
439 | struct wlan_network *tgt_network = &pmlmepriv->cur_network; | |
440 | struct sta_info *psta; | |
441 | ||
442 | unsigned long irqL; | |
443 | ||
444 | if (pmppriv->mode == MP_ON) { | |
445 | pmppriv->bSetTxPower = 0; | |
446 | _enter_critical_bh(&pmlmepriv->lock, &irqL); | |
447 | if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false) | |
448 | goto end_of_mp_stop_test; | |
449 | ||
450 | /* 3 1. disconnect psudo AdHoc */ | |
451 | rtw_indicate_disconnect(padapter); | |
452 | ||
453 | /* 3 2. clear psta used in mp test mode. */ | |
454 | psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress); | |
455 | if (psta) | |
456 | rtw_free_stainfo(padapter, psta); | |
457 | ||
458 | /* 3 3. return to normal state (default:station mode) */ | |
459 | pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE; */ | |
460 | ||
461 | /* flush the cur_network */ | |
462 | _rtw_memset(tgt_network, 0, sizeof(struct wlan_network)); | |
463 | ||
464 | _clr_fwstate_(pmlmepriv, WIFI_MP_STATE); | |
465 | ||
466 | end_of_mp_stop_test: | |
467 | ||
468 | _exit_critical_bh(&pmlmepriv->lock, &irqL); | |
469 | } | |
470 | } | |
471 | ||
472 | /*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/ | |
473 | /* | |
474 | * SetChannel | |
475 | * Description | |
476 | * Use H2C command to change channel, | |
477 | * not only modify rf register, but also other setting need to be done. | |
478 | */ | |
479 | void SetChannel(struct adapter *pAdapter) | |
480 | { | |
481 | Hal_SetChannel(pAdapter); | |
482 | } | |
483 | ||
484 | /* | |
485 | * Notice | |
486 | * Switch bandwitdth may change center frequency(channel) | |
487 | */ | |
488 | void SetBandwidth(struct adapter *pAdapter) | |
489 | { | |
490 | Hal_SetBandwidth(pAdapter); | |
491 | } | |
492 | ||
493 | void SetAntenna(struct adapter *pAdapter) | |
494 | { | |
495 | Hal_SetAntenna(pAdapter); | |
496 | } | |
497 | ||
498 | void SetAntennaPathPower(struct adapter *pAdapter) | |
499 | { | |
500 | Hal_SetAntennaPathPower(pAdapter); | |
501 | } | |
502 | ||
503 | void SetTxPower(struct adapter *pAdapter) | |
504 | { | |
505 | Hal_SetTxPower(pAdapter); | |
506 | } | |
507 | ||
508 | void SetDataRate(struct adapter *pAdapter) | |
509 | { | |
510 | Hal_SetDataRate(pAdapter); | |
511 | } | |
512 | ||
513 | void MP_PHY_SetRFPathSwitch(struct adapter *pAdapter , bool bMain) | |
514 | { | |
515 | PHY_SetRFPathSwitch(pAdapter, bMain); | |
516 | } | |
517 | ||
518 | s32 SetThermalMeter(struct adapter *pAdapter, u8 target_ther) | |
519 | { | |
520 | return Hal_SetThermalMeter(pAdapter, target_ther); | |
521 | } | |
522 | ||
523 | void GetThermalMeter(struct adapter *pAdapter, u8 *value) | |
524 | { | |
525 | Hal_GetThermalMeter(pAdapter, value); | |
526 | } | |
527 | ||
528 | void SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart) | |
529 | { | |
530 | PhySetTxPowerLevel(pAdapter); | |
531 | Hal_SetSingleCarrierTx(pAdapter, bStart); | |
532 | } | |
533 | ||
534 | void SetSingleToneTx(struct adapter *pAdapter, u8 bStart) | |
535 | { | |
536 | PhySetTxPowerLevel(pAdapter); | |
537 | Hal_SetSingleToneTx(pAdapter, bStart); | |
538 | } | |
539 | ||
540 | void SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart) | |
541 | { | |
542 | PhySetTxPowerLevel(pAdapter); | |
543 | Hal_SetCarrierSuppressionTx(pAdapter, bStart); | |
544 | } | |
545 | ||
546 | void SetContinuousTx(struct adapter *pAdapter, u8 bStart) | |
547 | { | |
548 | PhySetTxPowerLevel(pAdapter); | |
549 | Hal_SetContinuousTx(pAdapter, bStart); | |
550 | } | |
551 | ||
552 | ||
553 | void PhySetTxPowerLevel(struct adapter *pAdapter) | |
554 | { | |
555 | struct mp_priv *pmp_priv = &pAdapter->mppriv; | |
556 | ||
557 | if (pmp_priv->bSetTxPower == 0) /* for NO manually set power index */ | |
558 | PHY_SetTxPowerLevel8188E(pAdapter, pmp_priv->channel); | |
559 | } | |
560 | ||
561 | /* */ | |
562 | static void dump_mpframe(struct adapter *padapter, struct xmit_frame *pmpframe) | |
563 | { | |
564 | rtw_hal_mgnt_xmit(padapter, pmpframe); | |
565 | } | |
566 | ||
567 | static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv) | |
568 | { | |
569 | struct xmit_frame *pmpframe; | |
570 | struct xmit_buf *pxmitbuf; | |
571 | ||
572 | pmpframe = rtw_alloc_xmitframe(pxmitpriv); | |
573 | if (pmpframe == NULL) | |
574 | return NULL; | |
575 | ||
576 | pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); | |
577 | if (pxmitbuf == NULL) { | |
578 | rtw_free_xmitframe(pxmitpriv, pmpframe); | |
579 | return NULL; | |
580 | } | |
581 | ||
582 | pmpframe->frame_tag = MP_FRAMETAG; | |
583 | ||
584 | pmpframe->pxmitbuf = pxmitbuf; | |
585 | ||
586 | pmpframe->buf_addr = pxmitbuf->pbuf; | |
587 | ||
588 | pxmitbuf->priv_data = pmpframe; | |
589 | ||
590 | return pmpframe; | |
591 | } | |
592 | ||
593 | static int mp_xmit_packet_thread(void *context) | |
594 | { | |
595 | struct xmit_frame *pxmitframe; | |
596 | struct mp_tx *pmptx; | |
597 | struct mp_priv *pmp_priv; | |
598 | struct xmit_priv *pxmitpriv; | |
599 | struct adapter *padapter; | |
600 | ||
601 | pmp_priv = (struct mp_priv *)context; | |
602 | pmptx = &pmp_priv->tx; | |
603 | padapter = pmp_priv->papdater; | |
604 | pxmitpriv = &(padapter->xmitpriv); | |
605 | ||
606 | thread_enter("RTW_MP_THREAD"); | |
607 | ||
608 | /* DBG_88E("%s:pkTx Start\n", __func__); */ | |
609 | while (1) { | |
610 | pxmitframe = alloc_mp_xmitframe(pxmitpriv); | |
611 | if (pxmitframe == NULL) { | |
612 | if (pmptx->stop || | |
613 | padapter->bSurpriseRemoved || | |
614 | padapter->bDriverStopped) { | |
615 | goto exit; | |
616 | } else { | |
617 | rtw_msleep_os(1); | |
618 | continue; | |
619 | } | |
620 | } | |
621 | ||
622 | memcpy((u8 *)(pxmitframe->buf_addr+TXDESC_OFFSET), pmptx->buf, pmptx->write_size); | |
623 | memcpy(&(pxmitframe->attrib), &(pmptx->attrib), sizeof(struct pkt_attrib)); | |
624 | ||
625 | dump_mpframe(padapter, pxmitframe); | |
626 | ||
627 | pmptx->sended++; | |
628 | pmp_priv->tx_pktcount++; | |
629 | ||
630 | if (pmptx->stop || | |
631 | padapter->bSurpriseRemoved || | |
632 | padapter->bDriverStopped) | |
633 | goto exit; | |
634 | if ((pmptx->count != 0) && | |
635 | (pmptx->count == pmptx->sended)) | |
636 | goto exit; | |
637 | ||
638 | flush_signals_thread(); | |
639 | } | |
640 | ||
641 | exit: | |
642 | kfree(pmptx->pallocated_buf); | |
643 | pmptx->pallocated_buf = NULL; | |
644 | pmptx->stop = 1; | |
645 | ||
646 | thread_exit(); | |
647 | } | |
648 | ||
649 | void fill_txdesc_for_mp(struct adapter *padapter, struct tx_desc *ptxdesc) | |
650 | { | |
651 | struct mp_priv *pmp_priv = &padapter->mppriv; | |
652 | memcpy(ptxdesc, &(pmp_priv->tx.desc), TXDESC_SIZE); | |
653 | } | |
654 | ||
655 | void SetPacketTx(struct adapter *padapter) | |
656 | { | |
657 | u8 *ptr, *pkt_start, *pkt_end; | |
658 | u32 pkt_size; | |
659 | struct tx_desc *desc; | |
660 | struct rtw_ieee80211_hdr *hdr; | |
661 | u8 payload; | |
662 | s32 bmcast; | |
663 | struct pkt_attrib *pattrib; | |
664 | struct mp_priv *pmp_priv; | |
665 | ||
666 | ||
667 | pmp_priv = &padapter->mppriv; | |
668 | if (pmp_priv->tx.stop) | |
669 | return; | |
670 | pmp_priv->tx.sended = 0; | |
671 | pmp_priv->tx.stop = 0; | |
672 | pmp_priv->tx_pktcount = 0; | |
673 | ||
674 | /* 3 1. update_attrib() */ | |
675 | pattrib = &pmp_priv->tx.attrib; | |
676 | memcpy(pattrib->src, padapter->eeprompriv.mac_addr, ETH_ALEN); | |
677 | memcpy(pattrib->ta, pattrib->src, ETH_ALEN); | |
678 | memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); | |
679 | bmcast = IS_MCAST(pattrib->ra); | |
680 | if (bmcast) { | |
681 | pattrib->mac_id = 1; | |
682 | pattrib->psta = rtw_get_bcmc_stainfo(padapter); | |
683 | } else { | |
684 | pattrib->mac_id = 0; | |
685 | pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv)); | |
686 | } | |
687 | ||
688 | pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen; | |
689 | ||
690 | /* 3 2. allocate xmit buffer */ | |
691 | pkt_size = pattrib->last_txcmdsz; | |
692 | ||
693 | kfree(pmp_priv->tx.pallocated_buf); | |
694 | pmp_priv->tx.write_size = pkt_size; | |
695 | pmp_priv->tx.buf_size = pkt_size + XMITBUF_ALIGN_SZ; | |
696 | pmp_priv->tx.pallocated_buf = rtw_zmalloc(pmp_priv->tx.buf_size); | |
697 | if (pmp_priv->tx.pallocated_buf == NULL) { | |
698 | DBG_88E("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size); | |
699 | return; | |
700 | } | |
701 | pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pmp_priv->tx.pallocated_buf), XMITBUF_ALIGN_SZ); | |
702 | ptr = pmp_priv->tx.buf; | |
703 | ||
704 | desc = &(pmp_priv->tx.desc); | |
705 | _rtw_memset(desc, 0, TXDESC_SIZE); | |
706 | pkt_start = ptr; | |
707 | pkt_end = pkt_start + pkt_size; | |
708 | ||
709 | /* 3 3. init TX descriptor */ | |
710 | /* offset 0 */ | |
711 | desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); | |
712 | desc->txdw0 |= cpu_to_le32(pkt_size & 0x0000FFFF); /* packet size */ | |
713 | desc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00FF0000); /* 32 bytes for TX Desc */ | |
714 | if (bmcast) | |
715 | desc->txdw0 |= cpu_to_le32(BMC); /* broadcast packet */ | |
716 | ||
717 | desc->txdw1 |= cpu_to_le32((0x01 << 26) & 0xff000000); | |
718 | /* offset 4 */ | |
719 | desc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x3F); /* CAM_ID(MAC_ID) */ | |
720 | desc->txdw1 |= cpu_to_le32((pattrib->qsel << QSEL_SHT) & 0x00001F00); /* Queue Select, TID */ | |
721 | ||
722 | desc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); /* Rate Adaptive ID */ | |
723 | /* offset 8 */ | |
724 | /* offset 12 */ | |
725 | ||
726 | desc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0x0fff0000); | |
727 | ||
728 | /* offset 16 */ | |
729 | desc->txdw4 |= cpu_to_le32(HW_SSN); | |
730 | desc->txdw4 |= cpu_to_le32(USERATE); | |
731 | desc->txdw4 |= cpu_to_le32(DISDATAFB); | |
732 | ||
733 | if (pmp_priv->preamble) { | |
734 | if (pmp_priv->rateidx <= MPT_RATE_54M) | |
735 | desc->txdw4 |= cpu_to_le32(DATA_SHORT); /* CCK Short Preamble */ | |
736 | } | |
737 | if (pmp_priv->bandwidth == HT_CHANNEL_WIDTH_40) | |
738 | desc->txdw4 |= cpu_to_le32(DATA_BW); | |
739 | ||
740 | /* offset 20 */ | |
741 | desc->txdw5 |= cpu_to_le32(pmp_priv->rateidx & 0x0000001F); | |
742 | ||
743 | if (pmp_priv->preamble) { | |
744 | if (pmp_priv->rateidx > MPT_RATE_54M) | |
745 | desc->txdw5 |= cpu_to_le32(SGI); /* MCS Short Guard Interval */ | |
746 | } | |
747 | desc->txdw5 |= cpu_to_le32(RTY_LMT_EN); /* retry limit enable */ | |
748 | desc->txdw5 |= cpu_to_le32(0x00180000); /* DATA/RTS Rate Fallback Limit */ | |
749 | ||
750 | /* 3 4. make wlan header, make_wlanhdr() */ | |
751 | hdr = (struct rtw_ieee80211_hdr *)pkt_start; | |
752 | SetFrameSubType(&hdr->frame_ctl, pattrib->subtype); | |
753 | memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); /* DA */ | |
754 | memcpy(hdr->addr2, pattrib->src, ETH_ALEN); /* SA */ | |
755 | memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); /* RA, BSSID */ | |
756 | ||
757 | /* 3 5. make payload */ | |
758 | ptr = pkt_start + pattrib->hdrlen; | |
759 | ||
760 | switch (pmp_priv->tx.payload) { | |
761 | case 0: | |
762 | payload = 0x00; | |
763 | break; | |
764 | case 1: | |
765 | payload = 0x5a; | |
766 | break; | |
767 | case 2: | |
768 | payload = 0xa5; | |
769 | break; | |
770 | case 3: | |
771 | payload = 0xff; | |
772 | break; | |
773 | default: | |
774 | payload = 0x00; | |
775 | break; | |
776 | } | |
777 | ||
778 | _rtw_memset(ptr, payload, pkt_end - ptr); | |
779 | ||
780 | /* 3 6. start thread */ | |
781 | pmp_priv->tx.PktTxThread = kthread_run(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD"); | |
782 | if (IS_ERR(pmp_priv->tx.PktTxThread)) | |
783 | DBG_88E("Create PktTx Thread Fail !!!!!\n"); | |
784 | } | |
785 | ||
786 | void SetPacketRx(struct adapter *pAdapter, u8 bStartRx) | |
787 | { | |
788 | struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); | |
789 | ||
790 | if (bStartRx) { | |
791 | /* Accept CRC error and destination address */ | |
792 | pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS; | |
793 | ||
794 | pHalData->ReceiveConfig |= ACRC32; | |
795 | ||
796 | rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig); | |
797 | ||
798 | /* Accept all data frames */ | |
799 | rtw_write16(pAdapter, REG_RXFLTMAP2, 0xFFFF); | |
800 | } else { | |
801 | rtw_write32(pAdapter, REG_RCR, 0); | |
802 | } | |
803 | } | |
804 | ||
805 | void ResetPhyRxPktCount(struct adapter *pAdapter) | |
806 | { | |
807 | u32 i, phyrx_set = 0; | |
808 | ||
809 | for (i = 0; i <= 0xF; i++) { | |
810 | phyrx_set = 0; | |
811 | phyrx_set |= _RXERR_RPT_SEL(i); /* select */ | |
812 | phyrx_set |= RXERR_RPT_RST; /* set counter to zero */ | |
813 | rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set); | |
814 | } | |
815 | } | |
816 | ||
817 | static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit) | |
818 | { | |
819 | /* selection */ | |
820 | u32 phyrx_set = 0, count = 0; | |
821 | ||
822 | phyrx_set = _RXERR_RPT_SEL(selbit & 0xF); | |
823 | rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set); | |
824 | ||
825 | /* Read packet count */ | |
826 | count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK; | |
827 | ||
828 | return count; | |
829 | } | |
830 | ||
831 | u32 GetPhyRxPktReceived(struct adapter *pAdapter) | |
832 | { | |
833 | u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0; | |
834 | ||
835 | OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_OK); | |
836 | CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_OK); | |
837 | HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_OK); | |
838 | ||
839 | return OFDM_cnt + CCK_cnt + HT_cnt; | |
840 | } | |
841 | ||
842 | u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter) | |
843 | { | |
844 | u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0; | |
845 | ||
846 | OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_FAIL); | |
847 | CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_FAIL); | |
848 | HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_FAIL); | |
849 | ||
850 | return OFDM_cnt + CCK_cnt + HT_cnt; | |
851 | } | |
852 | ||
853 | /* reg 0x808[9:0]: FFT data x */ | |
854 | /* reg 0x808[22]: 0 --> 1 to get 1 FFT data y */ | |
855 | /* reg 0x8B4[15:0]: FFT data y report */ | |
856 | static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point) | |
857 | { | |
858 | int psd_val; | |
859 | ||
860 | ||
861 | psd_val = rtw_read32(pAdapter, 0x808); | |
862 | psd_val &= 0xFFBFFC00; | |
863 | psd_val |= point; | |
864 | ||
865 | rtw_write32(pAdapter, 0x808, psd_val); | |
866 | rtw_mdelay_os(1); | |
867 | psd_val |= 0x00400000; | |
868 | ||
869 | rtw_write32(pAdapter, 0x808, psd_val); | |
870 | rtw_mdelay_os(1); | |
871 | psd_val = rtw_read32(pAdapter, 0x8B4); | |
872 | ||
873 | psd_val &= 0x0000FFFF; | |
874 | ||
875 | return psd_val; | |
876 | } | |
877 | ||
878 | /* | |
879 | *pts start_point_min stop_point_max | |
880 | * 128 64 64 + 128 = 192 | |
881 | * 256 128 128 + 256 = 384 | |
882 | * 512 256 256 + 512 = 768 | |
883 | * 1024 512 512 + 1024 = 1536 | |
884 | * | |
885 | */ | |
886 | u32 mp_query_psd(struct adapter *pAdapter, u8 *data) | |
887 | { | |
888 | u32 i, psd_pts = 0, psd_start = 0, psd_stop = 0; | |
889 | u32 psd_data = 0; | |
890 | ||
891 | ||
892 | if (!netif_running(pAdapter->pnetdev)) { | |
893 | RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! interface not opened!\n")); | |
894 | return 0; | |
895 | } | |
896 | ||
897 | if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) { | |
898 | RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! not in MP mode!\n")); | |
899 | return 0; | |
900 | } | |
901 | ||
902 | if (strlen(data) == 0) { /* default value */ | |
903 | psd_pts = 128; | |
904 | psd_start = 64; | |
905 | psd_stop = 128; | |
906 | } else { | |
907 | sscanf(data, "pts =%d, start =%d, stop =%d", &psd_pts, &psd_start, &psd_stop); | |
908 | } | |
909 | ||
ffceff44 | 910 | _rtw_memset(data, '\0', sizeof(*data)); |
7b464c9f LF |
911 | |
912 | i = psd_start; | |
913 | while (i < psd_stop) { | |
914 | if (i >= psd_pts) { | |
915 | psd_data = rtw_GetPSDData(pAdapter, i-psd_pts); | |
916 | } else { | |
917 | psd_data = rtw_GetPSDData(pAdapter, i); | |
918 | } | |
919 | sprintf(data, "%s%x ", data, psd_data); | |
920 | i++; | |
921 | } | |
922 | ||
923 | rtw_msleep_os(100); | |
924 | return strlen(data)+1; | |
925 | } | |
926 | ||
927 | void _rtw_mp_xmit_priv(struct xmit_priv *pxmitpriv) | |
928 | { | |
929 | int i, res; | |
930 | struct adapter *padapter = pxmitpriv->adapter; | |
931 | struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; | |
932 | ||
933 | u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; | |
934 | u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; | |
935 | if (padapter->registrypriv.mp_mode == 0) { | |
936 | max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; | |
937 | num_xmit_extbuf = NR_XMIT_EXTBUFF; | |
938 | } else { | |
939 | max_xmit_extbuf_size = 20000; | |
940 | num_xmit_extbuf = 1; | |
941 | } | |
942 | ||
943 | pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; | |
944 | for (i = 0; i < num_xmit_extbuf; i++) { | |
945 | rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); | |
946 | ||
947 | pxmitbuf++; | |
948 | } | |
949 | ||
950 | if (pxmitpriv->pallocated_xmit_extbuf) | |
951 | rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, num_xmit_extbuf * sizeof(struct xmit_buf) + 4); | |
952 | ||
953 | if (padapter->registrypriv.mp_mode == 0) { | |
954 | max_xmit_extbuf_size = 20000; | |
955 | num_xmit_extbuf = 1; | |
956 | } else { | |
957 | max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; | |
958 | num_xmit_extbuf = NR_XMIT_EXTBUFF; | |
959 | } | |
960 | ||
961 | /* Init xmit extension buff */ | |
962 | _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue); | |
963 | ||
964 | pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4); | |
965 | ||
966 | if (pxmitpriv->pallocated_xmit_extbuf == NULL) { | |
967 | RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n")); | |
968 | res = _FAIL; | |
969 | goto exit; | |
970 | } | |
971 | ||
972 | pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); | |
973 | ||
974 | pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; | |
975 | ||
976 | for (i = 0; i < num_xmit_extbuf; i++) { | |
977 | _rtw_init_listhead(&pxmitbuf->list); | |
978 | ||
979 | pxmitbuf->priv_data = NULL; | |
980 | pxmitbuf->padapter = padapter; | |
981 | pxmitbuf->ext_tag = true; | |
982 | ||
983 | res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); | |
984 | if (res == _FAIL) { | |
985 | res = _FAIL; | |
986 | goto exit; | |
987 | } | |
988 | ||
989 | rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue)); | |
990 | pxmitbuf++; | |
991 | } | |
992 | ||
993 | pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; | |
994 | ||
995 | exit: | |
996 | ; | |
997 | } |