| /****************************************************************************** |
| * |
| * 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 fw_dl.c |
| */ |
| |
| /******************************************************************************* |
| * 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" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************* |
| */ |
| |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************* |
| */ |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************* |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************* |
| */ |
| |
| #if CFG_ENABLE_FW_DOWNLOAD |
| uint32_t wlanGetDataMode(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx, IN uint8_t ucFeatureSet) |
| { |
| uint32_t u4DataMode = 0; |
| |
| if (ucFeatureSet & DOWNLOAD_CONFIG_ENCRYPTION_MODE) { |
| u4DataMode |= DOWNLOAD_CONFIG_RESET_OPTION; |
| u4DataMode |= (ucFeatureSet & |
| 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 |
| return u4DataMode; |
| } |
| |
| void wlanGetHarvardFwInfo(IN struct ADAPTER *prAdapter, |
| IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, |
| OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload) |
| { |
| struct TAILER_FORMAT_T *prTailer; |
| |
| if (eDlIdx == IMG_DL_IDX_N9_FW) |
| prTailer = &prAdapter->rVerInfo.rN9tailer[u4SecIdx]; |
| else |
| prTailer = &prAdapter->rVerInfo.rCR4tailer[u4SecIdx]; |
| |
| *pu4Addr = prTailer->addr; |
| *pu4Len = (prTailer->len + LEN_4_BYTE_CRC); |
| *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, |
| prTailer->feature_set); |
| *pfgIsEMIDownload = FALSE; |
| } |
| |
| void wlanGetConnacFwInfo(IN struct ADAPTER *prAdapter, |
| IN uint8_t u4SecIdx, IN enum ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, |
| OUT uint32_t *pu4DataMode, OUT u_int8_t *pfgIsEMIDownload) |
| { |
| struct TAILER_REGION_FORMAT_T *prTailer = |
| &prAdapter->rVerInfo.rRegionTailers[u4SecIdx]; |
| |
| *pu4Addr = prTailer->u4Addr; |
| *pu4Len = prTailer->u4Len; |
| *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, |
| prTailer->ucFeatureSet); |
| *pfgIsEMIDownload = prTailer->ucFeatureSet & |
| DOWNLOAD_CONFIG_EMI; |
| } |
| |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| void wlanImageSectionGetCompressFwInfo(IN struct ADAPTER |
| *prAdapter, IN void *pvFwImageMapFile, |
| IN uint32_t u4FwImageFileLength, IN uint8_t ucTotSecNum, |
| IN uint8_t ucCurSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT uint32_t *pu4Addr, OUT uint32_t *pu4Len, |
| OUT uint32_t *pu4DataMode, OUT uint32_t *pu4BlockSize, |
| OUT uint32_t *pu4CRC, OUT uint32_t *pu4UncompressedLength) |
| { |
| struct FW_IMAGE_TAILER_T_2 *prFwHead; |
| struct TAILER_FORMAT_T_2 *prTailer; |
| uint8_t aucBuf[32]; |
| |
| prFwHead = (struct FW_IMAGE_TAILER_T_2 *) |
| (pvFwImageMapFile + u4FwImageFileLength - sizeof( |
| struct FW_IMAGE_TAILER_T_2)); |
| if (ucTotSecNum == 1) |
| prTailer = &prFwHead->dlm_info; |
| else |
| prTailer = &prFwHead->ilm_info; |
| |
| prTailer = &prTailer[ucCurSecNum]; |
| |
| *pu4Addr = prTailer->addr; |
| *pu4Len = (prTailer->len); |
| *pu4BlockSize = (prTailer->block_size); |
| *pu4CRC = (prTailer->crc); |
| *pu4UncompressedLength = (prTailer->real_size); |
| *pu4DataMode = wlanGetDataMode(prAdapter, eDlIdx, |
| prTailer->feature_set); |
| |
| /* 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); |
| kalMemZero(aucBuf, 32); |
| kalStrnCpy(aucBuf, prTailer->ram_version, |
| sizeof(prTailer->ram_version)); |
| DBGLOG(INIT, INFO, "date[%s] version[%s]\n", |
| prTailer->ram_built_date, aucBuf); |
| } |
| /* Backup to FW version info */ |
| if (eDlIdx == IMG_DL_IDX_N9_FW) { |
| kalMemCopy(&prAdapter->rVerInfo.rN9Compressedtailer, |
| prTailer, sizeof(struct TAILER_FORMAT_T_2)); |
| prAdapter->rVerInfo.fgIsN9CompressedFW = TRUE; |
| } else { |
| kalMemCopy(&prAdapter->rVerInfo.rCR4Compressedtailer, |
| prTailer, sizeof(struct TAILER_FORMAT_T_2)); |
| prAdapter->rVerInfo.fgIsCR4CompressedFW = TRUE; |
| } |
| } |
| #endif |
| |
| void wlanImageSectionGetPatchInfo(IN struct ADAPTER |
| *prAdapter, |
| IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, |
| OUT uint32_t *pu4StartOffset, OUT uint32_t *pu4Addr, |
| OUT uint32_t *pu4Len, |
| OUT uint32_t *pu4DataMode) |
| { |
| struct PATCH_FORMAT_T *prPatchFormat; |
| uint8_t aucBuffer[32]; |
| struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; |
| |
| prPatchFormat = (struct PATCH_FORMAT_T *) pvFwImageMapFile; |
| |
| *pu4StartOffset = offsetof(struct PATCH_FORMAT_T, |
| ucPatchImage); |
| *pu4Addr = prChipInfo->patch_addr; |
| *pu4Len = u4FwImageFileLength - offsetof(struct |
| PATCH_FORMAT_T, ucPatchImage); |
| *pu4DataMode = wlanGetDataMode(prAdapter, IMG_DL_IDX_PATCH, |
| 0); |
| |
| /* Dump image information */ |
| kalMemZero(aucBuffer, 32); |
| kalStrnCpy(aucBuffer, prPatchFormat->aucPlatform, 4); |
| 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); |
| DBGLOG(INIT, INFO, "date[%s]\n", aucBuffer); |
| |
| /* Backup to FW version info */ |
| kalMemCopy(&prAdapter->rVerInfo.rPatchHeader, prPatchFormat, |
| sizeof(struct PATCH_FORMAT_T)); |
| } |
| |
| uint32_t wlanDownloadSection(IN struct ADAPTER *prAdapter, |
| IN uint32_t u4Addr, IN uint32_t u4Len, |
| IN uint32_t u4DataMode, IN uint8_t *pucStartPtr, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| uint32_t u4ImgSecSize, u4Offset; |
| uint8_t *pucSecBuf; |
| |
| if (wlanImageSectionConfig(prAdapter, u4Addr, u4Len, |
| u4DataMode, eDlIdx) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, |
| "Firmware download configuration failed!\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| for (u4Offset = 0; u4Offset < u4Len; |
| u4Offset += CMD_PKT_SIZE_FOR_IMAGE) { |
| if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4Len) |
| u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; |
| else |
| u4ImgSecSize = u4Len - u4Offset; |
| |
| pucSecBuf = (uint8_t *) pucStartPtr + u4Offset; |
| if (wlanImageSectionDownload(prAdapter, u4ImgSecSize, |
| pucSecBuf) != |
| WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, ERROR, |
| "Firmware scatter download failed!\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint32_t wlanDownloadEMISection(IN struct ADAPTER |
| *prAdapter, IN uint32_t u4DestAddr, |
| IN uint32_t u4Len, IN uint8_t *pucStartPtr) |
| { |
| #if CFG_MTK_ANDROID_EMI |
| uint8_t __iomem *pucEmiBaseAddr = NULL; |
| uint32_t u4Offset = u4DestAddr & WIFI_EMI_ADDR_MASK; |
| |
| if (!gConEmiPhyBase) { |
| DBGLOG(INIT, ERROR, |
| "Consys emi memory address gConEmiPhyBase invalid\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| request_mem_region(gConEmiPhyBase, gConEmiSize, "WIFI-EMI"); |
| kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, |
| WIFI_EMI_MEM_SIZE, false); |
| pucEmiBaseAddr = ioremap_nocache(gConEmiPhyBase, gConEmiSize); |
| DBGLOG(INIT, INFO, |
| "EmiPhyBase:0x%llx offset:0x%x, ioremap region 0x%lX @ 0x%lX\n", |
| (uint64_t)gConEmiPhyBase, u4Offset, gConEmiSize, pucEmiBaseAddr); |
| if (!pucEmiBaseAddr) { |
| DBGLOG(INIT, ERROR, "ioremap failed\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemCopy((pucEmiBaseAddr + u4Offset), pucStartPtr, u4Len); |
| |
| kalSetEmiMpuProtection(gConEmiPhyBase, WIFI_EMI_MEM_OFFSET, |
| WIFI_EMI_MEM_SIZE, true); |
| iounmap(pucEmiBaseAddr); |
| release_mem_region(gConEmiPhyBase, gConEmiSize); |
| #endif /* CFG_MTK_ANDROID_EMI */ |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| u_int8_t wlanImageSectionCheckFwCompressInfo( |
| IN struct ADAPTER *prAdapter, |
| IN void *pvFwImageMapFile, IN uint32_t u4FwImageFileLength, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| uint8_t ucCompression; |
| struct FW_IMAGE_TAILER_CHECK *prCheckInfo; |
| |
| if (eDlIdx == IMG_DL_IDX_PATCH) |
| return FALSE; |
| |
| prCheckInfo = (struct FW_IMAGE_TAILER_CHECK *) |
| (pvFwImageMapFile + u4FwImageFileLength - sizeof( |
| struct FW_IMAGE_TAILER_CHECK)); |
| DBGLOG(INIT, INFO, "feature_set %d\n", |
| prCheckInfo->feature_set); |
| ucCompression = (uint8_t)((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; |
| } |
| |
| uint32_t wlanCompressedImageSectionDownloadStage( |
| IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, |
| IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx, |
| OUT uint8_t *pucIsCompressed, |
| OUT struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) |
| { |
| uint32_t i; |
| int32_t i4TotalLen; |
| uint32_t u4FileOffset = 0; |
| uint32_t u4StartOffset = 0; |
| uint32_t u4DataMode = 0; |
| uint32_t u4Addr, u4Len, u4BlockSize, u4CRC; |
| uint32_t u4UnCompressedLength; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| uint8_t *pucStartPtr; |
| uint32_t u4offset = 0, u4ChunkSize; |
| /* 3a. parse file header for decision of |
| * divided firmware download or not |
| */ |
| if (wlanImageSectionCheckFwCompressInfo(prAdapter, |
| pvFwImageMapFile, |
| u4FwImageFileLength, |
| eDlIdx) == TRUE) { |
| for (i = 0; i < ucSectionNumber; ++i) { |
| wlanImageSectionGetCompressFwInfo(prAdapter, |
| pvFwImageMapFile, |
| u4FwImageFileLength, ucSectionNumber, i, eDlIdx, |
| &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 = |
| (uint8_t *) 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); |
| |
| u4Status = wlanDownloadSection(prAdapter, |
| u4Addr + u4offset, |
| u4ChunkSize, |
| u4DataMode, |
| pvFwImageMapFile + u4FileOffset, |
| eDlIdx); |
| /* 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 { |
| u4Status = wlanImageSectionDownloadStage(prAdapter, |
| pvFwImageMapFile, u4FwImageFileLength, |
| ucSectionNumber, eDlIdx); |
| *pucIsCompressed = FALSE; |
| } |
| return u4Status; |
| } |
| #endif |
| |
| uint32_t wlanImageSectionDownloadStage( |
| IN struct ADAPTER *prAdapter, IN void *pvFwImageMapFile, |
| IN uint32_t u4FwImageFileLength, IN uint8_t ucSectionNumber, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| uint32_t u4SecIdx, u4Offset = 0; |
| uint32_t u4Addr, u4Len, u4DataMode = 0; |
| u_int8_t fgIsEMIDownload = FALSE; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo = prAdapter->chip_info; |
| |
| /* 3a. parse file header for decision of |
| * divided firmware download or not |
| */ |
| if (eDlIdx == IMG_DL_IDX_PATCH) { |
| wlanImageSectionGetPatchInfo(prAdapter, pvFwImageMapFile, |
| u4FwImageFileLength, |
| &u4Offset, &u4Addr, |
| &u4Len, &u4DataMode); |
| |
| DBGLOG(INIT, INFO, |
| "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", |
| u4Offset, u4Addr, u4Len, u4DataMode); |
| |
| u4Status = wlanDownloadSection(prAdapter, u4Addr, u4Len, |
| u4DataMode, |
| pvFwImageMapFile + u4Offset, |
| eDlIdx); |
| } else { |
| for (u4SecIdx = 0; u4SecIdx < ucSectionNumber; |
| u4SecIdx++, u4Offset += u4Len) { |
| prChipInfo->fw_dl_ops->getFwInfo(prAdapter, u4SecIdx, |
| eDlIdx, &u4Addr, |
| &u4Len, &u4DataMode, &fgIsEMIDownload); |
| |
| DBGLOG(INIT, INFO, |
| "DL Offset[%u] addr[0x%08x] len[%u] datamode[0x%08x]\n", |
| u4Offset, u4Addr, u4Len, u4DataMode); |
| |
| if (fgIsEMIDownload) |
| u4Status = wlanDownloadEMISection(prAdapter, |
| u4Addr, u4Len, |
| pvFwImageMapFile + u4Offset); |
| else |
| u4Status = wlanDownloadSection(prAdapter, |
| u4Addr, u4Len, |
| u4DataMode, |
| pvFwImageMapFile + u4Offset, eDlIdx); |
| |
| /* escape from loop if any pending error occurs */ |
| if (u4Status == WLAN_STATUS_FAILURE) |
| break; |
| } |
| } |
| return u4Status; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanPatchRecvSemaResp(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucCmdSeqNum, OUT uint8_t *pucPatchStatus) |
| { |
| struct mt66xx_chip_info *prChipInfo; |
| uint8_t *aucBuffer; |
| uint32_t u4EventSize; |
| struct INIT_WIFI_EVENT *prInitEvent; |
| struct INIT_EVENT_CMD_RESULT *prEventCmdResult; |
| uint32_t u4RxPktLength; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE |
| || fgIsBusAccessFailed == TRUE) |
| return WLAN_STATUS_FAILURE; |
| |
| u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + |
| sizeof(struct INIT_EVENT_CMD_RESULT); |
| aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); |
| |
| if (nicRxWaitResponse(prAdapter, 0, aucBuffer, u4EventSize, |
| &u4RxPktLength) != WLAN_STATUS_SUCCESS) { |
| |
| DBGLOG(INIT, WARN, "Wait patch semaphore response fail\n"); |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prInitEvent = (struct INIT_WIFI_EVENT *) |
| (aucBuffer + prChipInfo->rxd_size); |
| if (prInitEvent->ucEID != INIT_EVENT_ID_PATCH_SEMA_CTRL) { |
| DBGLOG(INIT, WARN, "Unexpected EVENT ID, get 0x%0x\n", |
| prInitEvent->ucEID); |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| if (prInitEvent->ucSeqNum != ucCmdSeqNum) { |
| DBGLOG(INIT, WARN, "Unexpected SeqNum %d, %d\n", |
| ucCmdSeqNum, prInitEvent->ucSeqNum); |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prEventCmdResult = (struct INIT_EVENT_CMD_RESULT *) |
| prInitEvent->aucBuffer; |
| |
| *pucPatchStatus = prEventCmdResult->ucStatus; |
| |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to check the patch semaphore control. |
| * |
| * @param prAdapter Pointer to the Adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanPatchSendSemaControl(IN struct ADAPTER |
| *prAdapter, OUT uint8_t *pucSeqNum) |
| { |
| struct mt66xx_chip_info *prChipInfo; |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct INIT_CMD_PATCH_SEMA_CONTROL *prPatchSemaControl; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| DEBUGFUNC("wlanImagePatchSemaphoreCheck"); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = |
| cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_PATCH_SEMA_CONTROL)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) |
| + sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL); |
| |
| /* 2. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( |
| 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 = (struct INIT_CMD_PATCH_SEMA_CONTROL *) |
| prInitHifTxHeader->rInitWifiCmd.aucBuffer; |
| kalMemZero(prPatchSemaControl, |
| sizeof(struct INIT_CMD_PATCH_SEMA_CONTROL)); |
| prPatchSemaControl->ucGetSemaphore = PATCH_GET_SEMA_CONTROL; |
| |
| /* 4. Send FW_Download command */ |
| if (nicTxInitCmd(prAdapter, prCmdInfo, |
| prChipInfo->u2TxInitCmdPort) != 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; |
| } |
| |
| u_int8_t wlanPatchIsDownloaded(IN struct ADAPTER *prAdapter) |
| { |
| uint8_t ucSeqNum, ucPatchStatus; |
| uint32_t rStatus; |
| uint32_t 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; |
| } |
| |
| uint32_t wlanPatchSendComplete(IN struct ADAPTER *prAdapter) |
| { |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| uint8_t ucTC, ucCmdSeqNum; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo; |
| struct INIT_CMD_PATCH_FINISH *prPatchFinish; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_PATCH_FINISH)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_PATCH_FINISH)); |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) |
| + sizeof(struct INIT_CMD_PATCH_FINISH); |
| |
| #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 = (struct INIT_HIF_TX_HEADER *) ( |
| 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; |
| |
| prPatchFinish = (struct INIT_CMD_PATCH_FINISH *) |
| prInitHifTxHeader->rInitWifiCmd.aucBuffer; |
| prPatchFinish->ucCheckCrc = 0; |
| |
| /* 5. Seend WIFI start command */ |
| while (1) { |
| /* 5.1 Acquire TX Resource */ |
| if (nicTxAcquireResource(prAdapter, ucTC, |
| nicTxGetPageCount(prAdapter, |
| 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, |
| prChipInfo->u2TxInitCmdPort) != |
| 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanImageSectionConfig( |
| IN struct ADAPTER *prAdapter, |
| IN uint32_t u4DestAddr, IN uint32_t u4ImgSecSize, |
| IN uint32_t u4DataMode, |
| IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| struct INIT_CMD_DOWNLOAD_CONFIG *prInitCmdDownloadConfig; |
| uint8_t ucTC, ucCmdSeqNum; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| DEBUGFUNC("wlanImageSectionConfig"); |
| |
| if (u4ImgSecSize == 0) |
| return WLAN_STATUS_SUCCESS; |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_DOWNLOAD_CONFIG)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) |
| + sizeof(struct 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 = (struct INIT_HIF_TX_HEADER *) ( |
| 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 = |
| (struct 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(prAdapter, |
| 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, |
| prChipInfo->u2TxInitCmdPort) != |
| 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 = wlanConfigWifiFuncStatus(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) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanImageSectionDownload(IN struct ADAPTER |
| *prAdapter, IN uint32_t u4ImgSecSize, |
| IN uint8_t *pucImgSecBuf) |
| { |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(pucImgSecBuf); |
| ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); |
| |
| DEBUGFUNC("wlanImageSectionDownload"); |
| |
| prChipInfo = prAdapter->chip_info; |
| |
| if (u4ImgSecSize == 0) |
| return WLAN_STATUS_SUCCESS; |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + |
| u4ImgSecSize); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) |
| + (uint16_t) u4ImgSecSize; |
| |
| /* 2. Setup common CMD Info Packet */ |
| prInitHifTxHeader = (struct INIT_HIF_TX_HEADER *) ( |
| 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, |
| prChipInfo->u2TxFwDlPort) != 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) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanImageQueryStatus(IN struct ADAPTER *prAdapter) |
| { |
| struct mt66xx_chip_info *prChipInfo; |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| uint8_t *aucBuffer; |
| uint32_t u4EventSize; |
| uint32_t u4RxPktLength; |
| struct INIT_WIFI_EVENT *prInitEvent; |
| struct INIT_EVENT_CMD_RESULT *prEventPendingError; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| uint8_t ucTC, ucCmdSeqNum; |
| struct HW_MAC_RX_DESC *prRxStatus; |
| uint8_t ucUnexpectCnt = 0; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| DEBUGFUNC("wlanImageQueryStatus"); |
| |
| /* 1. Allocate CMD Info Packet and it Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + |
| sizeof(struct INIT_EVENT_CMD_RESULT); |
| aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, |
| sizeof(struct INIT_HIF_TX_HEADER)); |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER); |
| |
| #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 = (struct INIT_HIF_TX_HEADER *) ( |
| 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(prAdapter, |
| 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, |
| prChipInfo->u2TxInitCmdPort) != |
| 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 */ |
| while (TRUE) { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE |
| || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else if (nicRxWaitResponse(prAdapter, 0, |
| aucBuffer, u4EventSize, |
| &u4RxPktLength) != |
| WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else { |
| /* header checking .. */ |
| prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; |
| if (prRxStatus->u2PktTYpe != |
| RXM_RXD_PKT_TYPE_SW_EVENT) { |
| DBGLOG(INIT, ERROR, |
| "%s: skip unexpected Rx pkt type[0x%04x]\n", |
| __func__, prRxStatus->u2PktTYpe); |
| |
| ucUnexpectCnt++; |
| |
| if (ucUnexpectCnt > 5) { |
| DBGLOG(INIT, WARN, |
| "%s: break since ucUnexpectCnt > %d\n", |
| __func__, ucUnexpectCnt); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| continue; |
| } |
| |
| prInitEvent = (struct INIT_WIFI_EVENT *) |
| (aucBuffer + prChipInfo->rxd_size); |
| |
| /* EID / SeqNum check */ |
| if (prInitEvent->ucEID != INIT_EVENT_ID_PENDING_ERROR) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| prEventPendingError = |
| (struct INIT_EVENT_CMD_RESULT *) |
| prInitEvent->aucBuffer; |
| /* 0 for download success */ |
| if (prEventPendingError->ucStatus != 0) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| u4Status = WLAN_STATUS_SUCCESS; |
| break; |
| } |
| } |
| |
| /* 7. Free CMD Info Packet. */ |
| cmdBufFreeCmdInfo(prAdapter, prCmdInfo); |
| |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| |
| 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanConfigWifiFuncStatus(IN struct ADAPTER |
| *prAdapter, IN uint8_t ucCmdSeqNum) |
| { |
| struct mt66xx_chip_info *prChipInfo; |
| uint8_t *aucBuffer; |
| uint32_t u4EventSize; |
| struct INIT_WIFI_EVENT *prInitEvent; |
| struct INIT_EVENT_CMD_RESULT *prEventCmdResult; |
| uint32_t u4RxPktLength; |
| uint32_t u4Status; |
| uint8_t ucPortIdx = IMG_DL_STATUS_PORT_IDX; |
| struct HW_MAC_RX_DESC *prRxStatus; |
| uint8_t ucUnexpectCnt = 0; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| u4EventSize = prChipInfo->rxd_size + prChipInfo->init_event_size + |
| sizeof(struct INIT_EVENT_CMD_RESULT); |
| aucBuffer = kalMemAlloc(u4EventSize, PHY_MEM_TYPE); |
| |
| while (TRUE) { |
| if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE |
| || fgIsBusAccessFailed == TRUE) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else if (nicRxWaitResponse(prAdapter, ucPortIdx, |
| aucBuffer, u4EventSize, |
| &u4RxPktLength) != |
| WLAN_STATUS_SUCCESS) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else { |
| /* header checking .. */ |
| prRxStatus = (struct HW_MAC_RX_DESC *) aucBuffer; |
| if (prRxStatus->u2PktTYpe != |
| RXM_RXD_PKT_TYPE_SW_EVENT) { |
| DBGLOG(INIT, ERROR, |
| "%s: skip unexpected Rx pkt type[0x%04x]\n", |
| __func__, prRxStatus->u2PktTYpe); |
| |
| ucUnexpectCnt++; |
| |
| if (ucUnexpectCnt > 5) { |
| DBGLOG(INIT, WARN, |
| "%s: break since ucUnexpectCnt > %d\n", |
| __func__, ucUnexpectCnt); |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| continue; |
| } |
| |
| prInitEvent = (struct INIT_WIFI_EVENT *) |
| (aucBuffer + prChipInfo->rxd_size); |
| |
| /* EID / SeqNum check */ |
| if (prInitEvent->ucEID != INIT_EVENT_ID_CMD_RESULT) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } else if (prInitEvent->ucSeqNum != ucCmdSeqNum) { |
| u4Status = WLAN_STATUS_FAILURE; |
| break; |
| } |
| prEventCmdResult = |
| (struct INIT_EVENT_CMD_RESULT *) |
| prInitEvent->aucBuffer; |
| |
| /* 0 for download success */ |
| if (prEventCmdResult->ucStatus != 0) { |
| 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; |
| break; |
| } |
| u4Status = WLAN_STATUS_SUCCESS; |
| break; |
| } |
| } |
| |
| kalMemFree(aucBuffer, PHY_MEM_TYPE, u4EventSize); |
| |
| return u4Status; |
| } |
| |
| uint32_t wlanConfigWifiFunc(IN struct ADAPTER *prAdapter, |
| IN u_int8_t fgEnable, IN uint32_t u4StartAddress, |
| IN uint8_t ucPDA) |
| { |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| struct INIT_CMD_WIFI_START *prInitCmdWifiStart; |
| uint8_t ucTC, ucCmdSeqNum; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| DEBUGFUNC("wlanConfigWifiFunc"); |
| |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + |
| sizeof( |
| struct INIT_CMD_WIFI_START)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_WIFI_START)); |
| prCmdInfo->u2InfoBufLen = sizeof(struct INIT_HIF_TX_HEADER) |
| + sizeof(struct 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 = (struct INIT_HIF_TX_HEADER *) ( |
| 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 = (struct 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(prAdapter, |
| 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, |
| prChipInfo->u2TxInitCmdPort) |
| != 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 |
| uint32_t |
| wlanCompressedFWConfigWifiFunc(IN struct ADAPTER *prAdapter, |
| IN u_int8_t fgEnable, |
| IN uint32_t u4StartAddress, IN uint8_t ucPDA, |
| IN struct INIT_CMD_WIFI_DECOMPRESSION_START *prFwImageInFo) |
| { |
| struct CMD_INFO *prCmdInfo; |
| struct INIT_HIF_TX_HEADER *prInitHifTxHeader; |
| struct INIT_CMD_WIFI_DECOMPRESSION_START |
| *prInitCmdWifiStart; |
| uint8_t ucTC, ucCmdSeqNum; |
| uint32_t u4Status = WLAN_STATUS_SUCCESS; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| prChipInfo = prAdapter->chip_info; |
| |
| DEBUGFUNC("wlanConfigWifiFunc"); |
| /* 1. Allocate CMD Info Packet and its Buffer. */ |
| prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, |
| sizeof(struct INIT_HIF_TX_HEADER) + |
| sizeof(struct INIT_CMD_WIFI_DECOMPRESSION_START)); |
| |
| if (!prCmdInfo) { |
| DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| kalMemZero(prCmdInfo->pucInfoBuffer, |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct INIT_CMD_WIFI_DECOMPRESSION_START)); |
| prCmdInfo->u2InfoBufLen = |
| sizeof(struct INIT_HIF_TX_HEADER) + sizeof( |
| struct 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 = (struct INIT_HIF_TX_HEADER *) ( |
| 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 = (struct |
| 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(prAdapter, |
| 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, |
| prChipInfo->u2TxInitCmdPort) |
| != 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 |
| */ |
| /*----------------------------------------------------------------------------*/ |
| uint32_t wlanCRC32(uint8_t *buf, uint32_t len) |
| { |
| uint32_t i, crc32 = 0xFFFFFFFF; |
| const uint32_t 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 |
| |
| uint32_t wlanGetHarvardTailerInfo(IN struct ADAPTER |
| *prAdapter, IN void *prFwBuffer, IN uint32_t u4FwSize, |
| IN uint32_t ucTotSecNum, IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| struct TAILER_FORMAT_T *prTailers; |
| uint8_t *pucStartPtr; |
| uint32_t u4SecIdx; |
| uint8_t aucBuf[32]; |
| |
| pucStartPtr = prFwBuffer + u4FwSize - sizeof( |
| struct TAILER_FORMAT_T) * ucTotSecNum; |
| if (eDlIdx == IMG_DL_IDX_N9_FW) { |
| kalMemCopy(&prAdapter->rVerInfo.rN9tailer, pucStartPtr, |
| sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); |
| prTailers = prAdapter->rVerInfo.rN9tailer; |
| } else { |
| kalMemCopy(&prAdapter->rVerInfo.rCR4tailer, pucStartPtr, |
| sizeof(struct TAILER_FORMAT_T) * ucTotSecNum); |
| prTailers = prAdapter->rVerInfo.rCR4tailer; |
| } |
| |
| for (u4SecIdx = 0; u4SecIdx < ucTotSecNum; u4SecIdx++) { |
| /* Dump image information */ |
| DBGLOG(INIT, INFO, |
| "%s Section[%d]: chip_info[%u:E%u] feature[0x%02X]\n", |
| (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", u4SecIdx, |
| prTailers[u4SecIdx].chip_info, |
| prTailers[u4SecIdx].eco_code + 1, |
| prTailers[u4SecIdx].feature_set); |
| |
| kalMemZero(aucBuf, 32); |
| kalMemCopy(aucBuf, prTailers[u4SecIdx].ram_version, |
| sizeof(prTailers[u4SecIdx].ram_version)); |
| DBGLOG(INIT, INFO, "date[%s] version[%s]\n", |
| prTailers[u4SecIdx].ram_built_date, aucBuf); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint32_t wlanGetConnacTailerInfo(IN struct ADAPTER |
| *prAdapter, IN void *prFwBuffer, |
| IN uint32_t u4FwSize, IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; |
| struct TAILER_COMMON_FORMAT_T *prComTailer; |
| struct TAILER_REGION_FORMAT_T *prRegTailer; |
| uint8_t *pucImgPtr; |
| uint8_t *pucTailertPtr; |
| uint8_t *pucStartPtr; |
| uint32_t u4SecIdx; |
| uint8_t aucBuf[32]; |
| |
| pucImgPtr = prFwBuffer; |
| pucStartPtr = prFwBuffer + u4FwSize - |
| sizeof(struct TAILER_COMMON_FORMAT_T); |
| prComTailer = (struct TAILER_COMMON_FORMAT_T *) pucStartPtr; |
| kalMemCopy(&prVerInfo->rCommonTailer, prComTailer, |
| sizeof(struct TAILER_COMMON_FORMAT_T)); |
| |
| /* Dump image information */ |
| DBGLOG(INIT, INFO, |
| "%s INFO: chip_info[%u:E%u] region_num[%d]\n", |
| (eDlIdx == IMG_DL_IDX_N9_FW) ? "N9" : "CR4", |
| prComTailer->ucChipInfo, |
| prComTailer->ucEcoCode + 1, prComTailer->ucRegionNum); |
| |
| kalMemZero(aucBuf, 32); |
| kalMemCopy(aucBuf, prComTailer->aucRamVersion, |
| sizeof(prComTailer->aucRamVersion)); |
| DBGLOG(INIT, INFO, "date[%s] version[%s]\n", |
| prComTailer->aucRamBuiltDate, aucBuf); |
| |
| if (prComTailer->ucRegionNum > MAX_FWDL_SECTION_NUM) { |
| DBGLOG(INIT, INFO, |
| "Regions number[%d] > max section number[%d]\n", |
| prComTailer->ucRegionNum, MAX_FWDL_SECTION_NUM); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| pucStartPtr -= (prComTailer->ucRegionNum * |
| sizeof(struct TAILER_REGION_FORMAT_T)); |
| pucTailertPtr = pucStartPtr; |
| for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; u4SecIdx++) { |
| prRegTailer = (struct TAILER_REGION_FORMAT_T *) pucStartPtr; |
| kalMemCopy(&prVerInfo->rRegionTailers[u4SecIdx], |
| prRegTailer, sizeof(struct TAILER_REGION_FORMAT_T)); |
| |
| /* Dump image information */ |
| DBGLOG(INIT, TRACE, |
| "Region[%d]: addr[0x%08X] feature[0x%02X] size[%u]\n", |
| u4SecIdx, prRegTailer->u4Addr, |
| prRegTailer->ucFeatureSet, prRegTailer->u4Len); |
| DBGLOG(INIT, TRACE, |
| "uncompress_crc[0x%08X] uncompress_size[0x%08X] block_size[0x%08X]\n", |
| prRegTailer->u4CRC, prRegTailer->u4RealSize, |
| prRegTailer->u4BlockSize); |
| pucImgPtr += prRegTailer->u4Len; |
| pucStartPtr += sizeof(struct TAILER_REGION_FORMAT_T); |
| } |
| |
| if (prComTailer->ucFormatFlag && pucImgPtr < pucTailertPtr) |
| fwDlGetReleaseInfoSection(prAdapter, pucImgPtr); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to extract the wifi ram code start address |
| * |
| * @param prVerInfo Pointer to the P_WIFI_VER_INFO_T structure. |
| * |
| * @return addr The ram code entry address. |
| * 0: use firmware defaut setting |
| * others: use it as the start address |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| uint32_t wlanDetectRamEntry(IN struct WIFI_VER_INFO |
| *prVerInfo) |
| { |
| uint32_t addr = 0; |
| uint32_t u4SecIdx; |
| struct TAILER_COMMON_FORMAT_T *prComTailer = |
| &prVerInfo->rCommonTailer; |
| struct TAILER_REGION_FORMAT_T *prRegTailer; |
| |
| for (u4SecIdx = 0; u4SecIdx < prComTailer->ucRegionNum; |
| u4SecIdx++) { |
| prRegTailer = &(prVerInfo->rRegionTailers[u4SecIdx]); |
| |
| if (prRegTailer->ucFeatureSet & |
| DOWNLOAD_CONFIG_VALID_RAM_ENTRY) { |
| addr = prRegTailer->u4Addr; |
| break; |
| } |
| } |
| |
| return addr; |
| } |
| |
| uint32_t wlanHarvardFormatDownload(IN struct ADAPTER |
| *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| uint32_t u4FwSize = 0; |
| void *prFwBuffer = NULL; |
| uint32_t rDlStatus = 0; |
| uint32_t rCfgStatus = 0; |
| uint32_t ucTotSecNum; |
| uint8_t ucPDA; |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| u_int8_t fgIsCompressed = FALSE; |
| struct INIT_CMD_WIFI_DECOMPRESSION_START rFwImageInFo; |
| #endif |
| |
| if (eDlIdx == IMG_DL_IDX_N9_FW) { |
| ucTotSecNum = N9_FWDL_SECTION_NUM; |
| ucPDA = PDA_N9; |
| } else { |
| ucTotSecNum = CR4_FWDL_SECTION_NUM; |
| ucPDA = PDA_CR4; |
| } |
| |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, |
| &u4FwSize, eDlIdx); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| wlanGetHarvardTailerInfo(prAdapter, prFwBuffer, u4FwSize, |
| ucTotSecNum, eDlIdx); |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| rDlStatus = wlanCompressedImageSectionDownloadStage( |
| prAdapter, prFwBuffer, u4FwSize, ucTotSecNum, |
| eDlIdx, &fgIsCompressed, &rFwImageInFo); |
| if (eDlIdx == IMG_DL_IDX_CR4_FW) |
| prAdapter->fgIsCr4FwDownloaded = TRUE; |
| if (fgIsCompressed == TRUE) |
| rCfgStatus = wlanCompressedFWConfigWifiFunc(prAdapter, |
| FALSE, 0, ucPDA, &rFwImageInFo); |
| else |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); |
| #else |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, |
| prFwBuffer, u4FwSize, ucTotSecNum, eDlIdx); |
| if (eDlIdx == IMG_DL_IDX_CR4_FW) |
| prAdapter->fgIsCr4FwDownloaded = TRUE; |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, FALSE, 0, ucPDA); |
| #endif |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, |
| prFwBuffer); |
| |
| if ((rDlStatus != WLAN_STATUS_SUCCESS) |
| || (rCfgStatus != WLAN_STATUS_SUCCESS)) |
| return WLAN_STATUS_FAILURE; |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint32_t wlanConnacFormatDownload(IN struct ADAPTER |
| *prAdapter, IN enum ENUM_IMG_DL_IDX_T eDlIdx) |
| { |
| void *prFwBuffer = NULL; |
| uint32_t u4FwSize = 0; |
| uint32_t ram_entry = 0; |
| uint32_t rDlStatus = 0; |
| uint32_t rCfgStatus = 0; |
| uint8_t ucRegionNum; |
| uint8_t ucPDA; |
| |
| kalFirmwareImageMapping(prAdapter->prGlueInfo, &prFwBuffer, |
| &u4FwSize, eDlIdx); |
| if (prFwBuffer == NULL) { |
| DBGLOG(INIT, WARN, "FW[%u] load error!\n", eDlIdx); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| if (wlanGetConnacTailerInfo(prAdapter, prFwBuffer, u4FwSize, |
| eDlIdx) != WLAN_STATUS_SUCCESS) { |
| DBGLOG(INIT, WARN, "Get tailer info error!\n"); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| ucRegionNum = prAdapter->rVerInfo.rCommonTailer.ucRegionNum; |
| ucPDA = (eDlIdx == IMG_DL_IDX_N9_FW) ? PDA_N9 : PDA_CR4; |
| |
| rDlStatus = wlanImageSectionDownloadStage(prAdapter, |
| prFwBuffer, u4FwSize, ucRegionNum, eDlIdx); |
| |
| ram_entry = wlanDetectRamEntry(&prAdapter->rVerInfo); |
| rCfgStatus = wlanConfigWifiFunc(prAdapter, |
| (ram_entry == 0) ? FALSE : TRUE, |
| ram_entry, ucPDA); |
| |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, |
| prFwBuffer); |
| |
| if ((rDlStatus != WLAN_STATUS_SUCCESS) |
| || (rCfgStatus != WLAN_STATUS_SUCCESS)) |
| return WLAN_STATUS_FAILURE; |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint32_t wlanDownloadFW(IN struct ADAPTER *prAdapter) |
| { |
| uint32_t rStatus = 0; |
| u_int8_t fgReady; |
| struct mt66xx_chip_info *prChipInfo; |
| struct FWDL_OPS_T *prFwDlOps; |
| |
| if (!prAdapter) |
| return WLAN_STATUS_FAILURE; |
| |
| prChipInfo = prAdapter->chip_info; |
| prFwDlOps = prChipInfo->fw_dl_ops; |
| |
| DBGLOG(INIT, INFO, |
| "wlanDownloadFW:: Check ready_bits(=0x%x)\n", |
| prChipInfo->sw_ready_bits); |
| HAL_WIFI_FUNC_READY_CHECK(prAdapter, |
| prChipInfo->sw_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 (prFwDlOps->downloadPatch) |
| prFwDlOps->downloadPatch(prAdapter); |
| |
| DBGLOG(INIT, INFO, "FW download Start\n"); |
| |
| if (prFwDlOps->downloadFirmware) { |
| rStatus = prFwDlOps->downloadFirmware(prAdapter, |
| IMG_DL_IDX_N9_FW); |
| if (prChipInfo->is_support_cr4 |
| && rStatus == WLAN_STATUS_SUCCESS) |
| rStatus = prFwDlOps->downloadFirmware(prAdapter, |
| IMG_DL_IDX_CR4_FW); |
| } else |
| DBGLOG(INIT, WARN, "Without downlaod firmware Ops\n"); |
| |
| DBGLOG(INIT, INFO, "FW download End\n"); |
| |
| HAL_ENABLE_FWDL(prAdapter, FALSE); |
| |
| return rStatus; |
| } |
| |
| uint32_t wlanDownloadPatch(IN struct ADAPTER *prAdapter) |
| { |
| uint32_t u4FwSize = 0; |
| void *prFwBuffer = NULL; |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| uint8_t 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 download patch\n"); |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| /* Patch DL */ |
| do { |
| #if CFG_SUPPORT_COMPRESSION_FW_OPTION |
| wlanCompressedImageSectionDownloadStage(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; |
| } |
| |
| uint32_t wlanGetPatchInfo(IN struct ADAPTER *prAdapter) |
| { |
| uint32_t u4FwSize = 0; |
| void *prFwBuffer = NULL; |
| uint32_t 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; |
| } |
| |
| wlanImageSectionGetPatchInfo(prAdapter, prFwBuffer, |
| u4FwSize, &u4StartOffset, |
| &u4Addr, &u4Len, &u4DataMode); |
| |
| kalFirmwareImageUnmapping(prAdapter->prGlueInfo, NULL, |
| prFwBuffer); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint32_t fwDlGetFwdlInfo(struct ADAPTER *prAdapter, |
| char *pcBuf, int i4TotalLen) |
| { |
| struct WIFI_VER_INFO *prVerInfo = &prAdapter->rVerInfo; |
| struct FWDL_OPS_T *prFwDlOps; |
| uint32_t u4Offset = 0; |
| uint8_t aucBuf[32], aucDate[32]; |
| |
| prFwDlOps = prAdapter->chip_info->fw_dl_ops; |
| |
| kalMemZero(aucBuf, 32); |
| kalStrnCpy(aucBuf, prVerInfo->aucFwBranchInfo, 4); |
| kalMemZero(aucDate, 32); |
| kalStrnCpy(aucDate, prVerInfo->aucFwDateCode, 16); |
| |
| u4Offset += snprintf(pcBuf + u4Offset, |
| i4TotalLen - u4Offset, |
| "\nN9 FW version %s-%u.%u.%u[DEC] (%s)\n", |
| aucBuf, |
| (uint32_t)(prVerInfo->u2FwOwnVersion >> 8), |
| (uint32_t)(prVerInfo->u2FwOwnVersion & BITS(0, 7)), |
| prVerInfo->ucFwBuildNumber, aucDate); |
| |
| if (prFwDlOps->getFwDlInfo) |
| u4Offset += prFwDlOps->getFwDlInfo(prAdapter, |
| pcBuf + u4Offset, |
| i4TotalLen - u4Offset); |
| |
| if (!prVerInfo->fgPatchIsDlByDrv) { |
| u4Offset += snprintf(pcBuf + u4Offset, |
| i4TotalLen - u4Offset, |
| "MCU patch is not downloaded by wlan driver, read patch info\n"); |
| wlanGetPatchInfo(prAdapter); |
| } |
| |
| kalMemZero(aucBuf, 32); |
| kalMemZero(aucDate, 32); |
| kalStrnCpy(aucBuf, prVerInfo->rPatchHeader.aucPlatform, 12); |
| kalStrnCpy(aucDate, prVerInfo->rPatchHeader.aucBuildDate, |
| 16); |
| u4Offset += snprintf(pcBuf + u4Offset, |
| i4TotalLen - u4Offset, |
| "Patch platform %s. Date %s\n", |
| aucBuf, aucDate); |
| |
| u4Offset += snprintf(pcBuf + u4Offset, i4TotalLen - u4Offset, |
| "Drv version %u.%u[DEC]\n", |
| (uint32_t)(prVerInfo->u2FwPeerVersion >> 8), |
| (uint32_t)(prVerInfo->u2FwPeerVersion & BITS(0, 7))); |
| return u4Offset; |
| } |
| |
| void fwDlGetReleaseInfoSection(struct ADAPTER *prAdapter, uint8_t *pucStartPtr) |
| { |
| struct HEADER_RELEASE_INFO *prFirstInfo; |
| struct HEADER_RELEASE_INFO *prRelInfo; |
| uint8_t *pucCurPtr = pucStartPtr + RELEASE_INFO_SEPARATOR_LEN; |
| uint16_t u2Len = 0, u2Offset = 0; |
| |
| prFirstInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; |
| DBGLOG(INIT, INFO, "Release info tag[%u] len[%u]\n", |
| prFirstInfo->ucTag, prFirstInfo->u2Len); |
| |
| pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); |
| while (u2Offset < prFirstInfo->u2Len) { |
| prRelInfo = (struct HEADER_RELEASE_INFO *)pucCurPtr; |
| DBGLOG(INIT, INFO, "Release info tag[%u] len[%u] padding[%u]\n", |
| prRelInfo->ucTag, prRelInfo->u2Len, |
| prRelInfo->ucPaddingLen); |
| |
| pucCurPtr += sizeof(struct HEADER_RELEASE_INFO); |
| switch (prRelInfo->ucTag) { |
| case 0x01: |
| fwDlGetReleaseManifest(prAdapter, prRelInfo, pucCurPtr); |
| break; |
| default: |
| DBGLOG(INIT, WARN, "Not support release info tag[%u]\n", |
| prRelInfo->ucTag); |
| } |
| |
| u2Len = prRelInfo->u2Len + prRelInfo->ucPaddingLen; |
| pucCurPtr += u2Len; |
| u2Offset += u2Len + sizeof(struct HEADER_RELEASE_INFO); |
| } |
| } |
| |
| void fwDlGetReleaseManifest(struct ADAPTER *prAdapter, |
| struct HEADER_RELEASE_INFO *prRelInfo, |
| uint8_t *pucStartPtr) |
| { |
| kalMemZero(&prAdapter->rVerInfo.aucReleaseManifest, |
| sizeof(prAdapter->rVerInfo.aucReleaseManifest)); |
| kalMemCopy(&prAdapter->rVerInfo.aucReleaseManifest, |
| pucStartPtr, prRelInfo->u2Len); |
| DBGLOG(INIT, INFO, "Release manifest: %s\n", |
| prAdapter->rVerInfo.aucReleaseManifest); |
| } |
| |
| #endif /* CFG_ENABLE_FW_DOWNLOAD */ |