1f1d2b4d3SLarry Finger /******************************************************************************
2f1d2b4d3SLarry Finger  *
3f1d2b4d3SLarry Finger  * Copyright(c) 2009-2014  Realtek Corporation.
4f1d2b4d3SLarry Finger  *
5f1d2b4d3SLarry Finger  * This program is free software; you can redistribute it and/or modify it
6f1d2b4d3SLarry Finger  * under the terms of version 2 of the GNU General Public License as
7f1d2b4d3SLarry Finger  * published by the Free Software Foundation.
8f1d2b4d3SLarry Finger  *
9f1d2b4d3SLarry Finger  * This program is distributed in the hope that it will be useful, but WITHOUT
10f1d2b4d3SLarry Finger  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11f1d2b4d3SLarry Finger  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12f1d2b4d3SLarry Finger  * more details.
13f1d2b4d3SLarry Finger  *
14f1d2b4d3SLarry Finger  * The full GNU General Public License is included in this distribution in the
15f1d2b4d3SLarry Finger  * file called LICENSE.
16f1d2b4d3SLarry Finger  *
17f1d2b4d3SLarry Finger  * Contact Information:
18f1d2b4d3SLarry Finger  * wlanfae <wlanfae@realtek.com>
19f1d2b4d3SLarry Finger  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20f1d2b4d3SLarry Finger  * Hsinchu 300, Taiwan.
21f1d2b4d3SLarry Finger  *
22f1d2b4d3SLarry Finger  * Larry Finger <Larry.Finger@lwfinger.net>
23f1d2b4d3SLarry Finger  *
24f1d2b4d3SLarry Finger  *****************************************************************************/
25f1d2b4d3SLarry Finger 
26f1d2b4d3SLarry Finger #include "../wifi.h"
27f1d2b4d3SLarry Finger #include "../pci.h"
28f1d2b4d3SLarry Finger #include "../base.h"
29f1d2b4d3SLarry Finger #include "../core.h"
30f1d2b4d3SLarry Finger #include "reg.h"
31f1d2b4d3SLarry Finger #include "def.h"
32f1d2b4d3SLarry Finger #include "fw.h"
33f1d2b4d3SLarry Finger #include "dm.h"
34f1d2b4d3SLarry Finger 
35f1d2b4d3SLarry Finger static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
36f1d2b4d3SLarry Finger {
37f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
38f1d2b4d3SLarry Finger 	u8 tmp;
39f1d2b4d3SLarry Finger 
40f1d2b4d3SLarry Finger 	if (enable) {
41f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
42f1d2b4d3SLarry Finger 
43f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
44f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
45f1d2b4d3SLarry Finger 	} else {
46f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
48f1d2b4d3SLarry Finger 	}
49f1d2b4d3SLarry Finger }
50f1d2b4d3SLarry Finger 
51f1d2b4d3SLarry Finger static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw,
52f1d2b4d3SLarry Finger 				    const u8 *buffer, u32 size)
53f1d2b4d3SLarry Finger {
54f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
55f1d2b4d3SLarry Finger 	u32 blocksize = sizeof(u32);
56f1d2b4d3SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
57f1d2b4d3SLarry Finger 	u32 *pu4byteptr = (u32 *)buffer;
58f1d2b4d3SLarry Finger 	u32 i, offset, blockcount, remainsize;
59f1d2b4d3SLarry Finger 
60f1d2b4d3SLarry Finger 	blockcount = size / blocksize;
61f1d2b4d3SLarry Finger 	remainsize = size % blocksize;
62f1d2b4d3SLarry Finger 
63f1d2b4d3SLarry Finger 	for (i = 0; i < blockcount; i++) {
64f1d2b4d3SLarry Finger 		offset = i * blocksize;
65f1d2b4d3SLarry Finger 		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
66f1d2b4d3SLarry Finger 				*(pu4byteptr + i));
67f1d2b4d3SLarry Finger 	}
68f1d2b4d3SLarry Finger 
69f1d2b4d3SLarry Finger 	if (remainsize) {
70f1d2b4d3SLarry Finger 		offset = blockcount * blocksize;
71f1d2b4d3SLarry Finger 		bufferptr += offset;
72f1d2b4d3SLarry Finger 		for (i = 0; i < remainsize; i++) {
73f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv,
74f1d2b4d3SLarry Finger 				       (FW_8192C_START_ADDRESS + offset + i),
75f1d2b4d3SLarry Finger 				       *(bufferptr + i));
76f1d2b4d3SLarry Finger 		}
77f1d2b4d3SLarry Finger 	}
78f1d2b4d3SLarry Finger }
79f1d2b4d3SLarry Finger 
80f1d2b4d3SLarry Finger static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page,
81f1d2b4d3SLarry Finger 				   const u8 *buffer, u32 size)
82f1d2b4d3SLarry Finger {
83f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
84f1d2b4d3SLarry Finger 	u8 value8;
85f1d2b4d3SLarry Finger 	u8 u8page = (u8)(page & 0x07);
86f1d2b4d3SLarry Finger 
87f1d2b4d3SLarry Finger 	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
88f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
89f1d2b4d3SLarry Finger 
90f1d2b4d3SLarry Finger 	_rtl92ee_fw_block_write(hw, buffer, size);
91f1d2b4d3SLarry Finger }
92f1d2b4d3SLarry Finger 
93f1d2b4d3SLarry Finger static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
94f1d2b4d3SLarry Finger {
95f1d2b4d3SLarry Finger 	u32 fwlen = *pfwlen;
96f1d2b4d3SLarry Finger 	u8 remain = (u8)(fwlen % 4);
97f1d2b4d3SLarry Finger 
98f1d2b4d3SLarry Finger 	remain = (remain == 0) ? 0 : (4 - remain);
99f1d2b4d3SLarry Finger 
100f1d2b4d3SLarry Finger 	while (remain > 0) {
101f1d2b4d3SLarry Finger 		pfwbuf[fwlen] = 0;
102f1d2b4d3SLarry Finger 		fwlen++;
103f1d2b4d3SLarry Finger 		remain--;
104f1d2b4d3SLarry Finger 	}
105f1d2b4d3SLarry Finger 
106f1d2b4d3SLarry Finger 	*pfwlen = fwlen;
107f1d2b4d3SLarry Finger }
108f1d2b4d3SLarry Finger 
109f1d2b4d3SLarry Finger static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
110f1d2b4d3SLarry Finger 			      enum version_8192e version,
111f1d2b4d3SLarry Finger 			      u8 *buffer, u32 size)
112f1d2b4d3SLarry Finger {
113f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
114f1d2b4d3SLarry Finger 	u8 *bufferptr = (u8 *)buffer;
115f1d2b4d3SLarry Finger 	u32 pagenums, remainsize;
116f1d2b4d3SLarry Finger 	u32 page, offset;
117f1d2b4d3SLarry Finger 
118f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
119f1d2b4d3SLarry Finger 
120f1d2b4d3SLarry Finger 	_rtl92ee_fill_dummy(bufferptr, &size);
121f1d2b4d3SLarry Finger 
122f1d2b4d3SLarry Finger 	pagenums = size / FW_8192C_PAGE_SIZE;
123f1d2b4d3SLarry Finger 	remainsize = size % FW_8192C_PAGE_SIZE;
124f1d2b4d3SLarry Finger 
125a44f59d6SLarry Finger 	if (pagenums > 8)
126a44f59d6SLarry Finger 		pr_err("Page numbers should not greater then 8\n");
127f1d2b4d3SLarry Finger 
128f1d2b4d3SLarry Finger 	for (page = 0; page < pagenums; page++) {
129f1d2b4d3SLarry Finger 		offset = page * FW_8192C_PAGE_SIZE;
130f1d2b4d3SLarry Finger 		_rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
131f1d2b4d3SLarry Finger 				       FW_8192C_PAGE_SIZE);
132f1d2b4d3SLarry Finger 		udelay(2);
133f1d2b4d3SLarry Finger 	}
134f1d2b4d3SLarry Finger 
135f1d2b4d3SLarry Finger 	if (remainsize) {
136f1d2b4d3SLarry Finger 		offset = pagenums * FW_8192C_PAGE_SIZE;
137f1d2b4d3SLarry Finger 		page = pagenums;
138f1d2b4d3SLarry Finger 		_rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
139f1d2b4d3SLarry Finger 				       remainsize);
140f1d2b4d3SLarry Finger 	}
141f1d2b4d3SLarry Finger }
142f1d2b4d3SLarry Finger 
143f1d2b4d3SLarry Finger static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
144f1d2b4d3SLarry Finger {
145f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
146f1d2b4d3SLarry Finger 	int err = -EIO;
147f1d2b4d3SLarry Finger 	u32 counter = 0;
148f1d2b4d3SLarry Finger 	u32 value32;
149f1d2b4d3SLarry Finger 
150f1d2b4d3SLarry Finger 	do {
151f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
152f1d2b4d3SLarry Finger 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
153f1d2b4d3SLarry Finger 		 (!(value32 & FWDL_CHKSUM_RPT)));
154f1d2b4d3SLarry Finger 
155f1d2b4d3SLarry Finger 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
156a44f59d6SLarry Finger 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
157f1d2b4d3SLarry Finger 		       value32);
158f1d2b4d3SLarry Finger 		goto exit;
159f1d2b4d3SLarry Finger 	}
160f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
161f1d2b4d3SLarry Finger 	value32 |= MCUFWDL_RDY;
162f1d2b4d3SLarry Finger 	value32 &= ~WINTINI_RDY;
163f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
164f1d2b4d3SLarry Finger 
165f1d2b4d3SLarry Finger 	rtl92ee_firmware_selfreset(hw);
166f1d2b4d3SLarry Finger 	counter = 0;
167f1d2b4d3SLarry Finger 
168f1d2b4d3SLarry Finger 	do {
169f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
170c93ac39dSLarry Finger 		if (value32 & WINTINI_RDY)
171c93ac39dSLarry Finger 			return 0;
172f1d2b4d3SLarry Finger 
173f1d2b4d3SLarry Finger 		udelay(FW_8192C_POLLING_DELAY*10);
174f1d2b4d3SLarry Finger 
175f1d2b4d3SLarry Finger 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
176f1d2b4d3SLarry Finger 
177a44f59d6SLarry Finger 	pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
178f1d2b4d3SLarry Finger 	       value32, counter);
179f1d2b4d3SLarry Finger 
180f1d2b4d3SLarry Finger exit:
181f1d2b4d3SLarry Finger 	return err;
182f1d2b4d3SLarry Finger }
183f1d2b4d3SLarry Finger 
184f1d2b4d3SLarry Finger int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
185f1d2b4d3SLarry Finger {
186f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
187f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
188f1d2b4d3SLarry Finger 	struct rtlwifi_firmware_header *pfwheader;
189f1d2b4d3SLarry Finger 	u8 *pfwdata;
190f1d2b4d3SLarry Finger 	u32 fwsize;
191f1d2b4d3SLarry Finger 	int err;
192f1d2b4d3SLarry Finger 	enum version_8192e version = rtlhal->version;
193f1d2b4d3SLarry Finger 
194f1d2b4d3SLarry Finger 	if (!rtlhal->pfirmware)
195f1d2b4d3SLarry Finger 		return 1;
196f1d2b4d3SLarry Finger 
197f1d2b4d3SLarry Finger 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
198f1d2b4d3SLarry Finger 	rtlhal->fw_version = le16_to_cpu(pfwheader->version);
199f1d2b4d3SLarry Finger 	rtlhal->fw_subversion = pfwheader->subversion;
200f1d2b4d3SLarry Finger 	pfwdata = (u8 *)rtlhal->pfirmware;
201f1d2b4d3SLarry Finger 	fwsize = rtlhal->fwsize;
202f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
203f1d2b4d3SLarry Finger 		 "normal Firmware SIZE %d\n" , fwsize);
204f1d2b4d3SLarry Finger 
205f1d2b4d3SLarry Finger 	if (IS_FW_HEADER_EXIST(pfwheader)) {
206f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
207f1d2b4d3SLarry Finger 			 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
208f1d2b4d3SLarry Finger 			  pfwheader->version, pfwheader->signature,
209f1d2b4d3SLarry Finger 			  (int)sizeof(struct rtlwifi_firmware_header));
210f1d2b4d3SLarry Finger 
211f1d2b4d3SLarry Finger 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
212f1d2b4d3SLarry Finger 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
213f1d2b4d3SLarry Finger 	} else {
214f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
215f1d2b4d3SLarry Finger 			 "Firmware no Header, Signature(%#x)\n",
216f1d2b4d3SLarry Finger 			  pfwheader->signature);
217f1d2b4d3SLarry Finger 	}
218f1d2b4d3SLarry Finger 
219f1d2b4d3SLarry Finger 	if (rtlhal->mac_func_enable) {
220f1d2b4d3SLarry Finger 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
221f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
222f1d2b4d3SLarry Finger 			rtl92ee_firmware_selfreset(hw);
223f1d2b4d3SLarry Finger 		}
224f1d2b4d3SLarry Finger 	}
225f1d2b4d3SLarry Finger 	_rtl92ee_enable_fw_download(hw, true);
226f1d2b4d3SLarry Finger 	_rtl92ee_write_fw(hw, version, pfwdata, fwsize);
227f1d2b4d3SLarry Finger 	_rtl92ee_enable_fw_download(hw, false);
228f1d2b4d3SLarry Finger 
229f1d2b4d3SLarry Finger 	err = _rtl92ee_fw_free_to_go(hw);
230f1d2b4d3SLarry Finger 
231f1d2b4d3SLarry Finger 	return 0;
232f1d2b4d3SLarry Finger }
233f1d2b4d3SLarry Finger 
234f1d2b4d3SLarry Finger static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
235f1d2b4d3SLarry Finger {
236f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
237f1d2b4d3SLarry Finger 	u8 val_hmetfr;
238f1d2b4d3SLarry Finger 	bool result = false;
239f1d2b4d3SLarry Finger 
240f1d2b4d3SLarry Finger 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
241f1d2b4d3SLarry Finger 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
242f1d2b4d3SLarry Finger 		result = true;
243f1d2b4d3SLarry Finger 	return result;
244f1d2b4d3SLarry Finger }
245f1d2b4d3SLarry Finger 
246f1d2b4d3SLarry Finger static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
247f1d2b4d3SLarry Finger 				      u32 cmd_len, u8 *cmdbuffer)
248f1d2b4d3SLarry Finger {
249f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
250f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
251f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
252f1d2b4d3SLarry Finger 	u8 boxnum;
253f1d2b4d3SLarry Finger 	u16 box_reg = 0, box_extreg = 0;
254f1d2b4d3SLarry Finger 	u8 u1b_tmp;
255f1d2b4d3SLarry Finger 	bool isfw_read = false;
256f1d2b4d3SLarry Finger 	u8 buf_index = 0;
257f1d2b4d3SLarry Finger 	bool bwrite_sucess = false;
258f1d2b4d3SLarry Finger 	u8 wait_h2c_limmit = 100;
259f1d2b4d3SLarry Finger 	u8 boxcontent[4], boxextcontent[4];
260f1d2b4d3SLarry Finger 	u32 h2c_waitcounter = 0;
261f1d2b4d3SLarry Finger 	unsigned long flag;
262f1d2b4d3SLarry Finger 	u8 idx;
263f1d2b4d3SLarry Finger 
264f1d2b4d3SLarry Finger 	if (ppsc->dot11_psmode != EACTIVE ||
265f1d2b4d3SLarry Finger 	    ppsc->inactive_pwrstate == ERFOFF) {
266f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
267f1d2b4d3SLarry Finger 			 "FillH2CCommand8192E(): Return because RF is off!!!\n");
268f1d2b4d3SLarry Finger 		return;
269f1d2b4d3SLarry Finger 	}
270f1d2b4d3SLarry Finger 
271f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
272f1d2b4d3SLarry Finger 
273f1d2b4d3SLarry Finger 	/* 1. Prevent race condition in setting H2C cmd.
274f1d2b4d3SLarry Finger 	 * (copy from MgntActSet_RF_State().)
275f1d2b4d3SLarry Finger 	 */
276f1d2b4d3SLarry Finger 	while (true) {
277f1d2b4d3SLarry Finger 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
278f1d2b4d3SLarry Finger 		if (rtlhal->h2c_setinprogress) {
279f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
280f1d2b4d3SLarry Finger 				 "H2C set in progress! Wait to set..element_id(%d).\n",
281f1d2b4d3SLarry Finger 				  element_id);
282f1d2b4d3SLarry Finger 
283f1d2b4d3SLarry Finger 			while (rtlhal->h2c_setinprogress) {
284f1d2b4d3SLarry Finger 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
285f1d2b4d3SLarry Finger 						       flag);
286f1d2b4d3SLarry Finger 				h2c_waitcounter++;
287f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
288f1d2b4d3SLarry Finger 					 "Wait 100 us (%d times)...\n",
289f1d2b4d3SLarry Finger 					  h2c_waitcounter);
290f1d2b4d3SLarry Finger 				udelay(100);
291f1d2b4d3SLarry Finger 
292f1d2b4d3SLarry Finger 				if (h2c_waitcounter > 1000)
293f1d2b4d3SLarry Finger 					return;
294f1d2b4d3SLarry Finger 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
295f1d2b4d3SLarry Finger 						  flag);
296f1d2b4d3SLarry Finger 			}
297f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
298f1d2b4d3SLarry Finger 		} else {
299f1d2b4d3SLarry Finger 			rtlhal->h2c_setinprogress = true;
300f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
301f1d2b4d3SLarry Finger 			break;
302f1d2b4d3SLarry Finger 		}
303f1d2b4d3SLarry Finger 	}
304f1d2b4d3SLarry Finger 
305f1d2b4d3SLarry Finger 	while (!bwrite_sucess) {
306f1d2b4d3SLarry Finger 		/* 2. Find the last BOX number which has been writen. */
307f1d2b4d3SLarry Finger 		boxnum = rtlhal->last_hmeboxnum;
308f1d2b4d3SLarry Finger 		switch (boxnum) {
309f1d2b4d3SLarry Finger 		case 0:
310f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_0;
311f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_0;
312f1d2b4d3SLarry Finger 			break;
313f1d2b4d3SLarry Finger 		case 1:
314f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_1;
315f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_1;
316f1d2b4d3SLarry Finger 			break;
317f1d2b4d3SLarry Finger 		case 2:
318f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_2;
319f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_2;
320f1d2b4d3SLarry Finger 			break;
321f1d2b4d3SLarry Finger 		case 3:
322f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_3;
323f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_3;
324f1d2b4d3SLarry Finger 			break;
325f1d2b4d3SLarry Finger 		default:
326f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
327ad574889SJoe Perches 				 "switch case %#x not processed\n", boxnum);
328f1d2b4d3SLarry Finger 			break;
329f1d2b4d3SLarry Finger 		}
330f1d2b4d3SLarry Finger 
331f1d2b4d3SLarry Finger 		/* 3. Check if the box content is empty. */
332f1d2b4d3SLarry Finger 		isfw_read = false;
333f1d2b4d3SLarry Finger 		u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
334f1d2b4d3SLarry Finger 
335f1d2b4d3SLarry Finger 		if (u1b_tmp != 0xea) {
336f1d2b4d3SLarry Finger 			isfw_read = true;
337f1d2b4d3SLarry Finger 		} else {
338f1d2b4d3SLarry Finger 			if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
339f1d2b4d3SLarry Finger 			    rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
340f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
341f1d2b4d3SLarry Finger 		}
342f1d2b4d3SLarry Finger 
343f1d2b4d3SLarry Finger 		if (isfw_read) {
344f1d2b4d3SLarry Finger 			wait_h2c_limmit = 100;
345f1d2b4d3SLarry Finger 			isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
346f1d2b4d3SLarry Finger 			while (!isfw_read) {
347f1d2b4d3SLarry Finger 				wait_h2c_limmit--;
348f1d2b4d3SLarry Finger 				if (wait_h2c_limmit == 0) {
349f1d2b4d3SLarry Finger 					RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
350f1d2b4d3SLarry Finger 						 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
351f1d2b4d3SLarry Finger 						 boxnum);
352f1d2b4d3SLarry Finger 					break;
353f1d2b4d3SLarry Finger 				}
354f1d2b4d3SLarry Finger 				udelay(10);
355f1d2b4d3SLarry Finger 				isfw_read =
356f1d2b4d3SLarry Finger 				  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
357f1d2b4d3SLarry Finger 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
358f1d2b4d3SLarry Finger 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
359f1d2b4d3SLarry Finger 					 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
360f1d2b4d3SLarry Finger 					 boxnum, u1b_tmp);
361f1d2b4d3SLarry Finger 			}
362f1d2b4d3SLarry Finger 		}
363f1d2b4d3SLarry Finger 
364f1d2b4d3SLarry Finger 		/* If Fw has not read the last
365f1d2b4d3SLarry Finger 		 * H2C cmd, break and give up this H2C.
366f1d2b4d3SLarry Finger 		 */
367f1d2b4d3SLarry Finger 		if (!isfw_read) {
368f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
369f1d2b4d3SLarry Finger 				 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
370f1d2b4d3SLarry Finger 				 boxnum);
371f1d2b4d3SLarry Finger 			break;
372f1d2b4d3SLarry Finger 		}
373f1d2b4d3SLarry Finger 		/* 4. Fill the H2C cmd into box */
374f1d2b4d3SLarry Finger 		memset(boxcontent, 0, sizeof(boxcontent));
375f1d2b4d3SLarry Finger 		memset(boxextcontent, 0, sizeof(boxextcontent));
376f1d2b4d3SLarry Finger 		boxcontent[0] = element_id;
377f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
378f1d2b4d3SLarry Finger 			 "Write element_id box_reg(%4x) = %2x\n",
379f1d2b4d3SLarry Finger 			  box_reg, element_id);
380f1d2b4d3SLarry Finger 
381f1d2b4d3SLarry Finger 		switch (cmd_len) {
382f1d2b4d3SLarry Finger 		case 1:
383f1d2b4d3SLarry Finger 		case 2:
384f1d2b4d3SLarry Finger 		case 3:
385f1d2b4d3SLarry Finger 			/*boxcontent[0] &= ~(BIT(7));*/
386f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
387f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, cmd_len);
388f1d2b4d3SLarry Finger 
389f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
390f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
391f1d2b4d3SLarry Finger 					       boxcontent[idx]);
392f1d2b4d3SLarry Finger 			}
393f1d2b4d3SLarry Finger 			break;
394f1d2b4d3SLarry Finger 		case 4:
395f1d2b4d3SLarry Finger 		case 5:
396f1d2b4d3SLarry Finger 		case 6:
397f1d2b4d3SLarry Finger 		case 7:
398f1d2b4d3SLarry Finger 			/*boxcontent[0] |= (BIT(7));*/
399f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxextcontent),
400f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index+3, cmd_len-3);
401f1d2b4d3SLarry Finger 			memcpy((u8 *)(boxcontent) + 1,
402f1d2b4d3SLarry Finger 			       cmdbuffer + buf_index, 3);
403f1d2b4d3SLarry Finger 
404f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
405f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
406f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
407f1d2b4d3SLarry Finger 			}
408f1d2b4d3SLarry Finger 
409f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++) {
410f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
411f1d2b4d3SLarry Finger 					       boxcontent[idx]);
412f1d2b4d3SLarry Finger 			}
413f1d2b4d3SLarry Finger 			break;
414f1d2b4d3SLarry Finger 		default:
415f1d2b4d3SLarry Finger 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
416ad574889SJoe Perches 				 "switch case %#x not processed\n", cmd_len);
417f1d2b4d3SLarry Finger 			break;
418f1d2b4d3SLarry Finger 		}
419f1d2b4d3SLarry Finger 
420f1d2b4d3SLarry Finger 		bwrite_sucess = true;
421f1d2b4d3SLarry Finger 
422f1d2b4d3SLarry Finger 		rtlhal->last_hmeboxnum = boxnum + 1;
423f1d2b4d3SLarry Finger 		if (rtlhal->last_hmeboxnum == 4)
424f1d2b4d3SLarry Finger 			rtlhal->last_hmeboxnum = 0;
425f1d2b4d3SLarry Finger 
426f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
427f1d2b4d3SLarry Finger 			 "pHalData->last_hmeboxnum  = %d\n",
428f1d2b4d3SLarry Finger 			  rtlhal->last_hmeboxnum);
429f1d2b4d3SLarry Finger 	}
430f1d2b4d3SLarry Finger 
431f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
432f1d2b4d3SLarry Finger 	rtlhal->h2c_setinprogress = false;
433f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
434f1d2b4d3SLarry Finger 
435f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
436f1d2b4d3SLarry Finger }
437f1d2b4d3SLarry Finger 
438f1d2b4d3SLarry Finger void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
439f1d2b4d3SLarry Finger 			  u8 element_id, u32 cmd_len, u8 *cmdbuffer)
440f1d2b4d3SLarry Finger {
441f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
442f1d2b4d3SLarry Finger 	u32 tmp_cmdbuf[2];
443f1d2b4d3SLarry Finger 
444f1d2b4d3SLarry Finger 	if (!rtlhal->fw_ready) {
445531940f9SLarry Finger 		WARN_ONCE(true,
446531940f9SLarry Finger 			  "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
447f1d2b4d3SLarry Finger 		return;
448f1d2b4d3SLarry Finger 	}
449f1d2b4d3SLarry Finger 
450f1d2b4d3SLarry Finger 	memset(tmp_cmdbuf, 0, 8);
451f1d2b4d3SLarry Finger 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
452f1d2b4d3SLarry Finger 	_rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
453f1d2b4d3SLarry Finger }
454f1d2b4d3SLarry Finger 
455f1d2b4d3SLarry Finger void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
456f1d2b4d3SLarry Finger {
457f1d2b4d3SLarry Finger 	u8 u1b_tmp;
458f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
459f1d2b4d3SLarry Finger 
460f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
461f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
462f1d2b4d3SLarry Finger 
463f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
464f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
465f1d2b4d3SLarry Finger 
466f1d2b4d3SLarry Finger 	udelay(50);
467f1d2b4d3SLarry Finger 
468f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
469f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
470f1d2b4d3SLarry Finger 
471f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
472f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
473f1d2b4d3SLarry Finger 
474f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
475f1d2b4d3SLarry Finger 		 "  _8051Reset92E(): 8051 reset success .\n");
476f1d2b4d3SLarry Finger }
477f1d2b4d3SLarry Finger 
478f1d2b4d3SLarry Finger void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
479f1d2b4d3SLarry Finger {
480f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
481f1d2b4d3SLarry Finger 	u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
482f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
483f1d2b4d3SLarry Finger 	u8 rlbm , power_state = 0;
484f1d2b4d3SLarry Finger 
485f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
486f1d2b4d3SLarry Finger 
487f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
488f1d2b4d3SLarry Finger 	rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
489f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
490f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
491f1d2b4d3SLarry Finger 					 (rtlpriv->mac80211.p2p) ?
492f1d2b4d3SLarry Finger 					 ppsc->smart_ps : 1);
493f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
494f1d2b4d3SLarry Finger 					       ppsc->reg_max_lps_awakeintvl);
495f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
496f1d2b4d3SLarry Finger 	if (mode == FW_PS_ACTIVE_MODE)
497f1d2b4d3SLarry Finger 		power_state |= FW_PWR_STATE_ACTIVE;
498f1d2b4d3SLarry Finger 	else
499f1d2b4d3SLarry Finger 		power_state |= FW_PWR_STATE_RF_OFF;
500f1d2b4d3SLarry Finger 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
501f1d2b4d3SLarry Finger 
502f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
503f1d2b4d3SLarry Finger 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
504f1d2b4d3SLarry Finger 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
505f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
506f1d2b4d3SLarry Finger 			     u1_h2c_set_pwrmode);
507f1d2b4d3SLarry Finger }
508f1d2b4d3SLarry Finger 
509f1d2b4d3SLarry Finger void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
510f1d2b4d3SLarry Finger {
511f1d2b4d3SLarry Finger 	u8 parm[3] = { 0 , 0 , 0 };
512f1d2b4d3SLarry Finger 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
513f1d2b4d3SLarry Finger 	 *          bit1=0-->update Media Status to MACID
514f1d2b4d3SLarry Finger 	 *          bit1=1-->update Media Status from MACID to MACID_End
515f1d2b4d3SLarry Finger 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
516f1d2b4d3SLarry Finger 	 * parm[2]: MACID_End
517f1d2b4d3SLarry Finger 	 */
518f1d2b4d3SLarry Finger 
519f1d2b4d3SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
520f1d2b4d3SLarry Finger 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
521f1d2b4d3SLarry Finger 
522f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
523f1d2b4d3SLarry Finger }
524f1d2b4d3SLarry Finger 
525f1d2b4d3SLarry Finger #define BEACON_PG		0 /* ->1 */
526f1d2b4d3SLarry Finger #define PSPOLL_PG		2
527f1d2b4d3SLarry Finger #define NULL_PG			3
528f1d2b4d3SLarry Finger #define PROBERSP_PG		4 /* ->5 */
529f1d2b4d3SLarry Finger 
530f1d2b4d3SLarry Finger #define TOTAL_RESERVED_PKT_LEN	768
531f1d2b4d3SLarry Finger 
532f1d2b4d3SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
533f1d2b4d3SLarry Finger 	/* page 0 beacon */
534f1d2b4d3SLarry Finger 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
535f1d2b4d3SLarry Finger 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
536f1d2b4d3SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
537f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538f1d2b4d3SLarry Finger 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
539f1d2b4d3SLarry Finger 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
540f1d2b4d3SLarry Finger 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
541f1d2b4d3SLarry Finger 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
542f1d2b4d3SLarry Finger 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
543f1d2b4d3SLarry Finger 	0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
544f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546f1d2b4d3SLarry Finger 	0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
547f1d2b4d3SLarry Finger 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
548f1d2b4d3SLarry Finger 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
549f1d2b4d3SLarry Finger 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
550f1d2b4d3SLarry Finger 
551f1d2b4d3SLarry Finger 	/* page 1 beacon */
552f1d2b4d3SLarry Finger 	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
553f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563f1d2b4d3SLarry Finger 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
564f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
565f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568f1d2b4d3SLarry Finger 
569f1d2b4d3SLarry Finger 	/* page 2  ps-poll */
570f1d2b4d3SLarry Finger 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
571f1d2b4d3SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
572f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581f1d2b4d3SLarry Finger 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
582f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
583f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585f1d2b4d3SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586f1d2b4d3SLarry Finger 
587f1d2b4d3SLarry Finger 	/* page 3  null */
588f1d2b4d3SLarry Finger 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
589f1d2b4d3SLarry Finger 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
590f1d2b4d3SLarry Finger 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
591f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599f1d2b4d3SLarry Finger 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
600f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
601f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603f1d2b4d3SLarry Finger 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604f1d2b4d3SLarry Finger 
605f1d2b4d3SLarry Finger 	/* page 4  probe_resp */
606f1d2b4d3SLarry Finger 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
607f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
608f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
609f1d2b4d3SLarry Finger 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
610f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
611f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
612f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
613f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
614f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
615f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
616f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
620f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622f1d2b4d3SLarry Finger 
623f1d2b4d3SLarry Finger 	/* page 5  probe_resp */
624f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640f1d2b4d3SLarry Finger };
641f1d2b4d3SLarry Finger 
642f1d2b4d3SLarry Finger void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
643f1d2b4d3SLarry Finger {
644f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
645f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
646f1d2b4d3SLarry Finger 	struct sk_buff *skb = NULL;
647f1d2b4d3SLarry Finger 
648f1d2b4d3SLarry Finger 	u32 totalpacketlen;
649f1d2b4d3SLarry Finger 	u8 u1rsvdpageloc[5] = { 0 };
650f1d2b4d3SLarry Finger 	bool b_dlok = false;
651f1d2b4d3SLarry Finger 
652f1d2b4d3SLarry Finger 	u8 *beacon;
653f1d2b4d3SLarry Finger 	u8 *p_pspoll;
654f1d2b4d3SLarry Finger 	u8 *nullfunc;
655f1d2b4d3SLarry Finger 	u8 *p_probersp;
656f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
657f1d2b4d3SLarry Finger 	 *			(1) beacon
658f1d2b4d3SLarry Finger 	 *---------------------------------------------------------
659f1d2b4d3SLarry Finger 	 */
660f1d2b4d3SLarry Finger 	beacon = &reserved_page_packet[BEACON_PG * 128];
661f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
662f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
663f1d2b4d3SLarry Finger 
664f1d2b4d3SLarry Finger 	/*-------------------------------------------------------
665f1d2b4d3SLarry Finger 	 *			(2) ps-poll
666f1d2b4d3SLarry Finger 	 *--------------------------------------------------------
667f1d2b4d3SLarry Finger 	 */
668f1d2b4d3SLarry Finger 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
669f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
670f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
671f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
672f1d2b4d3SLarry Finger 
673f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
674f1d2b4d3SLarry Finger 
675f1d2b4d3SLarry Finger 	/*--------------------------------------------------------
676f1d2b4d3SLarry Finger 	 *			(3) null data
677f1d2b4d3SLarry Finger 	 *---------------------------------------------------------
678f1d2b4d3SLarry Finger 	 */
679f1d2b4d3SLarry Finger 	nullfunc = &reserved_page_packet[NULL_PG * 128];
680f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
681f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
682f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
683f1d2b4d3SLarry Finger 
684f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
685f1d2b4d3SLarry Finger 
686f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
687f1d2b4d3SLarry Finger 	 *			(4) probe response
688f1d2b4d3SLarry Finger 	 *----------------------------------------------------------
689f1d2b4d3SLarry Finger 	 */
690f1d2b4d3SLarry Finger 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
691f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
692f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
693f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
694f1d2b4d3SLarry Finger 
695f1d2b4d3SLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
696f1d2b4d3SLarry Finger 
697f1d2b4d3SLarry Finger 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
698f1d2b4d3SLarry Finger 
699f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
700f1d2b4d3SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
701f1d2b4d3SLarry Finger 		      &reserved_page_packet[0], totalpacketlen);
702f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
703f1d2b4d3SLarry Finger 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
704f1d2b4d3SLarry Finger 		      u1rsvdpageloc, 3);
705f1d2b4d3SLarry Finger 
706f1d2b4d3SLarry Finger 	skb = dev_alloc_skb(totalpacketlen);
707f1d2b4d3SLarry Finger 	memcpy((u8 *)skb_put(skb, totalpacketlen),
708f1d2b4d3SLarry Finger 	       &reserved_page_packet, totalpacketlen);
709f1d2b4d3SLarry Finger 
710f1d2b4d3SLarry Finger 	b_dlok = true;
711f1d2b4d3SLarry Finger 
712f1d2b4d3SLarry Finger 	if (b_dlok) {
713f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
714f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw.\n");
715f1d2b4d3SLarry Finger 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
716f1d2b4d3SLarry Finger 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
717f1d2b4d3SLarry Finger 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
718f1d2b4d3SLarry Finger 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
719f1d2b4d3SLarry Finger 	} else {
720f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
721f1d2b4d3SLarry Finger 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
722f1d2b4d3SLarry Finger 	}
723f1d2b4d3SLarry Finger }
724f1d2b4d3SLarry Finger 
725f1d2b4d3SLarry Finger /*Shoud check FW support p2p or not.*/
726f1d2b4d3SLarry Finger static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
727f1d2b4d3SLarry Finger {
728f1d2b4d3SLarry Finger 	u8 u1_ctwindow_period[1] = {ctwindow};
729f1d2b4d3SLarry Finger 
730f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
731f1d2b4d3SLarry Finger }
732f1d2b4d3SLarry Finger 
733f1d2b4d3SLarry Finger void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
734f1d2b4d3SLarry Finger {
735f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
736f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
737f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
738f1d2b4d3SLarry Finger 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
739f1d2b4d3SLarry Finger 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
740f1d2b4d3SLarry Finger 	u8 i;
741f1d2b4d3SLarry Finger 	u16 ctwindow;
742f1d2b4d3SLarry Finger 	u32 start_time, tsf_low;
743f1d2b4d3SLarry Finger 
744f1d2b4d3SLarry Finger 	switch (p2p_ps_state) {
745f1d2b4d3SLarry Finger 	case P2P_PS_DISABLE:
746f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
747f1d2b4d3SLarry Finger 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
748f1d2b4d3SLarry Finger 		break;
749f1d2b4d3SLarry Finger 	case P2P_PS_ENABLE:
750f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
751f1d2b4d3SLarry Finger 		/* update CTWindow value. */
752f1d2b4d3SLarry Finger 		if (p2pinfo->ctwindow > 0) {
753f1d2b4d3SLarry Finger 			p2p_ps_offload->ctwindow_en = 1;
754f1d2b4d3SLarry Finger 			ctwindow = p2pinfo->ctwindow;
755f1d2b4d3SLarry Finger 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
756f1d2b4d3SLarry Finger 		}
757f1d2b4d3SLarry Finger 		/* hw only support 2 set of NoA */
758f1d2b4d3SLarry Finger 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
759f1d2b4d3SLarry Finger 			/* To control the register setting for which NOA*/
760f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
761f1d2b4d3SLarry Finger 			if (i == 0)
762f1d2b4d3SLarry Finger 				p2p_ps_offload->noa0_en = 1;
763f1d2b4d3SLarry Finger 			else
764f1d2b4d3SLarry Finger 				p2p_ps_offload->noa1_en = 1;
765f1d2b4d3SLarry Finger 			/* config P2P NoA Descriptor Register */
766f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E0,
767f1d2b4d3SLarry Finger 					p2pinfo->noa_duration[i]);
768f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E4,
769f1d2b4d3SLarry Finger 					p2pinfo->noa_interval[i]);
770f1d2b4d3SLarry Finger 
771f1d2b4d3SLarry Finger 			/*Get Current TSF value */
772f1d2b4d3SLarry Finger 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
773f1d2b4d3SLarry Finger 
774f1d2b4d3SLarry Finger 			start_time = p2pinfo->noa_start_time[i];
775f1d2b4d3SLarry Finger 			if (p2pinfo->noa_count_type[i] != 1) {
776f1d2b4d3SLarry Finger 				while (start_time <= (tsf_low + (50 * 1024))) {
777f1d2b4d3SLarry Finger 					start_time += p2pinfo->noa_interval[i];
778f1d2b4d3SLarry Finger 					if (p2pinfo->noa_count_type[i] != 255)
779f1d2b4d3SLarry Finger 						p2pinfo->noa_count_type[i]--;
780f1d2b4d3SLarry Finger 				}
781f1d2b4d3SLarry Finger 			}
782f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
783f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, 0x5EC,
784f1d2b4d3SLarry Finger 					p2pinfo->noa_count_type[i]);
785f1d2b4d3SLarry Finger 		}
786f1d2b4d3SLarry Finger 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
787f1d2b4d3SLarry Finger 			/* rst p2p circuit */
788f1d2b4d3SLarry Finger 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
789f1d2b4d3SLarry Finger 			p2p_ps_offload->offload_en = 1;
790f1d2b4d3SLarry Finger 
791f1d2b4d3SLarry Finger 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
792f1d2b4d3SLarry Finger 				p2p_ps_offload->role = 1;
793f1d2b4d3SLarry Finger 				p2p_ps_offload->allstasleep = 0;
794f1d2b4d3SLarry Finger 			} else {
795f1d2b4d3SLarry Finger 				p2p_ps_offload->role = 0;
796f1d2b4d3SLarry Finger 			}
797f1d2b4d3SLarry Finger 			p2p_ps_offload->discovery = 0;
798f1d2b4d3SLarry Finger 		}
799f1d2b4d3SLarry Finger 		break;
800f1d2b4d3SLarry Finger 	case P2P_PS_SCAN:
801f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
802f1d2b4d3SLarry Finger 		p2p_ps_offload->discovery = 1;
803f1d2b4d3SLarry Finger 		break;
804f1d2b4d3SLarry Finger 	case P2P_PS_SCAN_DONE:
805f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
806f1d2b4d3SLarry Finger 		p2p_ps_offload->discovery = 0;
807f1d2b4d3SLarry Finger 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
808f1d2b4d3SLarry Finger 		break;
809f1d2b4d3SLarry Finger 	default:
810f1d2b4d3SLarry Finger 		break;
811f1d2b4d3SLarry Finger 	}
812f1d2b4d3SLarry Finger 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
813f1d2b4d3SLarry Finger 			     (u8 *)p2p_ps_offload);
814f1d2b4d3SLarry Finger }
815f1d2b4d3SLarry Finger 
816f1d2b4d3SLarry Finger static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
817f1d2b4d3SLarry Finger 					   u8 *cmd_buf, u8 cmd_len)
818f1d2b4d3SLarry Finger {
819f1d2b4d3SLarry Finger 	u8 rate = cmd_buf[0] & 0x3F;
820f1d2b4d3SLarry Finger 	bool collision_state = cmd_buf[3] & BIT(0);
821f1d2b4d3SLarry Finger 
822f1d2b4d3SLarry Finger 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
823f1d2b4d3SLarry Finger }
824f1d2b4d3SLarry Finger 
825f1d2b4d3SLarry Finger static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
826f1d2b4d3SLarry Finger 					 u8 c2h_cmd_len, u8 *tmp_buf)
827f1d2b4d3SLarry Finger {
828f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
829f1d2b4d3SLarry Finger 
830f1d2b4d3SLarry Finger 	switch (c2h_cmd_id) {
831f1d2b4d3SLarry Finger 	case C2H_8192E_DBG:
832f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
833f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_DBG!!\n");
834f1d2b4d3SLarry Finger 		break;
835f1d2b4d3SLarry Finger 	case C2H_8192E_TXBF:
836f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
837f1d2b4d3SLarry Finger 			 "[C2H], C2H_8192E_TXBF!!\n");
838f1d2b4d3SLarry Finger 		break;
839f1d2b4d3SLarry Finger 	case C2H_8192E_TX_REPORT:
840f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
841f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_TX_REPORT!\n");
842f1d2b4d3SLarry Finger 		break;
843f1d2b4d3SLarry Finger 	case C2H_8192E_BT_INFO:
844f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
845f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_BT_INFO!!\n");
846f1d2b4d3SLarry Finger 		rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
847f1d2b4d3SLarry Finger 							      c2h_cmd_len);
848f1d2b4d3SLarry Finger 		break;
849f1d2b4d3SLarry Finger 	case C2H_8192E_BT_MP:
850f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
851f1d2b4d3SLarry Finger 			 "[C2H], C2H_8723BE_BT_MP!!\n");
852f1d2b4d3SLarry Finger 		break;
853f1d2b4d3SLarry Finger 	case C2H_8192E_RA_RPT:
854f1d2b4d3SLarry Finger 		_rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
855f1d2b4d3SLarry Finger 		break;
856f1d2b4d3SLarry Finger 	default:
857f1d2b4d3SLarry Finger 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
858f1d2b4d3SLarry Finger 			 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
859f1d2b4d3SLarry Finger 		break;
860f1d2b4d3SLarry Finger 	}
861f1d2b4d3SLarry Finger }
862f1d2b4d3SLarry Finger 
863f1d2b4d3SLarry Finger void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
864f1d2b4d3SLarry Finger {
865f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
866f1d2b4d3SLarry Finger 	u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
867f1d2b4d3SLarry Finger 	u8 *tmp_buf = NULL;
868f1d2b4d3SLarry Finger 
869f1d2b4d3SLarry Finger 	c2h_cmd_id = buffer[0];
870f1d2b4d3SLarry Finger 	c2h_cmd_seq = buffer[1];
871f1d2b4d3SLarry Finger 	c2h_cmd_len = len - 2;
872f1d2b4d3SLarry Finger 	tmp_buf = buffer + 2;
873f1d2b4d3SLarry Finger 
874f1d2b4d3SLarry Finger 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
875f1d2b4d3SLarry Finger 		 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
876f1d2b4d3SLarry Finger 		 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
877f1d2b4d3SLarry Finger 
878f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
879f1d2b4d3SLarry Finger 		      "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
880f1d2b4d3SLarry Finger 
881f1d2b4d3SLarry Finger 	_rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
882f1d2b4d3SLarry Finger }
883