1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7
8 #include <linux/firmware.h>
9 #include <linux/slab.h>
10 #include <drv_types.h>
11 #include <rtl8723b_hal.h>
12 #include "hal_com_h2c.h"
13
_FWDownloadEnable(struct adapter * padapter,bool enable)14 static void _FWDownloadEnable(struct adapter *padapter, bool enable)
15 {
16 u8 tmp, count = 0;
17
18 if (enable) {
19 /* 8051 enable */
20 tmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
21 rtw_write8(padapter, REG_SYS_FUNC_EN+1, tmp|0x04);
22
23 tmp = rtw_read8(padapter, REG_MCUFWDL);
24 rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
25
26 do {
27 tmp = rtw_read8(padapter, REG_MCUFWDL);
28 if (tmp & 0x01)
29 break;
30 rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
31 msleep(1);
32 } while (count++ < 100);
33
34 /* 8051 reset */
35 tmp = rtw_read8(padapter, REG_MCUFWDL+2);
36 rtw_write8(padapter, REG_MCUFWDL+2, tmp&0xf7);
37 } else {
38 /* MCU firmware download disable. */
39 tmp = rtw_read8(padapter, REG_MCUFWDL);
40 rtw_write8(padapter, REG_MCUFWDL, tmp&0xfe);
41 }
42 }
43
_BlockWrite(struct adapter * padapter,void * buffer,u32 buffSize)44 static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
45 {
46 int ret = _SUCCESS;
47
48 u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
49 u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
50 u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */
51 u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
52 u32 remainSize_p1 = 0, remainSize_p2 = 0;
53 u8 *bufferPtr = buffer;
54 u32 i = 0, offset = 0;
55
56 /* 3 Phase #1 */
57 blockCount_p1 = buffSize / blockSize_p1;
58 remainSize_p1 = buffSize % blockSize_p1;
59
60 for (i = 0; i < blockCount_p1; i++) {
61 ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1)));
62 if (ret == _FAIL) {
63 netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
64 __func__, __LINE__, i);
65 goto exit;
66 }
67 }
68
69 /* 3 Phase #2 */
70 if (remainSize_p1) {
71 offset = blockCount_p1 * blockSize_p1;
72
73 blockCount_p2 = remainSize_p1/blockSize_p2;
74 remainSize_p2 = remainSize_p1%blockSize_p2;
75 }
76
77 /* 3 Phase #3 */
78 if (remainSize_p2) {
79 offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
80
81 blockCount_p3 = remainSize_p2 / blockSize_p3;
82
83 for (i = 0; i < blockCount_p3; i++) {
84 ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
85
86 if (ret == _FAIL) {
87 netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
88 __func__, __LINE__, i);
89 goto exit;
90 }
91 }
92 }
93 exit:
94 return ret;
95 }
96
_PageWrite(struct adapter * padapter,u32 page,void * buffer,u32 size)97 static int _PageWrite(
98 struct adapter *padapter,
99 u32 page,
100 void *buffer,
101 u32 size
102 )
103 {
104 u8 value8;
105 u8 u8Page = (u8) (page & 0x07);
106
107 value8 = (rtw_read8(padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
108 rtw_write8(padapter, REG_MCUFWDL+2, value8);
109
110 return _BlockWrite(padapter, buffer, size);
111 }
112
_WriteFW(struct adapter * padapter,void * buffer,u32 size)113 static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
114 {
115 /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
116 /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
117 int ret = _SUCCESS;
118 u32 pageNums, remainSize;
119 u32 page, offset;
120 u8 *bufferPtr = buffer;
121
122 pageNums = size / MAX_DLFW_PAGE_SIZE;
123 remainSize = size % MAX_DLFW_PAGE_SIZE;
124
125 for (page = 0; page < pageNums; page++) {
126 offset = page * MAX_DLFW_PAGE_SIZE;
127 ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
128
129 if (ret == _FAIL) {
130 netdev_dbg(padapter->pnetdev, "page write failed at %s %d\n",
131 __func__, __LINE__);
132 goto exit;
133 }
134 }
135
136 if (remainSize) {
137 offset = pageNums * MAX_DLFW_PAGE_SIZE;
138 page = pageNums;
139 ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize);
140
141 if (ret == _FAIL) {
142 netdev_dbg(padapter->pnetdev, "remaining page write failed at %s %d\n",
143 __func__, __LINE__);
144 goto exit;
145 }
146 }
147
148 exit:
149 return ret;
150 }
151
_8051Reset8723(struct adapter * padapter)152 void _8051Reset8723(struct adapter *padapter)
153 {
154 u8 cpu_rst;
155 u8 io_rst;
156
157
158 /* Reset 8051(WLMCU) IO wrapper */
159 /* 0x1c[8] = 0 */
160 /* Suggested by Isaac@SD1 and Gimmy@SD1, coding by Lucas@20130624 */
161 io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
162 io_rst &= ~BIT(0);
163 rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
164
165 cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
166 cpu_rst &= ~BIT(2);
167 rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
168
169 /* Enable 8051 IO wrapper */
170 /* 0x1c[8] = 1 */
171 io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
172 io_rst |= BIT(0);
173 rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
174
175 cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
176 cpu_rst |= BIT(2);
177 rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
178 }
179
180 u8 g_fwdl_chksum_fail;
181
polling_fwdl_chksum(struct adapter * adapter,u32 min_cnt,u32 timeout_ms)182 static s32 polling_fwdl_chksum(
183 struct adapter *adapter, u32 min_cnt, u32 timeout_ms
184 )
185 {
186 s32 ret = _FAIL;
187 u32 value32;
188 unsigned long start = jiffies;
189 u32 cnt = 0;
190
191 /* polling CheckSum report */
192 do {
193 cnt++;
194 value32 = rtw_read32(adapter, REG_MCUFWDL);
195 if (value32 & FWDL_ChkSum_rpt || adapter->bSurpriseRemoved || adapter->bDriverStopped)
196 break;
197 yield();
198 } while (jiffies_to_msecs(jiffies-start) < timeout_ms || cnt < min_cnt);
199
200 if (!(value32 & FWDL_ChkSum_rpt)) {
201 goto exit;
202 }
203
204 if (g_fwdl_chksum_fail) {
205 g_fwdl_chksum_fail--;
206 goto exit;
207 }
208
209 ret = _SUCCESS;
210
211 exit:
212
213 return ret;
214 }
215
216 u8 g_fwdl_wintint_rdy_fail;
217
_FWFreeToGo(struct adapter * adapter,u32 min_cnt,u32 timeout_ms)218 static s32 _FWFreeToGo(struct adapter *adapter, u32 min_cnt, u32 timeout_ms)
219 {
220 s32 ret = _FAIL;
221 u32 value32;
222 unsigned long start = jiffies;
223 u32 cnt = 0;
224
225 value32 = rtw_read32(adapter, REG_MCUFWDL);
226 value32 |= MCUFWDL_RDY;
227 value32 &= ~WINTINI_RDY;
228 rtw_write32(adapter, REG_MCUFWDL, value32);
229
230 _8051Reset8723(adapter);
231
232 /* polling for FW ready */
233 do {
234 cnt++;
235 value32 = rtw_read32(adapter, REG_MCUFWDL);
236 if (value32 & WINTINI_RDY || adapter->bSurpriseRemoved || adapter->bDriverStopped)
237 break;
238 yield();
239 } while (jiffies_to_msecs(jiffies - start) < timeout_ms || cnt < min_cnt);
240
241 if (!(value32 & WINTINI_RDY)) {
242 goto exit;
243 }
244
245 if (g_fwdl_wintint_rdy_fail) {
246 g_fwdl_wintint_rdy_fail--;
247 goto exit;
248 }
249
250 ret = _SUCCESS;
251
252 exit:
253
254 return ret;
255 }
256
257 #define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
258
rtl8723b_FirmwareSelfReset(struct adapter * padapter)259 void rtl8723b_FirmwareSelfReset(struct adapter *padapter)
260 {
261 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
262 u8 u1bTmp;
263 u8 Delay = 100;
264
265 if (
266 !(IS_FW_81xxC(padapter) && ((pHalData->FirmwareVersion < 0x21) || (pHalData->FirmwareVersion == 0x21 && pHalData->FirmwareSubVersion < 0x01)))
267 ) { /* after 88C Fw v33.1 */
268 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
269 rtw_write8(padapter, REG_HMETFR+3, 0x20);
270
271 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
272 while (u1bTmp & BIT2) {
273 Delay--;
274 if (Delay == 0)
275 break;
276 udelay(50);
277 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
278 }
279
280 if (Delay == 0) {
281 /* force firmware reset */
282 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
283 rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
284 }
285 }
286 }
287
288 /* */
289 /* Description: */
290 /* Download 8192C firmware code. */
291 /* */
292 /* */
rtl8723b_FirmwareDownload(struct adapter * padapter,bool bUsedWoWLANFw)293 s32 rtl8723b_FirmwareDownload(struct adapter *padapter, bool bUsedWoWLANFw)
294 {
295 s32 rtStatus = _SUCCESS;
296 u8 write_fw = 0;
297 unsigned long fwdl_start_time;
298 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
299 struct rt_firmware *pFirmware;
300 struct rt_firmware *pBTFirmware;
301 struct rt_firmware_hdr *pFwHdr = NULL;
302 u8 *pFirmwareBuf;
303 u32 FirmwareLen;
304 const struct firmware *fw;
305 struct device *device = dvobj_to_dev(padapter->dvobj);
306 u8 *fwfilepath;
307 struct dvobj_priv *psdpriv = padapter->dvobj;
308 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
309 u8 tmp_ps;
310
311 pFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
312 if (!pFirmware)
313 return _FAIL;
314 pBTFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
315 if (!pBTFirmware) {
316 kfree(pFirmware);
317 return _FAIL;
318 }
319 tmp_ps = rtw_read8(padapter, 0xa3);
320 tmp_ps &= 0xf8;
321 tmp_ps |= 0x02;
322 /* 1. write 0xA3[:2:0] = 3b'010 */
323 rtw_write8(padapter, 0xa3, tmp_ps);
324 /* 2. read power_state = 0xA0[1:0] */
325 tmp_ps = rtw_read8(padapter, 0xa0);
326 tmp_ps &= 0x03;
327 if (tmp_ps != 0x01)
328 pdbgpriv->dbg_downloadfw_pwr_state_cnt++;
329
330 fwfilepath = "rtlwifi/rtl8723bs_nic.bin";
331
332 pr_info("rtl8723bs: acquire FW from file:%s\n", fwfilepath);
333
334 rtStatus = request_firmware(&fw, fwfilepath, device);
335 if (rtStatus) {
336 pr_err("Request firmware failed with error 0x%x\n", rtStatus);
337 rtStatus = _FAIL;
338 goto exit;
339 }
340
341 if (!fw) {
342 pr_err("Firmware %s not available\n", fwfilepath);
343 rtStatus = _FAIL;
344 goto exit;
345 }
346
347 if (fw->size > FW_8723B_SIZE) {
348 rtStatus = _FAIL;
349 goto exit;
350 }
351
352 pFirmware->fw_buffer_sz = kmemdup(fw->data, fw->size, GFP_KERNEL);
353 if (!pFirmware->fw_buffer_sz) {
354 rtStatus = _FAIL;
355 goto exit;
356 }
357
358 pFirmware->fw_length = fw->size;
359 release_firmware(fw);
360 if (pFirmware->fw_length > FW_8723B_SIZE) {
361 rtStatus = _FAIL;
362 netdev_emerg(padapter->pnetdev,
363 "Firmware size:%u exceed %u\n",
364 pFirmware->fw_length, FW_8723B_SIZE);
365 goto release_fw1;
366 }
367
368 pFirmwareBuf = pFirmware->fw_buffer_sz;
369 FirmwareLen = pFirmware->fw_length;
370
371 /* To Check Fw header. Added by tynli. 2009.12.04. */
372 pFwHdr = (struct rt_firmware_hdr *)pFirmwareBuf;
373
374 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->version);
375 pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->subversion);
376 pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->signature);
377
378 if (IS_FW_HEADER_EXIST_8723B(pFwHdr)) {
379 /* Shift 32 bytes for FW header */
380 pFirmwareBuf = pFirmwareBuf + 32;
381 FirmwareLen = FirmwareLen - 32;
382 }
383
384 /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
385 /* or it will cause download Fw fail. 2010.02.01. by tynli. */
386 if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
387 rtw_write8(padapter, REG_MCUFWDL, 0x00);
388 rtl8723b_FirmwareSelfReset(padapter);
389 }
390
391 _FWDownloadEnable(padapter, true);
392 fwdl_start_time = jiffies;
393 while (
394 !padapter->bDriverStopped &&
395 !padapter->bSurpriseRemoved &&
396 (write_fw++ < 3 || jiffies_to_msecs(jiffies - fwdl_start_time) < 500)
397 ) {
398 /* reset FWDL chksum */
399 rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL)|FWDL_ChkSum_rpt);
400
401 rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
402 if (rtStatus != _SUCCESS)
403 continue;
404
405 rtStatus = polling_fwdl_chksum(padapter, 5, 50);
406 if (rtStatus == _SUCCESS)
407 break;
408 }
409 _FWDownloadEnable(padapter, false);
410 if (_SUCCESS != rtStatus)
411 goto fwdl_stat;
412
413 rtStatus = _FWFreeToGo(padapter, 10, 200);
414 if (_SUCCESS != rtStatus)
415 goto fwdl_stat;
416
417 fwdl_stat:
418
419 exit:
420 kfree(pFirmware->fw_buffer_sz);
421 kfree(pFirmware);
422 release_fw1:
423 kfree(pBTFirmware);
424 return rtStatus;
425 }
426
rtl8723b_InitializeFirmwareVars(struct adapter * padapter)427 void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
428 {
429 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
430
431 /* Init Fw LPS related. */
432 adapter_to_pwrctl(padapter)->fw_current_in_ps_mode = false;
433
434 /* Init H2C cmd. */
435 rtw_write8(padapter, REG_HMETFR, 0x0f);
436
437 /* Init H2C counter. by tynli. 2009.12.09. */
438 pHalData->LastHMEBoxNum = 0;
439 /* pHalData->H2CQueueHead = 0; */
440 /* pHalData->H2CQueueTail = 0; */
441 /* pHalData->H2CStopInsertQueue = false; */
442 }
443
444 /* */
445 /* Efuse related code */
446 /* */
hal_EfuseSwitchToBank(struct adapter * padapter,u8 bank,bool bPseudoTest)447 static u8 hal_EfuseSwitchToBank(
448 struct adapter *padapter, u8 bank, bool bPseudoTest
449 )
450 {
451 u8 bRet = false;
452 u32 value32 = 0;
453 #ifdef HAL_EFUSE_MEMORY
454 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
455 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
456 #endif
457
458
459 if (bPseudoTest) {
460 #ifdef HAL_EFUSE_MEMORY
461 pEfuseHal->fakeEfuseBank = bank;
462 #else
463 fakeEfuseBank = bank;
464 #endif
465 bRet = true;
466 } else {
467 value32 = rtw_read32(padapter, EFUSE_TEST);
468 bRet = true;
469 switch (bank) {
470 case 0:
471 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
472 break;
473 case 1:
474 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_0);
475 break;
476 case 2:
477 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_1);
478 break;
479 case 3:
480 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_2);
481 break;
482 default:
483 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
484 bRet = false;
485 break;
486 }
487 rtw_write32(padapter, EFUSE_TEST, value32);
488 }
489
490 return bRet;
491 }
492
Hal_GetEfuseDefinition(struct adapter * padapter,u8 efuseType,u8 type,void * pOut,bool bPseudoTest)493 void Hal_GetEfuseDefinition(
494 struct adapter *padapter,
495 u8 efuseType,
496 u8 type,
497 void *pOut,
498 bool bPseudoTest
499 )
500 {
501 switch (type) {
502 case TYPE_EFUSE_MAX_SECTION:
503 {
504 u8 *pMax_section = pOut;
505
506 if (efuseType == EFUSE_WIFI)
507 *pMax_section = EFUSE_MAX_SECTION_8723B;
508 else
509 *pMax_section = EFUSE_BT_MAX_SECTION;
510 }
511 break;
512
513 case TYPE_EFUSE_REAL_CONTENT_LEN:
514 {
515 u16 *pu2Tmp = pOut;
516
517 if (efuseType == EFUSE_WIFI)
518 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
519 else
520 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
521 }
522 break;
523
524 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
525 {
526 u16 *pu2Tmp = pOut;
527
528 if (efuseType == EFUSE_WIFI)
529 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
530 else
531 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN-EFUSE_PROTECT_BYTES_BANK);
532 }
533 break;
534
535 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
536 {
537 u16 *pu2Tmp = pOut;
538
539 if (efuseType == EFUSE_WIFI)
540 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
541 else
542 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN-(EFUSE_PROTECT_BYTES_BANK*3));
543 }
544 break;
545
546 case TYPE_EFUSE_MAP_LEN:
547 {
548 u16 *pu2Tmp = pOut;
549
550 if (efuseType == EFUSE_WIFI)
551 *pu2Tmp = EFUSE_MAX_MAP_LEN;
552 else
553 *pu2Tmp = EFUSE_BT_MAP_LEN;
554 }
555 break;
556
557 case TYPE_EFUSE_PROTECT_BYTES_BANK:
558 {
559 u8 *pu1Tmp = pOut;
560
561 if (efuseType == EFUSE_WIFI)
562 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
563 else
564 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
565 }
566 break;
567
568 case TYPE_EFUSE_CONTENT_LEN_BANK:
569 {
570 u16 *pu2Tmp = pOut;
571
572 if (efuseType == EFUSE_WIFI)
573 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
574 else
575 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
576 }
577 break;
578
579 default:
580 {
581 u8 *pu1Tmp = pOut;
582 *pu1Tmp = 0;
583 }
584 break;
585 }
586 }
587
588 #define VOLTAGE_V25 0x03
589
590 /* */
591 /* The following is for compile ok */
592 /* That should be merged with the original in the future */
593 /* */
594 #define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
595 #define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
596
Hal_EfusePowerSwitch(struct adapter * padapter,u8 bWrite,u8 PwrState)597 void Hal_EfusePowerSwitch(
598 struct adapter *padapter, u8 bWrite, u8 PwrState
599 )
600 {
601 u8 tempval;
602 u16 tmpV16;
603
604
605 if (PwrState) {
606 /* To avoid cannot access efuse registers after disable/enable several times during DTM test. */
607 /* Suggested by SD1 IsaacHsu. 2013.07.08, added by tynli. */
608 tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
609 if (tempval & BIT(0)) { /* SDIO local register is suspend */
610 u8 count = 0;
611
612
613 tempval &= ~BIT(0);
614 rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL, tempval);
615
616 /* check 0x86[1:0]= 10'2h, wait power state to leave suspend */
617 do {
618 tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
619 tempval &= 0x3;
620 if (tempval == 0x02)
621 break;
622
623 count++;
624 if (count >= 100)
625 break;
626
627 mdelay(10);
628 } while (1);
629 }
630
631 rtw_write8(padapter, REG_EFUSE_ACCESS_8723, EFUSE_ACCESS_ON_8723);
632
633 /* Reset: 0x0000h[28], default valid */
634 tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
635 if (!(tmpV16 & FEN_ELDR)) {
636 tmpV16 |= FEN_ELDR;
637 rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
638 }
639
640 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
641 tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
642 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
643 tmpV16 |= (LOADER_CLK_EN | ANA8M);
644 rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
645 }
646
647 if (bWrite) {
648 /* Enable LDO 2.5V before read/write action */
649 tempval = rtw_read8(padapter, EFUSE_TEST+3);
650 tempval &= 0x0F;
651 tempval |= (VOLTAGE_V25 << 4);
652 rtw_write8(padapter, EFUSE_TEST+3, (tempval | 0x80));
653
654 /* rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); */
655 }
656 } else {
657 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
658
659 if (bWrite) {
660 /* Disable LDO 2.5V after read/write action */
661 tempval = rtw_read8(padapter, EFUSE_TEST+3);
662 rtw_write8(padapter, EFUSE_TEST+3, (tempval & 0x7F));
663 }
664
665 }
666 }
667
hal_ReadEFuse_WiFi(struct adapter * padapter,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)668 static void hal_ReadEFuse_WiFi(
669 struct adapter *padapter,
670 u16 _offset,
671 u16 _size_byte,
672 u8 *pbuf,
673 bool bPseudoTest
674 )
675 {
676 #ifdef HAL_EFUSE_MEMORY
677 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
678 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
679 #endif
680 u8 *efuseTbl = NULL;
681 u16 eFuse_Addr = 0;
682 u8 offset, wden;
683 u8 efuseHeader, efuseExtHdr, efuseData;
684 u16 i, total, used;
685 u8 efuse_usage = 0;
686
687 /* */
688 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
689 /* */
690 if ((_offset + _size_byte) > EFUSE_MAX_MAP_LEN)
691 return;
692
693 efuseTbl = rtw_malloc(EFUSE_MAX_MAP_LEN);
694 if (!efuseTbl)
695 return;
696
697 /* 0xff will be efuse default value instead of 0x00. */
698 memset(efuseTbl, 0xFF, EFUSE_MAX_MAP_LEN);
699
700 /* switch bank back to bank 0 for later BT and wifi use. */
701 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
702
703 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
704 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
705 if (efuseHeader == 0xFF)
706 break;
707
708 /* Check PG header for section num. */
709 if (EXT_HEADER(efuseHeader)) { /* extended header */
710 offset = GET_HDR_OFFSET_2_0(efuseHeader);
711
712 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
713 if (ALL_WORDS_DISABLED(efuseExtHdr))
714 continue;
715
716 offset |= ((efuseExtHdr & 0xF0) >> 1);
717 wden = (efuseExtHdr & 0x0F);
718 } else {
719 offset = ((efuseHeader >> 4) & 0x0f);
720 wden = (efuseHeader & 0x0f);
721 }
722
723 if (offset < EFUSE_MAX_SECTION_8723B) {
724 u16 addr;
725 /* Get word enable value from PG header */
726
727 addr = offset * PGPKT_DATA_SIZE;
728 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
729 /* Check word enable condition in the section */
730 if (!(wden & (0x01<<i))) {
731 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
732 efuseTbl[addr] = efuseData;
733
734 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
735 efuseTbl[addr+1] = efuseData;
736 }
737 addr += 2;
738 }
739 } else {
740 eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
741 }
742 }
743
744 /* Copy from Efuse map to output pointer memory!!! */
745 for (i = 0; i < _size_byte; i++)
746 pbuf[i] = efuseTbl[_offset+i];
747
748 /* Calculate Efuse utilization */
749 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
750 used = eFuse_Addr - 1;
751 efuse_usage = (u8)((used*100)/total);
752 if (bPseudoTest) {
753 #ifdef HAL_EFUSE_MEMORY
754 pEfuseHal->fakeEfuseUsedBytes = used;
755 #else
756 fakeEfuseUsedBytes = used;
757 #endif
758 } else {
759 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
760 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_USAGE, (u8 *)&efuse_usage);
761 }
762
763 kfree(efuseTbl);
764 }
765
hal_ReadEFuse_BT(struct adapter * padapter,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)766 static void hal_ReadEFuse_BT(
767 struct adapter *padapter,
768 u16 _offset,
769 u16 _size_byte,
770 u8 *pbuf,
771 bool bPseudoTest
772 )
773 {
774 #ifdef HAL_EFUSE_MEMORY
775 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
776 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
777 #endif
778 u8 *efuseTbl;
779 u8 bank;
780 u16 eFuse_Addr;
781 u8 efuseHeader, efuseExtHdr, efuseData;
782 u8 offset, wden;
783 u16 i, total, used;
784 u8 efuse_usage;
785
786
787 /* */
788 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
789 /* */
790 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN)
791 return;
792
793 efuseTbl = rtw_malloc(EFUSE_BT_MAP_LEN);
794 if (!efuseTbl)
795 return;
796
797 /* 0xff will be efuse default value instead of 0x00. */
798 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
799
800 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total, bPseudoTest);
801
802 for (bank = 1; bank < 3; bank++) { /* 8723b Max bake 0~2 */
803 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
804 goto exit;
805
806 eFuse_Addr = 0;
807
808 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
809 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
810 if (efuseHeader == 0xFF)
811 break;
812
813 /* Check PG header for section num. */
814 if (EXT_HEADER(efuseHeader)) { /* extended header */
815 offset = GET_HDR_OFFSET_2_0(efuseHeader);
816
817 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
818 if (ALL_WORDS_DISABLED(efuseExtHdr))
819 continue;
820
821
822 offset |= ((efuseExtHdr & 0xF0) >> 1);
823 wden = (efuseExtHdr & 0x0F);
824 } else {
825 offset = ((efuseHeader >> 4) & 0x0f);
826 wden = (efuseHeader & 0x0f);
827 }
828
829 if (offset < EFUSE_BT_MAX_SECTION) {
830 u16 addr = offset * PGPKT_DATA_SIZE;
831
832 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
833 /* Check word enable condition in the section */
834 if (!(wden & (0x01<<i))) {
835 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
836 efuseTbl[addr] = efuseData;
837
838 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
839 efuseTbl[addr+1] = efuseData;
840 }
841 addr += 2;
842 }
843 } else {
844 eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
845 }
846 }
847
848 if ((eFuse_Addr - 1) < total)
849 break;
850
851 }
852
853 /* switch bank back to bank 0 for later BT and wifi use. */
854 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
855
856 /* Copy from Efuse map to output pointer memory!!! */
857 for (i = 0; i < _size_byte; i++)
858 pbuf[i] = efuseTbl[_offset+i];
859
860 /* */
861 /* Calculate Efuse utilization. */
862 /* */
863 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
864 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN*(bank-1)) + eFuse_Addr - 1;
865 efuse_usage = (u8)((used*100)/total);
866 if (bPseudoTest) {
867 #ifdef HAL_EFUSE_MEMORY
868 pEfuseHal->fakeBTEfuseUsedBytes = used;
869 #else
870 fakeBTEfuseUsedBytes = used;
871 #endif
872 } else {
873 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&used);
874 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_USAGE, (u8 *)&efuse_usage);
875 }
876
877 exit:
878 kfree(efuseTbl);
879 }
880
Hal_ReadEFuse(struct adapter * padapter,u8 efuseType,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)881 void Hal_ReadEFuse(
882 struct adapter *padapter,
883 u8 efuseType,
884 u16 _offset,
885 u16 _size_byte,
886 u8 *pbuf,
887 bool bPseudoTest
888 )
889 {
890 if (efuseType == EFUSE_WIFI)
891 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf, bPseudoTest);
892 else
893 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf, bPseudoTest);
894 }
895
hal_EfuseGetCurrentSize_WiFi(struct adapter * padapter,bool bPseudoTest)896 static u16 hal_EfuseGetCurrentSize_WiFi(
897 struct adapter *padapter, bool bPseudoTest
898 )
899 {
900 #ifdef HAL_EFUSE_MEMORY
901 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
902 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
903 #endif
904 u16 efuse_addr = 0;
905 u16 start_addr = 0; /* for debug */
906 u8 hworden = 0;
907 u8 efuse_data, word_cnts = 0;
908 u32 count = 0; /* for debug */
909
910
911 if (bPseudoTest) {
912 #ifdef HAL_EFUSE_MEMORY
913 efuse_addr = (u16)pEfuseHal->fakeEfuseUsedBytes;
914 #else
915 efuse_addr = (u16)fakeEfuseUsedBytes;
916 #endif
917 } else
918 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
919
920 start_addr = efuse_addr;
921
922 /* switch bank back to bank 0 for later BT and wifi use. */
923 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
924
925 count = 0;
926 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
927 if (efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) == false)
928 goto error;
929
930 if (efuse_data == 0xFF)
931 break;
932
933 if ((start_addr != 0) && (efuse_addr == start_addr)) {
934 count++;
935
936 efuse_data = 0xFF;
937 if (count < 4) {
938 /* try again! */
939
940 if (count > 2) {
941 /* try again form address 0 */
942 efuse_addr = 0;
943 start_addr = 0;
944 }
945
946 continue;
947 }
948
949 goto error;
950 }
951
952 if (EXT_HEADER(efuse_data)) {
953 efuse_addr++;
954 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
955 if (ALL_WORDS_DISABLED(efuse_data))
956 continue;
957
958 hworden = efuse_data & 0x0F;
959 } else {
960 hworden = efuse_data & 0x0F;
961 }
962
963 word_cnts = Efuse_CalculateWordCnts(hworden);
964 efuse_addr += (word_cnts*2)+1;
965 }
966
967 if (bPseudoTest) {
968 #ifdef HAL_EFUSE_MEMORY
969 pEfuseHal->fakeEfuseUsedBytes = efuse_addr;
970 #else
971 fakeEfuseUsedBytes = efuse_addr;
972 #endif
973 } else
974 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
975
976 goto exit;
977
978 error:
979 /* report max size to prevent write efuse */
980 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_addr, bPseudoTest);
981
982 exit:
983
984 return efuse_addr;
985 }
986
hal_EfuseGetCurrentSize_BT(struct adapter * padapter,u8 bPseudoTest)987 static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
988 {
989 #ifdef HAL_EFUSE_MEMORY
990 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
991 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
992 #endif
993 u16 btusedbytes;
994 u16 efuse_addr;
995 u8 bank, startBank;
996 u8 hworden = 0;
997 u8 efuse_data, word_cnts = 0;
998 u16 retU2 = 0;
999
1000 if (bPseudoTest) {
1001 #ifdef HAL_EFUSE_MEMORY
1002 btusedbytes = pEfuseHal->fakeBTEfuseUsedBytes;
1003 #else
1004 btusedbytes = fakeBTEfuseUsedBytes;
1005 #endif
1006 } else
1007 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&btusedbytes);
1008
1009 efuse_addr = (u16)((btusedbytes%EFUSE_BT_REAL_BANK_CONTENT_LEN));
1010 startBank = (u8)(1+(btusedbytes/EFUSE_BT_REAL_BANK_CONTENT_LEN));
1011
1012 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2, bPseudoTest);
1013
1014 for (bank = startBank; bank < 3; bank++) {
1015 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
1016 /* bank = EFUSE_MAX_BANK; */
1017 break;
1018
1019 /* only when bank is switched we have to reset the efuse_addr. */
1020 if (bank != startBank)
1021 efuse_addr = 0;
1022
1023 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1024 if (efuse_OneByteRead(padapter, efuse_addr,
1025 &efuse_data, bPseudoTest) == false)
1026 /* bank = EFUSE_MAX_BANK; */
1027 break;
1028
1029 if (efuse_data == 0xFF)
1030 break;
1031
1032 if (EXT_HEADER(efuse_data)) {
1033 efuse_addr++;
1034 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
1035
1036 if (ALL_WORDS_DISABLED(efuse_data)) {
1037 efuse_addr++;
1038 continue;
1039 }
1040
1041 hworden = efuse_data & 0x0F;
1042 } else {
1043 hworden = efuse_data & 0x0F;
1044 }
1045
1046 word_cnts = Efuse_CalculateWordCnts(hworden);
1047 /* read next header */
1048 efuse_addr += (word_cnts*2)+1;
1049 }
1050
1051 /* Check if we need to check next bank efuse */
1052 if (efuse_addr < retU2)
1053 break; /* don't need to check next bank. */
1054 }
1055
1056 retU2 = ((bank-1)*EFUSE_BT_REAL_BANK_CONTENT_LEN)+efuse_addr;
1057 if (bPseudoTest) {
1058 pEfuseHal->fakeBTEfuseUsedBytes = retU2;
1059 } else {
1060 pEfuseHal->BTEfuseUsedBytes = retU2;
1061 }
1062
1063 return retU2;
1064 }
1065
Hal_EfuseGetCurrentSize(struct adapter * padapter,u8 efuseType,bool bPseudoTest)1066 u16 Hal_EfuseGetCurrentSize(
1067 struct adapter *padapter, u8 efuseType, bool bPseudoTest
1068 )
1069 {
1070 u16 ret = 0;
1071
1072 if (efuseType == EFUSE_WIFI)
1073 ret = hal_EfuseGetCurrentSize_WiFi(padapter, bPseudoTest);
1074 else
1075 ret = hal_EfuseGetCurrentSize_BT(padapter, bPseudoTest);
1076
1077 return ret;
1078 }
1079
Hal_EfuseWordEnableDataWrite(struct adapter * padapter,u16 efuse_addr,u8 word_en,u8 * data,bool bPseudoTest)1080 static u8 Hal_EfuseWordEnableDataWrite(
1081 struct adapter *padapter,
1082 u16 efuse_addr,
1083 u8 word_en,
1084 u8 *data,
1085 bool bPseudoTest
1086 )
1087 {
1088 u16 tmpaddr = 0;
1089 u16 start_addr = efuse_addr;
1090 u8 badworden = 0x0F;
1091 u8 tmpdata[PGPKT_DATA_SIZE];
1092
1093 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
1094
1095 if (!(word_en & BIT(0))) {
1096 tmpaddr = start_addr;
1097 efuse_OneByteWrite(padapter, start_addr++, data[0], bPseudoTest);
1098 efuse_OneByteWrite(padapter, start_addr++, data[1], bPseudoTest);
1099
1100 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[0], bPseudoTest);
1101 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[1], bPseudoTest);
1102 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
1103 badworden &= (~BIT(0));
1104 }
1105 }
1106 if (!(word_en & BIT(1))) {
1107 tmpaddr = start_addr;
1108 efuse_OneByteWrite(padapter, start_addr++, data[2], bPseudoTest);
1109 efuse_OneByteWrite(padapter, start_addr++, data[3], bPseudoTest);
1110
1111 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[2], bPseudoTest);
1112 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[3], bPseudoTest);
1113 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1114 badworden &= (~BIT(1));
1115 }
1116 }
1117
1118 if (!(word_en & BIT(2))) {
1119 tmpaddr = start_addr;
1120 efuse_OneByteWrite(padapter, start_addr++, data[4], bPseudoTest);
1121 efuse_OneByteWrite(padapter, start_addr++, data[5], bPseudoTest);
1122
1123 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[4], bPseudoTest);
1124 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[5], bPseudoTest);
1125 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1126 badworden &= (~BIT(2));
1127 }
1128 }
1129
1130 if (!(word_en & BIT(3))) {
1131 tmpaddr = start_addr;
1132 efuse_OneByteWrite(padapter, start_addr++, data[6], bPseudoTest);
1133 efuse_OneByteWrite(padapter, start_addr++, data[7], bPseudoTest);
1134
1135 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[6], bPseudoTest);
1136 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[7], bPseudoTest);
1137 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1138 badworden &= (~BIT(3));
1139 }
1140 }
1141
1142 return badworden;
1143 }
1144
ReadChipVersion8723B(struct adapter * padapter)1145 static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
1146 {
1147 u32 value32;
1148 struct hal_version ChipVersion;
1149 struct hal_com_data *pHalData;
1150
1151 /* YJ, TODO, move read chip type here */
1152 pHalData = GET_HAL_DATA(padapter);
1153
1154 value32 = rtw_read32(padapter, REG_SYS_CFG);
1155 ChipVersion.ICType = CHIP_8723B;
1156 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1157 ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1158 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1159
1160 /* For regulator mode. by tynli. 2011.01.14 */
1161 pHalData->RegulatorMode = ((value32 & SPS_SEL) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1162
1163 value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
1164 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20); /* ROM code version. */
1165
1166 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1167 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1168 value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1169 pHalData->MultiFunc |= ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1170 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1171 pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1172 pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
1173
1174 dump_chip_info(ChipVersion);
1175
1176 pHalData->VersionID = ChipVersion;
1177
1178 return ChipVersion;
1179 }
1180
rtl8723b_read_chip_version(struct adapter * padapter)1181 void rtl8723b_read_chip_version(struct adapter *padapter)
1182 {
1183 ReadChipVersion8723B(padapter);
1184 }
1185
rtl8723b_InitBeaconParameters(struct adapter * padapter)1186 void rtl8723b_InitBeaconParameters(struct adapter *padapter)
1187 {
1188 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1189 u16 val16;
1190 u8 val8 = DIS_TSF_UDT;
1191
1192
1193 val16 = val8 | (val8 << 8); /* port0 and port1 */
1194
1195 /* Enable prot0 beacon function for PSTDMA */
1196 val16 |= EN_BCN_FUNCTION;
1197
1198 rtw_write16(padapter, REG_BCN_CTRL, val16);
1199
1200 /* TODO: Remove these magic number */
1201 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
1202 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1203 /* so don't set this register on STA mode. */
1204 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
1205 rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME_8723B); /* 5ms */
1206 rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME_8723B); /* 2ms */
1207
1208 /* Suggested by designer timchen. Change beacon AIFS to the largest number */
1209 /* because test chip does not contension before sending beacon. by tynli. 2009.11.03 */
1210 rtw_write16(padapter, REG_BCNTCFG, 0x660F);
1211
1212 pHalData->RegBcnCtrlVal = rtw_read8(padapter, REG_BCN_CTRL);
1213 pHalData->RegTxPause = rtw_read8(padapter, REG_TXPAUSE);
1214 pHalData->RegFwHwTxQCtrl = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2);
1215 pHalData->RegReg542 = rtw_read8(padapter, REG_TBTT_PROHIBIT+2);
1216 pHalData->RegCR_1 = rtw_read8(padapter, REG_CR+1);
1217 }
1218
_InitBurstPktLen_8723BS(struct adapter * Adapter)1219 void _InitBurstPktLen_8723BS(struct adapter *Adapter)
1220 {
1221 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1222
1223 rtw_write8(Adapter, 0x4c7, rtw_read8(Adapter, 0x4c7)|BIT(7)); /* enable single pkt ampdu */
1224 rtw_write8(Adapter, REG_RX_PKT_LIMIT_8723B, 0x18); /* for VHT packet length 11K */
1225 rtw_write8(Adapter, REG_MAX_AGGR_NUM_8723B, 0x1F);
1226 rtw_write8(Adapter, REG_PIFS_8723B, 0x00);
1227 rtw_write8(Adapter, REG_FWHW_TXQ_CTRL_8723B, rtw_read8(Adapter, REG_FWHW_TXQ_CTRL)&(~BIT(7)));
1228 if (pHalData->AMPDUBurstMode)
1229 rtw_write8(Adapter, REG_AMPDU_BURST_MODE_8723B, 0x5F);
1230 rtw_write8(Adapter, REG_AMPDU_MAX_TIME_8723B, 0x70);
1231
1232 /* ARFB table 9 for 11ac 5G 2SS */
1233 rtw_write32(Adapter, REG_ARFR0_8723B, 0x00000010);
1234 if (IS_NORMAL_CHIP(pHalData->VersionID))
1235 rtw_write32(Adapter, REG_ARFR0_8723B+4, 0xfffff000);
1236 else
1237 rtw_write32(Adapter, REG_ARFR0_8723B+4, 0x3e0ff000);
1238
1239 /* ARFB table 10 for 11ac 5G 1SS */
1240 rtw_write32(Adapter, REG_ARFR1_8723B, 0x00000010);
1241 rtw_write32(Adapter, REG_ARFR1_8723B+4, 0x003ff000);
1242 }
1243
ResumeTxBeacon(struct adapter * padapter)1244 static void ResumeTxBeacon(struct adapter *padapter)
1245 {
1246 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1247
1248 pHalData->RegFwHwTxQCtrl |= BIT(6);
1249 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
1250 rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0xff);
1251 pHalData->RegReg542 |= BIT(0);
1252 rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
1253 }
1254
StopTxBeacon(struct adapter * padapter)1255 static void StopTxBeacon(struct adapter *padapter)
1256 {
1257 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1258
1259 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1260 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
1261 rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0x64);
1262 pHalData->RegReg542 &= ~BIT(0);
1263 rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
1264
1265 CheckFwRsvdPageContent(padapter); /* 2010.06.23. Added by tynli. */
1266 }
1267
_BeaconFunctionEnable(struct adapter * padapter,u8 Enable,u8 Linked)1268 static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked)
1269 {
1270 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB);
1271 rtw_write8(padapter, REG_RD_CTRL+1, 0x6F);
1272 }
1273
rtl8723b_SetBeaconRelatedRegisters(struct adapter * padapter)1274 void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
1275 {
1276 u8 val8;
1277 u32 value32;
1278 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1279 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1280 u32 bcn_ctrl_reg;
1281
1282 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1283
1284 /* REG_BCN_INTERVAL */
1285 /* REG_BCNDMATIM */
1286 /* REG_ATIMWND */
1287 /* REG_TBTT_PROHIBIT */
1288 /* REG_DRVERLYINT */
1289 /* REG_BCN_MAX_ERR */
1290 /* REG_BCNTCFG (0x510) */
1291 /* REG_DUAL_TSF_RST */
1292 /* REG_BCN_CTRL (0x550) */
1293
1294
1295 bcn_ctrl_reg = REG_BCN_CTRL;
1296
1297 /* */
1298 /* ATIM window */
1299 /* */
1300 rtw_write16(padapter, REG_ATIMWND, 2);
1301
1302 /* */
1303 /* Beacon interval (in unit of TU). */
1304 /* */
1305 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
1306
1307 rtl8723b_InitBeaconParameters(padapter);
1308
1309 rtw_write8(padapter, REG_SLOT, 0x09);
1310
1311 /* */
1312 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1313 /* */
1314 value32 = rtw_read32(padapter, REG_TCR);
1315 value32 &= ~TSFRST;
1316 rtw_write32(padapter, REG_TCR, value32);
1317
1318 value32 |= TSFRST;
1319 rtw_write32(padapter, REG_TCR, value32);
1320
1321 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1322 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == true) {
1323 rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
1324 rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
1325 }
1326
1327 _BeaconFunctionEnable(padapter, true, true);
1328
1329 ResumeTxBeacon(padapter);
1330 val8 = rtw_read8(padapter, bcn_ctrl_reg);
1331 val8 |= DIS_BCNQ_SUB;
1332 rtw_write8(padapter, bcn_ctrl_reg, val8);
1333 }
1334
rtl8723b_SetHalODMVar(struct adapter * Adapter,enum hal_odm_variable eVariable,void * pValue1,bool bSet)1335 static void rtl8723b_SetHalODMVar(
1336 struct adapter *Adapter,
1337 enum hal_odm_variable eVariable,
1338 void *pValue1,
1339 bool bSet
1340 )
1341 {
1342 SetHalODMVar(Adapter, eVariable, pValue1, bSet);
1343 }
1344
hal_notch_filter_8723b(struct adapter * adapter,bool enable)1345 static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
1346 {
1347 if (enable)
1348 rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
1349 else
1350 rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
1351 }
1352
UpdateHalRAMask8723B(struct adapter * padapter,u32 mac_id,u8 rssi_level)1353 void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
1354 {
1355 u32 mask, rate_bitmap;
1356 u8 shortGIrate = false;
1357 struct sta_info *psta;
1358 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1359 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1360 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1361 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1362
1363 if (mac_id >= NUM_STA) /* CAM_SIZE */
1364 return;
1365
1366 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
1367 if (!psta)
1368 return;
1369
1370 shortGIrate = query_ra_short_GI(psta);
1371
1372 mask = psta->ra_mask;
1373
1374 rate_bitmap = 0xffffffff;
1375 rate_bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
1376
1377 mask &= rate_bitmap;
1378
1379 rate_bitmap = hal_btcoex_GetRaMask(padapter);
1380 mask &= ~rate_bitmap;
1381
1382 if (pHalData->fw_ractrl) {
1383 rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, psta->raid, psta->bw_mode, shortGIrate, mask);
1384 }
1385
1386 /* set correct initial date rate for each mac_id */
1387 pdmpriv->INIDATA_RATE[mac_id] = psta->init_rate;
1388 }
1389
1390
rtl8723b_set_hal_ops(struct hal_ops * pHalFunc)1391 void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
1392 {
1393 /* Efuse related function */
1394 pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
1395
1396 pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
1397
1398 pHalFunc->xmit_thread_handler = &hal_xmit_handler;
1399 pHalFunc->hal_notch_filter = &hal_notch_filter_8723b;
1400
1401 pHalFunc->c2h_handler = c2h_handler_8723b;
1402 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723b;
1403
1404 pHalFunc->fill_h2c_cmd = &FillH2CCmd8723B;
1405 }
1406
rtl8723b_InitAntenna_Selection(struct adapter * padapter)1407 void rtl8723b_InitAntenna_Selection(struct adapter *padapter)
1408 {
1409 u8 val;
1410
1411 val = rtw_read8(padapter, REG_LEDCFG2);
1412 /* Let 8051 take control antenna setting */
1413 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1414 rtw_write8(padapter, REG_LEDCFG2, val);
1415 }
1416
rtl8723b_init_default_value(struct adapter * padapter)1417 void rtl8723b_init_default_value(struct adapter *padapter)
1418 {
1419 struct hal_com_data *pHalData;
1420 struct dm_priv *pdmpriv;
1421 u8 i;
1422
1423
1424 pHalData = GET_HAL_DATA(padapter);
1425 pdmpriv = &pHalData->dmpriv;
1426
1427 padapter->registrypriv.wireless_mode = WIRELESS_11BG_24N;
1428
1429 /* init default value */
1430 pHalData->fw_ractrl = false;
1431 pHalData->bIQKInitialized = false;
1432 if (!adapter_to_pwrctl(padapter)->bkeepfwalive)
1433 pHalData->LastHMEBoxNum = 0;
1434
1435 pHalData->bIQKInitialized = false;
1436
1437 /* init dm default value */
1438 pdmpriv->TM_Trigger = 0;/* for IQK */
1439 /* pdmpriv->binitialized = false; */
1440 /* pdmpriv->prv_traffic_idx = 3; */
1441 /* pdmpriv->initialize = 0; */
1442
1443 pdmpriv->ThermalValue_HP_index = 0;
1444 for (i = 0; i < HP_THERMAL_NUM; i++)
1445 pdmpriv->ThermalValue_HP[i] = 0;
1446
1447 /* init Efuse variables */
1448 pHalData->EfuseUsedBytes = 0;
1449 pHalData->EfuseUsedPercentage = 0;
1450 #ifdef HAL_EFUSE_MEMORY
1451 pHalData->EfuseHal.fakeEfuseBank = 0;
1452 pHalData->EfuseHal.fakeEfuseUsedBytes = 0;
1453 memset(pHalData->EfuseHal.fakeEfuseContent, 0xFF, EFUSE_MAX_HW_SIZE);
1454 memset(pHalData->EfuseHal.fakeEfuseInitMap, 0xFF, EFUSE_MAX_MAP_LEN);
1455 memset(pHalData->EfuseHal.fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);
1456 pHalData->EfuseHal.BTEfuseUsedBytes = 0;
1457 pHalData->EfuseHal.BTEfuseUsedPercentage = 0;
1458 memset(pHalData->EfuseHal.BTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
1459 memset(pHalData->EfuseHal.BTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1460 memset(pHalData->EfuseHal.BTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1461 pHalData->EfuseHal.fakeBTEfuseUsedBytes = 0;
1462 memset(pHalData->EfuseHal.fakeBTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
1463 memset(pHalData->EfuseHal.fakeBTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1464 memset(pHalData->EfuseHal.fakeBTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1465 #endif
1466 }
1467
GetEEPROMSize8723B(struct adapter * padapter)1468 u8 GetEEPROMSize8723B(struct adapter *padapter)
1469 {
1470 u8 size = 0;
1471 u32 cr;
1472
1473 cr = rtw_read16(padapter, REG_9346CR);
1474 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1475 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1476
1477 return size;
1478 }
1479
1480 /* */
1481 /* */
1482 /* LLT R/W/Init function */
1483 /* */
1484 /* */
rtl8723b_InitLLTTable(struct adapter * padapter)1485 s32 rtl8723b_InitLLTTable(struct adapter *padapter)
1486 {
1487 unsigned long start, passing_time;
1488 u32 val32;
1489 s32 ret = _FAIL;
1490
1491 val32 = rtw_read32(padapter, REG_AUTO_LLT);
1492 val32 |= BIT_AUTO_INIT_LLT;
1493 rtw_write32(padapter, REG_AUTO_LLT, val32);
1494
1495 start = jiffies;
1496
1497 do {
1498 val32 = rtw_read32(padapter, REG_AUTO_LLT);
1499 if (!(val32 & BIT_AUTO_INIT_LLT)) {
1500 ret = _SUCCESS;
1501 break;
1502 }
1503
1504 passing_time = jiffies_to_msecs(jiffies - start);
1505 if (passing_time > 1000)
1506 break;
1507
1508 msleep(1);
1509 } while (1);
1510
1511 return ret;
1512 }
1513
hal_get_chnl_group_8723b(u8 channel,u8 * group)1514 static void hal_get_chnl_group_8723b(u8 channel, u8 *group)
1515 {
1516 if (1 <= channel && channel <= 2)
1517 *group = 0;
1518 else if (3 <= channel && channel <= 5)
1519 *group = 1;
1520 else if (6 <= channel && channel <= 8)
1521 *group = 2;
1522 else if (9 <= channel && channel <= 11)
1523 *group = 3;
1524 else if (12 <= channel && channel <= 14)
1525 *group = 4;
1526 }
1527
Hal_InitPGData(struct adapter * padapter,u8 * PROMContent)1528 void Hal_InitPGData(struct adapter *padapter, u8 *PROMContent)
1529 {
1530 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1531
1532 if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
1533 if (!pEEPROM->EepromOrEfuse) {
1534 /* Read EFUSE real map to shadow. */
1535 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
1536 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
1537 }
1538 } else {/* autoload fail */
1539 if (!pEEPROM->EepromOrEfuse)
1540 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
1541 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
1542 }
1543 }
1544
Hal_EfuseParseIDCode(struct adapter * padapter,u8 * hwinfo)1545 void Hal_EfuseParseIDCode(struct adapter *padapter, u8 *hwinfo)
1546 {
1547 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1548 /* struct hal_com_data *pHalData = GET_HAL_DATA(padapter); */
1549 u16 EEPROMId;
1550
1551
1552 /* Check 0x8129 again for making sure autoload status!! */
1553 EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
1554 if (EEPROMId != RTL_EEPROM_ID) {
1555 pEEPROM->bautoload_fail_flag = true;
1556 } else
1557 pEEPROM->bautoload_fail_flag = false;
1558 }
1559
Hal_ReadPowerValueFromPROM_8723B(struct adapter * Adapter,struct TxPowerInfo24G * pwrInfo24G,u8 * PROMContent,bool AutoLoadFail)1560 static void Hal_ReadPowerValueFromPROM_8723B(
1561 struct adapter *Adapter,
1562 struct TxPowerInfo24G *pwrInfo24G,
1563 u8 *PROMContent,
1564 bool AutoLoadFail
1565 )
1566 {
1567 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1568 u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_8723B, group, TxCount = 0;
1569
1570 memset(pwrInfo24G, 0, sizeof(struct TxPowerInfo24G));
1571
1572 if (0xFF == PROMContent[eeAddr+1])
1573 AutoLoadFail = true;
1574
1575 if (AutoLoadFail) {
1576 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
1577 /* 2.4G default value */
1578 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
1579 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
1580 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
1581 }
1582
1583 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
1584 if (TxCount == 0) {
1585 pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
1586 pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
1587 } else {
1588 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1589 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1590 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1591 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1592 }
1593 }
1594 }
1595
1596 return;
1597 }
1598
1599 pHalData->bTXPowerDataReadFromEEPORM = true; /* YJ, move, 120316 */
1600
1601 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
1602 /* 2 2.4G default value */
1603 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
1604 pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
1605 if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
1606 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
1607 }
1608
1609 for (group = 0; group < MAX_CHNL_GROUP_24G-1; group++) {
1610 pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
1611 if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
1612 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
1613 }
1614
1615 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
1616 if (TxCount == 0) {
1617 pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
1618 if (PROMContent[eeAddr] == 0xFF)
1619 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
1620 else {
1621 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
1622 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1623 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
1624 }
1625
1626 if (PROMContent[eeAddr] == 0xFF)
1627 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
1628 else {
1629 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
1630 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1631 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
1632 }
1633 pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
1634 eeAddr++;
1635 } else {
1636 if (PROMContent[eeAddr] == 0xFF)
1637 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1638 else {
1639 pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
1640 if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1641 pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
1642 }
1643
1644 if (PROMContent[eeAddr] == 0xFF)
1645 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1646 else {
1647 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
1648 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1649 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
1650 }
1651 eeAddr++;
1652
1653 if (PROMContent[eeAddr] == 0xFF)
1654 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1655 else {
1656 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
1657 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1658 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
1659 }
1660
1661 if (PROMContent[eeAddr] == 0xFF)
1662 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1663 else {
1664 pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
1665 if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
1666 pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
1667 }
1668 eeAddr++;
1669 }
1670 }
1671 }
1672 }
1673
1674
Hal_EfuseParseTxPowerInfo_8723B(struct adapter * padapter,u8 * PROMContent,bool AutoLoadFail)1675 void Hal_EfuseParseTxPowerInfo_8723B(
1676 struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail
1677 )
1678 {
1679 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1680 struct TxPowerInfo24G pwrInfo24G;
1681 u8 rfPath, ch, TxCount = 1;
1682
1683 Hal_ReadPowerValueFromPROM_8723B(padapter, &pwrInfo24G, PROMContent, AutoLoadFail);
1684 for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
1685 for (ch = 0 ; ch < CHANNEL_MAX_NUMBER; ch++) {
1686 u8 group = 0;
1687
1688 hal_get_chnl_group_8723b(ch + 1, &group);
1689
1690 if (ch == 14-1) {
1691 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][5];
1692 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
1693 } else {
1694 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
1695 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
1696 }
1697 }
1698
1699 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
1700 pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
1701 pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
1702 pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
1703 pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
1704 }
1705 }
1706
1707 /* 2010/10/19 MH Add Regulator recognize for CU. */
1708 if (!AutoLoadFail) {
1709 pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_8723B]&0x7); /* bit0~2 */
1710 if (PROMContent[EEPROM_RF_BOARD_OPTION_8723B] == 0xFF)
1711 pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION&0x7); /* bit0~2 */
1712 } else
1713 pHalData->EEPROMRegulatory = 0;
1714 }
1715
Hal_EfuseParseBTCoexistInfo_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1716 void Hal_EfuseParseBTCoexistInfo_8723B(
1717 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1718 )
1719 {
1720 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1721 u8 tempval;
1722 u32 tmpu4;
1723
1724 if (!AutoLoadFail) {
1725 tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1726 if (tmpu4 & BT_FUNC_EN)
1727 pHalData->EEPROMBluetoothCoexist = true;
1728 else
1729 pHalData->EEPROMBluetoothCoexist = false;
1730
1731 pHalData->EEPROMBluetoothType = BT_RTL8723B;
1732
1733 tempval = hwinfo[EEPROM_RF_BT_SETTING_8723B];
1734 if (tempval != 0xFF) {
1735 pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
1736 /* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */
1737 /* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */
1738 if (tempval & BIT(6))
1739 pHalData->ant_path = RF_PATH_B;
1740 else
1741 pHalData->ant_path = RF_PATH_A;
1742 } else {
1743 pHalData->EEPROMBluetoothAntNum = Ant_x1;
1744 if (pHalData->PackageType == PACKAGE_QFN68)
1745 pHalData->ant_path = RF_PATH_B;
1746 else
1747 pHalData->ant_path = RF_PATH_A;
1748 }
1749 } else {
1750 pHalData->EEPROMBluetoothCoexist = false;
1751 pHalData->EEPROMBluetoothType = BT_RTL8723B;
1752 pHalData->EEPROMBluetoothAntNum = Ant_x1;
1753 pHalData->ant_path = RF_PATH_A;
1754 }
1755
1756 if (padapter->registrypriv.ant_num > 0) {
1757 switch (padapter->registrypriv.ant_num) {
1758 case 1:
1759 pHalData->EEPROMBluetoothAntNum = Ant_x1;
1760 break;
1761 case 2:
1762 pHalData->EEPROMBluetoothAntNum = Ant_x2;
1763 break;
1764 default:
1765 break;
1766 }
1767 }
1768
1769 hal_btcoex_SetBTCoexist(padapter, pHalData->EEPROMBluetoothCoexist);
1770 hal_btcoex_SetPgAntNum(padapter, pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1);
1771 if (pHalData->EEPROMBluetoothAntNum == Ant_x1)
1772 hal_btcoex_SetSingleAntPath(padapter, pHalData->ant_path);
1773 }
1774
Hal_EfuseParseEEPROMVer_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1775 void Hal_EfuseParseEEPROMVer_8723B(
1776 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1777 )
1778 {
1779 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1780
1781 if (!AutoLoadFail)
1782 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723B];
1783 else
1784 pHalData->EEPROMVersion = 1;
1785 }
1786
1787
1788
Hal_EfuseParsePackageType_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1789 void Hal_EfuseParsePackageType_8723B(
1790 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1791 )
1792 {
1793 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1794 u8 package;
1795 u8 efuseContent;
1796
1797 Efuse_PowerSwitch(padapter, false, true);
1798 efuse_OneByteRead(padapter, 0x1FB, &efuseContent, false);
1799 Efuse_PowerSwitch(padapter, false, false);
1800
1801 package = efuseContent & 0x7;
1802 switch (package) {
1803 case 0x4:
1804 pHalData->PackageType = PACKAGE_TFBGA79;
1805 break;
1806 case 0x5:
1807 pHalData->PackageType = PACKAGE_TFBGA90;
1808 break;
1809 case 0x6:
1810 pHalData->PackageType = PACKAGE_QFN68;
1811 break;
1812 case 0x7:
1813 pHalData->PackageType = PACKAGE_TFBGA80;
1814 break;
1815
1816 default:
1817 pHalData->PackageType = PACKAGE_DEFAULT;
1818 break;
1819 }
1820 }
1821
1822
Hal_EfuseParseVoltage_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1823 void Hal_EfuseParseVoltage_8723B(
1824 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1825 )
1826 {
1827 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1828
1829 /* memcpy(pEEPROM->adjuseVoltageVal, &hwinfo[EEPROM_Voltage_ADDR_8723B], 1); */
1830 pEEPROM->adjuseVoltageVal = (hwinfo[EEPROM_Voltage_ADDR_8723B] & 0xf0) >> 4;
1831 }
1832
Hal_EfuseParseChnlPlan_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1833 void Hal_EfuseParseChnlPlan_8723B(
1834 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1835 )
1836 {
1837 padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan(
1838 padapter,
1839 hwinfo ? hwinfo[EEPROM_ChannelPlan_8723B] : 0xFF,
1840 padapter->registrypriv.channel_plan,
1841 RT_CHANNEL_DOMAIN_WORLD_NULL,
1842 AutoLoadFail
1843 );
1844
1845 Hal_ChannelPlanToRegulation(padapter, padapter->mlmepriv.ChannelPlan);
1846 }
1847
Hal_EfuseParseCustomerID_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1848 void Hal_EfuseParseCustomerID_8723B(
1849 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1850 )
1851 {
1852 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1853
1854 if (!AutoLoadFail)
1855 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723B];
1856 else
1857 pHalData->EEPROMCustomerID = 0;
1858 }
1859
Hal_EfuseParseAntennaDiversity_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1860 void Hal_EfuseParseAntennaDiversity_8723B(
1861 struct adapter *padapter,
1862 u8 *hwinfo,
1863 bool AutoLoadFail
1864 )
1865 {
1866 }
1867
Hal_EfuseParseXtal_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)1868 void Hal_EfuseParseXtal_8723B(
1869 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
1870 )
1871 {
1872 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1873
1874 if (!AutoLoadFail) {
1875 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_8723B];
1876 if (pHalData->CrystalCap == 0xFF)
1877 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; /* what value should 8812 set? */
1878 } else
1879 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B;
1880 }
1881
1882
Hal_EfuseParseThermalMeter_8723B(struct adapter * padapter,u8 * PROMContent,u8 AutoLoadFail)1883 void Hal_EfuseParseThermalMeter_8723B(
1884 struct adapter *padapter, u8 *PROMContent, u8 AutoLoadFail
1885 )
1886 {
1887 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1888
1889 /* */
1890 /* ThermalMeter from EEPROM */
1891 /* */
1892 if (!AutoLoadFail)
1893 pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_8723B];
1894 else
1895 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
1896
1897 if ((pHalData->EEPROMThermalMeter == 0xff) || AutoLoadFail) {
1898 pHalData->bAPKThermalMeterIgnore = true;
1899 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
1900 }
1901 }
1902
1903
Hal_ReadRFGainOffset(struct adapter * Adapter,u8 * PROMContent,bool AutoloadFail)1904 void Hal_ReadRFGainOffset(
1905 struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail
1906 )
1907 {
1908 /* */
1909 /* BB_RF Gain Offset from EEPROM */
1910 /* */
1911
1912 if (!AutoloadFail) {
1913 Adapter->eeprompriv.EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET];
1914 Adapter->eeprompriv.EEPROMRFGainVal = EFUSE_Read1Byte(Adapter, EEPROM_RF_GAIN_VAL);
1915 } else {
1916 Adapter->eeprompriv.EEPROMRFGainOffset = 0;
1917 Adapter->eeprompriv.EEPROMRFGainVal = 0xFF;
1918 }
1919 }
1920
BWMapping_8723B(struct adapter * Adapter,struct pkt_attrib * pattrib)1921 u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
1922 {
1923 u8 BWSettingOfDesc = 0;
1924 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1925
1926 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
1927 if (pattrib->bwmode == CHANNEL_WIDTH_40)
1928 BWSettingOfDesc = 1;
1929 else
1930 BWSettingOfDesc = 0;
1931 } else
1932 BWSettingOfDesc = 0;
1933
1934 /* if (pTcb->bBTTxPacket) */
1935 /* BWSettingOfDesc = 0; */
1936
1937 return BWSettingOfDesc;
1938 }
1939
SCMapping_8723B(struct adapter * Adapter,struct pkt_attrib * pattrib)1940 u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
1941 {
1942 u8 SCSettingOfDesc = 0;
1943 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1944
1945 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
1946 if (pattrib->bwmode == CHANNEL_WIDTH_40) {
1947 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
1948 } else if (pattrib->bwmode == CHANNEL_WIDTH_20) {
1949 if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) {
1950 SCSettingOfDesc = HT_DATA_SC_20_UPPER_OF_40MHZ;
1951 } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) {
1952 SCSettingOfDesc = HT_DATA_SC_20_LOWER_OF_40MHZ;
1953 } else {
1954 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
1955 }
1956 }
1957 } else {
1958 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
1959 }
1960
1961 return SCSettingOfDesc;
1962 }
1963
rtl8723b_cal_txdesc_chksum(struct tx_desc * ptxdesc)1964 static void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc)
1965 {
1966 u16 *usPtr = (u16 *)ptxdesc;
1967 u32 count;
1968 u32 index;
1969 u16 checksum = 0;
1970
1971
1972 /* Clear first */
1973 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
1974
1975 /* checksum is always calculated by first 32 bytes, */
1976 /* and it doesn't depend on TX DESC length. */
1977 /* Thomas, Lucas@SD4, 20130515 */
1978 count = 16;
1979
1980 for (index = 0; index < count; index++) {
1981 checksum |= le16_to_cpu(*(__le16 *)(usPtr + index));
1982 }
1983
1984 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
1985 }
1986
fill_txdesc_sectype(struct pkt_attrib * pattrib)1987 static u8 fill_txdesc_sectype(struct pkt_attrib *pattrib)
1988 {
1989 u8 sectype = 0;
1990 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
1991 switch (pattrib->encrypt) {
1992 /* SEC_TYPE */
1993 case _WEP40_:
1994 case _WEP104_:
1995 case _TKIP_:
1996 case _TKIP_WTMIC_:
1997 sectype = 1;
1998 break;
1999
2000 case _AES_:
2001 sectype = 3;
2002 break;
2003
2004 case _NO_PRIVACY_:
2005 default:
2006 break;
2007 }
2008 }
2009 return sectype;
2010 }
2011
fill_txdesc_vcs_8723b(struct adapter * padapter,struct pkt_attrib * pattrib,struct txdesc_8723b * ptxdesc)2012 static void fill_txdesc_vcs_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2013 {
2014 if (pattrib->vcs_mode) {
2015 switch (pattrib->vcs_mode) {
2016 case RTS_CTS:
2017 ptxdesc->rtsen = 1;
2018 /* ENABLE HW RTS */
2019 ptxdesc->hw_rts_en = 1;
2020 break;
2021
2022 case CTS_TO_SELF:
2023 ptxdesc->cts2self = 1;
2024 break;
2025
2026 case NONE_VCS:
2027 default:
2028 break;
2029 }
2030
2031 ptxdesc->rtsrate = 8; /* RTS Rate =24M */
2032 ptxdesc->rts_ratefb_lmt = 0xF;
2033
2034 if (padapter->mlmeextpriv.mlmext_info.preamble_mode == PREAMBLE_SHORT)
2035 ptxdesc->rts_short = 1;
2036
2037 /* Set RTS BW */
2038 if (pattrib->ht_en)
2039 ptxdesc->rts_sc = SCMapping_8723B(padapter, pattrib);
2040 }
2041 }
2042
fill_txdesc_phy_8723b(struct adapter * padapter,struct pkt_attrib * pattrib,struct txdesc_8723b * ptxdesc)2043 static void fill_txdesc_phy_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2044 {
2045 if (pattrib->ht_en) {
2046 ptxdesc->data_bw = BWMapping_8723B(padapter, pattrib);
2047
2048 ptxdesc->data_sc = SCMapping_8723B(padapter, pattrib);
2049 }
2050 }
2051
rtl8723b_fill_default_txdesc(struct xmit_frame * pxmitframe,u8 * pbuf)2052 static void rtl8723b_fill_default_txdesc(
2053 struct xmit_frame *pxmitframe, u8 *pbuf
2054 )
2055 {
2056 struct adapter *padapter;
2057 struct hal_com_data *pHalData;
2058 struct mlme_ext_priv *pmlmeext;
2059 struct mlme_ext_info *pmlmeinfo;
2060 struct pkt_attrib *pattrib;
2061 struct txdesc_8723b *ptxdesc;
2062 s32 bmcst;
2063
2064 memset(pbuf, 0, TXDESC_SIZE);
2065
2066 padapter = pxmitframe->padapter;
2067 pHalData = GET_HAL_DATA(padapter);
2068 pmlmeext = &padapter->mlmeextpriv;
2069 pmlmeinfo = &(pmlmeext->mlmext_info);
2070
2071 pattrib = &pxmitframe->attrib;
2072 bmcst = is_multicast_ether_addr(pattrib->ra);
2073
2074 ptxdesc = (struct txdesc_8723b *)pbuf;
2075
2076 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2077 u8 drv_userate = 0;
2078
2079 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2080 ptxdesc->rate_id = pattrib->raid;
2081 ptxdesc->qsel = pattrib->qsel;
2082 ptxdesc->seq = pattrib->seqnum;
2083
2084 ptxdesc->sectype = fill_txdesc_sectype(pattrib);
2085 fill_txdesc_vcs_8723b(padapter, pattrib, ptxdesc);
2086
2087 if (pattrib->icmp_pkt == 1 && padapter->registrypriv.wifi_spec == 1)
2088 drv_userate = 1;
2089
2090 if (
2091 (pattrib->ether_type != 0x888e) &&
2092 (pattrib->ether_type != 0x0806) &&
2093 (pattrib->ether_type != 0x88B4) &&
2094 (pattrib->dhcp_pkt != 1) &&
2095 (drv_userate != 1)
2096 ) {
2097 /* Non EAP & ARP & DHCP type data packet */
2098
2099 if (pattrib->ampdu_en) {
2100 ptxdesc->agg_en = 1; /* AGG EN */
2101 ptxdesc->max_agg_num = 0x1f;
2102 ptxdesc->ampdu_density = pattrib->ampdu_spacing;
2103 } else
2104 ptxdesc->bk = 1; /* AGG BK */
2105
2106 fill_txdesc_phy_8723b(padapter, pattrib, ptxdesc);
2107
2108 ptxdesc->data_ratefb_lmt = 0x1F;
2109
2110 if (!pHalData->fw_ractrl) {
2111 ptxdesc->userate = 1;
2112
2113 if (pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & BIT(7))
2114 ptxdesc->data_short = 1;
2115
2116 ptxdesc->datarate = pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & 0x7F;
2117 }
2118
2119 if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */
2120 ptxdesc->userate = 1;
2121 if (padapter->fix_rate & BIT(7))
2122 ptxdesc->data_short = 1;
2123
2124 ptxdesc->datarate = (padapter->fix_rate & 0x7F);
2125 ptxdesc->disdatafb = 1;
2126 }
2127
2128 if (pattrib->ldpc)
2129 ptxdesc->data_ldpc = 1;
2130 if (pattrib->stbc)
2131 ptxdesc->data_stbc = 1;
2132 } else {
2133 /* EAP data packet and ARP packet. */
2134 /* Use the 1M data rate to send the EAP/ARP packet. */
2135 /* This will maybe make the handshake smooth. */
2136
2137 ptxdesc->bk = 1; /* AGG BK */
2138 ptxdesc->userate = 1; /* driver uses rate */
2139 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2140 ptxdesc->data_short = 1;/* DATA_SHORT */
2141 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2142 }
2143
2144 ptxdesc->usb_txagg_num = pxmitframe->agg_num;
2145 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2146 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2147 ptxdesc->qsel = pattrib->qsel;
2148 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2149 ptxdesc->seq = pattrib->seqnum;
2150 ptxdesc->userate = 1; /* driver uses rate, 1M */
2151
2152 ptxdesc->mbssid = pattrib->mbssid & 0xF;
2153
2154 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2155 if (pattrib->retry_ctrl) {
2156 ptxdesc->data_rt_lmt = 6;
2157 } else {
2158 ptxdesc->data_rt_lmt = 12;
2159 }
2160
2161 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2162
2163 /* CCX-TXRPT ack for xmit mgmt frames. */
2164 if (pxmitframe->ack_report) {
2165 ptxdesc->spe_rpt = 1;
2166 ptxdesc->sw_define = (u8)(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.seq_no);
2167 }
2168 } else {
2169 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2170 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2171 ptxdesc->qsel = pattrib->qsel;
2172 ptxdesc->seq = pattrib->seqnum;
2173 ptxdesc->userate = 1; /* driver uses rate */
2174 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2175 }
2176
2177 ptxdesc->pktlen = pattrib->last_txcmdsz;
2178 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2179
2180 if (bmcst)
2181 ptxdesc->bmc = 1;
2182
2183 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS.
2184 * (1) The sequence number of each non-Qos frame / broadcast /
2185 * multicast / mgnt frame should be controlled by Hw because Fw
2186 * will also send null data which we cannot control when Fw LPS
2187 * enable.
2188 * --> default enable non-Qos data sequence number. 2010.06.23.
2189 * by tynli.
2190 * (2) Enable HW SEQ control for beacon packet, because we use
2191 * Hw beacon.
2192 * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos
2193 * packets.
2194 * 2010.06.23. Added by tynli.
2195 */
2196 if (!pattrib->qos_en) /* Hw set sequence number */
2197 ptxdesc->en_hwseq = 1; /* HWSEQ_EN */
2198 }
2199
2200 /* Description:
2201 *
2202 * Parameters:
2203 * pxmitframe xmitframe
2204 * pbuf where to fill tx desc
2205 */
rtl8723b_update_txdesc(struct xmit_frame * pxmitframe,u8 * pbuf)2206 void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2207 {
2208 struct tx_desc *pdesc;
2209
2210 rtl8723b_fill_default_txdesc(pxmitframe, pbuf);
2211 pdesc = (struct tx_desc *)pbuf;
2212 rtl8723b_cal_txdesc_chksum(pdesc);
2213 }
2214
2215 /* */
2216 /* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
2217 /* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
2218 /* Fw can tell Hw to send these packet derectly. */
2219 /* Added by tynli. 2009.10.15. */
2220 /* */
2221 /* type1:pspoll, type2:null */
rtl8723b_fill_fake_txdesc(struct adapter * padapter,u8 * pDesc,u32 BufferLen,u8 IsPsPoll,u8 IsBTQosNull,u8 bDataFrame)2222 void rtl8723b_fill_fake_txdesc(
2223 struct adapter *padapter,
2224 u8 *pDesc,
2225 u32 BufferLen,
2226 u8 IsPsPoll,
2227 u8 IsBTQosNull,
2228 u8 bDataFrame
2229 )
2230 {
2231 /* Clear all status */
2232 memset(pDesc, 0, TXDESC_SIZE);
2233
2234 SET_TX_DESC_FIRST_SEG_8723B(pDesc, 1); /* bFirstSeg; */
2235 SET_TX_DESC_LAST_SEG_8723B(pDesc, 1); /* bLastSeg; */
2236
2237 SET_TX_DESC_OFFSET_8723B(pDesc, 0x28); /* Offset = 32 */
2238
2239 SET_TX_DESC_PKT_SIZE_8723B(pDesc, BufferLen); /* Buffer size + command header */
2240 SET_TX_DESC_QUEUE_SEL_8723B(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
2241
2242 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error value by Hw. */
2243 if (IsPsPoll) {
2244 SET_TX_DESC_NAV_USE_HDR_8723B(pDesc, 1);
2245 } else {
2246 SET_TX_DESC_HWSEQ_EN_8723B(pDesc, 1); /* Hw set sequence number */
2247 SET_TX_DESC_HWSEQ_SEL_8723B(pDesc, 0);
2248 }
2249
2250 if (IsBTQosNull) {
2251 SET_TX_DESC_BT_INT_8723B(pDesc, 1);
2252 }
2253
2254 SET_TX_DESC_USE_RATE_8723B(pDesc, 1); /* use data rate which is set by Sw */
2255 SET_TX_DESC_OWN_8723B((u8 *)pDesc, 1);
2256
2257 SET_TX_DESC_TX_RATE_8723B(pDesc, DESC8723B_RATE1M);
2258
2259 /* */
2260 /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */
2261 /* */
2262 if (bDataFrame) {
2263 u32 EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;
2264
2265 switch (EncAlg) {
2266 case _NO_PRIVACY_:
2267 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2268 break;
2269 case _WEP40_:
2270 case _WEP104_:
2271 case _TKIP_:
2272 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x1);
2273 break;
2274 case _SMS4_:
2275 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x2);
2276 break;
2277 case _AES_:
2278 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x3);
2279 break;
2280 default:
2281 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2282 break;
2283 }
2284 }
2285
2286 /* USB interface drop packet if the checksum of descriptor isn't correct. */
2287 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
2288 rtl8723b_cal_txdesc_chksum((struct tx_desc *)pDesc);
2289 }
2290
hw_var_set_opmode(struct adapter * padapter,u8 variable,u8 * val)2291 static void hw_var_set_opmode(struct adapter *padapter, u8 variable, u8 *val)
2292 {
2293 u8 val8;
2294 u8 mode = *((u8 *)val);
2295
2296 {
2297 /* disable Port0 TSF update */
2298 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2299 val8 |= DIS_TSF_UDT;
2300 rtw_write8(padapter, REG_BCN_CTRL, val8);
2301
2302 /* set net_type */
2303 Set_MSR(padapter, mode);
2304
2305 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2306 {
2307 StopTxBeacon(padapter);
2308 }
2309
2310 /* disable atim wnd */
2311 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_ATIM);
2312 /* rtw_write8(padapter, REG_BCN_CTRL, 0x18); */
2313 } else if (mode == _HW_STATE_ADHOC_) {
2314 ResumeTxBeacon(padapter);
2315 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_BCNQ_SUB);
2316 } else if (mode == _HW_STATE_AP_) {
2317
2318 ResumeTxBeacon(padapter);
2319
2320 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|DIS_BCNQ_SUB);
2321
2322 /* Set RCR */
2323 rtw_write32(padapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0, reject ICV_ERR packet */
2324 /* enable to rx data frame */
2325 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2326 /* enable to rx ps-poll */
2327 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
2328
2329 /* Beacon Control related register for first time */
2330 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
2331
2332 /* rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); */
2333 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms */
2334 rtw_write16(padapter, REG_BCNTCFG, 0x00);
2335 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2336 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
2337
2338 /* reset TSF */
2339 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2340
2341 /* enable BCN0 Function for if1 */
2342 /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
2343 rtw_write8(padapter, REG_BCN_CTRL, (DIS_TSF_UDT|EN_BCN_FUNCTION|EN_TXBCN_RPT|DIS_BCNQ_SUB));
2344
2345 /* SW_BCN_SEL - Port0 */
2346 /* rtw_write8(Adapter, REG_DWBCN1_CTRL_8192E+2, rtw_read8(Adapter, REG_DWBCN1_CTRL_8192E+2) & ~BIT4); */
2347 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
2348
2349 /* select BCN on port 0 */
2350 rtw_write8(
2351 padapter,
2352 REG_CCK_CHECK_8723B,
2353 (rtw_read8(padapter, REG_CCK_CHECK_8723B)&~BIT_BCN_PORT_SEL)
2354 );
2355
2356 /* dis BCN1 ATIM WND if if2 is station */
2357 val8 = rtw_read8(padapter, REG_BCN_CTRL_1);
2358 val8 |= DIS_ATIM;
2359 rtw_write8(padapter, REG_BCN_CTRL_1, val8);
2360 }
2361 }
2362 }
2363
hw_var_set_macaddr(struct adapter * padapter,u8 variable,u8 * val)2364 static void hw_var_set_macaddr(struct adapter *padapter, u8 variable, u8 *val)
2365 {
2366 u8 idx = 0;
2367 u32 reg_macid = REG_MACID;
2368
2369 for (idx = 0 ; idx < 6; idx++)
2370 rtw_write8(GET_PRIMARY_ADAPTER(padapter), (reg_macid+idx), val[idx]);
2371 }
2372
hw_var_set_bssid(struct adapter * padapter,u8 variable,u8 * val)2373 static void hw_var_set_bssid(struct adapter *padapter, u8 variable, u8 *val)
2374 {
2375 u8 idx = 0;
2376 u32 reg_bssid = REG_BSSID;
2377
2378 for (idx = 0 ; idx < 6; idx++)
2379 rtw_write8(padapter, (reg_bssid+idx), val[idx]);
2380 }
2381
hw_var_set_bcn_func(struct adapter * padapter,u8 variable,u8 * val)2382 static void hw_var_set_bcn_func(struct adapter *padapter, u8 variable, u8 *val)
2383 {
2384 u32 bcn_ctrl_reg = REG_BCN_CTRL;
2385
2386 if (*(u8 *)val)
2387 rtw_write8(padapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
2388 else {
2389 u8 val8;
2390 val8 = rtw_read8(padapter, bcn_ctrl_reg);
2391 val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT);
2392
2393 /* Always enable port0 beacon function for PSTDMA */
2394 if (REG_BCN_CTRL == bcn_ctrl_reg)
2395 val8 |= EN_BCN_FUNCTION;
2396
2397 rtw_write8(padapter, bcn_ctrl_reg, val8);
2398 }
2399 }
2400
hw_var_set_correct_tsf(struct adapter * padapter,u8 variable,u8 * val)2401 static void hw_var_set_correct_tsf(struct adapter *padapter, u8 variable, u8 *val)
2402 {
2403 u8 val8;
2404 u64 tsf;
2405 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2406 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2407
2408 tsf = pmlmeext->TSFValue-do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024))-1024; /* us */
2409
2410 if (
2411 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
2412 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
2413 )
2414 StopTxBeacon(padapter);
2415
2416 {
2417 /* disable related TSF function */
2418 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2419 val8 &= ~EN_BCN_FUNCTION;
2420 rtw_write8(padapter, REG_BCN_CTRL, val8);
2421
2422 rtw_write32(padapter, REG_TSFTR, tsf);
2423 rtw_write32(padapter, REG_TSFTR+4, tsf>>32);
2424
2425 /* enable related TSF function */
2426 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2427 val8 |= EN_BCN_FUNCTION;
2428 rtw_write8(padapter, REG_BCN_CTRL, val8);
2429 }
2430
2431 if (
2432 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
2433 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
2434 )
2435 ResumeTxBeacon(padapter);
2436 }
2437
hw_var_set_mlme_disconnect(struct adapter * padapter,u8 variable,u8 * val)2438 static void hw_var_set_mlme_disconnect(struct adapter *padapter, u8 variable, u8 *val)
2439 {
2440 u8 val8;
2441
2442 /* Set RCR to not to receive data frame when NO LINK state */
2443 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); */
2444 /* reject all data frames */
2445 rtw_write16(padapter, REG_RXFLTMAP2, 0);
2446
2447 /* reset TSF */
2448 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2449
2450 /* disable update TSF */
2451 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2452 val8 |= DIS_TSF_UDT;
2453 rtw_write8(padapter, REG_BCN_CTRL, val8);
2454 }
2455
hw_var_set_mlme_sitesurvey(struct adapter * padapter,u8 variable,u8 * val)2456 static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 *val)
2457 {
2458 u32 value_rcr, rcr_clear_bit, reg_bcn_ctl;
2459 u16 value_rxfltmap2;
2460 u8 val8;
2461 struct hal_com_data *pHalData;
2462 struct mlme_priv *pmlmepriv;
2463
2464
2465 pHalData = GET_HAL_DATA(padapter);
2466 pmlmepriv = &padapter->mlmepriv;
2467
2468 reg_bcn_ctl = REG_BCN_CTRL;
2469
2470 rcr_clear_bit = RCR_CBSSID_BCN;
2471
2472 /* config RCR to receive different BSSID & not to receive data frame */
2473 value_rxfltmap2 = 0;
2474
2475 if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true))
2476 rcr_clear_bit = RCR_CBSSID_BCN;
2477
2478 value_rcr = rtw_read32(padapter, REG_RCR);
2479
2480 if (*((u8 *)val)) {
2481 /* under sitesurvey */
2482 value_rcr &= ~(rcr_clear_bit);
2483 rtw_write32(padapter, REG_RCR, value_rcr);
2484
2485 rtw_write16(padapter, REG_RXFLTMAP2, value_rxfltmap2);
2486
2487 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
2488 /* disable update TSF */
2489 val8 = rtw_read8(padapter, reg_bcn_ctl);
2490 val8 |= DIS_TSF_UDT;
2491 rtw_write8(padapter, reg_bcn_ctl, val8);
2492 }
2493
2494 /* Save original RRSR setting. */
2495 pHalData->RegRRSR = rtw_read16(padapter, REG_RRSR);
2496 } else {
2497 /* sitesurvey done */
2498 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
2499 /* enable to rx data frame */
2500 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2501
2502 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
2503 /* enable update TSF */
2504 val8 = rtw_read8(padapter, reg_bcn_ctl);
2505 val8 &= ~DIS_TSF_UDT;
2506 rtw_write8(padapter, reg_bcn_ctl, val8);
2507 }
2508
2509 value_rcr |= rcr_clear_bit;
2510 rtw_write32(padapter, REG_RCR, value_rcr);
2511
2512 /* Restore original RRSR setting. */
2513 rtw_write16(padapter, REG_RRSR, pHalData->RegRRSR);
2514 }
2515 }
2516
hw_var_set_mlme_join(struct adapter * padapter,u8 variable,u8 * val)2517 static void hw_var_set_mlme_join(struct adapter *padapter, u8 variable, u8 *val)
2518 {
2519 u8 val8;
2520 u16 val16;
2521 u32 val32;
2522 u8 RetryLimit = 0x30;
2523 u8 type = *(u8 *)val;
2524 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2525 struct eeprom_priv *pEEPROM;
2526
2527
2528 pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2529
2530 if (type == 0) { /* prepare to join */
2531 /* enable to rx data frame.Accept all data frame */
2532 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */
2533 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2534
2535 val32 = rtw_read32(padapter, REG_RCR);
2536 if (padapter->in_cta_test)
2537 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
2538 else
2539 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
2540 rtw_write32(padapter, REG_RCR, val32);
2541
2542 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
2543 RetryLimit = (pEEPROM->CustomerID == RT_CID_CCX) ? 7 : 48;
2544 else /* Ad-hoc Mode */
2545 RetryLimit = 0x7;
2546 } else if (type == 1) /* joinbss_event call back when join res < 0 */
2547 rtw_write16(padapter, REG_RXFLTMAP2, 0x00);
2548 else if (type == 2) { /* sta add event call back */
2549 /* enable update TSF */
2550 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2551 val8 &= ~DIS_TSF_UDT;
2552 rtw_write8(padapter, REG_BCN_CTRL, val8);
2553
2554 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
2555 RetryLimit = 0x7;
2556 }
2557
2558 val16 = (RetryLimit << RETRY_LIMIT_SHORT_SHIFT) | (RetryLimit << RETRY_LIMIT_LONG_SHIFT);
2559 rtw_write16(padapter, REG_RL, val16);
2560 }
2561
CCX_FwC2HTxRpt_8723b(struct adapter * padapter,u8 * pdata,u8 len)2562 void CCX_FwC2HTxRpt_8723b(struct adapter *padapter, u8 *pdata, u8 len)
2563 {
2564
2565 #define GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 6, 1)
2566 #define GET_8723B_C2H_TX_RPT_RETRY_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 7, 1)
2567
2568 if (GET_8723B_C2H_TX_RPT_RETRY_OVER(pdata) | GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(pdata)) {
2569 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
2570 }
2571 /*
2572 else if (seq_no != padapter->xmitpriv.seq_no) {
2573 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
2574 }
2575 */
2576 else
2577 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
2578 }
2579
c2h_id_filter_ccx_8723b(u8 * buf)2580 s32 c2h_id_filter_ccx_8723b(u8 *buf)
2581 {
2582 struct c2h_evt_hdr_88xx *c2h_evt = (struct c2h_evt_hdr_88xx *)buf;
2583 s32 ret = false;
2584 if (c2h_evt->id == C2H_CCX_TX_RPT)
2585 ret = true;
2586
2587 return ret;
2588 }
2589
2590
c2h_handler_8723b(struct adapter * padapter,u8 * buf)2591 s32 c2h_handler_8723b(struct adapter *padapter, u8 *buf)
2592 {
2593 struct c2h_evt_hdr_88xx *pC2hEvent = (struct c2h_evt_hdr_88xx *)buf;
2594 s32 ret = _SUCCESS;
2595
2596 if (!pC2hEvent) {
2597 ret = _FAIL;
2598 goto exit;
2599 }
2600
2601 switch (pC2hEvent->id) {
2602 case C2H_AP_RPT_RSP:
2603 break;
2604 case C2H_DBG:
2605 {
2606 }
2607 break;
2608
2609 case C2H_CCX_TX_RPT:
2610 /* CCX_FwC2HTxRpt(padapter, QueueID, pC2hEvent->payload); */
2611 break;
2612
2613 case C2H_EXT_RA_RPT:
2614 /* C2HExtRaRptHandler(padapter, pC2hEvent->payload, C2hEvent.CmdLen); */
2615 break;
2616
2617 case C2H_HW_INFO_EXCH:
2618 break;
2619
2620 case C2H_8723B_BT_INFO:
2621 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->plen, pC2hEvent->payload);
2622 break;
2623
2624 default:
2625 break;
2626 }
2627
2628 /* Clear event to notify FW we have read the command. */
2629 /* Note: */
2630 /* If this field isn't clear, the FW won't update the next command message. */
2631 /* rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); */
2632 exit:
2633 return ret;
2634 }
2635
process_c2h_event(struct adapter * padapter,struct c2h_evt_hdr_t * pC2hEvent,u8 * c2hBuf)2636 static void process_c2h_event(struct adapter *padapter, struct c2h_evt_hdr_t *pC2hEvent, u8 *c2hBuf)
2637 {
2638 if (!c2hBuf)
2639 return;
2640
2641 switch (pC2hEvent->CmdID) {
2642 case C2H_AP_RPT_RSP:
2643 break;
2644 case C2H_DBG:
2645 {
2646 }
2647 break;
2648
2649 case C2H_CCX_TX_RPT:
2650 /* CCX_FwC2HTxRpt(padapter, QueueID, tmpBuf); */
2651 break;
2652
2653 case C2H_EXT_RA_RPT:
2654 /* C2HExtRaRptHandler(padapter, tmpBuf, C2hEvent.CmdLen); */
2655 break;
2656
2657 case C2H_HW_INFO_EXCH:
2658 break;
2659
2660 case C2H_8723B_BT_INFO:
2661 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->CmdLen, c2hBuf);
2662 break;
2663
2664 default:
2665 break;
2666 }
2667 }
2668
C2HPacketHandler_8723B(struct adapter * padapter,u8 * pbuffer,u16 length)2669 void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length)
2670 {
2671 struct c2h_evt_hdr_t C2hEvent;
2672 u8 *tmpBuf = NULL;
2673 C2hEvent.CmdID = pbuffer[0];
2674 C2hEvent.CmdSeq = pbuffer[1];
2675 C2hEvent.CmdLen = length-2;
2676 tmpBuf = pbuffer+2;
2677
2678 process_c2h_event(padapter, &C2hEvent, tmpBuf);
2679 /* c2h_handler_8723b(padapter,&C2hEvent); */
2680 }
2681
SetHwReg8723B(struct adapter * padapter,u8 variable,u8 * val)2682 void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
2683 {
2684 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2685 u8 val8;
2686 u32 val32;
2687
2688 switch (variable) {
2689 case HW_VAR_MEDIA_STATUS:
2690 val8 = rtw_read8(padapter, MSR) & 0x0c;
2691 val8 |= *val;
2692 rtw_write8(padapter, MSR, val8);
2693 break;
2694
2695 case HW_VAR_MEDIA_STATUS1:
2696 val8 = rtw_read8(padapter, MSR) & 0x03;
2697 val8 |= *val << 2;
2698 rtw_write8(padapter, MSR, val8);
2699 break;
2700
2701 case HW_VAR_SET_OPMODE:
2702 hw_var_set_opmode(padapter, variable, val);
2703 break;
2704
2705 case HW_VAR_MAC_ADDR:
2706 hw_var_set_macaddr(padapter, variable, val);
2707 break;
2708
2709 case HW_VAR_BSSID:
2710 hw_var_set_bssid(padapter, variable, val);
2711 break;
2712
2713 case HW_VAR_BASIC_RATE:
2714 {
2715 struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info;
2716 u16 BrateCfg = 0;
2717 u16 rrsr_2g_force_mask = (RRSR_11M|RRSR_5_5M|RRSR_1M);
2718 u16 rrsr_2g_allow_mask = (RRSR_24M|RRSR_12M|RRSR_6M|RRSR_CCK_RATES);
2719
2720 HalSetBrateCfg(padapter, val, &BrateCfg);
2721
2722 /* apply force and allow mask */
2723 BrateCfg |= rrsr_2g_force_mask;
2724 BrateCfg &= rrsr_2g_allow_mask;
2725
2726 /* IOT consideration */
2727 if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) {
2728 /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */
2729 if ((BrateCfg & (RRSR_24M|RRSR_12M|RRSR_6M)) == 0)
2730 BrateCfg |= RRSR_6M;
2731 }
2732
2733 pHalData->BasicRateSet = BrateCfg;
2734
2735 /* Set RRSR rate table. */
2736 rtw_write16(padapter, REG_RRSR, BrateCfg);
2737 rtw_write8(padapter, REG_RRSR+2, rtw_read8(padapter, REG_RRSR+2)&0xf0);
2738 }
2739 break;
2740
2741 case HW_VAR_TXPAUSE:
2742 rtw_write8(padapter, REG_TXPAUSE, *val);
2743 break;
2744
2745 case HW_VAR_BCN_FUNC:
2746 hw_var_set_bcn_func(padapter, variable, val);
2747 break;
2748
2749 case HW_VAR_CORRECT_TSF:
2750 hw_var_set_correct_tsf(padapter, variable, val);
2751 break;
2752
2753 case HW_VAR_CHECK_BSSID:
2754 {
2755 u32 val32;
2756 val32 = rtw_read32(padapter, REG_RCR);
2757 if (*val)
2758 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
2759 else
2760 val32 &= ~(RCR_CBSSID_DATA|RCR_CBSSID_BCN);
2761 rtw_write32(padapter, REG_RCR, val32);
2762 }
2763 break;
2764
2765 case HW_VAR_MLME_DISCONNECT:
2766 hw_var_set_mlme_disconnect(padapter, variable, val);
2767 break;
2768
2769 case HW_VAR_MLME_SITESURVEY:
2770 hw_var_set_mlme_sitesurvey(padapter, variable, val);
2771
2772 hal_btcoex_ScanNotify(padapter, *val?true:false);
2773 break;
2774
2775 case HW_VAR_MLME_JOIN:
2776 hw_var_set_mlme_join(padapter, variable, val);
2777
2778 switch (*val) {
2779 case 0:
2780 /* prepare to join */
2781 hal_btcoex_ConnectNotify(padapter, true);
2782 break;
2783 case 1:
2784 /* joinbss_event callback when join res < 0 */
2785 hal_btcoex_ConnectNotify(padapter, false);
2786 break;
2787 case 2:
2788 /* sta add event callback */
2789 /* rtw_btcoex_MediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
2790 break;
2791 }
2792 break;
2793
2794 case HW_VAR_ON_RCR_AM:
2795 val32 = rtw_read32(padapter, REG_RCR);
2796 val32 |= RCR_AM;
2797 rtw_write32(padapter, REG_RCR, val32);
2798 break;
2799
2800 case HW_VAR_OFF_RCR_AM:
2801 val32 = rtw_read32(padapter, REG_RCR);
2802 val32 &= ~RCR_AM;
2803 rtw_write32(padapter, REG_RCR, val32);
2804 break;
2805
2806 case HW_VAR_BEACON_INTERVAL:
2807 rtw_write16(padapter, REG_BCN_INTERVAL, *((u16 *)val));
2808 break;
2809
2810 case HW_VAR_SLOT_TIME:
2811 rtw_write8(padapter, REG_SLOT, *val);
2812 break;
2813
2814 case HW_VAR_RESP_SIFS:
2815 /* SIFS_Timer = 0x0a0a0808; */
2816 /* RESP_SIFS for CCK */
2817 rtw_write8(padapter, REG_RESP_SIFS_CCK, val[0]); /* SIFS_T2T_CCK (0x08) */
2818 rtw_write8(padapter, REG_RESP_SIFS_CCK+1, val[1]); /* SIFS_R2T_CCK(0x08) */
2819 /* RESP_SIFS for OFDM */
2820 rtw_write8(padapter, REG_RESP_SIFS_OFDM, val[2]); /* SIFS_T2T_OFDM (0x0a) */
2821 rtw_write8(padapter, REG_RESP_SIFS_OFDM+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
2822 break;
2823
2824 case HW_VAR_ACK_PREAMBLE:
2825 {
2826 u8 regTmp = 0;
2827 u8 bShortPreamble = *val;
2828
2829 /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
2830 /* regTmp = (pHalData->nCur40MhzPrimeSC)<<5; */
2831 if (bShortPreamble)
2832 regTmp |= 0x80;
2833 rtw_write8(padapter, REG_RRSR+2, regTmp);
2834 }
2835 break;
2836
2837 case HW_VAR_CAM_EMPTY_ENTRY:
2838 {
2839 u8 ucIndex = *val;
2840 u8 i;
2841 u32 ulCommand = 0;
2842 u32 ulContent = 0;
2843 u32 ulEncAlgo = CAM_AES;
2844
2845 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
2846 /* filled id in CAM config 2 byte */
2847 if (i == 0) {
2848 ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2);
2849 /* ulContent |= CAM_VALID; */
2850 } else
2851 ulContent = 0;
2852
2853 /* polling bit, and No Write enable, and address */
2854 ulCommand = CAM_CONTENT_COUNT*ucIndex+i;
2855 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
2856 /* write content 0 is equal to mark as invalid */
2857 rtw_write32(padapter, WCAMI, ulContent); /* mdelay(40); */
2858 rtw_write32(padapter, RWCAM, ulCommand); /* mdelay(40); */
2859 }
2860 }
2861 break;
2862
2863 case HW_VAR_CAM_INVALID_ALL:
2864 rtw_write32(padapter, RWCAM, BIT(31)|BIT(30));
2865 break;
2866
2867 case HW_VAR_CAM_WRITE:
2868 {
2869 u32 cmd;
2870 u32 *cam_val = (u32 *)val;
2871
2872 rtw_write32(padapter, WCAMI, cam_val[0]);
2873
2874 cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
2875 rtw_write32(padapter, RWCAM, cmd);
2876 }
2877 break;
2878
2879 case HW_VAR_AC_PARAM_VO:
2880 rtw_write32(padapter, REG_EDCA_VO_PARAM, *((u32 *)val));
2881 break;
2882
2883 case HW_VAR_AC_PARAM_VI:
2884 rtw_write32(padapter, REG_EDCA_VI_PARAM, *((u32 *)val));
2885 break;
2886
2887 case HW_VAR_AC_PARAM_BE:
2888 pHalData->AcParam_BE = ((u32 *)(val))[0];
2889 rtw_write32(padapter, REG_EDCA_BE_PARAM, *((u32 *)val));
2890 break;
2891
2892 case HW_VAR_AC_PARAM_BK:
2893 rtw_write32(padapter, REG_EDCA_BK_PARAM, *((u32 *)val));
2894 break;
2895
2896 case HW_VAR_ACM_CTRL:
2897 {
2898 u8 ctrl = *((u8 *)val);
2899 u8 hwctrl = 0;
2900
2901 if (ctrl != 0) {
2902 hwctrl |= AcmHw_HwEn;
2903
2904 if (ctrl & BIT(1)) /* BE */
2905 hwctrl |= AcmHw_BeqEn;
2906
2907 if (ctrl & BIT(2)) /* VI */
2908 hwctrl |= AcmHw_ViqEn;
2909
2910 if (ctrl & BIT(3)) /* VO */
2911 hwctrl |= AcmHw_VoqEn;
2912 }
2913
2914 rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
2915 }
2916 break;
2917
2918 case HW_VAR_AMPDU_FACTOR:
2919 {
2920 u32 AMPDULen = (*((u8 *)val));
2921
2922 if (AMPDULen < HT_AGG_SIZE_32K)
2923 AMPDULen = (0x2000 << (*((u8 *)val)))-1;
2924 else
2925 AMPDULen = 0x7fff;
2926
2927 rtw_write32(padapter, REG_AMPDU_MAX_LENGTH_8723B, AMPDULen);
2928 }
2929 break;
2930
2931 case HW_VAR_H2C_FW_PWRMODE:
2932 {
2933 u8 psmode = *val;
2934
2935 /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
2936 /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
2937 if (psmode != PS_MODE_ACTIVE) {
2938 ODM_RF_Saving(&pHalData->odmpriv, true);
2939 }
2940
2941 /* if (psmode != PS_MODE_ACTIVE) { */
2942 /* rtl8723b_set_lowpwr_lps_cmd(padapter, true); */
2943 /* else { */
2944 /* rtl8723b_set_lowpwr_lps_cmd(padapter, false); */
2945 /* */
2946 rtl8723b_set_FwPwrMode_cmd(padapter, psmode);
2947 }
2948 break;
2949 case HW_VAR_H2C_PS_TUNE_PARAM:
2950 rtl8723b_set_FwPsTuneParam_cmd(padapter);
2951 break;
2952
2953 case HW_VAR_H2C_FW_JOINBSSRPT:
2954 rtl8723b_set_FwJoinBssRpt_cmd(padapter, *val);
2955 break;
2956
2957 case HW_VAR_INITIAL_GAIN:
2958 {
2959 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
2960 u32 rx_gain = *(u32 *)val;
2961
2962 if (rx_gain == 0xff) {/* restore rx gain */
2963 ODM_Write_DIG(&pHalData->odmpriv, pDigTable->BackupIGValue);
2964 } else {
2965 pDigTable->BackupIGValue = pDigTable->CurIGValue;
2966 ODM_Write_DIG(&pHalData->odmpriv, rx_gain);
2967 }
2968 }
2969 break;
2970
2971 case HW_VAR_EFUSE_USAGE:
2972 pHalData->EfuseUsedPercentage = *val;
2973 break;
2974
2975 case HW_VAR_EFUSE_BYTES:
2976 pHalData->EfuseUsedBytes = *((u16 *)val);
2977 break;
2978
2979 case HW_VAR_EFUSE_BT_USAGE:
2980 #ifdef HAL_EFUSE_MEMORY
2981 pHalData->EfuseHal.BTEfuseUsedPercentage = *val;
2982 #endif
2983 break;
2984
2985 case HW_VAR_EFUSE_BT_BYTES:
2986 #ifdef HAL_EFUSE_MEMORY
2987 pHalData->EfuseHal.BTEfuseUsedBytes = *((u16 *)val);
2988 #else
2989 BTEfuseUsedBytes = *((u16 *)val);
2990 #endif
2991 break;
2992
2993 case HW_VAR_FIFO_CLEARN_UP:
2994 {
2995 #define RW_RELEASE_EN BIT(18)
2996 #define RXDMA_IDLE BIT(17)
2997
2998 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2999 u8 trycnt = 100;
3000
3001 /* pause tx */
3002 rtw_write8(padapter, REG_TXPAUSE, 0xff);
3003
3004 /* keep sn */
3005 padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
3006
3007 if (!pwrpriv->bkeepfwalive) {
3008 /* RX DMA stop */
3009 val32 = rtw_read32(padapter, REG_RXPKT_NUM);
3010 val32 |= RW_RELEASE_EN;
3011 rtw_write32(padapter, REG_RXPKT_NUM, val32);
3012 do {
3013 val32 = rtw_read32(padapter, REG_RXPKT_NUM);
3014 val32 &= RXDMA_IDLE;
3015 if (val32)
3016 break;
3017 } while (--trycnt);
3018
3019 /* RQPN Load 0 */
3020 rtw_write16(padapter, REG_RQPN_NPQ, 0);
3021 rtw_write32(padapter, REG_RQPN, 0x80000000);
3022 mdelay(2);
3023 }
3024 }
3025 break;
3026
3027 case HW_VAR_APFM_ON_MAC:
3028 pHalData->bMacPwrCtrlOn = *val;
3029 break;
3030
3031 case HW_VAR_NAV_UPPER:
3032 {
3033 u32 usNavUpper = *((u32 *)val);
3034
3035 if (usNavUpper > HAL_NAV_UPPER_UNIT_8723B * 0xFF)
3036 break;
3037
3038 usNavUpper = DIV_ROUND_UP(usNavUpper,
3039 HAL_NAV_UPPER_UNIT_8723B);
3040 rtw_write8(padapter, REG_NAV_UPPER, (u8)usNavUpper);
3041 }
3042 break;
3043
3044 case HW_VAR_H2C_MEDIA_STATUS_RPT:
3045 {
3046 u16 mstatus_rpt = (*(u16 *)val);
3047 u8 mstatus, macId;
3048
3049 mstatus = (u8) (mstatus_rpt & 0xFF);
3050 macId = (u8)(mstatus_rpt >> 8);
3051 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, mstatus, macId);
3052 }
3053 break;
3054 case HW_VAR_BCN_VALID:
3055 {
3056 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
3057 val8 = rtw_read8(padapter, REG_TDECTRL+2);
3058 val8 |= BIT(0);
3059 rtw_write8(padapter, REG_TDECTRL+2, val8);
3060 }
3061 break;
3062
3063 case HW_VAR_DL_BCN_SEL:
3064 {
3065 /* SW_BCN_SEL - Port0 */
3066 val8 = rtw_read8(padapter, REG_DWBCN1_CTRL_8723B+2);
3067 val8 &= ~BIT(4);
3068 rtw_write8(padapter, REG_DWBCN1_CTRL_8723B+2, val8);
3069 }
3070 break;
3071
3072 case HW_VAR_DO_IQK:
3073 pHalData->bNeedIQK = true;
3074 break;
3075
3076 case HW_VAR_DL_RSVD_PAGE:
3077 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
3078 rtl8723b_download_BTCoex_AP_mode_rsvd_page(padapter);
3079 else
3080 rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
3081 break;
3082
3083 case HW_VAR_MACID_SLEEP:
3084 /* Input is MACID */
3085 val32 = *(u32 *)val;
3086 if (val32 > 31)
3087 break;
3088
3089 val8 = (u8)val32; /* macid is between 0~31 */
3090
3091 val32 = rtw_read32(padapter, REG_MACID_SLEEP);
3092 if (val32 & BIT(val8))
3093 break;
3094 val32 |= BIT(val8);
3095 rtw_write32(padapter, REG_MACID_SLEEP, val32);
3096 break;
3097
3098 case HW_VAR_MACID_WAKEUP:
3099 /* Input is MACID */
3100 val32 = *(u32 *)val;
3101 if (val32 > 31)
3102 break;
3103
3104 val8 = (u8)val32; /* macid is between 0~31 */
3105
3106 val32 = rtw_read32(padapter, REG_MACID_SLEEP);
3107 if (!(val32 & BIT(val8)))
3108 break;
3109 val32 &= ~BIT(val8);
3110 rtw_write32(padapter, REG_MACID_SLEEP, val32);
3111 break;
3112
3113 default:
3114 SetHwReg(padapter, variable, val);
3115 break;
3116 }
3117 }
3118
GetHwReg8723B(struct adapter * padapter,u8 variable,u8 * val)3119 void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
3120 {
3121 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3122 u8 val8;
3123 u16 val16;
3124
3125 switch (variable) {
3126 case HW_VAR_TXPAUSE:
3127 *val = rtw_read8(padapter, REG_TXPAUSE);
3128 break;
3129
3130 case HW_VAR_BCN_VALID:
3131 {
3132 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
3133 val8 = rtw_read8(padapter, REG_TDECTRL+2);
3134 *val = (BIT(0) & val8) ? true : false;
3135 }
3136 break;
3137
3138 case HW_VAR_FWLPS_RF_ON:
3139 {
3140 /* When we halt NIC, we should check if FW LPS is leave. */
3141 u32 valRCR;
3142
3143 if (
3144 padapter->bSurpriseRemoved ||
3145 (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)
3146 ) {
3147 /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */
3148 /* because Fw is unload. */
3149 *val = true;
3150 } else {
3151 valRCR = rtw_read32(padapter, REG_RCR);
3152 valRCR &= 0x00070000;
3153 if (valRCR)
3154 *val = false;
3155 else
3156 *val = true;
3157 }
3158 }
3159 break;
3160
3161 case HW_VAR_EFUSE_USAGE:
3162 *val = pHalData->EfuseUsedPercentage;
3163 break;
3164
3165 case HW_VAR_EFUSE_BYTES:
3166 *((u16 *)val) = pHalData->EfuseUsedBytes;
3167 break;
3168
3169 case HW_VAR_EFUSE_BT_USAGE:
3170 #ifdef HAL_EFUSE_MEMORY
3171 *val = pHalData->EfuseHal.BTEfuseUsedPercentage;
3172 #endif
3173 break;
3174
3175 case HW_VAR_EFUSE_BT_BYTES:
3176 #ifdef HAL_EFUSE_MEMORY
3177 *((u16 *)val) = pHalData->EfuseHal.BTEfuseUsedBytes;
3178 #else
3179 *((u16 *)val) = BTEfuseUsedBytes;
3180 #endif
3181 break;
3182
3183 case HW_VAR_APFM_ON_MAC:
3184 *val = pHalData->bMacPwrCtrlOn;
3185 break;
3186 case HW_VAR_CHK_HI_QUEUE_EMPTY:
3187 val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
3188 *val = (val16 & BIT(10)) ? true:false;
3189 break;
3190 default:
3191 GetHwReg(padapter, variable, val);
3192 break;
3193 }
3194 }
3195
3196 /* Description:
3197 * Change default setting of specified variable.
3198 */
SetHalDefVar8723B(struct adapter * padapter,enum hal_def_variable variable,void * pval)3199 u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3200 {
3201 u8 bResult = _SUCCESS;
3202
3203 switch (variable) {
3204 default:
3205 bResult = SetHalDefVar(padapter, variable, pval);
3206 break;
3207 }
3208
3209 return bResult;
3210 }
3211
3212 /* Description:
3213 * Query setting of specified variable.
3214 */
GetHalDefVar8723B(struct adapter * padapter,enum hal_def_variable variable,void * pval)3215 u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3216 {
3217 u8 bResult = _SUCCESS;
3218
3219 switch (variable) {
3220 case HAL_DEF_MAX_RECVBUF_SZ:
3221 *((u32 *)pval) = MAX_RECVBUF_SZ;
3222 break;
3223
3224 case HAL_DEF_RX_PACKET_OFFSET:
3225 *((u32 *)pval) = RXDESC_SIZE + DRVINFO_SZ*8;
3226 break;
3227
3228 case HW_VAR_MAX_RX_AMPDU_FACTOR:
3229 /* Stanley@BB.SD3 suggests 16K can get stable performance */
3230 /* The experiment was done on SDIO interface */
3231 /* coding by Lucas@20130730 */
3232 *(u32 *)pval = IEEE80211_HT_MAX_AMPDU_16K;
3233 break;
3234 case HAL_DEF_TX_LDPC:
3235 case HAL_DEF_RX_LDPC:
3236 *((u8 *)pval) = false;
3237 break;
3238 case HAL_DEF_TX_STBC:
3239 *((u8 *)pval) = 0;
3240 break;
3241 case HAL_DEF_RX_STBC:
3242 *((u8 *)pval) = 1;
3243 break;
3244 case HAL_DEF_EXPLICIT_BEAMFORMER:
3245 case HAL_DEF_EXPLICIT_BEAMFORMEE:
3246 *((u8 *)pval) = false;
3247 break;
3248
3249 case HW_DEF_RA_INFO_DUMP:
3250 {
3251 u8 mac_id = *(u8 *)pval;
3252 u32 cmd = 0x40000100 | mac_id;
3253
3254 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
3255 msleep(10);
3256 rtw_read32(padapter, 0x2F0); // info 1
3257
3258 cmd = 0x40000400 | mac_id;
3259 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
3260 msleep(10);
3261 rtw_read32(padapter, 0x2F0); // info 1
3262 rtw_read32(padapter, 0x2F4); // info 2
3263 rtw_read32(padapter, 0x2F8); // rate mask 1
3264 rtw_read32(padapter, 0x2FC); // rate mask 2
3265 }
3266 break;
3267
3268 case HAL_DEF_TX_PAGE_BOUNDARY:
3269 if (!padapter->registrypriv.wifi_spec) {
3270 *(u8 *)pval = TX_PAGE_BOUNDARY_8723B;
3271 } else {
3272 *(u8 *)pval = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B;
3273 }
3274 break;
3275
3276 case HAL_DEF_MACID_SLEEP:
3277 *(u8 *)pval = true; /* support macid sleep */
3278 break;
3279
3280 default:
3281 bResult = GetHalDefVar(padapter, variable, pval);
3282 break;
3283 }
3284
3285 return bResult;
3286 }
3287
rtl8723b_start_thread(struct adapter * padapter)3288 void rtl8723b_start_thread(struct adapter *padapter)
3289 {
3290 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3291
3292 xmitpriv->SdioXmitThread = kthread_run(rtl8723bs_xmit_thread, padapter, "RTWHALXT");
3293 }
3294
rtl8723b_stop_thread(struct adapter * padapter)3295 void rtl8723b_stop_thread(struct adapter *padapter)
3296 {
3297 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3298
3299 /* stop xmit_buf_thread */
3300 if (xmitpriv->SdioXmitThread) {
3301 complete(&xmitpriv->SdioXmitStart);
3302 wait_for_completion(&xmitpriv->SdioXmitTerminate);
3303 xmitpriv->SdioXmitThread = NULL;
3304 }
3305 }
3306