| /* |
| * 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 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, 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; |
| } |