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