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