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