Full support for Ginger Console
[linux-ginger.git] / drivers / staging / rtl8192su / r819xU_cmdpkt.c
blobe2ba93e307578c4507daec1f816fc2cbc56d6f7b
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
10 command packet.
12 Function:
14 Export:
16 Abbrev:
18 History:
19 Data Who Remark
21 05/06/2008 amy Create initial version porting from windows driver.
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)\
32 unsigned char i;\
33 u32 temp[10];\
35 memcpy(temp, Address, 40);\
36 for (i = 0; i <40; i+=4)\
37 printk("\r\n %08x", temp[i]);\
39 /*---------------------------Define functions---------------------------------*/
41 bool
42 SendTxCommandPacket(
43 struct net_device *dev,
44 void* pData,
45 u32 DataLen
48 bool rtStatus = true;
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;
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);
75 } else {
76 priv->ieee80211->softmac_hard_start_xmit(skb,dev);
79 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
80 return rtStatus;
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.
92 * Input: NONE
94 * Output: NONE
96 * Return: NONE
98 * Revised History:
99 * When Who Remark
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,
106 u32 packettype,
107 u32 buffer_len)
110 bool rt_status = true;
111 return rt_status;
112 } /* CMPK_Message_Handle_Tx */
114 /*-----------------------------------------------------------------------------
115 * Function: cmpk_counttxstatistic()
117 * Overview:
119 * Input: PADAPTER pAdapter - .
120 * CMPK_TXFB_T *psTx_FB - .
122 * Output: NONE
124 * Return: NONE
126 * Revised History:
127 * When Who Remark
128 * 05/12/2008 amy Create Version 0 porting from windows code.
130 *---------------------------------------------------------------------------*/
131 static void
132 cmpk_count_txstatistic(
133 struct net_device *dev,
134 cmpk_txfb_t *pstx_fb)
136 struct r8192_priv *priv = ieee80211_priv(dev);
137 #ifdef ENABLE_PS
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)
147 return;
149 #endif
151 #ifdef TODO
152 if(pAdapter->bInHctTest)
153 return;
154 #endif
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
157 feedback info. */
158 if (pstx_fb->tok)
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;
176 else
178 priv->stats.txunicast++;
179 priv->stats.txbytesunicast += pstx_fb->pkt_length;
182 else
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++;
197 else
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.
222 * Output: NONE
224 * Return: NONE
226 * Revised History:
227 * When Who Remark
228 * 05/08/2008 amy Create Version 0 porting from windows code.
230 *---------------------------------------------------------------------------*/
231 static void
232 cmpk_handle_tx_feedback(
233 struct net_device *dev,
234 u8 * pmsg)
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
255 or multicast. */
256 //CountTxStatistics( pAdapter, &tcb );
258 } /* cmpk_Handle_Tx_Feedback */
260 void
261 cmdpkt_beacontimerinterrupt_819xusb(
262 struct net_device *dev
265 struct r8192_priv *priv = ieee80211_priv(dev);
266 u16 tx_rate;
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)))
275 tx_rate = 60;
276 DMESG("send beacon frame tx rate is 6Mbpm\n");
278 else
280 tx_rate =10;
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.
304 * Output: NONE
306 * Return: NONE
308 * Revised History:
309 * When Who Remark
310 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
312 *---------------------------------------------------------------------------*/
313 static void
314 cmpk_handle_interrupt_status(
315 struct net_device *dev,
316 u8* pmsg)
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");
336 return;
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.
385 * Output: NONE
387 * Return: NONE
389 * Revised History:
390 * When Who Remark
391 * 05/12/2008 amy Create Version 0 porting from windows code.
393 *---------------------------------------------------------------------------*/
394 static void
395 cmpk_handle_query_config_rx(
396 struct net_device *dev,
397 u8* pmsg)
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.
429 * Input: NONE
431 * Output: NONE
433 * Return: NONE
435 * Revised History:
436 * When Who Remark
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);
445 #ifdef ENABLE_PS
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)
456 return;
458 #endif
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.
496 * Input: NONE
498 * Output: NONE
500 * Return: NONE
502 * Revised History:
503 * When Who Remark
504 * 05/12/2008 amy Create Version 0 porting from windows code.
506 *---------------------------------------------------------------------------*/
507 static void
508 cmpk_handle_tx_status(
509 struct net_device *dev,
510 u8* pmsg)
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
526 * Input: NONE
528 * Output: NONE
530 * Return: NONE
532 * Revised History:
533 * When Who Remark
534 * 05/12/2008 amy Create Version 0 porting from windows code.
536 *---------------------------------------------------------------------------*/
537 static void
538 cmpk_handle_tx_rate_history(
539 struct net_device *dev,
540 u8* pmsg)
542 cmpk_tx_rahis_t *ptxrate;
543 // RT_RF_POWER_STATE rtState;
544 u8 i, j;
545 u16 length = sizeof(cmpk_tx_rahis_t);
546 u32 *ptemp;
547 struct r8192_priv *priv = ieee80211_priv(dev);
550 #ifdef ENABLE_PS
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)
558 return;
560 #endif
562 ptemp = (u32 *)pmsg;
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++)
570 u16 temp1, temp2;
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 )
581 return;
584 for (i = 0; i < 16; i++)
586 // Collect CCK rate packet num
587 if (i < 4)
588 priv->stats.txrate.cck[i] += ptxrate->cck[i];
590 // Collect OFDM rate packet num
591 if (i< 8)
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.
610 * Input: NONE
612 * Output: NONE
614 * Return: NONE
616 * Revised History:
617 * When Who Remark
618 * 05/06/2008 amy Create Version 0 porting from windows code.
620 *---------------------------------------------------------------------------*/
621 extern u32
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);
628 int total_length;
629 u8 cmd_length, exe_cnt = 0;
630 u8 element_id;
631 u8 *pcmd_buff;
633 /* 0. Check inpt arguments. If is is a command queue message or pointer is
634 null. */
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];
663 switch(element_id)
665 case RX_TX_FEEDBACK:
666 cmpk_handle_tx_feedback (dev, pcmd_buff);
667 cmd_length = CMPK_RX_TX_FB_SIZE;
668 break;
670 case RX_INTERRUPT_STATUS:
671 cmpk_handle_interrupt_status(dev, pcmd_buff);
672 cmd_length = sizeof(cmpk_intr_sta_t);
673 break;
675 case BOTH_QUERY_CONFIG:
676 cmpk_handle_query_config_rx(dev, pcmd_buff);
677 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
678 break;
680 case RX_TX_STATUS:
681 cmpk_handle_tx_status(dev, pcmd_buff);
682 cmd_length = CMPK_RX_TX_STS_SIZE;
683 break;
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;
690 break;
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;
696 break;
698 default:
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 */