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