r819xU_cmdpkt.c revision 589b3d06fd159774f9f5c3639d8d5d938670c019
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
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);
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 *---------------------------------------------------------------------------*/
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. */
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
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	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