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#include "dm.h"
34
35static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
36{
37 struct rtl_priv *rtlpriv = rtl_priv(hw);
38 u8 tmp;
39
40 if (enable) {
41 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
42
43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
44 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
45 } else {
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
48 }
49}
50
51static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw,
52 const u8 *buffer, u32 size)
53{
54 struct rtl_priv *rtlpriv = rtl_priv(hw);
55 u32 blocksize = sizeof(u32);
56 u8 *bufferptr = (u8 *)buffer;
57 u32 *pu4byteptr = (u32 *)buffer;
58 u32 i, offset, blockcount, remainsize;
59
60 blockcount = size / blocksize;
61 remainsize = size % blocksize;
62
63 for (i = 0; i < blockcount; i++) {
64 offset = i * blocksize;
65 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
66 *(pu4byteptr + i));
67 }
68
69 if (remainsize) {
70 offset = blockcount * blocksize;
71 bufferptr += offset;
72 for (i = 0; i < remainsize; i++) {
73 rtl_write_byte(rtlpriv,
74 (FW_8192C_START_ADDRESS + offset + i),
75 *(bufferptr + i));
76 }
77 }
78}
79
80static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page,
81 const u8 *buffer, u32 size)
82{
83 struct rtl_priv *rtlpriv = rtl_priv(hw);
84 u8 value8;
85 u8 u8page = (u8)(page & 0x07);
86
87 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
88 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
89
90 _rtl92ee_fw_block_write(hw, buffer, size);
91}
92
93static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
94{
95 u32 fwlen = *pfwlen;
96 u8 remain = (u8)(fwlen % 4);
97
98 remain = (remain == 0) ? 0 : (4 - remain);
99
100 while (remain > 0) {
101 pfwbuf[fwlen] = 0;
102 fwlen++;
103 remain--;
104 }
105
106 *pfwlen = fwlen;
107}
108
109static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
110 enum version_8192e version,
111 u8 *buffer, u32 size)
112{
113 struct rtl_priv *rtlpriv = rtl_priv(hw);
114 u8 *bufferptr = (u8 *)buffer;
115 u32 pagenums, remainsize;
116 u32 page, offset;
117
118 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
119
120 _rtl92ee_fill_dummy(bufferptr, &size);
121
122 pagenums = size / FW_8192C_PAGE_SIZE;
123 remainsize = size % FW_8192C_PAGE_SIZE;
124
125 if (pagenums > 8) {
126 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
127 "Page numbers should not greater then 8\n");
128 }
129
130 for (page = 0; page < pagenums; page++) {
131 offset = page * FW_8192C_PAGE_SIZE;
132 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
133 FW_8192C_PAGE_SIZE);
134 udelay(2);
135 }
136
137 if (remainsize) {
138 offset = pagenums * FW_8192C_PAGE_SIZE;
139 page = pagenums;
140 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
141 remainsize);
142 }
143}
144
145static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
146{
147 struct rtl_priv *rtlpriv = rtl_priv(hw);
148 int err = -EIO;
149 u32 counter = 0;
150 u32 value32;
151
152 do {
153 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
154 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
155 (!(value32 & FWDL_CHKSUM_RPT)));
156
157 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
158 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
159 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
160 value32);
161 goto exit;
162 }
163
164 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
165 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
166
167 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
168 value32 |= MCUFWDL_RDY;
169 value32 &= ~WINTINI_RDY;
170 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
171
172 rtl92ee_firmware_selfreset(hw);
173 counter = 0;
174
175 do {
176 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
177 if (value32 & WINTINI_RDY) {
178 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
179 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
180 value32, counter);
181 err = 0;
182 goto exit;
183 }
184
185 udelay(FW_8192C_POLLING_DELAY*10);
186
187 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
188
189 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
190 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
191 value32, counter);
192
193exit:
194 return err;
195}
196
197int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
198{
199 struct rtl_priv *rtlpriv = rtl_priv(hw);
200 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
201 struct rtl92c_firmware_header *pfwheader;
202 u8 *pfwdata;
203 u32 fwsize;
204 int err;
205 enum version_8192e version = rtlhal->version;
206
207 if (!rtlhal->pfirmware)
208 return 1;
209
210 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
211 rtlhal->fw_version = pfwheader->version;
212 rtlhal->fw_subversion = pfwheader->subversion;
213 pfwdata = (u8 *)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 rtl92c_firmware_header));
223
224 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
225 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
226 } else {
227 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
228 "Firmware no Header, Signature(%#x)\n",
229 pfwheader->signature);
230 }
231
232 if (rtlhal->mac_func_enable) {
233 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
234 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
235 rtl92ee_firmware_selfreset(hw);
236 }
237 }
238 _rtl92ee_enable_fw_download(hw, true);
239 _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
240 _rtl92ee_enable_fw_download(hw, false);
241
242 err = _rtl92ee_fw_free_to_go(hw);
243 if (err) {
244 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
245 "Firmware is not ready to run!\n");
246 } else {
247 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
248 "Firmware is ready to run!\n");
249 }
250
251 return 0;
252}
253
254static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
255{
256 struct rtl_priv *rtlpriv = rtl_priv(hw);
257 u8 val_hmetfr;
258 bool result = false;
259
260 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
261 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
262 result = true;
263 return result;
264}
265
266static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
267 u32 cmd_len, u8 *cmdbuffer)
268{
269 struct rtl_priv *rtlpriv = rtl_priv(hw);
270 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
271 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
272 u8 boxnum;
273 u16 box_reg = 0, box_extreg = 0;
274 u8 u1b_tmp;
275 bool isfw_read = false;
276 u8 buf_index = 0;
277 bool bwrite_sucess = false;
278 u8 wait_h2c_limmit = 100;
279 u8 boxcontent[4], boxextcontent[4];
280 u32 h2c_waitcounter = 0;
281 unsigned long flag;
282 u8 idx;
283
284 if (ppsc->dot11_psmode != EACTIVE ||
285 ppsc->inactive_pwrstate == ERFOFF) {
286 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
287 "FillH2CCommand8192E(): Return because RF is off!!!\n");
288 return;
289 }
290
291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
292
293
294
295
296 while (true) {
297 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
298 if (rtlhal->h2c_setinprogress) {
299 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
300 "H2C set in progress! Wait to set..element_id(%d).\n",
301 element_id);
302
303 while (rtlhal->h2c_setinprogress) {
304 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
305 flag);
306 h2c_waitcounter++;
307 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
308 "Wait 100 us (%d times)...\n",
309 h2c_waitcounter);
310 udelay(100);
311
312 if (h2c_waitcounter > 1000)
313 return;
314 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
315 flag);
316 }
317 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
318 } else {
319 rtlhal->h2c_setinprogress = true;
320 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
321 break;
322 }
323 }
324
325 while (!bwrite_sucess) {
326
327 boxnum = rtlhal->last_hmeboxnum;
328 switch (boxnum) {
329 case 0:
330 box_reg = REG_HMEBOX_0;
331 box_extreg = REG_HMEBOX_EXT_0;
332 break;
333 case 1:
334 box_reg = REG_HMEBOX_1;
335 box_extreg = REG_HMEBOX_EXT_1;
336 break;
337 case 2:
338 box_reg = REG_HMEBOX_2;
339 box_extreg = REG_HMEBOX_EXT_2;
340 break;
341 case 3:
342 box_reg = REG_HMEBOX_3;
343 box_extreg = REG_HMEBOX_EXT_3;
344 break;
345 default:
346 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
347 "switch case not process\n");
348 break;
349 }
350
351
352 isfw_read = false;
353 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
354
355 if (u1b_tmp != 0xea) {
356 isfw_read = true;
357 } else {
358 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
359 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
360 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
361 }
362
363 if (isfw_read) {
364 wait_h2c_limmit = 100;
365 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
366 while (!isfw_read) {
367 wait_h2c_limmit--;
368 if (wait_h2c_limmit == 0) {
369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
370 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
371 boxnum);
372 break;
373 }
374 udelay(10);
375 isfw_read =
376 _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
377 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
378 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
379 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
380 boxnum, u1b_tmp);
381 }
382 }
383
384
385
386
387 if (!isfw_read) {
388 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
389 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
390 boxnum);
391 break;
392 }
393
394 memset(boxcontent, 0, sizeof(boxcontent));
395 memset(boxextcontent, 0, sizeof(boxextcontent));
396 boxcontent[0] = element_id;
397 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
398 "Write element_id box_reg(%4x) = %2x\n",
399 box_reg, element_id);
400
401 switch (cmd_len) {
402 case 1:
403 case 2:
404 case 3:
405
406 memcpy((u8 *)(boxcontent) + 1,
407 cmdbuffer + buf_index, cmd_len);
408
409 for (idx = 0; idx < 4; idx++) {
410 rtl_write_byte(rtlpriv, box_reg + idx,
411 boxcontent[idx]);
412 }
413 break;
414 case 4:
415 case 5:
416 case 6:
417 case 7:
418
419 memcpy((u8 *)(boxextcontent),
420 cmdbuffer + buf_index+3, cmd_len-3);
421 memcpy((u8 *)(boxcontent) + 1,
422 cmdbuffer + buf_index, 3);
423
424 for (idx = 0; idx < 4; idx++) {
425 rtl_write_byte(rtlpriv, box_extreg + idx,
426 boxextcontent[idx]);
427 }
428
429 for (idx = 0; idx < 4; idx++) {
430 rtl_write_byte(rtlpriv, box_reg + idx,
431 boxcontent[idx]);
432 }
433 break;
434 default:
435 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
436 "switch case not process\n");
437 break;
438 }
439
440 bwrite_sucess = true;
441
442 rtlhal->last_hmeboxnum = boxnum + 1;
443 if (rtlhal->last_hmeboxnum == 4)
444 rtlhal->last_hmeboxnum = 0;
445
446 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
447 "pHalData->last_hmeboxnum = %d\n",
448 rtlhal->last_hmeboxnum);
449 }
450
451 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
452 rtlhal->h2c_setinprogress = false;
453 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
454
455 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
456}
457
458void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
459 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
460{
461 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
462 u32 tmp_cmdbuf[2];
463
464 if (!rtlhal->fw_ready) {
465 RT_ASSERT(false,
466 "return H2C cmd because of Fw download fail!!!\n");
467 return;
468 }
469
470 memset(tmp_cmdbuf, 0, 8);
471 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
472 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
473}
474
475void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
476{
477 u8 u1b_tmp;
478 struct rtl_priv *rtlpriv = rtl_priv(hw);
479
480 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
481 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
482
483 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
485
486 udelay(50);
487
488 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
489 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
490
491 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
492 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
493
494 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
495 " _8051Reset92E(): 8051 reset success .\n");
496}
497
498void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
499{
500 struct rtl_priv *rtlpriv = rtl_priv(hw);
501 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
502 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
503 u8 rlbm , power_state = 0;
504
505 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
506
507 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
508 rlbm = 0;
509 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
510 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
511 (rtlpriv->mac80211.p2p) ?
512 ppsc->smart_ps : 1);
513 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
514 ppsc->reg_max_lps_awakeintvl);
515 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
516 if (mode == FW_PS_ACTIVE_MODE)
517 power_state |= FW_PWR_STATE_ACTIVE;
518 else
519 power_state |= FW_PWR_STATE_RF_OFF;
520 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
521
522 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
523 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
524 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
525 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
526 u1_h2c_set_pwrmode);
527}
528
529void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
530{
531 u8 parm[3] = { 0 , 0 , 0 };
532
533
534
535
536
537
538
539 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
540 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
541
542 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
543}
544
545#define BEACON_PG 0
546#define PSPOLL_PG 2
547#define NULL_PG 3
548#define PROBERSP_PG 4
549
550#define TOTAL_RESERVED_PKT_LEN 768
551
552static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
553
554 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
555 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
556 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
559 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
560 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
561 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
562 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
563 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
567 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
568 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
569 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
570
571
572 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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
589
590 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606
607
608 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
609 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
610 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624
625
626 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
627 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
628 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
629 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
630 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
631 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
632 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
633 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
634 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
635 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
636 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
640 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642
643
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,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660};
661
662void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
663{
664 struct rtl_priv *rtlpriv = rtl_priv(hw);
665 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
666 struct sk_buff *skb = NULL;
667
668 u32 totalpacketlen;
669 bool rtstatus;
670 u8 u1rsvdpageloc[5] = { 0 };
671 bool b_dlok = false;
672
673 u8 *beacon;
674 u8 *p_pspoll;
675 u8 *nullfunc;
676 u8 *p_probersp;
677
678
679
680
681 beacon = &reserved_page_packet[BEACON_PG * 128];
682 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
683 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
684
685
686
687
688
689 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
690 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
691 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
692 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
693
694 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
695
696
697
698
699
700 nullfunc = &reserved_page_packet[NULL_PG * 128];
701 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
702 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
703 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
704
705 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
706
707
708
709
710
711 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
712 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
713 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
714 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
715
716 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
717
718 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
719
720 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
721 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
722 &reserved_page_packet[0], totalpacketlen);
723 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
724 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
725 u1rsvdpageloc, 3);
726
727 skb = dev_alloc_skb(totalpacketlen);
728 memcpy((u8 *)skb_put(skb, totalpacketlen),
729 &reserved_page_packet, totalpacketlen);
730
731 rtstatus = rtl_cmd_send_packet(hw, skb);
732
733 if (rtstatus)
734 b_dlok = true;
735
736 if (b_dlok) {
737 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
738 "Set RSVD page location to Fw.\n");
739 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
740 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
741 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
742 sizeof(u1rsvdpageloc), u1rsvdpageloc);
743 } else {
744 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
745 "Set RSVD page location to Fw FAIL!!!!!!.\n");
746 }
747}
748
749
750static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
751{
752 u8 u1_ctwindow_period[1] = {ctwindow};
753
754 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
755}
756
757void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
758{
759 struct rtl_priv *rtlpriv = rtl_priv(hw);
760 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
761 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
762 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
763 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
764 u8 i;
765 u16 ctwindow;
766 u32 start_time, tsf_low;
767
768 switch (p2p_ps_state) {
769 case P2P_PS_DISABLE:
770 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
771 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
772 break;
773 case P2P_PS_ENABLE:
774 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
775
776 if (p2pinfo->ctwindow > 0) {
777 p2p_ps_offload->ctwindow_en = 1;
778 ctwindow = p2pinfo->ctwindow;
779 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
780 }
781
782 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
783
784 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
785 if (i == 0)
786 p2p_ps_offload->noa0_en = 1;
787 else
788 p2p_ps_offload->noa1_en = 1;
789
790 rtl_write_dword(rtlpriv, 0x5E0,
791 p2pinfo->noa_duration[i]);
792 rtl_write_dword(rtlpriv, 0x5E4,
793 p2pinfo->noa_interval[i]);
794
795
796 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
797
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]--;
804 }
805 }
806 rtl_write_dword(rtlpriv, 0x5E8, start_time);
807 rtl_write_dword(rtlpriv, 0x5EC,
808 p2pinfo->noa_count_type[i]);
809 }
810 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
811
812 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
813 p2p_ps_offload->offload_en = 1;
814
815 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
816 p2p_ps_offload->role = 1;
817 p2p_ps_offload->allstasleep = 0;
818 } else {
819 p2p_ps_offload->role = 0;
820 }
821 p2p_ps_offload->discovery = 0;
822 }
823 break;
824 case P2P_PS_SCAN:
825 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
826 p2p_ps_offload->discovery = 1;
827 break;
828 case P2P_PS_SCAN_DONE:
829 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
830 p2p_ps_offload->discovery = 0;
831 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
832 break;
833 default:
834 break;
835 }
836 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
837 (u8 *)p2p_ps_offload);
838}
839
840static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
841 u8 *cmd_buf, u8 cmd_len)
842{
843 u8 rate = cmd_buf[0] & 0x3F;
844 bool collision_state = cmd_buf[3] & BIT(0);
845
846 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
847}
848
849static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
850 u8 c2h_cmd_len, u8 *tmp_buf)
851{
852 struct rtl_priv *rtlpriv = rtl_priv(hw);
853
854 switch (c2h_cmd_id) {
855 case C2H_8192E_DBG:
856 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
857 "[C2H], C2H_8723BE_DBG!!\n");
858 break;
859 case C2H_8192E_TXBF:
860 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
861 "[C2H], C2H_8192E_TXBF!!\n");
862 break;
863 case C2H_8192E_TX_REPORT:
864 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
865 "[C2H], C2H_8723BE_TX_REPORT!\n");
866 break;
867 case C2H_8192E_BT_INFO:
868 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
869 "[C2H], C2H_8723BE_BT_INFO!!\n");
870 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
871 c2h_cmd_len);
872 break;
873 case C2H_8192E_BT_MP:
874 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
875 "[C2H], C2H_8723BE_BT_MP!!\n");
876 break;
877 case C2H_8192E_RA_RPT:
878 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
879 break;
880 default:
881 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
882 "[C2H], Unkown packet!! CmdId(%#X)!\n", c2h_cmd_id);
883 break;
884 }
885}
886
887void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
888{
889 struct rtl_priv *rtlpriv = rtl_priv(hw);
890 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
891 u8 *tmp_buf = NULL;
892
893 c2h_cmd_id = buffer[0];
894 c2h_cmd_seq = buffer[1];
895 c2h_cmd_len = len - 2;
896 tmp_buf = buffer + 2;
897
898 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
899 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
900 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
901
902 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
903 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
904
905 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
906}
907