ocfs2: Make the left masklogs compat.
[taoma-kernel.git] / drivers / net / wireless / rtlwifi / rtl8192ce / fw.c
blob11dd22b987e727e0fb401625c5ece7a279f644c4
1 /******************************************************************************
3 * Copyright(c) 2009-2010 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 <linux/firmware.h>
31 #include "../wifi.h"
32 #include "../pci.h"
33 #include "../base.h"
34 #include "reg.h"
35 #include "def.h"
36 #include "fw.h"
37 #include "table.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 _rtl92c_fw_block_write(struct ieee80211_hw *hw,
75 const u8 *buffer, u32 size)
77 struct rtl_priv *rtlpriv = rtl_priv(hw);
78 u32 blockSize = sizeof(u32);
79 u8 *bufferPtr = (u8 *) buffer;
80 u32 *pu4BytePtr = (u32 *) buffer;
81 u32 i, offset, blockCount, remainSize;
83 blockCount = size / blockSize;
84 remainSize = size % blockSize;
86 for (i = 0; i < blockCount; i++) {
87 offset = i * blockSize;
88 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
89 *(pu4BytePtr + i));
92 if (remainSize) {
93 offset = blockCount * blockSize;
94 bufferPtr += offset;
95 for (i = 0; i < remainSize; i++) {
96 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
97 offset + i), *(bufferPtr + i));
102 static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
103 u32 page, const u8 *buffer, u32 size)
105 struct rtl_priv *rtlpriv = rtl_priv(hw);
106 u8 value8;
107 u8 u8page = (u8) (page & 0x07);
109 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
111 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
112 _rtl92c_fw_block_write(hw, buffer, size);
115 static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
117 u32 fwlen = *pfwlen;
118 u8 remain = (u8) (fwlen % 4);
120 remain = (remain == 0) ? 0 : (4 - remain);
122 while (remain > 0) {
123 pfwbuf[fwlen] = 0;
124 fwlen++;
125 remain--;
128 *pfwlen = fwlen;
131 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
132 enum version_8192c version, u8 *buffer, u32 size)
134 struct rtl_priv *rtlpriv = rtl_priv(hw);
135 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
136 bool is_version_b;
137 u8 *bufferPtr = (u8 *) buffer;
139 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
141 is_version_b = IS_CHIP_VER_B(version);
142 if (is_version_b) {
143 u32 pageNums, remainSize;
144 u32 page, offset;
146 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
147 _rtl92c_fill_dummy(bufferPtr, &size);
149 pageNums = size / FW_8192C_PAGE_SIZE;
150 remainSize = size % FW_8192C_PAGE_SIZE;
152 if (pageNums > 4) {
153 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
154 ("Page numbers should not greater then 4\n"));
157 for (page = 0; page < pageNums; page++) {
158 offset = page * FW_8192C_PAGE_SIZE;
159 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
160 FW_8192C_PAGE_SIZE);
163 if (remainSize) {
164 offset = pageNums * FW_8192C_PAGE_SIZE;
165 page = pageNums;
166 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
167 remainSize);
169 } else {
170 _rtl92c_fw_block_write(hw, buffer, size);
174 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
176 struct rtl_priv *rtlpriv = rtl_priv(hw);
177 int err = -EIO;
178 u32 counter = 0;
179 u32 value32;
181 do {
182 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
183 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
184 (!(value32 & FWDL_ChkSum_rpt)));
186 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
187 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
188 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
189 value32));
190 goto exit;
193 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
194 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
196 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
197 value32 |= MCUFWDL_RDY;
198 value32 &= ~WINTINI_RDY;
199 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
201 counter = 0;
203 do {
204 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
205 if (value32 & WINTINI_RDY) {
206 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
207 ("Polling FW ready success!!"
208 " REG_MCUFWDL:0x%08x .\n",
209 value32));
210 err = 0;
211 goto exit;
214 mdelay(FW_8192C_POLLING_DELAY);
216 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
218 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
219 ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
221 exit:
222 return err;
225 int rtl92c_download_fw(struct ieee80211_hw *hw)
227 struct rtl_priv *rtlpriv = rtl_priv(hw);
228 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
229 struct rtl92c_firmware_header *pfwheader;
230 u8 *pfwdata;
231 u32 fwsize;
232 int err;
233 enum version_8192c version = rtlhal->version;
235 const struct firmware *firmware = NULL;
237 err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
238 rtlpriv->io.dev);
239 if (err) {
240 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
241 ("Failed to request firmware!\n"));
242 return 1;
245 if (firmware->size > 0x4000) {
246 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
247 ("Firmware is too big!\n"));
248 release_firmware(firmware);
249 return 1;
252 memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
253 fwsize = firmware->size;
254 release_firmware(firmware);
256 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
257 pfwdata = (u8 *) rtlhal->pfirmware;
259 if (IS_FW_HEADER_EXIST(pfwheader)) {
260 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
261 ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
262 pfwheader->version, pfwheader->signature,
263 (uint)sizeof(struct rtl92c_firmware_header)));
265 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
266 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
269 _rtl92c_enable_fw_download(hw, true);
270 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
271 _rtl92c_enable_fw_download(hw, false);
273 err = _rtl92c_fw_free_to_go(hw);
274 if (err) {
275 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
276 ("Firmware is not ready to run!\n"));
277 } else {
278 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
279 ("Firmware is ready to run!\n"));
282 return 0;
285 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
287 struct rtl_priv *rtlpriv = rtl_priv(hw);
288 u8 val_hmetfr, val_mcutst_1;
289 bool result = false;
291 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
292 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
294 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
295 result = true;
296 return result;
299 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
300 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
302 struct rtl_priv *rtlpriv = rtl_priv(hw);
303 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
304 u8 boxnum;
305 u16 box_reg, box_extreg;
306 u8 u1b_tmp;
307 bool isfw_read = false;
308 u8 buf_index;
309 bool bwrite_sucess = false;
310 u8 wait_h2c_limmit = 100;
311 u8 wait_writeh2c_limmit = 100;
312 u8 boxcontent[4], boxextcontent[2];
313 u32 h2c_waitcounter = 0;
314 unsigned long flag;
315 u8 idx;
317 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
319 while (true) {
320 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
321 if (rtlhal->b_h2c_setinprogress) {
322 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
323 ("H2C set in progress! Wait to set.."
324 "element_id(%d).\n", element_id));
326 while (rtlhal->b_h2c_setinprogress) {
327 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
328 flag);
329 h2c_waitcounter++;
330 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
331 ("Wait 100 us (%d times)...\n",
332 h2c_waitcounter));
333 udelay(100);
335 if (h2c_waitcounter > 1000)
336 return;
337 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
338 flag);
340 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
341 } else {
342 rtlhal->b_h2c_setinprogress = true;
343 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
344 break;
348 while (!bwrite_sucess) {
349 wait_writeh2c_limmit--;
350 if (wait_writeh2c_limmit == 0) {
351 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
352 ("Write H2C fail because no trigger "
353 "for FW INT!\n"));
354 break;
357 boxnum = rtlhal->last_hmeboxnum;
358 switch (boxnum) {
359 case 0:
360 box_reg = REG_HMEBOX_0;
361 box_extreg = REG_HMEBOX_EXT_0;
362 break;
363 case 1:
364 box_reg = REG_HMEBOX_1;
365 box_extreg = REG_HMEBOX_EXT_1;
366 break;
367 case 2:
368 box_reg = REG_HMEBOX_2;
369 box_extreg = REG_HMEBOX_EXT_2;
370 break;
371 case 3:
372 box_reg = REG_HMEBOX_3;
373 box_extreg = REG_HMEBOX_EXT_3;
374 break;
375 default:
376 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
377 ("switch case not process\n"));
378 break;
381 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
382 while (!isfw_read) {
384 wait_h2c_limmit--;
385 if (wait_h2c_limmit == 0) {
386 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
387 ("Wating too long for FW read "
388 "clear HMEBox(%d)!\n", boxnum));
389 break;
392 udelay(10);
394 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
395 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
396 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
397 ("Wating for FW read clear HMEBox(%d)!!! "
398 "0x1BF = %2x\n", boxnum, u1b_tmp));
401 if (!isfw_read) {
402 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
403 ("Write H2C register BOX[%d] fail!!!!! "
404 "Fw do not read.\n", boxnum));
405 break;
408 memset(boxcontent, 0, sizeof(boxcontent));
409 memset(boxextcontent, 0, sizeof(boxextcontent));
410 boxcontent[0] = element_id;
411 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
412 ("Write element_id box_reg(%4x) = %2x\n",
413 box_reg, element_id));
415 switch (cmd_len) {
416 case 1:
417 boxcontent[0] &= ~(BIT(7));
418 memcpy((u8 *) (boxcontent) + 1,
419 p_cmdbuffer + buf_index, 1);
421 for (idx = 0; idx < 4; idx++) {
422 rtl_write_byte(rtlpriv, box_reg + idx,
423 boxcontent[idx]);
425 break;
426 case 2:
427 boxcontent[0] &= ~(BIT(7));
428 memcpy((u8 *) (boxcontent) + 1,
429 p_cmdbuffer + buf_index, 2);
431 for (idx = 0; idx < 4; idx++) {
432 rtl_write_byte(rtlpriv, box_reg + idx,
433 boxcontent[idx]);
435 break;
436 case 3:
437 boxcontent[0] &= ~(BIT(7));
438 memcpy((u8 *) (boxcontent) + 1,
439 p_cmdbuffer + buf_index, 3);
441 for (idx = 0; idx < 4; idx++) {
442 rtl_write_byte(rtlpriv, box_reg + idx,
443 boxcontent[idx]);
445 break;
446 case 4:
447 boxcontent[0] |= (BIT(7));
448 memcpy((u8 *) (boxextcontent),
449 p_cmdbuffer + buf_index, 2);
450 memcpy((u8 *) (boxcontent) + 1,
451 p_cmdbuffer + buf_index + 2, 2);
453 for (idx = 0; idx < 2; idx++) {
454 rtl_write_byte(rtlpriv, box_extreg + idx,
455 boxextcontent[idx]);
458 for (idx = 0; idx < 4; idx++) {
459 rtl_write_byte(rtlpriv, box_reg + idx,
460 boxcontent[idx]);
462 break;
463 case 5:
464 boxcontent[0] |= (BIT(7));
465 memcpy((u8 *) (boxextcontent),
466 p_cmdbuffer + buf_index, 2);
467 memcpy((u8 *) (boxcontent) + 1,
468 p_cmdbuffer + buf_index + 2, 3);
470 for (idx = 0; idx < 2; idx++) {
471 rtl_write_byte(rtlpriv, box_extreg + idx,
472 boxextcontent[idx]);
475 for (idx = 0; idx < 4; idx++) {
476 rtl_write_byte(rtlpriv, box_reg + idx,
477 boxcontent[idx]);
479 break;
480 default:
481 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
482 ("switch case not process\n"));
483 break;
486 bwrite_sucess = true;
488 rtlhal->last_hmeboxnum = boxnum + 1;
489 if (rtlhal->last_hmeboxnum == 4)
490 rtlhal->last_hmeboxnum = 0;
492 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
493 ("pHalData->last_hmeboxnum = %d\n",
494 rtlhal->last_hmeboxnum));
497 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
498 rtlhal->b_h2c_setinprogress = false;
499 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
501 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
504 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
505 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
507 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
508 u32 tmp_cmdbuf[2];
510 if (rtlhal->bfw_ready == false) {
511 RT_ASSERT(false, ("return H2C cmd because of Fw "
512 "download fail!!!\n"));
513 return;
516 memset(tmp_cmdbuf, 0, 8);
517 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
518 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
520 return;
523 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
525 u8 u1b_tmp;
526 u8 delay = 100;
527 struct rtl_priv *rtlpriv = rtl_priv(hw);
529 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
530 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
532 while (u1b_tmp & BIT(2)) {
533 delay--;
534 if (delay == 0) {
535 RT_ASSERT(false, ("8051 reset fail.\n"));
536 break;
538 udelay(50);
539 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
543 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
545 struct rtl_priv *rtlpriv = rtl_priv(hw);
546 u8 u1_h2c_set_pwrmode[3] = {0};
547 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
549 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
551 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
552 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
553 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
554 ppsc->reg_max_lps_awakeintvl);
556 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
557 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
558 u1_h2c_set_pwrmode, 3);
559 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
563 static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
564 struct sk_buff *skb)
566 struct rtl_priv *rtlpriv = rtl_priv(hw);
567 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
568 struct rtl8192_tx_ring *ring;
569 struct rtl_tx_desc *pdesc;
570 u8 own;
571 unsigned long flags;
572 struct sk_buff *pskb = NULL;
574 ring = &rtlpci->tx_ring[BEACON_QUEUE];
576 pskb = __skb_dequeue(&ring->queue);
577 if (pskb)
578 kfree_skb(pskb);
580 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
582 pdesc = &ring->desc[0];
583 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
585 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
587 __skb_queue_tail(&ring->queue, skb);
589 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
591 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
593 return true;
596 #define BEACON_PG 0 /*->1*/
597 #define PSPOLL_PG 2
598 #define NULL_PG 3
599 #define PROBERSP_PG 4 /*->5*/
601 #define TOTAL_RESERVED_PKT_LEN 768
603 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
604 /* page 0 beacon */
605 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
606 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
607 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
610 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
611 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
612 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
613 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
614 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
615 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
619 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 /* page 1 beacon */
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 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 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 /* page 2 ps-poll */
641 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
642 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
655 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 /* page 3 null */
659 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
660 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
661 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
673 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 /* page 4 probe_resp */
677 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
678 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
679 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
680 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
681 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
682 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
683 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
684 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
685 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
686 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
687 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
691 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 /* page 5 probe_resp */
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
713 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
715 struct rtl_priv *rtlpriv = rtl_priv(hw);
716 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
717 struct sk_buff *skb = NULL;
719 u32 totalpacketlen;
720 bool rtstatus;
721 u8 u1RsvdPageLoc[3] = {0};
722 bool b_dlok = false;
724 u8 *beacon;
725 u8 *p_pspoll;
726 u8 *nullfunc;
727 u8 *p_probersp;
728 /*---------------------------------------------------------
729 (1) beacon
730 ---------------------------------------------------------*/
731 beacon = &reserved_page_packet[BEACON_PG * 128];
732 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
733 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
735 /*-------------------------------------------------------
736 (2) ps-poll
737 --------------------------------------------------------*/
738 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
739 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
740 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
741 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
743 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
745 /*--------------------------------------------------------
746 (3) null data
747 ---------------------------------------------------------*/
748 nullfunc = &reserved_page_packet[NULL_PG * 128];
749 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
750 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
751 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
753 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
755 /*---------------------------------------------------------
756 (4) probe response
757 ----------------------------------------------------------*/
758 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
759 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
760 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
761 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
763 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
765 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
767 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
768 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
769 &reserved_page_packet[0], totalpacketlen);
770 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
771 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
772 u1RsvdPageLoc, 3);
775 skb = dev_alloc_skb(totalpacketlen);
776 memcpy((u8 *) skb_put(skb, totalpacketlen),
777 &reserved_page_packet, totalpacketlen);
779 rtstatus = _rtl92c_cmd_send_packet(hw, skb);
781 if (rtstatus)
782 b_dlok = true;
784 if (b_dlok) {
785 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
786 ("Set RSVD page location to Fw.\n"));
787 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
788 "H2C_RSVDPAGE:\n",
789 u1RsvdPageLoc, 3);
790 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
791 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
792 } else
793 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
794 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
797 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
799 u8 u1_joinbssrpt_parm[1] = {0};
801 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
803 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);