| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /*! \file wlan_lib.c |
| * \brief Internal driver stack will export the required procedures here for GLUE Layer. |
| * |
| * This file contains all routines which are exported from MediaTek 802.11 Wireless |
| * LAN driver stack to GLUE Layer. |
| */ |
| |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| #include "mgmt/ais_fsm.h" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| /* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ |
| /* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ |
| const UINT_8 aucPriorityParam2TC[] = { |
| TC1_INDEX, |
| TC0_INDEX, |
| TC0_INDEX, |
| TC1_INDEX, |
| TC2_INDEX, |
| TC2_INDEX, |
| TC3_INDEX, |
| TC3_INDEX |
| }; |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| typedef struct _CODE_MAPPING_T { |
| UINT_32 u4RegisterValue; |
| INT_32 u4TxpowerOffset; |
| } CODE_MAPPING_T, *P_CODE_MAPPING_T; |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| BOOLEAN fgIsBusAccessFailed = FALSE; |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| #define SIGNED_EXTEND(n, _sValue) \ |
| (((_sValue) & BIT((n)-1)) ? ((_sValue) | BITS(n, 31)) : \ |
| ((_sValue) & ~BITS(n, 31))) |
| |
| /* TODO: Check */ |
| /* OID set handlers without the need to access HW register */ |
| PFN_OID_HANDLER_FUNC apfnOidSetHandlerWOHwAccess[] = { |
| wlanoidSetChannel, |
| wlanoidSetBeaconInterval, |
| wlanoidSetAtimWindow, |
| wlanoidSetFrequency, |
| }; |
| |
| /* TODO: Check */ |
| /* OID query handlers without the need to access HW register */ |
| PFN_OID_HANDLER_FUNC apfnOidQueryHandlerWOHwAccess[] = { |
| wlanoidQueryBssid, |
| wlanoidQuerySsid, |
| wlanoidQueryInfrastructureMode, |
| wlanoidQueryAuthMode, |
| wlanoidQueryEncryptionStatus, |
| wlanoidQueryPmkid, |
| wlanoidQueryNetworkTypeInUse, |
| wlanoidQueryBssidList, |
| wlanoidQueryAcpiDevicePowerState, |
| wlanoidQuerySupportedRates, |
| wlanoidQueryDesiredRates, |
| wlanoidQuery802dot11PowerSaveProfile, |
| wlanoidQueryBeaconInterval, |
| wlanoidQueryAtimWindow, |
| wlanoidQueryFrequency, |
| }; |
| |
| /* OID set handlers allowed in RF test mode */ |
| PFN_OID_HANDLER_FUNC apfnOidSetHandlerAllowedInRFTest[] = { |
| wlanoidRftestSetTestMode, |
| wlanoidRftestSetAbortTestMode, |
| wlanoidRftestSetAutoTest, |
| wlanoidSetMcrWrite, |
| wlanoidSetEepromWrite |
| }; |
| |
| /* OID query handlers allowed in RF test mode */ |
| PFN_OID_HANDLER_FUNC apfnOidQueryHandlerAllowedInRFTest[] = { |
| wlanoidRftestQueryAutoTest, |
| wlanoidQueryMcrRead, |
| wlanoidQueryEepromRead |
| } |
| |
| ; |
| |
| PFN_OID_HANDLER_FUNC apfnOidWOTimeoutCheck[] = { |
| wlanoidRftestSetTestMode, |
| wlanoidRftestSetAbortTestMode, |
| wlanoidSetAcpiDevicePowerState, |
| }; |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| #define COMPRESSION_OPTION_OFFSET 4 |
| #define COMPRESSION_OPTION_MASK BIT(4) |
| #endif |
| |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This is a private routine, which is used to check if HW access is needed |
| * for the OID query/ set handlers. |
| * |
| * \param[IN] pfnOidHandler Pointer to the OID handler. |
| * \param[IN] fgSetInfo It is a Set information handler. |
| * |
| * \retval TRUE This function needs HW access |
| * \retval FALSE This function does not need HW access |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) |
| { |
| PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; |
| UINT_32 i; |
| UINT_32 u4NumOfElem; |
| |
| if (fgSetInfo) { |
| apfnOidHandlerWOHwAccess = apfnOidSetHandlerWOHwAccess; |
| u4NumOfElem = sizeof(apfnOidSetHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); |
| } else { |
| apfnOidHandlerWOHwAccess = apfnOidQueryHandlerWOHwAccess; |
| u4NumOfElem = sizeof(apfnOidQueryHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); |
| } |
| |
| for (i = 0; i < u4NumOfElem; i++) { |
| if (apfnOidHandlerWOHwAccess[i] == pfnOidHandler) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } /* wlanIsHandlerNeedHwAccess */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is called to set flag for later handling card |
| * ejected event. |
| * |
| * \param[in] prAdapter Pointer to the Adapter structure. |
| * |
| * \return (none) |
| * |
| * \note When surprised removal happens, Glue layer should invoke this |
| * function to notify WPDD not to do any hw access. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanCardEjected(IN P_ADAPTER_T prAdapter) |
| { |
| DEBUGFUNC("wlanCardEjected"); |
| /* INITLOG(("\n")); */ |
| |
| ASSERT(prAdapter); |
| |
| /* mark that the card is being ejected, NDIS will shut us down soon */ |
| nicTxRelease(prAdapter, FALSE); |
| |
| } /* wlanCardEjected */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Create adapter object |
| * |
| * \param prAdapter This routine is call to allocate the driver software objects. |
| * If fails, return NULL. |
| * \retval NULL If it fails, NULL is returned. |
| * \retval NOT NULL If the adapter was initialized successfully. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo) |
| { |
| P_ADAPTER_T prAdpater = (P_ADAPTER_T) NULL; |
| |
| DEBUGFUNC("wlanAdapterCreate"); |
| |
| do { |
| prAdpater = (P_ADAPTER_T) kalMemAlloc(sizeof(ADAPTER_T), VIR_MEM_TYPE); |
| |
| if (!prAdpater) { |
| DBGLOG(INIT, ERROR, "Allocate ADAPTER memory ==> FAILED\n"); |
| break; |
| } |
| #if QM_TEST_MODE |
| g_rQM.prAdapter = prAdpater; |
| #endif |
| kalMemZero(prAdpater, sizeof(ADAPTER_T)); |
| prAdpater->prGlueInfo = prGlueInfo; |
| |
| } while (FALSE); |
| |
| return prAdpater; |
| } /* wlanAdapterCreate */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Destroy adapter object |
| * |
| * \param prAdapter This routine is call to destroy the driver software objects. |
| * If fails, return NULL. |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter) |
| { |
| |
| if (!prAdapter) |
| return; |
| |
| kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(ADAPTER_T)); |
| |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Initialize the adapter. The sequence is |
| * 1. Disable interrupt |
| * 2. Read adapter configuration from EEPROM and registry, verify chip ID. |
| * 3. Create NIC Tx/Rx resource. |
| * 4. Initialize the chip |
| * 5. Initialize the protocol |
| * 6. Enable Interrupt |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval WLAN_STATUS_SUCCESS: Success |
| * \retval WLAN_STATUS_FAILURE: Failed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanAdapterStart(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) |
| { |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| UINT_32 i; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanAdapterStart"); |
| |
| /* 4 <0> Reset variables in ADAPTER_T */ |
| /* prAdapter->fgIsFwOwn = TRUE; */ |
| prAdapter->fgIsEnterD3ReqIssued = FALSE; |
| |
| prAdapter->u4OwnFailedCount = 0; |
| prAdapter->u4OwnFailedLogCount = 0; |
| |
| QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); |
| #if CFG_SUPPORT_MULTITHREAD |
| QUEUE_INITIALIZE(&prAdapter->rTxCmdQueue); |
| QUEUE_INITIALIZE(&prAdapter->rTxCmdDoneQueue); |
| #if CFG_FIX_2_TX_PORT |
| QUEUE_INITIALIZE(&prAdapter->rTxP0Queue); |
| QUEUE_INITIALIZE(&prAdapter->rTxP1Queue); |
| #else |
| for (i = 0; i < TX_PORT_NUM; i++) |
| QUEUE_INITIALIZE(&prAdapter->rTxPQueue[i]); |
| #endif |
| QUEUE_INITIALIZE(&prAdapter->rRxQueue); |
| QUEUE_INITIALIZE(&prAdapter->rTxDataDoneQueue); |
| #endif |
| |
| /* Initialize rWlanInfo */ |
| kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); |
| |
| /* Initialize aprBssInfo[]. |
| * Important: index shall be same when mapping between aprBssInfo[] |
| * and arBssInfoPool[]. rP2pDevInfo is indexed to final one. |
| */ |
| for (i = 0; i < BSS_INFO_NUM; i++) |
| prAdapter->aprBssInfo[i] = &prAdapter->rWifiVar.arBssInfoPool[i]; |
| prAdapter->aprBssInfo[P2P_DEV_BSS_INDEX] = &prAdapter->rWifiVar.rP2pDevInfo; |
| |
| /* 4 <0.1> reset fgIsBusAccessFailed */ |
| fgIsBusAccessFailed = FALSE; |
| |
| do { |
| u4Status = nicAllocateAdapterMemory(prAdapter); |
| if (u4Status != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; |
| |
| DBGLOG(INIT, INFO, "wlanAdapterStart(): Acquiring LP-OWN\n"); |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| DBGLOG(INIT, INFO, "wlanAdapterStart(): Acquiring LP-OWN-end\n"); |
| |
| #if (CFG_ENABLE_FULL_PM == 0) |
| nicpmSetDriverOwn(prAdapter); |
| #endif |
| |
| if (prAdapter->fgIsFwOwn == TRUE) { |
| DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| /* 4 <1> Initialize the Adapter */ |
| u4Status = nicInitializeAdapter(prAdapter); |
| if (u4Status != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| /* 4 <2.1> Initialize System Service (MGMT Memory pool and STA_REC) */ |
| nicInitSystemService(prAdapter); |
| |
| /* 4 <2.2> Initialize Feature Options */ |
| wlanInitFeatureOption(prAdapter); |
| #if CFG_SUPPORT_MTK_SYNERGY |
| if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) { |
| if (prRegInfo->prNvramSettings->u2FeatureReserved & BIT(MTK_FEATURE_2G_256QAM_DISABLED)) |
| prAdapter->rWifiVar.aucMtkFeature[0] &= ~(MTK_SYNERGY_CAP_SUPPORT_24G_MCS89); |
| } |
| #endif |
| |
| /* 4 <2.3> Overwrite debug level settings */ |
| wlanCfgSetDebugLevel(prAdapter); |
| |
| /* 4 <3> Initialize Tx */ |
| nicTxInitialize(prAdapter); |
| wlanDefTxPowerCfg(prAdapter); |
| |
| /* 4 <4> Initialize Rx */ |
| nicRxInitialize(prAdapter); |
| |
| /* 4 <5> HIF SW info initialize */ |
| halHifSwInfoInit(prAdapter); |
| |
| /* 4 <6> Enable HIF cut-through to N9 mode, not visiting CR4 */ |
| HAL_ENABLE_FWDL(prAdapter, TRUE); |
| |
| /* 4 <7> Get ECO Version */ |
| wlanSetChipEcoInfo(prAdapter); |
| |
| #if CFG_ENABLE_FW_DOWNLOAD |
| /* 4 <8> FW/patch download */ |
| |
| /* 1. disable interrupt, download is done by polling mode only */ |
| nicDisableInterrupt(prAdapter); |
| |
| /* 2. Initialize Tx Resource to fw download state */ |
| nicTxInitResetResource(prAdapter); |
| |
| u4Status = wlanDownloadFW(prAdapter); |
| |
| if (u4Status != WLAN_STATUS_SUCCESS) |
| break; |
| #endif |
| |
| DBGLOG(INIT, INFO, "Waiting for Ready bit..\n"); |
| |
| /* 4 <9> check Wi-Fi FW asserts ready bit */ |
| u4Status = wlanCheckWifiFunc(prAdapter, TRUE); |
| |
| if (u4Status == WLAN_STATUS_SUCCESS) { |
| #if defined(_HIF_SDIO) |
| UINT_32 u4WHISR = 0; |
| UINT_16 au2TxCount[16]; |
| |
| /* 1. reset interrupt status */ |
| HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); |
| if (HAL_IS_TX_DONE_INTR(u4WHISR)) |
| HAL_READ_TX_RELEASED_COUNT(prAdapter, au2TxCount); |
| #endif |
| /* Set FW download success flag */ |
| prAdapter->fgIsFwDownloaded = TRUE; |
| |
| /* 2. query & reset TX Resource for normal operation */ |
| wlanQueryNicResourceInformation(prAdapter); |
| |
| #if (CFG_SUPPORT_NIC_CAPABILITY == 1) |
| |
| /* 2.9 Workaround for Capability CMD packet lost issue */ |
| DBGLOG(INIT, WARN, "Send a Dummy CMD as workaround\n"); |
| wlanSendDummyCmd(prAdapter, TRUE); |
| |
| /* 3. query for NIC capability */ |
| wlanQueryNicCapability(prAdapter); |
| |
| /* 4. query for NIC capability V2 */ |
| wlanQueryNicCapabilityV2(prAdapter); |
| |
| /* 5. reset TX Resource for normal operation |
| * based on the information reported from CMD_NicCapabilityV2 |
| */ |
| wlanUpdateNicResourceInformation(prAdapter); |
| |
| wlanPrintVersion(prAdapter); |
| #endif |
| |
| /* 6. update basic configuration */ |
| wlanUpdateBasicConfig(prAdapter); |
| |
| /* 7. Override network address */ |
| wlanUpdateNetworkAddress(prAdapter); |
| |
| /* 8. Apply Network Address */ |
| nicApplyNetworkAddress(prAdapter); |
| |
| /* 9. indicate disconnection as default status */ |
| kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); |
| } |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| |
| if (u4Status != WLAN_STATUS_SUCCESS) |
| break; |
| |
| /* OID timeout timer initialize */ |
| cnmTimerInitTimer(prAdapter, |
| &prAdapter->rOidTimeoutTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, (ULONG) NULL); |
| |
| prAdapter->ucOidTimeoutCount = 0; |
| |
| prAdapter->fgIsChipNoAck = FALSE; |
| |
| /* Return Indicated Rfb list timer */ |
| cnmTimerInitTimer(prAdapter, |
| &prAdapter->rPacketDelaySetupTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) wlanReturnPacketDelaySetupTimeout, (ULONG) NULL); |
| |
| /* Power state initialization */ |
| prAdapter->fgWiFiInSleepyState = FALSE; |
| prAdapter->rAcpiState = ACPI_STATE_D0; |
| |
| #if 0 |
| /* Online scan option */ |
| if (prRegInfo->fgDisOnlineScan == 0) |
| prAdapter->fgEnOnlineScan = TRUE; |
| else |
| prAdapter->fgEnOnlineScan = FALSE; |
| |
| /* Beacon lost detection option */ |
| if (prRegInfo->fgDisBcnLostDetection != 0) |
| prAdapter->fgDisBcnLostDetection = TRUE; |
| #else |
| if (prAdapter->rWifiVar.fgDisOnlineScan == 0) |
| prAdapter->fgEnOnlineScan = TRUE; |
| else |
| prAdapter->fgEnOnlineScan = FALSE; |
| |
| /* Beacon lost detection option */ |
| if (prAdapter->rWifiVar.fgDisBcnLostDetection != 0) |
| prAdapter->fgDisBcnLostDetection = TRUE; |
| #endif |
| |
| /* Load compile time constant */ |
| prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; |
| prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; |
| |
| #if 1 /* set PM parameters */ |
| prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; |
| #if 0 |
| prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; |
| prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; |
| prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; |
| #else |
| prAdapter->fgEnArpFilter = prAdapter->rWifiVar.fgEnArpFilter; |
| prAdapter->u4UapsdAcBmp = prAdapter->rWifiVar.u4UapsdAcBmp; |
| prAdapter->u4MaxSpLen = prAdapter->rWifiVar.u4MaxSpLen; |
| #endif |
| DBGLOG(INIT, TRACE, "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", |
| prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, prAdapter->u4MaxSpLen); |
| |
| prAdapter->fgEnCtiaPowerMode = FALSE; |
| |
| #endif |
| |
| /* MGMT Initialization */ |
| nicInitMGMT(prAdapter, prRegInfo); |
| |
| /* Enable WZC Disassociation */ |
| prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; |
| |
| /* Apply Rate Setting */ |
| if ((ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate) < FIXED_RATE_NUM) |
| prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate); |
| else |
| prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; |
| |
| if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) { |
| /* Enable Auto (Long/Short) Preamble */ |
| prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; |
| } else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && |
| prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) |
| || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && |
| prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) { |
| /* Force Short Preamble */ |
| prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; |
| } else { |
| /* Force Long Preamble */ |
| prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; |
| } |
| |
| /* Disable Hidden SSID Join */ |
| prAdapter->rWifiVar.fgEnableJoinToHiddenSSID = FALSE; |
| |
| /* Enable Short Slot Time */ |
| prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable = TRUE; |
| |
| /* configure available PHY type set */ |
| nicSetAvailablePhyTypeSet(prAdapter); |
| |
| #if 0 /* Marked for MT6630 */ |
| #if 1 /* set PM parameters */ |
| { |
| #if CFG_SUPPORT_PWR_MGT |
| prAdapter->u4PowerMode = prRegInfo->u4PowerMode; |
| #if CFG_ENABLE_WIFI_DIRECT |
| prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = |
| NETWORK_TYPE_P2P_INDEX; |
| prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; |
| #endif |
| #else |
| prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; |
| #endif |
| |
| nicConfigPowerSaveProfile(prAdapter, |
| prAdapter->prAisBssInfo->ucBssIndex, prAdapter->u4PowerMode, FALSE); |
| } |
| |
| #endif |
| #endif |
| /* Check if it is disabled by hardware */ |
| if (prAdapter->fgIsHw5GBandDisabled) |
| prAdapter->fgEnable5GBand = FALSE; |
| else |
| prAdapter->fgEnable5GBand = TRUE; |
| |
| #if CFG_SUPPORT_NVRAM |
| /* load manufacture data */ |
| if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) |
| wlanLoadManufactureData(prAdapter, prRegInfo); |
| else |
| DBGLOG(INIT, WARN, "%s: load manufacture data fail\n", __func__); |
| #endif |
| |
| #if 0 |
| /* Update Auto rate parameters in FW */ |
| nicRlmArUpdateParms(prAdapter, |
| prRegInfo->u4ArSysParam0, |
| prRegInfo->u4ArSysParam1, prRegInfo->u4ArSysParam2, prRegInfo->u4ArSysParam3); |
| #endif |
| |
| #if CFG_SUPPORT_DBDC |
| /* Update DBDC default setting */ |
| cnmInitDbdcSetting(prAdapter); |
| #endif /*CFG_SUPPORT_DBDC*/ |
| } while (FALSE); |
| |
| if (u4Status == WLAN_STATUS_SUCCESS) { |
| |
| /* restore to hardware default */ |
| HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); |
| HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); |
| |
| /* Enable interrupt */ |
| nicEnableInterrupt(prAdapter); |
| |
| } else { |
| /* release allocated memory */ |
| nicReleaseAdapterMemory(prAdapter); |
| } |
| |
| return u4Status; |
| } /* wlanAdapterStart */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Uninitialize the adapter |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval WLAN_STATUS_SUCCESS: Success |
| * \retval WLAN_STATUS_FAILURE: Failed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter) |
| { |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| |
| /* MGMT - unitialization */ |
| nicUninitMGMT(prAdapter); |
| |
| /* Release all CMD/MGMT/SEC frame in command queue */ |
| kalClearCommandQueue(prAdapter->prGlueInfo); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| |
| /* Flush all items in queues for multi-thread */ |
| wlanClearTxCommandQueue(prAdapter); |
| |
| wlanClearTxCommandDoneQueue(prAdapter); |
| |
| wlanClearDataQueue(prAdapter); |
| |
| wlanClearRxToOsQueue(prAdapter); |
| |
| #endif |
| /* Hif power off wifi */ |
| #if 1 |
| wlanPowerOffWifi(prAdapter); |
| #else |
| if (prAdapter->rAcpiState == ACPI_STATE_D0 && |
| !wlanIsChipNoAck(prAdapter) && !kalIsCardRemoved(prAdapter->prGlueInfo)) { |
| /* 0. Disable interrupt, this can be done without Driver own */ |
| nicDisableInterrupt(prAdapter); |
| |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| |
| /* 1. Set CMD to FW to tell WIFI to stop (enter power off state) */ |
| if (prAdapter->fgIsFwOwn == FALSE && wlanSendNicPowerCtrlCmd(prAdapter, 1) == WLAN_STATUS_SUCCESS) { |
| UINT_32 i; |
| /* 2. Clear pending interrupt */ |
| i = 0; |
| while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { |
| i++; |
| }; |
| |
| /* 3. Wait til RDY bit has been cleaerd */ |
| wlanCheckWifiFunc(prAdapter, FALSE); |
| } |
| #if !CFG_ENABLE_FULL_PM |
| /* 4. Set Onwership to F/W */ |
| nicpmSetFWOwn(prAdapter, FALSE); |
| #endif |
| |
| #if CFG_FORCE_RESET_UNDER_BUS_ERROR |
| if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == TRUE) { |
| /* force acquire firmware own */ |
| kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); |
| |
| /* delay for 10ms */ |
| kalMdelay(10); |
| |
| /* force firmware reset via software interrupt */ |
| kalDevRegWrite(prAdapter->prGlueInfo, MCR_WSICR, WSICR_H2D_SW_INT_SET); |
| |
| /* force release firmware own */ |
| kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); |
| } |
| #endif |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| } |
| #endif |
| |
| nicRxUninitialize(prAdapter); |
| |
| nicTxRelease(prAdapter, FALSE); |
| |
| /* System Service Uninitialization */ |
| nicUninitSystemService(prAdapter); |
| |
| nicReleaseAdapterMemory(prAdapter); |
| |
| #if defined(_HIF_SPI) |
| /* Note: restore the SPI Mode Select from 32 bit to default */ |
| nicRestoreSpiDefMode(prAdapter); |
| #endif |
| |
| return u4Status; |
| } /* wlanAdapterStop */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called by ISR (interrupt). |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval TRUE: NIC's interrupt |
| * \retval FALSE: Not NIC's interrupt |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOL wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl) |
| { |
| ASSERT(prAdapter); |
| |
| if (fgGlobalIntrCtrl) { |
| nicDisableInterrupt(prAdapter); |
| |
| /* wlanIST(prAdapter); */ |
| } |
| |
| return TRUE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called by IST (task_let). |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanIST(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| |
| nicProcessIST(prAdapter); |
| #if defined(CONFIG_ANDROID) && (CFG_ENABLE_WAKE_LOCK) |
| if (KAL_WAKE_LOCK_ACTIVE(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock)) |
| KAL_WAKE_UNLOCK(prAdapter, &prAdapter->prGlueInfo->rIntrWakeLock); |
| #endif |
| nicEnableInterrupt(prAdapter); |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| |
| |
| } |
| |
| VOID wlanClearPendingInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 i; |
| |
| i = 0; |
| while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { |
| i++; |
| }; |
| } |
| |
| WLAN_STATUS wlanCheckWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgRdyChk) |
| { |
| BOOLEAN fgResult, fgTimeout; |
| UINT_32 u4Result, u4Status, u4StartTime, u4CurTime; |
| |
| u4StartTime = kalGetTimeTick(); |
| fgTimeout = FALSE; |
| |
| #if defined(_HIF_USB) |
| if (prAdapter->prGlueInfo->rHifInfo.state != USB_STATE_LINK_UP) |
| return WLAN_STATUS_FAILURE; |
| #endif |
| |
| while (TRUE) { |
| if (fgRdyChk) |
| HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgResult); |
| else { |
| HAL_WIFI_FUNC_OFF_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgResult); |
| |
| if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) |
| DBGLOG(INIT, INFO, "Handle pending interrupt\n"); |
| } |
| u4CurTime = kalGetTimeTick(); |
| |
| if (CHECK_FOR_TIMEOUT(u4CurTime, u4StartTime, |
| CFG_RESPONSE_POLLING_TIMEOUT * CFG_RESPONSE_POLLING_DELAY)) { |
| |
| fgTimeout = TRUE; |
| } |
| |
| if (fgResult) { |
| if (fgRdyChk) |
| DBGLOG(INIT, INFO, "Ready bit asserted\n"); |
| else |
| DBGLOG(INIT, INFO, "Wi-Fi power off done!\n"); |
| |
| u4Status = WLAN_STATUS_SUCCESS; |
| |
| break; |
| } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| |
| break; |
| } else if (fgTimeout) { |
| HAL_WIFI_FUNC_GET_STATUS(prAdapter, u4Result); |
| DBGLOG(INIT, ERROR, "Waiting for %s: Timeout, Status=0x%08x\n", |
| fgRdyChk ? "ready bit" : "power off", u4Result); |
| |
| u4Status = WLAN_STATUS_FAILURE; |
| |
| break; |
| } |
| kalMsleep(CFG_RESPONSE_POLLING_DELAY); |
| |
| } |
| |
| return u4Status; |
| } |
| |
| WLAN_STATUS wlanPowerOffWifi(IN P_ADAPTER_T prAdapter) |
| { |
| WLAN_STATUS rStatus; |
| /* Hif power off wifi */ |
| rStatus = halHifPowerOffWifi(prAdapter); |
| prAdapter->fgIsCr4FwDownloaded = FALSE; |
| |
| return rStatus; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will check command queue to find out if any could be dequeued |
| * and/or send to HIF to MT6620 |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param prCmdQue Pointer of Command Queue (in Glue Layer) |
| * |
| * \retval WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue) |
| { |
| WLAN_STATUS rStatus; |
| QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; |
| P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; |
| P_QUE_ENTRY_T prQueueEntry; |
| P_CMD_INFO_T prCmdInfo; |
| P_MSDU_INFO_T prMsduInfo; |
| ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| ASSERT(prCmdQue); |
| |
| prTempCmdQue = &rTempCmdQue; |
| prMergeCmdQue = &rMergeCmdQue; |
| prStandInCmdQue = &rStandInCmdQue; |
| |
| QUEUE_INITIALIZE(prTempCmdQue); |
| QUEUE_INITIALIZE(prMergeCmdQue); |
| QUEUE_INITIALIZE(prStandInCmdQue); |
| |
| /* 4 <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); |
| QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); |
| |
| /* 4 <2> Dequeue from head and check it is able to be sent */ |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| switch (prCmdInfo->eCmdType) { |
| case COMMAND_TYPE_GENERAL_IOCTL: |
| case COMMAND_TYPE_NETWORK_IOCTL: |
| /* command packet will be always sent */ |
| eFrameAction = FRAME_ACTION_TX_PKT; |
| break; |
| |
| case COMMAND_TYPE_SECURITY_FRAME: |
| /* inquire with QM */ |
| prMsduInfo = prCmdInfo->prMsduInfo; |
| |
| eFrameAction = qmGetFrameAction(prAdapter, prMsduInfo->ucBssIndex, |
| prMsduInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X, |
| prCmdInfo->u2InfoBufLen); |
| break; |
| |
| case COMMAND_TYPE_MANAGEMENT_FRAME: |
| /* inquire with QM */ |
| prMsduInfo = prCmdInfo->prMsduInfo; |
| |
| eFrameAction = qmGetFrameAction(prAdapter, prMsduInfo->ucBssIndex, |
| prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU, |
| prMsduInfo->u2FrameLength); |
| break; |
| |
| default: |
| ASSERT(0); |
| break; |
| } |
| |
| /* 4 <3> handling upon dequeue result */ |
| if (eFrameAction == FRAME_ACTION_DROP_PKT) { |
| DBGLOG(INIT, INFO, "DROP CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", |
| prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); |
| wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_DROPPED_IN_DRIVER); |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { |
| DBGLOG(INIT, TRACE, "QUE back CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", |
| prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); |
| |
| QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); |
| } else if (eFrameAction == FRAME_ACTION_TX_PKT) { |
| /* 4 <4> Send the command */ |
| #if CFG_SUPPORT_MULTITHREAD |
| rStatus = wlanSendCommandMthread(prAdapter, prCmdInfo); |
| |
| if (rStatus == WLAN_STATUS_RESOURCES) { |
| /* no more TC4 resource for further transmission */ |
| DBGLOG(INIT, WARN, "NO Res CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", |
| prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); |
| |
| set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(prAdapter->prGlueInfo->ulFlag)); |
| |
| QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); |
| break; |
| } else if (rStatus == WLAN_STATUS_PENDING) { |
| /* Do nothing */ |
| /* Do nothing */ |
| } else if (rStatus == WLAN_STATUS_SUCCESS) { |
| /* Do nothing */ |
| /* Do nothing */ |
| } else { |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->fgIsOid) { |
| kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, |
| prCmdInfo->u4SetInfoLen, rStatus); |
| } |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| |
| #else |
| rStatus = wlanSendCommand(prAdapter, prCmdInfo); |
| |
| if (rStatus == WLAN_STATUS_RESOURCES) { |
| /* no more TC4 resource for further transmission */ |
| |
| DBGLOG(INIT, WARN, "NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u]\n", |
| prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); |
| |
| QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); |
| break; |
| } else if (rStatus == WLAN_STATUS_PENDING) { |
| /* command packet which needs further handling upon response */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), prQueueEntry); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| } else { |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (rStatus == WLAN_STATUS_SUCCESS) { |
| if (prCmdInfo->pfCmdDoneHandler) { |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, |
| prCmdInfo->pucInfoBuffer); |
| } |
| } else { |
| if (prCmdInfo->fgIsOid) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, rStatus); |
| } |
| } |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } |
| #endif |
| } else { |
| ASSERT(0); |
| } |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| /* 4 <3> Merge back to original queue */ |
| /* 4 <3.1> Merge prMergeCmdQue & prTempCmdQue */ |
| QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prTempCmdQue); |
| |
| /* 4 <3.2> Move prCmdQue to prStandInQue, due to prCmdQue might differ due to incoming 802.1X frames */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); |
| QUEUE_MOVE_ALL(prStandInCmdQue, prCmdQue); |
| |
| /* 4 <3.3> concatenate prStandInQue to prMergeCmdQue */ |
| QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prStandInCmdQue); |
| |
| /* 4 <3.4> then move prMergeCmdQue to prCmdQue */ |
| QUEUE_MOVE_ALL(prCmdQue, prMergeCmdQue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| kalSetTxCmdEvent2Hif(prAdapter->prGlueInfo); |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } /* end of wlanProcessCommandQueue() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will take CMD_INFO_T which carry some information of |
| * incoming OID and notify the NIC_TX to send CMD. |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param prCmdInfo Pointer of P_CMD_INFO_T |
| * |
| * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. |
| * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous |
| * frame finishing their transmission. |
| * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| ASSERT(prCmdInfo); |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| do { |
| /* <0> card removal check */ |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| rStatus = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| /* <1.1> Assign Traffic Class(TC) */ |
| ucTC = nicTxGetCmdResourceType(prCmdInfo); |
| |
| /* <1.2> Check if pending packet or resource was exhausted */ |
| rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo), TRUE); |
| if (rStatus == WLAN_STATUS_RESOURCES) { |
| DBGLOG(INIT, INFO, "NO Resource:%d\n", ucTC); |
| break; |
| } |
| /* <1.3> Forward CMD_INFO_T to NIC Layer */ |
| rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); |
| |
| /* <1.4> Set Pending in response to Query Command/Need Response */ |
| if (rStatus == WLAN_STATUS_SUCCESS) { |
| if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) |
| rStatus = WLAN_STATUS_PENDING; |
| } |
| |
| } while (FALSE); |
| |
| return rStatus; |
| } /* end of wlanSendCommand() */ |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will take CMD_INFO_T which carry some information of |
| * incoming OID and notify the NIC_TX to send CMD. |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param prCmdInfo Pointer of P_CMD_INFO_T |
| * |
| * \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. |
| * \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous |
| * frame finishing their transmission. |
| * \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanSendCommandMthread(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| ASSERT(prCmdInfo); |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| prTempCmdQue = &rTempCmdQue; |
| QUEUE_INITIALIZE(prTempCmdQue); |
| |
| do { |
| /* <0> card removal check */ |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| rStatus = WLAN_STATUS_FAILURE; |
| break; |
| } |
| /* <1> Normal case of sending CMD Packet */ |
| /* <1.1> Assign Traffic Class(TC) */ |
| ucTC = nicTxGetCmdResourceType(prCmdInfo); |
| |
| /* <1.2> Check if pending packet or resource was exhausted */ |
| rStatus = nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo), TRUE); |
| if (rStatus == WLAN_STATUS_RESOURCES) { |
| #if 0 |
| DBGLOG(INIT, WARN, "%s: NO Resource for CMD TYPE[%u] ID[0x%02X] SEQ[%u] TC[%u]\n", |
| __func__, prCmdInfo->eCmdType, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, ucTC); |
| #endif |
| break; |
| } |
| |
| /* Process to pending command queue firest */ |
| if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { |
| /* command packet which needs further handling upon response */ |
| /* |
| * KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| * QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T)prCmdInfo); |
| * KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| */ |
| } |
| QUEUE_INSERT_TAIL(prTempCmdQue, (P_QUE_ENTRY_T) prCmdInfo); |
| |
| /* <1.4> Set Pending in response to Query Command/Need Response */ |
| if (rStatus == WLAN_STATUS_SUCCESS) { |
| if ((!prCmdInfo->fgSetQuery) || |
| (prCmdInfo->fgNeedResp) || (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME)) { |
| rStatus = WLAN_STATUS_PENDING; |
| } |
| } |
| } while (FALSE); |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| QUEUE_CONCATENATE_QUEUES(&(prAdapter->rTxCmdQueue), prTempCmdQue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| |
| return rStatus; |
| } /* end of wlanSendCommandMthread() */ |
| |
| VOID wlanTxCmdDoneCb(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { |
| #if 0 |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| QUEUE_INSERT_TAIL(&prAdapter->rPendingCmdQueue, (P_QUE_ENTRY_T) prCmdInfo); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| #endif |
| } else { |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| QUEUE_INSERT_TAIL(&prAdapter->rTxCmdDoneQueue, (P_QUE_ENTRY_T) prCmdInfo); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| } |
| |
| /* call tx thread to work */ |
| set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prAdapter->prGlueInfo->ulFlag); |
| wake_up_interruptible(&prAdapter->prGlueInfo->waitq); |
| } |
| |
| WLAN_STATUS wlanTxCmdMthread(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue; |
| QUE_T rTempCmdDoneQue; |
| P_QUE_T prTempCmdDoneQue; |
| P_QUE_ENTRY_T prQueueEntry; |
| P_CMD_INFO_T prCmdInfo; |
| /* P_CMD_ACCESS_REG prCmdAccessReg; |
| * P_CMD_ACCESS_REG prEventAccessReg; |
| * UINT_32 u4Address; |
| */ |
| UINT_32 u4TxDoneQueueSize; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| |
| prTempCmdQue = &rTempCmdQue; |
| QUEUE_INITIALIZE(prTempCmdQue); |
| |
| prTempCmdDoneQue = &rTempCmdDoneQue; |
| QUEUE_INITIALIZE(prTempCmdDoneQue); |
| |
| KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); |
| |
| /* TX Command Queue */ |
| /* 4 <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| |
| /* 4 <2> Dequeue from head and check it is able to be sent */ |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| prCmdInfo->pfHifTxCmdDoneCb = wlanTxCmdDoneCb; |
| |
| if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) { |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), (P_QUE_ENTRY_T) prCmdInfo); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| } else { |
| QUEUE_INSERT_TAIL(prTempCmdDoneQue, prQueueEntry); |
| } |
| |
| nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX); |
| |
| /* DBGLOG(INIT, INFO, |
| * ("==> TX CMD QID: %d (Q:%d)\n", prCmdInfo->ucCID, prTempCmdQue->u4NumElem)); |
| */ |
| |
| GLUE_DEC_REF_CNT(prAdapter->prGlueInfo->i4TxPendingCmdNum); |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| QUEUE_CONCATENATE_QUEUES(&prAdapter->rTxCmdDoneQueue, prTempCmdDoneQue); |
| u4TxDoneQueueSize = prAdapter->rTxCmdDoneQueue.u4NumElem; |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); |
| |
| if (u4TxDoneQueueSize > 0) { |
| /* call tx thread to work */ |
| set_bit(GLUE_FLAG_TX_CMD_DONE_BIT, &prAdapter->prGlueInfo->ulFlag); |
| wake_up_interruptible(&prAdapter->prGlueInfo->waitq); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS wlanTxCmdDoneMthread(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue; |
| P_QUE_ENTRY_T prQueueEntry; |
| P_CMD_INFO_T prCmdInfo; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| |
| prTempCmdQue = &rTempCmdQue; |
| QUEUE_INITIALIZE(prTempCmdQue); |
| |
| /* 4 <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdDoneQueue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| |
| /* 4 <2> Dequeue from head and check it is able to be sent */ |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); |
| /* Not pending cmd, free it after TX succeed! */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to clear all commands in TX command queue |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearTxCommandQueue(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue = &rTempCmdQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| QUEUE_INITIALIZE(prTempCmdQue); |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->pfCmdTimeoutHandler) |
| prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); |
| else |
| wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); |
| |
| /* Release Tx resource for CMD which resource is allocated but not used */ |
| nicTxReleaseResource(prAdapter, nicTxGetCmdResourceType(prCmdInfo), |
| nicTxGetCmdPageCount(prCmdInfo), TRUE); |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to clear OID commands in TX command queue |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearTxOidCommand(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue = &rTempCmdQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| QUEUE_INITIALIZE(prTempCmdQue); |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| |
| QUEUE_MOVE_ALL(prTempCmdQue, &prAdapter->rTxCmdQueue); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->fgIsOid) { |
| |
| if (prCmdInfo->pfCmdTimeoutHandler) |
| prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); |
| else |
| wlanReleaseCommand(prAdapter, prCmdInfo, TX_RESULT_QUEUE_CLEARANCE); |
| |
| /* Release Tx resource for CMD which resource is allocated but not used */ |
| nicTxReleaseResource(prAdapter, nicTxGetCmdResourceType(prCmdInfo), |
| nicTxGetCmdPageCount(prCmdInfo), TRUE); |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| } else { |
| QUEUE_INSERT_TAIL(&prAdapter->rTxCmdQueue, prQueueEntry); |
| } |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_QUE); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to clear all commands in TX command done queue |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearTxCommandDoneQueue(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempCmdDoneQue; |
| P_QUE_T prTempCmdDoneQue = &rTempCmdDoneQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| QUEUE_INITIALIZE(prTempCmdDoneQue); |
| |
| /* 4 <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| QUEUE_MOVE_ALL(prTempCmdDoneQue, &prAdapter->rTxCmdDoneQueue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_CMD_DONE_QUE); |
| |
| /* 4 <2> Dequeue from head and check it is able to be sent */ |
| QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->pfCmdDoneHandler) |
| prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prCmdInfo->pucInfoBuffer); |
| /* Not pending cmd, free it after TX succeed! */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdDoneQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to clear all buffer in port 0/1 queue |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearDataQueue(IN P_ADAPTER_T prAdapter) |
| { |
| if (HAL_IS_TX_DIRECT()) |
| nicTxDirectClearHifQ(prAdapter); |
| else { |
| #if CFG_FIX_2_TX_PORT |
| QUE_T qDataPort0, qDataPort1; |
| P_QUE_T prDataPort0, prDataPort1; |
| P_MSDU_INFO_T prMsduInfo; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| prDataPort0 = &qDataPort0; |
| prDataPort1 = &qDataPort1; |
| |
| QUEUE_INITIALIZE(prDataPort0); |
| QUEUE_INITIALIZE(prDataPort1); |
| |
| /* <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); |
| QUEUE_MOVE_ALL(prDataPort0, &prAdapter->rTxP0Queue); |
| QUEUE_MOVE_ALL(prDataPort1, &prAdapter->rTxP1Queue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); |
| |
| /* <2> Release Tx resource */ |
| nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); |
| nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); |
| |
| /* <3> Return sk buffer */ |
| nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort0)); |
| nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort1)); |
| |
| /* <4> Clear pending MSDU info in data done queue */ |
| KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); |
| while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { |
| QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, prMsduInfo, P_MSDU_INFO_T); |
| |
| nicTxFreePacket(prAdapter, prMsduInfo, FALSE); |
| nicTxReturnMsduInfo(prAdapter, prMsduInfo); |
| } |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); |
| #else |
| |
| QUE_T qDataPort[TX_PORT_NUM]; |
| P_QUE_T prDataPort[TX_PORT_NUM]; |
| P_MSDU_INFO_T prMsduInfo; |
| INT_32 i; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| for (i = 0; i < TX_PORT_NUM; i++) { |
| prDataPort[i] = &qDataPort[i]; |
| QUEUE_INITIALIZE(prDataPort[i]); |
| } |
| |
| /* <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); |
| for (i = 0; i < TX_PORT_NUM; i++) |
| QUEUE_MOVE_ALL(prDataPort[i], &prAdapter->rTxPQueue[i]); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_PORT_QUE); |
| |
| /* <2> Return sk buffer */ |
| for (i = 0; i < TX_PORT_NUM; i++) { |
| nicTxReleaseMsduResource(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort[i])); |
| nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prDataPort[i])); |
| } |
| |
| /* <3> Clear pending MSDU info in data done queue */ |
| KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); |
| while (QUEUE_IS_NOT_EMPTY(&prAdapter->rTxDataDoneQueue)) { |
| QUEUE_REMOVE_HEAD(&prAdapter->rTxDataDoneQueue, prMsduInfo, P_MSDU_INFO_T); |
| |
| nicTxFreePacket(prAdapter, prMsduInfo, FALSE); |
| nicTxReturnMsduInfo(prAdapter, prMsduInfo); |
| } |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_DATA_DONE_QUE); |
| #endif |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to clear all buffer in port 0/1 queue |
| * \param prAdapter Pointer of Adapter Data Structure |
| * |
| * \retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearRxToOsQueue(IN P_ADAPTER_T prAdapter) |
| { |
| QUE_T rTempRxQue; |
| P_QUE_T prTempRxQue = &rTempRxQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| QUEUE_INITIALIZE(prTempRxQue); |
| |
| /* 4 <1> Move whole list of CMD_INFO to temp queue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| QUEUE_MOVE_ALL(prTempRxQue, &prAdapter->rRxQueue); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_TO_OS_QUE); |
| |
| /* 4 <2> Remove all skbuf */ |
| QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| kalRxIndicateOnePkt(prAdapter->prGlueInfo, (PVOID) GLUE_GET_PKT_DESCRIPTOR(prQueueEntry)); |
| QUEUE_REMOVE_HEAD(prTempRxQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will release thd CMD_INFO upon its attribution |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param prCmdInfo Pointer of CMD_INFO_T |
| * \param rTxDoneStatus Tx done status |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| P_MSDU_INFO_T prMsduInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prCmdInfo); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| switch (prCmdInfo->eCmdType) { |
| case COMMAND_TYPE_GENERAL_IOCTL: |
| case COMMAND_TYPE_NETWORK_IOCTL: |
| DBGLOG(INIT, INFO, "Free CMD: ID[0x%x] SeqNum[%u] OID[%u]\n", |
| prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo->fgIsOid); |
| |
| if (prCmdInfo->fgIsOid) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); |
| } |
| break; |
| |
| case COMMAND_TYPE_SECURITY_FRAME: |
| case COMMAND_TYPE_MANAGEMENT_FRAME: |
| prMsduInfo = prCmdInfo->prMsduInfo; |
| |
| if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { |
| kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); |
| /* Avoid skb multiple free */ |
| prMsduInfo->prPacket = NULL; |
| } |
| |
| DBGLOG(INIT, INFO, |
| "Free %s Frame: BSS[%u] WIDX:PID[%u:%u] SEQ[%u] STA[%u] RSP[%u] CMDSeq[%u]\n", |
| prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME ? "SEC" : "MGMT", |
| prMsduInfo->ucBssIndex, |
| prMsduInfo->ucWlanIndex, |
| prMsduInfo->ucPID, |
| prMsduInfo->ucTxSeqNum, |
| prMsduInfo->ucStaRecIndex, prMsduInfo->pfTxDoneHandler ? TRUE : FALSE, prCmdInfo->ucCmdSeqNum); |
| |
| /* invoke callbacks */ |
| if (prMsduInfo->pfTxDoneHandler != NULL) |
| prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, rTxDoneStatus); |
| |
| if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) |
| GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); |
| |
| cnmMgtPktFree(prAdapter, prMsduInfo); |
| break; |
| |
| default: |
| ASSERT(0); |
| break; |
| } |
| |
| } /* end of wlanReleaseCommand() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will search the CMD Queue to look for the pending OID and |
| * compelete it immediately when system request a reset. |
| * |
| * \param prAdapter ointer of Adapter Data Structure |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) |
| { |
| P_QUE_T prCmdQue; |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue = &rTempCmdQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| DEBUGFUNC("wlanReleasePendingOid"); |
| |
| ASSERT(prAdapter); |
| |
| if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) { |
| DBGLOG(OID, TRACE, "%s stopped! Releasing pending OIDs ..\n", KAL_GET_CURRENT_THREAD_NAME()); |
| } else { |
| DBGLOG(OID, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); |
| prAdapter->ucOidTimeoutCount++; |
| |
| if (prAdapter->ucOidTimeoutCount >= WLAN_OID_NO_ACK_THRESHOLD) { |
| if (!prAdapter->fgIsChipNoAck) { |
| DBGLOG(INIT, WARN, |
| "No response from chip for %u times, set NoAck flag!\n", |
| prAdapter->ucOidTimeoutCount); |
| } |
| |
| prAdapter->fgIsChipNoAck = TRUE; |
| } |
| set_bit(GLUE_FLAG_HIF_PRT_HIF_DBG_INFO_BIT, &(prAdapter->prGlueInfo->ulFlag)); |
| } |
| |
| do { |
| #if CFG_SUPPORT_MULTITHREAD |
| KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); |
| #endif |
| |
| /* 1: Clear Pending OID in prAdapter->rPendingCmdQueue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| |
| prCmdQue = &prAdapter->rPendingCmdQueue; |
| QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| if (prCmdInfo->fgIsOid) { |
| DBGLOG(OID, INFO, "Clear pending OID CMD ID[0x%02X] SEQ[%u] buf[0x%p]\n", |
| prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo->pucInfoBuffer); |
| |
| if (prCmdInfo->pfCmdTimeoutHandler) { |
| prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); |
| } else { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); |
| } |
| |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| nicTxCancelSendingCmd(prAdapter, prCmdInfo); |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } else { |
| QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); |
| } |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| /* Clear pending OID in main_thread to hif_thread command queue */ |
| wlanClearTxOidCommand(prAdapter); |
| #endif |
| |
| /* 2: Clear pending OID in glue layer command queue */ |
| kalOidCmdClearance(prAdapter->prGlueInfo); |
| |
| /* 3: Clear pending OID queued in pvOidEntry with REQ_FLAG_OID set */ |
| kalOidClearance(prAdapter->prGlueInfo); |
| |
| #if CFG_SUPPORT_MULTITHREAD |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_TX_CMD_CLEAR); |
| #endif |
| } while (FALSE); |
| |
| DBGLOG(OID, INFO, "End of Release pending OID\n"); |
| |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function will search the CMD Queue to look for the pending CMD/OID for specific |
| * NETWORK TYPE and compelete it immediately when system request a reset. |
| * |
| * \param prAdapter ointer of Adapter Data Structure |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanReleasePendingCMDbyBssIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) |
| { |
| #if 0 |
| |
| P_QUE_T prCmdQue; |
| QUE_T rTempCmdQue; |
| P_QUE_T prTempCmdQue = &rTempCmdQue; |
| P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; |
| P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| |
| do { |
| /* 1: Clear Pending OID in prAdapter->rPendingCmdQueue */ |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| |
| prCmdQue = &prAdapter->rPendingCmdQueue; |
| QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| while (prQueueEntry) { |
| prCmdInfo = (P_CMD_INFO_T) prQueueEntry; |
| |
| DBGLOG(P2P, TRACE, "Pending CMD for BSS:%d\n", prCmdInfo->ucBssIndex); |
| |
| if (prCmdInfo->ucBssIndex == ucBssIndex) { |
| if (prCmdInfo->pfCmdTimeoutHandler) { |
| prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); |
| } else if (prCmdInfo->fgIsOid) { |
| kalOidComplete(prAdapter->prGlueInfo, |
| prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); |
| } |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| } else { |
| QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); |
| } |
| |
| QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); |
| } |
| |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); |
| |
| } while (FALSE); |
| #endif |
| |
| |
| } /* wlanReleasePendingCMDbyBssIdx */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Return the indicated packet buffer and reallocate one to the RFB |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param pvPacket Pointer of returned packet |
| * |
| * \retval WLAN_STATUS_SUCCESS: Success |
| * \retval WLAN_STATUS_FAILURE: Failed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanReturnPacketDelaySetupTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_SW_RFB_T prSwRfb = NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| WLAN_STATUS status = WLAN_STATUS_SUCCESS; |
| P_QUE_T prQueList; |
| |
| ASSERT(prAdapter); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| prQueList = &prRxCtrl->rIndicatedRfbList; |
| DBGLOG(RX, WARN, "%s: IndicatedRfbList num = %u\n", __func__, prQueList->u4NumElem); |
| |
| while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| |
| status = nicRxSetupRFB(prAdapter, prSwRfb); |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| |
| if (status != WLAN_STATUS_SUCCESS) |
| break; |
| } |
| |
| if (status != WLAN_STATUS_SUCCESS) { |
| DBGLOG(RX, WARN, "Restart ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); |
| /* restart timer */ |
| cnmTimerStartTimer(prAdapter, |
| &prAdapter->rPacketDelaySetupTimer, |
| SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Return the packet buffer and reallocate one to the RFB |
| * |
| * \param prAdapter Pointer of Adapter Data Structure |
| * \param pvPacket Pointer of returned packet |
| * |
| * \retval WLAN_STATUS_SUCCESS: Success |
| * \retval WLAN_STATUS_FAILURE: Failed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket) |
| { |
| P_RX_CTRL_T prRxCtrl; |
| P_SW_RFB_T prSwRfb = NULL; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| DEBUGFUNC("wlanReturnPacket"); |
| |
| ASSERT(prAdapter); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| ASSERT(prRxCtrl); |
| |
| if (pvPacket) { |
| kalPacketFree(prAdapter->prGlueInfo, pvPacket); |
| RX_ADD_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT, 1); |
| #if CFG_NATIVE_802_11 |
| if (GLUE_TEST_FLAG(prAdapter->prGlueInfo, GLUE_FLAG_HALT)) { |
| /*Todo:: nothing */ |
| /*Todo:: nothing */ |
| } |
| #endif |
| } |
| |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| if (!prSwRfb) { |
| DBGLOG(RX, WARN, "No free SwRfb!\n"); |
| return; |
| } |
| |
| if (nicRxSetupRFB(prAdapter, prSwRfb)) { |
| DBGLOG(RX, WARN, "Cannot allocate packet buffer for SwRfb!\n"); |
| if (!timerPendingTimer(&prAdapter->rPacketDelaySetupTimer)) { |
| DBGLOG(RX, WARN, "Start ReturnIndicatedRfb Timer (%u)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); |
| cnmTimerStartTimer(prAdapter, &prAdapter->rPacketDelaySetupTimer, |
| SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); |
| } |
| } |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is a required function that returns information about |
| * the capabilities and status of the driver and/or its network adapter. |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * \param[IN] pfnOidQryHandler Function pointer for the OID query handler. |
| * \param[IN] pvInfoBuf Points to a buffer for return the query information. |
| * \param[IN] u4QueryBufferLen Specifies the number of bytes at pvInfoBuf. |
| * \param[OUT] pu4QueryInfoLen Points to the number of bytes it written or is needed. |
| * |
| * \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS |
| wlanQueryInformation(IN P_ADAPTER_T prAdapter, |
| IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, |
| IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen) |
| { |
| WLAN_STATUS status = WLAN_STATUS_FAILURE; |
| |
| ASSERT(prAdapter); |
| ASSERT(pu4QryInfoLen); |
| |
| /* ignore any OID request after connected, under PS current measurement mode */ |
| if (prAdapter->u4PsCurrentMeasureEn && |
| (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { |
| /* note: return WLAN_STATUS_FAILURE or |
| * WLAN_STATUS_SUCCESS for blocking OIDs during current measurement ?? |
| */ |
| return WLAN_STATUS_SUCCESS; |
| } |
| #if 1 |
| /* most OID handler will just queue a command packet */ |
| status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); |
| #else |
| if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| |
| /* Reset sleepy state */ |
| if (prAdapter->fgWiFiInSleepyState == TRUE) |
| prAdapter->fgWiFiInSleepyState = FALSE; |
| |
| status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| } else |
| status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); |
| #endif |
| |
| return status; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is a required function that allows bound protocol drivers, |
| * or NDIS, to request changes in the state information that the miniport |
| * maintains for particular object identifiers, such as changes in multicast |
| * addresses. |
| * |
| * \param[IN] prAdapter Pointer to the Glue info structure. |
| * \param[IN] pfnOidSetHandler Points to the OID set handlers. |
| * \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. |
| * \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. |
| * \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. |
| * |
| * \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS |
| wlanSetInformation(IN P_ADAPTER_T prAdapter, |
| IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, |
| IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) |
| { |
| WLAN_STATUS status = WLAN_STATUS_FAILURE; |
| |
| ASSERT(prAdapter); |
| ASSERT(pu4SetInfoLen); |
| |
| /* ignore any OID request after connected, under PS current measurement mode */ |
| if (prAdapter->u4PsCurrentMeasureEn && |
| (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) { |
| /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS |
| * for blocking OIDs during current measurement ?? |
| */ |
| return WLAN_STATUS_SUCCESS; |
| } |
| #if 1 |
| /* most OID handler will just queue a command packet |
| * for power state transition OIDs, handler will acquire power control by itself |
| */ |
| status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); |
| #else |
| if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| |
| /* Reset sleepy state */ |
| if (prAdapter->fgWiFiInSleepyState == TRUE) |
| prAdapter->fgWiFiInSleepyState = FALSE; |
| |
| status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| } else { |
| status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); |
| } |
| #endif |
| |
| return status; |
| } |
| |
| #if CFG_SUPPORT_WAPI |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is a used to query driver's config wapi mode or not |
| * |
| * \param[IN] prAdapter Pointer to the Glue info structure. |
| * |
| * \retval TRUE for use wapi mode |
| * |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| return prAdapter->rWifiVar.rConnSettings.fgWapiMode; |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called to set RX filter to Promiscuous Mode. |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) |
| { |
| ASSERT(prAdapter); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called to set RX filter to allow to receive |
| * broadcast address packets. |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) |
| { |
| ASSERT(prAdapter); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called to send out CMD_ID_DUMMY command packet |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * |
| * \return WLAN_STATUS_SUCCESS |
| * \return WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanSendDummyCmd(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsReqTxRsrc) |
| { |
| WLAN_STATUS status = WLAN_STATUS_SUCCESS; |
| P_GLUE_INFO_T prGlueInfo; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| |
| ASSERT(prAdapter); |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = (UINT_16) CMD_HDR_SIZE; |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->pfCmdTimeoutHandler = NULL; |
| prCmdInfo->fgIsOid = TRUE; |
| prCmdInfo->ucCID = CMD_ID_DUMMY_RSV; |
| prCmdInfo->fgSetQuery = TRUE; |
| prCmdInfo->fgNeedResp = FALSE; |
| prCmdInfo->ucCmdSeqNum = 0; |
| prCmdInfo->u4SetInfoLen = 0; |
| |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| |
| if (fgIsReqTxRsrc) { |
| if (wlanSendCommand(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Fail to transmit CMD_ID_DUMMY command\n"); |
| status = WLAN_STATUS_FAILURE; |
| } |
| } else { |
| if (nicTxCmd(prAdapter, prCmdInfo, TC4_INDEX) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Fail to transmit CMD_ID_DUMMY command\n"); |
| status = WLAN_STATUS_FAILURE; |
| } |
| } |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called to send out CMD_NIC_POWER_CTRL command packet |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * \param[IN] ucPowerMode refer to CMD/EVENT document |
| * |
| * \return WLAN_STATUS_SUCCESS |
| * \return WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode) |
| { |
| WLAN_STATUS status = WLAN_STATUS_SUCCESS; |
| P_GLUE_INFO_T prGlueInfo; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| UINT_8 ucTC, ucCmdSeqNum; |
| |
| ASSERT(prAdapter); |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| |
| /* 1. Prepare CMD */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| /* 2.1 increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); |
| |
| /* 2.2 Setup common CMD Info Packet */ |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->pfCmdTimeoutHandler = NULL; |
| prCmdInfo->fgIsOid = TRUE; |
| prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; |
| prCmdInfo->fgSetQuery = TRUE; |
| prCmdInfo->fgNeedResp = FALSE; |
| prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; |
| prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); |
| |
| /* 2.3 Setup WIFI_CMD_T */ |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| |
| kalMemZero(prWifiCmd->aucBuffer, sizeof(CMD_NIC_POWER_CTRL)); |
| ((P_CMD_NIC_POWER_CTRL) (prWifiCmd->aucBuffer))->ucPowerMode = ucPowerMode; |
| |
| /* 3. Issue CMD for entering specific power mode */ |
| ucTC = TC4_INDEX; |
| |
| while (1) { |
| /* 3.0 Removal check */ |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| /* 3.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetCmdPageCount(prCmdInfo), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| status = WLAN_STATUS_FAILURE; |
| prAdapter->fgIsChipNoAck = TRUE; |
| break; |
| } |
| continue; |
| } |
| break; |
| }; |
| |
| /* 3.2 Send CMD Info Packet */ |
| if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Fail to transmit CMD_NIC_POWER_CTRL command\n"); |
| status = WLAN_STATUS_FAILURE; |
| } |
| |
| /* 4. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| /* 5. Add flag */ |
| if (ucPowerMode == 1) |
| prAdapter->fgIsEnterD3ReqIssued = TRUE; |
| |
| return status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is called to check if it is RF test mode and |
| * the OID is allowed to be called or not |
| * |
| * \param[IN] prAdapter Pointer to the Adapter structure. |
| * \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) |
| { |
| PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; |
| UINT_32 i; |
| UINT_32 u4NumOfElem; |
| |
| if (fgSetInfo) { |
| apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; |
| u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); |
| } else { |
| apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; |
| u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); |
| } |
| |
| for (i = 0; i < u4NumOfElem; i++) { |
| if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) |
| return TRUE; |
| } |
| |
| return FALSE; |
| } |
| |
| #if CFG_ENABLE_FW_DOWNLOAD |
| VOID wlanImageSectionGetFwInfo(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, |
| IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, |
| OUT PUINT_32 pu4DataMode) |
| { |
| UINT_32 u4DataMode = 0; |
| fw_image_tailer_t *prFwHead; |
| tailer_format_t *prTailer; |
| |
| prFwHead = (fw_image_tailer_t *) (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_t)); |
| if (ucTotSecNum == 1) |
| prTailer = &prFwHead->dlm_info; |
| else |
| prTailer = &prFwHead->ilm_info; |
| |
| |
| prTailer = &prTailer[ucCurSecNum]; |
| |
| *pu4StartOffset = 0; |
| *pu4Addr = prTailer->addr; |
| *pu4Len = (prTailer->len + LEN_4_BYTE_CRC); |
| if (prTailer->feature_set & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { |
| u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; |
| u4DataMode |= (prTailer->feature_set & DOWNLOAD_CONFIG_KEY_INDEX_MASK); |
| u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; |
| } |
| |
| if (eDlIdx == IMG_DL_IDX_CR4_FW) |
| u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; |
| |
| #if CFG_ENABLE_FW_DOWNLOAD_ACK |
| u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ |
| #endif |
| |
| *pu4DataMode = u4DataMode; |
| |
| /* Dump image information */ |
| if (ucCurSecNum == 0) { |
| DBGLOG(INIT, INFO, "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", |
| (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", prTailer->chip_info, |
| prTailer->eco_code + 1, prTailer->feature_set); |
| DBGLOG(INIT, INFO, "date[%s] version[%c%c%c%c%c%c%c%c%c%c]\n", |
| prTailer->ram_built_date, |
| prTailer->ram_version[0], prTailer->ram_version[1], |
| prTailer->ram_version[2], prTailer->ram_version[3], |
| prTailer->ram_version[4], prTailer->ram_version[5], |
| prTailer->ram_version[6], prTailer->ram_version[7], |
| prTailer->ram_version[8], prTailer->ram_version[9]); |
| } |
| |
| /* Backup to FW version info */ |
| if (eDlIdx == IMG_DL_IDX_N9_FW) |
| kalMemCopy(&prAdapter->rVerInfo.rN9tailer, prTailer, sizeof(tailer_format_t)); |
| else |
| kalMemCopy(&prAdapter->rVerInfo.rCR4tailer, prTailer, sizeof(tailer_format_t)); |
| } |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| VOID wlanImageSectionGetCompressFwInfo(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, |
| IN ENUM_IMG_DL_IDX_T eDlIdx, OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, |
| OUT PUINT_32 pu4DataMode, OUT PUINT_32 pu4BlockSize, OUT PUINT_32 pu4CRC, OUT PUINT_32 pu4UncompressedLength) |
| { |
| UINT_32 u4DataMode = 0; |
| fw_image_tailer_t_2 *prFwHead; |
| tailer_format_t_2 *prTailer; |
| |
| prFwHead = (fw_image_tailer_t_2 *) (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_t_2)); |
| if (ucTotSecNum == 1) |
| prTailer = &prFwHead->dlm_info; |
| else |
| prTailer = &prFwHead->ilm_info; |
| |
| prTailer = &prTailer[ucCurSecNum]; |
| |
| *pu4StartOffset = 0; |
| *pu4Addr = prTailer->addr; |
| *pu4Len = (prTailer->len); |
| *pu4BlockSize = (prTailer->block_size); |
| *pu4CRC = (prTailer->crc); |
| *pu4UncompressedLength = (prTailer->real_size); |
| if (prTailer->feature_set & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { |
| u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; |
| u4DataMode |= (prTailer->feature_set & DOWNLOAD_CONFIG_KEY_INDEX_MASK); |
| u4DataMode |= DOWNLOAD_CONFIG_ENCRYPTION_MODE; |
| } |
| if (eDlIdx == IMG_DL_IDX_CR4_FW) |
| u4DataMode |= DOWNLOAD_CONFIG_WORKING_PDA_OPTION; |
| |
| #if CFG_ENABLE_FW_DOWNLOAD_ACK |
| u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ |
| #endif |
| |
| *pu4DataMode = u4DataMode; |
| |
| /* Dump image information */ |
| if (ucCurSecNum == 0) { |
| DBGLOG(INIT, INFO, "%s INFO: chip_info[%u:E%u] feature[0x%02X]\n", |
| (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", prTailer->chip_info, |
| prTailer->eco_code, prTailer->feature_set); |
| DBGLOG(INIT, INFO, "date[%s] version[%c%c%c%c%c%c%c%c%c%c]\n", prTailer->ram_built_date, |
| prTailer->ram_version[0], prTailer->ram_version[1], |
| prTailer->ram_version[2], prTailer->ram_version[3], |
| prTailer->ram_version[4], prTailer->ram_version[5], |
| prTailer->ram_version[6], prTailer->ram_version[7], |
| prTailer->ram_version[8], prTailer->ram_version[9]); |
| } |
| /* Backup to FW version info */ |
| if (eDlIdx == IMG_DL_IDX_N9_FW) { |
| kalMemCopy(&prAdapter->rVerInfo.rN9Compressedtailer, prTailer, sizeof(tailer_format_t_2)); |
| prAdapter->rVerInfo.fgIsN9CompressedFW = TRUE; |
| } else { |
| kalMemCopy(&prAdapter->rVerInfo.rCR4Compressedtailer, prTailer, sizeof(tailer_format_t_2)); |
| prAdapter->rVerInfo.fgIsCR4CompressedFW = TRUE; |
| } |
| } |
| #endif |
| VOID wlanImageSectionGetPatchInfo(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, |
| IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, |
| OUT PUINT_32 pu4DataMode) |
| { |
| P_PATCH_FORMAT_T prPatchFormat; |
| UINT_32 u4DataMode = 0; |
| UINT_8 aucBuffer[32]; |
| struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; |
| |
| prPatchFormat = (P_PATCH_FORMAT_T) pvFwImageMapFile; |
| |
| *pu4StartOffset = offsetof(PATCH_FORMAT_T, ucPatchImage); |
| *pu4Addr = prChipInfo->patch_addr; |
| *pu4Len = u4FwImageFileLength - offsetof(PATCH_FORMAT_T, ucPatchImage); |
| |
| #if CFG_ENABLE_FW_DOWNLOAD_ACK |
| u4DataMode |= DOWNLOAD_CONFIG_ACK_OPTION; /* ACK needed */ |
| #endif |
| *pu4DataMode = u4DataMode; |
| |
| /* Dump image information */ |
| kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); |
| aucBuffer[4] = '\0'; |
| DBGLOG(INIT, INFO, "PATCH INFO: platform[%s] HW/SW ver[0x%04X] ver[0x%04X]\n", |
| aucBuffer, prPatchFormat->u4SwHwVersion, prPatchFormat->u4PatchVersion); |
| |
| kalStrnCpy(aucBuffer, prPatchFormat->aucBuildDate, 16); |
| aucBuffer[16] = '\0'; |
| DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); |
| |
| /* Backup to FW version info */ |
| kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, sizeof(PATCH_FORMAT_T)); |
| } |
| |
| VOID wlanImageSectionGetInfo(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, |
| IN UINT_8 ucTotSecNum, IN UINT_8 ucCurSecNum, IN ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT PUINT_32 pu4StartOffset, OUT PUINT_32 pu4Addr, OUT PUINT_32 pu4Len, |
| OUT PUINT_32 pu4DataMode) |
| { |
| if (eDlIdx == IMG_DL_IDX_PATCH) { |
| wlanImageSectionGetPatchInfo(prAdapter, pvFwImageMapFile, u4FwImageFileLength, |
| ucTotSecNum, ucCurSecNum, eDlIdx, pu4StartOffset, pu4Addr, pu4Len, |
| pu4DataMode); |
| } else { |
| wlanImageSectionGetFwInfo(prAdapter, pvFwImageMapFile, u4FwImageFileLength, |
| ucTotSecNum, ucCurSecNum, eDlIdx, pu4StartOffset, pu4Addr, pu4Len, |
| pu4DataMode); |
| } |
| } |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| |
| BOOLEAN wlanImageSectionCheckFwCompressInfo(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, IN ENUM_IMG_DL_IDX_T eDlIdx) { |
| UINT_8 ucCompression; |
| fw_image_tailer_check *prCheckInfo; |
| |
| if (eDlIdx == IMG_DL_IDX_PATCH) |
| return FALSE; |
| |
| prCheckInfo = (fw_image_tailer_check *) |
| (pvFwImageMapFile + u4FwImageFileLength - sizeof(fw_image_tailer_check)); |
| DBGLOG(INIT, INFO, "feature_set %d\n", prCheckInfo->feature_set); |
| ucCompression = (UINT_8)((prCheckInfo->feature_set & COMPRESSION_OPTION_MASK) |
| >> COMPRESSION_OPTION_OFFSET); |
| DBGLOG(INIT, INFO, "Compressed Check INFORMATION %d\n", ucCompression); |
| if (ucCompression == 1) { |
| DBGLOG(INIT, INFO, "Compressed FW\n"); |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| |
| WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, IN PVOID pvFwImageMapFile, |
| IN UINT_32 u4FwImageFileLength, IN UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT PUINT_8 pucIsCompressed, OUT P_INIT_CMD_WIFI_DECOMPRESSION_START prFwImageInFo) |
| { |
| UINT_32 u4ImgSecSize; |
| UINT_32 j, i; |
| INT_32 i4TotalLen; |
| UINT_32 u4FileOffset = 0; |
| UINT_32 u4StartOffset = 0; |
| UINT_32 u4DataMode = 0; |
| UINT_32 u4Addr, u4Len, u4BlockSize, u4CRC, u4UnCompressedLength; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| PUINT_8 pucSecBuf, pucStartPtr; |
| UINT_32 u4offset = 0, u4ChunkSize; |
| /* 3a. parse file header for decision of divided firmware download or not */ |
| for (i = 0; i < ucSectionNumber; ++i) { |
| if (wlanImageSectionCheckFwCompressInfo(prAdapter, pvFwImageMapFile, |
| u4FwImageFileLength, eDlIdx) == TRUE){ |
| wlanImageSectionGetCompressFwInfo(prAdapter, pvFwImageMapFile, |
| u4FwImageFileLength, ucSectionNumber, i, eDlIdx, |
| &u4StartOffset, &u4Addr, &u4Len, &u4DataMode, |
| &u4BlockSize, &u4CRC, &u4UnCompressedLength); |
| u4offset = 0; |
| if (i == 0) { |
| prFwImageInFo->u4BlockSize = u4BlockSize; |
| prFwImageInFo->u4Region1Address = u4Addr; |
| prFwImageInFo->u4Region1CRC = u4CRC; |
| prFwImageInFo->u4Region1length = u4UnCompressedLength; |
| } else { |
| prFwImageInFo->u4Region2Address = u4Addr; |
| prFwImageInFo->u4Region2CRC = u4CRC; |
| prFwImageInFo->u4Region2length = u4UnCompressedLength; |
| } |
| i4TotalLen = u4Len; |
| DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", |
| u4FileOffset, u4Addr, u4Len, u4DataMode); |
| DBGLOG(INIT, INFO, "DL BLOCK[%u] COMlen[%u] CRC[%u]\n", |
| u4BlockSize, u4UnCompressedLength, u4CRC); |
| pucStartPtr = (PUINT_8)pvFwImageMapFile + u4StartOffset; |
| while (i4TotalLen) { |
| u4ChunkSize = *((unsigned int *)(pucStartPtr+u4FileOffset)); |
| u4FileOffset += 4; |
| DBGLOG(INIT, INFO, "Downloaded Length %d! Addr %x\n", i4TotalLen, u4Addr + u4offset); |
| DBGLOG(INIT, INFO, "u4ChunkSize Length %d!\n", u4ChunkSize); |
| if (wlanImageSectionConfig(prAdapter, (u4Addr + u4offset), u4ChunkSize, |
| u4DataMode, eDlIdx) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| for (j = 0; j < u4ChunkSize; j += CMD_PKT_SIZE_FOR_IMAGE) { |
| if (j + CMD_PKT_SIZE_FOR_IMAGE < u4ChunkSize) |
| u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; |
| else |
| u4ImgSecSize = u4ChunkSize - j; |
| pucSecBuf = (PUINT_8)pucStartPtr + u4FileOffset + j; |
| if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) |
| != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| } |
| /* escape from loop if any pending error occurs */ |
| if (u4Status == WLAN_STATUS_FAILURE) |
| break; |
| i4TotalLen -= u4ChunkSize; |
| u4offset += u4BlockSize; |
| u4FileOffset += u4ChunkSize; |
| if (i4TotalLen < 0) { |
| DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| } |
| *pucIsCompressed = TRUE; |
| } else { |
| wlanImageSectionGetInfo(prAdapter, pvFwImageMapFile, |
| u4FwImageFileLength, ucSectionNumber, i, eDlIdx, |
| &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); |
| pucStartPtr = (PUINT_8)pvFwImageMapFile + u4StartOffset; |
| |
| DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", |
| u4FileOffset, u4Addr, u4Len, u4DataMode); |
| |
| if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, u4DataMode, eDlIdx) |
| != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); |
| |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| for (j = 0; j < u4Len; j += CMD_PKT_SIZE_FOR_IMAGE) { |
| if (j + CMD_PKT_SIZE_FOR_IMAGE < u4Len) |
| u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; |
| else |
| u4ImgSecSize = u4Len - j; |
| |
| pucSecBuf = (PUINT_8)pucStartPtr + u4FileOffset + j; |
| if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) |
| != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| } |
| |
| /* escape from loop if any pending error occurs */ |
| if (u4Status == WLAN_STATUS_FAILURE) |
| break; |
| u4FileOffset += u4Len; |
| *pucIsCompressed = FALSE; |
| } |
| } |
| return u4Status; |
| } |
| #else |
| WLAN_STATUS wlanImageSectionDownloadStage(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength, |
| IN UINT_8 ucSectionNumber, IN ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| UINT_32 u4ImgSecSize; |
| UINT_32 j, i; |
| UINT_32 u4FileOffset = 0; |
| UINT_32 u4StartOffset = 0; |
| UINT_32 u4DataMode = 0; |
| UINT_32 u4Addr, u4Len; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| PUINT_8 pucSecBuf, pucStartPtr; |
| |
| /* 3a. parse file header for decision of divided firmware download or not */ |
| for (i = 0; i < ucSectionNumber; ++i) { |
| wlanImageSectionGetInfo(prAdapter, pvFwImageMapFile, |
| u4FwImageFileLength, ucSectionNumber, i, eDlIdx, |
| &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); |
| |
| pucStartPtr = (PUINT_8) pvFwImageMapFile + u4StartOffset; |
| |
| DBGLOG(INIT, INFO, "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", |
| u4FileOffset, u4Addr, u4Len, u4DataMode); |
| |
| if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, u4DataMode, eDlIdx) |
| != WLAN_STATUS_SUCCESS) { |
| |
| DBGLOG(INIT, ERROR, "Firmware download configuration failed!\n"); |
| |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| for (j = 0; j < u4Len; j += CMD_PKT_SIZE_FOR_IMAGE) { |
| if (j + CMD_PKT_SIZE_FOR_IMAGE < u4Len) |
| u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; |
| else |
| u4ImgSecSize = u4Len - j; |
| |
| pucSecBuf = (PUINT_8) pucStartPtr + u4FileOffset + j; |
| if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, pucSecBuf) |
| != WLAN_STATUS_SUCCESS) { |
| |
| DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); |
| |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| kalMdelay(1); |
| } |
| |
| /* escape from loop if any pending error occurs */ |
| if (u4Status == WLAN_STATUS_FAILURE) |
| break; |
| |
| |
| u4FileOffset += u4Len; |
| } |
| |
| return u4Status; |
| } |
| #endif |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to confirm the status of |
| * previously patch semaphore control |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * ucCmdSeqNum Sequence number of previous firmware scatter |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanPatchRecvSemaResp(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum, OUT PUINT_8 pucPatchStatus) |
| { |
| UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; |
| P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; |
| P_INIT_EVENT_CMD_RESULT prEventCmdResult; |
| UINT_32 u4RxPktLength; |
| |
| ASSERT(prAdapter); |
| |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) |
| return WLAN_STATUS_FAILURE; |
| |
| |
| if (nicRxWaitResponse(prAdapter, 0, aucBuffer, |
| sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT), |
| &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| |
| DBGLOG(INIT, WARN, "Wait patch semaphore response fail\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; |
| if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PATCH_SEMA_CTRL) { |
| DBGLOG(INIT, WARN, "Unexpected EVENT ID, get 0x%0x\n", prInitHifRxHeader->rInitWifiEvent.ucEID); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { |
| DBGLOG(INIT, WARN, "Unexpected SeqNum %d, %d\n", ucCmdSeqNum, |
| prInitHifRxHeader->rInitWifiEvent.ucSeqNum); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prEventCmdResult = (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); |
| |
| *pucPatchStatus = prEventCmdResult->ucStatus; |
| |
| #if 0 |
| if (prEventCmdResult->ucStatus != PATCH_STATUS_GET_SEMA_NEED_PATCH) { |
| DBGLOG(INIT, INFO, "Patch status[%d], skip patch\n", prEventCmdResult->ucStatus); |
| return WLAN_STATUS_FAILURE; |
| } |
| DBGLOG(INIT, INFO, "Status[%d], ready to patch\n", prEventCmdResult->ucStatus); |
| return WLAN_STATUS_SUCCESS; |
| |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check the patch semaphore control. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanPatchSendSemaControl(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucSeqNum) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| P_INIT_CMD_PATCH_SEMA_CONTROL prPatchSemaControl; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanImagePatchSemaphoreCheck"); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = |
| cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_PATCH_SEMA_CONTROL)); |
| |
| /* DBGLOG(INIT, ERROR, "sizeof INIT_HIF_TX_HEADER_T = %d\n", sizeof(INIT_HIF_TX_HEADER_T)); */ |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_PATCH_SEMA_CONTROL); |
| |
| /* 2. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_SEMAPHORE_CONTROL; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PDA_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| *pucSeqNum = prInitHifTxHeader->rInitWifiCmd.ucSeqNum; |
| |
| /* 3. Setup DOWNLOAD_BUF */ |
| prPatchSemaControl = (P_INIT_CMD_PATCH_SEMA_CONTROL) prInitHifTxHeader->rInitWifiCmd.aucBuffer; |
| kalMemZero(prPatchSemaControl, sizeof(INIT_CMD_PATCH_SEMA_CONTROL)); |
| prPatchSemaControl->ucGetSemaphore = PATCH_GET_SEMA_CONTROL; |
| |
| /* 4. Send FW_Download command */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); |
| } |
| /* 5. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| BOOLEAN wlanPatchIsDownloaded(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 ucSeqNum, ucPatchStatus; |
| WLAN_STATUS rStatus; |
| UINT_32 u4Count; |
| |
| ucPatchStatus = PATCH_STATUS_NO_SEMA_NEED_PATCH; |
| u4Count = 0; |
| |
| while (ucPatchStatus == PATCH_STATUS_NO_SEMA_NEED_PATCH) { |
| |
| if (u4Count) |
| kalMdelay(100); |
| |
| |
| rStatus = wlanPatchSendSemaControl(prAdapter, &ucSeqNum); |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, WARN, "Send patch SEMA control CMD failed!!\n"); |
| break; |
| } |
| |
| rStatus = wlanPatchRecvSemaResp(prAdapter, ucSeqNum, &ucPatchStatus); |
| if (rStatus != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, WARN, "Recv patch SEMA control EVT failed!!\n"); |
| break; |
| } |
| |
| u4Count++; |
| |
| if (u4Count > 50) { |
| DBGLOG(INIT, WARN, "Patch status check timeout!!\n"); |
| break; |
| } |
| } |
| |
| if (ucPatchStatus == PATCH_STATUS_NO_NEED_TO_PATCH) |
| return TRUE; |
| else |
| return FALSE; |
| |
| } |
| |
| WLAN_STATUS wlanPatchSendComplete(IN P_ADAPTER_T prAdapter) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| UINT_8 ucTC, ucCmdSeqNum; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T)); |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); |
| |
| #if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) |
| /* 2. Always use TC4 (TC4 as CPU) */ |
| ucTC = TC4_INDEX; |
| #else |
| /* 2. Use TC0's resource to send patch finish command. |
| * Only TC0 is allowed because SDIO HW always reports |
| * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) |
| */ |
| ucTC = TC0_INDEX; |
| #endif |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_FINISH; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| /* 5. Seend WIFI start command */ |
| while (1) { |
| /* 5.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| goto exit; |
| } |
| continue; |
| } |
| /* 5.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); |
| goto exit; |
| } |
| |
| break; |
| }; |
| |
| DBGLOG(INIT, INFO, "PATCH FINISH CMD send, waiting for RSP\n"); |
| |
| /* kalMdelay(10000); */ |
| |
| u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); |
| |
| if (u4Status != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "PATCH FINISH EVT failed\n"); |
| else |
| DBGLOG(INIT, INFO, "PATCH FINISH EVT success!!\n"); |
| |
| exit: |
| /* 6. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to configure FWDL parameters |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * u4DestAddr Address of destination address |
| * u4ImgSecSize Length of the firmware block |
| * fgReset should be set to TRUE if this is the 1st configuration |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanImageSectionConfig(IN P_ADAPTER_T prAdapter, |
| IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN UINT_32 u4DataMode, |
| IN ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| P_INIT_CMD_DOWNLOAD_CONFIG prInitCmdDownloadConfig; |
| UINT_8 ucTC, ucCmdSeqNum; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanImageSectionConfig"); |
| |
| if (u4ImgSecSize == 0) |
| return WLAN_STATUS_SUCCESS; |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_CONFIG)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_CONFIG); |
| |
| #if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) |
| /* 2. Use TC4's resource to download image. (TC4 as CPU) */ |
| ucTC = TC4_INDEX; |
| #else |
| /* 2. Use TC0's resource to send init_cmd. |
| * Only TC0 is allowed because SDIO HW always reports |
| * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) |
| */ |
| ucTC = TC0_INDEX; |
| #endif |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| |
| if (eDlIdx == IMG_DL_IDX_PATCH) |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_PATCH_START; |
| else |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_CONFIG; |
| |
| |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| /* 5. Setup CMD_DOWNLOAD_CONFIG */ |
| prInitCmdDownloadConfig = (P_INIT_CMD_DOWNLOAD_CONFIG) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); |
| prInitCmdDownloadConfig->u4Address = u4DestAddr; |
| prInitCmdDownloadConfig->u4Length = u4ImgSecSize; |
| prInitCmdDownloadConfig->u4DataMode = u4DataMode; |
| |
| /* 6. Send FW_Download command */ |
| while (1) { |
| /* 6.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| goto exit; |
| } |
| continue; |
| } |
| /* 6.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); |
| goto exit; |
| } |
| |
| break; |
| }; |
| |
| #if CFG_ENABLE_FW_DOWNLOAD_ACK |
| /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ |
| u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); |
| #endif |
| |
| exit: |
| /* 8. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to download FW image. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| ASSERT(pucImgSecBuf); |
| ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); |
| |
| DEBUGFUNC("wlanImageSectionDownload"); |
| |
| if (u4ImgSecSize == 0) |
| return WLAN_STATUS_SUCCESS; |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + u4ImgSecSize); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + (UINT_16) u4ImgSecSize; |
| |
| /* 2. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PDA_PQ_ID; |
| prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PDA_PACKET_TYPE_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_PDA_FWDL; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = 0; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PDA_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = 0; |
| |
| /* 3. Setup DOWNLOAD_BUF */ |
| kalMemCopy(prInitHifTxHeader->rInitWifiCmd.aucBuffer, pucImgSecBuf, u4ImgSecSize); |
| |
| /* 4. Send FW_Download command */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); |
| } |
| /* 5. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to confirm previously firmware download is done without error |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR)]; |
| UINT_32 u4RxPktLength; |
| P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; |
| P_INIT_EVENT_PENDING_ERROR prEventPendingError; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| UINT_8 ucTC, ucCmdSeqNum; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanImageQueryStatus"); |
| |
| /* 1. Allocate CMD Info Packet and it Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T)); |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); |
| |
| #if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) |
| /* 2. Always use TC4 */ |
| ucTC = TC4_INDEX; |
| #else |
| /* 2. Use TC0's resource to send init_cmd |
| * Only TC0 is allowed because SDIO HW always reports |
| * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) |
| */ |
| ucTC = TC0_INDEX; |
| #endif |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| /* 5. Send command */ |
| while (1) { |
| /* 5.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| break; |
| } |
| continue; |
| |
| } |
| /* 5.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); |
| } |
| |
| break; |
| }; |
| |
| /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ |
| do { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else if (nicRxWaitResponse(prAdapter, |
| 0, |
| aucBuffer, |
| sizeof(INIT_HIF_RX_HEADER_T) + |
| sizeof(INIT_EVENT_PENDING_ERROR), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; |
| |
| /* EID / SeqNum check */ |
| if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| prEventPendingError = |
| (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); |
| if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| u4Status = WLAN_STATUS_SUCCESS; |
| } |
| } |
| } |
| } while (FALSE); |
| |
| /* 7. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to confirm the status of |
| * previously downloaded firmware scatter |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * ucCmdSeqNum Sequence number of previous firmware scatter |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum) |
| { |
| UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; |
| P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; |
| P_INIT_EVENT_CMD_RESULT prEventCmdResult; |
| UINT_32 u4RxPktLength; |
| WLAN_STATUS u4Status; |
| |
| UINT_8 ucPortIdx = IMG_DL_STATUS_PORT_IDX; |
| |
| ASSERT(prAdapter); |
| |
| do { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else if (nicRxWaitResponse(prAdapter, |
| ucPortIdx, |
| aucBuffer, |
| sizeof(INIT_HIF_RX_HEADER_T) + |
| sizeof(INIT_EVENT_CMD_RESULT), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; |
| |
| /* EID / SeqNum check */ |
| if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| prEventCmdResult = |
| (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); |
| if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ |
| DBGLOG(INIT, ERROR, "Start CMD failed, status[%u]\n", |
| prEventCmdResult->ucStatus); |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| if (prEventCmdResult->ucStatus == WIFI_FW_DECOMPRESSION_FAILED) |
| DBGLOG(INIT, ERROR, "Start Decompression CMD failed, status[%u]\n", |
| prEventCmdResult->ucStatus); |
| #endif |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| u4Status = WLAN_STATUS_SUCCESS; |
| } |
| } |
| } |
| } while (FALSE); |
| |
| return u4Status; |
| } |
| |
| WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, |
| IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress, IN UINT_8 ucPDA) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| P_INIT_CMD_WIFI_START prInitCmdWifiStart; |
| UINT_8 ucTC, ucCmdSeqNum; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanConfigWifiFunc"); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); |
| prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); |
| |
| #if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) |
| /* 2. Always use TC4 (TC4 as CPU) */ |
| ucTC = TC4_INDEX; |
| #else |
| /* 2. Use TC0's resource to send init_cmd. |
| * Only TC0 is allowed because SDIO HW always reports |
| * CPU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) |
| */ |
| ucTC = TC0_INDEX; |
| #endif |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); |
| prInitCmdWifiStart->u4Override = 0; |
| if (fgEnable) |
| prInitCmdWifiStart->u4Override |= START_OVERRIDE_START_ADDRESS; |
| |
| /* 5G cal until send efuse buffer mode CMD */ |
| #if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) |
| if (prAdapter->fgIsSupportDelayCal == TRUE) |
| prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; |
| #endif |
| |
| if (ucPDA == PDA_CR4) |
| prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; |
| |
| prInitCmdWifiStart->u4Address = u4StartAddress; |
| |
| /* 5. Seend WIFI start command */ |
| while (1) { |
| /* 5.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| goto exit; |
| } |
| continue; |
| } |
| /* 5.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); |
| goto exit; |
| } |
| |
| break; |
| }; |
| |
| DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); |
| |
| u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); |
| |
| if (u4Status != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "FW_START EVT failed\n"); |
| else |
| DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); |
| |
| exit: |
| /* 6. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| WLAN_STATUS |
| wlanCompressedFWConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, |
| IN UINT_32 u4StartAddress, IN UINT_8 ucPDA, IN P_INIT_CMD_WIFI_DECOMPRESSION_START prFwImageInFo) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| P_INIT_CMD_WIFI_DECOMPRESSION_START prInitCmdWifiStart; |
| UINT_8 ucTC, ucCmdSeqNum; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| DEBUGFUNC("wlanConfigWifiFunc"); |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(INIT_HIF_TX_HEADER_T) + |
| sizeof(INIT_CMD_WIFI_DECOMPRESSION_START)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, |
| sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_DECOMPRESSION_START)); |
| prCmdInfo->u2InfoBufLen = |
| sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_DECOMPRESSION_START); |
| |
| /* 2. Always use TC0 */ |
| ucTC = TC0_INDEX; |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DECOMPRESSED_WIFI_START; |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| prInitCmdWifiStart = (P_INIT_CMD_WIFI_DECOMPRESSION_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); |
| prInitCmdWifiStart->u4Override = 0; |
| if (fgEnable) |
| prInitCmdWifiStart->u4Override |= START_OVERRIDE_START_ADDRESS; |
| |
| /* 5G cal until send efuse buffer mode CMD */ |
| #if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) |
| if (prAdapter->fgIsSupportDelayCal == TRUE) |
| prInitCmdWifiStart->u4Override |= START_DELAY_CALIBRATION; |
| #endif |
| if (ucPDA == PDA_CR4) |
| prInitCmdWifiStart->u4Override |= START_WORKING_PDA_OPTION; |
| |
| #if CFG_COMPRESSION_DEBUG |
| prInitCmdWifiStart->u4Override |= START_CRC_CHECK; |
| #endif |
| #if CFG_DECOMPRESSION_TMP_ADDRESS |
| prInitCmdWifiStart->u4Override |= CHANGE_DECOMPRESSION_TMP_ADDRESS; |
| prInitCmdWifiStart->u4DecompressTmpAddress = 0xE6000; |
| #endif |
| prInitCmdWifiStart->u4Address = u4StartAddress; |
| prInitCmdWifiStart->u4Region1Address = prFwImageInFo->u4Region1Address; |
| prInitCmdWifiStart->u4Region1CRC = prFwImageInFo->u4Region1CRC; |
| prInitCmdWifiStart->u4BlockSize = prFwImageInFo->u4BlockSize; |
| prInitCmdWifiStart->u4Region1length = prFwImageInFo->u4Region1length; |
| prInitCmdWifiStart->u4Region2Address = prFwImageInFo->u4Region2Address; |
| prInitCmdWifiStart->u4Region2CRC = prFwImageInFo->u4Region2CRC; |
| prInitCmdWifiStart->u4Region2length = prFwImageInFo->u4Region2length; |
| |
| while (1) { |
| /* 5.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| break; |
| } |
| continue; |
| |
| } |
| /* 5.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); |
| } |
| |
| break; |
| }; |
| |
| DBGLOG(INIT, INFO, "FW_START CMD send, waiting for RSP\n"); |
| |
| u4Status = wlanConfigWifiFuncStatus(prAdapter, ucCmdSeqNum); |
| |
| if (u4Status != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "FW_START EVT failed\n"); |
| else |
| DBGLOG(INIT, INFO, "FW_START EVT success!!\n"); |
| |
| |
| /* 6. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| #endif |
| #if 0 |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to generate CRC32 checksum |
| * |
| * @param buf Pointer to the data. |
| * @param len data length |
| * |
| * @return crc32 value |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len) |
| { |
| UINT_32 i, crc32 = 0xFFFFFFFF; |
| const UINT_32 crc32_ccitt_table[256] = { |
| 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, |
| 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, |
| 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, |
| 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, |
| 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, |
| 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, |
| 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, |
| 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, |
| 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, |
| 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, |
| 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, |
| 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, |
| 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, |
| 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, |
| 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, |
| 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, |
| 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, |
| 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, |
| 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, |
| 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, |
| 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, |
| 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, |
| 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, |
| 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, |
| 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, |
| 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, |
| 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, |
| 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, |
| 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, |
| 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, |
| 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, |
| 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, |
| 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, |
| 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, |
| 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, |
| 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, |
| 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, |
| 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, |
| 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, |
| 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, |
| 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, |
| 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, |
| 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, |
| 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, |
| 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, |
| 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, |
| 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, |
| 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, |
| 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, |
| 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, |
| 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, |
| 0x2d02ef8d |
| }; |
| |
| for (i = 0; i < len; i++) |
| crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); |
| |
| return ~crc32; |
| } |
| #endif |
| |
| WLAN_STATUS wlanDownloadFW(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 u4FwSize = 0; |
| PVOID prFwBuffer = NULL; |
| BOOLEAN fgReady; |
| WLAN_STATUS rDlStatus = 0; |
| WLAN_STATUS rCfgStatus = 0; |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| BOOLEAN fgIsCompressed = FALSE; |
| INIT_CMD_WIFI_DECOMPRESSION_START rFwImageInFo; |
| |
| #endif |
| |
| if (!prAdapter) |
| return WLAN_STATUS_FAILURE; |
| |
| |
| HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_READY_BITS, &fgReady); |
| |
| if (fgReady) { |
| DBGLOG(INIT, INFO, "Wi-Fi is already ON!, turn off before FW DL!\n"); |
| |
| if (wlanPowerOffWifi(prAdapter) != WLAN_STATUS_SUCCESS) |
| return WLAN_STATUS_FAILURE; |
| |
| nicpmWakeUpWiFi(prAdapter); |
| HAL_HIF_INIT(prAdapter); |
| } |
| |
| HAL_ENABLE_FWDL(prAdapter, TRUE); |
| |
| #if (MTK_WCN_HIF_SDIO == 0) |
| wlanDownloadPatch(prAdapter); |
| #endif |
| |
| DBGLOG(INIT, INFO, "FW download Start\n"); |
| |
| do { |
| /* N9 ILM+DLM */ |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_N9_FW); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_N9_FW); |
| break; |
| } |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 2, |
| IMG_DL_IDX_N9_FW, &fgIsCompressed, &rFwImageInFo); |
| if (fgIsCompressed == TRUE) |
| rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9, &rFwImageInFo); |
| else |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9); |
| |
| #else |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 2, IMG_DL_IDX_N9_FW); |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_N9); |
| #endif |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); |
| |
| if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) |
| break; |
| /* wlanCheckWifiN9Func(prAdapter); */ |
| |
| /* CR4 bin */ |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_CR4_FW); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_CR4_FW); |
| break; |
| } |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, |
| u4FwSize, CR4_FWDL_SECTION_NUM, IMG_DL_IDX_CR4_FW, &fgIsCompressed, &rFwImageInFo); |
| prAdapter->fgIsCr4FwDownloaded = TRUE; |
| if (fgIsCompressed == TRUE) |
| rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4, &rFwImageInFo); |
| else |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4); |
| |
| #else |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, prFwBuffer, |
| u4FwSize, CR4_FWDL_SECTION_NUM, IMG_DL_IDX_CR4_FW); |
| prAdapter->fgIsCr4FwDownloaded = TRUE; |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, PDA_CR4); |
| #endif |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); |
| |
| if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) |
| break; |
| |
| } while (0); |
| DBGLOG(INIT, INFO, "FW download End\n"); |
| |
| HAL_ENABLE_FWDL(prAdapter, FALSE); |
| |
| if ((rDlStatus != WLAN_STATUS_SUCCESS) || (rCfgStatus != WLAN_STATUS_SUCCESS)) |
| return WLAN_STATUS_FAILURE; |
| else |
| return WLAN_STATUS_SUCCESS; |
| |
| } |
| |
| WLAN_STATUS wlanDownloadPatch(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 u4FwSize = 0; |
| PVOID prFwBuffer = NULL; |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| UINT_8 ucIsCompressed; |
| #endif |
| if (!prAdapter) |
| return WLAN_STATUS_FAILURE; |
| |
| |
| DBGLOG(INIT, INFO, "Patch download Start\n"); |
| |
| prAdapter->rVerInfo.fgPatchIsDlByDrv = FALSE; |
| |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_PATCH); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_PATCH); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| if (wlanPatchIsDownloaded(prAdapter)) { |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); |
| DBGLOG(INIT, INFO, "No need to DL patch\n"); |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /* Patch DL */ |
| do { |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH, |
| &ucIsCompressed, NULL); |
| #else |
| wlanImageSectionDownloadStage(prAdapter, prFwBuffer, u4FwSize, 1, IMG_DL_IDX_PATCH); |
| #endif |
| wlanPatchSendComplete(prAdapter); |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); |
| |
| prAdapter->rVerInfo.fgPatchIsDlByDrv = TRUE; |
| } while (0); |
| |
| DBGLOG(INIT, INFO, "Patch download End\n"); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS wlanGetPatchInfo(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 u4FwSize = 0; |
| PVOID prFwBuffer = NULL; |
| UINT_32 u4StartOffset, u4Addr, u4Len, u4DataMode; |
| |
| if (!prAdapter) |
| return WLAN_STATUS_FAILURE; |
| |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, &u4FwSize, IMG_DL_IDX_PATCH); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", IMG_DL_IDX_PATCH); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| wlanImageSectionGetInfo(prAdapter, prFwBuffer, u4FwSize, 1, 1, IMG_DL_IDX_PATCH, |
| &u4StartOffset, &u4Addr, &u4Len, &u4DataMode); |
| |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, prFwBuffer); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to get the chip information |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| VOID wlanSetChipEcoInfo(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 hw_version, sw_version = 0; |
| struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; |
| UINT_32 chip_id = prChipInfo->chip_id; |
| /* WLAN_STATUS status; */ |
| |
| DEBUGFUNC("wlanSetChipEcoInfo.\n"); |
| |
| if (wlanAccessRegister(prAdapter, TOP_HVR, &hw_version, 0, 0) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "wlanSetChipEcoInfo >> get TOP_HVR failed.\n"); |
| } else if (wlanAccessRegister(prAdapter, TOP_FVR, &sw_version, 0, 0) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, "wlanSetChipEcoInfo >> get TOP_FVR failed.\n"); |
| } else { |
| /* success */ |
| nicSetChipHwVer((UINT_8)(GET_HW_VER(hw_version) & 0xFF)); |
| nicSetChipFactoryVer((UINT_8)((GET_HW_VER(hw_version) >> 8) & 0xF)); |
| nicSetChipSwVer((UINT_8)GET_FW_VER(sw_version)); |
| |
| /* Assign current chip version */ |
| prAdapter->chip_info->eco_ver = nicGetChipEcoVer(prAdapter); |
| } |
| |
| DBGLOG(INIT, INFO, "Chip ID[%04X] Version[E%u] HW[0x%08x] SW[0x%08x]\n", |
| chip_id, prAdapter->chip_info->eco_ver, hw_version, sw_version); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to read/write a certain N9 |
| * register by inband command in blocking mode in ROM code stage |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * u4DestAddr Address of destination address |
| * u4ImgSecSize Length of the firmware block |
| * fgReset should be set to TRUE if this is the 1st configuration |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanAccessRegister(IN P_ADAPTER_T prAdapter, |
| IN UINT_32 u4Addr, IN UINT_32 *pru4Result, IN UINT_32 u4Data, |
| IN UINT_8 ucSetQuery) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; |
| P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; |
| P_INIT_CMD_ACCESS_REG prInitCmdAccessReg; |
| P_INIT_EVENT_ACCESS_REG prInitEventAccessReg; |
| UINT_8 ucTC, ucCmdSeqNum; |
| UINT_16 cmd_size; |
| UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_ACCESS_REG)]; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanAccessRegister"); |
| |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| cmd_size = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_ACCESS_REG); |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, cmd_size); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = cmd_size; |
| |
| #if (CFG_USE_TC4_RESOURCE_FOR_INIT_CMD == 1) |
| /* 2. Use TC4's resource to download image. (TC4 as CPU) */ |
| ucTC = TC4_INDEX; |
| #else |
| /* 2. Use TC0's resource to download image. |
| * Only TC0 is allowed because SDIO HW always reports |
| * MCU's TXQ_CNT at TXQ0_CNT in CR4 architecutre) |
| */ |
| ucTC = TC0_INDEX; |
| #endif |
| |
| /* 3. increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* 4. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); |
| prInitHifTxHeader->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prInitHifTxHeader->u2PQ_ID = INIT_CMD_PQ_ID; |
| prInitHifTxHeader->ucHeaderFormat = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->ucPktFt = INIT_PKT_FT_CMD; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_ACCESS_REG; |
| |
| prInitHifTxHeader->rInitWifiCmd.ucPktTypeID = INIT_CMD_PACKET_TYPE_ID; |
| prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; |
| |
| /* 5. Setup CMD_ACCESS_REG */ |
| prInitCmdAccessReg = (P_INIT_CMD_ACCESS_REG) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); |
| prInitCmdAccessReg->ucSetQuery = ucSetQuery; |
| prInitCmdAccessReg->u4Address = u4Addr; |
| prInitCmdAccessReg->u4Data = u4Data; |
| |
| /* 6. Send CMD_ACCESS_REG command */ |
| while (1) { |
| /* 6.1 Acquire TX Resource */ |
| if (nicTxAcquireResource |
| (prAdapter, ucTC, nicTxGetPageCount(prCmdInfo->u2InfoBufLen, TRUE), TRUE) |
| == WLAN_STATUS_RESOURCES) { |
| if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); |
| goto exit; |
| } |
| continue; |
| } |
| /* 6.2 Send CMD Info Packet */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); |
| goto exit; |
| } |
| |
| break; |
| }; |
| |
| /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ |
| u4Status = wlanAccessRegisterStatus(prAdapter, ucCmdSeqNum, ucSetQuery, aucBuffer, sizeof(aucBuffer)); |
| if (ucSetQuery == 0) { |
| prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T)aucBuffer; |
| prInitEventAccessReg = (P_INIT_EVENT_ACCESS_REG)prInitHifRxHeader->rInitWifiEvent.aucBuffer; |
| |
| if (prInitEventAccessReg->u4Address != u4Addr) { |
| DBGLOG(INIT, ERROR, "Event reports address incorrect. 0x%08x, 0x%08x.\n", |
| u4Addr, prInitEventAccessReg->u4Address); |
| u4Status = WLAN_STATUS_FAILURE; |
| } |
| *pru4Result = prInitEventAccessReg->u4Data; |
| } |
| |
| exit: |
| /* 8. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to get the response of INIT_CMD_ACCESS_REG |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * ucCmdSeqNum Sequence number of previous firmware scatter |
| * ucSetQuery Read or write |
| * prEvent the pointer of buffer to store the response |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanAccessRegisterStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum, |
| IN UINT_8 ucSetQuery, IN PVOID prEvent, |
| IN UINT_32 u4EventLen) |
| { |
| /* UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_CMD_ACCESS_REG)]; */ |
| P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; |
| /* P_INIT_EVENT_CMD_RESULT prEventCmdResult; |
| * P_INIT_CMD_ACCESS_REG prEventCmdAccessReg; |
| */ |
| UINT_32 u4RxPktLength; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| UINT_8 ucPortIdx = IMG_DL_STATUS_PORT_IDX; |
| |
| ASSERT(prAdapter); |
| |
| do { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else if (nicRxWaitResponse(prAdapter, |
| ucPortIdx, |
| prEvent, |
| u4EventLen, &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| } else { |
| prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) prEvent; |
| |
| /* EID / SeqNum check */ |
| if (((prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) |
| && (ucSetQuery == 1)) || |
| ((prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_ACCESS_REG) |
| && (ucSetQuery == 0))) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, |
| "wlanAccessRegisterStatus: incorrect ucEID. ucSetQuery = 0x%x\n", ucSetQuery); |
| } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { |
| u4Status = WLAN_STATUS_FAILURE; |
| DBGLOG(INIT, ERROR, |
| "wlanAccessRegisterStatus: incorrect ucCmdSeqNum. = 0x%x\n", ucCmdSeqNum); |
| } else { |
| } |
| } |
| } while (FALSE); |
| |
| return u4Status; |
| } |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to process queued RX packets |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * prSwRfbListHead Pointer to head of RX packets link list |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) |
| { |
| P_SW_RFB_T prSwRfb, prNextSwRfb; |
| P_TX_CTRL_T prTxCtrl; |
| P_RX_CTRL_T prRxCtrl; |
| |
| ASSERT(prAdapter); |
| ASSERT(prSwRfbListHead); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| prSwRfb = prSwRfbListHead; |
| |
| do { |
| /* save next first */ |
| prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); |
| |
| switch (prSwRfb->eDst) { |
| case RX_PKT_DESTINATION_HOST: |
| nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_FORWARD: |
| nicRxProcessForwardPkt(prAdapter, prSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_HOST_WITH_FORWARD: |
| nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb); |
| break; |
| |
| case RX_PKT_DESTINATION_NULL: |
| nicRxReturnRFB(prAdapter, prSwRfb); |
| break; |
| |
| default: |
| break; |
| } |
| |
| #if CFG_HIF_RX_STARVATION_WARNING |
| prRxCtrl->u4DequeuedCnt++; |
| #endif |
| prSwRfb = prNextSwRfb; |
| } while (prSwRfb); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to purge queued TX packets |
| * by indicating failure to OS and returned to free list |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * prMsduInfoListHead Pointer to head of TX packets link list |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfoListHead); |
| |
| nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); |
| nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check if the OID handler needs timeout |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * pfnOidHandler Pointer to the OID handler |
| * |
| * @return TRUE |
| * FALSE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN UINT_32 u4Timeout) |
| { |
| PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; |
| UINT_32 i; |
| UINT_32 u4NumOfElem; |
| UINT_32 u4OidTimeout; |
| |
| apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; |
| u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); |
| |
| for (i = 0; i < u4NumOfElem; i++) { |
| if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) |
| return FALSE; |
| } |
| |
| /* Decrease OID timeout threshold if chip NoAck/resetting */ |
| if (wlanIsChipNoAck(prAdapter)) { |
| u4OidTimeout = WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING; |
| DBGLOG(INIT, INFO, "Decrease OID timeout to %ums due to NoACK/CHIP-RESET\n", u4OidTimeout); |
| } else { |
| u4OidTimeout = u4Timeout; |
| } |
| |
| /* Set OID timer for timeout check */ |
| cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), u4OidTimeout); |
| |
| return TRUE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to clear any pending OID timeout check |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to override network address |
| * if NVRAM has a valid value |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return WLAN_STATUS_FAILURE The request could not be processed |
| * WLAN_STATUS_PENDING The request has been queued for later processing |
| * WLAN_STATUS_SUCCESS The request has been processed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter) |
| { |
| const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; |
| PARAM_MAC_ADDRESS rMacAddr; |
| UINT_32 u4SysTime; |
| |
| DEBUGFUNC("wlanUpdateNetworkAddress"); |
| |
| ASSERT(prAdapter); |
| |
| if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE || IS_BMCAST_MAC_ADDR(rMacAddr) |
| || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { |
| /* eFUSE has a valid address, don't do anything */ |
| if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { |
| #if CFG_SHOW_MACADDR_SOURCE |
| DBGLOG(INIT, INFO, "Using embedded MAC address"); |
| #endif |
| return WLAN_STATUS_SUCCESS; |
| } |
| #if CFG_SHOW_MACADDR_SOURCE |
| DBGLOG(INIT, INFO, "Using dynamically generated MAC address"); |
| #endif |
| /* dynamic generate */ |
| u4SysTime = (UINT_32) kalGetTimeTick(); |
| |
| rMacAddr[0] = 0x00; |
| rMacAddr[1] = 0x08; |
| rMacAddr[2] = 0x22; |
| |
| kalMemCopy(&rMacAddr[3], &u4SysTime, 3); |
| |
| } else { |
| #if CFG_SHOW_MACADDR_SOURCE |
| DBGLOG(INIT, INFO, "Using host-supplied MAC address"); |
| #endif |
| } |
| |
| COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, rMacAddr); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to update basic configuration into firmware domain |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return WLAN_STATUS_FAILURE The request could not be processed |
| * WLAN_STATUS_PENDING The request has been queued for later processing |
| * WLAN_STATUS_SUCCESS The request has been processed |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanUpdateBasicConfig(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 ucCmdSeqNum; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| P_CMD_BASIC_CONFIG_T prCmdBasicConfig; |
| P_PSE_CMD_HDR_T prPseCmdHdr; |
| WLAN_STATUS rResult; |
| P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; |
| |
| DEBUGFUNC("wlanUpdateBasicConfig"); |
| |
| ASSERT(prAdapter); |
| |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| /* increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* compose CMD_BUILD_CONNECTION cmd pkt */ |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG_T); |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->pfCmdTimeoutHandler = NULL; |
| prCmdInfo->fgIsOid = FALSE; |
| prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; |
| prCmdInfo->fgSetQuery = TRUE; |
| prCmdInfo->fgNeedResp = FALSE; |
| prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; |
| prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG_T); |
| |
| /* Setup WIFI_CMD_T */ |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| |
| prPseCmdHdr = (P_PSE_CMD_HDR_T) (prCmdInfo->pucInfoBuffer); |
| prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; |
| prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; |
| prPseCmdHdr->u2Hf = TXD_HF_CMD; |
| prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; |
| prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; |
| |
| prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof(PSE_CMD_HDR_T); |
| |
| /* configure CMD_BASIC_CONFIG */ |
| |
| prCmdBasicConfig = (P_CMD_BASIC_CONFIG_T) (prWifiCmd->aucBuffer); |
| kalMemZero(prCmdBasicConfig, sizeof(CMD_BASIC_CONFIG_T)); |
| prCmdBasicConfig->ucNative80211 = 0; |
| prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; |
| prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; |
| prCmdBasicConfig->ucCtrlFlagAssertPath = prWifiVar->ucCtrlFlagAssertPath; |
| prCmdBasicConfig->ucCtrlFlagDebugLevel = prWifiVar->ucCtrlFlagDebugLevel; |
| |
| #if CFG_TCP_IP_CHKSUM_OFFLOAD |
| if (prAdapter->fgIsSupportCsumOffload) { |
| if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) |
| prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(2); |
| |
| if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) |
| prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(1); |
| |
| if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) |
| prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(0); |
| |
| if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) |
| prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(2); |
| |
| if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) |
| prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(1); |
| |
| if (prAdapter->u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) |
| prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(0); |
| } |
| #endif |
| |
| rResult = wlanSendCommand(prAdapter, prCmdInfo); |
| |
| if (rResult != WLAN_STATUS_SUCCESS) { |
| kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); |
| |
| return WLAN_STATUS_PENDING; |
| } |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check if the device is in RF test mode |
| * |
| * @param pfnOidHandler Pointer to the OID handler |
| * |
| * @return TRUE |
| * FALSE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| return prAdapter->fgTestMode; |
| } |
| |
| BOOLEAN wlanProcessTxFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) |
| { |
| UINT_32 u4SysTime; |
| UINT_8 ucMacHeaderLen; |
| TX_PACKET_INFO rTxPacketInfo; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prPacket); |
| prChipInfo = prAdapter->chip_info; |
| |
| if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, prPacket, &rTxPacketInfo)) { |
| |
| /* Save the value of Priority Parameter */ |
| GLUE_SET_PKT_TID(prPacket, rTxPacketInfo.ucPriorityParam); |
| |
| #if 1 |
| if (rTxPacketInfo.u2Flag) { |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_1X)) { |
| P_STA_RECORD_T prStaRec; |
| |
| DBGLOG(RSN, INFO, "T1X len=%d\n", rTxPacketInfo.u4PacketLen); |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| GLUE_GET_PKT_BSS_IDX(prPacket), |
| rTxPacketInfo.aucEthDestAddr); |
| |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); |
| /* |
| * if (secIsProtected1xFrame(prAdapter, prStaRec) && !kalIs24Of4Packet(prPacket)) |
| * GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X); |
| */ |
| } |
| |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_NON_PROTECTED_1X)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_NON_PROTECTED_1X); |
| |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_802_3)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); |
| |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_VLAN_EXIST) |
| && FEAT_SUP_LLC_VLAN_TX(prChipInfo)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); |
| |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_DHCP)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); |
| |
| if (rTxPacketInfo.u2Flag & BIT(ENUM_PKT_ARP)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); |
| } |
| #else |
| if (rTxPacketInfo.fgIs1X) { |
| P_STA_RECORD_T prStaRec; |
| |
| DBGLOG(RSN, INFO, "T1X len=%d\n", rTxPacketInfo.u4PacketLen); |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| GLUE_GET_PKT_BSS_IDX(prPacket), rTxPacketInfo.aucEthDestAddr); |
| |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_1X); |
| |
| if (secIsProtected1xFrame(prAdapter, prStaRec)) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X); |
| } |
| |
| if (rTxPacketInfo.fgIs802_3) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_802_3); |
| |
| if (rTxPacketInfo.fgIsVlanExists) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_VLAN_EXIST); |
| |
| if (rTxPacketInfo.fgIsDhcp) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_DHCP); |
| |
| if (rTxPacketInfo.fgIsArp) |
| GLUE_SET_PKT_FLAG(prPacket, ENUM_PKT_ARP); |
| #endif |
| |
| ucMacHeaderLen = ETHER_HEADER_LEN; |
| |
| /* Save the value of Header Length */ |
| GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen); |
| |
| /* Save the value of Frame Length */ |
| GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16) rTxPacketInfo.u4PacketLen); |
| |
| /* Save the value of Arrival Time */ |
| u4SysTime = (OS_SYSTIME) kalGetTimeTick(); |
| GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); |
| |
| return TRUE; |
| } |
| |
| return FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to identify 802.1x and Bluetooth-over-Wi-Fi |
| * security frames, and queued into command queue for strict ordering |
| * due to 802.1x frames before add-key OIDs are not to be encrypted |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param prPacket Pointer of native packet |
| * |
| * @return TRUE |
| * FALSE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) |
| { |
| P_CMD_INFO_T prCmdInfo; |
| P_STA_RECORD_T prStaRec; |
| UINT_8 ucBssIndex; |
| UINT_32 u4PacketLen; |
| UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; |
| P_MSDU_INFO_T prMsduInfo; |
| UINT_8 ucStaRecIndex; |
| |
| ASSERT(prAdapter); |
| ASSERT(prPacket); |
| |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, 0); |
| |
| /* Get MSDU_INFO for TxDone */ |
| prMsduInfo = cnmPktAlloc(prAdapter, 0); |
| |
| u4PacketLen = (UINT_32) GLUE_GET_PKT_FRAME_LEN(prPacket); |
| |
| if (prCmdInfo && prMsduInfo) { |
| ucBssIndex = GLUE_GET_PKT_BSS_IDX(prPacket); |
| |
| kalGetEthDestAddr(prAdapter->prGlueInfo, prPacket, aucEthDestAddr); |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, ucBssIndex, aucEthDestAddr); |
| |
| prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; |
| prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; |
| prCmdInfo->prPacket = prPacket; |
| prCmdInfo->prMsduInfo = prMsduInfo; |
| prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; |
| prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; |
| prCmdInfo->fgIsOid = FALSE; |
| prCmdInfo->fgSetQuery = TRUE; |
| prCmdInfo->fgNeedResp = FALSE; |
| |
| if (prStaRec) |
| ucStaRecIndex = prStaRec->ucIndex; |
| else |
| ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; |
| |
| /* Fill-up MSDU_INFO */ |
| nicTxSetDataPacket(prAdapter, prMsduInfo, ucBssIndex, |
| ucStaRecIndex, 0, u4PacketLen, nicTxDummyTxDone, |
| MSDU_RATE_MODE_AUTO, TX_PACKET_OS, 0, FALSE, TRUE); |
| |
| prMsduInfo->prPacket = prPacket; |
| /* No Tx descriptor template for MMPDU */ |
| prMsduInfo->fgIsTXDTemplateValid = FALSE; |
| |
| if (GLUE_TEST_PKT_FLAG(prPacket, ENUM_PKT_PROTECTED_1X)) |
| nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME, TRUE); |
| #if CFG_SUPPORT_MULTITHREAD |
| nicTxComposeSecurityFrameDesc(prAdapter, prCmdInfo, prMsduInfo->aucTxDescBuffer, NULL); |
| #endif |
| |
| kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); |
| |
| GLUE_SET_EVENT(prAdapter->prGlueInfo); |
| |
| return TRUE; |
| } |
| DBGLOG(RSN, INFO, "Failed to alloc CMD/MGMT INFO for 1X frame!!\n"); |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| cnmPktFree(prAdapter, prMsduInfo); |
| |
| |
| return FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi |
| * security frames has been sent to firmware |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param prCmdInfo Pointer of CMD_INFO_T |
| * @param pucEventBuf meaningless, only for API compatibility |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) |
| { |
| P_MSDU_INFO_T prMsduInfo = prCmdInfo->prMsduInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prCmdInfo); |
| |
| if (GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex)->eNetworkType == |
| NETWORK_TYPE_AIS && prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { |
| P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucBssIndex); |
| |
| if (prSta) { |
| kalMsleep(10); |
| if (authSendDeauthFrame(prAdapter, |
| GET_BSS_INFO_BY_INDEX(prAdapter, |
| prMsduInfo->ucBssIndex), prSta, |
| (P_SW_RFB_T) NULL, REASON_CODE_MIC_FAILURE, (PFN_TX_DONE_HANDLER) NULL |
| /* secFsmEventDeauthTxDone left upper layer handle the 60 timer */ |
| ) != WLAN_STATUS_SUCCESS) { |
| ASSERT(FALSE); |
| } |
| /* secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); */ |
| } |
| } |
| |
| kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_SUCCESS); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi |
| * security frames has failed sending to firmware |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param prCmdInfo Pointer of CMD_INFO_T |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prCmdInfo); |
| |
| kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called before AIS is starting a new scan |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter) |
| { |
| BOOLEAN fgKeepCurrOne = FALSE; |
| UINT_32 i; |
| |
| ASSERT(prAdapter); |
| |
| /* clear scanning result */ |
| if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { |
| for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { |
| if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, |
| prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { |
| fgKeepCurrOne = TRUE; |
| |
| if (i != 0) { |
| /* copy structure */ |
| kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[0]), |
| &(prAdapter->rWlanInfo.arScanResult[i]), |
| OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); |
| } |
| |
| if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { |
| if (prAdapter->rWlanInfo.apucScanResultIEs[i] != |
| &(prAdapter->rWlanInfo.aucScanIEBuf[0])) { |
| /* move IEs to head */ |
| kalMemCopy(prAdapter->rWlanInfo.aucScanIEBuf, |
| prAdapter->rWlanInfo.apucScanResultIEs[i], |
| prAdapter->rWlanInfo.arScanResult[i].u4IELength); |
| } |
| /* modify IE pointer */ |
| prAdapter->rWlanInfo.apucScanResultIEs[0] = |
| &(prAdapter->rWlanInfo.aucScanIEBuf[0]); |
| } else { |
| prAdapter->rWlanInfo.apucScanResultIEs[0] = NULL; |
| } |
| |
| break; |
| } |
| } |
| } |
| |
| if (fgKeepCurrOne == TRUE) { |
| prAdapter->rWlanInfo.u4ScanResultNum = 1; |
| prAdapter->rWlanInfo.u4ScanIEBufferUsage = ALIGN_4(prAdapter->rWlanInfo.arScanResult[0].u4IELength); |
| } else { |
| prAdapter->rWlanInfo.u4ScanResultNum = 0; |
| prAdapter->rWlanInfo.u4ScanIEBufferUsage = 0; |
| } |
| |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called when AIS received a beacon timeout event |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param arBSSID MAC address of the specified BSS |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID) |
| { |
| UINT_32 i, j, u4IELength = 0, u4IEMoveLength; |
| PUINT_8 pucIEPtr; |
| |
| ASSERT(prAdapter); |
| |
| /* clear scanning result */ |
| i = 0; |
| while (1) { |
| if (i >= prAdapter->rWlanInfo.u4ScanResultNum) |
| break; |
| |
| if (EQUAL_MAC_ADDR(arBSSID, prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { |
| /* backup current IE length */ |
| u4IELength = ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4IELength); |
| pucIEPtr = prAdapter->rWlanInfo.apucScanResultIEs[i]; |
| |
| /* removed from middle */ |
| for (j = i + 1; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { |
| kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[j - 1]), |
| &(prAdapter->rWlanInfo.arScanResult[j]), |
| OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); |
| |
| prAdapter->rWlanInfo.apucScanResultIEs[j - 1] = |
| prAdapter->rWlanInfo.apucScanResultIEs[j]; |
| } |
| |
| prAdapter->rWlanInfo.u4ScanResultNum--; |
| |
| /* remove IE buffer if needed := move rest of IE buffer */ |
| if (u4IELength > 0) { |
| u4IEMoveLength = prAdapter->rWlanInfo.u4ScanIEBufferUsage - |
| (((ULONG) pucIEPtr) + u4IELength - |
| ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); |
| |
| kalMemCopy(pucIEPtr, (PUINT_8) (((ULONG) pucIEPtr) + u4IELength), u4IEMoveLength); |
| |
| prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; |
| |
| /* correction of pointers to IE buffer */ |
| for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { |
| if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { |
| prAdapter->rWlanInfo.apucScanResultIEs[j] = |
| (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - |
| u4IELength); |
| } |
| } |
| } |
| } |
| |
| i++; |
| } |
| |
| } |
| |
| #if CFG_TEST_WIFI_DIRECT_GO |
| VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) |
| { |
| #if 0 |
| P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; |
| |
| prMsgFuncSwitch = |
| (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); |
| if (!prMsgFuncSwitch) { |
| ASSERT(FALSE); |
| return; |
| } |
| |
| prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; |
| prMsgFuncSwitch->fgIsFuncOn = TRUE; |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); |
| #endif |
| |
| } |
| |
| VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) |
| { |
| |
| P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; |
| UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
| |
| prMsgConnReq = |
| (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); |
| if (!prMsgConnReq) { |
| ASSERT(FALSE); |
| return; |
| } |
| |
| prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; |
| |
| /*=====Param Modified for test=====*/ |
| COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); |
| prMsgConnReq->fgIsTobeGO = TRUE; |
| prMsgConnReq->fgIsPersistentGroup = FALSE; |
| |
| /*=====Param Modified for test=====*/ |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); |
| |
| } |
| #endif |
| |
| VOID wlanPrintVersion(IN P_ADAPTER_T prAdapter) |
| { |
| P_WIFI_VER_INFO_T prVerInfo = &prAdapter->rVerInfo; |
| tailer_format_t *prTailer; |
| UINT_8 aucBuf[32], aucDate[32]; |
| |
| kalMemCopy(aucBuf, prVerInfo->aucFwBranchInfo, 4); |
| aucBuf[4] = '\0'; |
| DBGLOG(SW4, INFO, "N9 FW version %s-%u.%u.%u[DEC] (%s)\n", |
| aucBuf, (prVerInfo->u2FwOwnVersion >> 8), (prVerInfo->u2FwOwnVersion & BITS(0, 7)), |
| prVerInfo->ucFwBuildNumber, prVerInfo->aucFwDateCode); |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| if (prVerInfo->fgIsN9CompressedFW) { |
| tailer_format_t_2 *prTailer; |
| |
| prTailer = &prVerInfo->rN9Compressedtailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| } else { |
| prTailer = &prVerInfo->rN9tailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| } |
| if (prVerInfo->fgIsCR4CompressedFW) { |
| tailer_format_t_2 *prTailer; |
| |
| prTailer = &prVerInfo->rCR4Compressedtailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| } else { |
| prTailer = &prVerInfo->rCR4tailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| } |
| #else |
| prTailer = &prVerInfo->rN9tailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "N9 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| |
| prTailer = &prVerInfo->rCR4tailer; |
| kalMemCopy(aucBuf, prTailer->ram_version, 10); |
| aucBuf[10] = '\0'; |
| DBGLOG(SW4, INFO, "CR4 tailer version %s (%s) info %u:E%u\n", |
| aucBuf, prTailer->ram_built_date, prTailer->chip_info, |
| prTailer->eco_code + 1); |
| #endif |
| if (!prVerInfo->fgPatchIsDlByDrv) { |
| DBGLOG(SW4, INFO, "Patch is not downloaded by driver, read patch binary\n"); |
| wlanGetPatchInfo(prAdapter); |
| } |
| |
| kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, 4); |
| aucBuf[4] = '\0'; |
| kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, 16); |
| aucDate[16] = '\0'; |
| DBGLOG(SW4, INFO, "Patch platform %s version 0x%04X %s\n", |
| aucBuf, prVerInfo->rPatchHeader.u4PatchVersion, aucDate); |
| |
| DBGLOG(SW4, INFO, "Drv version %u.%u[DEC]\n", |
| (prVerInfo->u2FwPeerVersion >> 8), (prVerInfo->u2FwPeerVersion & BITS(0, 7))); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to retrieve NIC capability from firmware |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; |
| UINT_8 ucCmdSeqNum; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| UINT_32 u4RxPktLength; |
| UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY_T)]; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| P_WIFI_EVENT_T prEvent; |
| P_EVENT_NIC_CAPABILITY_T prEventNicCapability; |
| P_PSE_CMD_HDR_T prPseCmdHdr; |
| |
| ASSERT(prAdapter); |
| |
| DEBUGFUNC("wlanQueryNicCapability"); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY_T)); |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| /* increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* compose CMD_BUILD_CONNECTION cmd pkt */ |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY_T); |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->fgIsOid = FALSE; |
| prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; |
| prCmdInfo->fgSetQuery = FALSE; |
| prCmdInfo->fgNeedResp = TRUE; |
| prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; |
| prCmdInfo->u4SetInfoLen = 0; |
| |
| /* Setup WIFI_CMD_T */ |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| |
| prPseCmdHdr = (P_PSE_CMD_HDR_T) (prCmdInfo->pucInfoBuffer); |
| prPseCmdHdr->u2Qidx = TXD_Q_IDX_MCU_RQ0; |
| prPseCmdHdr->u2Pidx = TXD_P_IDX_MCU; |
| prPseCmdHdr->u2Hf = TXD_HF_CMD; |
| prPseCmdHdr->u2Ft = TXD_FT_LONG_FORMAT; |
| prPseCmdHdr->u2PktFt = TXD_PKT_FT_CMD; |
| |
| prWifiCmd->u2Length = prWifiCmd->u2TxByteCount - sizeof(PSE_CMD_HDR_T); |
| |
| wlanSendCommand(prAdapter, prCmdInfo); |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| while (TRUE) { |
| if (nicRxWaitResponse(prAdapter, 1, aucBuffer, |
| sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY_T), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| |
| DBGLOG(INIT, WARN, "%s: wait for event failed!\n", __func__); |
| return WLAN_STATUS_FAILURE; |
| } |
| /* header checking .. */ |
| prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; |
| if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) { |
| DBGLOG(INIT, WARN, "%s: skip unexpected Rx pkt type[0x%04x]\n", __func__, |
| prRxStatus->u2PktTYpe); |
| continue; |
| } |
| |
| prEvent = (P_WIFI_EVENT_T) aucBuffer; |
| if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) { |
| DBGLOG(INIT, WARN, "%s: skip unexpected event ID[0x%02x]\n", __func__, prEvent->ucEID); |
| continue; |
| } else { |
| break; |
| } |
| } |
| |
| prEventNicCapability = (P_EVENT_NIC_CAPABILITY_T) (prEvent->aucBuffer); |
| |
| prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; |
| kalMemCopy(prAdapter->rVerInfo.aucFwBranchInfo, prEventNicCapability->aucBranchInfo, 4); |
| prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; |
| prAdapter->rVerInfo.ucFwBuildNumber = prEventNicCapability->ucFwBuildNumber; |
| kalMemCopy(prAdapter->rVerInfo.aucFwDateCode, prEventNicCapability->aucDateCode, 16); |
| prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; |
| prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; |
| prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; |
| prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) |
| (!IS_BMCAST_MAC_ADDR(prEventNicCapability->aucMacAddr) && |
| !EQUAL_MAC_ADDR(aucZeroMacAddr, prEventNicCapability->aucMacAddr)); |
| |
| COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, prEventNicCapability->aucMacAddr); |
| COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prEventNicCapability->aucMacAddr); |
| |
| prAdapter->rWifiVar.ucStaVht &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucApVht &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucP2pGoVht &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucP2pGcVht &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| |
| prAdapter->rWifiVar.ucStaVhtBfee &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucStaVhtMuBfee &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucStaVhtBfer &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| |
| prAdapter->rWifiVar.ucVhtAmsduInAmpduRx &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| prAdapter->rWifiVar.ucVhtAmsduInAmpduTx &= (!(prEventNicCapability->ucHwNotSupportAC)); |
| |
| if (prEventNicCapability->ucHwNotSupportAC) { |
| prAdapter->rWifiVar.ucStaBandwidth = MAX_BW_40MHZ; |
| prAdapter->rWifiVar.ucSta5gBandwidth = MAX_BW_40MHZ; |
| prAdapter->rWifiVar.ucP2p5gBandwidth = MAX_BW_40MHZ; |
| prAdapter->rWifiVar.ucApBandwidth = MAX_BW_40MHZ; |
| prAdapter->rWifiVar.ucAp5gBandwidth = MAX_BW_40MHZ; |
| } |
| |
| prAdapter->u4FwCompileFlag0 = prEventNicCapability->u4CompileFlag0; |
| prAdapter->u4FwCompileFlag1 = prEventNicCapability->u4CompileFlag1; |
| prAdapter->u4FwFeatureFlag0 = prEventNicCapability->u4FeatureFlag0; |
| prAdapter->u4FwFeatureFlag1 = prEventNicCapability->u4FeatureFlag1; |
| |
| if (prEventNicCapability->ucHwSetNss1x1) |
| prAdapter->rWifiVar.ucNSS = 1; |
| |
| #if CFG_SUPPORT_DBDC |
| if (prEventNicCapability->ucHwNotSupportDBDC) |
| prAdapter->rWifiVar.ucDbdcMode = DBDC_MODE_DISABLED; |
| #endif |
| |
| #if CFG_ENABLE_CAL_LOG |
| DBGLOG(INIT, TRACE, "RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", |
| prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); |
| #endif |
| |
| #if CFG_SISO_SW_DEVELOP |
| if ((!prEventNicCapability->ucHwNotSupportDBDC) && (!prEventNicCapability->ucHwSetNss1x1)) { |
| prAdapter->rWifiFemCfg.u2WifiPath = |
| (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); |
| } else if ((!prEventNicCapability->ucHwNotSupportDBDC) && (prEventNicCapability->ucHwSetNss1x1)) { |
| prAdapter->rWifiFemCfg.u2WifiPath = |
| (WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1); |
| } else if ((prEventNicCapability->ucHwNotSupportDBDC) && (prEventNicCapability->ucHwSetNss1x1)) { |
| prAdapter->rWifiFemCfg.u2WifiPath = |
| (WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1); |
| } else if ((prEventNicCapability->ucHwNotSupportDBDC) && (!prEventNicCapability->ucHwSetNss1x1)) { |
| prAdapter->rWifiFemCfg.u2WifiPath = |
| (WLAN_FLAG_2G4_WF0 | WLAN_FLAG_5G_WF0 | WLAN_FLAG_2G4_WF1 | WLAN_FLAG_5G_WF1); |
| } else |
| ASSERT(0); |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #if TXPWR_USE_PDSLOPE |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) |
| { |
| UINT_8 ucCmdSeqNum; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| UINT_32 u4RxPktLength; |
| UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| P_WIFI_EVENT_T prEvent; |
| P_CMD_ACCESS_REG prCmdMcrQuery; |
| |
| ASSERT(prAdapter); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| /* increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* compose CMD_BUILD_CONNECTION cmd pkt */ |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; |
| prCmdInfo->fgIsOid = FALSE; |
| prCmdInfo->ucCID = CMD_ID_ACCESS_REG; |
| prCmdInfo->fgSetQuery = FALSE; |
| prCmdInfo->fgNeedResp = TRUE; |
| prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; |
| prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); |
| |
| /* Setup WIFI_CMD_T */ |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, sizeof(CMD_ACCESS_REG)); |
| |
| wlanSendCommand(prAdapter, prCmdInfo); |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| if (nicRxWaitResponse(prAdapter, |
| 1, |
| aucBuffer, |
| sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG), &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| return WLAN_STATUS_FAILURE; |
| } |
| /* header checking .. */ |
| prRxStatus = (P_HW_MAC_RX_DESC_T) aucBuffer; |
| if (prRxStatus->u2PktTYpe != RXM_RXD_PKT_TYPE_SW_EVENT) |
| return WLAN_STATUS_FAILURE; |
| |
| prEvent = (P_WIFI_EVENT_T) aucBuffer; |
| |
| if (prEvent->ucEID != EVENT_ID_ACCESS_REG) |
| return WLAN_STATUS_FAILURE; |
| |
| prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); |
| prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; |
| prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| static INT_32 wlanIntRound(INT_32 au4Input) |
| { |
| |
| if (au4Input >= 0) { |
| if ((au4Input % 10) == 5) { |
| au4Input = au4Input + 5; |
| return au4Input; |
| } |
| } |
| |
| if (au4Input < 0) { |
| if ((au4Input % 10) == -5) { |
| au4Input = au4Input - 5; |
| return au4Input; |
| } |
| } |
| |
| return au4Input; |
| } |
| |
| static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) |
| { |
| |
| PARAM_MCR_RW_STRUCT_T rMcrRdInfo; |
| INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; |
| INT_8 auTxPwrOffset_Round; |
| |
| rMcrRdInfo.u4McrOffset = 0x60205c68; |
| rMcrRdInfo.u4McrData = 0; |
| au4TxPwrOffset = au4Input; |
| wlanQueryPdMcr(prAdapter, &rMcrRdInfo); |
| |
| au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); |
| au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; |
| |
| au4TxPwrOffset_Round = -au4TxPwrOffset_Round; |
| |
| if (au4TxPwrOffset_Round < -128) |
| au4TxPwrOffset_Round = 128; |
| else if (au4TxPwrOffset_Round < 0) |
| au4TxPwrOffset_Round += 256; |
| else if (au4TxPwrOffset_Round > 127) |
| au4TxPwrOffset_Round = 127; |
| |
| auTxPwrOffset_Round = (UINT_8) au4TxPwrOffset_Round; |
| |
| return au4TxPwrOffset_Round; |
| } |
| |
| #endif |
| |
| #if CFG_SUPPORT_NVRAM_5G |
| WLAN_STATUS wlanLoadManufactureData_5G(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) |
| { |
| |
| P_BANDEDGE_5G_T pr5GBandEdge; |
| |
| ASSERT(prAdapter); |
| |
| pr5GBandEdge = &prRegInfo->prOldEfuseMapping->r5GBandEdgePwr; |
| |
| /* 1. set band edge tx power if available */ |
| if (pr5GBandEdge->uc5GBandEdgePwrUsed != 0) { |
| CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; |
| |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = 0; |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM20; |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM40; |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM80 = pr5GBandEdge->c5GBandEdgeMaxPwrOFDM80; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_EDGE_TXPWR_LIMIT_5G, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); |
| |
| /* dumpMemory8(&rCmdEdgeTxPwrLimit,4); */ |
| } |
| |
| DEBUGFUNC("wlanLoadManufactureData_5G"); |
| |
| /*2.set channel offset for 8 sub-band */ |
| if (prRegInfo->prOldEfuseMapping->uc5GChannelOffsetVaild) { |
| CMD_POWER_OFFSET_T rCmdPowerOffset; |
| UINT_8 i; |
| |
| rCmdPowerOffset.ucBand = BAND_5G; |
| for (i = 0; i < MAX_SUBBAND_NUM_5G; i++) |
| rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->auc5GChOffset[i]; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_CHANNEL_PWR_OFFSET, |
| TRUE, |
| FALSE, |
| FALSE, NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); |
| /* dumpMemory8(&rCmdPowerOffset,9); */ |
| } |
| |
| /*3.set 5G AC power */ |
| if (prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid) { |
| |
| CMD_TX_AC_PWR_T rCmdAcPwr; |
| |
| kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr, sizeof(AC_PWR_SETTING_STRUCT)); |
| rCmdAcPwr.ucBand = BAND_5G; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_80211AC_TX_PWR, |
| TRUE, |
| FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), (PUINT_8) &rCmdAcPwr, NULL, 0); |
| /* dumpMemory8(&rCmdAcPwr,9); */ |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| #endif |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to load manufacture data from NVRAM |
| * if available and valid |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param prRegInfo Pointer of REG_INFO_T |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) |
| { |
| #if CFG_SUPPORT_RDD_TEST_MODE |
| CMD_RDD_CH_T rRddParam; |
| #endif |
| CMD_NVRAM_SETTING_T rCmdNvramSettings; |
| |
| ASSERT(prAdapter); |
| |
| /* 1. Version Check */ |
| kalGetConfigurationVersion(prAdapter->prGlueInfo, |
| &(prAdapter->rVerInfo.u2Part1CfgOwnVersion), |
| &(prAdapter->rVerInfo.u2Part1CfgPeerVersion), |
| &(prAdapter->rVerInfo.u2Part2CfgOwnVersion), |
| &(prAdapter->rVerInfo.u2Part2CfgPeerVersion)); |
| |
| #if (CFG_SW_NVRAM_VERSION_CHECK == 1) |
| if (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION) { |
| return WLAN_STATUS_FAILURE; |
| } |
| #endif |
| |
| /* MT6620 E1/E2 would be ignored directly */ |
| if (prAdapter->rVerInfo.u2Part1CfgOwnVersion == 0x0001) { |
| prRegInfo->ucTxPwrValid = 1; |
| } else { |
| /* 2. Load TX power gain parameters if valid */ |
| if (prRegInfo->ucTxPwrValid != 0) { |
| /* send to F/W */ |
| |
| nicUpdateTxPower(prAdapter, (P_CMD_TX_PWR_T) (&(prRegInfo->rTxPwr))); |
| } |
| } |
| |
| /* Todo : Temp Open 20150806 Sam */ |
| prRegInfo->ucEnable5GBand = 1; |
| prRegInfo->ucSupport5GBand = 1; |
| |
| /* 3. Check if needs to support 5GHz */ |
| if (prRegInfo->ucEnable5GBand) { |
| #if CFG_SUPPORT_NVRAM_5G |
| wlanLoadManufactureData_5G(prAdapter, prRegInfo); |
| #endif |
| /* check if it is disabled by hardware */ |
| if (prAdapter->fgIsHw5GBandDisabled || prRegInfo->ucSupport5GBand == 0) |
| prAdapter->fgEnable5GBand = FALSE; |
| else |
| prAdapter->fgEnable5GBand = TRUE; |
| } else |
| prAdapter->fgEnable5GBand = FALSE; |
| |
| /* 4. Send EFUSE data */ |
| #if CFG_SUPPORT_NVRAM_5G |
| /* If NvRAM read failed, this pointer will be NULL */ |
| if (prRegInfo->prOldEfuseMapping) { |
| /*2.set channel offset for 3 sub-band */ |
| if (prRegInfo->prOldEfuseMapping->ucChannelOffsetVaild) { |
| CMD_POWER_OFFSET_T rCmdPowerOffset; |
| UINT_8 i; |
| |
| rCmdPowerOffset.ucBand = BAND_2G4; |
| for (i = 0; i < 3; i++) |
| rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->aucChOffset[i]; |
| rCmdPowerOffset.ucSubBandOffset[i] = prRegInfo->prOldEfuseMapping->acAllChannelOffset; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_CHANNEL_PWR_OFFSET, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, NULL, sizeof(rCmdPowerOffset), (PUINT_8) &rCmdPowerOffset, NULL, 0); |
| /* dumpMemory8(&rCmdPowerOffset,9); */ |
| } |
| } |
| #else |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_PHY_PARAM, |
| TRUE, |
| FALSE, |
| FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); |
| |
| #endif |
| /*RSSI path compasation */ |
| if (prRegInfo->ucRssiPathCompasationUsed) { |
| CMD_RSSI_PATH_COMPASATION_T rCmdRssiPathCompasation; |
| |
| rCmdRssiPathCompasation.c2GRssiCompensation = prRegInfo->rRssiPathCompasation.c2GRssiCompensation; |
| rCmdRssiPathCompasation.c5GRssiCompensation = prRegInfo->rRssiPathCompasation.c5GRssiCompensation; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_PATH_COMPASATION, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(rCmdRssiPathCompasation), (PUINT_8) &rCmdRssiPathCompasation, NULL, 0); |
| } |
| #if CFG_SUPPORT_RDD_TEST_MODE |
| rRddParam.ucRddTestMode = (UINT_8) prRegInfo->u4RddTestMode; |
| rRddParam.ucRddShutCh = (UINT_8) prRegInfo->u4RddShutFreq; |
| rRddParam.ucRddStartCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStartFreq); |
| rRddParam.ucRddStopCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStopFreq); |
| rRddParam.ucRddDfs = (UINT_8) prRegInfo->u4RddDfs; |
| prAdapter->ucRddStatus = 0; |
| nicUpdateRddTestMode(prAdapter, (P_CMD_RDD_CH_T) (&rRddParam)); |
| #endif |
| |
| /* 5. Get 16-bits Country Code and Bandwidth */ |
| prAdapter->rWifiVar.rConnSettings.u2CountryCode = |
| (((UINT_16) prRegInfo->au2CountryCode[0]) << 8) | (((UINT_16) prRegInfo->au2CountryCode[1]) & BITS(0, 7)); |
| |
| #if 0 /* Bandwidth control will be controlled by GUI. 20110930 |
| * So ignore the setting from registry/NVRAM |
| */ |
| prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = |
| prRegInfo->uc2G4BwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; |
| prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = |
| prRegInfo->uc5GBwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; |
| #endif |
| |
| /* 6. Set domain and channel information to chip */ |
| rlmDomainSendCmd(prAdapter, FALSE); |
| |
| /* Update supported channel list in channel table */ |
| wlanUpdateChannelTable(prAdapter->prGlueInfo); |
| |
| |
| /* 7. set band edge tx power if available */ |
| if (prRegInfo->fg2G4BandEdgePwrUsed) { |
| CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; |
| |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; |
| rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_EDGE_TXPWR_LIMIT, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8) &rCmdEdgeTxPwrLimit, NULL, 0); |
| } |
| /*8. Set 2.4G AC power */ |
| if (prRegInfo->prOldEfuseMapping && prRegInfo->prOldEfuseMapping->uc11AcTxPwrValid2G) { |
| |
| CMD_TX_AC_PWR_T rCmdAcPwr; |
| |
| kalMemCopy(&rCmdAcPwr.rAcPwr, &prRegInfo->prOldEfuseMapping->r11AcTxPwr2G, |
| sizeof(AC_PWR_SETTING_STRUCT)); |
| rCmdAcPwr.ucBand = BAND_2G4; |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_80211AC_TX_PWR, |
| TRUE, |
| FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_AC_PWR_T), (PUINT_8) &rCmdAcPwr, NULL, 0); |
| /* dumpMemory8(&rCmdAcPwr,9); */ |
| } |
| /* 9. Send the full Parameters of NVRAM to FW */ |
| |
| kalMemCopy(&rCmdNvramSettings.rNvramSettings, |
| &prRegInfo->prNvramSettings->u2Part1OwnVersion, sizeof(WIFI_CFG_PARAM_STRUCT)); |
| ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_SET_NVRAM_SETTINGS, |
| TRUE, |
| FALSE, |
| FALSE, NULL, NULL, sizeof(rCmdNvramSettings), (PUINT_8) &rCmdNvramSettings, NULL, 0); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check |
| * Media Stream Mode is set to non-default value or not, |
| * and clear to default value if above criteria is met |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return TRUE |
| * The media stream mode was non-default value and has been reset |
| * FALSE |
| * The media stream mode is default value |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| if (prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode != 0) { |
| prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; |
| |
| return TRUE; |
| } else { |
| return FALSE; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check if any pending timer has expired |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| cnmTimerDoTimeOutCheck(prAdapter); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check if any pending mailbox message |
| * to be handled |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 i; |
| |
| ASSERT(prAdapter); |
| |
| for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) |
| mboxRcvAllMsg(prAdapter, (ENUM_MBOX_ID_T) i); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to enqueue a single TX packet into CORE |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * prNativePacket Pointer of Native Packet |
| * |
| * @return WLAN_STATUS_SUCCESS |
| * WLAN_STATUS_RESOURCES |
| * WLAN_STATUS_INVALID_PACKET |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| P_MSDU_INFO_T prMsduInfo; |
| |
| ASSERT(prAdapter); |
| |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| prMsduInfo = cnmPktAlloc(prAdapter, 0); |
| |
| if (!prMsduInfo) |
| return WLAN_STATUS_RESOURCES; |
| |
| if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket)) { |
| /* prMsduInfo->eSrc = TX_PACKET_OS; */ |
| |
| /* Tx profiling */ |
| wlanTxProfilingTagMsdu(prAdapter, prMsduInfo, TX_PROF_TAG_DRV_ENQUE); |
| |
| /* enqueue to QM */ |
| nicTxEnqueueMsdu(prAdapter, prMsduInfo); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); |
| |
| nicTxReturnMsduInfo(prAdapter, prMsduInfo); |
| |
| return WLAN_STATUS_INVALID_PACKET; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to flush pending TX packets in CORE |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| return nicTxFlush(prAdapter); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief this function sends pending MSDU_INFO_T to MT6620 |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * @param pfgHwAccess Pointer for tracking LP-OWN status |
| * |
| * @retval WLAN_STATUS_SUCCESS Reset is done successfully. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| P_MSDU_INFO_T prMsduInfo; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| ASSERT(prAdapter); |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| #if !CFG_SUPPORT_MULTITHREAD |
| ASSERT(pfgHwAccess); |
| #endif |
| |
| /* <1> dequeue packet by txDequeuTxPackets() */ |
| #if CFG_SUPPORT_MULTITHREAD |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| prMsduInfo = qmDequeueTxPacketsMthread(prAdapter, &prTxCtrl->rTc); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| #else |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| prMsduInfo = qmDequeueTxPackets(prAdapter, &prTxCtrl->rTc); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); |
| #endif |
| if (prMsduInfo != NULL) { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { |
| #if !CFG_SUPPORT_MULTITHREAD |
| /* <2> Acquire LP-OWN if necessary */ |
| if (*pfgHwAccess == FALSE) { |
| *pfgHwAccess = TRUE; |
| |
| wlanAcquirePowerControl(prAdapter); |
| } |
| #endif |
| /* <3> send packets */ |
| #if CFG_SUPPORT_MULTITHREAD |
| nicTxMsduInfoListMthread(prAdapter, prMsduInfo); |
| #else |
| nicTxMsduInfoList(prAdapter, prMsduInfo); |
| #endif |
| /* <4> update TC by txAdjustTcQuotas() */ |
| nicTxAdjustTcq(prAdapter); |
| } else |
| wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to acquire power control from firmware |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| /* DBGLOG(INIT, INFO, ("Acquire Power Ctrl\n")); */ |
| |
| ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); |
| |
| /* Reset sleepy state */ |
| if (prAdapter->fgWiFiInSleepyState == TRUE) |
| prAdapter->fgWiFiInSleepyState = FALSE; |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to release power control to firmware |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| /* DBGLOG(INIT, INFO, ("Release Power Ctrl\n")); */ |
| |
| RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to report currently pending TX frames count |
| * (command packets are not included) |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return number of pending TX frames |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter) |
| { |
| P_TX_CTRL_T prTxCtrl; |
| UINT_32 u4Num; |
| |
| ASSERT(prAdapter); |
| prTxCtrl = &prAdapter->rTxCtrl; |
| |
| u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + |
| (UINT_32) GLUE_GET_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); |
| |
| return u4Num; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to report current ACPI state |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return ACPI_STATE_D0 Normal Operation Mode |
| * ACPI_STATE_D3 Suspend Mode |
| */ |
| /*----------------------------------------------------------------------------*/ |
| ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| |
| return prAdapter->rAcpiState; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to update current ACPI state only |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param ePowerState ACPI_STATE_D0 Normal Operation Mode |
| * ACPI_STATE_D3 Suspend Mode |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState) |
| { |
| ASSERT(prAdapter); |
| ASSERT(ePowerState <= ACPI_STATE_D3); |
| |
| prAdapter->rAcpiState = ePowerState; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to query ECO version from HIFSYS CR |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return zero Unable to retrieve ECO version information |
| * non-zero ECO version (1-based) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 ucEcoVersion; |
| |
| ASSERT(prAdapter); |
| |
| #if CFG_MULTI_ECOVER_SUPPORT |
| ucEcoVersion = nicGetChipEcoVer(prAdapter); |
| DBGLOG(INIT, TRACE, "%s: %u\n", __func__, ucEcoVersion); |
| return ucEcoVersion; |
| #else |
| if (nicVerifyChipID(prAdapter) == TRUE) |
| return prAdapter->ucRevID + 1; |
| else |
| return 0; |
| #endif |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to setting the default Tx Power configuration |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return zero Unable to retrieve ECO version information |
| * non-zero ECO version (1-based) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 i; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_SET_TXPWR_CTRL_T prTxpwr; |
| |
| ASSERT(prGlueInfo); |
| |
| prTxpwr = &prGlueInfo->rTxPwr; |
| |
| prTxpwr->c2GLegacyStaPwrOffset = 0; |
| prTxpwr->c2GHotspotPwrOffset = 0; |
| prTxpwr->c2GP2pPwrOffset = 0; |
| prTxpwr->c2GBowPwrOffset = 0; |
| prTxpwr->c5GLegacyStaPwrOffset = 0; |
| prTxpwr->c5GHotspotPwrOffset = 0; |
| prTxpwr->c5GP2pPwrOffset = 0; |
| prTxpwr->c5GBowPwrOffset = 0; |
| prTxpwr->ucConcurrencePolicy = 0; |
| for (i = 0; i < 3; i++) |
| prTxpwr->acReserved1[i] = 0; |
| |
| for (i = 0; i < 14; i++) |
| prTxpwr->acTxPwrLimit2G[i] = 63; |
| |
| for (i = 0; i < 4; i++) |
| prTxpwr->acTxPwrLimit5G[i] = 63; |
| |
| for (i = 0; i < 2; i++) |
| prTxpwr->acReserved2[i] = 0; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to |
| * set preferred band configuration corresponding to network type |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param eBand Given band |
| * @param ucBssIndex BSS Info Index |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN UINT_8 ucBssIndex) |
| { |
| ASSERT(prAdapter); |
| ASSERT(eBand <= BAND_NUM); |
| ASSERT(ucBssIndex <= MAX_BSS_INDEX); |
| |
| |
| /* 1. set prefer band according to network type */ |
| prAdapter->aePreferBand[ucBssIndex] = eBand; |
| |
| /* 2. remove buffered BSS descriptors correspondingly */ |
| if (eBand == BAND_2G4) |
| scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, ucBssIndex); |
| else if (eBand == BAND_5G) |
| scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, ucBssIndex); |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to |
| * get channel information corresponding to specified network type |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * @param ucBssIndex BSS Info Index |
| * |
| * @return channel number |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) |
| { |
| P_BSS_INFO_T prBssInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(ucBssIndex <= MAX_BSS_INDEX); |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| return prBssInfo->ucPrimaryChannel; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to |
| * check unconfigured system properties and generate related message on |
| * scan list to notify users |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter) |
| { |
| #if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) |
| const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; |
| BOOLEAN fgIsConfExist = TRUE; |
| BOOLEAN fgGenErrMsg = FALSE; |
| P_REG_INFO_T prRegInfo = NULL; |
| #if 0 |
| const UINT_8 aucBCAddr[] = BC_MAC_ADDR; |
| P_WLAN_BEACON_FRAME_T prBeacon = NULL; |
| P_IE_SSID_T prSsid = NULL; |
| UINT_32 u4ErrCode = 0; |
| UINT_8 aucErrMsg[32]; |
| PARAM_SSID_T rSsid; |
| PARAM_802_11_CONFIG_T rConfiguration; |
| PARAM_RATES_EX rSupportedRates; |
| #endif |
| #endif |
| |
| DEBUGFUNC("wlanCheckSystemConfiguration"); |
| |
| ASSERT(prAdapter); |
| |
| #if (CFG_NVRAM_EXISTENCE_CHECK == 1) |
| if (kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { |
| fgIsConfExist = FALSE; |
| fgGenErrMsg = TRUE; |
| } |
| #endif |
| |
| #if (CFG_SW_NVRAM_VERSION_CHECK == 1) |
| prRegInfo = kalGetConfiguration(prAdapter->prGlueInfo); |
| |
| #if (CFG_SUPPORT_PWR_LIMIT_COUNTRY == 1) |
| if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION/* NVRAM */ |
| || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION |
| || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && |
| (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) |
| || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) |
| || prRegInfo->ucTxPwrValid == 0 |
| || prAdapter->fgIsPowerLimitTableValid == FALSE)) |
| fgGenErrMsg = TRUE; |
| #else |
| if (fgIsConfExist == TRUE && (prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION/* NVRAM */ |
| || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION |
| || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && |
| (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) |
| || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) |
| || prRegInfo->ucTxPwrValid == 0)) |
| fgGenErrMsg = TRUE; |
| #endif |
| #endif |
| #if 0/* remove NVRAM WARNING in scan result */ |
| if (fgGenErrMsg == TRUE) { |
| prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); |
| |
| /* initialization */ |
| kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); |
| |
| /* prBeacon initialization */ |
| prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; |
| COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); |
| COPY_MAC_ADDR(prBeacon->aucSrcAddr, aucZeroMacAddr); |
| COPY_MAC_ADDR(prBeacon->aucBSSID, aucZeroMacAddr); |
| prBeacon->u2BeaconInterval = 100; |
| prBeacon->u2CapInfo = CAP_INFO_ESS; |
| |
| /* prSSID initialization */ |
| prSsid = (P_IE_SSID_T) (&prBeacon->aucInfoElem[0]); |
| prSsid->ucId = ELEM_ID_SSID; |
| |
| /* rConfiguration initialization */ |
| rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); |
| rConfiguration.u4BeaconPeriod = 100; |
| rConfiguration.u4ATIMWindow = 1; |
| rConfiguration.u4DSConfig = 2412; |
| rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); |
| |
| /* rSupportedRates initialization */ |
| kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); |
| } |
| #if (CFG_NVRAM_EXISTENCE_CHECK == 1) |
| #define NVRAM_ERR_MSG "NVRAM WARNING: Err = 0x01" |
| if (kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { |
| COPY_SSID(prSsid->aucSSID, prSsid->ucLength, NVRAM_ERR_MSG, (UINT_8) (strlen(NVRAM_ERR_MSG))); |
| |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) prBeacon, |
| OFFSET_OF(WLAN_BEACON_FRAME_T, |
| aucInfoElem) + OFFSET_OF(IE_SSID_T, aucSSID) + prSsid->ucLength, 1, 0); |
| |
| COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); |
| nicAddScanResult(prAdapter, |
| prBeacon->aucBSSID, |
| &rSsid, |
| 0, |
| 0, |
| PARAM_NETWORK_TYPE_FH, |
| &rConfiguration, |
| NET_TYPE_INFRA, |
| rSupportedRates, |
| OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, |
| aucSSID) + |
| prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, |
| (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); |
| } |
| #endif |
| |
| #if (CFG_SW_NVRAM_VERSION_CHECK == 1) |
| #define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" |
| if (fgIsConfExist == TRUE) { |
| if ((prAdapter->rVerInfo.u2Part1CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2Part1CfgOwnVersion < CFG_DRV_PEER_VERSION |
| || prAdapter->rVerInfo.u2Part2CfgOwnVersion < CFG_DRV_PEER_VERSION /* NVRAM */ |
| || prAdapter->rVerInfo.u2FwPeerVersion > CFG_DRV_OWN_VERSION |
| || prAdapter->rVerInfo.u2FwOwnVersion < CFG_DRV_PEER_VERSION)) |
| u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; |
| |
| if (prRegInfo->ucTxPwrValid == 0) |
| u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; |
| |
| if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) |
| || EQUAL_MAC_ADDR(aucZeroMacAddr, |
| prRegInfo->aucMacAddr))) { |
| u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; |
| } |
| #if CFG_SUPPORT_PWR_LIMIT_COUNTRY |
| if (prAdapter->fgIsPowerLimitTableValid == FALSE) |
| u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; |
| #endif |
| if (u4ErrCode != 0) { |
| sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); |
| COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, (UINT_8) (strlen(aucErrMsg))); |
| |
| kalIndicateBssInfo(prAdapter->prGlueInfo, |
| (PUINT_8) prBeacon, |
| OFFSET_OF(WLAN_BEACON_FRAME_T, |
| aucInfoElem) + OFFSET_OF(IE_SSID_T, |
| aucSSID) + prSsid->ucLength, 1, 0); |
| |
| COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); |
| nicAddScanResult(prAdapter, prBeacon->aucBSSID, &rSsid, 0, 0, |
| PARAM_NETWORK_TYPE_FH, &rConfiguration, NET_TYPE_INFRA, |
| rSupportedRates, OFFSET_OF(WLAN_BEACON_FRAME_T, |
| aucInfoElem) + |
| OFFSET_OF(IE_SSID_T, |
| aucSSID) + prSsid->ucLength - |
| WLAN_MAC_MGMT_HEADER_LEN, |
| (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); |
| } |
| } |
| #endif |
| |
| if (fgGenErrMsg == TRUE) |
| cnmMemFree(prAdapter, prBeacon); |
| #endif |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS |
| wlanoidQueryBssStatistics(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) |
| { |
| P_PARAM_GET_BSS_STATISTICS prQueryBssStatistics; |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| WLAN_STATUS rResult = WLAN_STATUS_FAILURE; |
| UINT_8 ucBssIndex; |
| ENUM_WMM_ACI_T eAci; |
| |
| DEBUGFUNC("wlanoidQueryBssStatistics"); |
| |
| do { |
| ASSERT(pvQueryBuffer); |
| |
| /* 4 1. Sanity test */ |
| if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) |
| break; |
| |
| if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) |
| break; |
| |
| if (u4QueryBufferLen < sizeof(P_PARAM_GET_BSS_STATISTICS)) { |
| *pu4QueryInfoLen = sizeof(P_PARAM_GET_BSS_STATISTICS); |
| rResult = WLAN_STATUS_BUFFER_TOO_SHORT; |
| break; |
| } |
| |
| prQueryBssStatistics = (P_PARAM_GET_BSS_STATISTICS) pvQueryBuffer; |
| *pu4QueryInfoLen = sizeof(PARAM_GET_BSS_STATISTICS); |
| |
| ucBssIndex = prQueryBssStatistics->ucBssIndex; |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| if (prBssInfo) { /*AIS*/ |
| if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| prStaRec = prBssInfo->prStaRecOfAP; |
| if (prStaRec) { |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| prQueryBssStatistics->arLinkStatistics[eAci].u4TxMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxMsdu; |
| prQueryBssStatistics->arLinkStatistics[eAci].u4RxMsdu = |
| prStaRec->arLinkStatistics[eAci].u4RxMsdu; |
| prQueryBssStatistics->arLinkStatistics[eAci].u4TxDropMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxDropMsdu + |
| prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; |
| prQueryBssStatistics->arLinkStatistics[eAci].u4TxFailMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; |
| prQueryBssStatistics->arLinkStatistics[eAci].u4TxRetryMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; |
| } |
| } |
| } |
| rResult = WLAN_STATUS_SUCCESS; |
| |
| /*P2P */ |
| /* TODO */ |
| |
| /*BOW*/ |
| /* TODO */ |
| } |
| |
| } while (FALSE); |
| |
| return rResult; |
| |
| } |
| |
| VOID wlanDumpBssStatistics(IN P_ADAPTER_T prAdapter, UINT_8 ucBssIdx) |
| { |
| P_BSS_INFO_T prBssInfo; |
| P_STA_RECORD_T prStaRec; |
| ENUM_WMM_ACI_T eAci; |
| WIFI_WMM_AC_STAT_T arLLStats[WMM_AC_INDEX_NUM]; |
| UINT_8 ucIdx; |
| |
| if (ucBssIdx > MAX_BSS_INDEX) { |
| DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIdx); |
| return; |
| } |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); |
| if (!prBssInfo) { |
| DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIdx); |
| return; |
| } |
| /* <1> fill per-BSS statistics */ |
| #if 0 |
| /*AIS*/ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| prStaRec = prBssInfo->prStaRecOfAP; |
| if (prStaRec) { |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| prBssInfo->arLinkStatistics[eAci].u4TxMsdu = prStaRec->arLinkStatistics[eAci].u4TxMsdu; |
| prBssInfo->arLinkStatistics[eAci].u4RxMsdu = prStaRec->arLinkStatistics[eAci].u4RxMsdu; |
| prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu += |
| prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; |
| prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; |
| prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; |
| } |
| } |
| } |
| #else |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| arLLStats[eAci].u4TxMsdu = prBssInfo->arLinkStatistics[eAci].u4TxMsdu; |
| arLLStats[eAci].u4RxMsdu = prBssInfo->arLinkStatistics[eAci].u4RxMsdu; |
| arLLStats[eAci].u4TxDropMsdu = prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu; |
| arLLStats[eAci].u4TxFailMsdu = prBssInfo->arLinkStatistics[eAci].u4TxFailMsdu; |
| arLLStats[eAci].u4TxRetryMsdu = prBssInfo->arLinkStatistics[eAci].u4TxRetryMsdu; |
| } |
| |
| for (ucIdx = 0; ucIdx < CFG_STA_REC_NUM; ucIdx++) { |
| prStaRec = cnmGetStaRecByIndex(prAdapter, ucIdx); |
| if (!prStaRec) |
| continue; |
| if (prStaRec->ucBssIndex != ucBssIdx) |
| continue; |
| /* now the valid sta_rec is valid */ |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| arLLStats[eAci].u4TxMsdu += prStaRec->arLinkStatistics[eAci].u4TxMsdu; |
| arLLStats[eAci].u4RxMsdu += prStaRec->arLinkStatistics[eAci].u4RxMsdu; |
| arLLStats[eAci].u4TxDropMsdu += prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; |
| arLLStats[eAci].u4TxFailMsdu += prStaRec->arLinkStatistics[eAci].u4TxFailMsdu; |
| arLLStats[eAci].u4TxRetryMsdu += prStaRec->arLinkStatistics[eAci].u4TxRetryMsdu; |
| } |
| } |
| #endif |
| |
| /* <2>Dump BSS statistics */ |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| DBGLOG(SW4, INFO, "LLS BSS[%u] %s: T[%06u] R[%06u] T_D[%06u] T_F[%06u]\n", |
| prBssInfo->ucBssIndex, apucACI2Str[eAci], arLLStats[eAci].u4TxMsdu, |
| arLLStats[eAci].u4RxMsdu, arLLStats[eAci].u4TxDropMsdu, arLLStats[eAci].u4TxFailMsdu); |
| } |
| } |
| |
| VOID wlanDumpAllBssStatistics(IN P_ADAPTER_T prAdapter) |
| { |
| P_BSS_INFO_T prBssInfo; |
| /* ENUM_WMM_ACI_T eAci; */ |
| UINT_32 ucIdx; |
| |
| /* wlanUpdateAllBssStatistics(prAdapter); */ |
| |
| for (ucIdx = 0; ucIdx < BSS_INFO_NUM; ucIdx++) { |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucIdx); |
| if (!IS_BSS_ACTIVE(prBssInfo)) { |
| DBGLOG(SW4, TRACE, "Invalid BssInfo index[%u], skip dump!\n", ucIdx); |
| continue; |
| } |
| |
| wlanDumpBssStatistics(prAdapter, ucIdx); |
| } |
| } |
| |
| WLAN_STATUS |
| wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) |
| { |
| WLAN_STATUS rResult = WLAN_STATUS_FAILURE; |
| P_STA_RECORD_T prStaRec, prTempStaRec; |
| P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; |
| UINT_8 ucStaRecIdx; |
| P_QUE_MGT_T prQM; |
| CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; |
| UINT_8 ucIdx; |
| ENUM_WMM_ACI_T eAci; |
| |
| DEBUGFUNC("wlanoidQueryStaStatistics"); |
| |
| if (prAdapter == NULL) |
| return WLAN_STATUS_FAILURE; |
| prQM = &prAdapter->rQM; |
| |
| if (prAdapter->fgIsEnableLpdvt) |
| return WLAN_STATUS_NOT_SUPPORTED; |
| |
| do { |
| ASSERT(pvQueryBuffer); |
| |
| /* 4 1. Sanity test */ |
| if (pu4QueryInfoLen == NULL) |
| break; |
| |
| if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) |
| break; |
| |
| if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { |
| *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); |
| rResult = WLAN_STATUS_BUFFER_TOO_SHORT; |
| break; |
| } |
| |
| prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; |
| *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); |
| |
| /* 4 5. Get driver global QM counter */ |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { |
| prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; |
| prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; |
| } |
| #endif |
| |
| /* 4 2. Get StaRec by MAC address */ |
| prStaRec = NULL; |
| |
| for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; ucStaRecIdx++) { |
| prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); |
| if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { |
| if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { |
| prStaRec = prTempStaRec; |
| break; |
| } |
| } |
| } |
| |
| if (!prStaRec) { |
| rResult = WLAN_STATUS_INVALID_DATA; |
| break; |
| } |
| |
| prQueryStaStatistics->u4Flag |= BIT(0); |
| |
| #if CFG_ENABLE_PER_STA_STATISTICS |
| /* 4 3. Get driver statistics */ |
| prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; |
| prQueryStaStatistics->u4RxTotalCount = prStaRec->u4TotalRxPktsNumber; |
| prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; |
| prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; |
| if (prStaRec->u4TotalTxPktsNumber) { |
| prQueryStaStatistics->u4TxAverageProcessTime = |
| (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); |
| } else |
| prQueryStaStatistics->u4TxAverageProcessTime = 0; |
| |
| /*link layer statistics */ |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| prQueryStaStatistics->arLinkStatistics[eAci].u4TxMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxMsdu; |
| prQueryStaStatistics->arLinkStatistics[eAci].u4RxMsdu = |
| prStaRec->arLinkStatistics[eAci].u4RxMsdu; |
| prQueryStaStatistics->arLinkStatistics[eAci].u4TxDropMsdu = |
| prStaRec->arLinkStatistics[eAci].u4TxDropMsdu; |
| } |
| |
| for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { |
| prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = |
| prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx]; |
| /* Reset */ |
| prQM->au4QmTcResourceEmptyCounter[prStaRec->ucBssIndex][ucIdx] = 0; |
| } |
| |
| /* 4 4.1 Reset statistics */ |
| if (prQueryStaStatistics->ucReadClear) { |
| prStaRec->u4ThresholdCounter = 0; |
| prStaRec->u4TotalTxPktsNumber = 0; |
| prStaRec->u4TotalTxPktsTime = 0; |
| prStaRec->u4TotalRxPktsNumber = 0; |
| prStaRec->u4MaxTxPktsTime = 0; |
| } |
| /*link layer statistics */ |
| if (prQueryStaStatistics->ucLlsReadClear) { |
| for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { |
| prStaRec->arLinkStatistics[eAci].u4TxMsdu = 0; |
| prStaRec->arLinkStatistics[eAci].u4RxMsdu = 0; |
| prStaRec->arLinkStatistics[eAci].u4TxDropMsdu = 0; |
| } |
| } |
| #endif |
| |
| for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) |
| prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->aprTargetQueue[ucIdx]->u4NumElem; |
| |
| rResult = WLAN_STATUS_SUCCESS; |
| |
| /* 4 6. Ensure FW supports get station link status */ |
| if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { |
| |
| DBGLOG(REQ, LOUD, "%s index[%x]\n", __func__, prStaRec->ucIndex); |
| rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; |
| COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); |
| rQueryCmdStaStatistics.ucReadClear = prQueryStaStatistics->ucReadClear; |
| rQueryCmdStaStatistics.ucLlsReadClear = prQueryStaStatistics->ucLlsReadClear; |
| rQueryCmdStaStatistics.ucResetCounter = prQueryStaStatistics->ucResetCounter; |
| |
| rResult = wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_GET_STA_STATISTICS, |
| FALSE, |
| TRUE, |
| TRUE, |
| nicCmdEventQueryStaStatistics, |
| nicOidCmdTimeoutCommon, |
| sizeof(CMD_GET_STA_STATISTICS_T), |
| (PUINT_8) &rQueryCmdStaStatistics, |
| pvQueryBuffer, u4QueryBufferLen); |
| |
| prQueryStaStatistics->u4Flag |= BIT(1); |
| } else { |
| rResult = WLAN_STATUS_NOT_SUPPORTED; |
| } |
| |
| } while (FALSE); |
| |
| return rResult; |
| } /* wlanoidQueryP2pVersion */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to query Nic resource information |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanQueryNicResourceInformation(IN P_ADAPTER_T prAdapter) |
| { |
| /* 3 1. Get Nic resource information from FW */ |
| |
| /* 3 2. Setup resource parameter */ |
| |
| /* 3 3. Reset Tx resource */ |
| nicTxResetResource(prAdapter); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to query Nic resource information |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| |
| WLAN_STATUS wlanQueryNicCapabilityV2(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 ucCmdSeqNum; |
| P_CMD_INFO_T prCmdInfo; |
| P_WIFI_CMD_T prWifiCmd; |
| UINT_32 u4RxPktLength; |
| P_UINT_8 prEventBuff; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| P_WIFI_EVENT_T prEvent; |
| struct mt66xx_chip_info *prChipInfo; |
| UINT_32 chip_id; |
| |
| prChipInfo = prAdapter->chip_info; |
| chip_id = prChipInfo->chip_id; |
| |
| |
| ASSERT(prAdapter); |
| |
| /* Get Nic resource information from FW */ |
| if (prAdapter->u4FwFeatureFlag0 & FEATURE_FLAG0_NIC_CAPABILITY_V2) { |
| |
| DBGLOG(INIT, INFO, "Support NIC_CAPABILITY_V2 feature\n"); |
| |
| /* |
| * send NIC_CAPABILITY_V2 query cmd |
| */ |
| |
| /* 1. Allocate CMD Info Packet and its Buffer */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| /* increase command sequence number */ |
| ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); |
| |
| /* compose CMD_BUILD_CONNECTION cmd pkt */ |
| prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; |
| prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; |
| prCmdInfo->pfCmdDoneHandler = NULL; |
| prCmdInfo->fgIsOid = FALSE; |
| prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY_V2; |
| prCmdInfo->fgSetQuery = FALSE; |
| prCmdInfo->fgNeedResp = TRUE; |
| prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; |
| prCmdInfo->u4SetInfoLen = 0; |
| |
| /* Setup WIFI_CMD_T */ |
| prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); |
| prWifiCmd->u2TxByteCount = prCmdInfo->u2InfoBufLen; |
| prWifiCmd->u2PQ_ID = CMD_PQ_ID; |
| prWifiCmd->ucPktTypeID = CMD_PACKET_TYPE_ID; |
| prWifiCmd->ucCID = prCmdInfo->ucCID; |
| prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; |
| prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; |
| |
| prWifiCmd->u2Length = prCmdInfo->u2InfoBufLen - (UINT_16) OFFSET_OF(WIFI_CMD_T, u2Length); |
| |
| wlanSendCommand(prAdapter, prCmdInfo); |
| |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| /* |
| * receive nic_capability_v2 event |
| */ |
| |
| |
| /* allocate event buffer */ |
| prEventBuff = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, CFG_RX_MAX_PKT_SIZE); |
| if (!prEventBuff) { |
| DBGLOG(INIT, WARN, "%s: event buffer alloc failed!\n", __func__); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| /* get event */ |
| while (TRUE) { |
| if (nicRxWaitResponse(prAdapter, |
| 1, |
| prEventBuff, |
| CFG_RX_MAX_PKT_SIZE, |
| &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, WARN, "%s: wait for event failed!\n", __func__); |
| |
| /* free event buffer */ |
| cnmMemFree(prAdapter, prEventBuff); |
| |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| /* header checking .. */ |
| prRxStatus = (P_HW_MAC_RX_DESC_T) prEventBuff; |
| if ((prRxStatus->u2PktTYpe & RXM_RXD_PKT_TYPE_SW_BITMAP) != RXM_RXD_PKT_TYPE_SW_EVENT) { |
| |
| DBGLOG(INIT, WARN, "%s: skip unexpected Rx pkt type[0x%04x]\n", __func__, |
| prRxStatus->u2PktTYpe); |
| |
| continue; |
| } |
| |
| prEvent = (P_WIFI_EVENT_T) prEventBuff; |
| if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY_V2) { |
| DBGLOG(INIT, WARN, "%s: skip unexpected event ID[0x%02x]\n", __func__, prEvent->ucEID); |
| |
| continue; |
| } else { |
| /* hit */ |
| break; |
| } |
| } |
| |
| /* |
| * parsing elemens |
| */ |
| |
| nicCmdEventQueryNicCapabilityV2(prAdapter, prEvent->aucBuffer); |
| |
| /* |
| * free event buffer |
| */ |
| cnmMemFree(prAdapter, prEventBuff); |
| } |
| |
| /* Fill capability for different Chip version */ |
| if (chip_id == HQA_CHIP_ID_6632) { |
| /* 6632 only */ |
| prAdapter->fgIsSupportBufferBinSize16Byte = TRUE; |
| prAdapter->fgIsSupportDelayCal = FALSE; |
| prAdapter->fgIsSupportGetFreeEfuseBlockCount = FALSE; |
| prAdapter->fgIsSupportQAAccessEfuse = FALSE; |
| prAdapter->fgIsSupportPowerOnSendBufferModeCMD = FALSE; |
| prAdapter->fgIsSupportGetTxPower = FALSE; |
| } else { |
| prAdapter->fgIsSupportBufferBinSize16Byte = FALSE; |
| prAdapter->fgIsSupportDelayCal = TRUE; |
| prAdapter->fgIsSupportGetFreeEfuseBlockCount = TRUE; |
| prAdapter->fgIsSupportQAAccessEfuse = TRUE; |
| prAdapter->fgIsSupportPowerOnSendBufferModeCMD = TRUE; |
| prAdapter->fgIsSupportGetTxPower = TRUE; |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| VOID wlanSetNicResourceParameters(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 string[128], idx; |
| UINT_32 u4share; |
| P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| P_QUE_MGT_T prQM = &prAdapter->rQM; |
| #endif |
| |
| /* |
| * Use the settings in config file first, |
| * else, use the settings reported from firmware. |
| */ |
| |
| |
| /* |
| * 1. assign free page count for each TC |
| */ |
| |
| /* 1 1. update free page count in TC control: MCU and LMAC */ |
| prWifiVar->au4TcPageCount[TC4_INDEX] = |
| prAdapter->nicTxReousrce.u4McuTotalResource * NIC_TX_MAX_PAGE_PER_FRAME; /* MCU */ |
| |
| u4share = prAdapter->nicTxReousrce.u4LmacTotalResource/(TC_NUM - 1); /* LMAC. Except TC_4, which is MCU */ |
| for (idx = TC0_INDEX; idx < TC_NUM; idx++) { |
| if (idx != TC4_INDEX) |
| prWifiVar->au4TcPageCount[idx] = u4share * NIC_TX_MAX_PAGE_PER_FRAME; |
| } |
| |
| /* 1 2. if there is remaings, give them to TC_3, which is VO */ |
| prWifiVar->au4TcPageCount[TC3_INDEX] += |
| (prAdapter->nicTxReousrce.u4LmacTotalResource%(TC_NUM - 1)) * NIC_TX_MAX_PAGE_PER_FRAME; |
| |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| /* |
| * 2. assign guaranteed page count for each TC |
| */ |
| |
| /* 2 1. update guaranteed page count in QM */ |
| for (idx = 0; idx < TC_NUM; idx++) |
| prQM->au4GuaranteedTcResource[idx] = prWifiVar->au4TcPageCount[idx]; |
| #endif |
| |
| |
| #if CFG_SUPPORT_CFG_FILE |
| /* |
| * 3. Use the settings in config file first, |
| * else, use the settings reported from firmware. |
| */ |
| |
| /* 3 1. update for free page count */ |
| for (idx = 0; idx < TC_NUM; idx++) { |
| |
| /* construct prefix: Tc0Page, Tc1Page... */ |
| memset(string, 0, sizeof(string)/sizeof(UINT_8)); |
| snprintf(string, sizeof(string)/sizeof(UINT_8), "Tc%xPage", idx); |
| |
| /* update the final value */ |
| prWifiVar->au4TcPageCount[idx] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, |
| string, prWifiVar->au4TcPageCount[idx]); |
| } |
| |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| /* 3 2. update for guaranteed page count */ |
| for (idx = 0; idx < TC_NUM; idx++) { |
| |
| /* construct prefix: Tc0Grt, Tc1Grt... */ |
| memset(string, 0, sizeof(string)/sizeof(UINT_8)); |
| snprintf(string, sizeof(string)/sizeof(UINT_8), "Tc%xGrt", idx); |
| |
| /* update the final value */ |
| prQM->au4GuaranteedTcResource[idx] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, |
| string, prQM->au4GuaranteedTcResource[idx]); |
| } |
| #endif /* end of #if QM_ADAPTIVE_TC_RESOURCE_CTRL */ |
| |
| #endif /* end of #if CFG_SUPPORT_CFG_FILE */ |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to query Nic resource information |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanUpdateNicResourceInformation(IN P_ADAPTER_T prAdapter) |
| { |
| /* |
| * 3 1. Query TX resource |
| */ |
| |
| /* information is not got from firmware, use default value */ |
| if (prAdapter->fgIsNicTxReousrceValid != TRUE) |
| return; |
| |
| /* 3 2. Setup resource parameters */ |
| wlanSetNicResourceParameters(prAdapter); |
| |
| /* 3 3. Reset Tx resource */ |
| nicTxResetResource(prAdapter); |
| |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| /* 3 4. Reset QM resource */ |
| qmResetTcControlResource(prAdapter); |
| #endif |
| |
| halTxResourceResetHwTQCounter(prAdapter); |
| } |
| |
| |
| #if 0 |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to SET network interface index for a network interface. |
| * A network interface is a TX/RX data port hooked to OS. |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * @param ucNetInterfaceIndex Index of network interface |
| * @param ucBssIndex Index of BSS |
| * |
| * @return VOID |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanBindNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucNetInterfaceIndex, IN PVOID pvNetInterface) |
| { |
| P_NET_INTERFACE_INFO_T prNetIfInfo; |
| |
| prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucNetInterfaceIndex]; |
| |
| prNetIfInfo->pvNetInterface = pvNetInterface; |
| } |
| #endif |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to SET BSS index for a network interface. |
| * A network interface is a TX/RX data port hooked to OS. |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * @param ucNetInterfaceIndex Index of network interface |
| * @param ucBssIndex Index of BSS |
| * |
| * @return VOID |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanBindBssIdxToNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex, IN PVOID pvNetInterface) |
| { |
| P_NET_INTERFACE_INFO_T prNetIfInfo; |
| |
| if (ucBssIndex >= ARRAY_SIZE(prGlueInfo->arNetInterfaceInfo)) { |
| DBGLOG(INIT, ERROR, "Array index out of bound, ucBssIndex=%u\n", ucBssIndex); |
| return; |
| } |
| |
| prNetIfInfo = &prGlueInfo->arNetInterfaceInfo[ucBssIndex]; |
| |
| prNetIfInfo->ucBssIndex = ucBssIndex; |
| prNetIfInfo->pvNetInterface = pvNetInterface; |
| /* prGlueInfo->aprBssIdxToNetInterfaceInfo[ucBssIndex] = prNetIfInfo; */ |
| } |
| |
| #if 0 |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to GET BSS index for a network interface. |
| * A network interface is a TX/RX data port hooked to OS. |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * @param ucNetInterfaceIndex Index of network interface |
| * |
| * @return UINT_8 Index of BSS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 wlanGetBssIdxByNetInterface(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvNetInterface) |
| { |
| UINT_8 ucIdx = 0; |
| |
| for (ucIdx = 0; ucIdx < HW_BSSID_NUM; ucIdx++) { |
| if (prGlueInfo->arNetInterfaceInfo[ucIdx].pvNetInterface == pvNetInterface) |
| break; |
| } |
| |
| return ucIdx; |
| } |
| #endif |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to GET network interface for a BSS. |
| * A network interface is a TX/RX data port hooked to OS. |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * @param ucBssIndex Index of BSS |
| * |
| * @return PVOID pointer of network interface structure |
| */ |
| /*----------------------------------------------------------------------------*/ |
| PVOID wlanGetNetInterfaceByBssIdx(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucBssIndex) |
| { |
| return prGlueInfo->arNetInterfaceInfo[ucBssIndex].pvNetInterface; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to get BSS-INDEX for AIS network. |
| * |
| * @param prAdapter Pointer of ADAPTER_T |
| * |
| * @return value, as corresponding index of BSS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 wlanGetAisBssIndex(IN P_ADAPTER_T prAdapter) |
| { |
| ASSERT(prAdapter); |
| ASSERT(prAdapter->prAisBssInfo); |
| |
| return prAdapter->prAisBssInfo->ucBssIndex; |
| } |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to initialize WLAN feature options |
| * |
| * @param prAdapter Pointer of ADAPTER_T |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanInitFeatureOption(IN P_ADAPTER_T prAdapter) |
| { |
| P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| P_QUE_MGT_T prQM = &prAdapter->rQM; |
| #endif |
| |
| /* Feature options will be filled by config file */ |
| |
| prWifiVar->ucQoS = (UINT_8) wlanCfgGetUint32(prAdapter, "Qos", FEATURE_ENABLED); |
| |
| prWifiVar->ucStaHt = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHT", FEATURE_ENABLED); |
| prWifiVar->ucStaVht = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHT", FEATURE_ENABLED); |
| |
| prWifiVar->ucApHt = (UINT_8) wlanCfgGetUint32(prAdapter, "ApHT", FEATURE_ENABLED); |
| prWifiVar->ucApVht = (UINT_8) wlanCfgGetUint32(prAdapter, "ApVHT", FEATURE_ENABLED); |
| |
| prWifiVar->ucP2pGoHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoHT", FEATURE_ENABLED); |
| prWifiVar->ucP2pGoVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoVHT", FEATURE_ENABLED); |
| |
| prWifiVar->ucP2pGcHt = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcHT", FEATURE_ENABLED); |
| prWifiVar->ucP2pGcVht = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGcVHT", FEATURE_ENABLED); |
| |
| prWifiVar->ucAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduRx", FEATURE_ENABLED); |
| prWifiVar->ucAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmpduTx", FEATURE_ENABLED); |
| |
| prWifiVar->ucAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmsduInAmpduRx", FEATURE_ENABLED); |
| prWifiVar->ucAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "AmsduInAmpduTx", FEATURE_ENABLED); |
| prWifiVar->ucHtAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "HtAmsduInAmpduRx", FEATURE_DISABLED); |
| prWifiVar->ucHtAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "HtAmsduInAmpduTx", FEATURE_DISABLED); |
| prWifiVar->ucVhtAmsduInAmpduRx = (UINT_8) wlanCfgGetUint32(prAdapter, "VhtAmsduInAmpduRx", FEATURE_ENABLED); |
| prWifiVar->ucVhtAmsduInAmpduTx = (UINT_8) wlanCfgGetUint32(prAdapter, "VhtAmsduInAmpduTx", FEATURE_ENABLED); |
| |
| prWifiVar->ucTspec = (UINT_8) wlanCfgGetUint32(prAdapter, "Tspec", FEATURE_DISABLED); |
| |
| prWifiVar->ucUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "Uapsd", FEATURE_ENABLED); |
| prWifiVar->ucStaUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "StaUapsd", FEATURE_DISABLED); |
| prWifiVar->ucApUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "ApUapsd", FEATURE_DISABLED); |
| prWifiVar->ucP2pUapsd = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pUapsd", FEATURE_ENABLED); |
| prWifiVar->u4RegP2pIfAtProbe = (UINT_8) wlanCfgGetUint32(prAdapter, "RegP2pIfAtProbe", FEATURE_DISABLED); |
| prWifiVar->ucP2pShareMacAddr = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pShareMacAddr", FEATURE_DISABLED); |
| |
| prWifiVar->ucTxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiTx", FEATURE_ENABLED); |
| prWifiVar->ucRxShortGI = (UINT_8) wlanCfgGetUint32(prAdapter, "SgiRx", FEATURE_ENABLED); |
| |
| prWifiVar->ucTxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcTx", FEATURE_ENABLED); |
| prWifiVar->ucRxLdpc = (UINT_8) wlanCfgGetUint32(prAdapter, "LdpcRx", FEATURE_ENABLED); |
| |
| prWifiVar->ucTxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcTx", FEATURE_ENABLED); |
| prWifiVar->ucRxStbc = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcRx", FEATURE_ENABLED); |
| prWifiVar->ucRxStbcNss = (UINT_8) wlanCfgGetUint32(prAdapter, "StbcRxNss", 1); |
| |
| prWifiVar->ucTxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfTx", FEATURE_ENABLED); |
| prWifiVar->ucRxGf = (UINT_8) wlanCfgGetUint32(prAdapter, "GfRx", FEATURE_ENABLED); |
| |
| prWifiVar->ucMCS32 = (UINT_8) wlanCfgGetUint32(prAdapter, "MCS32", FEATURE_DISABLED); |
| |
| prWifiVar->ucSigTaRts = (UINT_8) wlanCfgGetUint32(prAdapter, "SigTaRts", FEATURE_DISABLED); |
| prWifiVar->ucDynBwRts = (UINT_8) wlanCfgGetUint32(prAdapter, "DynBwRts", FEATURE_DISABLED); |
| prWifiVar->ucTxopPsTx = (UINT_8) wlanCfgGetUint32(prAdapter, "TxopPsTx", FEATURE_DISABLED); |
| |
| prWifiVar->ucStaHtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHTBfee", FEATURE_ENABLED); |
| prWifiVar->ucStaVhtBfee = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTBfee", FEATURE_ENABLED); |
| prWifiVar->ucStaVhtMuBfee = (UINT_8)wlanCfgGetUint32(prAdapter, "StaVHTMuBfee", FEATURE_ENABLED); |
| prWifiVar->ucStaHtBfer = (UINT_8) wlanCfgGetUint32(prAdapter, "StaHTBfer", FEATURE_DISABLED); |
| prWifiVar->ucStaVhtBfer = (UINT_8) wlanCfgGetUint32(prAdapter, "StaVHTBfer", FEATURE_DISABLED); |
| |
| /* 0: disabled |
| * 1: Tx done event to driver |
| * 2: Tx status to FW only |
| */ |
| prWifiVar->ucDataTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "DataTxDone", 0); |
| prWifiVar->ucDataTxRateMode = (UINT_8) wlanCfgGetUint32(prAdapter, "DataTxRateMode", DATA_RATE_MODE_AUTO); |
| prWifiVar->u4DataTxRateCode = wlanCfgGetUint32(prAdapter, "DataTxRateCode", 0x0); |
| |
| prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); |
| DBGLOG(INIT, INFO, "ucApWpsMode = %u\n", prWifiVar->ucApWpsMode); |
| |
| prWifiVar->ucThreadScheduling = (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadSched", 0); |
| prWifiVar->ucThreadPriority = (UINT_8) wlanCfgGetUint32(prAdapter, "ThreadPriority", WLAN_THREAD_TASK_PRIORITY); |
| prWifiVar->cThreadNice = (INT_8) wlanCfgGetInt32(prAdapter, "ThreadNice", WLAN_THREAD_TASK_NICE); |
| |
| prAdapter->rQM.u4MaxForwardBufferCount = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "ApForwardBufferCnt", QM_FWD_PKT_QUE_THRESHOLD); |
| |
| /* AP channel setting |
| * 0: auto |
| */ |
| prWifiVar->ucApChannel = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChannel", 0); |
| |
| /* |
| * 0: SCN |
| * 1: SCA |
| * 2: RES |
| * 3: SCB |
| */ |
| prWifiVar->ucApSco = (UINT_8) wlanCfgGetUint32(prAdapter, "ApSco", 0); |
| prWifiVar->ucP2pGoSco = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pGoSco", 0); |
| |
| /* Max bandwidth setting |
| * 0: 20Mhz |
| * 1: 40Mhz |
| * 2: 80Mhz |
| * 3: 160Mhz |
| * 4: 80+80Mhz |
| * Note: For VHT STA, BW 80Mhz is a must! |
| */ |
| prWifiVar->ucStaBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "StaBw", MAX_BW_160MHZ); |
| prWifiVar->ucSta2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta2gBw", MAX_BW_20MHZ); |
| prWifiVar->ucSta5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Sta5gBw", MAX_BW_80MHZ); |
| prWifiVar->ucP2p2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p2gBw", MAX_BW_40MHZ); |
| prWifiVar->ucP2p5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "P2p5gBw", MAX_BW_80MHZ); |
| prWifiVar->ucApBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "ApBw", MAX_BW_160MHZ); |
| prWifiVar->ucAp2gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap2gBw", MAX_BW_40MHZ); |
| prWifiVar->ucAp5gBandwidth = (UINT_8) wlanCfgGetUint32(prAdapter, "Ap5gBw", MAX_BW_80MHZ); |
| prWifiVar->ucApChnlDefFromCfg = (UINT_8) wlanCfgGetUint32(prAdapter, "ApChnlDefFromCfg", FEATURE_ENABLED); |
| |
| prWifiVar->ucNSS = (UINT_8) wlanCfgGetUint32(prAdapter, "Nss", 2); |
| |
| /* Max Rx MPDU length setting |
| * 0: 3k |
| * 1: 8k |
| * 2: 11k |
| */ |
| prWifiVar->ucRxMaxMpduLen = (UINT_8) wlanCfgGetUint32(prAdapter, "RxMaxMpduLen", VHT_CAP_INFO_MAX_MPDU_LEN_3K); |
| /* Max Tx AMSDU in AMPDU length *in BYTES* */ |
| prWifiVar->u4TxMaxAmsduInAmpduLen = wlanCfgGetUint32(prAdapter, "TxMaxAmsduInAmpduLen", 4096); |
| |
| prWifiVar->ucStaDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "StaDisconnectDetectTh", 0); |
| prWifiVar->ucApDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "ApDisconnectDetectTh", 0); |
| prWifiVar->ucP2pDisconnectDetectTh = (UINT_8) wlanCfgGetUint32(prAdapter, "P2pDisconnectDetectTh", 0); |
| |
| prWifiVar->ucTcRestrict = (UINT_8) wlanCfgGetUint32(prAdapter, "TcRestrict", 0xFF); |
| /* Max Tx dequeue limit: 0 => auto */ |
| prWifiVar->u4MaxTxDeQLimit = (UINT_32) wlanCfgGetUint32(prAdapter, "MaxTxDeQLimit", 0x0); |
| prWifiVar->ucAlwaysResetUsedRes = (UINT_32) wlanCfgGetUint32(prAdapter, "AlwaysResetUsedRes", 0x0); |
| |
| #if CFG_SUPPORT_MTK_SYNERGY |
| prWifiVar->ucMtkOui = (UINT_8) wlanCfgGetUint32(prAdapter, "MtkOui", FEATURE_ENABLED); |
| prWifiVar->u4MtkOuiCap = (UINT_32) wlanCfgGetUint32(prAdapter, "MtkOuiCap", 0); |
| prWifiVar->aucMtkFeature[0] = 0xff; |
| prWifiVar->aucMtkFeature[1] = 0xff; |
| prWifiVar->aucMtkFeature[2] = 0xff; |
| prWifiVar->aucMtkFeature[3] = 0xff; |
| #endif |
| |
| prWifiVar->ucCmdRsvResource = (UINT_8) wlanCfgGetUint32(prAdapter, "TxCmdRsv", QM_CMD_RESERVED_THRESHOLD); |
| prWifiVar->u4MgmtQueueDelayTimeout = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "TxMgmtQueTO", QM_MGMT_QUEUED_TIMEOUT); /* ms */ |
| |
| /* Performance related */ |
| prWifiVar->u4HifIstLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "IstLoop", CFG_IST_LOOP_COUNT); |
| prWifiVar->u4Rx2OsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2OsLoop", 4); |
| prWifiVar->u4HifTxloopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "HifTxLoop", 1); |
| prWifiVar->u4TxFromOsLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "OsTxLoop", 1); |
| prWifiVar->u4TxRxLoopCount = (UINT_32) wlanCfgGetUint32(prAdapter, "Rx2ReorderLoop", 1); |
| prWifiVar->u4TxIntThCount = (UINT_32) wlanCfgGetUint32(prAdapter, "IstTxTh", HIF_IST_TX_THRESHOLD); |
| |
| prWifiVar->u4NetifStopTh = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStopTh", CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD); |
| prWifiVar->u4NetifStartTh = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "NetifStartTh", CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD); |
| prWifiVar->ucTxBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "TxBaSize", 64); |
| prWifiVar->ucRxHtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxHtBaSize", 64); |
| prWifiVar->ucRxVhtBaSize = (UINT_8) wlanCfgGetUint32(prAdapter, "RxVhtBaSize", 64); |
| |
| /* Tx Buffer Management */ |
| prWifiVar->ucExtraTxDone = (UINT_32) wlanCfgGetUint32(prAdapter, "ExtraTxDone", 1); |
| prWifiVar->ucTxDbg = (UINT_32) wlanCfgGetUint32(prAdapter, "TxDbg", 0); |
| |
| kalMemZero(prWifiVar->au4TcPageCount, sizeof(prWifiVar->au4TcPageCount)); |
| |
| prWifiVar->au4TcPageCount[TC0_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Page", NIC_TX_PAGE_COUNT_TC0); |
| prWifiVar->au4TcPageCount[TC1_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Page", NIC_TX_PAGE_COUNT_TC1); |
| prWifiVar->au4TcPageCount[TC2_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Page", NIC_TX_PAGE_COUNT_TC2); |
| prWifiVar->au4TcPageCount[TC3_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Page", NIC_TX_PAGE_COUNT_TC3); |
| prWifiVar->au4TcPageCount[TC4_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Page", NIC_TX_PAGE_COUNT_TC4); |
| prWifiVar->au4TcPageCount[TC5_INDEX] = (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Page", NIC_TX_PAGE_COUNT_TC5); |
| |
| #if QM_ADAPTIVE_TC_RESOURCE_CTRL |
| prQM->au4MinReservedTcResource[TC0_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0MinRsv", QM_MIN_RESERVED_TC0_RESOURCE); |
| prQM->au4MinReservedTcResource[TC1_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1MinRsv", QM_MIN_RESERVED_TC1_RESOURCE); |
| prQM->au4MinReservedTcResource[TC2_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2MinRsv", QM_MIN_RESERVED_TC2_RESOURCE); |
| prQM->au4MinReservedTcResource[TC3_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3MinRsv", QM_MIN_RESERVED_TC3_RESOURCE); |
| prQM->au4MinReservedTcResource[TC4_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4MinRsv", QM_MIN_RESERVED_TC4_RESOURCE); |
| prQM->au4MinReservedTcResource[TC5_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5MinRsv", QM_MIN_RESERVED_TC5_RESOURCE); |
| |
| prQM->au4GuaranteedTcResource[TC0_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc0Grt", QM_GUARANTEED_TC0_RESOURCE); |
| prQM->au4GuaranteedTcResource[TC1_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc1Grt", QM_GUARANTEED_TC1_RESOURCE); |
| prQM->au4GuaranteedTcResource[TC2_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc2Grt", QM_GUARANTEED_TC2_RESOURCE); |
| prQM->au4GuaranteedTcResource[TC3_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc3Grt", QM_GUARANTEED_TC3_RESOURCE); |
| prQM->au4GuaranteedTcResource[TC4_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc4Grt", QM_GUARANTEED_TC4_RESOURCE); |
| prQM->au4GuaranteedTcResource[TC5_INDEX] = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "Tc5Grt", QM_GUARANTEED_TC5_RESOURCE); |
| |
| prQM->u4TimeToAdjustTcResource = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "TcAdjustTime", QM_INIT_TIME_TO_ADJUST_TC_RSC); |
| prQM->u4TimeToUpdateQueLen = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenUpdateTime", QM_INIT_TIME_TO_UPDATE_QUE_LEN); |
| prQM->u4QueLenMovingAverage = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "QueLenMovingAvg", QM_QUE_LEN_MOVING_AVE_FACTOR); |
| prQM->u4ExtraReservedTcResource = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "TcExtraRsv", QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY); |
| #endif |
| |
| /* Stats log */ |
| prWifiVar->u4StatsLogTimeout = (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogTO", WLAN_TX_STATS_LOG_TIMEOUT); |
| prWifiVar->u4StatsLogDuration = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "StatsLogDur", WLAN_TX_STATS_LOG_DURATION); |
| |
| prWifiVar->ucDhcpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "DhcpTxDone", 1); |
| prWifiVar->ucArpTxDone = (UINT_8) wlanCfgGetUint32(prAdapter, "ArpTxDone", 1); |
| |
| prWifiVar->ucMacAddrOverride = (UINT_8) wlanCfgGetInt32(prAdapter, "MacOverride", 0); |
| if (wlanCfgGet(prAdapter, "MacAddr", prWifiVar->aucMacAddrStr, "00:0c:e7:66:32:e1", 0)) |
| DBGLOG(INIT, ERROR, "get MacAddr fail, use defaul\n"); |
| |
| prWifiVar->ucCtiaMode = (UINT_8) wlanCfgGetUint32(prAdapter, "CtiaMode", 0); |
| |
| /* Combine ucTpTestMode and ucSigmaTestMode in one flag */ |
| /* ucTpTestMode == 0, for normal driver */ |
| /* ucTpTestMode == 1, for pure throughput test mode (ex: RvR) */ |
| /* ucTpTestMode == 2, for sigma TGn/TGac/PMF */ |
| /* ucTpTestMode == 3, for sigma WMM PS */ |
| prWifiVar->ucTpTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "TpTestMode", 0); |
| |
| #if 0 |
| prWifiVar->ucSigmaTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "SigmaTestMode", 0); |
| #endif |
| |
| #if CFG_SUPPORT_DBDC |
| prWifiVar->ucDbdcMode = (UINT_8) wlanCfgGetUint32(prAdapter, "DbdcMode", DBDC_MODE_DYNAMIC); |
| #endif /*CFG_SUPPORT_DBDC*/ |
| #if (CFG_EFUSE_BUFFER_MODE_DELAY_CAL == 1) |
| prWifiVar->ucEfuseBufferModeCal = (UINT_8) wlanCfgGetUint32(prAdapter, "EfuseBufferModeCal", 0); |
| #endif |
| prWifiVar->ucCalTimingCtrl = (UINT_8) wlanCfgGetUint32(prAdapter, "CalTimingCtrl", 0 /* power on full cal */); |
| prWifiVar->ucWow = (UINT_8) wlanCfgGetUint32(prAdapter, "Wow", FEATURE_DISABLED); |
| prWifiVar->ucOffload = (UINT_8) wlanCfgGetUint32(prAdapter, "Offload", FEATURE_DISABLED); |
| prWifiVar->ucAdvPws = (UINT_8) wlanCfgGetUint32(prAdapter, "AdvPws", FEATURE_ENABLED); |
| prWifiVar->ucWowOnMdtim = (UINT_8) wlanCfgGetUint32(prAdapter, "WowOnMdtim", 1); |
| prWifiVar->ucWowOffMdtim = (UINT_8) wlanCfgGetUint32(prAdapter, "WowOffMdtim", 3); |
| prWifiVar->ucWowPwsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "WowPwsMode", Param_PowerModeFast_PSP); |
| prWifiVar->ucListenDtimInterval = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "ListenDtimInt", DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD); |
| prWifiVar->ucEapolOffload = (UINT_8) wlanCfgGetUint32(prAdapter, "EapolOffload", FEATURE_ENABLED); |
| |
| #if CFG_WOW_SUPPORT |
| prAdapter->rWowCtrl.fgWowEnable = (UINT_8) wlanCfgGetUint32(prAdapter, "WowEnable", FEATURE_ENABLED); |
| prAdapter->rWowCtrl.ucScenarioId = (UINT_8) wlanCfgGetUint32(prAdapter, "WowScenarioId", 0); |
| prAdapter->rWowCtrl.ucBlockCount = (UINT_8) wlanCfgGetUint32(prAdapter, "WowPinCnt", 1); |
| prAdapter->rWowCtrl.astWakeHif[0].ucWakeupHif = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "WowHif", ENUM_HIF_TYPE_GPIO); |
| prAdapter->rWowCtrl.astWakeHif[0].ucGpioPin = (UINT_8) wlanCfgGetUint32(prAdapter, "WowGpioPin", 0xFF); |
| prAdapter->rWowCtrl.astWakeHif[0].ucTriggerLvl = (UINT_8) wlanCfgGetUint32(prAdapter, "WowTriggerLevel", 3); |
| prAdapter->rWowCtrl.astWakeHif[0].u4GpioInterval = wlanCfgGetUint32(prAdapter, "GpioInterval", 0); |
| #endif |
| |
| /* SW Test Mode: Mainly used for Sigma */ |
| prWifiVar->u4SwTestMode = (UINT_8) wlanCfgGetUint32(prAdapter, "Sigma", ENUM_SW_TEST_MODE_NONE); |
| prWifiVar->ucCtrlFlagAssertPath = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "AssertPath", DBG_ASSERT_PATH_DEFAULT); |
| prWifiVar->ucCtrlFlagDebugLevel = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "AssertLevel", DBG_ASSERT_CTRL_LEVEL_DEFAULT); |
| prWifiVar->u4ScanCtrl = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "ScanCtrl", SCN_CTRL_DEFAULT_SCAN_CTRL); |
| prWifiVar->ucScanChannelListenTime = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "ScnChListenTime", 0); |
| |
| /* Wake lock related configuration */ |
| prWifiVar->u4WakeLockRxTimeout = |
| wlanCfgGetUint32(prAdapter, "WakeLockRxTO", WAKE_LOCK_RX_TIMEOUT); |
| prWifiVar->u4WakeLockThreadWakeup = |
| wlanCfgGetUint32(prAdapter, "WakeLockThreadTO", WAKE_LOCK_THREAD_WAKEUP_TIMEOUT); |
| |
| prWifiVar->ucSmartRTS = (UINT_8) wlanCfgGetUint32(prAdapter, "SmartRTS", 0); |
| #if 1 |
| /* add more cfg from RegInfo */ |
| prWifiVar->u4UapsdAcBmp = (UINT_32) wlanCfgGetUint32(prAdapter, "UapsdAcBmp", 0); |
| prWifiVar->u4MaxSpLen = (UINT_32) wlanCfgGetUint32(prAdapter, "MaxSpLen", 0); |
| prWifiVar->fgDisOnlineScan = (UINT_32) wlanCfgGetUint32(prAdapter, "DisOnlineScan", 0); |
| prWifiVar->fgDisBcnLostDetection = (UINT_32) wlanCfgGetUint32(prAdapter, "DisBcnLostDetection", 0); |
| prWifiVar->fgDisRoaming = (UINT_32) wlanCfgGetUint32(prAdapter, "DisRoaming", 0); |
| prWifiVar->fgEnArpFilter = (UINT_32) wlanCfgGetUint32(prAdapter, "EnArpFilter", FEATURE_ENABLED); |
| #endif |
| |
| /* Driver Flow Control Dequeue Quota. Now is only used by DBDC */ |
| prWifiVar->uDeQuePercentEnable = |
| (UINT_8) wlanCfgGetUint32(prAdapter, "DeQuePercentEnable", 1); |
| prWifiVar->u4DeQuePercentVHT80Nss1 = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT80NSS1", QM_DEQUE_PERCENT_VHT80_NSS1); |
| prWifiVar->u4DeQuePercentVHT40Nss1 = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT40NSS1", QM_DEQUE_PERCENT_VHT40_NSS1); |
| prWifiVar->u4DeQuePercentVHT20Nss1 = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentVHT20NSS1", QM_DEQUE_PERCENT_VHT20_NSS1); |
| prWifiVar->u4DeQuePercentHT40Nss1 = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentHT40NSS1", QM_DEQUE_PERCENT_HT40_NSS1); |
| prWifiVar->u4DeQuePercentHT20Nss1 = |
| (UINT_32) wlanCfgGetUint32(prAdapter, "DeQuePercentHT20NSS1", QM_DEQUE_PERCENT_HT20_NSS1); |
| |
| /* Support TDLS 5.5.4.2 optional case */ |
| prWifiVar->fgTdlsBufferSTASleep = (BOOLEAN) wlanCfgGetUint32(prAdapter, "TdlsBufferSTASleep", FEATURE_DISABLED); |
| /* Support USB Whole chip reset recover */ |
| prWifiVar->fgChipResetRecover = (BOOLEAN) wlanCfgGetUint32(prAdapter, "ChipResetRecover", FEATURE_ENABLED); |
| |
| #if CFG_SUPPORT_ANT_SELECT |
| prWifiVar->ucSpeIdxCtrl = (UINT_8) wlanCfgGetUint32(prAdapter, "SpeIdxCtrl", 2); |
| #endif |
| } |
| |
| VOID wlanCfgSetSwCtrl(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 i = 0; |
| CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; |
| CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; |
| |
| const CHAR acDelim[] = " "; |
| CHAR *pcPtr = NULL; |
| CHAR *pcDupValue = NULL; |
| UINT_32 au4Values[2]; |
| UINT_32 u4TokenCount = 0; |
| UINT_32 u4BufLen = 0; |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; |
| INT_32 u4Ret = 0; |
| |
| for (i = 0; i < WLAN_CFG_SET_SW_CTRL_LEN_MAX; i++) { |
| kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); |
| kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); |
| kalSprintf(aucKey, "SwCtrl%d", i); |
| |
| /* get nothing */ |
| if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) |
| continue; |
| if (!kalStrCmp(aucValue, "")) |
| continue; |
| |
| pcDupValue = aucValue; |
| u4TokenCount = 0; |
| |
| while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { |
| |
| if (!kalStrCmp(pcPtr, "")) |
| continue; |
| |
| /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ |
| u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); |
| if (u4Ret) |
| DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); |
| u4TokenCount++; |
| |
| /* Only need 2 tokens */ |
| if (u4TokenCount >= 2) |
| break; |
| } |
| |
| if (u4TokenCount != 2) |
| continue; |
| |
| rSwCtrlInfo.u4Id = au4Values[0]; |
| rSwCtrlInfo.u4Data = au4Values[1]; |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetSwCtrlWrite, |
| &rSwCtrlInfo, sizeof(rSwCtrlInfo), FALSE, FALSE, TRUE, &u4BufLen); |
| |
| } |
| } |
| |
| VOID wlanCfgSetChip(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 i = 0; |
| CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; |
| CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; |
| |
| UINT_32 u4BufLen = 0; |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; |
| |
| for (i = 0; i < WLAN_CFG_SET_CHIP_LEN_MAX; i++) { |
| kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); |
| kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); |
| kalSnprintf(aucKey, sizeof(aucKey), "SetChip%d", i); |
| |
| /* get nothing */ |
| if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) |
| continue; |
| if (!kalStrCmp(aucValue, "")) |
| continue; |
| |
| kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); |
| |
| rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; |
| rChipConfigInfo.u2MsgSize = kalStrnLen(aucValue, WLAN_CFG_VALUE_LEN_MAX); |
| kalStrnCpy(rChipConfigInfo.aucCmd, aucValue, CHIP_CONFIG_RESP_SIZE); |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetChipConfig, |
| &rChipConfigInfo, sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, &u4BufLen); |
| } |
| |
| } |
| |
| VOID wlanCfgSetDebugLevel(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 i = 0; |
| CHAR aucKey[WLAN_CFG_VALUE_LEN_MAX]; |
| CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; |
| const CHAR acDelim[] = " "; |
| CHAR *pcDupValue; |
| CHAR *pcPtr = NULL; |
| |
| UINT_32 au4Values[2]; |
| UINT_32 u4TokenCount = 0; |
| UINT_32 u4DbgIdx = 0; |
| UINT_32 u4DbgMask = 0; |
| INT_32 u4Ret = 0; |
| |
| for (i = 0; i < WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX; i++) { |
| kalMemZero(aucValue, WLAN_CFG_VALUE_LEN_MAX); |
| kalMemZero(aucKey, WLAN_CFG_VALUE_LEN_MAX); |
| kalSprintf(aucKey, "DbgLevel%d", i); |
| |
| /* get nothing */ |
| if (wlanCfgGet(prAdapter, aucKey, aucValue, "", 0) != WLAN_STATUS_SUCCESS) |
| continue; |
| if (!kalStrCmp(aucValue, "")) |
| continue; |
| |
| pcDupValue = aucValue; |
| u4TokenCount = 0; |
| |
| while ((pcPtr = kalStrSep((char **)(&pcDupValue), acDelim)) != NULL) { |
| |
| if (!kalStrCmp(pcPtr, "")) |
| continue; |
| |
| /* au4Values[u4TokenCount] = kalStrtoul(pcPtr, NULL, 0); */ |
| u4Ret = kalkStrtou32(pcPtr, 0, &(au4Values[u4TokenCount])); |
| if (u4Ret) |
| DBGLOG(INIT, LOUD, "parse au4Values error u4Ret=%d\n", u4Ret); |
| u4TokenCount++; |
| |
| /* Only need 2 tokens */ |
| if (u4TokenCount >= 2) |
| break; |
| } |
| |
| if (u4TokenCount != 2) |
| continue; |
| |
| u4DbgIdx = au4Values[0]; |
| u4DbgMask = au4Values[1]; |
| |
| /* DBG level special control */ |
| if (u4DbgIdx == 0xFFFFFFFF) { |
| wlanSetDebugLevel(DBG_ALL_MODULE_IDX, u4DbgMask); |
| DBGLOG(INIT, INFO, "Set ALL DBG module log level to [0x%02x]!", (UINT_8) u4DbgMask); |
| } else if (u4DbgIdx == 0xFFFFFFFE) { |
| wlanDebugInit(); |
| DBGLOG(INIT, INFO, "Reset ALL DBG module log level to DEFAULT!"); |
| } else if (u4DbgIdx < DBG_MODULE_NUM) { |
| wlanSetDebugLevel(u4DbgIdx, u4DbgMask); |
| DBGLOG(INIT, INFO, "Set DBG module[%lu] log level to [0x%02x]!", u4DbgIdx, (UINT_8) u4DbgMask); |
| } |
| } |
| |
| } |
| |
| VOID wlanCfgSetCountryCode(IN P_ADAPTER_T prAdapter) |
| { |
| CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; |
| |
| /* Apply COUNTRY Config */ |
| if (wlanCfgGet(prAdapter, "Country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { |
| prAdapter->rWifiVar.rConnSettings.u2CountryCode = |
| (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); |
| |
| DBGLOG(INIT, TRACE, "u2CountryCode=0x%04x\n", |
| prAdapter->rWifiVar.rConnSettings.u2CountryCode); |
| |
| if (regd_is_single_sku_en()) { |
| rlmDomainOidSetCountry(prAdapter, aucValue, 2); |
| return; |
| } |
| |
| /* Force to re-search country code in country domains */ |
| prAdapter->prDomainInfo = NULL; |
| rlmDomainSendCmd(prAdapter, TRUE); |
| |
| /* Update supported channel list in channel table based on current country domain */ |
| wlanUpdateChannelTable(prAdapter->prGlueInfo); |
| } |
| } |
| |
| #if CFG_SUPPORT_CFG_FILE |
| |
| P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, BOOLEAN fgGetCfgRec) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg = NULL; |
| P_WLAN_CFG_REC_T prWlanCfgRec = NULL; |
| UINT_32 i, u32MaxNum; |
| |
| if (fgGetCfgRec) { |
| prWlanCfgRec = prAdapter->prWlanCfgRec; |
| u32MaxNum = WLAN_CFG_REC_ENTRY_NUM_MAX; |
| ASSERT(prWlanCfgRec); |
| } else { |
| prWlanCfg = prAdapter->prWlanCfg; |
| u32MaxNum = WLAN_CFG_ENTRY_NUM_MAX; |
| ASSERT(prWlanCfg); |
| } |
| |
| |
| ASSERT(pucKey); |
| |
| prWlanCfgEntry = NULL; |
| |
| for (i = 0; i < u32MaxNum; i++) { |
| if (fgGetCfgRec) |
| prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; |
| else |
| prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; |
| |
| if (prWlanCfgEntry->aucKey[0] != '\0') { |
| DBGLOG(INIT, LOUD, "compare key %s saved key %s\n", pucKey, prWlanCfgEntry->aucKey); |
| if (kalStrnCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) |
| return prWlanCfgEntry; |
| } |
| } |
| |
| DBGLOG(INIT, TRACE, "wifi config there is no entry \'%s\'\n", pucKey); |
| return NULL; |
| |
| } |
| |
| |
| P_WLAN_CFG_ENTRY_T wlanCfgGetEntryByIndex(IN P_ADAPTER_T prAdapter, const UINT_8 ucIdx, UINT_32 flag) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg; |
| P_WLAN_CFG_REC_T prWlanCfgRec; |
| |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| prWlanCfgRec = prAdapter->prWlanCfgRec; |
| |
| ASSERT(prWlanCfg); |
| ASSERT(prWlanCfgRec); |
| |
| |
| prWlanCfgEntry = NULL; |
| |
| if (flag & WLAN_CFG_REC_FLAG_BIT) |
| prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[ucIdx]; |
| else |
| prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[ucIdx]; |
| |
| if (prWlanCfgEntry->aucKey[0] != '\0') { |
| DBGLOG(INIT, LOUD, "get Index(%d) saved key %s\n", ucIdx, prWlanCfgEntry->aucKey); |
| return prWlanCfgEntry; |
| } |
| |
| DBGLOG(INIT, TRACE, "wifi config there is no entry at index(%d)\n", ucIdx); |
| return NULL; |
| |
| } |
| |
| |
| |
| WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg; |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| |
| ASSERT(prWlanCfg); |
| ASSERT(pucValue); |
| |
| /* Find the exist */ |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); |
| |
| if (prWlanCfgEntry) { |
| kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); |
| return WLAN_STATUS_SUCCESS; |
| } |
| if (pucValueDef) |
| kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); |
| return WLAN_STATUS_FAILURE; |
| |
| |
| } |
| |
| VOID wlanCfgRecordValue(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) |
| { |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; |
| |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); |
| |
| kalMemZero(aucBuf, sizeof(aucBuf)); |
| |
| kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); |
| |
| wlanCfgSet(prAdapter, pucKey, aucBuf, 1); |
| } |
| |
| |
| |
| UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) |
| { |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg; |
| UINT_32 u4Value; |
| INT_32 u4Ret; |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| |
| ASSERT(prWlanCfg); |
| |
| u4Value = u4ValueDef; |
| /* Find the exist */ |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); |
| |
| if (prWlanCfgEntry) { |
| /* u4Ret = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ |
| u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); |
| if (u4Ret) |
| DBGLOG(INIT, LOUD, "parse aucValue error u4Ret=%d\n", u4Ret); |
| } |
| |
| wlanCfgRecordValue(prAdapter, pucKey, u4Value); |
| |
| return u4Value; |
| } |
| |
| INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) |
| { |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg; |
| INT_32 i4Value = 0; |
| INT_32 i4Ret = 0; |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| |
| ASSERT(prWlanCfg); |
| |
| i4Value = i4ValueDef; |
| /* Find the exist */ |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); |
| |
| if (prWlanCfgEntry) { |
| /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ |
| i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); |
| if (i4Ret) |
| DBGLOG(INIT, LOUD, "parse aucValue error i4Ret=%d\n", i4Ret); |
| } |
| |
| wlanCfgRecordValue(prAdapter, pucKey, (UINT32)i4Value); |
| |
| return i4Value; |
| } |
| |
| WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg = NULL; |
| P_WLAN_CFG_REC_T prWlanCfgRec = NULL; |
| UINT_32 u4EntryIndex; |
| UINT_32 i; |
| UINT_8 ucExist; |
| BOOLEAN fgGetCfgRec = FALSE; |
| |
| |
| fgGetCfgRec = u4Flags & WLAN_CFG_REC_FLAG_BIT; |
| |
| ASSERT(pucKey); |
| |
| /* Find the exist */ |
| ucExist = 0; |
| if (fgGetCfgRec) { |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, TRUE); |
| prWlanCfgRec = prAdapter->prWlanCfgRec; |
| ASSERT(prWlanCfgRec); |
| } else { |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); |
| prWlanCfg = prAdapter->prWlanCfg; |
| ASSERT(prWlanCfg); |
| } |
| |
| if (!prWlanCfgEntry) { |
| /* Find the empty */ |
| for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { |
| if (fgGetCfgRec) |
| prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[i]; |
| else |
| prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; |
| if (prWlanCfgEntry->aucKey[0] == '\0') |
| break; |
| } |
| |
| u4EntryIndex = i; |
| if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { |
| if (fgGetCfgRec) |
| prWlanCfgEntry = &prWlanCfgRec->arWlanCfgBuf[u4EntryIndex]; |
| else |
| prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; |
| kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); |
| } else { |
| prWlanCfgEntry = NULL; |
| DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); |
| } |
| } /* !prWlanCfgEntry */ |
| else |
| ucExist = 1; |
| |
| if (prWlanCfgEntry) { |
| if (ucExist == 0) { |
| kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); |
| prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; |
| } |
| |
| if (pucValue && pucValue[0] != '\0') { |
| kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); |
| prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; |
| |
| if (ucExist) { |
| if (prWlanCfgEntry->pfSetCb) |
| prWlanCfgEntry->pfSetCb(prAdapter, |
| prWlanCfgEntry->aucKey, |
| prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); |
| } |
| } else { |
| /* Call the pfSetCb if value is empty ? */ |
| /* remove the entry if value is empty */ |
| kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); |
| } |
| |
| } |
| /* prWlanCfgEntry */ |
| if (prWlanCfgEntry) { |
| DBGLOG(INIT, INFO, "Set wifi config exist %u \'%s\' \'%s\'\n", |
| ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); |
| return WLAN_STATUS_SUCCESS; |
| } |
| if (pucKey) |
| DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", pucKey); |
| |
| if (pucValue) |
| DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", pucValue); |
| |
| return WLAN_STATUS_FAILURE; |
| |
| |
| } |
| |
| WLAN_STATUS |
| wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| P_WLAN_CFG_T prWlanCfg; |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| ASSERT(prWlanCfg); |
| |
| /* Find the exist */ |
| prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey, FALSE); |
| |
| if (prWlanCfgEntry) { |
| prWlanCfgEntry->pfSetCb = pfSetCb; |
| prWlanCfgEntry->pPrivate = pPrivate; |
| } |
| |
| if (prWlanCfgEntry) |
| return WLAN_STATUS_SUCCESS; |
| else |
| return WLAN_STATUS_FAILURE; |
| |
| } |
| |
| WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) |
| { |
| |
| P_WLAN_CFG_T prWlanCfg; |
| UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; |
| |
| prWlanCfg = prAdapter->prWlanCfg; |
| |
| ASSERT(prWlanCfg); |
| |
| kalMemZero(aucBuf, sizeof(aucBuf)); |
| |
| kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); |
| |
| return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); |
| } |
| |
| enum { |
| STATE_EOF = 0, |
| STATE_TEXT = 1, |
| STATE_NEWLINE = 2 |
| }; |
| |
| struct WLAN_CFG_PARSE_STATE_S { |
| CHAR *ptr; |
| CHAR *text; |
| #if CFG_SUPPORT_EASY_DEBUG |
| UINT_32 textsize; |
| #endif |
| INT_32 nexttoken; |
| UINT_32 maxSize; |
| }; |
| |
| INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) |
| { |
| CHAR *x = state->ptr; |
| CHAR *s; |
| |
| if (state->nexttoken) { |
| INT_32 t = state->nexttoken; |
| |
| state->nexttoken = 0; |
| return t; |
| } |
| |
| for (;;) { |
| switch (*x) { |
| case 0: |
| state->ptr = x; |
| return STATE_EOF; |
| case '\n': |
| x++; |
| state->ptr = x; |
| return STATE_NEWLINE; |
| case ' ': |
| case ',': |
| /*case ':': should not including : , mac addr would be fail*/ |
| case '\t': |
| case '\r': |
| x++; |
| continue; |
| case '#': |
| while (*x && (*x != '\n')) |
| x++; |
| if (*x == '\n') { |
| state->ptr = x + 1; |
| return STATE_NEWLINE; |
| } |
| state->ptr = x; |
| return STATE_EOF; |
| |
| default: |
| goto text; |
| } |
| } |
| |
| textdone: |
| state->ptr = x; |
| *s = 0; |
| return STATE_TEXT; |
| text: |
| state->text = s = x; |
| textresume: |
| for (;;) { |
| switch (*x) { |
| case 0: |
| goto textdone; |
| case ' ': |
| case ',': |
| /*case ':': |
| */ |
| case '\t': |
| case '\r': |
| x++; |
| goto textdone; |
| case '\n': |
| state->nexttoken = STATE_NEWLINE; |
| x++; |
| goto textdone; |
| case '"': |
| x++; |
| for (;;) { |
| switch (*x) { |
| case 0: |
| /* unterminated quoted thing */ |
| state->ptr = x; |
| return STATE_EOF; |
| case '"': |
| x++; |
| goto textresume; |
| default: |
| *s++ = *x++; |
| } |
| } |
| break; |
| case '\\': |
| x++; |
| switch (*x) { |
| case 0: |
| goto textdone; |
| case 'n': |
| *s++ = '\n'; |
| break; |
| case 'r': |
| *s++ = '\r'; |
| break; |
| case 't': |
| *s++ = '\t'; |
| break; |
| case '\\': |
| *s++ = '\\'; |
| break; |
| case '\r': |
| /* \ <cr> <lf> -> line continuation */ |
| if (x[1] != '\n') { |
| x++; |
| continue; |
| } |
| case '\n': |
| /* \ <lf> -> line continuation */ |
| x++; |
| /* eat any extra whitespace */ |
| while ((*x == ' ') || (*x == '\t')) |
| x++; |
| continue; |
| default: |
| /* unknown escape -- just copy */ |
| *s++ = *x++; |
| } |
| continue; |
| default: |
| *s++ = *x++; |
| #if CFG_SUPPORT_EASY_DEBUG |
| state->textsize++; |
| #endif |
| } |
| } |
| return STATE_EOF; |
| } |
| |
| WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) |
| { |
| struct WLAN_CFG_PARSE_STATE_S state; |
| CHAR **args; |
| INT_32 nargs; |
| |
| if (cmdLine == NULL || argc == NULL || argv == NULL) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| args = argv; |
| nargs = 0; |
| state.ptr = cmdLine; |
| state.nexttoken = 0; |
| state.maxSize = 0; |
| #if CFG_SUPPORT_EASY_DEBUG |
| state.textsize = 0; |
| #endif |
| |
| if (kalStrnLen(cmdLine, 512) >= 512) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| for (;;) { |
| switch (wlanCfgFindNextToken(&state)) { |
| case STATE_EOF: |
| goto exit; |
| case STATE_NEWLINE: |
| goto exit; |
| case STATE_TEXT: |
| if (nargs < WLAN_CFG_ARGV_MAX) |
| args[nargs++] = state.text; |
| break; |
| } |
| } |
| |
| exit: |
| *argc = nargs; |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #if CFG_WOW_SUPPORT |
| WLAN_STATUS wlanCfgParseArgumentLong(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) |
| { |
| struct WLAN_CFG_PARSE_STATE_S state; |
| CHAR **args; |
| INT_32 nargs; |
| |
| if (cmdLine == NULL || argc == NULL || argv == NULL) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| args = argv; |
| nargs = 0; |
| state.ptr = cmdLine; |
| state.nexttoken = 0; |
| state.maxSize = 0; |
| #if CFG_SUPPORT_EASY_DEBUG |
| state.textsize = 0; |
| #endif |
| |
| if (kalStrnLen(cmdLine, 512) >= 512) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| for (;;) { |
| switch (wlanCfgFindNextToken(&state)) { |
| case STATE_EOF: |
| goto exit; |
| case STATE_NEWLINE: |
| goto exit; |
| case STATE_TEXT: |
| if (nargs < WLAN_CFG_ARGV_MAX_LONG) |
| args[nargs++] = state.text; |
| break; |
| } |
| } |
| |
| exit: |
| *argc = nargs; |
| return WLAN_STATUS_SUCCESS; |
| } |
| #endif |
| |
| WLAN_STATUS |
| wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, |
| PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) |
| { |
| |
| UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; |
| UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; |
| UINT_32 u4Len; |
| |
| kalMemZero(aucKey, sizeof(aucKey)); |
| kalMemZero(aucValue, sizeof(aucValue)); |
| |
| if ((pucKeyHead == NULL) |
| || (pucValueHead == NULL) |
| ) |
| return WLAN_STATUS_FAILURE; |
| |
| if (pucKeyTail) { |
| if (pucKeyHead > pucKeyTail) |
| return WLAN_STATUS_FAILURE; |
| u4Len = pucKeyTail - pucKeyHead + 1; |
| } else |
| u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); |
| |
| if (u4Len >= WLAN_CFG_KEY_LEN_MAX) |
| u4Len = WLAN_CFG_KEY_LEN_MAX - 1; |
| |
| kalStrnCpy(aucKey, pucKeyHead, u4Len); |
| |
| if (pucValueTail) { |
| if (pucValueHead > pucValueTail) |
| return WLAN_STATUS_FAILURE; |
| u4Len = pucValueTail - pucValueHead + 1; |
| } else |
| u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); |
| |
| if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) |
| u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; |
| |
| kalStrnCpy(aucValue, pucValueHead, u4Len); |
| |
| return wlanCfgSet(prAdapter, aucKey, aucValue, 0); |
| } |
| |
| enum { |
| WAIT_KEY_HEAD = 0, |
| WAIT_KEY_TAIL, |
| WAIT_VALUE_HEAD, |
| WAIT_VALUE_TAIL, |
| WAIT_COMMENT_TAIL |
| }; |
| |
| #if CFG_SUPPORT_EASY_DEBUG |
| |
| INT_8 atoi(UCHAR ch) |
| { |
| if (ch >= 'a' && ch <= 'f') |
| return ch - 87; |
| else if (ch >= 'A' && ch <= 'F') |
| return ch - 55; |
| else if (ch >= '0' && ch <= '9') |
| return ch - 48; |
| |
| return 0; |
| } |
| |
| WLAN_STATUS wlanCfgParseToFW(PCHAR *args, PCHAR args_size, UCHAR nargs, PCHAR buffer, UCHAR times) |
| { |
| PUCHAR data = NULL; |
| char ch; |
| INT_32 i = 0, j = 0; |
| UINT_32 bufferindex = 0, base = 0; |
| UINT_32 sum = 0, startOffset = 0; |
| CMD_FORMAT_V1_T cmd_v1; |
| |
| memset(&cmd_v1, 0, sizeof(CMD_FORMAT_V1_T)); |
| |
| #if 0 |
| cmd_v1.itemType = atoi(*args[ED_ITEMTYPE_SITE]); |
| #else |
| cmd_v1.itemType = ITEM_TYPE_DEC; |
| #endif |
| if (buffer == NULL || |
| args_size[ED_STRING_SITE] == 0 || |
| args_size[ED_VALUE_SITE] == 0 || |
| (cmd_v1.itemType < ITEM_TYPE_DEC || cmd_v1.itemType > ITEM_TYPE_STR)) { |
| DBGLOG(INIT, ERROR, "cfg args wrong\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| cmd_v1.itemStringLength = args_size[ED_STRING_SITE]; |
| strncpy(cmd_v1.itemString, args[ED_STRING_SITE], cmd_v1.itemStringLength); |
| DBGLOG(INIT, INFO, "itemString:"); |
| for (i = 0; i < cmd_v1.itemStringLength; i++) |
| DBGLOG(INIT, INFO, "%c", cmd_v1.itemString[i]); |
| DBGLOG(INIT, INFO, "\n"); |
| |
| DBGLOG(INIT, INFO, "cmd_v1.itemType = %d\n", cmd_v1.itemType); |
| if (cmd_v1.itemType == ITEM_TYPE_DEC || cmd_v1.itemType == ITEM_TYPE_HEX) { |
| data = args[ED_VALUE_SITE]; |
| |
| switch (cmd_v1.itemType) { |
| case ITEM_TYPE_DEC: |
| base = 10; |
| startOffset = 0; |
| break; |
| case ITEM_TYPE_HEX: |
| ch = *data; |
| if (args_size[ED_VALUE_SITE] < 3 || ch != '0') { |
| DBGLOG(INIT, WARN, "Hex args must have prefix '0x'\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| data++; |
| ch = *data; |
| if (ch != 'x' && ch != 'X') { |
| DBGLOG(INIT, WARN, "Hex args must have prefix '0x'\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| data++; |
| base = 16; |
| startOffset = 2; |
| break; |
| } |
| |
| for (j = args_size[ED_VALUE_SITE] - 1 - startOffset; j >= 0; j--) { |
| sum = sum * base + atoi(*data); |
| DBGLOG(INIT, WARN, "size:%d data[%d]=%u, sum=%u\n", |
| args_size[ED_VALUE_SITE], j, atoi(*data), sum); |
| |
| data++; |
| } |
| |
| bufferindex = 0; |
| do { |
| cmd_v1.itemValue[bufferindex++] = sum & 0xFF; |
| sum = sum >> 8; |
| } while (sum > 0); |
| cmd_v1.itemValueLength = bufferindex; |
| } else if (cmd_v1.itemType == ITEM_TYPE_STR) { |
| cmd_v1.itemValueLength = args_size[ED_VALUE_SITE]; |
| strncpy(cmd_v1.itemValue, args[ED_VALUE_SITE], cmd_v1.itemValueLength); |
| } |
| |
| DBGLOG(INIT, INFO, "Length = %d itemValue:", cmd_v1.itemValueLength); |
| for (i = cmd_v1.itemValueLength - 1; i >= 0; i--) |
| DBGLOG(INIT, ERROR, "%d,", cmd_v1.itemValue[i]); |
| DBGLOG(INIT, INFO, "\n"); |
| memcpy(((P_CMD_FORMAT_V1_T)buffer)+times, &cmd_v1, sizeof(CMD_FORMAT_V1_T)); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to send WLAN feature options to firmware |
| * |
| * @param prAdapter Pointer of ADAPTER_T |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanFeatureToFw(IN P_ADAPTER_T prAdapter) |
| { |
| |
| P_WLAN_CFG_ENTRY_T prWlanCfgEntry; |
| UINT_32 i; |
| CMD_HEADER_T rCmdV1Header; |
| WLAN_STATUS rStatus; |
| CMD_FORMAT_V1_T rCmd_v1; |
| UCHAR ucTimes = 0; |
| |
| |
| |
| rCmdV1Header.cmdType = CMD_TYPE_SET; |
| rCmdV1Header.cmdVersion = CMD_VER_1; |
| rCmdV1Header.cmdBufferLen = 0; |
| rCmdV1Header.itemNum = 0; |
| |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| kalMemSet(&rCmd_v1, 0, sizeof(CMD_FORMAT_V1_T)); |
| |
| |
| prWlanCfgEntry = NULL; |
| |
| for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { |
| |
| prWlanCfgEntry = wlanCfgGetEntryByIndex(prAdapter, i, 0); |
| |
| if (prWlanCfgEntry) { |
| |
| rCmd_v1.itemType = ITEM_TYPE_STR; |
| |
| |
| /*send string format to firmware */ |
| rCmd_v1.itemStringLength = kalStrLen(prWlanCfgEntry->aucKey); |
| kalMemZero(rCmd_v1.itemString, MAX_CMD_NAME_MAX_LENGTH); |
| kalMemCopy(rCmd_v1.itemString, prWlanCfgEntry->aucKey, rCmd_v1.itemStringLength); |
| |
| |
| rCmd_v1.itemValueLength = kalStrLen(prWlanCfgEntry->aucValue); |
| kalMemZero(rCmd_v1.itemValue, MAX_CMD_VALUE_MAX_LENGTH); |
| kalMemCopy(rCmd_v1.itemValue, prWlanCfgEntry->aucValue, rCmd_v1.itemValueLength); |
| |
| |
| |
| DBGLOG(INIT, WARN, "Send key word (%s) WITH (%s) to firmware\n", |
| rCmd_v1.itemString, rCmd_v1.itemValue); |
| |
| kalMemCopy(((P_CMD_FORMAT_V1_T)rCmdV1Header.buffer)+ucTimes, |
| &rCmd_v1, sizeof(CMD_FORMAT_V1_T)); |
| |
| |
| ucTimes++; |
| rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); |
| rCmdV1Header.itemNum += ucTimes; |
| |
| |
| if (ucTimes == MAX_CMD_ITEM_MAX) { |
| /* Send to FW */ |
| rCmdV1Header.itemNum = ucTimes; |
| |
| rStatus = wlanSendSetQueryCmd( |
| prAdapter, /* prAdapter */ |
| CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler*/ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ |
| (PUINT_8)&rCmdV1Header, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| if (rStatus == WLAN_STATUS_FAILURE) |
| DBGLOG(INIT, INFO, "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", rStatus); |
| |
| DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d\n", ucTimes); |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| rCmdV1Header.cmdBufferLen = 0; |
| ucTimes = 0; |
| } |
| |
| |
| } else { |
| break; |
| } |
| } |
| |
| |
| if (ucTimes != 0) { |
| /* Send to FW */ |
| rCmdV1Header.itemNum = ucTimes; |
| |
| DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", rCmdV1Header.itemNum); |
| |
| rStatus = wlanSendSetQueryCmd( |
| prAdapter, /* prAdapter */ |
| CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler*/ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ |
| (PUINT_8)&rCmdV1Header, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| if (rStatus == WLAN_STATUS_FAILURE) |
| DBGLOG(INIT, INFO, "[Fail]kalIoctl wifiSefCFG fail 0x%x\n", rStatus); |
| |
| DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d\n", ucTimes); |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| rCmdV1Header.cmdBufferLen = 0; |
| ucTimes = 0; |
| } |
| |
| } |
| |
| |
| |
| WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, BOOLEAN isFwConfig) |
| { |
| struct WLAN_CFG_PARSE_STATE_S state; |
| PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; |
| PPCHAR ppcArgs; |
| INT_32 i4Nargs; |
| CHAR arcArgv_size[WLAN_CFG_ARGV_MAX]; |
| UCHAR ucTimes = 0; |
| WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; |
| CMD_HEADER_T rCmdV1Header; |
| CHAR ucTmp[WLAN_CFG_VALUE_LEN_MAX]; |
| UINT_8 i; |
| |
| PUINT_8 pucCurrBuf = ucTmp; |
| UINT_32 u4CurrSize = ARRAY_SIZE(ucTmp); |
| UINT_32 u4RetSize = 0; |
| |
| rCmdV1Header.cmdType = CMD_TYPE_SET; |
| rCmdV1Header.cmdVersion = CMD_VER_1; |
| rCmdV1Header.cmdBufferLen = 0; |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| |
| if (pucConfigBuf == NULL) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| if (u4ConfigBufLen == 0) |
| return WLAN_STATUS_FAILURE; |
| |
| ppcArgs = apcArgv; |
| i4Nargs = 0; |
| state.ptr = pucConfigBuf; |
| state.nexttoken = 0; |
| state.textsize = 0; |
| state.maxSize = u4ConfigBufLen; |
| DBGLOG(INIT, INFO, "wlanCfgParse()\n"); |
| |
| for (;;) { |
| switch (wlanCfgFindNextToken(&state)) { |
| case STATE_EOF: |
| if (i4Nargs < 2) |
| goto exit; |
| |
| DBGLOG(INIT, INFO, "STATE_EOF\n"); |
| |
| /*3 parmeter mode transforation */ |
| if (i4Nargs == 3 && !isFwConfig && |
| arcArgv_size[0] == 1) { |
| |
| /*parsing and transfer the format |
| *Format 1:Dec 2.Hex 3.String |
| */ |
| |
| kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); |
| pucCurrBuf = ucTmp; |
| u4CurrSize = ARRAY_SIZE(ucTmp); |
| |
| if ((*ppcArgs[0] == '2') && (*(ppcArgs[2]) != '0') && (*(ppcArgs[2]+1) != 'x')) { |
| DBGLOG(INIT, WARN, "config file got a hex format\n"); |
| kalSnprintf(pucCurrBuf, u4CurrSize, "0x%s", ppcArgs[2]); |
| } else { |
| kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[2]); |
| } |
| DBGLOG(INIT, WARN, "[3 parameter mode][%s],[%s],[%s]\n", ppcArgs[0], ppcArgs[1], ucTmp); |
| wlanCfgParseAddEntry(prAdapter, ppcArgs[1], NULL, ucTmp, NULL); |
| kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); |
| kalMemSet(apcArgv, 0, WLAN_CFG_ARGV_MAX); |
| i4Nargs = 0; |
| goto exit; |
| |
| } |
| |
| wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ppcArgs[1], NULL); |
| |
| if (isFwConfig) { |
| |
| WLAN_STATUS ret; |
| |
| |
| ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, i4Nargs, rCmdV1Header.buffer, ucTimes); |
| if (ret == WLAN_STATUS_SUCCESS) { |
| ucTimes++; |
| rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); |
| } |
| } |
| |
| goto exit; |
| |
| |
| case STATE_NEWLINE: |
| if (i4Nargs < 2) |
| break; |
| |
| DBGLOG(INIT, INFO, "STATE_NEWLINE\n"); |
| #if 1 |
| /*3 parmeter mode transforation */ |
| if (i4Nargs == 3 && !isFwConfig && |
| arcArgv_size[0] == 1) { |
| |
| /*parsing and transfer the format |
| *Format 1:Dec 2.Hex 3.String |
| */ |
| kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); |
| pucCurrBuf = ucTmp; |
| u4CurrSize = ARRAY_SIZE(ucTmp); |
| |
| if ((*ppcArgs[0] == '2') && (*(ppcArgs[2]) != '0') && (*(ppcArgs[2]+1) != 'x')) { |
| DBGLOG(INIT, WARN, "config file got a hex format\n"); |
| kalSnprintf(pucCurrBuf, u4CurrSize, "0x%s", ppcArgs[2]); |
| |
| } else { |
| kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[2]); |
| } |
| |
| |
| DBGLOG(INIT, WARN, "[3 parameter mode][%s],[%s],[%s]\n", ppcArgs[0], ppcArgs[1], ucTmp); |
| wlanCfgParseAddEntry(prAdapter, ppcArgs[1], NULL, ucTmp, NULL); |
| kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); |
| kalMemSet(apcArgv, 0, WLAN_CFG_ARGV_MAX); |
| i4Nargs = 0; |
| break; |
| |
| } |
| #if 1 |
| /*combine the argument to save in temp*/ |
| pucCurrBuf = ucTmp; |
| u4CurrSize = ARRAY_SIZE(ucTmp); |
| |
| kalMemZero(ucTmp, WLAN_CFG_VALUE_LEN_MAX); |
| |
| if (i4Nargs == 2) { |
| /*no space for it, driver can't accept space in the end of the line*/ |
| /*ToDo: skip the space when parsing*/ |
| kalSnprintf(pucCurrBuf, u4CurrSize, "%s", ppcArgs[1]); |
| } else { |
| for (i = 1; i < i4Nargs; i++) { |
| if (u4CurrSize <= 1) { |
| DBGLOG(INIT, ERROR, "write to pucCurrBuf out of bound, i=%d\n", i); |
| break; |
| } |
| u4RetSize = scnprintf(pucCurrBuf, u4CurrSize, "%s ", ppcArgs[i]); |
| pucCurrBuf += u4RetSize; |
| u4CurrSize -= u4RetSize; |
| } |
| } |
| |
| DBGLOG(INIT, WARN, "Save to driver temp buffer as [%s]\n", ucTmp); |
| wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ucTmp, NULL); |
| #else |
| wlanCfgParseAddEntry(prAdapter, ppcArgs[0], NULL, ppcArgs[1], NULL); |
| #endif |
| |
| if (isFwConfig) { |
| |
| WLAN_STATUS ret; |
| |
| ret = wlanCfgParseToFW(ppcArgs, arcArgv_size, i4Nargs, rCmdV1Header.buffer, ucTimes); |
| if (ret == WLAN_STATUS_SUCCESS) { |
| ucTimes++; |
| rCmdV1Header.cmdBufferLen += sizeof(CMD_FORMAT_V1_T); |
| } |
| |
| if (ucTimes == MAX_CMD_ITEM_MAX) { |
| /* Send to FW */ |
| rCmdV1Header.itemNum = ucTimes; |
| rStatus = wlanSendSetQueryCmd( |
| prAdapter, /* prAdapter */ |
| CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler*/ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ |
| (PUINT_8) &rCmdV1Header, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| if (rStatus == WLAN_STATUS_FAILURE) |
| DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG fail 0x%x\n", rStatus); |
| DBGLOG(INIT, INFO, "kalIoctl wifiSefCFG num:%d X\n", ucTimes); |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| rCmdV1Header.cmdBufferLen = 0; |
| ucTimes = 0; |
| } |
| |
| } |
| |
| #endif |
| kalMemSet(arcArgv_size, 0, WLAN_CFG_ARGV_MAX); |
| kalMemSet(apcArgv, 0, WLAN_CFG_ARGV_MAX); |
| i4Nargs = 0; |
| break; |
| |
| case STATE_TEXT: |
| if (i4Nargs < WLAN_CFG_ARGV_MAX) { |
| ppcArgs[i4Nargs++] = state.text; |
| arcArgv_size[i4Nargs-1] = state.textsize; |
| state.textsize = 0; |
| DBGLOG(INIT, INFO, " nargs= %d STATE_TEXT = %s, SIZE = %d\n", |
| i4Nargs-1, ppcArgs[i4Nargs-1], arcArgv_size[i4Nargs-1]); |
| } |
| break; |
| } |
| } |
| |
| exit: |
| if (ucTimes != 0 && isFwConfig) { |
| /* Send to FW */ |
| rCmdV1Header.itemNum = ucTimes; |
| |
| DBGLOG(INIT, INFO, "cmdV1Header.itemNum:%d\n", rCmdV1Header.itemNum); |
| rStatus = wlanSendSetQueryCmd( |
| prAdapter, /* prAdapter */ |
| CMD_ID_GET_SET_CUSTOMER_CFG, /* 0x70 */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler*/ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HEADER_T), /* u4SetQueryInfoLen */ |
| (PUINT_8) &rCmdV1Header, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| if (rStatus == WLAN_STATUS_FAILURE) |
| DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG fail 0x%x\n", rStatus); |
| |
| DBGLOG(INIT, WARN, "kalIoctl wifiSefCFG num:%d X\n", ucTimes); |
| kalMemSet(rCmdV1Header.buffer, 0, MAX_CMD_BUFFER_LENGTH); |
| rCmdV1Header.cmdBufferLen = 0; |
| ucTimes = 0; |
| } |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #else |
| WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) |
| { |
| |
| struct WLAN_CFG_PARSE_STATE_S state; |
| PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; |
| CHAR **args; |
| INT_32 nargs; |
| |
| if (pucConfigBuf == NULL) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { |
| ASSERT(0); |
| return WLAN_STATUS_FAILURE; |
| } |
| if (u4ConfigBufLen == 0) |
| return WLAN_STATUS_FAILURE; |
| args = apcArgv; |
| nargs = 0; |
| state.ptr = pucConfigBuf; |
| state.nexttoken = 0; |
| state.maxSize = u4ConfigBufLen; |
| |
| for (;;) { |
| switch (wlanCfgFindNextToken(&state)) { |
| case STATE_EOF: |
| if (nargs > 1) |
| wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); |
| goto exit; |
| case STATE_NEWLINE: |
| if (nargs > 1) |
| wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); |
| /*args[0] is parameter, args[1] is the value*/ |
| nargs = 0; |
| break; |
| case STATE_TEXT: |
| if (nargs < WLAN_CFG_ARGV_MAX) |
| args[nargs++] = state.text; |
| break; |
| } |
| } |
| |
| exit: |
| return WLAN_STATUS_SUCCESS; |
| |
| #if 0 |
| /* Old version */ |
| UINT_32 i; |
| UINT_8 c; |
| PUINT_8 pbuf; |
| UINT_8 ucState; |
| PUINT_8 pucKeyTail = NULL; |
| PUINT_8 pucKeyHead = NULL; |
| PUINT_8 pucValueHead = NULL; |
| PUINT_8 pucValueTail = NULL; |
| |
| ucState = WAIT_KEY_HEAD; |
| pbuf = pucConfigBuf; |
| |
| for (i = 0; i < u4ConfigBufLen; i++) { |
| c = pbuf[i]; |
| if (c == '\r' || c == '\n') { |
| |
| if (ucState == WAIT_VALUE_TAIL) { |
| /* Entry found */ |
| if (pucValueHead) |
| wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, |
| pucValueHead, pucValueTail); |
| } |
| ucState = WAIT_KEY_HEAD; |
| pucKeyTail = NULL; |
| pucKeyHead = NULL; |
| pucValueHead = NULL; |
| pucValueTail = NULL; |
| |
| } else if (c == '=') { |
| if (ucState == WAIT_KEY_TAIL) { |
| pucKeyTail = &pbuf[i - 1]; |
| ucState = WAIT_VALUE_HEAD; |
| } |
| } else if (c == ' ' || c == '\t') { |
| if (ucState == WAIT_KEY_TAIL) { |
| pucKeyTail = &pbuf[i - 1]; |
| ucState = WAIT_VALUE_HEAD; |
| } |
| } else { |
| |
| if (c == '#') { |
| /* comments */ |
| if (ucState == WAIT_KEY_HEAD) |
| ucState = WAIT_COMMENT_TAIL; |
| else if (ucState == WAIT_VALUE_TAIL) |
| pucValueTail = &pbuf[i]; |
| |
| } else { |
| if (ucState == WAIT_KEY_HEAD) { |
| pucKeyHead = &pbuf[i]; |
| pucKeyTail = &pbuf[i]; |
| ucState = WAIT_KEY_TAIL; |
| } else if (ucState == WAIT_VALUE_HEAD) { |
| pucValueHead = &pbuf[i]; |
| pucValueTail = &pbuf[i]; |
| ucState = WAIT_VALUE_TAIL; |
| } else if (ucState == WAIT_VALUE_TAIL) |
| pucValueTail = &pbuf[i]; |
| } |
| } |
| |
| } /* for */ |
| |
| if (ucState == WAIT_VALUE_TAIL) { |
| /* Entry found */ |
| if (pucValueTail) |
| wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); |
| } |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| #endif |
| |
| |
| WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) |
| { |
| P_WLAN_CFG_T prWlanCfg; |
| P_WLAN_CFG_REC_T prWlanCfgRec; |
| /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ |
| prAdapter->prWlanCfg = &prAdapter->rWlanCfg; |
| prWlanCfg = prAdapter->prWlanCfg; |
| |
| prAdapter->prWlanCfgRec = &prAdapter->rWlanCfgRec; |
| prWlanCfgRec = prAdapter->prWlanCfgRec; |
| |
| kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); |
| ASSERT(prWlanCfg); |
| prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; |
| prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; |
| prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; |
| |
| prWlanCfgRec->u4WlanCfgEntryNumMax = WLAN_CFG_REC_ENTRY_NUM_MAX; |
| prWlanCfgRec->u4WlanCfgKeyLenMax = WLAN_CFG_REC_ENTRY_NUM_MAX; |
| prWlanCfgRec->u4WlanCfgValueLenMax = WLAN_CFG_REC_ENTRY_NUM_MAX; |
| |
| DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); |
| #if DBG |
| /* self test */ |
| wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); |
| if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) |
| DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); |
| |
| wlanCfgSet(prAdapter, "ConfigValid", "1", 0); |
| if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) |
| DBGLOG(INIT, INFO, "wifi config error %u\n", __LINE__); |
| |
| #endif |
| /*load default value because kalMemZero in this function*/ |
| wlanLoadDefaultCustomerSetting(prAdapter); |
| |
| /* Parse the pucConfigBuff */ |
| |
| if (pucConfigBuf && (u4ConfigBufLen > 0)) |
| #if CFG_SUPPORT_EASY_DEBUG |
| wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen, FALSE); |
| #else |
| wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); |
| #endif |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #endif /* CFG_SUPPORT_CFG_FILE */ |
| |
| INT_32 wlanHexToNum(CHAR c) |
| { |
| if (c >= '0' && c <= '9') |
| return c - '0'; |
| if (c >= 'a' && c <= 'f') |
| return c - 'a' + 10; |
| if (c >= 'A' && c <= 'F') |
| return c - 'A' + 10; |
| return -1; |
| } |
| |
| INT_32 wlanHexToByte(PCHAR hex) |
| { |
| INT_32 a, b; |
| |
| a = wlanHexToNum(*hex++); |
| if (a < 0) |
| return -1; |
| b = wlanHexToNum(*hex++); |
| if (b < 0) |
| return -1; |
| return (a << 4) | b; |
| } |
| |
| INT_32 wlanHwAddrToBin(PCHAR txt, UINT_8 *addr) |
| { |
| INT_32 i; |
| PCHAR pos = txt; |
| |
| for (i = 0; i < 6; i++) { |
| INT_32 a, b; |
| |
| while (*pos == ':' || *pos == '.' || *pos == '-') |
| pos++; |
| |
| a = wlanHexToNum(*pos++); |
| if (a < 0) |
| return -1; |
| b = wlanHexToNum(*pos++); |
| if (b < 0) |
| return -1; |
| *addr++ = (a << 4) | b; |
| } |
| |
| return pos - txt; |
| } |
| |
| BOOLEAN wlanIsChipNoAck(IN P_ADAPTER_T prAdapter) |
| { |
| BOOLEAN fgIsNoAck; |
| |
| fgIsNoAck = prAdapter->fgIsChipNoAck |
| #if CFG_CHIP_RESET_SUPPORT |
| || kalIsResetting() |
| #endif |
| || fgIsBusAccessFailed; |
| |
| return fgIsNoAck; |
| } |
| |
| BOOLEAN wlanIsChipRstRecEnabled(IN P_ADAPTER_T prAdapter) |
| { |
| return prAdapter->rWifiVar.fgChipResetRecover; |
| } |
| |
| BOOLEAN wlanIsChipAssert(IN P_ADAPTER_T prAdapter) |
| { |
| return prAdapter->rWifiVar.fgChipResetRecover && prAdapter->fgIsChipAssert; |
| } |
| |
| VOID wlanChipRstPreAct(IN P_ADAPTER_T prAdapter) |
| { |
| P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; |
| INT_32 i4BssIdx; |
| UINT_32 u4ClientCount = 0; |
| P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; |
| P_STA_RECORD_T prNextCurrStaRec = (P_STA_RECORD_T) NULL; |
| P_LINK_T prClientList; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| |
| KAL_ACQUIRE_MUTEX(prAdapter, MUTEX_CHIP_RST); |
| if (prAdapter->fgIsChipAssert) { |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); |
| return; |
| } |
| prAdapter->fgIsChipAssert = TRUE; |
| KAL_RELEASE_MUTEX(prAdapter, MUTEX_CHIP_RST); |
| |
| for (i4BssIdx = 0; i4BssIdx < HW_BSSID_NUM; i4BssIdx++) { |
| prBssInfo = prAdapter->aprBssInfo[i4BssIdx]; |
| |
| if (!prBssInfo->fgIsInUse) |
| continue; |
| |
| if (prBssInfo->eNetworkType == NETWORK_TYPE_AIS) { |
| |
| if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) |
| kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); |
| } else if (prBssInfo->eNetworkType == NETWORK_TYPE_P2P) { |
| if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { |
| u4ClientCount = bssGetClientCount(prAdapter, prBssInfo); |
| |
| if (u4ClientCount == 0) |
| continue; |
| |
| prClientList = &prBssInfo->rStaRecOfClientList; |
| LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prNextCurrStaRec, |
| prClientList, rLinkEntry, STA_RECORD_T) { |
| kalP2PGOStationUpdate(prAdapter->prGlueInfo, |
| (UINT_8) prBssInfo->u4PrivateData, prCurrStaRec, FALSE); |
| LINK_REMOVE_KNOWN_ENTRY(prClientList, &prCurrStaRec->rLinkEntry); |
| } |
| } else if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| if (prBssInfo->prStaRecOfAP == NULL) |
| continue; |
| #if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) |
| kalP2PGCIndicateConnectionStatus(prGlueInfo, |
| (UINT_8) prBssInfo->u4PrivateData, |
| NULL, NULL, 0, 0, |
| WLAN_STATUS_MEDIA_DISCONNECT); |
| #else |
| kalP2PGCIndicateConnectionStatus(prGlueInfo, |
| (UINT_8) prBssInfo->u4PrivateData, NULL, NULL, 0, 0); |
| #endif |
| prBssInfo->prStaRecOfAP = NULL; |
| |
| } |
| } |
| } |
| } |
| |
| #if CFG_ENABLE_PER_STA_STATISTICS |
| VOID wlanTxLifetimeUpdateStaStats(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) |
| { |
| P_STA_RECORD_T prStaRec; |
| UINT_32 u4DeltaTime; |
| P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if (prStaRec) { |
| u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - prPktProfile->rHardXmitArrivalTimestamp); |
| |
| /* Update StaRec statistics */ |
| prStaRec->u4TotalTxPktsNumber++; |
| prStaRec->u4TotalTxPktsTime += u4DeltaTime; |
| |
| if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) |
| prStaRec->u4MaxTxPktsTime = u4DeltaTime; |
| if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) |
| prStaRec->u4ThresholdCounter++; |
| } |
| } |
| #endif |
| |
| BOOLEAN wlanTxLifetimeIsProfilingEnabled(IN P_ADAPTER_T prAdapter) |
| { |
| BOOLEAN fgEnabled = FALSE; |
| #if CFG_SUPPORT_WFD |
| P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; |
| |
| prWfdCfgSettings = &prAdapter->rWifiVar.rWfdConfigureSettings; |
| |
| if (prWfdCfgSettings->ucWfdEnable > 0) |
| fgEnabled = TRUE; |
| #endif |
| |
| return fgEnabled; |
| } |
| |
| BOOLEAN wlanTxLifetimeIsTargetMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) |
| { |
| BOOLEAN fgResult = TRUE; |
| |
| #if 0 |
| switch (prMsduInfo->ucTID) { |
| /* BK */ |
| case 1: |
| case 2: |
| |
| /* BE */ |
| case 0: |
| case 3: |
| fgResult = FALSE; |
| break; |
| /* VI */ |
| case 4: |
| case 5: |
| |
| /* VO */ |
| case 6: |
| case 7: |
| fgResult = TRUE; |
| break; |
| default: |
| break; |
| } |
| #endif |
| return fgResult; |
| } |
| |
| VOID wlanTxLifetimeTagPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) |
| { |
| P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; |
| |
| if (!wlanTxLifetimeIsProfilingEnabled(prAdapter)) |
| return; |
| |
| switch (eTag) { |
| case TX_PROF_TAG_OS_TO_DRV: |
| /* arrival time is tagged in wlanProcessTxFrame */ |
| break; |
| |
| case TX_PROF_TAG_DRV_ENQUE: |
| /* Reset packet profile */ |
| prPktProfile->fgIsValid = FALSE; |
| if (wlanTxLifetimeIsTargetMsdu(prAdapter, prMsduInfo)) { |
| /* Enable packet lifetime profiling */ |
| prPktProfile->fgIsValid = TRUE; |
| |
| /* Packet arrival time at kernel Hard Xmit */ |
| prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prMsduInfo->prPacket); |
| |
| /* Packet enqueue time */ |
| prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); |
| } |
| break; |
| |
| case TX_PROF_TAG_DRV_DEQUE: |
| if (prPktProfile->fgIsValid) |
| prPktProfile->rDequeueTimestamp = (OS_SYSTIME) kalGetTimeTick(); |
| break; |
| |
| case TX_PROF_TAG_DRV_TX_DONE: |
| if (prPktProfile->fgIsValid) { |
| prPktProfile->rHifTxDoneTimestamp = (OS_SYSTIME) kalGetTimeTick(); |
| |
| #if CFG_ENABLE_PER_STA_STATISTICS |
| wlanTxLifetimeUpdateStaStats(prAdapter, prMsduInfo); |
| #endif |
| } |
| break; |
| |
| case TX_PROF_TAG_MAC_TX_DONE: |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| VOID wlanTxProfilingTagPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket, IN ENUM_TX_PROFILING_TAG_T eTag) |
| { |
| #if CFG_MET_PACKET_TRACE_SUPPORT |
| kalMetTagPacket(prAdapter->prGlueInfo, prPacket, eTag); |
| #endif |
| } |
| |
| VOID wlanTxProfilingTagMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_PROFILING_TAG_T eTag) |
| { |
| wlanTxLifetimeTagPacket(prAdapter, prMsduInfo, eTag); |
| |
| wlanTxProfilingTagPacket(prAdapter, prMsduInfo->prPacket, eTag); |
| } |
| |
| VOID wlanUpdateTxStatistics(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgTxDrop) |
| { |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prBssInfo; |
| ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; |
| P_QUE_MGT_T prQM = &prAdapter->rQM; |
| OS_SYSTIME rCurTime; |
| |
| eAci = aucTid2ACI[prMsduInfo->ucUserPriority]; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if (prStaRec) { |
| if (fgTxDrop) |
| prStaRec->arLinkStatistics[eAci].u4TxDropMsdu++; |
| else |
| prStaRec->arLinkStatistics[eAci].u4TxMsdu++; |
| } else { |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); |
| |
| if (fgTxDrop) |
| prBssInfo->arLinkStatistics[eAci].u4TxDropMsdu++; |
| else |
| prBssInfo->arLinkStatistics[eAci].u4TxMsdu++; |
| } |
| |
| /* Trigger FW stats log every 20s */ |
| rCurTime = (OS_SYSTIME) kalGetTimeTick(); |
| |
| DBGLOG(INIT, LOUD, "CUR[%u] LAST[%u] TO[%u]\n", rCurTime, |
| prQM->rLastTxPktDumpTime, CHECK_FOR_TIMEOUT(rCurTime, |
| prQM->rLastTxPktDumpTime, |
| MSEC_TO_SYSTIME(prAdapter->rWifiVar.u4StatsLogTimeout))); |
| |
| if (CHECK_FOR_TIMEOUT(rCurTime, prQM->rLastTxPktDumpTime, |
| MSEC_TO_SYSTIME(prAdapter->rWifiVar.u4StatsLogTimeout))) { |
| |
| wlanTriggerStatsLog(prAdapter, prAdapter->rWifiVar.u4StatsLogDuration); |
| wlanDumpAllBssStatistics(prAdapter); |
| |
| prQM->rLastTxPktDumpTime = rCurTime; |
| } |
| } |
| |
| VOID wlanUpdateRxStatistics(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_STA_RECORD_T prStaRec; |
| ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; |
| |
| eAci = aucTid2ACI[prSwRfb->ucTid]; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| if (prStaRec) |
| prStaRec->arLinkStatistics[eAci].u4RxMsdu++; |
| } |
| |
| WLAN_STATUS wlanTriggerStatsLog(IN P_ADAPTER_T prAdapter, IN UINT_32 u4DurationInMs) |
| { |
| CMD_STATS_LOG_T rStatsLogCmd; |
| WLAN_STATUS rResult; |
| |
| if (prAdapter->fgIsEnableLpdvt) |
| return WLAN_STATUS_NOT_SUPPORTED; |
| |
| kalMemZero(&rStatsLogCmd, sizeof(CMD_STATS_LOG_T)); |
| |
| rStatsLogCmd.u4DurationInMs = u4DurationInMs; |
| |
| rResult = wlanSendSetQueryCmd(prAdapter, CMD_ID_STATS_LOG, TRUE, FALSE, |
| FALSE, nicCmdEventSetCommon, nicOidCmdTimeoutCommon, |
| sizeof(CMD_STATS_LOG_T), (PUINT_8) &rStatsLogCmd, NULL, 0); |
| |
| return rResult; |
| } |
| |
| WLAN_STATUS |
| wlanDhcpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| DBGLOG(SW4, INFO, "DHCP PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", |
| prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS wlanArpTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| DBGLOG(SW4, INFO, "ARP PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", |
| prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS wlan1xTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, |
| IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| DBGLOG(SW4, INFO, "1x PKT[0x%08x] WIDX:PID[%u:%u] Status[%u]\n", |
| prMsduInfo->u4TxDoneTag, prMsduInfo->ucWlanIndex, prMsduInfo->ucPID, rTxDoneStatus); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #if CFG_ASSERT_DUMP |
| VOID wlanCorDumpTimerReset(IN P_ADAPTER_T prAdapter, BOOLEAN fgIsResetN9) |
| { |
| |
| if (prAdapter->fgN9AssertDumpOngoing || prAdapter->fgCr4AssertDumpOngoing) { |
| |
| if (fgIsResetN9) { |
| cnmTimerStopTimer(prAdapter, &prAdapter->rN9CorDumpTimer); |
| cnmTimerStartTimer(prAdapter, &prAdapter->rN9CorDumpTimer, 5000); |
| } else { |
| cnmTimerStopTimer(prAdapter, &prAdapter->rCr4CorDumpTimer); |
| cnmTimerStartTimer(prAdapter, &prAdapter->rCr4CorDumpTimer, 5000); |
| } |
| } else { |
| DBGLOG(INIT, INFO, "Cr4, N9 CorDump Is not ongoing, ignore timer reset\n"); |
| } |
| } |
| |
| VOID wlanN9CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) |
| { |
| |
| if (prAdapter->fgN9CorDumpFileOpend) { |
| DBGLOG(INIT, INFO, "\n[DUMP_N9]====N9 ASSERT_END====\n"); |
| prAdapter->fgN9AssertDumpOngoing = FALSE; |
| kalCloseCorDumpFile(TRUE); |
| prAdapter->fgN9CorDumpFileOpend = FALSE; |
| } |
| } |
| |
| VOID wlanCr4CorDumpTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr) |
| { |
| |
| if (prAdapter->fgCr4CorDumpFileOpend) { |
| DBGLOG(INIT, INFO, "\n[DUMP_Cr4]====Cr4 ASSERT_END====\n"); |
| prAdapter->fgCr4AssertDumpOngoing = FALSE; |
| kalCloseCorDumpFile(FALSE); |
| prAdapter->fgCr4CorDumpFileOpend = FALSE; |
| } |
| } |
| #endif |
| |
| BOOL |
| wlanGetWlanIdxByAddress(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucAddr, OUT PUINT_8 pucIndex) |
| { |
| UINT_8 ucStaRecIdx; |
| P_STA_RECORD_T prTempStaRec; |
| |
| for (ucStaRecIdx = 0; ucStaRecIdx < CFG_STA_REC_NUM; ucStaRecIdx++) { |
| prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); |
| if (pucAddr) { |
| if (prTempStaRec->fgIsInUse && EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucAddr)) { |
| *pucIndex = prTempStaRec->ucWlanIndex; |
| return TRUE; |
| } |
| } else { |
| if (prTempStaRec->fgIsInUse && prTempStaRec->ucStaState == STA_STATE_3) { |
| *pucIndex = prTempStaRec->ucWlanIndex; |
| return TRUE; |
| } |
| } |
| } |
| return FALSE; |
| } |
| |
| |
| PUINT_8 |
| wlanGetStaAddrByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex) |
| { |
| P_WLAN_TABLE_T prWtbl; |
| |
| if (!prAdapter) |
| ASSERT(FALSE); |
| prWtbl = prAdapter->rWifiVar.arWtbl; |
| if (ucIndex < WTBL_SIZE) { |
| if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) |
| return &prWtbl[ucIndex].aucMacAddr[0]; |
| } |
| return NULL; |
| } |
| |
| VOID |
| wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, struct net_device *prDev, BOOLEAN fgSuspend) |
| { |
| WLAN_STATUS rStatus; |
| UINT_32 u4SetInfoLen; |
| P_NETDEV_PRIVATE_GLUE_INFO prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) NULL; |
| CMD_SUSPEND_MODE_SETTING_T rSuspendCmd; |
| |
| prNetDevPrivate = (P_NETDEV_PRIVATE_GLUE_INFO) netdev_priv(prDev); |
| |
| if (prNetDevPrivate->prGlueInfo != prGlueInfo) |
| DBGLOG(REQ, WARN, "%s: unexpected prGlueInfo(0x%p)!\n", __func__, prNetDevPrivate->prGlueInfo); |
| |
| rSuspendCmd.ucBssIndex = prNetDevPrivate->ucBssIdx; |
| rSuspendCmd.ucEnableSuspendMode = fgSuspend; |
| |
| if (prGlueInfo->prAdapter->rWifiVar.ucWow && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { |
| /* cfg enable + wow enable => Wow On mdtim*/ |
| rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOnMdtim; |
| DBGLOG(REQ, INFO, "mdtim [1]\n"); |
| } else if (prGlueInfo->prAdapter->rWifiVar.ucWow && !prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { |
| if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { |
| /* cfg enable + wow disable + adv pws enable => Wow Off mdtim */ |
| rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; |
| DBGLOG(REQ, INFO, "mdtim [2]\n"); |
| } |
| } else if (!prGlueInfo->prAdapter->rWifiVar.ucWow) { |
| if (prGlueInfo->prAdapter->rWifiVar.ucAdvPws) { |
| /* cfg disable + adv pws enable => MT6632 case => Wow Off mdtim */ |
| rSuspendCmd.ucMdtim = prGlueInfo->prAdapter->rWifiVar.ucWowOffMdtim; |
| DBGLOG(REQ, INFO, "mdtim [3]\n"); |
| } |
| } |
| |
| /* When FW receive command, it check connection state to decide apply setting or not */ |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidNotifyFwSuspend, |
| (PVOID)&rSuspendCmd, |
| sizeof(rSuspendCmd), |
| FALSE, |
| FALSE, |
| TRUE, |
| &u4SetInfoLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) |
| DBGLOG(REQ, INFO, "wlanNotifyFwSuspend fail\n"); |
| } |
| |
| WLAN_STATUS |
| wlanGetStaIdxByWlanIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex, OUT PUINT_8 pucStaIdx) |
| { |
| P_WLAN_TABLE_T prWtbl; |
| |
| if (!prAdapter) |
| ASSERT(FALSE); |
| |
| prWtbl = prAdapter->rWifiVar.arWtbl; |
| |
| if (ucIndex < WTBL_SIZE) { |
| if (prWtbl[ucIndex].ucUsed && prWtbl[ucIndex].ucPairwise) { |
| *pucStaIdx = prWtbl[ucIndex].ucStaIndex; |
| return WLAN_STATUS_SUCCESS; |
| } |
| } |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| #if CFG_AUTO_CHANNEL_SEL_SUPPORT |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is called to query LTE safe channels. |
| * |
| * \param[in] pvAdapter Pointer to the Adapter structure. |
| * \param[out] pvQueryBuffer A pointer to the buffer that holds the result of |
| * the query. |
| * \param[in] u4QueryBufferLen The length of the query buffer. |
| * \param[out] pu4QueryInfoLen If the call is successful, returns the number of |
| * bytes written into the query buffer. If the call |
| * failed due to invalid length of the query buffer, |
| * returns the amount of storage needed. |
| * |
| * \retval WLAN_STATUS_PENDING |
| * \retval WLAN_STATUS_FAILURE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS |
| wlanoidQueryLteSafeChannel(IN P_ADAPTER_T prAdapter, |
| IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) |
| { |
| WLAN_STATUS rResult = WLAN_STATUS_FAILURE; |
| CMD_GET_LTE_SAFE_CHN_T rQuery_LTE_SAFE_CHN; |
| |
| do { |
| /* Sanity test */ |
| if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) |
| break; |
| if ((pvQueryBuffer == NULL) || (u4QueryBufferLen == 0)) |
| break; |
| |
| /* Get LTE safe channel list */ |
| rResult = wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_GET_LTE_CHN, |
| FALSE, |
| TRUE, |
| TRUE, /* Query ID */ |
| nicCmdEventQueryLteSafeChn, /* The handler to receive firmware notification */ |
| nicOidCmdTimeoutCommon, |
| sizeof(CMD_GET_LTE_SAFE_CHN_T), |
| (PUINT_8)&rQuery_LTE_SAFE_CHN, |
| pvQueryBuffer, |
| u4QueryBufferLen); |
| DBGLOG(P2P, INFO, "[ACS] Get safe LTE Channels\n"); |
| } while (FALSE); |
| |
| return rResult; |
| } /* wlanoidQueryLteSafeChannel */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Add dirtiness to neighbor channels of a BSS to estimate channel quality. |
| * |
| * \param[in] prAdapter Pointer to the Adapter structure. |
| * \param[in] prBssDesc Pointer to the BSS description. |
| * \param[in] u4Dirtiness Expected dirtiness value. |
| * \param[in] ucCentralChannel Central channel of the given BSS. |
| * \param[in] ucCoveredRange With ucCoveredRange and ucCentralChannel, |
| * all the affected channels can be enumerated. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID |
| wlanAddDirtinessToAffectedChannels(P_ADAPTER_T prAdapter, |
| P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtiness, UINT_8 ucCentralChannel, |
| UINT_8 ucCoveredRange) |
| { |
| UINT_8 ucIdx, ucStart, ucEnd; |
| BOOL bIs5GChl = ucCentralChannel > 14; |
| UINT_8 ucLeftNeighborChannel, ucRightNeighborChannel, |
| ucLeftNeighborChannel2 = 0, ucRightNeighborChannel2 = 0, |
| ucLeftestCoveredChannel, ucRightestCoveredChannel; |
| P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); |
| |
| ucLeftestCoveredChannel = ucCentralChannel > ucCoveredRange ? |
| ucCentralChannel - ucCoveredRange : 1; |
| |
| ucLeftNeighborChannel = ucLeftestCoveredChannel ? |
| ucLeftestCoveredChannel - 1 : 0; |
| |
| /* align leftest covered ch and left neighbor ch to valid 5g ch */ |
| if (bIs5GChl) { |
| ucLeftestCoveredChannel += 2; |
| ucLeftNeighborChannel -= 1; |
| } else { |
| /* we select the nearest 2 ch to the leftest covered ch as left neighbor chs */ |
| ucLeftNeighborChannel2 = |
| ucLeftNeighborChannel > 1 ? ucLeftNeighborChannel - 1 : 0; |
| } |
| |
| /* handle corner cases of 5g ch*/ |
| if (ucLeftestCoveredChannel > 14 && ucLeftestCoveredChannel <= 36) { |
| ucLeftestCoveredChannel = 36; |
| ucLeftNeighborChannel = 0; |
| } else if (ucLeftestCoveredChannel > 64 && ucLeftestCoveredChannel <= 100) { |
| ucLeftestCoveredChannel = 100; |
| ucLeftNeighborChannel = 0; |
| } else if (ucLeftestCoveredChannel > 140 && ucLeftestCoveredChannel <= 149) { |
| ucLeftestCoveredChannel = 149; |
| ucLeftNeighborChannel = 0; |
| } else if (ucLeftestCoveredChannel > 173 && ucLeftestCoveredChannel <= 184) { |
| ucLeftestCoveredChannel = 184; |
| ucLeftNeighborChannel = 0; |
| } |
| |
| /* |
| * because ch 14 is 12MHz away to ch13, we must shift the leftest covered ch and |
| * left neighbor ch when central ch is ch 14 |
| */ |
| if (ucCentralChannel == 14) { |
| ucLeftestCoveredChannel = 13; |
| ucLeftNeighborChannel = 12; |
| ucLeftNeighborChannel2 = 11; |
| } |
| |
| ucRightestCoveredChannel = ucCentralChannel + ucCoveredRange; |
| ucRightNeighborChannel = ucRightestCoveredChannel + 1; |
| |
| /* align rightest covered ch and right neighbor ch to valid 5g ch */ |
| if (bIs5GChl) { |
| ucRightestCoveredChannel -= 2; |
| ucRightNeighborChannel += 1; |
| } else { |
| /* we select the nearest 2 ch to the rightest covered ch as right neighbor ch */ |
| ucRightNeighborChannel2 = |
| ucRightNeighborChannel < 13 ? ucRightNeighborChannel + 1 : 0; |
| } |
| |
| /* handle corner cases */ |
| if (ucRightestCoveredChannel >= 14 && ucRightestCoveredChannel < 36) { |
| if (ucRightestCoveredChannel == 14) { |
| ucRightestCoveredChannel = 13; |
| ucRightNeighborChannel = 14; |
| } else { |
| ucRightestCoveredChannel = 14; |
| ucRightNeighborChannel = 0; |
| } |
| |
| ucRightNeighborChannel2 = 0; |
| } else if (ucRightestCoveredChannel >= 64 && ucRightestCoveredChannel < 100) { |
| ucRightestCoveredChannel = 64; |
| ucRightNeighborChannel = 0; |
| } else if (ucRightestCoveredChannel >= 140 && ucRightestCoveredChannel < 149) { |
| ucRightestCoveredChannel = 140; |
| ucRightNeighborChannel = 0; |
| } else if (ucRightestCoveredChannel >= 173 && ucRightestCoveredChannel < 184) { |
| ucRightestCoveredChannel = 173; |
| ucRightNeighborChannel = 0; |
| } |
| |
| DBGLOG(SCN, TRACE, "central ch %d\n", ucCentralChannel); |
| |
| ucStart = wlanGetChannelIndex(ucLeftestCoveredChannel); |
| ucEnd = wlanGetChannelIndex(ucRightestCoveredChannel); |
| |
| for (ucIdx = ucStart; ucIdx <= ucEnd; ucIdx++) { |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += u4Dirtiness; |
| DBGLOG(SCN, TRACE, "Add dirtiness %d, to covered ch %d\n", |
| u4Dirtiness, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); |
| } |
| |
| if (ucLeftNeighborChannel != 0) { |
| ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel); |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); |
| DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", |
| u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); |
| } |
| |
| if (ucRightNeighborChannel != 0) { |
| ucIdx = wlanGetChannelIndex(ucRightNeighborChannel); |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); |
| DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", |
| u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); |
| } |
| |
| if (!bIs5GChl) { |
| if (ucLeftNeighborChannel2 != 0) { |
| ucIdx = wlanGetChannelIndex(ucLeftNeighborChannel2); |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); |
| DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", |
| u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); |
| } |
| |
| if (ucRightNeighborChannel2 != 0) { |
| ucIdx = wlanGetChannelIndex(ucRightNeighborChannel2); |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness += (u4Dirtiness >> 1); |
| DBGLOG(SCN, TRACE, "Add dirtiness %d, to neighbor ch %d\n", |
| u4Dirtiness >> 1, prGetChnLoad->rEachChnLoad[ucIdx].ucChannel); |
| } |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief For a scanned BSS, add dirtiness to the channels 1)around its primary |
| * channels and 2) in its working BW to represent the quality degrade. |
| * |
| * \param[in] prAdapter Pointer to the Adapter structure. |
| * \param[in] prBssDesc Pointer to the BSS description. |
| * \param[in] u4Dirtiness Expected dirtiness value. |
| * \param[in] bIsIndexOne True means index 1, False means index 2. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| static VOID |
| wlanCalculateChannelDirtiness(IN P_ADAPTER_T prAdapter, |
| P_BSS_DESC_T prBssDesc, UINT_32 u4Dirtiness, BOOL bIsIndexOne) |
| { |
| UINT_8 ucCoveredRange = 0, ucCentralChannel = 0, ucCentralChannel2 = 0; |
| |
| if (bIsIndexOne) { |
| DBGLOG(SCN, TRACE, "Process dirtiness index 1\n"); |
| ucCentralChannel = prBssDesc->ucChannelNum; |
| ucCoveredRange = 2; |
| } else { |
| DBGLOG(SCN, TRACE, "Process dirtiness index 2, "); |
| switch (prBssDesc->eChannelWidth) { |
| case CW_20_40MHZ: |
| if (prBssDesc->eSco == CHNL_EXT_SCA) { |
| DBGLOG(SCN, TRACE, "BW40\n"); |
| ucCentralChannel = prBssDesc->ucChannelNum + 2; |
| ucCoveredRange = 4; |
| } else if (prBssDesc->eSco == CHNL_EXT_SCB) { |
| DBGLOG(SCN, TRACE, "BW40\n"); |
| ucCentralChannel = prBssDesc->ucChannelNum - 2; |
| ucCoveredRange = 4; |
| } else { |
| DBGLOG(SCN, TRACE, "BW20\n"); |
| ucCentralChannel = prBssDesc->ucChannelNum; |
| ucCoveredRange = 2; |
| } |
| break; |
| case CW_80MHZ: |
| DBGLOG(SCN, TRACE, "BW80\n"); |
| ucCentralChannel = prBssDesc->ucCenterFreqS1; |
| ucCoveredRange = 8; |
| break; |
| case CW_160MHZ: |
| DBGLOG(SCN, TRACE, "BW160\n"); |
| ucCentralChannel = prBssDesc->ucCenterFreqS1; |
| ucCoveredRange = 16; |
| break; |
| case CW_80P80MHZ: |
| DBGLOG(SCN, TRACE, "BW8080\n"); |
| ucCentralChannel = prBssDesc->ucCenterFreqS1; |
| ucCentralChannel2 = prBssDesc->ucCenterFreqS2; |
| ucCoveredRange = 8; |
| break; |
| default: |
| ucCentralChannel = prBssDesc->ucChannelNum; |
| ucCoveredRange = 2; |
| break; |
| }; |
| } |
| |
| wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, u4Dirtiness, |
| ucCentralChannel, ucCoveredRange); |
| |
| /* 80 + 80 secondary 80 case */ |
| if (bIsIndexOne || ucCentralChannel2 == 0) |
| return; |
| |
| wlanAddDirtinessToAffectedChannels(prAdapter, prBssDesc, u4Dirtiness, |
| ucCentralChannel2, ucCoveredRange); |
| } |
| |
| VOID |
| wlanInitChnLoadInfoChannelList(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_8 ucIdx = 0; |
| P_PARAM_GET_CHN_INFO prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); |
| |
| for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ucIdx++) |
| prGetChnLoad->rEachChnLoad[ucIdx].ucChannel = |
| wlanGetChannelNumFromIndex(ucIdx); |
| } |
| |
| WLAN_STATUS |
| wlanCalculateAllChannelDirtiness(IN P_ADAPTER_T prAdapter) |
| { |
| WLAN_STATUS rResult = WLAN_STATUS_SUCCESS; |
| PARAM_RSSI i4Rssi = 0; |
| P_BSS_DESC_T prBssDesc = NULL; |
| UINT_32 u4Dirtiness = 0; |
| P_LINK_T prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); |
| |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { |
| i4Rssi = RCPI_TO_dBm(prBssDesc->ucRCPI); |
| |
| if (i4Rssi >= ACS_AP_RSSI_LEVEL_HIGH) |
| u4Dirtiness = ACS_DIRTINESS_LEVEL_HIGH; |
| else if (i4Rssi >= ACS_AP_RSSI_LEVEL_LOW) |
| u4Dirtiness = ACS_DIRTINESS_LEVEL_MID; |
| else |
| u4Dirtiness = ACS_DIRTINESS_LEVEL_LOW; |
| |
| DBGLOG(SCN, TRACE, "Found an AP(%s), primary ch %d\n", |
| prBssDesc->aucSSID, prBssDesc->ucChannelNum); |
| |
| /* dirtiness index1 */ |
| wlanCalculateChannelDirtiness(prAdapter, prBssDesc, u4Dirtiness, TRUE); |
| |
| /* dirtiness index2 */ |
| wlanCalculateChannelDirtiness(prAdapter, prBssDesc, |
| u4Dirtiness >> 1, FALSE); |
| } |
| |
| return rResult; |
| } |
| |
| UINT_8 |
| wlanGetChannelIndex(IN UINT_8 channel) |
| { |
| UINT_8 ucIdx = 1; |
| |
| if (channel <= 14) |
| ucIdx = channel - 1; |
| else if (channel >= 36 && channel <= 64) |
| ucIdx = 14 + (channel - 36) / 4; |
| else if (channel >= 100 && channel <= 140) |
| ucIdx = 14 + 8 + (channel - 100) / 4; |
| else if (channel >= 149 && channel <= 173) |
| ucIdx = 14 + 8 + 11 + (channel - 149) / 4; |
| else if (channel >= 184 && channel <= 216) |
| ucIdx = 14 + 8 + 11 + 7 + (channel - 184) / 4; |
| else |
| DBGLOG(SCN, ERROR, "Invalid ch %u\n", channel); |
| |
| return ucIdx; |
| } |
| |
| /*---------------------------------------------------------------------*/ |
| /*! |
| * \brief Get ch index by the given ch num; the reverse function of |
| * wlanGetChannelIndex |
| * |
| * \param[in] ucIdx Channel index |
| * \param[out] ucChannel Channel number |
| */ |
| /*---------------------------------------------------------------------*/ |
| |
| UINT_8 |
| wlanGetChannelNumFromIndex(IN UINT_8 ucIdx) |
| { |
| UINT_8 ucChannel = 0; |
| |
| if (ucIdx >= 40) |
| ucChannel = ((ucIdx - 40) << 2) + 184; |
| else if (ucIdx >= 33) |
| ucChannel = ((ucIdx - 33) << 2) + 149; |
| else if (ucIdx >= 22) |
| ucChannel = ((ucIdx - 22) << 2) + 100; |
| else if (ucIdx >= 14) |
| ucChannel = ((ucIdx - 14) << 2) + 36; |
| else |
| ucChannel = ucIdx + 1; |
| |
| return ucChannel; |
| } |
| |
| VOID |
| wlanSortChannel(IN P_ADAPTER_T prAdapter) |
| { |
| P_PARAM_GET_CHN_INFO prChnLoadInfo = &(prAdapter->rWifiVar.rChnLoadInfo); |
| INT_8 ucIdx = 0, ucRoot = 0, ucChild = 0; |
| PARAM_CHN_RANK_INFO rChnRankInfo; |
| |
| /* prepare unsorted ch rank list */ |
| for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) { |
| prChnLoadInfo->rChnRankList[ucIdx].ucChannel = |
| prChnLoadInfo->rEachChnLoad[ucIdx].ucChannel; |
| prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness = |
| prChnLoadInfo->rEachChnLoad[ucIdx].u4Dirtiness; |
| } |
| |
| /* heapify ch rank list */ |
| for (ucIdx = MAX_CHN_NUM / 2 - 1; ucIdx >= 0; --ucIdx) { |
| for (ucRoot = ucIdx; ucRoot * 2 + 1 < MAX_CHN_NUM; |
| ucRoot = ucChild) { |
| |
| ucChild = ucRoot * 2 + 1; |
| if (ucChild < MAX_CHN_NUM - 1 && |
| prChnLoadInfo->rChnRankList[ucChild + 1].u4Dirtiness > |
| prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) |
| ucChild += 1; |
| |
| if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= |
| prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) |
| break; |
| |
| rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; |
| prChnLoadInfo->rChnRankList[ucChild] = prChnLoadInfo->rChnRankList[ucRoot]; |
| prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; |
| } |
| } |
| |
| /* sort ch rank list */ |
| for (ucIdx = MAX_CHN_NUM - 1; ucIdx > 0; ucIdx--) { |
| rChnRankInfo = prChnLoadInfo->rChnRankList[0]; |
| prChnLoadInfo->rChnRankList[0] = prChnLoadInfo->rChnRankList[ucIdx]; |
| prChnLoadInfo->rChnRankList[ucIdx] = rChnRankInfo; |
| |
| for (ucRoot = 0; ucRoot * 2 + 1 < ucIdx; ucRoot = ucChild) { |
| ucChild = ucRoot * 2 + 1; |
| if (ucChild < ucIdx - 1 && |
| prChnLoadInfo->rChnRankList[ucChild + 1].u4Dirtiness > |
| prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness) |
| ucChild += 1; |
| |
| if (prChnLoadInfo->rChnRankList[ucChild].u4Dirtiness <= |
| prChnLoadInfo->rChnRankList[ucRoot].u4Dirtiness) |
| break; |
| |
| rChnRankInfo = prChnLoadInfo->rChnRankList[ucChild]; |
| prChnLoadInfo->rChnRankList[ucChild] = prChnLoadInfo->rChnRankList[ucRoot]; |
| prChnLoadInfo->rChnRankList[ucRoot] = rChnRankInfo; |
| } |
| } |
| |
| for (ucIdx = 0; ucIdx < MAX_CHN_NUM; ++ucIdx) |
| DBGLOG(SCN, INFO, "[ACS]channel=%d, dirtiness=%d\n", |
| prChnLoadInfo->rChnRankList[ucIdx].ucChannel, |
| prChnLoadInfo->rChnRankList[ucIdx].u4Dirtiness); |
| |
| } |
| #endif |
| |
| UINT_8 wlanGetAntPathType( |
| IN P_ADAPTER_T prAdapter, |
| IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor |
| ) |
| { |
| UINT_8 ucFianlWfPathType = eWfPathFavor; |
| #if CFG_SUPPORT_ANT_SELECT |
| UINT_8 ucNss = prAdapter->rWifiVar.ucNSS; |
| UINT_8 ucSpeIdxCtrl = prAdapter->rWifiVar.ucSpeIdxCtrl; |
| |
| if (ucSpeIdxCtrl == 0) |
| ucFianlWfPathType = ENUM_WF_0_ONE_STREAM_PATH_FAVOR; |
| else if (ucSpeIdxCtrl == 1) |
| ucFianlWfPathType = ENUM_WF_1_ONE_STREAM_PATH_FAVOR; |
| else if (ucSpeIdxCtrl == 2) { |
| if (ucNss > 1) |
| ucFianlWfPathType = ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR; |
| else |
| ucFianlWfPathType = ENUM_WF_NON_FAVOR; |
| } else |
| ucFianlWfPathType = ENUM_WF_NON_FAVOR; |
| #endif |
| return ucFianlWfPathType; |
| } |
| |
| #if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) |
| UINT_8 |
| wlanAntPathFavorSelect( |
| enum ENUM_WF_PATH_FAVOR_T eWfPathFavor |
| ) |
| { |
| UINT_8 ucRetValSpeIdx = 0; |
| |
| if ((eWfPathFavor == ENUM_WF_NON_FAVOR) || |
| (eWfPathFavor == ENUM_WF_0_ONE_STREAM_PATH_FAVOR) || |
| (eWfPathFavor == ENUM_WF_0_1_TWO_STREAM_PATH_FAVOR)) |
| ucRetValSpeIdx = ANTENNA_WF0; |
| else if (eWfPathFavor == ENUM_WF_0_1_DUP_STREAM_PATH_FAVOR) |
| ucRetValSpeIdx = 0x18; |
| else if (eWfPathFavor == ENUM_WF_1_ONE_STREAM_PATH_FAVOR) |
| ucRetValSpeIdx = ANTENNA_WF1; |
| else |
| ucRetValSpeIdx = ANTENNA_WF0; |
| |
| return ucRetValSpeIdx; |
| } |
| #endif |
| |
| UINT_8 |
| wlanGetSpeIdx(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex, IN enum ENUM_WF_PATH_FAVOR_T eWfPathFavor) |
| { |
| UINT_8 ucRetValSpeIdx = 0; |
| #if ((CFG_SISO_SW_DEVELOP == 1) || (CFG_SUPPORT_ANT_SELECT == 1)) |
| P_BSS_INFO_T prBssInfo; |
| ENUM_BAND_T eBand = BAND_NULL; |
| |
| if (ucBssIndex > MAX_BSS_INDEX) { |
| DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIndex); |
| ASSERT(0); |
| } |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| /* |
| * if DBDC enable return 0, else depend 2.4G/5G & support WF path |
| * retrun accurate value |
| */ |
| if (!prAdapter->rWifiVar.fgDbDcModeEn) { |
| if (prBssInfo->fgIsGranted) |
| eBand = prBssInfo->eBandGranted; |
| else |
| eBand = prBssInfo->eBand; |
| |
| if (eBand == BAND_2G4) { |
| if (IS_WIFI_2G4_SISO(prAdapter)) { |
| if (IS_WIFI_2G4_WF0_SUPPORT(prAdapter)) |
| ucRetValSpeIdx = ANTENNA_WF0; |
| else |
| ucRetValSpeIdx = ANTENNA_WF1; |
| } else |
| ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); |
| } else if (eBand == BAND_5G) { |
| if (IS_WIFI_5G_SISO(prAdapter)) { |
| if (IS_WIFI_5G_WF0_SUPPORT(prAdapter)) |
| ucRetValSpeIdx = ANTENNA_WF0; |
| else |
| ucRetValSpeIdx = ANTENNA_WF1; |
| } else |
| ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); |
| } else |
| ucRetValSpeIdx = wlanAntPathFavorSelect(eWfPathFavor); |
| } |
| DBGLOG(INIT, INFO, "SpeIdx:%d,D:%d,G=%d,B=%d,Bss=%d\n", |
| ucRetValSpeIdx, prAdapter->rWifiVar.fgDbDcModeEn, |
| prBssInfo->fgIsGranted, eBand, ucBssIndex); |
| #endif |
| return ucRetValSpeIdx; |
| } |
| |
| UINT_8 |
| wlanGetSupportNss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIndex) |
| { |
| UINT_8 ucRetValNss = prAdapter->rWifiVar.ucNSS; |
| #if CFG_SISO_SW_DEVELOP |
| P_BSS_INFO_T prBssInfo; |
| ENUM_BAND_T eBand = BAND_NULL; |
| |
| if (ucBssIndex > MAX_BSS_INDEX) { |
| DBGLOG(SW4, INFO, "Invalid BssInfo index[%u], skip dump!\n", ucBssIndex); |
| ASSERT(0); |
| } |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| /* |
| * depend 2.4G/5G support SISO/MIMO |
| * retrun accurate value |
| */ |
| if (prBssInfo->fgIsGranted) |
| eBand = prBssInfo->eBandGranted; |
| else |
| eBand = prBssInfo->eBand; |
| |
| if ((eBand == BAND_2G4) && IS_WIFI_2G4_SISO(prAdapter)) |
| ucRetValNss = 1; |
| else if ((eBand == BAND_5G) && IS_WIFI_5G_SISO(prAdapter)) |
| ucRetValNss = 1; |
| DBGLOG(INIT, INFO, "Nss=%d,G=%d,B=%d,Bss=%d\n", |
| ucRetValNss, prBssInfo->fgIsGranted, eBand, ucBssIndex); |
| #endif |
| return ucRetValNss; |
| } |
| |
| INT_32 wlanGetFileContent(P_ADAPTER_T prAdapter, |
| const PUINT_8 pcFileName, PUINT_8 pucBuf, |
| UINT_32 u4MaxFileLen, PUINT_32 pu4ReadFileLen, BOOL bReqFw) |
| { |
| if (bReqFw) |
| return kalRequestFirmware(pcFileName, pucBuf, |
| u4MaxFileLen, pu4ReadFileLen, |
| prAdapter->prGlueInfo->prDev); |
| |
| return kalReadToFile(pcFileName, pucBuf, |
| u4MaxFileLen, pu4ReadFileLen); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to update some info before connected, |
| * some decision need some info before bss info update |
| * |
| * @param prAdapter Pointer of Adapter Data Structure |
| * |
| * @return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| #if CFG_SUPPORT_ANT_SELECT |
| WLAN_STATUS wlanUpdateExtInfo(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 u4BufLen = 0; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| PARAM_CUSTOM_SW_CTRL_STRUCT_T rSwCtrlInfo; |
| |
| rSwCtrlInfo.u4Id = 0xa0640001; |
| rSwCtrlInfo.u4Data = prAdapter->rWifiVar.ucNSS; |
| |
| return kalIoctl(prGlueInfo, |
| wlanoidSetSwCtrlWrite, |
| &rSwCtrlInfo, sizeof(rSwCtrlInfo), |
| FALSE, FALSE, TRUE, &u4BufLen); |
| } |
| #endif |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is a wrapper to send eapol offload (rekey) command |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * |
| * @return VOID |
| */ |
| /*----------------------------------------------------------------------------*/ |
| int wlanSuspendRekeyOffload(P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRekeyDisable) |
| { |
| UINT_32 u4BufLen; |
| P_PARAM_GTK_REKEY_DATA prGtkData; |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| INT_32 i4Rslt = -EINVAL; |
| |
| ASSERT(prGlueInfo); |
| |
| prGtkData = |
| (P_PARAM_GTK_REKEY_DATA) kalMemAlloc(sizeof(PARAM_GTK_REKEY_DATA), VIR_MEM_TYPE); |
| |
| if (!prGtkData) |
| return WLAN_STATUS_SUCCESS; |
| |
| /* if enable => enable FW rekey offload. if disable, let rekey back to supplicant */ |
| prGtkData->ucRekeyDisable = ucRekeyDisable; |
| |
| if (!ucRekeyDisable) { |
| DBGLOG(RSN, INFO, "kek\n"); |
| DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); |
| DBGLOG(RSN, INFO, "kck\n"); |
| DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); |
| DBGLOG(RSN, INFO, "replay count\n"); |
| DBGLOG_MEM8(RSN, ERROR, (PUINT_8)prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); |
| |
| kalMemCopy(prGtkData->aucKek, prGlueInfo->rWpaInfo.aucKek, NL80211_KEK_LEN); |
| kalMemCopy(prGtkData->aucKck, prGlueInfo->rWpaInfo.aucKck, NL80211_KCK_LEN); |
| kalMemCopy(prGtkData->aucReplayCtr, prGlueInfo->rWpaInfo.aucReplayCtr, NL80211_REPLAY_CTR_LEN); |
| |
| prGtkData->ucBssIndex = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; |
| |
| prGtkData->u4Proto = NL80211_WPA_VERSION_2; |
| if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) |
| prGtkData->u4Proto = NL80211_WPA_VERSION_1; |
| |
| if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_TKIP) |
| prGtkData->u4PairwiseCipher = BIT(3); |
| else if (prGlueInfo->rWpaInfo.u4CipherPairwise == IW_AUTH_CIPHER_CCMP) |
| prGtkData->u4PairwiseCipher = BIT(4); |
| else { |
| kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_TKIP) |
| prGtkData->u4GroupCipher = BIT(3); |
| else if (prGlueInfo->rWpaInfo.u4CipherGroup == IW_AUTH_CIPHER_CCMP) |
| prGtkData->u4GroupCipher = BIT(4); |
| else { |
| kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| prGtkData->u4KeyMgmt = prGlueInfo->rWpaInfo.u4KeyMgmt; |
| prGtkData->u4MgmtGroupCipher = 0; |
| |
| } else { |
| /* inform FW disable EAPOL offload */ |
| DBGLOG(RSN, INFO, "Disable EAPOL offload\n"); |
| } |
| |
| rStatus = kalIoctl(prGlueInfo, |
| wlanoidSetGtkRekeyData, |
| prGtkData, sizeof(PARAM_GTK_REKEY_DATA), FALSE, FALSE, TRUE, &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) |
| DBGLOG(INIT, INFO, "Suspend GTK rekey data error:%lx\n", rStatus); |
| else |
| i4Rslt = 0; |
| |
| kalMemFree(prGtkData, VIR_MEM_TYPE, sizeof(PARAM_GTK_REKEY_DATA)); |
| |
| return i4Rslt; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is a wrapper to send power-saving mode command |
| * when AIS enter wow, and send WOW command |
| * Also let GC/GO/AP enter deactivate state to enter TOP sleep |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * |
| * @return VOID |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanSuspendPmHandle(P_GLUE_INFO_T prGlueInfo) |
| { |
| UINT_8 idx; |
| PARAM_POWER_MODE ePwrMode; |
| P_BSS_INFO_T prBssInfo; |
| |
| /* if wifi.cfg EAPOL offload is 0, we set rekey offload when enter wow */ |
| if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { |
| wlanSuspendRekeyOffload(prGlueInfo, FALSE); |
| DBGLOG(HAL, STATE, "Suspend rekey offload\n"); |
| } |
| |
| /* 1) wifi cfg "Wow" is true, 2) wow is enable 3) WIfI connected => execute WOW flow */ |
| /* Send power-saving cmd when enter wow state, even w/o cfg80211 support */ |
| if (prGlueInfo->prAdapter->rWifiVar.ucWow && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { |
| if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { |
| /* AIS bss enter wow power mode, default fast power-saving */ |
| ePwrMode = prGlueInfo->prAdapter->rWifiVar.ucWowPwsMode; |
| idx = prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex; |
| nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, idx, ePwrMode, FALSE, TRUE); |
| DBGLOG(HAL, STATE, "Suspend wow power save idx:%d, mode:%d\n", idx, ePwrMode); |
| |
| DBGLOG(HAL, STATE, "enter WOW flow\n"); |
| kalWowProcess(prGlueInfo, TRUE); |
| } |
| } |
| |
| for (idx = 0; idx < MAX_BSS_INDEX; idx++) { |
| prBssInfo = prGlueInfo->prAdapter->aprBssInfo[idx]; |
| if (!prBssInfo) |
| continue; |
| |
| /* Stop GO/GC/AP bss to let TOP sleep */ |
| if ((idx != prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex) && |
| IS_BSS_ACTIVE(prBssInfo)) { |
| nicPmIndicateBssAbort(prGlueInfo->prAdapter, idx); |
| nicDeactivateNetwork(prGlueInfo->prAdapter, idx); |
| nicUpdateBss(prGlueInfo->prAdapter, idx); |
| } |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is to restore power-saving mode command when AIS leave wow |
| * But ignore GC/GO/AP role |
| * |
| * @param prGlueInfo Pointer of prGlueInfo Data Structure |
| * |
| * @return VOID |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID wlanResumePmHandle(P_GLUE_INFO_T prGlueInfo) |
| { |
| PARAM_POWER_MODE ePwrMode = Param_PowerModeCAM; |
| |
| /* if wifi.cfg EAPOL offload is disble, we disable FW offload when leave wow */ |
| if (!prGlueInfo->prAdapter->rWifiVar.ucEapolOffload) { |
| wlanSuspendRekeyOffload(prGlueInfo, TRUE); |
| DBGLOG(HAL, STATE, "Resume rekey offload disable\n"); |
| } |
| |
| if (prGlueInfo->prAdapter->rWifiVar.ucWow && prGlueInfo->prAdapter->rWowCtrl.fgWowEnable) { |
| if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { |
| DBGLOG(HAL, STATE, "leave WOW flow. AIS BssIndex:%d\n", |
| prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex); |
| kalWowProcess(prGlueInfo, FALSE); |
| |
| /* resume AIS power-saving cmd when leave wow state, ignore ePwrMode input */ |
| nicConfigPowerSaveWowProfile(prGlueInfo->prAdapter, |
| prGlueInfo->prAdapter->prAisBssInfo->ucBssIndex, ePwrMode, FALSE, FALSE); |
| } |
| } |
| } |
| |