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