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