/* * txCtrlBlk.c * * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. * 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 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: txCtrlBlk.c * * PURPOSE: Maintains active packets Tx attributes table (including descriptor). * * DESCRIPTION: * ============ * This module allocates and frees table entry for each packet in the Tx * process (from sendPkt by upper driver until Tx-complete). * ****************************************************************************/ #define __FILE_ID__ FILE_ID_99 #include "osApi.h" #include "tidef.h" #include "report.h" #include "context.h" #include "TWDriver.h" #include "txCtrlBlk_api.h" /* The TxCtrlBlk module object - contains the control-block table. */ typedef struct { TI_HANDLE hOs; TI_HANDLE hReport; TI_HANDLE hContext; TTxCtrlBlk aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM]; /* The table of control-block entries. */ #ifdef TI_DBG /* Just for debug. */ TI_UINT32 uNumUsedEntries; #endif } TTxCtrlBlkObj; /**************************************************************************** * txCtrlBlk_Create() **************************************************************************** * DESCRIPTION: Create the Tx control block table object * * INPUTS: hOs * * OUTPUT: None * * RETURNS: The Created object ****************************************************************************/ TI_HANDLE txCtrlBlk_Create (TI_HANDLE hOs) { TTxCtrlBlkObj *pTxCtrlBlk; pTxCtrlBlk = os_memoryAlloc (hOs, sizeof(TTxCtrlBlkObj)); if (pTxCtrlBlk == NULL) return NULL; os_memoryZero (hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj)); pTxCtrlBlk->hOs = hOs; return( (TI_HANDLE)pTxCtrlBlk ); } /**************************************************************************** * txCtrlBlk_Destroy() **************************************************************************** * DESCRIPTION: Destroy the Tx control block table object * * INPUTS: hTxCtrlBlk - The object to free * * OUTPUT: None * * RETURNS: TI_OK or TI_NOK ****************************************************************************/ TI_STATUS txCtrlBlk_Destroy (TI_HANDLE hTxCtrlBlk) { TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; if (pTxCtrlBlk) os_memoryFree(pTxCtrlBlk->hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj)); return TI_OK; } /**************************************************************************** * txCtrlBlk_Init() **************************************************************************** DESCRIPTION: Initialize the Tx control block module. ****************************************************************************/ TI_STATUS txCtrlBlk_Init (TI_HANDLE hTxCtrlBlk, TI_HANDLE hReport, TI_HANDLE hContext) { TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; TTxnStruct *pTxn; TI_UINT8 entry; pTxCtrlBlk->hReport = hReport; pTxCtrlBlk->hContext = hContext; /* For all entries, write the entry index in the descriptor and the next entry address in the next free entery pointer. Init also some other fields. */ for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++) { pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID = entry; pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry + 1]); pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.aid = 1; /* The value for infrastructure BSS */ pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.reserved = 0; /* Prepare the Txn fields to the host-slave register (fixed address) */ pTxn = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxnStruct); TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_FIXED_ADDR) } /* Write null in the next-free index of the last entry. */ pTxCtrlBlk->aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM - 1].pNextFreeEntry = NULL; #ifdef TI_DBG pTxCtrlBlk->uNumUsedEntries = 0; #endif return TI_OK; } /**************************************************************************** * txCtrlBlk_Alloc() **************************************************************************** * DESCRIPTION: Allocate a free control-block entry for the current Tx packet's parameters (including the descriptor structure). Note that entry 0 in the list is never allocated and points to the first free entry. ****************************************************************************/ TTxCtrlBlk *txCtrlBlk_Alloc (TI_HANDLE hTxCtrlBlk) { TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; TTxCtrlBlk *pCurrentEntry; /* The pointer of the new entry allocated for the packet. */ TTxCtrlBlk *pFirstFreeEntry; /* The first entry just points to the first free entry. */ pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]); /* Protect block allocation from preemption (may be called from external context) */ context_EnterCriticalSection (pTxCtrlBlk->hContext); pCurrentEntry = pFirstFreeEntry->pNextFreeEntry; /* Get free entry. */ #ifdef TI_DBG /* If no free entries, print error (not expected to happen) and return NULL. */ if (pCurrentEntry->pNextFreeEntry == NULL) { TRACE1(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_alloc(): No free entry, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries); context_LeaveCriticalSection (pTxCtrlBlk->hContext); return NULL; } pTxCtrlBlk->uNumUsedEntries++; #endif /* Link the first entry to the next free entry. */ pFirstFreeEntry->pNextFreeEntry = pCurrentEntry->pNextFreeEntry; context_LeaveCriticalSection (pTxCtrlBlk->hContext); /* Clear the next-free-entry index just as an indication that our entry is not free. */ pCurrentEntry->pNextFreeEntry = 0; pCurrentEntry->tTxPktParams.uFlags = 0; pCurrentEntry->tTxPktParams.uHeadroomSize = 0; return pCurrentEntry; } /**************************************************************************** * txCtrlBlk_Free() **************************************************************************** * DESCRIPTION: Link the freed entry after entry 0, so now it is the first free entry to be allocated. ****************************************************************************/ void txCtrlBlk_Free (TI_HANDLE hTxCtrlBlk, TTxCtrlBlk *pCurrentEntry) { TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; TTxCtrlBlk *pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]); if (!pTxCtrlBlk) { return; } #ifdef TI_DBG /* If the pointed entry is already free, print error and exit (not expected to happen). */ if (pCurrentEntry->pNextFreeEntry != 0) { TRACE2(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_free(): Entry %d alredy free, UsedEntries=%d\n", pCurrentEntry->tTxDescriptor.descID, pTxCtrlBlk->uNumUsedEntries); return; } pTxCtrlBlk->uNumUsedEntries--; #endif /* Protect block freeing from preemption (may be called from external context) */ context_EnterCriticalSection (pTxCtrlBlk->hContext); /* Link the freed entry between entry 0 and the next free entry. */ pCurrentEntry->pNextFreeEntry = pFirstFreeEntry->pNextFreeEntry; pFirstFreeEntry->pNextFreeEntry = pCurrentEntry; context_LeaveCriticalSection (pTxCtrlBlk->hContext); } /**************************************************************************** * txCtrlBlk_GetPointer() **************************************************************************** * DESCRIPTION: Return a pointer to the control block entry of the requested packet. Used upon tx-complete to retrieve info after getting the descId from the FW. ****************************************************************************/ TTxCtrlBlk *txCtrlBlk_GetPointer (TI_HANDLE hTxCtrlBlk, TI_UINT8 descId) { TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; return ( &(pTxCtrlBlk->aTxCtrlBlkTbl[descId]) ); } /**************************************************************************** * txCtrlBlk_PrintTable() **************************************************************************** * DESCRIPTION: Print the txCtrlBlk table main fields. ****************************************************************************/ #ifdef TI_DBG void txCtrlBlk_PrintTable (TI_HANDLE hTxCtrlBlk) { #ifdef REPORT_LOG TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk; TI_UINT8 entry; WLAN_OS_REPORT((" Tx-Control-Block Information, UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries)); WLAN_OS_REPORT(("==============================================\n")); for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++) { WLAN_OS_REPORT(("Entry %d: DescID=%d, Next=0x%x, Len=%d, StartTime=%d, TID=%d, ExtraBlks=%d, TotalBlks=%d, Flags=0x%x\n", entry, pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID, pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry, ENDIAN_HANDLE_WORD(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.length), ENDIAN_HANDLE_LONG(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.startTime), pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.tid, pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.extraMemBlks, pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.totalMemBlks, pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxPktParams.uFlags)); } #endif } #endif /* TI_DBG */