rtl8812a_cmd.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  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.
  8. *
  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
  12. * more details.
  13. *
  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
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTL8812A_CMD_C_
  21. //#include <drv_types.h>
  22. #include <rtl8812a_hal.h>
  23. #define CONFIG_H2C_EF
  24. #define RTL8812_MAX_H2C_BOX_NUMS 4
  25. #define RTL8812_MAX_CMD_LEN 7
  26. #define RTL8812_MESSAGE_BOX_SIZE 4
  27. #define RTL8812_EX_MESSAGE_BOX_SIZE 4
  28. static u8 _is_fw_read_cmd_down(_adapter* padapter, u8 msgbox_num)
  29. {
  30. u8 read_down = _FALSE;
  31. int retry_cnts = 100;
  32. u8 valid;
  33. //DBG_8192C(" _is_fw_read_cmd_down ,reg_1cc(%x),msg_box(%d)...\n",rtw_read8(padapter,REG_HMETFR),msgbox_num);
  34. do{
  35. valid = rtw_read8(padapter,REG_HMETFR) & BIT(msgbox_num);
  36. if(0 == valid ){
  37. read_down = _TRUE;
  38. }
  39. #ifdef CONFIG_WOWLAN
  40. rtw_msleep_os(2);
  41. #endif
  42. }while( (!read_down) && (retry_cnts--));
  43. return read_down;
  44. }
  45. /*****************************************
  46. * H2C Msg format :
  47. * 0x1DF - 0x1D0
  48. *| 31 - 8 | 7-5 4 - 0 |
  49. *| h2c_msg |Class_ID CMD_ID |
  50. *
  51. * Extend 0x1FF - 0x1F0
  52. *|31 - 0 |
  53. *|ext_msg|
  54. ******************************************/
  55. static s32 FillH2CCmd_8812(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
  56. {
  57. u8 bcmd_down = _FALSE;
  58. s32 retry_cnts = 100;
  59. u8 h2c_box_num;
  60. u32 msgbox_addr;
  61. u32 msgbox_ex_addr;
  62. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  63. u8 cmd_idx,ext_cmd_len;
  64. u32 h2c_cmd = 0;
  65. u32 h2c_cmd_ex = 0;
  66. s32 ret = _FAIL;
  67. _func_enter_;
  68. padapter = GET_PRIMARY_ADAPTER(padapter);
  69. pHalData = GET_HAL_DATA(padapter);
  70. if(padapter->bFWReady == _FALSE)
  71. {
  72. //DBG_8192C("FillH2CCmd_8812(): return H2C cmd because fw is not ready\n");
  73. return ret;
  74. }
  75. _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
  76. if (!pCmdBuffer) {
  77. goto exit;
  78. }
  79. if (CmdLen > RTL8812_MAX_CMD_LEN) {
  80. goto exit;
  81. }
  82. if (padapter->bSurpriseRemoved == _TRUE)
  83. goto exit;
  84. //pay attention to if race condition happened in H2C cmd setting.
  85. do{
  86. h2c_box_num = pHalData->LastHMEBoxNum;
  87. if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){
  88. DBG_8192C(" fw read cmd failed...\n");
  89. goto exit;
  90. }
  91. *(u8*)(&h2c_cmd) = ElementID;
  92. if(CmdLen<=3)
  93. {
  94. _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen );
  95. }
  96. else{
  97. _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer,3);
  98. ext_cmd_len = CmdLen-3;
  99. _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer+3,ext_cmd_len );
  100. //Write Ext command
  101. msgbox_ex_addr = REG_HMEBOX_EXT0_8812 + (h2c_box_num *RTL8812_EX_MESSAGE_BOX_SIZE);
  102. #ifdef CONFIG_H2C_EF
  103. for(cmd_idx=0;cmd_idx<ext_cmd_len;cmd_idx++ ){
  104. rtw_write8(padapter,msgbox_ex_addr+cmd_idx,*((u8*)(&h2c_cmd_ex)+cmd_idx));
  105. }
  106. #else
  107. h2c_cmd_ex = le32_to_cpu( h2c_cmd_ex );
  108. rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex);
  109. #endif
  110. }
  111. // Write command
  112. msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *RTL8812_MESSAGE_BOX_SIZE);
  113. #ifdef CONFIG_H2C_EF
  114. for(cmd_idx=0;cmd_idx<RTL8812_MESSAGE_BOX_SIZE;cmd_idx++ ){
  115. rtw_write8(padapter,msgbox_addr+cmd_idx,*((u8*)(&h2c_cmd)+cmd_idx));
  116. }
  117. #else
  118. h2c_cmd = le32_to_cpu( h2c_cmd );
  119. rtw_write32(padapter,msgbox_addr, h2c_cmd);
  120. #endif
  121. bcmd_down = _TRUE;
  122. // DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n"
  123. // ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex);
  124. pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL8812_MAX_H2C_BOX_NUMS;
  125. }while((!bcmd_down) && (retry_cnts--));
  126. ret = _SUCCESS;
  127. exit:
  128. _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
  129. _func_exit_;
  130. return ret;
  131. }
  132. u8 rtl8812_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
  133. {
  134. u8 ElementID, CmdLen;
  135. u8 *pCmdBuffer;
  136. struct cmd_msg_parm *pcmdmsg;
  137. if(!pbuf)
  138. return H2C_PARAMETERS_ERROR;
  139. pcmdmsg = (struct cmd_msg_parm*)pbuf;
  140. ElementID = pcmdmsg->eid;
  141. CmdLen = pcmdmsg->sz;
  142. pCmdBuffer = pcmdmsg->buf;
  143. FillH2CCmd_8812(padapter, ElementID, CmdLen, pCmdBuffer);
  144. return H2C_SUCCESS;
  145. }
  146. u8 rtl8812_set_rssi_cmd(_adapter*padapter, u8 *param)
  147. {
  148. u8 res=_SUCCESS;
  149. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  150. _func_enter_;
  151. *((u32*) param ) = cpu_to_le32( *((u32*) param ) );
  152. FillH2CCmd_8812(padapter, H2C_8812_RSSI_REPORT, 4, param);
  153. _func_exit_;
  154. return res;
  155. }
  156. u8 Get_VHT_ENI(
  157. u32 IOTAction,
  158. u32 WirelessMode,
  159. u32 ratr_bitmap
  160. )
  161. {
  162. u8 Ret = 0;
  163. if(WirelessMode == WIRELESS_11_24AC)
  164. {
  165. if(ratr_bitmap & 0xfff00000) // Mix , 2SS
  166. Ret = 3;
  167. else // Mix, 1SS
  168. Ret = 2;
  169. }
  170. else if(WirelessMode == WIRELESS_11_5AC)
  171. {
  172. Ret = 1; // VHT
  173. }
  174. return (Ret << 4);
  175. }
  176. BOOLEAN
  177. Get_RA_ShortGI(
  178. PADAPTER Adapter,
  179. struct sta_info *psta,
  180. u8 shortGIrate
  181. )
  182. {
  183. BOOLEAN bShortGI;
  184. struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
  185. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  186. bShortGI = shortGIrate;
  187. #ifdef CONFIG_80211AC_VHT
  188. if( bShortGI &&
  189. IsSupportedVHT(psta->wireless_mode) &&
  190. (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP) &&
  191. TEST_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_ENABLE_TX)
  192. )
  193. {
  194. if(psta->vhtpriv.vht_highest_rate >= MGN_VHT2SS_MCS8)
  195. bShortGI = _FALSE;
  196. }
  197. #endif
  198. return bShortGI;
  199. }
  200. void
  201. Set_RA_LDPC_8812(
  202. struct sta_info *psta,
  203. BOOLEAN bLDPC
  204. )
  205. {
  206. if(psta == NULL)
  207. return;
  208. #ifdef CONFIG_80211AC_VHT
  209. if(psta->wireless_mode == WIRELESS_11_5AC)
  210. {
  211. if(bLDPC && TEST_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_CAP_TX))
  212. SET_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_ENABLE_TX);
  213. else
  214. CLEAR_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_ENABLE_TX);
  215. }
  216. else if(IsSupportedTxHT(psta->wireless_mode) || IsSupportedVHT(psta->wireless_mode))
  217. {
  218. if(bLDPC && TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_CAP_TX))
  219. SET_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_ENABLE_TX);
  220. else
  221. CLEAR_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_ENABLE_TX);
  222. }
  223. #endif
  224. //DBG_871X("MacId %d bLDPC %d\n", psta->mac_id, bLDPC);
  225. }
  226. u8
  227. Get_RA_LDPC_8812(
  228. struct sta_info *psta
  229. )
  230. {
  231. u8 bLDPC = 0;
  232. if(psta->mac_id == 1)
  233. bLDPC = 0;
  234. else if(psta != NULL)
  235. {
  236. #ifdef CONFIG_80211AC_VHT
  237. if(IsSupportedVHT(psta->wireless_mode))
  238. {
  239. if(TEST_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_CAP_TX))
  240. bLDPC = 1;
  241. else
  242. bLDPC = 0;
  243. }
  244. else if(IsSupportedTxHT(psta->wireless_mode))
  245. {
  246. if(TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_CAP_TX))
  247. bLDPC =1;
  248. else
  249. bLDPC =0;
  250. }
  251. else
  252. #endif
  253. bLDPC = 0;
  254. }
  255. return (bLDPC << 2);
  256. }
  257. void rtl8812_set_raid_cmd(PADAPTER padapter, u32 bitmap, u8* arg)
  258. {
  259. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  260. struct dm_priv *pdmpriv = &pHalData->dmpriv;
  261. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  262. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  263. struct sta_info *psta;
  264. u8 macid, init_rate, raid, shortGIrate=_FALSE;
  265. _func_enter_;
  266. macid = arg[0];
  267. raid = arg[1];
  268. shortGIrate = arg[2];
  269. init_rate = arg[3];
  270. psta = pmlmeinfo->FW_sta_info[macid].psta;
  271. if(psta == NULL)
  272. {
  273. return;
  274. }
  275. if(pHalData->fw_ractrl == _TRUE)
  276. {
  277. u8 H2CCommand[7] ={0};
  278. shortGIrate = Get_RA_ShortGI(padapter, psta, shortGIrate);
  279. H2CCommand[0] = macid;
  280. H2CCommand[1] = (raid & 0x1F) | (shortGIrate?0x80:0x00) ;
  281. H2CCommand[2] = (pmlmeext->cur_bwmode & 0x3) |Get_RA_LDPC_8812(psta) |Get_VHT_ENI(0, psta->wireless_mode, bitmap);
  282. H2CCommand[3] = (u8)(bitmap & 0x000000ff);
  283. H2CCommand[4] = (u8)((bitmap & 0x0000ff00) >>8);
  284. H2CCommand[5] = (u8)((bitmap & 0x00ff0000) >> 16);
  285. H2CCommand[6] = (u8)((bitmap & 0xff000000) >> 24);
  286. DBG_871X("rtl8812_set_raid_cmd, bitmap=0x%x, mac_id=0x%x, raid=0x%x, shortGIrate=%x\n", bitmap, macid, raid, shortGIrate);
  287. FillH2CCmd_8812(padapter, H2C_8812_RA_MASK, 7, H2CCommand);
  288. }
  289. if (shortGIrate==_TRUE)
  290. init_rate |= BIT(7);
  291. pdmpriv->INIDATA_RATE[macid] = init_rate;
  292. _func_exit_;
  293. }
  294. void rtl8812_Add_RateATid(PADAPTER pAdapter, u32 bitmap, u8* arg, u8 rssi_level)
  295. {
  296. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
  297. u8 macid;
  298. macid = arg[0];
  299. #ifdef CONFIG_ODM_REFRESH_RAMASK
  300. if(rssi_level != DM_RATR_STA_INIT)
  301. bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, macid, bitmap, rssi_level);
  302. #endif //CONFIG_ODM_REFRESH_RAMASK
  303. rtl8812_set_raid_cmd(pAdapter, bitmap, arg);
  304. }
  305. void rtl8812_set_FwPwrMode_cmd(PADAPTER padapter, u8 PSMode)
  306. {
  307. u8 u1H2CSetPwrMode[5]={0};
  308. struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
  309. u8 Mode = 0, RLBM = 0, PowerState = 0, LPSAwakeIntvl = 1;
  310. _func_enter_;
  311. DBG_871X("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __FUNCTION__,
  312. PSMode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable);
  313. switch(PSMode)
  314. {
  315. case PS_MODE_ACTIVE:
  316. Mode = 0;
  317. break;
  318. case PS_MODE_MIN:
  319. Mode = 1;
  320. break;
  321. case PS_MODE_MAX:
  322. RLBM = 1;
  323. Mode = 1;
  324. break;
  325. case PS_MODE_DTIM:
  326. RLBM = 2;
  327. Mode = 1;
  328. break;
  329. case PS_MODE_UAPSD_WMM:
  330. Mode = 2;
  331. break;
  332. default:
  333. Mode = 0;
  334. break;
  335. }
  336. if (Mode > PS_MODE_ACTIVE) {
  337. PowerState = 0x00;// AllON(0x0C), RFON(0x04), RFOFF(0x00)
  338. #ifdef CONFIG_EXT_CLK
  339. Mode |= BIT(7);//supporting 26M XTAL CLK_Request feature.
  340. #endif //CONFIG_EXT_CLK
  341. } else {
  342. PowerState = 0x0C;// AllON(0x0C), RFON(0x04), RFOFF(0x00)
  343. }
  344. // 0: Active, 1: LPS, 2: WMMPS
  345. SET_8812_H2CCMD_PWRMODE_PARM_MODE(u1H2CSetPwrMode, Mode);
  346. // 0:Min, 1:Max , 2:User define
  347. SET_8812_H2CCMD_PWRMODE_PARM_RLBM(u1H2CSetPwrMode, RLBM);
  348. // (LPS) smart_ps: 0: PS_Poll, 1: PS_Poll , 2: NullData
  349. // (WMM)smart_ps: 0:PS_Poll, 1:NullData
  350. SET_8812_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CSetPwrMode, pwrpriv->smart_ps);
  351. // AwakeInterval: Unit is beacon interval, this field is only valid in PS_DTIM mode
  352. SET_8812_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CSetPwrMode, LPSAwakeIntvl);
  353. // (WMM only)bAllQueueUAPSD
  354. SET_8812_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1H2CSetPwrMode, padapter->registrypriv.uapsd_enable);
  355. // AllON(0x0C), RFON(0x04), RFOFF(0x00)
  356. SET_8812_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CSetPwrMode, PowerState);
  357. FillH2CCmd_8812(padapter, H2C_8812_SETPWRMODE, sizeof(u1H2CSetPwrMode), (u8 *)&u1H2CSetPwrMode);
  358. _func_exit_;
  359. }
  360. void rtl8812_set_FwMediaStatus_cmd(PADAPTER padapter, u16 mstatus_rpt )
  361. {
  362. u8 u1JoinBssRptParm[3]={0};
  363. u8 mstatus, macId, macId_Ind = 0, macId_End = 0;
  364. mstatus = (u8) (mstatus_rpt & 0xFF);
  365. macId = (u8)(mstatus_rpt >> 8) ;
  366. SET_8812_H2CCMD_MSRRPT_PARM_OPMODE(u1JoinBssRptParm, mstatus);
  367. SET_8812_H2CCMD_MSRRPT_PARM_MACID_IND(u1JoinBssRptParm, macId_Ind);
  368. SET_8812_H2CCMD_MSRRPT_PARM_MACID(u1JoinBssRptParm, macId);
  369. SET_8812_H2CCMD_MSRRPT_PARM_MACID_END(u1JoinBssRptParm, macId_End);
  370. DBG_871X("[MacId], Set MacId Ctrl(original) = 0x%x \n", u1JoinBssRptParm[0]<<16|u1JoinBssRptParm[1]<<8|u1JoinBssRptParm[2]);
  371. FillH2CCmd_8812(padapter, H2C_8812_MSRRPT, 3, u1JoinBssRptParm);
  372. }
  373. void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
  374. {
  375. struct rtw_ieee80211_hdr *pwlanhdr;
  376. u16 *fctrl;
  377. u32 rate_len, pktlen;
  378. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  379. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  380. WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
  381. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  382. //DBG_871X("%s\n", __FUNCTION__);
  383. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  384. fctrl = &(pwlanhdr->frame_ctl);
  385. *(fctrl) = 0;
  386. _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
  387. _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
  388. _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
  389. SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
  390. //pmlmeext->mgnt_seq++;
  391. SetFrameSubType(pframe, WIFI_BEACON);
  392. pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
  393. pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
  394. //timestamp will be inserted by hardware
  395. pframe += 8;
  396. pktlen += 8;
  397. // beacon interval: 2 bytes
  398. _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
  399. pframe += 2;
  400. pktlen += 2;
  401. // capability info: 2 bytes
  402. _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
  403. pframe += 2;
  404. pktlen += 2;
  405. if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
  406. {
  407. //DBG_871X("ie len=%d\n", cur_network->IELength);
  408. pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
  409. _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);
  410. goto _ConstructBeacon;
  411. }
  412. //below for ad-hoc mode
  413. // SSID
  414. pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
  415. // supported rates...
  416. rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
  417. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
  418. // DS parameter set
  419. pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
  420. if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
  421. {
  422. u32 ATIMWindow;
  423. // IBSS Parameter Set...
  424. //ATIMWindow = cur->Configuration.ATIMWindow;
  425. ATIMWindow = 0;
  426. pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
  427. }
  428. //todo: ERP IE
  429. // EXTERNDED SUPPORTED RATE
  430. if (rate_len > 8)
  431. {
  432. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
  433. }
  434. //todo:HT for adhoc
  435. _ConstructBeacon:
  436. if ((pktlen + TXDESC_SIZE) > 512)
  437. {
  438. DBG_871X("beacon frame too large\n");
  439. return;
  440. }
  441. *pLength = pktlen;
  442. //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);
  443. }
  444. void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)
  445. {
  446. struct rtw_ieee80211_hdr *pwlanhdr;
  447. u16 *fctrl;
  448. u32 pktlen;
  449. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  450. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  451. //DBG_871X("%s\n", __FUNCTION__);
  452. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  453. // Frame control.
  454. fctrl = &(pwlanhdr->frame_ctl);
  455. *(fctrl) = 0;
  456. SetPwrMgt(fctrl);
  457. SetFrameSubType(pframe, WIFI_PSPOLL);
  458. // AID.
  459. SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
  460. // BSSID.
  461. _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  462. // TA.
  463. _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
  464. *pLength = 16;
  465. }
  466. void ConstructNullFunctionData(
  467. PADAPTER padapter,
  468. u8 *pframe,
  469. u32 *pLength,
  470. u8 *StaAddr,
  471. u8 bQoS,
  472. u8 AC,
  473. u8 bEosp,
  474. u8 bForcePowerSave)
  475. {
  476. struct rtw_ieee80211_hdr *pwlanhdr;
  477. u16 *fctrl;
  478. u32 pktlen;
  479. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  480. struct wlan_network *cur_network = &pmlmepriv->cur_network;
  481. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  482. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  483. //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
  484. pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;
  485. fctrl = &pwlanhdr->frame_ctl;
  486. *(fctrl) = 0;
  487. if (bForcePowerSave)
  488. {
  489. SetPwrMgt(fctrl);
  490. }
  491. switch(cur_network->network.InfrastructureMode)
  492. {
  493. case Ndis802_11Infrastructure:
  494. SetToDs(fctrl);
  495. _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  496. _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
  497. _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
  498. break;
  499. case Ndis802_11APMode:
  500. SetFrDs(fctrl);
  501. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  502. _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  503. _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
  504. break;
  505. case Ndis802_11IBSS:
  506. default:
  507. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  508. _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
  509. _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  510. break;
  511. }
  512. SetSeqNum(pwlanhdr, 0);
  513. if (bQoS == _TRUE) {
  514. struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
  515. SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
  516. pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos*)pframe;
  517. SetPriority(&pwlanqoshdr->qc, AC);
  518. SetEOSP(&pwlanqoshdr->qc, bEosp);
  519. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
  520. } else {
  521. SetFrameSubType(pframe, WIFI_DATA_NULL);
  522. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  523. }
  524. *pLength = pktlen;
  525. }
  526. void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)
  527. {
  528. struct rtw_ieee80211_hdr *pwlanhdr;
  529. u16 *fctrl;
  530. u8 *mac, *bssid;
  531. u32 pktlen;
  532. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  533. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  534. WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
  535. //DBG_871X("%s\n", __FUNCTION__);
  536. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  537. mac = myid(&(padapter->eeprompriv));
  538. bssid = cur_network->MacAddress;
  539. fctrl = &(pwlanhdr->frame_ctl);
  540. *(fctrl) = 0;
  541. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  542. _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
  543. _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
  544. SetSeqNum(pwlanhdr, 0);
  545. SetFrameSubType(fctrl, WIFI_PROBERSP);
  546. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  547. pframe += pktlen;
  548. if(cur_network->IELength>MAX_IE_SZ)
  549. return;
  550. _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
  551. pframe += cur_network->IELength;
  552. pktlen += cur_network->IELength;
  553. *pLength = pktlen;
  554. }
  555. // To check if reserved page content is destroyed by beacon beacuse beacon is too large.
  556. // 2010.06.23. Added by tynli.
  557. VOID
  558. CheckFwRsvdPageContent(
  559. IN PADAPTER Adapter
  560. )
  561. {
  562. HAL_DATA_TYPE* pHalData = GET_HAL_DATA(Adapter);
  563. u32 MaxBcnPageNum;
  564. if(pHalData->FwRsvdPageStartOffset != 0)
  565. {
  566. /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize);
  567. RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset),
  568. ("CheckFwRsvdPageContent(): The reserved page content has been"\
  569. "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!",
  570. MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/
  571. }
  572. }
  573. //
  574. // Description: Get the reserved page number in Tx packet buffer.
  575. // Retrun value: the page number.
  576. // 2012.08.09, by tynli.
  577. //
  578. u8
  579. GetTxBufferRsvdPageNum8812(
  580. IN PADAPTER Adapter,
  581. IN BOOLEAN bWoWLANBoundary
  582. )
  583. {
  584. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  585. u8 RsvdPageNum=0;
  586. u8 TxPageBndy= LAST_ENTRY_OF_TX_PKT_BUFFER_8812; // default reseved 1 page for the IC type which is undefined.
  587. if(bWoWLANBoundary)
  588. {
  589. rtw_hal_get_def_var(Adapter, HAL_DEF_TX_PAGE_BOUNDARY_WOWLAN, (u8 *)&TxPageBndy);
  590. }
  591. else
  592. {
  593. rtw_hal_get_def_var(Adapter, HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&TxPageBndy);
  594. }
  595. RsvdPageNum = LAST_ENTRY_OF_TX_PKT_BUFFER_8812 -TxPageBndy + 1;
  596. return RsvdPageNum;
  597. }
  598. //
  599. // Description: Fill the reserved packets that FW will use to RSVD page.
  600. // Now we just send 4 types packet to rsvd page.
  601. // (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
  602. // Input:
  603. // bDLFinished - FALSE: At the first time we will send all the packets as a large packet to Hw,
  604. // so we need to set the packet length to total lengh.
  605. // TRUE: At the second time, we should send the first packet (default:beacon)
  606. // to Hw again and set the lengh in descriptor to the real beacon lengh.
  607. // 2009.10.15 by tynli.
  608. static void SetFwRsvdPagePkt_8812(PADAPTER padapter, BOOLEAN bDLFinished)
  609. {
  610. PHAL_DATA_TYPE pHalData;
  611. struct xmit_frame *pcmdframe;
  612. struct pkt_attrib *pattrib;
  613. struct xmit_priv *pxmitpriv;
  614. struct mlme_ext_priv *pmlmeext;
  615. struct mlme_ext_info *pmlmeinfo;
  616. u32 PSPollLength, NullFunctionDataLength, QosNullLength;
  617. u32 BcnLen;
  618. u8 TotalPageNum=0, CurtPktPageNum=0, TxDescLen=0, RsvdPageNum=0;
  619. u8 *ReservedPagePacket;
  620. u8 RsvdPageLoc[5] = {0};
  621. u16 BufIndex=0, PageSize = 256;
  622. u32 TotalPacketLen, MaxRsvdPageBufSize=0;;
  623. //DBG_871X("%s\n", __FUNCTION__);
  624. pHalData = GET_HAL_DATA(padapter);
  625. pxmitpriv = &padapter->xmitpriv;
  626. pmlmeext = &padapter->mlmeextpriv;
  627. pmlmeinfo = &pmlmeext->mlmext_info;
  628. if(IS_HARDWARE_TYPE_8812(padapter))
  629. PageSize = 512;
  630. else if (IS_HARDWARE_TYPE_8821(padapter))
  631. PageSize = PAGE_SIZE_TX_8821A;
  632. // <tynli_note> The function SetFwRsvdPagePkt_8812() input must be added a value "bDLWholePackets" to
  633. // decide if download wowlan packets, and use "bDLWholePackets" to be GetTxBufferRsvdPageNum8812() 2nd input value.
  634. RsvdPageNum = GetTxBufferRsvdPageNum8812(padapter, _FALSE);
  635. MaxRsvdPageBufSize = RsvdPageNum*PageSize;
  636. pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv, MaxRsvdPageBufSize);
  637. if (pcmdframe == NULL) {
  638. return;
  639. }
  640. ReservedPagePacket = pcmdframe->buf_addr;
  641. TxDescLen = TXDESC_SIZE;//The desc lengh in Tx packet buffer of 8812A is 40 bytes.
  642. //(1) beacon
  643. BufIndex = TXDESC_OFFSET;
  644. ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BcnLen);
  645. // When we count the first page size, we need to reserve description size for the RSVD
  646. // packet, it will be filled in front of the packet in TXPKTBUF.
  647. CurtPktPageNum = (u8)PageNum(BcnLen+TxDescLen, PageSize);
  648. if(bDLFinished)
  649. {
  650. TotalPageNum += CurtPktPageNum;
  651. TotalPacketLen = (TotalPageNum*PageSize);
  652. DBG_871X("%s(): Beacon page size = %d\n",__FUNCTION__,TotalPageNum);
  653. }
  654. else
  655. {
  656. TotalPageNum += CurtPktPageNum;
  657. pHalData->FwRsvdPageStartOffset = TotalPageNum;
  658. BufIndex += (CurtPktPageNum*PageSize);
  659. if(BufIndex > MaxRsvdPageBufSize)
  660. {
  661. DBG_871X("%s(): Beacon: The rsvd page size is not enough!!BufIndex %d, MaxRsvdPageBufSize %d\n",__FUNCTION__,
  662. BufIndex,MaxRsvdPageBufSize);
  663. goto error;
  664. }
  665. //(2) ps-poll
  666. ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
  667. rtl8812a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE, _FALSE);
  668. SET_8812_H2CCMD_RSVDPAGE_LOC_PSPOLL(RsvdPageLoc, TotalPageNum);
  669. //DBG_871X("SetFwRsvdPagePkt_8812(): HW_VAR_SET_TX_CMD: PS-POLL %p %d\n",
  670. // &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen));
  671. CurtPktPageNum = (u8)PageNum(PSPollLength+TxDescLen, PageSize);
  672. BufIndex += (CurtPktPageNum*PageSize);
  673. TotalPageNum += CurtPktPageNum;
  674. if(BufIndex > MaxRsvdPageBufSize)
  675. {
  676. DBG_871X("%s(): ps-poll: The rsvd page size is not enough!!BufIndex %d, MaxRsvdPageBufSize %d\n",__FUNCTION__,
  677. BufIndex,MaxRsvdPageBufSize);
  678. goto error;
  679. }
  680. //(3) null data
  681. ConstructNullFunctionData(
  682. padapter,
  683. &ReservedPagePacket[BufIndex],
  684. &NullFunctionDataLength,
  685. get_my_bssid(&pmlmeinfo->network),
  686. _FALSE, 0, 0, _FALSE);
  687. rtl8812a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullFunctionDataLength, _FALSE, _FALSE);
  688. SET_8812_H2CCMD_RSVDPAGE_LOC_NULL_DATA(RsvdPageLoc, TotalPageNum);
  689. //DBG_871X("SetFwRsvdPagePkt_8812(): HW_VAR_SET_TX_CMD: NULL DATA %p %d\n",
  690. // &ReservedPagePacket[BufIndex-TxDescLen], (NullFunctionDataLength+TxDescLen));
  691. CurtPktPageNum = (u8)PageNum(NullFunctionDataLength+TxDescLen, PageSize);
  692. BufIndex += (CurtPktPageNum*PageSize);
  693. TotalPageNum += CurtPktPageNum;
  694. if(BufIndex > MaxRsvdPageBufSize)
  695. {
  696. DBG_871X("%s(): Null-data: The rsvd page size is not enough!!BufIndex %d, MaxRsvdPageBufSize %d\n",__FUNCTION__,
  697. BufIndex,MaxRsvdPageBufSize);
  698. goto error;
  699. }
  700. //(5) Qos null data
  701. ConstructNullFunctionData(
  702. padapter,
  703. &ReservedPagePacket[BufIndex],
  704. &QosNullLength,
  705. get_my_bssid(&pmlmeinfo->network),
  706. _TRUE, 0, 0, _FALSE);
  707. rtl8812a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, _FALSE, _FALSE);
  708. SET_8812_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(RsvdPageLoc, TotalPageNum);
  709. //DBG_871X("SetFwRsvdPagePkt_8812(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n",
  710. // &ReservedPagePacket[BufIndex-TxDescLen], (QosNullLength+TxDescLen));
  711. CurtPktPageNum = (u8)PageNum(QosNullLength+TxDescLen, PageSize);
  712. BufIndex += (CurtPktPageNum*PageSize);
  713. TotalPageNum += CurtPktPageNum;
  714. TotalPacketLen = (TotalPageNum * PageSize);
  715. }
  716. if(TotalPacketLen > MaxRsvdPageBufSize)
  717. {
  718. DBG_871X("%s(): ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",__FUNCTION__,
  719. TotalPacketLen,MaxRsvdPageBufSize);
  720. goto error;
  721. }
  722. else
  723. {
  724. // update attribute
  725. pattrib = &pcmdframe->attrib;
  726. update_mgntframe_attrib(padapter, pattrib);
  727. pattrib->qsel = 0x10;
  728. pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescLen;
  729. dump_mgntframe_and_wait(padapter, pcmdframe, 100);
  730. }
  731. if(!bDLFinished)
  732. {
  733. DBG_871X("%s: Set RSVD page location to Fw ,TotalPacketLen(%d), TotalPageNum(%d)\n", __FUNCTION__,TotalPacketLen,TotalPageNum);
  734. FillH2CCmd_8812(padapter, H2C_8812_RSVDPAGE, 5, RsvdPageLoc);
  735. }
  736. rtw_free_cmd_xmitbuf(pxmitpriv);
  737. return;
  738. error:
  739. rtw_free_cmdxmitframe(pxmitpriv, pcmdframe);
  740. }
  741. void rtl8812_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus)
  742. {
  743. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  744. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  745. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  746. BOOLEAN bSendBeacon=_FALSE;
  747. BOOLEAN bcn_valid = _FALSE;
  748. u8 DLBcnCount=0;
  749. u32 poll = 0;
  750. _func_enter_;
  751. DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);
  752. if(mstatus == 1)
  753. {
  754. // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
  755. // Suggested by filen. Added by tynli.
  756. rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
  757. // Do not set TSF again here or vWiFi beacon DMA INT will not work.
  758. //correct_TSF(padapter, pmlmeext);
  759. // Hw sequende enable by dedault. 2010.06.23. by tynli.
  760. //rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));
  761. //rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);
  762. //Set REG_CR bit 8. DMA beacon by SW.
  763. pHalData->RegCR_1 |= BIT0;
  764. rtw_write8(padapter, REG_CR+1, pHalData->RegCR_1);
  765. // Disable Hw protection for a time which revserd for Hw sending beacon.
  766. // Fix download reserved page packet fail that access collision with the protection time.
  767. // 2010.05.11. Added by tynli.
  768. //SetBcnCtrlReg(padapter, 0, BIT3);
  769. //SetBcnCtrlReg(padapter, BIT4, 0);
  770. rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));
  771. rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));
  772. if(pHalData->RegFwHwTxQCtrl&BIT6)
  773. {
  774. DBG_871X("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
  775. bSendBeacon = _TRUE;
  776. }
  777. // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
  778. rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));
  779. pHalData->RegFwHwTxQCtrl &= (~BIT6);
  780. // Clear beacon valid check bit.
  781. rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
  782. DLBcnCount = 0;
  783. poll = 0;
  784. do
  785. {
  786. // download rsvd page.
  787. SetFwRsvdPagePkt_8812(padapter, _FALSE);
  788. DLBcnCount++;
  789. do
  790. {
  791. rtw_yield_os();
  792. //rtw_mdelay_os(10);
  793. // check rsvd page download OK.
  794. rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));
  795. poll++;
  796. } while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
  797. }while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
  798. //RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage88ES(): 1 Download RSVD page failed!\n"));
  799. if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
  800. {
  801. }
  802. else if(!bcn_valid)
  803. DBG_871X("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __FUNCTION__ ,DLBcnCount, poll);
  804. else
  805. DBG_871X("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __FUNCTION__, DLBcnCount, poll);
  806. //
  807. // We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower)
  808. // becuase we need to free the Tx BCN Desc which is used by the first reserved page packet.
  809. // At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return
  810. // the beacon TCB in the following code. 2011.11.23. by tynli.
  811. //
  812. //if(bcn_valid && padapter->bEnterPnpSleep)
  813. if(0)
  814. {
  815. if(bSendBeacon)
  816. {
  817. rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
  818. DLBcnCount = 0;
  819. poll = 0;
  820. do
  821. {
  822. SetFwRsvdPagePkt_8812(padapter, _TRUE);
  823. DLBcnCount++;
  824. do
  825. {
  826. rtw_yield_os();
  827. //rtw_mdelay_os(10);
  828. // check rsvd page download OK.
  829. rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));
  830. poll++;
  831. } while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
  832. }while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
  833. //RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage(): 2 Download RSVD page failed!\n"));
  834. if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
  835. {
  836. }
  837. else if(!bcn_valid)
  838. DBG_871X("%s: 2 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __FUNCTION__ ,DLBcnCount, poll);
  839. else
  840. DBG_871X("%s: 2 Download RSVD success! DLBcnCount:%u, poll:%u\n", __FUNCTION__, DLBcnCount, poll);
  841. }
  842. }
  843. // Enable Bcn
  844. //SetBcnCtrlReg(padapter, BIT3, 0);
  845. //SetBcnCtrlReg(padapter, 0, BIT4);
  846. rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));
  847. rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));
  848. // To make sure that if there exists an adapter which would like to send beacon.
  849. // If exists, the origianl value of 0x422[6] will be 1, we should check this to
  850. // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
  851. // the beacon cannot be sent by HW.
  852. // 2010.06.23. Added by tynli.
  853. if(bSendBeacon)
  854. {
  855. rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));
  856. pHalData->RegFwHwTxQCtrl |= BIT6;
  857. }
  858. //
  859. // Update RSVD page location H2C to Fw.
  860. //
  861. if(bcn_valid)
  862. {
  863. rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
  864. DBG_871X("Set RSVD page location to Fw.\n");
  865. //FillH2CCmd88E(Adapter, H2C_88E_RSVDPAGE, H2C_RSVDPAGE_LOC_LENGTH, pMgntInfo->u1RsvdPageLoc);
  866. }
  867. // Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.
  868. //if(!padapter->bEnterPnpSleep)
  869. {
  870. // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
  871. pHalData->RegCR_1 &= (~BIT0);
  872. rtw_write8(padapter, REG_CR+1, pHalData->RegCR_1);
  873. }
  874. }
  875. #ifdef CONFIG_WOWLAN
  876. if (padapter->pwrctrlpriv.wowlan_mode){
  877. u16 media_status;
  878. media_status = mstatus;
  879. rtl8812_set_FwMediaStatus_cmd(padapter, media_status);
  880. DBG_871X_LEVEL(_drv_info_, "%s wowlan_mode is on\n", __func__);
  881. } else {
  882. DBG_871X_LEVEL(_drv_info_, "%s wowlan_mode is off\n", __func__);
  883. }
  884. #endif //CONFIG_WOWLAN
  885. _func_exit_;
  886. }
  887. #ifdef CONFIG_P2P_PS
  888. void rtl8812_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)
  889. {
  890. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  891. struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
  892. struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
  893. u8 *p2p_ps_offload = (u8 *)&pHalData->p2p_ps_offload;
  894. u8 i;
  895. _func_enter_;
  896. #if 1
  897. switch(p2p_ps_state)
  898. {
  899. case P2P_PS_DISABLE:
  900. DBG_8192C("P2P_PS_DISABLE \n");
  901. _rtw_memset(p2p_ps_offload, 0, 1);
  902. break;
  903. case P2P_PS_ENABLE:
  904. DBG_8192C("P2P_PS_ENABLE \n");
  905. // update CTWindow value.
  906. if( pwdinfo->ctwindow > 0 )
  907. {
  908. SET_8812_H2CCMD_P2P_PS_OFFLOAD_CTWINDOW_EN(p2p_ps_offload, 1);
  909. rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
  910. }
  911. // hw only support 2 set of NoA
  912. for( i=0 ; i<pwdinfo->noa_num ; i++)
  913. {
  914. // To control the register setting for which NOA
  915. rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
  916. if(i == 0) {
  917. SET_8812_H2CCMD_P2P_PS_OFFLOAD_NOA0_EN(p2p_ps_offload, 1);
  918. } else {
  919. SET_8812_H2CCMD_P2P_PS_OFFLOAD_NOA1_EN(p2p_ps_offload, 1);
  920. }
  921. // config P2P NoA Descriptor Register
  922. //DBG_8192C("%s(): noa_duration = %x\n",__FUNCTION__,pwdinfo->noa_duration[i]);
  923. rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
  924. //DBG_8192C("%s(): noa_interval = %x\n",__FUNCTION__,pwdinfo->noa_interval[i]);
  925. rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
  926. //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,pwdinfo->noa_start_time[i]);
  927. rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
  928. //DBG_8192C("%s(): noa_count = %x\n",__FUNCTION__,pwdinfo->noa_count[i]);
  929. rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
  930. }
  931. if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )
  932. {
  933. // rst p2p circuit
  934. rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
  935. SET_8812_H2CCMD_P2P_PS_OFFLOAD_ENABLE(p2p_ps_offload, 1);
  936. if(pwdinfo->role == P2P_ROLE_GO)
  937. {
  938. // 1: Owner, 0: Client
  939. SET_8812_H2CCMD_P2P_PS_OFFLOAD_ROLE(p2p_ps_offload, 1);
  940. SET_8812_H2CCMD_P2P_PS_OFFLOAD_ALLSTASLEEP(p2p_ps_offload, 0);
  941. }
  942. else
  943. {
  944. // 1: Owner, 0: Client
  945. SET_8812_H2CCMD_P2P_PS_OFFLOAD_ROLE(p2p_ps_offload, 0);
  946. }
  947. SET_8812_H2CCMD_P2P_PS_OFFLOAD_DISCOVERY(p2p_ps_offload, 0);
  948. }
  949. break;
  950. case P2P_PS_SCAN:
  951. DBG_8192C("P2P_PS_SCAN \n");
  952. SET_8812_H2CCMD_P2P_PS_OFFLOAD_DISCOVERY(p2p_ps_offload, 1);
  953. break;
  954. case P2P_PS_SCAN_DONE:
  955. DBG_8192C("P2P_PS_SCAN_DONE \n");
  956. SET_8812_H2CCMD_P2P_PS_OFFLOAD_DISCOVERY(p2p_ps_offload, 0);
  957. pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
  958. break;
  959. default:
  960. break;
  961. }
  962. DBG_871X("P2P_PS_OFFLOAD : %x\n", p2p_ps_offload[0]);
  963. FillH2CCmd_8812(padapter, H2C_8812_P2P_PS_OFFLOAD, 1, p2p_ps_offload);
  964. #endif
  965. _func_exit_;
  966. }
  967. #endif //CONFIG_P2P
  968. #ifdef CONFIG_TSF_RESET_OFFLOAD
  969. /*
  970. ask FW to Reset sync register at Beacon early interrupt
  971. */
  972. u8 rtl8812_reset_tsf(_adapter *padapter, u8 reset_port )
  973. {
  974. u8 buf[2];
  975. u8 res=_SUCCESS;
  976. s32 ret;
  977. _func_enter_;
  978. if (IFACE_PORT0==reset_port) {
  979. buf[0] = 0x1; buf[1] = 0;
  980. } else{
  981. buf[0] = 0x0; buf[1] = 0x1;
  982. }
  983. ret = FillH2CCmd_8812(padapter, H2C_8812_TSF_RESET, 2, buf);
  984. _func_exit_;
  985. return res;
  986. }
  987. int reset_tsf(PADAPTER Adapter, u8 reset_port )
  988. {
  989. u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;
  990. u32 reg_reset_tsf_cnt = (IFACE_PORT0==reset_port) ?
  991. REG_FW_RESET_TSF_CNT_0:REG_FW_RESET_TSF_CNT_1;
  992. u32 reg_bcncrtl = (IFACE_PORT0==reset_port) ?
  993. REG_BCN_CTRL_1:REG_BCN_CTRL;
  994. rtw_scan_abort(Adapter->pbuddy_adapter); /* site survey will cause reset_tsf fail */
  995. reset_cnt_after = reset_cnt_before = rtw_read8(Adapter,reg_reset_tsf_cnt);
  996. rtl8812_reset_tsf(Adapter, reset_port);
  997. while ((reset_cnt_after == reset_cnt_before ) && (loop_cnt < 10)) {
  998. rtw_msleep_os(100);
  999. loop_cnt++;
  1000. reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt);
  1001. }
  1002. return(loop_cnt >= 10) ? _FAIL : _TRUE;
  1003. }
  1004. #endif // CONFIG_TSF_RESET_OFFLOAD
  1005. #ifdef CONFIG_WOWLAN
  1006. void rtl8812_set_wowlan_cmd(_adapter* padapter, u8 enable)
  1007. {
  1008. u8 res=_SUCCESS;
  1009. u32 test=0;
  1010. struct recv_priv *precvpriv = &padapter->recvpriv;
  1011. SETWOWLAN_PARM pwowlan_parm;
  1012. struct pwrctrl_priv *pwrpriv=&padapter->pwrctrlpriv;
  1013. _func_enter_;
  1014. DBG_871X_LEVEL(_drv_always_, "+%s+\n", __func__);
  1015. pwowlan_parm.mode =0;
  1016. pwowlan_parm.gpio_index=0;
  1017. pwowlan_parm.gpio_duration=0;
  1018. pwowlan_parm.second_mode =0;
  1019. pwowlan_parm.reserve=0;
  1020. if(enable){
  1021. pwowlan_parm.mode |=FW_WOWLAN_FUN_EN;
  1022. pwrpriv->wowlan_magic =_TRUE;
  1023. pwrpriv->wowlan_unicast =_TRUE;
  1024. if(pwrpriv->wowlan_pattern ==_TRUE){
  1025. pwowlan_parm.mode |= FW_WOWLAN_PATTERN_MATCH;
  1026. DBG_871X_LEVEL(_drv_info_, "%s 2.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
  1027. }
  1028. if(pwrpriv->wowlan_magic ==_TRUE){
  1029. pwowlan_parm.mode |=FW_WOWLAN_MAGIC_PKT;
  1030. DBG_871X_LEVEL(_drv_info_, "%s 3.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
  1031. }
  1032. if(pwrpriv->wowlan_unicast ==_TRUE){
  1033. pwowlan_parm.mode |=FW_WOWLAN_UNICAST;
  1034. DBG_871X_LEVEL(_drv_info_, "%s 4.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
  1035. }
  1036. if(!(padapter->pwrctrlpriv.wowlan_wake_reason & FWDecisionDisconnect))
  1037. rtl8812a_set_FwJoinBssReport_cmd(padapter, 1);
  1038. else
  1039. DBG_871X_LEVEL(_drv_always_, "%s, disconnected, no FwJoinBssReport\n",__FUNCTION__);
  1040. rtw_msleep_os(2);
  1041. //WOWLAN_GPIO_ACTIVE means GPIO high active
  1042. //pwowlan_parm.mode |=FW_WOWLAN_GPIO_ACTIVE;
  1043. //pwowlan_parm.mode |=FW_WOWLAN_REKEY_WAKEUP;
  1044. pwowlan_parm.mode |=FW_WOWLAN_DEAUTH_WAKEUP;
  1045. //pwowlan_parm.mode |=FW_WOWLAN_ALL_PKT_DROP;
  1046. //DataPinWakeUp
  1047. pwowlan_parm.gpio_index=0x80;
  1048. DBG_871X_LEVEL(_drv_info_, "%s 5.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode);
  1049. DBG_871X_LEVEL(_drv_info_, "%s 6.pwowlan_parm.index=0x%x \n",__FUNCTION__,pwowlan_parm.gpio_index);
  1050. res = FillH2CCmd_8812(padapter, H2C_8812_WO_WLAN, 2, (u8 *)&pwowlan_parm);
  1051. rtw_msleep_os(2);
  1052. //disconnect decision
  1053. pwowlan_parm.mode =1;
  1054. pwowlan_parm.gpio_index=0;
  1055. pwowlan_parm.gpio_duration=0;
  1056. FillH2CCmd_8812(padapter, H2C_8812_DISCONNECT_DECISION, 3, (u8 *)&pwowlan_parm);
  1057. //keep alive period = 10 * 10 BCN interval
  1058. pwowlan_parm.mode =1;
  1059. pwowlan_parm.gpio_index=10;
  1060. res = FillH2CCmd_8812(padapter, H2C_8812_KEEP_ALIVE_CTRL, 2, (u8 *)&pwowlan_parm);
  1061. rtw_msleep_os(2);
  1062. //enable Remote wake ctrl
  1063. pwowlan_parm.mode = 1;
  1064. pwowlan_parm.gpio_index=0;
  1065. pwowlan_parm.gpio_duration=0;
  1066. res = FillH2CCmd_8812(padapter, H2C_8812_REMOTE_WAKE_CTRL, 3, (u8 *)&pwowlan_parm);
  1067. } else {
  1068. pwrpriv->wowlan_magic =_FALSE;
  1069. res = FillH2CCmd_8812(padapter, H2C_8812_WO_WLAN, 2, (u8 *)&pwowlan_parm);
  1070. rtw_msleep_os(2);
  1071. res = FillH2CCmd_8812(padapter, H2C_8812_REMOTE_WAKE_CTRL, 3, (u8 *)&pwowlan_parm);
  1072. }
  1073. _func_exit_;
  1074. DBG_871X_LEVEL(_drv_always_, "-%s res:%d-\n", __func__, res);
  1075. return ;
  1076. }
  1077. #endif //CONFIG_WOWLAN