diff -r 000000000000 -r 10c42ec6c05f TWD/FW_Transfer/RxXfer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TWD/FW_Transfer/RxXfer.c Tue Jun 29 12:34:26 2010 +0100 @@ -0,0 +1,677 @@ +/* + * RxXfer.c + * + * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. + * All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 or BSD License which accompanies + * this distribution. The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below. + * + * 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 Texas Instruments 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 + * OWNER 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. + */ + + +/**************************************************************************** + * + * MODULE: rxXfer.c + * + * PURPOSE: Rx Xfer module implementation.Responsible for reading Rx from the FW + * and forward it to the upper layers. + * + ****************************************************************************/ + +#define __FILE_ID__ FILE_ID_106 +#include "tidef.h" +#include "osApi.h" +#include "report.h" +#include "RxXfer.h" +#include "FwEvent_api.h" +#include "TWDriverInternal.h" +#include "RxQueue_api.h" +#include "TwIf.h" +#include "public_host_int.h" + +#define RX_DRIVER_COUNTER_ADDRESS 0x300538 +#define RX_DRIVER_DUMMY_WRITE_ADDRESS 0x300534 +#define PLCP_HEADER_LENGTH 8 +#define WORD_SIZE 4 +#define UNALIGNED_PAYLOAD 0x1 + +#define SLV_MEM_ADDR_VALUE(desc, offset)((RX_DESC_GET_MEM_BLK(desc)<<8)+ offset + 4) +#define SLV_MEM_CP_VALUE(desc, offset) (((RX_DESC_GET_MEM_BLK(desc)<<8)+ offset)) +/* Add an extra word for alignment the MAC payload in case of QoS MSDU */ +#define ALIGNMENT_SIZE(desc) ((RX_DESC_GET_UNALIGNED(desc) & UNALIGNED_PAYLOAD)? 2 : 0) +/*QOS definitions*/ +#define QOS_HW_ADDRESS 0x14FDA +#define QOS_SHIF_BACK_BUFFER 2 +#define QOS_LENGTH_DIFF 2 +#define QOS_SHIF_IN_BUFFER 4 +/************************ static function declaration *****************************/ + +static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct* pTxn); +static void rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uRxDesc, TI_UINT8 *pHostBuf, TI_UINT32 uBuffSize, TI_BOOL bDropPacket); +static void rxXfer_ForwardPacket (RxXfer_t* pRxXfer, TTxnStruct* pTxn); + +/**************************************************************************** + * RxXfer_Create() + **************************************************************************** + * DESCRIPTION: Create the RxXfer module object + * + * INPUTS: None + * + * OUTPUT: None + * + * RETURNS: The Created object + ****************************************************************************/ +TI_HANDLE rxXfer_Create (TI_HANDLE hOs) +{ + RxXfer_t *pRxXfer; + int i; + + pRxXfer = os_memoryAlloc (hOs, sizeof(RxXfer_t),MemoryNormal); + if (pRxXfer == NULL) + return NULL; + + /* For all the counters */ + os_memoryZero (hOs, pRxXfer, sizeof(RxXfer_t)); + + pRxXfer->pTempBuffer = os_memoryAlloc (hOs, MAX_PACKET_SIZE + WSPI_PAD_LEN_READ,MemoryDMA); + if (pRxXfer->pTempBuffer == NULL) + { + return NULL; + } + os_memoryZero (hOs, pRxXfer->pTempBuffer, MAX_PACKET_SIZE + WSPI_PAD_LEN_READ); + pRxXfer->pTempBuffer += WSPI_PAD_LEN_READ; + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + pRxXfer->aSlaveRegTxn[i].pRegData = os_memoryAlloc (hOs, 2*REGISTER_SIZE + WSPI_PAD_LEN_READ,MemoryDMA); + if (pRxXfer->aSlaveRegTxn[i].pRegData == NULL) + { + return NULL; + } + os_memoryZero (hOs, pRxXfer->aSlaveRegTxn[i].pRegData, 2*REGISTER_SIZE + WSPI_PAD_LEN_READ); + pRxXfer->aSlaveRegTxn[i].pRegData += WSPI_PAD_LEN_READ; + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + pRxXfer->aCounterTxn[i].pCounter = os_memoryAlloc (hOs, REGISTER_SIZE + WSPI_PAD_LEN_READ,MemoryDMA); + if (pRxXfer->aCounterTxn[i].pCounter == NULL) + { + return NULL; + } + os_memoryZero (hOs, pRxXfer->aCounterTxn[i].pCounter, REGISTER_SIZE + WSPI_PAD_LEN_READ); + pRxXfer->aCounterTxn[i].pCounter += WSPI_PAD_LEN_READ; + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + pRxXfer->aDummyTxn[i].pData = os_memoryAlloc (hOs, REGISTER_SIZE + WSPI_PAD_LEN_READ,MemoryDMA); + if (pRxXfer->aDummyTxn[i].pData == NULL) + { + return NULL; + } + os_memoryZero (hOs, pRxXfer->aDummyTxn[i].pData, REGISTER_SIZE + WSPI_PAD_LEN_READ); + pRxXfer->aDummyTxn[i].pData += WSPI_PAD_LEN_READ; + } + + + pRxXfer->hOs = hOs; + + return (TI_HANDLE)pRxXfer; +} + + +/**************************************************************************** + * RxXfer_Destroy() + **************************************************************************** + * DESCRIPTION: Destroy the RxXfer module object + * + * INPUTS: hRxXfer - The object to free + * + * OUTPUT: None + * + * RETURNS: + ****************************************************************************/ +void rxXfer_Destroy (TI_HANDLE hRxXfer) +{ + RxXfer_t *pRxXfer = (RxXfer_t *)hRxXfer; + int i; + + if (pRxXfer) + { + if (pRxXfer->pTempBuffer) + { + os_memoryFree (pRxXfer->hOs, pRxXfer->pTempBuffer - WSPI_PAD_LEN_READ, MAX_PACKET_SIZE + WSPI_PAD_LEN_READ); + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + if (pRxXfer->aSlaveRegTxn[i].pRegData) + { + os_memoryFree (pRxXfer->hOs, pRxXfer->aSlaveRegTxn[i].pRegData - WSPI_PAD_LEN_READ, 2*REGISTER_SIZE + WSPI_PAD_LEN_READ); + } + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + if (pRxXfer->aCounterTxn[i].pCounter) + { + os_memoryFree (pRxXfer->hOs, pRxXfer->aCounterTxn[i].pCounter - WSPI_PAD_LEN_READ, REGISTER_SIZE + WSPI_PAD_LEN_READ); + } + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + if (pRxXfer->aDummyTxn[i].pData) + { + os_memoryFree (pRxXfer->hOs, pRxXfer->aDummyTxn[i].pData - WSPI_PAD_LEN_READ, REGISTER_SIZE + WSPI_PAD_LEN_READ); + } + } + + os_memoryFree (pRxXfer->hOs, pRxXfer, sizeof(RxXfer_t)); + } +} + + +/**************************************************************************** + * rxXfer_init() + **************************************************************************** + * DESCRIPTION: Init the FwEvent module object + * + * INPUTS: hRxXfer - FwEvent handle; + * + * OUTPUT: None + * + * RETURNS: None + ****************************************************************************/ +void rxXfer_Init(TI_HANDLE hRxXfer, + TI_HANDLE hFwEvent, + TI_HANDLE hReport, + TI_HANDLE hTwIf, + TI_HANDLE hRxQueue) +{ + RxXfer_t *pRxXfer = (RxXfer_t *)hRxXfer; + + pRxXfer->hFwEvent = hFwEvent; + pRxXfer->hReport = hReport; + pRxXfer->hTwIf = hTwIf; + pRxXfer->hRxQueue = hRxQueue; + pRxXfer->uDrvRxCntr = 0; + + RxXfer_ReStart (hRxXfer); + +#ifdef TI_DBG + rxXfer_ClearStats (pRxXfer); +#endif +} + + +/**************************************************************************** + * rxXfer_Register_CB() + **************************************************************************** + * DESCRIPTION: Register the function to be called for request for buffer. + * + * INPUTS: hRxXfer - RxXfer handle; + * + * OUTPUT: None + * + * RETURNS: None + ****************************************************************************/ +void rxXfer_Register_CB (TI_HANDLE hRxXfer, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj) +{ + RxXfer_t* pRxXfer = (RxXfer_t *)hRxXfer; + + TRACE1(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_Register_CB (Value = 0x%x)\n", CallBackID); + + switch(CallBackID) + { + case TWD_INT_REQUEST_FOR_BUFFER: + pRxXfer->RequestForBufferCB = (TRequestForBufferCb)CBFunc; + pRxXfer->RequestForBufferCB_handle = CBObj; + break; + + default: + TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "rxXfer_Register_CB - Illegal value\n"); + return; + } +} + + +/**************************************************************************** + * rxXfer_ForwardPacket() + **************************************************************************** + * DESCRIPTION: Forward received packet to the upper layers. + * + * INPUTS: + * + * OUTPUT: + * + * RETURNS: + ****************************************************************************/ +static void rxXfer_ForwardPacket (RxXfer_t* pRxXfer, TTxnStruct* pTxn) +{ + RxIfDescriptor_t *pRxInfo; + TI_UINT16 uLenFromRxInfo; + + if (pTxn->uHwAddr == QOS_HW_ADDRESS)/*in case of QOS*/ + { + pTxn->aBuf[0]-= QOS_SHIF_BACK_BUFFER; + pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[0]); + /*in case of QOS we ask to read the data with 2 bytes shift so the packet will be alignd. + as a result we asked to read 2 bytes less, + since we are adding the mising 2 bytes (length) + we need to add those 2 bytes to the length*/ + pTxn->aLen[0]+= QOS_LENGTH_DIFF; + /*devide by 4 to have the value in word (from byte)*/ + pRxInfo->length = pTxn->aLen[0] >> 2; + /*fix back the endianaty and setting the missing value from the shor descriptor*/ + pRxInfo->length = ENDIAN_HANDLE_WORD(pRxInfo->length); + /*now we have the a regular Rx info with all parameters */ + pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[0]); + + } + else + { + /*in case of regular packet*/ + pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[0]); + } + + +#ifdef TI_DBG /* packet sanity check */ + /* Get length from RxInfo, handle endianess and convert to length in bytes */ + uLenFromRxInfo = ENDIAN_HANDLE_WORD(pRxInfo->length) << 2; + + /* If the length in the RxInfo is different than in the short descriptor, set error status */ + if (pTxn->aLen[0] != uLenFromRxInfo) + { + TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , ": Bad Length!! RxInfoLength=%d, ShortDescLen=%d, RxInfoStatus=0x%x\n", uLenFromRxInfo, pTxn->aLen[0], pRxInfo->status); + report_PrintDump(pTxn->aBuf[0], pTxn->aLen[0]); + pRxInfo->status &= ~RX_DESC_STATUS_MASK; + pRxInfo->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL; + pRxInfo->length = ENDIAN_HANDLE_WORD(pTxn->aLen[0] >> 2); + } +#endif + + /* Forward received packet to the upper layers */ + RxQueue_ReceivePacket (pRxXfer->hRxQueue, (const void *)pTxn->aBuf[0]); + + /* reset the aBuf field for clean on recovery purpose */ + pTxn->aBuf[0] = 0; +} + + +/**************************************************************************** + * rxXfer_RxEvent() + **************************************************************************** + * DESCRIPTION: Called upon Rx event from the FW.calls the SM + * + * INPUTS: hRxXfer - RxXfer handle; + * + * OUTPUT: None + * + * RETURNS: TWIF_OK in case of Synch mode, or TWIF_PENDING in case of Asynch mode + * (when returning TWIF_PENDING, FwEvent module expects the FwEvent_EventComplete() + * function call to finish the Rx Client handling + * + ****************************************************************************/ +TI_STATUS rxXfer_RxEvent (TI_HANDLE hRxXfer, FwStatus_t *pFwStatus) +{ + RxXfer_t *pRxXfer = (RxXfer_t *)hRxXfer; + TI_UINT32 uTempCounters; + FwStatCntrs_t *pFwStatusCounters; + TI_UINT32 i; + TI_STATUS rc; + + + uTempCounters = ENDIAN_HANDLE_LONG (pFwStatus->counters); +#ifdef TI_DBG + pRxXfer->DbgStats.counters = uTempCounters; +#endif + pFwStatusCounters = (FwStatCntrs_t*)(&uTempCounters); + + TRACE2(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , ": NewFwCntr=%d, OldFwCntr=%d\n", pFwStatusCounters->fwRxCntr, pRxXfer->uFwRxCntr); + + if (pFwStatusCounters->fwRxCntr%8 == pRxXfer->uFwRxCntr%8) + { + return TI_OK; + } + pRxXfer->uFwRxCntr = pFwStatusCounters->fwRxCntr; + + for (i = 0; i < NUM_RX_PKT_DESC; i++) + { + pRxXfer->aRxPktsDesc[i] = ENDIAN_HANDLE_LONG (pFwStatus->rxPktsDesc[i]); + } + + rc = rxXfer_Handle (pRxXfer); + + return rc; +} + + +/**************************************************************************** + * rxXfer_Handle() + **************************************************************************** + * DESCRIPTION: + * + * INPUTS: hRxXfer - RxXfer handle; + * + * OUTPUT: + * + * RETURNS: + ****************************************************************************/ +TI_STATUS rxXfer_Handle(TI_HANDLE hRxXfer) +{ +#ifndef _VLCT_ + RxXfer_t* pRxXfer = (RxXfer_t *)hRxXfer; + TI_UINT32 uRxDesc, uPacketIndex, uBuffSize, uSecurity; + TI_UINT8 *pHostBuf; + ERxBufferStatus eBufStatus; + + + if (pRxXfer->uAvailableTxn == 0 ) + { + TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "(): No available Txn structures left!\n"); + return TI_NOK; + } + + while (pRxXfer->uFwRxCntr%8 != pRxXfer->uDrvRxCntr%8) + { + uPacketIndex = pRxXfer->uDrvRxCntr % NUM_RX_PKT_DESC; + + uRxDesc = pRxXfer->aRxPktsDesc[uPacketIndex]; + + uBuffSize = RX_DESC_GET_LENGTH(uRxDesc) << 2; + + uSecurity = RX_DESC_GET_SECURITY(uRxDesc); + + /* prepare the read buffer */ + /* the RxBufAlloc() add an extra word for alignment the MAC payload in case of QoS MSDU */ + eBufStatus = pRxXfer->RequestForBufferCB(pRxXfer->RequestForBufferCB_handle, + (void**)&pHostBuf, + uBuffSize, + uSecurity); + + TRACE6(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , ": Index=%d, RxDesc=0x%x, DrvCntr=%d, FwCntr=%d, BufStatus=%d, BuffSize=%d\n", uPacketIndex, uRxDesc, pRxXfer->uDrvRxCntr, pRxXfer->uFwRxCntr, eBufStatus, uBuffSize); + + switch (eBufStatus) + { + case RX_BUF_ALLOC_PENDING: + return TI_OK; + + case RX_BUF_ALLOC_COMPLETE: + rxXfer_IssueTxn (pRxXfer, uRxDesc, pHostBuf, uBuffSize, TI_FALSE); + break; + + case RX_BUF_ALLOC_OUT_OF_MEM: + /* In case the allocation failed, we read the packet to a temporary buffer and ignore it */ + rxXfer_IssueTxn (pRxXfer, uRxDesc, pRxXfer->pTempBuffer, uBuffSize, TI_TRUE); + break; + } + + /* End of while */ + } +#endif + return TI_OK; +/* End of rxXfer_Handle() */ +} + + +/**************************************************************************** + * rxXfer_IssueTxn() + **************************************************************************** + * DESCRIPTION: + * + * INPUTS: + * + * OUTPUT: + * + * RETURNS: + ****************************************************************************/ +static void rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uRxDesc, TI_UINT8 *pHostBuf, TI_UINT32 uBuffSize, TI_BOOL bDropPacket) +{ + RxXfer_t *pRxXfer = (RxXfer_t *)hRxXfer; + TI_UINT32 uIndex = pRxXfer->uDrvRxCntr % MAX_CONSECUTIVE_READ_TXN; + TTxnStruct *pTxn; + ETxnStatus eStatus; + + /* Write the next mem block that we want to read */ + pRxXfer->aSlaveRegTxn[uIndex].tTxnStruct.uHwAddr = SLV_REG_DATA; + ((TI_UINT32*)(pRxXfer->aSlaveRegTxn[uIndex].pRegData))[0] = SLV_MEM_CP_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart); + ((TI_UINT32*)(pRxXfer->aSlaveRegTxn[uIndex].pRegData))[1] = SLV_MEM_ADDR_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart); + twIf_Transact(pRxXfer->hTwIf, &pRxXfer->aSlaveRegTxn[uIndex].tTxnStruct); + + /* prepare the read transaction */ + pTxn = (TTxnStruct*)&pRxXfer->aTxnStruct[uIndex]; + + if (!bDropPacket) + { + + if (ALIGNMENT_SIZE(uRxDesc)) + { + /*because the DMA requiers a 4 bytes alingned buffer and in the case of QOS we have + 2 more bytes in the WLAN header,we will give a 4 byte shifted buffer for the read. + in addition we will ask to read the data with 2 bytes shift, in this way we will + packet aligned. because of this 2 bytes shif the lenght for the read should be 2 + bytes shorter. + we will loose the first 2 bytes in the read (length in the RX info), + */ + BUILD_TTxnStruct(pTxn, SLV_MEM_QOS_DATA, pHostBuf +QOS_SHIF_IN_BUFFER , uBuffSize-QOS_LENGTH_DIFF, (TTxnDoneCb)rxXfer_TxnDoneCb, hRxXfer) + } + else + { + BUILD_TTxnStruct(pTxn, SLV_MEM_DATA, pHostBuf, uBuffSize, (TTxnDoneCb)rxXfer_TxnDoneCb, hRxXfer) + } + + } + else + { + TRACE0(pRxXfer->hReport, REPORT_SEVERITY_WARNING, "Request for Rx buffer failed! \n"); + BUILD_TTxnStruct(pTxn, SLV_MEM_DATA, pHostBuf, uBuffSize, NULL, NULL) + } + + eStatus = twIf_Transact(pRxXfer->hTwIf, pTxn); + + pRxXfer->uDrvRxCntr++; + + + + pTxn = &pRxXfer->aCounterTxn[uIndex].tTxnStruct; + *((TI_UINT32*)(pRxXfer->aCounterTxn[uIndex].pCounter)) = ENDIAN_HANDLE_LONG(pRxXfer->uDrvRxCntr); + TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) + BUILD_TTxnStruct(pTxn, RX_DRIVER_COUNTER_ADDRESS, pRxXfer->aCounterTxn[uIndex].pCounter, REGISTER_SIZE, NULL, NULL) + twIf_Transact(pRxXfer->hTwIf, pTxn); + + TRACE6(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , ": Counter-Txn: HwAddr=0x%x, Len0=%d, Data0=%d, DrvCount=%d, TxnParams=0x%x, RxDesc=0x%x\n", pTxn->uHwAddr, pTxn->aLen[0], *(TI_UINT32 *)(pTxn->aBuf[0]), pRxXfer->uDrvRxCntr, pTxn->uTxnParams, uRxDesc); + + + if (!bDropPacket) + { + if (eStatus == TXN_STATUS_COMPLETE) + { + /* Forward received packet to the upper layers */ + rxXfer_ForwardPacket (pRxXfer, &(pRxXfer->aTxnStruct[uIndex])); + } + else if (eStatus == TXN_STATUS_PENDING) + { + /* Decrease the number of available txn structures */ + pRxXfer->uAvailableTxn--; + } + else + { + TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , ": Status=%d, DrvCntr=%d, RxDesc=0x%x\n", eStatus, pRxXfer->uDrvRxCntr, uRxDesc); + } + } +} + + +/**************************************************************************** + * rxXfer_SetRxDirectAccessParams() + **************************************************************************** + * DESCRIPTION: + * + * INPUTS: + * + * OUTPUT: + * + * RETURNS: + ****************************************************************************/ +void rxXfer_SetRxDirectAccessParams (TI_HANDLE hRxXfer, TDmaParams *pDmaParams) +{ + RxXfer_t* pRxXfer = (RxXfer_t *)hRxXfer; + + pRxXfer->uPacketMemoryPoolStart = pDmaParams->PacketMemoryPoolStart; +} + + +/**************************************************************************** + * rxXfer_TxnDoneCb() + **************************************************************************** + * DESCRIPTION: Forward the packet to the registered CB + * + * INPUTS: + * + * OUTPUT: + * + * RETURNS: + ****************************************************************************/ +static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct* pTxn) +{ + RxXfer_t* pRxXfer = (RxXfer_t *)hRxXfer; + + /* Increase the number of available txn structures */ + pRxXfer->uAvailableTxn++; + + /* Forward received packet to the upper layers */ + rxXfer_ForwardPacket (pRxXfer, pTxn); + + /* Handle further packets if any */ + rxXfer_Handle(hRxXfer); +} + + +/**************************************************************************** + * RxXfer_ReStart() + **************************************************************************** + * DESCRIPTION: RxXfer_ReStart the RxXfer module object (called by the recovery) + * + * INPUTS: hRxXfer - The object to free + * + * OUTPUT: None + * + * RETURNS: NONE + ****************************************************************************/ +void RxXfer_ReStart(TI_HANDLE hRxXfer) +{ + RxXfer_t *pRxXfer = (RxXfer_t *)hRxXfer; + TTxnStruct* pTxn; + TI_UINT8 i; + + pRxXfer->uFwRxCntr = 0; + pRxXfer->uDrvRxCntr = 0; + pRxXfer->uAvailableTxn = MAX_CONSECUTIVE_READ_TXN - 1; + + /* Scan all transaction array and release only pending transaction */ + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + pTxn = &(pRxXfer->aSlaveRegTxn[i].tTxnStruct); + /* Check if buffer allocated and not the local one (signed by no callback) */ + if ((pTxn->hCbHandle != NULL) && (pTxn->aBuf[0] != 0)) + { + RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pTxn->aBuf[0]; + + WLAN_OS_REPORT (("RxXfer_ReStart: clean, in loop call RxQueue_ReceivePacket with TAG_CLASS_UNKNOWN\n")); + /* Set TAG_CLASS_UNKNOWN and call upper layer only to release the allocated buffer */ + pRxParams->packet_class_tag = TAG_CLASS_UNKNOWN; + RxQueue_ReceivePacket (pRxXfer->hRxQueue, (const void *)pTxn->aBuf[0]); + pTxn->aBuf[0] = 0; + } + } + + for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) + { + pTxn = &(pRxXfer->aSlaveRegTxn[i].tTxnStruct); + TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) + BUILD_TTxnStruct(pTxn, SLV_REG_DATA, pRxXfer->aSlaveRegTxn[i].pRegData, REGISTER_SIZE*2, NULL, NULL) + + pTxn = &pRxXfer->aTxnStruct[i]; + TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_FIXED_ADDR) + } + +} /* RxXfer_ReStart() */ + + +#ifdef TI_DBG +/**************************************************************************** + * rxXfer_ClearStats() + **************************************************************************** + * DESCRIPTION: + * + * INPUTS: + * pRxXfer The object + * + * OUTPUT: None + * + * RETURNS: TI_OK. + ****************************************************************************/ +void rxXfer_ClearStats (TI_HANDLE hRxXfer) +{ + RxXfer_t * pRxXfer = (RxXfer_t *)hRxXfer; + + os_memoryZero (pRxXfer->hOs, &pRxXfer->DbgStats, sizeof(RxXferStats_T)); +} + + +/**************************************************************************** + * rxXfer_PrintStats() + **************************************************************************** + * DESCRIPTION: . + * + * INPUTS: + * pRxXfer The object + * + * OUTPUT: None + * + * RETURNS: TI_OK. + ****************************************************************************/ +void rxXfer_PrintStats (TI_HANDLE hRxXfer) +{ + RxXfer_t * pRxXfer = (RxXfer_t *)hRxXfer; + + WLAN_OS_REPORT(("Print RX Xfer module info\n")); + WLAN_OS_REPORT(("=========================\n")); + WLAN_OS_REPORT(("Rx counter = 0x%x\n", pRxXfer->uFwRxCntr)); + WLAN_OS_REPORT(("Drv counter = 0x%x\n", pRxXfer->uDrvRxCntr)); + WLAN_OS_REPORT(("Fw Counters = 0x%x\n", pRxXfer->DbgStats.counters)); + WLAN_OS_REPORT(("AvailableTxn = 0x%x\n", pRxXfer->uAvailableTxn)); +} +#endif + +