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