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