1/*
2 * txCtrlBlk.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *  * Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  * Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *  * Neither the name Texas Instruments nor the names of its
18 *    contributors may be used to endorse or promote products derived
19 *    from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35/****************************************************************************
36 *
37 *   MODULE:  txCtrlBlk.c
38 *
39 *   PURPOSE: Maintains active packets Tx attributes table (including descriptor).
40 *
41 *	 DESCRIPTION:
42 *   ============
43 *		This module allocates and frees table entry for each packet in the Tx
44 *		process (from sendPkt by upper driver until Tx-complete).
45 *
46 ****************************************************************************/
47#define __FILE_ID__  FILE_ID_99
48#include "osApi.h"
49#include "tidef.h"
50#include "report.h"
51#include "context.h"
52#include "TWDriver.h"
53#include "txCtrlBlk_api.h"
54
55
56/* The TxCtrlBlk module object - contains the control-block table. */
57typedef struct
58{
59	TI_HANDLE   hOs;
60	TI_HANDLE   hReport;
61	TI_HANDLE   hContext;
62
63	TTxCtrlBlk  aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM]; /* The table of control-block entries. */
64
65#ifdef TI_DBG  /* Just for debug. */
66	TI_UINT32	uNumUsedEntries;
67#endif
68
69} TTxCtrlBlkObj;
70
71
72/****************************************************************************
73 *                      txCtrlBlk_Create()
74 ****************************************************************************
75 * DESCRIPTION:	Create the Tx control block table object
76 *
77 * INPUTS:	hOs
78 *
79 * OUTPUT:	None
80 *
81 * RETURNS:	The Created object
82 ****************************************************************************/
83TI_HANDLE txCtrlBlk_Create (TI_HANDLE hOs)
84{
85	TTxCtrlBlkObj *pTxCtrlBlk;
86
87	pTxCtrlBlk = os_memoryAlloc (hOs, sizeof(TTxCtrlBlkObj));
88	if (pTxCtrlBlk == NULL)
89		return NULL;
90
91	os_memoryZero (hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
92
93	pTxCtrlBlk->hOs = hOs;
94
95	return( (TI_HANDLE)pTxCtrlBlk );
96}
97
98
99/****************************************************************************
100 *                      txCtrlBlk_Destroy()
101 ****************************************************************************
102 * DESCRIPTION:	Destroy the Tx control block table object
103 *
104 * INPUTS:	hTxCtrlBlk - The object to free
105 *
106 * OUTPUT:	None
107 *
108 * RETURNS:	TI_OK or TI_NOK
109 ****************************************************************************/
110TI_STATUS txCtrlBlk_Destroy (TI_HANDLE hTxCtrlBlk)
111{
112	TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
113
114	if (pTxCtrlBlk)
115		os_memoryFree(pTxCtrlBlk->hOs, pTxCtrlBlk, sizeof(TTxCtrlBlkObj));
116
117	return TI_OK;
118}
119
120
121/****************************************************************************
122 *               txCtrlBlk_Init()
123 ****************************************************************************
124   DESCRIPTION:	 Initialize the Tx control block module.
125 ****************************************************************************/
126TI_STATUS txCtrlBlk_Init (TI_HANDLE hTxCtrlBlk, TI_HANDLE hReport, TI_HANDLE hContext)
127{
128	TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
129	TI_UINT8 entry;
130
131	pTxCtrlBlk->hReport  = hReport;
132	pTxCtrlBlk->hContext = hContext;
133
134	/* For all entries, write the entry index in the descriptor and the next entry address
135		 in the next free entery pointer. Init also some other fields. */
136	for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
137	{
138		pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID = entry;
139		pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry       = &(pTxCtrlBlk->aTxCtrlBlkTbl[entry + 1]);
140		pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.aid    = 1;  /* The value for infrastructure BSS */
141		pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.reserved  = 0;
142	}
143
144	/* Write null in the next-free index of the last entry. */
145	pTxCtrlBlk->aTxCtrlBlkTbl[CTRL_BLK_ENTRIES_NUM - 1].pNextFreeEntry = NULL;
146
147  #ifdef TI_DBG
148	pTxCtrlBlk->uNumUsedEntries = 0;
149  #endif
150
151	return TI_OK;
152}
153
154
155/****************************************************************************
156 *					txCtrlBlk_Alloc()
157 ****************************************************************************
158 * DESCRIPTION:
159	Allocate a free control-block entry for the current Tx packet's parameters
160	  (including the descriptor structure).
161	Note that entry 0 in the list is never allocated and points to the
162	  first free entry.
163 ****************************************************************************/
164TTxCtrlBlk *txCtrlBlk_Alloc (TI_HANDLE hTxCtrlBlk)
165{
166	TTxCtrlBlkObj   *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
167	TTxCtrlBlk      *pCurrentEntry; /* The pointer of the new entry allocated for the packet. */
168	TTxCtrlBlk      *pFirstFreeEntry; /* The first entry just points to the first free entry. */
169
170	pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
171
172    /* Protect block allocation from preemption (may be called from external context) */
173    context_EnterCriticalSection (pTxCtrlBlk->hContext);
174
175    pCurrentEntry = pFirstFreeEntry->pNextFreeEntry; /* Get free entry. */
176
177#ifdef TI_DBG
178	/* If no free entries, print error (not expected to happen) and return NULL. */
179	if (pCurrentEntry->pNextFreeEntry == NULL)
180	{
181TRACE1(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_alloc():  No free entry,  UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries);
182        context_LeaveCriticalSection (pTxCtrlBlk->hContext);
183		return NULL;
184	}
185	pTxCtrlBlk->uNumUsedEntries++;
186#endif
187
188	/* Link the first entry to the next free entry. */
189	pFirstFreeEntry->pNextFreeEntry = pCurrentEntry->pNextFreeEntry;
190
191    context_LeaveCriticalSection (pTxCtrlBlk->hContext);
192
193	/* Clear the next-free-entry index just as an indication that our entry is not free. */
194	pCurrentEntry->pNextFreeEntry = 0;
195
196    pCurrentEntry->tTxPktParams.uFlags = 0;
197    pCurrentEntry->tTxPktParams.uHeadroomSize = 0;
198
199	return pCurrentEntry;
200}
201
202
203/****************************************************************************
204 *					txCtrlBlk_Free()
205 ****************************************************************************
206 * DESCRIPTION:
207	Link the freed entry after entry 0, so now it is the first free entry to
208	  be allocated.
209 ****************************************************************************/
210void txCtrlBlk_Free (TI_HANDLE hTxCtrlBlk, TTxCtrlBlk *pCurrentEntry)
211{
212	TTxCtrlBlkObj   *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
213	TTxCtrlBlk *pFirstFreeEntry = &(pTxCtrlBlk->aTxCtrlBlkTbl[0]);
214
215	if (!pTxCtrlBlk) {
216		return;
217	}
218
219#ifdef TI_DBG
220	/* If the pointed entry is already free, print error and exit (not expected to happen). */
221	if (pCurrentEntry->pNextFreeEntry != 0)
222	{
223		TRACE2(pTxCtrlBlk->hReport, REPORT_SEVERITY_ERROR, "txCtrlBlk_free(): Entry %d alredy free, UsedEntries=%d\n", 			pCurrentEntry->tTxDescriptor.descID, pTxCtrlBlk->uNumUsedEntries);
224		return;
225	}
226	pTxCtrlBlk->uNumUsedEntries--;
227#endif
228
229	/* Protect block freeing from preemption (may be called from external context) */
230	context_EnterCriticalSection (pTxCtrlBlk->hContext);
231
232	/* Link the freed entry between entry 0 and the next free entry. */
233	pCurrentEntry->pNextFreeEntry   = pFirstFreeEntry->pNextFreeEntry;
234	pFirstFreeEntry->pNextFreeEntry = pCurrentEntry;
235
236	context_LeaveCriticalSection (pTxCtrlBlk->hContext);
237}
238
239
240/****************************************************************************
241 *					txCtrlBlk_GetPointer()
242 ****************************************************************************
243 * DESCRIPTION:
244	Return a pointer to the control block entry of the requested packet.
245	Used upon tx-complete to retrieve info after getting the descId from the FW.
246 ****************************************************************************/
247TTxCtrlBlk *txCtrlBlk_GetPointer (TI_HANDLE hTxCtrlBlk, TI_UINT8 descId)
248{
249	TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
250	return ( &(pTxCtrlBlk->aTxCtrlBlkTbl[descId]) );
251}
252
253
254/****************************************************************************
255 *                      txCtrlBlk_PrintTable()
256 ****************************************************************************
257 * DESCRIPTION:	 Print the txCtrlBlk table main fields.
258 ****************************************************************************/
259#ifdef TI_DBG
260void txCtrlBlk_PrintTable (TI_HANDLE hTxCtrlBlk)
261{
262#ifdef REPORT_LOG
263	TTxCtrlBlkObj *pTxCtrlBlk = (TTxCtrlBlkObj *)hTxCtrlBlk;
264	TI_UINT8 entry;
265
266	WLAN_OS_REPORT((" Tx-Control-Block Information,  UsedEntries=%d\n", pTxCtrlBlk->uNumUsedEntries));
267	WLAN_OS_REPORT(("==============================================\n"));
268
269	for(entry = 0; entry < CTRL_BLK_ENTRIES_NUM; entry++)
270	{
271		WLAN_OS_REPORT(("Entry %d: DescID=%d, Next=0x%x, Len=%d, StartTime=%d, TID=%d, ExtraBlks=%d, TotalBlks=%d, Flags=0x%x\n",
272			entry,
273			pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.descID,
274			pTxCtrlBlk->aTxCtrlBlkTbl[entry].pNextFreeEntry,
275			ENDIAN_HANDLE_WORD(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.length),
276			ENDIAN_HANDLE_LONG(pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.startTime),
277            pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.tid,
278			pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.extraMemBlks,
279            pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxDescriptor.totalMemBlks,
280            pTxCtrlBlk->aTxCtrlBlkTbl[entry].tTxPktParams.uFlags));
281	}
282#endif
283}
284#endif /* TI_DBG */
285
286