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
13static 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
19static 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
41static 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	rtl_dbg(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
69static 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
90void 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	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
108		"=====> 8051 reset success (%d)\n", delay);
109}
110
111static 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	rtl_dbg(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				rtl_dbg(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				rtl_dbg(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		rtl_dbg(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		rtl_dbg(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	rtl_dbg(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
159int 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	rtl_dbg(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		rtl_dbg(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				rtl_dbg(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");
252exit:
253	err = _rtl92d_fw_init(hw);
254	return err;
255}
256
257static 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
269static 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		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
290			"Return as RF is off!!!\n");
291		return;
292	}
293	rtl_dbg(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			rtl_dbg(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				rtl_dbg(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				rtl_dbg(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			rtl_dbg(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			rtl_dbg(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		rtl_dbg(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		rtl_dbg(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	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
441}
442
443void 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
454static 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, 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
485static 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
595void 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		rtl_dbg(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		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
664			"Set RSVD page location to Fw FAIL!!!!!!\n");
665}
666
667void 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