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 rt_status
42 SendTxCommandPacket(
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);
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
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
334 cmdpkt_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  *---------------------------------------------------------------------------*/
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 		{
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  *---------------------------------------------------------------------------*/
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
695 cmpk_message_handle_rx(
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 to be to 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 
757 			case RX_TX_PER_PKT_FEEDBACK:
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 */
787