1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2012 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "../pci.h" 6 #include "../base.h" 7 #include "../efuse.h" 8 #include "reg.h" 9 #include "def.h" 10 #include "fw.h" 11 #include "sw.h" 12 13 static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv) 14 { 15 return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ? 16 true : false; 17 } 18 19 static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable) 20 { 21 struct rtl_priv *rtlpriv = rtl_priv(hw); 22 u8 tmp; 23 24 if (enable) { 25 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 26 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); 27 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 28 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); 29 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 30 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 31 } else { 32 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 33 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 34 /* Reserved for fw extension. 35 * 0x81[7] is used for mac0 status , 36 * so don't write this reg here 37 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/ 38 } 39 } 40 41 static void _rtl92d_write_fw(struct ieee80211_hw *hw, 42 enum version_8192d version, u8 *buffer, u32 size) 43 { 44 struct rtl_priv *rtlpriv = rtl_priv(hw); 45 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 46 u8 *bufferptr = buffer; 47 u32 pagenums, remainsize; 48 u32 page, offset; 49 50 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); 51 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) 52 rtl_fill_dummy(bufferptr, &size); 53 pagenums = size / FW_8192D_PAGE_SIZE; 54 remainsize = size % FW_8192D_PAGE_SIZE; 55 if (pagenums > 8) 56 pr_err("Page numbers should not greater then 8\n"); 57 for (page = 0; page < pagenums; page++) { 58 offset = page * FW_8192D_PAGE_SIZE; 59 rtl_fw_page_write(hw, page, (bufferptr + offset), 60 FW_8192D_PAGE_SIZE); 61 } 62 if (remainsize) { 63 offset = pagenums * FW_8192D_PAGE_SIZE; 64 page = pagenums; 65 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); 66 } 67 } 68 69 static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw) 70 { 71 struct rtl_priv *rtlpriv = rtl_priv(hw); 72 u32 counter = 0; 73 u32 value32; 74 75 do { 76 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 77 } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) && 78 (!(value32 & FWDL_CHKSUM_RPT))); 79 if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) { 80 pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n", 81 value32); 82 return -EIO; 83 } 84 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 85 value32 |= MCUFWDL_RDY; 86 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 87 return 0; 88 } 89 90 void rtl92d_firmware_selfreset(struct ieee80211_hw *hw) 91 { 92 struct rtl_priv *rtlpriv = rtl_priv(hw); 93 u8 u1b_tmp; 94 u8 delay = 100; 95 96 /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */ 97 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); 98 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 99 while (u1b_tmp & BIT(2)) { 100 delay--; 101 if (delay == 0) 102 break; 103 udelay(50); 104 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 105 } 106 WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n"); 107 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 108 "=====> 8051 reset success (%d)\n", delay); 109 } 110 111 static int _rtl92d_fw_init(struct ieee80211_hw *hw) 112 { 113 struct rtl_priv *rtlpriv = rtl_priv(hw); 114 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 115 u32 counter; 116 117 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n"); 118 /* polling for FW ready */ 119 counter = 0; 120 do { 121 if (rtlhal->interfaceindex == 0) { 122 if (rtl_read_byte(rtlpriv, FW_MAC0_READY) & 123 MAC0_READY) { 124 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 125 "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", 126 rtl_read_byte(rtlpriv, 127 FW_MAC0_READY)); 128 return 0; 129 } 130 udelay(5); 131 } else { 132 if (rtl_read_byte(rtlpriv, FW_MAC1_READY) & 133 MAC1_READY) { 134 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 135 "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", 136 rtl_read_byte(rtlpriv, 137 FW_MAC1_READY)); 138 return 0; 139 } 140 udelay(5); 141 } 142 } while (counter++ < POLLING_READY_TIMEOUT_COUNT); 143 144 if (rtlhal->interfaceindex == 0) { 145 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 146 "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n", 147 rtl_read_byte(rtlpriv, FW_MAC0_READY)); 148 } else { 149 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 150 "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n", 151 rtl_read_byte(rtlpriv, FW_MAC1_READY)); 152 } 153 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 154 "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", 155 rtl_read_dword(rtlpriv, REG_MCUFWDL)); 156 return -1; 157 } 158 159 int rtl92d_download_fw(struct ieee80211_hw *hw) 160 { 161 struct rtl_priv *rtlpriv = rtl_priv(hw); 162 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 163 u8 *pfwheader; 164 u8 *pfwdata; 165 u32 fwsize; 166 int err; 167 enum version_8192d version = rtlhal->version; 168 u8 value; 169 u32 count; 170 bool fw_downloaded = false, fwdl_in_process = false; 171 unsigned long flags; 172 173 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) 174 return 1; 175 fwsize = rtlhal->fwsize; 176 pfwheader = rtlhal->pfirmware; 177 pfwdata = rtlhal->pfirmware; 178 rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader); 179 rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader); 180 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 181 "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n", 182 rtlhal->fw_version, rtlhal->fw_subversion, 183 GET_FIRMWARE_HDR_SIGNATURE(pfwheader)); 184 if (IS_FW_HEADER_EXIST(pfwheader)) { 185 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 186 "Shift 32 bytes for FW header!!\n"); 187 pfwdata = pfwdata + 32; 188 fwsize = fwsize - 32; 189 } 190 191 spin_lock_irqsave(&globalmutex_for_fwdownload, flags); 192 fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); 193 if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) 194 fwdl_in_process = true; 195 else 196 fwdl_in_process = false; 197 if (fw_downloaded) { 198 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); 199 goto exit; 200 } else if (fwdl_in_process) { 201 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); 202 for (count = 0; count < 5000; count++) { 203 udelay(500); 204 spin_lock_irqsave(&globalmutex_for_fwdownload, flags); 205 fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); 206 if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) 207 fwdl_in_process = true; 208 else 209 fwdl_in_process = false; 210 spin_unlock_irqrestore(&globalmutex_for_fwdownload, 211 flags); 212 if (fw_downloaded) 213 goto exit; 214 else if (!fwdl_in_process) 215 break; 216 else 217 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, 218 "Wait for another mac download fw\n"); 219 } 220 spin_lock_irqsave(&globalmutex_for_fwdownload, flags); 221 value = rtl_read_byte(rtlpriv, 0x1f); 222 value |= BIT(5); 223 rtl_write_byte(rtlpriv, 0x1f, value); 224 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); 225 } else { 226 value = rtl_read_byte(rtlpriv, 0x1f); 227 value |= BIT(5); 228 rtl_write_byte(rtlpriv, 0x1f, value); 229 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); 230 } 231 232 /* If 8051 is running in RAM code, driver should 233 * inform Fw to reset by itself, or it will cause 234 * download Fw fail.*/ 235 /* 8051 RAM code */ 236 if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { 237 rtl92d_firmware_selfreset(hw); 238 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); 239 } 240 _rtl92d_enable_fw_download(hw, true); 241 _rtl92d_write_fw(hw, version, pfwdata, fwsize); 242 _rtl92d_enable_fw_download(hw, false); 243 spin_lock_irqsave(&globalmutex_for_fwdownload, flags); 244 err = _rtl92d_fw_free_to_go(hw); 245 /* download fw over,clear 0x1f[5] */ 246 value = rtl_read_byte(rtlpriv, 0x1f); 247 value &= (~BIT(5)); 248 rtl_write_byte(rtlpriv, 0x1f, value); 249 spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); 250 if (err) 251 pr_err("fw is not ready to run!\n"); 252 exit: 253 err = _rtl92d_fw_init(hw); 254 return err; 255 } 256 257 static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) 258 { 259 struct rtl_priv *rtlpriv = rtl_priv(hw); 260 u8 val_hmetfr; 261 bool result = false; 262 263 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 264 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 265 result = true; 266 return result; 267 } 268 269 static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, 270 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 271 { 272 struct rtl_priv *rtlpriv = rtl_priv(hw); 273 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 274 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 275 u8 boxnum; 276 u16 box_reg = 0, box_extreg = 0; 277 u8 u1b_tmp; 278 bool isfw_read = false; 279 u8 buf_index = 0; 280 bool bwrite_success = false; 281 u8 wait_h2c_limmit = 100; 282 u8 wait_writeh2c_limmit = 100; 283 u8 boxcontent[4], boxextcontent[2]; 284 u32 h2c_waitcounter = 0; 285 unsigned long flag; 286 u8 idx; 287 288 if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) { 289 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 290 "Return as RF is off!!!\n"); 291 return; 292 } 293 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 294 while (true) { 295 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 296 if (rtlhal->h2c_setinprogress) { 297 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 298 "H2C set in progress! Wait to set..element_id(%d)\n", 299 element_id); 300 301 while (rtlhal->h2c_setinprogress) { 302 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 303 flag); 304 h2c_waitcounter++; 305 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 306 "Wait 100 us (%d times)...\n", 307 h2c_waitcounter); 308 udelay(100); 309 310 if (h2c_waitcounter > 1000) 311 return; 312 313 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 314 flag); 315 } 316 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 317 } else { 318 rtlhal->h2c_setinprogress = true; 319 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 320 break; 321 } 322 } 323 while (!bwrite_success) { 324 wait_writeh2c_limmit--; 325 if (wait_writeh2c_limmit == 0) { 326 pr_err("Write H2C fail because no trigger for FW INT!\n"); 327 break; 328 } 329 boxnum = rtlhal->last_hmeboxnum; 330 switch (boxnum) { 331 case 0: 332 box_reg = REG_HMEBOX_0; 333 box_extreg = REG_HMEBOX_EXT_0; 334 break; 335 case 1: 336 box_reg = REG_HMEBOX_1; 337 box_extreg = REG_HMEBOX_EXT_1; 338 break; 339 case 2: 340 box_reg = REG_HMEBOX_2; 341 box_extreg = REG_HMEBOX_EXT_2; 342 break; 343 case 3: 344 box_reg = REG_HMEBOX_3; 345 box_extreg = REG_HMEBOX_EXT_3; 346 break; 347 default: 348 pr_err("switch case %#x not processed\n", 349 boxnum); 350 break; 351 } 352 isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); 353 while (!isfw_read) { 354 wait_h2c_limmit--; 355 if (wait_h2c_limmit == 0) { 356 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 357 "Waiting too long for FW read clear HMEBox(%d)!\n", 358 boxnum); 359 break; 360 } 361 udelay(10); 362 isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); 363 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); 364 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 365 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", 366 boxnum, u1b_tmp); 367 } 368 if (!isfw_read) { 369 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 370 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 371 boxnum); 372 break; 373 } 374 memset(boxcontent, 0, sizeof(boxcontent)); 375 memset(boxextcontent, 0, sizeof(boxextcontent)); 376 boxcontent[0] = element_id; 377 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 378 "Write element_id box_reg(%4x) = %2x\n", 379 box_reg, element_id); 380 switch (cmd_len) { 381 case 1: 382 boxcontent[0] &= ~(BIT(7)); 383 memcpy(boxcontent + 1, cmdbuffer + buf_index, 1); 384 for (idx = 0; idx < 4; idx++) 385 rtl_write_byte(rtlpriv, box_reg + idx, 386 boxcontent[idx]); 387 break; 388 case 2: 389 boxcontent[0] &= ~(BIT(7)); 390 memcpy(boxcontent + 1, cmdbuffer + buf_index, 2); 391 for (idx = 0; idx < 4; idx++) 392 rtl_write_byte(rtlpriv, box_reg + idx, 393 boxcontent[idx]); 394 break; 395 case 3: 396 boxcontent[0] &= ~(BIT(7)); 397 memcpy(boxcontent + 1, cmdbuffer + buf_index, 3); 398 for (idx = 0; idx < 4; idx++) 399 rtl_write_byte(rtlpriv, box_reg + idx, 400 boxcontent[idx]); 401 break; 402 case 4: 403 boxcontent[0] |= (BIT(7)); 404 memcpy(boxextcontent, cmdbuffer + buf_index, 2); 405 memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2); 406 for (idx = 0; idx < 2; idx++) 407 rtl_write_byte(rtlpriv, box_extreg + idx, 408 boxextcontent[idx]); 409 for (idx = 0; idx < 4; idx++) 410 rtl_write_byte(rtlpriv, box_reg + idx, 411 boxcontent[idx]); 412 break; 413 case 5: 414 boxcontent[0] |= (BIT(7)); 415 memcpy(boxextcontent, cmdbuffer + buf_index, 2); 416 memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3); 417 for (idx = 0; idx < 2; idx++) 418 rtl_write_byte(rtlpriv, box_extreg + idx, 419 boxextcontent[idx]); 420 for (idx = 0; idx < 4; idx++) 421 rtl_write_byte(rtlpriv, box_reg + idx, 422 boxcontent[idx]); 423 break; 424 default: 425 pr_err("switch case %#x not processed\n", 426 cmd_len); 427 break; 428 } 429 bwrite_success = true; 430 rtlhal->last_hmeboxnum = boxnum + 1; 431 if (rtlhal->last_hmeboxnum == 4) 432 rtlhal->last_hmeboxnum = 0; 433 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 434 "pHalData->last_hmeboxnum = %d\n", 435 rtlhal->last_hmeboxnum); 436 } 437 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 438 rtlhal->h2c_setinprogress = false; 439 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 440 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 441 } 442 443 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, 444 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 445 { 446 u32 tmp_cmdbuf[2]; 447 448 memset(tmp_cmdbuf, 0, 8); 449 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); 450 _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); 451 return; 452 } 453 454 static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw, 455 struct sk_buff *skb) 456 { 457 struct rtl_priv *rtlpriv = rtl_priv(hw); 458 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 459 struct rtl8192_tx_ring *ring; 460 struct rtl_tx_desc *pdesc; 461 u8 idx = 0; 462 unsigned long flags; 463 struct sk_buff *pskb; 464 465 ring = &rtlpci->tx_ring[BEACON_QUEUE]; 466 pskb = __skb_dequeue(&ring->queue); 467 kfree_skb(pskb); 468 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); 469 pdesc = &ring->desc[idx]; 470 /* discard output from call below */ 471 rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN); 472 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); 473 __skb_queue_tail(&ring->queue, skb); 474 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); 475 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); 476 return true; 477 } 478 479 #define BEACON_PG 0 /*->1 */ 480 #define PSPOLL_PG 2 481 #define NULL_PG 3 482 #define PROBERSP_PG 4 /*->5 */ 483 #define TOTAL_RESERVED_PKT_LEN 768 484 485 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 486 /* page 0 beacon */ 487 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 488 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 489 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, 490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 491 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 492 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 493 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 494 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 495 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 496 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 497 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 500 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 501 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 503 504 /* page 1 beacon */ 505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 517 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, 518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 519 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 521 522 /* page 2 ps-poll */ 523 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, 524 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 535 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 537 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 539 540 /* page 3 null */ 541 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 542 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 543 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 553 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 555 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 557 558 /* page 4 probe_resp */ 559 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 560 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 561 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 562 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 563 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 564 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 565 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 566 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 567 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 568 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 569 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 572 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 573 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 575 576 /* page 5 probe_resp */ 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 593 }; 594 595 void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) 596 { 597 struct rtl_priv *rtlpriv = rtl_priv(hw); 598 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 599 struct sk_buff *skb = NULL; 600 u32 totalpacketlen; 601 bool rtstatus; 602 u8 u1rsvdpageloc[3] = { 0 }; 603 bool dlok = false; 604 u8 *beacon; 605 u8 *p_pspoll; 606 u8 *nullfunc; 607 u8 *p_probersp; 608 /*--------------------------------------------------------- 609 (1) beacon 610 ---------------------------------------------------------*/ 611 beacon = &reserved_page_packet[BEACON_PG * 128]; 612 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 613 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 614 /*------------------------------------------------------- 615 (2) ps-poll 616 --------------------------------------------------------*/ 617 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 618 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 619 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 620 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 621 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 622 /*-------------------------------------------------------- 623 (3) null data 624 ---------------------------------------------------------*/ 625 nullfunc = &reserved_page_packet[NULL_PG * 128]; 626 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 627 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 628 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 629 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 630 /*--------------------------------------------------------- 631 (4) probe response 632 ----------------------------------------------------------*/ 633 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 634 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 635 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 636 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 637 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 638 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 639 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 640 "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", 641 &reserved_page_packet[0], totalpacketlen); 642 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 643 "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", 644 u1rsvdpageloc, 3); 645 skb = dev_alloc_skb(totalpacketlen); 646 if (!skb) { 647 dlok = false; 648 } else { 649 skb_put_data(skb, &reserved_page_packet, totalpacketlen); 650 rtstatus = _rtl92d_cmd_send_packet(hw, skb); 651 652 if (rtstatus) 653 dlok = true; 654 } 655 if (dlok) { 656 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 657 "Set RSVD page location to Fw\n"); 658 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 659 "H2C_RSVDPAGE", u1rsvdpageloc, 3); 660 rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE, 661 sizeof(u1rsvdpageloc), u1rsvdpageloc); 662 } else 663 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 664 "Set RSVD page location to Fw FAIL!!!!!!\n"); 665 } 666 667 void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) 668 { 669 u8 u1_joinbssrpt_parm[1] = {0}; 670 671 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); 672 rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); 673 } 674