staging: rtl8192u: remove unused macros r819xU_cmdpkt.c
[linux-2.6/btrfs-unstable.git] / drivers / staging / rtl8192u / r819xU_cmdpkt.c
blob5bc361b16d4ca05e924bd3a326824c852a67b8f0
1 /******************************************************************************
3 * (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
5 * Module: r819xusb_cmdpkt.c
6 * (RTL8190 TX/RX command packet handler Source C File)
8 * Note: The module is responsible for handling TX and RX command packet.
9 * 1. TX : Send set and query configuration command packet.
10 * 2. RX : Receive tx feedback, beacon state, query configuration
11 * command packet.
13 * Function:
15 * Export:
17 * Abbrev:
19 * History:
21 * Date Who Remark
22 * 05/06/2008 amy Create initial version porting from
23 * windows driver.
25 ******************************************************************************/
26 #include "r8192U.h"
27 #include "r819xU_cmdpkt.h"
29 rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
31 rt_status rtStatus = RT_STATUS_SUCCESS;
32 struct r8192_priv *priv = ieee80211_priv(dev);
33 struct sk_buff *skb;
34 cb_desc *tcb_desc;
35 unsigned char *ptr_buf;
37 /* Get TCB and local buffer from common pool.
38 (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */
39 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
40 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
41 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
42 tcb_desc->queue_index = TXCMD_QUEUE;
43 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
44 tcb_desc->bLastIniPkt = 0;
45 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
46 ptr_buf = skb_put(skb, DataLen);
47 memcpy(ptr_buf, pData, DataLen);
48 tcb_desc->txbuf_size = (u16)DataLen;
50 if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
51 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
52 (priv->ieee80211->queue_stop)) {
53 RT_TRACE(COMP_FIRMWARE, "=== NULL packet ======> tx full!\n");
54 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
55 } else {
56 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
59 return rtStatus;
62 /*-----------------------------------------------------------------------------
63 * Function: cmpk_message_handle_tx()
65 * Overview: Driver internal module can call the API to send message to
66 * firmware side. For example, you can send a debug command packet.
67 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
68 * Otherwise, you can change MAC/PHT/RF register by firmware at
69 * run time. We do not support message more than one segment now.
71 * Input: NONE
73 * Output: NONE
75 * Return: NONE
77 * Revised History:
78 * When Who Remark
79 * 05/06/2008 amy porting from windows code.
81 *---------------------------------------------------------------------------*/
82 extern rt_status cmpk_message_handle_tx(struct net_device *dev,
83 u8 *codevirtualaddress,
84 u32 packettype, u32 buffer_len)
87 bool rt_status = true;
88 #ifdef RTL8192U
89 return rt_status;
90 #else
91 struct r8192_priv *priv = ieee80211_priv(dev);
92 u16 frag_threshold;
93 u16 frag_length, frag_offset = 0;
95 rt_firmware *pfirmware = priv->pFirmware;
96 struct sk_buff *skb;
97 unsigned char *seg_ptr;
98 cb_desc *tcb_desc;
99 u8 bLastIniPkt;
101 firmware_init_param(dev);
102 /* Fragmentation might be required */
103 frag_threshold = pfirmware->cmdpacket_frag_thresold;
104 do {
105 if ((buffer_len - frag_offset) > frag_threshold) {
106 frag_length = frag_threshold;
107 bLastIniPkt = 0;
109 } else {
110 frag_length = buffer_len - frag_offset;
111 bLastIniPkt = 1;
115 /* Allocate skb buffer to contain firmware info and tx
116 descriptor info add 4 to avoid packet appending overflow. */
117 #ifdef RTL8192U
118 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
119 #else
120 skb = dev_alloc_skb(frag_length + 4);
121 #endif
122 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
123 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
124 tcb_desc->queue_index = TXCMD_QUEUE;
125 tcb_desc->bCmdOrInit = packettype;
126 tcb_desc->bLastIniPkt = bLastIniPkt;
128 #ifdef RTL8192U
129 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
130 #endif
132 seg_ptr = skb_put(skb, buffer_len);
134 * Transform from little endian to big endian
135 * and pending zero
137 memcpy(seg_ptr, codevirtualaddress, buffer_len);
138 tcb_desc->txbuf_size = (u16)buffer_len;
141 if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
142 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
143 (priv->ieee80211->queue_stop)) {
144 RT_TRACE(COMP_FIRMWARE, "======> tx full!\n");
145 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
146 } else {
147 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
150 codevirtualaddress += frag_length;
151 frag_offset += frag_length;
153 } while (frag_offset < buffer_len);
155 return rt_status;
158 #endif
161 /*-----------------------------------------------------------------------------
162 * Function: cmpk_counttxstatistic()
164 * Overview:
166 * Input: PADAPTER pAdapter
167 * CMPK_TXFB_T *psTx_FB
169 * Output: NONE
171 * Return: NONE
173 * Revised History:
174 * When Who Remark
175 * 05/12/2008 amy Create Version 0 porting from windows code.
177 *---------------------------------------------------------------------------*/
178 static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb)
180 struct r8192_priv *priv = ieee80211_priv(dev);
181 #ifdef ENABLE_PS
182 RT_RF_POWER_STATE rtState;
184 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
185 (pu1Byte)(&rtState));
187 /* When RF is off, we should not count the packet for hw/sw synchronize
188 reason, ie. there may be a duration while sw switch is changed and
189 hw switch is being changed. */
190 if (rtState == eRfOff)
191 return;
192 #endif
194 #ifdef TODO
195 if (pAdapter->bInHctTest)
196 return;
197 #endif
198 /* We can not know the packet length and transmit type:
199 broadcast or uni or multicast. So the relative statistics
200 must be collected in tx feedback info. */
201 if (pstx_fb->tok) {
202 priv->stats.txfeedbackok++;
203 priv->stats.txoktotal++;
204 priv->stats.txokbytestotal += pstx_fb->pkt_length;
205 priv->stats.txokinperiod++;
207 /* We can not make sure broadcast/multicast or unicast mode. */
208 if (pstx_fb->pkt_type == PACKET_MULTICAST) {
209 priv->stats.txmulticast++;
210 priv->stats.txbytesmulticast += pstx_fb->pkt_length;
211 } else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
212 priv->stats.txbroadcast++;
213 priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
214 } else {
215 priv->stats.txunicast++;
216 priv->stats.txbytesunicast += pstx_fb->pkt_length;
218 } else {
219 priv->stats.txfeedbackfail++;
220 priv->stats.txerrtotal++;
221 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
223 /* We can not make sure broadcast/multicast or unicast mode. */
224 if (pstx_fb->pkt_type == PACKET_MULTICAST)
225 priv->stats.txerrmulticast++;
226 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
227 priv->stats.txerrbroadcast++;
228 else
229 priv->stats.txerrunicast++;
232 priv->stats.txretrycount += pstx_fb->retry_cnt;
233 priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
239 /*-----------------------------------------------------------------------------
240 * Function: cmpk_handle_tx_feedback()
242 * Overview: The function is responsible for extract the message inside TX
243 * feedbck message from firmware. It will contain dedicated info in
244 * ws-06-0063-rtl8190-command-packet-specification.
245 * Please refer to chapter "TX Feedback Element".
246 * We have to read 20 bytes in the command packet.
248 * Input: struct net_device *dev
249 * u8 *pmsg - Msg Ptr of the command packet.
251 * Output: NONE
253 * Return: NONE
255 * Revised History:
256 * When Who Remark
257 * 05/08/2008 amy Create Version 0 porting from windows code.
259 *---------------------------------------------------------------------------*/
260 static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
262 struct r8192_priv *priv = ieee80211_priv(dev);
263 cmpk_txfb_t rx_tx_fb;
265 priv->stats.txfeedback++;
267 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
268 /* It seems that FW use big endian(MIPS) and DRV use little endian in
269 windows OS. So we have to read the content byte by byte or transfer
270 endian type before copy the message copy. */
271 /* Use pointer to transfer structure memory. */
272 memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
273 /* 2. Use tx feedback info to count TX statistics. */
274 cmpk_count_txstatistic(dev, &rx_tx_fb);
275 /* Comment previous method for TX statistic function. */
276 /* Collect info TX feedback packet to fill TCB. */
277 /* We can not know the packet length and transmit type: broadcast or uni
278 or multicast. */
282 void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
284 struct r8192_priv *priv = ieee80211_priv(dev);
285 u16 tx_rate;
286 /* 87B have to S/W beacon for DTM encryption_cmn. */
287 if (priv->ieee80211->current_network.mode == IEEE_A ||
288 priv->ieee80211->current_network.mode == IEEE_N_5G ||
289 (priv->ieee80211->current_network.mode == IEEE_N_24G &&
290 (!priv->ieee80211->pHTInfo->bCurSuppCCK))) {
291 tx_rate = 60;
292 DMESG("send beacon frame tx rate is 6Mbpm\n");
293 } else {
294 tx_rate = 10;
295 DMESG("send beacon frame tx rate is 1Mbpm\n");
298 rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */
306 /*-----------------------------------------------------------------------------
307 * Function: cmpk_handle_interrupt_status()
309 * Overview: The function is responsible for extract the message from
310 * firmware. It will contain dedicated info in
311 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
312 * Please refer to chapter "Interrupt Status Element".
314 * Input: struct net_device *dev
315 * u8 *pmsg - Message Pointer of the command packet.
317 * Output: NONE
319 * Return: NONE
321 * Revised History:
322 * When Who Remark
323 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
325 *---------------------------------------------------------------------------*/
326 static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
328 cmpk_intr_sta_t rx_intr_status; /* */
329 struct r8192_priv *priv = ieee80211_priv(dev);
331 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
333 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
334 /* It seems that FW use big endian(MIPS) and DRV use little endian in
335 windows OS. So we have to read the content byte by byte or transfer
336 endian type before copy the message copy. */
337 rx_intr_status.length = pmsg[1];
338 if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) {
339 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
340 return;
344 /* Statistics of beacon for ad-hoc mode. */
345 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
346 /* 2 maybe need endian transform? */
347 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
349 DMESG("interrupt status = 0x%x\n",
350 rx_intr_status.interrupt_status);
352 if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
353 priv->ieee80211->bibsscoordinator = true;
354 priv->stats.txbeaconokint++;
355 } 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)
361 cmdpkt_beacontimerinterrupt_819xusb(dev);
365 /* Other informations in interrupt status we need? */
368 DMESG("<---- cmpk_handle_interrupt_status()\n");
373 /*-----------------------------------------------------------------------------
374 * Function: cmpk_handle_query_config_rx()
376 * Overview: The function is responsible for extract the message from
377 * firmware. It will contain dedicated info in
378 * ws-06-0063-rtl8190-command-packet-specification. Please
379 * refer to chapter "Beacon State Element".
381 * Input: u8 *pmsg - Message Pointer of the command packet.
383 * Output: NONE
385 * Return: NONE
387 * Revised History:
388 * When Who Remark
389 * 05/12/2008 amy Create Version 0 porting from windows code.
391 *---------------------------------------------------------------------------*/
392 static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
394 cmpk_query_cfg_t rx_query_cfg;
397 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
398 /* It seems that FW use big endian(MIPS) and DRV use little endian in
399 windows OS. So we have to read the content byte by byte or transfer
400 endian type before copy the message copy. */
401 rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000) >> 31;
402 rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
403 rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
404 rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
405 rx_query_cfg.cfg_offset = pmsg[7];
406 rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
407 (pmsg[10] << 8) | (pmsg[11] << 0);
408 rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
409 (pmsg[14] << 8) | (pmsg[15] << 0);
414 /*-----------------------------------------------------------------------------
415 * Function: cmpk_count_tx_status()
417 * Overview: Count aggregated tx status from firmwar of one type rx command
418 * packet element id = RX_TX_STATUS.
420 * Input: NONE
422 * Output: NONE
424 * Return: NONE
426 * Revised History:
427 * When Who Remark
428 * 05/12/2008 amy Create Version 0 porting from windows code.
430 *---------------------------------------------------------------------------*/
431 static void cmpk_count_tx_status(struct net_device *dev,
432 cmpk_tx_status_t *pstx_status)
434 struct r8192_priv *priv = ieee80211_priv(dev);
436 #ifdef ENABLE_PS
438 RT_RF_POWER_STATE rtstate;
440 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
441 (pu1Byte)(&rtState));
443 /* When RF is off, we should not count the packet for hw/sw synchronize
444 reason, ie. there may be a duration while sw switch is changed and
445 hw switch is being changed. */
446 if (rtState == eRfOff)
447 return;
448 #endif
450 priv->stats.txfeedbackok += pstx_status->txok;
451 priv->stats.txoktotal += pstx_status->txok;
453 priv->stats.txfeedbackfail += pstx_status->txfail;
454 priv->stats.txerrtotal += pstx_status->txfail;
456 priv->stats.txretrycount += pstx_status->txretry;
457 priv->stats.txfeedbackretry += pstx_status->txretry;
460 priv->stats.txmulticast += pstx_status->txmcok;
461 priv->stats.txbroadcast += pstx_status->txbcok;
462 priv->stats.txunicast += pstx_status->txucok;
464 priv->stats.txerrmulticast += pstx_status->txmcfail;
465 priv->stats.txerrbroadcast += pstx_status->txbcfail;
466 priv->stats.txerrunicast += pstx_status->txucfail;
468 priv->stats.txbytesmulticast += pstx_status->txmclength;
469 priv->stats.txbytesbroadcast += pstx_status->txbclength;
470 priv->stats.txbytesunicast += pstx_status->txuclength;
472 priv->stats.last_packet_rate = pstx_status->rate;
477 /*-----------------------------------------------------------------------------
478 * Function: cmpk_handle_tx_status()
480 * Overview: Firmware add a new tx feedback status to reduce rx command
481 * packet buffer operation load.
483 * Input: NONE
485 * Output: NONE
487 * Return: NONE
489 * Revised History:
490 * When Who Remark
491 * 05/12/2008 amy Create Version 0 porting from windows code.
493 *---------------------------------------------------------------------------*/
494 static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
496 cmpk_tx_status_t rx_tx_sts;
498 memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t));
499 /* 2. Use tx feedback info to count TX statistics. */
500 cmpk_count_tx_status(dev, &rx_tx_sts);
505 /*-----------------------------------------------------------------------------
506 * Function: cmpk_handle_tx_rate_history()
508 * Overview: Firmware add a new tx rate history
510 * Input: NONE
512 * Output: NONE
514 * Return: NONE
516 * Revised History:
517 * When Who Remark
518 * 05/12/2008 amy Create Version 0 porting from windows code.
520 *---------------------------------------------------------------------------*/
521 static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
523 cmpk_tx_rahis_t *ptxrate;
524 u8 i, j;
525 u16 length = sizeof(cmpk_tx_rahis_t);
526 u32 *ptemp;
527 struct r8192_priv *priv = ieee80211_priv(dev);
530 #ifdef ENABLE_PS
531 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
532 (pu1Byte)(&rtState));
534 /* When RF is off, we should not count the packet for hw/sw synchronize
535 reason, ie. there may be a duration while sw switch is changed and
536 hw switch is being changed. */
537 if (rtState == eRfOff)
538 return;
539 #endif
541 ptemp = (u32 *)pmsg;
543 /* Do endian transfer to word alignment(16 bits) for windows system.
544 You must do different endian transfer for linux and MAC OS */
545 for (i = 0; i < (length/4); i++) {
546 u16 temp1, temp2;
548 temp1 = ptemp[i] & 0x0000FFFF;
549 temp2 = ptemp[i] >> 16;
550 ptemp[i] = (temp1 << 16) | temp2;
553 ptxrate = (cmpk_tx_rahis_t *)pmsg;
555 if (ptxrate == NULL)
556 return;
558 for (i = 0; i < 16; i++) {
559 /* Collect CCK rate packet num */
560 if (i < 4)
561 priv->stats.txrate.cck[i] += ptxrate->cck[i];
563 /* Collect OFDM rate packet num */
564 if (i < 8)
565 priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
567 for (j = 0; j < 4; j++)
568 priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
574 /*-----------------------------------------------------------------------------
575 * Function: cmpk_message_handle_rx()
577 * Overview: In the function, we will capture different RX command packet
578 * info. Every RX command packet element has different message
579 * length and meaning in content. We only support three type of RX
580 * command packet now. Please refer to document
581 * ws-06-0063-rtl8190-command-packet-specification.
583 * Input: NONE
585 * Output: NONE
587 * Return: NONE
589 * Revised History:
590 * When Who Remark
591 * 05/06/2008 amy Create Version 0 porting from windows code.
593 *---------------------------------------------------------------------------*/
594 extern u32 cmpk_message_handle_rx(struct net_device *dev,
595 struct ieee80211_rx_stats *pstats)
597 int total_length;
598 u8 cmd_length, exe_cnt = 0;
599 u8 element_id;
600 u8 *pcmd_buff;
602 /* 0. Check inpt arguments. If is is a command queue message or
603 pointer is null. */
604 if (pstats == NULL)
605 return 0; /* This is not a command packet. */
607 /* 1. Read received command packet message length from RFD. */
608 total_length = pstats->Length;
610 /* 2. Read virtual address from RFD. */
611 pcmd_buff = pstats->virtual_address;
613 /* 3. Read command packet element id and length. */
614 element_id = pcmd_buff[0];
616 /* 4. Check every received command packet content according to different
617 element type. Because FW may aggregate RX command packet to
618 minimize transmit time between DRV and FW.*/
619 /* Add a counter to prevent the lock in the loop from being held too
620 long */
621 while (total_length > 0 && exe_cnt++ < 100) {
622 /* We support aggregation of different cmd in the same packet */
623 element_id = pcmd_buff[0];
625 switch (element_id) {
626 case RX_TX_FEEDBACK:
627 cmpk_handle_tx_feedback(dev, pcmd_buff);
628 cmd_length = CMPK_RX_TX_FB_SIZE;
629 break;
631 case RX_INTERRUPT_STATUS:
632 cmpk_handle_interrupt_status(dev, pcmd_buff);
633 cmd_length = sizeof(cmpk_intr_sta_t);
634 break;
636 case BOTH_QUERY_CONFIG:
637 cmpk_handle_query_config_rx(dev, pcmd_buff);
638 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
639 break;
641 case RX_TX_STATUS:
642 cmpk_handle_tx_status(dev, pcmd_buff);
643 cmd_length = CMPK_RX_TX_STS_SIZE;
644 break;
646 case RX_TX_PER_PKT_FEEDBACK:
647 /* You must at lease add a switch case element here,
648 Otherwise, we will jump to default case. */
649 cmd_length = CMPK_RX_TX_FB_SIZE;
650 break;
652 case RX_TX_RATE_HISTORY:
653 cmpk_handle_tx_rate_history(dev, pcmd_buff);
654 cmd_length = CMPK_TX_RAHIS_SIZE;
655 break;
657 default:
659 RT_TRACE(COMP_ERR, "---->%s():unknown CMD Element\n",
660 __func__);
661 return 1; /* This is a command packet. */
664 total_length -= cmd_length;
665 pcmd_buff += cmd_length;
667 return 1; /* This is a command packet. */