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