1 /******************************************************************************
3 (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
5 Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File)
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
21 05/06/2008 amy Create initial version porting from windows driver.
23 ******************************************************************************/
25 #include "r819xU_cmdpkt.h"
26 /*---------------------------Define Local Constant---------------------------*/
28 #define CMPK_DEBOUNCE_CNT 1
29 /* 2007/10/24 MH Add for printing a range of data. */
30 #define CMPK_PRINT(Address)\
35 memcpy(temp, Address, 40);\
36 for (i = 0; i <40; i+=4)\
37 printk("\r\n %08x", temp[i]);\
39 /*---------------------------Define functions---------------------------------*/
43 struct net_device
*dev
,
49 struct r8192_priv
*priv
= ieee80211_priv(dev
);
52 unsigned char *ptr_buf
;
53 //bool bLastInitPacket = false;
55 //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
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);
60 RT_TRACE(COMP_ERR
, "(%s): unable to alloc skb buffer\n",
65 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
66 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
67 tcb_desc
->queue_index
= TXCMD_QUEUE
;
68 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_NORMAL
;
69 tcb_desc
->bLastIniPkt
= 0;
70 skb_reserve(skb
, USB_HWDESC_HEADER_LEN
);
71 ptr_buf
= skb_put(skb
, DataLen
);
72 memset(ptr_buf
,0,DataLen
);
73 memcpy(ptr_buf
,pData
,DataLen
);
74 tcb_desc
->txbuf_size
= (u16
)DataLen
;
76 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
77 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
78 (priv
->ieee80211
->queue_stop
) ) {
79 RT_TRACE(COMP_FIRMWARE
,"===================NULL packet==================================> tx full!\n");
80 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
82 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
85 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
89 /*-----------------------------------------------------------------------------
90 * Function: cmpk_message_handle_tx()
92 * Overview: Driver internal module can call the API to send message to
93 * firmware side. For example, you can send a debug command packet.
94 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
95 * Otherwise, you can change MAC/PHT/RF register by firmware at
96 * run time. We do not support message more than one segment now.
106 * 05/06/2008 amy porting from windows code.
108 *---------------------------------------------------------------------------*/
109 extern bool cmpk_message_handle_tx(
110 struct net_device
*dev
,
111 u8
* codevirtualaddress
,
116 bool rt_status
= true;
118 } /* CMPK_Message_Handle_Tx */
120 /*-----------------------------------------------------------------------------
121 * Function: cmpk_counttxstatistic()
125 * Input: PADAPTER pAdapter - .
126 * CMPK_TXFB_T *psTx_FB - .
134 * 05/12/2008 amy Create Version 0 porting from windows code.
136 *---------------------------------------------------------------------------*/
138 cmpk_count_txstatistic(
139 struct net_device
*dev
,
140 cmpk_txfb_t
*pstx_fb
)
142 struct r8192_priv
*priv
= ieee80211_priv(dev
);
144 RT_RF_POWER_STATE rtState
;
146 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
148 // When RF is off, we should not count the packet for hw/sw synchronize
149 // reason, ie. there may be a duration while sw switch is changed and hw
150 // switch is being changed. 2006.12.04, by shien chang.
151 if (rtState
== eRfOff
)
158 if(pAdapter
->bInHctTest
)
161 /* We can not know the packet length and transmit type: broadcast or uni
162 or multicast. So the relative statistics must be collected in tx
166 priv
->stats
.txfeedbackok
++;
167 priv
->stats
.txoktotal
++;
168 priv
->stats
.txokbytestotal
+= pstx_fb
->pkt_length
;
169 priv
->stats
.txokinperiod
++;
171 /* We can not make sure broadcast/multicast or unicast mode. */
172 if (pstx_fb
->pkt_type
== PACKET_MULTICAST
)
174 priv
->stats
.txmulticast
++;
175 priv
->stats
.txbytesmulticast
+= pstx_fb
->pkt_length
;
177 else if (pstx_fb
->pkt_type
== PACKET_BROADCAST
)
179 priv
->stats
.txbroadcast
++;
180 priv
->stats
.txbytesbroadcast
+= pstx_fb
->pkt_length
;
184 priv
->stats
.txunicast
++;
185 priv
->stats
.txbytesunicast
+= pstx_fb
->pkt_length
;
190 priv
->stats
.txfeedbackfail
++;
191 priv
->stats
.txerrtotal
++;
192 priv
->stats
.txerrbytestotal
+= pstx_fb
->pkt_length
;
194 /* We can not make sure broadcast/multicast or unicast mode. */
195 if (pstx_fb
->pkt_type
== PACKET_MULTICAST
)
197 priv
->stats
.txerrmulticast
++;
199 else if (pstx_fb
->pkt_type
== PACKET_BROADCAST
)
201 priv
->stats
.txerrbroadcast
++;
205 priv
->stats
.txerrunicast
++;
209 priv
->stats
.txretrycount
+= pstx_fb
->retry_cnt
;
210 priv
->stats
.txfeedbackretry
+= pstx_fb
->retry_cnt
;
212 } /* cmpk_CountTxStatistic */
216 /*-----------------------------------------------------------------------------
217 * Function: cmpk_handle_tx_feedback()
219 * Overview: The function is responsible for extract the message inside TX
220 * feedbck message from firmware. It will contain dedicated info in
221 * ws-06-0063-rtl8190-command-packet-specification. Please
222 * refer to chapter "TX Feedback Element". We have to read 20 bytes
223 * in the command packet.
225 * Input: struct net_device * dev
226 * u8 * pmsg - Msg Ptr of the command packet.
234 * 05/08/2008 amy Create Version 0 porting from windows code.
236 *---------------------------------------------------------------------------*/
238 cmpk_handle_tx_feedback(
239 struct net_device
*dev
,
242 struct r8192_priv
*priv
= ieee80211_priv(dev
);
243 cmpk_txfb_t rx_tx_fb
; /* */
245 priv
->stats
.txfeedback
++;
247 /* 0. Display received message. */
248 //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
250 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
252 /* 2007/07/05 MH Use pointer to transfer structure memory. */
253 //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
254 memcpy((u8
*)&rx_tx_fb
, pmsg
, sizeof(cmpk_txfb_t
));
255 /* 2. Use tx feedback info to count TX statistics. */
256 cmpk_count_txstatistic(dev
, &rx_tx_fb
);
258 /* 2007/01/17 MH Comment previous method for TX statistic function. */
259 /* Collect info TX feedback packet to fill TCB. */
260 /* We can not know the packet length and transmit type: broadcast or uni
262 //CountTxStatistics( pAdapter, &tcb );
264 } /* cmpk_Handle_Tx_Feedback */
267 cmdpkt_beacontimerinterrupt_819xusb(
268 struct net_device
*dev
271 struct r8192_priv
*priv
= ieee80211_priv(dev
);
275 // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
277 if(priv
->ieee80211
->current_network
.mode
== IEEE_A
||
278 priv
->ieee80211
->current_network
.mode
== IEEE_N_5G
||
279 (priv
->ieee80211
->current_network
.mode
== IEEE_N_24G
&& (!priv
->ieee80211
->pHTInfo
->bCurSuppCCK
)))
282 DMESG("send beacon frame tx rate is 6Mbpm\n");
287 DMESG("send beacon frame tx rate is 1Mbpm\n");
290 rtl819xusb_beacon_tx(dev
,tx_rate
); // HW Beacon
299 /*-----------------------------------------------------------------------------
300 * Function: cmpk_handle_interrupt_status()
302 * Overview: The function is responsible for extract the message from
303 * firmware. It will contain dedicated info in
304 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
305 * Please refer to chapter "Interrupt Status Element".
307 * Input: struct net_device *dev,
308 * u8* pmsg - Message Pointer of the command packet.
316 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
318 *---------------------------------------------------------------------------*/
320 cmpk_handle_interrupt_status(
321 struct net_device
*dev
,
324 cmpk_intr_sta_t rx_intr_status
; /* */
325 struct r8192_priv
*priv
= ieee80211_priv(dev
);
327 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
329 /* 0. Display received message. */
330 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
332 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
333 /* It seems that FW use big endian(MIPS) and DRV use little endian in
334 windows OS. So we have to read the content byte by byte or transfer
335 endian type before copy the message copy. */
336 //rx_bcn_state.Element_ID = pMsg[0];
337 //rx_bcn_state.Length = pMsg[1];
338 rx_intr_status
.length
= pmsg
[1];
339 if (rx_intr_status
.length
!= (sizeof(cmpk_intr_sta_t
) - 2))
341 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
346 // Statistics of beacon for ad-hoc mode.
347 if( priv
->ieee80211
->iw_mode
== IW_MODE_ADHOC
)
349 //2 maybe need endian transform?
350 rx_intr_status
.interrupt_status
= *((u32
*)(pmsg
+ 4));
351 //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
353 DMESG("interrupt status = 0x%x\n", rx_intr_status
.interrupt_status
);
355 if (rx_intr_status
.interrupt_status
& ISR_TxBcnOk
)
357 priv
->ieee80211
->bibsscoordinator
= true;
358 priv
->stats
.txbeaconokint
++;
360 else if (rx_intr_status
.interrupt_status
& ISR_TxBcnErr
)
362 priv
->ieee80211
->bibsscoordinator
= false;
363 priv
->stats
.txbeaconerr
++;
366 if (rx_intr_status
.interrupt_status
& ISR_BcnTimerIntr
)
368 cmdpkt_beacontimerinterrupt_819xusb(dev
);
373 // Other informations in interrupt status we need?
376 DMESG("<---- cmpk_handle_interrupt_status()\n");
378 } /* cmpk_handle_interrupt_status */
381 /*-----------------------------------------------------------------------------
382 * Function: cmpk_handle_query_config_rx()
384 * Overview: The function is responsible for extract the message from
385 * firmware. It will contain dedicated info in
386 * ws-06-0063-rtl8190-command-packet-specification. Please
387 * refer to chapter "Beacon State Element".
389 * Input: u8 * pmsg - Message Pointer of the command packet.
397 * 05/12/2008 amy Create Version 0 porting from windows code.
399 *---------------------------------------------------------------------------*/
401 cmpk_handle_query_config_rx(
402 struct net_device
*dev
,
405 cmpk_query_cfg_t rx_query_cfg
; /* */
407 /* 0. Display received message. */
408 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
410 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
411 /* It seems that FW use big endian(MIPS) and DRV use little endian in
412 windows OS. So we have to read the content byte by byte or transfer
413 endian type before copy the message copy. */
414 //rx_query_cfg.Element_ID = pMsg[0];
415 //rx_query_cfg.Length = pMsg[1];
416 rx_query_cfg
.cfg_action
= (pmsg
[4] & 0x80000000)>>31;
417 rx_query_cfg
.cfg_type
= (pmsg
[4] & 0x60) >> 5;
418 rx_query_cfg
.cfg_size
= (pmsg
[4] & 0x18) >> 3;
419 rx_query_cfg
.cfg_page
= (pmsg
[6] & 0x0F) >> 0;
420 rx_query_cfg
.cfg_offset
= pmsg
[7];
421 rx_query_cfg
.value
= (pmsg
[8] << 24) | (pmsg
[9] << 16) |
422 (pmsg
[10] << 8) | (pmsg
[11] << 0);
423 rx_query_cfg
.mask
= (pmsg
[12] << 24) | (pmsg
[13] << 16) |
424 (pmsg
[14] << 8) | (pmsg
[15] << 0);
426 } /* cmpk_Handle_Query_Config_Rx */
429 /*-----------------------------------------------------------------------------
430 * Function: cmpk_count_tx_status()
432 * Overview: Count aggregated tx status from firmwar of one type rx command
433 * packet element id = RX_TX_STATUS.
443 * 05/12/2008 amy Create Version 0 porting from windows code.
445 *---------------------------------------------------------------------------*/
446 static void cmpk_count_tx_status( struct net_device
*dev
,
447 cmpk_tx_status_t
*pstx_status
)
449 struct r8192_priv
*priv
= ieee80211_priv(dev
);
453 RT_RF_POWER_STATE rtstate
;
455 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
457 // When RF is off, we should not count the packet for hw/sw synchronize
458 // reason, ie. there may be a duration while sw switch is changed and hw
459 // switch is being changed. 2006.12.04, by shien chang.
460 if (rtState
== eRfOff
)
466 priv
->stats
.txfeedbackok
+= pstx_status
->txok
;
467 priv
->stats
.txoktotal
+= pstx_status
->txok
;
469 priv
->stats
.txfeedbackfail
+= pstx_status
->txfail
;
470 priv
->stats
.txerrtotal
+= pstx_status
->txfail
;
472 priv
->stats
.txretrycount
+= pstx_status
->txretry
;
473 priv
->stats
.txfeedbackretry
+= pstx_status
->txretry
;
475 //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
476 //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
477 //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
479 priv
->stats
.txmulticast
+= pstx_status
->txmcok
;
480 priv
->stats
.txbroadcast
+= pstx_status
->txbcok
;
481 priv
->stats
.txunicast
+= pstx_status
->txucok
;
483 priv
->stats
.txerrmulticast
+= pstx_status
->txmcfail
;
484 priv
->stats
.txerrbroadcast
+= pstx_status
->txbcfail
;
485 priv
->stats
.txerrunicast
+= pstx_status
->txucfail
;
487 priv
->stats
.txbytesmulticast
+= pstx_status
->txmclength
;
488 priv
->stats
.txbytesbroadcast
+= pstx_status
->txbclength
;
489 priv
->stats
.txbytesunicast
+= pstx_status
->txuclength
;
491 priv
->stats
.last_packet_rate
= pstx_status
->rate
;
492 } /* cmpk_CountTxStatus */
496 /*-----------------------------------------------------------------------------
497 * Function: cmpk_handle_tx_status()
499 * Overview: Firmware add a new tx feedback status to reduce rx command
500 * packet buffer operation load.
510 * 05/12/2008 amy Create Version 0 porting from windows code.
512 *---------------------------------------------------------------------------*/
514 cmpk_handle_tx_status(
515 struct net_device
*dev
,
518 cmpk_tx_status_t rx_tx_sts
; /* */
520 memcpy((void*)&rx_tx_sts
, (void*)pmsg
, sizeof(cmpk_tx_status_t
));
521 /* 2. Use tx feedback info to count TX statistics. */
522 cmpk_count_tx_status(dev
, &rx_tx_sts
);
524 } /* cmpk_Handle_Tx_Status */
527 /*-----------------------------------------------------------------------------
528 * Function: cmpk_handle_tx_rate_history()
530 * Overview: Firmware add a new tx rate history
540 * 05/12/2008 amy Create Version 0 porting from windows code.
542 *---------------------------------------------------------------------------*/
544 cmpk_handle_tx_rate_history(
545 struct net_device
*dev
,
548 cmpk_tx_rahis_t
*ptxrate
;
549 // RT_RF_POWER_STATE rtState;
551 u16 length
= sizeof(cmpk_tx_rahis_t
);
553 struct r8192_priv
*priv
= ieee80211_priv(dev
);
557 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
559 // When RF is off, we should not count the packet for hw/sw synchronize
560 // reason, ie. there may be a duration while sw switch is changed and hw
561 // switch is being changed. 2006.12.04, by shien chang.
562 if (rtState
== eRfOff
)
571 // Do endian transfer to word alignment(16 bits) for windows system.
572 // You must do different endian transfer for linux and MAC OS
574 for (i
= 0; i
< (length
/4); i
++)
578 temp1
= ptemp
[i
]&0x0000FFFF;
579 temp2
= ptemp
[i
]>>16;
580 ptemp
[i
] = (temp1
<<16)|temp2
;
583 ptxrate
= (cmpk_tx_rahis_t
*)pmsg
;
585 if (ptxrate
== NULL
)
590 for (i
= 0; i
< 16; i
++)
592 // Collect CCK rate packet num
594 priv
->stats
.txrate
.cck
[i
] += ptxrate
->cck
[i
];
596 // Collect OFDM rate packet num
598 priv
->stats
.txrate
.ofdm
[i
] += ptxrate
->ofdm
[i
];
600 for (j
= 0; j
< 4; j
++)
601 priv
->stats
.txrate
.ht_mcs
[j
][i
] += ptxrate
->ht_mcs
[j
][i
];
604 } /* cmpk_Handle_Tx_Rate_History */
607 /*-----------------------------------------------------------------------------
608 * Function: cmpk_message_handle_rx()
610 * Overview: In the function, we will capture different RX command packet
611 * info. Every RX command packet element has different message
612 * length and meaning in content. We only support three type of RX
613 * command packet now. Please refer to document
614 * ws-06-0063-rtl8190-command-packet-specification.
624 * 05/06/2008 amy Create Version 0 porting from windows code.
626 *---------------------------------------------------------------------------*/
628 cmpk_message_handle_rx(
629 struct net_device
*dev
,
630 struct ieee80211_rx_stats
*pstats
)
632 // u32 debug_level = DBG_LOUD;
633 struct r8192_priv
*priv
= ieee80211_priv(dev
);
635 u8 cmd_length
, exe_cnt
= 0;
639 /* 0. Check inpt arguments. If is is a command queue message or pointer is
641 if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats
== NULL
))
643 /* Print error message. */
644 /*RT_TRACE(COMP_SEND, DebugLevel,
645 ("\n\r[CMPK]-->Err queue id or pointer"));*/
646 return 0; /* This is not a command packet. */
649 /* 1. Read received command packet message length from RFD. */
650 total_length
= pstats
->Length
;
652 /* 2. Read virtual address from RFD. */
653 pcmd_buff
= pstats
->virtual_address
;
655 /* 3. Read command pakcet element id and length. */
656 element_id
= pcmd_buff
[0];
657 /*RT_TRACE(COMP_SEND, DebugLevel,
658 ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
660 /* 4. Check every received command packet conent according to different
661 element type. Because FW may aggregate RX command packet to minimize
662 transmit time between DRV and FW.*/
663 // Add a counter to prevent to locked in the loop too long
664 while (total_length
> 0 || exe_cnt
++ >100)
666 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
667 element_id
= pcmd_buff
[0];
672 cmpk_handle_tx_feedback (dev
, pcmd_buff
);
673 cmd_length
= CMPK_RX_TX_FB_SIZE
;
676 case RX_INTERRUPT_STATUS
:
677 cmpk_handle_interrupt_status(dev
, pcmd_buff
);
678 cmd_length
= sizeof(cmpk_intr_sta_t
);
681 case BOTH_QUERY_CONFIG
:
682 cmpk_handle_query_config_rx(dev
, pcmd_buff
);
683 cmd_length
= CMPK_BOTH_QUERY_CONFIG_SIZE
;
687 cmpk_handle_tx_status(dev
, pcmd_buff
);
688 cmd_length
= CMPK_RX_TX_STS_SIZE
;
691 case RX_TX_PER_PKT_FEEDBACK
:
692 // You must at lease add a switch case element here,
693 // Otherwise, we will jump to default case.
694 //DbgPrint("CCX Test\r\n");
695 cmd_length
= CMPK_RX_TX_FB_SIZE
;
698 case RX_TX_RATE_HISTORY
:
699 //DbgPrint(" rx tx rate history\r\n");
700 cmpk_handle_tx_rate_history(dev
, pcmd_buff
);
701 cmd_length
= CMPK_TX_RAHIS_SIZE
;
706 RT_TRACE(COMP_ERR
, "---->cmpk_message_handle_rx():unknow CMD Element\n");
707 return 1; /* This is a command packet. */
709 // 2007/01/22 MH Display received rx command packet info.
710 //cmpk_Display_Message(cmd_length, pcmd_buff);
712 // 2007/01/22 MH Add to display tx statistic.
713 //cmpk_DisplayTxStatistic(pAdapter);
715 /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
716 priv
->stats
.rxcmdpkt
[element_id
]++;
718 total_length
-= cmd_length
;
719 pcmd_buff
+= cmd_length
;
720 } /* while (total_length > 0) */
721 return 1; /* This is a command packet. */
723 } /* CMPK_Message_Handle_Rx */