1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "../wifi.h"
27#include "../pci.h"
28#include "../base.h"
29#include "../core.h"
30#include "reg.h"
31#include "def.h"
32#include "fw.h"
33
34static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
35{
36 struct rtl_priv *rtlpriv = rtl_priv(hw);
37 u8 tmp;
38
39 if (enable) {
40 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
41 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
42
43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
44 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
45
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
48 } else {
49 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
50 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
51
52 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
53 }
54}
55
56static void _rtl88e_fw_block_write(struct ieee80211_hw *hw,
57 const u8 *buffer, u32 size)
58{
59 struct rtl_priv *rtlpriv = rtl_priv(hw);
60 u32 blocksize = sizeof(u32);
61 u8 *bufferptr = (u8 *)buffer;
62 u32 *pu4BytePtr = (u32 *)buffer;
63 u32 i, offset, blockcount, remainsize;
64
65 blockcount = size / blocksize;
66 remainsize = size % blocksize;
67
68 for (i = 0; i < blockcount; i++) {
69 offset = i * blocksize;
70 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
71 *(pu4BytePtr + i));
72 }
73
74 if (remainsize) {
75 offset = blockcount * blocksize;
76 bufferptr += offset;
77 for (i = 0; i < remainsize; i++) {
78 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
79 offset + i), *(bufferptr + i));
80 }
81 }
82}
83
84static void _rtl88e_fw_page_write(struct ieee80211_hw *hw,
85 u32 page, const u8 *buffer, u32 size)
86{
87 struct rtl_priv *rtlpriv = rtl_priv(hw);
88 u8 value8;
89 u8 u8page = (u8) (page & 0x07);
90
91 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
92
93 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
94 _rtl88e_fw_block_write(hw, buffer, size);
95}
96
97static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
98{
99 u32 fwlen = *pfwlen;
100 u8 remain = (u8) (fwlen % 4);
101
102 remain = (remain == 0) ? 0 : (4 - remain);
103
104 while (remain > 0) {
105 pfwbuf[fwlen] = 0;
106 fwlen++;
107 remain--;
108 }
109
110 *pfwlen = fwlen;
111}
112
113static void _rtl88e_write_fw(struct ieee80211_hw *hw,
114 enum version_8188e version, u8 *buffer, u32 size)
115{
116 struct rtl_priv *rtlpriv = rtl_priv(hw);
117 u8 *bufferptr = (u8 *)buffer;
118 u32 pagenums, remainsize;
119 u32 page, offset;
120
121 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
122
123 _rtl88e_fill_dummy(bufferptr, &size);
124
125 pagenums = size / FW_8192C_PAGE_SIZE;
126 remainsize = size % FW_8192C_PAGE_SIZE;
127
128 if (pagenums > 8) {
129 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
130 "Page numbers should not greater then 8\n");
131 }
132
133 for (page = 0; page < pagenums; page++) {
134 offset = page * FW_8192C_PAGE_SIZE;
135 _rtl88e_fw_page_write(hw, page, (bufferptr + offset),
136 FW_8192C_PAGE_SIZE);
137 }
138
139 if (remainsize) {
140 offset = pagenums * FW_8192C_PAGE_SIZE;
141 page = pagenums;
142 _rtl88e_fw_page_write(hw, page, (bufferptr + offset),
143 remainsize);
144 }
145}
146
147static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
148{
149 struct rtl_priv *rtlpriv = rtl_priv(hw);
150 int err = -EIO;
151 u32 counter = 0;
152 u32 value32;
153
154 do {
155 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
156 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
157 (!(value32 & FWDL_CHKSUM_RPT)));
158
159 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
160 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
161 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
162 value32);
163 goto exit;
164 }
165
166 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
167 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
168
169 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
170 value32 |= MCUFWDL_RDY;
171 value32 &= ~WINTINI_RDY;
172 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
173
174 rtl88e_firmware_selfreset(hw);
175 counter = 0;
176
177 do {
178 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
179 if (value32 & WINTINI_RDY) {
180 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
181 "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n",
182 value32);
183 err = 0;
184 goto exit;
185 }
186
187 udelay(FW_8192C_POLLING_DELAY);
188
189 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
190
191 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
192 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
193
194exit:
195 return err;
196}
197
198int rtl88e_download_fw(struct ieee80211_hw *hw,
199 bool buse_wake_on_wlan_fw)
200{
201 struct rtl_priv *rtlpriv = rtl_priv(hw);
202 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
203 struct rtlwifi_firmware_header *pfwheader;
204 u8 *pfwdata;
205 u32 fwsize;
206 int err;
207 enum version_8188e version = rtlhal->version;
208
209 if (!rtlhal->pfirmware)
210 return 1;
211
212 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
213 pfwdata = rtlhal->pfirmware;
214 fwsize = rtlhal->fwsize;
215 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
216 "normal Firmware SIZE %d\n", fwsize);
217
218 if (IS_FW_HEADER_EXIST(pfwheader)) {
219 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
220 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
221 pfwheader->version, pfwheader->signature,
222 (int)sizeof(struct rtlwifi_firmware_header));
223
224 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
225 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
226 }
227
228 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
229 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
230 rtl88e_firmware_selfreset(hw);
231 }
232 _rtl88e_enable_fw_download(hw, true);
233 _rtl88e_write_fw(hw, version, pfwdata, fwsize);
234 _rtl88e_enable_fw_download(hw, false);
235
236 err = _rtl88e_fw_free_to_go(hw);
237 if (err) {
238 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
239 "Firmware is not ready to run!\n");
240 } else {
241 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
242 "Firmware is ready to run!\n");
243 }
244
245 return 0;
246}
247
248static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
249{
250 struct rtl_priv *rtlpriv = rtl_priv(hw);
251 u8 val_hmetfr;
252
253 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
254 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
255 return true;
256 return false;
257}
258
259static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
260 u8 element_id, u32 cmd_len,
261 u8 *cmd_b)
262{
263 struct rtl_priv *rtlpriv = rtl_priv(hw);
264 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
265 u8 boxnum;
266 u16 box_reg = 0, box_extreg = 0;
267 u8 u1b_tmp;
268 bool isfw_read = false;
269 u8 buf_index = 0;
270 bool write_sucess = false;
271 u8 wait_h2c_limmit = 100;
272 u8 wait_writeh2c_limit = 100;
273 u8 boxcontent[4], boxextcontent[4];
274 u32 h2c_waitcounter = 0;
275 unsigned long flag;
276 u8 idx;
277
278 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
279
280 while (true) {
281 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
282 if (rtlhal->h2c_setinprogress) {
283 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
284 "H2C set in progress! Wait to set..element_id(%d).\n",
285 element_id);
286
287 while (rtlhal->h2c_setinprogress) {
288 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
289 flag);
290 h2c_waitcounter++;
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
292 "Wait 100 us (%d times)...\n",
293 h2c_waitcounter);
294 udelay(100);
295
296 if (h2c_waitcounter > 1000)
297 return;
298 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
299 flag);
300 }
301 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
302 } else {
303 rtlhal->h2c_setinprogress = true;
304 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
305 break;
306 }
307 }
308
309 while (!write_sucess) {
310 wait_writeh2c_limit--;
311 if (wait_writeh2c_limit == 0) {
312 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
313 "Write H2C fail because no trigger for FW INT!\n");
314 break;
315 }
316
317 boxnum = rtlhal->last_hmeboxnum;
318 switch (boxnum) {
319 case 0:
320 box_reg = REG_HMEBOX_0;
321 box_extreg = REG_HMEBOX_EXT_0;
322 break;
323 case 1:
324 box_reg = REG_HMEBOX_1;
325 box_extreg = REG_HMEBOX_EXT_1;
326 break;
327 case 2:
328 box_reg = REG_HMEBOX_2;
329 box_extreg = REG_HMEBOX_EXT_2;
330 break;
331 case 3:
332 box_reg = REG_HMEBOX_3;
333 box_extreg = REG_HMEBOX_EXT_3;
334 break;
335 default:
336 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
337 "switch case not process\n");
338 break;
339 }
340 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
341 while (!isfw_read) {
342 wait_h2c_limmit--;
343 if (wait_h2c_limmit == 0) {
344 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
345 "Waiting too long for FW read clear HMEBox(%d)!\n",
346 boxnum);
347 break;
348 }
349
350 udelay(10);
351
352 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
353 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
354 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
355 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
356 boxnum, u1b_tmp);
357 }
358
359 if (!isfw_read) {
360 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
361 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
362 boxnum);
363 break;
364 }
365
366 memset(boxcontent, 0, sizeof(boxcontent));
367 memset(boxextcontent, 0, sizeof(boxextcontent));
368 boxcontent[0] = element_id;
369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
370 "Write element_id box_reg(%4x) = %2x\n",
371 box_reg, element_id);
372
373 switch (cmd_len) {
374 case 1:
375 case 2:
376 case 3:
377
378 memcpy((u8 *)(boxcontent) + 1,
379 cmd_b + buf_index, cmd_len);
380
381 for (idx = 0; idx < 4; idx++) {
382 rtl_write_byte(rtlpriv, box_reg + idx,
383 boxcontent[idx]);
384 }
385 break;
386 case 4:
387 case 5:
388 case 6:
389 case 7:
390
391 memcpy((u8 *)(boxextcontent),
392 cmd_b + buf_index+3, cmd_len-3);
393 memcpy((u8 *)(boxcontent) + 1,
394 cmd_b + buf_index, 3);
395
396 for (idx = 0; idx < 2; idx++) {
397 rtl_write_byte(rtlpriv, box_extreg + idx,
398 boxextcontent[idx]);
399 }
400
401 for (idx = 0; idx < 4; idx++) {
402 rtl_write_byte(rtlpriv, box_reg + idx,
403 boxcontent[idx]);
404 }
405 break;
406 default:
407 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
408 "switch case not process\n");
409 break;
410 }
411
412 write_sucess = true;
413
414 rtlhal->last_hmeboxnum = boxnum + 1;
415 if (rtlhal->last_hmeboxnum == 4)
416 rtlhal->last_hmeboxnum = 0;
417
418 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
419 "pHalData->last_hmeboxnum = %d\n",
420 rtlhal->last_hmeboxnum);
421 }
422
423 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
424 rtlhal->h2c_setinprogress = false;
425 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
426
427 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
428}
429
430void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
431 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
432{
433 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
434 u32 tmp_cmdbuf[2];
435
436 if (!rtlhal->fw_ready) {
437 RT_ASSERT(false,
438 "return H2C cmd because of Fw download fail!!!\n");
439 return;
440 }
441
442 memset(tmp_cmdbuf, 0, 8);
443 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
444 _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
445
446 return;
447}
448
449void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
450{
451 u8 u1b_tmp;
452 struct rtl_priv *rtlpriv = rtl_priv(hw);
453
454 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
455 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
456 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
457 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
458 "8051Reset88E(): 8051 reset success\n");
459
460}
461
462void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
463{
464 struct rtl_priv *rtlpriv = rtl_priv(hw);
465 u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
466 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
467 u8 rlbm, power_state = 0;
468 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
469
470 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
471 rlbm = 0;
472 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
473 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
474 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
475 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
476 ppsc->reg_max_lps_awakeintvl);
477 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
478 if (mode == FW_PS_ACTIVE_MODE)
479 power_state |= FW_PWR_STATE_ACTIVE;
480 else
481 power_state |= FW_PWR_STATE_RF_OFF;
482
483 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
484
485 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
486 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
487 u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
488 rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
489 H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
490}
491
492void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
493{
494 u8 u1_joinbssrpt_parm[1] = { 0 };
495
496 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
497
498 rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
499}
500
501void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
502 u8 ap_offload_enable)
503{
504 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
505 u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
506
507 SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
508 SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
509 SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
510
511 rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
512 H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
513
514}
515
516#define BEACON_PG 0
517#define PSPOLL_PG 2
518#define NULL_PG 3
519#define PROBERSP_PG 4
520
521#define TOTAL_RESERVED_PKT_LEN 768
522
523static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
524
525 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
526 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
527 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
530 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
531 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
532 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
533 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
534 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
535 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
539 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541
542
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559
560
561 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
562 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
575 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577
578
579 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
580 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
581 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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 0x72, 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,
595
596
597 0x50, 0x00, 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 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
601 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
602 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
603 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
604 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
605 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
606 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
607 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
611 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613
614
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631};
632
633void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
634{
635 struct rtl_priv *rtlpriv = rtl_priv(hw);
636 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
637 struct sk_buff *skb = NULL;
638 u32 totalpacketlen;
639 bool rtstatus;
640 u8 u1rsvdpageloc[5] = { 0 };
641 bool b_dlok = false;
642 u8 *beacon;
643 u8 *p_pspoll;
644 u8 *nullfunc;
645 u8 *p_probersp;
646
647
648
649
650
651 beacon = &reserved_page_packet[BEACON_PG * 128];
652 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
653 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
654
655
656
657
658
659 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
660 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
661 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
662 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
663
664 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
665
666
667
668
669
670 nullfunc = &reserved_page_packet[NULL_PG * 128];
671 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
672 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
673 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
674
675 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
676
677
678
679
680
681 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
682 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
683 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
684 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
685
686 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
687
688 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
689
690 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
691 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
692 &reserved_page_packet[0], totalpacketlen);
693 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
694 "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
695 u1rsvdpageloc, 3);
696
697 skb = dev_alloc_skb(totalpacketlen);
698 memcpy(skb_put(skb, totalpacketlen),
699 &reserved_page_packet, totalpacketlen);
700
701 rtstatus = rtl_cmd_send_packet(hw, skb);
702
703 if (rtstatus)
704 b_dlok = true;
705
706 if (b_dlok) {
707 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
708 "Set RSVD page location to Fw.\n");
709 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
710 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
711 rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
712 sizeof(u1rsvdpageloc), u1rsvdpageloc);
713 } else
714 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
715 "Set RSVD page location to Fw FAIL!!!!!!.\n");
716}
717
718
719static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
720{
721 u8 u1_ctwindow_period[1] = { ctwindow};
722
723 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
724
725}
726
727void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
728{
729 struct rtl_priv *rtlpriv = rtl_priv(hw);
730 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
731 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
732 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
733 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
734 u8 i;
735 u16 ctwindow;
736 u32 start_time, tsf_low;
737
738 switch (p2p_ps_state) {
739 case P2P_PS_DISABLE:
740 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
741 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
742 break;
743 case P2P_PS_ENABLE:
744 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
745
746 if (p2pinfo->ctwindow > 0) {
747 p2p_ps_offload->ctwindow_en = 1;
748 ctwindow = p2pinfo->ctwindow;
749 rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
750 }
751
752
753 for (i = 0 ; i < p2pinfo->noa_num; i++) {
754
755 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
756 if (i == 0)
757 p2p_ps_offload->noa0_en = 1;
758 else
759 p2p_ps_offload->noa1_en = 1;
760
761
762 rtl_write_dword(rtlpriv, 0x5E0,
763 p2pinfo->noa_duration[i]);
764 rtl_write_dword(rtlpriv, 0x5E4,
765 p2pinfo->noa_interval[i]);
766
767
768 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
769
770 start_time = p2pinfo->noa_start_time[i];
771 if (p2pinfo->noa_count_type[i] != 1) {
772 while (start_time <= (tsf_low+(50*1024))) {
773 start_time += p2pinfo->noa_interval[i];
774 if (p2pinfo->noa_count_type[i] != 255)
775 p2pinfo->noa_count_type[i]--;
776 }
777 }
778 rtl_write_dword(rtlpriv, 0x5E8, start_time);
779 rtl_write_dword(rtlpriv, 0x5EC,
780 p2pinfo->noa_count_type[i]);
781 }
782
783 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
784
785 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
786
787 p2p_ps_offload->offload_en = 1;
788
789 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
790 p2p_ps_offload->role = 1;
791 p2p_ps_offload->allstasleep = -1;
792 } else {
793 p2p_ps_offload->role = 0;
794 }
795
796 p2p_ps_offload->discovery = 0;
797 }
798 break;
799 case P2P_PS_SCAN:
800 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
801 p2p_ps_offload->discovery = 1;
802 break;
803 case P2P_PS_SCAN_DONE:
804 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
805 p2p_ps_offload->discovery = 0;
806 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
807 break;
808 default:
809 break;
810 }
811
812 rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
813 (u8 *)p2p_ps_offload);
814
815}
816