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
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 ****************************************************************************
38 static void _rtl8723ae_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
40 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
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);
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
),
78 offset
= blockCount
* blockSize
;
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
);
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
,
104 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
105 u8
*bufferPtr
= (u8
*) buffer
;
106 u32 page_nums
, remain_size
;
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
;
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
),
126 offset
= page_nums
* FW_8192C_PAGE_SIZE
;
128 _rtl8723ae_fw_page_write(hw
, page
, (bufferPtr
+ offset
),
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
);
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",
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
);
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",
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
);
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
;
193 enum version_8723e version
= rtlhal
->version
;
195 if (!rtlhal
->pfirmware
)
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
);
222 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
223 "Firmware is not ready to run!\n");
225 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
226 "Firmware is ready to run!\n");
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
;
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)
245 static void _rtl8723ae_fill_h2c_command(struct ieee80211_hw
*hw
,
246 u8 element_id
, u32 cmd_len
,
249 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
250 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
252 u16 box_reg
= 0, box_extreg
= 0;
254 bool isfw_rd
= false;
255 bool bwrite_success
= false;
256 u8 wait_h2c_limmit
= 100;
257 u8 wait_writeh2c_limmit
= 100;
258 u8 boxcontent
[4], boxextcontent
[2];
259 u32 h2c_waitcounter
= 0;
263 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
, "come in\n");
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",
272 while (rtlhal
->h2c_setinprogress
) {
273 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
,
276 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
277 "Wait 100 us (%d times)...\n",
281 if (h2c_waitcounter
> 1000)
283 spin_lock_irqsave(&rtlpriv
->locks
.h2c_lock
,
286 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
288 rtlhal
->h2c_setinprogress
= true;
289 spin_unlock_irqrestore(&rtlpriv
->locks
.h2c_lock
, flag
);
294 while (!bwrite_success
) {
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 "
303 boxnum
= rtlhal
->last_hmeboxnum
;
306 box_reg
= REG_HMEBOX_0
;
307 box_extreg
= REG_HMEBOX_EXT_0
;
310 box_reg
= REG_HMEBOX_1
;
311 box_extreg
= REG_HMEBOX_EXT_1
;
314 box_reg
= REG_HMEBOX_2
;
315 box_extreg
= REG_HMEBOX_EXT_2
;
318 box_reg
= REG_HMEBOX_3
;
319 box_extreg
= REG_HMEBOX_EXT_3
;
322 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
323 "switch case not processed\n");
327 isfw_rd
= rtl8723ae_check_fw_read_last_h2c(hw
, boxnum
);
331 if (wait_h2c_limmit
== 0) {
332 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
333 "Waiting too long for FW read clear HMEBox(%d)!\n",
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 "Waiting for FW read clear HMEBox(%d)!!! "
344 "0x1BF = %2x\n", boxnum
, u1tmp
);
348 RT_TRACE(rtlpriv
, COMP_CMD
, DBG_LOUD
,
349 "Write H2C register BOX[%d] fail!!!!! "
350 "Fw do not read.\n", boxnum
);
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
);
363 boxcontent
[0] &= ~(BIT(7));
364 memcpy((u8
*) (boxcontent
) + 1,
367 for (idx
= 0; idx
< 4; idx
++) {
368 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
373 boxcontent
[0] &= ~(BIT(7));
374 memcpy((u8
*) (boxcontent
) + 1,
377 for (idx
= 0; idx
< 4; idx
++) {
378 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
383 boxcontent
[0] &= ~(BIT(7));
384 memcpy((u8
*) (boxcontent
) + 1,
387 for (idx
= 0; idx
< 4; idx
++) {
388 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
393 boxcontent
[0] |= (BIT(7));
394 memcpy((u8
*) (boxextcontent
),
396 memcpy((u8
*) (boxcontent
) + 1,
399 for (idx
= 0; idx
< 2; idx
++) {
400 rtl_write_byte(rtlpriv
, box_extreg
+ idx
,
404 for (idx
= 0; idx
< 4; idx
++) {
405 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
410 boxcontent
[0] |= (BIT(7));
411 memcpy((u8
*) (boxextcontent
),
413 memcpy((u8
*) (boxcontent
) + 1,
416 for (idx
= 0; idx
< 2; idx
++) {
417 rtl_write_byte(rtlpriv
, box_extreg
+ idx
,
421 for (idx
= 0; idx
< 4; idx
++) {
422 rtl_write_byte(rtlpriv
, box_reg
+ idx
,
427 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
428 "switch case not process\n");
432 bwrite_success
= 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) {
458 "return H2C cmd because of Fw download fail!!!\n");
462 _rtl8723ae_fill_h2c_command(hw
, element_id
, cmd_len
, p_cmdbuffer
);
466 void rtl8723ae_firmware_selfreset(struct ieee80211_hw
*hw
)
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)) {
480 u1tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
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
,
498 (rtlpriv
->mac80211
.p2p
) ?
500 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode
,
501 ppsc
->reg_max_lps_awakeintvl
);
503 RT_PRINT_DATA(rtlpriv
, COMP_CMD
, DBG_DMESG
,
504 "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
505 u1_h2c_set_pwrmode
, 3);
506 rtl8723ae_fill_h2c_cmd(hw
, H2C_SETPWRMODE
, 3, u1_h2c_set_pwrmode
);
510 static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw
*hw
,
513 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
514 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
515 struct rtl8192_tx_ring
*ring
;
516 struct rtl_tx_desc
*pdesc
;
518 struct sk_buff
*pskb
= NULL
;
520 ring
= &rtlpci
->tx_ring
[BEACON_QUEUE
];
522 pskb
= __skb_dequeue(&ring
->queue
);
526 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
528 pdesc
= &ring
->desc
[0];
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
);
541 static u8 reserved_page_packet
[TOTAL_RESERVED_PKT_LEN
] = {
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,
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,
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,
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
;
659 u8 u1RsvdPageLoc
[3] = { 0 };
666 /*---------------------------------------------------------
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 /*-------------------------------------------------------
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 /*--------------------------------------------------------
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 /*---------------------------------------------------------
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",
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
);
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
,
731 rtl8723ae_fill_h2c_cmd(hw
, H2C_RSVDPAGE
,
732 sizeof(u1RsvdPageLoc
), u1RsvdPageLoc
);
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
);
747 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw
*hw
,
750 u8 u1_ctwindow_period
[1] = {ctwindow
};
752 rtl8723ae_fill_h2c_cmd(hw
, H2C_P2P_PS_CTW_CMD
, 1, u1_ctwindow_period
);
755 void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw
*hw
, u8 p2p_ps_state
)
757 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
758 struct rtl_ps_ctl
*rtlps
= rtl_psc(rtl_priv(hw
));
759 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
760 struct rtl_p2p_ps_info
*p2pinfo
= &(rtlps
->p2p_ps_info
);
761 struct p2p_ps_offload_t
*p2p_ps_offload
= &rtlhal
->p2p_ps_offload
;
764 u32 start_time
, tsf_low
;
766 switch (p2p_ps_state
) {
768 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_DISABLE\n");
769 memset(p2p_ps_offload
, 0, sizeof(struct p2p_ps_offload_t
));
772 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_ENABLE\n");
773 /* update CTWindow value. */
774 if (p2pinfo
->ctwindow
> 0) {
775 p2p_ps_offload
->ctwindow_en
= 1;
776 ctwindow
= p2pinfo
->ctwindow
;
777 rtl8723e_set_p2p_ctw_period_cmd(hw
, ctwindow
);
780 /* hw only support 2 set of NoA */
781 for (i
= 0; i
< p2pinfo
->noa_num
; i
++) {
782 /* To control the register setting for which NOA*/
783 rtl_write_byte(rtlpriv
, 0x5cf, (i
<< 4));
785 p2p_ps_offload
->noa0_en
= 1;
787 p2p_ps_offload
->noa1_en
= 1;
789 /* config P2P NoA Descriptor Register */
790 rtl_write_dword(rtlpriv
, 0x5E0,
791 p2pinfo
->noa_duration
[i
]);
792 rtl_write_dword(rtlpriv
, 0x5E4,
793 p2pinfo
->noa_interval
[i
]);
795 /*Get Current TSF value */
796 tsf_low
= rtl_read_dword(rtlpriv
, REG_TSFTR
);
798 start_time
= p2pinfo
->noa_start_time
[i
];
799 if (p2pinfo
->noa_count_type
[i
] != 1) {
800 while (start_time
<= (tsf_low
+(50*1024))) {
801 start_time
+= p2pinfo
->noa_interval
[i
];
802 if (p2pinfo
->noa_count_type
[i
] != 255)
803 p2pinfo
->noa_count_type
[i
]--;
806 rtl_write_dword(rtlpriv
, 0x5E8, start_time
);
807 rtl_write_dword(rtlpriv
, 0x5EC,
808 p2pinfo
->noa_count_type
[i
]);
810 if ((p2pinfo
->opp_ps
== 1) || (p2pinfo
->noa_num
> 0)) {
811 /* rst p2p circuit */
812 rtl_write_byte(rtlpriv
, REG_DUAL_TSF_RST
, BIT(4));
814 p2p_ps_offload
->offload_en
= 1;
816 if (P2P_ROLE_GO
== rtlpriv
->mac80211
.p2p
) {
817 p2p_ps_offload
->role
= 1;
818 p2p_ps_offload
->allstasleep
= 0;
820 p2p_ps_offload
->role
= 0;
822 p2p_ps_offload
->discovery
= 0;
826 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN\n");
827 p2p_ps_offload
->discovery
= 1;
829 case P2P_PS_SCAN_DONE
:
830 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "P2P_PS_SCAN_DONE\n");
831 p2p_ps_offload
->discovery
= 0;
832 p2pinfo
->p2p_ps_state
= P2P_PS_ENABLE
;
837 rtl8723ae_fill_h2c_cmd(hw
, H2C_P2P_PS_OFFLOAD
, 1, (u8
*)p2p_ps_offload
);