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