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