/*
* 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;
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;
}
/* 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 */