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