Staging: drop redundant memset
[safe/jmp/linux-2.6] / drivers / staging / rtl8192u / 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 rt_status
42 SendTxCommandPacket(
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  *---------------------------------------------------------------------------*/
203 static  void
204 cmpk_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  *---------------------------------------------------------------------------*/
303 static  void
304 cmpk_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
333 void
334 cmdpkt_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  *---------------------------------------------------------------------------*/
386 static  void
387 cmpk_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  *---------------------------------------------------------------------------*/
467 static  void
468 cmpk_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  *---------------------------------------------------------------------------*/
513 static  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  *---------------------------------------------------------------------------*/
580 static  void
581 cmpk_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  *---------------------------------------------------------------------------*/
610 static  void
611 cmpk_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  *---------------------------------------------------------------------------*/
694 extern  u32
695 cmpk_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 */