| /* |
| ************************************************************************* |
| * Ralink Tech Inc. |
| * 5F., No.36, Taiyuan St., Jhubei City, |
| * Hsinchu County 302, |
| * Taiwan, R.O.C. |
| * |
| * (c) Copyright 2002-2007, Ralink Technology, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify * |
| * it under the terms of the GNU General Public License as published by * |
| * the Free Software Foundation; either version 2 of the License, or * |
| * (at your option) any later version. * |
| * * |
| * This program is distributed in the hope that it will be useful, * |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
| * GNU General Public License for more details. * |
| * * |
| * You should have received a copy of the GNU General Public License * |
| * along with this program; if not, write to the * |
| * Free Software Foundation, Inc., * |
| * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
| * * |
| ************************************************************************* |
| |
| Module Name: |
| cmm_asic.c |
| |
| Abstract: |
| Functions used to communicate with ASIC |
| |
| Revision History: |
| Who When What |
| -------- ---------- ---------------------------------------------- |
| */ |
| |
| #include "../rt_config.h" |
| |
| // Reset the RFIC setting to new series |
| RTMP_RF_REGS RF2850RegTable[] = { |
| // ch R1 R2 R3(TX0~4=0) R4 |
| {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b} |
| , |
| {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f} |
| , |
| {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b} |
| , |
| {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f} |
| , |
| {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b} |
| , |
| {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f} |
| , |
| {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b} |
| , |
| {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f} |
| , |
| {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b} |
| , |
| {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f} |
| , |
| {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b} |
| , |
| {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f} |
| , |
| {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b} |
| , |
| {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193} |
| , |
| |
| // 802.11 UNI / HyperLan 2 |
| {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3} |
| , |
| {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193} |
| , |
| {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183} |
| , |
| {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3} |
| , |
| {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b} |
| , |
| {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b} |
| , |
| {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193} |
| , |
| {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3} |
| , |
| {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b} |
| , |
| {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183} |
| , |
| {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193} |
| , |
| {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3} |
| , // Plugfest#4, Day4, change RFR3 left4th 9->5. |
| |
| // 802.11 HyperLan 2 |
| {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783} |
| , |
| |
| // 2008.04.30 modified |
| // The system team has AN to improve the EVM value |
| // for channel 102 to 108 for the RT2850/RT2750 dual band solution. |
| {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793} |
| , |
| {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3} |
| , |
| {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193} |
| , |
| |
| {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183} |
| , |
| {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b} |
| , |
| {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3} |
| , |
| {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193} |
| , |
| {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183} |
| , |
| {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193} |
| , |
| {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b} |
| , // 0x980ed1bb->0x980ed15b required by Rory 20070927 |
| {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3} |
| , |
| {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b} |
| , |
| {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193} |
| , |
| {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b} |
| , |
| {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183} |
| , |
| |
| // 802.11 UNII |
| {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7} |
| , |
| {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187} |
| , |
| {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f} |
| , |
| {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f} |
| , |
| {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7} |
| , |
| {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187} |
| , |
| {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197} |
| , |
| {167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f} |
| , |
| {169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327} |
| , |
| {171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307} |
| , |
| {173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f} |
| , |
| |
| // Japan |
| {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b} |
| , |
| {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13} |
| , |
| {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b} |
| , |
| {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23} |
| , |
| {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13} |
| , |
| {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b} |
| , |
| {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23} |
| , |
| |
| // still lack of MMAC(Japan) ch 34,38,42,46 |
| }; |
| |
| UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); |
| |
| FREQUENCY_ITEM FreqItems3020[] = { |
| /**************************************************/ |
| // ISM : 2.4 to 2.483 GHz // |
| /**************************************************/ |
| // 11g |
| /**************************************************/ |
| //-CH---N-------R---K----------- |
| {1, 241, 2, 2} |
| , |
| {2, 241, 2, 7} |
| , |
| {3, 242, 2, 2} |
| , |
| {4, 242, 2, 7} |
| , |
| {5, 243, 2, 2} |
| , |
| {6, 243, 2, 7} |
| , |
| {7, 244, 2, 2} |
| , |
| {8, 244, 2, 7} |
| , |
| {9, 245, 2, 2} |
| , |
| {10, 245, 2, 7} |
| , |
| {11, 246, 2, 2} |
| , |
| {12, 246, 2, 7} |
| , |
| {13, 247, 2, 2} |
| , |
| {14, 248, 2, 4} |
| , |
| }; |
| |
| UCHAR NUM_OF_3020_CHNL = (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)); |
| |
| VOID AsicUpdateAutoFallBackTable(IN PRTMP_ADAPTER pAd, IN PUCHAR pRateTable) |
| { |
| UCHAR i; |
| HT_FBK_CFG0_STRUC HtCfg0; |
| HT_FBK_CFG1_STRUC HtCfg1; |
| LG_FBK_CFG0_STRUC LgCfg0; |
| LG_FBK_CFG1_STRUC LgCfg1; |
| PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; |
| |
| // set to initial value |
| HtCfg0.word = 0x65432100; |
| HtCfg1.word = 0xedcba988; |
| LgCfg0.word = 0xedcba988; |
| LgCfg1.word = 0x00002100; |
| |
| pNextTxRate = (PRTMP_TX_RATE_SWITCH) pRateTable + 1; |
| for (i = 1; i < *((PUCHAR) pRateTable); i++) { |
| pCurrTxRate = (PRTMP_TX_RATE_SWITCH) pRateTable + 1 + i; |
| switch (pCurrTxRate->Mode) { |
| case 0: //CCK |
| break; |
| case 1: //OFDM |
| { |
| switch (pCurrTxRate->CurrMCS) { |
| case 0: |
| LgCfg0.field.OFDMMCS0FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 1: |
| LgCfg0.field.OFDMMCS1FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 2: |
| LgCfg0.field.OFDMMCS2FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 3: |
| LgCfg0.field.OFDMMCS3FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 4: |
| LgCfg0.field.OFDMMCS4FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 5: |
| LgCfg0.field.OFDMMCS5FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 6: |
| LgCfg0.field.OFDMMCS6FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| case 7: |
| LgCfg0.field.OFDMMCS7FBK = |
| (pNextTxRate->Mode == |
| MODE_OFDM) ? (pNextTxRate-> |
| CurrMCS + |
| 8) : pNextTxRate-> |
| CurrMCS; |
| break; |
| } |
| } |
| break; |
| case 2: //HT-MIX |
| case 3: //HT-GF |
| { |
| if ((pNextTxRate->Mode >= MODE_HTMIX) |
| && (pCurrTxRate->CurrMCS != |
| pNextTxRate->CurrMCS)) { |
| switch (pCurrTxRate->CurrMCS) { |
| case 0: |
| HtCfg0.field.HTMCS0FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 1: |
| HtCfg0.field.HTMCS1FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 2: |
| HtCfg0.field.HTMCS2FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 3: |
| HtCfg0.field.HTMCS3FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 4: |
| HtCfg0.field.HTMCS4FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 5: |
| HtCfg0.field.HTMCS5FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 6: |
| HtCfg0.field.HTMCS6FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 7: |
| HtCfg0.field.HTMCS7FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 8: |
| HtCfg1.field.HTMCS8FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 9: |
| HtCfg1.field.HTMCS9FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 10: |
| HtCfg1.field.HTMCS10FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 11: |
| HtCfg1.field.HTMCS11FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 12: |
| HtCfg1.field.HTMCS12FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 13: |
| HtCfg1.field.HTMCS13FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 14: |
| HtCfg1.field.HTMCS14FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| case 15: |
| HtCfg1.field.HTMCS15FBK = |
| pNextTxRate->CurrMCS; |
| break; |
| default: |
| DBGPRINT(RT_DEBUG_ERROR, |
| ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", |
| pCurrTxRate-> |
| CurrMCS)); |
| } |
| } |
| } |
| break; |
| } |
| |
| pNextTxRate = pCurrTxRate; |
| } |
| |
| RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); |
| RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); |
| RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); |
| RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); |
| } |
| |
| /* |
| ======================================================================== |
| |
| Routine Description: |
| Set MAC register value according operation mode. |
| OperationMode AND bNonGFExist are for MM and GF Proteciton. |
| If MM or GF mask is not set, those passing argument doesn't not take effect. |
| |
| Operation mode meaning: |
| = 0 : Pure HT, no preotection. |
| = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. |
| = 0x10: No Transmission in 40M is protected. |
| = 0x11: Transmission in both 40M and 20M shall be protected |
| if (bNonGFExist) |
| we should choose not to use GF. But still set correct ASIC registers. |
| ======================================================================== |
| */ |
| VOID AsicUpdateProtect(IN PRTMP_ADAPTER pAd, |
| IN USHORT OperationMode, |
| IN UCHAR SetMask, |
| IN BOOLEAN bDisableBGProtect, IN BOOLEAN bNonGFExist) |
| { |
| PROT_CFG_STRUC ProtCfg, ProtCfg4; |
| UINT32 Protect[6]; |
| USHORT offset; |
| UCHAR i; |
| UINT32 MacReg = 0; |
| |
| if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) { |
| return; |
| } |
| |
| if (pAd->BATable.numDoneOriginator) { |
| // |
| // enable the RTS/CTS to avoid channel collision |
| // |
| SetMask = ALLN_SETPROTECT; |
| OperationMode = 8; |
| } |
| // Config ASIC RTS threshold register |
| RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); |
| MacReg &= 0xFF0000FF; |
| // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 |
| if (((pAd->CommonCfg.BACapability.field.AmsduEnable) || |
| (pAd->CommonCfg.bAggregationCapable == TRUE)) |
| && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) { |
| MacReg |= (0x1000 << 8); |
| } else { |
| MacReg |= (pAd->CommonCfg.RtsThreshold << 8); |
| } |
| |
| RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); |
| |
| // Initial common protection settings |
| RTMPZeroMemory(Protect, sizeof(Protect)); |
| ProtCfg4.word = 0; |
| ProtCfg.word = 0; |
| ProtCfg.field.TxopAllowGF40 = 1; |
| ProtCfg.field.TxopAllowGF20 = 1; |
| ProtCfg.field.TxopAllowMM40 = 1; |
| ProtCfg.field.TxopAllowMM20 = 1; |
| ProtCfg.field.TxopAllowOfdm = 1; |
| ProtCfg.field.TxopAllowCck = 1; |
| ProtCfg.field.RTSThEn = 1; |
| ProtCfg.field.ProtectNav = ASIC_SHORTNAV; |
| |
| // update PHY mode and rate |
| if (pAd->CommonCfg.Channel > 14) |
| ProtCfg.field.ProtectRate = 0x4000; |
| ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; |
| |
| // Handle legacy(B/G) protection |
| if (bDisableBGProtect) { |
| //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; |
| ProtCfg.field.ProtectCtrl = 0; |
| Protect[0] = ProtCfg.word; |
| Protect[1] = ProtCfg.word; |
| pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ |
| } else { |
| //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; |
| ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected |
| Protect[0] = ProtCfg.word; |
| ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect |
| Protect[1] = ProtCfg.word; |
| pAd->FlgCtsEnabled = 1; /* CTS-self is used */ |
| } |
| |
| // Decide HT frame protection. |
| if ((SetMask & ALLN_SETPROTECT) != 0) { |
| switch (OperationMode) { |
| case 0x0: |
| // NO PROTECT |
| // 1.All STAs in the BSS are 20/40 MHz HT |
| // 2. in ai 20/40MHz BSS |
| // 3. all STAs are 20MHz in a 20MHz BSS |
| // Pure HT. no protection. |
| |
| // MM20_PROT_CFG |
| // Reserved (31:27) |
| // PROT_TXOP(25:20) -- 010111 |
| // PROT_NAV(19:18) -- 01 (Short NAV protection) |
| // PROT_CTRL(17:16) -- 00 (None) |
| // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) |
| Protect[2] = 0x01744004; |
| |
| // MM40_PROT_CFG |
| // Reserved (31:27) |
| // PROT_TXOP(25:20) -- 111111 |
| // PROT_NAV(19:18) -- 01 (Short NAV protection) |
| // PROT_CTRL(17:16) -- 00 (None) |
| // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) |
| Protect[3] = 0x03f44084; |
| |
| // CF20_PROT_CFG |
| // Reserved (31:27) |
| // PROT_TXOP(25:20) -- 010111 |
| // PROT_NAV(19:18) -- 01 (Short NAV protection) |
| // PROT_CTRL(17:16) -- 00 (None) |
| // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) |
| Protect[4] = 0x01744004; |
| |
| // CF40_PROT_CFG |
| // Reserved (31:27) |
| // PROT_TXOP(25:20) -- 111111 |
| // PROT_NAV(19:18) -- 01 (Short NAV protection) |
| // PROT_CTRL(17:16) -- 00 (None) |
| // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) |
| Protect[5] = 0x03f44084; |
| |
| if (bNonGFExist) { |
| // PROT_NAV(19:18) -- 01 (Short NAV protectiion) |
| // PROT_CTRL(17:16) -- 01 (RTS/CTS) |
| Protect[4] = 0x01754004; |
| Protect[5] = 0x03f54084; |
| } |
| pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; |
| break; |
| |
| case 1: |
| // This is "HT non-member protection mode." |
| // If there may be non-HT STAs my BSS |
| ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) |
| ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. |
| if (OPSTATUS_TEST_FLAG |
| (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { |
| ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. |
| ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; |
| } |
| //Assign Protection method for 20&40 MHz packets |
| ProtCfg.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg.field.ProtectNav = ASIC_SHORTNAV; |
| ProtCfg4.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; |
| Protect[2] = ProtCfg.word; |
| Protect[3] = ProtCfg4.word; |
| Protect[4] = ProtCfg.word; |
| Protect[5] = ProtCfg4.word; |
| pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; |
| break; |
| |
| case 2: |
| // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets |
| ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) |
| ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. |
| |
| //Assign Protection method for 40MHz packets |
| ProtCfg4.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; |
| Protect[2] = ProtCfg.word; |
| Protect[3] = ProtCfg4.word; |
| if (bNonGFExist) { |
| ProtCfg.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg.field.ProtectNav = ASIC_SHORTNAV; |
| } |
| Protect[4] = ProtCfg.word; |
| Protect[5] = ProtCfg4.word; |
| |
| pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; |
| break; |
| |
| case 3: |
| // HT mixed mode. PROTECT ALL! |
| // Assign Rate |
| ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. |
| ProtCfg4.word = 0x03f44084; |
| // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the |
| if (OPSTATUS_TEST_FLAG |
| (pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { |
| ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. |
| ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 |
| } |
| //Assign Protection method for 20&40 MHz packets |
| ProtCfg.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg.field.ProtectNav = ASIC_SHORTNAV; |
| ProtCfg4.field.ProtectCtrl = ASIC_RTS; |
| ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; |
| Protect[2] = ProtCfg.word; |
| Protect[3] = ProtCfg4.word; |
| Protect[4] = ProtCfg.word; |
| Protect[5] = ProtCfg4.word; |
| pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; |
| break; |
| |
| case 8: |
| // Special on for Atheros problem n chip. |
| Protect[2] = 0x01754004; |
| Protect[3] = 0x03f54084; |
| Protect[4] = 0x01754004; |
| Protect[5] = 0x03f54084; |
| pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; |
| break; |
| } |
| } |
| |
| offset = CCK_PROT_CFG; |
| for (i = 0; i < 6; i++) { |
| if ((SetMask & (1 << i))) { |
| RTMP_IO_WRITE32(pAd, offset + i * 4, Protect[i]); |
| } |
| } |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicSwitchChannel(IN PRTMP_ADAPTER pAd, IN UCHAR Channel, IN BOOLEAN bScan) |
| { |
| ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; |
| CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; |
| UCHAR index; |
| UINT32 Value = 0; //BbpReg, Value; |
| RTMP_RF_REGS *RFRegTable; |
| UCHAR RFValue; |
| |
| RFValue = 0; |
| // Search Tx power value |
| // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list |
| // in ChannelList, so use TxPower array instead. |
| // |
| for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) { |
| if (Channel == pAd->TxPower[index].Channel) { |
| TxPwer = pAd->TxPower[index].Power; |
| TxPwer2 = pAd->TxPower[index].Power2; |
| break; |
| } |
| } |
| |
| if (index == MAX_NUM_OF_CHANNELS) { |
| DBGPRINT(RT_DEBUG_ERROR, |
| ("AsicSwitchChannel: Can't find the Channel#%d \n", |
| Channel)); |
| } |
| #ifdef RT30xx |
| // The RF programming sequence is difference between 3xxx and 2xxx |
| if ((IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd)) |
| && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) |
| || (pAd->RfIcType == RFIC_3021) |
| || (pAd->RfIcType == RFIC_3022))) { |
| /* modify by WY for Read RF Reg. error */ |
| |
| for (index = 0; index < NUM_OF_3020_CHNL; index++) { |
| if (Channel == FreqItems3020[index].Channel) { |
| // Programming channel parameters |
| RT30xxWriteRFRegister(pAd, RF_R02, |
| FreqItems3020[index].N); |
| RT30xxWriteRFRegister(pAd, RF_R03, |
| FreqItems3020[index].K); |
| RT30xxReadRFRegister(pAd, RF_R06, &RFValue); |
| RFValue = |
| (RFValue & 0xFC) | FreqItems3020[index].R; |
| RT30xxWriteRFRegister(pAd, RF_R06, RFValue); |
| |
| // Set Tx0 Power |
| RT30xxReadRFRegister(pAd, RF_R12, &RFValue); |
| RFValue = (RFValue & 0xE0) | TxPwer; |
| RT30xxWriteRFRegister(pAd, RF_R12, RFValue); |
| |
| // Set Tx1 Power |
| RT30xxReadRFRegister(pAd, RF_R13, &RFValue); |
| RFValue = (RFValue & 0xE0) | TxPwer2; |
| RT30xxWriteRFRegister(pAd, RF_R13, RFValue); |
| |
| // Tx/Rx Stream setting |
| RT30xxReadRFRegister(pAd, RF_R01, &RFValue); |
| //if (IS_RT3090(pAd)) |
| // RFValue |= 0x01; // Enable RF block. |
| RFValue &= 0x03; //clear bit[7~2] |
| if (pAd->Antenna.field.TxPath == 1) |
| RFValue |= 0xA0; |
| else if (pAd->Antenna.field.TxPath == 2) |
| RFValue |= 0x80; |
| if (pAd->Antenna.field.RxPath == 1) |
| RFValue |= 0x50; |
| else if (pAd->Antenna.field.RxPath == 2) |
| RFValue |= 0x40; |
| RT30xxWriteRFRegister(pAd, RF_R01, RFValue); |
| |
| // Set RF offset |
| RT30xxReadRFRegister(pAd, RF_R23, &RFValue); |
| RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; |
| RT30xxWriteRFRegister(pAd, RF_R23, RFValue); |
| |
| // Set BW |
| if (!bScan |
| && (pAd->CommonCfg.BBPCurrentBW == BW_40)) { |
| RFValue = pAd->Mlme.CaliBW40RfR24; |
| //DISABLE_11N_CHECK(pAd); |
| } else { |
| RFValue = pAd->Mlme.CaliBW20RfR24; |
| } |
| RT30xxWriteRFRegister(pAd, RF_R24, RFValue); |
| RT30xxWriteRFRegister(pAd, RF_R31, RFValue); |
| |
| // Enable RF tuning |
| RT30xxReadRFRegister(pAd, RF_R07, &RFValue); |
| RFValue = RFValue | 0x1; |
| RT30xxWriteRFRegister(pAd, RF_R07, RFValue); |
| |
| // latch channel for future usage. |
| pAd->LatchRfRegs.Channel = Channel; |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", |
| Channel, pAd->RfIcType, TxPwer, |
| TxPwer2, pAd->Antenna.field.TxPath, |
| FreqItems3020[index].N, |
| FreqItems3020[index].K, |
| FreqItems3020[index].R)); |
| |
| break; |
| } |
| } |
| } else |
| #endif // RT30xx // |
| { |
| RFRegTable = RF2850RegTable; |
| switch (pAd->RfIcType) { |
| case RFIC_2820: |
| case RFIC_2850: |
| case RFIC_2720: |
| case RFIC_2750: |
| |
| for (index = 0; index < NUM_OF_2850_CHNL; index++) { |
| if (Channel == RFRegTable[index].Channel) { |
| R2 = RFRegTable[index].R2; |
| if (pAd->Antenna.field.TxPath == 1) { |
| R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; |
| } |
| |
| if (pAd->Antenna.field.RxPath == 2) { |
| R2 |= 0x40; // write 1 to off Rxpath. |
| } else if (pAd->Antenna.field.RxPath == |
| 1) { |
| R2 |= 0x20040; // write 1 to off RxPath |
| } |
| |
| if (Channel > 14) { |
| // initialize R3, R4 |
| R3 = (RFRegTable[index]. |
| R3 & 0xffffc1ff); |
| R4 = (RFRegTable[index]. |
| R4 & (~0x001f87c0)) | |
| (pAd->RfFreqOffset << 15); |
| |
| // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB |
| // R3 |
| if ((TxPwer >= -7) |
| && (TxPwer < 0)) { |
| TxPwer = (7 + TxPwer); |
| TxPwer = |
| (TxPwer > |
| 0xF) ? (0xF) |
| : (TxPwer); |
| R3 |= (TxPwer << 10); |
| DBGPRINT(RT_DEBUG_ERROR, |
| ("AsicSwitchChannel: TxPwer=%d \n", |
| TxPwer)); |
| } else { |
| TxPwer = |
| (TxPwer > |
| 0xF) ? (0xF) |
| : (TxPwer); |
| R3 |= |
| (TxPwer << 10) | (1 |
| << |
| 9); |
| } |
| |
| // R4 |
| if ((TxPwer2 >= -7) |
| && (TxPwer2 < 0)) { |
| TxPwer2 = (7 + TxPwer2); |
| TxPwer2 = |
| (TxPwer2 > |
| 0xF) ? (0xF) |
| : (TxPwer2); |
| R4 |= (TxPwer2 << 7); |
| DBGPRINT(RT_DEBUG_ERROR, |
| ("AsicSwitchChannel: TxPwer2=%d \n", |
| TxPwer2)); |
| } else { |
| TxPwer2 = |
| (TxPwer2 > |
| 0xF) ? (0xF) |
| : (TxPwer2); |
| R4 |= |
| (TxPwer2 << 7) | (1 |
| << |
| 6); |
| } |
| } else { |
| R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 |
| R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 << 6); // Set freq Offset & TxPwr1 |
| } |
| |
| // Based on BBP current mode before changing RF channel. |
| if (!bScan |
| && (pAd->CommonCfg.BBPCurrentBW == |
| BW_40)) { |
| R4 |= 0x200000; |
| } |
| // Update variables |
| pAd->LatchRfRegs.Channel = Channel; |
| pAd->LatchRfRegs.R1 = |
| RFRegTable[index].R1; |
| pAd->LatchRfRegs.R2 = R2; |
| pAd->LatchRfRegs.R3 = R3; |
| pAd->LatchRfRegs.R4 = R4; |
| |
| // Set RF value 1's set R3[bit2] = [0] |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R1); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R2); |
| RTMP_RF_IO_WRITE32(pAd, |
| (pAd->LatchRfRegs. |
| R3 & (~0x04))); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R4); |
| |
| RTMPusecDelay(200); |
| |
| // Set RF value 2's set R3[bit2] = [1] |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R1); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R2); |
| RTMP_RF_IO_WRITE32(pAd, |
| (pAd->LatchRfRegs. |
| R3 | 0x04)); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R4); |
| |
| RTMPusecDelay(200); |
| |
| // Set RF value 3's set R3[bit2] = [0] |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R1); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R2); |
| RTMP_RF_IO_WRITE32(pAd, |
| (pAd->LatchRfRegs. |
| R3 & (~0x04))); |
| RTMP_RF_IO_WRITE32(pAd, |
| pAd->LatchRfRegs.R4); |
| |
| break; |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", |
| Channel, pAd->RfIcType, (R3 & 0x00003e00) >> 9, |
| (R4 & 0x000007c0) >> 6, pAd->Antenna.field.TxPath, |
| pAd->LatchRfRegs.R1, pAd->LatchRfRegs.R2, |
| pAd->LatchRfRegs.R3, pAd->LatchRfRegs.R4)); |
| } |
| |
| // Change BBP setting during siwtch from a->g, g->a |
| if (Channel <= 14) { |
| ULONG TxPinCfg = 0x00050F0A; //Gary 2007/08/09 0x050A0A |
| |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); //(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. |
| //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); |
| |
| // Rx High power VGA offset for LNA select |
| if (pAd->NicConfig2.field.ExternalLNAForG) { |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); |
| } else { |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); |
| } |
| |
| // 5G band selection PIN, bit1 and bit2 are complement |
| RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); |
| Value &= (~0x6); |
| Value |= (0x04); |
| RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); |
| |
| // Turn off unused PA or LNA when only 1T or 1R |
| if (pAd->Antenna.field.TxPath == 1) { |
| TxPinCfg &= 0xFFFFFFF3; |
| } |
| if (pAd->Antenna.field.RxPath == 1) { |
| TxPinCfg &= 0xFFFFF3FF; |
| } |
| |
| RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); |
| |
| #if defined(RT3090) || defined(RT3390) |
| // PCIe PHY Transmit attenuation adjustment |
| if (IS_RT3090A(pAd) || IS_RT3390(pAd)) { |
| TX_ATTENUATION_CTRL_STRUC TxAttenuationCtrl = { |
| .word = 0}; |
| |
| RTMP_IO_READ32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, |
| &TxAttenuationCtrl.word); |
| |
| if (Channel == 14) // Channel #14 |
| { |
| TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 1; // Enable PCIe PHY Tx attenuation |
| TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 4; // 9/16 full drive level |
| } else // Channel #1~#13 |
| { |
| TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_EN = 0; // Disable PCIe PHY Tx attenuation |
| TxAttenuationCtrl.field.PCIE_PHY_TX_ATTEN_VALUE = 0; // n/a |
| } |
| |
| RTMP_IO_WRITE32(pAd, PCIE_PHY_TX_ATTENUATION_CTRL, |
| TxAttenuationCtrl.word); |
| } |
| #endif |
| } else { |
| ULONG TxPinCfg = 0x00050F05; //Gary 2007/8/9 0x050505 |
| |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, |
| (0x37 - GET_LNA_GAIN(pAd))); |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); //(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); |
| |
| // Rx High power VGA offset for LNA select |
| if (pAd->NicConfig2.field.ExternalLNAForA) { |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); |
| } else { |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); |
| } |
| |
| // 5G band selection PIN, bit1 and bit2 are complement |
| RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); |
| Value &= (~0x6); |
| Value |= (0x02); |
| RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); |
| |
| // Turn off unused PA or LNA when only 1T or 1R |
| if (pAd->Antenna.field.TxPath == 1) { |
| TxPinCfg &= 0xFFFFFFF3; |
| } |
| if (pAd->Antenna.field.RxPath == 1) { |
| TxPinCfg &= 0xFFFFF3FF; |
| } |
| |
| RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); |
| |
| } |
| |
| // R66 should be set according to Channel and use 20MHz when scanning |
| //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); |
| if (bScan) |
| RTMPSetAGCInitValue(pAd, BW_20); |
| else |
| RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); |
| |
| // |
| // On 11A, We should delay and wait RF/BBP to be stable |
| // and the appropriate time should be 1000 micro seconds |
| // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. |
| // |
| RTMPusecDelay(1000); |
| } |
| |
| VOID AsicResetBBPAgent(IN PRTMP_ADAPTER pAd) |
| { |
| BBP_CSR_CFG_STRUC BbpCsr; |
| DBGPRINT(RT_DEBUG_ERROR, ("Reset BBP Agent busy bit.!! \n")); |
| // Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. |
| RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); |
| BbpCsr.field.Busy = 0; |
| RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| This function is required for 2421 only, and should not be used during |
| site survey. It's only required after NIC decided to stay at a channel |
| for a longer period. |
| When this function is called, it's always after AsicSwitchChannel(). |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicLockChannel(IN PRTMP_ADAPTER pAd, IN UCHAR Channel) |
| { |
| } |
| |
| VOID AsicRfTuningExec(IN PVOID SystemSpecific1, |
| IN PVOID FunctionContext, |
| IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) |
| { |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| Gives CCK TX rate 2 more dB TX power. |
| This routine works only in LINK UP in INFRASTRUCTURE mode. |
| |
| calculate desired Tx power in RF R3.Tx0~5, should consider - |
| 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) |
| 1. TxPowerPercentage |
| 2. auto calibration based on TSSI feedback |
| 3. extra 2 db for CCK |
| 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP |
| |
| NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), |
| it should be called AFTER MlmeDynamicTxRatSwitching() |
| ========================================================================== |
| */ |
| VOID AsicAdjustTxPower(IN PRTMP_ADAPTER pAd) |
| { |
| INT i, j; |
| CHAR DeltaPwr = 0; |
| BOOLEAN bAutoTxAgc = FALSE; |
| UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; |
| UCHAR BbpR1 = 0, BbpR49 = 0, idx; |
| PCHAR pTxAgcCompensate; |
| ULONG TxPwr[5]; |
| CHAR Value; |
| CHAR Rssi = -127; |
| |
| if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || |
| #ifdef RTMP_MAC_PCI |
| (pAd->bPCIclkOff == TRUE) || |
| #endif // RTMP_MAC_PCI // |
| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || |
| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) |
| return; |
| |
| Rssi = RTMPMaxRssi(pAd, |
| pAd->StaCfg.RssiSample.AvgRssi0, |
| pAd->StaCfg.RssiSample.AvgRssi1, |
| pAd->StaCfg.RssiSample.AvgRssi2); |
| |
| if (pAd->CommonCfg.BBPCurrentBW == BW_40) { |
| if (pAd->CommonCfg.CentralChannel > 14) { |
| TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; |
| TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; |
| TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; |
| TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; |
| TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; |
| } else { |
| TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; |
| TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; |
| TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; |
| TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; |
| TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; |
| } |
| } else { |
| if (pAd->CommonCfg.Channel > 14) { |
| TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; |
| TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; |
| TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; |
| TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; |
| TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; |
| } else { |
| TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; |
| TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; |
| TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; |
| TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; |
| TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; |
| } |
| } |
| |
| // TX power compensation for temperature variation based on TSSI. try every 4 second |
| if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) { |
| if (pAd->CommonCfg.Channel <= 14) { |
| /* bg channel */ |
| bAutoTxAgc = pAd->bAutoTxAgcG; |
| TssiRef = pAd->TssiRefG; |
| pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; |
| pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; |
| TxAgcStep = pAd->TxAgcStepG; |
| pTxAgcCompensate = &pAd->TxAgcCompensateG; |
| } else { |
| /* a channel */ |
| bAutoTxAgc = pAd->bAutoTxAgcA; |
| TssiRef = pAd->TssiRefA; |
| pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; |
| pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; |
| TxAgcStep = pAd->TxAgcStepA; |
| pTxAgcCompensate = &pAd->TxAgcCompensateA; |
| } |
| |
| if (bAutoTxAgc) { |
| /* BbpR1 is unsigned char */ |
| RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); |
| |
| /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ |
| /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ |
| /* step value is defined in pAd->TxAgcStepG for tx power value */ |
| |
| /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ |
| /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 |
| above value are examined in mass factory production */ |
| /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ |
| |
| /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ |
| /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ |
| /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ |
| |
| if (BbpR49 > pTssiMinusBoundary[1]) { |
| // Reading is larger than the reference value |
| // check for how large we need to decrease the Tx power |
| for (idx = 1; idx < 5; idx++) { |
| if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range |
| break; |
| } |
| // The index is the step we should decrease, idx = 0 means there is nothing to compensate |
| // if (R3 > (ULONG) (TxAgcStep * (idx-1))) |
| *pTxAgcCompensate = -(TxAgcStep * (idx - 1)); |
| // else |
| // *pTxAgcCompensate = -((UCHAR)R3); |
| |
| DeltaPwr += (*pTxAgcCompensate); |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", |
| BbpR49, TssiRef, TxAgcStep, idx - 1)); |
| } else if (BbpR49 < pTssiPlusBoundary[1]) { |
| // Reading is smaller than the reference value |
| // check for how large we need to increase the Tx power |
| for (idx = 1; idx < 5; idx++) { |
| if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range |
| break; |
| } |
| // The index is the step we should increase, idx = 0 means there is nothing to compensate |
| *pTxAgcCompensate = TxAgcStep * (idx - 1); |
| DeltaPwr += (*pTxAgcCompensate); |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", |
| BbpR49, TssiRef, TxAgcStep, idx - 1)); |
| } else { |
| *pTxAgcCompensate = 0; |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", |
| BbpR49, TssiRef, TxAgcStep, 0)); |
| } |
| } |
| } else { |
| if (pAd->CommonCfg.Channel <= 14) { |
| bAutoTxAgc = pAd->bAutoTxAgcG; |
| pTxAgcCompensate = &pAd->TxAgcCompensateG; |
| } else { |
| bAutoTxAgc = pAd->bAutoTxAgcA; |
| pTxAgcCompensate = &pAd->TxAgcCompensateA; |
| } |
| |
| if (bAutoTxAgc) |
| DeltaPwr += (*pTxAgcCompensate); |
| } |
| |
| RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); |
| BbpR1 &= 0xFC; |
| |
| /* calculate delta power based on the percentage specified from UI */ |
| // E2PROM setting is calibrated for maximum TX power (i.e. 100%) |
| // We lower TX power here according to the percentage specified from UI |
| if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control |
| { |
| { |
| // to patch high power issue with some APs, like Belkin N1. |
| if (Rssi > -35) { |
| BbpR1 |= 0x02; // DeltaPwr -= 12; |
| } else if (Rssi > -40) { |
| BbpR1 |= 0x01; // DeltaPwr -= 6; |
| } else; |
| } |
| } else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW |
| ; |
| else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; |
| { |
| DeltaPwr -= 1; |
| } else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; |
| { |
| DeltaPwr -= 3; |
| } else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; |
| { |
| BbpR1 |= 0x01; |
| } else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; |
| { |
| BbpR1 |= 0x01; |
| DeltaPwr -= 3; |
| } else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; |
| { |
| BbpR1 |= 0x02; |
| } |
| |
| RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); |
| |
| /* reset different new tx power for different TX rate */ |
| for (i = 0; i < 5; i++) { |
| if (TxPwr[i] != 0xffffffff) { |
| for (j = 0; j < 8; j++) { |
| Value = (CHAR) ((TxPwr[i] >> j * 4) & 0x0F); /* 0 ~ 15 */ |
| |
| if ((Value + DeltaPwr) < 0) { |
| Value = 0; /* min */ |
| } else if ((Value + DeltaPwr) > 0xF) { |
| Value = 0xF; /* max */ |
| } else { |
| Value += DeltaPwr; /* temperature compensation */ |
| } |
| |
| /* fill new value to CSR offset */ |
| TxPwr[i] = |
| (TxPwr[i] & ~(0x0000000F << j * 4)) | (Value |
| << j |
| * 4); |
| } |
| |
| /* write tx power value to CSR */ |
| /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M |
| TX power for OFDM 6M/9M |
| TX power for CCK5.5M/11M |
| TX power for CCK1M/2M */ |
| /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ |
| RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i * 4, TxPwr[i]); |
| } |
| } |
| |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup |
| automatically. Instead, MCU will issue a TwakeUpInterrupt to host after |
| the wakeup timer timeout. Driver has to issue a separate command to wake |
| PHY up. |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicSleepThenAutoWakeup(IN PRTMP_ADAPTER pAd, |
| IN USHORT TbttNumToNextWakeUp) |
| { |
| RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| AsicForceWakeup() is used whenever manual wakeup is required |
| AsicForceSleep() should only be used when not in INFRA BSS. When |
| in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. |
| ========================================================================== |
| */ |
| VOID AsicForceSleep(IN PRTMP_ADAPTER pAd) |
| { |
| |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) |
| expired. |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| ========================================================================== |
| */ |
| VOID AsicForceWakeup(IN PRTMP_ADAPTER pAd, IN BOOLEAN bFromTx) |
| { |
| DBGPRINT(RT_DEBUG_INFO, ("--> AsicForceWakeup \n")); |
| RTMP_STA_FORCE_WAKEUP(pAd, bFromTx); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| Set My BSSID |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicSetBssid(IN PRTMP_ADAPTER pAd, IN PUCHAR pBssid) |
| { |
| ULONG Addr4; |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", pBssid[0], |
| pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5])); |
| |
| Addr4 = (ULONG) (pBssid[0]) | |
| (ULONG) (pBssid[1] << 8) | |
| (ULONG) (pBssid[2] << 16) | (ULONG) (pBssid[3] << 24); |
| RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); |
| |
| Addr4 = 0; |
| // always one BSSID in STA mode |
| Addr4 = (ULONG) (pBssid[4]) | (ULONG) (pBssid[5] << 8); |
| |
| RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); |
| } |
| |
| VOID AsicSetMcastWC(IN PRTMP_ADAPTER pAd) |
| { |
| MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; |
| USHORT offset; |
| |
| pEntry->Sst = SST_ASSOC; |
| pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index |
| pEntry->PsMode = PWR_ACTIVE; |
| pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; |
| offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicDelWcidTab(IN PRTMP_ADAPTER pAd, IN UCHAR Wcid) |
| { |
| ULONG Addr0 = 0x0, Addr1 = 0x0; |
| ULONG offset; |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n", Wcid)); |
| offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; |
| RTMP_IO_WRITE32(pAd, offset, Addr0); |
| offset += 4; |
| RTMP_IO_WRITE32(pAd, offset, Addr1); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicEnableRDG(IN PRTMP_ADAPTER pAd) |
| { |
| TX_LINK_CFG_STRUC TxLinkCfg; |
| UINT32 Data = 0; |
| |
| RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); |
| TxLinkCfg.field.TxRDGEn = 1; |
| RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); |
| |
| RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); |
| Data &= 0xFFFFFF00; |
| Data |= 0x80; |
| RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); |
| |
| //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicDisableRDG(IN PRTMP_ADAPTER pAd) |
| { |
| TX_LINK_CFG_STRUC TxLinkCfg; |
| UINT32 Data = 0; |
| |
| RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); |
| TxLinkCfg.field.TxRDGEn = 0; |
| RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); |
| |
| RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); |
| |
| Data &= 0xFFFFFF00; |
| //Data |= 0x20; |
| #ifndef WIFI_TEST |
| //if ( pAd->CommonCfg.bEnableTxBurst ) |
| // Data |= 0x60; // for performance issue not set the TXOP to 0 |
| #endif |
| if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) |
| && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) |
| ) { |
| // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode |
| if (pAd->CommonCfg.bEnableTxBurst) |
| Data |= 0x20; |
| } |
| RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicDisableSync(IN PRTMP_ADAPTER pAd) |
| { |
| BCN_TIME_CFG_STRUC csr; |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); |
| |
| // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect |
| // that NIC will never wakes up because TSF stops and no more |
| // TBTT interrupts |
| pAd->TbttTickCount = 0; |
| RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); |
| csr.field.bBeaconGen = 0; |
| csr.field.bTBTTEnable = 0; |
| csr.field.TsfSyncMode = 0; |
| csr.field.bTsfTicking = 0; |
| RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
| |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicEnableBssSync(IN PRTMP_ADAPTER pAd) |
| { |
| BCN_TIME_CFG_STRUC csr; |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); |
| |
| RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); |
| // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); |
| { |
| csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU |
| csr.field.bTsfTicking = 1; |
| csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode |
| csr.field.bBeaconGen = 0; // do NOT generate BEACON |
| csr.field.bTBTTEnable = 1; |
| } |
| RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| Note: |
| BEACON frame in shared memory should be built ok before this routine |
| can be called. Otherwise, a garbage frame maybe transmitted out every |
| Beacon period. |
| |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicEnableIbssSync(IN PRTMP_ADAPTER pAd) |
| { |
| BCN_TIME_CFG_STRUC csr9; |
| PUCHAR ptr; |
| UINT i; |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", |
| pAd->BeaconTxWI.MPDUtotalByteCount)); |
| |
| RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); |
| csr9.field.bBeaconGen = 0; |
| csr9.field.bTBTTEnable = 0; |
| csr9.field.bTsfTicking = 0; |
| RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); |
| |
| #ifdef RTMP_MAC_PCI |
| // move BEACON TXD and frame content to on-chip memory |
| ptr = (PUCHAR) & pAd->BeaconTxWI; |
| for (i = 0; i < TXWI_SIZE; i += 4) // 16-byte TXWI field |
| { |
| UINT32 longptr = |
| *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + |
| (*(ptr + 3) << 24); |
| RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); |
| ptr += 4; |
| } |
| |
| // start right after the 16-byte TXWI field |
| ptr = pAd->BeaconBuf; |
| for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 4) { |
| UINT32 longptr = |
| *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + |
| (*(ptr + 3) << 24); |
| RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); |
| ptr += 4; |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| // move BEACON TXD and frame content to on-chip memory |
| ptr = (PUCHAR) & pAd->BeaconTxWI; |
| for (i = 0; i < TXWI_SIZE; i += 2) // 16-byte TXWI field |
| { |
| //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); |
| //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr); |
| RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2); |
| ptr += 2; |
| } |
| |
| // start right after the 16-byte TXWI field |
| ptr = pAd->BeaconBuf; |
| for (i = 0; i < pAd->BeaconTxWI.MPDUtotalByteCount; i += 2) { |
| //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); |
| //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); |
| RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2); |
| ptr += 2; |
| } |
| #endif // RTMP_MAC_USB // |
| |
| // |
| // For Wi-Fi faily generated beacons between participating stations. |
| // Set TBTT phase adaptive adjustment step to 8us (default 16us) |
| // don't change settings 2006-5- by Jerry |
| //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); |
| |
| // start sending BEACON |
| csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU |
| csr9.field.bTsfTicking = 1; |
| csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode |
| csr9.field.bTBTTEnable = 1; |
| csr9.field.bBeaconGen = 1; |
| RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicSetEdcaParm(IN PRTMP_ADAPTER pAd, IN PEDCA_PARM pEdcaParm) |
| { |
| EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; |
| AC_TXOP_CSR0_STRUC csr0; |
| AC_TXOP_CSR1_STRUC csr1; |
| AIFSN_CSR_STRUC AifsnCsr; |
| CWMIN_CSR_STRUC CwminCsr; |
| CWMAX_CSR_STRUC CwmaxCsr; |
| int i; |
| |
| Ac0Cfg.word = 0; |
| Ac1Cfg.word = 0; |
| Ac2Cfg.word = 0; |
| Ac3Cfg.word = 0; |
| if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) { |
| DBGPRINT(RT_DEBUG_TRACE, ("AsicSetEdcaParm\n")); |
| OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); |
| for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { |
| if (pAd->MacTab.Content[i].ValidAsCLI |
| || pAd->MacTab.Content[i].ValidAsApCli) |
| CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab. |
| Content[i], |
| fCLIENT_STATUS_WMM_CAPABLE); |
| } |
| |
| //======================================================== |
| // MAC Register has a copy . |
| //======================================================== |
| //#ifndef WIFI_TEST |
| if (pAd->CommonCfg.bEnableTxBurst) { |
| // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode |
| Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode |
| } else |
| Ac0Cfg.field.AcTxop = 0; // QID_AC_BE |
| //#else |
| // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE |
| //#endif |
| Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; |
| Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; |
| Ac0Cfg.field.Aifsn = 2; |
| RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); |
| |
| Ac1Cfg.field.AcTxop = 0; // QID_AC_BK |
| Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; |
| Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; |
| Ac1Cfg.field.Aifsn = 2; |
| RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); |
| |
| if (pAd->CommonCfg.PhyMode == PHY_11B) { |
| Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms |
| Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms |
| } else { |
| Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms |
| Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms |
| } |
| Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; |
| Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; |
| Ac2Cfg.field.Aifsn = 2; |
| RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); |
| Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; |
| Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; |
| Ac3Cfg.field.Aifsn = 2; |
| RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); |
| |
| //======================================================== |
| // DMA Register has a copy too. |
| //======================================================== |
| csr0.field.Ac0Txop = 0; // QID_AC_BE |
| csr0.field.Ac1Txop = 0; // QID_AC_BK |
| RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); |
| if (pAd->CommonCfg.PhyMode == PHY_11B) { |
| csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms |
| csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms |
| } else { |
| csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms |
| csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms |
| } |
| RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); |
| |
| CwminCsr.word = 0; |
| CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; |
| CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; |
| CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; |
| CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; |
| RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); |
| |
| CwmaxCsr.word = 0; |
| CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; |
| CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; |
| CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; |
| CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; |
| RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); |
| |
| RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); |
| |
| NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); |
| } else { |
| OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); |
| //======================================================== |
| // MAC Register has a copy. |
| //======================================================== |
| // |
| // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 |
| // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. |
| // |
| //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this |
| |
| Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; |
| Ac0Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BE]; |
| Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; |
| Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; |
| |
| Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; |
| Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; |
| Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; |
| Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; |
| |
| Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; |
| if (pAd->Antenna.field.TxPath == 1) { |
| Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI] + 1; |
| Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI] + 1; |
| } else { |
| Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; |
| Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; |
| } |
| Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; |
| #ifdef RTMP_MAC_USB |
| Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 3; |
| #endif // RTMP_MAC_USB // |
| |
| { |
| // Tuning for Wi-Fi WMM S06 |
| if (pAd->CommonCfg.bWiFiTest && |
| pEdcaParm->Aifsn[QID_AC_VI] == 10) |
| Ac2Cfg.field.Aifsn -= 1; |
| |
| // Tuning for TGn Wi-Fi 5.2.32 |
| // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta |
| if (STA_TGN_WIFI_ON(pAd) && |
| pEdcaParm->Aifsn[QID_AC_VI] == 10) { |
| Ac0Cfg.field.Aifsn = 3; |
| Ac2Cfg.field.AcTxop = 5; |
| } |
| #ifdef RT30xx |
| if (pAd->RfIcType == RFIC_3020 |
| || pAd->RfIcType == RFIC_2020) { |
| // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. |
| Ac2Cfg.field.Aifsn = 5; |
| } |
| #endif // RT30xx // |
| } |
| |
| Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; |
| Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; |
| Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; |
| Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; |
| |
| //#ifdef WIFI_TEST |
| if (pAd->CommonCfg.bWiFiTest) { |
| if (Ac3Cfg.field.AcTxop == 102) { |
| Ac0Cfg.field.AcTxop = |
| pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm-> |
| Txop[QID_AC_BE] : 10; |
| Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE] - 1; /* AIFSN must >= 1 */ |
| Ac1Cfg.field.AcTxop = |
| pEdcaParm->Txop[QID_AC_BK]; |
| Ac1Cfg.field.Aifsn = |
| pEdcaParm->Aifsn[QID_AC_BK]; |
| Ac2Cfg.field.AcTxop = |
| pEdcaParm->Txop[QID_AC_VI]; |
| } /* End of if */ |
| } |
| //#endif // WIFI_TEST // |
| |
| RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); |
| RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); |
| RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); |
| RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); |
| |
| //======================================================== |
| // DMA Register has a copy too. |
| //======================================================== |
| csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; |
| csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; |
| RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); |
| |
| csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; |
| csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; |
| RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); |
| |
| CwminCsr.word = 0; |
| CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; |
| CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; |
| CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; |
| CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test |
| RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); |
| |
| CwmaxCsr.word = 0; |
| CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; |
| CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; |
| CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; |
| CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; |
| RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); |
| |
| AifsnCsr.word = 0; |
| AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; |
| AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; |
| AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; |
| |
| { |
| // Tuning for Wi-Fi WMM S06 |
| if (pAd->CommonCfg.bWiFiTest && |
| pEdcaParm->Aifsn[QID_AC_VI] == 10) |
| AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; |
| |
| // Tuning for TGn Wi-Fi 5.2.32 |
| // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta |
| if (STA_TGN_WIFI_ON(pAd) && |
| pEdcaParm->Aifsn[QID_AC_VI] == 10) { |
| AifsnCsr.field.Aifsn0 = 3; |
| AifsnCsr.field.Aifsn2 = 7; |
| } |
| |
| if (INFRA_ON(pAd)) |
| CLIENT_STATUS_SET_FLAG(&pAd->MacTab. |
| Content[BSSID_WCID], |
| fCLIENT_STATUS_WMM_CAPABLE); |
| } |
| |
| { |
| AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test |
| #ifdef RT30xx |
| // TODO: Shiang, this modification also suitable for RT3052/RT3050 ??? |
| if (pAd->RfIcType == RFIC_3020 |
| || pAd->RfIcType == RFIC_2020) { |
| AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. |
| } |
| #endif // RT30xx // |
| } |
| RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); |
| |
| NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, |
| sizeof(EDCA_PARM)); |
| if (!ADHOC_ON(pAd)) { |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", |
| pEdcaParm->EdcaUpdateCount)); |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" AC_BE %2d %2d %2d %4d %d\n", |
| pEdcaParm->Aifsn[0], pEdcaParm->Cwmin[0], |
| pEdcaParm->Cwmax[0], pEdcaParm->Txop[0] << 5, |
| pEdcaParm->bACM[0])); |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" AC_BK %2d %2d %2d %4d %d\n", |
| pEdcaParm->Aifsn[1], pEdcaParm->Cwmin[1], |
| pEdcaParm->Cwmax[1], pEdcaParm->Txop[1] << 5, |
| pEdcaParm->bACM[1])); |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" AC_VI %2d %2d %2d %4d %d\n", |
| pEdcaParm->Aifsn[2], pEdcaParm->Cwmin[2], |
| pEdcaParm->Cwmax[2], pEdcaParm->Txop[2] << 5, |
| pEdcaParm->bACM[2])); |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" AC_VO %2d %2d %2d %4d %d\n", |
| pEdcaParm->Aifsn[3], pEdcaParm->Cwmin[3], |
| pEdcaParm->Cwmax[3], pEdcaParm->Txop[3] << 5, |
| pEdcaParm->bACM[3])); |
| } |
| } |
| |
| } |
| |
| /* |
| ========================================================================== |
| Description: |
| |
| IRQL = PASSIVE_LEVEL |
| IRQL = DISPATCH_LEVEL |
| |
| ========================================================================== |
| */ |
| VOID AsicSetSlotTime(IN PRTMP_ADAPTER pAd, IN BOOLEAN bUseShortSlotTime) |
| { |
| ULONG SlotTime; |
| UINT32 RegValue = 0; |
| |
| if (pAd->CommonCfg.Channel > 14) |
| bUseShortSlotTime = TRUE; |
| |
| if (bUseShortSlotTime |
| && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) |
| return; |
| else if ((!bUseShortSlotTime) |
| && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))) |
| return; |
| |
| if (bUseShortSlotTime) |
| OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); |
| else |
| OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); |
| |
| SlotTime = (bUseShortSlotTime) ? 9 : 20; |
| |
| { |
| // force using short SLOT time for FAE to demo performance when TxBurst is ON |
| if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) |
| && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))) |
| || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) |
| && (pAd->CommonCfg.BACapability.field.Policy == |
| BA_NOTUSE)) |
| ) { |
| // In this case, we will think it is doing Wi-Fi test |
| // And we will not set to short slot when bEnableTxBurst is TRUE. |
| } else if (pAd->CommonCfg.bEnableTxBurst) { |
| OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); |
| SlotTime = 9; |
| } |
| } |
| |
| // |
| // For some reasons, always set it to short slot time. |
| // |
| // ToDo: Should consider capability with 11B |
| // |
| { |
| if (pAd->StaCfg.BssType == BSS_ADHOC) { |
| OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); |
| SlotTime = 20; |
| } |
| } |
| |
| RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); |
| RegValue = RegValue & 0xFFFFFF00; |
| |
| RegValue |= SlotTime; |
| |
| RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); |
| } |
| |
| /* |
| ======================================================================== |
| Description: |
| Add Shared key information into ASIC. |
| Update shared key, TxMic and RxMic to Asic Shared key table |
| Update its cipherAlg to Asic Shared key Mode. |
| |
| Return: |
| ======================================================================== |
| */ |
| VOID AsicAddSharedKeyEntry(IN PRTMP_ADAPTER pAd, |
| IN UCHAR BssIndex, |
| IN UCHAR KeyIdx, |
| IN UCHAR CipherAlg, |
| IN PUCHAR pKey, IN PUCHAR pTxMic, IN PUCHAR pRxMic) |
| { |
| ULONG offset; //, csr0; |
| SHAREDKEY_MODE_STRUC csr1; |
| #ifdef RTMP_MAC_PCI |
| INT i; |
| #endif // RTMP_MAC_PCI // |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex, |
| KeyIdx)); |
| //============================================================================================ |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], |
| BssIndex * 4 + KeyIdx)); |
| DBGPRINT_RAW(RT_DEBUG_TRACE, |
| (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], |
| pKey[5], pKey[6], pKey[7], pKey[8], pKey[9], |
| pKey[10], pKey[11], pKey[12], pKey[13], pKey[14], |
| pKey[15])); |
| if (pRxMic) { |
| DBGPRINT_RAW(RT_DEBUG_TRACE, |
| (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], |
| pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); |
| } |
| if (pTxMic) { |
| DBGPRINT_RAW(RT_DEBUG_TRACE, |
| (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], |
| pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); |
| } |
| //============================================================================================ |
| // |
| // fill key material - key + TX MIC + RX MIC |
| // |
| #ifdef RTMP_MAC_PCI |
| offset = |
| SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; |
| for (i = 0; i < MAX_LEN_OF_SHARE_KEY; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); |
| } |
| |
| offset += MAX_LEN_OF_SHARE_KEY; |
| if (pTxMic) { |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); |
| } |
| } |
| |
| offset += 8; |
| if (pRxMic) { |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); |
| } |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| { |
| offset = |
| SHARED_KEY_TABLE_BASE + (4 * BssIndex + |
| KeyIdx) * HW_KEY_ENTRY_SIZE; |
| RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY); |
| |
| offset += MAX_LEN_OF_SHARE_KEY; |
| if (pTxMic) { |
| RTUSBMultiWrite(pAd, offset, pTxMic, 8); |
| } |
| |
| offset += 8; |
| if (pRxMic) { |
| RTUSBMultiWrite(pAd, offset, pRxMic, 8); |
| } |
| } |
| #endif // RTMP_MAC_USB // |
| |
| // |
| // Update cipher algorithm. WSTA always use BSS0 |
| // |
| RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| &csr1.word); |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", |
| BssIndex, KeyIdx, csr1.word)); |
| if ((BssIndex % 2) == 0) { |
| if (KeyIdx == 0) |
| csr1.field.Bss0Key0CipherAlg = CipherAlg; |
| else if (KeyIdx == 1) |
| csr1.field.Bss0Key1CipherAlg = CipherAlg; |
| else if (KeyIdx == 2) |
| csr1.field.Bss0Key2CipherAlg = CipherAlg; |
| else |
| csr1.field.Bss0Key3CipherAlg = CipherAlg; |
| } else { |
| if (KeyIdx == 0) |
| csr1.field.Bss1Key0CipherAlg = CipherAlg; |
| else if (KeyIdx == 1) |
| csr1.field.Bss1Key1CipherAlg = CipherAlg; |
| else if (KeyIdx == 2) |
| csr1.field.Bss1Key2CipherAlg = CipherAlg; |
| else |
| csr1.field.Bss1Key3CipherAlg = CipherAlg; |
| } |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", |
| BssIndex, csr1.word)); |
| RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| csr1.word); |
| |
| } |
| |
| // IRQL = DISPATCH_LEVEL |
| VOID AsicRemoveSharedKeyEntry(IN PRTMP_ADAPTER pAd, |
| IN UCHAR BssIndex, IN UCHAR KeyIdx) |
| { |
| //ULONG SecCsr0; |
| SHAREDKEY_MODE_STRUC csr1; |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicRemoveSharedKeyEntry: #%d \n", BssIndex * 4 + KeyIdx)); |
| |
| RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| &csr1.word); |
| if ((BssIndex % 2) == 0) { |
| if (KeyIdx == 0) |
| csr1.field.Bss0Key0CipherAlg = 0; |
| else if (KeyIdx == 1) |
| csr1.field.Bss0Key1CipherAlg = 0; |
| else if (KeyIdx == 2) |
| csr1.field.Bss0Key2CipherAlg = 0; |
| else |
| csr1.field.Bss0Key3CipherAlg = 0; |
| } else { |
| if (KeyIdx == 0) |
| csr1.field.Bss1Key0CipherAlg = 0; |
| else if (KeyIdx == 1) |
| csr1.field.Bss1Key1CipherAlg = 0; |
| else if (KeyIdx == 2) |
| csr1.field.Bss1Key2CipherAlg = 0; |
| else |
| csr1.field.Bss1Key3CipherAlg = 0; |
| } |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", |
| BssIndex, csr1.word)); |
| RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| csr1.word); |
| ASSERT(BssIndex < 4); |
| ASSERT(KeyIdx < 4); |
| |
| } |
| |
| VOID AsicUpdateWCIDAttribute(IN PRTMP_ADAPTER pAd, |
| IN USHORT WCID, |
| IN UCHAR BssIndex, |
| IN UCHAR CipherAlg, |
| IN BOOLEAN bUsePairewiseKeyTable) |
| { |
| ULONG WCIDAttri = 0, offset; |
| |
| // |
| // Update WCID attribute. |
| // Only TxKey could update WCID attribute. |
| // |
| offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); |
| WCIDAttri = |
| (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); |
| RTMP_IO_WRITE32(pAd, offset, WCIDAttri); |
| } |
| |
| VOID AsicUpdateWCIDIVEIV(IN PRTMP_ADAPTER pAd, |
| IN USHORT WCID, IN ULONG uIV, IN ULONG uEIV) |
| { |
| ULONG offset; |
| |
| offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); |
| |
| RTMP_IO_WRITE32(pAd, offset, uIV); |
| RTMP_IO_WRITE32(pAd, offset + 4, uEIV); |
| } |
| |
| VOID AsicUpdateRxWCIDTable(IN PRTMP_ADAPTER pAd, |
| IN USHORT WCID, IN PUCHAR pAddr) |
| { |
| ULONG offset; |
| ULONG Addr; |
| |
| offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); |
| Addr = pAddr[0] + (pAddr[1] << 8) + (pAddr[2] << 16) + (pAddr[3] << 24); |
| RTMP_IO_WRITE32(pAd, offset, Addr); |
| Addr = pAddr[4] + (pAddr[5] << 8); |
| RTMP_IO_WRITE32(pAd, offset + 4, Addr); |
| } |
| |
| /* |
| ======================================================================== |
| |
| Routine Description: |
| Set Cipher Key, Cipher algorithm, IV/EIV to Asic |
| |
| Arguments: |
| pAd Pointer to our adapter |
| WCID WCID Entry number. |
| BssIndex BSSID index, station or none multiple BSSID support |
| this value should be 0. |
| KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled |
| pCipherKey Pointer to Cipher Key. |
| bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, |
| otherwise PairewiseKey table |
| bTxKey This is the transmit key if enabled. |
| |
| Return Value: |
| None |
| |
| Note: |
| This routine will set the relative key stuff to Asic including WCID attribute, |
| Cipher Key, Cipher algorithm and IV/EIV. |
| |
| IV/EIV will be update if this CipherKey is the transmission key because |
| ASIC will base on IV's KeyID value to select Cipher Key. |
| |
| If bTxKey sets to FALSE, this is not the TX key, but it could be |
| RX key |
| |
| For AP mode bTxKey must be always set to TRUE. |
| ======================================================================== |
| */ |
| VOID AsicAddKeyEntry(IN PRTMP_ADAPTER pAd, |
| IN USHORT WCID, |
| IN UCHAR BssIndex, |
| IN UCHAR KeyIdx, |
| IN PCIPHER_KEY pCipherKey, |
| IN BOOLEAN bUsePairewiseKeyTable, IN BOOLEAN bTxKey) |
| { |
| ULONG offset; |
| // ULONG WCIDAttri = 0; |
| UCHAR IV4 = 0; |
| PUCHAR pKey = pCipherKey->Key; |
| // ULONG KeyLen = pCipherKey->KeyLen; |
| PUCHAR pTxMic = pCipherKey->TxMic; |
| PUCHAR pRxMic = pCipherKey->RxMic; |
| PUCHAR pTxtsc = pCipherKey->TxTsc; |
| UCHAR CipherAlg = pCipherKey->CipherAlg; |
| SHAREDKEY_MODE_STRUC csr1; |
| #ifdef RTMP_MAC_PCI |
| UCHAR i; |
| #endif // RTMP_MAC_PCI // |
| |
| // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); |
| // |
| // 1.) decide key table offset |
| // |
| if (bUsePairewiseKeyTable) |
| offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); |
| else |
| offset = |
| SHARED_KEY_TABLE_BASE + (4 * BssIndex + |
| KeyIdx) * HW_KEY_ENTRY_SIZE; |
| |
| // |
| // 2.) Set Key to Asic |
| // |
| //for (i = 0; i < KeyLen; i++) |
| #ifdef RTMP_MAC_PCI |
| for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); |
| } |
| offset += MAX_LEN_OF_PEER_KEY; |
| |
| // |
| // 3.) Set MIC key if available |
| // |
| if (pTxMic) { |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); |
| } |
| } |
| offset += LEN_TKIP_TXMICK; |
| |
| if (pRxMic) { |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); |
| } |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY); |
| offset += MAX_LEN_OF_PEER_KEY; |
| |
| // |
| // 3.) Set MIC key if available |
| // |
| if (pTxMic) { |
| RTUSBMultiWrite(pAd, offset, pTxMic, 8); |
| } |
| offset += LEN_TKIP_TXMICK; |
| |
| if (pRxMic) { |
| RTUSBMultiWrite(pAd, offset, pRxMic, 8); |
| } |
| #endif // RTMP_MAC_USB // |
| |
| // |
| // 4.) Modify IV/EIV if needs |
| // This will force Asic to use this key ID by setting IV. |
| // |
| if (bTxKey) { |
| #ifdef RTMP_MAC_PCI |
| offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); |
| // |
| // Write IV |
| // |
| RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]); |
| RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f)); |
| RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]); |
| |
| IV4 = (KeyIdx << 6); |
| if ((CipherAlg == CIPHER_TKIP) |
| || (CipherAlg == CIPHER_TKIP_NO_MIC) |
| || (CipherAlg == CIPHER_AES)) |
| IV4 |= 0x20; // turn on extension bit means EIV existence |
| |
| RTMP_IO_WRITE8(pAd, offset + 3, IV4); |
| |
| // |
| // Write EIV |
| // |
| offset += 4; |
| for (i = 0; i < 4; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| UINT32 tmpVal; |
| |
| // |
| // Write IV |
| // |
| IV4 = (KeyIdx << 6); |
| if ((CipherAlg == CIPHER_TKIP) |
| || (CipherAlg == CIPHER_TKIP_NO_MIC) |
| || (CipherAlg == CIPHER_AES)) |
| IV4 |= 0x20; // turn on extension bit means EIV existence |
| |
| tmpVal = |
| pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + |
| (pTxtsc[0] << 16) + (IV4 << 24); |
| RTMP_IO_WRITE32(pAd, offset, tmpVal); |
| |
| // |
| // Write EIV |
| // |
| offset += 4; |
| RTMP_IO_WRITE32(pAd, offset, *(PUINT32) & pCipherKey->TxTsc[2]); |
| #endif // RTMP_MAC_USB // |
| |
| AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, |
| bUsePairewiseKeyTable); |
| } |
| |
| if (!bUsePairewiseKeyTable) { |
| // |
| // Only update the shared key security mode |
| // |
| RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| &csr1.word); |
| if ((BssIndex % 2) == 0) { |
| if (KeyIdx == 0) |
| csr1.field.Bss0Key0CipherAlg = CipherAlg; |
| else if (KeyIdx == 1) |
| csr1.field.Bss0Key1CipherAlg = CipherAlg; |
| else if (KeyIdx == 2) |
| csr1.field.Bss0Key2CipherAlg = CipherAlg; |
| else |
| csr1.field.Bss0Key3CipherAlg = CipherAlg; |
| } else { |
| if (KeyIdx == 0) |
| csr1.field.Bss1Key0CipherAlg = CipherAlg; |
| else if (KeyIdx == 1) |
| csr1.field.Bss1Key1CipherAlg = CipherAlg; |
| else if (KeyIdx == 2) |
| csr1.field.Bss1Key2CipherAlg = CipherAlg; |
| else |
| csr1.field.Bss1Key3CipherAlg = CipherAlg; |
| } |
| RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), |
| csr1.word); |
| } |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); |
| } |
| |
| /* |
| ======================================================================== |
| Description: |
| Add Pair-wise key material into ASIC. |
| Update pairwise key, TxMic and RxMic to Asic Pair-wise key table |
| |
| Return: |
| ======================================================================== |
| */ |
| VOID AsicAddPairwiseKeyEntry(IN PRTMP_ADAPTER pAd, |
| IN PUCHAR pAddr, |
| IN UCHAR WCID, IN CIPHER_KEY * pCipherKey) |
| { |
| INT i; |
| ULONG offset; |
| PUCHAR pKey = pCipherKey->Key; |
| PUCHAR pTxMic = pCipherKey->TxMic; |
| PUCHAR pRxMic = pCipherKey->RxMic; |
| #ifdef DBG |
| UCHAR CipherAlg = pCipherKey->CipherAlg; |
| #endif // DBG // |
| |
| // EKEY |
| offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); |
| #ifdef RTMP_MAC_PCI |
| for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY); |
| #endif // RTMP_MAC_USB // |
| for (i = 0; i < MAX_LEN_OF_PEER_KEY; i += 4) { |
| UINT32 Value; |
| RTMP_IO_READ32(pAd, offset + i, &Value); |
| } |
| |
| offset += MAX_LEN_OF_PEER_KEY; |
| |
| // MIC KEY |
| if (pTxMic) { |
| #ifdef RTMP_MAC_PCI |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]); |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8); |
| #endif // RTMP_MAC_USB // |
| } |
| offset += 8; |
| if (pRxMic) { |
| #ifdef RTMP_MAC_PCI |
| for (i = 0; i < 8; i++) { |
| RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); |
| } |
| #endif // RTMP_MAC_PCI // |
| #ifdef RTMP_MAC_USB |
| RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8); |
| #endif // RTMP_MAC_USB // |
| } |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n", WCID, |
| CipherName[CipherAlg])); |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pKey[0], pKey[1], pKey[2], pKey[3], pKey[4], pKey[5], |
| pKey[6], pKey[7], pKey[8], pKey[9], pKey[10], pKey[11], |
| pKey[12], pKey[13], pKey[14], pKey[15])); |
| if (pRxMic) { |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pRxMic[0], pRxMic[1], pRxMic[2], pRxMic[3], |
| pRxMic[4], pRxMic[5], pRxMic[6], pRxMic[7])); |
| } |
| if (pTxMic) { |
| DBGPRINT(RT_DEBUG_TRACE, |
| (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
| pTxMic[0], pTxMic[1], pTxMic[2], pTxMic[3], |
| pTxMic[4], pTxMic[5], pTxMic[6], pTxMic[7])); |
| } |
| } |
| |
| /* |
| ======================================================================== |
| Description: |
| Remove Pair-wise key material from ASIC. |
| |
| Return: |
| ======================================================================== |
| */ |
| VOID AsicRemovePairwiseKeyEntry(IN PRTMP_ADAPTER pAd, |
| IN UCHAR BssIdx, IN UCHAR Wcid) |
| { |
| ULONG WCIDAttri; |
| USHORT offset; |
| |
| // re-set the entry's WCID attribute as OPEN-NONE. |
| offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); |
| WCIDAttri = (BssIdx << 4) | PAIRWISEKEYTABLE; |
| RTMP_IO_WRITE32(pAd, offset, WCIDAttri); |
| } |
| |
| BOOLEAN AsicSendCommandToMcu(IN PRTMP_ADAPTER pAd, |
| IN UCHAR Command, |
| IN UCHAR Token, IN UCHAR Arg0, IN UCHAR Arg1) |
| { |
| |
| if (pAd->chipOps.sendCommandToMcu) |
| pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1); |
| |
| return TRUE; |
| } |
| |
| VOID AsicSetRxAnt(IN PRTMP_ADAPTER pAd, IN UCHAR Ant) |
| { |
| #ifdef RT30xx |
| /* RT3572 ATE need not to do this. */ |
| RT30xxSetRxAnt(pAd, Ant); |
| #endif // RT30xx // |
| } |
| |
| VOID AsicTurnOffRFClk(IN PRTMP_ADAPTER pAd, IN UCHAR Channel) |
| { |
| if (pAd->chipOps.AsicRfTurnOff) { |
| pAd->chipOps.AsicRfTurnOff(pAd); |
| } else { |
| // RF R2 bit 18 = 0 |
| UINT32 R1 = 0, R2 = 0, R3 = 0; |
| UCHAR index; |
| RTMP_RF_REGS *RFRegTable; |
| |
| RFRegTable = RF2850RegTable; |
| |
| switch (pAd->RfIcType) { |
| case RFIC_2820: |
| case RFIC_2850: |
| case RFIC_2720: |
| case RFIC_2750: |
| |
| for (index = 0; index < NUM_OF_2850_CHNL; index++) { |
| if (Channel == RFRegTable[index].Channel) { |
| R1 = RFRegTable[index].R1 & 0xffffdfff; |
| R2 = RFRegTable[index].R2 & 0xfffbffff; |
| R3 = RFRegTable[index].R3 & 0xfff3ffff; |
| |
| RTMP_RF_IO_WRITE32(pAd, R1); |
| RTMP_RF_IO_WRITE32(pAd, R2); |
| |
| // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. |
| // Set RF R2 bit18=0, R3 bit[18:19]=0 |
| //if (pAd->StaCfg.bRadio == FALSE) |
| if (1) { |
| RTMP_RF_IO_WRITE32(pAd, R3); |
| |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", |
| Channel, |
| pAd->RfIcType, R2, |
| R3)); |
| } else |
| DBGPRINT(RT_DEBUG_TRACE, |
| ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", |
| Channel, |
| pAd->RfIcType, R2)); |
| break; |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| } |
| |
| VOID AsicTurnOnRFClk(IN PRTMP_ADAPTER pAd, IN UCHAR Channel) |
| { |
| // RF R2 bit 18 = 0 |
| UINT32 R1 = 0, R2 = 0, R3 = 0; |
| UCHAR index; |
| RTMP_RF_REGS *RFRegTable; |
| |
| #ifdef PCIE_PS_SUPPORT |
| // The RF programming sequence is difference between 3xxx and 2xxx |
| if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { |
| return; |
| } |
| #endif // PCIE_PS_SUPPORT // |
| |
| RFRegTable = RF2850RegTable; |
| |
| switch (pAd->RfIcType) { |
| case RFIC_2820: |
| case RFIC_2850: |
| case RFIC_2720: |
| case RFIC_2750: |
| |
| for (index = 0; index < NUM_OF_2850_CHNL; index++) { |
| if (Channel == RFRegTable[index].Channel) { |
| R3 = pAd->LatchRfRegs.R3; |
| R3 &= 0xfff3ffff; |
| R3 |= 0x00080000; |
| RTMP_RF_IO_WRITE32(pAd, R3); |
| |
| R1 = RFRegTable[index].R1; |
| RTMP_RF_IO_WRITE32(pAd, R1); |
| |
| R2 = RFRegTable[index].R2; |
| if (pAd->Antenna.field.TxPath == 1) { |
| R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; |
| } |
| |
| if (pAd->Antenna.field.RxPath == 2) { |
| R2 |= 0x40; // write 1 to off Rxpath. |
| } else if (pAd->Antenna.field.RxPath == 1) { |
| R2 |= 0x20040; // write 1 to off RxPath |
| } |
| RTMP_RF_IO_WRITE32(pAd, R2); |
| |
| break; |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n", |
| Channel, pAd->RfIcType, R2)); |
| } |