spi-topcliff-pch: supports a spi mode setup and bit order setup by IO control
[zen-stable.git] / drivers / net / wireless / rtlwifi / rtl8192c / fw_common.c
bloba0af2330e23fc560981e902294a249c02bd7bd7a
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 #include <linux/firmware.h>
33 #include <linux/export.h>
34 #include "../wifi.h"
35 #include "../pci.h"
36 #include "../base.h"
37 #include "../rtl8192ce/reg.h"
38 #include "../rtl8192ce/def.h"
39 #include "fw_common.h"
41 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
43 struct rtl_priv *rtlpriv = rtl_priv(hw);
44 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
46 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
47 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
48 if (enable)
49 value32 |= MCUFWDL_EN;
50 else
51 value32 &= ~MCUFWDL_EN;
52 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
53 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
54 u8 tmp;
55 if (enable) {
57 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
58 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
59 tmp | 0x04);
61 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
62 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
64 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
65 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
66 } else {
68 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
69 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
71 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
76 static void rtl_block_fw_writeN(struct ieee80211_hw *hw, const u8 *buffer,
77 u32 size)
79 struct rtl_priv *rtlpriv = rtl_priv(hw);
80 u32 blockSize = REALTEK_USB_VENQT_MAX_BUF_SIZE - 20;
81 u8 *bufferPtr = (u8 *) buffer;
82 u32 i, offset, blockCount, remainSize;
84 blockCount = size / blockSize;
85 remainSize = size % blockSize;
87 for (i = 0; i < blockCount; i++) {
88 offset = i * blockSize;
89 rtlpriv->io.writeN_sync(rtlpriv,
90 (FW_8192C_START_ADDRESS + offset),
91 (void *)(bufferPtr + offset),
92 blockSize);
95 if (remainSize) {
96 offset = blockCount * blockSize;
97 rtlpriv->io.writeN_sync(rtlpriv,
98 (FW_8192C_START_ADDRESS + offset),
99 (void *)(bufferPtr + offset),
100 remainSize);
104 static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
105 const u8 *buffer, u32 size)
107 struct rtl_priv *rtlpriv = rtl_priv(hw);
108 u32 blockSize = sizeof(u32);
109 u8 *bufferPtr = (u8 *) buffer;
110 u32 *pu4BytePtr = (u32 *) buffer;
111 u32 i, offset, blockCount, remainSize;
112 u32 data;
114 if (rtlpriv->io.writeN_sync) {
115 rtl_block_fw_writeN(hw, buffer, size);
116 return;
118 blockCount = size / blockSize;
119 remainSize = size % blockSize;
120 if (remainSize) {
121 /* the last word is < 4 bytes - pad it with zeros */
122 for (i = 0; i < 4 - remainSize; i++)
123 *(bufferPtr + size + i) = 0;
124 blockCount++;
127 for (i = 0; i < blockCount; i++) {
128 offset = i * blockSize;
129 /* for big-endian platforms, the firmware data need to be byte
130 * swapped as it was read as a byte string and will be written
131 * as 32-bit dwords and byte swapped when written
133 data = le32_to_cpu(*(__le32 *)(pu4BytePtr + i));
134 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
135 data);
139 static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
140 u32 page, const u8 *buffer, u32 size)
142 struct rtl_priv *rtlpriv = rtl_priv(hw);
143 u8 value8;
144 u8 u8page = (u8) (page & 0x07);
146 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
148 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
149 _rtl92c_fw_block_write(hw, buffer, size);
152 static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
154 u32 fwlen = *pfwlen;
155 u8 remain = (u8) (fwlen % 4);
157 remain = (remain == 0) ? 0 : (4 - remain);
159 while (remain > 0) {
160 pfwbuf[fwlen] = 0;
161 fwlen++;
162 remain--;
165 *pfwlen = fwlen;
168 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
169 enum version_8192c version, u8 *buffer, u32 size)
171 struct rtl_priv *rtlpriv = rtl_priv(hw);
172 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
173 u8 *bufferPtr = (u8 *) buffer;
175 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
177 if (IS_CHIP_VER_B(version)) {
178 u32 pageNums, remainSize;
179 u32 page, offset;
181 if (IS_HARDWARE_TYPE_8192CE(rtlhal))
182 _rtl92c_fill_dummy(bufferPtr, &size);
184 pageNums = size / FW_8192C_PAGE_SIZE;
185 remainSize = size % FW_8192C_PAGE_SIZE;
187 if (pageNums > 4) {
188 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
189 ("Page numbers should not greater then 4\n"));
192 for (page = 0; page < pageNums; page++) {
193 offset = page * FW_8192C_PAGE_SIZE;
194 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
195 FW_8192C_PAGE_SIZE);
198 if (remainSize) {
199 offset = pageNums * FW_8192C_PAGE_SIZE;
200 page = pageNums;
201 _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
202 remainSize);
204 } else {
205 _rtl92c_fw_block_write(hw, buffer, size);
209 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
211 struct rtl_priv *rtlpriv = rtl_priv(hw);
212 u32 counter = 0;
213 u32 value32;
215 do {
216 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
217 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
218 (!(value32 & FWDL_ChkSum_rpt)));
220 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
221 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
222 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
223 value32));
224 return -EIO;
227 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
228 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
230 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
231 value32 |= MCUFWDL_RDY;
232 value32 &= ~WINTINI_RDY;
233 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
235 counter = 0;
237 do {
238 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
239 if (value32 & WINTINI_RDY) {
240 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
241 ("Polling FW ready success!!"
242 " REG_MCUFWDL:0x%08x .\n",
243 value32));
244 return 0;
247 mdelay(FW_8192C_POLLING_DELAY);
249 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
251 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
252 ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
253 return -EIO;
256 int rtl92c_download_fw(struct ieee80211_hw *hw)
258 struct rtl_priv *rtlpriv = rtl_priv(hw);
259 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
260 struct rtl92c_firmware_header *pfwheader;
261 u8 *pfwdata;
262 u32 fwsize;
263 enum version_8192c version = rtlhal->version;
265 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
266 return 1;
268 pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
269 pfwdata = (u8 *) rtlhal->pfirmware;
270 fwsize = rtlhal->fwsize;
272 if (IS_FW_HEADER_EXIST(pfwheader)) {
273 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
274 ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
275 le16_to_cpu(pfwheader->version),
276 le16_to_cpu(pfwheader->signature),
277 (uint)sizeof(struct rtl92c_firmware_header)));
279 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
280 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
283 _rtl92c_enable_fw_download(hw, true);
284 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
285 _rtl92c_enable_fw_download(hw, false);
287 if (_rtl92c_fw_free_to_go(hw)) {
288 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
289 ("Firmware is not ready to run!\n"));
290 } else {
291 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
292 ("Firmware is ready to run!\n"));
295 return 0;
297 EXPORT_SYMBOL(rtl92c_download_fw);
299 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
301 struct rtl_priv *rtlpriv = rtl_priv(hw);
302 u8 val_hmetfr, val_mcutst_1;
303 bool result = false;
305 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
306 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
308 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
309 result = true;
310 return result;
313 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
314 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
316 struct rtl_priv *rtlpriv = rtl_priv(hw);
317 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
318 u8 boxnum;
319 u16 box_reg = 0, box_extreg = 0;
320 u8 u1b_tmp;
321 bool isfw_read = false;
322 bool bwrite_sucess = false;
323 u8 wait_h2c_limmit = 100;
324 u8 wait_writeh2c_limmit = 100;
325 u8 boxcontent[4], boxextcontent[2];
326 u32 h2c_waitcounter = 0;
327 unsigned long flag;
328 u8 idx;
330 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
332 while (true) {
333 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
334 if (rtlhal->h2c_setinprogress) {
335 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
336 ("H2C set in progress! Wait to set.."
337 "element_id(%d).\n", element_id));
339 while (rtlhal->h2c_setinprogress) {
340 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
341 flag);
342 h2c_waitcounter++;
343 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
344 ("Wait 100 us (%d times)...\n",
345 h2c_waitcounter));
346 udelay(100);
348 if (h2c_waitcounter > 1000)
349 return;
350 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
351 flag);
353 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
354 } else {
355 rtlhal->h2c_setinprogress = true;
356 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
357 break;
361 while (!bwrite_sucess) {
362 wait_writeh2c_limmit--;
363 if (wait_writeh2c_limmit == 0) {
364 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
365 ("Write H2C fail because no trigger "
366 "for FW INT!\n"));
367 break;
370 boxnum = rtlhal->last_hmeboxnum;
371 switch (boxnum) {
372 case 0:
373 box_reg = REG_HMEBOX_0;
374 box_extreg = REG_HMEBOX_EXT_0;
375 break;
376 case 1:
377 box_reg = REG_HMEBOX_1;
378 box_extreg = REG_HMEBOX_EXT_1;
379 break;
380 case 2:
381 box_reg = REG_HMEBOX_2;
382 box_extreg = REG_HMEBOX_EXT_2;
383 break;
384 case 3:
385 box_reg = REG_HMEBOX_3;
386 box_extreg = REG_HMEBOX_EXT_3;
387 break;
388 default:
389 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
390 ("switch case not process\n"));
391 break;
394 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
395 while (!isfw_read) {
397 wait_h2c_limmit--;
398 if (wait_h2c_limmit == 0) {
399 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
400 ("Wating too long for FW read "
401 "clear HMEBox(%d)!\n", boxnum));
402 break;
405 udelay(10);
407 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
408 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
409 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
410 ("Wating for FW read clear HMEBox(%d)!!! "
411 "0x1BF = %2x\n", boxnum, u1b_tmp));
414 if (!isfw_read) {
415 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
416 ("Write H2C register BOX[%d] fail!!!!! "
417 "Fw do not read.\n", boxnum));
418 break;
421 memset(boxcontent, 0, sizeof(boxcontent));
422 memset(boxextcontent, 0, sizeof(boxextcontent));
423 boxcontent[0] = element_id;
424 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
425 ("Write element_id box_reg(%4x) = %2x\n",
426 box_reg, element_id));
428 switch (cmd_len) {
429 case 1:
430 boxcontent[0] &= ~(BIT(7));
431 memcpy((u8 *) (boxcontent) + 1,
432 p_cmdbuffer, 1);
434 for (idx = 0; idx < 4; idx++) {
435 rtl_write_byte(rtlpriv, box_reg + idx,
436 boxcontent[idx]);
438 break;
439 case 2:
440 boxcontent[0] &= ~(BIT(7));
441 memcpy((u8 *) (boxcontent) + 1,
442 p_cmdbuffer, 2);
444 for (idx = 0; idx < 4; idx++) {
445 rtl_write_byte(rtlpriv, box_reg + idx,
446 boxcontent[idx]);
448 break;
449 case 3:
450 boxcontent[0] &= ~(BIT(7));
451 memcpy((u8 *) (boxcontent) + 1,
452 p_cmdbuffer, 3);
454 for (idx = 0; idx < 4; idx++) {
455 rtl_write_byte(rtlpriv, box_reg + idx,
456 boxcontent[idx]);
458 break;
459 case 4:
460 boxcontent[0] |= (BIT(7));
461 memcpy((u8 *) (boxextcontent),
462 p_cmdbuffer, 2);
463 memcpy((u8 *) (boxcontent) + 1,
464 p_cmdbuffer + 2, 2);
466 for (idx = 0; idx < 2; idx++) {
467 rtl_write_byte(rtlpriv, box_extreg + idx,
468 boxextcontent[idx]);
471 for (idx = 0; idx < 4; idx++) {
472 rtl_write_byte(rtlpriv, box_reg + idx,
473 boxcontent[idx]);
475 break;
476 case 5:
477 boxcontent[0] |= (BIT(7));
478 memcpy((u8 *) (boxextcontent),
479 p_cmdbuffer, 2);
480 memcpy((u8 *) (boxcontent) + 1,
481 p_cmdbuffer + 2, 3);
483 for (idx = 0; idx < 2; idx++) {
484 rtl_write_byte(rtlpriv, box_extreg + idx,
485 boxextcontent[idx]);
488 for (idx = 0; idx < 4; idx++) {
489 rtl_write_byte(rtlpriv, box_reg + idx,
490 boxcontent[idx]);
492 break;
493 default:
494 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
495 ("switch case not process\n"));
496 break;
499 bwrite_sucess = true;
501 rtlhal->last_hmeboxnum = boxnum + 1;
502 if (rtlhal->last_hmeboxnum == 4)
503 rtlhal->last_hmeboxnum = 0;
505 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
506 ("pHalData->last_hmeboxnum = %d\n",
507 rtlhal->last_hmeboxnum));
510 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
511 rtlhal->h2c_setinprogress = false;
512 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
514 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
517 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
518 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
520 u32 tmp_cmdbuf[2];
522 memset(tmp_cmdbuf, 0, 8);
523 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
524 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
526 return;
528 EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
530 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
532 u8 u1b_tmp;
533 u8 delay = 100;
534 struct rtl_priv *rtlpriv = rtl_priv(hw);
536 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
537 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
539 while (u1b_tmp & BIT(2)) {
540 delay--;
541 if (delay == 0) {
542 RT_ASSERT(false, ("8051 reset fail.\n"));
543 break;
545 udelay(50);
546 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
549 EXPORT_SYMBOL(rtl92c_firmware_selfreset);
551 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
553 struct rtl_priv *rtlpriv = rtl_priv(hw);
554 u8 u1_h2c_set_pwrmode[3] = {0};
555 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
557 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
559 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
560 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
561 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
562 ppsc->reg_max_lps_awakeintvl);
564 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
565 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
566 u1_h2c_set_pwrmode, 3);
567 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
570 EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
572 static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
573 struct sk_buff *skb)
575 struct rtl_priv *rtlpriv = rtl_priv(hw);
576 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
577 struct rtl8192_tx_ring *ring;
578 struct rtl_tx_desc *pdesc;
579 unsigned long flags;
580 struct sk_buff *pskb = NULL;
582 ring = &rtlpci->tx_ring[BEACON_QUEUE];
584 pskb = __skb_dequeue(&ring->queue);
585 if (pskb)
586 kfree_skb(pskb);
588 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
590 pdesc = &ring->desc[0];
592 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
594 __skb_queue_tail(&ring->queue, skb);
596 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
598 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
600 return true;
603 #define BEACON_PG 0 /*->1*/
604 #define PSPOLL_PG 2
605 #define NULL_PG 3
606 #define PROBERSP_PG 4 /*->5*/
608 #define TOTAL_RESERVED_PKT_LEN 768
610 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
611 /* page 0 beacon */
612 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
613 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
614 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
617 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
618 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
619 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
620 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
621 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
622 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
626 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 /* page 1 beacon */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 /* page 2 ps-poll */
648 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
649 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
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 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
662 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 /* page 3 null */
666 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
667 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
668 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
680 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 /* page 4 probe_resp */
684 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
685 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
686 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
687 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
688 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
689 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
690 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
691 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
692 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
693 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
694 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
698 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 /* page 5 probe_resp */
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,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
722 struct rtl_priv *rtlpriv = rtl_priv(hw);
723 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
724 struct sk_buff *skb = NULL;
726 u32 totalpacketlen;
727 bool rtstatus;
728 u8 u1RsvdPageLoc[3] = {0};
729 bool dlok = false;
731 u8 *beacon;
732 u8 *pspoll;
733 u8 *nullfunc;
734 u8 *probersp;
735 /*---------------------------------------------------------
736 (1) beacon
737 ---------------------------------------------------------*/
738 beacon = &reserved_page_packet[BEACON_PG * 128];
739 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
740 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
742 /*-------------------------------------------------------
743 (2) ps-poll
744 --------------------------------------------------------*/
745 pspoll = &reserved_page_packet[PSPOLL_PG * 128];
746 SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
747 SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
748 SET_80211_PS_POLL_TA(pspoll, mac->mac_addr);
750 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
752 /*--------------------------------------------------------
753 (3) null data
754 ---------------------------------------------------------*/
755 nullfunc = &reserved_page_packet[NULL_PG * 128];
756 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
757 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
758 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
760 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
762 /*---------------------------------------------------------
763 (4) probe response
764 ----------------------------------------------------------*/
765 probersp = &reserved_page_packet[PROBERSP_PG * 128];
766 SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
767 SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
768 SET_80211_HDR_ADDRESS3(probersp, mac->bssid);
770 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
772 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
774 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
775 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
776 &reserved_page_packet[0], totalpacketlen);
777 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
778 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
779 u1RsvdPageLoc, 3);
782 skb = dev_alloc_skb(totalpacketlen);
783 if (!skb)
784 return;
785 memcpy((u8 *) skb_put(skb, totalpacketlen),
786 &reserved_page_packet, totalpacketlen);
788 rtstatus = _rtl92c_cmd_send_packet(hw, skb);
790 if (rtstatus)
791 dlok = true;
793 if (dlok) {
794 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
795 ("Set RSVD page location to Fw.\n"));
796 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
797 "H2C_RSVDPAGE:\n",
798 u1RsvdPageLoc, 3);
799 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
800 sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
801 } else
802 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
803 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
805 EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
807 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
809 u8 u1_joinbssrpt_parm[1] = {0};
811 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
813 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
815 EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);