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