linux/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
<<
>>
Prefs
   1/******************************************************************************
   2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
   3 *
   4 * This program is distributed in the hope that it will be useful, but WITHOUT
   5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   6 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   7 * more details.
   8 *
   9 * You should have received a copy of the GNU General Public License along with
  10 * this program; if not, write to the Free Software Foundation, Inc.,
  11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  12 *
  13 * The full GNU General Public License is included in this distribution in the
  14 * file called LICENSE.
  15 *
  16 * Contact Information:
  17 * wlanfae <wlanfae@realtek.com>
  18******************************************************************************/
  19
  20#include "rtl_core.h"
  21#include "r8192E_hw.h"
  22#include "r8192E_hwimg.h"
  23#include "r8192E_firmware.h"
  24#include <linux/firmware.h>
  25
  26void firmware_init_param(struct net_device *dev)
  27{
  28        struct r8192_priv *priv = rtllib_priv(dev);
  29        struct rt_firmware *pfirmware = priv->pFirmware;
  30
  31        pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(
  32                                             MAX_TRANSMIT_BUFFER_SIZE);
  33}
  34
  35static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
  36                             u32 buffer_len)
  37{
  38        struct r8192_priv *priv = rtllib_priv(dev);
  39        bool                rt_status = true;
  40        u16                 frag_threshold;
  41        u16                 frag_length, frag_offset = 0;
  42        int                 i;
  43
  44        struct rt_firmware *pfirmware = priv->pFirmware;
  45        struct sk_buff      *skb;
  46        unsigned char       *seg_ptr;
  47        struct cb_desc *tcb_desc;
  48        u8                  bLastIniPkt;
  49
  50        firmware_init_param(dev);
  51        frag_threshold = pfirmware->cmdpacket_frag_thresold;
  52        do {
  53                if ((buffer_len - frag_offset) > frag_threshold) {
  54                        frag_length = frag_threshold ;
  55                        bLastIniPkt = 0;
  56
  57                } else {
  58                        frag_length = buffer_len - frag_offset;
  59                        bLastIniPkt = 1;
  60
  61                }
  62
  63                skb  = dev_alloc_skb(frag_length + 4);
  64                memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
  65                tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
  66                tcb_desc->queue_index = TXCMD_QUEUE;
  67                tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
  68                tcb_desc->bLastIniPkt = bLastIniPkt;
  69
  70                seg_ptr = skb->data;
  71                for (i = 0; i < frag_length; i += 4) {
  72                        *seg_ptr++ = ((i+0) < frag_length) ?
  73                                     code_virtual_address[i+3] : 0;
  74                        *seg_ptr++ = ((i+1) < frag_length) ?
  75                                     code_virtual_address[i+2] : 0;
  76                        *seg_ptr++ = ((i+2) < frag_length) ?
  77                                     code_virtual_address[i+1] : 0;
  78                        *seg_ptr++ = ((i+3) < frag_length) ?
  79                                     code_virtual_address[i+0] : 0;
  80                }
  81                tcb_desc->txbuf_size = (u16)i;
  82                skb_put(skb, i);
  83
  84                if (!priv->rtllib->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
  85                    (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index])) ||
  86                    (priv->rtllib->queue_stop)) {
  87                        RT_TRACE(COMP_FIRMWARE, "===================> tx "
  88                                 "full!\n");
  89                        skb_queue_tail(&priv->rtllib->skb_waitQ
  90                                        [tcb_desc->queue_index], skb);
  91                } else {
  92                priv->rtllib->softmac_hard_start_xmit(skb, dev);
  93                }
  94
  95                code_virtual_address += frag_length;
  96                frag_offset += frag_length;
  97
  98        } while (frag_offset < buffer_len);
  99
 100        write_nic_byte(dev, TPPoll, TPPoll_CQ);
 101
 102        return rt_status;
 103}
 104
 105static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 106{
 107        bool            rt_status = true;
 108        u32             CPU_status = 0;
 109        unsigned long   timeout;
 110
 111        timeout = jiffies + MSECS(200);
 112        while (time_before(jiffies, timeout)) {
 113                CPU_status = read_nic_dword(dev, CPU_GEN);
 114                if (CPU_status & CPU_GEN_PUT_CODE_OK)
 115                        break;
 116                mdelay(2);
 117        }
 118
 119        if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
 120                RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
 121                goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
 122        } else {
 123                RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
 124        }
 125
 126        CPU_status = read_nic_dword(dev, CPU_GEN);
 127        write_nic_byte(dev, CPU_GEN,
 128                       (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
 129        mdelay(1);
 130
 131        timeout = jiffies + MSECS(200);
 132        while (time_before(jiffies, timeout)) {
 133                CPU_status = read_nic_dword(dev, CPU_GEN);
 134                if (CPU_status&CPU_GEN_BOOT_RDY)
 135                        break;
 136                mdelay(2);
 137        }
 138
 139        if (!(CPU_status&CPU_GEN_BOOT_RDY))
 140                goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
 141        else
 142                RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
 143
 144        return rt_status;
 145
 146CPUCheckMainCodeOKAndTurnOnCPU_Fail:
 147        RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
 148        rt_status = false;
 149        return rt_status;
 150}
 151
 152static bool CPUcheck_firmware_ready(struct net_device *dev)
 153{
 154
 155        bool    rt_status = true;
 156        u32     CPU_status = 0;
 157        unsigned long timeout;
 158
 159        timeout = jiffies + MSECS(20);
 160        while (time_before(jiffies, timeout)) {
 161                CPU_status = read_nic_dword(dev, CPU_GEN);
 162                if (CPU_status&CPU_GEN_FIRM_RDY)
 163                        break;
 164                mdelay(2);
 165        }
 166
 167        if (!(CPU_status&CPU_GEN_FIRM_RDY))
 168                goto CPUCheckFirmwareReady_Fail;
 169        else
 170                RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
 171
 172        return rt_status;
 173
 174CPUCheckFirmwareReady_Fail:
 175        RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
 176        rt_status = false;
 177        return rt_status;
 178
 179}
 180
 181static bool firmware_check_ready(struct net_device *dev,
 182                                        u8 load_fw_status)
 183{
 184        struct r8192_priv *priv = rtllib_priv(dev);
 185        struct rt_firmware *pfirmware = priv->pFirmware;
 186        bool rt_status  = true;
 187
 188        switch (load_fw_status) {
 189        case FW_INIT_STEP0_BOOT:
 190                pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
 191                break;
 192
 193        case FW_INIT_STEP1_MAIN:
 194                pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
 195
 196                rt_status = CPUcheck_maincodeok_turnonCPU(dev);
 197                if (rt_status)
 198                        pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
 199                else
 200                        RT_TRACE(COMP_FIRMWARE, "CPUcheck_maincodeok_turnon"
 201                                 "CPU fail!\n");
 202
 203                break;
 204
 205        case FW_INIT_STEP2_DATA:
 206                pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
 207                mdelay(1);
 208
 209                rt_status = CPUcheck_firmware_ready(dev);
 210                if (rt_status)
 211                        pfirmware->firmware_status = FW_STATUS_5_READY;
 212                else
 213                        RT_TRACE(COMP_FIRMWARE, "CPUcheck_firmware_ready fail"
 214                                 "(%d)!\n", rt_status);
 215
 216                break;
 217        default:
 218                rt_status = false;
 219                RT_TRACE(COMP_FIRMWARE, "Unknown firmware status");
 220                break;
 221        }
 222
 223        return rt_status;
 224}
 225
 226bool init_firmware(struct net_device *dev)
 227{
 228        struct r8192_priv *priv = rtllib_priv(dev);
 229        bool                    rt_status = true;
 230
 231        u8      *firmware_img_buf[3] = { &Rtl8192PciEFwBootArray[0],
 232                                         &Rtl8192PciEFwMainArray[0],
 233                                         &Rtl8192PciEFwDataArray[0]};
 234
 235        u32     firmware_img_len[3] = { sizeof(Rtl8192PciEFwBootArray),
 236                                        sizeof(Rtl8192PciEFwMainArray),
 237                                        sizeof(Rtl8192PciEFwDataArray)};
 238        u32     file_length = 0;
 239        u8      *mapped_file = NULL;
 240        u8      init_step = 0;
 241        enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
 242        enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
 243
 244        struct rt_firmware *pfirmware = priv->pFirmware;
 245
 246        RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
 247
 248        if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
 249                rst_opt = OPT_SYSTEM_RESET;
 250                starting_state = FW_INIT_STEP0_BOOT;
 251
 252        } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
 253                rst_opt = OPT_FIRMWARE_RESET;
 254                starting_state = FW_INIT_STEP2_DATA;
 255        } else {
 256                RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined"
 257                         " firmware state\n");
 258        }
 259
 260        priv->firmware_source = FW_SOURCE_IMG_FILE;
 261        for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA;
 262             init_step++) {
 263                if (rst_opt == OPT_SYSTEM_RESET) {
 264                        switch (priv->firmware_source) {
 265                        case FW_SOURCE_IMG_FILE:
 266                        {
 267                                if (pfirmware->firmware_buf_size[init_step] == 0) {
 268                                        const char *fw_name[3] = {
 269                                                        RTL8192E_BOOT_IMG_FW,
 270                                                        RTL8192E_MAIN_IMG_FW,
 271                                                        RTL8192E_DATA_IMG_FW
 272                                        };
 273                                        const struct firmware   *fw_entry;
 274                                        int rc;
 275                                        rc = request_firmware(&fw_entry,
 276                                         fw_name[init_step], &priv->pdev->dev);
 277                                        if (rc < 0) {
 278                                                RT_TRACE(COMP_FIRMWARE, "request firm"
 279                                                 "ware fail!\n");
 280                                                goto download_firmware_fail;
 281                                        }
 282                                        if (fw_entry->size >
 283                                    sizeof(pfirmware->firmware_buf[init_step])) {
 284                                                RT_TRACE(COMP_FIRMWARE, "img file size "
 285                                                 "exceed the container struct "
 286                                                 "buffer fail!\n");
 287                                                goto download_firmware_fail;
 288                                        }
 289
 290                                        if (init_step != FW_INIT_STEP1_MAIN) {
 291                                                memcpy(pfirmware->firmware_buf[init_step],
 292                                               fw_entry->data, fw_entry->size);
 293                                                pfirmware->firmware_buf_size[init_step] =
 294                                               fw_entry->size;
 295
 296                                        } else {
 297                                                memset(pfirmware->firmware_buf[init_step],
 298                                               0, 128);
 299                                                memcpy(&pfirmware->firmware_buf[init_step][128],
 300                                               fw_entry->data, fw_entry->size);
 301                                                pfirmware->firmware_buf_size[init_step] =
 302                                                         fw_entry->size + 128;
 303                                        }
 304
 305                                        if (rst_opt == OPT_SYSTEM_RESET)
 306                                                release_firmware(fw_entry);
 307                                }
 308                                mapped_file = pfirmware->firmware_buf[init_step];
 309                                file_length = pfirmware->firmware_buf_size[init_step];
 310                                break;
 311                        }
 312                        case FW_SOURCE_HEADER_FILE:
 313                                mapped_file =  firmware_img_buf[init_step];
 314                                file_length  = firmware_img_len[init_step];
 315                                if (init_step == FW_INIT_STEP2_DATA) {
 316                                        memcpy(pfirmware->firmware_buf[init_step], mapped_file, file_length);
 317                                        pfirmware->firmware_buf_size[init_step] = file_length;
 318                                }
 319                                break;
 320
 321                        default:
 322                                break;
 323                        }
 324
 325
 326                } else if (rst_opt == OPT_FIRMWARE_RESET) {
 327                        mapped_file = pfirmware->firmware_buf[init_step];
 328                        file_length = pfirmware->firmware_buf_size[init_step];
 329                }
 330
 331                rt_status = fw_download_code(dev, mapped_file, file_length);
 332                if (rt_status != true) {
 333                        goto download_firmware_fail;
 334                }
 335
 336                if (!firmware_check_ready(dev, init_step)) {
 337                        goto download_firmware_fail;
 338                }
 339        }
 340
 341        RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
 342        return rt_status;
 343
 344download_firmware_fail:
 345        RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
 346        rt_status = false;
 347        return rt_status;
 348
 349}
 350