xref: /openbmc/linux/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
15bd4f692SLarry Finger // SPDX-License-Identifier: GPL-2.0
25bd4f692SLarry Finger /* Copyright(c) 2009-2012  Realtek Corporation.*/
3f1d2b4d3SLarry Finger 
4f1d2b4d3SLarry Finger #include "../wifi.h"
5f1d2b4d3SLarry Finger #include "../pci.h"
6f1d2b4d3SLarry Finger #include "../base.h"
789d32c90SLarry Finger #include "../efuse.h"
8f1d2b4d3SLarry Finger #include "reg.h"
9f1d2b4d3SLarry Finger #include "def.h"
10f1d2b4d3SLarry Finger #include "fw.h"
11f1d2b4d3SLarry Finger #include "sw.h"
12f1d2b4d3SLarry Finger 
_rtl92d_is_fw_downloaded(struct rtl_priv * rtlpriv)13f1d2b4d3SLarry Finger static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
14f1d2b4d3SLarry Finger {
15f1d2b4d3SLarry Finger 	return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
16f1d2b4d3SLarry Finger 		true : false;
17f1d2b4d3SLarry Finger }
18f1d2b4d3SLarry Finger 
_rtl92d_enable_fw_download(struct ieee80211_hw * hw,bool enable)19f1d2b4d3SLarry Finger static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
20f1d2b4d3SLarry Finger {
21f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
22f1d2b4d3SLarry Finger 	u8 tmp;
23f1d2b4d3SLarry Finger 
24f1d2b4d3SLarry Finger 	if (enable) {
25f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
26f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
27f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
28f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
29f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
30f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
31f1d2b4d3SLarry Finger 	} else {
32f1d2b4d3SLarry Finger 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
33f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
34f1d2b4d3SLarry Finger 		/* Reserved for fw extension.
35f1d2b4d3SLarry Finger 		 * 0x81[7] is used for mac0 status ,
36f1d2b4d3SLarry Finger 		 * so don't write this reg here
37f1d2b4d3SLarry Finger 		 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
38f1d2b4d3SLarry Finger 	}
39f1d2b4d3SLarry Finger }
40f1d2b4d3SLarry Finger 
_rtl92d_write_fw(struct ieee80211_hw * hw,enum version_8192d version,u8 * buffer,u32 size)41f1d2b4d3SLarry Finger static void _rtl92d_write_fw(struct ieee80211_hw *hw,
42f1d2b4d3SLarry Finger 			     enum version_8192d version, u8 *buffer, u32 size)
43f1d2b4d3SLarry Finger {
44f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
45f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
4689d32c90SLarry Finger 	u8 *bufferptr = buffer;
4789d32c90SLarry Finger 	u32 pagenums, remainsize;
48f1d2b4d3SLarry Finger 	u32 page, offset;
49f1d2b4d3SLarry Finger 
50*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
51f1d2b4d3SLarry Finger 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
5289d32c90SLarry Finger 		rtl_fill_dummy(bufferptr, &size);
53f1d2b4d3SLarry Finger 	pagenums = size / FW_8192D_PAGE_SIZE;
5489d32c90SLarry Finger 	remainsize = size % FW_8192D_PAGE_SIZE;
55c93ac39dSLarry Finger 	if (pagenums > 8)
56b8c79f45SLarry Finger 		pr_err("Page numbers should not greater then 8\n");
57f1d2b4d3SLarry Finger 	for (page = 0; page < pagenums; page++) {
58f1d2b4d3SLarry Finger 		offset = page * FW_8192D_PAGE_SIZE;
5989d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset),
60f1d2b4d3SLarry Finger 				  FW_8192D_PAGE_SIZE);
61f1d2b4d3SLarry Finger 	}
6289d32c90SLarry Finger 	if (remainsize) {
63f1d2b4d3SLarry Finger 		offset = pagenums * FW_8192D_PAGE_SIZE;
64f1d2b4d3SLarry Finger 		page = pagenums;
6589d32c90SLarry Finger 		rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
66f1d2b4d3SLarry Finger 	}
67f1d2b4d3SLarry Finger }
68f1d2b4d3SLarry Finger 
_rtl92d_fw_free_to_go(struct ieee80211_hw * hw)69f1d2b4d3SLarry Finger static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
70f1d2b4d3SLarry Finger {
71f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
72f1d2b4d3SLarry Finger 	u32 counter = 0;
73f1d2b4d3SLarry Finger 	u32 value32;
74f1d2b4d3SLarry Finger 
75f1d2b4d3SLarry Finger 	do {
76f1d2b4d3SLarry Finger 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
77f1d2b4d3SLarry Finger 	} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
78b83faedaSLarry Finger 		 (!(value32 & FWDL_CHKSUM_RPT)));
79f1d2b4d3SLarry Finger 	if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
80b8c79f45SLarry Finger 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
81f1d2b4d3SLarry Finger 		       value32);
82f1d2b4d3SLarry Finger 		return -EIO;
83f1d2b4d3SLarry Finger 	}
84f1d2b4d3SLarry Finger 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
85f1d2b4d3SLarry Finger 	value32 |= MCUFWDL_RDY;
86f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
87f1d2b4d3SLarry Finger 	return 0;
88f1d2b4d3SLarry Finger }
89f1d2b4d3SLarry Finger 
rtl92d_firmware_selfreset(struct ieee80211_hw * hw)90f1d2b4d3SLarry Finger void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
91f1d2b4d3SLarry Finger {
92f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
93f1d2b4d3SLarry Finger 	u8 u1b_tmp;
94f1d2b4d3SLarry Finger 	u8 delay = 100;
95f1d2b4d3SLarry Finger 
96f1d2b4d3SLarry Finger 	/* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
97f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
98f1d2b4d3SLarry Finger 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
99f1d2b4d3SLarry Finger 	while (u1b_tmp & BIT(2)) {
100f1d2b4d3SLarry Finger 		delay--;
101f1d2b4d3SLarry Finger 		if (delay == 0)
102f1d2b4d3SLarry Finger 			break;
103f1d2b4d3SLarry Finger 		udelay(50);
104f1d2b4d3SLarry Finger 		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
105f1d2b4d3SLarry Finger 	}
106531940f9SLarry Finger 	WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
107*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
108f1d2b4d3SLarry Finger 		"=====> 8051 reset success (%d)\n", delay);
109f1d2b4d3SLarry Finger }
110f1d2b4d3SLarry Finger 
_rtl92d_fw_init(struct ieee80211_hw * hw)111f1d2b4d3SLarry Finger static int _rtl92d_fw_init(struct ieee80211_hw *hw)
112f1d2b4d3SLarry Finger {
113f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
114f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
115f1d2b4d3SLarry Finger 	u32 counter;
116f1d2b4d3SLarry Finger 
117*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
118f1d2b4d3SLarry Finger 	/* polling for FW ready */
119f1d2b4d3SLarry Finger 	counter = 0;
120f1d2b4d3SLarry Finger 	do {
121f1d2b4d3SLarry Finger 		if (rtlhal->interfaceindex == 0) {
122f1d2b4d3SLarry Finger 			if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
123f1d2b4d3SLarry Finger 			    MAC0_READY) {
124*6bf8bc19SLarry Finger 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
125f1d2b4d3SLarry Finger 					"Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
126f1d2b4d3SLarry Finger 					rtl_read_byte(rtlpriv,
127f1d2b4d3SLarry Finger 						      FW_MAC0_READY));
128f1d2b4d3SLarry Finger 				return 0;
129f1d2b4d3SLarry Finger 			}
130f1d2b4d3SLarry Finger 			udelay(5);
131f1d2b4d3SLarry Finger 		} else {
132f1d2b4d3SLarry Finger 			if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
133f1d2b4d3SLarry Finger 			    MAC1_READY) {
134*6bf8bc19SLarry Finger 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
135f1d2b4d3SLarry Finger 					"Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
136f1d2b4d3SLarry Finger 					rtl_read_byte(rtlpriv,
137f1d2b4d3SLarry Finger 						      FW_MAC1_READY));
138f1d2b4d3SLarry Finger 				return 0;
139f1d2b4d3SLarry Finger 			}
140f1d2b4d3SLarry Finger 			udelay(5);
141f1d2b4d3SLarry Finger 		}
142f1d2b4d3SLarry Finger 	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
143f1d2b4d3SLarry Finger 
144f1d2b4d3SLarry Finger 	if (rtlhal->interfaceindex == 0) {
145*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
146f1d2b4d3SLarry Finger 			"Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
147f1d2b4d3SLarry Finger 			rtl_read_byte(rtlpriv, FW_MAC0_READY));
148f1d2b4d3SLarry Finger 	} else {
149*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
150f1d2b4d3SLarry Finger 			"Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
151f1d2b4d3SLarry Finger 			rtl_read_byte(rtlpriv, FW_MAC1_READY));
152f1d2b4d3SLarry Finger 	}
153*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
1547d129adfSShaokun Zhang 		"Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
155f1d2b4d3SLarry Finger 		rtl_read_dword(rtlpriv, REG_MCUFWDL));
156f1d2b4d3SLarry Finger 	return -1;
157f1d2b4d3SLarry Finger }
158f1d2b4d3SLarry Finger 
rtl92d_download_fw(struct ieee80211_hw * hw)159f1d2b4d3SLarry Finger int rtl92d_download_fw(struct ieee80211_hw *hw)
160f1d2b4d3SLarry Finger {
161f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
162f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
163f1d2b4d3SLarry Finger 	u8 *pfwheader;
164f1d2b4d3SLarry Finger 	u8 *pfwdata;
165f1d2b4d3SLarry Finger 	u32 fwsize;
166f1d2b4d3SLarry Finger 	int err;
167f1d2b4d3SLarry Finger 	enum version_8192d version = rtlhal->version;
168f1d2b4d3SLarry Finger 	u8 value;
169f1d2b4d3SLarry Finger 	u32 count;
170f1d2b4d3SLarry Finger 	bool fw_downloaded = false, fwdl_in_process = false;
171f1d2b4d3SLarry Finger 	unsigned long flags;
172f1d2b4d3SLarry Finger 
173f1d2b4d3SLarry Finger 	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
174f1d2b4d3SLarry Finger 		return 1;
175f1d2b4d3SLarry Finger 	fwsize = rtlhal->fwsize;
176f1d2b4d3SLarry Finger 	pfwheader = rtlhal->pfirmware;
177f1d2b4d3SLarry Finger 	pfwdata = rtlhal->pfirmware;
178f1d2b4d3SLarry Finger 	rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
179f1d2b4d3SLarry Finger 	rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
180*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
181f1d2b4d3SLarry Finger 		"FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
182f1d2b4d3SLarry Finger 		rtlhal->fw_version, rtlhal->fw_subversion,
183f1d2b4d3SLarry Finger 		GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
184f1d2b4d3SLarry Finger 	if (IS_FW_HEADER_EXIST(pfwheader)) {
185*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
186f1d2b4d3SLarry Finger 			"Shift 32 bytes for FW header!!\n");
187f1d2b4d3SLarry Finger 		pfwdata = pfwdata + 32;
188f1d2b4d3SLarry Finger 		fwsize = fwsize - 32;
189f1d2b4d3SLarry Finger 	}
190f1d2b4d3SLarry Finger 
191f1d2b4d3SLarry Finger 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
192f1d2b4d3SLarry Finger 	fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
193f1d2b4d3SLarry Finger 	if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
194f1d2b4d3SLarry Finger 		fwdl_in_process = true;
195f1d2b4d3SLarry Finger 	else
196f1d2b4d3SLarry Finger 		fwdl_in_process = false;
197f1d2b4d3SLarry Finger 	if (fw_downloaded) {
198f1d2b4d3SLarry Finger 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
199f1d2b4d3SLarry Finger 		goto exit;
200f1d2b4d3SLarry Finger 	} else if (fwdl_in_process) {
201f1d2b4d3SLarry Finger 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
202f1d2b4d3SLarry Finger 		for (count = 0; count < 5000; count++) {
203f1d2b4d3SLarry Finger 			udelay(500);
204f1d2b4d3SLarry Finger 			spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
205f1d2b4d3SLarry Finger 			fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
206f1d2b4d3SLarry Finger 			if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
207f1d2b4d3SLarry Finger 				fwdl_in_process = true;
208f1d2b4d3SLarry Finger 			else
209f1d2b4d3SLarry Finger 				fwdl_in_process = false;
210f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&globalmutex_for_fwdownload,
211f1d2b4d3SLarry Finger 					       flags);
212f1d2b4d3SLarry Finger 			if (fw_downloaded)
213f1d2b4d3SLarry Finger 				goto exit;
214f1d2b4d3SLarry Finger 			else if (!fwdl_in_process)
215f1d2b4d3SLarry Finger 				break;
216f1d2b4d3SLarry Finger 			else
217*6bf8bc19SLarry Finger 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
218f1d2b4d3SLarry Finger 					"Wait for another mac download fw\n");
219f1d2b4d3SLarry Finger 		}
220f1d2b4d3SLarry Finger 		spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
221f1d2b4d3SLarry Finger 		value = rtl_read_byte(rtlpriv, 0x1f);
222f1d2b4d3SLarry Finger 		value |= BIT(5);
223f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, 0x1f, value);
224f1d2b4d3SLarry Finger 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
225f1d2b4d3SLarry Finger 	} else {
226f1d2b4d3SLarry Finger 		value = rtl_read_byte(rtlpriv, 0x1f);
227f1d2b4d3SLarry Finger 		value |= BIT(5);
228f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, 0x1f, value);
229f1d2b4d3SLarry Finger 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
230f1d2b4d3SLarry Finger 	}
231f1d2b4d3SLarry Finger 
232f1d2b4d3SLarry Finger 	/* If 8051 is running in RAM code, driver should
233f1d2b4d3SLarry Finger 	 * inform Fw to reset by itself, or it will cause
234f1d2b4d3SLarry Finger 	 * download Fw fail.*/
235f1d2b4d3SLarry Finger 	/* 8051 RAM code */
236f1d2b4d3SLarry Finger 	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
237f1d2b4d3SLarry Finger 		rtl92d_firmware_selfreset(hw);
238f1d2b4d3SLarry Finger 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
239f1d2b4d3SLarry Finger 	}
240f1d2b4d3SLarry Finger 	_rtl92d_enable_fw_download(hw, true);
241f1d2b4d3SLarry Finger 	_rtl92d_write_fw(hw, version, pfwdata, fwsize);
242f1d2b4d3SLarry Finger 	_rtl92d_enable_fw_download(hw, false);
243f1d2b4d3SLarry Finger 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
244f1d2b4d3SLarry Finger 	err = _rtl92d_fw_free_to_go(hw);
245f1d2b4d3SLarry Finger 	/* download fw over,clear 0x1f[5] */
246f1d2b4d3SLarry Finger 	value = rtl_read_byte(rtlpriv, 0x1f);
247f1d2b4d3SLarry Finger 	value &= (~BIT(5));
248f1d2b4d3SLarry Finger 	rtl_write_byte(rtlpriv, 0x1f, value);
249f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
250c93ac39dSLarry Finger 	if (err)
251b8c79f45SLarry Finger 		pr_err("fw is not ready to run!\n");
252f1d2b4d3SLarry Finger exit:
253f1d2b4d3SLarry Finger 	err = _rtl92d_fw_init(hw);
254f1d2b4d3SLarry Finger 	return err;
255f1d2b4d3SLarry Finger }
256f1d2b4d3SLarry Finger 
_rtl92d_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)257f1d2b4d3SLarry Finger static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
258f1d2b4d3SLarry Finger {
259f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
260f1d2b4d3SLarry Finger 	u8 val_hmetfr;
261f1d2b4d3SLarry Finger 	bool result = false;
262f1d2b4d3SLarry Finger 
263f1d2b4d3SLarry Finger 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
264f1d2b4d3SLarry Finger 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
265f1d2b4d3SLarry Finger 		result = true;
266f1d2b4d3SLarry Finger 	return result;
267f1d2b4d3SLarry Finger }
268f1d2b4d3SLarry Finger 
_rtl92d_fill_h2c_command(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)269f1d2b4d3SLarry Finger static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
270f1d2b4d3SLarry Finger 			      u8 element_id, u32 cmd_len, u8 *cmdbuffer)
271f1d2b4d3SLarry Finger {
272f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
273f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
274f1d2b4d3SLarry Finger 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
275f1d2b4d3SLarry Finger 	u8 boxnum;
276f1d2b4d3SLarry Finger 	u16 box_reg = 0, box_extreg = 0;
277f1d2b4d3SLarry Finger 	u8 u1b_tmp;
278f1d2b4d3SLarry Finger 	bool isfw_read = false;
279f1d2b4d3SLarry Finger 	u8 buf_index = 0;
280f1d2b4d3SLarry Finger 	bool bwrite_success = false;
281f1d2b4d3SLarry Finger 	u8 wait_h2c_limmit = 100;
282f1d2b4d3SLarry Finger 	u8 wait_writeh2c_limmit = 100;
283f1d2b4d3SLarry Finger 	u8 boxcontent[4], boxextcontent[2];
284f1d2b4d3SLarry Finger 	u32 h2c_waitcounter = 0;
285f1d2b4d3SLarry Finger 	unsigned long flag;
286f1d2b4d3SLarry Finger 	u8 idx;
287f1d2b4d3SLarry Finger 
288f1d2b4d3SLarry Finger 	if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
289*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
290f1d2b4d3SLarry Finger 			"Return as RF is off!!!\n");
291f1d2b4d3SLarry Finger 		return;
292f1d2b4d3SLarry Finger 	}
293*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
294f1d2b4d3SLarry Finger 	while (true) {
295f1d2b4d3SLarry Finger 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
296f1d2b4d3SLarry Finger 		if (rtlhal->h2c_setinprogress) {
297*6bf8bc19SLarry Finger 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
298f1d2b4d3SLarry Finger 				"H2C set in progress! Wait to set..element_id(%d)\n",
299f1d2b4d3SLarry Finger 				element_id);
300f1d2b4d3SLarry Finger 
301f1d2b4d3SLarry Finger 			while (rtlhal->h2c_setinprogress) {
302f1d2b4d3SLarry Finger 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
303f1d2b4d3SLarry Finger 						       flag);
304f1d2b4d3SLarry Finger 				h2c_waitcounter++;
305*6bf8bc19SLarry Finger 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
306f1d2b4d3SLarry Finger 					"Wait 100 us (%d times)...\n",
307f1d2b4d3SLarry Finger 					h2c_waitcounter);
308f1d2b4d3SLarry Finger 				udelay(100);
309f1d2b4d3SLarry Finger 
310f1d2b4d3SLarry Finger 				if (h2c_waitcounter > 1000)
311f1d2b4d3SLarry Finger 					return;
312f1d2b4d3SLarry Finger 
313f1d2b4d3SLarry Finger 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
314f1d2b4d3SLarry Finger 						  flag);
315f1d2b4d3SLarry Finger 			}
316f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
317f1d2b4d3SLarry Finger 		} else {
318f1d2b4d3SLarry Finger 			rtlhal->h2c_setinprogress = true;
319f1d2b4d3SLarry Finger 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
320f1d2b4d3SLarry Finger 			break;
321f1d2b4d3SLarry Finger 		}
322f1d2b4d3SLarry Finger 	}
323f1d2b4d3SLarry Finger 	while (!bwrite_success) {
324f1d2b4d3SLarry Finger 		wait_writeh2c_limmit--;
325f1d2b4d3SLarry Finger 		if (wait_writeh2c_limmit == 0) {
326b8c79f45SLarry Finger 			pr_err("Write H2C fail because no trigger for FW INT!\n");
327f1d2b4d3SLarry Finger 			break;
328f1d2b4d3SLarry Finger 		}
329f1d2b4d3SLarry Finger 		boxnum = rtlhal->last_hmeboxnum;
330f1d2b4d3SLarry Finger 		switch (boxnum) {
331f1d2b4d3SLarry Finger 		case 0:
332f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_0;
333f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_0;
334f1d2b4d3SLarry Finger 			break;
335f1d2b4d3SLarry Finger 		case 1:
336f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_1;
337f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_1;
338f1d2b4d3SLarry Finger 			break;
339f1d2b4d3SLarry Finger 		case 2:
340f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_2;
341f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_2;
342f1d2b4d3SLarry Finger 			break;
343f1d2b4d3SLarry Finger 		case 3:
344f1d2b4d3SLarry Finger 			box_reg = REG_HMEBOX_3;
345f1d2b4d3SLarry Finger 			box_extreg = REG_HMEBOX_EXT_3;
346f1d2b4d3SLarry Finger 			break;
347f1d2b4d3SLarry Finger 		default:
348b8c79f45SLarry Finger 			pr_err("switch case %#x not processed\n",
349b8c79f45SLarry Finger 			       boxnum);
350f1d2b4d3SLarry Finger 			break;
351f1d2b4d3SLarry Finger 		}
352f1d2b4d3SLarry Finger 		isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
353f1d2b4d3SLarry Finger 		while (!isfw_read) {
354f1d2b4d3SLarry Finger 			wait_h2c_limmit--;
355f1d2b4d3SLarry Finger 			if (wait_h2c_limmit == 0) {
356*6bf8bc19SLarry Finger 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
357f1d2b4d3SLarry Finger 					"Waiting too long for FW read clear HMEBox(%d)!\n",
358f1d2b4d3SLarry Finger 					boxnum);
359f1d2b4d3SLarry Finger 				break;
360f1d2b4d3SLarry Finger 			}
361f1d2b4d3SLarry Finger 			udelay(10);
362f1d2b4d3SLarry Finger 			isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
363f1d2b4d3SLarry Finger 			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
364*6bf8bc19SLarry Finger 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
365f1d2b4d3SLarry Finger 				"Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
366f1d2b4d3SLarry Finger 				boxnum, u1b_tmp);
367f1d2b4d3SLarry Finger 		}
368f1d2b4d3SLarry Finger 		if (!isfw_read) {
369*6bf8bc19SLarry Finger 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
370f1d2b4d3SLarry Finger 				"Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
371f1d2b4d3SLarry Finger 				boxnum);
372f1d2b4d3SLarry Finger 			break;
373f1d2b4d3SLarry Finger 		}
374f1d2b4d3SLarry Finger 		memset(boxcontent, 0, sizeof(boxcontent));
375f1d2b4d3SLarry Finger 		memset(boxextcontent, 0, sizeof(boxextcontent));
376f1d2b4d3SLarry Finger 		boxcontent[0] = element_id;
377*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
378f1d2b4d3SLarry Finger 			"Write element_id box_reg(%4x) = %2x\n",
379f1d2b4d3SLarry Finger 			box_reg, element_id);
380f1d2b4d3SLarry Finger 		switch (cmd_len) {
381f1d2b4d3SLarry Finger 		case 1:
382f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
383f1d2b4d3SLarry Finger 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
384f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++)
385f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
386f1d2b4d3SLarry Finger 					       boxcontent[idx]);
387f1d2b4d3SLarry Finger 			break;
388f1d2b4d3SLarry Finger 		case 2:
389f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
390f1d2b4d3SLarry Finger 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
391f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++)
392f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
393f1d2b4d3SLarry Finger 					       boxcontent[idx]);
394f1d2b4d3SLarry Finger 			break;
395f1d2b4d3SLarry Finger 		case 3:
396f1d2b4d3SLarry Finger 			boxcontent[0] &= ~(BIT(7));
397f1d2b4d3SLarry Finger 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
398f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++)
399f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
400f1d2b4d3SLarry Finger 					       boxcontent[idx]);
401f1d2b4d3SLarry Finger 			break;
402f1d2b4d3SLarry Finger 		case 4:
403f1d2b4d3SLarry Finger 			boxcontent[0] |= (BIT(7));
404f1d2b4d3SLarry Finger 			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
405f1d2b4d3SLarry Finger 			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
406f1d2b4d3SLarry Finger 			for (idx = 0; idx < 2; idx++)
407f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
408f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
409f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++)
410f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
411f1d2b4d3SLarry Finger 					       boxcontent[idx]);
412f1d2b4d3SLarry Finger 			break;
413f1d2b4d3SLarry Finger 		case 5:
414f1d2b4d3SLarry Finger 			boxcontent[0] |= (BIT(7));
415f1d2b4d3SLarry Finger 			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
416f1d2b4d3SLarry Finger 			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
417f1d2b4d3SLarry Finger 			for (idx = 0; idx < 2; idx++)
418f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_extreg + idx,
419f1d2b4d3SLarry Finger 					       boxextcontent[idx]);
420f1d2b4d3SLarry Finger 			for (idx = 0; idx < 4; idx++)
421f1d2b4d3SLarry Finger 				rtl_write_byte(rtlpriv, box_reg + idx,
422f1d2b4d3SLarry Finger 					       boxcontent[idx]);
423f1d2b4d3SLarry Finger 			break;
424f1d2b4d3SLarry Finger 		default:
425b8c79f45SLarry Finger 			pr_err("switch case %#x not processed\n",
426b8c79f45SLarry Finger 			       cmd_len);
427f1d2b4d3SLarry Finger 			break;
428f1d2b4d3SLarry Finger 		}
429f1d2b4d3SLarry Finger 		bwrite_success = true;
430f1d2b4d3SLarry Finger 		rtlhal->last_hmeboxnum = boxnum + 1;
431f1d2b4d3SLarry Finger 		if (rtlhal->last_hmeboxnum == 4)
432f1d2b4d3SLarry Finger 			rtlhal->last_hmeboxnum = 0;
433*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
434f1d2b4d3SLarry Finger 			"pHalData->last_hmeboxnum  = %d\n",
435f1d2b4d3SLarry Finger 			rtlhal->last_hmeboxnum);
436f1d2b4d3SLarry Finger 	}
437f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
438f1d2b4d3SLarry Finger 	rtlhal->h2c_setinprogress = false;
439f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
440*6bf8bc19SLarry Finger 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
441f1d2b4d3SLarry Finger }
442f1d2b4d3SLarry Finger 
rtl92d_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)443f1d2b4d3SLarry Finger void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
444f1d2b4d3SLarry Finger 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
445f1d2b4d3SLarry Finger {
446f1d2b4d3SLarry Finger 	u32 tmp_cmdbuf[2];
447f1d2b4d3SLarry Finger 
448f1d2b4d3SLarry Finger 	memset(tmp_cmdbuf, 0, 8);
449f1d2b4d3SLarry Finger 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
450f1d2b4d3SLarry Finger 	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
451f1d2b4d3SLarry Finger 	return;
452f1d2b4d3SLarry Finger }
453f1d2b4d3SLarry Finger 
_rtl92d_cmd_send_packet(struct ieee80211_hw * hw,struct sk_buff * skb)454f1d2b4d3SLarry Finger static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
455f1d2b4d3SLarry Finger 				    struct sk_buff *skb)
456f1d2b4d3SLarry Finger {
457f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
458f1d2b4d3SLarry Finger 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
459f1d2b4d3SLarry Finger 	struct rtl8192_tx_ring *ring;
460f1d2b4d3SLarry Finger 	struct rtl_tx_desc *pdesc;
461f1d2b4d3SLarry Finger 	u8 idx = 0;
462f1d2b4d3SLarry Finger 	unsigned long flags;
463f1d2b4d3SLarry Finger 	struct sk_buff *pskb;
464f1d2b4d3SLarry Finger 
465f1d2b4d3SLarry Finger 	ring = &rtlpci->tx_ring[BEACON_QUEUE];
466f1d2b4d3SLarry Finger 	pskb = __skb_dequeue(&ring->queue);
467f1d2b4d3SLarry Finger 	kfree_skb(pskb);
468f1d2b4d3SLarry Finger 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
469f1d2b4d3SLarry Finger 	pdesc = &ring->desc[idx];
470f1d2b4d3SLarry Finger 	/* discard output from call below */
4710c07bd74SPing-Ke Shih 	rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
472f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
473f1d2b4d3SLarry Finger 	__skb_queue_tail(&ring->queue, skb);
474f1d2b4d3SLarry Finger 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
475f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
476f1d2b4d3SLarry Finger 	return true;
477f1d2b4d3SLarry Finger }
478f1d2b4d3SLarry Finger 
479f1d2b4d3SLarry Finger #define BEACON_PG		0	/*->1 */
480f1d2b4d3SLarry Finger #define PSPOLL_PG		2
481f1d2b4d3SLarry Finger #define NULL_PG			3
482f1d2b4d3SLarry Finger #define PROBERSP_PG		4	/*->5 */
483f1d2b4d3SLarry Finger #define TOTAL_RESERVED_PKT_LEN	768
484f1d2b4d3SLarry Finger 
485f1d2b4d3SLarry Finger static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
486f1d2b4d3SLarry Finger 	/* page 0 beacon */
487f1d2b4d3SLarry Finger 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
488f1d2b4d3SLarry Finger 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
489f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
490f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
492f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
493f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
494f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
495f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
496f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
497f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
501f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503f1d2b4d3SLarry Finger 
504f1d2b4d3SLarry Finger 	/* page 1 beacon */
505f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517f1d2b4d3SLarry Finger 	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
518f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519f1d2b4d3SLarry Finger 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521f1d2b4d3SLarry Finger 
522f1d2b4d3SLarry Finger 	/* page 2  ps-poll */
523f1d2b4d3SLarry Finger 	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
524f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
525f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535f1d2b4d3SLarry Finger 	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
536f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
537f1d2b4d3SLarry Finger 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539f1d2b4d3SLarry Finger 
540f1d2b4d3SLarry Finger 	/* page 3  null */
541f1d2b4d3SLarry Finger 	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
542f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
543f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553f1d2b4d3SLarry Finger 	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
554f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
555f1d2b4d3SLarry Finger 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557f1d2b4d3SLarry Finger 
558f1d2b4d3SLarry Finger 	/* page 4  probe_resp */
559f1d2b4d3SLarry Finger 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
560f1d2b4d3SLarry Finger 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
561f1d2b4d3SLarry Finger 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
562f1d2b4d3SLarry Finger 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
563f1d2b4d3SLarry Finger 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
564f1d2b4d3SLarry Finger 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
565f1d2b4d3SLarry Finger 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
566f1d2b4d3SLarry Finger 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
567f1d2b4d3SLarry Finger 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
568f1d2b4d3SLarry Finger 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
569f1d2b4d3SLarry Finger 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572f1d2b4d3SLarry Finger 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
573f1d2b4d3SLarry Finger 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575f1d2b4d3SLarry Finger 
576f1d2b4d3SLarry Finger 	/* page 5  probe_resp */
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 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592f1d2b4d3SLarry Finger 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593f1d2b4d3SLarry Finger };
594f1d2b4d3SLarry Finger 
rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool dl_finished)595f1d2b4d3SLarry Finger void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
596f1d2b4d3SLarry Finger {
597f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
598f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
599f1d2b4d3SLarry Finger 	struct sk_buff *skb = NULL;
600f1d2b4d3SLarry Finger 	u32 totalpacketlen;
601f1d2b4d3SLarry Finger 	bool rtstatus;
602b83faedaSLarry Finger 	u8 u1rsvdpageloc[3] = { 0 };
603f1d2b4d3SLarry Finger 	bool dlok = false;
604f1d2b4d3SLarry Finger 	u8 *beacon;
605f1d2b4d3SLarry Finger 	u8 *p_pspoll;
606f1d2b4d3SLarry Finger 	u8 *nullfunc;
607f1d2b4d3SLarry Finger 	u8 *p_probersp;
608f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
609f1d2b4d3SLarry Finger 						(1) beacon
610f1d2b4d3SLarry Finger 	---------------------------------------------------------*/
611f1d2b4d3SLarry Finger 	beacon = &reserved_page_packet[BEACON_PG * 128];
612f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
613f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
614f1d2b4d3SLarry Finger 	/*-------------------------------------------------------
615f1d2b4d3SLarry Finger 						(2) ps-poll
616f1d2b4d3SLarry Finger 	--------------------------------------------------------*/
617f1d2b4d3SLarry Finger 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
618f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
619f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
620f1d2b4d3SLarry Finger 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
621b83faedaSLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
622f1d2b4d3SLarry Finger 	/*--------------------------------------------------------
623f1d2b4d3SLarry Finger 						(3) null data
624f1d2b4d3SLarry Finger 	---------------------------------------------------------*/
625f1d2b4d3SLarry Finger 	nullfunc = &reserved_page_packet[NULL_PG * 128];
626f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
627f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
628f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
629b83faedaSLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
630f1d2b4d3SLarry Finger 	/*---------------------------------------------------------
631f1d2b4d3SLarry Finger 						(4) probe response
632f1d2b4d3SLarry Finger 	----------------------------------------------------------*/
633f1d2b4d3SLarry Finger 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
634f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
635f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
636f1d2b4d3SLarry Finger 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
637b83faedaSLarry Finger 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
638f1d2b4d3SLarry Finger 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
639f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
640f1d2b4d3SLarry Finger 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
641f1d2b4d3SLarry Finger 		      &reserved_page_packet[0], totalpacketlen);
642f1d2b4d3SLarry Finger 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
643f1d2b4d3SLarry Finger 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
644b83faedaSLarry Finger 		      u1rsvdpageloc, 3);
645f1d2b4d3SLarry Finger 	skb = dev_alloc_skb(totalpacketlen);
646f1d2b4d3SLarry Finger 	if (!skb) {
647f1d2b4d3SLarry Finger 		dlok = false;
648f1d2b4d3SLarry Finger 	} else {
649ad941e69Syuan linyu 		skb_put_data(skb, &reserved_page_packet, totalpacketlen);
650f1d2b4d3SLarry Finger 		rtstatus = _rtl92d_cmd_send_packet(hw, skb);
651f1d2b4d3SLarry Finger 
652f1d2b4d3SLarry Finger 		if (rtstatus)
653f1d2b4d3SLarry Finger 			dlok = true;
654f1d2b4d3SLarry Finger 	}
655f1d2b4d3SLarry Finger 	if (dlok) {
656*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
657f1d2b4d3SLarry Finger 			"Set RSVD page location to Fw\n");
658f1d2b4d3SLarry Finger 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
659b83faedaSLarry Finger 			      "H2C_RSVDPAGE", u1rsvdpageloc, 3);
660f1d2b4d3SLarry Finger 		rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
661b83faedaSLarry Finger 			sizeof(u1rsvdpageloc), u1rsvdpageloc);
662f1d2b4d3SLarry Finger 	} else
663*6bf8bc19SLarry Finger 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
664f1d2b4d3SLarry Finger 			"Set RSVD page location to Fw FAIL!!!!!!\n");
665f1d2b4d3SLarry Finger }
666f1d2b4d3SLarry Finger 
rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw * hw,u8 mstatus)667f1d2b4d3SLarry Finger void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
668f1d2b4d3SLarry Finger {
669f1d2b4d3SLarry Finger 	u8 u1_joinbssrpt_parm[1] = {0};
670f1d2b4d3SLarry Finger 
671f1d2b4d3SLarry Finger 	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
672f1d2b4d3SLarry Finger 	rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
673f1d2b4d3SLarry Finger }
674