Merge tag 'range-macro' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[deliverable/linux.git] / drivers / staging / rtl8192u / r819xU_cmdpkt.c
CommitLineData
8fc8598e 1/******************************************************************************
6df9f669
XR
2 *
3 * (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
4 *
5 * Module: r819xusb_cmdpkt.c
6 * (RTL8190 TX/RX command packet handler Source C File)
7 *
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.
12 *
13 * Function:
14 *
15 * Export:
16 *
17 * Abbrev:
18 *
19 * History:
20 *
21 * Date Who Remark
22 * 05/06/2008 amy Create initial version porting from
23 * windows driver.
24 *
25 ******************************************************************************/
8fc8598e
JC
26#include "r8192U.h"
27#include "r819xU_cmdpkt.h"
6df9f669 28
fa6b108b 29rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
8fc8598e
JC
30{
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;
8fc8598e 36
6df9f669
XR
37 /* Get TCB and local buffer from common pool.
38 (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */
8fc8598e 39 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
c3aed231
IP
40 if (!skb)
41 return RT_STATUS_FAILURE;
fa6b108b 42 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
9772acad 43 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
8fc8598e
JC
44 tcb_desc->queue_index = TXCMD_QUEUE;
45 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
46 tcb_desc->bLastIniPkt = 0;
47 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
48 ptr_buf = skb_put(skb, DataLen);
fa6b108b
XR
49 memcpy(ptr_buf, pData, DataLen);
50 tcb_desc->txbuf_size = (u16)DataLen;
8fc8598e 51
fa6b108b 52 if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
f70edb9f
XR
53 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
54 (priv->ieee80211->queue_stop)) {
55 RT_TRACE(COMP_FIRMWARE, "=== NULL packet ======> tx full!\n");
56 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
57 } else {
58 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
59 }
8fc8598e 60
8fc8598e
JC
61 return rtStatus;
62}
63
64/*-----------------------------------------------------------------------------
65 * Function: cmpk_message_handle_tx()
66 *
67 * Overview: Driver internal module can call the API to send message to
6df9f669
XR
68 * firmware side. For example, you can send a debug command packet.
69 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
70 * Otherwise, you can change MAC/PHT/RF register by firmware at
71 * run time. We do not support message more than one segment now.
8fc8598e 72 *
6df9f669 73 * Input: NONE
8fc8598e 74 *
6df9f669 75 * Output: NONE
8fc8598e 76 *
6df9f669 77 * Return: NONE
8fc8598e
JC
78 *
79 * Revised History:
80 * When Who Remark
81 * 05/06/2008 amy porting from windows code.
82 *
83 *---------------------------------------------------------------------------*/
fa6b108b
XR
84extern rt_status cmpk_message_handle_tx(struct net_device *dev,
85 u8 *codevirtualaddress,
86 u32 packettype, u32 buffer_len)
8fc8598e
JC
87{
88
35997ff0 89 bool rt_status = true;
8fc8598e
JC
90#ifdef RTL8192U
91 return rt_status;
92#else
93 struct r8192_priv *priv = ieee80211_priv(dev);
94 u16 frag_threshold;
95 u16 frag_length, frag_offset = 0;
8fc8598e
JC
96
97 rt_firmware *pfirmware = priv->pFirmware;
98 struct sk_buff *skb;
99 unsigned char *seg_ptr;
100 cb_desc *tcb_desc;
101 u8 bLastIniPkt;
102
103 firmware_init_param(dev);
6df9f669 104 /* Fragmentation might be required */
8fc8598e
JC
105 frag_threshold = pfirmware->cmdpacket_frag_thresold;
106 do {
a71d7679 107 if ((buffer_len - frag_offset) > frag_threshold) {
fa6b108b 108 frag_length = frag_threshold;
8fc8598e
JC
109 bLastIniPkt = 0;
110
111 } else {
112 frag_length = buffer_len - frag_offset;
113 bLastIniPkt = 1;
114
115 }
116
6df9f669
XR
117 /* Allocate skb buffer to contain firmware info and tx
118 descriptor info add 4 to avoid packet appending overflow. */
f70edb9f 119#ifdef RTL8192U
8fc8598e 120 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
f70edb9f 121#else
8fc8598e 122 skb = dev_alloc_skb(frag_length + 4);
f70edb9f 123#endif
fa6b108b 124 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
9772acad 125 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
8fc8598e
JC
126 tcb_desc->queue_index = TXCMD_QUEUE;
127 tcb_desc->bCmdOrInit = packettype;
128 tcb_desc->bLastIniPkt = bLastIniPkt;
129
f70edb9f 130#ifdef RTL8192U
8fc8598e 131 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
f70edb9f 132#endif
8fc8598e
JC
133
134 seg_ptr = skb_put(skb, buffer_len);
135 /*
136 * Transform from little endian to big endian
589b3d06 137 * and pending zero
8fc8598e 138 */
fa6b108b
XR
139 memcpy(seg_ptr, codevirtualaddress, buffer_len);
140 tcb_desc->txbuf_size = (u16)buffer_len;
8fc8598e
JC
141
142
fa6b108b 143 if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
f70edb9f
XR
144 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
145 (priv->ieee80211->queue_stop)) {
146 RT_TRACE(COMP_FIRMWARE, "======> tx full!\n");
8fc8598e
JC
147 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
148 } else {
fa6b108b 149 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
8fc8598e
JC
150 }
151
152 codevirtualaddress += frag_length;
153 frag_offset += frag_length;
154
fa6b108b 155 } while (frag_offset < buffer_len);
8fc8598e
JC
156
157 return rt_status;
158
159
160#endif
6df9f669 161}
8fc8598e
JC
162
163/*-----------------------------------------------------------------------------
164 * Function: cmpk_counttxstatistic()
165 *
166 * Overview:
167 *
6df9f669
XR
168 * Input: PADAPTER pAdapter
169 * CMPK_TXFB_T *psTx_FB
8fc8598e
JC
170 *
171 * Output: NONE
172 *
173 * Return: NONE
174 *
175 * Revised History:
6df9f669
XR
176 * When Who Remark
177 * 05/12/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
178 *
179 *---------------------------------------------------------------------------*/
fa6b108b 180static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb)
8fc8598e
JC
181{
182 struct r8192_priv *priv = ieee80211_priv(dev);
183#ifdef ENABLE_PS
184 RT_RF_POWER_STATE rtState;
185
f70edb9f
XR
186 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
187 (pu1Byte)(&rtState));
8fc8598e 188
6df9f669
XR
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
191 hw switch is being changed. */
8fc8598e 192 if (rtState == eRfOff)
8fc8598e 193 return;
8fc8598e
JC
194#endif
195
196#ifdef TODO
a71d7679 197 if (pAdapter->bInHctTest)
8fc8598e
JC
198 return;
199#endif
6df9f669
XR
200 /* We can not know the packet length and transmit type:
201 broadcast or uni or multicast. So the relative statistics
202 must be collected in tx feedback info. */
05cdf47a 203 if (pstx_fb->tok) {
8fc8598e
JC
204 priv->stats.txfeedbackok++;
205 priv->stats.txoktotal++;
206 priv->stats.txokbytestotal += pstx_fb->pkt_length;
207 priv->stats.txokinperiod++;
208
209 /* We can not make sure broadcast/multicast or unicast mode. */
05cdf47a 210 if (pstx_fb->pkt_type == PACKET_MULTICAST) {
8fc8598e
JC
211 priv->stats.txmulticast++;
212 priv->stats.txbytesmulticast += pstx_fb->pkt_length;
05cdf47a 213 } else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
8fc8598e
JC
214 priv->stats.txbroadcast++;
215 priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
05cdf47a 216 } else {
8fc8598e
JC
217 priv->stats.txunicast++;
218 priv->stats.txbytesunicast += pstx_fb->pkt_length;
219 }
05cdf47a 220 } else {
8fc8598e
JC
221 priv->stats.txfeedbackfail++;
222 priv->stats.txerrtotal++;
223 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
224
225 /* We can not make sure broadcast/multicast or unicast mode. */
226 if (pstx_fb->pkt_type == PACKET_MULTICAST)
8fc8598e 227 priv->stats.txerrmulticast++;
8fc8598e 228 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
8fc8598e 229 priv->stats.txerrbroadcast++;
8fc8598e 230 else
8fc8598e 231 priv->stats.txerrunicast++;
8fc8598e
JC
232 }
233
234 priv->stats.txretrycount += pstx_fb->retry_cnt;
235 priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
236
6df9f669 237}
8fc8598e
JC
238
239
240
241/*-----------------------------------------------------------------------------
242 * Function: cmpk_handle_tx_feedback()
243 *
244 * Overview: The function is responsible for extract the message inside TX
6df9f669
XR
245 * feedbck message from firmware. It will contain dedicated info in
246 * ws-06-0063-rtl8190-command-packet-specification.
247 * Please refer to chapter "TX Feedback Element".
248 * We have to read 20 bytes in the command packet.
8fc8598e 249 *
6df9f669
XR
250 * Input: struct net_device *dev
251 * u8 *pmsg - Msg Ptr of the command packet.
8fc8598e
JC
252 *
253 * Output: NONE
254 *
255 * Return: NONE
256 *
257 * Revised History:
6df9f669
XR
258 * When Who Remark
259 * 05/08/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
260 *
261 *---------------------------------------------------------------------------*/
fa6b108b 262static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
8fc8598e
JC
263{
264 struct r8192_priv *priv = ieee80211_priv(dev);
6df9f669 265 cmpk_txfb_t rx_tx_fb;
8fc8598e
JC
266
267 priv->stats.txfeedback++;
268
8fc8598e
JC
269 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
270 /* It seems that FW use big endian(MIPS) and DRV use little endian in
271 windows OS. So we have to read the content byte by byte or transfer
272 endian type before copy the message copy. */
6df9f669 273 /* Use pointer to transfer structure memory. */
9772acad 274 memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
8fc8598e
JC
275 /* 2. Use tx feedback info to count TX statistics. */
276 cmpk_count_txstatistic(dev, &rx_tx_fb);
6df9f669 277 /* Comment previous method for TX statistic function. */
8fc8598e
JC
278 /* Collect info TX feedback packet to fill TCB. */
279 /* We can not know the packet length and transmit type: broadcast or uni
280 or multicast. */
8fc8598e 281
6df9f669 282}
8fc8598e 283
fa6b108b 284void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
8fc8598e
JC
285{
286 struct r8192_priv *priv = ieee80211_priv(dev);
287 u16 tx_rate;
6df9f669 288 /* 87B have to S/W beacon for DTM encryption_cmn. */
fa6b108b 289 if (priv->ieee80211->current_network.mode == IEEE_A ||
8fc8598e 290 priv->ieee80211->current_network.mode == IEEE_N_5G ||
f70edb9f
XR
291 (priv->ieee80211->current_network.mode == IEEE_N_24G &&
292 (!priv->ieee80211->pHTInfo->bCurSuppCCK))) {
8fc8598e
JC
293 tx_rate = 60;
294 DMESG("send beacon frame tx rate is 6Mbpm\n");
05cdf47a 295 } else {
fa6b108b 296 tx_rate = 10;
8fc8598e
JC
297 DMESG("send beacon frame tx rate is 1Mbpm\n");
298 }
299
6df9f669 300 rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */
8fc8598e 301
8fc8598e
JC
302
303}
304
305
306
307
308/*-----------------------------------------------------------------------------
309 * Function: cmpk_handle_interrupt_status()
310 *
311 * Overview: The function is responsible for extract the message from
6df9f669
XR
312 * firmware. It will contain dedicated info in
313 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
314 * Please refer to chapter "Interrupt Status Element".
8fc8598e 315 *
6df9f669
XR
316 * Input: struct net_device *dev
317 * u8 *pmsg - Message Pointer of the command packet.
8fc8598e
JC
318 *
319 * Output: NONE
320 *
321 * Return: NONE
322 *
323 * Revised History:
6df9f669
XR
324 * When Who Remark
325 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
8fc8598e
JC
326 *
327 *---------------------------------------------------------------------------*/
fa6b108b 328static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
8fc8598e
JC
329{
330 cmpk_intr_sta_t rx_intr_status; /* */
331 struct r8192_priv *priv = ieee80211_priv(dev);
332
333 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
334
8fc8598e
JC
335 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
336 /* It seems that FW use big endian(MIPS) and DRV use little endian in
337 windows OS. So we have to read the content byte by byte or transfer
338 endian type before copy the message copy. */
8fc8598e 339 rx_intr_status.length = pmsg[1];
05cdf47a 340 if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) {
8fc8598e
JC
341 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
342 return;
343 }
344
345
6df9f669 346 /* Statistics of beacon for ad-hoc mode. */
fa6b108b 347 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
6df9f669 348 /* 2 maybe need endian transform? */
8fc8598e 349 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
8fc8598e 350
f70edb9f
XR
351 DMESG("interrupt status = 0x%x\n",
352 rx_intr_status.interrupt_status);
8fc8598e 353
05cdf47a 354 if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
8fc8598e
JC
355 priv->ieee80211->bibsscoordinator = true;
356 priv->stats.txbeaconokint++;
05cdf47a 357 } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) {
8fc8598e
JC
358 priv->ieee80211->bibsscoordinator = false;
359 priv->stats.txbeaconerr++;
360 }
361
362 if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
8fc8598e 363 cmdpkt_beacontimerinterrupt_819xusb(dev);
8fc8598e
JC
364
365 }
366
6df9f669 367 /* Other informations in interrupt status we need? */
8fc8598e
JC
368
369
370 DMESG("<---- cmpk_handle_interrupt_status()\n");
371
6df9f669 372}
8fc8598e
JC
373
374
375/*-----------------------------------------------------------------------------
376 * Function: cmpk_handle_query_config_rx()
377 *
378 * Overview: The function is responsible for extract the message from
6df9f669
XR
379 * firmware. It will contain dedicated info in
380 * ws-06-0063-rtl8190-command-packet-specification. Please
381 * refer to chapter "Beacon State Element".
8fc8598e 382 *
6df9f669 383 * Input: u8 *pmsg - Message Pointer of the command packet.
8fc8598e
JC
384 *
385 * Output: NONE
386 *
387 * Return: NONE
388 *
389 * Revised History:
6df9f669
XR
390 * When Who Remark
391 * 05/12/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
392 *
393 *---------------------------------------------------------------------------*/
fa6b108b 394static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
8fc8598e 395{
6df9f669 396 cmpk_query_cfg_t rx_query_cfg;
8fc8598e 397
8fc8598e
JC
398
399 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
400 /* It seems that FW use big endian(MIPS) and DRV use little endian in
401 windows OS. So we have to read the content byte by byte or transfer
402 endian type before copy the message copy. */
fa6b108b 403 rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000) >> 31;
35997ff0
SH
404 rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
405 rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
406 rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
fa6b108b
XR
407 rx_query_cfg.cfg_offset = pmsg[7];
408 rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
409 (pmsg[10] << 8) | (pmsg[11] << 0);
410 rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
411 (pmsg[14] << 8) | (pmsg[15] << 0);
8fc8598e 412
6df9f669 413}
8fc8598e
JC
414
415
416/*-----------------------------------------------------------------------------
417 * Function: cmpk_count_tx_status()
418 *
419 * Overview: Count aggregated tx status from firmwar of one type rx command
6df9f669 420 * packet element id = RX_TX_STATUS.
8fc8598e 421 *
6df9f669 422 * Input: NONE
8fc8598e 423 *
6df9f669 424 * Output: NONE
8fc8598e 425 *
6df9f669 426 * Return: NONE
8fc8598e
JC
427 *
428 * Revised History:
6df9f669
XR
429 * When Who Remark
430 * 05/12/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
431 *
432 *---------------------------------------------------------------------------*/
fa6b108b
XR
433static void cmpk_count_tx_status(struct net_device *dev,
434 cmpk_tx_status_t *pstx_status)
8fc8598e
JC
435{
436 struct r8192_priv *priv = ieee80211_priv(dev);
437
438#ifdef ENABLE_PS
439
440 RT_RF_POWER_STATE rtstate;
441
f70edb9f
XR
442 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
443 (pu1Byte)(&rtState));
8fc8598e 444
6df9f669
XR
445 /* When RF is off, we should not count the packet for hw/sw synchronize
446 reason, ie. there may be a duration while sw switch is changed and
447 hw switch is being changed. */
8fc8598e 448 if (rtState == eRfOff)
8fc8598e 449 return;
8fc8598e
JC
450#endif
451
452 priv->stats.txfeedbackok += pstx_status->txok;
453 priv->stats.txoktotal += pstx_status->txok;
454
455 priv->stats.txfeedbackfail += pstx_status->txfail;
456 priv->stats.txerrtotal += pstx_status->txfail;
457
fa6b108b 458 priv->stats.txretrycount += pstx_status->txretry;
8fc8598e
JC
459 priv->stats.txfeedbackretry += pstx_status->txretry;
460
8fc8598e 461
fa6b108b
XR
462 priv->stats.txmulticast += pstx_status->txmcok;
463 priv->stats.txbroadcast += pstx_status->txbcok;
8fc8598e
JC
464 priv->stats.txunicast += pstx_status->txucok;
465
466 priv->stats.txerrmulticast += pstx_status->txmcfail;
467 priv->stats.txerrbroadcast += pstx_status->txbcfail;
468 priv->stats.txerrunicast += pstx_status->txucfail;
469
470 priv->stats.txbytesmulticast += pstx_status->txmclength;
471 priv->stats.txbytesbroadcast += pstx_status->txbclength;
fa6b108b 472 priv->stats.txbytesunicast += pstx_status->txuclength;
8fc8598e 473
fa6b108b 474 priv->stats.last_packet_rate = pstx_status->rate;
6df9f669 475}
8fc8598e
JC
476
477
478
479/*-----------------------------------------------------------------------------
480 * Function: cmpk_handle_tx_status()
481 *
482 * Overview: Firmware add a new tx feedback status to reduce rx command
6df9f669 483 * packet buffer operation load.
8fc8598e
JC
484 *
485 * Input: NONE
486 *
487 * Output: NONE
488 *
489 * Return: NONE
490 *
491 * Revised History:
6df9f669
XR
492 * When Who Remark
493 * 05/12/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
494 *
495 *---------------------------------------------------------------------------*/
fa6b108b 496static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
8fc8598e 497{
6df9f669 498 cmpk_tx_status_t rx_tx_sts;
8fc8598e 499
9772acad 500 memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t));
8fc8598e
JC
501 /* 2. Use tx feedback info to count TX statistics. */
502 cmpk_count_tx_status(dev, &rx_tx_sts);
503
6df9f669 504}
8fc8598e
JC
505
506
507/*-----------------------------------------------------------------------------
508 * Function: cmpk_handle_tx_rate_history()
509 *
510 * Overview: Firmware add a new tx rate history
511 *
512 * Input: NONE
513 *
514 * Output: NONE
515 *
516 * Return: NONE
517 *
518 * Revised History:
6df9f669
XR
519 * When Who Remark
520 * 05/12/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
521 *
522 *---------------------------------------------------------------------------*/
fa6b108b 523static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
8fc8598e
JC
524{
525 cmpk_tx_rahis_t *ptxrate;
fa6b108b
XR
526 u8 i, j;
527 u16 length = sizeof(cmpk_tx_rahis_t);
528 u32 *ptemp;
8fc8598e
JC
529 struct r8192_priv *priv = ieee80211_priv(dev);
530
531
532#ifdef ENABLE_PS
f70edb9f
XR
533 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
534 (pu1Byte)(&rtState));
8fc8598e 535
6df9f669
XR
536 /* When RF is off, we should not count the packet for hw/sw synchronize
537 reason, ie. there may be a duration while sw switch is changed and
538 hw switch is being changed. */
8fc8598e 539 if (rtState == eRfOff)
8fc8598e 540 return;
8fc8598e
JC
541#endif
542
543 ptemp = (u32 *)pmsg;
544
6df9f669
XR
545 /* Do endian transfer to word alignment(16 bits) for windows system.
546 You must do different endian transfer for linux and MAC OS */
05cdf47a 547 for (i = 0; i < (length/4); i++) {
8fc8598e
JC
548 u16 temp1, temp2;
549
fa6b108b
XR
550 temp1 = ptemp[i] & 0x0000FFFF;
551 temp2 = ptemp[i] >> 16;
552 ptemp[i] = (temp1 << 16) | temp2;
8fc8598e
JC
553 }
554
555 ptxrate = (cmpk_tx_rahis_t *)pmsg;
556
fa6b108b 557 if (ptxrate == NULL)
8fc8598e 558 return;
8fc8598e 559
05cdf47a 560 for (i = 0; i < 16; i++) {
6df9f669 561 /* Collect CCK rate packet num */
8fc8598e
JC
562 if (i < 4)
563 priv->stats.txrate.cck[i] += ptxrate->cck[i];
564
6df9f669 565 /* Collect OFDM rate packet num */
fa6b108b 566 if (i < 8)
8fc8598e
JC
567 priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
568
569 for (j = 0; j < 4; j++)
570 priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
571 }
572
6df9f669 573}
8fc8598e
JC
574
575
576/*-----------------------------------------------------------------------------
577 * Function: cmpk_message_handle_rx()
578 *
579 * Overview: In the function, we will capture different RX command packet
6df9f669
XR
580 * info. Every RX command packet element has different message
581 * length and meaning in content. We only support three type of RX
582 * command packet now. Please refer to document
583 * ws-06-0063-rtl8190-command-packet-specification.
8fc8598e
JC
584 *
585 * Input: NONE
586 *
587 * Output: NONE
588 *
589 * Return: NONE
590 *
591 * Revised History:
6df9f669
XR
592 * When Who Remark
593 * 05/06/2008 amy Create Version 0 porting from windows code.
8fc8598e
JC
594 *
595 *---------------------------------------------------------------------------*/
fa6b108b
XR
596extern u32 cmpk_message_handle_rx(struct net_device *dev,
597 struct ieee80211_rx_stats *pstats)
8fc8598e 598{
8fc8598e
JC
599 int total_length;
600 u8 cmd_length, exe_cnt = 0;
601 u8 element_id;
602 u8 *pcmd_buff;
603
6df9f669
XR
604 /* 0. Check inpt arguments. If is is a command queue message or
605 pointer is null. */
fa6b108b 606 if (pstats == NULL)
8fc8598e 607 return 0; /* This is not a command packet. */
8fc8598e
JC
608
609 /* 1. Read received command packet message length from RFD. */
610 total_length = pstats->Length;
611
612 /* 2. Read virtual address from RFD. */
613 pcmd_buff = pstats->virtual_address;
614
589b3d06 615 /* 3. Read command packet element id and length. */
8fc8598e 616 element_id = pcmd_buff[0];
8fc8598e 617
589b3d06 618 /* 4. Check every received command packet content according to different
6df9f669
XR
619 element type. Because FW may aggregate RX command packet to
620 minimize transmit time between DRV and FW.*/
621 /* Add a counter to prevent the lock in the loop from being held too
622 long */
05cdf47a 623 while (total_length > 0 && exe_cnt++ < 100) {
6df9f669 624 /* We support aggregation of different cmd in the same packet */
8fc8598e
JC
625 element_id = pcmd_buff[0];
626
05cdf47a 627 switch (element_id) {
f70edb9f
XR
628 case RX_TX_FEEDBACK:
629 cmpk_handle_tx_feedback(dev, pcmd_buff);
630 cmd_length = CMPK_RX_TX_FB_SIZE;
631 break;
632
633 case RX_INTERRUPT_STATUS:
634 cmpk_handle_interrupt_status(dev, pcmd_buff);
635 cmd_length = sizeof(cmpk_intr_sta_t);
636 break;
637
638 case BOTH_QUERY_CONFIG:
639 cmpk_handle_query_config_rx(dev, pcmd_buff);
640 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
641 break;
642
643 case RX_TX_STATUS:
644 cmpk_handle_tx_status(dev, pcmd_buff);
645 cmd_length = CMPK_RX_TX_STS_SIZE;
646 break;
647
648 case RX_TX_PER_PKT_FEEDBACK:
649 /* You must at lease add a switch case element here,
650 Otherwise, we will jump to default case. */
651 cmd_length = CMPK_RX_TX_FB_SIZE;
652 break;
653
654 case RX_TX_RATE_HISTORY:
655 cmpk_handle_tx_rate_history(dev, pcmd_buff);
656 cmd_length = CMPK_TX_RAHIS_SIZE;
657 break;
658
659 default:
660
661 RT_TRACE(COMP_ERR, "---->%s():unknown CMD Element\n",
662 __func__);
663 return 1; /* This is a command packet. */
8fc8598e 664 }
8fc8598e 665
8fc8598e
JC
666 total_length -= cmd_length;
667 pcmd_buff += cmd_length;
f2a04351 668 }
8fc8598e
JC
669 return 1; /* This is a command packet. */
670
6df9f669 671}
This page took 0.4041 seconds and 5 git commands to generate.