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