Merge branch 'topic/aloop' into topic/misc
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rtl8192u / r819xU_cmdpkt.c
CommitLineData
8fc8598e
JC
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.
e406322b
MCC
8 1. TX : Send set and query configuration command packet.
9 2. RX : Receive tx feedback, beacon state, query configuration
10 command packet.
8fc8598e
JC
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
41rt_status
42SendTxCommandPacket(
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;
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);
8fc8598e
JC
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 *---------------------------------------------------------------------------*/
102 extern rt_status cmpk_message_handle_tx(
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);
114 u16 frag_threshold;
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
e406322b 160 * and pending zero
8fc8598e
JC
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 *---------------------------------------------------------------------------*/
203static void
204cmpk_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 *---------------------------------------------------------------------------*/
303static void
304cmpk_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. */
8fc8598e
JC
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);
8fc8598e
JC
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
333void
334cmdpkt_beacontimerinterrupt_819xusb(
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 *---------------------------------------------------------------------------*/
386static void
387cmpk_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 {
435 cmdpkt_beacontimerinterrupt_819xusb(dev);
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 *---------------------------------------------------------------------------*/
467static void
468cmpk_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 *---------------------------------------------------------------------------*/
513static 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 *---------------------------------------------------------------------------*/
580static void
581cmpk_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 *---------------------------------------------------------------------------*/
610static void
611cmpk_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 *---------------------------------------------------------------------------*/
694extern u32
695cmpk_message_handle_rx(
696 struct net_device *dev,
697 struct ieee80211_rx_stats *pstats)
698{
699// u32 debug_level = DBG_LOUD;
700 struct r8192_priv *priv = ieee80211_priv(dev);
701 int total_length;
702 u8 cmd_length, exe_cnt = 0;
703 u8 element_id;
704 u8 *pcmd_buff;
705
706 /* 0. Check inpt arguments. If is is a command queue message or pointer is
707 null. */
708 if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
709 {
710 /* Print error message. */
711 /*RT_TRACE(COMP_SEND, DebugLevel,
712 ("\n\r[CMPK]-->Err queue id or pointer"));*/
713 return 0; /* This is not a command packet. */
714 }
715
716 /* 1. Read received command packet message length from RFD. */
717 total_length = pstats->Length;
718
719 /* 2. Read virtual address from RFD. */
720 pcmd_buff = pstats->virtual_address;
721
722 /* 3. Read command pakcet element id and length. */
723 element_id = pcmd_buff[0];
724 /*RT_TRACE(COMP_SEND, DebugLevel,
725 ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
726
727 /* 4. Check every received command packet conent according to different
728 element type. Because FW may aggregate RX command packet to minimize
729 transmit time between DRV and FW.*/
730 // Add a counter to prevent to locked in the loop too long
731 while (total_length > 0 || exe_cnt++ >100)
732 {
733 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
734 element_id = pcmd_buff[0];
735
736 switch(element_id)
737 {
738 case RX_TX_FEEDBACK:
739 cmpk_handle_tx_feedback (dev, pcmd_buff);
740 cmd_length = CMPK_RX_TX_FB_SIZE;
741 break;
742
743 case RX_INTERRUPT_STATUS:
744 cmpk_handle_interrupt_status(dev, pcmd_buff);
745 cmd_length = sizeof(cmpk_intr_sta_t);
746 break;
747
748 case BOTH_QUERY_CONFIG:
749 cmpk_handle_query_config_rx(dev, pcmd_buff);
750 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
751 break;
752
753 case RX_TX_STATUS:
754 cmpk_handle_tx_status(dev, pcmd_buff);
755 cmd_length = CMPK_RX_TX_STS_SIZE;
756 break;
757
758 case RX_TX_PER_PKT_FEEDBACK:
759 // You must at lease add a switch case element here,
760 // Otherwise, we will jump to default case.
761 //DbgPrint("CCX Test\r\n");
762 cmd_length = CMPK_RX_TX_FB_SIZE;
763 break;
764
765 case RX_TX_RATE_HISTORY:
766 //DbgPrint(" rx tx rate history\r\n");
767 cmpk_handle_tx_rate_history(dev, pcmd_buff);
768 cmd_length = CMPK_TX_RAHIS_SIZE;
769 break;
770
771 default:
772
e406322b 773 RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n");
8fc8598e
JC
774 return 1; /* This is a command packet. */
775 }
776 // 2007/01/22 MH Display received rx command packet info.
777 //cmpk_Display_Message(cmd_length, pcmd_buff);
778
779 // 2007/01/22 MH Add to display tx statistic.
780 //cmpk_DisplayTxStatistic(pAdapter);
781
782 /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
783 priv->stats.rxcmdpkt[element_id]++;
784
785 total_length -= cmd_length;
786 pcmd_buff += cmd_length;
787 } /* while (total_length > 0) */
788 return 1; /* This is a command packet. */
789
790} /* CMPK_Message_Handle_Rx */