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