e2ba93e307578c4507daec1f816fc2cbc56d6f7b
[safe/jmp/linux-2.6] / drivers / staging / rtl8192su / r819xU_cmdpkt.c
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
41 bool
42 SendTxCommandPacket(
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  *---------------------------------------------------------------------------*/
131 static  void
132 cmpk_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  *---------------------------------------------------------------------------*/
231 static  void
232 cmpk_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
260 void
261 cmdpkt_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  *---------------------------------------------------------------------------*/
313 static  void
314 cmpk_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  *---------------------------------------------------------------------------*/
394 static  void
395 cmpk_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  *---------------------------------------------------------------------------*/
440 static  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  *---------------------------------------------------------------------------*/
507 static  void
508 cmpk_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  *---------------------------------------------------------------------------*/
537 static  void
538 cmpk_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  *---------------------------------------------------------------------------*/
621 extern  u32
622 cmpk_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 */