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 ******************************************************************************/ 15#include <osdep_service.h> 16#include <drv_types.h> 17 18#include <hal_intf.h> 19#include <hal_com.h> 20#include <rtl8723a_hal.h> 21#include <usb_ops_linux.h> 22 23#define _HAL_INIT_C_ 24 25void dump_chip_info23a(struct hal_version ChipVersion) 26{ 27 int cnt = 0; 28 u8 buf[128]; 29 30 cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_"); 31 32 cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ? 33 "Normal_Chip" : "Test_Chip"); 34 cnt += sprintf((buf + cnt), "%s_", 35 IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC"); 36 if (IS_A_CUT(ChipVersion)) 37 cnt += sprintf((buf + cnt), "A_CUT_"); 38 else if (IS_B_CUT(ChipVersion)) 39 cnt += sprintf((buf + cnt), "B_CUT_"); 40 else if (IS_C_CUT(ChipVersion)) 41 cnt += sprintf((buf + cnt), "C_CUT_"); 42 else if (IS_D_CUT(ChipVersion)) 43 cnt += sprintf((buf + cnt), "D_CUT_"); 44 else if (IS_E_CUT(ChipVersion)) 45 cnt += sprintf((buf + cnt), "E_CUT_"); 46 else 47 cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_", 48 ChipVersion.CUTVersion); 49 50 if (IS_1T1R(ChipVersion)) 51 cnt += sprintf((buf + cnt), "1T1R_"); 52 else if (IS_1T2R(ChipVersion)) 53 cnt += sprintf((buf + cnt), "1T2R_"); 54 else if (IS_2T2R(ChipVersion)) 55 cnt += sprintf((buf + cnt), "2T2R_"); 56 else 57 cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_", 58 ChipVersion.RFType); 59 60 cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer); 61 62 DBG_8723A("%s", buf); 63} 64 65#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 66 67/* return the final channel plan decision */ 68/* hw_channel_plan: channel plan from HW (efuse/eeprom) */ 69/* sw_channel_plan: channel plan from SW (registry/module param) */ 70/* def_channel_plan: channel plan used when the former two is invalid */ 71u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan, 72 u8 sw_channel_plan, u8 def_channel_plan, 73 bool AutoLoadFail) 74{ 75 u8 swConfig; 76 u8 chnlPlan; 77 78 swConfig = true; 79 if (!AutoLoadFail) { 80 if (!rtw_is_channel_plan_valid(sw_channel_plan)) 81 swConfig = false; 82 if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK) 83 swConfig = false; 84 } 85 86 if (swConfig == true) 87 chnlPlan = sw_channel_plan; 88 else 89 chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK); 90 91 if (!rtw_is_channel_plan_valid(chnlPlan)) 92 chnlPlan = def_channel_plan; 93 94 return chnlPlan; 95} 96 97u8 MRateToHwRate23a(u8 rate) 98{ 99 u8 ret = DESC_RATE1M; 100 101 switch (rate) { 102 /* CCK and OFDM non-HT rates */ 103 case IEEE80211_CCK_RATE_1MB: 104 ret = DESC_RATE1M; 105 break; 106 case IEEE80211_CCK_RATE_2MB: 107 ret = DESC_RATE2M; 108 break; 109 case IEEE80211_CCK_RATE_5MB: 110 ret = DESC_RATE5_5M; 111 break; 112 case IEEE80211_CCK_RATE_11MB: 113 ret = DESC_RATE11M; 114 break; 115 case IEEE80211_OFDM_RATE_6MB: 116 ret = DESC_RATE6M; 117 break; 118 case IEEE80211_OFDM_RATE_9MB: 119 ret = DESC_RATE9M; 120 break; 121 case IEEE80211_OFDM_RATE_12MB: 122 ret = DESC_RATE12M; 123 break; 124 case IEEE80211_OFDM_RATE_18MB: 125 ret = DESC_RATE18M; 126 break; 127 case IEEE80211_OFDM_RATE_24MB: 128 ret = DESC_RATE24M; 129 break; 130 case IEEE80211_OFDM_RATE_36MB: 131 ret = DESC_RATE36M; 132 break; 133 case IEEE80211_OFDM_RATE_48MB: 134 ret = DESC_RATE48M; 135 break; 136 case IEEE80211_OFDM_RATE_54MB: 137 ret = DESC_RATE54M; 138 break; 139 140 /* HT rates since here */ 141 /* case MGN_MCS0: ret = DESC_RATEMCS0; break; */ 142 /* case MGN_MCS1: ret = DESC_RATEMCS1; break; */ 143 /* case MGN_MCS2: ret = DESC_RATEMCS2; break; */ 144 /* case MGN_MCS3: ret = DESC_RATEMCS3; break; */ 145 /* case MGN_MCS4: ret = DESC_RATEMCS4; break; */ 146 /* case MGN_MCS5: ret = DESC_RATEMCS5; break; */ 147 /* case MGN_MCS6: ret = DESC_RATEMCS6; break; */ 148 /* case MGN_MCS7: ret = DESC_RATEMCS7; break; */ 149 150 default: 151 break; 152 } 153 return ret; 154} 155 156void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS) 157{ 158 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 159 u8 i, is_brate, brate; 160 u16 brate_cfg = 0; 161 u8 rate_index; 162 163 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 164 is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK; 165 brate = mBratesOS[i] & 0x7f; 166 167 if (is_brate) { 168 switch (brate) { 169 case IEEE80211_CCK_RATE_1MB: 170 brate_cfg |= RATE_1M; 171 break; 172 case IEEE80211_CCK_RATE_2MB: 173 brate_cfg |= RATE_2M; 174 break; 175 case IEEE80211_CCK_RATE_5MB: 176 brate_cfg |= RATE_5_5M; 177 break; 178 case IEEE80211_CCK_RATE_11MB: 179 brate_cfg |= RATE_11M; 180 break; 181 case IEEE80211_OFDM_RATE_6MB: 182 brate_cfg |= RATE_6M; 183 break; 184 case IEEE80211_OFDM_RATE_9MB: 185 brate_cfg |= RATE_9M; 186 break; 187 case IEEE80211_OFDM_RATE_12MB: 188 brate_cfg |= RATE_12M; 189 break; 190 case IEEE80211_OFDM_RATE_18MB: 191 brate_cfg |= RATE_18M; 192 break; 193 case IEEE80211_OFDM_RATE_24MB: 194 brate_cfg |= RATE_24M; 195 break; 196 case IEEE80211_OFDM_RATE_36MB: 197 brate_cfg |= RATE_36M; 198 break; 199 case IEEE80211_OFDM_RATE_48MB: 200 brate_cfg |= RATE_48M; 201 break; 202 case IEEE80211_OFDM_RATE_54MB: 203 brate_cfg |= RATE_54M; 204 break; 205 } 206 } 207 } 208 209 /* 2007.01.16, by Emily */ 210 /* Select RRSR (in Legacy-OFDM and CCK) */ 211 /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, 212 and 1M from the Basic rate. */ 213 /* We do not use other rates. */ 214 /* 2011.03.30 add by Luke Lee */ 215 /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */ 216 /* because CCK 2M has poor TXEVM */ 217 /* CCK 5.5M & 11M ACK should be enabled for better 218 performance */ 219 220 brate_cfg = (brate_cfg | 0xd) & 0x15d; 221 pHalData->BasicRateSet = brate_cfg; 222 brate_cfg |= 0x01; /* default enable 1M ACK rate */ 223 DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg); 224 225 /* Set RRSR rate table. */ 226 rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff); 227 rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff); 228 rtl8723au_write8(padapter, REG_RRSR + 2, 229 rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0); 230 231 rate_index = 0; 232 /* Set RTS initial rate */ 233 while (brate_cfg > 0x1) { 234 brate_cfg = (brate_cfg >> 1); 235 rate_index++; 236 } 237 /* Ziv - Check */ 238 rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index); 239 240 return; 241} 242 243static void _OneOutPipeMapping(struct rtw_adapter *pAdapter) 244{ 245 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); 246 247 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ 248 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ 249 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */ 250 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ 251 252 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ 253 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ 254 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ 255 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */ 256} 257 258static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) 259{ 260 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); 261 262 if (bWIFICfg) { /* WMM */ 263 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ 264 /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */ 265 /* 0:H, 1:L */ 266 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */ 267 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ 268 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ 269 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */ 270 271 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ 272 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ 273 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ 274 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ 275 } else { /* typical setting */ 276 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ 277 /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */ 278 /* 0:H, 1:L */ 279 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ 280 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */ 281 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */ 282 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ 283 284 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ 285 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ 286 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ 287 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ 288 } 289} 290 291static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg) 292{ 293 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); 294 295 if (bWIFICfg) { /* for WMM */ 296 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ 297 /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */ 298 /* 0:H, 1:N, 2:L */ 299 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ 300 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ 301 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ 302 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */ 303 304 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ 305 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ 306 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ 307 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ 308 } else { /* typical setting */ 309 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */ 310 /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */ 311 /* 0:H, 1:N, 2:L */ 312 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */ 313 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */ 314 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */ 315 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */ 316 317 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */ 318 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */ 319 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */ 320 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/ 321 } 322} 323 324bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe) 325{ 326 struct registry_priv *pregistrypriv = &pAdapter->registrypriv; 327 bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false; 328 bool result = true; 329 330 switch (NumOutPipe) { 331 case 2: 332 _TwoOutPipeMapping(pAdapter, bWIFICfg); 333 break; 334 case 3: 335 _ThreeOutPipeMapping(pAdapter, bWIFICfg); 336 break; 337 case 1: 338 _OneOutPipeMapping(pAdapter); 339 break; 340 default: 341 result = false; 342 break; 343 } 344 345 return result; 346} 347 348/* 349* C2H event format: 350* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID 351* BITS [127:120] [119:16] [15:8] [7:4] [3:0] 352*/ 353 354void c2h_evt_clear23a(struct rtw_adapter *adapter) 355{ 356 rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); 357} 358 359int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf) 360{ 361 int ret = _FAIL; 362 struct c2h_evt_hdr *c2h_evt; 363 int i; 364 u8 trigger; 365 366 if (buf == NULL) 367 goto exit; 368 369 trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR); 370 371 if (trigger == C2H_EVT_HOST_CLOSE) 372 goto exit; /* Not ready */ 373 else if (trigger != C2H_EVT_FW_CLOSE) 374 goto clear_evt; /* Not a valid value */ 375 376 c2h_evt = (struct c2h_evt_hdr *)buf; 377 378 memset(c2h_evt, 0, 16); 379 380 *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL); 381 *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1); 382 383 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ", 384 &c2h_evt, sizeof(c2h_evt)); 385 386 if (0) { 387 DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n", 388 __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq, 389 trigger); 390 } 391 392 /* Read the content */ 393 for (i = 0; i < c2h_evt->plen; i++) 394 c2h_evt->payload[i] = rtl8723au_read8(adapter, 395 REG_C2HEVT_MSG_NORMAL + 396 sizeof(*c2h_evt) + i); 397 398 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, 399 "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload, 400 c2h_evt->plen); 401 402 ret = _SUCCESS; 403 404clear_evt: 405 /* 406 * Clear event to notify FW we have read the command. 407 * If this field isn't clear, the FW won't update the 408 * next command message. 409 */ 410 c2h_evt_clear23a(adapter); 411exit: 412 return ret; 413} 414 415void 416rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet) 417{ 418 u8 SecMinSpace; 419 420 if (MinSpacingToSet <= 7) { 421 switch (padapter->securitypriv.dot11PrivacyAlgrthm) { 422 case 0: 423 case WLAN_CIPHER_SUITE_CCMP: 424 SecMinSpace = 0; 425 break; 426 427 case WLAN_CIPHER_SUITE_WEP40: 428 case WLAN_CIPHER_SUITE_WEP104: 429 case WLAN_CIPHER_SUITE_TKIP: 430 SecMinSpace = 6; 431 break; 432 default: 433 SecMinSpace = 7; 434 break; 435 } 436 437 if (MinSpacingToSet < SecMinSpace) 438 MinSpacingToSet = SecMinSpace; 439 440 /* RT_TRACE(COMP_MLME, DBG_LOUD, 441 ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", 442 padapter->MgntInfo.MinSpaceCfg)); */ 443 MinSpacingToSet |= 444 rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8; 445 rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE, 446 MinSpacingToSet); 447 } 448} 449 450void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet) 451{ 452 u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; 453 u8 MaxAggNum; 454 u8 *pRegToSet; 455 u8 index = 0; 456 457 pRegToSet = RegToSet_Normal; /* 0xb972a841; */ 458 459 if (rtl8723a_BT_enabled(padapter) && 460 rtl8723a_BT_using_antenna_1(padapter)) 461 MaxAggNum = 0x8; 462 else 463 MaxAggNum = 0xF; 464 465 if (FactorToSet <= 3) { 466 FactorToSet = (1 << (FactorToSet + 2)); 467 if (FactorToSet > MaxAggNum) 468 FactorToSet = MaxAggNum; 469 470 for (index = 0; index < 4; index++) { 471 if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) 472 pRegToSet[index] = (pRegToSet[index] & 0x0f) | 473 (FactorToSet << 4); 474 475 if ((pRegToSet[index] & 0x0f) > FactorToSet) 476 pRegToSet[index] = (pRegToSet[index] & 0xf0) | 477 FactorToSet; 478 479 rtl8723au_write8(padapter, REG_AGGLEN_LMT + index, 480 pRegToSet[index]); 481 } 482 483 /* RT_TRACE(COMP_MLME, DBG_LOUD, 484 ("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */ 485 } 486} 487 488void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl) 489{ 490 u8 hwctrl = 0; 491 492 if (ctrl != 0) { 493 hwctrl |= AcmHw_HwEn; 494 495 if (ctrl & BIT(1)) /* BE */ 496 hwctrl |= AcmHw_BeqEn; 497 498 if (ctrl & BIT(2)) /* VI */ 499 hwctrl |= AcmHw_ViqEn; 500 501 if (ctrl & BIT(3)) /* VO */ 502 hwctrl |= AcmHw_VoqEn; 503 } 504 505 DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl); 506 rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl); 507} 508 509void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status) 510{ 511 u8 val8; 512 513 val8 = rtl8723au_read8(padapter, MSR) & 0x0c; 514 val8 |= status; 515 rtl8723au_write8(padapter, MSR, val8); 516} 517 518void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status) 519{ 520 u8 val8; 521 522 val8 = rtl8723au_read8(padapter, MSR) & 0x03; 523 val8 |= status << 2; 524 rtl8723au_write8(padapter, MSR, val8); 525} 526 527void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val) 528{ 529 if (val) 530 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0); 531 else 532 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT); 533} 534 535void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val) 536{ 537 u32 val32; 538 539 val32 = rtl8723au_read32(padapter, REG_RCR); 540 if (val) 541 val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN; 542 else 543 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); 544 rtl8723au_write32(padapter, REG_RCR, val32); 545} 546 547void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag) 548{ 549 if (flag) { /* under sitesurvey */ 550 u32 v32; 551 552 /* config RCR to receive different BSSID & not 553 to receive data frame */ 554 v32 = rtl8723au_read32(padapter, REG_RCR); 555 v32 &= ~(RCR_CBSSID_BCN); 556 rtl8723au_write32(padapter, REG_RCR, v32); 557 /* reject all data frame */ 558 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0); 559 560 /* disable update TSF */ 561 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0); 562 } else { /* sitesurvey done */ 563 564 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 565 struct mlme_ext_info *pmlmeinfo; 566 u32 v32; 567 568 pmlmeinfo = &pmlmeext->mlmext_info; 569 570 if ((is_client_associated_to_ap23a(padapter) == true) || 571 ((pmlmeinfo->state & 0x03) == MSR_ADHOC) || 572 ((pmlmeinfo->state & 0x03) == MSR_AP)) { 573 /* enable to rx data frame */ 574 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF); 575 576 /* enable update TSF */ 577 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT); 578 } 579 580 v32 = rtl8723au_read32(padapter, REG_RCR); 581 v32 |= RCR_CBSSID_BCN; 582 rtl8723au_write32(padapter, REG_RCR, v32); 583 } 584 585 rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false); 586} 587 588void rtl8723a_on_rcr_am(struct rtw_adapter *padapter) 589{ 590 rtl8723au_write32(padapter, REG_RCR, 591 rtl8723au_read32(padapter, REG_RCR) | RCR_AM); 592 DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, 593 rtl8723au_read32(padapter, REG_RCR)); 594} 595 596void rtl8723a_off_rcr_am(struct rtw_adapter *padapter) 597{ 598 rtl8723au_write32(padapter, REG_RCR, 599 rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM)); 600 DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__, 601 rtl8723au_read32(padapter, REG_RCR)); 602} 603 604void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime) 605{ 606 u8 u1bAIFS, aSifsTime; 607 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 608 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 609 610 rtl8723au_write8(padapter, REG_SLOT, slottime); 611 612 if (pmlmeinfo->WMM_enable == 0) { 613 if (pmlmeext->cur_wireless_mode == WIRELESS_11B) 614 aSifsTime = 10; 615 else 616 aSifsTime = 16; 617 618 u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime); 619 620 /* <Roger_EXP> Temporary removed, 2008.06.20. */ 621 rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS); 622 rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS); 623 rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS); 624 rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS); 625 } 626} 627 628void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble) 629{ 630 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 631 u8 regTmp; 632 633 /* Joseph marked out for Netgear 3500 TKIP 634 channel 7 issue.(Temporarily) */ 635 regTmp = (pHalData->nCur40MhzPrimeSC) << 5; 636 /* regTmp = 0; */ 637 if (bShortPreamble) 638 regTmp |= 0x80; 639 rtl8723au_write8(padapter, REG_RRSR + 2, regTmp); 640} 641 642void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec) 643{ 644 rtl8723au_write8(padapter, REG_SECCFG, sec); 645} 646 647void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex) 648{ 649 u8 i; 650 u32 ulCommand = 0; 651 u32 ulContent = 0; 652 u32 ulEncAlgo = CAM_AES; 653 654 for (i = 0; i < CAM_CONTENT_COUNT; i++) { 655 /* filled id in CAM config 2 byte */ 656 if (i == 0) { 657 ulContent |= (ucIndex & 0x03) | 658 ((u16) (ulEncAlgo) << 2); 659 /* ulContent |= CAM_VALID; */ 660 } else { 661 ulContent = 0; 662 } 663 /* polling bit, and No Write enable, and address */ 664 ulCommand = CAM_CONTENT_COUNT * ucIndex + i; 665 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; 666 /* write content 0 is equall to mark invalid */ 667 /* delay_ms(40); */ 668 rtl8723au_write32(padapter, WCAMI, ulContent); 669 /* RT_TRACE(COMP_SEC, DBG_LOUD, 670 ("rtl8723a_cam_empty_entry(): WRITE A4: %lx\n", 671 ulContent));*/ 672 /* delay_ms(40); */ 673 rtl8723au_write32(padapter, REG_CAMCMD, ulCommand); 674 /* RT_TRACE(COMP_SEC, DBG_LOUD, 675 ("rtl8723a_cam_empty_entry(): WRITE A0: %lx\n", 676 ulCommand));*/ 677 } 678} 679 680void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter) 681{ 682 rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30)); 683} 684 685void rtl8723a_cam_write(struct rtw_adapter *padapter, 686 u8 entry, u16 ctrl, const u8 *mac, const u8 *key) 687{ 688 u32 cmd; 689 unsigned int i, val, addr; 690 int j; 691 692 addr = entry << 3; 693 694 for (j = 5; j >= 0; j--) { 695 switch (j) { 696 case 0: 697 val = ctrl | (mac[0] << 16) | (mac[1] << 24); 698 break; 699 case 1: 700 val = mac[2] | (mac[3] << 8) | 701 (mac[4] << 16) | (mac[5] << 24); 702 break; 703 default: 704 i = (j - 2) << 2; 705 val = key[i] | (key[i+1] << 8) | 706 (key[i+2] << 16) | (key[i+3] << 24); 707 break; 708 } 709 710 rtl8723au_write32(padapter, WCAMI, val); 711 cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); 712 rtl8723au_write32(padapter, REG_CAMCMD, cmd); 713 714 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/ 715 } 716} 717 718void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter) 719{ 720#define RW_RELEASE_EN BIT(18) 721#define RXDMA_IDLE BIT(17) 722 723 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; 724 u8 trycnt = 100; 725 726 /* pause tx */ 727 rtl8723au_write8(padapter, REG_TXPAUSE, 0xff); 728 729 /* keep sn */ 730 padapter->xmitpriv.nqos_ssn = rtl8723au_read16(padapter, REG_NQOS_SEQ); 731 732 if (pwrpriv->bkeepfwalive != true) { 733 u32 v32; 734 735 /* RX DMA stop */ 736 v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM); 737 v32 |= RW_RELEASE_EN; 738 rtl8723au_write32(padapter, REG_RXPKT_NUM, v32); 739 do { 740 v32 = rtl8723au_read32(padapter, 741 REG_RXPKT_NUM) & RXDMA_IDLE; 742 if (!v32) 743 break; 744 } while (trycnt--); 745 if (trycnt == 0) 746 DBG_8723A("Stop RX DMA failed......\n"); 747 748 /* RQPN Load 0 */ 749 rtl8723au_write16(padapter, REG_RQPN_NPQ, 0); 750 rtl8723au_write32(padapter, REG_RQPN, 0x80000000); 751 mdelay(10); 752 } 753} 754 755void rtl8723a_bcn_valid(struct rtw_adapter *padapter) 756{ 757 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, 758 write 1 to clear, Clear by sw */ 759 rtl8723au_write8(padapter, REG_TDECTRL + 2, 760 rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0)); 761} 762 763bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter) 764{ 765 bool retval; 766 767 retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false; 768 769 return retval; 770} 771 772void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval) 773{ 774 rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval); 775} 776 777void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter, 778 u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2) 779{ 780 /* SIFS_Timer = 0x0a0a0808; */ 781 /* RESP_SIFS for CCK */ 782 /* SIFS_T2T_CCK (0x08) */ 783 rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1); 784 /* SIFS_R2T_CCK(0x08) */ 785 rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2); 786 /* RESP_SIFS for OFDM */ 787 /* SIFS_T2T_OFDM (0x0a) */ 788 rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1); 789 /* SIFS_R2T_OFDM(0x0a) */ 790 rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2); 791} 792 793void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo) 794{ 795 rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo); 796} 797 798void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi) 799{ 800 rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi); 801} 802 803void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be) 804{ 805 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 806 807 pHalData->AcParam_BE = be; 808 rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be); 809} 810 811void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk) 812{ 813 rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk); 814} 815 816void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val) 817{ 818 rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val); 819} 820 821void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain) 822{ 823 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 824 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable; 825 826 if (rx_gain == 0xff) /* restore rx gain */ 827 ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue); 828 else { 829 pDigTable->BackupIGValue = pDigTable->CurIGValue; 830 ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain); 831 } 832} 833 834void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter) 835{ 836 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 837 838 pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility; 839} 840 841void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter) 842{ 843 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 844 845 pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility; 846} 847 848void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val) 849{ 850 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 851 852 if (val == DYNAMIC_ALL_FUNC_ENABLE) 853 pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag; 854 else 855 pHalData->odmpriv.SupportAbility |= val; 856} 857 858void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val) 859{ 860 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 861 862 pHalData->odmpriv.SupportAbility &= val; 863} 864 865void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val) 866{ 867 rtl8723au_write8(padapter, REG_USB_HRPWM, val); 868} 869 870u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter) 871{ 872 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); 873 874 return pHalData->rf_type; 875} 876 877bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter) 878{ 879 bool retval; 880 u32 valRCR; 881 882 /* When we halt NIC, we should check if FW LPS is leave. */ 883 884 if ((padapter->bSurpriseRemoved == true) || 885 (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) { 886 /* If it is in HW/SW Radio OFF or IPS state, we do 887 not check Fw LPS Leave, because Fw is unload. */ 888 retval = true; 889 } else { 890 valRCR = rtl8723au_read32(padapter, REG_RCR); 891 if (valRCR & 0x00070000) 892 retval = false; 893 else 894 retval = true; 895 } 896 897 return retval; 898} 899 900bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter) 901{ 902 u32 hgq; 903 904 hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION); 905 906 return ((hgq & 0x0000ff00) == 0) ? true : false; 907} 908