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