1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 Realtek Corporation. 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 * The full GNU General Public License is included in this distribution in the 15 * file called LICENSE. 16 * 17 * Contact Information: 18 * wlanfae <wlanfae@realtek.com> 19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 20 * Hsinchu 300, Taiwan. 21 * 22 * Larry Finger <Larry.Finger@lwfinger.net> 23 * 24 *****************************************************************************/ 25 26 #include "../wifi.h" 27 #include "../pci.h" 28 #include "../base.h" 29 #include "../core.h" 30 #include "reg.h" 31 #include "def.h" 32 #include "fw.h" 33 #include "dm.h" 34 35 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable) 36 { 37 struct rtl_priv *rtlpriv = rtl_priv(hw); 38 u8 tmp; 39 40 if (enable) { 41 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); 42 43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 44 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 45 } else { 46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 48 } 49 } 50 51 static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw, 52 const u8 *buffer, u32 size) 53 { 54 struct rtl_priv *rtlpriv = rtl_priv(hw); 55 u32 blocksize = sizeof(u32); 56 u8 *bufferptr = (u8 *)buffer; 57 u32 *pu4byteptr = (u32 *)buffer; 58 u32 i, offset, blockcount, remainsize; 59 60 blockcount = size / blocksize; 61 remainsize = size % blocksize; 62 63 for (i = 0; i < blockcount; i++) { 64 offset = i * blocksize; 65 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), 66 *(pu4byteptr + i)); 67 } 68 69 if (remainsize) { 70 offset = blockcount * blocksize; 71 bufferptr += offset; 72 for (i = 0; i < remainsize; i++) { 73 rtl_write_byte(rtlpriv, 74 (FW_8192C_START_ADDRESS + offset + i), 75 *(bufferptr + i)); 76 } 77 } 78 } 79 80 static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page, 81 const u8 *buffer, u32 size) 82 { 83 struct rtl_priv *rtlpriv = rtl_priv(hw); 84 u8 value8; 85 u8 u8page = (u8)(page & 0x07); 86 87 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; 88 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); 89 90 _rtl92ee_fw_block_write(hw, buffer, size); 91 } 92 93 static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen) 94 { 95 u32 fwlen = *pfwlen; 96 u8 remain = (u8)(fwlen % 4); 97 98 remain = (remain == 0) ? 0 : (4 - remain); 99 100 while (remain > 0) { 101 pfwbuf[fwlen] = 0; 102 fwlen++; 103 remain--; 104 } 105 106 *pfwlen = fwlen; 107 } 108 109 static void _rtl92ee_write_fw(struct ieee80211_hw *hw, 110 enum version_8192e version, 111 u8 *buffer, u32 size) 112 { 113 struct rtl_priv *rtlpriv = rtl_priv(hw); 114 u8 *bufferptr = (u8 *)buffer; 115 u32 pagenums, remainsize; 116 u32 page, offset; 117 118 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size); 119 120 _rtl92ee_fill_dummy(bufferptr, &size); 121 122 pagenums = size / FW_8192C_PAGE_SIZE; 123 remainsize = size % FW_8192C_PAGE_SIZE; 124 125 if (pagenums > 8) { 126 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 127 "Page numbers should not greater then 8\n"); 128 } 129 130 for (page = 0; page < pagenums; page++) { 131 offset = page * FW_8192C_PAGE_SIZE; 132 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset), 133 FW_8192C_PAGE_SIZE); 134 udelay(2); 135 } 136 137 if (remainsize) { 138 offset = pagenums * FW_8192C_PAGE_SIZE; 139 page = pagenums; 140 _rtl92ee_fw_page_write(hw, page, (bufferptr + offset), 141 remainsize); 142 } 143 } 144 145 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw) 146 { 147 struct rtl_priv *rtlpriv = rtl_priv(hw); 148 int err = -EIO; 149 u32 counter = 0; 150 u32 value32; 151 152 do { 153 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 154 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && 155 (!(value32 & FWDL_CHKSUM_RPT))); 156 157 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { 158 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 159 "chksum report faill ! REG_MCUFWDL:0x%08x .\n", 160 value32); 161 goto exit; 162 } 163 164 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 165 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); 166 167 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 168 value32 |= MCUFWDL_RDY; 169 value32 &= ~WINTINI_RDY; 170 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 171 172 rtl92ee_firmware_selfreset(hw); 173 counter = 0; 174 175 do { 176 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 177 if (value32 & WINTINI_RDY) { 178 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , 179 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n", 180 value32, counter); 181 err = 0; 182 goto exit; 183 } 184 185 udelay(FW_8192C_POLLING_DELAY*10); 186 187 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); 188 189 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 190 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n", 191 value32, counter); 192 193 exit: 194 return err; 195 } 196 197 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) 198 { 199 struct rtl_priv *rtlpriv = rtl_priv(hw); 200 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 201 struct rtlwifi_firmware_header *pfwheader; 202 u8 *pfwdata; 203 u32 fwsize; 204 int err; 205 enum version_8192e version = rtlhal->version; 206 207 if (!rtlhal->pfirmware) 208 return 1; 209 210 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; 211 rtlhal->fw_version = le16_to_cpu(pfwheader->version); 212 rtlhal->fw_subversion = pfwheader->subversion; 213 pfwdata = (u8 *)rtlhal->pfirmware; 214 fwsize = rtlhal->fwsize; 215 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 216 "normal Firmware SIZE %d\n" , fwsize); 217 218 if (IS_FW_HEADER_EXIST(pfwheader)) { 219 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 220 "Firmware Version(%d), Signature(%#x),Size(%d)\n", 221 pfwheader->version, pfwheader->signature, 222 (int)sizeof(struct rtlwifi_firmware_header)); 223 224 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); 225 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); 226 } else { 227 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 228 "Firmware no Header, Signature(%#x)\n", 229 pfwheader->signature); 230 } 231 232 if (rtlhal->mac_func_enable) { 233 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { 234 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); 235 rtl92ee_firmware_selfreset(hw); 236 } 237 } 238 _rtl92ee_enable_fw_download(hw, true); 239 _rtl92ee_write_fw(hw, version, pfwdata, fwsize); 240 _rtl92ee_enable_fw_download(hw, false); 241 242 err = _rtl92ee_fw_free_to_go(hw); 243 if (err) { 244 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 245 "Firmware is not ready to run!\n"); 246 } else { 247 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , 248 "Firmware is ready to run!\n"); 249 } 250 251 return 0; 252 } 253 254 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) 255 { 256 struct rtl_priv *rtlpriv = rtl_priv(hw); 257 u8 val_hmetfr; 258 bool result = false; 259 260 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 261 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 262 result = true; 263 return result; 264 } 265 266 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 267 u32 cmd_len, u8 *cmdbuffer) 268 { 269 struct rtl_priv *rtlpriv = rtl_priv(hw); 270 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 271 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 272 u8 boxnum; 273 u16 box_reg = 0, box_extreg = 0; 274 u8 u1b_tmp; 275 bool isfw_read = false; 276 u8 buf_index = 0; 277 bool bwrite_sucess = false; 278 u8 wait_h2c_limmit = 100; 279 u8 boxcontent[4], boxextcontent[4]; 280 u32 h2c_waitcounter = 0; 281 unsigned long flag; 282 u8 idx; 283 284 if (ppsc->dot11_psmode != EACTIVE || 285 ppsc->inactive_pwrstate == ERFOFF) { 286 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 287 "FillH2CCommand8192E(): Return because RF is off!!!\n"); 288 return; 289 } 290 291 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n"); 292 293 /* 1. Prevent race condition in setting H2C cmd. 294 * (copy from MgntActSet_RF_State().) 295 */ 296 while (true) { 297 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 298 if (rtlhal->h2c_setinprogress) { 299 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 300 "H2C set in progress! Wait to set..element_id(%d).\n", 301 element_id); 302 303 while (rtlhal->h2c_setinprogress) { 304 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 305 flag); 306 h2c_waitcounter++; 307 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 308 "Wait 100 us (%d times)...\n", 309 h2c_waitcounter); 310 udelay(100); 311 312 if (h2c_waitcounter > 1000) 313 return; 314 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 315 flag); 316 } 317 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 318 } else { 319 rtlhal->h2c_setinprogress = true; 320 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 321 break; 322 } 323 } 324 325 while (!bwrite_sucess) { 326 /* 2. Find the last BOX number which has been writen. */ 327 boxnum = rtlhal->last_hmeboxnum; 328 switch (boxnum) { 329 case 0: 330 box_reg = REG_HMEBOX_0; 331 box_extreg = REG_HMEBOX_EXT_0; 332 break; 333 case 1: 334 box_reg = REG_HMEBOX_1; 335 box_extreg = REG_HMEBOX_EXT_1; 336 break; 337 case 2: 338 box_reg = REG_HMEBOX_2; 339 box_extreg = REG_HMEBOX_EXT_2; 340 break; 341 case 3: 342 box_reg = REG_HMEBOX_3; 343 box_extreg = REG_HMEBOX_EXT_3; 344 break; 345 default: 346 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 347 "switch case not process\n"); 348 break; 349 } 350 351 /* 3. Check if the box content is empty. */ 352 isfw_read = false; 353 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); 354 355 if (u1b_tmp != 0xea) { 356 isfw_read = true; 357 } else { 358 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea || 359 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea) 360 rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff); 361 } 362 363 if (isfw_read) { 364 wait_h2c_limmit = 100; 365 isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum); 366 while (!isfw_read) { 367 wait_h2c_limmit--; 368 if (wait_h2c_limmit == 0) { 369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 370 "Waiting too long for FW read clear HMEBox(%d)!!!\n", 371 boxnum); 372 break; 373 } 374 udelay(10); 375 isfw_read = 376 _rtl92ee_check_fw_read_last_h2c(hw, boxnum); 377 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 378 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 379 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 380 boxnum, u1b_tmp); 381 } 382 } 383 384 /* If Fw has not read the last 385 * H2C cmd, break and give up this H2C. 386 */ 387 if (!isfw_read) { 388 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 389 "Write H2C reg BOX[%d] fail,Fw don't read.\n", 390 boxnum); 391 break; 392 } 393 /* 4. Fill the H2C cmd into box */ 394 memset(boxcontent, 0, sizeof(boxcontent)); 395 memset(boxextcontent, 0, sizeof(boxextcontent)); 396 boxcontent[0] = element_id; 397 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 398 "Write element_id box_reg(%4x) = %2x\n", 399 box_reg, element_id); 400 401 switch (cmd_len) { 402 case 1: 403 case 2: 404 case 3: 405 /*boxcontent[0] &= ~(BIT(7));*/ 406 memcpy((u8 *)(boxcontent) + 1, 407 cmdbuffer + buf_index, cmd_len); 408 409 for (idx = 0; idx < 4; idx++) { 410 rtl_write_byte(rtlpriv, box_reg + idx, 411 boxcontent[idx]); 412 } 413 break; 414 case 4: 415 case 5: 416 case 6: 417 case 7: 418 /*boxcontent[0] |= (BIT(7));*/ 419 memcpy((u8 *)(boxextcontent), 420 cmdbuffer + buf_index+3, cmd_len-3); 421 memcpy((u8 *)(boxcontent) + 1, 422 cmdbuffer + buf_index, 3); 423 424 for (idx = 0; idx < 4; idx++) { 425 rtl_write_byte(rtlpriv, box_extreg + idx, 426 boxextcontent[idx]); 427 } 428 429 for (idx = 0; idx < 4; idx++) { 430 rtl_write_byte(rtlpriv, box_reg + idx, 431 boxcontent[idx]); 432 } 433 break; 434 default: 435 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, 436 "switch case not process\n"); 437 break; 438 } 439 440 bwrite_sucess = true; 441 442 rtlhal->last_hmeboxnum = boxnum + 1; 443 if (rtlhal->last_hmeboxnum == 4) 444 rtlhal->last_hmeboxnum = 0; 445 446 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , 447 "pHalData->last_hmeboxnum = %d\n", 448 rtlhal->last_hmeboxnum); 449 } 450 451 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 452 rtlhal->h2c_setinprogress = false; 453 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 454 455 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n"); 456 } 457 458 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, 459 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 460 { 461 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 462 u32 tmp_cmdbuf[2]; 463 464 if (!rtlhal->fw_ready) { 465 RT_ASSERT(false, 466 "return H2C cmd because of Fw download fail!!!\n"); 467 return; 468 } 469 470 memset(tmp_cmdbuf, 0, 8); 471 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); 472 _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); 473 } 474 475 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw) 476 { 477 u8 u1b_tmp; 478 struct rtl_priv *rtlpriv = rtl_priv(hw); 479 480 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 481 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); 482 483 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); 485 486 udelay(50); 487 488 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 489 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); 490 491 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 492 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); 493 494 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD , 495 " _8051Reset92E(): 8051 reset success .\n"); 496 } 497 498 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 499 { 500 struct rtl_priv *rtlpriv = rtl_priv(hw); 501 u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 }; 502 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 503 u8 rlbm , power_state = 0; 504 505 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode); 506 507 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 508 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ 509 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 510 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 511 (rtlpriv->mac80211.p2p) ? 512 ppsc->smart_ps : 1); 513 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 514 ppsc->reg_max_lps_awakeintvl); 515 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 516 if (mode == FW_PS_ACTIVE_MODE) 517 power_state |= FW_PWR_STATE_ACTIVE; 518 else 519 power_state |= FW_PWR_STATE_RF_OFF; 520 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 521 522 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 523 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 524 u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH); 525 rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH, 526 u1_h2c_set_pwrmode); 527 } 528 529 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 530 { 531 u8 parm[3] = { 0 , 0 , 0 }; 532 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 533 * bit1=0-->update Media Status to MACID 534 * bit1=1-->update Media Status from MACID to MACID_End 535 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 536 * parm[2]: MACID_End 537 */ 538 539 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 540 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 541 542 rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm); 543 } 544 545 #define BEACON_PG 0 /* ->1 */ 546 #define PSPOLL_PG 2 547 #define NULL_PG 3 548 #define PROBERSP_PG 4 /* ->5 */ 549 550 #define TOTAL_RESERVED_PKT_LEN 768 551 552 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 553 /* page 0 beacon */ 554 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 555 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 556 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 558 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 559 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 560 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 561 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 562 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 563 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 566 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 567 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 568 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 569 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 570 571 /* page 1 beacon */ 572 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, 573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 583 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 584 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 588 589 /* page 2 ps-poll */ 590 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 591 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 601 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 602 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 605 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 606 607 /* page 3 null */ 608 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 609 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 610 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, 611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 619 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 620 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 623 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 624 625 /* page 4 probe_resp */ 626 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 627 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 628 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 629 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 630 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 631 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 632 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 633 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 634 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 635 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 636 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 639 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 640 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 642 643 /* page 5 probe_resp */ 644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 660 }; 661 662 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) 663 { 664 struct rtl_priv *rtlpriv = rtl_priv(hw); 665 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 666 struct sk_buff *skb = NULL; 667 668 u32 totalpacketlen; 669 u8 u1rsvdpageloc[5] = { 0 }; 670 bool b_dlok = false; 671 672 u8 *beacon; 673 u8 *p_pspoll; 674 u8 *nullfunc; 675 u8 *p_probersp; 676 /*--------------------------------------------------------- 677 * (1) beacon 678 *--------------------------------------------------------- 679 */ 680 beacon = &reserved_page_packet[BEACON_PG * 128]; 681 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 682 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 683 684 /*------------------------------------------------------- 685 * (2) ps-poll 686 *-------------------------------------------------------- 687 */ 688 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 689 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 690 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 691 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 692 693 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 694 695 /*-------------------------------------------------------- 696 * (3) null data 697 *--------------------------------------------------------- 698 */ 699 nullfunc = &reserved_page_packet[NULL_PG * 128]; 700 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 701 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 702 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 703 704 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 705 706 /*--------------------------------------------------------- 707 * (4) probe response 708 *---------------------------------------------------------- 709 */ 710 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 711 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 712 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 713 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 714 715 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 716 717 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 718 719 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 720 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 721 &reserved_page_packet[0], totalpacketlen); 722 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 723 "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 724 u1rsvdpageloc, 3); 725 726 skb = dev_alloc_skb(totalpacketlen); 727 memcpy((u8 *)skb_put(skb, totalpacketlen), 728 &reserved_page_packet, totalpacketlen); 729 730 b_dlok = true; 731 732 if (b_dlok) { 733 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , 734 "Set RSVD page location to Fw.\n"); 735 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , 736 "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); 737 rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE, 738 sizeof(u1rsvdpageloc), u1rsvdpageloc); 739 } else { 740 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 741 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 742 } 743 } 744 745 /*Shoud check FW support p2p or not.*/ 746 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) 747 { 748 u8 u1_ctwindow_period[1] = {ctwindow}; 749 750 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); 751 } 752 753 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) 754 { 755 struct rtl_priv *rtlpriv = rtl_priv(hw); 756 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 757 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 758 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; 759 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 760 u8 i; 761 u16 ctwindow; 762 u32 start_time, tsf_low; 763 764 switch (p2p_ps_state) { 765 case P2P_PS_DISABLE: 766 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n"); 767 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 768 break; 769 case P2P_PS_ENABLE: 770 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n"); 771 /* update CTWindow value. */ 772 if (p2pinfo->ctwindow > 0) { 773 p2p_ps_offload->ctwindow_en = 1; 774 ctwindow = p2pinfo->ctwindow; 775 rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow); 776 } 777 /* hw only support 2 set of NoA */ 778 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 779 /* To control the register setting for which NOA*/ 780 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 781 if (i == 0) 782 p2p_ps_offload->noa0_en = 1; 783 else 784 p2p_ps_offload->noa1_en = 1; 785 /* config P2P NoA Descriptor Register */ 786 rtl_write_dword(rtlpriv, 0x5E0, 787 p2pinfo->noa_duration[i]); 788 rtl_write_dword(rtlpriv, 0x5E4, 789 p2pinfo->noa_interval[i]); 790 791 /*Get Current TSF value */ 792 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 793 794 start_time = p2pinfo->noa_start_time[i]; 795 if (p2pinfo->noa_count_type[i] != 1) { 796 while (start_time <= (tsf_low + (50 * 1024))) { 797 start_time += p2pinfo->noa_interval[i]; 798 if (p2pinfo->noa_count_type[i] != 255) 799 p2pinfo->noa_count_type[i]--; 800 } 801 } 802 rtl_write_dword(rtlpriv, 0x5E8, start_time); 803 rtl_write_dword(rtlpriv, 0x5EC, 804 p2pinfo->noa_count_type[i]); 805 } 806 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { 807 /* rst p2p circuit */ 808 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 809 p2p_ps_offload->offload_en = 1; 810 811 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 812 p2p_ps_offload->role = 1; 813 p2p_ps_offload->allstasleep = 0; 814 } else { 815 p2p_ps_offload->role = 0; 816 } 817 p2p_ps_offload->discovery = 0; 818 } 819 break; 820 case P2P_PS_SCAN: 821 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n"); 822 p2p_ps_offload->discovery = 1; 823 break; 824 case P2P_PS_SCAN_DONE: 825 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n"); 826 p2p_ps_offload->discovery = 0; 827 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 828 break; 829 default: 830 break; 831 } 832 rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1, 833 (u8 *)p2p_ps_offload); 834 } 835 836 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw, 837 u8 *cmd_buf, u8 cmd_len) 838 { 839 u8 rate = cmd_buf[0] & 0x3F; 840 bool collision_state = cmd_buf[3] & BIT(0); 841 842 rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state); 843 } 844 845 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id, 846 u8 c2h_cmd_len, u8 *tmp_buf) 847 { 848 struct rtl_priv *rtlpriv = rtl_priv(hw); 849 850 switch (c2h_cmd_id) { 851 case C2H_8192E_DBG: 852 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 853 "[C2H], C2H_8723BE_DBG!!\n"); 854 break; 855 case C2H_8192E_TXBF: 856 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 857 "[C2H], C2H_8192E_TXBF!!\n"); 858 break; 859 case C2H_8192E_TX_REPORT: 860 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE , 861 "[C2H], C2H_8723BE_TX_REPORT!\n"); 862 break; 863 case C2H_8192E_BT_INFO: 864 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 865 "[C2H], C2H_8723BE_BT_INFO!!\n"); 866 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 867 c2h_cmd_len); 868 break; 869 case C2H_8192E_BT_MP: 870 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 871 "[C2H], C2H_8723BE_BT_MP!!\n"); 872 break; 873 case C2H_8192E_RA_RPT: 874 _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); 875 break; 876 default: 877 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 878 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); 879 break; 880 } 881 } 882 883 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 884 { 885 struct rtl_priv *rtlpriv = rtl_priv(hw); 886 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 887 u8 *tmp_buf = NULL; 888 889 c2h_cmd_id = buffer[0]; 890 c2h_cmd_seq = buffer[1]; 891 c2h_cmd_len = len - 2; 892 tmp_buf = buffer + 2; 893 894 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 895 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 896 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 897 898 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 899 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 900 901 _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 902 } 903