blob: 20c2ce26bc9df3531f25e918eb321a81b3c124fe [file] [log] [blame]
<
/*
*************************************************************************
* 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:
rtmp_init.c
Abstract:
Miniport generic portion header file
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Paul Lin 2002-08-01 created
John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme
Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
*/
#include "../rt_config.h"
#ifdef RT2860
#include "firmware.h"
#include <linux/bitrev.h>
#endif
#ifdef RT2870
/* New firmware handles both RT2870 and RT3070. */
#include "../../rt3070/firmware.h"
#endif
UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
ULONG BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x00000100, 0x00000200, 0x00000400, 0x00000800,
0x00001000, 0x00002000, 0x00004000, 0x00008000,
0x00010000, 0x00020000, 0x00040000, 0x00080000,
0x00100000, 0x00200000, 0x00400000, 0x00800000,
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000};
char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"};
//
// BBP register initialization set
//
REG_PAIR BBPRegTable[] = {
{BBP_R65, 0x2C}, // fix rssi issue
{BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial
{BBP_R69, 0x12},
{BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa
{BBP_R73, 0x10},
{BBP_R81, 0x37},
{BBP_R82, 0x62},
{BBP_R83, 0x6A},
{BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before
{BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28
{BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28
{BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28
{BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528
{BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before.
};
#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR))
//
// RF register initialization set
//
#ifdef RT2870
REG_PAIR RT30xx_RFRegTable[] = {
{RF_R04, 0x40},
{RF_R05, 0x03},
{RF_R06, 0x02},
{RF_R07, 0x70},
{RF_R09, 0x0F},
{RF_R10, 0x41},
{RF_R11, 0x21},
{RF_R12, 0x7B},
{RF_R14, 0x90},
{RF_R15, 0x58},
{RF_R16, 0xB3},
{RF_R17, 0x92},
{RF_R18, 0x2C},
{RF_R19, 0x02},
{RF_R20, 0xBA},
{RF_R21, 0xDB},
{RF_R24, 0x16},
{RF_R25, 0x01},
{RF_R29, 0x1F},
};
#define NUM_RF_REG_PARMS (sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR))
#endif // RT2870 //
//
// ASIC register initialization sets
//
RTMP_REG_PAIR MACRegTable[] = {
#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200)
{BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
{BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100)
{BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
{BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
#else
#error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!!
#endif // HW_BEACON_OFFSET //
{LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap
{HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.
{MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX
{RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control,
{BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2
{TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test
{TX_SW_CFG1, 0x80606}, // Gary,2006-08-23
{TX_LINK_CFG, 0x1020}, // Gary,2006-08-23
{TX_TIMEOUT_CFG, 0x000a2090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01
{MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes.
{LED_CFG, 0x7f031e46}, // Gary, 2006-08-23
{PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20
{TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03
{AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder
{CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
{OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
//PS packets use Tx1Q (for HCCA) when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
#ifdef RT2870
{PBF_CFG, 0xf40006}, // Only enable Queue 2
{MM40_PROT_CFG, 0x3F44084}, // Initial Auto_Responder, because QA will turn off Auto-Responder
{WPDMA_GLO_CFG, 0x00000030},
#endif // RT2870 //
{GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS
{GF40_PROT_CFG, 0x03F44084},
{MM20_PROT_CFG, 0x01744004},
#ifdef RT2860
{MM40_PROT_CFG, 0x03F54084},
#endif
{TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff.
{TX_RTS_CFG, 0x00092b20},
{EXP_ACK_TIME, 0x002400ca}, // default value
{TXOP_HLDR_ET, 0x00000002},
/* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
will always lost. So we change the SIFS of CCK from 10us to 16us. */
{XIFS_TIME_CFG, 0x33a41010},
{PWR_PIN_CFG, 0x00000003}, // patch for 2880-E
};
RTMP_REG_PAIR STAMACRegTable[] = {
{WMM_AIFSN_CFG, 0x00002273},
{WMM_CWMIN_CFG, 0x00002344},
{WMM_CWMAX_CFG, 0x000034aa},
};
#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR))
#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR))
#ifdef RT2870
//
// RT2870 Firmware Spec only used 1 oct for version expression
//
#define FIRMWARE_MINOR_VERSION 7
#endif // RT2870 //
// New 8k byte firmware size for RT3071/RT3072
#define FIRMWAREIMAGE_MAX_LENGTH 0x2000
#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR))
#define FIRMWARE_MAJOR_VERSION 0
#define FIRMWAREIMAGEV1_LENGTH 0x1000
#define FIRMWAREIMAGEV2_LENGTH 0x1000
#ifdef RT2860
#define FIRMWARE_MINOR_VERSION 2
#endif
/*
========================================================================
Routine Description:
Allocate RTMP_ADAPTER data block and do some initialization
Arguments:
Adapter Pointer to our adapter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
NDIS_STATUS RTMPAllocAdapterBlock(
IN PVOID handle,
OUT PRTMP_ADAPTER *ppAdapter)
{
PRTMP_ADAPTER pAd;
NDIS_STATUS Status;
INT index;
UCHAR *pBeaconBuf = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n"));
*ppAdapter = NULL;
do
{
// Allocate RTMP_ADAPTER memory block
pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG);
if (pBeaconBuf == NULL)
{
Status = NDIS_STATUS_FAILURE;
DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n"));
break;
}
Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n"));
break;
}
pAd->BeaconBuf = pBeaconBuf;
printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER));
// Init spin locks
NdisAllocateSpinLock(&pAd->MgmtRingLock);
#ifdef RT2860
NdisAllocateSpinLock(&pAd->RxRingLock);
#endif
for (index =0 ; index < NUM_OF_TX_RING; index++)
{
NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]);
NdisAllocateSpinLock(&pAd->DeQueueLock[index]);
pAd->DeQueueRunning[index] = FALSE;
}
NdisAllocateSpinLock(&pAd->irq_lock);
} while (FALSE);
if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf))
kfree(pBeaconBuf);
*ppAdapter = pAd;
DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status));
return Status;
}
/*
========================================================================
Routine Description:
Read initial Tx power per MCS and BW from EEPROM
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
VOID RTMPReadTxPwrPerRate(
IN PRTMP_ADAPTER pAd)
{
ULONG data, Adata, Gdata;
USHORT i, value, value2;
INT Apwrdelta, Gpwrdelta;
UCHAR t1,t2,t3,t4;
BOOLEAN bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE;
//
// Get power delta for 20MHz and 40MHz.
//
DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n"));
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2);
Apwrdelta = 0;
Gpwrdelta = 0;
if ((value2 & 0xff) != 0xff)
{
if ((value2 & 0x80))
Gpwrdelta = (value2&0xf);
if ((value2 & 0x40))
bGpwrdeltaMinus = FALSE;
else
bGpwrdeltaMinus = TRUE;
}
if ((value2 & 0xff00) != 0xff00)
{
if ((value2 & 0x8000))
Apwrdelta = ((value2&0xf00)>>8);
if ((value2 & 0x4000))
bApwrdeltaMinus = FALSE;
else
bApwrdeltaMinus = TRUE;
}
DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta));
//
// Get Txpower per MCS for 20MHz in 2.4G.
//
for (i=0; i<5; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value);
data = value;
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
if (bGpwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Gpwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Gpwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Gpwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Gpwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Gpwrdelta)
t1 = (value&0xf)-(Gpwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Gpwrdelta)
t2 = ((value&0xf0)>>4)-(Gpwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Gpwrdelta)
t3 = ((value&0xf00)>>8)-(Gpwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Gpwrdelta)
t4 = ((value&0xf000)>>12)-(Gpwrdelta);
else
t4 = 0;
}
Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value);
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
if (bGpwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Gpwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Gpwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Gpwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Gpwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Gpwrdelta)
t1 = (value&0xf)-(Gpwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Gpwrdelta)
t2 = ((value&0xf0)>>4)-(Gpwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Gpwrdelta)
t3 = ((value&0xf00)>>8)-(Gpwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Gpwrdelta)
t4 = ((value&0xf000)>>12)-(Gpwrdelta);
else
t4 = 0;
}
Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
data |= (value<<16);
pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata;
pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata;
if (data != 0xffffffff)
RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data);
DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata));
}
//
// Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G
//
bValid = TRUE;
for (i=0; i<6; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value);
if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
{
bValid = FALSE;
break;
}
}
//
// Get Txpower per MCS for 40MHz in 2.4G.
//
if (bValid)
{
for (i=0; i<4; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value);
if (bGpwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Gpwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Gpwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Gpwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Gpwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Gpwrdelta)
t1 = (value&0xf)-(Gpwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Gpwrdelta)
t2 = ((value&0xf0)>>4)-(Gpwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Gpwrdelta)
t3 = ((value&0xf00)>>8)-(Gpwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Gpwrdelta)
t4 = ((value&0xf000)>>12)-(Gpwrdelta);
else
t4 = 0;
}
Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value);
if (bGpwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Gpwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Gpwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Gpwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Gpwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Gpwrdelta)
t1 = (value&0xf)-(Gpwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Gpwrdelta)
t2 = ((value&0xf0)>>4)-(Gpwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Gpwrdelta)
t3 = ((value&0xf00)>>8)-(Gpwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Gpwrdelta)
t4 = ((value&0xf000)>>12)-(Gpwrdelta);
else
t4 = 0;
}
Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
if (i == 0)
pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000);
else
pAd->Tx40MPwrCfgGBand[i+1] = Gdata;
DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata));
}
}
//
// Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
//
bValid = TRUE;
for (i=0; i<8; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value);
if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
{
bValid = FALSE;
break;
}
}
//
// Get Txpower per MCS for 20MHz in 5G.
//
if (bValid)
{
for (i=0; i<5; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value);
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value);
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
if (i == 0)
pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000);
else
pAd->Tx20MPwrCfgABand[i] = Adata;
DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata));
}
}
//
// Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
//
bValid = TRUE;
for (i=0; i<6; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value);
if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
{
bValid = FALSE;
break;
}
}
//
// Get Txpower per MCS for 40MHz in 5G.
//
if (bValid)
{
for (i=0; i<4; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value);
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value);
if (bApwrdeltaMinus == FALSE)
{
t1 = (value&0xf)+(Apwrdelta);
if (t1 > 0xf)
t1 = 0xf;
t2 = ((value&0xf0)>>4)+(Apwrdelta);
if (t2 > 0xf)
t2 = 0xf;
t3 = ((value&0xf00)>>8)+(Apwrdelta);
if (t3 > 0xf)
t3 = 0xf;
t4 = ((value&0xf000)>>12)+(Apwrdelta);
if (t4 > 0xf)
t4 = 0xf;
}
else
{
if ((value&0xf) > Apwrdelta)
t1 = (value&0xf)-(Apwrdelta);
else
t1 = 0;
if (((value&0xf0)>>4) > Apwrdelta)
t2 = ((value&0xf0)>>4)-(Apwrdelta);
else
t2 = 0;
if (((value&0xf00)>>8) > Apwrdelta)
t3 = ((value&0xf00)>>8)-(Apwrdelta);
else
t3 = 0;
if (((value&0xf000)>>12) > Apwrdelta)
t4 = ((value&0xf000)>>12)-(Apwrdelta);
else
t4 = 0;
}
Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
if (i == 0)
pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000);
else
pAd->Tx40MPwrCfgABand[i+1] = Adata;
DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata));
}
}
}
/*
========================================================================
Routine Description:
Read initial channel power parameters from EEPROM
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
VOID RTMPReadChannelPwr(
IN PRTMP_ADAPTER pAd)
{
UCHAR i, choffset;
EEPROM_TX_PWR_STRUC Power;
EEPROM_TX_PWR_STRUC Power2;
// Read Tx power value for all channels
// Value from 1 - 0x7f. Default value is 24.
// Power value : 2.4G 0x00 (0) ~ 0x1F (31)
// : 5.5G 0xF9 (-7) ~ 0x0F (15)
// 0. 11b/g, ch1 - ch 14
for (i = 0; i < 7; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word);
RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word);
pAd->TxPower[i * 2].Channel = i * 2 + 1;
pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2;
if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0))
pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER;
else
pAd->TxPower[i * 2].Power = Power.field.Byte0;
if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0))
pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER;
else
pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1;
if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0))
pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER;
else
pAd->TxPower[i * 2].Power2 = Power2.field.Byte0;
if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0))
pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER;
else
pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1;
}
// 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)
// 1.1 Fill up channel
choffset = 14;
for (i = 0; i < 4; i++)
{
pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0;
pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2;
pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4;
pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
}
// 1.2 Fill up power
for (i = 0; i < 6; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word);
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word);
if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
}
// 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)
// 2.1 Fill up channel
choffset = 14 + 12;
for (i = 0; i < 5; i++)
{
pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0;
pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2;
pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4;
pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
}
pAd->TxPower[3 * 5 + choffset + 0].Channel = 140;
pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
// 2.2 Fill up power
for (i = 0; i < 8; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
}
// 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz)
// 3.1 Fill up channel
choffset = 14 + 12 + 16;
for (i = 0; i < 2; i++)
{
pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0;
pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2;
pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4;
pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
}
pAd->TxPower[3 * 2 + choffset + 0].Channel = 165;
pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
// 3.2 Fill up power
for (i = 0; i < 4; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
}
// 4. Print and Debug
choffset = 14 + 12 + 16 + 7;
}
/*
========================================================================
Routine Description:
Read the following from the registry
1. All the parameters
2. NetworkAddres
Arguments:
Adapter Pointer to our adapter
WrapperConfigurationContext For use by NdisOpenConfiguration
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_RESOURCES
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
NDIS_STATUS NICReadRegParameters(
IN PRTMP_ADAPTER pAd,
IN NDIS_HANDLE WrapperConfigurationContext
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status));
return Status;
}
#ifdef RT2870
/*
========================================================================
Routine Description:
For RF filter calibration purpose
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
========================================================================
*/
VOID RTMPFilterCalibration(
IN PRTMP_ADAPTER pAd)
{
UCHAR R55x = 0, value, FilterTarget = 0x1E, BBPValue=0;
UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0;
UCHAR RF_R24_Value = 0;
// Give bbp filter initial value
#ifndef RT2870
pAd->Mlme.CaliBW20RfR24 = 0x16;
pAd->Mlme.CaliBW40RfR24 = 0x36; //Bit[5] must be 1 for BW 40
#else
pAd->Mlme.CaliBW20RfR24 = 0x1F;
pAd->Mlme.CaliBW40RfR24 = 0x2F; //Bit[5] must be 1 for BW 40
#endif
do
{
if (loop == 1) //BandWidth = 40 MHz
{
// Write 0x27 to RF_R24 to program filter
RF_R24_Value = 0x27;
RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
if (IS_RT3090(pAd))
FilterTarget = 0x15;
else
FilterTarget = 0x19;
// when calibrate BW40, BBP mask must set to BW40.
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
BBPValue&= (~0x18);
BBPValue|= (0x10);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
#ifdef RT2870
// set to BW40
RT30xxReadRFRegister(pAd, RF_R31, &value);
value |= 0x20;
RT30xxWriteRFRegister(pAd, RF_R31, value);
#endif
}
else //BandWidth = 20 MHz
{
// Write 0x07 to RF_R24 to program filter
RF_R24_Value = 0x07;
RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
if (IS_RT3090(pAd))
FilterTarget = 0x13;
else
FilterTarget = 0x16;
#ifdef RT2870
// set to BW20
RT30xxReadRFRegister(pAd, RF_R31, &value);
value &= (~0x20);
RT30xxWriteRFRegister(pAd, RF_R31, value);
#endif
}
// Write 0x01 to RF_R22 to enable baseband loopback mode
RT30xxReadRFRegister(pAd, RF_R22, &value);
value |= 0x01;
RT30xxWriteRFRegister(pAd, RF_R22, value);
// Write 0x00 to BBP_R24 to set power & frequency of passband test tone
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0);
do
{
// Write 0x90 to BBP_R25 to transmit test tone
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90);
RTMPusecDelay(1000);
// Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0]
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value);
R55x = value & 0xFF;
} while ((ReTry++ < 100) && (R55x == 0));
// Write 0x06 to BBP_R24 to set power & frequency of stopband test tone
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06);
while(TRUE)
{
// Write 0x90 to BBP_R25 to transmit test tone
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90);
//We need to wait for calibration
RTMPusecDelay(1000);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value);
value &= 0xFF;
if ((R55x - value) < FilterTarget)
{
RF_R24_Value ++;
}
else if ((R55x - value) == FilterTarget)
{
RF_R24_Value ++;
count ++;
}
else
{
break;
}
// prevent infinite loop cause driver hang.
if (loopcnt++ > 100)
{
DBGPRINT(RT_DEBUG_ERROR, ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt));
break;
}
// Write RF_R24 to program filter
RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
}
if (count > 0)
{
RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0));
}
// Store for future usage
if (loopcnt < 100)
{
if (loop++ == 0)
{
//BandWidth = 20 MHz
pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value;
}
else
{
//BandWidth = 40 MHz
pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value;
break;
}
}
else
break;
RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value);
// reset count
count = 0;
} while(TRUE);
//
// Set back to initial state
//
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0);
RT30xxReadRFRegister(pAd, RF_R22, &value);
value &= ~(0x01);
RT30xxWriteRFRegister(pAd, RF_R22, value);
// set BBP back to BW20
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
BBPValue&= (~0x18);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
DBGPRINT(RT_DEBUG_TRACE, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24));
}
VOID NICInitRT30xxRFRegisters(IN PRTMP_ADAPTER pAd)
{
INT i;
// Driver must read EEPROM to get RfIcType before initial RF registers
// Initialize RF register to default value
if (IS_RT3070(pAd) || IS_RT3071(pAd))
{
// Init RF calibration
// Driver should toggle RF R30 bit7 before init RF registers
UINT32 RfReg = 0;
UINT32 data;
RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg);
RfReg |= 0x80;
RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg);
RTMPusecDelay(1000);
RfReg &= 0x7F;
RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg);
// Initialize RF register to default value
for (i = 0; i < NUM_RF_REG_PARMS; i++)
{
RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value);
}
if (IS_RT3070(pAd))
{
// Update MAC 0x05D4 from 01xxxxxx to 0Dxxxxxx (voltage 1.2V to 1.35V) for RT3070 to improve yield rate
RTUSBReadMACRegister(pAd, LDO_CFG0, &data);
data = ((data & 0xF0FFFFFF) | 0x0D000000);
RTUSBWriteMACRegister(pAd, LDO_CFG0, data);
}
else if (IS_RT3071(pAd))
{
// Driver should set RF R6 bit6 on before init RF registers
RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg);
RfReg |= 0x40;
RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg);
// init R31
RT30xxWriteRFRegister(pAd, RF_R31, 0x14);
// RT3071 version E has fixed this issue
if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
{
// patch tx EVM issue temporarily
RTUSBReadMACRegister(pAd, LDO_CFG0, &data);
data = ((data & 0xE0FFFFFF) | 0x0D000000);
RTUSBWriteMACRegister(pAd, LDO_CFG0, data);
}
else
{
RTMP_IO_READ32(pAd, LDO_CFG0, &data);
data = ((data & 0xE0FFFFFF) | 0x01000000);
RTMP_IO_WRITE32(pAd, LDO_CFG0, data);
}
// patch LNA_PE_G1 failed issue
RTUSBReadMACRegister(pAd, GPIO_SWITCH, &data);
data &= ~(0x20);
RTUSBWriteMACRegister(pAd, GPIO_SWITCH, data);
}
//For RF filter Calibration
RTMPFilterCalibration(pAd);
// Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration()
if ((pAd->MACVersion & 0xffff) < 0x0211)
RT30xxWriteRFRegister(pAd, RF_R27, 0x3);
// set led open drain enable
RTUSBReadMACRegister(pAd, OPT_14, &data);
data |= 0x01;
RTUSBWriteMACRegister(pAd, OPT_14, data);
if (IS_RT3071(pAd))
{
// add by johnli, RF power sequence setup, load RF normal operation-mode setup
RT30xxLoadRFNormalModeSetup(pAd);
}
}
}
#endif // RT2870 //
/*
========================================================================
Routine Description:
Read initial parameters from EEPROM
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
VOID NICReadEEPROMParameters(
IN PRTMP_ADAPTER pAd,
IN PUCHAR mac_addr)
{
UINT32 data = 0;
USHORT i, value, value2;
UCHAR TmpPhy;
EEPROM_TX_PWR_STRUC Power;
EEPROM_VERSION_STRUC Version;
EEPROM_ANTENNA_STRUC Antenna;
EEPROM_NIC_CONFIG2_STRUC NicConfig2;
DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n"));
// Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8
RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data));
if((data & 0x30) == 0)
pAd->EEPROMAddressNum = 6; // 93C46
else if((data & 0x30) == 0x10)
pAd->EEPROMAddressNum = 8; // 93C66
else
pAd->EEPROMAddressNum = 8; // 93C86
DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum ));
// RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize
// MAC address registers according to E2PROM setting
if (mac_addr == NULL ||
strlen(mac_addr) != 17 ||
mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' ||
mac_addr[11] != ':' || mac_addr[14] != ':')
{
USHORT Addr01,Addr23,Addr45 ;
RT28xx_EEPROM_READ16(pAd, 0x04, Addr01);
RT28xx_EEPROM_READ16(pAd, 0x06, Addr23);
RT28xx_EEPROM_READ16(pAd, 0x08, Addr45);
pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n"));
}
else
{
INT j;
PUCHAR macptr;
macptr = mac_addr;
for (j=0; j<MAC_ADDR_LEN; j++)
{
AtoH(macptr, &pAd->PermanentAddress[j], 1);
macptr=macptr+3;
}
DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n"));
}
{
//more conveninet to test mbssid, so ap's bssid &0xf1
if (pAd->PermanentAddress[0] == 0xff)
pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8;
//if (pAd->PermanentAddress[5] == 0xff)
// pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8;
DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
pAd->PermanentAddress[0], pAd->PermanentAddress[1],
pAd->PermanentAddress[2], pAd->PermanentAddress[3],
pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
if (pAd->bLocalAdminMAC == FALSE)
{
MAC_DW0_STRUC csr2;
MAC_DW1_STRUC csr3;
COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress);
csr2.field.Byte0 = pAd->CurrentAddress[0];
csr2.field.Byte1 = pAd->CurrentAddress[1];
csr2.field.Byte2 = pAd->CurrentAddress[2];
csr2.field.Byte3 = pAd->CurrentAddress[3];
RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word);
csr3.word = 0;
csr3.field.Byte4 = pAd->CurrentAddress[4];
csr3.field.Byte5 = pAd->CurrentAddress[5];
csr3.field.U2MeMask = 0xff;
RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word);
DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
pAd->PermanentAddress[0], pAd->PermanentAddress[1],
pAd->PermanentAddress[2], pAd->PermanentAddress[3],
pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
}
}
// if not return early. cause fail at emulation.
// Init the channel number for TX channel power
RTMPReadChannelPwr(pAd);
// if E2PROM version mismatch with driver's expectation, then skip
// all subsequent E2RPOM retieval and set a system error bit to notify GUI
RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word);
pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256;
DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber));
if (Version.field.Version > VALID_EEPROM_VERSION)
{
DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION));
/*pAd->SystemErrorBitmap |= 0x00000001;
// hard-code default value when no proper E2PROM installed
pAd->bAutoTxAgcA = FALSE;
pAd->bAutoTxAgcG = FALSE;
// Default the channel power
for (i = 0; i < MAX_NUM_OF_CHANNELS; i++)
pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER;
// Default the channel power
for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++)
pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER;
for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++)
pAd->EEPROMDefaultValue[i] = 0xffff;
return; */
}
// Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd
RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value);
pAd->EEPROMDefaultValue[0] = value;
RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
pAd->EEPROMDefaultValue[1] = value;
RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region
pAd->EEPROMDefaultValue[2] = value;
for(i = 0; i < 8; i++)
{
RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value);
pAd->EEPROMDefaultValue[i+3] = value;
}
// We have to parse NIC configuration 0 at here.
// If TSSI did not have preloaded value, it should reset the TxAutoAgc to false
// Therefore, we have to read TxAutoAgc control beforehand.
// Read Tx AGC control bit
Antenna.word = pAd->EEPROMDefaultValue[0];
if (Antenna.word == 0xFFFF)
{
if(IS_RT3090(pAd))
{
Antenna.word = 0;
Antenna.field.RfIcType = RFIC_3020;
Antenna.field.TxPath = 1;
Antenna.field.RxPath = 1;
}
else
{
Antenna.word = 0;
Antenna.field.RfIcType = RFIC_2820;
Antenna.field.TxPath = 1;
Antenna.field.RxPath = 2;
DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word));
}
}
// Choose the desired Tx&Rx stream.
if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath))
pAd->CommonCfg.TxStream = Antenna.field.TxPath;
if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath))
{
pAd->CommonCfg.RxStream = Antenna.field.RxPath;
if ((pAd->MACVersion < RALINK_2883_VERSION) &&
(pAd->CommonCfg.RxStream > 2))
{
// only 2 Rx streams for RT2860 series
pAd->CommonCfg.RxStream = 2;
}
}
// 3*3
// read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2
// yet implement
for(i=0; i<3; i++)
{
}
NicConfig2.word = pAd->EEPROMDefaultValue[1];
{
if ((NicConfig2.word & 0x00ff) == 0xff)
{
NicConfig2.word &= 0xff00;
}
if ((NicConfig2.word >> 8) == 0xff)
{
NicConfig2.word &= 0x00ff;
}
}
if (NicConfig2.field.DynamicTxAgcControl == 1)
pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
else
pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath));
// Save the antenna for future use
pAd->Antenna.word = Antenna.word;
//
// Reset PhyMode if we don't support 802.11a
// Only RFIC_2850 & RFIC_2750 support 802.11a
//
if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750))
{
if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) ||
(pAd->CommonCfg.PhyMode == PHY_11A))
pAd->CommonCfg.PhyMode = PHY_11BG_MIXED;
else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) ||
(pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) ||
(pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) ||
(pAd->CommonCfg.PhyMode == PHY_11N_5G))
pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED;
}
// Read TSSI reference and TSSI boundary for temperature compensation. This is ugly
// 0. 11b/g
{
/* these are tempature reference value (0x00 ~ 0xFE)
ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) +
TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */
RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word);
pAd->TssiMinusBoundaryG[4] = Power.field.Byte0;
pAd->TssiMinusBoundaryG[3] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0x70, Power.word);
pAd->TssiMinusBoundaryG[2] = Power.field.Byte0;
pAd->TssiMinusBoundaryG[1] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0x72, Power.word);
pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */
pAd->TssiPlusBoundaryG[1] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0x74, Power.word);
pAd->TssiPlusBoundaryG[2] = Power.field.Byte0;
pAd->TssiPlusBoundaryG[3] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0x76, Power.word);
pAd->TssiPlusBoundaryG[4] = Power.field.Byte0;
pAd->TxAgcStepG = Power.field.Byte1;
pAd->TxAgcCompensateG = 0;
pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG;
pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG;
// Disable TxAgc if the based value is not right
if (pAd->TssiRefG == 0xff)
pAd->bAutoTxAgcG = FALSE;
DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1],
pAd->TssiRefG,
pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4],
pAd->TxAgcStepG, pAd->bAutoTxAgcG));
}
// 1. 11a
{
RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word);
pAd->TssiMinusBoundaryA[4] = Power.field.Byte0;
pAd->TssiMinusBoundaryA[3] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word);
pAd->TssiMinusBoundaryA[2] = Power.field.Byte0;
pAd->TssiMinusBoundaryA[1] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word);
pAd->TssiRefA = Power.field.Byte0;
pAd->TssiPlusBoundaryA[1] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word);
pAd->TssiPlusBoundaryA[2] = Power.field.Byte0;
pAd->TssiPlusBoundaryA[3] = Power.field.Byte1;
RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word);
pAd->TssiPlusBoundaryA[4] = Power.field.Byte0;
pAd->TxAgcStepA = Power.field.Byte1;
pAd->TxAgcCompensateA = 0;
pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA;
pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA;
// Disable TxAgc if the based value is not right
if (pAd->TssiRefA == 0xff)
pAd->bAutoTxAgcA = FALSE;
DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1],
pAd->TssiRefA,
pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4],
pAd->TxAgcStepA, pAd->bAutoTxAgcA));
}
pAd->BbpRssiToDbmDelta = 0x0;
// Read frequency offset setting for RF
RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value);
if ((value & 0x00FF) != 0x00FF)
pAd->RfFreqOffset = (ULONG) (value & 0x00FF);
else
pAd->RfFreqOffset = 0;
DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset));
//CountryRegion byte offset (38h)
value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band
value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band
if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND))
{
pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80;
pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80;
TmpPhy = pAd->CommonCfg.PhyMode;
pAd->CommonCfg.PhyMode = 0xff;
RTMPSetPhyMode(pAd, TmpPhy);
SetCommonHT(pAd);
}
//
// Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.
// The valid value are (-10 ~ 10)
//
RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value);
pAd->BGRssiOffset0 = value & 0x00ff;
pAd->BGRssiOffset1 = (value >> 8);
RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value);
pAd->BGRssiOffset2 = value & 0x00ff;
pAd->ALNAGain1 = (value >> 8);
RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value);
pAd->BLNAGain = value & 0x00ff;
pAd->ALNAGain0 = (value >> 8);
// Validate 11b/g RSSI_0 offset.
if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10))
pAd->BGRssiOffset0 = 0;
// Validate 11b/g RSSI_1 offset.
if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10))
pAd->BGRssiOffset1 = 0;
// Validate 11b/g RSSI_2 offset.
if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10))
pAd->BGRssiOffset2 = 0;
RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value);
pAd->ARssiOffset0 = value & 0x00ff;
pAd->ARssiOffset1 = (value >> 8);
RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value);
pAd->ARssiOffset2 = value & 0x00ff;
pAd->ALNAGain2 = (value >> 8);
if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00))
pAd->ALNAGain1 = pAd->ALNAGain0;
if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00))
pAd->ALNAGain2 = pAd->ALNAGain0;
// Validate 11a RSSI_0 offset.
if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10))
pAd->ARssiOffset0 = 0;
// Validate 11a RSSI_1 offset.
if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10))
pAd->ARssiOffset1 = 0;
//Validate 11a RSSI_2 offset.
if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10))
pAd->ARssiOffset2 = 0;
//
// Get LED Setting.
//
RT28xx_EEPROM_READ16(pAd, 0x3a, value);
pAd->LedCntl.word = (value&0xff00) >> 8;
RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value);
pAd->Led1 = value;
RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value);
pAd->Led2 = value;
RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value);
pAd->Led3 = value;
RTMPReadTxPwrPerRate(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n"));
}
/*
========================================================================
Routine Description:
Set default value from EEPROM
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
VOID NICInitAsicFromEEPROM(
IN PRTMP_ADAPTER pAd)
{
UINT32 data = 0;
UCHAR BBPR1 = 0;
USHORT i;
EEPROM_ANTENNA_STRUC Antenna;
EEPROM_NIC_CONFIG2_STRUC NicConfig2;
UCHAR BBPR3 = 0;
DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n"));
for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++)
{
UCHAR BbpRegIdx, BbpValue;
if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0))
{
BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8);
BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue);
}
}
#ifndef RT2870
Antenna.word = pAd->Antenna.word;
#else
Antenna.word = pAd->EEPROMDefaultValue[0];
if (Antenna.word == 0xFFFF)
{
DBGPRINT(RT_DEBUG_ERROR, ("E2PROM error, hard code as 0x%04x\n", Antenna.word));
BUG_ON(Antenna.word == 0xFFFF);
}
#endif
pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath;
pAd->RfIcType = (UCHAR) Antenna.field.RfIcType;
#ifdef RT2870
DBGPRINT(RT_DEBUG_WARN, ("pAd->RfIcType = %d, RealRxPath=%d, TxPath = %d\n", pAd->RfIcType, pAd->Mlme.RealRxPath,Antenna.field.TxPath));
// Save the antenna for future use
pAd->Antenna.word = Antenna.word;
#endif
NicConfig2.word = pAd->EEPROMDefaultValue[1];
#ifdef RT2870
{
if ((NicConfig2.word & 0x00ff) == 0xff)
{
NicConfig2.word &= 0xff00;
}
if ((NicConfig2.word >> 8) == 0xff)
{
NicConfig2.word &= 0x00ff;
}
}
#endif
// Save the antenna for future use
pAd->NicConfig2.word = NicConfig2.word;
#ifdef RT2870
// set default antenna as main
if (pAd->RfIcType == RFIC_3020)
AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
#endif
//
// Send LED Setting to MCU.
//
if (pAd->LedCntl.word == 0xFF)
{
pAd->LedCntl.word = 0x01;
pAd->Led1 = 0x5555;
pAd->Led2 = 0x2221;
#ifdef RT2860
pAd->Led3 = 0xA9F8;
#endif
#ifdef RT2870
pAd->Led3 = 0x5627;
#endif // RT2870 //
}
AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8));
AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8));
AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8));
pAd->LedIndicatorStregth = 0xFF;
RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up
{
// Read Hardware controlled Radio state enable bit
if (NicConfig2.field.HardwareRadioControl == 1)
{
pAd->StaCfg.bHardwareRadio = TRUE;
// Read GPIO pin2 as Hardware controlled radio state
RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
if ((data & 0x04) == 0)
{
pAd->StaCfg.bHwRadio = FALSE;
pAd->StaCfg.bRadio = FALSE;
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
}
}
else
pAd->StaCfg.bHardwareRadio = FALSE;
if (pAd->StaCfg.bRadio == FALSE)
{
RTMPSetLED(pAd, LED_RADIO_OFF);
}
else
{
RTMPSetLED(pAd, LED_RADIO_ON);
#ifdef RT2860
AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00);
// 2-1. wait command ok.
AsicCheckCommanOk(pAd, PowerWakeCID);
#endif
}
}
// Turn off patching for cardbus controller
if (NicConfig2.field.CardbusAcceleration == 1)
{
}
if (NicConfig2.field.DynamicTxAgcControl == 1)
pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
else
pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
/* BBP has been programmed so reset to UNKNOWN_BAND */
pAd->CommonCfg.BandState = UNKNOWN_BAND;
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
BBPR3 &= (~0x18);
if(pAd->Antenna.field.RxPath == 3)
{
BBPR3 |= (0x10);
}
else if(pAd->Antenna.field.RxPath == 2)
{
BBPR3 |= (0x8);
}
else if(pAd->Antenna.field.RxPath == 1)
{
BBPR3 |= (0x0);
}
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
{
// Handle the difference when 1T
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1);
if(pAd->Antenna.field.TxPath == 1)
{
BBPR1 &= (~0x18);
}
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1);
DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio));
}
DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word));
DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n"));
}
/*
========================================================================
Routine Description:
Initialize NIC hardware
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
NDIS_STATUS NICInitializeAdapter(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN bHardReset)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
WPDMA_GLO_CFG_STRUC GloCfg;
#ifdef RT2860
UINT32 Value;
DELAY_INT_CFG_STRUC IntCfg;
#endif
ULONG i =0, j=0;
AC_TXOP_CSR0_STRUC csr0;
DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n"));
// 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
retry:
i = 0;
do
{
RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
break;
RTMPusecDelay(1000);
i++;
}while ( i<100);
DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word));
GloCfg.word &= 0xff0;
GloCfg.field.EnTXWriteBackDDONE =1;
RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
// Record HW Beacon offset
pAd->BeaconOffset[0] = HW_BEACON_BASE0;
pAd->BeaconOffset[1] = HW_BEACON_BASE1;
pAd->BeaconOffset[2] = HW_BEACON_BASE2;
pAd->BeaconOffset[3] = HW_BEACON_BASE3;
pAd->BeaconOffset[4] = HW_BEACON_BASE4;
pAd->BeaconOffset[5] = HW_BEACON_BASE5;
pAd->BeaconOffset[6] = HW_BEACON_BASE6;
pAd->BeaconOffset[7] = HW_BEACON_BASE7;
//
// write all shared Ring's base address into ASIC
//
// asic simulation sequence put this ahead before loading firmware.
// pbf hardware reset
#ifdef RT2860
RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings.
RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f);
RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00);
#endif
// Initialze ASIC for TX & Rx operation
if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS)
{
if (j++ == 0)
{
NICLoadFirmware(pAd);
goto retry;
}
return NDIS_STATUS_FAILURE;
}
#ifdef RT2860
// Write AC_BK base address register
Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value));
// Write AC_BE base address register
Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value));
// Write AC_VI base address register
Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value));
// Write AC_VO base address register
Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value));
// Write HCCA base address register
Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value));
// Write MGMT_BASE_CSR register
Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value));
// Write RX_BASE_CSR register
Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa);
RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value);
DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value));
// Init RX Ring index pointer
pAd->RxRing.RxSwReadIdx = 0;
pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1;
RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
// Init TX rings index pointer
{
for (i=0; i<NUM_OF_TX_RING; i++)
{
pAd->TxRing[i].TxSwFreeIdx = 0;
pAd->TxRing[i].TxCpuIdx = 0;
RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx);
}
}
// init MGMT ring index pointer
pAd->MgmtRing.TxSwFreeIdx = 0;
pAd->MgmtRing.TxCpuIdx = 0;
RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
//
// set each Ring's SIZE into ASIC. Descriptor Size is fixed by design.
//
// Write TX_RING_CSR0 register
Value = TX_RING_SIZE;
RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value);
RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value);
RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value);
RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value);
RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value);
Value = MGMT_RING_SIZE;
RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value);
// Write RX_RING_CSR register
Value = RX_RING_SIZE;
RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value);
#endif /* RT2860 */
// WMM parameter
csr0.word = 0;
RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
if (pAd->CommonCfg.PhyMode == PHY_11B)
{
csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms
csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms
}
else
{
csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms
csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms
}
RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word);
#ifdef RT2860
// 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
i = 0;
do
{
RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
break;
RTMPusecDelay(1000);
i++;
}while ( i < 100);
GloCfg.word &= 0xff0;
GloCfg.field.EnTXWriteBackDDONE =1;
RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
IntCfg.word = 0;
RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word);
#endif
// reset action
// Load firmware
// Status = NICLoadFirmware(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n"));
return Status;
}
/*
========================================================================
Routine Description:
Initialize ASIC
Arguments:
Adapter Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
Note:
========================================================================
*/
NDIS_STATUS NICInitializeAsic(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN bHardReset)
{
ULONG Index = 0;
UCHAR R0 = 0xff;
UINT32 MacCsr12 = 0, Counter = 0;
#ifdef RT2870
UINT32 MacCsr0 = 0;
NTSTATUS Status;
UCHAR Value = 0xff;
UINT32 eFuseCtrl;
#endif
USHORT KeyIdx;
INT i,apidx;
DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n"));
#ifdef RT2860
if (bHardReset == TRUE)
{
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
}
else
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
#endif
#ifdef RT2870
//
// Make sure MAC gets ready after NICLoadFirmware().
//
Index = 0;
//To avoid hang-on issue when interface up in kernel 2.4,
//we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly.
do
{
RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF))
break;
RTMPusecDelay(10);
} while (Index++ < 100);
pAd->MACVersion = MacCsr0;
DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion));
// turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue.
RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacCsr12);
MacCsr12 &= (~0x2000);
RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MacCsr12);
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0);
Status = RTUSBVenderReset(pAd);
#endif
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
// Initialize MAC register to default value
#ifdef RT2860
for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++)
{
RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value);
}
#endif
#ifdef RT2870
for(Index=0; Index<NUM_MAC_REG_PARMS; Index++)
{
#ifdef RT3070
if ((MACRegTable[Index].Register == TX_SW_CFG0) && (IS_RT3070(pAd) || IS_RT3071(pAd)))
{
MACRegTable[Index].Value = 0x00000400;
}
#endif // RT3070 //
RTMP_IO_WRITE32(pAd, (USHORT)MACRegTable[Index].Register, MACRegTable[Index].Value);
}
#endif // RT2870 //
{
for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++)
{
#ifdef RT2860
RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
#endif
#ifdef RT2870
RTMP_IO_WRITE32(pAd, (USHORT)STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
#endif
}
}
// Initialize RT3070 serial MAc registers which is different from RT2870 serial
if (IS_RT3090(pAd))
{
RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0);
// RT3071 version E has fixed this issue
if ((pAd->MACVersion & 0xffff) < 0x0211)
{
if (pAd->NicConfig2.field.DACTestBit == 1)
{
RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically
}
else
{
RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); // To fix throughput drop drastically
}
}
else
{
RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0);
}
}
#ifdef RT2870
else if (IS_RT3070(pAd))
{
RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0);
RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically
}
#endif // RT30xx //
//
// Before program BBP, we need to wait BBP/RF get wake up.
//
Index = 0;
do
{
RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12);
if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable
break;
DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12));
RTMPusecDelay(1000);
} while (Index++ < 100);
// The commands to firmware should be after these commands, these commands will init firmware
// PCI and USB are not the same because PCI driver needs to wait for PCI bus ready
RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent
RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0);
RTMPusecDelay(1000);
// Read BBP register, make sure BBP is up and running before write new data
Index = 0;
do
{
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0);
DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0));
} while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00)));
//ASSERT(Index < 20); //this will cause BSOD on Check-build driver
if ((R0 == 0xff) || (R0 == 0x00))
return NDIS_STATUS_FAILURE;
// Initialize BBP register to default value
for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value);
}
#ifndef RT2870
// for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT.
if ((pAd->MACVersion&0xffff) != 0x0101)
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19);
#else
// for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT.
// RT3090 should not program BBP R84 to 0x19, otherwise TX will block.
if (((pAd->MACVersion&0xffff) != 0x0101) && (!IS_RT30xx(pAd)))
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19);
// add by johnli, RF power sequence setup
if (IS_RT30xx(pAd))
{ //update for RT3070/71/72/90/91/92.
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33);
}
if (IS_RT3090(pAd))
{
UCHAR bbpreg=0;
// enable DC filter
if ((pAd->MACVersion & 0xffff) >= 0x0211)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0);
}
// improve power consumption
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg);
if (pAd->Antenna.field.TxPath == 1)
{
// turn off tx DAC_1
bbpreg = (bbpreg | 0x20);
}
if (pAd->Antenna.field.RxPath == 1)
{
// turn off tx ADC_1
bbpreg &= (~0x2);
}
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg);
// improve power consumption in RT3071 Ver.E
if ((pAd->MACVersion & 0xffff) >= 0x0211)
{
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg);
bbpreg &= (~0x3);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg);
}
}
#endif
if (pAd->MACVersion == 0x28600100)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12);
}
if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3
{
// enlarge MAX_LEN_CFG
UINT32 csr;
RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr);
csr &= 0xFFF;
csr |= 0x2000;
RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr);
}
#ifdef RT2870
{
UCHAR MAC_Value[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0,0};
//Initialize WCID table
Value = 0xff;
for(Index =0 ;Index < 254;Index++)
{
RTUSBMultiWrite(pAd, (USHORT)(MAC_WCID_BASE + Index * 8), MAC_Value, 8);
}
}
#endif // RT2870 //
// Add radio off control
{
if (pAd->StaCfg.bRadio == FALSE)
{
// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818);
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n"));
}
}
// Clear raw counters
RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
// ASIC will keep garbage value after boot
// Clear all seared key table when initial
// This routine can be ignored in radio-ON/OFF operation.
if (bHardReset)
{
for (KeyIdx = 0; KeyIdx < 4; KeyIdx++)
{
RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0);
}
// Clear all pairwise key table when initial
for (KeyIdx = 0; KeyIdx < 256; KeyIdx++)
{
RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1);
}
}
// It isn't necessary to clear this space when not hard reset.
if (bHardReset == TRUE)
{
// clear all on-chip BEACON frame space
for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++)
{
for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4)
RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00);
}
}
#ifdef RT2870
AsicDisableSync(pAd);
// Clear raw counters
RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
// Default PCI clock cycle per ms is different as default setting, which is based on PCI.
RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter);
Counter&=0xffffff00;
Counter|=0x000001e;
RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter);
pAd->bUseEfuse=FALSE;
RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl);
pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0;
if(pAd->bUseEfuse)
{
DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse\n"));
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n"));
}
#endif
{
// for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT.
if ((pAd->MACVersion&0xffff) != 0x0101)
RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f);
}
DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n"));
return NDIS_STATUS_SUCCESS;
}
#ifdef RT2860
VOID NICRestoreBBPValue(
IN PRTMP_ADAPTER pAd)
{
UCHAR index;
UCHAR Value = 0;
ULONG Data;
DBGPRINT(RT_DEBUG_TRACE, ("---> NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!! \n"));
// Initialize BBP register to default value (rtmp_init.c)
for (index = 0; index < NUM_BBP_REG_PARMS; index++)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[index].Register, BBPRegTable[index].Value);
}
// copy from (rtmp_init.c)
if (pAd->MACVersion == 0x28600100)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12);
}
// copy from (connect.c LinkUp function)
if (INFRA_ON(pAd))
{
// Change to AP channel
if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
{
// Must using 40MHz.
pAd->CommonCfg.BBPCurrentBW = BW_40;
AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
Value &= (~0x18);
Value |= 0x10;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
// RX : control channel at lower
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
Value &= (~0x20);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
// Record BBPR3 setting, But don't keep R Antenna # information.
pAd->StaCfg.BBPR3 = Value;
RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
Data &= 0xfffffffe;
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
if (pAd->MACVersion == 0x28600100)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
}
DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
}
else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
{
// Must using 40MHz.
pAd->CommonCfg.BBPCurrentBW = BW_40;
AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
Value &= (~0x18);
Value |= 0x10;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
Data |= 0x1;
RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
Value |= (0x20);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
// Record BBPR3 setting, But don't keep R Antenna # information.
pAd->StaCfg.BBPR3 = Value;
if (pAd->MACVersion == 0x28600100)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
}
DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
}
else
{
pAd->CommonCfg.BBPCurrentBW = BW_20;
AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
AsicLockChannel(pAd, pAd->CommonCfg.Channel);
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
Value &= (~0x18);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);