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);
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 memset(ptr_buf
,0,DataLen
);
67 memcpy(ptr_buf
,pData
,DataLen
);
68 tcb_desc
->txbuf_size
= (u16
)DataLen
;
70 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
71 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
72 (priv
->ieee80211
->queue_stop
) ) {
73 RT_TRACE(COMP_FIRMWARE
,"===================NULL packet==================================> tx full!\n");
74 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
76 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
79 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
83 /*-----------------------------------------------------------------------------
84 * Function: cmpk_message_handle_tx()
86 * Overview: Driver internal module can call the API to send message to
87 * firmware side. For example, you can send a debug command packet.
88 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
89 * Otherwise, you can change MAC/PHT/RF register by firmware at
90 * run time. We do not support message more than one segment now.
100 * 05/06/2008 amy porting from windows code.
102 *---------------------------------------------------------------------------*/
103 extern bool cmpk_message_handle_tx(
104 struct net_device
*dev
,
105 u8
* codevirtualaddress
,
110 bool rt_status
= true;
112 } /* CMPK_Message_Handle_Tx */
114 /*-----------------------------------------------------------------------------
115 * Function: cmpk_counttxstatistic()
119 * Input: PADAPTER pAdapter - .
120 * CMPK_TXFB_T *psTx_FB - .
128 * 05/12/2008 amy Create Version 0 porting from windows code.
130 *---------------------------------------------------------------------------*/
132 cmpk_count_txstatistic(
133 struct net_device
*dev
,
134 cmpk_txfb_t
*pstx_fb
)
136 struct r8192_priv
*priv
= ieee80211_priv(dev
);
138 RT_RF_POWER_STATE rtState
;
140 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
142 // When RF is off, we should not count the packet for hw/sw synchronize
143 // reason, ie. there may be a duration while sw switch is changed and hw
144 // switch is being changed. 2006.12.04, by shien chang.
145 if (rtState
== eRfOff
)
152 if(pAdapter
->bInHctTest
)
155 /* We can not know the packet length and transmit type: broadcast or uni
156 or multicast. So the relative statistics must be collected in tx
160 priv
->stats
.txfeedbackok
++;
161 priv
->stats
.txoktotal
++;
162 priv
->stats
.txokbytestotal
+= pstx_fb
->pkt_length
;
163 priv
->stats
.txokinperiod
++;
165 /* We can not make sure broadcast/multicast or unicast mode. */
166 if (pstx_fb
->pkt_type
== PACKET_MULTICAST
)
168 priv
->stats
.txmulticast
++;
169 priv
->stats
.txbytesmulticast
+= pstx_fb
->pkt_length
;
171 else if (pstx_fb
->pkt_type
== PACKET_BROADCAST
)
173 priv
->stats
.txbroadcast
++;
174 priv
->stats
.txbytesbroadcast
+= pstx_fb
->pkt_length
;
178 priv
->stats
.txunicast
++;
179 priv
->stats
.txbytesunicast
+= pstx_fb
->pkt_length
;
184 priv
->stats
.txfeedbackfail
++;
185 priv
->stats
.txerrtotal
++;
186 priv
->stats
.txerrbytestotal
+= pstx_fb
->pkt_length
;
188 /* We can not make sure broadcast/multicast or unicast mode. */
189 if (pstx_fb
->pkt_type
== PACKET_MULTICAST
)
191 priv
->stats
.txerrmulticast
++;
193 else if (pstx_fb
->pkt_type
== PACKET_BROADCAST
)
195 priv
->stats
.txerrbroadcast
++;
199 priv
->stats
.txerrunicast
++;
203 priv
->stats
.txretrycount
+= pstx_fb
->retry_cnt
;
204 priv
->stats
.txfeedbackretry
+= pstx_fb
->retry_cnt
;
206 } /* cmpk_CountTxStatistic */
210 /*-----------------------------------------------------------------------------
211 * Function: cmpk_handle_tx_feedback()
213 * Overview: The function is responsible for extract the message inside TX
214 * feedbck message from firmware. It will contain dedicated info in
215 * ws-06-0063-rtl8190-command-packet-specification. Please
216 * refer to chapter "TX Feedback Element". We have to read 20 bytes
217 * in the command packet.
219 * Input: struct net_device * dev
220 * u8 * pmsg - Msg Ptr of the command packet.
228 * 05/08/2008 amy Create Version 0 porting from windows code.
230 *---------------------------------------------------------------------------*/
232 cmpk_handle_tx_feedback(
233 struct net_device
*dev
,
236 struct r8192_priv
*priv
= ieee80211_priv(dev
);
237 cmpk_txfb_t rx_tx_fb
; /* */
239 priv
->stats
.txfeedback
++;
241 /* 0. Display received message. */
242 //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
244 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
246 /* 2007/07/05 MH Use pointer to transfer structure memory. */
247 //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
248 memcpy((u8
*)&rx_tx_fb
, pmsg
, sizeof(cmpk_txfb_t
));
249 /* 2. Use tx feedback info to count TX statistics. */
250 cmpk_count_txstatistic(dev
, &rx_tx_fb
);
252 /* 2007/01/17 MH Comment previous method for TX statistic function. */
253 /* Collect info TX feedback packet to fill TCB. */
254 /* We can not know the packet length and transmit type: broadcast or uni
256 //CountTxStatistics( pAdapter, &tcb );
258 } /* cmpk_Handle_Tx_Feedback */
261 cmdpkt_beacontimerinterrupt_819xusb(
262 struct net_device
*dev
265 struct r8192_priv
*priv
= ieee80211_priv(dev
);
269 // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
271 if(priv
->ieee80211
->current_network
.mode
== IEEE_A
||
272 priv
->ieee80211
->current_network
.mode
== IEEE_N_5G
||
273 (priv
->ieee80211
->current_network
.mode
== IEEE_N_24G
&& (!priv
->ieee80211
->pHTInfo
->bCurSuppCCK
)))
276 DMESG("send beacon frame tx rate is 6Mbpm\n");
281 DMESG("send beacon frame tx rate is 1Mbpm\n");
284 rtl819xusb_beacon_tx(dev
,tx_rate
); // HW Beacon
293 /*-----------------------------------------------------------------------------
294 * Function: cmpk_handle_interrupt_status()
296 * Overview: The function is responsible for extract the message from
297 * firmware. It will contain dedicated info in
298 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
299 * Please refer to chapter "Interrupt Status Element".
301 * Input: struct net_device *dev,
302 * u8* pmsg - Message Pointer of the command packet.
310 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
312 *---------------------------------------------------------------------------*/
314 cmpk_handle_interrupt_status(
315 struct net_device
*dev
,
318 cmpk_intr_sta_t rx_intr_status
; /* */
319 struct r8192_priv
*priv
= ieee80211_priv(dev
);
321 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
323 /* 0. Display received message. */
324 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
326 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
327 /* It seems that FW use big endian(MIPS) and DRV use little endian in
328 windows OS. So we have to read the content byte by byte or transfer
329 endian type before copy the message copy. */
330 //rx_bcn_state.Element_ID = pMsg[0];
331 //rx_bcn_state.Length = pMsg[1];
332 rx_intr_status
.length
= pmsg
[1];
333 if (rx_intr_status
.length
!= (sizeof(cmpk_intr_sta_t
) - 2))
335 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
340 // Statistics of beacon for ad-hoc mode.
341 if( priv
->ieee80211
->iw_mode
== IW_MODE_ADHOC
)
343 //2 maybe need endian transform?
344 rx_intr_status
.interrupt_status
= *((u32
*)(pmsg
+ 4));
345 //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
347 DMESG("interrupt status = 0x%x\n", rx_intr_status
.interrupt_status
);
349 if (rx_intr_status
.interrupt_status
& ISR_TxBcnOk
)
351 priv
->ieee80211
->bibsscoordinator
= true;
352 priv
->stats
.txbeaconokint
++;
354 else if (rx_intr_status
.interrupt_status
& ISR_TxBcnErr
)
356 priv
->ieee80211
->bibsscoordinator
= false;
357 priv
->stats
.txbeaconerr
++;
360 if (rx_intr_status
.interrupt_status
& ISR_BcnTimerIntr
)
362 cmdpkt_beacontimerinterrupt_819xusb(dev
);
367 // Other informations in interrupt status we need?
370 DMESG("<---- cmpk_handle_interrupt_status()\n");
372 } /* cmpk_handle_interrupt_status */
375 /*-----------------------------------------------------------------------------
376 * Function: cmpk_handle_query_config_rx()
378 * Overview: The function is responsible for extract the message from
379 * firmware. It will contain dedicated info in
380 * ws-06-0063-rtl8190-command-packet-specification. Please
381 * refer to chapter "Beacon State Element".
383 * Input: u8 * pmsg - Message Pointer of the command packet.
391 * 05/12/2008 amy Create Version 0 porting from windows code.
393 *---------------------------------------------------------------------------*/
395 cmpk_handle_query_config_rx(
396 struct net_device
*dev
,
399 cmpk_query_cfg_t rx_query_cfg
; /* */
401 /* 0. Display received message. */
402 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
404 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
405 /* It seems that FW use big endian(MIPS) and DRV use little endian in
406 windows OS. So we have to read the content byte by byte or transfer
407 endian type before copy the message copy. */
408 //rx_query_cfg.Element_ID = pMsg[0];
409 //rx_query_cfg.Length = pMsg[1];
410 rx_query_cfg
.cfg_action
= (pmsg
[4] & 0x80000000)>>31;
411 rx_query_cfg
.cfg_type
= (pmsg
[4] & 0x60) >> 5;
412 rx_query_cfg
.cfg_size
= (pmsg
[4] & 0x18) >> 3;
413 rx_query_cfg
.cfg_page
= (pmsg
[6] & 0x0F) >> 0;
414 rx_query_cfg
.cfg_offset
= pmsg
[7];
415 rx_query_cfg
.value
= (pmsg
[8] << 24) | (pmsg
[9] << 16) |
416 (pmsg
[10] << 8) | (pmsg
[11] << 0);
417 rx_query_cfg
.mask
= (pmsg
[12] << 24) | (pmsg
[13] << 16) |
418 (pmsg
[14] << 8) | (pmsg
[15] << 0);
420 } /* cmpk_Handle_Query_Config_Rx */
423 /*-----------------------------------------------------------------------------
424 * Function: cmpk_count_tx_status()
426 * Overview: Count aggregated tx status from firmwar of one type rx command
427 * packet element id = RX_TX_STATUS.
437 * 05/12/2008 amy Create Version 0 porting from windows code.
439 *---------------------------------------------------------------------------*/
440 static void cmpk_count_tx_status( struct net_device
*dev
,
441 cmpk_tx_status_t
*pstx_status
)
443 struct r8192_priv
*priv
= ieee80211_priv(dev
);
447 RT_RF_POWER_STATE rtstate
;
449 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
451 // When RF is off, we should not count the packet for hw/sw synchronize
452 // reason, ie. there may be a duration while sw switch is changed and hw
453 // switch is being changed. 2006.12.04, by shien chang.
454 if (rtState
== eRfOff
)
460 priv
->stats
.txfeedbackok
+= pstx_status
->txok
;
461 priv
->stats
.txoktotal
+= pstx_status
->txok
;
463 priv
->stats
.txfeedbackfail
+= pstx_status
->txfail
;
464 priv
->stats
.txerrtotal
+= pstx_status
->txfail
;
466 priv
->stats
.txretrycount
+= pstx_status
->txretry
;
467 priv
->stats
.txfeedbackretry
+= pstx_status
->txretry
;
469 //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
470 //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
471 //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
473 priv
->stats
.txmulticast
+= pstx_status
->txmcok
;
474 priv
->stats
.txbroadcast
+= pstx_status
->txbcok
;
475 priv
->stats
.txunicast
+= pstx_status
->txucok
;
477 priv
->stats
.txerrmulticast
+= pstx_status
->txmcfail
;
478 priv
->stats
.txerrbroadcast
+= pstx_status
->txbcfail
;
479 priv
->stats
.txerrunicast
+= pstx_status
->txucfail
;
481 priv
->stats
.txbytesmulticast
+= pstx_status
->txmclength
;
482 priv
->stats
.txbytesbroadcast
+= pstx_status
->txbclength
;
483 priv
->stats
.txbytesunicast
+= pstx_status
->txuclength
;
485 priv
->stats
.last_packet_rate
= pstx_status
->rate
;
486 } /* cmpk_CountTxStatus */
490 /*-----------------------------------------------------------------------------
491 * Function: cmpk_handle_tx_status()
493 * Overview: Firmware add a new tx feedback status to reduce rx command
494 * packet buffer operation load.
504 * 05/12/2008 amy Create Version 0 porting from windows code.
506 *---------------------------------------------------------------------------*/
508 cmpk_handle_tx_status(
509 struct net_device
*dev
,
512 cmpk_tx_status_t rx_tx_sts
; /* */
514 memcpy((void*)&rx_tx_sts
, (void*)pmsg
, sizeof(cmpk_tx_status_t
));
515 /* 2. Use tx feedback info to count TX statistics. */
516 cmpk_count_tx_status(dev
, &rx_tx_sts
);
518 } /* cmpk_Handle_Tx_Status */
521 /*-----------------------------------------------------------------------------
522 * Function: cmpk_handle_tx_rate_history()
524 * Overview: Firmware add a new tx rate history
534 * 05/12/2008 amy Create Version 0 porting from windows code.
536 *---------------------------------------------------------------------------*/
538 cmpk_handle_tx_rate_history(
539 struct net_device
*dev
,
542 cmpk_tx_rahis_t
*ptxrate
;
543 // RT_RF_POWER_STATE rtState;
545 u16 length
= sizeof(cmpk_tx_rahis_t
);
547 struct r8192_priv
*priv
= ieee80211_priv(dev
);
551 pAdapter
->HalFunc
.GetHwRegHandler(pAdapter
, HW_VAR_RF_STATE
, (pu1Byte
)(&rtState
));
553 // When RF is off, we should not count the packet for hw/sw synchronize
554 // reason, ie. there may be a duration while sw switch is changed and hw
555 // switch is being changed. 2006.12.04, by shien chang.
556 if (rtState
== eRfOff
)
565 // Do endian transfer to word alignment(16 bits) for windows system.
566 // You must do different endian transfer for linux and MAC OS
568 for (i
= 0; i
< (length
/4); i
++)
572 temp1
= ptemp
[i
]&0x0000FFFF;
573 temp2
= ptemp
[i
]>>16;
574 ptemp
[i
] = (temp1
<<16)|temp2
;
577 ptxrate
= (cmpk_tx_rahis_t
*)pmsg
;
579 if (ptxrate
== NULL
)
584 for (i
= 0; i
< 16; i
++)
586 // Collect CCK rate packet num
588 priv
->stats
.txrate
.cck
[i
] += ptxrate
->cck
[i
];
590 // Collect OFDM rate packet num
592 priv
->stats
.txrate
.ofdm
[i
] += ptxrate
->ofdm
[i
];
594 for (j
= 0; j
< 4; j
++)
595 priv
->stats
.txrate
.ht_mcs
[j
][i
] += ptxrate
->ht_mcs
[j
][i
];
598 } /* cmpk_Handle_Tx_Rate_History */
601 /*-----------------------------------------------------------------------------
602 * Function: cmpk_message_handle_rx()
604 * Overview: In the function, we will capture different RX command packet
605 * info. Every RX command packet element has different message
606 * length and meaning in content. We only support three type of RX
607 * command packet now. Please refer to document
608 * ws-06-0063-rtl8190-command-packet-specification.
618 * 05/06/2008 amy Create Version 0 porting from windows code.
620 *---------------------------------------------------------------------------*/
622 cmpk_message_handle_rx(
623 struct net_device
*dev
,
624 struct ieee80211_rx_stats
*pstats
)
626 // u32 debug_level = DBG_LOUD;
627 struct r8192_priv
*priv
= ieee80211_priv(dev
);
629 u8 cmd_length
, exe_cnt
= 0;
633 /* 0. Check inpt arguments. If is is a command queue message or pointer is
635 if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats
== NULL
))
637 /* Print error message. */
638 /*RT_TRACE(COMP_SEND, DebugLevel,
639 ("\n\r[CMPK]-->Err queue id or pointer"));*/
640 return 0; /* This is not a command packet. */
643 /* 1. Read received command packet message length from RFD. */
644 total_length
= pstats
->Length
;
646 /* 2. Read virtual address from RFD. */
647 pcmd_buff
= pstats
->virtual_address
;
649 /* 3. Read command pakcet element id and length. */
650 element_id
= pcmd_buff
[0];
651 /*RT_TRACE(COMP_SEND, DebugLevel,
652 ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
654 /* 4. Check every received command packet conent according to different
655 element type. Because FW may aggregate RX command packet to minimize
656 transmit time between DRV and FW.*/
657 // Add a counter to prevent to locked in the loop too long
658 while (total_length
> 0 || exe_cnt
++ >100)
660 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
661 element_id
= pcmd_buff
[0];
666 cmpk_handle_tx_feedback (dev
, pcmd_buff
);
667 cmd_length
= CMPK_RX_TX_FB_SIZE
;
670 case RX_INTERRUPT_STATUS
:
671 cmpk_handle_interrupt_status(dev
, pcmd_buff
);
672 cmd_length
= sizeof(cmpk_intr_sta_t
);
675 case BOTH_QUERY_CONFIG
:
676 cmpk_handle_query_config_rx(dev
, pcmd_buff
);
677 cmd_length
= CMPK_BOTH_QUERY_CONFIG_SIZE
;
681 cmpk_handle_tx_status(dev
, pcmd_buff
);
682 cmd_length
= CMPK_RX_TX_STS_SIZE
;
685 case RX_TX_PER_PKT_FEEDBACK
:
686 // You must at lease add a switch case element here,
687 // Otherwise, we will jump to default case.
688 //DbgPrint("CCX Test\r\n");
689 cmd_length
= CMPK_RX_TX_FB_SIZE
;
692 case RX_TX_RATE_HISTORY
:
693 //DbgPrint(" rx tx rate history\r\n");
694 cmpk_handle_tx_rate_history(dev
, pcmd_buff
);
695 cmd_length
= CMPK_TX_RAHIS_SIZE
;
700 RT_TRACE(COMP_ERR
, "---->cmpk_message_handle_rx():unknow CMD Element\n");
701 return 1; /* This is a command packet. */
703 // 2007/01/22 MH Display received rx command packet info.
704 //cmpk_Display_Message(cmd_length, pcmd_buff);
706 // 2007/01/22 MH Add to display tx statistic.
707 //cmpk_DisplayTxStatistic(pAdapter);
709 /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
710 priv
->stats
.rxcmdpkt
[element_id
]++;
712 total_length
-= cmd_length
;
713 pcmd_buff
+= cmd_length
;
714 } /* while (total_length > 0) */
715 return 1; /* This is a command packet. */
717 } /* CMPK_Message_Handle_Rx */