linux/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  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 * The full GNU General Public License is included in this distribution in the
  15 * file called LICENSE.
  16 *
  17 * Contact Information:
  18 * wlanfae <wlanfae@realtek.com>
  19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20 * Hsinchu 300, Taiwan.
  21 *
  22 * Larry Finger <Larry.Finger@lwfinger.net>
  23 *
  24 *****************************************************************************/
  25
  26#include "../wifi.h"
  27#include "../pci.h"
  28#include "../base.h"
  29#include "../efuse.h"
  30#include "reg.h"
  31#include "def.h"
  32#include "fw.h"
  33#include "sw.h"
  34
  35static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
  36{
  37        return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
  38                true : false;
  39}
  40
  41static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  42{
  43        struct rtl_priv *rtlpriv = rtl_priv(hw);
  44        u8 tmp;
  45
  46        if (enable) {
  47                tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  48                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
  49                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  50                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
  51                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  52                rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  53        } else {
  54                tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  55                rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  56                /* Reserved for fw extension.
  57                 * 0x81[7] is used for mac0 status ,
  58                 * so don't write this reg here
  59                 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
  60        }
  61}
  62
  63static void _rtl92d_write_fw(struct ieee80211_hw *hw,
  64                             enum version_8192d version, u8 *buffer, u32 size)
  65{
  66        struct rtl_priv *rtlpriv = rtl_priv(hw);
  67        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  68        u8 *bufferptr = buffer;
  69        u32 pagenums, remainsize;
  70        u32 page, offset;
  71
  72        RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
  73        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
  74                rtl_fill_dummy(bufferptr, &size);
  75        pagenums = size / FW_8192D_PAGE_SIZE;
  76        remainsize = size % FW_8192D_PAGE_SIZE;
  77        if (pagenums > 8)
  78                pr_err("Page numbers should not greater then 8\n");
  79        for (page = 0; page < pagenums; page++) {
  80                offset = page * FW_8192D_PAGE_SIZE;
  81                rtl_fw_page_write(hw, page, (bufferptr + offset),
  82                                  FW_8192D_PAGE_SIZE);
  83        }
  84        if (remainsize) {
  85                offset = pagenums * FW_8192D_PAGE_SIZE;
  86                page = pagenums;
  87                rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  88        }
  89}
  90
  91static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
  92{
  93        struct rtl_priv *rtlpriv = rtl_priv(hw);
  94        u32 counter = 0;
  95        u32 value32;
  96
  97        do {
  98                value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  99        } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
 100                 (!(value32 & FWDL_ChkSum_rpt)));
 101        if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
 102                pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
 103                       value32);
 104                return -EIO;
 105        }
 106        value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
 107        value32 |= MCUFWDL_RDY;
 108        rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
 109        return 0;
 110}
 111
 112void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
 113{
 114        struct rtl_priv *rtlpriv = rtl_priv(hw);
 115        u8 u1b_tmp;
 116        u8 delay = 100;
 117
 118        /* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
 119        rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
 120        u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 121        while (u1b_tmp & BIT(2)) {
 122                delay--;
 123                if (delay == 0)
 124                        break;
 125                udelay(50);
 126                u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
 127        }
 128        WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
 129        RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 130                 "=====> 8051 reset success (%d)\n", delay);
 131}
 132
 133static int _rtl92d_fw_init(struct ieee80211_hw *hw)
 134{
 135        struct rtl_priv *rtlpriv = rtl_priv(hw);
 136        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 137        u32 counter;
 138
 139        RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
 140        /* polling for FW ready */
 141        counter = 0;
 142        do {
 143                if (rtlhal->interfaceindex == 0) {
 144                        if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
 145                            MAC0_READY) {
 146                                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 147                                         "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
 148                                         rtl_read_byte(rtlpriv,
 149                                                       FW_MAC0_READY));
 150                                return 0;
 151                        }
 152                        udelay(5);
 153                } else {
 154                        if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
 155                            MAC1_READY) {
 156                                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 157                                         "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
 158                                         rtl_read_byte(rtlpriv,
 159                                                       FW_MAC1_READY));
 160                                return 0;
 161                        }
 162                        udelay(5);
 163                }
 164        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 165
 166        if (rtlhal->interfaceindex == 0) {
 167                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 168                         "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
 169                         rtl_read_byte(rtlpriv, FW_MAC0_READY));
 170        } else {
 171                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 172                         "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
 173                         rtl_read_byte(rtlpriv, FW_MAC1_READY));
 174        }
 175        RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 176                 "Polling FW ready fail!! REG_MCUFWDL:0x%08ul\n",
 177                 rtl_read_dword(rtlpriv, REG_MCUFWDL));
 178        return -1;
 179}
 180
 181int rtl92d_download_fw(struct ieee80211_hw *hw)
 182{
 183        struct rtl_priv *rtlpriv = rtl_priv(hw);
 184        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 185        u8 *pfwheader;
 186        u8 *pfwdata;
 187        u32 fwsize;
 188        int err;
 189        enum version_8192d version = rtlhal->version;
 190        u8 value;
 191        u32 count;
 192        bool fw_downloaded = false, fwdl_in_process = false;
 193        unsigned long flags;
 194
 195        if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 196                return 1;
 197        fwsize = rtlhal->fwsize;
 198        pfwheader = rtlhal->pfirmware;
 199        pfwdata = rtlhal->pfirmware;
 200        rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
 201        rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
 202        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 203                 "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
 204                 rtlhal->fw_version, rtlhal->fw_subversion,
 205                 GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
 206        if (IS_FW_HEADER_EXIST(pfwheader)) {
 207                RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 208                         "Shift 32 bytes for FW header!!\n");
 209                pfwdata = pfwdata + 32;
 210                fwsize = fwsize - 32;
 211        }
 212
 213        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 214        fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
 215        if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
 216                fwdl_in_process = true;
 217        else
 218                fwdl_in_process = false;
 219        if (fw_downloaded) {
 220                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 221                goto exit;
 222        } else if (fwdl_in_process) {
 223                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 224                for (count = 0; count < 5000; count++) {
 225                        udelay(500);
 226                        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 227                        fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
 228                        if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
 229                                fwdl_in_process = true;
 230                        else
 231                                fwdl_in_process = false;
 232                        spin_unlock_irqrestore(&globalmutex_for_fwdownload,
 233                                               flags);
 234                        if (fw_downloaded)
 235                                goto exit;
 236                        else if (!fwdl_in_process)
 237                                break;
 238                        else
 239                                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 240                                         "Wait for another mac download fw\n");
 241                }
 242                spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 243                value = rtl_read_byte(rtlpriv, 0x1f);
 244                value |= BIT(5);
 245                rtl_write_byte(rtlpriv, 0x1f, value);
 246                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 247        } else {
 248                value = rtl_read_byte(rtlpriv, 0x1f);
 249                value |= BIT(5);
 250                rtl_write_byte(rtlpriv, 0x1f, value);
 251                spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 252        }
 253
 254        /* If 8051 is running in RAM code, driver should
 255         * inform Fw to reset by itself, or it will cause
 256         * download Fw fail.*/
 257        /* 8051 RAM code */
 258        if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
 259                rtl92d_firmware_selfreset(hw);
 260                rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
 261        }
 262        _rtl92d_enable_fw_download(hw, true);
 263        _rtl92d_write_fw(hw, version, pfwdata, fwsize);
 264        _rtl92d_enable_fw_download(hw, false);
 265        spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
 266        err = _rtl92d_fw_free_to_go(hw);
 267        /* download fw over,clear 0x1f[5] */
 268        value = rtl_read_byte(rtlpriv, 0x1f);
 269        value &= (~BIT(5));
 270        rtl_write_byte(rtlpriv, 0x1f, value);
 271        spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
 272        if (err)
 273                pr_err("fw is not ready to run!\n");
 274exit:
 275        err = _rtl92d_fw_init(hw);
 276        return err;
 277}
 278
 279static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
 280{
 281        struct rtl_priv *rtlpriv = rtl_priv(hw);
 282        u8 val_hmetfr;
 283        bool result = false;
 284
 285        val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
 286        if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
 287                result = true;
 288        return result;
 289}
 290
 291static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
 292                              u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 293{
 294        struct rtl_priv *rtlpriv = rtl_priv(hw);
 295        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 296        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 297        u8 boxnum;
 298        u16 box_reg = 0, box_extreg = 0;
 299        u8 u1b_tmp;
 300        bool isfw_read = false;
 301        u8 buf_index = 0;
 302        bool bwrite_success = false;
 303        u8 wait_h2c_limmit = 100;
 304        u8 wait_writeh2c_limmit = 100;
 305        u8 boxcontent[4], boxextcontent[2];
 306        u32 h2c_waitcounter = 0;
 307        unsigned long flag;
 308        u8 idx;
 309
 310        if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
 311                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 312                         "Return as RF is off!!!\n");
 313                return;
 314        }
 315        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
 316        while (true) {
 317                spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 318                if (rtlhal->h2c_setinprogress) {
 319                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 320                                 "H2C set in progress! Wait to set..element_id(%d)\n",
 321                                 element_id);
 322
 323                        while (rtlhal->h2c_setinprogress) {
 324                                spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
 325                                                       flag);
 326                                h2c_waitcounter++;
 327                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 328                                         "Wait 100 us (%d times)...\n",
 329                                         h2c_waitcounter);
 330                                udelay(100);
 331
 332                                if (h2c_waitcounter > 1000)
 333                                        return;
 334
 335                                spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
 336                                                  flag);
 337                        }
 338                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 339                } else {
 340                        rtlhal->h2c_setinprogress = true;
 341                        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 342                        break;
 343                }
 344        }
 345        while (!bwrite_success) {
 346                wait_writeh2c_limmit--;
 347                if (wait_writeh2c_limmit == 0) {
 348                        pr_err("Write H2C fail because no trigger for FW INT!\n");
 349                        break;
 350                }
 351                boxnum = rtlhal->last_hmeboxnum;
 352                switch (boxnum) {
 353                case 0:
 354                        box_reg = REG_HMEBOX_0;
 355                        box_extreg = REG_HMEBOX_EXT_0;
 356                        break;
 357                case 1:
 358                        box_reg = REG_HMEBOX_1;
 359                        box_extreg = REG_HMEBOX_EXT_1;
 360                        break;
 361                case 2:
 362                        box_reg = REG_HMEBOX_2;
 363                        box_extreg = REG_HMEBOX_EXT_2;
 364                        break;
 365                case 3:
 366                        box_reg = REG_HMEBOX_3;
 367                        box_extreg = REG_HMEBOX_EXT_3;
 368                        break;
 369                default:
 370                        pr_err("switch case %#x not processed\n",
 371                               boxnum);
 372                        break;
 373                }
 374                isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
 375                while (!isfw_read) {
 376                        wait_h2c_limmit--;
 377                        if (wait_h2c_limmit == 0) {
 378                                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 379                                         "Waiting too long for FW read clear HMEBox(%d)!\n",
 380                                         boxnum);
 381                                break;
 382                        }
 383                        udelay(10);
 384                        isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
 385                        u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
 386                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 387                                 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
 388                                 boxnum, u1b_tmp);
 389                }
 390                if (!isfw_read) {
 391                        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 392                                 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 393                                 boxnum);
 394                        break;
 395                }
 396                memset(boxcontent, 0, sizeof(boxcontent));
 397                memset(boxextcontent, 0, sizeof(boxextcontent));
 398                boxcontent[0] = element_id;
 399                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 400                         "Write element_id box_reg(%4x) = %2x\n",
 401                         box_reg, element_id);
 402                switch (cmd_len) {
 403                case 1:
 404                        boxcontent[0] &= ~(BIT(7));
 405                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
 406                        for (idx = 0; idx < 4; idx++)
 407                                rtl_write_byte(rtlpriv, box_reg + idx,
 408                                               boxcontent[idx]);
 409                        break;
 410                case 2:
 411                        boxcontent[0] &= ~(BIT(7));
 412                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
 413                        for (idx = 0; idx < 4; idx++)
 414                                rtl_write_byte(rtlpriv, box_reg + idx,
 415                                               boxcontent[idx]);
 416                        break;
 417                case 3:
 418                        boxcontent[0] &= ~(BIT(7));
 419                        memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
 420                        for (idx = 0; idx < 4; idx++)
 421                                rtl_write_byte(rtlpriv, box_reg + idx,
 422                                               boxcontent[idx]);
 423                        break;
 424                case 4:
 425                        boxcontent[0] |= (BIT(7));
 426                        memcpy(boxextcontent, cmdbuffer + buf_index, 2);
 427                        memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
 428                        for (idx = 0; idx < 2; idx++)
 429                                rtl_write_byte(rtlpriv, box_extreg + idx,
 430                                               boxextcontent[idx]);
 431                        for (idx = 0; idx < 4; idx++)
 432                                rtl_write_byte(rtlpriv, box_reg + idx,
 433                                               boxcontent[idx]);
 434                        break;
 435                case 5:
 436                        boxcontent[0] |= (BIT(7));
 437                        memcpy(boxextcontent, cmdbuffer + buf_index, 2);
 438                        memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
 439                        for (idx = 0; idx < 2; idx++)
 440                                rtl_write_byte(rtlpriv, box_extreg + idx,
 441                                               boxextcontent[idx]);
 442                        for (idx = 0; idx < 4; idx++)
 443                                rtl_write_byte(rtlpriv, box_reg + idx,
 444                                               boxcontent[idx]);
 445                        break;
 446                default:
 447                        pr_err("switch case %#x not processed\n",
 448                               cmd_len);
 449                        break;
 450                }
 451                bwrite_success = true;
 452                rtlhal->last_hmeboxnum = boxnum + 1;
 453                if (rtlhal->last_hmeboxnum == 4)
 454                        rtlhal->last_hmeboxnum = 0;
 455                RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 456                         "pHalData->last_hmeboxnum  = %d\n",
 457                         rtlhal->last_hmeboxnum);
 458        }
 459        spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 460        rtlhal->h2c_setinprogress = false;
 461        spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 462        RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 463}
 464
 465void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
 466                         u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 467{
 468        u32 tmp_cmdbuf[2];
 469
 470        memset(tmp_cmdbuf, 0, 8);
 471        memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 472        _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
 473        return;
 474}
 475
 476static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
 477                                    struct sk_buff *skb)
 478{
 479        struct rtl_priv *rtlpriv = rtl_priv(hw);
 480        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 481        struct rtl8192_tx_ring *ring;
 482        struct rtl_tx_desc *pdesc;
 483        u8 idx = 0;
 484        unsigned long flags;
 485        struct sk_buff *pskb;
 486
 487        ring = &rtlpci->tx_ring[BEACON_QUEUE];
 488        pskb = __skb_dequeue(&ring->queue);
 489        kfree_skb(pskb);
 490        spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 491        pdesc = &ring->desc[idx];
 492        /* discard output from call below */
 493        rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
 494        rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
 495        __skb_queue_tail(&ring->queue, skb);
 496        spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
 497        rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
 498        return true;
 499}
 500
 501#define BEACON_PG               0       /*->1 */
 502#define PSPOLL_PG               2
 503#define NULL_PG                 3
 504#define PROBERSP_PG             4       /*->5 */
 505#define TOTAL_RESERVED_PKT_LEN  768
 506
 507static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 508        /* page 0 beacon */
 509        0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 510        0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 511        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
 512        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 513        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 514        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 515        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 516        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 517        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 518        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 519        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 520        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 521        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 522        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 523        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 524        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 525
 526        /* page 1 beacon */
 527        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 528        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 529        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 530        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 531        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 532        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 533        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 534        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 535        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 536        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 537        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 538        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 539        0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
 540        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 541        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 542        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 543
 544        /* page 2  ps-poll */
 545        0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
 546        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 547        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 548        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 549        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 550        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 551        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 552        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 553        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 554        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 555        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 556        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 557        0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 558        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 559        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 560        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 561
 562        /* page 3  null */
 563        0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 564        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 565        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 566        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 567        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 568        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 569        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 570        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 571        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 572        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 573        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 574        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 575        0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 576        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 577        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 578        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 579
 580        /* page 4  probe_resp */
 581        0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 582        0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 583        0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 584        0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 585        0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 586        0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 587        0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 588        0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 589        0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 590        0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 591        0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 592        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 593        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 594        0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 595        0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 596        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 597
 598        /* page 5  probe_resp */
 599        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 600        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 601        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 602        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 603        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 604        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 605        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 606        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 607        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 608        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 609        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 610        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 611        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 612        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 613        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 614        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 615};
 616
 617void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
 618{
 619        struct rtl_priv *rtlpriv = rtl_priv(hw);
 620        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 621        struct sk_buff *skb = NULL;
 622        u32 totalpacketlen;
 623        bool rtstatus;
 624        u8 u1RsvdPageLoc[3] = { 0 };
 625        bool dlok = false;
 626        u8 *beacon;
 627        u8 *p_pspoll;
 628        u8 *nullfunc;
 629        u8 *p_probersp;
 630        /*---------------------------------------------------------
 631                                                (1) beacon
 632        ---------------------------------------------------------*/
 633        beacon = &reserved_page_packet[BEACON_PG * 128];
 634        SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 635        SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 636        /*-------------------------------------------------------
 637                                                (2) ps-poll
 638        --------------------------------------------------------*/
 639        p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 640        SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 641        SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 642        SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 643        SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
 644        /*--------------------------------------------------------
 645                                                (3) null data
 646        ---------------------------------------------------------*/
 647        nullfunc = &reserved_page_packet[NULL_PG * 128];
 648        SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 649        SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 650        SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 651        SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
 652        /*---------------------------------------------------------
 653                                                (4) probe response
 654        ----------------------------------------------------------*/
 655        p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 656        SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 657        SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 658        SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 659        SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
 660        totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 661        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 662                      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
 663                      &reserved_page_packet[0], totalpacketlen);
 664        RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 665                      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
 666                      u1RsvdPageLoc, 3);
 667        skb = dev_alloc_skb(totalpacketlen);
 668        if (!skb) {
 669                dlok = false;
 670        } else {
 671                skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 672                rtstatus = _rtl92d_cmd_send_packet(hw, skb);
 673
 674                if (rtstatus)
 675                        dlok = true;
 676        }
 677        if (dlok) {
 678                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 679                         "Set RSVD page location to Fw\n");
 680                RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 681                              "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
 682                rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
 683                        sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
 684        } else
 685                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 686                         "Set RSVD page location to Fw FAIL!!!!!!\n");
 687}
 688
 689void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 690{
 691        u8 u1_joinbssrpt_parm[1] = {0};
 692
 693        SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
 694        rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 695}
 696