/*
 * 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: wroute.c
 *
 * Purpose: handle WMAC frame relay & filtering
 *
 * Author: Lyndon Chen
 *
 * Date: May 20, 2003
 *
 * Functions:
 *      ROUTEbRelay - Relay packet
 *
 * Revision History:
 *
 */

#include "mac.h"
#include "tcrc.h"
#include "rxtx.h"
#include "wroute.h"
#include "card.h"
#include "baseband.h"

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

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

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

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

/*
 * Description:
 *      Relay packet.  Return true if packet is copy to DMA1
 *
 * Parameters:
 *  In:
 *      pDevice             -
 *      pbySkbData          - rx packet skb data
 *  Out:
 *      true, false
 *
 * Return Value: true if packet duplicate; otherwise false
 *
 */
bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData,
		 unsigned int uDataLen, unsigned int uNodeIndex)
{
	PSMgmtObject    pMgmt = pDevice->pMgmt;
	PSTxDesc        pHeadTD, pLastTD;
	unsigned int cbFrameBodySize;
	unsigned int uMACfragNum;
	unsigned char byPktType;
	bool bNeedEncryption = false;
	SKeyItem        STempKey;
	PSKeyItem       pTransmitKey = NULL;
	unsigned int cbHeaderSize;
	unsigned int ii;
	unsigned char *pbyBSSID;

	if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 0) {
		DBG_PRT(MSG_LEVEL_DEBUG,
			KERN_INFO "Relay can't allocate TD1..\n");
		return false;
	}

	pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA];

	pHeadTD->m_td1TD1.byTCR = (TCR_EDP | TCR_STP);

	memcpy(pDevice->sTxEthHeader.abyDstAddr, pbySkbData, ETH_HLEN);

	cbFrameBodySize = uDataLen - ETH_HLEN;

	if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN)
		cbFrameBodySize += 8;

	if (pDevice->bEncryptionEnable == true) {
		bNeedEncryption = true;

		// get group key
		pbyBSSID = pDevice->abyBroadcastAddr;
		if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID,
		    GROUP_KEY, &pTransmitKey) == false) {
			pTransmitKey = NULL;
			DBG_PRT(MSG_LEVEL_DEBUG,
				KERN_DEBUG "KEY is NULL. [%d]\n",
				pDevice->pMgmt->eCurrMode);
		} else {
			DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n");
		}
	}

	if (pDevice->bEnableHostWEP) {
		if (uNodeIndex < MAX_NODE_NUM + 1) {
			pTransmitKey = &STempKey;
			pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite;
			pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex;
			pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength;
			pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16;
			pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0;
			memcpy(pTransmitKey->abyKey,
			       &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0],
			       pTransmitKey->uKeyLength);
		}
	}

	uMACfragNum = cbGetFragCount(pDevice, pTransmitKey,
				     cbFrameBodySize, &pDevice->sTxEthHeader);

	if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA))
		return false;

	byPktType = pDevice->byPacketType;

	if (pDevice->bFixRate) {
		if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
			if (pDevice->uConnectionRate >= RATE_11M)
				pDevice->wCurrentRate = RATE_11M;
			else
				pDevice->wCurrentRate = pDevice->uConnectionRate;
		} else {
			if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) &&
			    (pDevice->uConnectionRate <= RATE_6M)) {
				pDevice->wCurrentRate = RATE_6M;
			} else {
				if (pDevice->uConnectionRate >= RATE_54M)
					pDevice->wCurrentRate = RATE_54M;
				else
					pDevice->wCurrentRate = pDevice->uConnectionRate;
			}
		}
	} else {
		pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate;
	}

	if (pDevice->wCurrentRate <= RATE_11M)
		byPktType = PK_TYPE_11B;

	vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff,
			    bNeedEncryption, cbFrameBodySize, TYPE_AC0DMA,
			    pHeadTD, &pDevice->sTxEthHeader, pbySkbData,
			    pTransmitKey, uNodeIndex, &uMACfragNum,
			    &cbHeaderSize);

	if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) {
		// Disable PS
		MACbPSWakeup(pDevice->PortOffset);
	}

	pDevice->bPWBitOn = false;

	pLastTD = pHeadTD;
	for (ii = 0; ii < uMACfragNum; ii++) {
		// Poll Transmit the adapter
		wmb();
		pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC;
		wmb();
		if (ii == (uMACfragNum - 1))
			pLastTD = pHeadTD;
		pHeadTD = pHeadTD->next;
	}

	pLastTD->pTDInfo->skb = NULL;
	pLastTD->pTDInfo->byFlags = 0;

	pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;

	MACvTransmitAC0(pDevice->PortOffset);

	return true;
}
