Adding support for MOXA ART SoC. Testing port of linux-2.6.32.60-moxart.
[linux-3.6.7-moxart.git] / drivers / net / wireless / rtlwifi / rtl8192c / fw_common.c
blob44febfde9493425b9d9c47d04cf66e4be72ff815
1 /******************************************************************************
3 * Copyright(c) 2009-2012 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
28 *****************************************************************************/
30 #include "../wifi.h"
31 #include "../pci.h"
32 #include "../base.h"
33 #include "../rtl8192ce/reg.h"
34 #include "../rtl8192ce/def.h"
35 #include "fw_common.h"
36 #include <linux/export.h>
37 #include <linux/kmemleak.h>
39 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
41 struct rtl_priv *rtlpriv = rtl_priv(hw);
42 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
44 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
45 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
46 if (enable)
47 value32 |= MCUFWDL_EN;
48 else
49 value32 &= ~MCUFWDL_EN;
50 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
51 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
52 u8 tmp;
53 if (enable) {
55 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
56 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
57 tmp | 0x04);
59 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
60 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
62 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
63 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
64 } else {
66 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
67 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
69 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
74 static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
75 u32 size)
77 struct rtl_priv *rtlpriv = rtl_priv(hw);
78 u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
79 u8 *bufferPtr = (u8 *) buffer;
80 u32 i, offset, blockCount, remainSize;
82 blockCount = size / blockSize;
83 remainSize = size % blockSize;
85 for (i = 0; i < blockCount; i++) {
86 offset = i * blockSize;
87 rtlpriv->io.writeN_sync(rtlpriv,
88 (FW_8192C_START_ADDRESS + offset),
89 (void *)(bufferPtr + offset),
90 blockSize);
93 if (remainSize) {
94 offset = blockCount * blockSize;
95 rtlpriv->io.writeN_sync(rtlpriv,
96 (FW_8192C_START_ADDRESS + offset),
97 (void *)(bufferPtr + offset),
98 remainSize);
102 static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
103 const u8 *buffer, u32 size)
105 struct rtl_priv *rtlpriv = rtl_priv(hw);
106 u32 blockSize = sizeof(u32);
107 u8 *bufferPtr = (u8 *) buffer;
108 u32 *pu4BytePtr = (u32 *) buffer;
109 u32 i, offset, blockCount, remainSize;
110 u32 data;
112 if (rtlpriv->io.writeN_sync) {
113 rtl_block_fw_writeN(hw, buffer, size);
114 return;
116 blockCount = size / blockSize;
117 remainSize = size % blockSize;
118 if (remainSize) {
119 /* the last word is < 4 bytes - pad it with zeros */
120 for (i = 0; i < 4 - remainSize; i++)
121 *(bufferPtr + size + i) = 0;
122 blockCount++;
125 for (i = 0; i < blockCount; i++) {
126 offset = i * blockSize;
127 /* for big-endian platforms, the firmware data need to be byte
128 * swapped as it was read as a byte string and will be written
129 * as 32-bit dwords and byte swapped when written
131 data = le32_to_cpu(*(__le32 *)(pu4BytePtr + i));
132 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
133 data);
137 static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
138 u32 page, const u8 *buffer, u32 size)
140 struct rtl_priv *rtlpriv = rtl_priv(hw);
141 u8 value8;
142 u8 u8page = (u8) (page & 0x07);
144 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
146 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
147 _rtl92c_fw_block_write(hw, buffer, size);
150 static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
152 u32 fwlen = *pfwlen;
153 u8 remain = (u8) (fwlen % 4);
155 remain = (remain == 0) ? 0 : (4 - remain);
157 while (remain > 0) {
158 pfwbuf[fwlen] = 0;
159 fwlen++;
160 remain--;
163 *pfwlen = fwlen;
166 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
167 enum version_8192c version, u8 *buffer, u32 size)
169 struct rtl_priv *rtlpriv = rtl_priv(hw);
170 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
171 u8 *bufferPtr = buffer;
173 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes\n", size);
175 if (IS_CHIP_VER_B(version)) {
176 u32 pageNums, remainSize;
177 u32 page, offset;
179 if (IS_HARDWARE_TYPE_8192CE(rtlhal))
180 _rtl92c_fill_dummy(bufferPtr, &size);
182 pageNums = size / FW_8192C_PAGE_SIZE;
183 remainSize = size % FW_8192C_PAGE_SIZE;
185 if (pageNums > 4) {
186 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
187 "Page numbers should not greater then 4\n");
190 for (page = 0; page < pageNums; page++) {
191 offset = page * FW_8192C_PAGE_SIZE;
192 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
193 FW_8192C_PAGE_SIZE);
196 if (remainSize) {
197 offset = pageNums * FW_8192C_PAGE_SIZE;
198 page = pageNums;
199 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
200 remainSize);
202 } else {
203 _rtl92c_fw_block_write(hw, buffer, size);
207 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
209 struct rtl_priv *rtlpriv = rtl_priv(hw);
210 u32 counter = 0;
211 u32 value32;
213 do {
214 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
215 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
216 (!(value32 & FWDL_ChkSum_rpt)));
218 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
219 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
220 "chksum report faill ! REG_MCUFWDL:0x%08x\n", value32);
221 return -EIO;
224 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
225 "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32);
227 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
228 value32 |= MCUFWDL_RDY;
229 value32 &= ~WINTINI_RDY;
230 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
232 counter = 0;
234 do {
235 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
236 if (value32 & WINTINI_RDY) {
237 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
238 "Polling FW ready success!! REG_MCUFWDL:0x%08x\n",
239 value32);
240 return 0;
243 mdelay(FW_8192C_POLLING_DELAY);
245 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
247 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
248 "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", value32);
249 return -EIO;
252 int rtl92c_download_fw(struct ieee80211_hw *hw)
254 struct rtl_priv *rtlpriv = rtl_priv(hw);
255 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
256 struct rtl92c_firmware_header *pfwheader;
257 u8 *pfwdata;
258 u32 fwsize;
259 enum version_8192c version = rtlhal->version;
261 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
262 return 1;
264 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
265 pfwdata = rtlhal->pfirmware;
266 fwsize = rtlhal->fwsize;
268 if (IS_FW_HEADER_EXIST(pfwheader)) {
269 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
270 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
271 le16_to_cpu(pfwheader->version),
272 le16_to_cpu(pfwheader->signature),
273 (uint)sizeof(struct rtl92c_firmware_header));
275 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
276 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
279 _rtl92c_enable_fw_download(hw, true);
280 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
281 _rtl92c_enable_fw_download(hw, false);
283 if (_rtl92c_fw_free_to_go(hw)) {
284 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
285 "Firmware is not ready to run!\n");
286 } else {
287 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
288 "Firmware is ready to run!\n");
291 return 0;
293 EXPORT_SYMBOL(rtl92c_download_fw);
295 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
297 struct rtl_priv *rtlpriv = rtl_priv(hw);
298 u8 val_hmetfr, val_mcutst_1;
299 bool result = false;
301 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
302 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
304 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
305 result = true;
306 return result;
309 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
310 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
312 struct rtl_priv *rtlpriv = rtl_priv(hw);
313 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
314 u8 boxnum;
315 u16 box_reg = 0, box_extreg = 0;
316 u8 u1b_tmp;
317 bool isfw_read = false;
318 bool bwrite_sucess = false;
319 u8 wait_h2c_limmit = 100;
320 u8 wait_writeh2c_limmit = 100;
321 u8 boxcontent[4], boxextcontent[2];
322 u32 h2c_waitcounter = 0;
323 unsigned long flag;
324 u8 idx;
326 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
328 while (true) {
329 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
330 if (rtlhal->h2c_setinprogress) {
331 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
332 "H2C set in progress! Wait to set..element_id(%d)\n",
333 element_id);
335 while (rtlhal->h2c_setinprogress) {
336 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
337 flag);
338 h2c_waitcounter++;
339 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
340 "Wait 100 us (%d times)...\n",
341 h2c_waitcounter);
342 udelay(100);
344 if (h2c_waitcounter > 1000)
345 return;
346 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
347 flag);
349 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
350 } else {
351 rtlhal->h2c_setinprogress = true;
352 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
353 break;
357 while (!bwrite_sucess) {
358 wait_writeh2c_limmit--;
359 if (wait_writeh2c_limmit == 0) {
360 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
361 "Write H2C fail because no trigger for FW INT!\n");
362 break;
365 boxnum = rtlhal->last_hmeboxnum;
366 switch (boxnum) {
367 case 0:
368 box_reg = REG_HMEBOX_0;
369 box_extreg = REG_HMEBOX_EXT_0;
370 break;
371 case 1:
372 box_reg = REG_HMEBOX_1;
373 box_extreg = REG_HMEBOX_EXT_1;
374 break;
375 case 2:
376 box_reg = REG_HMEBOX_2;
377 box_extreg = REG_HMEBOX_EXT_2;
378 break;
379 case 3:
380 box_reg = REG_HMEBOX_3;
381 box_extreg = REG_HMEBOX_EXT_3;
382 break;
383 default:
384 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
385 "switch case not processed\n");
386 break;
389 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
390 while (!isfw_read) {
392 wait_h2c_limmit--;
393 if (wait_h2c_limmit == 0) {
394 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
395 "Waiting too long for FW read clear HMEBox(%d)!\n",
396 boxnum);
397 break;
400 udelay(10);
402 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
403 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
404 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
405 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
406 boxnum, u1b_tmp);
409 if (!isfw_read) {
410 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
411 "Write H2C register BOX[%d] fail!!!!! Fw do not read\n",
412 boxnum);
413 break;
416 memset(boxcontent, 0, sizeof(boxcontent));
417 memset(boxextcontent, 0, sizeof(boxextcontent));
418 boxcontent[0] = element_id;
419 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
420 "Write element_id box_reg(%4x) = %2x\n",
421 box_reg, element_id);
423 switch (cmd_len) {
424 case 1:
425 boxcontent[0] &= ~(BIT(7));
426 memcpy((u8 *) (boxcontent) + 1,
427 p_cmdbuffer, 1);
429 for (idx = 0; idx < 4; idx++) {
430 rtl_write_byte(rtlpriv, box_reg + idx,
431 boxcontent[idx]);
433 break;
434 case 2:
435 boxcontent[0] &= ~(BIT(7));
436 memcpy((u8 *) (boxcontent) + 1,
437 p_cmdbuffer, 2);
439 for (idx = 0; idx < 4; idx++) {
440 rtl_write_byte(rtlpriv, box_reg + idx,
441 boxcontent[idx]);
443 break;
444 case 3:
445 boxcontent[0] &= ~(BIT(7));
446 memcpy((u8 *) (boxcontent) + 1,
447 p_cmdbuffer, 3);
449 for (idx = 0; idx < 4; idx++) {
450 rtl_write_byte(rtlpriv, box_reg + idx,
451 boxcontent[idx]);
453 break;
454 case 4:
455 boxcontent[0] |= (BIT(7));
456 memcpy((u8 *) (boxextcontent),
457 p_cmdbuffer, 2);
458 memcpy((u8 *) (boxcontent) + 1,
459 p_cmdbuffer + 2, 2);
461 for (idx = 0; idx < 2; idx++) {
462 rtl_write_byte(rtlpriv, box_extreg + idx,
463 boxextcontent[idx]);
466 for (idx = 0; idx < 4; idx++) {
467 rtl_write_byte(rtlpriv, box_reg + idx,
468 boxcontent[idx]);
470 break;
471 case 5:
472 boxcontent[0] |= (BIT(7));
473 memcpy((u8 *) (boxextcontent),
474 p_cmdbuffer, 2);
475 memcpy((u8 *) (boxcontent) + 1,
476 p_cmdbuffer + 2, 3);
478 for (idx = 0; idx < 2; idx++) {
479 rtl_write_byte(rtlpriv, box_extreg + idx,
480 boxextcontent[idx]);
483 for (idx = 0; idx < 4; idx++) {
484 rtl_write_byte(rtlpriv, box_reg + idx,
485 boxcontent[idx]);
487 break;
488 default:
489 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
490 "switch case not processed\n");
491 break;
494 bwrite_sucess = true;
496 rtlhal->last_hmeboxnum = boxnum + 1;
497 if (rtlhal->last_hmeboxnum == 4)
498 rtlhal->last_hmeboxnum = 0;
500 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
501 "pHalData->last_hmeboxnum = %d\n",
502 rtlhal->last_hmeboxnum);
505 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
506 rtlhal->h2c_setinprogress = false;
507 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
509 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
512 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
513 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
515 u32 tmp_cmdbuf[2];
517 memset(tmp_cmdbuf, 0, 8);
518 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
519 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
521 return;
523 EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
525 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
527 u8 u1b_tmp;
528 u8 delay = 100;
529 struct rtl_priv *rtlpriv = rtl_priv(hw);
531 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
532 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
534 while (u1b_tmp & BIT(2)) {
535 delay--;
536 if (delay == 0) {
537 RT_ASSERT(false, "8051 reset fail\n");
538 break;
540 udelay(50);
541 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
544 EXPORT_SYMBOL(rtl92c_firmware_selfreset);
546 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
548 struct rtl_priv *rtlpriv = rtl_priv(hw);
549 u8 u1_h2c_set_pwrmode[3] = {0};
550 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
552 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
554 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
555 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
556 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
557 ppsc->reg_max_lps_awakeintvl);
559 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
560 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode",
561 u1_h2c_set_pwrmode, 3);
562 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
565 EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
567 static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
568 struct sk_buff *skb)
570 struct rtl_priv *rtlpriv = rtl_priv(hw);
571 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
572 struct rtl8192_tx_ring *ring;
573 struct rtl_tx_desc *pdesc;
574 unsigned long flags;
575 struct sk_buff *pskb = NULL;
577 ring = &rtlpci->tx_ring[BEACON_QUEUE];
579 pskb = __skb_dequeue(&ring->queue);
580 if (pskb)
581 kfree_skb(pskb);
583 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
585 pdesc = &ring->desc[0];
587 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
589 __skb_queue_tail(&ring->queue, skb);
591 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
593 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
595 return true;
598 #define BEACON_PG 0 /*->1*/
599 #define PSPOLL_PG 2
600 #define NULL_PG 3
601 #define PROBERSP_PG 4 /*->5*/
603 #define TOTAL_RESERVED_PKT_LEN 768
605 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
606 /* page 0 beacon */
607 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
608 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
609 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
612 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
613 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
614 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
615 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
616 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
617 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
621 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 /* page 1 beacon */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 /* page 2 ps-poll */
643 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
644 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
657 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 /* page 3 null */
661 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
662 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
663 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
675 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 /* page 4 probe_resp */
679 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
680 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
681 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
682 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
683 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
684 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
685 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
686 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
687 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
688 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
689 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
693 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 /* page 5 probe_resp */
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
717 struct rtl_priv *rtlpriv = rtl_priv(hw);
718 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
719 struct sk_buff *skb = NULL;
721 u32 totalpacketlen;
722 bool rtstatus;
723 u8 u1RsvdPageLoc[3] = {0};
724 bool dlok = false;
726 u8 *beacon;
727 u8 *pspoll;
728 u8 *nullfunc;
729 u8 *probersp;
730 /*---------------------------------------------------------
731 (1) beacon
732 ---------------------------------------------------------*/
733 beacon = &reserved_page_packet[BEACON_PG * 128];
734 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
735 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
737 /*-------------------------------------------------------
738 (2) ps-poll
739 --------------------------------------------------------*/
740 pspoll = &reserved_page_packet[PSPOLL_PG * 128];
741 SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
742 SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
743 SET_80211_PS_POLL_TA(pspoll, mac->mac_addr);
745 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
747 /*--------------------------------------------------------
748 (3) null data
749 ---------------------------------------------------------*/
750 nullfunc = &reserved_page_packet[NULL_PG * 128];
751 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
752 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
753 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
755 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
757 /*---------------------------------------------------------
758 (4) probe response
759 ----------------------------------------------------------*/
760 probersp = &reserved_page_packet[PROBERSP_PG * 128];
761 SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
762 SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
763 SET_80211_HDR_ADDRESS3(probersp, mac->bssid);
765 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
767 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
769 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
770 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
771 &reserved_page_packet[0], totalpacketlen);
772 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
773 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
774 u1RsvdPageLoc, 3);
777 skb = dev_alloc_skb(totalpacketlen);
778 if (!skb)
779 return;
780 kmemleak_not_leak(skb);
782 memcpy((u8 *) skb_put(skb, totalpacketlen),
783 &reserved_page_packet, totalpacketlen);
785 rtstatus = _rtl92c_cmd_send_packet(hw, skb);
787 if (rtstatus)
788 dlok = true;
790 if (dlok) {
791 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
792 "Set RSVD page location to Fw\n");
793 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
794 "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
795 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
796 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
797 } else
798 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
799 "Set RSVD page location to Fw FAIL!!!!!!\n");
801 EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
803 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
805 u8 u1_joinbssrpt_parm[1] = {0};
807 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
809 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
811 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);