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