platforms/os/Symbian/WVSS/src/wha/TIWhaTxRx.cpp
changeset 0 10c42ec6c05f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platforms/os/Symbian/WVSS/src/wha/TIWhaTxRx.cpp	Tue Jun 29 12:34:26 2010 +0100
@@ -0,0 +1,963 @@
+/*
+ * TIWhaTxRx.cpp
+ *
+ * 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.
+ */
+
+
+
+
+/** \file  TIWhaTxRx.cpp 
+ *  \brief  Control the data path from UMAC and back to UMAC
+ *
+ *  \see   
+*/
+
+#include "TIWha.h"
+
+/*******************************************************************************
+ * stuff for C file linking.                                                   *
+ *******************************************************************************/
+
+extern "C" 
+{
+
+#include "tidef.h"
+#include "report.h"
+#include "timer.h"
+#include "TWDriver.h"
+#include "version.h"
+#include "osApi.h"
+#include "context.h"
+#include "BusDrv.h"
+#include "public_types.h"
+#define __FILE_ID__								FILE_ID_147
+}
+
+static const TI_UINT8 WMEQosAcToTid[MAX_NUM_OF_AC] = { 0, 2, 4, 6 };
+
+#define WORD_SIZE                       4
+#define WORD_ALIGN_MASK                 0xFFFC
+#define GET_EXTRA_BYTES(status)		( (status & 0xc0) >> 6)
+#define KEY_GEM_TYPE                    4
+#define QOS_PADDING_SIZE                4
+#define QOS_SHIFT_SIZE                  2
+
+
+/********************************************************************************
+*																				*
+*                       MACROS and INLINE FUNCTIONS           					*
+*																				*
+*********************************************************************************/
+/* Update packet length in the descriptor according to HW interface requirements */
+static inline TI_UINT16 TranslateLengthToFw (TTxCtrlBlk *pPktCtrlBlk)
+{
+    TI_UINT16 uPktLen      = pPktCtrlBlk->tTxDescriptor.length;
+    TI_UINT16 uLastWordPad = (4 - (uPktLen & 3)) & 0x3;  /* Find number of bytes needed to align */
+
+    uPktLen = (uPktLen + uLastWordPad) >> 2;     /* Add alignment bytes and convert to words */
+	pPktCtrlBlk->tTxDescriptor.length = ENDIAN_HANDLE_WORD(uPktLen);
+
+    return uLastWordPad;
+}
+
+/* Translate packet timestamp to FW time, and update also lifeTime and uDriverDelay */
+static inline void TranslateTimeToFw (TwdCtrl *iTwdCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT16 uLifeTime)
+{
+    TI_UINT32 uPktStartTime = pPktCtrlBlk->tTxDescriptor.startTime;  /* Contains host start time */
+
+    /* Save host packet handling time until this point (for statistics) */
+    pPktCtrlBlk->tTxPktParams.uDriverDelay = os_timeStampMs (iTwdCtrl->tOsContext.hOsa) - uPktStartTime;
+                                             
+    /* Translate packet timestamp to FW time and undate descriptor */
+    uPktStartTime = TWD_TranslateToFwTime (iTwdCtrl->hTWD, uPktStartTime); 
+	pPktCtrlBlk->tTxDescriptor.startTime = ENDIAN_HANDLE_LONG (uPktStartTime);
+	pPktCtrlBlk->tTxDescriptor.lifeTime  = ENDIAN_HANDLE_WORD (uLifeTime);
+}
+
+
+/** 
+ * \fn     RxMemFailTimerCb
+ * \brief  Call again the rxXfer module to handle all pending packets.
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+void TIWha::RxMemFailTimerCb ()
+{
+	TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "RxMemFailTimerCb uRxMemFailCount %d\n",uRxMemFailCount);
+
+    bRxMemFailTimerRunning = TI_FALSE;
+
+    /* if uRxMemFailCount == 0 it means that Rx allocation is back to life - no need to call RxXfer */
+    if (uRxMemFailCount)
+    {
+        TWD_rxXfer_Handle(iTwdCtrl.hTWD);
+    }
+}
+
+/** 
+ * \fn     RequestForBuffer
+ * \brief  member function. calls LDD
+ * 
+ * \note    
+ * \param  aLength - aligned length of packet.
+ * \return  
+ * \sa      
+ */ 
+ERxBufferStatus TIWha::RequestForBufferCb (void **pWbuf, TI_UINT16 aLength, TI_UINT32 uEncryptionFlag)
+{
+    /* Total security overhead to be asked for in RequestForBuffer ()  */
+    TI_UINT32 uExtraSecurityLength = 0; 
+    /* Offset to be used when returning the buffer pointer. It will be used shifting the header backwards */
+    TI_UINT32 uSecurityOffset	   = 0;	
+    ERxBufferStatus eBufferStatus;
+    TI_UINT8* pRequestedBuf = NULL;
+
+    /*
+     * We should manipulate the packet according to the security mode. See ReceivePacket() for
+     * more details. 
+     * We have 2 issues to deal with:
+     * 1) Add additional length to the buffer request.
+    	 * 2) Change the pointer such that it will point forward by the size that should be added after the header.
+     *   	It is done in order to pull back the header later in GWSI_AdaptCB_ReceivePacket() to support GWSI spec.
+     */
+
+    
+    switch (uEncryptionFlag) 
+    {
+        case KEY_NULL:		
+        	uExtraSecurityLength = 0;
+        	uSecurityOffset		 = 0;
+            break;
+    
+        case KEY_WEP:	
+            uExtraSecurityLength = IV_FIELD_SIZE + ICV_FIELD_SIZE;
+        	uSecurityOffset		 = IV_FIELD_SIZE;
+            break;
+    
+        case KEY_TKIP:
+        	uExtraSecurityLength = IV_FIELD_SIZE + EIV_FIELD_SIZE + MIC_FIELD_SIZE + ICV_FIELD_SIZE;
+        	uSecurityOffset		 = IV_FIELD_SIZE + EIV_FIELD_SIZE;
+            break;
+    
+        case KEY_AES:		
+        	uExtraSecurityLength = AES_AFTER_HEADER_FIELD_SIZE + MIC_FIELD_SIZE;
+        	uSecurityOffset		 = AES_AFTER_HEADER_FIELD_SIZE;
+            break;
+
+        #ifdef GEM_SUPPORT
+            case KEY_GEM_TYPE:
+                uExtraSecurityLength = GEM_AFTER_HEADER_FIELD_SIZE + GEM_MIC_FIELD_SIZE;
+            	uSecurityOffset		 = GEM_AFTER_HEADER_FIELD_SIZE + GEM_BUFFER_ALIGNMENT;
+                break;
+        #endif
+
+        default:
+            TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "RequestForBuffer: uEncryptionFlag = %d uExtraSecurityLength = %d\n", uEncryptionFlag, uExtraSecurityLength);
+            break;
+    }
+    
+
+    if (iRxPacketsAllocated < MAX_WHA_RX_BUFFERS)
+    {
+        /* 
+         * We are requesting extra bytes for security, but decreasing WSPI_PAD_LEN_READ since the spec indicates
+         *  that the Rx offset will be added any way 
+         */
+        if( bErrorIndication == TI_FALSE)
+        {    
+            pRequestedBuf = (TI_UINT8*) WhaCb()->RequestForBuffer(aLength - sizeof(RxIfDescriptor_t) + uExtraSecurityLength + QOS_PADDING_SIZE + PAYLOAD_ALIGN_PAD_BYTES);
+        }
+        #if TI_DBG
+            else
+            {
+                WLAN_OS_REPORT(("%s : CommandResponse Block call to LDD response \n",__FUNCTION__));
+            }
+        #endif	
+        
+        if ( pRequestedBuf == NULL )
+        { 
+            #ifdef PLT_TESTER
+                return RX_BUF_ALLOC_OUT_OF_MEM;
+            #endif
+                                  
+            uRxMemFailCount++;
+			/* In case no timer is running - start a new timer to call RxXfer later */
+			if (!bRxMemFailTimerRunning) 
+			{
+                #ifdef TI_DBG
+                if (uRxMemFailCount == 1)
+                {
+                    /* Print error only for the first time */
+                    TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR, "Start hRxMemFailTimer for the first time\n");
+                }
+                #endif
+                TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "Start hRxMemFailTimer uRxMemFailCount %d\n",uRxMemFailCount);
+                /* In case we fail too many times, just mark as OUT_OF_MEM so the Rx packet will be dropped */
+                if (uRxMemFailCount > MAX_CONSECUTIVE_RX_MEM_FAIL)
+                {
+                    return RX_BUF_ALLOC_OUT_OF_MEM;
+                }
+
+				bRxMemFailTimerRunning = TI_TRUE;
+                os_timerStart(&iTwdCtrl.tOsContext,hRxMemFailTimer,RX_ALLOC_FAIL_TIME_OUT);
+			}
+
+            /* In this case rxXfer will exit the loop and wait for someone to trigger the SM again */      
+			return RX_BUF_ALLOC_PENDING;
+        }
+
+        /* Increase the number of allocated buffers */
+        iRxPacketsAllocated++;
+    
+#ifdef TI_DBG
+        /* Just have a print in case we are out of the bad situation of RX_BUF_ALLOC_OUT_OF_MEM */
+        if (uRxMemFailCount)
+        {
+					TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR, "Rx allocation succeeded after %d times\n",uRxMemFailCount);
+        }
+#endif /* TI_DBG */
+
+        /* Rx allocation succeeded so set counter to zero */
+        uRxMemFailCount = 0;
+
+        TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "RequestForBuffer: uEncryptionFlag = %d uExtraSecurityLength = %d\n", uEncryptionFlag, uExtraSecurityLength);
+
+        TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "RequestForBuffer: len = %d OriginalPointer = 0x%x, allocatedBuffer#= %d \n", aLength, *pWbuf, iRxPacketsAllocated);
+
+        TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "RequestForBuffer: Pointer2Buffer= 0x%x, Buffer= 0x%x \n",pWbuf, *pWbuf);
+
+        /* The packet will be read as if it started uSecurityOffset bytes ahead and ReceivePacket() will take it back */
+        /* pWbuf points to the actual start of the data */
+        pRequestedBuf += uSecurityOffset + WSPI_PAD_LEN_READ;
+        
+        *pWbuf = (void*)pRequestedBuf;
+        
+        eBufferStatus = RX_BUF_ALLOC_COMPLETE;       
+    }
+    else
+    {
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_WARNING, "RequestForBuffer: RX_BUF_ALLOC_PENDING");
+        /* RxXfer will try to allocate the buffer again when other buffer will be released */ 
+        eBufferStatus = RX_BUF_ALLOC_PENDING;       
+    }
+    
+    return eBufferStatus;
+}
+
+ 
+/** 
+ * \fn     ReceivePacket
+ * \brief  member function. calls LDD
+ * 
+ * \note    
+ * \param  aStatus - not used but retrieved from RxIfDescriptor_t.
+ * \param  aBuf	   - pointer to start of RxIfDescriptor_t.
+ * \return  
+ * \sa      
+ */ 
+void TIWha::ReceivePacketCb (const void *aBuf)
+{
+	WHA::TStatus 		aStatus;
+	TUint16				aLength;
+	WHA::TRate			aRate;
+	WHA::TRcpi			aRcpi;
+	WHA::TChannelNumber aChannel;
+	TUint32 			aFlags;
+	/* move aBuf to begeinnig of MAC heder */
+	const void*			aFrame = (TI_UINT8*)aBuf + sizeof(RxIfDescriptor_t);
+    dot11_header_t      *pDot11Hdr = (dot11_header_t*)aFrame;
+	RxIfDescriptor_t*	pRxParams = (RxIfDescriptor_t*)aBuf;
+    TBool               bQos;
+
+    
+    
+	switch (pRxParams->status)
+	{
+	case RX_FAILURE_NONE:                     
+        aStatus = WHA::KSuccess;          
+        break;
+
+    case RX_FAILURE_MIC_ERROR:   
+        aStatus = WHA::KMicFailure; 
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR , "ReceivePacket MIC_FAILURE !!! \n");
+        break; 
+
+    case RX_FAILURE_DECRYPT:     
+        aStatus = WHA::KDecryptFailure;   
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR , "ReceivePacket DECRYPT_FAILURE !!! \n");
+        break; 
+
+    default: 
+    	TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR ,"ReceivePacketCb : WHA::KFailed");
+        aStatus = WHA::KFailed;
+	}
+
+    /* convert to LDD rate */
+	aRate	= TIWhaUtils::PolicyToWhaRate ((ETxRateClassId)pRxParams->rate);
+
+	/* calculate RCPI form RSSI */
+	if (pRxParams->rx_level >= 0)
+		aRcpi = 220;
+	else
+		if (pRxParams->rx_level <= -110)
+			aRcpi = 0;
+		else
+			aRcpi = (pRxParams->rx_level + 110)*2;
+
+	/* Channel of received frame */
+	aChannel = pRxParams->channel;
+
+    /* pRxParams->length refer to total length form MAC heder in bytes */
+	aLength = pRxParams->length*WORD_SIZE - pRxParams->extraBytes - sizeof(RxIfDescriptor_t);
+
+	/* flags description:
+	   1. bits 0 - 15 are optional
+	   2. bits 16 - 18 security TBD when security integrated
+	   3. bit 19 for more pending frames
+	   4. bit 20 packet was received during a measurement process or not
+     */
+    aFlags = 0;
+
+    /*
+	 * The next adaptation code is meant to align with the driver legacy operation of extra padding for security:
+	 *
+	 * WEP: 	TnetwDrv	 	HEADER - DATA
+	 *    		Upper layer		HEADER - IV (4) - DATA - ICV (4)
+	 *
+	 * TKIP: 	TnetwDrv	 	HEADER - DATA 
+	 *			Upper layer		HEADER - IV (4)  - EIV (4) - DATA - MIC (8) - ICV (4)
+	 *   		
+	 * AES: 	TnetwDrv	 	HEADER - DATA
+	 *			Upper layer		HEADER - RSN (8) - DATA - MIC (8) 	
+	 *
+     * GEM: 	TnetwDrv	 	HEADER - DATA
+	 *			Upper layer		HEADER - KeyIdx(1) - Reserved(1) - PN(16) - DATA - MIC (16) 	
+     *
+	 * Note: 	Adding the offset is done even if the packet status is error	
+	 */
+    bQos = IS_QOS_FRAME(pDot11Hdr->fc);
+    TUint8 shiftBytes = WSPI_PAD_LEN_READ; 
+    
+    switch (pRxParams->flags & RX_DESC_ENCRYPT_MASK)
+    {
+        case RX_DESC_ENCRYPT_WEP:
+            ALIGN_HEADER_TO_DATA_BACKWARD (aFrame, WEP_AFTER_HEADER_FIELD_SIZE, bQos)
+            shiftBytes += WEP_AFTER_HEADER_FIELD_SIZE;
+            /* Increase length size by 8 (IV + ICV) */
+            aLength += (WEP_AFTER_HEADER_FIELD_SIZE + ICV_FIELD_SIZE);
+            aFlags |= WHA_WEP;
+            break;
+        
+        case RX_DESC_ENCRYPT_TKIP:
+            ALIGN_HEADER_TO_DATA_BACKWARD (aFrame, TKIP_AFTER_HEADER_FIELD_SIZE, bQos)
+            shiftBytes += TKIP_AFTER_HEADER_FIELD_SIZE;
+            /* Increase length size by 20 (IV + EIV + MIC + ICV) */
+            aLength += (TKIP_AFTER_HEADER_FIELD_SIZE + MIC_FIELD_SIZE + ICV_FIELD_SIZE);
+            aFlags |= WHA_TKIP;
+            break;
+    
+        case RX_DESC_ENCRYPT_AES:
+            ALIGN_HEADER_TO_DATA_BACKWARD (aFrame, AES_AFTER_HEADER_FIELD_SIZE, bQos)
+            shiftBytes += AES_AFTER_HEADER_FIELD_SIZE;
+            /* Increase length size by 16 (AES(RSN padding) + MIC) */
+            aLength += (AES_AFTER_HEADER_FIELD_SIZE + MIC_FIELD_SIZE);
+            aFlags |= WHA_AES;
+            break;
+
+        #ifdef GEM_SUPPORT
+            case RX_DESC_ENCRYPT_GEM:
+                ALIGN_HEADER_TO_DATA_BACKWARD (aFrame, GEM_AFTER_HEADER_FIELD_SIZE, bQos)
+                shiftBytes += GEM_AFTER_HEADER_FIELD_SIZE + GEM_BUFFER_ALIGNMENT;
+                /* Increase length size by 34 ( GEM_KeyIdx(1) + GEM_Reserved(1) + GEM_PN(16) + GEM_MIC(16) ) */
+                aLength += (GEM_AFTER_HEADER_FIELD_SIZE + GEM_MIC_FIELD_SIZE);
+                aFlags |= WHA_GEM;
+                break;
+        #endif
+
+        default:
+            /* Do nothing */
+            break;
+    }
+
+	/*if QOS frame the pointer starts 2 bytes before so the shiftbytes will be 2 mor bytes*/
+	if (bQos)
+	{
+		shiftBytes += QOS_SHIFT_SIZE;
+	}
+
+
+
+    /* Call upper layer */
+    if( bErrorIndication == TI_FALSE)
+    {    
+        WhaCb()->ReceivePacket (aStatus, 
+							aFrame, 
+							aLength, 
+							aRate, 
+							aRcpi, 
+							aChannel,
+							(TUint8*)aBuf - shiftBytes,  
+							aFlags);
+    }
+    #if TI_DBG
+        else
+        {
+            WLAN_OS_REPORT(("%s : CommandResponse Block call to LDD response \n",__FUNCTION__));
+        }
+    #endif	
+
+    /* Decrease the number of allocated buffers */
+    iRxPacketsAllocated--;
+
+    TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "end of ReceivePacket(), allocated buffer = %d\n", iRxPacketsAllocated);
+}
+
+
+/** 
+ * \fn     SendPacket
+ * \brief  member function. 
+ * 
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+WHA::TStatus TIWha::SendPacket(
+								  const void* aFrame,
+								  TUint16 aLength,
+								  WHA::TQueueId aQueueId,
+								  TUint8 aTxRateClassId,
+								  WHA::TRate aMaxTransmitRate,
+								  TBool aMore,
+								  WHA::TPacketId aPacketId,
+								  WHA::TPowerLevel aPowerLevel,
+								  TUint32 aExpiryTime,
+								  void* aReserved )
+{    
+    TTxCtrlBlk *pPktCtrlBlk;
+    void* aData = (void*)aFrame;
+    WHA::TStatus whaStatus;
+    TI_STATUS tiStatus;
+
+    TRACE4(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, " aFrame = 0x%x len = %d aQueue = %d rateClass = %d\n", aFrame, aLength, aQueueId, aTxRateClassId);
+
+    TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, " aMaxTransmitRate = 0x%x aPacketId = 0x%x aExpiryTime = %d \n",aMaxTransmitRate, aPacketId, aExpiryTime);
+    
+
+    AlignTxForTWD (aData, aLength);
+
+    /* 
+     * Prepare packet for transmision by filling up all the fields. 
+     */
+    
+     whaStatus = preparePktCtrlBlk ( &pPktCtrlBlk,
+                                     aData,
+                                     aLength,
+                                     aQueueId,
+                                     aTxRateClassId,
+                                     aMaxTransmitRate,
+                                     aMore,
+                                     aPacketId,
+                                     aPowerLevel,
+                                     aExpiryTime);
+
+    if ( whaStatus == WHA::KQueueFull)
+    {
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_WARNING , "****** KQueueFull ****** \n");
+        AlignTxSecurityForUMAC (TRUE);
+        return WHA::KQueueFull;
+    }
+
+   TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "aFrame=%x, Buffer= %x \n", aFrame, pPktCtrlBlk->tTxnStruct.aBuf[0]);
+
+    /*
+     *  Call the Tx-Xfer to start packet transfer to the FW and return its result.       
+     */
+
+    tiStatus  = TWD_txXfer_SendPacket ( iTwdCtrl.hTWD, pPktCtrlBlk);
+
+   TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, " status = %d \n", tiStatus);
+
+    switch (tiStatus)
+    {
+        case TXN_STATUS_COMPLETE:
+            /* TxXferCb () won't be called so Align Tx packet before */
+            AlignTxSecurityForUMAC (TRUE);
+            /* Mark that TxXferCb won't be called */
+            pPktCtrlBlk->tTxPktParams.uFlags = TX_CTRL_FLAG_XFER_DONE_ISSUED;
+            return WHA::KSuccessXfer;
+        case TXN_STATUS_OK:
+            pPktCtrlBlk->tTxPktParams.uFlags = 0;
+            if (whaStatus == WHA::KPending) {
+                return WHA::KPending;
+            }
+            return WHA::KSuccess;
+        case TXN_STATUS_PENDING:
+            /* The packet is pending in spi level and not in driver level */
+            pPktCtrlBlk->tTxPktParams.uFlags = 0;
+            if (whaStatus == WHA::KPending) {
+                return WHA::KPending;
+            }
+            return WHA::KSuccess;
+        case TXN_STATUS_ERROR:
+            /* TxXferCb () won't be called so Align Tx packet before */
+            AlignTxSecurityForUMAC (TRUE);
+            return WHA::KQueueFull;
+        default:
+            /* TxXferCb () won't be called so Align Tx packet before */
+            AlignTxSecurityForUMAC (TRUE);
+            return WHA::KFailed;
+    }
+}
+
+/** 
+ * \fn     preparePktCtrlBlk
+ * \brief  prepare the Ctrl Block with the given parameters
+ * 
+ * \note    
+ * \return   txCtrlBlkEntry_t*
+ * \sa      
+ */ 
+WHA::TStatus TIWha::preparePktCtrlBlk ( TTxCtrlBlk **pPktCtrlBlk,
+                                       const void* aFrame,
+                                       TUint16 aLength,
+                                       WHA::TQueueId aQueueId,
+                                       TUint8 aTxRateClassId,
+                                       WHA::TRate aMaxTransmitRate,
+                                       TBool aMore,
+                                       WHA::TPacketId aPacketId,
+                                       WHA::TPowerLevel aPowerLevel,
+                                       TUint32 aExpiryTime)
+{
+    TI_UINT16 txDescAttr; /* Tx-descriptor fields values. */
+    TI_UINT16 uLastWordPad;
+	TI_UINT8  uAligmentPad;
+    TI_UINT32 tempaFrame;    
+    *pPktCtrlBlk = NULL;
+    ETxHwQueStatus eHwQueStatus;
+
+    /* Allocates a Control-Block for the packet Tx parameters and descriptor. */
+    *pPktCtrlBlk = TWD_txCtrlBlk_Alloc (iTwdCtrl.hTWD);
+    
+    /* If null entry (not expected to happen) return ERROR. */
+    if (!*pPktCtrlBlk)
+    {
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR, ": Tx Ctrl-Blk allocation failed!!!\n");
+        return WHA::KQueueFull;
+    }
+
+    /*  Save the aPacketId for use in TxXferCb & TxCompleteCb */
+    iPacketIdTable[(*pPktCtrlBlk)->tTxDescriptor.descID] = aPacketId;
+
+    TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, ": iPacketIdTable[%d]= %d\n", (*pPktCtrlBlk)->tTxDescriptor.descID, aPacketId);
+
+    /*
+     *  Fill in parameters of  pPktCtrlBlk                                                                                   
+     */
+    /* Move aFrame back in order to leave room for the tx_descriptor */
+    tempaFrame = (TI_UINT32)aFrame - TX_DESCRIPTOR_SIZE;
+    aFrame = (void*)tempaFrame;
+    
+	uAligmentPad = ((4 -(aLength & 0x3)) & 0x3);
+    /* data is given with the header, this is different then full driver  */
+    (*pPktCtrlBlk)->tTxnStruct.aLen[0] =  aLength + TX_DESCRIPTOR_SIZE + uAligmentPad;
+    (*pPktCtrlBlk)->tTxnStruct.aBuf[0] = (TI_UINT8*)aFrame;
+    /* Not relevant since we are not incharge on the memory release */
+    (*pPktCtrlBlk)->tTxPktParams.uInputPktLen = 0;
+    (*pPktCtrlBlk)->tTxPktParams.pInputPkt = 0;
+
+    /* 
+     *  Build packet descriptor (for FW interface).  
+     */
+    (*pPktCtrlBlk)->tTxDescriptor.tid = WMEQosAcToTid[aQueueId];
+    (*pPktCtrlBlk)->tTxDescriptor.startTime = os_timeStampMs (iTwdCtrl.tOsContext.hOsa);
+    TranslateTimeToFw (&iTwdCtrl, (*pPktCtrlBlk), 2000/*aExpiryTime*/);
+
+   TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, ": aExpiryTime= %d, desc.startTime= %d, desc.lifeTime= %d \n", aExpiryTime, (*pPktCtrlBlk)->tTxDescriptor.startTime, (*pPktCtrlBlk)->tTxDescriptor.lifeTime);
+
+    /* Initialize tTxDescriptor.length with the real packet length in bytes */
+    (*pPktCtrlBlk)->tTxDescriptor.length = aLength + TX_DESCRIPTOR_SIZE;
+    
+     /* Call HwQueue for Hw resources allocation. If not available return NULL. */
+    eHwQueStatus = TWD_txHwQueue_AllocResources (iTwdCtrl.hTWD, (*pPktCtrlBlk));
+                   
+    if (eHwQueStatus == TX_HW_QUE_STATUS_STOP_CURRENT)
+    {
+        /* Free Ctrl block. */
+        TWD_txCtrlBlk_Free(iTwdCtrl.hTWD, (*pPktCtrlBlk));
+
+        TRACE0(iTwdCtrl.hReport, REPORT_SEVERITY_WARNING, ": Tx Hw resources allocation failed!!!\n");
+        return WHA::KQueueFull;
+    }
+
+    /* txCtrl_TranslateLengthToFw() will translate it to the length in FW format */
+    uLastWordPad = TranslateLengthToFw((*pPktCtrlBlk));
+
+    /* Upper layer is using '1' for first policy, while TnetwDrv is using '0' for it. */
+    txDescAttr = (aTxRateClassId - 1 ) << TX_ATTR_OFST_RATE_POLICY;
+    
+    /* if there is a security padding then the WLAN packet was stuffed with 2 extra bytes for alignment */
+    if (iSecurityPadding != 0) 
+    {        
+        txDescAttr |= TX_ATTR_HEADER_PAD;        
+    }
+    
+    txDescAttr |= uLastWordPad << TX_ATTR_OFST_LAST_WORD_PAD;
+        
+    (*pPktCtrlBlk)->tTxDescriptor.txAttr = txDescAttr; 
+    
+    /*
+     * Copy the descriptor parameters to the packet header.    
+     */
+    os_memoryCopy(iTwdCtrl.tOsContext.hOsa, const_cast<void*>(aFrame), (TxIfDescriptor_t*)&(*pPktCtrlBlk)->tTxDescriptor, sizeof(TxIfDescriptor_t));
+    
+    return eHwQueStatus == TX_HW_QUE_STATUS_STOP_NEXT ? WHA::KPending : WHA::KSuccess;    
+}
+
+/** 
+ * \fn     AlignTxForTWD
+ * \brief  Aligment header to TWD structure -- Check HT and Security. 
+ * 
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+WHA::TStatus TIWha::AlignTxForTWD (void*& aFrame,TUint16& aLength)    
+{
+    /* Use the header to retrieve the frame ctrl of the packet */
+    dot11_header_t  *pDot11Hdr = (dot11_header_t*)aFrame; 
+    TI_UINT32 tempaFrame;
+
+    /* By default we won't handle any alignment */
+    iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] = 0;
+	#ifdef HT_SUPPORT
+		if (IS_HT_FRAME(pDot11Hdr->fc))
+		{
+		iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] = HT_CONTROL_FILED_SIZE;
+		aLength -= HT_CONTROL_FILED_SIZE;
+		}
+	#endif /* HT_SUPPORT */
+    	
+	/* Qos heaser is needed to determine the WLAN Header size  */
+    	iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrSend] = IS_QOS_FRAME(pDot11Hdr->fc);
+    
+    /* zero iSecurityPadding for every new packet */
+      iSecurityPadding = 0;
+    
+    /* Check if using security. If so we should convert the packet format as the description below */
+    if (IS_WEP_ON(pDot11Hdr->fc))
+    {
+    	TI_UINT8* pMac;
+        ECipherSuite eSecurityMode;
+
+        pMac = &pDot11Hdr->address1[0]; /* hold the first mac address */
+
+    	/* Use group key on Multicast/broadcast. else use pairwise */
+        if (MAC_MULTICAST(pMac))
+        {
+            eSecurityMode = iTwdCtrl.eGroupKeyMode;
+        }
+        else
+        {
+            eSecurityMode = iTwdCtrl.ePairwiseKeyMode;
+        }
+         
+    	/*
+    	 * The next adaptation code is meant to align with the driver legacy operation of extra padding for security:
+    	 *
+    	 * WEP: 	Upper layer		HEADER - IV (4) - DATA - ICV (4)
+    	 *   		TnetwDrv	 	HEADER - DATA
+    	 *
+    	 * TKIP: 	Upper layer		HEADER - IV (4)  - EIV (4) - DATA - MIC (8) - ICV (4)
+    	 *   		TnetwDrv	 	HEADER - EIV (4) - DATA 
+    	 *
+    	 * AES: 	Upper layer		HEADER - RSN (8) - DATA - MIC (8)
+    	 *   		TnetwDrv	 	HEADER - RSN (8) - DATA
+    	 */
+    				 	
+        TRACE4(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "SendPacket(): send = %d Handle = %d, QoS = %d, encryption = %d\n",iTwdCtrl.TxAlign.uCurrSend, iTwdCtrl.TxAlign.uCurrHandle, 
+            iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrSend], eSecurityMode);
+
+        switch (eSecurityMode) 
+    	{
+        case TWD_CIPHER_WEP:
+            /* Mark the offset between header and data */
+            iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] += WEP_AFTER_HEADER_FIELD_SIZE;
+            /* Decrease length size by 8 (IV + ICV) */
+            aLength -= (IV_FIELD_SIZE + ICV_FIELD_SIZE);
+            break;
+
+    	case TWD_CIPHER_TKIP:
+            /* Mark the offset between header and data */
+            iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] += IV_FIELD_SIZE;
+            /* Decrease length size by 16 (IV + MIC + ICV) */
+            aLength -= (IV_FIELD_SIZE + MIC_FIELD_SIZE + ICV_FIELD_SIZE);
+            break;
+
+    	case TWD_CIPHER_AES_WRAP:
+    	case TWD_CIPHER_AES_CCMP:
+    		/* Decrease length size by 8 (MIC) */
+    		aLength -=  MIC_FIELD_SIZE;
+    		break;
+        #ifdef GEM_SUPPORT
+            case TWD_CIPHER_GEM:
+                /* Mark the offset between header and data */
+                iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] += GEM_AFTER_HEADER_FIELD_SIZE;
+                /* Decrease length size by 34 bytes (KEY_IDX_FIELD_SIZE + RESERVED_FIELD_SIZE + PN_FIELD_SIZE + MIC) */
+        		aLength -=  (GEM_AFTER_HEADER_FIELD_SIZE + GEM_MIC_FIELD_SIZE);
+                /* Add padding of two bytes before wlan header, */
+                /* because it will be unaligned after the header will be moved 18 bytes */
+                iSecurityPadding = GEM_AFTER_HEADER_PAD;
+                break;
+        #endif
+        
+    	default:
+    		/* Unknown security with Encryption ON. return ERROR */
+                TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR, "SendPacket(): Encryption ON but unknown security mode = %d\n",     			 eSecurityMode);
+    		return WHA::KFailed;
+    	}
+    }
+
+	/* Check if the header packet should move */
+    if (iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend] > 0)
+    {
+        ALIGN_HEADER_TO_DATA_FORWARD (aFrame, iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend], 
+                                     iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrSend])
+    }
+
+    /* Move the frame iSecurityPadding (2 bytes) backward */    
+    tempaFrame = (TI_UINT32)aFrame - iSecurityPadding;
+    aFrame = (void*)tempaFrame;
+    /* Increase the length by size of iSecurityPadding (2 bytes) */
+    aLength+= iSecurityPadding;
+    /* Mark the current packet - Note that it is needed only when we have security */
+    iTwdCtrl.TxAlign.pFrame[iTwdCtrl.TxAlign.uCurrSend] = (void*)aFrame;
+    /* For the next packet to be send */
+    
+    iTwdCtrl.TxAlign.uCurrSend++;
+    iTwdCtrl.TxAlign.uCurrSend %= MAX_XFER_WAITING_PACKETS;
+
+    return WHA::KSuccess;
+}
+
+
+/** 
+ * \fn     AlignTxSecurityForUMAC
+ * \brief  security alignment. 
+ *
+ * Handle packet alignment after Xfer done
+ *               It is done here after the pointer was changed in TIWha::SendPacket()
+ *               and at this point the pointer is not needed any more.
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+void TIWha::AlignTxSecurityForUMAC (TBool aQFull)
+{
+    TRACE5(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "AlignTxSecurityForUMAC(): send = %d Handle = %d, QoS = %d, Offset = %d pFrame = %p\n",iTwdCtrl.TxAlign.uCurrSend, iTwdCtrl.TxAlign.uCurrHandle,iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrHandle], 
+        iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrHandle],iTwdCtrl.TxAlign.pFrame[iTwdCtrl.TxAlign.uCurrHandle]);
+
+    if (aQFull) {
+        
+        iTwdCtrl.TxAlign.uCurrSend = iTwdCtrl.TxAlign.uCurrSend > 0? iTwdCtrl.TxAlign.uCurrSend - 1 : 49;
+        TRACE5(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "AlignTxSecurityForUMAC() -- ** aQFull **: send = %d Handle = %d, QoS = %d, Offset = %d pFrame = %p\n",iTwdCtrl.TxAlign.uCurrSend, iTwdCtrl.TxAlign.uCurrHandle,iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrHandle], 
+            iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrHandle],iTwdCtrl.TxAlign.pFrame[iTwdCtrl.TxAlign.uCurrHandle]);
+
+        ALIGN_HEADER_TO_DATA_BACKWARD (iTwdCtrl.TxAlign.pFrame[iTwdCtrl.TxAlign.uCurrSend], 
+            iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrSend], 
+            iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrSend])
+        return;
+    }
+
+    /* Check if the packet should be aligned */
+    if (iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrHandle])
+    {
+        ALIGN_HEADER_TO_DATA_BACKWARD (iTwdCtrl.TxAlign.pFrame[iTwdCtrl.TxAlign.uCurrHandle], 
+            iTwdCtrl.TxAlign.uHeaderToDataOffset[iTwdCtrl.TxAlign.uCurrHandle], 
+            iTwdCtrl.TxAlign.bIsQosHeader[iTwdCtrl.TxAlign.uCurrHandle])
+    }
+
+    /* For the next packet to be handled */
+    iTwdCtrl.TxAlign.uCurrHandle++;
+    iTwdCtrl.TxAlign.uCurrHandle %= MAX_XFER_WAITING_PACKETS;
+}
+
+
+/** 
+ * \fn     TxXferCb
+ * \brief  
+ *    Called by the TNETW driver upon Xfer-Done of transmitted packet.
+ *   Calls the UMAC Xfer-Done handler.
+ *
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+void TIWha::TxXferCb ( TTxCtrlBlk *pPktCtrlBlk)
+{
+    TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION,  "TxXferCb(): packetId=0x%x flags = 0x%x\n",iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID], pPktCtrlBlk->tTxPktParams.uFlags);
+        
+#ifdef TI_DBG
+    /* If the pointed entry is already free, print error and exit (not expected to happen). */
+    if (pPktCtrlBlk->pNextFreeEntry != NULL)
+    {
+        TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "TxXferCb(): Pkt already free!!, DescID=%d, flags=%d, packetId=0x%x\n",pPktCtrlBlk->tTxDescriptor.descID, pPktCtrlBlk->tTxPktParams.uFlags,iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]);
+    
+        return;
+    }
+#endif
+
+    /* Check If this is the second time we call TxXferCb for this packet (i.e. TxCompleteCb called it explicitly) */
+    if (pPktCtrlBlk->tTxPktParams.uFlags &  TX_CTRL_FLAG_XFER_DONE_ISSUED)
+    {
+        
+        /* TRACE2(iTwdCtrl.hReport, REPORT_SEVERITY_ERROR,  TIWLANWHA_MODULE_LOG, MSG_2262, "TxXferCb(): already called for this packet!!, DescID=%d, flags=%d, packetId=0x%x\n",pPktCtrlBlk->tTxDescriptor.descID, pPktCtrlBlk->tTxPktParams.uFlagsiPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]); */        
+    }
+    else /* TxXferCB called for the first time. call UMAC */
+    {
+        pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_XFER_DONE_ISSUED;
+        
+        AlignTxSecurityForUMAC ();
+
+        TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "TxXferCb(): call WhaCb()->SendPacketTransfer, descID= %d\n", pPktCtrlBlk->tTxDescriptor.descID);
+        TRACE1(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "TxXferCb(): call WhaCb()->SendPacketTransfer, PacketID= %d\n", iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]);
+       
+        if( bErrorIndication == TI_FALSE)
+        {    
+            WhaCb()->SendPacketTransfer ((WHA::TPacketId)iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]);
+        }
+        #if TI_DBG
+            else
+            {
+                WLAN_OS_REPORT(("%s : CommandResponse Block call to LDD response \n",__FUNCTION__));
+            }
+        #endif	
+    }
+}
+
+/** 
+ * \fn     TxCompleteCb
+ * \brief      Called upon Tx-complete of transmitted packet.
+ *    Handles it as follows:
+ *    1) Update the HwQueue to free queue resources.
+ *    2) Call the upper driver's tx-complete handler.
+ *    3) Free the packet's Control-Block if Xfer-Done already occured.
+ *
+ * \note    
+ * \return  
+ * \sa      
+ */ 
+void TIWha::TxCompleteCb ( TxResultDescriptor_t *pTxResultInfo, TI_UINT32 backpressure)
+{
+    /* Get the packet's control block pointer by the descId index. */
+    TTxCtrlBlk *pPktCtrlBlk = TWD_txCtrlBlk_GetPointer(iTwdCtrl.hTWD, pTxResultInfo->descID);
+    WHA::TStatus status;
+    
+    TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "TxCompleteCb(): DescID=%d, flags=%d, packetId=0x%x\n", 
+        pTxResultInfo->descID, pPktCtrlBlk->tTxPktParams.uFlags, 
+        iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]);
+
+#ifdef TI_DBG
+    /* If the pointed entry is already free, print error and exit (not expected to happen). */
+    if (pPktCtrlBlk->pNextFreeEntry != NULL)
+    {
+       TRACE3(iTwdCtrl.hReport, REPORT_SEVERITY_INFORMATION, "TxCompleteCb(): Pkt already free!!, DescID=%d, flags=%d, packetId=0x%x\n", 
+            pPktCtrlBlk->tTxDescriptor.descID, pPktCtrlBlk->tTxPktParams.uFlags, 
+            iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID]);
+       
+        return;
+    }
+#endif
+
+
+    /* Check if TxXferCb was called for this packet */
+    if ((pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_XFER_DONE_ISSUED) == 0)
+    {
+        /* Xfer was not  called, so call it here. Note that once TxComplete was called, there will be no TxXfer */
+        TxXferCb (pPktCtrlBlk);
+    }
+
+    /* We return Success on every tx result because of stange behaviour in the upper layer */
+    /* It seems that on results other than success the OS closes the socket */
+    switch (pTxResultInfo->status)
+    {
+        case TX_SUCCESS:
+            status = WHA::KSuccess;
+            break;
+        case TX_RETRY_EXCEEDED:
+            status = WHA::KErrorRetryExceeded;
+            WLAN_OS_REPORT(("ERROR: TxCompletewith status = %d",pTxResultInfo->status));
+            break;
+        case TX_TIMEOUT:
+            status = WHA::KErrorLifetimeExceeded;
+            WLAN_OS_REPORT(("ERROR: TxCompletewith status = %d",pTxResultInfo->status));
+            break;
+        case TX_PEER_NOT_FOUND:
+            status = WHA::KErrorNoLink;
+            WLAN_OS_REPORT(("ERROR: TxCompletewith status = %d",pTxResultInfo->status));
+            break;
+        case TX_DISABLED:
+            status = WHA::KErrorMacNotResponding;
+            WLAN_OS_REPORT(("ERROR: TxCompletewith status = %d",pTxResultInfo->status));
+            break;
+        default:
+            status = WHA::KFailed;
+            WLAN_OS_REPORT(("ERROR: TxCompletewith status = %d",pTxResultInfo->status));
+            break;
+    }
+
+    /* Call the UMAC tx-complete handler */
+    if( bErrorIndication == TI_FALSE)
+    {    
+        WhaCb()->SendPacketComplete(     status,
+								(WHA::TPacketId)iPacketIdTable[pPktCtrlBlk->tTxDescriptor.descID],
+								TIWhaUtils::PolicyToWhaRate ((ETxRateClassId)pTxResultInfo->rate),
+								pTxResultInfo->mediumDelay, /* aPacketQueueDelay */
+								pTxResultInfo->fwHandlingTime, /* aMediaDelay */
+			 					pTxResultInfo->ackFailures);
+    }
+    #if TI_DBG
+        else
+        {
+            WLAN_OS_REPORT(("%s : CommandResponse Block call to LDD response \n",__FUNCTION__));
+        }
+    #endif	
+
+    /* Free Ctrl block. */
+    TWD_txCtrlBlk_Free(iTwdCtrl.hTWD, pPktCtrlBlk);
+}
+
+