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