1/****************************************************************************
2**+-----------------------------------------------------------------------+**
3**|                                                                       |**
4**| Copyright(c) 1998 - 2008 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/*																		   */
38/*		MODULE:													   */
39/*		PURPOSE:		 						   */
40/*																		   */
41/***************************************************************************/
42#include "fourX.h"
43#include "report.h"
44#include "osApi.h"
45#include "utils.h"
46#include "802_11Defs.h"
47
48
49static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr);
50
51static TI_STATUS fourX_MakeConcatDecision(fourX_t*				pFourX,
52										   MsduList_t*			pMsduList,
53										   hwTxInformation_t*	pHwTxInformation,
54										   UINT32					numOfReadyMsdu,
55										   UINT16*				concatFlags,
56                                           UINT32*              numOfMsduToConcat);
57
58static TI_STATUS fourX_prepareMsduListToConcat(fourX_t*		pFourX,
59											   mem_MSDU_T**	returnMsduPtr,
60											   MsduList_t*  pMsduList,
61                                               UINT32       maxNumMsduToConcat);
62
63
64/*************************************************************************
65*                        concat_create                                 *
66**************************************************************************
67* DESCRIPTION:	This function initializes the Ctrl data module.
68*
69* INPUT:		hOs - handle to Os Abstraction Layer
70*
71* OUTPUT:		TxCmplt_CB - call back function that return to configMngr
72*				in order to register in the Hal
73*
74* RETURN:		Handle to the allocated Ctrl data control block
75************************************************************************/
76
77fourX_t* fourX_create(TI_HANDLE hOs)
78{
79	fourX_t*			pFourX;
80	deConcatenator_t*	pDeConcatenator;
81	concatenator_t*		pConcatenator;
82	ackEmul_t*			pAckEmul;
83
84
85	if( hOs  == NULL )
86	{
87	    WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): OS handle Error - Aborting\n"));
88		return NULL;
89	}
90
91	/* alocate concatenator block */
92	pFourX = os_memoryAlloc(hOs, (sizeof(fourX_t)));
93
94	/* create 4x sub moduls */
95	pConcatenator = concat_create(hOs);
96	pDeConcatenator = deConcat_create(hOs);
97	pAckEmul = ackEmul_create(hOs);
98
99
100	if ( (!pFourX) || (!pConcatenator) || (!pDeConcatenator) || (!pAckEmul))
101	{
102		utils_nullMemoryFree(hOs, pDeConcatenator, sizeof(deConcatenator_t));
103		utils_nullMemoryFree(hOs, pConcatenator, sizeof(concatenator_t));
104		utils_nullMemoryFree(hOs, pAckEmul, sizeof(ackEmul_t));
105		utils_nullMemoryFree(hOs, pFourX, sizeof(fourX_t));
106	    WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): Error Creating fourX module- Aborting\n"));
107		return(NULL);
108	}
109
110	/* reset control module control block */
111	os_memoryZero(hOs, pFourX, (sizeof(fourX_t)));
112
113	pFourX->pConcatenator = pConcatenator;
114	pFourX->pDeConcatenator = pDeConcatenator;
115	pFourX->pAckEmul = pAckEmul;
116
117	pFourX->hOs = hOs;
118
119	return(pFourX);
120}
121
122/***************************************************************************
123*							ctrlData_config				                   *
124****************************************************************************
125* DESCRIPTION:	This function configures the Ctrl Data module
126*
127* INPUTS:		hCtrlData - The object
128*				hOs - Handle to the Os Abstraction Layer
129*				hReport - Handle to the Report object
130* 				ctrlDataInitParams - pointer to Ctrl module init parameters
131* OUTPUT:
132*
133* RETURNS:		OK - Configuration succesfull
134*				NOK - Configuration unsuccesfull
135***************************************************************************/
136TI_STATUS fourX_config(fourX_t*				pFourX,
137					   TI_HANDLE			hOs,
138					   TI_HANDLE			hReport,
139					   TI_HANDLE			hMemMngr,
140					   TI_HANDLE			hWhalCtrl,
141					   TI_HANDLE			hTxData,
142					   fourXInitParams_t*	fourXInitParams)
143{
144	/* check parameters validity */
145	if( (pFourX == NULL) || (hOs == NULL) || (hReport == NULL) ||
146		(hMemMngr == NULL) || (hWhalCtrl == NULL) || (hTxData == NULL))
147	{
148	    WLAN_OS_REPORT(("FATAL ERROR: fourX_config(): Parameters Error - Aborting\n"));
149		return NOK;
150	}
151
152	/* set objects handles */
153	pFourX->hOs = hOs;
154	pFourX->hReport = hReport;
155	pFourX->hMemMngr = hMemMngr;
156	pFourX->hWhalCtrl = hWhalCtrl;
157	pFourX->hTxData = hTxData;
158
159	/* configure 4x parameters - TODO USE fourXInitParams */
160	pFourX->desiredConcatenationEnable = DESIRED_CONCATENATION_ENABLE_DEF;
161	pFourX->desiredCWMinEnable = DESIRED_CWMIN_ENABLE_DEF;
162	pFourX->desiredCWComboEnable = DESIRED_CWCOMBO_ENABLE_DEF;
163	pFourX->desiredAckEmulationEnable = DESIRED_ACKEMULATION_ENABLE_DEF;
164	pFourX->desiredERP_ProtectionEnable = DESIRED_ERP_PROTECTION_ENABLE_DEF;
165	pFourX->desiredMaxConcatSize = MAX_CONCAT_SIZE_DEF;
166	pFourX->desiredCWMin = CW_MIN_DEF;
167	pFourX->desiredCWMax = CW_MAX_DEF;
168
169
170	/* configure 4x sub modules */
171	concat_config(pFourX->pConcatenator, hOs, hReport, hMemMngr);
172	deConcat_config(pFourX->pDeConcatenator, hOs, hReport, hMemMngr);
173	ackEmul_config(pFourX->pAckEmul,hWhalCtrl,hOs,hReport,hMemMngr);
174
175
176	WLAN_REPORT_INIT(pFourX->hReport, FOUR_X_MODULE_LOG,
177		(".....fouorX configured successfully\n"));
178
179	return OK;
180}
181
182/***************************************************************************
183*							ctrlData_unLoad				                   *
184****************************************************************************
185* DESCRIPTION:	This function unload the Ctrl data module.
186*
187* INPUTS:		hCtrlData - the object
188*
189* OUTPUT:
190*
191* RETURNS:		OK - Unload succesfull
192*				NOK - Unload unsuccesfull
193***************************************************************************/
194
195TI_STATUS fourX_destroy(fourX_t* pFourX)
196{
197	concat_destroy(pFourX->pConcatenator);
198	deConcat_destroy(pFourX->pDeConcatenator);
199	ackEmul_destroy(pFourX->pAckEmul);
200
201	/* free control module controll block */
202	os_memoryFree(pFourX->hOs, pFourX, sizeof(fourX_t));
203
204	return OK;
205}
206
207
208static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr)
209{
210    dot114xMsdu_t*	pdot114xHeader;
211	UINT8			tiSnapDataArray[8] = {0xAA,0xAA,0x03,0x08,0x00,0x28,0x60,0xD0};
212
213	/* Check frame len validity */
214	if(msduPtr->dataLen < sizeof(dot114xMsdu_t))
215		return NOT_4X_MSDU;
216
217    pdot114xHeader = (dot114xMsdu_t*)memMgr_BufData(msduPtr->firstBDPtr);
218
219    /*
220       Verify a TI SNAP header.
221    */
222    if( os_memoryCompare(pFourX->hOs,
223						 (void*)&(pdot114xHeader->msduHeader.snapHeader),
224						 tiSnapDataArray,
225						 sizeof(Wlan_LlcHeader_T)) != 0)
226	{
227		return NOT_4X_MSDU;
228	}
229
230    switch (pdot114xHeader->header4x.type)
231	{
232
233    case CONCATENATION :
234        return CONCATENATION;
235/*		break; - unreachable*/
236
237    case MANAGMENT_4X :
238        return MANAGMENT_4X;
239/*		break; - unreachable*/
240
241    default:
242		return NOT_4X_MSDU;
243/*		break; - unreachable*/
244
245    }
246}
247
248TI_STATUS fourX_rxMsdu(fourX_t*	pFourX, mem_MSDU_T**	rxMsduPtr)
249{
250    Wlan4XType_t	type4xMsdu;
251	mem_MSDU_T*		currMsduPtr;
252
253	type4xMsdu = fourX_parseRxFrame(pFourX, *rxMsduPtr);
254
255	switch (type4xMsdu)
256	{
257		case CONCATENATION :
258		   /*
259			* Deconcatenate Msdu
260			*/
261            WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
262			        (" Received Concat msdu \n"));
263			if(deConcat_deConcatMsdu(pFourX->pDeConcatenator, rxMsduPtr) != OK)
264			{
265		        WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
266			        (" Failed to deconcat packet \n"));
267
268				return NOK;
269			}
270			break;
271
272		case MANAGMENT_4X :
273			break;
274
275		default:
276			break;
277
278    }
279
280	if(pFourX->ackEmulationEnable)
281	{
282		/* call ack emulation for each packet */
283		currMsduPtr = *rxMsduPtr;
284		while(currMsduPtr)
285		{
286			wdrv_ackEmulationRxPacket(pFourX->pAckEmul, currMsduPtr);
287			currMsduPtr = currMsduPtr->nextMSDUinList;
288		}
289	}
290	return OK;
291
292}
293
294#define NUM_MSDU_TO_COPY 8
295
296/***************************************************************************
297*							fourX_CopyReplace
298****************************************************************************
299* DESCRIPTION:	This function copy OS data blocks to local data blocks
300*				in the MSDU in order to release OS resources and to enable
301*				high stream of data from the OS
302*
303* INPUTS:
304*
305* OUTPUT:
306*
307* RETURNS:
308***************************************************************************/
309TI_STATUS fourX_CopyReplace(fourX_t* pFourX, mem_MSDU_T **pMsdu, MsduList_t *pMsduList, mem_MSDU_T **pNewMsdu)
310{
311	mem_MSDU_T		*pOrigMsdu;
312
313	pOrigMsdu = (*pMsdu);
314
315	/*
316	 * The copy is to new msdu pointed by pMsdu
317	 */
318	if(txData_copyPacketToMsdu(pFourX->hTxData, pMsdu, 0 /* dont FreeOldMsdu */) != OK)
319	{
320		/* no msdu to transmit */
321		WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
322			(" fourX_CopyReplace() : txData_copyPacketToMsdu FAILED  \n"));
323
324		return NOK;
325	}
326
327	/*
328	 * Still use the old Msdu with its pointers, so swap the BDs of the new and the orig Msdu
329	 */
330	wlan_memMngrSwapMsdu(pFourX->hMemMngr, pOrigMsdu, (*pMsdu));
331
332	/* return the new msdu to free later */
333	(*pNewMsdu) = (*pMsdu);
334	/* use the orig Msdu */
335	(*pMsdu) = pOrigMsdu;
336
337	return OK;
338}
339
340
341/***************************************************************************
342*							fourX_CopyOsData
343****************************************************************************
344* DESCRIPTION:	This function scan the Msdu list and copy OS data blocks to
345*				local data blocks .
346*				in the MSDU in order to release OS resources and to enable
347*				high stream of data from the OS
348*
349* INPUTS:
350*
351* OUTPUT:
352*
353* RETURNS:
354***************************************************************************/
355UINT32 fourX_CopyOsData(fourX_t* pFourX, MsduList_t *pMsduList)
356{
357	int NumMsduToCopy = 0;
358	mem_MSDU_T *pMsdu;
359	mem_MSDU_T *pNewMsdu=NULL;
360	mem_MSDU_T *pMsduFreeList=NULL;
361	mem_MSDU_T *pMsduFreeCurr=NULL;
362	mem_MSDU_T *pKeepNext=NULL;
363	int i;
364	int NumOfCopiedPackets=0;
365
366	os_protectLock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* START OF CRITICAL SECTION */
367
368	if (pMsduList->CurrNumOfMsdu == 0)
369	{
370		pFourX->counters.count6 = 0;
371		pFourX->counters.count7 = 0;
372		os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */
373		return 0;
374	}
375
376	/*
377	 * Find how many msdu to copy
378	 */
379	if (pMsduList->CurrNumOfMsdu <= NUM_MSDU_TO_COPY)
380		NumMsduToCopy = pMsduList->CurrNumOfMsdu;
381	else
382		NumMsduToCopy = NUM_MSDU_TO_COPY;
383
384	pMsdu=pMsduList->first;
385
386	/*
387	 * Start the copy
388	 */
389	for (i=0; (i<NumMsduToCopy) ; i++)
390	{
391		if (pMsdu == NULL)
392		{
393			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
394				(" fourX_CopyMsdu() : fourX_CopyReplace FAILED, pMsdu is NULL i=%d, Num=%d (Actual=%d) \n", i, NumMsduToCopy, pMsduList->CurrNumOfMsdu));
395
396			break;
397		}
398		/*
399		 * Already copied - skip it
400		 */
401		if (pMsdu->freeFunc == NULL)
402		{
403			pMsdu=pMsdu->nextMSDUinList;
404			NumOfCopiedPackets++;
405			continue;
406		}
407
408		WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
409			(" fourX_CopyMsdu() : i=%d, CopyReplace 0x%x\n", i , pMsdu));
410
411		/*
412		 * Copy and replace in the list
413		 */
414		if(fourX_CopyReplace(pFourX, &pMsdu, pMsduList, &pNewMsdu) != OK)
415		{
416			/* no msdu to transmit */
417			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
418				(" fourX_CopyMsdu() : fourX_CopyReplace FAILED  \n"));
419
420			break;
421		}
422
423		/*
424		 * Enter the new Msdu to the free list
425		 */
426		if (pMsduFreeList == NULL)
427		{
428			pMsduFreeList = pNewMsdu;
429		}
430		else
431		{
432			pMsduFreeCurr = pMsduFreeList;
433			while (pMsduFreeCurr->nextMSDUinList != NULL)
434				pMsduFreeCurr = pMsduFreeCurr->nextMSDUinList;
435			pMsduFreeCurr->nextMSDUinList = pNewMsdu;
436		}
437		pNewMsdu->nextMSDUinList = NULL;
438
439		/* copy the next msdu */
440		pMsdu=pMsdu->nextMSDUinList;
441		NumOfCopiedPackets++;
442	}
443
444	pFourX->counters.count6 = pMsduList->CurrNumOfMsdu;
445	pFourX->counters.count7 = i;
446
447	/* !!!! This is the right place for the unlock */
448	os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */
449
450	/*
451	 * free loop, do not call the free inside lock !!!
452	 */
453	pMsduFreeCurr = pMsduFreeList;
454	while (pMsduFreeCurr != NULL)
455	{
456		pKeepNext = pMsduFreeCurr->nextMSDUinList;
457
458		wlan_memMngrFreeMSDU(pFourX->hMemMngr, memMgr_MsduHandle(pMsduFreeCurr));
459
460		pMsduFreeCurr=pKeepNext;
461	}
462
463	return NumOfCopiedPackets;
464}
465
466
467
468TI_STATUS fourX_txMsduDeQueue(fourX_t*				pFourX,
469							  mem_MSDU_T**			returnMsduPtr,
470							  MsduList_t*			pMsduList,
471							  hwTxInformation_t*	pHwTxInformation)
472{
473	TI_STATUS		status;
474	mem_MSDU_T*		firstMsduPtr;
475	UINT16			concatFlags = 0;
476    UINT32          numOfMsduToConcat;
477	UINT32			numMsdu = 0;
478
479	*returnMsduPtr = NULL;
480
481
482#ifdef NO_COPY_NDIS_BUFFERS
483	/*
484	 * Scan the Msdu list and copy OS data blocks to local data blocks .
485	 * in the MSDU in order to release OS resources and to enable
486	 * high stream of data from the OS.
487	 */
488	numMsdu = fourX_CopyOsData(pFourX, pMsduList);
489	/* This function copied up to 8 or numOfMsdu in list packets from OS to Shared memory
490	 * As there is NDISfreeFunc after the copy, New un-copied packets can enter the msduList,
491	 * but the scheduler was blocked from entering the send again.
492	 */
493#else
494
495	if (pMsduList->CurrNumOfMsdu < NUM_MSDU_TO_COPY )
496		numMsdu = pMsduList->CurrNumOfMsdu;
497	else
498		numMsdu = NUM_MSDU_TO_COPY;
499#endif
500
501	/*if(pFourX->concatenationEnable != TRUE)*/
502	status = fourX_MakeConcatDecision(pFourX,pMsduList,pHwTxInformation,numMsdu,
503                                       &concatFlags,&numOfMsduToConcat);
504
505
506	switch(status)
507	{
508	case MAKE_CONCATENATION:
509
510	   /*
511		* Make Concatenation
512		*/
513
514		fourX_prepareMsduListToConcat(pFourX,
515									  &firstMsduPtr,
516									  pMsduList,
517                                      numOfMsduToConcat);
518
519		if(firstMsduPtr == NULL)
520			return NOK;
521
522
523		return concat_concatMsduList(pFourX->pConcatenator,
524							  firstMsduPtr,
525							  returnMsduPtr,
526							  concatFlags);
527
528
529	case SEND_ONE_MSDU:
530
531	   /*
532		* Send Only One Msdu
533		*/
534
535		if((msduList_GetFirst( pMsduList, returnMsduPtr )) != OK)
536		{
537			/* msdu list is empty - should never reach here */
538			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
539				(" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n"));
540
541			return NOK;
542		}
543
544		return OK;
545
546	case DO_NOT_SEND_MSDU:
547
548	   /*
549		* Don't Send any Msdu
550		*/
551
552		return NOK;
553
554	default:
555		break;
556
557	}
558	return OK;
559}
560
561TI_STATUS fourX_txMsduBeforInsertToQueue(fourX_t* pFourX,
562										 mem_MSDU_T** msduPtr)
563{
564/* no ACK emulation !!!!!!!!!!!!!!!!!! */
565#if 0
566	UINT32 discardPacket;
567	if(pFourX->ackEmulationEnable)
568	{
569		wdrv_ackEmulationTxPacket(pFourX->pAckEmul, *msduPtr, &discardPacket);
570		if (discardPacket == TRUE)
571		{
572			wlan_memMngrFreeMSDU(pFourX->hMemMngr, (*msduPtr)->handle);
573			(*msduPtr) = NULL;
574			return OK;
575		}
576	}
577#endif
578	return OK;
579}
580
581static TI_STATUS fourX_prepareMsduListToConcat(fourX_t*		pFourX,
582											   mem_MSDU_T**	returnMsduPtr,
583											   MsduList_t*	pMsduList,
584                                               UINT32       maxNumMsduToConcat)
585{
586	mem_MSDU_T*		currentMsduPtr;
587	mem_MSDU_T*		PrevMsduPtr=NULL;
588	UINT32			totalLen = 0;
589	BOOL			firsdMsduInList = TRUE;
590	UINT32			numOfMsdu = 0;
591
592
593	*returnMsduPtr = NULL;
594
595	while(maxNumMsduToConcat--)
596	{
597		/* prepare a link list of msdu in the concatenator format */
598		if((msduList_WatchFirst( pMsduList, &currentMsduPtr )) != OK)
599		{
600			/* msdu list is empty - can return now */
601			WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG,
602				(" fourX_txMsduDeQueue: msduList_WatchFirst() : No Msdu to watch \n"));
603			break;
604		}
605		totalLen += currentMsduPtr->dataLen;
606
607		if(totalLen > 4032/*pFourX->currentMaxConcatSize*/)
608			break;
609
610		if((msduList_GetFirst( pMsduList, &currentMsduPtr )) != OK)
611		{
612			/* msdu list is empty - should never reach here */
613			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
614				(" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n"));
615			break;
616		}
617
618		/* In this phase, the free func should be NULL !!!!!!!!!!! */
619		if (currentMsduPtr->freeFunc)
620		{
621			WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG,
622				(" fourX_txMsduDeQueue:msduList_GetFirst() : fourX_prepareMsduListToConcat, free funct is not NULL !!!!!!!\n"));
623		}
624
625		numOfMsdu++;
626
627		if(firsdMsduInList == TRUE)
628		{
629			*returnMsduPtr = currentMsduPtr;
630			firsdMsduInList = FALSE;
631		}
632		else
633		{
634			PrevMsduPtr->nextMSDUinList = currentMsduPtr;
635		}
636
637		PrevMsduPtr = currentMsduPtr;
638	}
639
640	return OK;
641}
642
643static TI_STATUS fourX_MakeConcatDecision(fourX_t*				pFourX,
644										   MsduList_t*			pMsduList,
645										   hwTxInformation_t*	pHwTxInformation,
646										   UINT32					numOfReadyMsdu,
647										   UINT16*				concatFlags,
648                                           UINT32*              numOfMsduToConcat)
649{
650	memMgrResources_t memMgrResources;
651
652#ifdef TNETW_MASTER_MODE
653	UINT32 limitResourcees;
654#endif
655
656	*numOfMsduToConcat = 0;
657
658	/* get MemoryMgr resources for concatenation */
659	wlan_memMngrGetMemMgrResources(pFourX->hMemMngr, &memMgrResources);
660
661#ifdef TNETW_MASTER_MODE
662	limitResourcees = MIN(memMgrResources.numOfFreeBufPool2 ,(MIN(memMgrResources.numOfFreeBufPool1-1 , pHwTxInformation->hwNumOfFreeBDs)));
663
664
665
666	/* No free space in HW to send */
667    if( (pHwTxInformation->hwNumOfFreeMsdu == 0) || (limitResourcees < 2) )
668    {
669        pFourX->counters.count1++;
670        return DO_NOT_SEND_MSDU;
671	}
672
673    /*
674	 * Phase 1: At least 3 waiting msdu for concat (and enough space in HW)
675	 * --------------------------------------------------------------------
676	 * In case there are 2 msdu the decision will be later
677     * We have resources to send, decide if to concat, send single or wait.
678     */
679    if(  numOfReadyMsdu >= 3 )
680    {
681        pFourX->counters.count2++;
682        /* We have enough msdus to concat. */
683		*concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
684
685		/* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */
686		if (limitResourcees < 5)
687			return DO_NOT_SEND_MSDU;
688
689		/* minimum 2 bd for each msdu and one for cocat header */
690		*numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu);
691
692		/* minimum 2 msdu to concat */
693		if (*numOfMsduToConcat < 2)
694			return SEND_ONE_MSDU;
695
696		return MAKE_CONCATENATION;
697    }
698
699
700	/*
701	 * Phase 2: Less than 3 waiting msdu, and the HW already has Msdu to send
702	 * ----------------------------------------------------------------------
703	 * It is allowed to delay the msdu and continue queueing more MSDU
704	 */
705	if(pHwTxInformation->hwNumOfBusyMsdu > 1)
706	{
707        pFourX->counters.count3++;
708	   /*
709		* ACX has enough packets to send, delay the current sending.
710		*/
711		return DO_NOT_SEND_MSDU;
712	}
713
714	/*
715	 * Phase 3: Less than 3 waiting msdu, and the HW is free to send
716	 * -------------------------------------------------------------
717	 * It is NOT allowed to delay the msdu, so send it
718	 */
719    else
720    {
721	   /*
722		* Phase 4: There are 2 msdu to concat and the HW is free to send
723		* --------------------------------------------------------------
724        */
725        if(  numOfReadyMsdu > 1 )
726		{
727            pFourX->counters.count4++;
728            /* We have enough msdus to concat. */
729            *concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
730
731			/* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */
732			if (limitResourcees < 5)
733				return DO_NOT_SEND_MSDU;
734
735			/* minimum 2 bd for each msdu and one for cocat header */
736			*numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu);
737
738			/* minimum 2 msdu to concat */
739			if (*numOfMsduToConcat < 2)
740				return SEND_ONE_MSDU;
741
742	         return MAKE_CONCATENATION;
743        }
744	   /*
745		* Phase 5: There are only one msdu to send, send it (no concatination)
746		* --------------------------------------------------------------------
747		*/
748        else
749        {
750            pFourX->counters.count5++;
751			/*
752			 * There space in HW and only one MSDU to send, send it as single.
753			 */
754            return SEND_ONE_MSDU;
755        }
756    }
757
758
759#else /* SLAVE_MODE */
760		if((pHwTxInformation->hwTotalAvailMem > 4095) && (numOfReadyMsdu > 1))
761			{
762				*concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT;
763				return MAKE_CONCATENATION;
764			}
765		else
766        {
767			if(pHwTxInformation->hwTotalAvailMem > pMsduList->first->dataLen)
768				return SEND_ONE_MSDU;
769			else
770				return DO_NOT_SEND_MSDU;
771        }
772
773#endif /* MASTER/SALVE modes */
774
775
776
777}
778
779
780/* debug functions */
781void fourX_printParams(fourX_t* pFourX)
782{
783
784	WLAN_OS_REPORT(("          FOUR X Parameters          \n"));
785	WLAN_OS_REPORT(("-------------------------------------\n"));
786
787	WLAN_OS_REPORT(("hOs                           = 0x%X\n",pFourX->hOs  ));
788	WLAN_OS_REPORT(("hReport                       = 0x%X\n",pFourX->hReport  ));
789	WLAN_OS_REPORT(("hMemMngr                      = 0x%X\n\n",pFourX->hMemMngr  ));
790
791	WLAN_OS_REPORT(("concatenationEnable           = %d\n",pFourX->concatenationEnable  ));
792	WLAN_OS_REPORT(("CWMinEnable                   = %d\n",pFourX->CWMinEnable  ));
793	WLAN_OS_REPORT(("CWComboEnable                 = %d\n",pFourX->CWComboEnable  ));
794	WLAN_OS_REPORT(("ackEmulationEnable            = %d\n",pFourX->ackEmulationEnable  ));
795	WLAN_OS_REPORT(("ERP_ProtectionEnable          = %d\n\n",pFourX->ERP_ProtectionEnable  ));
796
797	WLAN_OS_REPORT(("desiredConcatenationEnable    = %d\n",pFourX->desiredConcatenationEnable  ));
798	WLAN_OS_REPORT(("desiredCWMinEnable            = %d\n",pFourX->desiredCWMinEnable  ));
799	WLAN_OS_REPORT(("desiredCWComboEnable          = %d\n",pFourX->desiredCWComboEnable  ));
800	WLAN_OS_REPORT(("desiredAckEmulationEnable     = %d\n",pFourX->desiredAckEmulationEnable  ));
801	WLAN_OS_REPORT(("desiredERP_ProtectionEnable   = %d\n\n",pFourX->desiredERP_ProtectionEnable  ));
802
803	WLAN_OS_REPORT(("desiredMaxConcatSize          = %d\n",pFourX->desiredMaxConcatSize  ));
804	WLAN_OS_REPORT(("desiredCWMin                  = %d\n",pFourX->desiredCWMin  ));
805	WLAN_OS_REPORT(("desiredCWMax                  = %d\n\n",pFourX->desiredCWMax  ));
806
807
808	/* AP supported features */
809
810
811	/* 4x parameters */
812	WLAN_OS_REPORT(("currentMaxConcatSize          = %d\n",pFourX->currentMaxConcatSize  ));
813	WLAN_OS_REPORT(("currentCWMin                  = %d\n",pFourX->currentCWMin  ));
814	WLAN_OS_REPORT(("currentCWMax                  = %d\n\n",pFourX->currentCWMax  ));
815
816
817	WLAN_OS_REPORT(("ApFourX_Capabilities.fourXProtocolVersion        = %d\n", pFourX->ApFourX_Capabilities.fourXProtocolVersion));
818	WLAN_OS_REPORT(("-------------------------------------------------\n"));
819
820	WLAN_OS_REPORT(("AP_Cap.concatenationParams.enableDisable          = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.enableDisable));
821	WLAN_OS_REPORT(("AP_Cap.concatenationParams.concatenationSize      = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.concatenationSize));
822
823	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.enableDisable       = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.enableDisable));
824	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMin               = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMin));
825	WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMax               = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMax));
826
827	WLAN_OS_REPORT(("AP_Cap.CWCombParams.enableDisable                 = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.enableDisable));
828	WLAN_OS_REPORT(("AP_Cap.CWCombParams.DIFS                          = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.DIFS));
829	WLAN_OS_REPORT(("AP_Cap.CWCombParams.SLOT                          = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.SLOT));
830	WLAN_OS_REPORT(("AP_Cap.CWCombParams.CWMin                         = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.CWMin));
831
832	WLAN_OS_REPORT(("AP_Cap.ackEmulationParams.enableDisable           = %d\n", pFourX->ApFourX_Capabilities.ackEmulationParams.enableDisable));
833
834	WLAN_OS_REPORT(("AP_Cap.ERP_ProtectionParams.enableDisable         = %d\n", pFourX->ApFourX_Capabilities.ERP_ProtectionParams.enableDisable));
835
836   	WLAN_OS_REPORT(("No Free Msdu in ACX   = %d\n", pFourX->counters.count1));
837   	WLAN_OS_REPORT(("Concat more than 2    = %d\n", pFourX->counters.count2));
838   	WLAN_OS_REPORT(("Delay sending         = %d\n", pFourX->counters.count3));
839   	WLAN_OS_REPORT(("Concat less than 3    = %d\n", pFourX->counters.count4));
840   	WLAN_OS_REPORT(("send one msdu         = %d\n", pFourX->counters.count5));
841
842	WLAN_OS_REPORT(("Msdu in Queue Total   = %d\n", pFourX->counters.count6));
843	WLAN_OS_REPORT(("Msdu in Queue Copied  = %d\n", pFourX->counters.count7));
844
845}
846