1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
35 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
37 struct rtl_priv *rtlpriv = rtl_priv(hw);
41 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
44 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
51 static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw,
52 const u8 *buffer, u32 size)
54 struct rtl_priv *rtlpriv = rtl_priv(hw);
55 u32 blocksize = sizeof(u32);
56 u8 *bufferptr = (u8 *)buffer;
57 u32 *pu4byteptr = (u32 *)buffer;
58 u32 i, offset, blockcount, remainsize;
60 blockcount = size / blocksize;
61 remainsize = size % blocksize;
63 for (i = 0; i < blockcount; i++) {
64 offset = i * blocksize;
65 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
70 offset = blockcount * blocksize;
72 for (i = 0; i < remainsize; i++) {
73 rtl_write_byte(rtlpriv,
74 (FW_8192C_START_ADDRESS + offset + i),
80 static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page,
81 const u8 *buffer, u32 size)
83 struct rtl_priv *rtlpriv = rtl_priv(hw);
85 u8 u8page = (u8)(page & 0x07);
87 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
88 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
90 _rtl92ee_fw_block_write(hw, buffer, size);
93 static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
96 u8 remain = (u8)(fwlen % 4);
98 remain = (remain == 0) ? 0 : (4 - remain);
109 static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
110 enum version_8192e version,
111 u8 *buffer, u32 size)
113 struct rtl_priv *rtlpriv = rtl_priv(hw);
114 u8 *bufferptr = (u8 *)buffer;
115 u32 pagenums, remainsize;
118 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
120 _rtl92ee_fill_dummy(bufferptr, &size);
122 pagenums = size / FW_8192C_PAGE_SIZE;
123 remainsize = size % FW_8192C_PAGE_SIZE;
126 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
127 "Page numbers should not greater then 8\n");
130 for (page = 0; page < pagenums; page++) {
131 offset = page * FW_8192C_PAGE_SIZE;
132 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
138 offset = pagenums * FW_8192C_PAGE_SIZE;
140 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
145 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
147 struct rtl_priv *rtlpriv = rtl_priv(hw);
153 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
154 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
155 (!(value32 & FWDL_CHKSUM_RPT)));
157 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
158 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
159 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
164 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
165 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
167 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
168 value32 |= MCUFWDL_RDY;
169 value32 &= ~WINTINI_RDY;
170 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
172 rtl92ee_firmware_selfreset(hw);
176 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
177 if (value32 & WINTINI_RDY) {
178 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
179 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
185 udelay(FW_8192C_POLLING_DELAY*10);
187 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
189 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
190 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
197 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
199 struct rtl_priv *rtlpriv = rtl_priv(hw);
200 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
201 struct rtlwifi_firmware_header *pfwheader;
205 enum version_8192e version = rtlhal->version;
207 if (!rtlhal->pfirmware)
210 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
211 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
212 rtlhal->fw_subversion = pfwheader->subversion;
213 pfwdata = (u8 *)rtlhal->pfirmware;
214 fwsize = rtlhal->fwsize;
215 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
216 "normal Firmware SIZE %d\n" , fwsize);
218 if (IS_FW_HEADER_EXIST(pfwheader)) {
219 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
220 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
221 pfwheader->version, pfwheader->signature,
222 (int)sizeof(struct rtlwifi_firmware_header));
224 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
225 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
227 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader->signature);
232 if (rtlhal->mac_func_enable) {
233 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
234 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
235 rtl92ee_firmware_selfreset(hw);
238 _rtl92ee_enable_fw_download(hw, true);
239 _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
240 _rtl92ee_enable_fw_download(hw, false);
242 err = _rtl92ee_fw_free_to_go(hw);
244 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
245 "Firmware is not ready to run!\n");
247 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
248 "Firmware is ready to run!\n");
254 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
256 struct rtl_priv *rtlpriv = rtl_priv(hw);
260 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
261 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
266 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
267 u32 cmd_len, u8 *cmdbuffer)
269 struct rtl_priv *rtlpriv = rtl_priv(hw);
270 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
271 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
273 u16 box_reg = 0, box_extreg = 0;
275 bool isfw_read = false;
277 bool bwrite_sucess = false;
278 u8 wait_h2c_limmit = 100;
279 u8 boxcontent[4], boxextcontent[4];
280 u32 h2c_waitcounter = 0;
284 if (ppsc->dot11_psmode != EACTIVE ||
285 ppsc->inactive_pwrstate == ERFOFF) {
286 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
287 "FillH2CCommand8192E(): Return because RF is off!!!\n");
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
293 /* 1. Prevent race condition in setting H2C cmd.
294 * (copy from MgntActSet_RF_State().)
297 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
298 if (rtlhal->h2c_setinprogress) {
299 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
300 "H2C set in progress! Wait to set..element_id(%d).\n",
303 while (rtlhal->h2c_setinprogress) {
304 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
307 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
308 "Wait 100 us (%d times)...\n",
312 if (h2c_waitcounter > 1000)
314 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
317 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
319 rtlhal->h2c_setinprogress = true;
320 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
325 while (!bwrite_sucess) {
326 /* 2. Find the last BOX number which has been writen. */
327 boxnum = rtlhal->last_hmeboxnum;
330 box_reg = REG_HMEBOX_0;
331 box_extreg = REG_HMEBOX_EXT_0;
334 box_reg = REG_HMEBOX_1;
335 box_extreg = REG_HMEBOX_EXT_1;
338 box_reg = REG_HMEBOX_2;
339 box_extreg = REG_HMEBOX_EXT_2;
342 box_reg = REG_HMEBOX_3;
343 box_extreg = REG_HMEBOX_EXT_3;
346 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
347 "switch case %#x not processed\n", boxnum);
351 /* 3. Check if the box content is empty. */
353 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
355 if (u1b_tmp != 0xea) {
358 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
359 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
360 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
364 wait_h2c_limmit = 100;
365 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
368 if (wait_h2c_limmit == 0) {
369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
370 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
376 _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
377 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
378 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
379 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
384 /* If Fw has not read the last
385 * H2C cmd, break and give up this H2C.
388 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
389 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
393 /* 4. Fill the H2C cmd into box */
394 memset(boxcontent, 0, sizeof(boxcontent));
395 memset(boxextcontent, 0, sizeof(boxextcontent));
396 boxcontent[0] = element_id;
397 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
398 "Write element_id box_reg(%4x) = %2x\n",
399 box_reg, element_id);
405 /*boxcontent[0] &= ~(BIT(7));*/
406 memcpy((u8 *)(boxcontent) + 1,
407 cmdbuffer + buf_index, cmd_len);
409 for (idx = 0; idx < 4; idx++) {
410 rtl_write_byte(rtlpriv, box_reg + idx,
418 /*boxcontent[0] |= (BIT(7));*/
419 memcpy((u8 *)(boxextcontent),
420 cmdbuffer + buf_index+3, cmd_len-3);
421 memcpy((u8 *)(boxcontent) + 1,
422 cmdbuffer + buf_index, 3);
424 for (idx = 0; idx < 4; idx++) {
425 rtl_write_byte(rtlpriv, box_extreg + idx,
429 for (idx = 0; idx < 4; idx++) {
430 rtl_write_byte(rtlpriv, box_reg + idx,
435 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
436 "switch case %#x not processed\n", cmd_len);
440 bwrite_sucess = true;
442 rtlhal->last_hmeboxnum = boxnum + 1;
443 if (rtlhal->last_hmeboxnum == 4)
444 rtlhal->last_hmeboxnum = 0;
446 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
447 "pHalData->last_hmeboxnum = %d\n",
448 rtlhal->last_hmeboxnum);
451 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
452 rtlhal->h2c_setinprogress = false;
453 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
455 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
458 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
459 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
461 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
464 if (!rtlhal->fw_ready) {
466 "return H2C cmd because of Fw download fail!!!\n");
470 memset(tmp_cmdbuf, 0, 8);
471 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
472 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
475 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
478 struct rtl_priv *rtlpriv = rtl_priv(hw);
480 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
481 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
483 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
488 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
489 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
491 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
492 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
494 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
495 " _8051Reset92E(): 8051 reset success .\n");
498 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
500 struct rtl_priv *rtlpriv = rtl_priv(hw);
501 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
502 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
503 u8 rlbm , power_state = 0;
505 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
507 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
508 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
509 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
510 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
511 (rtlpriv->mac80211.p2p) ?
513 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
514 ppsc->reg_max_lps_awakeintvl);
515 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
516 if (mode == FW_PS_ACTIVE_MODE)
517 power_state |= FW_PWR_STATE_ACTIVE;
519 power_state |= FW_PWR_STATE_RF_OFF;
520 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
522 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
523 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
524 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
525 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
529 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
531 u8 parm[3] = { 0 , 0 , 0 };
532 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
533 * bit1=0-->update Media Status to MACID
534 * bit1=1-->update Media Status from MACID to MACID_End
535 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
539 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
540 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
542 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
545 #define BEACON_PG 0 /* ->1 */
548 #define PROBERSP_PG 4 /* ->5 */
550 #define TOTAL_RESERVED_PKT_LEN 768
552 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
554 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
555 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
556 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
559 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
560 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
561 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
562 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
563 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
567 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
568 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
569 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
572 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
609 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
610 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 /* page 4 probe_resp */
626 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
627 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
628 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
629 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
630 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
631 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
632 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
633 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
634 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
635 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
636 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
640 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 /* page 5 probe_resp */
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
664 struct rtl_priv *rtlpriv = rtl_priv(hw);
665 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
666 struct sk_buff *skb = NULL;
669 u8 u1rsvdpageloc[5] = { 0 };
676 /*---------------------------------------------------------
678 *---------------------------------------------------------
680 beacon = &reserved_page_packet[BEACON_PG * 128];
681 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
682 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
684 /*-------------------------------------------------------
686 *--------------------------------------------------------
688 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
689 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
690 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
691 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
693 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
695 /*--------------------------------------------------------
697 *---------------------------------------------------------
699 nullfunc = &reserved_page_packet[NULL_PG * 128];
700 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
701 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
702 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
704 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
706 /*---------------------------------------------------------
708 *----------------------------------------------------------
710 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
711 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
712 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
713 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
715 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
717 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
719 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
720 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
721 &reserved_page_packet[0], totalpacketlen);
722 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
723 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
726 skb = dev_alloc_skb(totalpacketlen);
727 memcpy((u8 *)skb_put(skb, totalpacketlen),
728 &reserved_page_packet, totalpacketlen);
730 rtstatus = rtl_cmd_send_packet(hw, skb);
735 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
736 "Set RSVD page location to Fw.\n");
737 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
738 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
739 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
740 sizeof(u1rsvdpageloc), u1rsvdpageloc);
742 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
743 "Set RSVD page location to Fw FAIL!!!!!!.\n");
747 /*Shoud check FW support p2p or not.*/
748 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
750 u8 u1_ctwindow_period[1] = {ctwindow};
752 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
755 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
757 struct rtl_priv *rtlpriv = rtl_priv(hw);
758 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
759 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
760 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
761 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
764 u32 start_time, tsf_low;
766 switch (p2p_ps_state) {
768 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
769 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
772 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
773 /* update CTWindow value. */
774 if (p2pinfo->ctwindow > 0) {
775 p2p_ps_offload->ctwindow_en = 1;
776 ctwindow = p2pinfo->ctwindow;
777 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
779 /* hw only support 2 set of NoA */
780 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
781 /* To control the register setting for which NOA*/
782 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
784 p2p_ps_offload->noa0_en = 1;
786 p2p_ps_offload->noa1_en = 1;
787 /* config P2P NoA Descriptor Register */
788 rtl_write_dword(rtlpriv, 0x5E0,
789 p2pinfo->noa_duration[i]);
790 rtl_write_dword(rtlpriv, 0x5E4,
791 p2pinfo->noa_interval[i]);
793 /*Get Current TSF value */
794 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
796 start_time = p2pinfo->noa_start_time[i];
797 if (p2pinfo->noa_count_type[i] != 1) {
798 while (start_time <= (tsf_low + (50 * 1024))) {
799 start_time += p2pinfo->noa_interval[i];
800 if (p2pinfo->noa_count_type[i] != 255)
801 p2pinfo->noa_count_type[i]--;
804 rtl_write_dword(rtlpriv, 0x5E8, start_time);
805 rtl_write_dword(rtlpriv, 0x5EC,
806 p2pinfo->noa_count_type[i]);
808 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
809 /* rst p2p circuit */
810 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
811 p2p_ps_offload->offload_en = 1;
813 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
814 p2p_ps_offload->role = 1;
815 p2p_ps_offload->allstasleep = 0;
817 p2p_ps_offload->role = 0;
819 p2p_ps_offload->discovery = 0;
823 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
824 p2p_ps_offload->discovery = 1;
826 case P2P_PS_SCAN_DONE:
827 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
828 p2p_ps_offload->discovery = 0;
829 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
834 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
835 (u8 *)p2p_ps_offload);
838 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
839 u8 *cmd_buf, u8 cmd_len)
841 u8 rate = cmd_buf[0] & 0x3F;
842 bool collision_state = cmd_buf[3] & BIT(0);
844 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
847 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
848 u8 c2h_cmd_len, u8 *tmp_buf)
850 struct rtl_priv *rtlpriv = rtl_priv(hw);
852 switch (c2h_cmd_id) {
854 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
855 "[C2H], C2H_8723BE_DBG!!\n");
858 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
859 "[C2H], C2H_8192E_TXBF!!\n");
861 case C2H_8192E_TX_REPORT:
862 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
863 "[C2H], C2H_8723BE_TX_REPORT!\n");
865 case C2H_8192E_BT_INFO:
866 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
867 "[C2H], C2H_8723BE_BT_INFO!!\n");
868 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
871 case C2H_8192E_BT_MP:
872 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
873 "[C2H], C2H_8723BE_BT_MP!!\n");
875 case C2H_8192E_RA_RPT:
876 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
879 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
880 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
885 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
887 struct rtl_priv *rtlpriv = rtl_priv(hw);
888 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
891 c2h_cmd_id = buffer[0];
892 c2h_cmd_seq = buffer[1];
893 c2h_cmd_len = len - 2;
894 tmp_buf = buffer + 2;
896 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
897 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
898 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
900 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
901 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
903 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);