rtlwifi: rtl8723ae: Add new driver
[linux-2.6.git] / drivers / net / wireless / rtlwifi / rtl8723ae / fw.c
blobf55b1767ef574cd8c7afdfa4a98509008f1472f3
1 /******************************************************************************
3 * Copyright(c) 2009-2012 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
28 ****************************************************************************
31 #include "../wifi.h"
32 #include "../pci.h"
33 #include "../base.h"
34 #include "reg.h"
35 #include "def.h"
36 #include "fw.h"
38 static void _rtl8723ae_enable_fw_download(struct ieee80211_hw *hw, bool enable)
40 struct rtl_priv *rtlpriv = rtl_priv(hw);
41 u8 tmp;
42 if (enable) {
43 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
44 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
49 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
50 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
51 } else {
52 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
53 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
55 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
59 static void _rtl8723ae_fw_block_write(struct ieee80211_hw *hw,
60 const u8 *buffer, u32 size)
62 struct rtl_priv *rtlpriv = rtl_priv(hw);
63 u32 blockSize = sizeof(u32);
64 u8 *bufferPtr = (u8 *) buffer;
65 u32 *pu4BytePtr = (u32 *) buffer;
66 u32 i, offset, blockCount, remainSize;
68 blockCount = size / blockSize;
69 remainSize = size % blockSize;
71 for (i = 0; i < blockCount; i++) {
72 offset = i * blockSize;
73 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
74 *(pu4BytePtr + i));
77 if (remainSize) {
78 offset = blockCount * blockSize;
79 bufferPtr += offset;
80 for (i = 0; i < remainSize; i++) {
81 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
82 offset + i), *(bufferPtr + i));
87 static void _rtl8723ae_fw_page_write(struct ieee80211_hw *hw,
88 u32 page, const u8 *buffer, u32 size)
90 struct rtl_priv *rtlpriv = rtl_priv(hw);
91 u8 value8;
92 u8 u8page = (u8) (page & 0x07);
94 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
96 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
97 _rtl8723ae_fw_block_write(hw, buffer, size);
100 static void _rtl8723ae_write_fw(struct ieee80211_hw *hw,
101 enum version_8723e version, u8 *buffer,
102 u32 size)
104 struct rtl_priv *rtlpriv = rtl_priv(hw);
105 u8 *bufferPtr = (u8 *) buffer;
106 u32 page_nums, remain_size;
107 u32 page, offset;
109 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
111 page_nums = size / FW_8192C_PAGE_SIZE;
112 remain_size = size % FW_8192C_PAGE_SIZE;
114 if (page_nums > 6) {
115 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
116 "Page numbers should not be greater then 6\n");
119 for (page = 0; page < page_nums; page++) {
120 offset = page * FW_8192C_PAGE_SIZE;
121 _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
122 FW_8192C_PAGE_SIZE);
125 if (remain_size) {
126 offset = page_nums * FW_8192C_PAGE_SIZE;
127 page = page_nums;
128 _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
129 remain_size);
132 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
135 static int _rtl8723ae_fw_free_to_go(struct ieee80211_hw *hw)
137 struct rtl_priv *rtlpriv = rtl_priv(hw);
138 int err = -EIO;
139 u32 counter = 0;
140 u32 value32;
142 do {
143 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
144 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
145 (!(value32 & FWDL_ChkSum_rpt)));
147 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
148 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
149 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
150 value32);
151 goto exit;
154 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
155 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
157 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
158 value32 |= MCUFWDL_RDY;
159 value32 &= ~WINTINI_RDY;
160 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
162 counter = 0;
164 do {
165 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
166 if (value32 & WINTINI_RDY) {
167 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
168 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
169 value32);
170 err = 0;
171 goto exit;
174 mdelay(FW_8192C_POLLING_DELAY);
176 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
178 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
179 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
181 exit:
182 return err;
185 int rtl8723ae_download_fw(struct ieee80211_hw *hw)
187 struct rtl_priv *rtlpriv = rtl_priv(hw);
188 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
189 struct rtl8723ae_firmware_header *pfwheader;
190 u8 *pfwdata;
191 u32 fwsize;
192 int err;
193 enum version_8723e version = rtlhal->version;
195 if (!rtlhal->pfirmware)
196 return 1;
198 pfwheader = (struct rtl8723ae_firmware_header *)rtlhal->pfirmware;
199 pfwdata = (u8 *) rtlhal->pfirmware;
200 fwsize = rtlhal->fwsize;
202 if (IS_FW_HEADER_EXIST(pfwheader)) {
203 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
204 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
205 pfwheader->version, pfwheader->signature,
206 (int)sizeof(struct rtl8723ae_firmware_header));
208 pfwdata = pfwdata + sizeof(struct rtl8723ae_firmware_header);
209 fwsize = fwsize - sizeof(struct rtl8723ae_firmware_header);
212 if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
213 rtl8723ae_firmware_selfreset(hw);
214 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
216 _rtl8723ae_enable_fw_download(hw, true);
217 _rtl8723ae_write_fw(hw, version, pfwdata, fwsize);
218 _rtl8723ae_enable_fw_download(hw, false);
220 err = _rtl8723ae_fw_free_to_go(hw);
221 if (err) {
222 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
223 "Firmware is not ready to run!\n");
224 } else {
225 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
226 "Firmware is ready to run!\n");
228 return 0;
231 static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
233 struct rtl_priv *rtlpriv = rtl_priv(hw);
234 u8 val_hmetfr, val_mcutst_1;
235 bool result = false;
237 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
238 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
240 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
241 result = true;
242 return result;
245 static void _rtl8723ae_fill_h2c_command(struct ieee80211_hw *hw,
246 u8 element_id, u32 cmd_len,
247 u8 *p_cmdbuffer)
249 struct rtl_priv *rtlpriv = rtl_priv(hw);
250 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
251 u8 boxnum;
252 u16 box_reg = 0, box_extreg = 0;
253 u8 u1tmp;
254 bool isfw_rd = false;
255 bool bwrite_sucess = false;
256 u8 wait_h2c_limmit = 100;
257 u8 wait_writeh2c_limmit = 100;
258 u8 boxcontent[4], boxextcontent[2];
259 u32 h2c_waitcounter = 0;
260 unsigned long flag;
261 u8 idx;
263 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
265 while (true) {
266 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
267 if (rtlhal->h2c_setinprogress) {
268 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
269 "H2C set in progress! Wait to set..element_id(%d).\n",
270 element_id);
272 while (rtlhal->h2c_setinprogress) {
273 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
274 flag);
275 h2c_waitcounter++;
276 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
277 "Wait 100 us (%d times)...\n",
278 h2c_waitcounter);
279 udelay(100);
281 if (h2c_waitcounter > 1000)
282 return;
283 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
284 flag);
286 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
287 } else {
288 rtlhal->h2c_setinprogress = true;
289 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
290 break;
294 while (!bwrite_sucess) {
295 wait_writeh2c_limmit--;
296 if (wait_writeh2c_limmit == 0) {
297 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
298 "Write H2C fail because no trigger "
299 "for FW INT!\n");
300 break;
303 boxnum = rtlhal->last_hmeboxnum;
304 switch (boxnum) {
305 case 0:
306 box_reg = REG_HMEBOX_0;
307 box_extreg = REG_HMEBOX_EXT_0;
308 break;
309 case 1:
310 box_reg = REG_HMEBOX_1;
311 box_extreg = REG_HMEBOX_EXT_1;
312 break;
313 case 2:
314 box_reg = REG_HMEBOX_2;
315 box_extreg = REG_HMEBOX_EXT_2;
316 break;
317 case 3:
318 box_reg = REG_HMEBOX_3;
319 box_extreg = REG_HMEBOX_EXT_3;
320 break;
321 default:
322 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
323 "switch case not processed\n");
324 break;
327 isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
328 while (!isfw_rd) {
330 wait_h2c_limmit--;
331 if (wait_h2c_limmit == 0) {
332 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
333 "Wating too long for FW read clear HMEBox(%d)!\n",
334 boxnum);
335 break;
338 udelay(10);
340 isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
341 u1tmp = rtl_read_byte(rtlpriv, 0x1BF);
342 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
343 "Wating for FW read clear HMEBox(%d)!!! "
344 "0x1BF = %2x\n", boxnum, u1tmp);
347 if (!isfw_rd) {
348 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
349 "Write H2C register BOX[%d] fail!!!!! "
350 "Fw do not read.\n", boxnum);
351 break;
354 memset(boxcontent, 0, sizeof(boxcontent));
355 memset(boxextcontent, 0, sizeof(boxextcontent));
356 boxcontent[0] = element_id;
357 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
358 "Write element_id box_reg(%4x) = %2x\n",
359 box_reg, element_id);
361 switch (cmd_len) {
362 case 1:
363 boxcontent[0] &= ~(BIT(7));
364 memcpy((u8 *) (boxcontent) + 1,
365 p_cmdbuffer, 1);
367 for (idx = 0; idx < 4; idx++) {
368 rtl_write_byte(rtlpriv, box_reg + idx,
369 boxcontent[idx]);
371 break;
372 case 2:
373 boxcontent[0] &= ~(BIT(7));
374 memcpy((u8 *) (boxcontent) + 1,
375 p_cmdbuffer, 2);
377 for (idx = 0; idx < 4; idx++) {
378 rtl_write_byte(rtlpriv, box_reg + idx,
379 boxcontent[idx]);
381 break;
382 case 3:
383 boxcontent[0] &= ~(BIT(7));
384 memcpy((u8 *) (boxcontent) + 1,
385 p_cmdbuffer, 3);
387 for (idx = 0; idx < 4; idx++) {
388 rtl_write_byte(rtlpriv, box_reg + idx,
389 boxcontent[idx]);
391 break;
392 case 4:
393 boxcontent[0] |= (BIT(7));
394 memcpy((u8 *) (boxextcontent),
395 p_cmdbuffer, 2);
396 memcpy((u8 *) (boxcontent) + 1,
397 p_cmdbuffer + 2, 2);
399 for (idx = 0; idx < 2; idx++) {
400 rtl_write_byte(rtlpriv, box_extreg + idx,
401 boxextcontent[idx]);
404 for (idx = 0; idx < 4; idx++) {
405 rtl_write_byte(rtlpriv, box_reg + idx,
406 boxcontent[idx]);
408 break;
409 case 5:
410 boxcontent[0] |= (BIT(7));
411 memcpy((u8 *) (boxextcontent),
412 p_cmdbuffer, 2);
413 memcpy((u8 *) (boxcontent) + 1,
414 p_cmdbuffer + 2, 3);
416 for (idx = 0; idx < 2; idx++) {
417 rtl_write_byte(rtlpriv, box_extreg + idx,
418 boxextcontent[idx]);
421 for (idx = 0; idx < 4; idx++) {
422 rtl_write_byte(rtlpriv, box_reg + idx,
423 boxcontent[idx]);
425 break;
426 default:
427 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
428 "switch case not process\n");
429 break;
432 bwrite_sucess = true;
434 rtlhal->last_hmeboxnum = boxnum + 1;
435 if (rtlhal->last_hmeboxnum == 4)
436 rtlhal->last_hmeboxnum = 0;
438 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
439 "pHalData->last_hmeboxnum = %d\n",
440 rtlhal->last_hmeboxnum);
443 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
444 rtlhal->h2c_setinprogress = false;
445 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
447 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
450 void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
451 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
453 struct rtl_priv *rtlpriv = rtl_priv(hw);
454 struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
456 if (rtlhal->fw_ready == false) {
457 RT_ASSERT(false,
458 "return H2C cmd because of Fw download fail!!!\n");
459 return;
462 _rtl8723ae_fill_h2c_command(hw, element_id, cmd_len, p_cmdbuffer);
463 return;
466 void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
468 u8 u1tmp;
469 u8 delay = 100;
470 struct rtl_priv *rtlpriv = rtl_priv(hw);
472 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
473 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
475 while (u1tmp & BIT(2)) {
476 delay--;
477 if (delay == 0)
478 break;
479 udelay(50);
480 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
482 if (delay == 0) {
483 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1tmp&(~BIT(2)));
488 void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
490 struct rtl_priv *rtlpriv = rtl_priv(hw);
491 u8 u1_h2c_set_pwrmode[3] = { 0 };
492 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
494 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
496 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
497 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
498 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
499 ppsc->reg_max_lps_awakeintvl);
501 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
502 "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
503 u1_h2c_set_pwrmode, 3);
504 rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
508 static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
509 struct sk_buff *skb)
511 struct rtl_priv *rtlpriv = rtl_priv(hw);
512 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
513 struct rtl8192_tx_ring *ring;
514 struct rtl_tx_desc *pdesc;
515 u8 own;
516 unsigned long flags;
517 struct sk_buff *pskb = NULL;
519 ring = &rtlpci->tx_ring[BEACON_QUEUE];
521 pskb = __skb_dequeue(&ring->queue);
522 if (pskb)
523 kfree_skb(pskb);
525 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
527 pdesc = &ring->desc[0];
528 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
530 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
532 __skb_queue_tail(&ring->queue, skb);
534 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
536 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
538 return true;
541 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
542 /* page 0 beacon */
543 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
544 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
545 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
548 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
549 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
550 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
551 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
552 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
553 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
557 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 /* page 1 beacon */
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 /* page 2 ps-poll */
579 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
580 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
593 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 /* page 3 null */
597 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
598 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
599 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
611 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 /* page 4 probe_resp */
615 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
616 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
617 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
618 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
619 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
620 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
621 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
622 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
623 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
624 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
625 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
629 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 /* page 5 probe_resp */
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
653 struct rtl_priv *rtlpriv = rtl_priv(hw);
654 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
655 struct sk_buff *skb = NULL;
657 u32 totalpacketlen;
658 bool rtstatus;
659 u8 u1RsvdPageLoc[3] = { 0 };
660 bool dlok = false;
662 u8 *beacon;
663 u8 *p_pspoll;
664 u8 *nullfunc;
665 u8 *p_probersp;
666 /*---------------------------------------------------------
667 (1) beacon
668 ---------------------------------------------------------
670 beacon = &reserved_page_packet[BEACON_PG * 128];
671 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
672 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
674 /*-------------------------------------------------------
675 (2) ps-poll
676 --------------------------------------------------------
678 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
679 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
680 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
681 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
683 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
685 /*--------------------------------------------------------
686 (3) null data
687 ---------------------------------------------------------i
689 nullfunc = &reserved_page_packet[NULL_PG * 128];
690 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
691 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
692 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
694 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
696 /*---------------------------------------------------------
697 (4) probe response
698 ----------------------------------------------------------
700 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
701 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
702 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
703 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
705 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
707 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
709 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
710 "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
711 &reserved_page_packet[0], totalpacketlen);
712 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
713 "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
714 u1RsvdPageLoc, 3);
716 skb = dev_alloc_skb(totalpacketlen);
717 memcpy((u8 *) skb_put(skb, totalpacketlen),
718 &reserved_page_packet, totalpacketlen);
720 rtstatus = _rtl8723ae_cmd_send_packet(hw, skb);
722 if (rtstatus)
723 dlok = true;
725 if (dlok) {
726 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
727 "Set RSVD page location to Fw.\n");
728 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
729 "H2C_RSVDPAGE:\n",
730 u1RsvdPageLoc, 3);
731 rtl8723ae_fill_h2c_cmd(hw, H2C_RSVDPAGE,
732 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
733 } else
734 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
735 "Set RSVD page location to Fw FAIL!!!!!!.\n");
738 void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
740 u8 u1_joinbssrpt_parm[1] = { 0 };
742 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
744 rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);