|  | /* | 
|  | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | 
|  | * All rights reserved. | 
|  | * | 
|  | * 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., | 
|  | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 
|  | * | 
|  | * File: card.c | 
|  | * Purpose: Provide functions to setup NIC operation mode | 
|  | * Functions: | 
|  | *      s_vSafeResetTx - Rest Tx | 
|  | *      CARDvSetRSPINF - Set RSPINF | 
|  | *      vUpdateIFS - Update slotTime,SIFS,DIFS, and EIFS | 
|  | *      CARDvUpdateBasicTopRate - Update BasicTopRate | 
|  | *      CARDbAddBasicRate - Add to BasicRateSet | 
|  | *      CARDbSetBasicRate - Set Basic Tx Rate | 
|  | *      CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet | 
|  | *      CARDvSetLoopbackMode - Set Loopback mode | 
|  | *      CARDbSoftwareReset - Sortware reset NIC | 
|  | *      CARDqGetTSFOffset - Calculate TSFOffset | 
|  | *      CARDbGetCurrentTSF - Read Current NIC TSF counter | 
|  | *      CARDqGetNextTBTT - Calculate Next Beacon TSF counter | 
|  | *      CARDvSetFirstNextTBTT - Set NIC Beacon time | 
|  | *      CARDvUpdateNextTBTT - Sync. NIC Beacon time | 
|  | *      CARDbRadioPowerOff - Turn Off NIC Radio Power | 
|  | *      CARDbRadioPowerOn - Turn On NIC Radio Power | 
|  | *      CARDbSetWEPMode - Set NIC Wep mode | 
|  | *      CARDbSetTxPower - Set NIC tx power | 
|  | * | 
|  | * Revision History: | 
|  | *      06-10-2003 Bryan YC Fan:  Re-write codes to support VT3253 spec. | 
|  | *      08-26-2003 Kyle Hsu:      Modify the definition type of dwIoBase. | 
|  | *      09-01-2003 Bryan YC Fan:  Add vUpdateIFS(). | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include "device.h" | 
|  | #include "tmacro.h" | 
|  | #include "card.h" | 
|  | #include "baseband.h" | 
|  | #include "mac.h" | 
|  | #include "desc.h" | 
|  | #include "rf.h" | 
|  | #include "power.h" | 
|  | #include "key.h" | 
|  | #include "rc4.h" | 
|  | #include "country.h" | 
|  | #include "datarate.h" | 
|  | #include "rndis.h" | 
|  | #include "control.h" | 
|  |  | 
|  | //static int          msglevel                =MSG_LEVEL_DEBUG; | 
|  | static int          msglevel                =MSG_LEVEL_INFO; | 
|  |  | 
|  | //const u16 cwRXBCNTSFOff[MAX_RATE] = | 
|  | //{17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; | 
|  |  | 
|  | const u16 cwRXBCNTSFOff[MAX_RATE] = | 
|  | {192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3}; | 
|  |  | 
|  | /* | 
|  | * Description: Set NIC media channel | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice             - The adapter to be set | 
|  | *      uConnectionChannel  - Channel to be set | 
|  | *  Out: | 
|  | *      none | 
|  | */ | 
|  | void CARDbSetMediaChannel(struct vnt_private *pDevice, u32 uConnectionChannel) | 
|  | { | 
|  |  | 
|  | if (pDevice->byBBType == BB_TYPE_11A) { // 15 ~ 38 | 
|  | if ((uConnectionChannel < (CB_MAX_CHANNEL_24G+1)) || (uConnectionChannel > CB_MAX_CHANNEL)) | 
|  | uConnectionChannel = (CB_MAX_CHANNEL_24G+1); | 
|  | } else { | 
|  | if ((uConnectionChannel > CB_MAX_CHANNEL_24G) || (uConnectionChannel == 0)) // 1 ~ 14 | 
|  | uConnectionChannel = 1; | 
|  | } | 
|  |  | 
|  | // clear NAV | 
|  | MACvRegBitsOn(pDevice, MAC_REG_MACCR, MACCR_CLRNAV); | 
|  |  | 
|  | // Set Channel[7] = 0 to tell H/W channel is changing now. | 
|  | MACvRegBitsOff(pDevice, MAC_REG_CHANNEL, 0x80); | 
|  |  | 
|  | //if (pMgmt->uCurrChannel == uConnectionChannel) | 
|  | //    return bResult; | 
|  |  | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_SELECT_CHANNLE, | 
|  | (u16) uConnectionChannel, | 
|  | 0, | 
|  | 0, | 
|  | NULL | 
|  | ); | 
|  |  | 
|  | //{{ RobertYu: 20041202 | 
|  | //// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput | 
|  |  | 
|  | if (pDevice->byBBType == BB_TYPE_11A) { | 
|  | pDevice->byCurPwr = 0xFF; | 
|  | RFbRawSetPower(pDevice, pDevice->abyOFDMAPwrTbl[uConnectionChannel-15], RATE_54M); | 
|  | } else if (pDevice->byBBType == BB_TYPE_11G) { | 
|  | pDevice->byCurPwr = 0xFF; | 
|  | RFbRawSetPower(pDevice, pDevice->abyOFDMPwrTbl[uConnectionChannel-1], RATE_54M); | 
|  | } else { | 
|  | pDevice->byCurPwr = 0xFF; | 
|  | RFbRawSetPower(pDevice, pDevice->abyCCKPwrTbl[uConnectionChannel-1], RATE_1M); | 
|  | } | 
|  | ControlvWriteByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_CHANNEL,(u8)(uConnectionChannel|0x80)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Get CCK mode basic rate | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice             - The adapter to be set | 
|  | *      wRateIdx            - Receiving data rate | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: response Control frame rate | 
|  | * | 
|  | */ | 
|  | static u16 swGetCCKControlRate(struct vnt_private *pDevice, u16 wRateIdx) | 
|  | { | 
|  | u16 ui = wRateIdx; | 
|  |  | 
|  | while (ui > RATE_1M) { | 
|  | if (pDevice->wBasicRate & (1 << ui)) | 
|  | return ui; | 
|  | ui--; | 
|  | } | 
|  |  | 
|  | return RATE_1M; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Get OFDM mode basic rate | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice             - The adapter to be set | 
|  | *      wRateIdx            - Receiving data rate | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: response Control frame rate | 
|  | * | 
|  | */ | 
|  | static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx) | 
|  | { | 
|  | u16 ui = wRateIdx; | 
|  |  | 
|  | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BASIC RATE: %X\n", | 
|  | pDevice->wBasicRate); | 
|  |  | 
|  | if (!CARDbIsOFDMinBasicRate(pDevice)) { | 
|  | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | 
|  | "swGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx); | 
|  | if (wRateIdx > RATE_24M) | 
|  | wRateIdx = RATE_24M; | 
|  | return wRateIdx; | 
|  | } | 
|  |  | 
|  | while (ui > RATE_11M) { | 
|  | if (pDevice->wBasicRate & (1 << ui)) { | 
|  | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | 
|  | "swGetOFDMControlRate: %d\n", ui); | 
|  | return ui; | 
|  | } | 
|  | ui--; | 
|  | } | 
|  |  | 
|  | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"swGetOFDMControlRate: 6M\n"); | 
|  |  | 
|  | return RATE_24M; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      wRate           - Tx Rate | 
|  | *      byPktType       - Tx Packet type | 
|  | *  Out: | 
|  | *      pbyTxRate       - pointer to RSPINF TxRate field | 
|  | *      pbyRsvTime      - pointer to RSPINF RsvTime field | 
|  | * | 
|  | * Return Value: none | 
|  | * | 
|  | */ | 
|  | void | 
|  | CARDvCalculateOFDMRParameter ( | 
|  | u16 wRate, | 
|  | u8 byBBType, | 
|  | u8 * pbyTxRate, | 
|  | u8 * pbyRsvTime | 
|  | ) | 
|  | { | 
|  | switch (wRate) { | 
|  | case RATE_6M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9B; | 
|  | *pbyRsvTime = 24; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8B; | 
|  | *pbyRsvTime = 30; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_9M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9F; | 
|  | *pbyRsvTime = 16; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8F; | 
|  | *pbyRsvTime = 22; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_12M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9A; | 
|  | *pbyRsvTime = 12; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8A; | 
|  | *pbyRsvTime = 18; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_18M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9E; | 
|  | *pbyRsvTime = 8; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8E; | 
|  | *pbyRsvTime = 14; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_36M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9D; | 
|  | *pbyRsvTime = 4; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8D; | 
|  | *pbyRsvTime = 10; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_48M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x98; | 
|  | *pbyRsvTime = 4; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x88; | 
|  | *pbyRsvTime = 10; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_54M : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x9C; | 
|  | *pbyRsvTime = 4; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x8C; | 
|  | *pbyRsvTime = 10; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case RATE_24M : | 
|  | default : | 
|  | if (byBBType == BB_TYPE_11A) {//5GHZ | 
|  | *pbyTxRate = 0x99; | 
|  | *pbyRsvTime = 8; | 
|  | } | 
|  | else { | 
|  | *pbyTxRate = 0x89; | 
|  | *pbyRsvTime = 14; | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Set RSPINF | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice             - The adapter to be set | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: None. | 
|  | * | 
|  | */ | 
|  | void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType) | 
|  | { | 
|  | struct vnt_phy_field phy[4]; | 
|  | u8 abyTxRate[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; /* For OFDM */ | 
|  | u8 abyRsvTime[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; | 
|  | u8 abyData[34]; | 
|  | int i; | 
|  |  | 
|  | //RSPINF_b_1 | 
|  | BBvCalculateParameter(pDevice, 14, | 
|  | swGetCCKControlRate(pDevice, RATE_1M), PK_TYPE_11B, &phy[0]); | 
|  |  | 
|  | ///RSPINF_b_2 | 
|  | BBvCalculateParameter(pDevice, 14, | 
|  | swGetCCKControlRate(pDevice, RATE_2M), PK_TYPE_11B, &phy[1]); | 
|  |  | 
|  | //RSPINF_b_5 | 
|  | BBvCalculateParameter(pDevice, 14, | 
|  | swGetCCKControlRate(pDevice, RATE_5M), PK_TYPE_11B, &phy[2]); | 
|  |  | 
|  | //RSPINF_b_11 | 
|  | BBvCalculateParameter(pDevice, 14, | 
|  | swGetCCKControlRate(pDevice, RATE_11M), PK_TYPE_11B, &phy[3]); | 
|  |  | 
|  | //RSPINF_a_6 | 
|  | CARDvCalculateOFDMRParameter (RATE_6M, | 
|  | byBBType, | 
|  | &abyTxRate[0], | 
|  | &abyRsvTime[0]); | 
|  |  | 
|  | //RSPINF_a_9 | 
|  | CARDvCalculateOFDMRParameter (RATE_9M, | 
|  | byBBType, | 
|  | &abyTxRate[1], | 
|  | &abyRsvTime[1]); | 
|  |  | 
|  | //RSPINF_a_12 | 
|  | CARDvCalculateOFDMRParameter (RATE_12M, | 
|  | byBBType, | 
|  | &abyTxRate[2], | 
|  | &abyRsvTime[2]); | 
|  |  | 
|  | //RSPINF_a_18 | 
|  | CARDvCalculateOFDMRParameter (RATE_18M, | 
|  | byBBType, | 
|  | &abyTxRate[3], | 
|  | &abyRsvTime[3]); | 
|  |  | 
|  | //RSPINF_a_24 | 
|  | CARDvCalculateOFDMRParameter (RATE_24M, | 
|  | byBBType, | 
|  | &abyTxRate[4], | 
|  | &abyRsvTime[4]); | 
|  |  | 
|  | //RSPINF_a_36 | 
|  | CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_36M), | 
|  | byBBType, | 
|  | &abyTxRate[5], | 
|  | &abyRsvTime[5]); | 
|  |  | 
|  | //RSPINF_a_48 | 
|  | CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_48M), | 
|  | byBBType, | 
|  | &abyTxRate[6], | 
|  | &abyRsvTime[6]); | 
|  |  | 
|  | //RSPINF_a_54 | 
|  | CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), | 
|  | byBBType, | 
|  | &abyTxRate[7], | 
|  | &abyRsvTime[7]); | 
|  |  | 
|  | //RSPINF_a_72 | 
|  | CARDvCalculateOFDMRParameter (swGetOFDMControlRate(pDevice, RATE_54M), | 
|  | byBBType, | 
|  | &abyTxRate[8], | 
|  | &abyRsvTime[8]); | 
|  |  | 
|  | put_unaligned(phy[0].len, (u16 *)&abyData[0]); | 
|  | abyData[2] = phy[0].signal; | 
|  | abyData[3] = phy[0].service; | 
|  |  | 
|  | put_unaligned(phy[1].len, (u16 *)&abyData[4]); | 
|  | abyData[6] = phy[1].signal; | 
|  | abyData[7] = phy[1].service; | 
|  |  | 
|  | put_unaligned(phy[2].len, (u16 *)&abyData[8]); | 
|  | abyData[10] = phy[2].signal; | 
|  | abyData[11] = phy[2].service; | 
|  |  | 
|  | put_unaligned(phy[3].len, (u16 *)&abyData[12]); | 
|  | abyData[14] = phy[3].signal; | 
|  | abyData[15] = phy[3].service; | 
|  |  | 
|  | for (i = 0; i < 9; i++) { | 
|  | abyData[16+i*2] = abyTxRate[i]; | 
|  | abyData[16+i*2+1] = abyRsvTime[i]; | 
|  | } | 
|  |  | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_WRITE, | 
|  | MAC_REG_RSPINF_B_1, | 
|  | MESSAGE_REQUEST_MACREG, | 
|  | 34, | 
|  | &abyData[0]); | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Update IFS | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice             - The adapter to be set | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: None. | 
|  | * | 
|  | */ | 
|  | void vUpdateIFS(struct vnt_private *pDevice) | 
|  | { | 
|  | u8 byMaxMin = 0; | 
|  | u8 byData[4]; | 
|  |  | 
|  | if (pDevice->byPacketType==PK_TYPE_11A) {//0000 0000 0000 0000,11a | 
|  | pDevice->uSlot = C_SLOT_SHORT; | 
|  | pDevice->uSIFS = C_SIFS_A; | 
|  | pDevice->uDIFS = C_SIFS_A + 2*C_SLOT_SHORT; | 
|  | pDevice->uCwMin = C_CWMIN_A; | 
|  | byMaxMin = 4; | 
|  | } | 
|  | else if (pDevice->byPacketType==PK_TYPE_11B) {//0000 0001 0000 0000,11b | 
|  | pDevice->uSlot = C_SLOT_LONG; | 
|  | pDevice->uSIFS = C_SIFS_BG; | 
|  | pDevice->uDIFS = C_SIFS_BG + 2*C_SLOT_LONG; | 
|  | pDevice->uCwMin = C_CWMIN_B; | 
|  | byMaxMin = 5; | 
|  | } | 
|  | else {// PK_TYPE_11GA & PK_TYPE_11GB | 
|  | u8 byRate = 0; | 
|  | bool bOFDMRate = false; | 
|  | unsigned int ii = 0; | 
|  | PWLAN_IE_SUPP_RATES pItemRates = NULL; | 
|  |  | 
|  | pDevice->uSIFS = C_SIFS_BG; | 
|  | if (pDevice->bShortSlotTime) { | 
|  | pDevice->uSlot = C_SLOT_SHORT; | 
|  | } else { | 
|  | pDevice->uSlot = C_SLOT_LONG; | 
|  | } | 
|  | pDevice->uDIFS = C_SIFS_BG + 2*pDevice->uSlot; | 
|  |  | 
|  | pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt.abyCurrSuppRates; | 
|  | for (ii = 0; ii < pItemRates->len; ii++) { | 
|  | byRate = (u8)(pItemRates->abyRates[ii]&0x7F); | 
|  | if (RATEwGetRateIdx(byRate) > RATE_11M) { | 
|  | bOFDMRate = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (bOFDMRate == false) { | 
|  | pItemRates = (PWLAN_IE_SUPP_RATES)pDevice->vnt_mgmt | 
|  | .abyCurrExtSuppRates; | 
|  | for (ii = 0; ii < pItemRates->len; ii++) { | 
|  | byRate = (u8)(pItemRates->abyRates[ii]&0x7F); | 
|  | if (RATEwGetRateIdx(byRate) > RATE_11M) { | 
|  | bOFDMRate = true; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | if (bOFDMRate == true) { | 
|  | pDevice->uCwMin = C_CWMIN_A; | 
|  | byMaxMin = 4; | 
|  | } else { | 
|  | pDevice->uCwMin = C_CWMIN_B; | 
|  | byMaxMin = 5; | 
|  | } | 
|  | } | 
|  |  | 
|  | pDevice->uCwMax = C_CWMAX; | 
|  | pDevice->uEIFS = C_EIFS; | 
|  |  | 
|  | byData[0] = (u8)pDevice->uSIFS; | 
|  | byData[1] = (u8)pDevice->uDIFS; | 
|  | byData[2] = (u8)pDevice->uEIFS; | 
|  | byData[3] = (u8)pDevice->uSlot; | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_WRITE, | 
|  | MAC_REG_SIFS, | 
|  | MESSAGE_REQUEST_MACREG, | 
|  | 4, | 
|  | &byData[0]); | 
|  |  | 
|  | byMaxMin |= 0xA0;//1010 1111,C_CWMAX = 1023 | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_WRITE, | 
|  | MAC_REG_CWMAXMIN0, | 
|  | MESSAGE_REQUEST_MACREG, | 
|  | 1, | 
|  | &byMaxMin); | 
|  | } | 
|  |  | 
|  | void CARDvUpdateBasicTopRate(struct vnt_private *pDevice) | 
|  | { | 
|  | u8 byTopOFDM = RATE_24M, byTopCCK = RATE_1M; | 
|  | u8 ii; | 
|  |  | 
|  | //Determines the highest basic rate. | 
|  | for (ii = RATE_54M; ii >= RATE_6M; ii --) { | 
|  | if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) { | 
|  | byTopOFDM = ii; | 
|  | break; | 
|  | } | 
|  | } | 
|  | pDevice->byTopOFDMBasicRate = byTopOFDM; | 
|  |  | 
|  | for (ii = RATE_11M;; ii --) { | 
|  | if ( (pDevice->wBasicRate) & ((u16)(1<<ii)) ) { | 
|  | byTopCCK = ii; | 
|  | break; | 
|  | } | 
|  | if (ii == RATE_1M) | 
|  | break; | 
|  | } | 
|  | pDevice->byTopCCKBasicRate = byTopCCK; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Set NIC Tx Basic Rate | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be set | 
|  | *      wBasicRate      - Basic Rate to be set | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: true if succeeded; false if failed. | 
|  | * | 
|  | */ | 
|  | void CARDbAddBasicRate(struct vnt_private *pDevice, u16 wRateIdx) | 
|  | { | 
|  | u16 wRate = (1 << wRateIdx); | 
|  |  | 
|  | pDevice->wBasicRate |= wRate; | 
|  |  | 
|  | //Determines the highest basic rate. | 
|  | CARDvUpdateBasicTopRate(pDevice); | 
|  | } | 
|  |  | 
|  | int CARDbIsOFDMinBasicRate(struct vnt_private *pDevice) | 
|  | { | 
|  | int ii; | 
|  |  | 
|  | for (ii = RATE_54M; ii >= RATE_6M; ii --) { | 
|  | if ((pDevice->wBasicRate) & ((u16)(1<<ii))) | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | u8 CARDbyGetPktType(struct vnt_private *pDevice) | 
|  | { | 
|  |  | 
|  | if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) { | 
|  | return (u8)pDevice->byBBType; | 
|  | } | 
|  | else if (CARDbIsOFDMinBasicRate(pDevice)) { | 
|  | return PK_TYPE_11GA; | 
|  | } | 
|  | else { | 
|  | return PK_TYPE_11GB; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Calculate TSF offset of two TSF input | 
|  | *              Get TSF Offset from RxBCN's TSF and local TSF | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be sync. | 
|  | *      qwTSF1          - Rx BCN's TSF | 
|  | *      qwTSF2          - Local TSF | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: TSF Offset value | 
|  | * | 
|  | */ | 
|  | u64 CARDqGetTSFOffset(u8 byRxRate, u64 qwTSF1, u64 qwTSF2) | 
|  | { | 
|  | u64 qwTSFOffset = 0; | 
|  | u16 wRxBcnTSFOffst = 0; | 
|  |  | 
|  | wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE]; | 
|  |  | 
|  | qwTSF2 += (u64)wRxBcnTSFOffst; | 
|  |  | 
|  | qwTSFOffset = qwTSF1 - qwTSF2; | 
|  |  | 
|  | return qwTSFOffset; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Sync. TSF counter to BSS | 
|  | *              Get TSF offset and write to HW | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be sync. | 
|  | *      qwBSSTimestamp  - Rx BCN's TSF | 
|  | *      qwLocalTSF      - Local TSF | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: none | 
|  | * | 
|  | */ | 
|  | void CARDvAdjustTSF(struct vnt_private *pDevice, u8 byRxRate, | 
|  | u64 qwBSSTimestamp, u64 qwLocalTSF) | 
|  | { | 
|  | u64 qwTSFOffset = 0; | 
|  | u8 pbyData[8]; | 
|  |  | 
|  | qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF); | 
|  | // adjust TSF | 
|  | // HW's TSF add TSF Offset reg | 
|  |  | 
|  | pbyData[0] = (u8)qwTSFOffset; | 
|  | pbyData[1] = (u8)(qwTSFOffset >> 8); | 
|  | pbyData[2] = (u8)(qwTSFOffset >> 16); | 
|  | pbyData[3] = (u8)(qwTSFOffset >> 24); | 
|  | pbyData[4] = (u8)(qwTSFOffset >> 32); | 
|  | pbyData[5] = (u8)(qwTSFOffset >> 40); | 
|  | pbyData[6] = (u8)(qwTSFOffset >> 48); | 
|  | pbyData[7] = (u8)(qwTSFOffset >> 56); | 
|  |  | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_SET_TSFTBTT, | 
|  | MESSAGE_REQUEST_TSF, | 
|  | 0, | 
|  | 8, | 
|  | pbyData | 
|  | ); | 
|  |  | 
|  | } | 
|  | /* | 
|  | * Description: Read NIC TSF counter | 
|  | *              Get local TSF counter | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be read | 
|  | *  Out: | 
|  | *      qwCurrTSF       - Current TSF counter | 
|  | * | 
|  | * Return Value: true if success; otherwise false | 
|  | * | 
|  | */ | 
|  | bool CARDbGetCurrentTSF(struct vnt_private *pDevice, u64 *pqwCurrTSF) | 
|  | { | 
|  |  | 
|  | *pqwCurrTSF = pDevice->qwCurrTSF; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Clear NIC TSF counter | 
|  | *              Clear local TSF counter | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be read | 
|  | * | 
|  | * Return Value: true if success; otherwise false | 
|  | * | 
|  | */ | 
|  | bool CARDbClearCurrentTSF(struct vnt_private *pDevice) | 
|  | { | 
|  |  | 
|  | MACvRegBitsOn(pDevice, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); | 
|  |  | 
|  | pDevice->qwCurrTSF = 0; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Read NIC TSF counter | 
|  | *              Get NEXTTBTT from adjusted TSF and Beacon Interval | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      qwTSF           - Current TSF counter | 
|  | *      wbeaconInterval - Beacon Interval | 
|  | *  Out: | 
|  | *      qwCurrTSF       - Current TSF counter | 
|  | * | 
|  | * Return Value: TSF value of next Beacon | 
|  | * | 
|  | */ | 
|  | u64 CARDqGetNextTBTT(u64 qwTSF, u16 wBeaconInterval) | 
|  | { | 
|  |  | 
|  | unsigned int    uLowNextTBTT; | 
|  | unsigned int    uHighRemain, uLowRemain; | 
|  | unsigned int    uBeaconInterval; | 
|  |  | 
|  | uBeaconInterval = wBeaconInterval * 1024; | 
|  | // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval | 
|  | uLowNextTBTT = ((qwTSF & 0xffffffffU) >> 10) << 10; | 
|  | uLowRemain = (uLowNextTBTT) % uBeaconInterval; | 
|  | uHighRemain = ((0x80000000 % uBeaconInterval) * 2 * (u32)(qwTSF >> 32)) | 
|  | % uBeaconInterval; | 
|  | uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval; | 
|  | uLowRemain = uBeaconInterval - uLowRemain; | 
|  |  | 
|  | // check if carry when add one beacon interval | 
|  | if ((~uLowNextTBTT) < uLowRemain) | 
|  | qwTSF = ((qwTSF >> 32) + 1) << 32; | 
|  |  | 
|  | qwTSF = (qwTSF & 0xffffffff00000000ULL) | | 
|  | (u64)(uLowNextTBTT + uLowRemain); | 
|  |  | 
|  | return (qwTSF); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Set NIC TSF counter for first Beacon time | 
|  | *              Get NEXTTBTT from adjusted TSF and Beacon Interval | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      dwIoBase        - IO Base | 
|  | *      wBeaconInterval - Beacon Interval | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: none | 
|  | * | 
|  | */ | 
|  | void CARDvSetFirstNextTBTT(struct vnt_private *pDevice, u16 wBeaconInterval) | 
|  | { | 
|  | u64 qwNextTBTT = 0; | 
|  | u8 pbyData[8]; | 
|  |  | 
|  | CARDbClearCurrentTSF(pDevice); | 
|  | //CARDbGetCurrentTSF(pDevice, &qwNextTBTT); //Get Local TSF counter | 
|  | qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); | 
|  | // Set NextTBTT | 
|  |  | 
|  | pbyData[0] = (u8)qwNextTBTT; | 
|  | pbyData[1] = (u8)(qwNextTBTT >> 8); | 
|  | pbyData[2] = (u8)(qwNextTBTT >> 16); | 
|  | pbyData[3] = (u8)(qwNextTBTT >> 24); | 
|  | pbyData[4] = (u8)(qwNextTBTT >> 32); | 
|  | pbyData[5] = (u8)(qwNextTBTT >> 40); | 
|  | pbyData[6] = (u8)(qwNextTBTT >> 48); | 
|  | pbyData[7] = (u8)(qwNextTBTT >> 56); | 
|  |  | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_SET_TSFTBTT, | 
|  | MESSAGE_REQUEST_TBTT, | 
|  | 0, | 
|  | 8, | 
|  | pbyData | 
|  | ); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Sync NIC TSF counter for Beacon time | 
|  | *              Get NEXTTBTT and write to HW | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be set | 
|  | *      qwTSF           - Current TSF counter | 
|  | *      wBeaconInterval - Beacon Interval | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: none | 
|  | * | 
|  | */ | 
|  | void CARDvUpdateNextTBTT(struct vnt_private *pDevice, u64 qwTSF, | 
|  | u16 wBeaconInterval) | 
|  | { | 
|  | u8 pbyData[8]; | 
|  |  | 
|  | qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval); | 
|  |  | 
|  | // Set NextTBTT | 
|  |  | 
|  | pbyData[0] = (u8)qwTSF; | 
|  | pbyData[1] = (u8)(qwTSF >> 8); | 
|  | pbyData[2] = (u8)(qwTSF >> 16); | 
|  | pbyData[3] = (u8)(qwTSF >> 24); | 
|  | pbyData[4] = (u8)(qwTSF >> 32); | 
|  | pbyData[5] = (u8)(qwTSF >> 40); | 
|  | pbyData[6] = (u8)(qwTSF >> 48); | 
|  | pbyData[7] = (u8)(qwTSF >> 56); | 
|  |  | 
|  | CONTROLnsRequestOut(pDevice, | 
|  | MESSAGE_TYPE_SET_TSFTBTT, | 
|  | MESSAGE_REQUEST_TBTT, | 
|  | 0, | 
|  | 8, | 
|  | pbyData | 
|  | ); | 
|  |  | 
|  | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | 
|  | "Card:Update Next TBTT[%8lx]\n", (unsigned long)qwTSF); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Turn off Radio power | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be turned off | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: true if success; otherwise false | 
|  | * | 
|  | */ | 
|  | int CARDbRadioPowerOff(struct vnt_private *pDevice) | 
|  | { | 
|  | int bResult = true; | 
|  |  | 
|  | //if (pDevice->bRadioOff == true) | 
|  | //    return true; | 
|  |  | 
|  | pDevice->bRadioOff = true; | 
|  |  | 
|  | switch (pDevice->byRFType) { | 
|  | case RF_AL2230: | 
|  | case RF_AL2230S: | 
|  | case RF_AIROHA7230: | 
|  | case RF_VT3226:     //RobertYu:20051111 | 
|  | case RF_VT3226D0: | 
|  | case RF_VT3342A0:   //RobertYu:20060609 | 
|  | MACvRegBitsOff(pDevice, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | MACvRegBitsOff(pDevice, MAC_REG_HOSTCR, HOSTCR_RXON); | 
|  |  | 
|  | BBvSetDeepSleep(pDevice); | 
|  |  | 
|  | return bResult; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Description: Turn on Radio power | 
|  | * | 
|  | * Parameters: | 
|  | *  In: | 
|  | *      pDevice         - The adapter to be turned on | 
|  | *  Out: | 
|  | *      none | 
|  | * | 
|  | * Return Value: true if success; otherwise false | 
|  | * | 
|  | */ | 
|  | int CARDbRadioPowerOn(struct vnt_private *pDevice) | 
|  | { | 
|  | int bResult = true; | 
|  |  | 
|  | if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //if (pDevice->bRadioOff == false) | 
|  | //    return true; | 
|  |  | 
|  | pDevice->bRadioOff = false; | 
|  |  | 
|  | BBvExitDeepSleep(pDevice); | 
|  |  | 
|  | MACvRegBitsOn(pDevice, MAC_REG_HOSTCR, HOSTCR_RXON); | 
|  |  | 
|  | switch (pDevice->byRFType) { | 
|  | case RF_AL2230: | 
|  | case RF_AL2230S: | 
|  | case RF_AIROHA7230: | 
|  | case RF_VT3226:     //RobertYu:20051111 | 
|  | case RF_VT3226D0: | 
|  | case RF_VT3342A0:   //RobertYu:20060609 | 
|  | MACvRegBitsOn(pDevice, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | return bResult; | 
|  | } | 
|  |  | 
|  | void CARDvSetBSSMode(struct vnt_private *pDevice) | 
|  | { | 
|  | // Set BB and packet type at the same time.//{{RobertYu:20050222, AL7230 have two TX PA output, only connet to b/g now | 
|  | // so in 11a mode need to set the MAC Reg0x4C to 11b/g mode to turn on PA | 
|  | if( (pDevice->byRFType == RF_AIROHA7230 ) && (pDevice->byBBType == BB_TYPE_11A) ) | 
|  | { | 
|  | MACvSetBBType(pDevice, BB_TYPE_11G); | 
|  | } | 
|  | else | 
|  | { | 
|  | MACvSetBBType(pDevice, pDevice->byBBType); | 
|  | } | 
|  | pDevice->byPacketType = CARDbyGetPktType(pDevice); | 
|  |  | 
|  | if (pDevice->byBBType == BB_TYPE_11A) { | 
|  | ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x03); | 
|  | } else if (pDevice->byBBType == BB_TYPE_11B) { | 
|  | ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x02); | 
|  | } else if (pDevice->byBBType == BB_TYPE_11G) { | 
|  | ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0x88, 0x08); | 
|  | } | 
|  |  | 
|  | vUpdateIFS(pDevice); | 
|  | CARDvSetRSPINF(pDevice, (u8)pDevice->byBBType); | 
|  |  | 
|  | if ( pDevice->byBBType == BB_TYPE_11A ) { | 
|  | //request by Jack 2005-04-26 | 
|  | if (pDevice->byRFType == RF_AIROHA7230) { | 
|  | pDevice->abyBBVGA[0] = 0x20; | 
|  | ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, pDevice->abyBBVGA[0]); | 
|  | } | 
|  | pDevice->abyBBVGA[2] = 0x10; | 
|  | pDevice->abyBBVGA[3] = 0x10; | 
|  | } else { | 
|  | //request by Jack 2005-04-26 | 
|  | if (pDevice->byRFType == RF_AIROHA7230) { | 
|  | pDevice->abyBBVGA[0] = 0x1C; | 
|  | ControlvWriteByte(pDevice, MESSAGE_REQUEST_BBREG, 0xE7, pDevice->abyBBVGA[0]); | 
|  | } | 
|  | pDevice->abyBBVGA[2] = 0x0; | 
|  | pDevice->abyBBVGA[3] = 0x0; | 
|  | } | 
|  | } |