/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * File: wctl.c
 *
 * Purpose: handle WMAC duplicate filter & defragment
 *
 * Author: Jerry Chen
 *
 * Date: Jun. 27, 2002
 *
 * Functions:
 *      WCTLbIsDuplicate - Test if duplicate packet
 *      WCTLuSearchDFCB - Search DeFragment Control Database
 *      WCTLuInsertDFCB - Insert DeFragment Control Database
 *      WCTLbHandleFragment - Handle received fragment packet
 *
 * Revision History:
 *
 */

#include "wctl.h"
#include "device.h"
#include "card.h"

/*---------------------  Static Definitions -------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/
// static int          msglevel                =MSG_LEVEL_INFO;
/*---------------------  Static Functions  --------------------------*/

/*---------------------  Export Variables  --------------------------*/

/*
 * Description:
 *      Scan Rx cache.  Return true if packet is duplicate, else
 *      inserts in receive cache and returns false.
 *
 * Parameters:
 *  In:
 *      pCache      - Receive packets history
 *      pMACHeader  - 802.11 MAC Header of received packet
 *  Out:
 *      none
 *
 * Return Value: true if packet duplicate; otherwise false
 *
 */

bool WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader)
{
	unsigned int uIndex;
	unsigned int ii;
	PSCacheEntry    pCacheEntry;

	if (IS_FC_RETRY(pMACHeader)) {
		uIndex = pCache->uInPtr;
		for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
			pCacheEntry = &(pCache->asCacheEntry[uIndex]);
			if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
			    (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
) {
				/* Duplicate match */
				return true;
			}
			ADD_ONE_WITH_WRAP_AROUND(uIndex, DUPLICATE_RX_CACHE_LENGTH);
		}
	}
	/* Not fount in cache - insert */
	pCacheEntry = &pCache->asCacheEntry[pCache->uInPtr];
	pCacheEntry->wFmSequence = pMACHeader->wSeqCtl;
	memcpy(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
	ADD_ONE_WITH_WRAP_AROUND(pCache->uInPtr, DUPLICATE_RX_CACHE_LENGTH);
	return false;
}

/*
 * Description:
 *      Found if sequence number of received fragment packet in Defragment Database
 *
 * Parameters:
 *  In:
 *      pDevice     - Pointer to adapter
 *      pMACHeader  - 802.11 MAC Header of received packet
 *  Out:
 *      none
 *
 * Return Value: index number in Defragment Database
 *
 */
unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
{
	unsigned int ii;

	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
		if ((pDevice->sRxDFCB[ii].bInUse == true) &&
		    (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
) {
			//
			return ii;
		}
	}
	return pDevice->cbDFCB;
}

/*
 * Description:
 *      Insert received fragment packet in Defragment Database
 *
 * Parameters:
 *  In:
 *      pDevice     - Pointer to adapter
 *      pMACHeader  - 802.11 MAC Header of received packet
 *  Out:
 *      none
 *
 * Return Value: index number in Defragment Database
 *
 */
unsigned int WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
{
	unsigned int ii;

	if (pDevice->cbFreeDFCB == 0)
		return pDevice->cbDFCB;
	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
		if (pDevice->sRxDFCB[ii].bInUse == false) {
			pDevice->cbFreeDFCB--;
			pDevice->sRxDFCB[ii].uLifetime = pDevice->dwMaxReceiveLifetime;
			pDevice->sRxDFCB[ii].bInUse = true;
			pDevice->sRxDFCB[ii].wSequence = (pMACHeader->wSeqCtl >> 4);
			pDevice->sRxDFCB[ii].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
			memcpy(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0]), ETH_ALEN);
			return ii;
		}
	}
	return pDevice->cbDFCB;
}

/*
 * Description:
 *      Handle received fragment packet
 *
 * Parameters:
 *  In:
 *      pDevice         - Pointer to adapter
 *      pMACHeader      - 802.11 MAC Header of received packet
 *      cbFrameLength   - Frame length
 *      bWEP            - is WEP packet
 *  Out:
 *      none
 *
 * Return Value: true if it is valid fragment packet and we have resource to defragment; otherwise false
 *
 */
bool WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, unsigned int cbFrameLength, bool bWEP, bool bExtIV)
{
	unsigned int uHeaderSize;

	if (bWEP == true) {
		uHeaderSize = 28;
		if (bExtIV)
			// ExtIV
			uHeaderSize += 4;
	} else {
		uHeaderSize = 24;
	}

	if (IS_FIRST_FRAGMENT_PKT(pMACHeader)) {
		pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
		if (pDevice->uCurrentDFCBIdx < pDevice->cbDFCB) {
			// duplicate, we must flush previous DCB
			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].uLifetime = pDevice->dwMaxReceiveLifetime;
			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence = (pMACHeader->wSeqCtl >> 4);
			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum = (pMACHeader->wSeqCtl & 0x000F);
		} else {
			pDevice->uCurrentDFCBIdx = WCTLuInsertDFCB(pDevice, pMACHeader);
			if (pDevice->uCurrentDFCBIdx == pDevice->cbDFCB) {
				return false;
			}
		}
		// reserve 4 byte to match MAC RX Buffer
		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (unsigned char *)(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4);
		memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, pMACHeader, cbFrameLength);
		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength = cbFrameLength;
		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += cbFrameLength;
		pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
		//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
		return false;
	} else {
		pDevice->uCurrentDFCBIdx = WCTLuSearchDFCB(pDevice, pMACHeader);
		if (pDevice->uCurrentDFCBIdx != pDevice->cbDFCB) {
			if ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wSequence == (pMACHeader->wSeqCtl >> 4)) &&
			    (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum == (pMACHeader->wSeqCtl & 0x000F)) &&
			    ((pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength + cbFrameLength - uHeaderSize) < 2346)) {
				memcpy(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer, ((unsigned char *)(pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize));
				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize);
				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize);
				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++;
				//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Second pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
			} else {
				// seq error or frag # error flush DFCB
				pDevice->cbFreeDFCB++;
				pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
				return false;
			}
		} else {
			return false;
		}
		if (IS_LAST_FRAGMENT_PKT(pMACHeader)) {
			//enq defragcontrolblock
			pDevice->cbFreeDFCB++;
			pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].bInUse = false;
			//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx);
			return true;
		}
		return false;
	}
}
