~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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);