linux/drivers/staging/rtl8192e/r819xE_cmdpkt.c
<<
>>
Prefs
   1/******************************************************************************
   2
   3     (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
   4
   5 Module:        r819xusb_cmdpkt.c       (RTL8190 TX/RX command packet handler Source C File)
   6
   7 Note:      The module is responsible for handling TX and RX command packet.
   8                        1. TX : Send set and query configuration command packet.
   9                        2. RX : Receive tx feedback, beacon state, query configuration
  10                                command packet.
  11
  12 Function:
  13
  14 Export:
  15
  16 Abbrev:
  17
  18 History:
  19        Data            Who             Remark
  20
  21        05/06/2008  amy         Create initial version porting from windows driver.
  22
  23******************************************************************************/
  24#include "r8192E.h"
  25#include "r8192E_hw.h"
  26#include "r819xE_cmdpkt.h"
  27/*---------------------------Define Local Constant---------------------------*/
  28/* Debug constant*/
  29#define         CMPK_DEBOUNCE_CNT                       1
  30/* 2007/10/24 MH Add for printing a range of data. */
  31#define         CMPK_PRINT(Address)\
  32{\
  33        unsigned char   i;\
  34        u32     temp[10];\
  35        \
  36        memcpy(temp, Address, 40);\
  37        for (i = 0; i <40; i+=4)\
  38                printk("\r\n %08x", temp[i]);\
  39}\
  40
  41/*---------------------------Define functions---------------------------------*/
  42/*-----------------------------------------------------------------------------
  43 * Function:    cmpk_message_handle_tx()
  44 *
  45 * Overview:    Driver internal module can call the API to send message to
  46 *                              firmware side. For example, you can send a debug command packet.
  47 *                              Or you can send a request for FW to modify RLX4181 LBUS HW bank.
  48 *                              Otherwise, you can change MAC/PHT/RF register by firmware at
  49 *                              run time. We do not support message more than one segment now.
  50 *
  51 * Input:               NONE
  52 *
  53 * Output:              NONE
  54 *
  55 * Return:              NONE
  56 *
  57 * Revised History:
  58 *      When            Who             Remark
  59 *      05/06/2008      amy             porting from windows code.
  60 *
  61 *---------------------------------------------------------------------------*/
  62RT_STATUS cmpk_message_handle_tx(
  63        struct net_device *dev,
  64        u8*     code_virtual_address,
  65        u32     packettype,
  66        u32     buffer_len)
  67{
  68
  69        RT_STATUS           rt_status = RT_STATUS_SUCCESS;
  70#ifdef RTL8192U
  71        return rt_status;
  72#else
  73        struct r8192_priv   *priv = ieee80211_priv(dev);
  74        u16                 frag_threshold;
  75        u16                 frag_length = 0, frag_offset = 0;
  76        rt_firmware         *pfirmware = priv->pFirmware;
  77        struct sk_buff      *skb;
  78        unsigned char       *seg_ptr;
  79        cb_desc             *tcb_desc;
  80        u8                  bLastIniPkt;
  81
  82        PTX_FWINFO_8190PCI      pTxFwInfo = NULL;
  83        int i;
  84
  85        //spin_lock_irqsave(&priv->tx_lock,flags);
  86        RT_TRACE(COMP_CMDPKT,"%s(),buffer_len is %d\n",__FUNCTION__,buffer_len);
  87        firmware_init_param(dev);
  88        //Fragmentation might be required
  89        frag_threshold = pfirmware->cmdpacket_frag_thresold;
  90        do {
  91            if((buffer_len - frag_offset) > frag_threshold) {
  92                frag_length = frag_threshold ;
  93                bLastIniPkt = 0;
  94
  95            } else {
  96                frag_length =(u16)(buffer_len - frag_offset);
  97                bLastIniPkt = 1;
  98
  99            }
 100
 101            /* Allocate skb buffer to contain firmware info and tx descriptor info
 102             * add 4 to avoid packet appending overflow.
 103             * */
 104#ifdef RTL8192U
 105            skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
 106#else
 107            skb  = dev_alloc_skb(frag_length + priv->ieee80211->tx_headroom + 4);
 108#endif
 109            if(skb == NULL) {
 110                rt_status = RT_STATUS_FAILURE;
 111                goto Failed;
 112            }
 113
 114            memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
 115            tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
 116            tcb_desc->queue_index = TXCMD_QUEUE;
 117            tcb_desc->bCmdOrInit = packettype;
 118            tcb_desc->bLastIniPkt = bLastIniPkt;
 119            tcb_desc->pkt_size = frag_length;
 120
 121#ifdef RTL8192U
 122            skb_reserve(skb, USB_HWDESC_HEADER_LEN);
 123#endif
 124
 125            //seg_ptr = skb_put(skb, frag_length + priv->ieee80211->tx_headroom);
 126            seg_ptr = skb_put(skb, priv->ieee80211->tx_headroom);
 127
 128            pTxFwInfo = (PTX_FWINFO_8190PCI)seg_ptr;
 129            memset(pTxFwInfo,0,sizeof(TX_FWINFO_8190PCI));
 130            memset(pTxFwInfo,0x12,8);
 131
 132            seg_ptr +=sizeof(TX_FWINFO_8190PCI);
 133
 134            /*
 135             * Transform from little endian to big endian
 136             * and pending  zero
 137             */
 138            seg_ptr = skb->tail;
 139            for(i=0 ; i < frag_length; i+=4) {
 140                *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
 141                *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
 142                *seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0;
 143                *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0;
 144            }
 145            skb_put(skb, i);
 146            priv->ieee80211->softmac_hard_start_xmit(skb,dev);
 147
 148            code_virtual_address += frag_length;
 149            frag_offset += frag_length;
 150
 151        }while(frag_offset < buffer_len);
 152
 153Failed:
 154        //spin_unlock_irqrestore(&priv->tx_lock,flags);
 155        return rt_status;
 156
 157
 158#endif
 159}       /* CMPK_Message_Handle_Tx */
 160
 161/*-----------------------------------------------------------------------------
 162 * Function:    cmpk_counttxstatistic()
 163 *
 164 * Overview:
 165 *
 166 * Input:       PADAPTER        pAdapter                -       .
 167 *                              CMPK_TXFB_T *psTx_FB    -       .
 168 *
 169 * Output:      NONE
 170 *
 171 * Return:      NONE
 172 *
 173 * Revised History:
 174 *  When                Who             Remark
 175 *  05/12/2008  amy     Create Version 0 porting from windows code.
 176 *
 177 *---------------------------------------------------------------------------*/
 178static  void
 179cmpk_count_txstatistic(
 180        struct net_device *dev,
 181        cmpk_txfb_t     *pstx_fb)
 182{
 183        struct r8192_priv *priv = ieee80211_priv(dev);
 184#ifdef ENABLE_PS
 185        RT_RF_POWER_STATE       rtState;
 186
 187        pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
 188
 189        // When RF is off, we should not count the packet for hw/sw synchronize
 190        // reason, ie. there may be a duration while sw switch is changed and hw
 191        // switch is being changed. 2006.12.04, by shien chang.
 192        if (rtState == eRfOff)
 193        {
 194                return;
 195        }
 196#endif
 197
 198#ifdef TODO
 199        if(pAdapter->bInHctTest)
 200                return;
 201#endif
 202        /* We can not know the packet length and transmit type: broadcast or uni
 203           or multicast. So the relative statistics must be collected in tx
 204           feedback info. */
 205        if (pstx_fb->tok)
 206        {
 207                priv->stats.txfeedbackok++;
 208                priv->stats.txoktotal++;
 209                priv->stats.txokbytestotal += pstx_fb->pkt_length;
 210                priv->stats.txokinperiod++;
 211
 212                /* We can not make sure broadcast/multicast or unicast mode. */
 213                if (pstx_fb->pkt_type == PACKET_MULTICAST)
 214                {
 215                        priv->stats.txmulticast++;
 216                        priv->stats.txbytesmulticast += pstx_fb->pkt_length;
 217                }
 218                else if (pstx_fb->pkt_type == PACKET_BROADCAST)
 219                {
 220                        priv->stats.txbroadcast++;
 221                        priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
 222                }
 223                else
 224                {
 225                        priv->stats.txunicast++;
 226                        priv->stats.txbytesunicast += pstx_fb->pkt_length;
 227                }
 228        }
 229        else
 230        {
 231                priv->stats.txfeedbackfail++;
 232                priv->stats.txerrtotal++;
 233                priv->stats.txerrbytestotal += pstx_fb->pkt_length;
 234
 235                /* We can not make sure broadcast/multicast or unicast mode. */
 236                if (pstx_fb->pkt_type == PACKET_MULTICAST)
 237                {
 238                        priv->stats.txerrmulticast++;
 239                }
 240                else if (pstx_fb->pkt_type == PACKET_BROADCAST)
 241                {
 242                        priv->stats.txerrbroadcast++;
 243                }
 244                else
 245                {
 246                        priv->stats.txerrunicast++;
 247                }
 248        }
 249
 250        priv->stats.txretrycount += pstx_fb->retry_cnt;
 251        priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
 252
 253}       /* cmpk_CountTxStatistic */
 254
 255
 256
 257/*-----------------------------------------------------------------------------
 258 * Function:    cmpk_handle_tx_feedback()
 259 *
 260 * Overview:    The function is responsible for extract the message inside TX
 261 *                              feedbck message from firmware. It will contain dedicated info in
 262 *                              ws-06-0063-rtl8190-command-packet-specification. Please
 263 *                              refer to chapter "TX Feedback Element". We have to read 20 bytes
 264 *                              in the command packet.
 265 *
 266 * Input:       struct net_device *    dev
 267 *                              u8      *       pmsg            -       Msg Ptr of the command packet.
 268 *
 269 * Output:      NONE
 270 *
 271 * Return:      NONE
 272 *
 273 * Revised History:
 274 *  When                Who             Remark
 275 *  05/08/2008  amy             Create Version 0 porting from windows code.
 276 *
 277 *---------------------------------------------------------------------------*/
 278static  void
 279cmpk_handle_tx_feedback(
 280        struct net_device *dev,
 281        u8      *       pmsg)
 282{
 283        struct r8192_priv *priv = ieee80211_priv(dev);
 284        cmpk_txfb_t             rx_tx_fb;       /* */
 285
 286        priv->stats.txfeedback++;
 287
 288        /* 0. Display received message. */
 289        //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
 290
 291        /* 1. Extract TX feedback info from RFD to temp structure buffer. */
 292        /* It seems that FW use big endian(MIPS) and DRV use little endian in
 293           windows OS. So we have to read the content byte by byte or transfer
 294           endian type before copy the message copy. */
 295#if 0           // The TX FEEDBACK packet element address
 296        //rx_tx_fb.Element_ID   = pMsg[0];
 297        //rx_tx_fb.Length               = pMsg[1];
 298        rx_tx_fb.TOK                    = pMsg[2]>>7;
 299        rx_tx_fb.Fail_Reason    = (pMsg[2] & 0x70) >> 4;
 300        rx_tx_fb.TID                    = (pMsg[2] & 0x0F);
 301        rx_tx_fb.Qos_Pkt                = pMsg[3] >> 7;
 302        rx_tx_fb.Bandwidth              = (pMsg[3] & 0x40) >> 6;
 303        rx_tx_fb.Retry_Cnt              = pMsg[5];
 304        rx_tx_fb.Pkt_ID                 = (pMsg[6] << 8) | pMsg[7];
 305        rx_tx_fb.Seq_Num                = (pMsg[8] << 8) | pMsg[9];
 306        rx_tx_fb.S_Rate                 = pMsg[10];
 307        rx_tx_fb.F_Rate                 = pMsg[11];
 308        rx_tx_fb.S_RTS_Rate     = pMsg[12];
 309        rx_tx_fb.F_RTS_Rate     = pMsg[13];
 310        rx_tx_fb.pkt_length     = (pMsg[14] << 8) | pMsg[15];
 311#endif
 312        /* 2007/07/05 MH Use pointer to transfer structure memory. */
 313        //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
 314        memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
 315        /* 2. Use tx feedback info to count TX statistics. */
 316        cmpk_count_txstatistic(dev, &rx_tx_fb);
 317#if 0
 318        /* 2007/07/11 MH Assign current operate rate.  */
 319        if (pAdapter->RegWirelessMode == WIRELESS_MODE_A ||
 320                pAdapter->RegWirelessMode == WIRELESS_MODE_B ||
 321                pAdapter->RegWirelessMode == WIRELESS_MODE_G)
 322        {
 323                pMgntInfo->CurrentOperaRate = (rx_tx_fb.F_Rate & 0x7F);
 324        }
 325        else if (pAdapter->RegWirelessMode == WIRELESS_MODE_N_24G ||
 326                         pAdapter->RegWirelessMode == WIRELESS_MODE_N_5G)
 327        {
 328                pMgntInfo->HTCurrentOperaRate = (rx_tx_fb.F_Rate & 0x8F);
 329        }
 330#endif
 331        /* 2007/01/17 MH Comment previous method for TX statistic function. */
 332        /* Collect info TX feedback packet to fill TCB. */
 333        /* We can not know the packet length and transmit type: broadcast or uni
 334           or multicast. */
 335        //CountTxStatistics( pAdapter, &tcb );
 336
 337}       /* cmpk_Handle_Tx_Feedback */
 338
 339static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
 340{
 341        struct r8192_priv *priv = ieee80211_priv(dev);
 342        u16 tx_rate;
 343        {
 344                //
 345                // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
 346                //
 347                if((priv->ieee80211->current_network.mode == IEEE_A)  ||
 348                        (priv->ieee80211->current_network.mode == IEEE_N_5G) ||
 349                        ((priv->ieee80211->current_network.mode == IEEE_N_24G)  && (!priv->ieee80211->pHTInfo->bCurSuppCCK)))
 350                {
 351                        tx_rate = 60;
 352                        DMESG("send beacon frame  tx rate is 6Mbpm\n");
 353                }
 354                else
 355                {
 356                        tx_rate =10;
 357                        DMESG("send beacon frame  tx rate is 1Mbpm\n");
 358                }
 359
 360                //rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon
 361
 362        }
 363
 364}
 365
 366
 367
 368
 369/*-----------------------------------------------------------------------------
 370 * Function:    cmpk_handle_interrupt_status()
 371 *
 372 * Overview:    The function is responsible for extract the message from
 373 *                              firmware. It will contain dedicated info in
 374 *                              ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
 375 *                              Please refer to chapter "Interrupt Status Element".
 376 *
 377 * Input:       struct net_device *dev,
 378 *                      u8*     pmsg            -       Message Pointer of the command packet.
 379 *
 380 * Output:      NONE
 381 *
 382 * Return:      NONE
 383 *
 384 * Revised History:
 385 *  When                        Who                     Remark
 386 *  05/12/2008  amy             Add this for rtl8192 porting from windows code.
 387 *
 388 *---------------------------------------------------------------------------*/
 389static  void
 390cmpk_handle_interrupt_status(
 391        struct net_device *dev,
 392        u8*     pmsg)
 393{
 394        cmpk_intr_sta_t         rx_intr_status; /* */
 395        struct r8192_priv *priv = ieee80211_priv(dev);
 396
 397        DMESG("---> cmpk_Handle_Interrupt_Status()\n");
 398
 399        /* 0. Display received message. */
 400        //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
 401
 402        /* 1. Extract TX feedback info from RFD to temp structure buffer. */
 403        /* It seems that FW use big endian(MIPS) and DRV use little endian in
 404           windows OS. So we have to read the content byte by byte or transfer
 405           endian type before copy the message copy. */
 406        //rx_bcn_state.Element_ID       = pMsg[0];
 407        //rx_bcn_state.Length           = pMsg[1];
 408        rx_intr_status.length = pmsg[1];
 409        if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
 410        {
 411                DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
 412                return;
 413        }
 414
 415
 416        // Statistics of beacon for ad-hoc mode.
 417        if(     priv->ieee80211->iw_mode == IW_MODE_ADHOC)
 418        {
 419                //2 maybe need endian transform?
 420                rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
 421                //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
 422
 423                DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
 424
 425                if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
 426                {
 427                        priv->ieee80211->bibsscoordinator = true;
 428                        priv->stats.txbeaconokint++;
 429                }
 430                else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
 431                {
 432                        priv->ieee80211->bibsscoordinator = false;
 433                        priv->stats.txbeaconerr++;
 434                }
 435
 436                if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
 437                {
 438                        cmdpkt_beacontimerinterrupt_819xusb(dev);
 439                }
 440
 441        }
 442
 443         // Other informations in interrupt status we need?
 444
 445
 446        DMESG("<---- cmpk_handle_interrupt_status()\n");
 447
 448}       /* cmpk_handle_interrupt_status */
 449
 450
 451/*-----------------------------------------------------------------------------
 452 * Function:    cmpk_handle_query_config_rx()
 453 *
 454 * Overview:    The function is responsible for extract the message from
 455 *                              firmware. It will contain dedicated info in
 456 *                              ws-06-0063-rtl8190-command-packet-specification. Please
 457 *                              refer to chapter "Beacon State Element".
 458 *
 459 * Input:       u8 *  pmsg      -       Message Pointer of the command packet.
 460 *
 461 * Output:      NONE
 462 *
 463 * Return:      NONE
 464 *
 465 * Revised History:
 466 *  When                Who             Remark
 467 *  05/12/2008  amy             Create Version 0 porting from windows code.
 468 *
 469 *---------------------------------------------------------------------------*/
 470static  void
 471cmpk_handle_query_config_rx(
 472        struct net_device *dev,
 473        u8*        pmsg)
 474{
 475        cmpk_query_cfg_t        rx_query_cfg;   /* */
 476
 477        /* 0. Display received message. */
 478        //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
 479
 480        /* 1. Extract TX feedback info from RFD to temp structure buffer. */
 481        /* It seems that FW use big endian(MIPS) and DRV use little endian in
 482           windows OS. So we have to read the content byte by byte or transfer
 483           endian type before copy the message copy. */
 484        //rx_query_cfg.Element_ID       = pMsg[0];
 485        //rx_query_cfg.Length           = pMsg[1];
 486        rx_query_cfg.cfg_action         = (pmsg[4] & 0x80000000)>>31;
 487        rx_query_cfg.cfg_type           = (pmsg[4] & 0x60) >> 5;
 488        rx_query_cfg.cfg_size           = (pmsg[4] & 0x18) >> 3;
 489        rx_query_cfg.cfg_page           = (pmsg[6] & 0x0F) >> 0;
 490        rx_query_cfg.cfg_offset                 = pmsg[7];
 491        rx_query_cfg.value                      = (pmsg[8] << 24) | (pmsg[9] << 16) |
 492                                                                  (pmsg[10] << 8) | (pmsg[11] << 0);
 493        rx_query_cfg.mask                       = (pmsg[12] << 24) | (pmsg[13] << 16) |
 494                                                                  (pmsg[14] << 8) | (pmsg[15] << 0);
 495
 496}       /* cmpk_Handle_Query_Config_Rx */
 497
 498
 499/*-----------------------------------------------------------------------------
 500 * Function:    cmpk_count_tx_status()
 501 *
 502 * Overview:    Count aggregated tx status from firmwar of one type rx command
 503 *                              packet element id = RX_TX_STATUS.
 504 *
 505 * Input:               NONE
 506 *
 507 * Output:              NONE
 508 *
 509 * Return:              NONE
 510 *
 511 * Revised History:
 512 *      When            Who             Remark
 513 *      05/12/2008      amy             Create Version 0 porting from windows code.
 514 *
 515 *---------------------------------------------------------------------------*/
 516static  void    cmpk_count_tx_status(   struct net_device *dev,
 517                                                                        cmpk_tx_status_t        *pstx_status)
 518{
 519        struct r8192_priv *priv = ieee80211_priv(dev);
 520
 521#ifdef ENABLE_PS
 522
 523        RT_RF_POWER_STATE       rtstate;
 524
 525        pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
 526
 527        // When RF is off, we should not count the packet for hw/sw synchronize
 528        // reason, ie. there may be a duration while sw switch is changed and hw
 529        // switch is being changed. 2006.12.04, by shien chang.
 530        if (rtState == eRfOff)
 531        {
 532                return;
 533        }
 534#endif
 535
 536        priv->stats.txfeedbackok        += pstx_status->txok;
 537        priv->stats.txoktotal           += pstx_status->txok;
 538
 539        priv->stats.txfeedbackfail      += pstx_status->txfail;
 540        priv->stats.txerrtotal          += pstx_status->txfail;
 541
 542        priv->stats.txretrycount                += pstx_status->txretry;
 543        priv->stats.txfeedbackretry     += pstx_status->txretry;
 544
 545        //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
 546        //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
 547        //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
 548
 549        priv->stats.txmulticast += pstx_status->txmcok;
 550        priv->stats.txbroadcast += pstx_status->txbcok;
 551        priv->stats.txunicast           += pstx_status->txucok;
 552
 553        priv->stats.txerrmulticast      += pstx_status->txmcfail;
 554        priv->stats.txerrbroadcast      += pstx_status->txbcfail;
 555        priv->stats.txerrunicast        += pstx_status->txucfail;
 556
 557        priv->stats.txbytesmulticast    += pstx_status->txmclength;
 558        priv->stats.txbytesbroadcast    += pstx_status->txbclength;
 559        priv->stats.txbytesunicast              += pstx_status->txuclength;
 560
 561        priv->stats.last_packet_rate            = pstx_status->rate;
 562}       /* cmpk_CountTxStatus */
 563
 564
 565
 566/*-----------------------------------------------------------------------------
 567 * Function:    cmpk_handle_tx_status()
 568 *
 569 * Overview:    Firmware add a new tx feedback status to reduce rx command
 570 *                              packet buffer operation load.
 571 *
 572 * Input:               NONE
 573 *
 574 * Output:              NONE
 575 *
 576 * Return:              NONE
 577 *
 578 * Revised History:
 579 *      When            Who             Remark
 580 *      05/12/2008      amy             Create Version 0 porting from windows code.
 581 *
 582 *---------------------------------------------------------------------------*/
 583static  void
 584cmpk_handle_tx_status(
 585        struct net_device *dev,
 586        u8*        pmsg)
 587{
 588        cmpk_tx_status_t        rx_tx_sts;      /* */
 589
 590        memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t));
 591        /* 2. Use tx feedback info to count TX statistics. */
 592        cmpk_count_tx_status(dev, &rx_tx_sts);
 593
 594}       /* cmpk_Handle_Tx_Status */
 595
 596
 597/*-----------------------------------------------------------------------------
 598 * Function:    cmpk_handle_tx_rate_history()
 599 *
 600 * Overview:    Firmware add a new tx rate history
 601 *
 602 * Input:               NONE
 603 *
 604 * Output:              NONE
 605 *
 606 * Return:              NONE
 607 *
 608 * Revised History:
 609 *      When            Who             Remark
 610 *      05/12/2008      amy             Create Version 0 porting from windows code.
 611 *
 612 *---------------------------------------------------------------------------*/
 613static  void
 614cmpk_handle_tx_rate_history(
 615        struct net_device *dev,
 616        u8*        pmsg)
 617{
 618        cmpk_tx_rahis_t *ptxrate;
 619//      RT_RF_POWER_STATE       rtState;
 620        u8                              i, j;
 621        u16                             length = sizeof(cmpk_tx_rahis_t);
 622        u32                             *ptemp;
 623        struct r8192_priv *priv = ieee80211_priv(dev);
 624
 625
 626#ifdef ENABLE_PS
 627        pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
 628
 629        // When RF is off, we should not count the packet for hw/sw synchronize
 630        // reason, ie. there may be a duration while sw switch is changed and hw
 631        // switch is being changed. 2006.12.04, by shien chang.
 632        if (rtState == eRfOff)
 633        {
 634                return;
 635        }
 636#endif
 637
 638        ptemp = (u32 *)pmsg;
 639
 640        //
 641        // Do endian transfer to word alignment(16 bits) for windows system.
 642        // You must do different endian transfer for linux and MAC OS
 643        //
 644        for (i = 0; i < (length/4); i++)
 645        {
 646                u16      temp1, temp2;
 647
 648                temp1 = ptemp[i]&0x0000FFFF;
 649                temp2 = ptemp[i]>>16;
 650                ptemp[i] = (temp1<<16)|temp2;
 651        }
 652
 653        ptxrate = (cmpk_tx_rahis_t *)pmsg;
 654
 655        if (ptxrate == NULL )
 656        {
 657                return;
 658        }
 659
 660        for (i = 0; i < 16; i++)
 661        {
 662                // Collect CCK rate packet num
 663                if (i < 4)
 664                        priv->stats.txrate.cck[i] += ptxrate->cck[i];
 665
 666                // Collect OFDM rate packet num
 667                if (i< 8)
 668                        priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
 669
 670                for (j = 0; j < 4; j++)
 671                        priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
 672        }
 673
 674}       /* cmpk_Handle_Tx_Rate_History */
 675
 676
 677/*-----------------------------------------------------------------------------
 678 * Function:    cmpk_message_handle_rx()
 679 *
 680 * Overview:    In the function, we will capture different RX command packet
 681 *                              info. Every RX command packet element has different message
 682 *                              length and meaning in content. We only support three type of RX
 683 *                              command packet now. Please refer to document
 684 *                              ws-06-0063-rtl8190-command-packet-specification.
 685 *
 686 * Input:       NONE
 687 *
 688 * Output:      NONE
 689 *
 690 * Return:      NONE
 691 *
 692 * Revised History:
 693 *  When                Who             Remark
 694 *  05/06/2008  amy             Create Version 0 porting from windows code.
 695 *
 696 *---------------------------------------------------------------------------*/
 697u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *pstats)
 698{
 699//      u32                     debug_level = DBG_LOUD;
 700        struct r8192_priv *priv = ieee80211_priv(dev);
 701        int                     total_length;
 702        u8                      cmd_length, exe_cnt = 0;
 703        u8                      element_id;
 704        u8                      *pcmd_buff;
 705
 706        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx()\n");
 707
 708        /* 0. Check inpt arguments. If is is a command queue message or pointer is
 709              null. */
 710        if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
 711        {
 712                /* Print error message. */
 713                /*RT_TRACE(COMP_SEND, DebugLevel,
 714                                ("\n\r[CMPK]-->Err queue id or pointer"));*/
 715                return 0;       /* This is not a command packet. */
 716        }
 717
 718        /* 1. Read received command packet message length from RFD. */
 719        total_length = pstats->Length;
 720
 721        /* 2. Read virtual address from RFD. */
 722        pcmd_buff = pstats->virtual_address;
 723
 724        /* 3. Read command pakcet element id and length. */
 725        element_id = pcmd_buff[0];
 726        /*RT_TRACE(COMP_SEND, DebugLevel,
 727                        ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
 728
 729        /* 4. Check every received command packet conent according to different
 730              element type. Because FW may aggregate RX command packet to minimize
 731              transmit time between DRV and FW.*/
 732        // Add a counter to prevent to locked in the loop too long
 733        while (total_length > 0 || exe_cnt++ >100)
 734        {
 735                /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
 736                element_id = pcmd_buff[0];
 737
 738                switch(element_id)
 739                {
 740                        case RX_TX_FEEDBACK:
 741
 742                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_FEEDBACK\n");
 743                                cmpk_handle_tx_feedback (dev, pcmd_buff);
 744                                cmd_length = CMPK_RX_TX_FB_SIZE;
 745                                break;
 746
 747                        case RX_INTERRUPT_STATUS:
 748
 749                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_INTERRUPT_STATUS\n");
 750                                cmpk_handle_interrupt_status(dev, pcmd_buff);
 751                                cmd_length = sizeof(cmpk_intr_sta_t);
 752                                break;
 753
 754                        case BOTH_QUERY_CONFIG:
 755
 756                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():BOTH_QUERY_CONFIG\n");
 757                                cmpk_handle_query_config_rx(dev, pcmd_buff);
 758                                cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
 759                                break;
 760
 761                        case RX_TX_STATUS:
 762
 763                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_STATUS\n");
 764                                cmpk_handle_tx_status(dev, pcmd_buff);
 765                                cmd_length = CMPK_RX_TX_STS_SIZE;
 766                                break;
 767
 768                        case RX_TX_PER_PKT_FEEDBACK:
 769                                // You must at lease add a switch case element here,
 770                                // Otherwise, we will jump to default case.
 771                                //DbgPrint("CCX Test\r\n");
 772                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_PER_PKT_FEEDBACK\n");
 773                                cmd_length = CMPK_RX_TX_FB_SIZE;
 774                                break;
 775
 776                        case RX_TX_RATE_HISTORY:
 777                                //DbgPrint(" rx tx rate history\r\n");
 778
 779                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_HISTORY\n");
 780                                cmpk_handle_tx_rate_history(dev, pcmd_buff);
 781                                cmd_length = CMPK_TX_RAHIS_SIZE;
 782                                break;
 783
 784                        default:
 785
 786                                RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():unknow CMD Element\n");
 787                                return 1;       /* This is a command packet. */
 788                }
 789                // 2007/01/22 MH Display received rx command packet info.
 790                //cmpk_Display_Message(cmd_length, pcmd_buff);
 791
 792                // 2007/01/22 MH Add to display tx statistic.
 793                //cmpk_DisplayTxStatistic(pAdapter);
 794
 795                /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
 796                priv->stats.rxcmdpkt[element_id]++;
 797
 798                total_length -= cmd_length;
 799                pcmd_buff    += cmd_length;
 800        }       /* while (total_length > 0) */
 801        return  1;      /* This is a command packet. */
 802
 803        RT_TRACE(COMP_EVENTS, "<----cmpk_message_handle_rx()\n");
 804}       /* CMPK_Message_Handle_Rx */
 805