diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2009-02-25 16:14:55 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-04-03 14:54:24 -0700 |
commit | e642f09951f7cbb69983781b07bb9cd881546ac4 (patch) | |
tree | c783967792f17f0abfab38c9a893fb9565b8bae2 /drivers/staging/rt3070/rt_ate.c | |
parent | 21a6a6e9f81fb26fbcecbb1304018d34dcd1794f (diff) |
Staging: add rt3070 wireless driver
This is the Ralink RT3070 driver from the company that does horrible
things like reading a config file from /etc. However, the driver that
is currently under development from the wireless development community
is not working at all yet, so distros and users are using this version
instead (quite common hardware on a lot of netbook machines).
So here is this driver, for now, until the wireless developers get a
"clean" version into the main tree, or until this version is cleaned up
sufficiently to move out of the staging tree.
Ported to the Linux build system, fixed lots of build issues, forward
ported to the current kernel version, and other minor cleanups were all
done by me.
Cc: Linux wireless <linux-wireless@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rt3070/rt_ate.c')
-rw-r--r-- | drivers/staging/rt3070/rt_ate.c | 6506 |
1 files changed, 6506 insertions, 0 deletions
diff --git a/drivers/staging/rt3070/rt_ate.c b/drivers/staging/rt3070/rt_ate.c new file mode 100644 index 00000000000..9238d960121 --- /dev/null +++ b/drivers/staging/rt3070/rt_ate.c @@ -0,0 +1,6506 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* + */ + +#include "rt_config.h" + +#ifdef UCOS +INT IoctlResponse(PUCHAR payload, PUCHAR msg, INT len); +#endif // UCOS // + +#define ATE_BBP_REG_NUM 168 +UCHAR restore_BBP[ATE_BBP_REG_NUM]={0}; + +#ifdef RALINK_ATE +UCHAR TemplateFrame[24] = {0x08/* Data type */,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00}; // 802.11 MAC Header, Type:Data, Length:24bytes +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +#ifdef RT2870 +extern UCHAR EpToQueue[]; +extern VOID RTUSBRejectPendingPackets( IN PRTMP_ADAPTER pAd); +#endif // RT2870 // + +#ifdef RT30xx +//2008/07/10:KH adds to support 3070 ATE<-- +extern FREQUENCY_ITEM FreqItems3020[]; +extern UCHAR NUM_OF_3020_CHNL; +//2008/07/10:KH adds to support 3070 ATE--> +#endif // RT30xx // + +#ifdef UCOS +extern INT ConsoleResponse(IN PUCHAR buff); +extern int (*remote_display)(char *); +#endif // UCOS // + +static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */ +static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */ +static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */ + +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable); + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd); + +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx); + +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +static int CheckMCSValid( + IN UCHAR Mode, + IN UCHAR Mcs); + + +#ifdef RT2870 +static VOID ATEWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst); + +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR MIMOps, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING Transmit); + +#endif // RT2870 // + +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd); + +/*=========================end of prototype=========================*/ + + +#ifdef RT2870 +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + USB_DMA_CFG_STRUC UsbCfg; + + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + if (UsbCfg.field.TxBusy) + result = 1; + else + result = 0; + + return result; +} + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + USB_DMA_CFG_STRUC UsbCfg; + + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + if (UsbCfg.field.RxBusy) + result = 1; + else + result = 0; + + return result; +} + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable) +{ + BOOLEAN value; + ULONG WaitCnt; + USB_DMA_CFG_STRUC UsbCfg; + + value = Enable > 0 ? 1 : 0; + + // check DMA is in busy mode. + WaitCnt = 0; + while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) + { + RTMPusecDelay(10); + if (WaitCnt++ > 100) + break; + } + + //Why not to clear USB DMA TX path first ??? + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + UsbCfg.field.TxBulkEn = value; + UsbCfg.field.RxBulkEn = value; + RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word); // abort all TX rings + RTMPusecDelay(5000); + + return; +} +#endif // RT2870 // + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // Soft reset, set BBP R21 bit0=1->0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData |= 0x00000001; //set bit0=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData &= ~(0x00000001); //set bit0=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + return; +} + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd) +{ + // Set RF value 1's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 2's set R3[bit2] = [1] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 3's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + return; +} + +static int CheckMCSValid( + UCHAR Mode, + UCHAR Mcs) +{ + int i; + PCHAR pRateTab; + + switch(Mode) + { + case 0: + pRateTab = CCKRateTable; + break; + case 1: + pRateTab = OFDMRateTable; + break; + case 2: + case 3: + pRateTab = HTMIXRateTable; + break; + default: + ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode)); + return -1; + break; + } + + i = 0; + while(pRateTab[i] != -1) + { + if (pRateTab[i] == Mcs) + return 0; + i++; + } + + return -1; +} + +#if 1 +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + BOOLEAN bPowerReduce = FALSE; +#ifdef RT30xx + UCHAR RFValue; +#endif // RT30xx // +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (pAd->ate.Channel <= 14) + { + if (TxPower > 31) + { + // + // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + } + else// 5.5 GHz + { + if (TxPower > 15) + { + // + // R3, R4 can't large than 15 (0x0F) + // + R = 15; + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0 + // + // -1 ~ -7 + ASSERT((TxPower >= -7)); + R = (ULONG)(TxPower + 7); + bPowerReduce = TRUE; + } + else + { + // 0 ~ 15 + R = (ULONG) TxPower; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); + } +//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time<-- +#ifdef RT30xx + if(IS_RT30xx(pAd)) + { + // Set Tx Power + + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPower; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + ATEDBGPRINT(RT_DEBUG_TRACE, ("3070 or 2070:%s (TxPower=%d, RFValue=%x)\n", __FUNCTION__, TxPower, RFValue)); + + } + else +#endif // RT30xx // + { + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else// 5.5GHz + { + if (bPowerReduce == FALSE) + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + + /* Clear bit 9 of R3 to reduce 7dB. */ + pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); + } + else + { + R = (R << 7); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + + /* Clear bit 6 of R4 to reduce 7dB. */ + pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); + } + } + } + RtmpRfIoWrite(pAd); + } +//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time--> + + return 0; + } +} +#else// 1 // +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + // TODO: how to get current TxPower0/1 from pAd->LatchRfRegs ? + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (TxPower > 31) + { + // + // R3, R4 can't large than 36 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R3=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + + RtmpRfIoWrite(pAd); + + return 0; + } +} +#endif // 1 // +/* + ========================================================================== + Description: + Set ATE operation mode to + 0. ATESTART = Start ATE Mode + 1. ATESTOP = Stop ATE Mode + 2. TXCONT = Continuous Transmit + 3. TXCARR = Transmit Carrier + 4. TXFRAME = Transmit Frames + 5. RXFRAME = Receive Frames +#ifdef RALINK_28xx_QA + 6. TXSTOP = Stop Any Type of Transmition + 7. RXSTOP = Stop Receiving Frames +#endif // RALINK_28xx_QA // + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +/* */ +/* */ +/*=======================End of RT2860=======================*/ + + +/*======================Start of RT2870======================*/ +/* */ +/* */ + +#ifdef RT2870 +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 Value; + UCHAR BbpData; + UINT32 MacData; + UINT i=0, atemode; + //NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + //PUCHAR pDest; + UINT32 temp; + ULONG IrqFlags; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n")); + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pAd->ate.Channel); + + RTMPusecDelay(5000); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + /* Enter ATE mode and set Tx/Rx Idle */ + if (!strcmp(arg, "ATESTART")) + { +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#endif // CONFIG_STA_SUPPORT // + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n")); + + netif_stop_queue(pAd->net_dev); + + atemode = pAd->ate.Mode; + pAd->ate.Mode = ATE_START; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable auto responder + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp); + temp = temp & 0xFFFFFFFE; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp); + + // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + // clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + // Stop continuous TX production test. + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);//disable or cancel pending irp first ??? + + if (atemode & ATE_TXCARR +#ifdef RT30xx + || atemode & ATE_TXCONT +#endif // RT30xx // +) + { +#ifdef RT30xx + //Hardware Reset BBP + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp |0x00000002; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp & ~(0x00000002); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + //Restore All BBP Value + for(i=0;i<ATE_BBP_REG_NUM;i++) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd,i,restore_BBP[i]); +#endif // RT30xx // + + // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else if (atemode & ATE_TXCARRSUPP) + { +#ifdef RT30xx + //Hardware Reset BBP + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp |0x00000002; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp & ~(0x00000002); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + //Restore All BBP Value + for(i=0;i<ATE_BBP_REG_NUM;i++) + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd,i,restore_BBP[i]); +#endif // RT30xx // + + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // No Carrier Suppression set BBP R24 bit0=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); + BbpData &= 0xFFFFFFFE; //clear bit0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); + } + // We should free some resource which allocate when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT. + // TODO:Should we free some resource which was allocated when LoopBack and ATE_STOP ? + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + if (atemode & ATE_TXCONT) + { + // Not Cont. TX anymore, so set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + // Abort Tx, Rx DMA. + RtmpDmaEnable(pAd, 0); + + { + // It seems nothing to free, + // because we didn't allocate any resource when we entered ATE_TXFRAME mode latestly. + } + + // Start Tx, RX DMA + RtmpDmaEnable(pAd, 1); + } + + RTUSBRejectPendingPackets(pAd); + RTUSBCleanUpDataBulkOutQueue(pAd); + +#ifdef CONFIG_STA_SUPPORT + // + // It will be called in MlmeSuspend(). + // + // Cancel pending timers + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); +#endif // CONFIG_STA_SUPPORT // + + //RTUSBCleanUpMLMEWaitQueue(pAd); /* not used in RT28xx */ + RTUSBCleanUpMLMEBulkOutQueue(pAd); + + // Sometimes kernel will hang on, so we avoid calling MlmeSuspend(). +// MlmeSuspend(pAd, TRUE); + //RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Make sure there are no pending bulk in/out IRPs before we go on. +/*=========================================================================*/ + /* pAd->PendingRx is not of type atomic_t anymore in 28xx */ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + while ((pAd->PendingRx > 0)) //pAd->BulkFlags != 0 wait bulk out finish + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else + NdisInterlockedDecrement(&pAd->PendingRx); +#endif + /* delay 0.5 seconds */ + RTMPusecDelay(500000); + pAd->PendingRx = 0; + } + /* peter : why don't we have to get BulkOutLock first ? */ + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + /* pAd->BulkOutPending[y] will be set to FALSE in RTUSBCancelPendingBulkOutIRP(pAd) */ + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + /* we have enough time delay in RTUSBCancelPendingBulkOutIRP(pAd) + ** so this is not necessary + */ +// RTMPusecDelay(500000); + } + + /* pAd->PendingRx is not of type atomic_t anymore in 28xx */ +// ASSERT(atomic_read(&pAd->PendingRx) == 0); + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + + // reset Rx statistics. + pAd->ate.LastSNR0 = 0; + pAd->ate.LastSNR1 = 0; + pAd->ate.LastRssi0 = 0; + pAd->ate.LastRssi1 = 0; + pAd->ate.LastRssi2 = 0; + pAd->ate.AvgRssi0 = 0; + pAd->ate.AvgRssi1 = 0; + pAd->ate.AvgRssi2 = 0; + pAd->ate.AvgRssi0X8 = 0; + pAd->ate.AvgRssi1X8 = 0; + pAd->ate.AvgRssi2X8 = 0; + pAd->ate.NumOfAvgRssiSample = 0; + +#ifdef RALINK_28xx_QA + // Tx frame + pAd->ate.bQATxStart = FALSE; + pAd->ate.bQARxStart = FALSE; + pAd->ate.seq = 0; + + // counters + pAd->ate.U2M = 0; + pAd->ate.OtherData = 0; + pAd->ate.Beacon = 0; + pAd->ate.OtherCount = 0; + pAd->ate.TxAc0 = 0; + pAd->ate.TxAc1 = 0; + pAd->ate.TxAc2 = 0; + pAd->ate.TxAc3 = 0; + pAd->ate.TxHCCA = 0; + pAd->ate.TxMgmt = 0; + pAd->ate.RSSI0 = 0; + pAd->ate.RSSI1 = 0; + pAd->ate.RSSI2 = 0; + pAd->ate.SNR0 = 0; + pAd->ate.SNR1 = 0; + + // control + pAd->ate.TxDoneCount = 0; + pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running +#endif // RALINK_28xx_QA // + + // Soft reset BBP. + BbpSoftReset(pAd); + + +#ifdef CONFIG_STA_SUPPORT + AsicDisableSync(pAd); + + /* + ** If we skip "LinkDown()", we should disable protection + ** to prevent from sending out RTS or CTS-to-self. + */ + ATEDisableAsicProtect(pAd); + RTMPStationStop(pAd); +#endif // CONFIG_STA_SUPPORT // + + // Default value in BBP R22 is 0x0. + BbpData = 0; + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + //Clean ATE Bulk in/out counter and continue setup + InterlockedExchange(&pAd->BulkOutRemained, 0); + + /* NdisAcquireSpinLock()/NdisReleaseSpinLock() need only one argument in RT28xx */ + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + pAd->ContinBulkIn = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + } + else if (!strcmp(arg, "ATESTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE : ATESTOP ===>\n")); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);//0820 + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); // recover the MAC_SYS_CTRL register back. + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + /* + ** Abort Tx, RX DMA. + ** Q : How to do the following I/O if Tx, Rx DMA is aborted ? + ** Ans : Bulk endpoints are aborted, while the control endpoint is not. + */ + RtmpDmaEnable(pAd, 0); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + /* Make sure there are no pending bulk in/out IRPs before we go on. */ +/*=========================================================================*/ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + +// ASSERT(atomic_read(&pAd->PendingRx) == 0); + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ +/* Reset Rx RING */ +/*=========================================================================*/ +// InterlockedExchange(&pAd->PendingRx, 0); + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = RX_RING_SIZE - 1; // Rx Bulk pointer + pAd->NextRxBulkInPosition = 0; + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); + /* peter : why don't we have to get BulkInLock first ? */ + pRxContext->pAd = pAd; + pRxContext->pIrp = NULL; + /* peter debug ++ */ + pRxContext->BulkInOffset = 0; + pRxContext->bRxHandling = FALSE; + /* peter debug -- */ + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; +// pRxContext->ReorderInUse = FALSE; +// pRxContext->ReadPosOffset = 0; + } + +/*=========================================================================*/ +/* Reset Tx RING */ +/*=========================================================================*/ + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + +/*=========================================================================*/ + // Enable auto responder. + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp); + temp = temp | (0x01); + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp); + +/*================================================*/ + AsicEnableBssSync(pAd); + + /* Soft reset BBP.*/ + /* In 2870 chipset, ATE_BBP_IO_READ8_BY_REG_ID() == RTMP_BBP_IO_READ8_BY_REG_ID() */ + /* Both rt2870ap and rt2870sta use BbpSoftReset(pAd) to do BBP soft reset */ + BbpSoftReset(pAd); +/*================================================*/ + { +#ifdef CONFIG_STA_SUPPORT + // Set all state machines back IDLE + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; +#endif // CONFIG_STA_SUPPORT // + + // + // ===> refer to MlmeRestartStateMachine(). + // When we entered ATE_START mode, PeriodicTimer was not cancelled. + // So we don't have to set it here. + // + //RTMPSetTimer(pAd, &pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + + ASSERT(pAd->CommonCfg.Channel != 0); + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + +#ifdef CONFIG_STA_SUPPORT + RTMPStationStart(pAd); +#endif // CONFIG_STA_SUPPORT // + } +// +// These two steps have been done when entering ATE_STOP mode. +// + // Clean ATE Bulk in/out counter and continue setup. + InterlockedExchange(&pAd->BulkOutRemained, 0); + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + pAd->ContinBulkIn = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + /* Wait 50ms to prevent next URB to bulkout during HW reset. */ + /* todo : remove this if not necessary */ + NdisMSleep(50000); + + pAd->ate.Mode = ATE_STOP; + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + +/*=========================================================================*/ + /* restore RX_FILTR_CFG */ +#ifdef CONFIG_STA_SUPPORT + /* restore RX_FILTR_CFG in order that QA maybe set it to 0x3 */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); +#endif // CONFIG_STA_SUPPORT // +/*=========================================================================*/ + + // Enable Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Wait 10ms to wait all of the bulk-in URBs to complete. + /* todo : remove this if not necessary */ + NdisMSleep(10000); + + // Everything is ready to start normal Tx/Rx. + RTUSBBulkReceive(pAd); + netif_start_queue(pAd->net_dev); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATE : ATESTOP \n")); + } + else if (!strcmp(arg, "TXCARR")) // Tx Carrier + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n")); + pAd->ate.Mode |= ATE_TXCARR; + +#ifdef RT30xx + for(i=0;i<ATE_BBP_REG_NUM;i++) + restore_BBP[i]=0; + //Record All BBP Value + for(i=0;i<ATE_BBP_REG_NUM;i++) + ATE_BBP_IO_READ8_BY_REG_ID(pAd,i,&restore_BBP[i]); +#endif // RT30xx // + + // Disable Rx + // May be we need not to do this, because these have been done in ATE_START mode ??? + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // QA has done the following steps if it is used. + if (pAd->ate.bQATxStart == FALSE) + { + // Soft reset BBP. + BbpSoftReset(pAd); + + // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1 + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value = Value | 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + } + else if (!strcmp(arg, "TXCONT")) // Tx Continue + { + if (pAd->ate.bQATxStart == TRUE) + { + /* set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test) + and bit2(MAC TX enable) back to zero. */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData &= 0xFFFFFFEB; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + // set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF7F; //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + + /* for TxCont mode. + ** Step 1: Send 50 packets first then wait for a moment. + ** Step 2: Send more 50 packet then start continue mode. + */ + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n")); + +#ifdef RT30xx + for(i=0;i<ATE_BBP_REG_NUM;i++) + restore_BBP[i]=0; + //Record All BBP Value + for(i=0;i<ATE_BBP_REG_NUM;i++) + ATE_BBP_IO_READ8_BY_REG_ID(pAd,i,&restore_BBP[i]); +#endif // RT30xx // + + // Step 1: send 50 packets first. + pAd->ate.Mode |= ATE_TXCONT; + pAd->ate.TxCount = 50; + pAd->ate.TxDoneCount = 0; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + + /* Only needed if we have to send some normal frames. */ + SetJapanFilter(pAd); + + // Setup frame format. + ATESetUpFrame(pAd, 0); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + NdisAcquireSpinLock(&pAd->GenericLock);//0820 + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Kick bulk out + RTUSBKickBulkOut(pAd); + + /* To make sure all the 50 frames have been bulk out before executing step 2 */ + while (atomic_read(&pAd->BulkOutRemained) > 0) + { + RTMPusecDelay(5000); + } + + // Step 2: send more 50 packets then start continue mode. + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Cont. TX set BBP R22 bit7=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData |= 0x00000080; //set bit7=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + pAd->ate.TxCount = 50; + pAd->ate.TxDoneCount = 0; + + SetJapanFilter(pAd); + + // Setup frame format. + ATESetUpFrame(pAd, 0); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + NdisAcquireSpinLock(&pAd->GenericLock);//0820 + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + // Kick bulk out + RTUSBKickBulkOut(pAd); + +#if 1 + RTMPusecDelay(500); +#else + while (atomic_read(&pAd->BulkOutRemained) > 0) + { + RTMPusecDelay(5000); + } +#endif // 1 // + + // Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData |= 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + } + else if (!strcmp(arg, "TXFRAME")) // Tx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=0x%08x)\n", pAd->ate.TxCount)); + pAd->ate.Mode |= ATE_TXFRAME; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + +#ifdef RALINK_28xx_QA + // add this for LoopBack mode + if (pAd->ate.bQARxStart == FALSE) + { + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#else + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); +#endif // RALINK_28xx_QA // + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + SetJapanFilter(pAd); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + pAd->ate.TxDoneCount = 0; + + // Setup frame format + ATESetUpFrame(pAd, 0); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Check count is continuous or not yet. + // + // Due to the type mismatch between "pAd->BulkOutRemained"(atomic_t) and "pAd->ate.TxCount"(UINT32) + // + if (pAd->ate.TxCount == 0) + { + InterlockedExchange(&pAd->BulkOutRemained, 0); + } + else + { + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + } + ATEDBGPRINT(RT_DEBUG_TRACE, ("bulk out count = %d\n", atomic_read(&pAd->BulkOutRemained))); + ASSERT((atomic_read(&pAd->BulkOutRemained) >= 0)); + + if (atomic_read(&pAd->BulkOutRemained) == 0) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packet countinuously\n")); + + /* In 28xx, NdisAcquireSpinLock() == spin_lock_bh() */ + /* NdisAcquireSpinLock only need one argument in 28xx. */ + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = TRUE; + NdisReleaseSpinLock(&pAd->GenericLock); + + /* In 28xx, BULK_OUT_LOCK() == spin_lock_irqsave() */ + BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK + pAd->BulkOutPending[0] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packets depend on counter\n")); + + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags); + pAd->BulkOutPending[0] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Kick bulk out + RTUSBKickBulkOut(pAd); + } +#ifdef RALINK_28xx_QA + else if (!strcmp(arg, "TXSTOP")) //Enter ATE mode and set Tx/Rx Idle + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n")); + + atemode = pAd->ate.Mode; + pAd->ate.Mode &= ATE_TXSTOP; + pAd->ate.bQATxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + +/*=========================================================================*/ + if (atemode & ATE_TXCARR) + { + // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else if (atemode & ATE_TXCARRSUPP) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // No Carrier Suppression set BBP R24 bit0=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); + BbpData &= 0xFFFFFFFE; //clear bit0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); + } + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + if (atemode & ATE_TXCONT) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + } + +/*=========================================================================*/ + RTUSBRejectPendingPackets(pAd); + RTUSBCleanUpDataBulkOutQueue(pAd); + + /* not used in RT28xx */ + //RTUSBCleanUpMLMEWaitQueue(pAd); + /* empty function so far */ + RTUSBCleanUpMLMEBulkOutQueue(pAd); +/*=========================================================================*/ + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); +/*=========================================================================*/ + + /* In 28xx, pAd->PendingRx is not of type atomic_t anymore */ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + /* peter todo : BulkInLock */ + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + // Enable Tx, Rx DMA. + RtmpDmaEnable(pAd, 1); + + /* task Tx status : 0 --> task is idle, 1 --> task is running */ + pAd->ate.TxStatus = 0; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData &= (0xfffffffb); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + //Clean ATE Bulk in/out counter and continue setup + InterlockedExchange(&pAd->BulkOutRemained, 0); + + pAd->ContinBulkOut = FALSE; + } + else if (!strcmp(arg, "RXSTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n")); + atemode = pAd->ate.Mode; + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.bQARxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + +/*=========================================================================*/ + RTUSBRejectPendingPackets(pAd); + RTUSBCleanUpDataBulkOutQueue(pAd); + + /* not used in RT28xx */ + //RTUSBCleanUpMLMEWaitQueue(pAd); + RTUSBCleanUpMLMEBulkOutQueue(pAd); +/*=========================================================================*/ + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); +/*=========================================================================*/ +// while ((atomic_read(&pAd->PendingRx) > 0)) + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + + // Soft reset BBP. + BbpSoftReset(pAd); + pAd->ContinBulkIn = FALSE; + } +#endif // RALINK_28xx_QA // + else if (!strcmp(arg, "RXFRAME")) // Rx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n")); + + // Disable Rx of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + pAd->ate.Mode |= ATE_RXFRAME; + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Disable TX of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Reset Rx RING. + for ( i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + + // + // Get the urb from kernel back to driver. + // + RTUSB_UNLINK_URB(pRxContext->pUrb); + + /* Sleep 200 microsecs to give cancellation time to work. */ + NdisMSleep(200); + pAd->BulkInReq = 0; + +// InterlockedExchange(&pAd->PendingRx, 0); + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = RX_RING_SIZE - 1; // Rx Bulk pointer + pAd->NextRxBulkInPosition = 0; + } + + // read to clear counters + RTUSBReadMACRegister(pAd, RX_STA_CNT0, &temp); //RX PHY & RX CRC count + RTUSBReadMACRegister(pAd, RX_STA_CNT1, &temp); //RX PLCP error count & CCA false alarm count + RTUSBReadMACRegister(pAd, RX_STA_CNT2, &temp); //RX FIFO overflow frame count & RX duplicated filtered frame count + + pAd->ContinBulkIn = TRUE; + + // Enable Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable RX of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Kick bulk in + RTUSBBulkReceive(pAd); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n")); + return FALSE; + } + RTMPusecDelay(5000); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n")); + + return TRUE; +} +#endif // RT2870 // + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (ATECmdHandler(pAd, arg)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n")); + + + return TRUE; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr3[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0], + pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr2[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0], + pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr1[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr1[0], + pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Channel + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR channel; + + channel = simple_strtol(arg, 0, 10); + + if ((channel < 1) || (channel > 216))// to allow A band channel : ((channel < 1) || (channel > 14)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n")); + return FALSE; + } + pAd->ate.Channel = channel; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power0 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else// 5.5GHz + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower0 = TxPower; + ATETxPwrHandler(pAd, 0); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power1 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower1 = TxPower; + ATETxPwrHandler(pAd, 1); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 2) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.TxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Rx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 3) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.RxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF frequence offset + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_FREQOFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR RFFreqOffset; + ULONG R4; + + RFFreqOffset = simple_strtol(arg, 0, 10); +#ifndef RT30xx + if(RFFreqOffset >= 64) +#endif // RT30xx // +#ifdef RT30xx +//2008/08/06: KH modified the limit of offset value from 65 to 95(0x5F) + if(RFFreqOffset >= 95) +#endif // RT30xx // + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n")); + return FALSE; + } + + pAd->ate.RFFreqOffset = RFFreqOffset; +#ifdef RT30xx + if(IS_RT30xx(pAd)) + { + // Set RF offset + UCHAR RFValue; + RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue); + //2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" + RFValue = (RFValue & 0x80) | pAd->ate.RFFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue); + } + else +#endif // RT30xx // + { + + R4 = pAd->ate.RFFreqOffset << 15; // shift TX power control to correct RF register bit position + R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + } + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + int i; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if(BBPCurrentBW == 0) + pAd->ate.TxWI.BW = BW_20; + else + pAd->ate.TxWI.BW = BW_40; + + if(pAd->ate.TxWI.BW == BW_20) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } + } + + //Set BBP R4 bit[4:3]=0:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0B + //to improve Rx sensitivity. + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x08 + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x11 + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1 + // (Japan filter coefficients) + // This segment of code will only works when ATETXMODE and ATECHANNEL + // were set to MODE_CCK and 14 respectively before ATETXBW is set to 0. + //===================================================================== + if (pAd->ate.Channel == 14) + { + int TxMode = pAd->ate.TxWI.PHYMODE; + if (TxMode == MODE_CCK) + { + // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; //set bit5=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + + //===================================================================== + // If bandwidth != 40M, RF Reg4 bit 21 = 0. +#ifdef RT30xx + // Set BW + if(IS_RT30xx(pAd)) + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW20RfR24); + else +#endif // RT30xx // + { + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + } + + } + else if(pAd->ate.TxWI.BW == BW_40) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } +#ifdef DOT11_N_SUPPORT + if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } +#endif // DOT11_N_SUPPORT // + } + + //Set BBP R4 bit[4:3]=1:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0C + //to improve Rx sensitivity. + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x1A + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x0A + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If bandwidth = 40M, set RF Reg4 bit 21 = 1. +#ifdef RT30xx + // Set BW + if(IS_RT30xx(pAd)) + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW40RfR24); + else +#endif // RT30xx // + { + pAd->LatchRfRegs.R4 |= 0x00200000; + RtmpRfIoWrite(pAd); + } + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame length + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxLength = simple_strtol(arg, 0, 10); + + if((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) + { + pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */); + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame count + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxCount = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame MCS + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR MCS; + int result; + + MCS = simple_strtol(arg, 0, 10); + result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS); + + if (result != -1) + { + pAd->ate.TxWI.MCS = (UCHAR)MCS; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame Mode + 0: MODE_CCK + 1: MODE_OFDM + 2: MODE_HTMIX + 3: MODE_HTGREENFIELD + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.PHYMODE > 3) + { + pAd->ate.TxWI.PHYMODE = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range. it should be in range of 0~3\n")); + ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame GI + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.ShortGI > 1) + { + pAd->ate.TxWI.ShortGI = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.bRxFer = simple_strtol(arg, 0, 10); + + if (pAd->ate.bRxFer == 1) + { + pAd->ate.RxCntPerSec = 0; + pAd->ate.RxTotalCnt = 0; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFer = %d)\n", pAd->ate.bRxFer)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n")); + + + return TRUE; +} + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support RT30xx ATE<-- + if(IS_RT30xx(pAd)) + { + /* modify by WY for Read RF Reg. error */ + UCHAR RFValue; + INT index=0; + for (index = 0; index < 32; index++) + { + RT30xxReadRFRegister(pAd, index, (PUCHAR)&RFValue); + printk("R%d=%d\n",index,RFValue); + } + } + else +//2008/07/10:KH add to support RT30xx ATE--> +#endif // RT30xx // + { + ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1); + ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2); + ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3); + ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4); + } + return TRUE; +} + +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R1 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; + +} + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R2 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R3 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R4 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- +INT SET_ATE_3070RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *this_char; + CHAR *value; + UINT32 Reg,RFValue; + if(IS_RT30xx(pAd)) + { + printk("SET_ATE_3070RF_Proc=%s\n",arg); + this_char =arg; + if ((value = strchr(this_char, ':')) != NULL) + *value++ = 0; + Reg= simple_strtol(this_char, 0, 16); + RFValue= simple_strtol(value, 0, 16); + printk("RF Reg[%d]=%d\n",Reg,RFValue); + RT30xxWriteRFRegister(pAd, Reg,RFValue); + } + else + printk("Warning!! Only 3070 Support\n"); + return TRUE; +} +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // +/* + ========================================================================== + Description: + Load and Write EEPROM from a binary file prepared in advance. + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +#ifndef UCOS +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + BOOLEAN ret = FALSE; + PUCHAR src = EEPROM_BIN_FILE_NAME; + struct file *srcf; + INT32 retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + UINT32 FileLength = 0; + UINT32 value = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __FUNCTION__, value)); + + if (value > 0) + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* save uid and gid used for filesystem access. + ** set user and group to 0 (root) + */ + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + /* as root */ + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + do + { + /* open the bin file */ + srcf = filp_open(src, O_RDONLY, 0); + + if (IS_ERR(srcf)) + { + ate_print("%s - Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(srcf), src); + break; + } + + /* the object must have a read method */ + if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL)) + { + ate_print("%s - %s does not have a read method\n", __FUNCTION__, src); + break; + } + + /* read the firmware from the file *.bin */ + FileLength = srcf->f_op->read(srcf, + (PUCHAR)WriteEEPROM, + EEPROM_SIZE, + &srcf->f_pos); + + if (FileLength != EEPROM_SIZE) + { + ate_print("%s: error file length (=%d) in e2p.bin\n", + __FUNCTION__, FileLength); + break; + } + else + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + ret = TRUE; + } + break; + } while(TRUE); + + /* close firmware file */ + if (IS_ERR(srcf)) + { + ; + } + else + { + retval = filp_close(srcf, NULL); + if (retval) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); + + } + } + + /* restore */ + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + } + ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __FUNCTION__, ret)); + + return ret; + +} +#else +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + struct iwreq *wrq = (struct iwreq *)arg; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> %s (wrq->u.data.length = %d)\n\n", __FUNCTION__, wrq->u.data.length)); + + if (wrq->u.data.length != EEPROM_SIZE) + { + ate_print("%s: error length (=%d) from host\n", + __FUNCTION__, wrq->u.data.length); + return FALSE; + } + else/* (wrq->u.data.length == EEPROM_SIZE) */ + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* fill the local buffer */ + NdisMoveMemory((PUCHAR)WriteEEPROM, wrq->u.data.pointer, wrq->u.data.length); + + do + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + + } while(FALSE); + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __FUNCTION__)); + + return TRUE; + +} +#endif // !UCOS // + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT buffer[EEPROM_SIZE/2]; + USHORT *p; + int i; + + rt_ee_read_all(pAd, (USHORT *)buffer); + p = buffer; + for (i = 0; i < (EEPROM_SIZE/2); i++) + { + ate_print("%4.4x ", *p); + if (((i+1) % 16) == 0) + ate_print("\n"); + p++; + } + return TRUE; +} + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("Mode=%d\n", pAd->ate.Mode); + ate_print("TxPower0=%d\n", pAd->ate.TxPower0); + ate_print("TxPower1=%d\n", pAd->ate.TxPower1); + ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel); + ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel); + ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW); + ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI); + ate_print("MCS=%d\n", pAd->ate.TxWI.MCS); + ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE); + ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]); + ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]); + ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]); + ate_print("Channel=%d\n", pAd->ate.Channel); + ate_print("TxLength=%d\n", pAd->ate.TxLength); + ate_print("TxCount=%u\n", pAd->ate.TxCount); + ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset); + ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n"); + return TRUE; +} + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n"); + ate_print("ATEDA\n"); + ate_print("ATESA\n"); + ate_print("ATEBSSID\n"); + ate_print("ATECHANNEL, range:0~14(unless A band !)\n"); + ate_print("ATETXPOW0, set power level of antenna 1.\n"); + ate_print("ATETXPOW1, set power level of antenna 2.\n"); + ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n"); + ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n"); + ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n"); + ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n"); + ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */)); + ate_print("ATETXCNT, set how many frame going to transmit.\n"); + ate_print("ATETXMCS, set MCS, reference to rate table.\n"); + ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n"); + ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n"); + ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n"); + ate_print("ATERRF, show all RF registers.\n"); + ate_print("ATEWRF1, set RF1 register.\n"); + ate_print("ATEWRF2, set RF2 register.\n"); + ate_print("ATEWRF3, set RF3 register.\n"); + ate_print("ATEWRF4, set RF4 register.\n"); + ate_print("ATELDE2P, load EEPROM from .bin file.\n"); + ate_print("ATERE2P, display all EEPROM content.\n"); + ate_print("ATESHOW, display all parameters of ATE.\n"); + ate_print("ATEHELP, online help.\n"); + + return TRUE; +} + +/* + ========================================================================== + Description: + + AsicSwitchChannel() dedicated for ATE. + + ========================================================================== +*/ +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index, BbpValue = 0, R66 = 0x30; + RTMP_RF_REGS *RFRegTable; + UCHAR Channel; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + if (pAd->ate.Channel != pAd->LatchRfRegs.Channel) + { + pAd->ate.Channel = pAd->LatchRfRegs.Channel; + } + return; + } + else +#endif // RALINK_28xx_QA // + Channel = pAd->ate.Channel; + + // Select antenna + AsicAntennaSelect(pAd, Channel); + + // fill Tx power value + TxPwer = pAd->ate.TxPower0; + TxPwer2 = pAd->ate.TxPower1; +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + + // The RF programming sequence is difference between 3xxx and 2xxx + // The 3070 is 1T1R. Therefore, we don't need to set the number of Tx/Rx path and the only job is to set the parameters of channels. + if (IS_RT30xx(pAd) && ((pAd->RfIcType == RFIC_3020) || +(pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022) || +(pAd->RfIcType == RFIC_2020))) + { + /* modify by WY for Read RF Reg. error */ + UCHAR RFValue; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { + // Programming channel parameters + RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); + + RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; + RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue); + + // Set Tx Power + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + // Set RF offset + RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue); + //2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" + RFValue = (RFValue & 0x80) | pAd->ate.RFFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue); + + // Set BW + if (pAd->ate.TxWI.BW == BW_40) + { + RFValue = pAd->Mlme.CaliBW40RfR24; + //DISABLE_11N_CHECK(pAd); + } + else + { + RFValue = pAd->Mlme.CaliBW20RfR24; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue); + + // Enable RF tuning + RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue); + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // +{ + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + /* But only 2850 and 2750 support 5.5GHz band... */ + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + R2 |= 0x40; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + /* Only enable two Antenna to receive. */ + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + + if (pAd->Antenna.field.TxPath == 2) + { + if (pAd->ate.TxAntennaSel == 1) + { + R2 |= 0x4000; // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; //11100111B + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pAd->ate.TxAntennaSel == 2) + { + R2 |= 0x8000; // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + if (pAd->Antenna.field.RxPath == 3) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 3: + R2 |= 0x30000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + + if (Channel > 14) + { + // initialize R3, R4 + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15); + + // According the Rory's suggestion to solve the middle range issue. + // 5.5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB + // R3 + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + // R4 + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6);// Set freq offset & TxPwr1 + } + + // Based on BBP current mode before changing RF channel. + if (pAd->ate.TxWI.BW == BW_40) + { + R4 |=0x200000; + } + + // Update variables + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + break; + } + } + break; + + default: + break; + } +} + // Change BBP setting during switch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* For 1T/2R chip only... */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + } + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + else + { + ULONG TxPinCfg = 0x00050F05;//2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue); + ASSERT((BbpValue == 0x00)); + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + // R66 should be set according to Channel and use 20MHz when scanning + if (Channel <= 14) + { + // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + // 5.5 GHz band + if (pAd->ate.TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + + // + // On 11A, We should delay and wait RF/BBP to be stable + // and the appropriate time should be 1000 micro seconds + // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + // + RTMPusecDelay(1000); + + if (Channel > 14) + { + // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } +} + +// +// In fact, no one will call this routine so far ! +// +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in ATE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRateSwitching() + ========================================================================== + */ +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[5]; + CHAR Value; + + /* no one calls this procedure so far */ + if (pAd->ate.TxWI.BW == BW_40) + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + // TX power compensation for temperature variation based on TSSI. + // Do it per 4 seconds. + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->ate.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) + { + // Reading is larger than the reference value. + // Check for how large we need to decrease the Tx power. + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range + break; + } + // The index is the step we should decrease, idx = 0 means there is nothing to compensate +// if (R3 > (ULONG) (TxAgcStep * (idx-1))) + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); +// else +// *pTxAgcCompensate = -((UCHAR)R3); + + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < pTssiPlusBoundary[1]) + { + // Reading is smaller than the reference value + // check for how large we need to increase the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range + break; + } + // The index is the step we should increase, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + ATEDBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->ate.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* calculate delta power based on the percentage specified from UI */ + // E2PROM setting is calibrated for maximum TX power (i.e. 100%) + // We lower TX power here according to the percentage specified from UI + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control + ; + else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW + { + DeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW + { + DeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW + { + DeltaPwr -= 6; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW + { + DeltaPwr -= 9; + } + else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW + { + DeltaPwr -= 12; + } + + /* reset different new tx power for different TX rate */ + for(i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + + + } + } + +} + +/* + ======================================================================== + Routine Description: + Write TxWI for ATE mode. + + Return Value: + None + ======================================================================== +*/ + +#ifdef RT2870 +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR MIMOps, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING Transmit) +{ + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + pTxWI->FRAG= FRAG; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + + pTxWI->MIMOps = PWR_ACTIVE; + pTxWI->MpduDensity = 4; + pTxWI->ACK = Ack; + pTxWI->txop = Txopmode; + pTxWI->NSEQ = NSeq; + pTxWI->BAWinSize = BASize; + + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + pTxWI->BW = Transmit.field.BW; + pTxWI->ShortGI = Transmit.field.ShortGI; + pTxWI->STBC= Transmit.field.STBC; + + pTxWI->MCS = Transmit.field.MCS; + pTxWI->PHYMODE= Transmit.field.MODE; + +#ifdef DOT11_N_SUPPORT + // + // MMPS is 802.11n features. Because TxWI->MCS > 7 must be HT mode, + // so need not check if it's HT rate. + // + if ((MIMOps == MMPS_STATIC) && (pTxWI->MCS > 7)) + pTxWI->MCS = 7; + + if ((MIMOps == MMPS_DYNAMIC) && (pTxWI->MCS > 7)) // SMPS protect 2 spatial. + pTxWI->MIMOps = 1; +#endif // DOT11_N_SUPPORT // + + pTxWI->CFACK = CfAck; + + return; +} +#endif // RT2870 // +/* + ======================================================================== + + Routine Description: + Disable protection for ATE. + ======================================================================== +*/ +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + + // Config ASIC RTS threshold register + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + // Initial common protection settings + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + // Handle legacy(B/G) protection + ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + + // NO PROTECT + // 1.All STAs in the BSS are 20/40 MHz HT + // 2. in ai 20/40MHz BSS + // 3. all STAs are 20MHz in a 20MHz BSS + // Pure HT. no protection. + + // MM20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[2] = 0x01744004; + + // MM40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[3] = 0x03f44084; + + // CF20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[4] = 0x01744004; + + // CF40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[5] = 0x03f44084; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + +} + +#ifdef RT2870 +/* + ======================================================================== + Routine Description: + Write TxInfo for ATE mode. + + Return Value: + None + ======================================================================== +*/ +static VOID ATEWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst) +{ + pTxInfo->USBDMATxPktLen = USBDMApktLen; + pTxInfo->QSEL = QueueSel; + + if (QueueSel != FIFO_EDCA) + ATEDBGPRINT(RT_DEBUG_TRACE, ("=======> QueueSel != FIFO_EDCA<=======\n")); + + pTxInfo->USBDMANextVLD = NextValid; + pTxInfo->USBDMATxburst = TxBurst; + pTxInfo->WIV = bWiv; + pTxInfo->SwUseLastRound = 0; + pTxInfo->rsv = 0; + pTxInfo->rsv2 = 0; + + return; +} +#endif // RT2870 // + +/* There are two ways to convert Rssi */ +#if 1 +// +// The way used with GET_LNA_GAIN(). +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-12 - RssiOffset - LNAGain - Rssi); +} +#else +// +// The way originally used in ATE of rt2860ap. +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + if (pAd->LatchRfRegs.Channel > 14) + { + LNAGain = pAd->ALNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + LNAGain = pAd->BLNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-32 - RssiOffset + LNAGain - Rssi); +} +#endif /* end of #if 1 */ + +/* + ======================================================================== + + Routine Description: + Set Japan filter coefficients if needed. + Note: + This routine should only be called when + entering TXFRAME mode or TXCONT mode. + + ======================================================================== +*/ +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // + // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1 + // (Japan Tx filter coefficients)when (TXFRAME or TXCONT). + // + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); + + if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20)) + { + BbpData |= 0x20; // turn on + ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n")); + } + else + { + BbpData &= 0xdf; // turn off + ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n")); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); +} + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI) +{ + /* There are two ways to collect RSSI. */ +#if 1 + //pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + if (pRxWI->RSSI0 != 0) + { + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + } + if (pRxWI->RSSI1 != 0) + { + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + } + if (pRxWI->RSSI2 != 0) + { + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + } + + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ? + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ? + + pAd->ate.NumOfAvgRssiSample ++; +#else + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0); + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1); + pAd->ate.RxCntPerSec++; + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + pAd->ate.NumOfAvgRssiSample ++; +#endif +} + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd) +{ +// BOOLEAN Cancelled; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n")); + + // For rx statistics, we need to keep this timer running. +// RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n")); +} + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd) +{ + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); +} +#endif // CONFIG_STA_SUPPORT // + +/* + ========================================================================== + Description: + Setup Frame format. + NOTE: + This routine should only be used in ATE mode. + ========================================================================== + */ + +#ifdef RT2870 +/*======================Start of RT2870======================*/ +/* */ +/* */ +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx) +{ + UINT j; + PTX_CONTEXT pNullContext; + PUCHAR pDest; + HTTRANSMIT_SETTING TxHTPhyMode; + PTXWI_STRUC pTxWI; + PTXINFO_STRUC pTxInfo; + UINT32 TransferBufferLength, OrgBufferLength = 0; + UCHAR padLen = 0; +#ifdef RALINK_28xx_QA + PHEADER_802_11 pHeader80211 = NULL; +#endif // RALINK_28xx_QA // + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + return -1; + } + + /* We always use QID_AC_BE and FIFO_EDCA in ATE mode. */ + + pNullContext = &(pAd->NullContext); + ASSERT(pNullContext != NULL); + + if (pNullContext->InUse == FALSE) + { + // Set the in use bit + pNullContext->InUse = TRUE; + NdisZeroMemory(&(pAd->NullFrame), sizeof(HEADER_802_11)); + + // Fill 802.11 header. +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pHeader80211 = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen); +// pDest = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen); +// pHeader80211 = (PHEADER_802_11)pDest; + } + else +#endif // RALINK_28xx_QA // + { + // Fill 802.11 header. + NdisMoveMemory(&(pAd->NullFrame), TemplateFrame, sizeof(HEADER_802_11)); + } +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)&(pAd->NullFrame), DIR_READ, FALSE); +#endif // RT_BIG_ENDIAN // + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + /* modify sequence number.... */ + if (pAd->ate.TxDoneCount == 0) + { + pAd->ate.seq = pHeader80211->Sequence; + } + else + { + pHeader80211->Sequence = ++pAd->ate.seq; + } + /* We already got all the addr. fields from QA GUI. */ + } + else +#endif // RALINK_28xx_QA // + { + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->ate.Addr1); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->ate.Addr2); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->ate.Addr3); + } + + RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], TX_BUFFER_NORMSIZE);//??? + pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0]; + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // Avoid to exceed the range of WirelessPacket[]. + ASSERT(pAd->ate.TxInfo.USBDMATxPktLen <= (MAX_FRAME_SIZE - 34/* == 2312 */)); + NdisMoveMemory(pTxInfo, &(pAd->ate.TxInfo), sizeof(pAd->ate.TxInfo)); + } + else +#endif // RALINK_28xx_QA // + { + // Avoid to exceed the range of WirelessPacket[]. + ASSERT(pAd->ate.TxLength <= (MAX_FRAME_SIZE - 34/* == 2312 */)); + + // pTxInfo->USBDMATxPktLen will be updated to include padding later. + ATEWriteTxInfo(pAd, pTxInfo, (USHORT)(TXWI_SIZE + pAd->ate.TxLength), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxInfo->QSEL = FIFO_EDCA; + } + + pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; + + // Fill TxWI. + if (pAd->ate.bQATxStart == TRUE) + { + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = pAd->ate.TxWI.STBC; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ, + pAd->ate.TxWI.BAWinSize, BSSID_WCID, pAd->ate.TxWI.MPDUtotalByteCount/* include 802.11 header */, pAd->ate.TxWI.PacketId, 0, pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, TxHTPhyMode); + } + else + { + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = 0; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + + ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE/* No ack required. */, FALSE, 0, BSSID_WCID, pAd->ate.TxLength, + 0, 0, IFS_HTTXOP, FALSE, TxHTPhyMode);// "MMPS_STATIC" instead of "MMPS_DYNAMIC" ??? + } + + RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); + + pDest = &(pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE+sizeof(HEADER_802_11)]); + + // Prepare frame payload +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // copy pattern + if ((pAd->ate.PLen != 0)) + { + for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen) + { + RTMPMoveMemory(pDest, pAd->ate.Pattern, pAd->ate.PLen); + pDest += pAd->ate.PLen; + } + } + TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxWI.MPDUtotalByteCount; + } + else +#endif // RALINK_28xx_QA // + { + for (j = 0; j < (pAd->ate.TxLength - sizeof(HEADER_802_11)); j++) + { + *pDest = 0xA5; + pDest += 1; + } + TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxLength; + } + +#if 1 + OrgBufferLength = TransferBufferLength; + TransferBufferLength = (TransferBufferLength + 3) & (~3); + + // Always add 4 extra bytes at every packet. + padLen = TransferBufferLength - OrgBufferLength + 4;/* 4 == last packet padding */ + ASSERT((padLen <= (RTMP_PKT_TAIL_PADDING - 4/* 4 == MaxBulkOutsize alignment padding */))); + + /* Now memzero all extra padding bytes. */ + NdisZeroMemory(pDest, padLen); + pDest += padLen; +#else + if ((TransferBufferLength % 4) == 1) + { + NdisZeroMemory(pDest, 7); + pDest += 7; + TransferBufferLength += 3; + } + else if ((TransferBufferLength % 4) == 2) + { + NdisZeroMemory(pDest, 6); + pDest += 6; + TransferBufferLength += 2; + } + else if ((TransferBufferLength % 4) == 3) + { + NdisZeroMemory(pDest, 5); + pDest += 5; + TransferBufferLength += 1; + } +#endif // 1 // + + // Update pTxInfo->USBDMATxPktLen to include padding. + pTxInfo->USBDMATxPktLen = TransferBufferLength - TXINFO_SIZE; + + TransferBufferLength += 4; + + // If TransferBufferLength is multiple of 64, add extra 4 bytes again. + if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0) + { + NdisZeroMemory(pDest, 4); + TransferBufferLength += 4; + } + + // Fill out frame length information for global Bulk out arbitor + pAd->NullContext.BulkOutSize = TransferBufferLength; + } +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); + RTMPFrameEndianChange(pAd, (((PUCHAR)pTxInfo)+TXWI_SIZE+TXINFO_SIZE), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + return 0; +} + +VOID ATE_RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pNullContext; + UCHAR BulkOutPipeId; + NTSTATUS Status; + unsigned long IrqFlags; + ULONG OldValue; + + pNullContext = (PTX_CONTEXT)pUrb->context; + pAd = pNullContext->pAd; + + + // Reset Null frame context flags + pNullContext->IRPPending = FALSE; + pNullContext->InUse = FALSE; + Status = pUrb->status; + + // Store BulkOut PipeId + BulkOutPipeId = pNullContext->BulkOutPipeId; + pAd->BulkOutDataOneSecCount++; + + if (Status == USB_ST_NOERROR) + { +#ifdef RALINK_28xx_QA + if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) + { + if (pAd->ate.QID == BulkOutPipeId) + { + // Let Rx can have a chance to break in during Tx process, + // especially for loopback mode in QA ATE. + // To trade off between tx performance and loopback mode integrity. + /* Q : Now Rx is handled by tasklet, do we still need this delay ? */ + /* Ans : Even tasklet is used, Rx/Tx < 1 if we do not delay for a while right here. */ + RTMPusecDelay(500); + pAd->ate.TxDoneCount++; + pAd->RalinkCounters.KickTxCount++; + ASSERT(pAd->ate.QID == 0); + pAd->ate.TxAc0++; + } + } +#endif // RALINK_28xx_QA // + pAd->BulkOutComplete++; + + pAd->Counters8023.GoodTransmits++; + + /* Don't worry about the queue is empty or not. This function will check itself. */ + RTMPDeQueuePacket(pAd, TRUE, BulkOutPipeId, MAX_TX_PROCESS); + + /* In 28xx, SendTxWaitQueue ==> TxSwQueue */ +/* + if (pAd->SendTxWaitQueue[BulkOutPipeId].Number > 0) + { + RTMPDeQueuePacket(pAd, BulkOutPipeId); + } +*/ + } + else // STATUS_OTHER + { + pAd->BulkOutCompleteOther++; + + ATEDBGPRINT(RT_DEBUG_ERROR, ("BulkOutDataPacket Failed STATUS_OTHER = 0x%x . \n", Status)); + ATEDBGPRINT(RT_DEBUG_ERROR, (">>BulkOutReq=0x%lx, BulkOutComplete=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete)); + + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + /* In 28xx, RT_OID_USB_RESET_BULK_OUT ==> CMDTHREAD_RESET_BULK_OUT */ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + // Check + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + pAd->bulkResetPipeid = BulkOutPipeId; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + } + + + + if (atomic_read(&pAd->BulkOutRemained) > 0) + { + atomic_dec(&pAd->BulkOutRemained); + } + + // 1st - Transmit Success + OldValue = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart++; + + if (pAd->WlanCounters.TransmittedFragmentCount.u.LowPart < OldValue) + { + pAd->WlanCounters.TransmittedFragmentCount.u.HighPart++; + } + + if(((pAd->ContinBulkOut == TRUE ) ||(atomic_read(&pAd->BulkOutRemained) > 0)) && (pAd->ate.Mode & ATE_TXFRAME)) + { + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + } + else + { + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); +#ifdef RALINK_28xx_QA + pAd->ate.TxStatus = 0; +#endif // RALINK_28xx_QA // + } + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + // Always call Bulk routine, even reset bulk. + // The protection of rest bulk should be in BulkOut routine. + RTUSBKickBulkOut(pAd); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID ATE_RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId) +{ + PTX_CONTEXT pNullContext = &(pAd->NullContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + + ASSERT(BulkOutPipeId == 0); + + /* Build up the frame first. */ +// ATESetUpFrame(pAd, 0); + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + if (pAd->BulkOutPending[BulkOutPipeId] == TRUE) + { + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + + pAd->BulkOutPending[BulkOutPipeId] = TRUE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + // Increase Total transmit byte counter + pAd->RalinkCounters.OneSecTransmittedByteCount += pNullContext->BulkOutSize; + pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; + + // Clear ATE frame bulk out flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Init Tx context descriptor + pNullContext->IRPPending = TRUE; + RTUSBInitTxDesc(pAd, pNullContext, BulkOutPipeId, (usb_complete_t)ATE_RTUSBBulkOutDataPacketComplete); + pUrb = pNullContext->pUrb; + + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("ATE_RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); + return; + } + + pAd->BulkOutReq++; + return; + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID ATE_RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd) +{ + PRX_CONTEXT pRxContext; + UINT i; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("--->ATE_RTUSBCancelPendingBulkInIRP\n")); +#if 1 + for ( i = 0; i < (RX_RING_SIZE); i++) + { + pRxContext = &(pAd->RxContext[i]); + if(pRxContext->IRPPending == TRUE) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + pRxContext->IRPPending = FALSE; + pRxContext->InUse = FALSE; + //NdisInterlockedDecrement(&pAd->PendingRx); + //pAd->PendingRx--; + } + } +#else + for ( i = 0; i < (RX_RING_SIZE); i++) + { + pRxContext = &(pAd->RxContext[i]); + if(atomic_read(&pRxContext->IrpLock) == IRPLOCK_CANCELABLE) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + } + InterlockedExchange(&pRxContext->IrpLock, IRPLOCK_CANCE_START); + } +#endif // 1 // + ATEDBGPRINT(RT_DEBUG_TRACE, ("<---ATE_RTUSBCancelPendingBulkInIRP\n")); + return; +} +#endif // RT2870 // + +VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAd, i*2, value); + Data[i] = value; + i++; + } +} + +VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + value = Data[i]; + RT28xx_EEPROM_WRITE16(pAd, i*2, value); + i ++; + } +} +#ifdef RALINK_28xx_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader) +{ + // update counter first + if (pHeader != NULL) + { + if (pHeader->FC.Type == BTYPE_DATA) + { + if (pRxD->U2M) + pAd->ate.U2M++; + else + pAd->ate.OtherData++; + } + else if (pHeader->FC.Type == BTYPE_MGMT) + { + if (pHeader->FC.SubType == SUBTYPE_BEACON) + pAd->ate.Beacon++; + else + pAd->ate.OtherCount++; + } + else if (pHeader->FC.Type == BTYPE_CNTL) + { + pAd->ate.OtherCount++; + } + } + pAd->ate.RSSI0 = pRxWI->RSSI0; + pAd->ate.RSSI1 = pRxWI->RSSI1; + pAd->ate.RSSI2 = pRxWI->RSSI2; + pAd->ate.SNR0 = pRxWI->SNR0; + pAd->ate.SNR1 = pRxWI->SNR1; +} + +/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */ +#define RACFG_CMD_RF_WRITE_ALL 0x0000 +#define RACFG_CMD_E2PROM_READ16 0x0001 +#define RACFG_CMD_E2PROM_WRITE16 0x0002 +#define RACFG_CMD_E2PROM_READ_ALL 0x0003 +#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004 +#define RACFG_CMD_IO_READ 0x0005 +#define RACFG_CMD_IO_WRITE 0x0006 +#define RACFG_CMD_IO_READ_BULK 0x0007 +#define RACFG_CMD_BBP_READ8 0x0008 +#define RACFG_CMD_BBP_WRITE8 0x0009 +#define RACFG_CMD_BBP_READ_ALL 0x000a +#define RACFG_CMD_GET_COUNTER 0x000b +#define RACFG_CMD_CLEAR_COUNTER 0x000c + +#define RACFG_CMD_RSV1 0x000d +#define RACFG_CMD_RSV2 0x000e +#define RACFG_CMD_RSV3 0x000f + +#define RACFG_CMD_TX_START 0x0010 +#define RACFG_CMD_GET_TX_STATUS 0x0011 +#define RACFG_CMD_TX_STOP 0x0012 +#define RACFG_CMD_RX_START 0x0013 +#define RACFG_CMD_RX_STOP 0x0014 +#define RACFG_CMD_GET_NOISE_LEVEL 0x0015 + +#define RACFG_CMD_ATE_START 0x0080 +#define RACFG_CMD_ATE_STOP 0x0081 + +#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100 +#define RACFG_CMD_ATE_START_TX_CONT 0x0101 +#define RACFG_CMD_ATE_START_TX_FRAME 0x0102 +#define RACFG_CMD_ATE_SET_BW 0x0103 +#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104 +#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105 +#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106 +#define RACFG_CMD_ATE_GET_STATISTICS 0x0107 +#define RACFG_CMD_ATE_RESET_COUNTER 0x0108 +#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109 +#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a +#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b +#define RACFG_CMD_ATE_SET_CHANNEL 0x010c +#define RACFG_CMD_ATE_SET_ADDR1 0x010d +#define RACFG_CMD_ATE_SET_ADDR2 0x010e +#define RACFG_CMD_ATE_SET_ADDR3 0x010f +#define RACFG_CMD_ATE_SET_RATE 0x0110 +#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111 +#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112 +#define RACFG_CMD_ATE_START_RX_FRAME 0x0113 +#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114 +#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115 +#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116 +#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117 +#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118 +#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 +#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a + + + +#define A2Hex(_X, _p) \ +{ \ + UCHAR *p; \ + _X = 0; \ + p = _p; \ + while (((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= '0') && (*p <= '9'))) \ + { \ + if ((*p >= 'a') && (*p <= 'f')) \ + _X = _X * 16 + *p - 87; \ + else if ((*p >= 'A') && (*p <= 'F')) \ + _X = _X * 16 + *p - 55; \ + else if ((*p >= '0') && (*p <= '9')) \ + _X = _X * 16 + *p - 48; \ + p++; \ + } \ +} + + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len); + +#ifdef UCOS +int ate_copy_to_user( + IN PUCHAR payload, + IN PUCHAR msg, + IN INT len) +{ + memmove(payload, msg, len); + return 0; +} + +#undef copy_to_user +#define copy_to_user(x,y,z) ate_copy_to_user((PUCHAR)x, (PUCHAR)y, z) +#endif // UCOS // + +#define LEN_OF_ARG 16 + +VOID RtmpDoAte( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + unsigned short Command_Id; + struct ate_racfghdr *pRaCfg; + INT Status = NDIS_STATUS_SUCCESS; + + + + if((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL) + { + Status = -EINVAL; + return; + } + + NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr)); + + if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + kfree(pRaCfg); + return; + } + + + Command_Id = ntohs(pRaCfg->command_id); + + ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id)); + + switch (Command_Id) + { + // We will get this command when QA starts. + case RACFG_CMD_ATE_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n")); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_ATE_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START is done !\n")); + } + Set_ATE_Proc(pAdapter, "ATESTART"); + } + break; + + // We will get this command either QA is closed or ated is killed by user. + case RACFG_CMD_ATE_STOP: + { +#ifndef UCOS + INT32 ret; +#endif // !UCOS // + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n")); + + // Distinguish this command came from QA(via ated) + // or ate daemon according to the existence of pid in payload. + // No need to prepare feedback if this cmd came directly from ate daemon. + pRaCfg->length = ntohs(pRaCfg->length); + + if (pRaCfg->length == sizeof(pAdapter->ate.AtePid)) + { + // This command came from QA. + // Get the pid of ATE daemon. + memcpy((UCHAR *)&pAdapter->ate.AtePid, + (&pRaCfg->data[0]) - 2/* == &(pRaCfg->status) */, + sizeof(pAdapter->ate.AtePid)); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_STOP\n")); + Status = -EFAULT; + } + + // + // kill ATE daemon when leaving ATE mode. + // We must kill ATE daemon first before setting ATESTOP, + // or Microsoft will report sth. wrong. +#ifndef UCOS + ret = kill_proc(pAdapter->ate.AtePid, SIGTERM, 1); + if (ret) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to signal thread\n", pAdapter->net_dev->name)); + } +#endif // !UCOS // + } + +#ifdef UCOS + // Roger add to avoid error message after close QA + if (pAdapter->CSRBaseAddress == RT2860_CSR_ADDR) + { + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_AP_START\n")); + Status = -EFAULT; + } + } +#endif // UCOS // + + // AP might have in ATE_STOP mode due to cmd from QA. + if (ATE_ON(pAdapter)) + { + // Someone has killed ate daemon while QA GUI is still open. + Set_ATE_Proc(pAdapter, "ATESTOP"); + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n")); + } + } + break; + + case RACFG_CMD_RF_WRITE_ALL: + { + UINT32 R1, R2, R3, R4; + USHORT channel; + + memcpy(&R1, pRaCfg->data-2, 4); + memcpy(&R2, pRaCfg->data+2, 4); + memcpy(&R3, pRaCfg->data+6, 4); + memcpy(&R4, pRaCfg->data+10, 4); + memcpy(&channel, pRaCfg->data+14, 2); + + pAdapter->LatchRfRegs.R1 = ntohl(R1); + pAdapter->LatchRfRegs.R2 = ntohl(R2); + pAdapter->LatchRfRegs.R3 = ntohl(R3); + pAdapter->LatchRfRegs.R4 = ntohl(R4); + pAdapter->LatchRfRegs.Channel = ntohs(channel); + + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RF_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RF_WRITE_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ16: + { + USHORT offset, value, tmp; + + offset = ntohs(pRaCfg->status); + /* "tmp" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAdapter, offset, tmp); + value = tmp; + value = htons(value); + + ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value)); + + // prepare feedback + pRaCfg->length = htons(4); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 2); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("sizeof(struct ate_racfghdr) = %d\n", sizeof(struct ate_racfghdr))); + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE16: + { + USHORT offset, value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 2); + value = ntohs(value); + RT28xx_EEPROM_WRITE16(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_WRITE16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE); + + // prepare feedback + pRaCfg->length = htons(2+EEPROM_SIZE); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE); + memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_E2PROM_WRITE_ALL is done !\n")); + } + + } + break; + + case RACFG_CMD_IO_READ: + { + UINT32 offset; + UINT32 value; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset out. + offset &= 0x0000FFFF; + RTMP_IO_READ32(pAdapter, offset, &value); + value = htonl(value); + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 4); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ is done !\n")); + } + } + break; + + case RACFG_CMD_IO_WRITE: + { + UINT32 offset, value; + + memcpy(&offset, pRaCfg->data-2, 4); + memcpy(&value, pRaCfg->data+2, 4); + + offset = ntohl(offset); + + // We do not need the base address. + // So just extract out the offset. + offset &= 0x0000FFFF; + value = ntohl(value); + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value)); + RTMP_IO_WRITE32(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_WRITE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_WRITE is done !\n")); + } + } + break; + + case RACFG_CMD_IO_READ_BULK: + { + UINT32 offset; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset. + offset &= 0x0000FFFF; + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + if (len > 371) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("len is too large, make it smaller\n")); + pRaCfg->length = htons(2); + pRaCfg->status = htons(1); + break; + } + + RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes + + // prepare feedback + pRaCfg->length = htons(2+len*4);// unit in four bytes + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ_BULK is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ8: + { + USHORT offset; + UCHAR value; + + value = 0; + offset = ntohs(pRaCfg->status); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + // prepare feedback + pRaCfg->length = htons(3); + pRaCfg->status = htons(0); + pRaCfg->data[0] = value; + + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP value = %x\n", value)); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ8 is done !\n")); + } + } + break; + case RACFG_CMD_BBP_WRITE8: + { + USHORT offset; + UCHAR value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 1); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + + if ((offset == BBP_R1) || (offset == BBP_R3)) + { + SyncTxRxConfig(pAdapter, offset, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_WRITE8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_WRITE8 is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ_ALL: + { + USHORT j; + + for (j = 0; j < 137; j++) + { + pRaCfg->data[j] = 0; + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+137); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ_ALL is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_E2PROM_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + if (offset + len <= EEPROM_SIZE) + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len); + else + ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n")); + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_E2PROM_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_E2PROM_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_E2PROM_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_IO_WRITE_BULK: + { + UINT32 offset, i, value; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + for (i = 0; i < len; i += 4) + { + memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4); + printk("Write %x %x\n", offset + i, value); + RTMP_IO_WRITE32(pAdapter, (offset +i) & 0xffff, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_IO_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_IO_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_WRITE_BULK is done !\n")); + } + } + break; + +#ifdef CONFIG_RALINK_RT3052 + case RACFG_CMD_ATE_RF_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + RT30xxReadRFRegister(pAdapter, j, &pRaCfg->data[j - offset]); + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_RF_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + RT30xxWriteRFRegister(pAdapter, j, *value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_WRITE_BULK is done !\n")); + } + + } + break; +#endif + + + case RACFG_CMD_GET_NOISE_LEVEL: + { + UCHAR channel; + INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */ + + channel = (ntohs(pRaCfg->status) & 0x00FF); + CalNoiseLevel(pAdapter, channel, buffer); + memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10)); + + // prepare feedback + pRaCfg->length = htons(2 + (sizeof(INT32)*3*10)); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_NOISE_LEVEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_NOISE_LEVEL is done !\n")); + } + } + break; + + case RACFG_CMD_GET_COUNTER: + { + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4); + + pRaCfg->length = htons(2+60); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_COUNTER is done !\n")); + } + } + break; + + case RACFG_CMD_CLEAR_COUNTER: + { + pAdapter->ate.U2M = 0; + pAdapter->ate.OtherData = 0; + pAdapter->ate.Beacon = 0; + pAdapter->ate.OtherCount = 0; + pAdapter->ate.TxAc0 = 0; + pAdapter->ate.TxAc1 = 0; + pAdapter->ate.TxAc2 = 0; + pAdapter->ate.TxAc3 = 0; + pAdapter->ate.TxHCCA = 0; + pAdapter->ate.TxMgmt = 0; + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_CLEAR_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_CLEAR_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_TX_START: + { + USHORT *p; + USHORT err = 1; + UCHAR Bbp22Value = 0, Bbp24Value = 0; + + if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME)) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n")); + err = 2; + goto TX_START_ERROR; + } + else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME)) + { + int i = 0; + + while ((i++ < 10) && (pAdapter->ate.TxStatus != 0)) + { + RTMPusecDelay(5000); + } + + // force it to stop + pAdapter->ate.TxStatus = 0; + pAdapter->ate.TxDoneCount = 0; + //pAdapter->ate.Repeat = 0; + pAdapter->ate.bQATxStart = FALSE; + } + + // If pRaCfg->length == 0, this "RACFG_CMD_TX_START" is for Carrier test or Carrier Suppression. + if (ntohs(pRaCfg->length) != 0) + { + // Get frame info +#ifdef RT2870 + NdisMoveMemory(&pAdapter->ate.TxInfo, pRaCfg->data - 2, 4); +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR) &pAdapter->ate.TxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // +#endif // RT2870 // + + NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + + NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4); + pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount); + + p = (USHORT *)(&pRaCfg->data[22]); + //p = pRaCfg->data + 22; + // always use QID_AC_BE + pAdapter->ate.QID = 0; + p = (USHORT *)(&pRaCfg->data[24]); + //p = pRaCfg->data + 24; + pAdapter->ate.HLen = ntohs(*p); + + if (pAdapter->ate.HLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n")); + err = 3; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen); + + + pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28); + + if (pAdapter->ate.PLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n")); + err = 4; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen); + pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen; + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value); + + switch (Bbp22Value) + { + case BBP22_TXFRAME: + { + if (pAdapter->ate.TxCount == 0) + { + } + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXFRAME"); + } + break; + + case BBP22_TXCONT_OR_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n")); + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, 24, &Bbp24Value); + + switch (Bbp24Value) + { + case BBP24_TXCONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCONT"); + } + break; + + case BBP24_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n")); + pAdapter->ate.bQATxStart = TRUE; + pAdapter->ate.Mode |= ATE_TXCARRSUPP; + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + } + break; + + case BBP22_TXCARR: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCARR"); + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + + if (pAdapter->ate.bQATxStart == TRUE) + { + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() was failed in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_START is done !\n")); + } + break; + } + +TX_START_ERROR: + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(err); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("feedback of TX_START_ERROR is done !\n")); + } + } + break; + + case RACFG_CMD_GET_TX_STATUS: + { + UINT32 count; + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + count = htonl(pAdapter->ate.TxDoneCount); + NdisMoveMemory(pRaCfg->data, &count, 4); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_TX_STATUS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_TX_STATUS is done !\n")); + } + } + break; + + case RACFG_CMD_TX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n")); + + Set_ATE_Proc(pAdapter, "TXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_TX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_STOP is done !\n")); + } + } + break; + + case RACFG_CMD_RX_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + pAdapter->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + + case RACFG_CMD_RX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n")); + + Set_ATE_Proc(pAdapter, "RXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_STOP is done !\n")); + } + } + break; + + /* The following cases are for new ATE GUI(not QA). */ + /*==================================================*/ + case RACFG_CMD_ATE_START_TX_CARRIER: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n")); + + Set_ATE_Proc(pAdapter, "TXCARR"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CARRIER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CARRIER is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_CONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n")); + + Set_ATE_Proc(pAdapter, "TXCONT"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CONT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CONT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n")); + + Set_ATE_Proc(pAdapter, "TXFRAME"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_FRAME\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_FRAME is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_BW: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + + Set_ATE_TX_BW_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_BW\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_BW is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER0: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER0_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER0\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER0 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER1: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER1_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER1 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_FREQ_OFFSET: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_FREQ_OFFSET is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_GET_STATISTICS: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n")); + + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4); + + if (pAdapter->ate.RxAntennaSel == 0) + { + INT32 RSSI0 = 0; + INT32 RSSI1 = 0; + INT32 RSSI2 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta); + RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4); + pRaCfg->length = htons(2+52); + } + else + { + INT32 RSSI0 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + pRaCfg->length = htons(2+44); + } + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_GET_STATISTICS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_GET_STATISTICS is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_RESET_COUNTER: + { + SHORT value = 1; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n")); + + sprintf((PCHAR)str, "%d", value); + Set_ResetStatCounter_Proc(pAdapter, str); + + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RESET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RESET_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_SEL_TX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_TX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SEL_RX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_RX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_RX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_PREAMBLE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MODE_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_PREAMBLE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_PREAMBLE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_CHANNEL: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_CHANNEL_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_CHANNEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_CHANNEL is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR1: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR1 is done !\n (ADDR1 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr1[0], + pAdapter->ate.Addr1[1], pAdapter->ate.Addr1[2], pAdapter->ate.Addr1[3], pAdapter->ate.Addr1[4], pAdapter->ate.Addr1[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR2: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR2\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR2 is done !\n (ADDR2 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr2[0], + pAdapter->ate.Addr2[1], pAdapter->ate.Addr2[2], pAdapter->ate.Addr2[3], pAdapter->ate.Addr2[4], pAdapter->ate.Addr2[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR3: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR3\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR3 is done !\n (ADDR3 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr3[0], + pAdapter->ate.Addr3[1], pAdapter->ate.Addr3[2], pAdapter->ate.Addr3[3], pAdapter->ate.Addr3[4], pAdapter->ate.Addr3[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_RATE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MCS_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_RATE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_RATE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_LEN: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_LENGTH_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_LEN is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_COUNT: + { + USHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + { + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_COUNT_Proc(pAdapter, str); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_COUNT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_RX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + default: + break; + } + ASSERT(pRaCfg != NULL); + if (pRaCfg != NULL) + { + kfree(pRaCfg); + } + return; +} + +VOID BubbleSort(INT32 n, INT32 a[]) +{ + INT32 k, j, temp; + + for (k = n-1; k>0; k--) + { + for (j = 0; j<k; j++) + { + if(a[j] > a[j+1]) + { + temp = a[j]; + a[j]=a[j+1]; + a[j+1]=temp; + } + } + } +} + +VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10]) +{ + INT32 RSSI0, RSSI1, RSSI2; + CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset; + UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0; + UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0; + USHORT LNA_Gain = 0; + INT32 j = 0; + UCHAR Org_Channel = pAd->ate.Channel; + USHORT GainValue = 0, OffsetValue = 0; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value); + + //********************************************************************** + // Read the value of LNA gain and Rssi offset + //********************************************************************** + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue); + + // for Noise Level + if (channel <= 14) + { + LNA_Gain = GainValue & 0x00FF; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + else + { + LNA_Gain = (GainValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + //********************************************************************** + { + pAd->ate.Channel = channel; + ATEAsicSwitchChannel(pAd); + mdelay(5); + + data = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data); + mdelay(5); + + // Start Rx + pAd->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAd, "RXFRAME"); + + mdelay(5); + + for (j = 0; j < 10; j++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2); + + mdelay(10); + + // Calculate RSSI 0 + if (BbpR50Rssi0 == 0) + { + RSSI0 = -100; + } + else + { + RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset); + } + RSSI[0][j] = RSSI0; + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + // Calculate RSSI 1 + if (BbpR51Rssi1 == 0) + { + RSSI1 = -100; + } + else + { + RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset); + } + RSSI[1][j] = RSSI1; + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + // Calculate RSSI 2 + if (BbpR52Rssi2 == 0) + RSSI2 = -100; + else + RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset); + + RSSI[2][j] = RSSI2; + } + } + + // Stop Rx + Set_ATE_Proc(pAd, "RXSTOP"); + + mdelay(5); + + BubbleSort(10, RSSI[0]); // 1R + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + BubbleSort(10, RSSI[1]); + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + BubbleSort(10, RSSI[2]); + } + + } + + pAd->ate.Channel = Org_Channel; + ATEAsicSwitchChannel(pAd); + + // Restore original value + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value); + + return; +} + +BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value) +{ + UCHAR tmp = 0, bbp_data = 0; + + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + + /* confirm again */ + ASSERT(bbp_data == value); + + switch(offset) + { + case BBP_R1: + /* Need to sync. tx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3; + switch(tmp) + { + /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */ + case 2: + /* All */ + pAd->ate.TxAntennaSel = 0; + break; + /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */ + case 0: + /* Antenna one */ + pAd->ate.TxAntennaSel = 1; + break; + /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.TxAntennaSel = 2; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R1 */ + + case BBP_R3: + /* Need to sync. rx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */); + switch(tmp) + { + /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */ + case 3: + /* All */ + pAd->ate.RxAntennaSel = 0; + break; + /* The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, */ + /* unless the BBP R3 bit[4:3] = 2 */ + case 0: + /* Antenna one */ + pAd->ate.RxAntennaSel = 1; + tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3); + if (tmp == 2)// 3R + { + /* Default : All ADCs will be used by QA */ + pAd->ate.RxAntennaSel = 0; + } + break; + /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.RxAntennaSel = 2; + break; + /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */ + case 2: + /* Antenna three */ + pAd->ate.RxAntennaSel = 3; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R3 */ + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + + } + return TRUE; +} + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i, Value = 0; + ULONG *pDst, *pSrc; + UCHAR *p8; + + p8 = src; + pDst = (ULONG *) dst; + pSrc = (ULONG *) src; + + for (i = 0 ; i < (len/4); i++) + { + /* For alignment issue, we need a variable "Value". */ + memmove(&Value, pSrc, 4); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + if ((len % 4) != 0) + { + /* wish that it will never reach here */ + memmove(&Value, pSrc, (len % 4)); + Value = htonl(Value); + memmove(pDst, &Value, (len % 4)); + } +} + +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i; + UCHAR *pDst, *pSrc; + + pDst = dst; + pSrc = src; + + for (i = 0; i < (len/2); i++) + { + memmove(pDst, pSrc, 2); + *((USHORT *)pDst) = htons(*((USHORT *)pDst)); + pDst+=2; + pSrc+=2; + } + + if ((len % 2) != 0) + { + memmove(pDst, pSrc, 1); + } +} + +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len) +{ + UINT32 i, Value; + UINT32 *pDst, *pSrc; + + pDst = (UINT32 *) dst; + pSrc = (UINT32 *) src; + + for (i = 0 ; i < (len/4); i++) + { + RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + return; +} + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "TXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "RXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + |