ipv6: Use ERR_CAST in addrconf_dst_alloc.
[pandora-kernel.git] / drivers / net / wireless / rtlwifi / rtl8192ce / fw.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
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.
8  *
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.
13  *
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
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29
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"
38
39 static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
40 {
41         struct rtl_priv *rtlpriv = rtl_priv(hw);
42         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
43
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) {
54
55                         tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
56                         rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
57                                        tmp | 0x04);
58
59                         tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
60                         rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
61
62                         tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
63                         rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
64                 } else {
65
66                         tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
67                         rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
68
69                         rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
70                 }
71         }
72 }
73
74 static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
75                                    const u8 *buffer, u32 size)
76 {
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;
82
83         blockCount = size / blockSize;
84         remainSize = size % blockSize;
85
86         for (i = 0; i < blockCount; i++) {
87                 offset = i * blockSize;
88                 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
89                                 *(pu4BytePtr + i));
90         }
91
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));
98                 }
99         }
100 }
101
102 static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
103                                   u32 page, const u8 *buffer, u32 size)
104 {
105         struct rtl_priv *rtlpriv = rtl_priv(hw);
106         u8 value8;
107         u8 u8page = (u8) (page & 0x07);
108
109         value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
110
111         rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
112         _rtl92c_fw_block_write(hw, buffer, size);
113 }
114
115 static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
116 {
117         u32 fwlen = *pfwlen;
118         u8 remain = (u8) (fwlen % 4);
119
120         remain = (remain == 0) ? 0 : (4 - remain);
121
122         while (remain > 0) {
123                 pfwbuf[fwlen] = 0;
124                 fwlen++;
125                 remain--;
126         }
127
128         *pfwlen = fwlen;
129 }
130
131 static void _rtl92c_write_fw(struct ieee80211_hw *hw,
132                              enum version_8192c version, u8 *buffer, u32 size)
133 {
134         struct rtl_priv *rtlpriv = rtl_priv(hw);
135         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
136         u8 *bufferPtr = (u8 *) buffer;
137
138         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
139
140         if (IS_CHIP_VER_B(version)) {
141                 u32 pageNums, remainSize;
142                 u32 page, offset;
143
144                 if (IS_HARDWARE_TYPE_8192CE(rtlhal))
145                         _rtl92c_fill_dummy(bufferPtr, &size);
146
147                 pageNums = size / FW_8192C_PAGE_SIZE;
148                 remainSize = size % FW_8192C_PAGE_SIZE;
149
150                 if (pageNums > 4) {
151                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
152                                  ("Page numbers should not greater then 4\n"));
153                 }
154
155                 for (page = 0; page < pageNums; page++) {
156                         offset = page * FW_8192C_PAGE_SIZE;
157                         _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
158                                               FW_8192C_PAGE_SIZE);
159                 }
160
161                 if (remainSize) {
162                         offset = pageNums * FW_8192C_PAGE_SIZE;
163                         page = pageNums;
164                         _rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
165                                               remainSize);
166                 }
167         } else {
168                 _rtl92c_fw_block_write(hw, buffer, size);
169         }
170 }
171
172 static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
173 {
174         struct rtl_priv *rtlpriv = rtl_priv(hw);
175         int err = -EIO;
176         u32 counter = 0;
177         u32 value32;
178
179         do {
180                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
181         } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
182                  (!(value32 & FWDL_ChkSum_rpt)));
183
184         if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
185                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
186                          ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
187                           value32));
188                 goto exit;
189         }
190
191         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
192                  ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
193
194         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
195         value32 |= MCUFWDL_RDY;
196         value32 &= ~WINTINI_RDY;
197         rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
198
199         counter = 0;
200
201         do {
202                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
203                 if (value32 & WINTINI_RDY) {
204                         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
205                                  ("Polling FW ready success!!"
206                                  " REG_MCUFWDL:0x%08x .\n",
207                                  value32));
208                         err = 0;
209                         goto exit;
210                 }
211
212                 mdelay(FW_8192C_POLLING_DELAY);
213
214         } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
215
216         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
217                  ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
218
219 exit:
220         return err;
221 }
222
223 int rtl92c_download_fw(struct ieee80211_hw *hw)
224 {
225         struct rtl_priv *rtlpriv = rtl_priv(hw);
226         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
227         struct rtl92c_firmware_header *pfwheader;
228         u8 *pfwdata;
229         u32 fwsize;
230         int err;
231         enum version_8192c version = rtlhal->version;
232         const struct firmware *firmware;
233
234         printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n",
235                rtlpriv->cfg->fw_name);
236         err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
237                                rtlpriv->io.dev);
238         if (err) {
239                 printk(KERN_ERR "rtl8192cu: Firmware loading failed\n");
240                 return 1;
241         }
242
243         if (firmware->size > 0x4000) {
244                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
245                          ("Firmware is too big!\n"));
246                 release_firmware(firmware);
247                 return 1;
248         }
249
250         memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
251         fwsize = firmware->size;
252         release_firmware(firmware);
253
254         pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
255         pfwdata = (u8 *) rtlhal->pfirmware;
256
257         if (IS_FW_HEADER_EXIST(pfwheader)) {
258                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
259                          ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
260                           pfwheader->version, pfwheader->signature,
261                           (uint)sizeof(struct rtl92c_firmware_header)));
262
263                 pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
264                 fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
265         }
266
267         _rtl92c_enable_fw_download(hw, true);
268         _rtl92c_write_fw(hw, version, pfwdata, fwsize);
269         _rtl92c_enable_fw_download(hw, false);
270
271         err = _rtl92c_fw_free_to_go(hw);
272         if (err) {
273                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
274                          ("Firmware is not ready to run!\n"));
275         } else {
276                 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
277                          ("Firmware is ready to run!\n"));
278         }
279
280         return 0;
281 }
282
283 static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
284 {
285         struct rtl_priv *rtlpriv = rtl_priv(hw);
286         u8 val_hmetfr, val_mcutst_1;
287         bool result = false;
288
289         val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
290         val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
291
292         if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
293                 result = true;
294         return result;
295 }
296
297 static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
298                               u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
299 {
300         struct rtl_priv *rtlpriv = rtl_priv(hw);
301         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
302         u8 boxnum;
303         u16 box_reg, box_extreg;
304         u8 u1b_tmp;
305         bool isfw_read = false;
306         u8 buf_index;
307         bool bwrite_sucess = false;
308         u8 wait_h2c_limmit = 100;
309         u8 wait_writeh2c_limmit = 100;
310         u8 boxcontent[4], boxextcontent[2];
311         u32 h2c_waitcounter = 0;
312         unsigned long flag;
313         u8 idx;
314
315         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
316
317         while (true) {
318                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
319                 if (rtlhal->h2c_setinprogress) {
320                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
321                                  ("H2C set in progress! Wait to set.."
322                                   "element_id(%d).\n", element_id));
323
324                         while (rtlhal->h2c_setinprogress) {
325                                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
326                                                        flag);
327                                 h2c_waitcounter++;
328                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
329                                          ("Wait 100 us (%d times)...\n",
330                                           h2c_waitcounter));
331                                 udelay(100);
332
333                                 if (h2c_waitcounter > 1000)
334                                         return;
335                                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
336                                                   flag);
337                         }
338                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
339                 } else {
340                         rtlhal->h2c_setinprogress = true;
341                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
342                         break;
343                 }
344         }
345
346         while (!bwrite_sucess) {
347                 wait_writeh2c_limmit--;
348                 if (wait_writeh2c_limmit == 0) {
349                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
350                                  ("Write H2C fail because no trigger "
351                                   "for FW INT!\n"));
352                         break;
353                 }
354
355                 boxnum = rtlhal->last_hmeboxnum;
356                 switch (boxnum) {
357                 case 0:
358                         box_reg = REG_HMEBOX_0;
359                         box_extreg = REG_HMEBOX_EXT_0;
360                         break;
361                 case 1:
362                         box_reg = REG_HMEBOX_1;
363                         box_extreg = REG_HMEBOX_EXT_1;
364                         break;
365                 case 2:
366                         box_reg = REG_HMEBOX_2;
367                         box_extreg = REG_HMEBOX_EXT_2;
368                         break;
369                 case 3:
370                         box_reg = REG_HMEBOX_3;
371                         box_extreg = REG_HMEBOX_EXT_3;
372                         break;
373                 default:
374                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
375                                  ("switch case not process\n"));
376                         break;
377                 }
378
379                 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
380                 while (!isfw_read) {
381
382                         wait_h2c_limmit--;
383                         if (wait_h2c_limmit == 0) {
384                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
385                                          ("Wating too long for FW read "
386                                           "clear HMEBox(%d)!\n", boxnum));
387                                 break;
388                         }
389
390                         udelay(10);
391
392                         isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
393                         u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
394                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
395                                  ("Wating for FW read clear HMEBox(%d)!!! "
396                                   "0x1BF = %2x\n", boxnum, u1b_tmp));
397                 }
398
399                 if (!isfw_read) {
400                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
401                                  ("Write H2C register BOX[%d] fail!!!!! "
402                                   "Fw do not read.\n", boxnum));
403                         break;
404                 }
405
406                 memset(boxcontent, 0, sizeof(boxcontent));
407                 memset(boxextcontent, 0, sizeof(boxextcontent));
408                 boxcontent[0] = element_id;
409                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
410                          ("Write element_id box_reg(%4x) = %2x\n",
411                           box_reg, element_id));
412
413                 switch (cmd_len) {
414                 case 1:
415                         boxcontent[0] &= ~(BIT(7));
416                         memcpy((u8 *) (boxcontent) + 1,
417                                p_cmdbuffer + buf_index, 1);
418
419                         for (idx = 0; idx < 4; idx++) {
420                                 rtl_write_byte(rtlpriv, box_reg + idx,
421                                                boxcontent[idx]);
422                         }
423                         break;
424                 case 2:
425                         boxcontent[0] &= ~(BIT(7));
426                         memcpy((u8 *) (boxcontent) + 1,
427                                p_cmdbuffer + buf_index, 2);
428
429                         for (idx = 0; idx < 4; idx++) {
430                                 rtl_write_byte(rtlpriv, box_reg + idx,
431                                                boxcontent[idx]);
432                         }
433                         break;
434                 case 3:
435                         boxcontent[0] &= ~(BIT(7));
436                         memcpy((u8 *) (boxcontent) + 1,
437                                p_cmdbuffer + buf_index, 3);
438
439                         for (idx = 0; idx < 4; idx++) {
440                                 rtl_write_byte(rtlpriv, box_reg + idx,
441                                                boxcontent[idx]);
442                         }
443                         break;
444                 case 4:
445                         boxcontent[0] |= (BIT(7));
446                         memcpy((u8 *) (boxextcontent),
447                                p_cmdbuffer + buf_index, 2);
448                         memcpy((u8 *) (boxcontent) + 1,
449                                p_cmdbuffer + buf_index + 2, 2);
450
451                         for (idx = 0; idx < 2; idx++) {
452                                 rtl_write_byte(rtlpriv, box_extreg + idx,
453                                                boxextcontent[idx]);
454                         }
455
456                         for (idx = 0; idx < 4; idx++) {
457                                 rtl_write_byte(rtlpriv, box_reg + idx,
458                                                boxcontent[idx]);
459                         }
460                         break;
461                 case 5:
462                         boxcontent[0] |= (BIT(7));
463                         memcpy((u8 *) (boxextcontent),
464                                p_cmdbuffer + buf_index, 2);
465                         memcpy((u8 *) (boxcontent) + 1,
466                                p_cmdbuffer + buf_index + 2, 3);
467
468                         for (idx = 0; idx < 2; idx++) {
469                                 rtl_write_byte(rtlpriv, box_extreg + idx,
470                                                boxextcontent[idx]);
471                         }
472
473                         for (idx = 0; idx < 4; idx++) {
474                                 rtl_write_byte(rtlpriv, box_reg + idx,
475                                                boxcontent[idx]);
476                         }
477                         break;
478                 default:
479                         RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
480                                  ("switch case not process\n"));
481                         break;
482                 }
483
484                 bwrite_sucess = true;
485
486                 rtlhal->last_hmeboxnum = boxnum + 1;
487                 if (rtlhal->last_hmeboxnum == 4)
488                         rtlhal->last_hmeboxnum = 0;
489
490                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
491                          ("pHalData->last_hmeboxnum  = %d\n",
492                           rtlhal->last_hmeboxnum));
493         }
494
495         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
496         rtlhal->h2c_setinprogress = false;
497         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
498
499         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
500 }
501
502 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
503                          u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
504 {
505         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
506         u32 tmp_cmdbuf[2];
507
508         if (rtlhal->fw_ready == false) {
509                 RT_ASSERT(false, ("return H2C cmd because of Fw "
510                                   "download fail!!!\n"));
511                 return;
512         }
513
514         memset(tmp_cmdbuf, 0, 8);
515         memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
516         _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
517
518         return;
519 }
520
521 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
522 {
523         u8 u1b_tmp;
524         u8 delay = 100;
525         struct rtl_priv *rtlpriv = rtl_priv(hw);
526
527         rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
528         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
529
530         while (u1b_tmp & BIT(2)) {
531                 delay--;
532                 if (delay == 0) {
533                         RT_ASSERT(false, ("8051 reset fail.\n"));
534                         break;
535                 }
536                 udelay(50);
537                 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
538         }
539 }
540
541 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
542 {
543         struct rtl_priv *rtlpriv = rtl_priv(hw);
544         u8 u1_h2c_set_pwrmode[3] = {0};
545         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
546
547         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
548
549         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
550         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
551         SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
552                                               ppsc->reg_max_lps_awakeintvl);
553
554         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
555                       "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
556                       u1_h2c_set_pwrmode, 3);
557         rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
558
559 }
560
561 #define BEACON_PG               0 /*->1*/
562 #define PSPOLL_PG               2
563 #define NULL_PG                 3
564 #define PROBERSP_PG             4 /*->5*/
565
566 #define TOTAL_RESERVED_PKT_LEN  768
567
568 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
569         /* page 0 beacon */
570         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
571         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
572         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
573         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
575         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
576         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
577         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
578         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
579         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
580         0x03, 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         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
584         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586
587         /* page 1 beacon */
588         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
601         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604
605         /* page 2  ps-poll */
606         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
607         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
608         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
619         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
620         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622
623         /* page 3  null */
624         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
625         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
626         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 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         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
637         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
638         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640
641         /* page 4  probe_resp */
642         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
643         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
644         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
645         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
646         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
647         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
648         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
649         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
650         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
651         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
652         0x03, 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         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
656         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658
659         /* page 5  probe_resp */
660         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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         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 };
677
678 void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
679 {
680         struct rtl_priv *rtlpriv = rtl_priv(hw);
681         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
682         struct sk_buff *skb = NULL;
683
684         u32 totalpacketlen;
685         bool rtstatus;
686         u8 u1RsvdPageLoc[3] = {0};
687         bool b_dlok = false;
688
689         u8 *beacon;
690         u8 *p_pspoll;
691         u8 *nullfunc;
692         u8 *p_probersp;
693         /*---------------------------------------------------------
694                                 (1) beacon
695         ---------------------------------------------------------*/
696         beacon = &reserved_page_packet[BEACON_PG * 128];
697         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
698         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
699
700         /*-------------------------------------------------------
701                                 (2) ps-poll
702         --------------------------------------------------------*/
703         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
704         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
705         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
706         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
707
708         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
709
710         /*--------------------------------------------------------
711                                 (3) null data
712         ---------------------------------------------------------*/
713         nullfunc = &reserved_page_packet[NULL_PG * 128];
714         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
715         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
716         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
717
718         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
719
720         /*---------------------------------------------------------
721                                 (4) probe response
722         ----------------------------------------------------------*/
723         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
724         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
725         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
726         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
727
728         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
729
730         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
731
732         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
733                       "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
734                       &reserved_page_packet[0], totalpacketlen);
735         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
736                       "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
737                       u1RsvdPageLoc, 3);
738
739
740         skb = dev_alloc_skb(totalpacketlen);
741         memcpy((u8 *) skb_put(skb, totalpacketlen),
742                &reserved_page_packet, totalpacketlen);
743
744         rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb);
745
746         if (rtstatus)
747                 b_dlok = true;
748
749         if (b_dlok) {
750                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
751                          ("Set RSVD page location to Fw.\n"));
752                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
753                                 "H2C_RSVDPAGE:\n",
754                                 u1RsvdPageLoc, 3);
755                 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
756                                     sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
757         } else
758                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
759                          ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
760 }
761
762 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
763 {
764         u8 u1_joinbssrpt_parm[1] = {0};
765
766         SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
767
768         rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
769 }