1 /******************************************************************************
3 * Copyright(c) 2009-2010 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 *****************************************************************************/
34 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
36 struct rtl_priv *rtlpriv = rtl_priv(hw);
40 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
42 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
43 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(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(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),
146 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
148 struct rtl_priv *rtlpriv = rtl_priv(hw);
154 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
155 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
156 (!(value32 & FWDL_ChkSum_rpt)));
158 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
159 RT_TRACE(COMP_ERR, DBG_EMERG,
160 "chksum report faill ! REG_MCUFWDL:0x%08x\n",
165 RT_TRACE(COMP_FW, DBG_TRACE,
166 "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32);
168 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
169 value32 |= MCUFWDL_RDY;
170 value32 &= ~WINTINI_RDY;
171 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
173 rtl92ee_firmware_selfreset(hw);
177 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
178 if (value32 & WINTINI_RDY) {
179 RT_TRACE(COMP_FW, DBG_LOUD,
180 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
186 udelay(FW_8192C_POLLING_DELAY*10);
188 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
190 RT_TRACE(COMP_ERR, DBG_EMERG,
191 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
198 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
200 struct rtl_priv *rtlpriv = rtl_priv(hw);
201 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
202 struct rtl92c_firmware_header *pfwheader;
206 enum version_8192e version = rtlhal->version;
208 if (!rtlhal->pfirmware)
211 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
212 rtlhal->fw_version = pfwheader->version;
213 rtlhal->fw_subversion = pfwheader->subversion;
214 pfwdata = (u8 *) rtlhal->pfirmware;
215 fwsize = rtlhal->fwsize;
216 RT_TRACE(COMP_FW, DBG_DMESG, "normal Firmware SIZE %d\n", fwsize);
218 if (IS_FW_HEADER_EXIST(pfwheader)) {
219 RT_TRACE(COMP_FW, DBG_DMESG,
220 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
221 pfwheader->version, pfwheader->signature,
222 (int)sizeof(struct rtl92c_firmware_header));
224 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
225 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
227 RT_TRACE(COMP_FW, DBG_DMESG,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader->signature);
232 if (rtlhal->b_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(COMP_ERR, DBG_EMERG,
245 "Firmware is not ready to run!\n");
247 RT_TRACE(COMP_FW, DBG_LOUD, "Firmware is ready to run!\n");
253 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
255 struct rtl_priv *rtlpriv = rtl_priv(hw);
259 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
260 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
265 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
266 u32 cmd_len, u8 *p_cmdbuffer)
268 struct rtl_priv *rtlpriv = rtl_priv(hw);
269 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
270 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
272 u16 box_reg = 0, box_extreg = 0;
274 bool isfw_read = false;
276 bool bwrite_sucess = false;
277 u8 wait_h2c_limmit = 100;
278 u8 boxcontent[4], boxextcontent[4];
279 u32 h2c_waitcounter = 0;
283 if (ppsc->dot11_psmode != EACTIVE ||
284 ppsc->inactive_pwrstate == ERFOFF) {
285 RT_TRACE(COMP_CMD, DBG_LOUD,
286 "FillH2CCommand8192E(): Return because RF is off!!!\n");
290 RT_TRACE(COMP_CMD, DBG_LOUD, "come in\n");
292 /* 1. Prevent race condition in setting H2C cmd.
293 * (copy from MgntActSet_RF_State().)
296 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
297 if (rtlhal->b_h2c_setinprogress) {
298 RT_TRACE(COMP_CMD, DBG_LOUD ,
299 "H2C set in progress! Wait to set..element_id(%d)\n",
302 while (rtlhal->b_h2c_setinprogress) {
303 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
306 RT_TRACE(COMP_CMD, DBG_LOUD,
307 "Wait 100 us (%d times)...\n",
311 if (h2c_waitcounter > 1000)
313 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
316 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
318 rtlhal->b_h2c_setinprogress = true;
319 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
324 while (!bwrite_sucess) {
325 /* cosa remove this because never reach this. */
326 /*wait_writeh2c_limmit--;
327 if (wait_writeh2c_limmit == 0) {
328 RT_TRACE(COMP_ERR, DBG_EMERG,
329 "Write H2C fail because no trigger for FW INT!\n");
333 /* 2. Find the last BOX number which has been writen. */
334 boxnum = rtlhal->last_hmeboxnum;
337 box_reg = REG_HMEBOX_0;
338 box_extreg = REG_HMEBOX_EXT_0;
341 box_reg = REG_HMEBOX_1;
342 box_extreg = REG_HMEBOX_EXT_1;
345 box_reg = REG_HMEBOX_2;
346 box_extreg = REG_HMEBOX_EXT_2;
349 box_reg = REG_HMEBOX_3;
350 box_extreg = REG_HMEBOX_EXT_3;
353 RT_TRACE(COMP_ERR, DBG_EMERG,
354 "switch case not processed\n");
358 /* 3. Check if the box content is empty. */
360 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
362 if (u1b_tmp != 0xea) {
365 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
366 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
367 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
370 if (isfw_read == true) {
371 wait_h2c_limmit = 100;
372 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
375 if (wait_h2c_limmit == 0) {
376 RT_TRACE(COMP_CMD, DBG_LOUD,
377 "Wating too long for FW read clear HMEBox(%d)!!!\n",
382 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw,
384 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
385 RT_TRACE(COMP_CMD, DBG_LOUD,
386 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
391 /* If Fw has not read the last
392 H2C cmd, break and give up this H2C. */
394 RT_TRACE(COMP_CMD, DBG_LOUD ,
395 "Write H2C reg BOX[%d] fail, Fw doesn't read\n",
399 /* 4. Fill the H2C cmd into box */
400 memset(boxcontent, 0, sizeof(boxcontent));
401 memset(boxextcontent, 0, sizeof(boxextcontent));
402 boxcontent[0] = element_id;
403 RT_TRACE(COMP_CMD, DBG_LOUD,
404 "Write element_id box_reg(%4x) = %2x\n",
405 box_reg, element_id);
411 /*boxcontent[0] &= ~(BIT(7));*/
412 memcpy((u8 *) (boxcontent) + 1,
413 p_cmdbuffer + buf_index, cmd_len);
415 for (idx = 0; idx < 4; idx++) {
416 rtl_write_byte(rtlpriv, box_reg + idx,
424 /*boxcontent[0] |= (BIT(7));*/
425 memcpy((u8 *) (boxextcontent),
426 p_cmdbuffer + buf_index+3, cmd_len-3);
427 memcpy((u8 *) (boxcontent) + 1,
428 p_cmdbuffer + buf_index, 3);
430 for (idx = 0; idx < 4; idx++) {
431 rtl_write_byte(rtlpriv, box_extreg + idx,
435 for (idx = 0; idx < 4; idx++) {
436 rtl_write_byte(rtlpriv, box_reg + idx,
441 RT_TRACE(COMP_ERR, DBG_EMERG,
442 "switch case not processed\n");
446 bwrite_sucess = true;
448 rtlhal->last_hmeboxnum = boxnum + 1;
449 if (rtlhal->last_hmeboxnum == 4)
450 rtlhal->last_hmeboxnum = 0;
452 RT_TRACE(COMP_CMD, DBG_LOUD, "pHalData->last_hmeboxnum = %d\n",
453 rtlhal->last_hmeboxnum);
456 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
457 rtlhal->b_h2c_setinprogress = false;
458 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
460 RT_TRACE(COMP_CMD, DBG_LOUD, "go out\n");
463 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
464 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
466 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
469 if (rtlhal->bfw_ready == false) {
470 RT_ASSERT(false, ("return H2C cmd because of Fw "
471 "download fail!!!\n"));
475 memset(tmp_cmdbuf, 0, 8);
476 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
477 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
482 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
485 struct rtl_priv *rtlpriv = rtl_priv(hw);
487 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
488 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
490 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
491 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
495 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
496 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
498 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
499 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
501 RT_TRACE(COMP_INIT, DBG_LOUD,
502 " _8051Reset92E(): 8051 reset success\n");
505 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
507 struct rtl_priv *rtlpriv = rtl_priv(hw);
508 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
509 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
510 u8 rlbm , power_state = 0;
511 RT_TRACE(COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
513 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
514 rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM = 2.*/
515 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
516 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
517 (rtlpriv->mac80211.p2p) ?
519 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
520 ppsc->reg_max_lps_awakeintvl);
521 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
522 if (mode == FW_PS_ACTIVE_MODE)
523 power_state |= FW_PWR_STATE_ACTIVE;
525 power_state |= FW_PWR_STATE_RF_OFF;
526 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
528 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
529 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
530 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
531 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
536 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
538 u8 parm[3] = { 0 , 0 , 0 };
539 /* parm[0]: bit0 = 0-->Disconnect, bit0 = 1-->Connect
540 * bit1 = 0-->update Media Status to MACID
541 * bit1 = 1-->update Media Status from MACID to MACID_End
542 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
543 * parm[2]: MACID_End*/
545 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
546 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
548 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
551 static bool _rtl92ee_cmd_send_packet(struct ieee80211_hw *hw,
554 struct rtl_priv *rtlpriv = rtl_priv(hw);
555 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
556 struct rtl8192_tx_ring *ring;
557 struct rtl_tx_desc *pdesc;
559 struct sk_buff *pskb = NULL;
561 ring = &rtlpci->tx_ring[BEACON_QUEUE];
563 pskb = __skb_dequeue(&ring->queue);
567 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
568 /*this is wrong, fill_tx_cmddesc needs update*/
569 pdesc = &ring->desc[0];
571 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
573 __skb_queue_tail(&ring->queue, skb);
575 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
580 #define BEACON_PG 0 /* ->1 */
583 #define PROBERSP_PG 4 /* ->5 */
585 #define TOTAL_RESERVED_PKT_LEN 768
589 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
591 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
592 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
593 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
596 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
597 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
598 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
599 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
600 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
604 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
605 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
606 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
609 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
628 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
646 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
647 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 /* page 4 probe_resp */
663 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
664 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
665 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
666 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
667 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
668 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
669 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
670 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
671 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
672 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
673 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
677 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 /* page 5 probe_resp */
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
703 struct rtl_priv *rtlpriv = rtl_priv(hw);
704 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
705 struct sk_buff *skb = NULL;
709 u8 u1RsvdPageLoc[5] = { 0 };
716 /*---------------------------------------------------------
718 ---------------------------------------------------------*/
719 beacon = &reserved_page_packet[BEACON_PG * 128];
720 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
721 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
723 /*-------------------------------------------------------
725 --------------------------------------------------------*/
726 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
727 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
728 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
729 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
731 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
733 /*--------------------------------------------------------
735 ---------------------------------------------------------*/
736 nullfunc = &reserved_page_packet[NULL_PG * 128];
737 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
738 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
739 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
741 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
743 /*---------------------------------------------------------
745 ----------------------------------------------------------*/
746 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
747 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
748 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
749 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
751 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
753 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
755 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
756 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
757 &reserved_page_packet[0], totalpacketlen);
758 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
759 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
763 skb = dev_alloc_skb(totalpacketlen);
764 memcpy((u8 *) skb_put(skb, totalpacketlen),
765 &reserved_page_packet, totalpacketlen);
767 rtstatus = _rtl92ee_cmd_send_packet(hw, skb);
773 RT_TRACE(COMP_POWER, DBG_LOUD,
774 "Set RSVD page location to Fw\n");
775 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
776 "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
777 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
778 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
780 RT_TRACE(COMP_ERR, DBG_WARNING,
781 "Set RSVD page location to Fw FAIL!!!!!!\n");
784 /*Shoud check FW support p2p or not.*/
785 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
787 u8 u1_ctwindow_period[1] = {ctwindow};
789 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
793 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
795 struct rtl_priv *rtlpriv = rtl_priv(hw);
796 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
797 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
798 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
799 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
802 u32 start_time, tsf_low;
804 switch (p2p_ps_state) {
806 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
807 memset(p2p_ps_offload, 0, 1);
810 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
811 /* update CTWindow value. */
812 if (p2pinfo->ctwindow > 0) {
813 p2p_ps_offload->CTWindow_En = 1;
814 ctwindow = p2pinfo->ctwindow;
815 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
817 /* hw only support 2 set of NoA */
818 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
819 /* To control the register setting for which NOA*/
820 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
822 p2p_ps_offload->NoA0_En = 1;
824 p2p_ps_offload->NoA1_En = 1;
825 /* config P2P NoA Descriptor Register */
826 rtl_write_dword(rtlpriv, 0x5E0,
827 p2pinfo->noa_duration[i]);
828 rtl_write_dword(rtlpriv, 0x5E4,
829 p2pinfo->noa_interval[i]);
831 /*Get Current
\14TSF value */
832 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
834 start_time = p2pinfo->noa_start_time[i];
835 if (p2pinfo->noa_count_type[i] != 1) {
836 while (start_time <= (tsf_low + (50 * 1024))) {
837 start_time += p2pinfo->noa_interval[i];
838 if (p2pinfo->noa_count_type[i] != 255)
839 p2pinfo->noa_count_type[i]--;
842 rtl_write_dword(rtlpriv, 0x5E8, start_time);
843 rtl_write_dword(rtlpriv, 0x5EC,
844 p2pinfo->noa_count_type[i]);
846 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
847 /* rst p2p circuit */
848 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
849 p2p_ps_offload->Offload_En = 1;
851 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
852 p2p_ps_offload->role = 1;
853 p2p_ps_offload->AllStaSleep = 0;
855 p2p_ps_offload->role = 0;
857 p2p_ps_offload->discovery = 0;
861 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
862 p2p_ps_offload->discovery = 1;
864 case P2P_PS_SCAN_DONE:
865 RT_TRACE(COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
866 p2p_ps_offload->discovery = 0;
867 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
873 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
874 (u8 *)p2p_ps_offload);
878 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
879 u8 *cmd_buf, u8 cmd_len)
881 u8 rate = cmd_buf[0] & 0x3F;
882 bool collision_state = cmd_buf[3] & BIT(0);
884 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
887 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
888 u8 c2h_cmd_len, u8 *tmp_buf)
890 struct rtl_priv *rtlpriv = rtl_priv(hw);
892 switch (c2h_cmd_id) {
894 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_DBG!!\n");
897 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8192E_TXBF!!\n");
899 case C2H_8192E_TX_REPORT:
900 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_TX_REPORT!\n");
902 case C2H_8192E_BT_INFO:
903 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_BT_INFO!!\n");
904 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
907 case C2H_8192E_BT_MP:
908 RT_TRACE(COMP_FW, DBG_TRACE, "[C2H], C2H_8723BE_BT_MP!!\n");
910 case C2H_8192E_RA_RPT:
911 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
914 RT_TRACE(COMP_FW, DBG_TRACE,
915 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id);
920 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
922 struct rtl_priv *rtlpriv = rtl_priv(hw);
923 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
926 c2h_cmd_id = buffer[0];
927 c2h_cmd_seq = buffer[1];
928 c2h_cmd_len = len - 2;
929 tmp_buf = buffer + 2;
931 RT_TRACE(COMP_FW, DBG_TRACE,
932 "[C2H packet], c2hCmdId = 0x%x, c2hCmdSeq = 0x%x, c2hCmdLen =%d\n",
933 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
935 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
936 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
938 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);