text: /*
   * 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 & filterring
   *
   * 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 int          msglevel                =MSG_LEVEL_DEBUG;
  /*---------------------  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, (unsigned char *)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 = (unsigned char)pDevice->byPacketType;
  
      if (pDevice->bFixRate) {
          if (pDevice->eCurrentPHYType == PHY_TYPE_11B) {
              if (pDevice->uConnectionRate >= RATE_11M) {
                  pDevice->wCurrentRate = RATE_11M;
              } else {
                  pDevice->wCurrentRate = (unsigned short)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 = (unsigned short)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 = 0;
      pLastTD->pTDInfo->byFlags = 0;
  
      pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
  
      MACvTransmitAC0(pDevice->PortOffset);
  
      return true;
  }
  
  
  
  