1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTL8192D_CMD_C_
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <recv_osdep.h>
26 #include <cmd_osdep.h>
27 #include <mlme_osdep.h>
28 #include <rtw_byteorder.h>
30 #include <rtw_ioctl_set.h>
32 #include <rtl8192d_hal.h>
34 #ifndef PLATFORM_FREEBSD
42 BOOLEAN Result = _FALSE;
44 valHMETFR = rtw_read8(Adapter, REG_HMETFR);
46 //DbgPrint("CheckWriteH2C(): Reg[0x%2x] = %x\n",REG_HMETFR, valHMETFR);
48 if(((valHMETFR>>BoxNum)&BIT0) == 1)
54 #endif //PLATFORM_FREEBSD
63 BOOLEAN Result = _FALSE;
65 valHMETFR = rtw_read8(Adapter, REG_HMETFR);
66 //RT_TRACE(COMP_INIT,DBG_LOUD,("REG[%x] = %x\n", REG_HMETFR, valHMETFR));
68 // Do not seperate to 91C and 88C, we use the same setting. Suggested by SD4 Filen. 2009.12.03.
69 if(((valHMETFR>>BoxNum)&BIT0) == 0)
80 // bit [31-8] | 7 | [6-0]
81 // RSVD | CMD_EXT | CMD_ID
83 // BOX Extension 0-4 format:
87 /*****************************************
89 *| 31 - 8 |7 | 6 - 0 |
90 *| h2c_msg |Ext_bit |CMD_ID |
92 ******************************************/
93 static void _FillH2CCmd92D(_adapter* padapter, u8 ElementID, u32 CmdLen, u8* pCmdBuffer)
95 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
97 u16 BOXReg=0, BOXExtReg=0;
98 u8 BoxContent[4], BoxExtContent[2];
100 u8 U1btmp; //Read 0x1bf
101 u8 bWriteSucess = _FALSE;
102 u8 IsFwRead = _FALSE;
103 u8 WaitH2cLimmit = 100;
104 u8 WaitWriteH2cLimmit = 100;
109 padapter = GET_PRIMARY_ADAPTER(padapter);
110 pHalData = GET_HAL_DATA(padapter);
112 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
114 //DBG_8192C("FillH2CCmd : ElementID=%d \n",ElementID);
118 WaitWriteH2cLimmit--;
119 if(WaitWriteH2cLimmit == 0)
121 DBG_8192C("FillH2CCmd92C():Write H2C fail because no trigger for FW INT!!!!!!!!\n");
125 // 2. Find the last BOX number which has been writen.
126 BoxNum = pHalData->LastHMEBoxNum;
130 BOXReg = REG_HMEBOX_0;
131 BOXExtReg = REG_HMEBOX_EXT_0;
134 BOXReg = REG_HMEBOX_1;
135 BOXExtReg = REG_HMEBOX_EXT_1;
138 BOXReg = REG_HMEBOX_2;
139 BOXExtReg = REG_HMEBOX_EXT_2;
142 BOXReg = REG_HMEBOX_3;
143 BOXExtReg = REG_HMEBOX_EXT_3;
149 // 3. Check if the box content is empty.
150 IsFwRead = CheckFwReadLastH2C(padapter, BoxNum);
155 if(WaitH2cLimmit == 0)
157 DBG_8192C("FillH2CCmd92C(): Wating too long for FW read clear HMEBox(%d)!!!\n", BoxNum);
160 rtw_udelay_os(10); //us
161 IsFwRead = CheckFwReadLastH2C(padapter, BoxNum);
162 U1btmp = rtw_read8(padapter, 0x1BF);
163 //DBG_8192C("FillH2CCmd92C(): Wating for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", BoxNum, U1btmp);
166 // If Fw has not read the last H2C cmd, break and give up this H2C.
169 DBG_8192C("FillH2CCmd92C(): Write H2C register BOX[%d] fail!!!!! Fw do not read. \n", BoxNum);
173 // 4. Fill the H2C cmd into box
174 _rtw_memset(BoxContent, 0, sizeof(BoxContent));
175 _rtw_memset(BoxExtContent, 0, sizeof(BoxExtContent));
177 BoxContent[0] = ElementID; // Fill element ID
179 //DBG_8192C("FillH2CCmd92C():Write ElementID BOXReg(%4x) = %2x \n", BOXReg, ElementID);
185 BoxContent[0] &= ~(BIT7);
186 _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 1);
187 //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent));
189 for(idx= 0; idx < 4; idx++)
191 rtw_write8(padapter, BOXReg+idx, BoxContent[idx]);
197 BoxContent[0] &= ~(BIT7);
198 _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 2);
199 //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent));
200 for(idx=0; idx < 4; idx++)
202 rtw_write8(padapter, BOXReg+idx, BoxContent[idx]);
208 BoxContent[0] &= ~(BIT7);
209 _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 3);
210 //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent));
211 for(idx = 0; idx < 4 ; idx++)
213 rtw_write8(padapter, BOXReg+idx, BoxContent[idx]);
219 BoxContent[0] |= (BIT7);
220 _rtw_memcpy((u8 *)(BoxExtContent), pCmdBuffer+BufIndex, 2);
221 _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex+2, 2);
222 //PlatformEFIOWrite2Byte(Adapter, BOXExtReg, *((pu2Byte)BoxExtContent));
223 //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent));
224 for(idx = 0 ; idx < 2 ; idx ++)
226 rtw_write8(padapter, BOXExtReg+idx, BoxExtContent[idx]);
228 for(idx = 0 ; idx < 4 ; idx ++)
230 rtw_write8(padapter, BOXReg+idx, BoxContent[idx]);
236 BoxContent[0] |= (BIT7);
237 _rtw_memcpy((u8 *)(BoxExtContent), pCmdBuffer+BufIndex, 2);
238 _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex+2, 3);
239 //PlatformEFIOWrite2Byte(Adapter, BOXExtReg, *((pu2Byte)BoxExtContent));
240 //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent));
241 for(idx = 0 ; idx < 2 ; idx ++)
243 rtw_write8(padapter, BOXExtReg+idx, BoxExtContent[idx]);
245 for(idx = 0 ; idx < 4 ; idx ++)
247 rtw_write8(padapter, BOXReg+idx, BoxContent[idx]);
255 //DBG_8192C("FillH2CCmd(): BoxExtContent=0x%04x\n", *(u16*)BoxExtContent);
256 //DBG_8192C("FillH2CCmd(): BoxContent=0x%08x\n", *(u32*)BoxContent);
258 // 5. Normal chip does not need to check if the H2C cmd has be written successfully.
259 // 92D test chip does not need to check,
260 bWriteSucess = _TRUE;
262 // Record the next BoxNum
263 pHalData->LastHMEBoxNum = BoxNum+1;
264 if(pHalData->LastHMEBoxNum == 4) // loop to 0
265 pHalData->LastHMEBoxNum = 0;
267 //DBG_8192C("FillH2CCmd92C():pHalData->LastHMEBoxNum = %d\n", pHalData->LastHMEBoxNum);
271 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
286 //Adapter = ADJUST_TO_ADAPTIVE_ADAPTER(Adapter, TRUE);
288 if(Adapter->bFWReady == _FALSE)
290 DBG_8192C("FillH2CCmd92D(): return H2C cmd because of Fw download fail!!!\n");
294 _rtw_memset(tmpCmdBuf, 0, 8);
295 _rtw_memcpy(tmpCmdBuf, pCmdBuffer, CmdLen);
297 _FillH2CCmd92D(Adapter, ElementID, CmdLen, (u8 *)&tmpCmdBuf);
302 u8 rtl8192d_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf);
303 u8 rtl8192d_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
305 u8 ElementID, CmdLen;
307 struct cmd_msg_parm *pcmdmsg;
310 return H2C_PARAMETERS_ERROR;
312 pcmdmsg = (struct cmd_msg_parm*)pbuf;
313 ElementID = pcmdmsg->eid;
314 CmdLen = pcmdmsg->sz;
315 pCmdBuffer = pcmdmsg->buf;
317 FillH2CCmd92D(padapter, ElementID, CmdLen, pCmdBuffer);
323 u8 rtl8192d_set_raid_cmd(_adapter*padapter, u32 mask, u8 arg)
330 _rtw_memset(buf, 0, 5);
331 mask = cpu_to_le32( mask );
332 _rtw_memcpy(buf, &mask, 4);
335 FillH2CCmd92D(padapter, H2C_RA_MASK, 5, buf);
343 //bitmap[0:27] = tx_rate_bitmap
344 //bitmap[28:31]= Rate Adaptive id
347 void rtl8192d_Add_RateATid(PADAPTER pAdapter, u32 bitmap, u8 arg)
350 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
352 if(pHalData->fw_ractrl == _TRUE)
354 rtl8192d_set_raid_cmd(pAdapter, bitmap, arg);
358 u8 macid, init_rate, shortGIrate=_FALSE;
360 init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
364 shortGIrate = (arg&BIT(5)) ? _TRUE:_FALSE;
366 if (shortGIrate==_TRUE)
369 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
375 void rtl8192d_set_FwPwrMode_cmd(_adapter*padapter, u8 Mode)
377 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
378 u8 u1H2CSetPwrMode[3]={0};
379 u8 beacon_interval = 1;
383 DBG_871X("%s(): Mode = %d, SmartPS = %d\n", __FUNCTION__,Mode,pwrpriv->smart_ps);
385 SET_H2CCMD_PWRMODE_PARM_MODE(u1H2CSetPwrMode, Mode);
386 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CSetPwrMode, pwrpriv->smart_ps);
387 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CSetPwrMode, beacon_interval);
389 FillH2CCmd92D(padapter, H2C_SETPWRMODE, 3, u1H2CSetPwrMode);
394 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength);
395 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
397 struct rtw_ieee80211_hdr *pwlanhdr;
399 u32 rate_len, pktlen;
400 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
401 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
402 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
403 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
406 //DBG_871X("%s\n", __FUNCTION__);
408 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
410 fctrl = &(pwlanhdr->frame_ctl);
413 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
414 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
415 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
417 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
419 SetFrameSubType(pframe, WIFI_BEACON);
421 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
422 pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
424 //timestamp will be inserted by hardware
428 // beacon interval: 2 bytes
429 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
434 // capability info: 2 bytes
435 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
441 if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
443 DBG_871X("ie len=%u\n", cur_network->IELength);
444 pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
445 _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);
447 goto _ConstructBeacon;
450 //below for ad-hoc mode
453 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
455 // supported rates...
456 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
457 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
460 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
462 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
465 // IBSS Parameter Set...
466 //ATIMWindow = cur->Configuration.ATIMWindow;
468 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
475 // EXTERNDED SUPPORTED RATE
478 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
486 if ((pktlen + TXDESC_SIZE) > 512)
488 DBG_871X("beacon frame too large\n");
494 //DBG_871X("%s bcn_sz=%u\n", __FUNCTION__, pktlen);
498 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength);
499 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)
501 struct rtw_ieee80211_hdr *pwlanhdr;
503 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
504 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
506 //DBG_871X("%s\n", __FUNCTION__);
508 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
511 fctrl = &(pwlanhdr->frame_ctl);
514 SetFrameSubType(pframe, WIFI_PSPOLL);
517 SetDuration(pframe, (pmlmeinfo->aid| 0xc000));
520 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
523 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
528 void ConstructNullFunctionData(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bForcePowerSave);
529 void ConstructNullFunctionData(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bForcePowerSave)
531 struct rtw_ieee80211_hdr *pwlanhdr;
534 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
535 struct wlan_network *cur_network = &pmlmepriv->cur_network;
536 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
537 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
539 //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
541 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
543 fctrl = &(pwlanhdr->frame_ctl);
550 switch(cur_network->network.InfrastructureMode)
552 case Ndis802_11Infrastructure:
554 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
555 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
556 _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
558 case Ndis802_11APMode:
560 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
561 _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
562 _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
566 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
567 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
568 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
572 SetSeqNum(pwlanhdr, 0);
574 SetFrameSubType(pframe, WIFI_DATA_NULL);
576 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
577 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
582 void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID);
583 void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)
585 struct rtw_ieee80211_hdr *pwlanhdr;
589 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
590 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
591 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
594 //DBG_871X("%s\n", __FUNCTION__);
596 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
598 mac = myid(&(padapter->eeprompriv));
599 bssid = cur_network->MacAddress;
601 fctrl = &(pwlanhdr->frame_ctl);
603 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
604 _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
605 _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
607 SetSeqNum(pwlanhdr, 0);
608 SetFrameSubType(fctrl, WIFI_PROBERSP);
610 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
613 if(cur_network->IELength>MAX_IE_SZ)
616 _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
617 pframe += cur_network->IELength;
618 pktlen += cur_network->IELength;
624 // Description: In normal chip, we should send some packet to Hw which will be used by Fw
625 // in FW LPS mode. The function is to fill the Tx descriptor of this packets, then
626 // Fw can tell Hw to send these packet derectly.
627 // Added by tynli. 2009.10.15.
630 FillFakeTxDescriptor92D(
637 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
638 struct tx_desc *ptxdesc = (struct tx_desc *)pDesc;
641 _rtw_memset(pDesc, 0, 32);
644 ptxdesc->txdw0 |= cpu_to_le32( OWN | FSG | LSG); //own, bFirstSeg, bLastSeg;
646 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); //32 bytes for TX Desc
648 ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); // Buffer size + command header
651 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); // Fixed queue of Mgnt queue
653 //Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw.
656 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
660 ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); // Hw set sequence number
661 ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); //set bit3 to 1. Suugested by TimChen. 2009.12.29.
665 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate
667 if(pHalData->CurrentBandType92D == BAND_ON_5G)
668 ptxdesc->txdw5 |= cpu_to_le32(BIT(2));// use OFDM 6Mbps
670 #ifdef CONFIG_USB_HCI
671 // USB interface drop packet if the checksum of descriptor isn't correct.
672 // Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.).
673 rtl8192du_cal_txdesc_chksum(ptxdesc);
676 RT_PRINT_DATA(_module_rtl8712_cmd_c_, _drv_info_, "FillFakeTxDescriptor92D(): H2C Tx Desc Content ----->\n", pDesc, TXDESC_SIZE);
681 // Description: Fill the reserved packets that FW will use to RSVD page.
682 // Now we just send 4 types packet to rsvd page.
683 // (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
685 // bDLFinished - FALSE: At the first time we will send all the packets as a large packet to Hw,
686 // so we need to set the packet length to total lengh.
687 // TRUE: At the second time, we should send the first packet (default:beacon)
688 // to Hw again and set the lengh in descriptor to the real beacon lengh.
689 // 2009.10.15 by tynli.
690 void SetFwRsvdPagePkt(PADAPTER Adapter, BOOLEAN bDLFinished);
691 void SetFwRsvdPagePkt(PADAPTER Adapter, BOOLEAN bDLFinished)
693 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
694 struct xmit_frame *pmgntframe;
695 struct pkt_attrib *pattrib;
696 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
697 struct mlme_ext_priv *pmlmeext = &(Adapter->mlmeextpriv);
698 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
699 u32 BeaconLength, ProbeRspLength, PSPollLength, NullFunctionDataLength;
700 u8 *ReservedPagePacket;
701 u8 PageNum=0, U1bTmp, TxDescLen=0, TxDescOffset=0;
704 u8 u1RsvdPageLoc[3]={0};
705 BOOLEAN bDLOK = _FALSE;
707 DBG_871X("%s\n", __FUNCTION__);
709 ReservedPagePacket = (u8*)rtw_malloc(1000);
710 if(ReservedPagePacket == NULL){
711 DBG_871X("%s(): alloc ReservedPagePacket fail !!!\n", __FUNCTION__);
715 _rtw_memset(ReservedPagePacket, 0, 1000);
717 TxDescLen = 32;//TX_DESC_SIZE;
719 #ifdef CONFIG_USB_HCI
720 BufIndex = TXDESC_OFFSET;
721 TxDescOffset = TxDescLen+8; //Shift index for 8 bytes because the dummy bytes in the first descipstor.
728 ConstructBeacon(Adapter,&ReservedPagePacket[BufIndex],&BeaconLength);
730 RT_PRINT_DATA(_module_rtl8712_cmd_c_, _drv_info_,
731 "SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: BCN\n",
732 &ReservedPagePacket[BufIndex], (BeaconLength+BufIndex));
734 //--------------------------------------------------------------------
736 // When we count the first page size, we need to reserve description size for the RSVD
737 // packet, it will be filled in front of the packet in TXPKTBUF.
738 U1bTmp = (u8)PageNum_128(BeaconLength+TxDescLen);
740 // To reserved 2 pages for beacon buffer. 2010.06.24.
743 pHalData->FwRsvdPageStartOffset = PageNum;
745 BufIndex = (PageNum*128) + TxDescOffset;
748 ConstructPSPoll(Adapter, &ReservedPagePacket[BufIndex],&PSPollLength);
750 FillFakeTxDescriptor92D(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE);
752 RT_PRINT_DATA(_module_rtl8712_cmd_c_, _drv_info_,
753 "SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PS-POLL\n",
754 &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen));
756 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PageNum );
758 //------------------------------------------------------------------
760 U1bTmp = (u8)PageNum_128(PSPollLength+TxDescLen);
763 BufIndex = (PageNum*128) + TxDescOffset;
766 ConstructNullFunctionData(
768 &ReservedPagePacket[BufIndex],
769 &NullFunctionDataLength,
770 get_my_bssid(&(pmlmeinfo->network)),
773 FillFakeTxDescriptor92D(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], NullFunctionDataLength, _FALSE);
775 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, PageNum);
777 RT_PRINT_DATA(_module_rtl8712_cmd_c_, _drv_info_,
778 "SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: NULL DATA \n",
779 &ReservedPagePacket[BufIndex-TxDescLen], (NullFunctionDataLength+TxDescLen));
780 //------------------------------------------------------------------
782 U1bTmp = (u8)PageNum_128(NullFunctionDataLength+TxDescLen);
785 BufIndex = (PageNum*128) + TxDescOffset;
790 &ReservedPagePacket[BufIndex],
792 get_my_bssid(&(pmlmeinfo->network)),
795 FillFakeTxDescriptor92D(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, _FALSE);
797 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PageNum);
799 RT_PRINT_DATA(_module_rtl8712_cmd_c_, _drv_info_,
800 "SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PROBE RSP \n",
801 &ReservedPagePacket[BufIndex-TxDescLen], (ProbeRspLength-TxDescLen));
803 //------------------------------------------------------------------
805 U1bTmp = (u8)PageNum_128(ProbeRspLength+TxDescLen);
809 TotalPacketLen = (PageNum*128);
811 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
817 pattrib = &pmgntframe->attrib;
818 update_mgntframe_attrib(Adapter, pattrib);
819 pattrib->qsel = 0x10;
820 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescLen;
821 _rtw_memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
823 rtw_hal_mgnt_xmit(Adapter, pmgntframe);
829 DBG_871X("Set RSVD page location to Fw.\n");
830 FillH2CCmd92D(Adapter, H2C_RSVDPAGE, sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
831 //FillH2CCmd92D(Adapter, H2C_RSVDPAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
834 rtw_mfree(ReservedPagePacket,1000);
837 void rtl8192d_set_FwJoinBssReport_cmd(_adapter* padapter, u8 mstatus)
839 u8 u1JoinBssRptParm[1]={0};
840 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
841 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
842 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
843 BOOLEAN bRecover = _FALSE;
847 DBG_871X("%s\n", __FUNCTION__);
851 // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
852 // Suggested by filen. Added by tynli.
853 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
854 // Do not set TSF again here or vWiFi beacon DMA INT will not work.
855 //rtw_hal_set_hwreg(Adapter, HW_VAR_CORRECT_TSF, (pu1Byte)(&bTypeIbss));
856 // Hw sequende enable by dedault. 2010.06.23. by tynli.
859 pHalData->RegCR_1 |= BIT0;
860 rtw_write8(padapter, REG_CR+1, pHalData->RegCR_1);
862 // Disable Hw protection for a time which revserd for Hw sending beacon.
863 // Fix download reserved page packet fail that access collision with the protection time.
864 // 2010.05.11. Added by tynli.
865 //SetBcnCtrlReg(Adapter, 0, BIT3);
866 //SetBcnCtrlReg(Adapter, BIT4, 0);
867 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));
868 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));
870 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
871 if(pHalData->RegFwHwTxQCtrl&BIT6)
873 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));
874 pHalData->RegFwHwTxQCtrl &= (~BIT6);
875 SetFwRsvdPagePkt(padapter, 0);
877 // 2010.05.11. Added by tynli.
878 //SetBcnCtrlReg(Adapter, BIT3, 0);
879 //SetBcnCtrlReg(Adapter, 0, BIT4);
880 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));
881 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));
883 // To make sure that if there exists an adapter which would like to send beacon.
884 // If exists, the origianl value of 0x422[6] will be 1, we should check this to
885 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
886 // the beacon cannot be sent by HW.
887 // 2010.06.23. Added by tynli.
890 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));
891 pHalData->RegFwHwTxQCtrl |= BIT6;
894 // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
895 pHalData->RegCR_1 &= (~BIT0);
896 rtw_write8(padapter, REG_CR+1, pHalData->RegCR_1);
899 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1JoinBssRptParm, mstatus);
901 FillH2CCmd92D(padapter, H2C_JOINBSSRPT, 1, u1JoinBssRptParm);
907 void rtl8192d_set_p2p_ctw_period_cmd(_adapter* padapter, u8 ctwindow)
909 u8 CTWPeriod = ctwindow;
911 FillH2CCmd92D(padapter, H2C_P2P_PS_CTW_CMD, 1, (u8 *)(&CTWPeriod));
915 void rtl8192d_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)
917 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
918 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
919 struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
920 struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
923 u32 start_time, tsf_low;
930 DBG_8192C("P2P_PS_DISABLE \n");
931 _rtw_memset(p2p_ps_offload, 0 ,1);
934 DBG_8192C("P2P_PS_ENABLE \n");
935 // update CTWindow value.
936 if( pwdinfo->ctwindow > 0 )
938 p2p_ps_offload->CTWindow_En = 1;
939 ctwindow = pwdinfo->ctwindow;
940 rtl8192d_set_p2p_ctw_period_cmd(padapter, ctwindow);
941 //rtw_write16(padapter, REG_ATIMWND, ctwindow);
944 // hw only support 2 set of NoA
945 for( i=0 ; i<pwdinfo->noa_num ; i++)
947 // To control the register setting for which NOA
948 rtw_write8(padapter, 0x5CF, (i << 4));
950 p2p_ps_offload->NoA0_En = 1;
952 p2p_ps_offload->NoA1_En = 1;
954 // config P2P NoA Descriptor Register
955 rtw_write32(padapter, 0x5E0, pwdinfo->noa_duration[i]);
957 rtw_write32(padapter, 0x5E4, pwdinfo->noa_interval[i]);
959 //Get Current
\14TSF value
960 tsf_low = rtw_read32(padapter, REG_TSFTR);
962 start_time = pwdinfo->noa_start_time[i];
963 if(pwdinfo->noa_count[i] != 1)
965 while( start_time <= (tsf_low+(50*1024) ) )
967 start_time += pwdinfo->noa_interval[i];
968 if(pwdinfo->noa_count[i] != 255)
969 pwdinfo->noa_count[i]--;
972 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,start_time);
973 rtw_write32(padapter, 0x5E8, start_time);
975 rtw_write8(padapter, 0x5EC, pwdinfo->noa_count[i]);
978 if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )
981 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
983 p2p_ps_offload->Offload_En = 1;
985 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
987 p2p_ps_offload->role= 1;
988 p2p_ps_offload->AllStaSleep = 0;
992 p2p_ps_offload->role= 0;
995 p2p_ps_offload->discovery = 0;
999 DBG_8192C("P2P_PS_SCAN \n");
1000 p2p_ps_offload->discovery = 1;
1002 case P2P_PS_SCAN_DONE:
1003 DBG_8192C("P2P_PS_SCAN_DONE \n");
1004 p2p_ps_offload->discovery = 0;
1005 pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
1011 FillH2CCmd92D(padapter, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
1016 #endif // CONFIG_P2P_PS
1020 #ifdef CONFIG_TSF_RESET_OFFLOAD
1022 ask FW to Reset sync register at Beacon early interrupt
1024 u8 rtl8192d_reset_tsf(_adapter *padapter, u8 reset_port )
1030 if (IFACE_PORT0==reset_port) {
1031 buf[0] = 0x1; buf[1] = 0;
1034 buf[0] = 0x0; buf[1] = 0x1;
1036 FillH2CCmd92D(padapter, H2C_92D_RESET_TSF, 2, buf);
1042 int reset_tsf(PADAPTER Adapter, u8 reset_port )
1044 u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;
1045 u32 reg_reset_tsf_cnt = (IFACE_PORT0==reset_port) ?
1046 REG_FW_RESET_TSF_CNT_0:REG_FW_RESET_TSF_CNT_1;
1048 rtw_scan_abort(Adapter->pbuddy_adapter); /* site survey will cause reset_tsf fail */
1049 reset_cnt_after = reset_cnt_before = rtw_read8(Adapter,reg_reset_tsf_cnt);
1050 rtl8192d_reset_tsf(Adapter, reset_port);
1052 while ((reset_cnt_after == reset_cnt_before ) && (loop_cnt < 10)) {
1055 reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt);
1058 return(loop_cnt >= 10) ? _FAIL : _TRUE;
1062 #endif // CONFIG_TSF_RESET_OFFLOAD
1064 #ifdef CONFIG_WOWLAN
1066 void rtl8192d_set_wowlan_cmd(_adapter* padapter)
1070 struct recv_priv *precvpriv = &padapter->recvpriv;
1072 SETWOWLAN_PARM pwowlan_parm;
1073 struct pwrctrl_priv *pwrpriv=&padapter->pwrctrlpriv;
1077 pwowlan_parm.mode =0;
1078 pwowlan_parm.gpio_index=0;
1079 pwowlan_parm.gpio_duration=0;
1080 pwowlan_parm.second_mode =0;
1081 pwowlan_parm.reserve=0;
1085 if(pwrpriv->wowlan_mode ==_TRUE){
1087 test = rtw_read8(padapter, REG_RXPKT_NUM+2);
1089 rtw_write8(padapter, REG_RXPKT_NUM+2, test);
1090 //286 BIT(1) , not 1(means idle) do rx urb
1091 test = rtw_read8(padapter, REG_RXPKT_NUM+2) & BIT(1);
1092 //printk("line(%d) 0x286=%d\n", __LINE__, rtw_read8(padapter, REG_RXPKT_NUM+2));
1094 while(test != BIT(1))
1096 tasklet_schedule(&precvpriv->recv_tasklet);
1097 test = rtw_read8(padapter, REG_RXPKT_NUM+2) & BIT(1);
1099 //printk("line(%d) 0x286=%d\n", __LINE__, test);
1101 //mask usb se0 reset by Alex and DD
1102 test = rtw_read8(padapter, 0xf8);
1103 test &= ~(BIT(3)|BIT(4));
1104 rtw_write8(padapter, 0xf8, test);
1106 pwowlan_parm.mode |=FW_WOWLAN_FUN_EN;
1107 //printk("\n %s 1.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1108 if(pwrpriv->wowlan_pattern ==_TRUE){
1109 pwowlan_parm.mode |= FW_WOWLAN_PATTERN_MATCH;
1110 //printk("\n %s 2.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1112 if(pwrpriv->wowlan_magic ==_TRUE){
1113 //pwowlan_parm.mode |=FW_WOWLAN_MAGIC_PKT;
1114 //printk("\n %s 3.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1116 if(pwrpriv->wowlan_unicast ==_TRUE){
1117 pwowlan_parm.mode |=FW_WOWLAN_UNICAST;
1118 //printk("\n %s 4.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1121 rtl8192d_set_FwJoinBssReport_cmd(padapter, 1);
1123 //WOWLAN_GPIO_ACTIVE means GPIO high active
1124 //pwowlan_parm.mode |=FW_WOWLAN_GPIO_ACTIVE;
1125 pwowlan_parm.mode |=FW_WOWLAN_REKEY_WAKEUP;
1126 pwowlan_parm.mode |=FW_WOWLAN_DEAUTH_WAKEUP;
1129 pwowlan_parm.gpio_index=0;
1131 //duration unit is 64us
1132 pwowlan_parm.gpio_duration=0xff;
1134 pwowlan_parm.second_mode|=FW_WOWLAN_GPIO_WAKEUP_EN;
1135 pwowlan_parm.second_mode|=FW_FW_PARSE_MAGIC_PKT;
1136 //printk("\n %s 5.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1137 { u8 *ptr=(u8 *)&pwowlan_parm;
1138 printk("\n %s H2C_WO_WLAN=%x %02x:%02x:%02x:%02x:%02x \n",__FUNCTION__,H2C_WO_WLAN_CMD,ptr[0],ptr[1],ptr[2],ptr[3],ptr[4] );
1140 FillH2CCmd92D(padapter, H2C_WO_WLAN_CMD, 4, (u8 *)&pwowlan_parm);
1143 //keep alive period = 3 * 10 BCN interval
1144 pwowlan_parm.mode =3;
1145 pwowlan_parm.gpio_index=3;
1146 FillH2CCmd92D(padapter, KEEP_ALIVE_CONTROL_CMD, 2, (u8 *)&pwowlan_parm);
1147 printk("%s after KEEP_ALIVE_CONTROL_CMD register 0x81=%x \n",__FUNCTION__,rtw_read8(padapter, 0x85));
1149 pwowlan_parm.mode =1;
1150 pwowlan_parm.gpio_index=0;
1151 pwowlan_parm.gpio_duration=0;
1152 FillH2CCmd92D(padapter, DISCONNECT_DECISION_CTRL_CMD, 3, (u8 *)&pwowlan_parm);
1153 printk("%s after DISCONNECT_DECISION_CTRL_CMD register 0x81=%x \n",__FUNCTION__,rtw_read8(padapter, 0x85));
1155 //enable GPIO wakeup
1156 pwowlan_parm.mode =1;
1157 pwowlan_parm.gpio_index=0;
1158 pwowlan_parm.gpio_duration=0;
1159 FillH2CCmd92D(padapter, REMOTE_WAKE_CTRL_CMD, 1, (u8 *)&pwowlan_parm);
1160 printk("%s after DISCONNECT_DECISION_CTRL_CMD register \n",__FUNCTION__);
1164 FillH2CCmd92D(padapter, H2C_WO_WLAN_CMD, 4, (u8 *)&pwowlan_parm);
1173 #endif //CONFIG_WOWLAN