diff options
78 files changed, 49521 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/80211hdr.h b/drivers/staging/vt6655/80211hdr.h new file mode 100644 index 00000000000..b4bbb8d3c24 --- /dev/null +++ b/drivers/staging/vt6655/80211hdr.h @@ -0,0 +1,357 @@ +/* + * 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: 80211hdr.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with 802.11 MAC headers. + * + * Author: Lyndon Chen + * + * Date: Apr 8, 2002 + * + */ + + + +#ifndef __80211HDR_H__ +#define __80211HDR_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +// bit type +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +// 802.11 frame related, defined as 802.11 spec +#define WLAN_ADDR_LEN 6 +#define WLAN_CRC_LEN 4 +#define WLAN_CRC32_LEN 4 +#define WLAN_FCS_LEN 4 +#define WLAN_BSSID_LEN 6 +#define WLAN_BSS_TS_LEN 8 +#define WLAN_HDR_ADDR2_LEN 16 +#define WLAN_HDR_ADDR3_LEN 24 +#define WLAN_HDR_ADDR4_LEN 30 +#define WLAN_IEHDR_LEN 2 +#define WLAN_SSID_MAXLEN 32 +//#define WLAN_RATES_MAXLEN 255 +#define WLAN_RATES_MAXLEN 16 +#define WLAN_RATES_MAXLEN_11B 4 +#define WLAN_RSN_MAXLEN 32 +#define WLAN_DATA_MAXLEN 2312 +#define WLAN_A3FR_MAXLEN (WLAN_HDR_ADDR3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) + + +#define WLAN_BEACON_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 0) +#define WLAN_NULLDATA_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 0) +#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 2) +#define WLAN_ASSOCREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_ASSOCRESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_REASSOCREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_REASSOCRESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_PROBEREQ_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_PROBERESP_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_AUTHEN_FR_MAXLEN WLAN_A3FR_MAXLEN +#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_ADDR3_LEN + 2) + + +#define WLAN_WEP_NKEYS 4 +#define WLAN_WEP40_KEYLEN 5 +#define WLAN_WEP104_KEYLEN 13 +#define WLAN_WEP232_KEYLEN 29 +//#define WLAN_WEPMAX_KEYLEN 29 +#define WLAN_WEPMAX_KEYLEN 32 +#define WLAN_CHALLENGE_IE_MAXLEN 255 +#define WLAN_CHALLENGE_IE_LEN 130 +#define WLAN_CHALLENGE_LEN 128 +#define WLAN_WEP_IV_LEN 4 +#define WLAN_WEP_ICV_LEN 4 +#define WLAN_FRAGS_MAX 16 + +// Frame Type +#define WLAN_TYPE_MGR 0x00 +#define WLAN_TYPE_CTL 0x01 +#define WLAN_TYPE_DATA 0x02 + +#define WLAN_FTYPE_MGMT 0x00 +#define WLAN_FTYPE_CTL 0x01 +#define WLAN_FTYPE_DATA 0x02 + + +// Frame Subtypes +#define WLAN_FSTYPE_ASSOCREQ 0x00 +#define WLAN_FSTYPE_ASSOCRESP 0x01 +#define WLAN_FSTYPE_REASSOCREQ 0x02 +#define WLAN_FSTYPE_REASSOCRESP 0x03 +#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBERESP 0x05 +#define WLAN_FSTYPE_BEACON 0x08 +#define WLAN_FSTYPE_ATIM 0x09 +#define WLAN_FSTYPE_DISASSOC 0x0a +#define WLAN_FSTYPE_AUTHEN 0x0b +#define WLAN_FSTYPE_DEAUTHEN 0x0c +#define WLAN_FSTYPE_ACTION 0x0d + +// Control +#define WLAN_FSTYPE_PSPOLL 0x0a +#define WLAN_FSTYPE_RTS 0x0b +#define WLAN_FSTYPE_CTS 0x0c +#define WLAN_FSTYPE_ACK 0x0d +#define WLAN_FSTYPE_CFEND 0x0e +#define WLAN_FSTYPE_CFENDCFACK 0x0f + +// Data +#define WLAN_FSTYPE_DATAONLY 0x00 +#define WLAN_FSTYPE_DATA_CFACK 0x01 +#define WLAN_FSTYPE_DATA_CFPOLL 0x02 +#define WLAN_FSTYPE_DATA_CFACK_CFPOLL 0x03 +#define WLAN_FSTYPE_NULL 0x04 +#define WLAN_FSTYPE_CFACK 0x05 +#define WLAN_FSTYPE_CFPOLL 0x06 +#define WLAN_FSTYPE_CFACK_CFPOLL 0x07 + + +#ifdef __BIG_ENDIAN + +// GET & SET Frame Control bit +#define WLAN_GET_FC_PRVER(n) ((((WORD)(n) >> 8) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((WORD)(n) >> 8) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((WORD)(n) >> 8) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((WORD)(n) << 8) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((WORD)(n) << 8) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((WORD)(n) << 8) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((WORD)(n) << 8) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((WORD)(n) << 8) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((WORD)(n) << 8) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((WORD)(n) << 8) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((WORD)(n) << 8) & (BIT15)) >> 15) + +// Sequence Field bit +#define WLAN_GET_SEQ_FRGNUM(n) (((WORD)(n) >> 8) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((WORD)(n) >> 8) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + + +// Capability Field bit +#define WLAN_GET_CAP_INFO_ESS(n) (((n) >> 8) & BIT0) +#define WLAN_GET_CAP_INFO_IBSS(n) ((((n) >> 8) & BIT1) >> 1) +#define WLAN_GET_CAP_INFO_CFPOLLABLE(n) ((((n) >> 8) & BIT2) >> 2) +#define WLAN_GET_CAP_INFO_CFPOLLREQ(n) ((((n) >> 8) & BIT3) >> 3) +#define WLAN_GET_CAP_INFO_PRIVACY(n) ((((n) >> 8) & BIT4) >> 4) +#define WLAN_GET_CAP_INFO_SHORTPREAMBLE(n) ((((n) >> 8) & BIT5) >> 5) +#define WLAN_GET_CAP_INFO_PBCC(n) ((((n) >> 8) & BIT6) >> 6) +#define WLAN_GET_CAP_INFO_AGILITY(n) ((((n) >> 8) & BIT7) >> 7) +#define WLAN_GET_CAP_INFO_SPECTRUMMNG(n) ((((n)) & BIT8) >> 10) +#define WLAN_GET_CAP_INFO_SHORTSLOTTIME(n) ((((n)) & BIT10) >> 10) +#define WLAN_GET_CAP_INFO_DSSSOFDM(n) ((((n)) & BIT13) >> 13) +#define WLAN_GET_CAP_INFO_GRPACK(n) ((((n)) & BIT14) >> 14) + + +#else + +// GET & SET Frame Control bit +#define WLAN_GET_FC_PRVER(n) (((WORD)(n)) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((WORD)(n)) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((WORD)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((WORD)(n)) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((WORD)(n)) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((WORD)(n)) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((WORD)(n)) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((WORD)(n)) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((WORD)(n)) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((WORD)(n)) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((WORD)(n)) & (BIT15)) >> 15) + + +// Sequence Field bit +#define WLAN_GET_SEQ_FRGNUM(n) (((WORD)(n)) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((WORD)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) + + +// Capability Field bit +#define WLAN_GET_CAP_INFO_ESS(n) ((n) & BIT0) +#define WLAN_GET_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1) +#define WLAN_GET_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2) +#define WLAN_GET_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3) +#define WLAN_GET_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4) +#define WLAN_GET_CAP_INFO_SHORTPREAMBLE(n) (((n) & BIT5) >> 5) +#define WLAN_GET_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6) +#define WLAN_GET_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7) +#define WLAN_GET_CAP_INFO_SPECTRUMMNG(n) (((n) & BIT8) >> 10) +#define WLAN_GET_CAP_INFO_SHORTSLOTTIME(n) (((n) & BIT10) >> 10) +#define WLAN_GET_CAP_INFO_DSSSOFDM(n) (((n) & BIT13) >> 13) +#define WLAN_GET_CAP_INFO_GRPACK(n) (((n) & BIT14) >> 14) + + +#endif //#ifdef __BIG_ENDIAN + + +#define WLAN_SET_CAP_INFO_ESS(n) (n) +#define WLAN_SET_CAP_INFO_IBSS(n) ((n) << 1) +#define WLAN_SET_CAP_INFO_CFPOLLABLE(n) ((n) << 2) +#define WLAN_SET_CAP_INFO_CFPOLLREQ(n) ((n) << 3) +#define WLAN_SET_CAP_INFO_PRIVACY(n) ((n) << 4) +#define WLAN_SET_CAP_INFO_SHORTPREAMBLE(n) ((n) << 5) +#define WLAN_SET_CAP_INFO_SPECTRUMMNG(n) ((n) << 8) +#define WLAN_SET_CAP_INFO_PBCC(n) ((n) << 6) +#define WLAN_SET_CAP_INFO_AGILITY(n) ((n) << 7) +#define WLAN_SET_CAP_INFO_SHORTSLOTTIME(n) ((n) << 10) +#define WLAN_SET_CAP_INFO_DSSSOFDM(n) ((n) << 13) +#define WLAN_SET_CAP_INFO_GRPACK(n) ((n) << 14) + + +#define WLAN_SET_FC_PRVER(n) ((WORD)(n)) +#define WLAN_SET_FC_FTYPE(n) (((WORD)(n)) << 2) +#define WLAN_SET_FC_FSTYPE(n) (((WORD)(n)) << 4) +#define WLAN_SET_FC_TODS(n) (((WORD)(n)) << 8) +#define WLAN_SET_FC_FROMDS(n) (((WORD)(n)) << 9) +#define WLAN_SET_FC_MOREFRAG(n) (((WORD)(n)) << 10) +#define WLAN_SET_FC_RETRY(n) (((WORD)(n)) << 11) +#define WLAN_SET_FC_PWRMGT(n) (((WORD)(n)) << 12) +#define WLAN_SET_FC_MOREDATA(n) (((WORD)(n)) << 13) +#define WLAN_SET_FC_ISWEP(n) (((WORD)(n)) << 14) +#define WLAN_SET_FC_ORDER(n) (((WORD)(n)) << 15) + +#define WLAN_SET_SEQ_FRGNUM(n) ((WORD)(n)) +#define WLAN_SET_SEQ_SEQNUM(n) (((WORD)(n)) << 4) + +// ERP Field bit + +#define WLAN_GET_ERP_NONERP_PRESENT(n) ((n) & BIT0) +#define WLAN_GET_ERP_USE_PROTECTION(n) (((n) & BIT1) >> 1) +#define WLAN_GET_ERP_BARKER_MODE(n) (((n) & BIT2) >> 2) + +#define WLAN_SET_ERP_NONERP_PRESENT(n) (n) +#define WLAN_SET_ERP_USE_PROTECTION(n) ((n) << 1) +#define WLAN_SET_ERP_BARKER_MODE(n) ((n) << 2) + + + +// Support & Basic Rates field +#define WLAN_MGMT_IS_BASICRATE(b) ((b) & BIT7) +#define WLAN_MGMT_GET_RATE(b) ((b) & ~BIT7) + +// TIM field +#define WLAN_MGMT_IS_MULTICAST_TIM(b) ((b) & BIT0) +#define WLAN_MGMT_GET_TIM_OFFSET(b) (((b) & ~BIT0) >> 1) + +// 3-Addr & 4-Addr +#define WLAN_HDR_A3_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR3_LEN) +#define WLAN_HDR_A4_DATA_PTR(p) (((PBYTE)(p)) + WLAN_HDR_ADDR4_LEN) + +// IEEE ADDR +#define IEEE_ADDR_UNIVERSAL 0x02 +#define IEEE_ADDR_GROUP 0x01 + +typedef struct { + BYTE abyAddr[6]; +} IEEE_ADDR, *PIEEE_ADDR; + +// 802.11 Header Format + +typedef struct tagWLAN_80211HDR_A2 { + + WORD wFrameCtl; + WORD wDurationID; + BYTE abyAddr1[WLAN_ADDR_LEN]; + BYTE abyAddr2[WLAN_ADDR_LEN]; + +}__attribute__ ((__packed__)) +WLAN_80211HDR_A2, *PWLAN_80211HDR_A2; + +typedef struct tagWLAN_80211HDR_A3 { + + WORD wFrameCtl; + WORD wDurationID; + BYTE abyAddr1[WLAN_ADDR_LEN]; + BYTE abyAddr2[WLAN_ADDR_LEN]; + BYTE abyAddr3[WLAN_ADDR_LEN]; + WORD wSeqCtl; + +}__attribute__ ((__packed__)) +WLAN_80211HDR_A3, *PWLAN_80211HDR_A3; + +typedef struct tagWLAN_80211HDR_A4 { + + WORD wFrameCtl; + WORD wDurationID; + BYTE abyAddr1[WLAN_ADDR_LEN]; + BYTE abyAddr2[WLAN_ADDR_LEN]; + BYTE abyAddr3[WLAN_ADDR_LEN]; + WORD wSeqCtl; + BYTE abyAddr4[WLAN_ADDR_LEN]; + +}__attribute__ ((__packed__)) +WLAN_80211HDR_A4, *PWLAN_80211HDR_A4; + + +typedef union tagUWLAN_80211HDR { + + WLAN_80211HDR_A2 sA2; + WLAN_80211HDR_A3 sA3; + WLAN_80211HDR_A4 sA4; + +} UWLAN_80211HDR, *PUWLAN_80211HDR; + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + +#endif // __80211HDR_H__ + + diff --git a/drivers/staging/vt6655/80211mgr.c b/drivers/staging/vt6655/80211mgr.c new file mode 100644 index 00000000000..84745fb6b03 --- /dev/null +++ b/drivers/staging/vt6655/80211mgr.c @@ -0,0 +1,1050 @@ +/* + * 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: 80211mgr.c + * + * Purpose: Handles the 802.11 managment support functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + * Functions: + * vMgrEncodeBeacon - Encode the Beacon frame + * vMgrDecodeBeacon - Decode the Beacon frame + * vMgrEncodeIBSSATIM - Encode the IBSS ATIM frame + * vMgrDecodeIBSSATIM - Decode the IBSS ATIM frame + * vMgrEncodeDisassociation - Encode the Disassociation frame + * vMgrDecodeDisassociation - Decode the Disassociation frame + * vMgrEncodeAssocRequest - Encode the Association request frame + * vMgrDecodeAssocRequest - Decode the Association request frame + * vMgrEncodeAssocResponse - Encode the Association response frame + * vMgrDecodeAssocResponse - Decode the Association response frame + * vMgrEncodeReAssocRequest - Encode the ReAssociation request frame + * vMgrDecodeReAssocRequest - Decode the ReAssociation request frame + * vMgrEncodeProbeRequest - Encode the Probe request frame + * vMgrDecodeProbeRequest - Decode the Probe request frame + * vMgrEncodeProbeResponse - Encode the Probe response frame + * vMgrDecodeProbeResponse - Decode the Probe response frame + * vMgrEncodeAuthen - Encode the Authentication frame + * vMgrDecodeAuthen - Decode the Authentication frame + * vMgrEncodeDeauthen - Encode the DeAuthentication frame + * vMgrDecodeDeauthen - Decode the DeAuthentication frame + * vMgrEncodeReassocResponse - Encode the Reassociation response frame + * vMgrDecodeReassocResponse - Decode the Reassociation response frame + * + * Revision History: + * + */ + + + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WPA_H__) +#include "wpa.h" +#endif + + + +/*--------------------- Static Definitions -------------------------*/ + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; +/*--------------------- Static Functions --------------------------*/ + + + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + +/*+ + * + * Routine Description: + * Encode Beacon frame body offset + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeBeacon( + IN PWLAN_FR_BEACON pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_TS); + pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_BCN_INT); + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_CAPINFO); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_BEACON_OFF_SSID; + + return; +} + +/*+ + * + * Routine Description: + * Decode Beacon frame body offset + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrDecodeBeacon( + IN PWLAN_FR_BEACON pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_TS); + pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_BCN_INT); + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_BEACON_OFF_CAPINFO); + + // Information elements + pItem = (PWLAN_IE)((PBYTE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))) + + WLAN_BEACON_OFF_SSID); + while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ){ + + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + case WLAN_EID_FH_PARMS: + //pFrame->pFHParms = (PWLAN_IE_FH_PARMS)pItem; + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + case WLAN_EID_TIM: + if (pFrame->pTIM == NULL) + pFrame->pTIM = (PWLAN_IE_TIM)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) { + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + } + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: //7 + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: //32 + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: //37 + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: //40 + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in beacon decode.\n", pItem->byElementID); + break; + + } + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + } + + return; +} + + +/*+ + * + * Routine Description: + * Encode IBSS ATIM + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrEncodeIBSSATIM( + IN PWLAN_FR_IBSSATIM pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + pFrame->len = WLAN_HDR_ADDR3_LEN; + + return; +} + + +/*+ + * + * Routine Description: + * Decode IBSS ATIM + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeIBSSATIM( + IN PWLAN_FR_IBSSATIM pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + return; +} + + +/*+ + * + * Routine Description: + * Encode Disassociation + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeDisassociation( + IN PWLAN_FR_DISASSOC pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + + // Fixed Fields + pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DISASSOC_OFF_REASON); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DISASSOC_OFF_REASON + sizeof(*(pFrame->pwReason)); + + return; +} + + +/*+ + * + * Routine Description: + * Decode Disassociation + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeDisassociation( + IN PWLAN_FR_DISASSOC pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DISASSOC_OFF_REASON); + + return; +} + +/*+ + * + * Routine Description: + * Encode Association Request + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrEncodeAssocRequest( + IN PWLAN_FR_ASSOCREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_LISTEN_INT); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCREQ_OFF_LISTEN_INT + sizeof(*(pFrame->pwListenInterval)); + return; +} + + +/*+ + * + * Routine Description: (AP) + * Decode Association Request + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeAssocRequest( + IN PWLAN_FR_ASSOCREQ pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_LISTEN_INT); + + // Information elements + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCREQ_OFF_SSID); + + while (((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { + switch (pItem->byElementID){ + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) { + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + } + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in assocreq decode.\n", + pItem->byElementID); + break; + } + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + } + return; +} + +/*+ + * + * Routine Description: (AP) + * Encode Association Response + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeAssocResponse( + IN PWLAN_FR_ASSOCRESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_STATUS); + pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_AID); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_ASSOCRESP_OFF_AID + + sizeof(*(pFrame->pwAid)); + + return; +} + + +/*+ + * + * Routine Description: + * Decode Association Response + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeAssocResponse( + IN PWLAN_FR_ASSOCRESP pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_STATUS); + pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_AID); + + // Information elements + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_ASSOCRESP_OFF_SUPP_RATES); + + pItem = (PWLAN_IE)(pFrame->pSuppRates); + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + + if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pFrame->pExtSuppRates=[%p].\n", pItem); + } + else { + pFrame->pExtSuppRates = NULL; + } + return; +} + + +/*+ + * + * Routine Description: + * Encode Reassociation Request + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeReassocRequest( + IN PWLAN_FR_REASSOCREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_LISTEN_INT); + pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CURR_AP); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCREQ_OFF_CURR_AP + sizeof(*(pFrame->pAddrCurrAP)); + + return; +} + + +/*+ + * + * Routine Description: (AP) + * Decode Reassociation Request + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrDecodeReassocRequest( + IN PWLAN_FR_REASSOCREQ pFrame + ) +{ + PWLAN_IE pItem; + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CAP_INFO); + pFrame->pwListenInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_LISTEN_INT); + pFrame->pAddrCurrAP = (PIEEE_ADDR)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_CURR_AP); + + // Information elements + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCREQ_OFF_SSID); + + while(((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) { + + switch (pItem->byElementID){ + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) { + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + } + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Unrecognized EID=%dd in reassocreq decode.\n", + pItem->byElementID); + break; + } + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + } + return; +} + + + +/*+ + * + * Routine Description: + * Encode Probe Request + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrEncodeProbeRequest( + IN PWLAN_FR_PROBEREQ pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + pFrame->len = WLAN_HDR_ADDR3_LEN; + return; +} + +/*+ + * + * Routine Description: + * Decode Probe Request + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeProbeRequest( + IN PWLAN_FR_PROBEREQ pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Information elements + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))); + + while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in probereq\n", pItem->byElementID); + break; + } + + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + } + return; +} + + +/*+ + * + * Routine Description: + * Encode Probe Response + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrEncodeProbeResponse( + IN PWLAN_FR_PROBERESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_TS); + pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_BCN_INT); + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_CAP_INFO); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_PROBERESP_OFF_CAP_INFO + + sizeof(*(pFrame->pwCapInfo)); + + return; +} + + + +/*+ + * + * Routine Description: + * Decode Probe Response + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeProbeResponse( + IN PWLAN_FR_PROBERESP pFrame + ) +{ + PWLAN_IE pItem; +// BYTE byCheckEID = 0; + + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pqwTimestamp = (PQWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_TS); + pFrame->pwBeaconInterval = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_BCN_INT); + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_CAP_INFO); + + // Information elements + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_PROBERESP_OFF_SSID); + + while( ((PBYTE)pItem) < (pFrame->pBuf + pFrame->len) ) { + /* + if (pItem->byElementID < byCheckEID) + break; + else + byCheckEID = pItem->byElementID; +*/ + switch (pItem->byElementID) { + case WLAN_EID_SSID: + if (pFrame->pSSID == NULL) + pFrame->pSSID = (PWLAN_IE_SSID)pItem; + break; + case WLAN_EID_SUPP_RATES: + if (pFrame->pSuppRates == NULL) + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + case WLAN_EID_FH_PARMS: + break; + case WLAN_EID_DS_PARMS: + if (pFrame->pDSParms == NULL) + pFrame->pDSParms = (PWLAN_IE_DS_PARMS)pItem; + break; + case WLAN_EID_CF_PARMS: + if (pFrame->pCFParms == NULL) + pFrame->pCFParms = (PWLAN_IE_CF_PARMS)pItem; + break; + case WLAN_EID_IBSS_PARMS: + if (pFrame->pIBSSParms == NULL) + pFrame->pIBSSParms = (PWLAN_IE_IBSS_PARMS)pItem; + break; + + case WLAN_EID_RSN: + if (pFrame->pRSN == NULL) { + pFrame->pRSN = (PWLAN_IE_RSN)pItem; + } + break; + case WLAN_EID_RSN_WPA: + if (pFrame->pRSNWPA == NULL) { + if (WPAb_Is_RSN((PWLAN_IE_RSN_EXT)pItem) == TRUE) + pFrame->pRSNWPA = (PWLAN_IE_RSN_EXT)pItem; + } + break; + case WLAN_EID_ERP: + if (pFrame->pERP == NULL) + pFrame->pERP = (PWLAN_IE_ERP)pItem; + break; + case WLAN_EID_EXTSUPP_RATES: + if (pFrame->pExtSuppRates == NULL) + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + break; + + case WLAN_EID_COUNTRY: //7 + if (pFrame->pIE_Country == NULL) + pFrame->pIE_Country = (PWLAN_IE_COUNTRY)pItem; + break; + + case WLAN_EID_PWR_CONSTRAINT: //32 + if (pFrame->pIE_PowerConstraint == NULL) + pFrame->pIE_PowerConstraint = (PWLAN_IE_PW_CONST)pItem; + break; + + case WLAN_EID_CH_SWITCH: //37 + if (pFrame->pIE_CHSW == NULL) + pFrame->pIE_CHSW = (PWLAN_IE_CH_SW)pItem; + break; + + case WLAN_EID_QUIET: //40 + if (pFrame->pIE_Quiet == NULL) + pFrame->pIE_Quiet = (PWLAN_IE_QUIET)pItem; + break; + + case WLAN_EID_IBSS_DFS: + if (pFrame->pIE_IBSSDFS == NULL) + pFrame->pIE_IBSSDFS = (PWLAN_IE_IBSS_DFS)pItem; + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Bad EID=%dd in proberesp\n", pItem->byElementID); + break; + } + + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + } + return; +} + + +/*+ + * + * Routine Description: + * Encode Authentication frame + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeAuthen( + IN PWLAN_FR_AUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_ALG); + pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_SEQ); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_STATUS); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_AUTHEN_OFF_STATUS + sizeof(*(pFrame->pwStatus)); + + return; +} + + +/*+ + * + * Routine Description: + * Decode Authentication + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeAuthen( + IN PWLAN_FR_AUTHEN pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwAuthAlgorithm = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_ALG); + pFrame->pwAuthSequence = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_AUTH_SEQ); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_STATUS); + + // Information elements + pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_AUTHEN_OFF_CHALLENGE); + + if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) { + pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem; + } + + return; +} + + +/*+ + * + * Routine Description: + * Encode Authentication + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeDeauthen( + IN PWLAN_FR_DEAUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DEAUTHEN_OFF_REASON); + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_DEAUTHEN_OFF_REASON + sizeof(*(pFrame->pwReason)); + + return; +} + + +/*+ + * + * Routine Description: + * Decode Deauthentication + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDecodeDeauthen( + IN PWLAN_FR_DEAUTHEN pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwReason = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_DEAUTHEN_OFF_REASON); + + return; +} + + +/*+ + * + * Routine Description: (AP) + * Encode Reassociation Response + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrEncodeReassocResponse( + IN PWLAN_FR_REASSOCRESP pFrame + ) +{ + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_STATUS); + pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_AID); + + pFrame->len = WLAN_HDR_ADDR3_LEN + WLAN_REASSOCRESP_OFF_AID + sizeof(*(pFrame->pwAid)); + + return; +} + + +/*+ + * + * Routine Description: + * Decode Reassociation Response + * + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrDecodeReassocResponse( + IN PWLAN_FR_REASSOCRESP pFrame + ) +{ + PWLAN_IE pItem; + + pFrame->pHdr = (PUWLAN_80211HDR)pFrame->pBuf; + + // Fixed Fields + pFrame->pwCapInfo = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_CAP_INFO); + pFrame->pwStatus = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_STATUS); + pFrame->pwAid = (PWORD)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_AID); + + //Information elements + pFrame->pSuppRates = (PWLAN_IE_SUPP_RATES)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3)) + + WLAN_REASSOCRESP_OFF_SUPP_RATES); + + pItem = (PWLAN_IE)(pFrame->pSuppRates); + pItem = (PWLAN_IE)(((PBYTE)pItem) + 2 + pItem->len); + + if ((((PBYTE)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_EXTSUPP_RATES)) { + pFrame->pExtSuppRates = (PWLAN_IE_SUPP_RATES)pItem; + } + return; +} diff --git a/drivers/staging/vt6655/80211mgr.h b/drivers/staging/vt6655/80211mgr.h new file mode 100644 index 00000000000..dc54a65edab --- /dev/null +++ b/drivers/staging/vt6655/80211mgr.h @@ -0,0 +1,832 @@ +/* + * 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: 80211mgr.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with 802.11 managment frames. + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + + +#ifndef __80211MGR_H__ +#define __80211MGR_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +#define WLAN_MIN_ARRAY 1 + +// Information Element ID value +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARMS 2 +#define WLAN_EID_DS_PARMS 3 +#define WLAN_EID_CF_PARMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARMS 6 +#define WLAN_EID_COUNTRY 7 +#define WLAN_EID_CHALLENGE 16 +#define WLAN_EID_PWR_CONSTRAINT 32 +#define WLAN_EID_PWR_CAPABILITY 33 +#define WLAN_EID_TPC_REQ 34 +#define WLAN_EID_TPC_REP 35 +#define WLAN_EID_SUPP_CH 36 +#define WLAN_EID_CH_SWITCH 37 +#define WLAN_EID_MEASURE_REQ 38 +#define WLAN_EID_MEASURE_REP 39 +#define WLAN_EID_QUIET 40 +#define WLAN_EID_IBSS_DFS 41 +#define WLAN_EID_ERP 42 +// reference 802.11i 7.3.2 table 20 +#define WLAN_EID_RSN 48 +#define WLAN_EID_EXTSUPP_RATES 50 +// reference WiFi WPA spec. +#define WLAN_EID_RSN_WPA 221 + + +#define WLAN_EID_ERP_NONERP_PRESENT 0x01 +#define WLAN_EID_ERP_USE_PROTECTION 0x02 +#define WLAN_EID_ERP_BARKER_MODE 0x04 + +// Reason Codes +#define WLAN_MGMT_REASON_RSVD 0 +#define WLAN_MGMT_REASON_UNSPEC 1 +#define WLAN_MGMT_REASON_PRIOR_AUTH_INVALID 2 +#define WLAN_MGMT_REASON_DEAUTH_LEAVING 3 +#define WLAN_MGMT_REASON_DISASSOC_INACTIVE 4 +#define WLAN_MGMT_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_MGMT_REASON_CLASS2_NONAUTH 6 +#define WLAN_MGMT_REASON_CLASS3_NONASSOC 7 +#define WLAN_MGMT_REASON_DISASSOC_STA_HASLEFT 8 +#define WLAN_MGMT_REASON_CANT_ASSOC_NONAUTH 9 +#define WLAN_MGMT_REASON_DISASSOC_PWR_CAP_UNACCEPT 10 +#define WLAN_MGMT_REASON_DISASSOC_SUPP_CH_UNACCEPT 11 +#define WLAN_MGMT_REASON_INVALID_IE 13 +#define WLAN_MGMT_REASON_MIC_FAILURE 14 +#define WLAN_MGMT_REASON_4WAY_HANDSHAKE_TIMEOUT 15 +#define WLAN_MGMT_REASON_GRPKEY_UPDATE_TIMEOUT 16 +#define WLAN_MGMT_REASON_4WAY_INFO_DIFFERENT 17 +#define WLAN_MGMT_REASON_MULTCAST_CIPHER_INVALID 18 +#define WLAN_MGMT_REASON_UNCAST_CIPHER_INVALID 19 +#define WLAN_MGMT_REASON_AKMP_INVALID 20 +#define WLAN_MGMT_REASON_RSNE_UNSUPPORTED 21 +#define WLAN_MGMT_REASON_RSNE_CAP_INVALID 22 +#define WLAN_MGMT_REASON_80211X_AUTH_FAILED 23 + +// Status Codes +#define WLAN_MGMT_STATUS_SUCCESS 0 +#define WLAN_MGMT_STATUS_UNSPEC_FAILURE 1 +#define WLAN_MGMT_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_MGMT_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG 13 +#define WLAN_MGMT_STATUS_RX_AUTH_NOSEQ 14 +#define WLAN_MGMT_STATUS_CHALLENGE_FAIL 15 +#define WLAN_MGMT_STATUS_AUTH_TIMEOUT 16 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY 17 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_RATES 18 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE 19 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC 20 +#define WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY 21 + +// reference 802.11h 7.3.1.9 +// +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_SPECTRUM_MNG 22 +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_PWR_CAP 23 +#define WLAN_MGMT_STATUS_ASSOC_REJECT_BCS_SUPP_CH 24 +// +// reference 802.11g 7.3.1.9 +// +#define WLAN_MGMT_STATUS_SHORTSLOTTIME_UNSUPPORTED 25 +#define WLAN_MGMT_STATUS_DSSSOFDM_UNSUPPORTED 26 +// +// reference 802.11i 7.3.1.9 table 19 +// +#define WLAN_MGMT_STATUS_INVALID_IE 40 +#define WLAN_MGMT_STATUS_GROUP_CIPHER_INVALID 41 +#define WLAN_MGMT_STATUS_PAIRWISE_CIPHER_INVALID 42 +#define WLAN_MGMT_STATUS_AKMP_INVALID 43 +#define WLAN_MGMT_STATUS_UNSUPPORT_RSN_IE_VER 44 +#define WLAN_MGMT_STATUS_INVALID_RSN_IE_CAP 45 +#define WLAN_MGMT_STATUS_CIPHER_REJECT 46 + + + +// Auth Algorithm +#define WLAN_AUTH_ALG_OPENSYSTEM 0 +#define WLAN_AUTH_ALG_SHAREDKEY 1 + + + +// Management Frame Field Offsets +// Note: Not all fields are listed because of variable lengths. +// Note: These offsets are from the start of the frame data + +#define WLAN_BEACON_OFF_TS 0 +#define WLAN_BEACON_OFF_BCN_INT 8 +#define WLAN_BEACON_OFF_CAPINFO 10 +#define WLAN_BEACON_OFF_SSID 12 + +#define WLAN_DISASSOC_OFF_REASON 0 + +#define WLAN_ASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_ASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_ASSOCREQ_OFF_SSID 4 + +#define WLAN_ASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_ASSOCRESP_OFF_STATUS 2 +#define WLAN_ASSOCRESP_OFF_AID 4 +#define WLAN_ASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_REASSOCREQ_OFF_CAP_INFO 0 +#define WLAN_REASSOCREQ_OFF_LISTEN_INT 2 +#define WLAN_REASSOCREQ_OFF_CURR_AP 4 +#define WLAN_REASSOCREQ_OFF_SSID 10 + +#define WLAN_REASSOCRESP_OFF_CAP_INFO 0 +#define WLAN_REASSOCRESP_OFF_STATUS 2 +#define WLAN_REASSOCRESP_OFF_AID 4 +#define WLAN_REASSOCRESP_OFF_SUPP_RATES 6 + +#define WLAN_PROBEREQ_OFF_SSID 0 + +#define WLAN_PROBERESP_OFF_TS 0 +#define WLAN_PROBERESP_OFF_BCN_INT 8 +#define WLAN_PROBERESP_OFF_CAP_INFO 10 +#define WLAN_PROBERESP_OFF_SSID 12 + +#define WLAN_AUTHEN_OFF_AUTH_ALG 0 +#define WLAN_AUTHEN_OFF_AUTH_SEQ 2 +#define WLAN_AUTHEN_OFF_STATUS 4 +#define WLAN_AUTHEN_OFF_CHALLENGE 6 + +#define WLAN_DEAUTHEN_OFF_REASON 0 + + +// +// Cipher Suite Selectors defiened in 802.11i +// +#define WLAN_11i_CSS_USE_GROUP 0 +#define WLAN_11i_CSS_WEP40 1 +#define WLAN_11i_CSS_TKIP 2 +#define WLAN_11i_CSS_CCMP 4 +#define WLAN_11i_CSS_WEP104 5 +#define WLAN_11i_CSS_UNKNOWN 255 + +// +// Authentication and Key Management Suite Selectors defined in 802.11i +// +#define WLAN_11i_AKMSS_802_1X 1 +#define WLAN_11i_AKMSS_PSK 2 +#define WLAN_11i_AKMSS_UNKNOWN 255 + +// Measurement type definitions reference ieee 802.11h Table 20b +#define MEASURE_TYPE_BASIC 0 +#define MEASURE_TYPE_CCA 1 +#define MEASURE_TYPE_RPI 2 + +// Measurement request mode definitions reference ieee 802.11h Figure 46h +#define MEASURE_MODE_ENABLE 0x02 +#define MEASURE_MODE_REQ 0x04 +#define MEASURE_MODE_REP 0x08 + +// Measurement report mode definitions reference ieee 802.11h Figure 46m +#define MEASURE_MODE_LATE 0x01 +#define MEASURE_MODE_INCAPABLE 0x02 +#define MEASURE_MODE_REFUSED 0x04 + + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + + +// Information Element Types + +#pragma pack(1) +typedef struct tagWLAN_IE { + BYTE byElementID; + BYTE len; +}__attribute__ ((__packed__)) +WLAN_IE, *PWLAN_IE; + + +// Service Set Identity (SSID) +#pragma pack(1) +typedef struct tagWLAN_IE_SSID { + BYTE byElementID; + BYTE len; + BYTE abySSID[1]; +}__attribute__ ((__packed__)) +WLAN_IE_SSID, *PWLAN_IE_SSID; + + +// Supported Rates +#pragma pack(1) +typedef struct tagWLAN_IE_SUPP_RATES { + BYTE byElementID; + BYTE len; + BYTE abyRates[1]; +}__attribute__ ((__packed__)) +WLAN_IE_SUPP_RATES, *PWLAN_IE_SUPP_RATES; + + + +// FH Parameter Set +#pragma pack(1) +typedef struct _WLAN_IE_FH_PARMS { + BYTE byElementID; + BYTE len; + WORD wDwellTime; + BYTE byHopSet; + BYTE byHopPattern; + BYTE byHopIndex; +} WLAN_IE_FH_PARMS, *PWLAN_IE_FH_PARMS; + + +// DS Parameter Set +#pragma pack(1) +typedef struct tagWLAN_IE_DS_PARMS { + BYTE byElementID; + BYTE len; + BYTE byCurrChannel; +}__attribute__ ((__packed__)) +WLAN_IE_DS_PARMS, *PWLAN_IE_DS_PARMS; + + +// CF Parameter Set +#pragma pack(1) +typedef struct tagWLAN_IE_CF_PARMS { + BYTE byElementID; + BYTE len; + BYTE byCFPCount; + BYTE byCFPPeriod; + WORD wCFPMaxDuration; + WORD wCFPDurRemaining; +}__attribute__ ((__packed__)) +WLAN_IE_CF_PARMS, *PWLAN_IE_CF_PARMS; + + +// TIM +#pragma pack(1) +typedef struct tagWLAN_IE_TIM { + BYTE byElementID; + BYTE len; + BYTE byDTIMCount; + BYTE byDTIMPeriod; + BYTE byBitMapCtl; + BYTE byVirtBitMap[1]; +}__attribute__ ((__packed__)) +WLAN_IE_TIM, *PWLAN_IE_TIM; + + +// IBSS Parameter Set +#pragma pack(1) +typedef struct tagWLAN_IE_IBSS_PARMS { + BYTE byElementID; + BYTE len; + WORD wATIMWindow; +}__attribute__ ((__packed__)) +WLAN_IE_IBSS_PARMS, *PWLAN_IE_IBSS_PARMS; + + +// Challenge Text +#pragma pack(1) +typedef struct tagWLAN_IE_CHALLENGE { + BYTE byElementID; + BYTE len; + BYTE abyChallenge[1]; +}__attribute__ ((__packed__)) +WLAN_IE_CHALLENGE, *PWLAN_IE_CHALLENGE; + + +#pragma pack(1) +typedef struct tagWLAN_IE_RSN_EXT { + BYTE byElementID; + BYTE len; + BYTE abyOUI[4]; + WORD wVersion; + BYTE abyMulticast[4]; + WORD wPKCount; + struct { + BYTE abyOUI[4]; + } PKSList[1]; // the rest is variable so need to + // overlay ieauth structure +} WLAN_IE_RSN_EXT, *PWLAN_IE_RSN_EXT; + +#pragma pack(1) +typedef struct tagWLAN_IE_RSN_AUTH { + WORD wAuthCount; + struct { + BYTE abyOUI[4]; + } AuthKSList[1]; +} WLAN_IE_RSN_AUTH, *PWLAN_IE_RSN_AUTH; + +// RSN Identity +#pragma pack(1) +typedef struct tagWLAN_IE_RSN { + BYTE byElementID; + BYTE len; + WORD wVersion; + BYTE abyRSN[WLAN_MIN_ARRAY]; +} WLAN_IE_RSN, *PWLAN_IE_RSN; + + +// ERP +#pragma pack(1) +typedef struct tagWLAN_IE_ERP { + BYTE byElementID; + BYTE len; + BYTE byContext; +}__attribute__ ((__packed__)) +WLAN_IE_ERP, *PWLAN_IE_ERP; + + +#pragma pack(1) +typedef struct _MEASEURE_REQ { + BYTE byChannel; + BYTE abyStartTime[8]; + BYTE abyDuration[2]; +} MEASEURE_REQ, *PMEASEURE_REQ, + MEASEURE_REQ_BASIC, *PMEASEURE_REQ_BASIC, + MEASEURE_REQ_CCA, *PMEASEURE_REQ_CCA, + MEASEURE_REQ_RPI, *PMEASEURE_REQ_RPI; + +typedef struct _MEASEURE_REP_BASIC { + BYTE byChannel; + BYTE abyStartTime[8]; + BYTE abyDuration[2]; + BYTE byMap; +} MEASEURE_REP_BASIC, *PMEASEURE_REP_BASIC; + +typedef struct _MEASEURE_REP_CCA { + BYTE byChannel; + BYTE abyStartTime[8]; + BYTE abyDuration[2]; + BYTE byCCABusyFraction; +} MEASEURE_REP_CCA, *PMEASEURE_REP_CCA; + +typedef struct _MEASEURE_REP_RPI { + BYTE byChannel; + BYTE abyStartTime[8]; + BYTE abyDuration[2]; + BYTE abyRPIdensity[8]; +} MEASEURE_REP_RPI, *PMEASEURE_REP_RPI; + +typedef union _MEASEURE_REP { + + MEASEURE_REP_BASIC sBasic; + MEASEURE_REP_CCA sCCA; + MEASEURE_REP_RPI sRPI; + +} MEASEURE_REP, *PMEASEURE_REP; + +typedef struct _WLAN_IE_MEASURE_REQ { + BYTE byElementID; + BYTE len; + BYTE byToken; + BYTE byMode; + BYTE byType; + MEASEURE_REQ sReq; +} WLAN_IE_MEASURE_REQ, *PWLAN_IE_MEASURE_REQ; + +typedef struct _WLAN_IE_MEASURE_REP { + BYTE byElementID; + BYTE len; + BYTE byToken; + BYTE byMode; + BYTE byType; + MEASEURE_REP sRep; +} WLAN_IE_MEASURE_REP, *PWLAN_IE_MEASURE_REP; + +typedef struct _WLAN_IE_CH_SW { + BYTE byElementID; + BYTE len; + BYTE byMode; + BYTE byChannel; + BYTE byCount; +} WLAN_IE_CH_SW, *PWLAN_IE_CH_SW; + +typedef struct _WLAN_IE_QUIET { + BYTE byElementID; + BYTE len; + BYTE byQuietCount; + BYTE byQuietPeriod; + BYTE abyQuietDuration[2]; + BYTE abyQuietOffset[2]; +} WLAN_IE_QUIET, *PWLAN_IE_QUIET; + +typedef struct _WLAN_IE_COUNTRY { + BYTE byElementID; + BYTE len; + BYTE abyCountryString[3]; + BYTE abyCountryInfo[3]; +} WLAN_IE_COUNTRY, *PWLAN_IE_COUNTRY; + +typedef struct _WLAN_IE_PW_CONST { + BYTE byElementID; + BYTE len; + BYTE byPower; +} WLAN_IE_PW_CONST, *PWLAN_IE_PW_CONST; + +typedef struct _WLAN_IE_PW_CAP { + BYTE byElementID; + BYTE len; + BYTE byMinPower; + BYTE byMaxPower; +} WLAN_IE_PW_CAP, *PWLAN_IE_PW_CAP; + +typedef struct _WLAN_IE_SUPP_CH { + BYTE byElementID; + BYTE len; + BYTE abyChannelTuple[2]; +} WLAN_IE_SUPP_CH, *PWLAN_IE_SUPP_CH; + +typedef struct _WLAN_IE_TPC_REQ { + BYTE byElementID; + BYTE len; +} WLAN_IE_TPC_REQ, *PWLAN_IE_TPC_REQ; + +typedef struct _WLAN_IE_TPC_REP { + BYTE byElementID; + BYTE len; + BYTE byTxPower; + BYTE byLinkMargin; +} WLAN_IE_TPC_REP, *PWLAN_IE_TPC_REP; + + +typedef struct _WLAN_IE_IBSS_DFS { + BYTE byElementID; + BYTE len; + BYTE abyDFSOwner[6]; + BYTE byDFSRecovery; + BYTE abyChannelMap[2]; +} WLAN_IE_IBSS_DFS, *PWLAN_IE_IBSS_DFS; + +#pragma pack() + + + +// Frame Types +// prototype structure, all mgmt frame types will start with these members +typedef struct tagWLAN_FR_MGMT { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + +} WLAN_FR_MGMT, *PWLAN_FR_MGMT; + +// Beacon frame +typedef struct tagWLAN_FR_BEACON { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + // fixed fields + PQWORD pqwTimestamp; + PWORD pwBeaconInterval; + PWORD pwCapInfo; + /*-- info elements ----------*/ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; +// PWLAN_IE_FH_PARMS pFHParms; + PWLAN_IE_DS_PARMS pDSParms; + PWLAN_IE_CF_PARMS pCFParms; + PWLAN_IE_TIM pTIM; + PWLAN_IE_IBSS_PARMS pIBSSParms; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_ERP pERP; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_COUNTRY pIE_Country; + PWLAN_IE_PW_CONST pIE_PowerConstraint; + PWLAN_IE_CH_SW pIE_CHSW; + PWLAN_IE_IBSS_DFS pIE_IBSSDFS; + PWLAN_IE_QUIET pIE_Quiet; + +} WLAN_FR_BEACON, *PWLAN_FR_BEACON; + + +// IBSS ATIM frame +typedef struct tagWLAN_FR_IBSSATIM { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + + // fixed fields + // info elements + // this frame type has a null body + +} WLAN_FR_IBSSATIM, *PWLAN_FR_IBSSATIM; + +// Disassociation +typedef struct tagWLAN_FR_DISASSOC { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwReason; + /*-- info elements ----------*/ + +} WLAN_FR_DISASSOC, *PWLAN_FR_DISASSOC; + +// Association Request +typedef struct tagWLAN_FR_ASSOCREQ { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwCapInfo; + PWORD pwListenInterval; + /*-- info elements ----------*/ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_PW_CAP pCurrPowerCap; + PWLAN_IE_SUPP_CH pCurrSuppCh; + +} WLAN_FR_ASSOCREQ, *PWLAN_FR_ASSOCREQ; + +// Association Response +typedef struct tagWLAN_FR_ASSOCRESP { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwCapInfo; + PWORD pwStatus; + PWORD pwAid; + /*-- info elements ----------*/ + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_ASSOCRESP, *PWLAN_FR_ASSOCRESP; + +// Reassociation Request +typedef struct tagWLAN_FR_REASSOCREQ { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + + /*-- fixed fields -----------*/ + PWORD pwCapInfo; + PWORD pwListenInterval; + PIEEE_ADDR pAddrCurrAP; + + /*-- info elements ----------*/ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_REASSOCREQ, *PWLAN_FR_REASSOCREQ; + +// Reassociation Response +typedef struct tagWLAN_FR_REASSOCRESP { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwCapInfo; + PWORD pwStatus; + PWORD pwAid; + /*-- info elements ----------*/ + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_REASSOCRESP, *PWLAN_FR_REASSOCRESP; + +// Probe Request +typedef struct tagWLAN_FR_PROBEREQ { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + /*-- info elements ----------*/ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_SUPP_RATES pExtSuppRates; + +} WLAN_FR_PROBEREQ, *PWLAN_FR_PROBEREQ; + +// Probe Response +typedef struct tagWLAN_FR_PROBERESP { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PQWORD pqwTimestamp; + PWORD pwBeaconInterval; + PWORD pwCapInfo; + /*-- info elements ----------*/ + PWLAN_IE_SSID pSSID; + PWLAN_IE_SUPP_RATES pSuppRates; + PWLAN_IE_DS_PARMS pDSParms; + PWLAN_IE_CF_PARMS pCFParms; + PWLAN_IE_IBSS_PARMS pIBSSParms; + PWLAN_IE_RSN pRSN; + PWLAN_IE_RSN_EXT pRSNWPA; + PWLAN_IE_ERP pERP; + PWLAN_IE_SUPP_RATES pExtSuppRates; + PWLAN_IE_COUNTRY pIE_Country; + PWLAN_IE_PW_CONST pIE_PowerConstraint; + PWLAN_IE_CH_SW pIE_CHSW; + PWLAN_IE_IBSS_DFS pIE_IBSSDFS; + PWLAN_IE_QUIET pIE_Quiet; + +} WLAN_FR_PROBERESP, *PWLAN_FR_PROBERESP; + +// Authentication +typedef struct tagWLAN_FR_AUTHEN { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwAuthAlgorithm; + PWORD pwAuthSequence; + PWORD pwStatus; + /*-- info elements ----------*/ + PWLAN_IE_CHALLENGE pChallenge; + +} WLAN_FR_AUTHEN, *PWLAN_FR_AUTHEN; + +// Deauthenication +typedef struct tagWLAN_FR_DEAUTHEN { + + UINT uType; + UINT len; + PBYTE pBuf; + PUWLAN_80211HDR pHdr; + /*-- fixed fields -----------*/ + PWORD pwReason; + + /*-- info elements ----------*/ + +} WLAN_FR_DEAUTHEN, *PWLAN_FR_DEAUTHEN; + +/*--------------------- Export Functions --------------------------*/ +VOID +vMgrEncodeBeacon( + IN PWLAN_FR_BEACON pFrame + ); + +VOID +vMgrDecodeBeacon( + IN PWLAN_FR_BEACON pFrame + ); + +VOID +vMgrEncodeIBSSATIM( + IN PWLAN_FR_IBSSATIM pFrame + ); + +VOID +vMgrDecodeIBSSATIM( + IN PWLAN_FR_IBSSATIM pFrame + ); + +VOID +vMgrEncodeDisassociation( + IN PWLAN_FR_DISASSOC pFrame + ); + +VOID +vMgrDecodeDisassociation( + IN PWLAN_FR_DISASSOC pFrame + ); + +VOID +vMgrEncodeAssocRequest( + IN PWLAN_FR_ASSOCREQ pFrame + ); + +VOID +vMgrDecodeAssocRequest( + IN PWLAN_FR_ASSOCREQ pFrame + ); + +VOID +vMgrEncodeAssocResponse( + IN PWLAN_FR_ASSOCRESP pFrame + ); + +VOID +vMgrDecodeAssocResponse( + IN PWLAN_FR_ASSOCRESP pFrame + ); + +VOID +vMgrEncodeReassocRequest( + IN PWLAN_FR_REASSOCREQ pFrame + ); + +VOID +vMgrDecodeReassocRequest( + IN PWLAN_FR_REASSOCREQ pFrame + ); + +VOID +vMgrEncodeProbeRequest( + IN PWLAN_FR_PROBEREQ pFrame + ); + +VOID +vMgrDecodeProbeRequest( + IN PWLAN_FR_PROBEREQ pFrame + ); + +VOID +vMgrEncodeProbeResponse( + IN PWLAN_FR_PROBERESP pFrame + ); + +VOID +vMgrDecodeProbeResponse( + IN PWLAN_FR_PROBERESP pFrame + ); + +VOID +vMgrEncodeAuthen( + IN PWLAN_FR_AUTHEN pFrame + ); + +VOID +vMgrDecodeAuthen( + IN PWLAN_FR_AUTHEN pFrame + ); + +VOID +vMgrEncodeDeauthen( + IN PWLAN_FR_DEAUTHEN pFrame + ); + +VOID +vMgrDecodeDeauthen( + IN PWLAN_FR_DEAUTHEN pFrame + ); + +VOID +vMgrEncodeReassocResponse( + IN PWLAN_FR_REASSOCRESP pFrame + ); + +VOID +vMgrDecodeReassocResponse( + IN PWLAN_FR_REASSOCRESP pFrame + ); + +#endif// __80211MGR_H__ diff --git a/drivers/staging/vt6655/IEEE11h.c b/drivers/staging/vt6655/IEEE11h.c new file mode 100644 index 00000000000..5f25b8e88bd --- /dev/null +++ b/drivers/staging/vt6655/IEEE11h.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1996, 2005 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: IEEE11h.c + * + * Purpose: + * + * Functions: + * + * Revision History: + * + * Author: Yiching Chen + * + * Date: Mar. 31, 2005 + * + */ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__IEEE11h_H__) +#include "IEEE11h.h" +#endif + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif + + + +/*--------------------- Static Definitions -------------------------*/ +static int msglevel =MSG_LEVEL_INFO; + +#pragma pack(1) + +typedef struct _WLAN_FRAME_ACTION { + WLAN_80211HDR_A3 Header; + BYTE byCategory; + BYTE byAction; + BYTE abyVars[1]; +} WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION; + +typedef struct _WLAN_FRAME_MSRREQ { + WLAN_80211HDR_A3 Header; + BYTE byCategory; + BYTE byAction; + BYTE byDialogToken; + WLAN_IE_MEASURE_REQ sMSRReqEIDs[1]; +} WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ; + +typedef struct _WLAN_FRAME_MSRREP { + WLAN_80211HDR_A3 Header; + BYTE byCategory; + BYTE byAction; + BYTE byDialogToken; + WLAN_IE_MEASURE_REP sMSRRepEIDs[1]; +} WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP; + +typedef struct _WLAN_FRAME_TPCREQ { + WLAN_80211HDR_A3 Header; + BYTE byCategory; + BYTE byAction; + BYTE byDialogToken; + WLAN_IE_TPC_REQ sTPCReqEIDs; +} WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ; + +typedef struct _WLAN_FRAME_TPCREP { + WLAN_80211HDR_A3 Header; + BYTE byCategory; + BYTE byAction; + BYTE byDialogToken; + WLAN_IE_TPC_REP sTPCRepEIDs; +} WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP; + +#pragma pack() + +// action field reference ieee 802.11h Table 20e +#define ACTION_MSRREQ 0 +#define ACTION_MSRREP 1 +#define ACTION_TPCREQ 2 +#define ACTION_TPCREP 3 +#define ACTION_CHSW 4 + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +static BOOL s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq, UINT uLength) +{ + UINT uNumOfEIDs = 0; + BOOL bResult = TRUE; + + if (uLength <= WLAN_A3FR_MAXLEN) { + MEMvCopy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength); + } + uNumOfEIDs = ((uLength - OFFSET(WLAN_FRAME_MSRREQ, sMSRReqEIDs))/ (sizeof(WLAN_IE_MEASURE_REQ))); + pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]); + pMgmt->uLengthOfRepEIDs = 0; + bResult = CARDbStartMeasure(pMgmt->pAdapter, + ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs, + uNumOfEIDs + ); + return (bResult); +} + + +static BOOL s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, BYTE byRate, BYTE byRSSI) +{ + PWLAN_FRAME_TPCREP pFrame; + PSTxMgmtPacket pTxPacket = NULL; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + + pFrame = (PWLAN_FRAME_TPCREP)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + + pFrame->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) + ); + + MEMvCopy( pFrame->Header.abyAddr1, pTPCReq->Header.abyAddr2, WLAN_ADDR_LEN); + MEMvCopy( pFrame->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); + MEMvCopy( pFrame->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + pFrame->byCategory = 0; + pFrame->byAction = 3; + pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken; + + pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP; + pFrame->sTPCRepEIDs.len = 2; + pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); + switch (byRate) { + case RATE_54M: + pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI; + break; + case RATE_48M: + pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI; + break; + case RATE_36M: + pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI; + break; + case RATE_24M: + pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI; + break; + case RATE_18M: + pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI; + break; + case RATE_12M: + pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI; + break; + case RATE_9M: + pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI; + break; + case RATE_6M: + default: + pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI; + break; + } + + pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP); + pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - WLAN_HDR_ADDR3_LEN; + if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) + return (FALSE); + return (TRUE); +// return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, sizeof(WLAN_FRAME_TPCREP))); + +} + + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +/*+ + * + * Description: + * Handles action management frames. + * + * Parameters: + * In: + * pMgmt - Management Object structure + * pRxPacket - Received packet + * Out: + * none + * + * Return Value: None. + * +-*/ +BOOL +IEEE11hbMgrRxAction ( + IN PVOID pMgmtHandle, + IN PVOID pRxPacket + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; + PWLAN_FRAME_ACTION pAction = NULL; + UINT uLength = 0; + PWLAN_IE_CH_SW pChannelSwitch = NULL; + + + // decode the frame + uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen; + if (uLength > WLAN_A3FR_MAXLEN) { + return (FALSE); + } + + + pAction = (PWLAN_FRAME_ACTION) (((PSRxMgmtPacket)pRxPacket)->p80211Header); + + if (pAction->byCategory == 0) { + switch (pAction->byAction) { + case ACTION_MSRREQ: + return (s_bRxMSRReq(pMgmt, (PWLAN_FRAME_MSRREQ) pAction, uLength)); + break; + case ACTION_MSRREP: + break; + case ACTION_TPCREQ: + return (s_bRxTPCReq(pMgmt, + (PWLAN_FRAME_TPCREQ) pAction, + ((PSRxMgmtPacket)pRxPacket)->byRxRate, + (BYTE) ((PSRxMgmtPacket)pRxPacket)->uRSSI)); + break; + case ACTION_TPCREP: + break; + case ACTION_CHSW: + pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars); + if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) && + (pChannelSwitch->len == 3)) { + // valid element id + CARDbChannelSwitch( pMgmt->pAdapter, + pChannelSwitch->byMode, + CARDbyGetChannelMapping(pMgmt->pAdapter, pChannelSwitch->byChannel, pMgmt->eCurrentPHYMode), + pChannelSwitch->byCount + ); + } + break; + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Action = %d\n", pAction->byAction); + break; + } + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", pAction->byCategory); + pAction->byCategory |= 0x80; + + //return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, uLength)); + return (TRUE); + } + return (TRUE); +} + + +BOOL IEEE11hbMSRRepTx ( + IN PVOID pMgmtHandle + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; + PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket)); + UINT uLength = 0; + PSTxMgmtPacket pTxPacket = NULL; + + pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + + + pMSRRep->Header.wFrameCtl = ( WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) + ); + + MEMvCopy( pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN); + MEMvCopy( pMSRRep->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); + MEMvCopy( pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + pMSRRep->byCategory = 0; + pMSRRep->byAction = 1; + pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken; + + uLength = pMgmt->uLengthOfRepEIDs + OFFSET(WLAN_FRAME_MSRREP, sMSRRepEIDs); + + pTxPacket->cbMPDULen = uLength; + pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN; + if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) + return (FALSE); + return (TRUE); +// return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, uLength)); + +} + diff --git a/drivers/staging/vt6655/IEEE11h.h b/drivers/staging/vt6655/IEEE11h.h new file mode 100644 index 00000000000..22bcaf1f681 --- /dev/null +++ b/drivers/staging/vt6655/IEEE11h.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1996, 2005 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: IEEE11h.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with IEEE 802.11h. + * + * Author: Yiching Chen + * + * Date: Mar. 31, 2005 + * + */ + +#ifndef __IEEE11h_H__ +#define __IEEE11h_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL IEEE11hbMSRRepTx ( + IN PVOID pMgmtHandle + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __IEEE11h_H__ diff --git a/drivers/staging/vt6655/Makefile b/drivers/staging/vt6655/Makefile new file mode 100644 index 00000000000..be44423c117 --- /dev/null +++ b/drivers/staging/vt6655/Makefile @@ -0,0 +1,218 @@ +# +# Build options: +# PRIV_OBJ := 1 for object version +# + +IO_MAP := 0 +HOSTAP := 1 +PRIV_OBJ := 0 + + + +#KSP : = 0 +KSP := /lib/modules/$(shell uname -r)/build \ +# /usr/src/linux-$(shell uname -r) \ +# /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ +# /usr/src/kernel-headers-$(shell uname -r) \ +# /usr/src/kernel-source-$(shell uname -r) \ +# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ +# /usr/src/linux /home/plice + +#test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) + +#KSP := $(foreach dir, $(KSP), $(test_dir)) + + +KSRC := $(firstword $(KSP)) + +#ifeq (,$(KSRC)) +# $( error Linux kernel source not found) +#endif + +# check kernel version +KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/') +KERVER2=$(shell uname -r | cut -d. -f2) + +ifeq ($(KVER), 2.6) +# 2.6 kernel +TARGET = viawget.ko + +else +TARGET = viawget.o + +endif + +INSTDIR := $(shell find /lib/modules/$(shell uname -r) -name $(TARGET) -printf "%h\n" | sort | head -1) +ifeq (,$(INSTDIR)) + ifeq (,$(KERVER2)) + ifneq (,$(wildcard /lib/modules/$(shell uname -r)/kernel)) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + else + ifneq ($(KERVER2),2) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + endif +endif + + +SRC = device_main.c card.c mac.c baseband.c wctl.c 80211mgr.c \ + wcmd.c wmgr.c bssdb.c wpa2.c rxtx.c dpc.c power.c datarate.c \ + srom.c mib.c rc4.c tether.c tcrc.c ioctl.c hostap.c wpa.c key.c \ + tkip.c michael.c wroute.c rf.c iwctl.c wpactl.c aes_ccmp.c \ + vntwifi.c IEEE11h.c + +ifeq ($(IO_MAP), 1) + EXTRA_CFLAGS += -DIO_MAP +endif + +ifeq ($(HOSTAP), 1) + EXTRA_CFLAGS += -DHOSTAP +endif + +ifeq ($(PRIV_OBJ), 1) + EXTRA_CFLAGS += -DPRIVATE_OBJ +endif + +EXTRA_CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/../solomon + +EXTRA_CFLAGS += -I$(PWD)/include -I$(PWD)/solomon + +# build rule +ifeq ($(KVER), 2.6) +# 2.6 kernel + +ifndef KERNEL_CONF +KERNEL_CONF= $(KSRC)/.config +endif + +include ${KERNEL_CONF} + +obj-m += viawget.o + +viawget-objs := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o aes_ccmp.o \ + vntwifi.o IEEE11h.o + +.c.o: + $(CC) $(CFLAGS) -o $@ $< + +default: + make -C $(KSRC) SUBDIRS=$(shell pwd) modules + +else + +# 2.2/2.4 kernel +OBJS := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o aes_ccmp.o \ + vntwifi.o IEEE11h.o + +VERSION_FILE := $(KSRC)/include/linux/version.h +CONFIG_FILE := $(KSRC)/include/linux/config.h + + +ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) +endif + +ifeq (,$(wildcard $(CONFIG_FILE))) + $(error Linux kernel source not configured - missing config.h) +endif + +ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version))) + CC := kgcc gcc cc +else + CC := gcc cc +endif + +test_cc = $(shell which $(cc) > /dev/null 2>&1 && echo $(cc)) +CC := $(foreach cc, $(CC), $(test_cc)) +CC := $(firstword $(CC)) + +EXTRA_CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe +EXTRA_CFLAGS += -I$(KSRC)/include -Wstrict-prototypes -fomit-frame-pointer -fno-strict-aliasing +EXTRA_CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ + echo "-DMODVERSIONS -include $(KSRC)/include/linux/modversions.h") + +.SILENT: $(TARGET) clean + + +# look for SMP in config.h +SMP := $(shell $(CC) $(CFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{ print $$3 }') + +ifneq ($(SMP),1) + SMP := 0 +endif + + +ifeq ($(SMP), 1) + EXTRA_CFLAGS += -D__SMP__ +endif + + +ifeq ($(PRIV_OBJ), 1) + EXTRA_CFLAGS += -DPRIVATE_OBJ + TARGET = x86g_up.o + +ifeq ($(SMP), 1) + TARGET = x86g_smp.o +endif + +endif + + +# check x86_64 +SUBARCH := $(shell uname -m) +ifeq ($(SUBARCH),x86_64) + EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone +endif + + +$(TARGET): $(filter-out $(TARGET), $(SRC:.c=.o)) + $(LD) -r $^ -o $@ + echo; echo + echo "**************************************************" + echo "Build options:" + echo " VERSION $(KVER)" + echo -n " SMP " + if [ "$(SMP)" = "1" ]; \ + then echo "Enabled"; else echo "Disabled"; fi + + + +endif # ifeq ($(KVER),2.6) + + +ifeq ($(KVER), 2.6) +install: default +else +install: clean $(TARGET) +endif + mkdir -p $(MOD_ROOT)$(INSTDIR) + install -m 644 -o root $(TARGET) $(MOD_ROOT)$(INSTDIR) + +ifeq (,$(MOD_ROOT)) + /sbin/depmod -a || true +else + /sbin/depmod -b $(MOD_ROOT) -a || true +endif + + +uninstall: + rm -f $(INSTDIR)/$(TARGET) + /sbin/depmod -a + +clean: + rm -f $(TARGET) $(SRC:.c=.o) *.o *~ + rm -f .*.o.d .*.o.cmd .*.ko.cmd *.mod.c *.mod.o + +-include .depend.mak diff --git a/drivers/staging/vt6655/Makefile.arm b/drivers/staging/vt6655/Makefile.arm new file mode 100644 index 00000000000..2d2ccaded6a --- /dev/null +++ b/drivers/staging/vt6655/Makefile.arm @@ -0,0 +1,181 @@ +# +# +# Build options: +# PRIV_OBJ := 1 for object version +# BIG_ENDIAN := 1 for big-endian mode +# +# arm-linux-tools chain are located at: +# /usr/local/bin/arm-linux-gcc +# /usr/local/bin/arm-linux-ld +# + +IO_MAP := 0 +HOSTAP := 1 +PRIV_OBJ := 1 +BIG_ENDIAN := 1 + +test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) +KSP := $(foreach dir, $(KSP), $(test_dir)) + +KSRC := $(firstword $(KSP)) + +#ifeq (,$(KSRC)) +# $(error Linux kernel source not found) +#endif + +# check kernel version +KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/') +KERVER2=$(shell uname -r | cut -d. -f2) + +ifeq ($(KVER), 2.6) +# 2.6 kernel +TARGET = viawget.ko + +else +TARGET = viawget.o + +endif + +INSTDIR := $(shell find /lib/modules/$(shell uname -r) -name $(TARGET) -printf "%h\n" | sort | head -1) +ifeq (,$(INSTDIR)) + ifeq (,$(KERVER2)) + ifneq (,$(wildcard /lib/modules/$(shell uname -r)/kernel)) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + else + ifneq ($(KERVER2),2) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + endif +endif + + +SRC = device_main.c card.c mac.c baseband.c wctl.c 80211mgr.c \ + wcmd.c wmgr.c bssdb.c rxtx.c dpc.c power.c datarate.c srom.c \ + mib.c rc4.c tether.c tcrc.c ioctl.c hostap.c wpa.c key.c tkip.c \ + michael.c wroute.c rf.c iwctl.c wpactl.c wpa2.c aes_ccmp.c + +ifeq ($(IO_MAP), 1) + CFLAGS += -DIO_MAP +endif + +ifeq ($(HOSTAP), 1) + CFLAGS += -DHOSTAP +endif + +ifeq ($(PRIV_OBJ), 1) + CFLAGS += -DPRIVATE_OBJ +endif + +ifeq ($(BIG_ENDIAN), 1) + CFLAGS += -D__BIG_ENDIAN + CFLAGS += -mbig-endian + LDOPTS += -EB +else + CFLAGS += -mlittle-endian + LDOPTS += -EL +endif + +CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/../solomon + + +# build rule +ifeq ($(KVER), 2.6) +# 2.6 kernel + +ifndef KERNEL_CONF +KERNEL_CONF= $(KSRC)/.config +endif + +include ${KERNEL_CONF} + +obj-m += viawget.o + +viawget-objs := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o aes_ccmp.o + +.c.o: + $(CC) $(CFLAGS) -o $@ $< + +default: + make -C $(KSRC) SUBDIRS=$(shell pwd) modules + +else + +# 2.2/2.4 kernel +OBJS := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o + + +CC := /usr/local/bin/arm-linux-gcc +LD := /usr/local/bin/arm-linux-ld + +CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe +#CFLAGS += -Wstrict-prototypes -fomit-frame-pointer +COPTS+= -march=armv4 -fno-strict-aliasing -fno-common +#COPTS+= -mapcs-32 -mtune=xscale -mshort-load-bytes -msoft-float -mfp=2 +#COPTS+= -mthumb -mcpu=arm9 -ffunction-sections -fdata-sections + + +.SILENT: $(TARGET) clean + + + +ifeq ($(PRIV_OBJ), 1) + +ifeq ($(BIG_ENDIAN), 1) + TARGET = arm_be_g.o +else + TARGET = arm_le_g.o +endif + +endif + + + +$(TARGET): $(filter-out $(TARGET), $(SRC:.c=.o)) + $(LD) $(LDOPTS) -r $^ -o $@ + echo + echo "***********************************" + echo "Build options:" + echo " VERSION $(KVER)" + echo -n " SMP " + if [ "$(SMP)" = "1" ]; \ + then echo "Enabled"; else echo "Disabled"; fi + + +endif # ifeq ($(KVER),2.6) + + +ifeq ($(KVER), 2.6) +install: default +else +install: clean $(TARGET) +endif + mkdir -p $(MOD_ROOT)$(INSTDIR) + install -m 644 -o root $(TARGET) $(MOD_ROOT)$(INSTDIR) + +ifeq (,$(MOD_ROOT)) + /sbin/depmod -a || true +else + /sbin/depmod -b $(MOD_ROOT) -a || true +endif + + +uninstall: + rm -f $(INSTDIR)/$(TARGET) + /sbin/depmod -a + +clean: + rm -f $(TARGET) $(SRC:.c=.o) *~ + rm -f .*.o.d .*.o.cmd .*.ko.cmd *.mod.c *.mod.o + +-include .depend.mak diff --git a/drivers/staging/vt6655/Makefile.x86 b/drivers/staging/vt6655/Makefile.x86 new file mode 100644 index 00000000000..69082f09ba7 --- /dev/null +++ b/drivers/staging/vt6655/Makefile.x86 @@ -0,0 +1,209 @@ +# +# Build options: +# PRIV_OBJ := 1 for object version +# + +IO_MAP := 0 +HOSTAP := 1 +PRIV_OBJ := 1 + +KSP := /lib/modules/$(shell uname -r)/build \ + /usr/src/linux-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ + /usr/src/kernel-headers-$(shell uname -r) \ + /usr/src/kernel-source-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux + +test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) +KSP := $(foreach dir, $(KSP), $(test_dir)) + +KSRC := $(firstword $(KSP)) + +ifeq (,$(KSRC)) + $(error Linux kernel source not found) +endif + +# check kernel version +KVER := $(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/') +KERVER2=$(shell uname -r | cut -d. -f2) + +ifeq ($(KVER), 2.6) +# 2.6 kernel +TARGET = viawget.ko + +else +TARGET = viawget.o + +endif + +INSTDIR := $(shell find /lib/modules/$(shell uname -r) -name $(TARGET) -printf "%h\n" | sort | head -1) +ifeq (,$(INSTDIR)) + ifeq (,$(KERVER2)) + ifneq (,$(wildcard /lib/modules/$(shell uname -r)/kernel)) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + else + ifneq ($(KERVER2),2) + INSTDIR := /lib/modules/$(shell uname -r)/kernel/drivers/net + else + INSTDIR := /lib/modules/$(shell uname -r)/net + endif + endif +endif + + +SRC = device_main.c card.c mac.c baseband.c wctl.c 80211mgr.c \ + wcmd.c wmgr.c bssdb.c wpa2.c rxtx.c dpc.c power.c datarate.c \ + srom.c mib.c rc4.c tether.c tcrc.c ioctl.c hostap.c wpa.c key.c \ + tkip.c michael.c wroute.c rf.c iwctl.c wpactl.c aes_ccmp.c + +ifeq ($(IO_MAP), 1) + CFLAGS += -DIO_MAP +endif + +ifeq ($(HOSTAP), 1) + CFLAGS += -DHOSTAP +endif + +ifeq ($(PRIV_OBJ), 1) + CFLAGS += -DPRIVATE_OBJ +endif + +CFLAGS += -I$(PWD) -I$(PWD)/../include -I$(PWD)/../solomon + + +# build rule +ifeq ($(KVER), 2.6) +# 2.6 kernel + +ifndef KERNEL_CONF +KERNEL_CONF= $(KSRC)/.config +endif + +include ${KERNEL_CONF} + +obj-m += viawget.o + +viawget-objs := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o aes_ccmp.o + +.c.o: + $(CC) $(CFLAGS) -o $@ $< + +default: + make -C $(KSRC) SUBDIRS=$(shell pwd) modules + +else + +# 2.2/2.4 kernel +OBJS := device_main.o card.o mac.o baseband.o wctl.o 80211mgr.o \ + wcmd.o wmgr.o bssdb.o rxtx.o dpc.o power.o datarate.o srom.o \ + mib.o rc4.o tether.o tcrc.o ioctl.o hostap.o wpa.o key.o tkip.o \ + michael.o wroute.o rf.o iwctl.o wpactl.o wpa2.o aes_ccmp.o + +VERSION_FILE := $(KSRC)/include/linux/version.h +CONFIG_FILE := $(KSRC)/include/linux/config.h + + +ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) +endif + +ifeq (,$(wildcard $(CONFIG_FILE))) + $(error Linux kernel source not configured - missing config.h) +endif + +ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version))) + CC := kgcc gcc cc +else + CC := gcc cc +endif + +test_cc = $(shell which $(cc) > /dev/null 2>&1 && echo $(cc)) +CC := $(foreach cc, $(CC), $(test_cc)) +CC := $(firstword $(CC)) + +CFLAGS += -Wall -DLINUX -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -D__NO_VERSION__ -O2 -pipe +CFLAGS += -I$(KSRC)/include -Wstrict-prototypes -fomit-frame-pointer +CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ + echo "-DMODVERSIONS -include $(KSRC)/include/linux/modversions.h") + +.SILENT: $(TARGET) clean + + +# look for SMP in config.h +SMP := $(shell $(CC) $(CFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{ print $$3 }') + +ifneq ($(SMP),1) + SMP := 0 +endif + + +ifeq ($(SMP), 1) + CFLAGS += -D__SMP__ +endif + + +ifeq ($(PRIV_OBJ), 1) + CFLAGS += -DPRIVATE_OBJ + TARGET = x86g_up.o + +ifeq ($(SMP), 1) + TARGET = x86g_smp.o +endif + +endif + + +# check x86_64 +SUBARCH := $(shell uname -m) +ifeq ($(SUBARCH),x86_64) + CFLAGS += -mcmodel=kernel -mno-red-zone +endif + + +$(TARGET): $(filter-out $(TARGET), $(SRC:.c=.o)) + $(LD) -r $^ -o $@ + echo; echo + echo "**************************************************" + echo "Build options:" + echo " VERSION $(KVER)" + echo -n " SMP " + if [ "$(SMP)" = "1" ]; \ + then echo "Enabled"; else echo "Disabled"; fi + + + +endif # ifeq ($(KVER),2.6) + + +ifeq ($(KVER), 2.6) +install: default +else +install: clean $(TARGET) +endif + mkdir -p $(MOD_ROOT)$(INSTDIR) + install -m 644 -o root $(TARGET) $(MOD_ROOT)$(INSTDIR) + +ifeq (,$(MOD_ROOT)) + /sbin/depmod -a || true +else + /sbin/depmod -b $(MOD_ROOT) -a || true +endif + + +uninstall: + rm -f $(INSTDIR)/$(TARGET) + /sbin/depmod -a + +clean: + rm -f $(TARGET) $(SRC:.c=.o) *~ + rm -f .*.o.d .*.o.cmd .*.ko.cmd *.mod.c *.mod.o + +-include .depend.mak diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c new file mode 100644 index 00000000000..59cc018d48a --- /dev/null +++ b/drivers/staging/vt6655/aes_ccmp.c @@ -0,0 +1,410 @@ +/* + * 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: aes_ccmp.c + * + * Purpose: AES_CCMP decryption + * + * Author: Warren Hsu + * + * Date: Feb 15, 2005 + * + * Functions: + * AESbGenCCMP - Parsing RX-packet + * + * + * Revision History: + * + */ + +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/* + * SBOX Table + */ + +BYTE sbox_table[256] = +{ +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, +0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, +0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, +0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, +0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, +0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, +0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, +0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +BYTE dot2_table[256] = { +0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, +0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, +0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, +0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, +0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, +0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, +0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, +0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, +0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, +0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, +0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, +0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, +0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, +0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, +0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, +0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 +}; + +BYTE dot3_table[256] = { +0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, +0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, +0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, +0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, +0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, +0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, +0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, +0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, +0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, +0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, +0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, +0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, +0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, +0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, +0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, +0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a +}; + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +void xor_128(BYTE *a, BYTE *b, BYTE *out) +{ +PDWORD dwPtrA = (PDWORD) a; +PDWORD dwPtrB = (PDWORD) b; +PDWORD dwPtrOut =(PDWORD) out; + + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); +} + + +void xor_32(BYTE *a, BYTE *b, BYTE *out) +{ +PDWORD dwPtrA = (PDWORD) a; +PDWORD dwPtrB = (PDWORD) b; +PDWORD dwPtrOut =(PDWORD) out; + + (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); +} + +void AddRoundKey(BYTE *key, int round) +{ +BYTE sbox_key[4]; +BYTE rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + + sbox_key[0] = sbox_table[key[13]]; + sbox_key[1] = sbox_table[key[14]]; + sbox_key[2] = sbox_table[key[15]]; + sbox_key[3] = sbox_table[key[12]]; + + key[0] = key[0] ^ rcon_table[round]; + xor_32(&key[0], sbox_key, &key[0]); + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +void SubBytes(BYTE *in, BYTE *out) +{ +int i; + + for (i=0; i< 16; i++) + { + out[i] = sbox_table[in[i]]; + } +} + +void ShiftRows(BYTE *in, BYTE *out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +void MixColumns(BYTE *in, BYTE *out) +{ + + out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3]; + out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3]; + out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]]; + out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]]; +} + + +void AESv128(BYTE *key, BYTE *data, BYTE *ciphertext) +{ +int i; +int round; +BYTE TmpdataA[16]; +BYTE TmpdataB[16]; +BYTE abyRoundKey[16]; + + for(i=0; i<16; i++) + abyRoundKey[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(abyRoundKey, data, ciphertext); + AddRoundKey(abyRoundKey, round); + } + else if (round == 10) + { + SubBytes(ciphertext, TmpdataA); + ShiftRows(TmpdataA, TmpdataB); + xor_128(TmpdataB, abyRoundKey, ciphertext); + } + else // round 1 ~ 9 + { + SubBytes(ciphertext, TmpdataA); + ShiftRows(TmpdataA, TmpdataB); + MixColumns(&TmpdataB[0], &TmpdataA[0]); + MixColumns(&TmpdataB[4], &TmpdataA[4]); + MixColumns(&TmpdataB[8], &TmpdataA[8]); + MixColumns(&TmpdataB[12], &TmpdataA[12]); + xor_128(TmpdataA, abyRoundKey, ciphertext); + AddRoundKey(abyRoundKey, round); + } + } + +} + +/* + * Description: AES decryption + * + * Parameters: + * In: + * pbyRxKey - The key used to decrypt + * pbyFrame - Starting address of packet header + * wFrameSize - Total packet size including CRC + * Out: + * none + * + * Return Value: MIC compare result + * + */ +BOOL AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize) +{ +BYTE abyNonce[13]; +BYTE MIC_IV[16]; +BYTE MIC_HDR1[16]; +BYTE MIC_HDR2[16]; +BYTE abyMIC[16]; +BYTE abyCTRPLD[16]; +BYTE abyTmp[16]; +BYTE abyPlainText[16]; +BYTE abyLastCipher[16]; + +PS802_11Header pMACHeader = (PS802_11Header) pbyFrame; +PBYTE pbyIV; +PBYTE pbyPayload; +WORD wHLen = 22; +WORD wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC +BOOL bA4 = FALSE; +BYTE byTmp; +WORD wCnt; +int ii,jj,kk; + + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && + WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + bA4 = TRUE; + pbyIV += 6; // 6 is 802.11 address4 + wHLen += 6; + wPayloadSize -= 6; + } + pbyPayload = pbyIV + 8; //IV-length + + abyNonce[0] = 0x00; //now is 0, if Qos here will be priority + MEMvCopy(&(abyNonce[1]), pMACHeader->abyAddr2, U_ETHER_ADDR_LEN); + abyNonce[7] = pbyIV[7]; + abyNonce[8] = pbyIV[6]; + abyNonce[9] = pbyIV[5]; + abyNonce[10] = pbyIV[4]; + abyNonce[11] = pbyIV[1]; + abyNonce[12] = pbyIV[0]; + + //MIC_IV + MIC_IV[0] = 0x59; + MEMvCopy(&(MIC_IV[1]), &(abyNonce[0]), 13); + MIC_IV[14] = (BYTE)(wPayloadSize >> 8); + MIC_IV[15] = (BYTE)(wPayloadSize & 0xff); + + //MIC_HDR1 + MIC_HDR1[0] = (BYTE)(wHLen >> 8); + MIC_HDR1[1] = (BYTE)(wHLen & 0xff); + byTmp = (BYTE)(pMACHeader->wFrameCtl & 0xff); + MIC_HDR1[2] = byTmp & 0x8f; + byTmp = (BYTE)(pMACHeader->wFrameCtl >> 8); + byTmp &= 0x87; + MIC_HDR1[3] = byTmp | 0x40; + MEMvCopy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, U_ETHER_ADDR_LEN); + MEMvCopy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, U_ETHER_ADDR_LEN); + + //MIC_HDR2 + MEMvCopy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, U_ETHER_ADDR_LEN); + byTmp = (BYTE)(pMACHeader->wSeqCtl & 0xff); + MIC_HDR2[6] = byTmp & 0x0f; + MIC_HDR2[7] = 0; + if ( bA4 ) { + MEMvCopy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, U_ETHER_ADDR_LEN); + } else { + MIC_HDR2[8] = 0x00; + MIC_HDR2[9] = 0x00; + MIC_HDR2[10] = 0x00; + MIC_HDR2[11] = 0x00; + MIC_HDR2[12] = 0x00; + MIC_HDR2[13] = 0x00; + } + MIC_HDR2[14] = 0x00; + MIC_HDR2[15] = 0x00; + + //CCMP + AESv128(pbyRxKey,MIC_IV,abyMIC); + for ( kk=0; kk<16; kk++ ) { + abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk]; + } + AESv128(pbyRxKey,abyTmp,abyMIC); + for ( kk=0; kk<16; kk++ ) { + abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk]; + } + AESv128(pbyRxKey,abyTmp,abyMIC); + + wCnt = 1; + abyCTRPLD[0] = 0x01; + MEMvCopy(&(abyCTRPLD[1]), &(abyNonce[0]), 13); + + for(jj=wPayloadSize; jj>16; jj=jj-16) { + + abyCTRPLD[14] = (BYTE) (wCnt >> 8); + abyCTRPLD[15] = (BYTE) (wCnt & 0xff); + + AESv128(pbyRxKey,abyCTRPLD,abyTmp); + + for ( kk=0; kk<16; kk++ ) { + abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk]; + } + for ( kk=0; kk<16; kk++ ) { + abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk]; + } + AESv128(pbyRxKey,abyTmp,abyMIC); + + MEMvCopy(pbyPayload, abyPlainText, 16); + wCnt++; + pbyPayload += 16; + } //for wPayloadSize + + //last payload + MEMvCopy(&(abyLastCipher[0]), pbyPayload, jj); + for ( ii=jj; ii<16; ii++ ) { + abyLastCipher[ii] = 0x00; + } + + abyCTRPLD[14] = (BYTE) (wCnt >> 8); + abyCTRPLD[15] = (BYTE) (wCnt & 0xff); + + AESv128(pbyRxKey,abyCTRPLD,abyTmp); + for ( kk=0; kk<16; kk++ ) { + abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk]; + } + MEMvCopy(pbyPayload, abyPlainText, jj); + pbyPayload += jj; + + //for MIC calculation + for ( ii=jj; ii<16; ii++ ) { + abyPlainText[ii] = 0x00; + } + for ( kk=0; kk<16; kk++ ) { + abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk]; + } + AESv128(pbyRxKey,abyTmp,abyMIC); + + //=>above is the calculate MIC + //-------------------------------------------- + + wCnt = 0; + abyCTRPLD[14] = (BYTE) (wCnt >> 8); + abyCTRPLD[15] = (BYTE) (wCnt & 0xff); + AESv128(pbyRxKey,abyCTRPLD,abyTmp); + for ( kk=0; kk<8; kk++ ) { + abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk]; + } + //=>above is the dec-MIC from packet + //-------------------------------------------- + + if ( MEMEqualMemory(abyMIC,abyTmp,8) ) { + return TRUE; + } else { + return FALSE; + } + +} diff --git a/drivers/staging/vt6655/aes_ccmp.h b/drivers/staging/vt6655/aes_ccmp.h new file mode 100644 index 00000000000..2b1920f2860 --- /dev/null +++ b/drivers/staging/vt6655/aes_ccmp.h @@ -0,0 +1,48 @@ +/* + * 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: aes_ccmp.h + * + * Purpose: AES_CCMP Decryption + * + * Author: Warren Hsu + * + * Date: Feb 15, 2005 + * + */ + +#ifndef __AES_H__ +#define __AES_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +BOOL AESbGenCCMP(PBYTE pbyRxKey, PBYTE pbyFrame, WORD wFrameSize); + +#endif //__AES_H__ diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c new file mode 100644 index 00000000000..bc6db869953 --- /dev/null +++ b/drivers/staging/vt6655/baseband.c @@ -0,0 +1,2990 @@ +/* + * 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: baseband.c + * + * Purpose: Implement functions to access baseband + * + * Author: Kyle Hsu + * + * Date: Aug.22, 2002 + * + * Functions: + * BBuGetFrameTime - Calculate data frame transmitting time + * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal parameter for baseband Tx + * BBbReadEmbeded - Embeded read baseband register via MAC + * BBbWriteEmbeded - Embeded write baseband register via MAC + * BBbIsRegBitsOn - Test if baseband register bits on + * BBbIsRegBitsOff - Test if baseband register bits off + * BBbVT3253Init - VIA VT3253 baseband chip init code + * BBvReadAllRegs - Read All Baseband Registers + * BBvLoopbackOn - Turn on BaseBand Loopback mode + * BBvLoopbackOff - Turn off BaseBand Loopback mode + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support. + * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and BBvCaculateParameter(). + * cancel the setting of MAC_REG_SOFTPWRCTL on BBbVT3253Init(). + * Add the comments. + * 09-01-2003 Bryan YC Fan: RF & BB tables updated. + * Modified BBvLoopbackOn & BBvLoopbackOff(). + */ + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__SROM_H__) +#include "srom.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +//#define PLICE_DEBUG + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + + + +#define CB_VT3253_INIT_FOR_RFMD 446 +BYTE byVT3253InitTab_RFMD[CB_VT3253_INIT_FOR_RFMD][2] = { + {0x00, 0x30}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x00}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x70}, + {0x09, 0x45}, + {0x0a, 0x2a}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x01}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x9d}, + {0x1c, 0x05}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0xa8}, + {0x2e, 0x1a}, + {0x2f, 0x0c}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x0d}, + {0x3e, 0x51}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x06}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x08}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x80}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x14}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x44}, + {0x61, 0x04}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x04}, + {0x67, 0xb7}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x0b}, + {0x81, 0x00}, + {0x82, 0x3c}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x08}, + {0x8b, 0xa6}, + {0x8c, 0x84}, + {0x8d, 0x47}, + {0x8e, 0xbb}, + {0x8f, 0x02}, + {0x90, 0x21}, + {0x91, 0x0c}, + {0x92, 0x04}, + {0x93, 0x22}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x04}, + {0xa8, 0x10}, + {0xa9, 0x00}, + {0xaa, 0x8f}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x80}, + {0xb0, 0x38}, + {0xb1, 0x00}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0xee}, + {0xb5, 0xff}, + {0xb6, 0x10}, + {0xb7, 0x00}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x00}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x10}, + {0xc2, 0x18}, + {0xc3, 0x20}, + {0xc4, 0x10}, + {0xc5, 0x00}, + {0xc6, 0x22}, + {0xc7, 0x14}, + {0xc8, 0x0f}, + {0xc9, 0x08}, + {0xca, 0xa4}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x20}, + {0xcf, 0x00}, + {0xd0, 0x00}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x33}, + {0xd6, 0x70}, + {0xd7, 0x01}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0x00}, + {0xe2, 0xcc}, + {0xe3, 0x04}, + {0xe4, 0x08}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x0e}, + {0xe8, 0x88}, + {0xe9, 0xd4}, + {0xea, 0x05}, + {0xeb, 0xf0}, + {0xec, 0x79}, + {0xed, 0x0f}, + {0xee, 0x04}, + {0xef, 0x04}, + {0xf0, 0x00}, + {0xf1, 0x00}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xF0, 0x00}, + {0xF1, 0xF8}, + {0xF0, 0x80}, + {0xF0, 0x00}, + {0xF1, 0xF4}, + {0xF0, 0x81}, + {0xF0, 0x01}, + {0xF1, 0xF0}, + {0xF0, 0x82}, + {0xF0, 0x02}, + {0xF1, 0xEC}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0xE8}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0xE4}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0xE0}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0xDC}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0xD8}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0xD4}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0xD0}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0xCC}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0xC8}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0xC4}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0xC0}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0xBC}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0xB8}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0xB4}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0xB0}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0xAC}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0xA8}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0xA4}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0xA0}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x9C}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x98}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x94}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x90}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x8C}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x88}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x84}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x80}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x7C}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x78}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x74}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x70}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x6C}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x68}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x64}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x60}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x5C}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x58}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x54}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x50}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x4C}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x48}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x44}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x40}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x3C}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x38}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x34}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x30}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x2C}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x28}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x24}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x20}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x1C}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x18}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x14}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x10}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x0C}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x08}, + {0xF0, 0x00}, + {0xF0, 0x3C}, + {0xF1, 0x04}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x00}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x00}, + {0xF0, 0xBF}, + {0xF0, 0x3F}, + {0xF1, 0x00}, + {0xF0, 0xC0}, + {0xF0, 0x00}, +}; + +#define CB_VT3253B0_INIT_FOR_RFMD 256 +BYTE byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x81}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x38}, + {0x09, 0x45}, + {0x0a, 0x2a}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8e}, + {0x1c, 0x06}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x34}, + {0x2e, 0x18}, + {0x2f, 0x0c}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0xf8}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x09}, + {0x3e, 0x0d}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x08}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x80}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x14}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x39}, + {0x61, 0x83}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0xc0}, + {0x67, 0x49}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x89}, + {0x81, 0x00}, + {0x82, 0x0e}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0e}, + {0x8b, 0xa7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x23}, + {0x91, 0x0c}, + {0x92, 0x06}, + {0x93, 0x08}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0xcd}, + {0xa4, 0x07}, + {0xa5, 0x33}, + {0xa6, 0x18}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x28}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x38}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0x00}, + {0xb5, 0x00}, + {0xb6, 0x84}, + {0xb7, 0xfd}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x00}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x20}, + {0xc2, 0x18}, + {0xc3, 0x20}, + {0xc4, 0x10}, + {0xc5, 0x2c}, + {0xc6, 0x1e}, + {0xc7, 0x10}, + {0xc8, 0x12}, + {0xc9, 0x01}, + {0xca, 0x6f}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x00}, + {0xcf, 0x22}, + {0xd0, 0x00}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x33}, + {0xd6, 0x80}, + {0xd7, 0x21}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xB3}, + {0xe2, 0x00}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x18}, + {0xe8, 0x08}, + {0xe9, 0xd4}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x10}, + {0xee, 0x30}, + {0xef, 0x02}, + {0xf0, 0x00}, + {0xf1, 0x09}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + +#define CB_VT3253B0_AGC_FOR_RFMD2959 195 +// For RFMD2959 +BYTE byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = { + {0xF0, 0x00}, + {0xF1, 0x3E}, + {0xF0, 0x80}, + {0xF0, 0x00}, + {0xF1, 0x3E}, + {0xF0, 0x81}, + {0xF0, 0x01}, + {0xF1, 0x3E}, + {0xF0, 0x82}, + {0xF0, 0x02}, + {0xF1, 0x3E}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0x3B}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0x39}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0x38}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0x37}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0x36}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0x35}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0x35}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0x34}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0x34}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0x33}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0x32}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0x31}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0x30}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0x2F}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0x2F}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0x2E}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0x2D}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0x2C}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0x2B}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x2B}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x2A}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x29}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x28}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x27}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x26}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x25}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x24}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x24}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x23}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x22}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x21}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x20}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x20}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x1F}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x1E}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x1D}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x1C}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x1B}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x1B}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x1A}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x1A}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x19}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x18}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x17}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x16}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x15}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x15}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x15}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x14}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x13}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x12}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x11}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x10}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x0F}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x0E}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x0D}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x0C}, + {0xF0, 0xBC}, + {0xF0, 0x3C}, + {0xF1, 0x0B}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x0B}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x0A}, + {0xF0, 0xBF}, + {0xF0, 0x3F}, + {0xF1, 0x09}, + {0xF0, 0x00}, +}; + +#define CB_VT3253B0_INIT_FOR_AIROHA2230 256 +// For AIROHA +BYTE byVT3253B0_AIROHA2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x80}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x70}, + {0x09, 0x41}, + {0x0a, 0x2A}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8f}, + {0x1c, 0x09}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x4a}, + {0x2e, 0x00}, + {0x2f, 0x0a}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x79}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x0b}, + {0x3e, 0x48}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x09}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x73}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x15}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0xe4}, + {0x61, 0x80}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x98}, + {0x67, 0x0a}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + //{0x6c, 0x80}, + {0x6c, 0x00}, //RobertYu:20050125, request by JJSue + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x8c}, + {0x81, 0x01}, + {0x82, 0x09}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0f}, + {0x8b, 0xb7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x22}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x01}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x00}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x38}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0xff}, + {0xb5, 0x0f}, + {0xb6, 0xe4}, + {0xb7, 0xe2}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x01}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x18}, + {0xc1, 0x20}, + {0xc2, 0x07}, + {0xc3, 0x18}, + {0xc4, 0xff}, + {0xc5, 0x2c}, + {0xc6, 0x0c}, + {0xc7, 0x0a}, + {0xc8, 0x0e}, + {0xc9, 0x01}, + {0xca, 0x68}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x00}, + {0xcf, 0x25}, + {0xd0, 0x40}, + {0xd1, 0x12}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x28}, + {0xd6, 0x80}, + {0xd7, 0x2A}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xB3}, + {0xe2, 0x00}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x1C}, + {0xe8, 0x00}, + {0xe9, 0xf4}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x20}, + {0xee, 0x30}, + {0xef, 0x01}, + {0xf0, 0x00}, + {0xf1, 0x3e}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + + + +#define CB_VT3253B0_INIT_FOR_UW2451 256 +//For UW2451 +BYTE byVT3253B0_UW2451[CB_VT3253B0_INIT_FOR_UW2451][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x81}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x38}, + {0x09, 0x45}, + {0x0a, 0x28}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8f}, + {0x1c, 0x0f}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x18}, + {0x2e, 0x00}, + {0x2f, 0x0a}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x03}, + {0x3e, 0x1d}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x09}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x90}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x15}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0xb3}, + {0x61, 0x81}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x57}, + {0x67, 0x6c}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + //{0x6c, 0x80}, + {0x6c, 0x00}, //RobertYu:20050125, request by JJSue + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x8c}, + {0x81, 0x00}, + {0x82, 0x0e}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0e}, + {0x8b, 0xa7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xe3}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x00}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x18}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0x00}, + {0xb5, 0x00}, + {0xb6, 0x00}, + {0xb7, 0x00}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x01}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x20}, + {0xc2, 0x00}, + {0xc3, 0x20}, + {0xc4, 0x00}, + {0xc5, 0x2c}, + {0xc6, 0x1c}, + {0xc7, 0x10}, + {0xc8, 0x10}, + {0xc9, 0x01}, + {0xca, 0x68}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x09}, + {0xce, 0x00}, + {0xcf, 0x20}, + {0xd0, 0x40}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x20}, + {0xd5, 0x28}, + {0xd6, 0xa0}, + {0xd7, 0x2a}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xd3}, + {0xe2, 0xc0}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x12}, + {0xe8, 0x12}, + {0xe9, 0x34}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x20}, + {0xee, 0x30}, + {0xef, 0x01}, + {0xf0, 0x00}, + {0xf1, 0x3e}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + +#define CB_VT3253B0_AGC 193 +// For AIROHA +BYTE byVT3253B0_AGC[CB_VT3253B0_AGC][2] = { + {0xF0, 0x00}, + {0xF1, 0x00}, + {0xF0, 0x80}, + {0xF0, 0x01}, + {0xF1, 0x00}, + {0xF0, 0x81}, + {0xF0, 0x02}, + {0xF1, 0x02}, + {0xF0, 0x82}, + {0xF0, 0x03}, + {0xF1, 0x04}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0x04}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0x06}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0x06}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0x06}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0x08}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0x08}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0x0A}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0x0A}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0x0C}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0x0C}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0x0E}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0x0E}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0x10}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0x10}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0x12}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0x12}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0x14}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0x14}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0x16}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x16}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x18}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x18}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x1A}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x1A}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x1C}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x1C}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x1E}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x1E}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x20}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x20}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x22}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x22}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x24}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x24}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x26}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x26}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x28}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x28}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x2A}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x2A}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x2C}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x2C}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x2E}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x2E}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x30}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x30}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x32}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x32}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x34}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x34}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x36}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x36}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x38}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x38}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x3A}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x3A}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x3C}, + {0xF0, 0xBC}, + {0xF0, 0x3C}, + {0xF1, 0x3C}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x3E}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x3E}, + {0xF0, 0xBF}, + {0xF0, 0x00}, +}; + +const WORD awcFrameTime[MAX_RATE] = +{10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216}; + + +/*--------------------- Static Functions --------------------------*/ + +static +ULONG +s_ulGetRatio(PSDevice pDevice); + +static +VOID +s_vChangeAntenna( + IN PSDevice pDevice + ); + +static +VOID +s_vChangeAntenna ( + IN PSDevice pDevice + ) +{ + +#ifdef PLICE_DEBUG + //printk("Enter s_vChangeAntenna:original RxMode is %d,TxMode is %d\n",pDevice->byRxAntennaMode,pDevice->byTxAntennaMode); +#endif + if ( pDevice->dwRxAntennaSel == 0) { + pDevice->dwRxAntennaSel=1; + if (pDevice->bTxRxAntInv == TRUE) + BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A); + else + BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B); + } else { + pDevice->dwRxAntennaSel=0; + if (pDevice->bTxRxAntInv == TRUE) + BBvSetRxAntennaMode(pDevice->PortOffset, ANT_B); + else + BBvSetRxAntennaMode(pDevice->PortOffset, ANT_A); + } + if ( pDevice->dwTxAntennaSel == 0) { + pDevice->dwTxAntennaSel=1; + BBvSetTxAntennaMode(pDevice->PortOffset, ANT_B); + } else { + pDevice->dwTxAntennaSel=0; + BBvSetTxAntennaMode(pDevice->PortOffset, ANT_A); + } +} + + +/*--------------------- Export Variables --------------------------*/ +/* + * Description: Calculate data frame transmitting time + * + * Parameters: + * In: + * byPreambleType - Preamble Type + * byPktType - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA + * cbFrameLength - Baseband Type + * wRate - Tx Rate + * Out: + * + * Return Value: FrameTime + * + */ +UINT +BBuGetFrameTime ( + IN BYTE byPreambleType, + IN BYTE byPktType, + IN UINT cbFrameLength, + IN WORD wRate + ) +{ + UINT uFrameTime; + UINT uPreamble; + UINT uTmp; + UINT uRateIdx = (UINT)wRate; + UINT uRate = 0; + + + if (uRateIdx > RATE_54M) { + return 0; + } + + uRate = (UINT)awcFrameTime[uRateIdx]; + + if (uRateIdx <= 3) { //CCK mode + + if (byPreambleType == 1) {//Short + uPreamble = 96; + } else { + uPreamble = 192; + } + uFrameTime = (cbFrameLength * 80) / uRate; //????? + uTmp = (uFrameTime * uRate) / 80; + if (cbFrameLength != uTmp) { + uFrameTime ++; + } + + return (uPreamble + uFrameTime); + } + else { + uFrameTime = (cbFrameLength * 8 + 22) / uRate; //???????? + uTmp = ((uFrameTime * uRate) - 22) / 8; + if(cbFrameLength != uTmp) { + uFrameTime ++; + } + uFrameTime = uFrameTime * 4; //??????? + if(byPktType != PK_TYPE_11A) { + uFrameTime += 6; //?????? + } + return (20 + uFrameTime); //?????? + } +} + +/* + * Description: Caculate Length, Service, and Signal fields of Phy for Tx + * + * Parameters: + * In: + * pDevice - Device Structure + * cbFrameLength - Tx Frame Length + * wRate - Tx Rate + * Out: + * pwPhyLen - pointer to Phy Length field + * pbyPhySrv - pointer to Phy Service field + * pbyPhySgn - pointer to Phy Signal field + * + * Return Value: none + * + */ +VOID +BBvCaculateParameter ( + IN PSDevice pDevice, + IN UINT cbFrameLength, + IN WORD wRate, + IN BYTE byPacketType, + OUT PWORD pwPhyLen, + OUT PBYTE pbyPhySrv, + OUT PBYTE pbyPhySgn + ) +{ + UINT cbBitCount; + UINT cbUsCount = 0; + UINT cbTmp; + BOOL bExtBit; + BYTE byPreambleType = pDevice->byPreambleType; + BOOL bCCK = pDevice->bCCK; + + cbBitCount = cbFrameLength * 8; + bExtBit = FALSE; + + switch (wRate) { + case RATE_1M : + cbUsCount = cbBitCount; + *pbyPhySgn = 0x00; + break; + + case RATE_2M : + cbUsCount = cbBitCount / 2; + if (byPreambleType == 1) + *pbyPhySgn = 0x09; + else // long preamble + *pbyPhySgn = 0x01; + break; + + case RATE_5M : + if (bCCK == FALSE) + cbBitCount ++; + cbUsCount = (cbBitCount * 10) / 55; + cbTmp = (cbUsCount * 55) / 10; + if (cbTmp != cbBitCount) + cbUsCount ++; + if (byPreambleType == 1) + *pbyPhySgn = 0x0a; + else // long preamble + *pbyPhySgn = 0x02; + break; + + case RATE_11M : + + if (bCCK == FALSE) + cbBitCount ++; + cbUsCount = cbBitCount / 11; + cbTmp = cbUsCount * 11; + if (cbTmp != cbBitCount) { + cbUsCount ++; + if ((cbBitCount - cbTmp) <= 3) + bExtBit = TRUE; + } + if (byPreambleType == 1) + *pbyPhySgn = 0x0b; + else // long preamble + *pbyPhySgn = 0x03; + break; + + case RATE_6M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9B; //1001 1011 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8B; //1000 1011 + } + break; + + case RATE_9M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9F; //1001 1111 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8F; //1000 1111 + } + break; + + case RATE_12M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9A; //1001 1010 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8A; //1000 1010 + } + break; + + case RATE_18M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9E; //1001 1110 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8E; //1000 1110 + } + break; + + case RATE_24M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x99; //1001 1001 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x89; //1000 1001 + } + break; + + case RATE_36M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9D; //1001 1101 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8D; //1000 1101 + } + break; + + case RATE_48M : + if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x98; //1001 1000 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x88; //1000 1000 + } + break; + + case RATE_54M : + if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9C; //1001 1100 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8C; //1000 1100 + } + break; + + default : + if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ + *pbyPhySgn = 0x9C; //1001 1100 + } + else {//11g, 2.4GHZ + *pbyPhySgn = 0x8C; //1000 1100 + } + break; + } + + if (byPacketType == PK_TYPE_11B) { + *pbyPhySrv = 0x00; + if (bExtBit) + *pbyPhySrv = *pbyPhySrv | 0x80; + *pwPhyLen = (WORD)cbUsCount; + } + else { + *pbyPhySrv = 0x00; + *pwPhyLen = (WORD)cbFrameLength; + } +} + +/* + * Description: Read a byte from BASEBAND, by embeded programming + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byBBAddr - address of register in Baseband + * Out: + * pbyData - data read + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL BBbReadEmbeded (DWORD_PTR dwIoBase, BYTE byBBAddr, PBYTE pbyData) +{ + WORD ww; + BYTE byValue; + + // BB reg offset + VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr); + + // turn on REGR + MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGR); + // W_MAX_TIMEOUT is the timeout period + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue); + if (BITbIsBitOn(byValue, BBREGCTL_DONE)) + break; + } + + // get BB data + VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData); + + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x30); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x30)\n"); + return FALSE; + } + return TRUE; +} + + +/* + * Description: Write a Byte to BASEBAND, by embeded programming + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byBBAddr - address of register in Baseband + * byData - data to write + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL BBbWriteEmbeded (DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byData) +{ + WORD ww; + BYTE byValue; + + // BB reg offset + VNSvOutPortB(dwIoBase + MAC_REG_BBREGADR, byBBAddr); + // set BB data + VNSvOutPortB(dwIoBase + MAC_REG_BBREGDATA, byData); + + // turn on BBREGCTL_REGW + MACvRegBitsOn(dwIoBase, MAC_REG_BBREGCTL, BBREGCTL_REGW); + // W_MAX_TIMEOUT is the timeout period + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_BBREGCTL, &byValue); + if (BITbIsBitOn(byValue, BBREGCTL_DONE)) + break; + } + + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x31); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x31)\n"); + return FALSE; + } + return TRUE; +} + + +/* + * Description: Test if all bits are set for the Baseband register + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byBBAddr - address of register in Baseband + * byTestBits - TestBits + * Out: + * none + * + * Return Value: TRUE if all TestBits are set; FALSE otherwise. + * + */ +BOOL BBbIsRegBitsOn (DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byTestBits) +{ + BYTE byOrgData; + + BBbReadEmbeded(dwIoBase, byBBAddr, &byOrgData); + return BITbIsAllBitsOn(byOrgData, byTestBits); +} + + +/* + * Description: Test if all bits are clear for the Baseband register + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byBBAddr - address of register in Baseband + * byTestBits - TestBits + * Out: + * none + * + * Return Value: TRUE if all TestBits are clear; FALSE otherwise. + * + */ +BOOL BBbIsRegBitsOff (DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byTestBits) +{ + BYTE byOrgData; + + BBbReadEmbeded(dwIoBase, byBBAddr, &byOrgData); + return BITbIsAllBitsOff(byOrgData, byTestBits); +} + +/* + * Description: VIA VT3253 Baseband chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byRevId - Revision ID + * byRFType - RF type + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +BOOL BBbVT3253Init (PSDevice pDevice) +{ + BOOL bResult = TRUE; + int ii; + DWORD_PTR dwIoBase = pDevice->PortOffset; + BYTE byRFType = pDevice->byRFType; + BYTE byLocalID = pDevice->byLocalID; + + if (byRFType == RF_RFMD2959) { + if (byLocalID <= REV_ID_VT3253_A1) { + for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253InitTab_RFMD[ii][0],byVT3253InitTab_RFMD[ii][1]); + } + } else { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_RFMD[ii][0],byVT3253B0_RFMD[ii][1]); + } + for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC4_RFMD2959[ii][0],byVT3253B0_AGC4_RFMD2959[ii][1]); + } + VNSvOutPortD(dwIoBase + MAC_REG_ITRTMSET, 0x23); + MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); + } + pDevice->abyBBVGA[0] = 0x18; + pDevice->abyBBVGA[1] = 0x0A; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -50; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + } else if ((byRFType == RF_AIROHA) || (byRFType == RF_AL2230S) ) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + } + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + } + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + } else if (byRFType == RF_UW2451) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); + } + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + } + VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); + MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); + + pDevice->abyBBVGA[0] = 0x14; + pDevice->abyBBVGA[1] = 0x0A; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -60; + pDevice->ldBmThreshold[1] = -50; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + } else if (byRFType == RF_UW2452) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_UW2451[ii][0],byVT3253B0_UW2451[ii][1]); + } + // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //bResult &= BBbWriteEmbeded(dwIoBase,0x09,0x41); + // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //bResult &= BBbWriteEmbeded(dwIoBase,0x0a,0x28); + // Select VC1/VC2, CR215 = 0x02->0x06 + bResult &= BBbWriteEmbeded(dwIoBase,0xd7,0x06); + + //{{RobertYu:20050125, request by Jack + bResult &= BBbWriteEmbeded(dwIoBase,0x90,0x20); + bResult &= BBbWriteEmbeded(dwIoBase,0x97,0xeb); + //}} + + //{{RobertYu:20050221, request by Jack + bResult &= BBbWriteEmbeded(dwIoBase,0xa6,0x00); + bResult &= BBbWriteEmbeded(dwIoBase,0xa8,0x30); + //}} + bResult &= BBbWriteEmbeded(dwIoBase,0xb0,0x58); + + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + } + //VNSvOutPortB(dwIoBase + MAC_REG_ITRTMSET, 0x23); // RobertYu: 20050104, 20050131 disable PA_Delay + //MACvRegBitsOn(dwIoBase, MAC_REG_PAPEDELAY, BIT0); // RobertYu: 20050104, 20050131 disable PA_Delay + + pDevice->abyBBVGA[0] = 0x14; + pDevice->abyBBVGA[1] = 0x0A; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -60; + pDevice->ldBmThreshold[1] = -50; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + //}} RobertYu + + } else if (byRFType == RF_VT3226) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + } + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + } + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + // Fix VT3226 DFC system timing issue + MACvSetRFLE_LatchBase(dwIoBase); + //{{ RobertYu: 20050104 + } else if (byRFType == RF_AIROHA7230) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AIROHA2230[ii][0],byVT3253B0_AIROHA2230[ii][1]); + } + + //{{ RobertYu:20050223, request by JerryChung + // Init ANT B select,TX Config CR09 = 0x61->0x45, 0x45->0x41(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //bResult &= BBbWriteEmbeded(dwIoBase,0x09,0x41); + // Init ANT B select,RX Config CR10 = 0x28->0x2A, 0x2A->0x28(VC1/VC2 define, make the ANT_A, ANT_B inverted) + //bResult &= BBbWriteEmbeded(dwIoBase,0x0a,0x28); + // Select VC1/VC2, CR215 = 0x02->0x06 + bResult &= BBbWriteEmbeded(dwIoBase,0xd7,0x06); + //}} + + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) { + bResult &= BBbWriteEmbeded(dwIoBase,byVT3253B0_AGC[ii][0],byVT3253B0_AGC[ii][1]); + } + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[1] = 0x10; + pDevice->abyBBVGA[2] = 0x0; + pDevice->abyBBVGA[3] = 0x0; + pDevice->ldBmThreshold[0] = -70; + pDevice->ldBmThreshold[1] = -48; + pDevice->ldBmThreshold[2] = 0; + pDevice->ldBmThreshold[3] = 0; + //}} RobertYu + } else { + // No VGA Table now + pDevice->bUpdateBBVGA = FALSE; + pDevice->abyBBVGA[0] = 0x1C; + } + + if (byLocalID > REV_ID_VT3253_A1) { + BBbWriteEmbeded(dwIoBase, 0x04, 0x7F); + BBbWriteEmbeded(dwIoBase, 0x0D, 0x01); + } + + return bResult; +} + + + +/* + * Description: Read All Baseband Registers + * + * Parameters: + * In: + * dwIoBase - I/O base address + * pbyBBRegs - Point to struct that stores Baseband Registers + * Out: + * none + * + * Return Value: none + * + */ +VOID BBvReadAllRegs (DWORD_PTR dwIoBase, PBYTE pbyBBRegs) +{ + int ii; + BYTE byBase = 1; + for (ii = 0; ii < BB_MAX_CONTEXT_SIZE; ii++) { + BBbReadEmbeded(dwIoBase, (BYTE)(ii*byBase), pbyBBRegs); + pbyBBRegs += byBase; + } +} + +/* + * Description: Turn on BaseBand Loopback mode + * + * Parameters: + * In: + * dwIoBase - I/O base address + * bCCK - If CCK is set + * Out: + * none + * + * Return Value: none + * + */ + + +void BBvLoopbackOn (PSDevice pDevice) +{ + BYTE byData; + DWORD_PTR dwIoBase = pDevice->PortOffset; + + //CR C9 = 0x00 + BBbReadEmbeded(dwIoBase, 0xC9, &pDevice->byBBCRc9);//CR201 + BBbWriteEmbeded(dwIoBase, 0xC9, 0); + BBbReadEmbeded(dwIoBase, 0x4D, &pDevice->byBBCR4d);//CR77 + BBbWriteEmbeded(dwIoBase, 0x4D, 0x90); + + //CR 88 = 0x02(CCK), 0x03(OFDM) + BBbReadEmbeded(dwIoBase, 0x88, &pDevice->byBBCR88);//CR136 + + if (pDevice->uConnectionRate <= RATE_11M) { //CCK + // Enable internal digital loopback: CR33 |= 0000 0001 + BBbReadEmbeded(dwIoBase, 0x21, &byData);//CR33 + BBbWriteEmbeded(dwIoBase, 0x21, (BYTE)(byData | 0x01));//CR33 + // CR154 = 0x00 + BBbWriteEmbeded(dwIoBase, 0x9A, 0); //CR154 + + BBbWriteEmbeded(dwIoBase, 0x88, 0x02);//CR239 + } + else { //OFDM + // Enable internal digital loopback:CR154 |= 0000 0001 + BBbReadEmbeded(dwIoBase, 0x9A, &byData);//CR154 + BBbWriteEmbeded(dwIoBase, 0x9A, (BYTE)(byData | 0x01));//CR154 + // CR33 = 0x00 + BBbWriteEmbeded(dwIoBase, 0x21, 0); //CR33 + + BBbWriteEmbeded(dwIoBase, 0x88, 0x03);//CR239 + } + + //CR14 = 0x00 + BBbWriteEmbeded(dwIoBase, 0x0E, 0);//CR14 + + // Disable TX_IQUN + BBbReadEmbeded(pDevice->PortOffset, 0x09, &pDevice->byBBCR09); + BBbWriteEmbeded(pDevice->PortOffset, 0x09, (BYTE)(pDevice->byBBCR09 & 0xDE)); +} + +/* + * Description: Turn off BaseBand Loopback mode + * + * Parameters: + * In: + * pDevice - Device Structure + * + * Out: + * none + * + * Return Value: none + * + */ +void BBvLoopbackOff (PSDevice pDevice) +{ + BYTE byData; + DWORD_PTR dwIoBase = pDevice->PortOffset; + + BBbWriteEmbeded(dwIoBase, 0xC9, pDevice->byBBCRc9);//CR201 + BBbWriteEmbeded(dwIoBase, 0x88, pDevice->byBBCR88);//CR136 + BBbWriteEmbeded(dwIoBase, 0x09, pDevice->byBBCR09);//CR136 + BBbWriteEmbeded(dwIoBase, 0x4D, pDevice->byBBCR4d);//CR77 + + if (pDevice->uConnectionRate <= RATE_11M) { // CCK + // Set the CR33 Bit2 to disable internal Loopback. + BBbReadEmbeded(dwIoBase, 0x21, &byData);//CR33 + BBbWriteEmbeded(dwIoBase, 0x21, (BYTE)(byData & 0xFE));//CR33 + } + else { // OFDM + BBbReadEmbeded(dwIoBase, 0x9A, &byData);//CR154 + BBbWriteEmbeded(dwIoBase, 0x9A, (BYTE)(byData & 0xFE));//CR154 + } + BBbReadEmbeded(dwIoBase, 0x0E, &byData);//CR14 + BBbWriteEmbeded(dwIoBase, 0x0E, (BYTE)(byData | 0x80));//CR14 + +} + + + +/* + * Description: Set ShortSlotTime mode + * + * Parameters: + * In: + * pDevice - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +VOID +BBvSetShortSlotTime (PSDevice pDevice) +{ + BYTE byBBRxConf=0; + BYTE byBBVGA=0; + + BBbReadEmbeded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 + + if (pDevice->bShortSlotTime) { + byBBRxConf &= 0xDF;//1101 1111 + } else { + byBBRxConf |= 0x20;//0010 0000 + } + + // patch for 3253B0 Baseband with Cardbus module + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byBBVGA); + if (byBBVGA == pDevice->abyBBVGA[0]) { + byBBRxConf |= 0x20;//0010 0000 + } + + BBbWriteEmbeded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 + +} + +VOID BBvSetVGAGainOffset(PSDevice pDevice, BYTE byData) +{ + BYTE byBBRxConf=0; + + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, byData); + + BBbReadEmbeded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10 + // patch for 3253B0 Baseband with Cardbus module + if (byData == pDevice->abyBBVGA[0]) { + byBBRxConf |= 0x20;//0010 0000 + } else if (pDevice->bShortSlotTime) { + byBBRxConf &= 0xDF;//1101 1111 + } else { + byBBRxConf |= 0x20;//0010 0000 + } + pDevice->byBBVGACurrent = byData; + BBbWriteEmbeded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10 +} + + +/* + * Description: Baseband SoftwareReset + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +VOID +BBvSoftwareReset (DWORD_PTR dwIoBase) +{ + BBbWriteEmbeded(dwIoBase, 0x50, 0x40); + BBbWriteEmbeded(dwIoBase, 0x50, 0); + BBbWriteEmbeded(dwIoBase, 0x9C, 0x01); + BBbWriteEmbeded(dwIoBase, 0x9C, 0); +} + +/* + * Description: Baseband Power Save Mode ON + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +VOID +BBvPowerSaveModeON (DWORD_PTR dwIoBase) +{ + BYTE byOrgData; + + BBbReadEmbeded(dwIoBase, 0x0D, &byOrgData); + byOrgData |= BIT0; + BBbWriteEmbeded(dwIoBase, 0x0D, byOrgData); +} + +/* + * Description: Baseband Power Save Mode OFF + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +VOID +BBvPowerSaveModeOFF (DWORD_PTR dwIoBase) +{ + BYTE byOrgData; + + BBbReadEmbeded(dwIoBase, 0x0D, &byOrgData); + byOrgData &= ~(BIT0); + BBbWriteEmbeded(dwIoBase, 0x0D, byOrgData); +} + +/* + * Description: Set Tx Antenna mode + * + * Parameters: + * In: + * pDevice - Device Structure + * byAntennaMode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ + +VOID +BBvSetTxAntennaMode (DWORD_PTR dwIoBase, BYTE byAntennaMode) +{ + BYTE byBBTxConf; + +#ifdef PLICE_DEBUG + //printk("Enter BBvSetTxAntennaMode\n"); +#endif + BBbReadEmbeded(dwIoBase, 0x09, &byBBTxConf);//CR09 + if (byAntennaMode == ANT_DIVERSITY) { + // bit 1 is diversity + byBBTxConf |= 0x02; + } else if (byAntennaMode == ANT_A) { + // bit 2 is ANTSEL + byBBTxConf &= 0xF9; // 1111 1001 + } else if (byAntennaMode == ANT_B) { +#ifdef PLICE_DEBUG + //printk("BBvSetTxAntennaMode:ANT_B\n"); +#endif + byBBTxConf &= 0xFD; // 1111 1101 + byBBTxConf |= 0x04; + } + BBbWriteEmbeded(dwIoBase, 0x09, byBBTxConf);//CR09 +} + + + + +/* + * Description: Set Rx Antenna mode + * + * Parameters: + * In: + * pDevice - Device Structure + * byAntennaMode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ + +VOID +BBvSetRxAntennaMode (DWORD_PTR dwIoBase, BYTE byAntennaMode) +{ + BYTE byBBRxConf; + + BBbReadEmbeded(dwIoBase, 0x0A, &byBBRxConf);//CR10 + if (byAntennaMode == ANT_DIVERSITY) { + byBBRxConf |= 0x01; + + } else if (byAntennaMode == ANT_A) { + byBBRxConf &= 0xFC; // 1111 1100 + } else if (byAntennaMode == ANT_B) { + byBBRxConf &= 0xFE; // 1111 1110 + byBBRxConf |= 0x02; + } + BBbWriteEmbeded(dwIoBase, 0x0A, byBBRxConf);//CR10 +} + + +/* + * Description: BBvSetDeepSleep + * + * Parameters: + * In: + * pDevice - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +VOID +BBvSetDeepSleep (DWORD_PTR dwIoBase, BYTE byLocalID) +{ + BBbWriteEmbeded(dwIoBase, 0x0C, 0x17);//CR12 + BBbWriteEmbeded(dwIoBase, 0x0D, 0xB9);//CR13 +} + +VOID +BBvExitDeepSleep (DWORD_PTR dwIoBase, BYTE byLocalID) +{ + BBbWriteEmbeded(dwIoBase, 0x0C, 0x00);//CR12 + BBbWriteEmbeded(dwIoBase, 0x0D, 0x01);//CR13 +} + + + +static +ULONG +s_ulGetRatio (PSDevice pDevice) +{ +ULONG ulRatio = 0; +ULONG ulMaxPacket; +ULONG ulPacketNum; + + //This is a thousand-ratio + ulMaxPacket = pDevice->uNumSQ3[RATE_54M]; + if ( pDevice->uNumSQ3[RATE_54M] != 0 ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_54M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_54M; + } + if ( pDevice->uNumSQ3[RATE_48M] > ulMaxPacket ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_48M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_48M; + ulMaxPacket = pDevice->uNumSQ3[RATE_48M]; + } + if ( pDevice->uNumSQ3[RATE_36M] > ulMaxPacket ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] + + pDevice->uNumSQ3[RATE_36M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_36M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_36M; + ulMaxPacket = pDevice->uNumSQ3[RATE_36M]; + } + if ( pDevice->uNumSQ3[RATE_24M] > ulMaxPacket ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] + + pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_24M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_24M; + ulMaxPacket = pDevice->uNumSQ3[RATE_24M]; + } + if ( pDevice->uNumSQ3[RATE_18M] > ulMaxPacket ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] + + pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] + + pDevice->uNumSQ3[RATE_18M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_18M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_18M; + ulMaxPacket = pDevice->uNumSQ3[RATE_18M]; + } + if ( pDevice->uNumSQ3[RATE_12M] > ulMaxPacket ) { + ulPacketNum = pDevice->uNumSQ3[RATE_54M] + pDevice->uNumSQ3[RATE_48M] + + pDevice->uNumSQ3[RATE_36M] + pDevice->uNumSQ3[RATE_24M] + + pDevice->uNumSQ3[RATE_18M] + pDevice->uNumSQ3[RATE_12M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_12M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_12M; + ulMaxPacket = pDevice->uNumSQ3[RATE_12M]; + } + if ( pDevice->uNumSQ3[RATE_11M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] - + pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] - + pDevice->uNumSQ3[RATE_6M] - pDevice->uNumSQ3[RATE_9M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_11M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_11M; + ulMaxPacket = pDevice->uNumSQ3[RATE_11M]; + } + if ( pDevice->uNumSQ3[RATE_9M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] - + pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M] - + pDevice->uNumSQ3[RATE_6M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_9M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_9M; + ulMaxPacket = pDevice->uNumSQ3[RATE_9M]; + } + if ( pDevice->uNumSQ3[RATE_6M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] - + pDevice->uNumSQ3[RATE_2M] - pDevice->uNumSQ3[RATE_5M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_6M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_6M; + ulMaxPacket = pDevice->uNumSQ3[RATE_6M]; + } + if ( pDevice->uNumSQ3[RATE_5M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M] - + pDevice->uNumSQ3[RATE_2M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_5M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_55M; + ulMaxPacket = pDevice->uNumSQ3[RATE_5M]; + } + if ( pDevice->uNumSQ3[RATE_2M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt - pDevice->uNumSQ3[RATE_1M]; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_2M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_2M; + ulMaxPacket = pDevice->uNumSQ3[RATE_2M]; + } + if ( pDevice->uNumSQ3[RATE_1M] > ulMaxPacket ) { + ulPacketNum = pDevice->uDiversityCnt; + ulRatio = (ulPacketNum * 1000 / pDevice->uDiversityCnt); + //ulRatio = (pDevice->uNumSQ3[RATE_1M] * 1000 / pDevice->uDiversityCnt); + ulRatio += TOP_RATE_1M; + } + + return ulRatio; +} + + +VOID +BBvClearAntDivSQ3Value (PSDevice pDevice) +{ + UINT ii; + + pDevice->uDiversityCnt = 0; + for (ii = 0; ii < MAX_RATE; ii++) { + pDevice->uNumSQ3[ii] = 0; + } +} + + +/* + * Description: Antenna Diversity + * + * Parameters: + * In: + * pDevice - Device Structure + * byRSR - RSR from received packet + * bySQ3 - SQ3 value from received packet + * Out: + * none + * + * Return Value: none + * + */ + +VOID +BBvAntennaDiversity (PSDevice pDevice, BYTE byRxRate, BYTE bySQ3) +{ + + if ((byRxRate >= MAX_RATE) || (pDevice->wAntDiversityMaxRate >= MAX_RATE)) { + return; + } + pDevice->uDiversityCnt++; + // DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->uDiversityCnt = %d\n", (int)pDevice->uDiversityCnt); + + pDevice->uNumSQ3[byRxRate]++; + + if (pDevice->byAntennaState == 0) { + + if (pDevice->uDiversityCnt > pDevice->ulDiversityNValue) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ulDiversityNValue=[%d],54M-[%d]\n", + (int)pDevice->ulDiversityNValue, (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate]); + + if (pDevice->uNumSQ3[pDevice->wAntDiversityMaxRate] < pDevice->uDiversityCnt/2) { + + pDevice->ulRatio_State0 = s_ulGetRatio(pDevice); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State0, rate = [%08x]\n", (int)pDevice->ulRatio_State0); + + if ( pDevice->byTMax == 0 ) + return; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1.[%08x], uNumSQ3[%d]=%d, %d\n", + (int)pDevice->ulRatio_State0, (int)pDevice->wAntDiversityMaxRate, + (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt); +#ifdef PLICE_DEBUG + //printk("BBvAntennaDiversity1:call s_vChangeAntenna\n"); +#endif + s_vChangeAntenna(pDevice); + pDevice->byAntennaState = 1; + del_timer(&pDevice->TimerSQ3Tmax3); + del_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax1.expires = RUN_AT(pDevice->byTMax * HZ); + add_timer(&pDevice->TimerSQ3Tmax1); + + } else { + + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + } + BBvClearAntDivSQ3Value(pDevice); + + } + } else { //byAntennaState == 1 + + if (pDevice->uDiversityCnt > pDevice->ulDiversityMValue) { + + del_timer(&pDevice->TimerSQ3Tmax1); + + pDevice->ulRatio_State1 = s_ulGetRatio(pDevice); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RX:SQ3_State1, rate0 = %08x,rate1 = %08x\n", + (int)pDevice->ulRatio_State0,(int)pDevice->ulRatio_State1); + + if (pDevice->ulRatio_State1 < pDevice->ulRatio_State0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", + (int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1, + (int)pDevice->wAntDiversityMaxRate, + (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt); +#ifdef PLICE_DEBUG + //printk("BBvAntennaDiversity2:call s_vChangeAntenna\n"); +#endif + s_vChangeAntenna(pDevice); + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + } + pDevice->byAntennaState = 0; + BBvClearAntDivSQ3Value(pDevice); + } + } //byAntennaState +} + +/*+ + * + * Description: + * Timer for SQ3 antenna diversity + * + * Parameters: + * In: + * Out: + * none + * + * Return Value: none + * +-*/ + +VOID +TimerSQ3CallBack ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerSQ3CallBack..."); + + + spin_lock_irq(&pDevice->lock); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.[%08x][%08x], %d\n",(int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1, (int)pDevice->uDiversityCnt); +#ifdef PLICE_DEBUG + //printk("TimerSQ3CallBack1:call s_vChangeAntenna\n"); +#endif + + s_vChangeAntenna(pDevice); + pDevice->byAntennaState = 0; + BBvClearAntDivSQ3Value(pDevice); + + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + + spin_unlock_irq(&pDevice->lock); + + return; +} + + +/*+ + * + * Description: + * Timer for SQ3 antenna diversity + * + * Parameters: + * In: + * pvSysSpec1 + * hDeviceContext - Pointer to the adapter + * pvSysSpec2 + * pvSysSpec3 + * Out: + * none + * + * Return Value: none + * +-*/ + +VOID +TimerState1CallBack ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TimerState1CallBack..."); + + spin_lock_irq(&pDevice->lock); + if (pDevice->uDiversityCnt < pDevice->ulDiversityMValue/100) { +#ifdef PLICE_DEBUG + //printk("TimerSQ3CallBack2:call s_vChangeAntenna\n"); +#endif + + s_vChangeAntenna(pDevice); + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + } else { + pDevice->ulRatio_State1 = s_ulGetRatio(pDevice); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SQ3_State1, rate0 = %08x,rate1 = %08x\n", + (int)pDevice->ulRatio_State0,(int)pDevice->ulRatio_State1); + + if ( pDevice->ulRatio_State1 < pDevice->ulRatio_State0 ) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", + (int)pDevice->ulRatio_State0, (int)pDevice->ulRatio_State1, + (int)pDevice->wAntDiversityMaxRate, + (int)pDevice->uNumSQ3[(int)pDevice->wAntDiversityMaxRate], (int)pDevice->uDiversityCnt); +#ifdef PLICE_DEBUG + //printk("TimerSQ3CallBack3:call s_vChangeAntenna\n"); +#endif + + s_vChangeAntenna(pDevice); + + pDevice->TimerSQ3Tmax3.expires = RUN_AT(pDevice->byTMax3 * HZ); + pDevice->TimerSQ3Tmax2.expires = RUN_AT(pDevice->byTMax2 * HZ); + add_timer(&pDevice->TimerSQ3Tmax3); + add_timer(&pDevice->TimerSQ3Tmax2); + } + } + pDevice->byAntennaState = 0; + BBvClearAntDivSQ3Value(pDevice); + spin_unlock_irq(&pDevice->lock); + + return; +} + diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h new file mode 100644 index 00000000000..09cf4f961ac --- /dev/null +++ b/drivers/staging/vt6655/baseband.h @@ -0,0 +1,198 @@ +/* + * 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: baseband.h + * + * Purpose: Implement functions to access baseband + * + * Author: Jerry Chen + * + * Date: Jun. 5, 2002 + * + */ + + +#ifndef __BASEBAND_H__ +#define __BASEBAND_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +#if !defined(__TETHER_H__) +#include "tether.h" +#endif + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +// +// Registers in the BASEBAND +// +#define BB_MAX_CONTEXT_SIZE 256 + + +// +// Baseband RF pair definition in eeprom (Bits 6..0) +// + +/* +#define RATE_1M 0 +#define RATE_2M 1 +#define RATE_5M 2 +#define RATE_11M 3 +#define RATE_6M 4 +#define RATE_9M 5 +#define RATE_12M 6 +#define RATE_18M 7 +#define RATE_24M 8 +#define RATE_36M 9 +#define RATE_48M 10 +#define RATE_54M 11 +#define RATE_AUTO 12 +#define MAX_RATE 12 + + +//0:11A 1:11B 2:11G +#define BB_TYPE_11A 0 +#define BB_TYPE_11B 1 +#define BB_TYPE_11G 2 + +//0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate) +#define PK_TYPE_11A 0 +#define PK_TYPE_11B 1 +#define PK_TYPE_11GB 2 +#define PK_TYPE_11GA 3 +*/ + + +#define PREAMBLE_LONG 0 +#define PREAMBLE_SHORT 1 + + +#define F5G 0 +#define F2_4G 1 + +#define TOP_RATE_54M 0x80000000 +#define TOP_RATE_48M 0x40000000 +#define TOP_RATE_36M 0x20000000 +#define TOP_RATE_24M 0x10000000 +#define TOP_RATE_18M 0x08000000 +#define TOP_RATE_12M 0x04000000 +#define TOP_RATE_11M 0x02000000 +#define TOP_RATE_9M 0x01000000 +#define TOP_RATE_6M 0x00800000 +#define TOP_RATE_55M 0x00400000 +#define TOP_RATE_2M 0x00200000 +#define TOP_RATE_1M 0x00100000 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + + + +#define BBvClearFOE(dwIoBase) \ +{ \ + BBbWriteEmbeded(dwIoBase, 0xB1, 0); \ +} + +#define BBvSetFOE(dwIoBase) \ +{ \ + BBbWriteEmbeded(dwIoBase, 0xB1, 0x0C); \ +} + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +UINT +BBuGetFrameTime( + IN BYTE byPreambleType, + IN BYTE byPktType, + IN UINT cbFrameLength, + IN WORD wRate + ); + +VOID +BBvCaculateParameter ( + IN PSDevice pDevice, + IN UINT cbFrameLength, + IN WORD wRate, + IN BYTE byPacketType, + OUT PWORD pwPhyLen, + OUT PBYTE pbyPhySrv, + OUT PBYTE pbyPhySgn + ); + +BOOL BBbReadEmbeded(DWORD_PTR dwIoBase, BYTE byBBAddr, PBYTE pbyData); +BOOL BBbWriteEmbeded(DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byData); + +VOID BBvReadAllRegs(DWORD_PTR dwIoBase, PBYTE pbyBBRegs); +void BBvLoopbackOn(PSDevice pDevice); +void BBvLoopbackOff(PSDevice pDevice); +void BBvSetShortSlotTime(PSDevice pDevice); +BOOL BBbIsRegBitsOn(DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byTestBits); +BOOL BBbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byBBAddr, BYTE byTestBits); +VOID BBvSetVGAGainOffset(PSDevice pDevice, BYTE byData); + +// VT3253 Baseband +BOOL BBbVT3253Init(PSDevice pDevice); +VOID BBvSoftwareReset(DWORD_PTR dwIoBase); +VOID BBvPowerSaveModeON(DWORD_PTR dwIoBase); +VOID BBvPowerSaveModeOFF(DWORD_PTR dwIoBase); +VOID BBvSetTxAntennaMode(DWORD_PTR dwIoBase, BYTE byAntennaMode); +VOID BBvSetRxAntennaMode(DWORD_PTR dwIoBase, BYTE byAntennaMode); +VOID BBvSetDeepSleep(DWORD_PTR dwIoBase, BYTE byLocalID); +VOID BBvExitDeepSleep(DWORD_PTR dwIoBase, BYTE byLocalID); + +// timer for antenna diversity +VOID +TimerSQ3CallBack( + IN HANDLE hDeviceContext + ); +VOID +TimerState1CallBack( + IN HANDLE hDeviceContext + ); + +void BBvAntennaDiversity(PSDevice pDevice, BYTE byRxRate, BYTE bySQ3); +VOID +BBvClearAntDivSQ3Value (PSDevice pDevice); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __BASEBAND_H__ + + + diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c new file mode 100644 index 00000000000..4bac7b69445 --- /dev/null +++ b/drivers/staging/vt6655/bssdb.c @@ -0,0 +1,1791 @@ +/* + * 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: bssdb.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * BSSpSearchBSSList - Search known BSS list for Desire SSID or BSSID + * BSSvClearBSSList - Clear BSS List + * BSSbInsertToBSSList - Insert a BSS set into known BSS list + * BSSbUpdateToBSSList - Update BSS set in known BSS list + * BSSDBbIsSTAInNodeDB - Search Node DB table to find the index of matched DstAddr + * BSSvCreateOneNode - Allocate an Node for Node DB + * BSSvUpdateAPNode - Update AP Node content in Index 0 of KnownNodeDB + * BSSvSecondCallBack - One second timer callback function to update Node DB info & AP link status + * BSSvUpdateNodeTxCounter - Update Tx attemps, Tx failure counter in Node DB for auto-fall back rate control + * + * Revision History: + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + */ + + +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif//chester +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__DATARATE_H__) +#include "datarate.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__WPA_H__) +#include "wpa.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__WPA2_H__) +#include "wpa2.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +//DavidWang +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif + +//#define PLICE_DEBUG +/*--------------------- Static Definitions -------------------------*/ + + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + + + +const WORD awHWRetry0[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, + {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, + {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} + }; +const WORD awHWRetry1[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} + }; + + + +/*--------------------- Static Functions --------------------------*/ + +VOID s_vCheckSensitivity( + IN HANDLE hDeviceContext + ); + +#ifdef Calcu_LinkQual +VOID s_uCalculateLinkQual( + IN HANDLE hDeviceContext + ); +#endif + + +VOID s_vCheckPreEDThreshold( + IN HANDLE hDeviceContext + ); +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + + + + +/*+ + * + * Routine Description: + * Search known BSS list for Desire SSID or BSSID. + * + * Return Value: + * PTR to KnownBSS or NULL + * +-*/ + +PKnownBSS +BSSpSearchBSSList( + IN HANDLE hDeviceContext, + IN PBYTE pbyDesireBSSID, + IN PBYTE pbyDesireSSID, + IN CARD_PHY_TYPE ePhyType + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PBYTE pbyBSSID = NULL; + PWLAN_IE_SSID pSSID = NULL; + PKnownBSS pCurrBSS = NULL; + PKnownBSS pSelect = NULL; +BYTE ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00}; + UINT ii = 0; +// UINT jj = 0; //DavidWang + if (pbyDesireBSSID != NULL) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSpSearchBSSList BSSID[%02X %02X %02X-%02X %02X %02X]\n", + *pbyDesireBSSID,*(pbyDesireBSSID+1),*(pbyDesireBSSID+2), + *(pbyDesireBSSID+3),*(pbyDesireBSSID+4),*(pbyDesireBSSID+5)); + if ((!IS_BROADCAST_ADDRESS(pbyDesireBSSID)) && + (memcmp(pbyDesireBSSID, ZeroBSSID, 6)!= 0)) { + pbyBSSID = pbyDesireBSSID; + } + } + if (pbyDesireSSID != NULL) { + if (((PWLAN_IE_SSID)pbyDesireSSID)->len != 0) { + pSSID = (PWLAN_IE_SSID) pbyDesireSSID; + } + } + + if (pbyBSSID != NULL) { + // match BSSID first + for (ii = 0; ii <MAX_BSS_NUM; ii++) { + pCurrBSS = &(pMgmt->sBSSList[ii]); +if(pDevice->bLinkPass==FALSE) pCurrBSS->bSelected = FALSE; + if ((pCurrBSS->bActive) && + (pCurrBSS->bSelected == FALSE)) { + if (IS_ETH_ADDRESS_EQUAL(pCurrBSS->abyBSSID, pbyBSSID)) { + if (pSSID != NULL) { + // compare ssid + if (MEMEqualMemory(pSSID->abySSID, + ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, + pSSID->len)) { + if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) || + ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) + ) { + pCurrBSS->bSelected = TRUE; + return(pCurrBSS); + } + } + } else { + if ((pMgmt->eConfigMode == WMAC_CONFIG_AUTO) || + ((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) + ) { + pCurrBSS->bSelected = TRUE; + return(pCurrBSS); + } + } + } + } + } + } else { + // ignore BSSID + for (ii = 0; ii <MAX_BSS_NUM; ii++) { + pCurrBSS = &(pMgmt->sBSSList[ii]); + //2007-0721-01<Add>by MikeLiu + pCurrBSS->bSelected = FALSE; + if (pCurrBSS->bActive) { + + if (pSSID != NULL) { + // matched SSID + if (!MEMEqualMemory(pSSID->abySSID, + ((PWLAN_IE_SSID)pCurrBSS->abySSID)->abySSID, + pSSID->len) || + (pSSID->len != ((PWLAN_IE_SSID)pCurrBSS->abySSID)->len)) { + // SSID not match skip this BSS + continue; + } + } + if (((pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) && WLAN_GET_CAP_INFO_ESS(pCurrBSS->wCapInfo)) || + ((pMgmt->eConfigMode == WMAC_CONFIG_ESS_STA) && WLAN_GET_CAP_INFO_IBSS(pCurrBSS->wCapInfo)) + ) { + // Type not match skip this BSS + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSS type mismatch.... Config[%d] BSS[0x%04x]\n", pMgmt->eConfigMode, pCurrBSS->wCapInfo); + continue; + } + + if (ePhyType != PHY_TYPE_AUTO) { + if (((ePhyType == PHY_TYPE_11A) && (PHY_TYPE_11A != pCurrBSS->eNetworkTypeInUse)) || + ((ePhyType != PHY_TYPE_11A) && (PHY_TYPE_11A == pCurrBSS->eNetworkTypeInUse))) { + // PhyType not match skip this BSS + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Physical type mismatch.... ePhyType[%d] BSS[%d]\n", ePhyType, pCurrBSS->eNetworkTypeInUse); + continue; + } + } +/* + if (pMgmt->eAuthenMode < WMAC_AUTH_WPA) { + if (pCurrBSS->bWPAValid == TRUE) { + // WPA AP will reject connection of station without WPA enable. + continue; + } + } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) { + if (pCurrBSS->bWPAValid == FALSE) { + // station with WPA enable can't join NonWPA AP. + continue; + } + } else if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + if (pCurrBSS->bWPA2Valid == FALSE) { + // station with WPA2 enable can't join NonWPA2 AP. + continue; + } + } +*/ + if (pSelect == NULL) { + pSelect = pCurrBSS; + } else { + // compare RSSI, select signal strong one + if (pCurrBSS->uRSSI < pSelect->uRSSI) { + pSelect = pCurrBSS; + } + } + } + } + if (pSelect != NULL) { + pSelect->bSelected = TRUE; +/* + if (pDevice->bRoaming == FALSE) { + // Einsn Add @20070907 + ZERO_MEMORY(pbyDesireSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + MEMvCopy(pbyDesireSSID,pCurrBSS->abySSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1) ; + }*/ + + return(pSelect); + } + } + return(NULL); + +} + + +/*+ + * + * Routine Description: + * Clear BSS List + * + * Return Value: + * None. + * +-*/ + + +VOID +BSSvClearBSSList( + IN HANDLE hDeviceContext, + IN BOOL bKeepCurrBSSID + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (bKeepCurrBSSID) { + if (pMgmt->sBSSList[ii].bActive && + IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) { + // bKeepCurrBSSID = FALSE; + continue; + } + } + + if ((pMgmt->sBSSList[ii].bActive) && (pMgmt->sBSSList[ii].uClearCount < BSS_CLEAR_COUNT)) { + pMgmt->sBSSList[ii].uClearCount ++; + continue; + } + + pMgmt->sBSSList[ii].bActive = FALSE; + memset(&pMgmt->sBSSList[ii], 0, sizeof(KnownBSS)); + } + BSSvClearAnyBSSJoinRecord(pDevice); + + return; +} + + + +/*+ + * + * Routine Description: + * search BSS list by BSSID & SSID if matched + * + * Return Value: + * TRUE if found. + * +-*/ +PKnownBSS +BSSpAddrIsInBSSList( + IN HANDLE hDeviceContext, + IN PBYTE abyBSSID, + IN PWLAN_IE_SSID pSSID + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PKnownBSS pBSSList = NULL; + UINT ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSSList = &(pMgmt->sBSSList[ii]); + if (pBSSList->bActive) { + if (IS_ETH_ADDRESS_EQUAL(pBSSList->abyBSSID, abyBSSID)) { +// if (pSSID == NULL) +// return pBSSList; + if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){ + if (memcmp(pSSID->abySSID, + ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID, + pSSID->len) == 0) + return pBSSList; + } + } + } + } + + return NULL; +}; + + + + +/*+ + * + * Routine Description: + * Insert a BSS set into known BSS list + * + * Return Value: + * TRUE if success. + * +-*/ + +BOOL +BSSbInsertToBSSList ( + IN HANDLE hDeviceContext, + IN PBYTE abyBSSIDAddr, + IN QWORD qwTimestamp, + IN WORD wBeaconInterval, + IN WORD wCapInfo, + IN BYTE byCurrChannel, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pSuppRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates, + IN PERPObject psERP, + IN PWLAN_IE_RSN pRSN, + IN PWLAN_IE_RSN_EXT pRSNWPA, + IN PWLAN_IE_COUNTRY pIE_Country, + IN PWLAN_IE_QUIET pIE_Quiet, + IN UINT uIELength, + IN PBYTE pbyIEs, + IN HANDLE pRxPacketContext + ) +{ + + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PSRxMgmtPacket pRxPacket = (PSRxMgmtPacket)pRxPacketContext; + PKnownBSS pBSSList = NULL; + UINT ii; + BOOL bParsingQuiet = FALSE; + PWLAN_IE_QUIET pQuiet = NULL; + + + + pBSSList = (PKnownBSS)&(pMgmt->sBSSList[0]); + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSSList = (PKnownBSS)&(pMgmt->sBSSList[ii]); + if (!pBSSList->bActive) + break; + } + + if (ii == MAX_BSS_NUM){ + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Get free KnowBSS node failed.\n"); + return FALSE; + } + // save the BSS info + pBSSList->bActive = TRUE; + memcpy( pBSSList->abyBSSID, abyBSSIDAddr, WLAN_BSSID_LEN); + HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp)); + LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp)); + pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval); + pBSSList->wCapInfo = cpu_to_le16(wCapInfo); + pBSSList->uClearCount = 0; + + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + memcpy( pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + + pBSSList->uChannel = byCurrChannel; + + if (pSuppRates->len > WLAN_RATES_MAXLEN) + pSuppRates->len = WLAN_RATES_MAXLEN; + memcpy( pBSSList->abySuppRates, pSuppRates, pSuppRates->len + WLAN_IEHDR_LEN); + + if (pExtSuppRates != NULL) { + if (pExtSuppRates->len > WLAN_RATES_MAXLEN) + pExtSuppRates->len = WLAN_RATES_MAXLEN; + memcpy(pBSSList->abyExtSuppRates, pExtSuppRates, pExtSuppRates->len + WLAN_IEHDR_LEN); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbInsertToBSSList: pExtSuppRates->len = %d\n", pExtSuppRates->len); + + } else { + memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + } + pBSSList->sERP.byERP = psERP->byERP; + pBSSList->sERP.bERPExist = psERP->bERPExist; + + // Check if BSS is 802.11a/b/g + if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; + } else { + if (pBSSList->sERP.bERPExist == TRUE) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; + } else { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; + } + } + + pBSSList->byRxRate = pRxPacket->byRxRate; + pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF; + pBSSList->uRSSI = pRxPacket->uRSSI; + pBSSList->bySQ = pRxPacket->bySQ; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // assoc with BSS + if (pBSSList == pMgmt->pCurrBSS) { + bParsingQuiet = TRUE; + } + } + + WPA_ClearRSN(pBSSList); + + if (pRSNWPA != NULL) { + UINT uLen = pRSNWPA->len + 2; + + if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + pBSSList->wWPALen = uLen; + memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); + WPA_ParseRSN(pBSSList, pRSNWPA); + } + } + + WPA2_ClearRSN(pBSSList); + + if (pRSN != NULL) { + UINT uLen = pRSN->len + 2; + if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + pBSSList->wRSNLen = uLen; + memcpy(pBSSList->byRSNIE, pRSN, uLen); + WPA2vParseRSN(pBSSList, pRSN); + } + } + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pBSSList->bWPA2Valid == TRUE)) { + + PSKeyItem pTransmitKey = NULL; + BOOL bIs802_1x = FALSE; + + for (ii = 0; ii < pBSSList->wAKMSSAuthCount; ii ++) { + if (pBSSList->abyAKMSSAuthType[ii] == WLAN_11i_AKMSS_802_1X) { + bIs802_1x = TRUE; + break; + } + } + if ((bIs802_1x == TRUE) && (pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len) && + (MEMEqualMemory(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID, pSSID->len))) { + + bAdd_PMKID_Candidate((HANDLE)pDevice, pBSSList->abyBSSID, &pBSSList->sRSNCapObj); + + if ((pDevice->bLinkPass == TRUE) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if ((KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, PAIRWISE_KEY, &pTransmitKey) == TRUE) || + (KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBSSID, GROUP_KEY, &pTransmitKey) == TRUE)) { + pDevice->gsPMKIDCandidate.StatusType = Ndis802_11StatusType_PMKID_CandidateList; + pDevice->gsPMKIDCandidate.Version = 1; + + } + + } + } + } + + if (pDevice->bUpdateBBVGA) { + // Moniter if RSSI is too strong. + pBSSList->byRSSIStatCnt = 0; + RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &pBSSList->ldBmMAX); + pBSSList->ldBmAverage[0] = pBSSList->ldBmMAX; + for (ii = 1; ii < RSSI_STAT_COUNT; ii++) + pBSSList->ldBmAverage[ii] = 0; + } + + if ((pIE_Country != NULL) && + (pMgmt->b11hEnable == TRUE)) { + CARDvSetCountryInfo(pMgmt->pAdapter, + pBSSList->eNetworkTypeInUse, + pIE_Country); + } + + + + if ((bParsingQuiet == TRUE) && (pIE_Quiet != NULL)) { + if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && + (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { + // valid EID + if (pQuiet == NULL) { + pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; + CARDbSetQuiet( pMgmt->pAdapter, + TRUE, + pQuiet->byQuietCount, + pQuiet->byQuietPeriod, + *((PWORD)pQuiet->abyQuietDuration), + *((PWORD)pQuiet->abyQuietOffset) + ); + } else { + pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; + CARDbSetQuiet( pMgmt->pAdapter, + FALSE, + pQuiet->byQuietCount, + pQuiet->byQuietPeriod, + *((PWORD)pQuiet->abyQuietDuration), + *((PWORD)pQuiet->abyQuietOffset) + ); + } + } + } + + if ((bParsingQuiet == TRUE) && + (pQuiet != NULL)) { + CARDbStartQuiet(pMgmt->pAdapter); + } + + pBSSList->uIELength = uIELength; + if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN) + pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN; + MEMvCopy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength); + + return TRUE; +} + + +/*+ + * + * Routine Description: + * Update BSS set in known BSS list + * + * Return Value: + * TRUE if success. + * +-*/ +// TODO: input structure modify + +BOOL +BSSbUpdateToBSSList ( + IN HANDLE hDeviceContext, + IN QWORD qwTimestamp, + IN WORD wBeaconInterval, + IN WORD wCapInfo, + IN BYTE byCurrChannel, + IN BOOL bChannelHit, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pSuppRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates, + IN PERPObject psERP, + IN PWLAN_IE_RSN pRSN, + IN PWLAN_IE_RSN_EXT pRSNWPA, + IN PWLAN_IE_COUNTRY pIE_Country, + IN PWLAN_IE_QUIET pIE_Quiet, + IN PKnownBSS pBSSList, + IN UINT uIELength, + IN PBYTE pbyIEs, + IN HANDLE pRxPacketContext + ) +{ + int ii; + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PSRxMgmtPacket pRxPacket = (PSRxMgmtPacket)pRxPacketContext; + LONG ldBm; + BOOL bParsingQuiet = FALSE; + PWLAN_IE_QUIET pQuiet = NULL; + + + + if (pBSSList == NULL) + return FALSE; + + HIDWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(HIDWORD(qwTimestamp)); + LODWORD(pBSSList->qwBSSTimestamp) = cpu_to_le32(LODWORD(qwTimestamp)); + pBSSList->wBeaconInterval = cpu_to_le16(wBeaconInterval); + pBSSList->wCapInfo = cpu_to_le16(wCapInfo); + pBSSList->uClearCount = 0; + pBSSList->uChannel = byCurrChannel; +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BSSbUpdateToBSSList: pBSSList->uChannel: %d\n", pBSSList->uChannel); + + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + + if ((pSSID->len != 0) && (pSSID->abySSID[0] != 0)) + memcpy(pBSSList->abySSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + memcpy(pBSSList->abySuppRates, pSuppRates,pSuppRates->len + WLAN_IEHDR_LEN); + + if (pExtSuppRates != NULL) { + memcpy(pBSSList->abyExtSuppRates, pExtSuppRates,pExtSuppRates->len + WLAN_IEHDR_LEN); + } else { + memset(pBSSList->abyExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + } + pBSSList->sERP.byERP = psERP->byERP; + pBSSList->sERP.bERPExist = psERP->bERPExist; + + // Check if BSS is 802.11a/b/g + if (pBSSList->uChannel > CB_MAX_CHANNEL_24G) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11A; + } else { + if (pBSSList->sERP.bERPExist == TRUE) { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11G; + } else { + pBSSList->eNetworkTypeInUse = PHY_TYPE_11B; + } + } + + pBSSList->byRxRate = pRxPacket->byRxRate; + pBSSList->qwLocalTSF = pRxPacket->qwLocalTSF; + if(bChannelHit) + pBSSList->uRSSI = pRxPacket->uRSSI; + pBSSList->bySQ = pRxPacket->bySQ; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // assoc with BSS + if (pBSSList == pMgmt->pCurrBSS) { + bParsingQuiet = TRUE; + } + } + + WPA_ClearRSN(pBSSList); //mike update + + if (pRSNWPA != NULL) { + UINT uLen = pRSNWPA->len + 2; + if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSNWPA - pbyIEs))) { + pBSSList->wWPALen = uLen; + memcpy(pBSSList->byWPAIE, pRSNWPA, uLen); + WPA_ParseRSN(pBSSList, pRSNWPA); + } + } + + WPA2_ClearRSN(pBSSList); //mike update + + if (pRSN != NULL) { + UINT uLen = pRSN->len + 2; + if (uLen <= (uIELength - (UINT)(ULONG_PTR)((PBYTE)pRSN - pbyIEs))) { + pBSSList->wRSNLen = uLen; + memcpy(pBSSList->byRSNIE, pRSN, uLen); + WPA2vParseRSN(pBSSList, pRSN); + } + } + + if (pRxPacket->uRSSI != 0) { + RFvRSSITodBm(pDevice, (BYTE)(pRxPacket->uRSSI), &ldBm); + // Moniter if RSSI is too strong. + pBSSList->byRSSIStatCnt++; + pBSSList->byRSSIStatCnt %= RSSI_STAT_COUNT; + pBSSList->ldBmAverage[pBSSList->byRSSIStatCnt] = ldBm; + for(ii=0;ii<RSSI_STAT_COUNT;ii++) { + if (pBSSList->ldBmAverage[ii] != 0) { + pBSSList->ldBmMAX = max(pBSSList->ldBmAverage[ii], ldBm); + } + } + } + + if ((pIE_Country != NULL) && + (pMgmt->b11hEnable == TRUE)) { + CARDvSetCountryInfo(pMgmt->pAdapter, + pBSSList->eNetworkTypeInUse, + pIE_Country); + } + + if ((bParsingQuiet == TRUE) && (pIE_Quiet != NULL)) { + if ((((PWLAN_IE_QUIET)pIE_Quiet)->len == 8) && + (((PWLAN_IE_QUIET)pIE_Quiet)->byQuietCount != 0)) { + // valid EID + if (pQuiet == NULL) { + pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; + CARDbSetQuiet( pMgmt->pAdapter, + TRUE, + pQuiet->byQuietCount, + pQuiet->byQuietPeriod, + *((PWORD)pQuiet->abyQuietDuration), + *((PWORD)pQuiet->abyQuietOffset) + ); + } else { + pQuiet = (PWLAN_IE_QUIET)pIE_Quiet; + CARDbSetQuiet( pMgmt->pAdapter, + FALSE, + pQuiet->byQuietCount, + pQuiet->byQuietPeriod, + *((PWORD)pQuiet->abyQuietDuration), + *((PWORD)pQuiet->abyQuietOffset) + ); + } + } + } + + if ((bParsingQuiet == TRUE) && + (pQuiet != NULL)) { + CARDbStartQuiet(pMgmt->pAdapter); + } + + pBSSList->uIELength = uIELength; + if (pBSSList->uIELength > WLAN_BEACON_FR_MAXLEN) + pBSSList->uIELength = WLAN_BEACON_FR_MAXLEN; + memcpy(pBSSList->abyIEs, pbyIEs, pBSSList->uIELength); + + return TRUE; +} + + + + + +/*+ + * + * Routine Description: + * Search Node DB table to find the index of matched DstAddr + * + * Return Value: + * None + * +-*/ + +BOOL +BSSDBbIsSTAInNodeDB( + IN PVOID pMgmtObject, + IN PBYTE abyDstAddr, + OUT PUINT puNodeIndex + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + UINT ii; + + // Index = 0 reserved for AP Node + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + if (IS_ETH_ADDRESS_EQUAL(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) { + *puNodeIndex = ii; + return TRUE; + } + } + } + + return FALSE; +}; + + + +/*+ + * + * Routine Description: + * Find an empty node and allocated; if no empty found, + * instand used of most inactive one. + * + * Return Value: + * None + * +-*/ +VOID +BSSvCreateOneNode( + IN HANDLE hDeviceContext, + OUT PUINT puNodeIndex + ) +{ + + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT ii; + UINT BigestCount = 0; + UINT SelectIndex; + struct sk_buff *skb; + // Index = 0 reserved for AP Node (In STA mode) + // Index = 0 reserved for Broadcast/MultiCast (In AP mode) + SelectIndex = 1; + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + if (pMgmt->sNodeDBTable[ii].uInActiveCount > BigestCount) { + BigestCount = pMgmt->sNodeDBTable[ii].uInActiveCount; + SelectIndex = ii; + } + } + else { + break; + } + } + + // if not found replace uInActiveCount is largest one. + if ( ii == (MAX_NODE_NUM + 1)) { + *puNodeIndex = SelectIndex; + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Replace inactive node = %d\n", SelectIndex); + // clear ps buffer + if (pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue.next != NULL) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue)) != NULL) + dev_kfree_skb(skb); + } + } + else { + *puNodeIndex = ii; + } + + memset(&pMgmt->sNodeDBTable[*puNodeIndex], 0, sizeof(KnownNodeDB)); + pMgmt->sNodeDBTable[*puNodeIndex].bActive = TRUE; + pMgmt->sNodeDBTable[*puNodeIndex].uRatePollTimeout = FALLBACK_POLL_SECOND; + // for AP mode PS queue + skb_queue_head_init(&pMgmt->sNodeDBTable[*puNodeIndex].sTxPSQueue); + pMgmt->sNodeDBTable[*puNodeIndex].byAuthSequence = 0; + pMgmt->sNodeDBTable[*puNodeIndex].wEnQueueCnt = 0; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create node index = %d\n", ii); + return; +}; + + + +/*+ + * + * Routine Description: + * Remove Node by NodeIndex + * + * + * Return Value: + * None + * +-*/ +VOID +BSSvRemoveOneNode( + IN HANDLE hDeviceContext, + IN UINT uNodeIndex + ) +{ + + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + struct sk_buff *skb; + + + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue)) != NULL) + dev_kfree_skb(skb); + // clear context + memset(&pMgmt->sNodeDBTable[uNodeIndex], 0, sizeof(KnownNodeDB)); + // clear tx bit map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[uNodeIndex].wAID >> 3] &= ~byMask[pMgmt->sNodeDBTable[uNodeIndex].wAID & 7]; + + return; +}; +/*+ + * + * Routine Description: + * Update AP Node content in Index 0 of KnownNodeDB + * + * + * Return Value: + * None + * +-*/ + +VOID +BSSvUpdateAPNode( + IN HANDLE hDeviceContext, + IN PWORD pwCapInfo, + IN PWLAN_IE_SUPP_RATES pSuppRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uRateLen = WLAN_RATES_MAXLEN; + + memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); + + pMgmt->sNodeDBTable[0].bActive = TRUE; + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + uRateLen); + pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pExtSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + uRateLen); + RATEvParseMaxRate((PVOID) pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + TRUE, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); + memcpy(pMgmt->sNodeDBTable[0].abyMACAddr, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxSuppRate; + pMgmt->sNodeDBTable[0].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*pwCapInfo); + pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; +#ifdef PLICE_DEBUG + printk("BSSvUpdateAPNode:MaxSuppRate is %d\n",pMgmt->sNodeDBTable[0].wMaxSuppRate); +#endif + // Auto rate fallback function initiation. + // RATEbInit(pDevice); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->sNodeDBTable[0].wTxDataRate = %d \n", pMgmt->sNodeDBTable[0].wTxDataRate); + +}; + + + + + +/*+ + * + * Routine Description: + * Add Multicast Node content in Index 0 of KnownNodeDB + * + * + * Return Value: + * None + * +-*/ + + +VOID +BSSvAddMulticastNode( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + + if (!pDevice->bEnableHostWEP) + memset(&pMgmt->sNodeDBTable[0], 0, sizeof(KnownNodeDB)); + memset(pMgmt->sNodeDBTable[0].abyMACAddr, 0xff, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[0].bActive = TRUE; + pMgmt->sNodeDBTable[0].bPSEnable = FALSE; + skb_queue_head_init(&pMgmt->sNodeDBTable[0].sTxPSQueue); + RATEvParseMaxRate((PVOID) pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + TRUE, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); + pMgmt->sNodeDBTable[0].wTxDataRate = pMgmt->sNodeDBTable[0].wMaxBasicRate; +#ifdef PLICE_DEBUG + printk("BSSvAddMultiCastNode:pMgmt->sNodeDBTable[0].wTxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate); +#endif + pMgmt->sNodeDBTable[0].uRatePollTimeout = FALLBACK_POLL_SECOND; + +}; + + + + + +/*+ + * + * Routine Description: + * + * + * Second call back function to update Node DB info & AP link status + * + * + * Return Value: + * none. + * +-*/ + //2008-4-14 <add> by chester for led issue + #ifdef FOR_LED_ON_NOTEBOOK +BOOL cc=FALSE; +UINT status; +#endif +VOID +BSSvSecondCallBack( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT ii; + PWLAN_IE_SSID pItemSSID, pCurrSSID; + UINT uSleepySTACnt = 0; + UINT uNonShortSlotSTACnt = 0; + UINT uLongPreambleSTACnt = 0; +viawget_wpa_header* wpahdr; + + spin_lock_irq(&pDevice->lock); + + pDevice->uAssocCount = 0; + + pDevice->byERPFlag &= + ~(WLAN_SET_ERP_BARKER_MODE(1) | WLAN_SET_ERP_NONERP_PRESENT(1)); + //2008-4-14 <add> by chester for led issue +#ifdef FOR_LED_ON_NOTEBOOK +MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); +if (((BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA)&&(pDevice->bHWRadioOff == FALSE))||(BITbIsBitOn(pDevice->byGPIO,GPIO0_DATA)&&(pDevice->bHWRadioOff == TRUE)))&&(cc==FALSE)){ +cc=TRUE; +} +else if(cc==TRUE){ + +if(pDevice->bHWRadioOff == TRUE){ + if (BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA)) +//||(BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOn(pDevice->byRadioCtl, EEP_RADIOCTL_INV))) +{if(status==1) goto start; +status=1; +CARDbRadioPowerOff(pDevice); + pMgmt->sNodeDBTable[0].bActive = FALSE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + //netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + +} + if (BITbIsBitOn(pDevice->byGPIO,GPIO0_DATA)) +//||(BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOn(pDevice->byRadioCtl, EEP_RADIOCTL_INV))) +{if(status==2) goto start; +status=2; +CARDbRadioPowerOn(pDevice); +} } +else{ + if (BITbIsBitOn(pDevice->byGPIO,GPIO0_DATA)) +//||(BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOn(pDevice->byRadioCtl, EEP_RADIOCTL_INV))) +{if(status==3) goto start; +status=3; +CARDbRadioPowerOff(pDevice); + pMgmt->sNodeDBTable[0].bActive = FALSE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + //netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + +} + if (BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA)) +//||(BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOn(pDevice->byRadioCtl, EEP_RADIOCTL_INV))) +{if(status==4) goto start; +status=4; +CARDbRadioPowerOn(pDevice); +} } +} +start: +#endif + + + if (pDevice->wUseProtectCntDown > 0) { + pDevice->wUseProtectCntDown --; + } + else { + // disable protect mode + pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1)); + } + +{ + pDevice->byReAssocCount++; + if((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != TRUE)) { //10 sec timeout + printk("Re-association timeout!!!\n"); + pDevice->byReAssocCount = 0; + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + } + else if(pDevice->bLinkPass == TRUE) + pDevice->byReAssocCount = 0; +} + +#ifdef Calcu_LinkQual + s_uCalculateLinkQual((HANDLE)pDevice); +#endif + + for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { + + if (pMgmt->sNodeDBTable[ii].bActive) { + + // Increase in-activity counter + pMgmt->sNodeDBTable[ii].uInActiveCount++; + + if (ii > 0) { + if (pMgmt->sNodeDBTable[ii].uInActiveCount > MAX_INACTIVE_COUNT) { + BSSvRemoveOneNode(pDevice, ii); + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO + "Inactive timeout [%d] sec, STA index = [%d] remove\n", MAX_INACTIVE_COUNT, ii); + continue; + } + + if (pMgmt->sNodeDBTable[ii].eNodeState >= NODE_ASSOC) { + + pDevice->uAssocCount++; + + // check if Non ERP exist + if (pMgmt->sNodeDBTable[ii].uInActiveCount < ERP_RECOVER_COUNT) { + if (!pMgmt->sNodeDBTable[ii].bShortPreamble) { + pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1); + uLongPreambleSTACnt ++; + } + if (!pMgmt->sNodeDBTable[ii].bERPExist) { + pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1); + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + } + if (!pMgmt->sNodeDBTable[ii].bShortSlotTime) + uNonShortSlotSTACnt++; + } + } + + // check if any STA in PS mode + if (pMgmt->sNodeDBTable[ii].bPSEnable) + uSleepySTACnt++; + + + } + + // Rate fallback check + + if (!pDevice->bFixRate) { +/* + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (ii == 0)) + RATEvTxRateFallBack(pDevice, &(pMgmt->sNodeDBTable[ii])); +*/ + if (ii > 0) { + // ii = 0 for multicast node (AP & Adhoc) + RATEvTxRateFallBack((PVOID)pDevice, &(pMgmt->sNodeDBTable[ii])); + } + else { + // ii = 0 reserved for unicast AP node (Infra STA) + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) +#ifdef PLICE_DEBUG + printk("SecondCallback:Before:TxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate); +#endif + RATEvTxRateFallBack((PVOID)pDevice, &(pMgmt->sNodeDBTable[ii])); +#ifdef PLICE_DEBUG + printk("SecondCallback:After:TxDataRate is %d\n",pMgmt->sNodeDBTable[0].wTxDataRate); +#endif + + } + + } + + // check if pending PS queue + if (pMgmt->sNodeDBTable[ii].wEnQueueCnt != 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index= %d, Queue = %d pending \n", + ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); + if ((ii >0) && (pMgmt->sNodeDBTable[ii].wEnQueueCnt > 15)) { + BSSvRemoveOneNode(pDevice, ii); + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Pending many queues PS STA Index = %d remove \n", ii); + continue; + } + } + } + + } + + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->eCurrentPHYType == PHY_TYPE_11G)) { + + // on/off protect mode + if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)) { + if (!pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice->PortOffset); + pDevice->bProtectMode = TRUE; + } + } + else { + if (pDevice->bProtectMode) { + MACvDisableProtectMD(pDevice->PortOffset); + pDevice->bProtectMode = FALSE; + } + } + // on/off short slot time + + if (uNonShortSlotSTACnt > 0) { + if (pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = FALSE; + BBvSetShortSlotTime(pDevice); + vUpdateIFS((PVOID)pDevice); + } + } + else { + if (!pDevice->bShortSlotTime) { + pDevice->bShortSlotTime = TRUE; + BBvSetShortSlotTime(pDevice); + vUpdateIFS((PVOID)pDevice); + } + } + + // on/off barker long preamble mode + + if (uLongPreambleSTACnt > 0) { + if (!pDevice->bBarkerPreambleMd) { + MACvEnableBarkerPreambleMd(pDevice->PortOffset); + pDevice->bBarkerPreambleMd = TRUE; + } + } + else { + if (pDevice->bBarkerPreambleMd) { + MACvDisableBarkerPreambleMd(pDevice->PortOffset); + pDevice->bBarkerPreambleMd = FALSE; + } + } + + } + + + // Check if any STA in PS mode, enable DTIM multicast deliver + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (uSleepySTACnt > 0) + pMgmt->sNodeDBTable[0].bPSEnable = TRUE; + else + pMgmt->sNodeDBTable[0].bPSEnable = FALSE; + } + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pCurrSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; +//printk("pCurrSSID=%s\n",pCurrSSID->abySSID); + if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { + + if (pMgmt->sNodeDBTable[0].bActive) { // Assoc with BSS + // DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Callback inactive Count = [%d]\n", pMgmt->sNodeDBTable[0].uInActiveCount); + //if (pDevice->bUpdateBBVGA) { + // s_vCheckSensitivity((HANDLE) pDevice); + //} + if (pDevice->bUpdateBBVGA) { + // s_vCheckSensitivity((HANDLE) pDevice); + s_vCheckPreEDThreshold((HANDLE)pDevice); + } + if ((pMgmt->sNodeDBTable[0].uInActiveCount >= (LOST_BEACON_COUNT/2)) && + (pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) ) { + pDevice->byBBVGANew = pDevice->abyBBVGA[0]; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL); + } + + + if (pMgmt->sNodeDBTable[0].uInActiveCount >= LOST_BEACON_COUNT) { + pMgmt->sNodeDBTable[0].bActive = FALSE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + pDevice->bRoaming = TRUE; + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost AP beacon [%d] sec, disconnected !\n", pMgmt->sNodeDBTable[0].uInActiveCount); + if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_DISASSOC_MSG; + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; +//2008-4-3 modify by Chester for wpa +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw = pDevice->skb->data; +#endif + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + }; + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + } + } + else if (pItemSSID->len != 0) { + if (pDevice->uAutoReConnectTime < 10) { + pDevice->uAutoReConnectTime++; + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //network manager support need not do Roaming scan??? + if(pDevice->bWPASuppWextEnabled ==TRUE) + pDevice->uAutoReConnectTime = 0; + #endif + + } + else { + //mike use old encryption status for wpa reauthen + if(pDevice->bWPADEVUp) + pDevice->eEncryptionStatus = pDevice->eOldEncryptionStatus; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming ...\n"); + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID); + pDevice->uAutoReConnectTime = 0; + } + } + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + // if adhoc started which essid is NULL string, rescaning. + if ((pMgmt->eCurrState == WMAC_STATE_STARTED) && (pCurrSSID->len == 0)) { + if (pDevice->uAutoReConnectTime < 10) { + pDevice->uAutoReConnectTime++; + } + else { + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Adhoc re-scaning ...\n"); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + pDevice->uAutoReConnectTime = 0; + }; + } + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { + if (pDevice->bUpdateBBVGA) { + //s_vCheckSensitivity((HANDLE) pDevice); + s_vCheckPreEDThreshold((HANDLE)pDevice); + } + if (pMgmt->sNodeDBTable[0].uInActiveCount >=ADHOC_LOST_BEACON_COUNT) { + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost other STA beacon [%d] sec, started !\n", pMgmt->sNodeDBTable[0].uInActiveCount); + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + pMgmt->eCurrState = WMAC_STATE_STARTED; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + } + } + } + + spin_unlock_irq(&pDevice->lock); + + pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ); + add_timer(&pMgmt->sTimerSecondCallback); + return; +} + + + + +/*+ + * + * Routine Description: + * + * + * Update Tx attemps, Tx failure counter in Node DB + * + * + * Return Value: + * none. + * +-*/ + + + +VOID +BSSvUpdateNodeTxCounter( + IN HANDLE hDeviceContext, + IN BYTE byTsr0, + IN BYTE byTsr1, + IN PBYTE pbyBuffer, + IN UINT uFIFOHeaderSize + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex = 0; + BYTE byTxRetry = (byTsr0 & TSR0_NCR); + PSTxBufHead pTxBufHead; + PS802_11Header pMACHeader; + WORD wRate; + WORD wFallBackRate = RATE_1M; + BYTE byFallBack; + UINT ii; +// UINT txRetryTemp; +//PLICE_DEBUG-> + //txRetryTemp = byTxRetry; + //if (txRetryTemp== 8) + //txRetryTemp -=3; +//PLICE_DEBUG <- + pTxBufHead = (PSTxBufHead) pbyBuffer; + if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_0) { + byFallBack = AUTO_FB_0; + } else if (pTxBufHead->wFIFOCtl & FIFOCTL_AUTO_FB_1) { + byFallBack = AUTO_FB_1; + } else { + byFallBack = AUTO_FB_NONE; + } + wRate = pTxBufHead->wReserved; //?wRate + //printk("BSSvUpdateNodeTxCounter:byTxRetry is %d\n",byTxRetry); + +//printk("BSSvUpdateNodeTx:wRate is %d,byFallback is %d\n",wRate,byFallBack); +//#ifdef PLICE_DEBUG + //printk("BSSvUpdateNodeTx: wRate is %d\n",wRate); +////#endif + // Only Unicast using support rates + if (pTxBufHead->wFIFOCtl & FIFOCTL_NEEDACK) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wRate %04X, byTsr0 %02X, byTsr1 %02X\n", wRate, byTsr0, byTsr1); + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) { + pMgmt->sNodeDBTable[0].uTxAttempts += 1; + if ((byTsr1 & TSR1_TERR) == 0) { + // transmit success, TxAttempts at least plus one + pMgmt->sNodeDBTable[0].uTxOk[MAX_RATE]++; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + wFallBackRate = wRate; + } else if (byFallBack == AUTO_FB_0) { +//PLICE_DEBUG + if (byTxRetry < 5) + //if (txRetryTemp < 5) + wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry]; + //wFallBackRate = awHWRetry0[wRate-RATE_12M][byTxRetry]; + //wFallBackRate = awHWRetry0[wRate-RATE_18M][txRetryTemp] +1; + else + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + //wFallBackRate = awHWRetry0[wRate-RATE_12M][4]; + } else if (byFallBack == AUTO_FB_1) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + } + pMgmt->sNodeDBTable[0].uTxOk[wFallBackRate]++; + } else { + pMgmt->sNodeDBTable[0].uTxFailures ++; + } + pMgmt->sNodeDBTable[0].uTxRetry += byTxRetry; + if (byTxRetry != 0) { + pMgmt->sNodeDBTable[0].uTxFail[MAX_RATE]+=byTxRetry; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + pMgmt->sNodeDBTable[0].uTxFail[wRate]+=byTxRetry; + } else if (byFallBack == AUTO_FB_0) { +//PLICE_DEBUG + for(ii=0;ii<byTxRetry;ii++) + //for (ii=0;ii<txRetryTemp;ii++) + { + if (ii < 5) + { + +//PLICE_DEBUG + wFallBackRate = awHWRetry0[wRate-RATE_18M][ii]; + //printk(" II is %d:BSSvUpdateNodeTx:wFallBackRate is %d\n",ii,wFallBackRate); + //wFallBackRate = awHWRetry0[wRate-RATE_12M][ii]; + } + else + { + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + //printk("ii is %d BSSvUpdateNodeTx:wFallBackRate is %d\n",ii,wFallBackRate); + //wFallBackRate = awHWRetry0[wRate-RATE_12M][4]; + } + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } + } else if (byFallBack == AUTO_FB_1) { + for(ii=0;ii<byTxRetry;ii++) { + if (ii < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][ii]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[0].uTxFail[wFallBackRate]++; + } + } + } + }; + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + + pMACHeader = (PS802_11Header)(pbyBuffer + uFIFOHeaderSize); + + if (BSSDBbIsSTAInNodeDB((HANDLE)pMgmt, &(pMACHeader->abyAddr1[0]), &uNodeIndex)){ + pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts += 1; + if ((byTsr1 & TSR1_TERR) == 0) { + // transmit success, TxAttempts at least plus one + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + wFallBackRate = wRate; + } else if (byFallBack == AUTO_FB_0) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry0[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + } else if (byFallBack == AUTO_FB_1) { + if (byTxRetry < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][byTxRetry]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + } + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wFallBackRate]++; + } else { + pMgmt->sNodeDBTable[uNodeIndex].uTxFailures ++; + } + pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += byTxRetry; + if (byTxRetry != 0) { + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[MAX_RATE]+=byTxRetry; + if ( (byFallBack == AUTO_FB_NONE) || + (wRate < RATE_18M) ) { + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wRate]+=byTxRetry; + } else if (byFallBack == AUTO_FB_0) { + for(ii=0;ii<byTxRetry;ii++) { + if (ii < 5) + wFallBackRate = awHWRetry0[wRate-RATE_18M][ii]; + else + wFallBackRate = awHWRetry0[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + } + } else if (byFallBack == AUTO_FB_1) { + for(ii=0;ii<byTxRetry;ii++) { + if (ii < 5) + wFallBackRate = awHWRetry1[wRate-RATE_18M][ii]; + else + wFallBackRate = awHWRetry1[wRate-RATE_18M][4]; + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[wFallBackRate]++; + } + } + } + }; + } + }; + + return; + +} + + + + +/*+ + * + * Routine Description: + * Clear Nodes & skb in DB Table + * + * + * Parameters: + * In: + * hDeviceContext - The adapter context. + * uStartIndex - starting index + * Out: + * none + * + * Return Value: + * None. + * +-*/ + + +VOID +BSSvClearNodeDBTable( + IN HANDLE hDeviceContext, + IN UINT uStartIndex + ) + +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + struct sk_buff *skb; + UINT ii; + + for (ii = uStartIndex; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive) { + // check if sTxPSQueue has been initial + if (pMgmt->sNodeDBTable[ii].sTxPSQueue.next != NULL) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS skb != NULL %d\n", ii); + dev_kfree_skb(skb); + } + } + memset(&pMgmt->sNodeDBTable[ii], 0, sizeof(KnownNodeDB)); + } + } + + return; +}; + + +VOID s_vCheckSensitivity( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PKnownBSS pBSSList = NULL; + PSMgmtObject pMgmt = pDevice->pMgmt; + int ii; + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) && (pDevice->byRFType == RF_RFMD2959) && + (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { + return; + } + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); + if (pBSSList != NULL) { + // Updata BB Reg if RSSI is too strong. + LONG LocalldBmAverage = 0; + LONG uNumofdBm = 0; + for (ii = 0; ii < RSSI_STAT_COUNT; ii++) { + if (pBSSList->ldBmAverage[ii] != 0) { + uNumofdBm ++; + LocalldBmAverage += pBSSList->ldBmAverage[ii]; + } + } + if (uNumofdBm > 0) { + LocalldBmAverage = LocalldBmAverage/uNumofdBm; + for (ii=0;ii<BB_VGA_LEVEL;ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LocalldBmAverage:%ld, %ld %02x\n", LocalldBmAverage, pDevice->ldBmThreshold[ii], pDevice->abyBBVGA[ii]); + if (LocalldBmAverage < pDevice->ldBmThreshold[ii]) { + pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; + break; + } + } + if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { + pDevice->uBBVGADiffCount++; + if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_CHANGE_BBSENSITIVITY, NULL); + } else { + pDevice->uBBVGADiffCount = 0; + } + } + } + } +} + + +VOID +BSSvClearAnyBSSJoinRecord ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT ii; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pMgmt->sBSSList[ii].bSelected = FALSE; + } + return; +} + +#ifdef Calcu_LinkQual +VOID s_uCalculateLinkQual( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + ULONG TxOkRatio, TxCnt; + ULONG RxOkRatio,RxCnt; + ULONG RssiRatio; + long ldBm; + +TxCnt = pDevice->scStatistic.TxNoRetryOkCount + + pDevice->scStatistic.TxRetryOkCount + + pDevice->scStatistic.TxFailCount; +RxCnt = pDevice->scStatistic.RxFcsErrCnt + + pDevice->scStatistic.RxOkCnt; +TxOkRatio = (TxCnt < 6) ? 4000:((pDevice->scStatistic.TxNoRetryOkCount * 4000) / TxCnt); +RxOkRatio = (RxCnt < 6) ? 2000:((pDevice->scStatistic.RxOkCnt * 2000) / RxCnt); +//decide link quality +if(pDevice->bLinkPass !=TRUE) +{ + // printk("s_uCalculateLinkQual-->Link disconnect and Poor quality**\n"); + pDevice->scStatistic.LinkQuality = 0; + pDevice->scStatistic.SignalStren = 0; +} +else +{ + RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm); + if(-ldBm < 50) { + RssiRatio = 4000; + } + else if(-ldBm > 90) { + RssiRatio = 0; + } + else { + RssiRatio = (40-(-ldBm-50))*4000/40; + } + pDevice->scStatistic.SignalStren = RssiRatio/40; + pDevice->scStatistic.LinkQuality = (RssiRatio+TxOkRatio+RxOkRatio)/100; +} + pDevice->scStatistic.RxFcsErrCnt = 0; + pDevice->scStatistic.RxOkCnt = 0; + pDevice->scStatistic.TxFailCount = 0; + pDevice->scStatistic.TxNoRetryOkCount = 0; + pDevice->scStatistic.TxRetryOkCount = 0; + return; +} +#endif + +VOID s_vCheckPreEDThreshold( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PKnownBSS pBSSList = NULL; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + pBSSList = BSSpAddrIsInBSSList(pDevice, pMgmt->abyCurrBSSID, (PWLAN_IE_SSID)pMgmt->abyCurrSSID); + if (pBSSList != NULL) { + pDevice->byBBPreEDRSSI = (BYTE) (~(pBSSList->ldBmAverRange) + 1); + //BBvUpdatePreEDThreshold(pDevice, FALSE); + } + } + return; +} diff --git a/drivers/staging/vt6655/bssdb.h b/drivers/staging/vt6655/bssdb.h new file mode 100644 index 00000000000..d35616d4883 --- /dev/null +++ b/drivers/staging/vt6655/bssdb.h @@ -0,0 +1,380 @@ +/* + * 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: bssdb.h + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Author: Lyndon Chen + * + * Date: July 16, 2002 + * + */ + +#ifndef __BSSDB_H__ +#define __BSSDB_H__ + +//#if !defined(__DEVICE_H__) +//#include "device.h" +//#endif +#include <linux/skbuff.h> +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + +#define MAX_NODE_NUM 64 +#define MAX_BSS_NUM 42 +#define LOST_BEACON_COUNT 10 // 10 sec, XP defined +#define MAX_PS_TX_BUF 32 // sta max power saving tx buf +#define ADHOC_LOST_BEACON_COUNT 30 // 30 sec, beacon lost for adhoc only +#define MAX_INACTIVE_COUNT 300 // 300 sec, inactive STA node refresh + +#define USE_PROTECT_PERIOD 10 // 10 sec, Use protect mode check period +#define ERP_RECOVER_COUNT 30 // 30 sec, ERP support callback check +#define BSS_CLEAR_COUNT 1 + +#define RSSI_STAT_COUNT 10 +#define MAX_CHECK_RSSI_COUNT 8 + +// STA dwflags +#define WLAN_STA_AUTH BIT0 +#define WLAN_STA_ASSOC BIT1 +#define WLAN_STA_PS BIT2 +#define WLAN_STA_TIM BIT3 +// permanent; do not remove entry on expiration +#define WLAN_STA_PERM BIT4 +// If 802.1X is used, this flag is +// controlling whether STA is authorized to +// send and receive non-IEEE 802.1X frames +#define WLAN_STA_AUTHORIZED BIT5 + +#define MAX_RATE 12 + +#define MAX_WPA_IE_LEN 64 + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Types ------------------------------*/ + +// +// IEEE 802.11 Structures and definitions +// + +typedef enum _NDIS_802_11_NETWORK_TYPE +{ + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM24, + Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; + + +typedef struct tagSERPObject { + BOOL bERPExist; + BYTE byERP; +} ERPObject, DEF* PERPObject; + + +typedef struct tagSRSNCapObject { + BOOL bRSNCapExist; + WORD wRSNCap; +} SRSNCapObject, DEF* PSRSNCapObject; + +// BSS info(AP) +#pragma pack(1) +typedef struct tagKnownBSS { + // BSS info + BOOL bActive; + BYTE abyBSSID[WLAN_BSSID_LEN]; + UINT uChannel; + BYTE abySuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE abyExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + UINT uRSSI; + BYTE bySQ; + WORD wBeaconInterval; + WORD wCapInfo; + BYTE abySSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + BYTE byRxRate; +// WORD wATIMWindow; + BYTE byRSSIStatCnt; + LONG ldBmMAX; + LONG ldBmAverage[RSSI_STAT_COUNT]; + LONG ldBmAverRange; + //For any BSSID selection improvment + BOOL bSelected; + + //++ WPA informations + BOOL bWPAValid; + BYTE byGKType; + BYTE abyPKType[4]; + WORD wPKCount; + BYTE abyAuthType[4]; + WORD wAuthCount; + BYTE byDefaultK_as_PK; + BYTE byReplayIdx; + //-- + + //++ WPA2 informations + BOOL bWPA2Valid; + BYTE byCSSGK; + WORD wCSSPKCount; + BYTE abyCSSPK[4]; + WORD wAKMSSAuthCount; + BYTE abyAKMSSAuthType[4]; + + //++ wpactl + BYTE byWPAIE[MAX_WPA_IE_LEN]; + BYTE byRSNIE[MAX_WPA_IE_LEN]; + WORD wWPALen; + WORD wRSNLen; + + // Clear count + UINT uClearCount; +// BYTE abyIEs[WLAN_BEACON_FR_MAXLEN]; + UINT uIELength; + QWORD qwBSSTimestamp; + QWORD qwLocalTSF; // local TSF timer + +// NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + CARD_PHY_TYPE eNetworkTypeInUse; + + ERPObject sERP; + SRSNCapObject sRSNCapObj; + BYTE abyIEs[1024]; // don't move this field !! + +}__attribute__ ((__packed__)) +KnownBSS , DEF* PKnownBSS; + +//2006-1116-01,<Add> by NomadZhao +#pragma pack() + +typedef enum tagNODE_STATE { + NODE_FREE, + NODE_AGED, + NODE_KNOWN, + NODE_AUTH, + NODE_ASSOC +} NODE_STATE, *PNODE_STATE; + + +// STA node info +typedef struct tagKnownNodeDB { + // STA info + BOOL bActive; + BYTE abyMACAddr[WLAN_ADDR_LEN]; + BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; + BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; + WORD wTxDataRate; + BOOL bShortPreamble; + BOOL bERPExist; + BOOL bShortSlotTime; + UINT uInActiveCount; + WORD wMaxBasicRate; //Get from byTopOFDMBasicRate or byTopCCKBasicRate which depends on packetTyp. + WORD wMaxSuppRate; //Records the highest supported rate getting from SuppRates IE and ExtSuppRates IE in Beacon. + WORD wSuppRate; + BYTE byTopOFDMBasicRate;//Records the highest basic rate in OFDM mode + BYTE byTopCCKBasicRate; //Records the highest basic rate in CCK mode + + // For AP mode + struct sk_buff_head sTxPSQueue; + WORD wCapInfo; + WORD wListenInterval; + WORD wAID; + NODE_STATE eNodeState; + BOOL bPSEnable; + BOOL bRxPSPoll; + BYTE byAuthSequence; + ULONG ulLastRxJiffer; + BYTE bySuppRate; + DWORD dwFlags; + WORD wEnQueueCnt; + + BOOL bOnFly; + ULONGLONG KeyRSC; + BYTE byKeyIndex; + DWORD dwKeyIndex; + BYTE byCipherSuite; + DWORD dwTSC47_16; + WORD wTSC15_0; + UINT uWepKeyLength; + BYTE abyWepKey[WLAN_WEPMAX_KEYLEN]; + // + // Auto rate fallback vars + BOOL bIsInFallback; + UINT uAverageRSSI; + UINT uRateRecoveryTimeout; + UINT uRatePollTimeout; + UINT uTxFailures; + UINT uTxAttempts; + + UINT uTxRetry; + UINT uFailureRatio; + UINT uRetryRatio; + UINT uTxOk[MAX_RATE+1]; + UINT uTxFail[MAX_RATE+1]; + UINT uTimeCount; + +} KnownNodeDB, DEF* PKnownNodeDB; + + +/*--------------------- Export Functions --------------------------*/ + + + +PKnownBSS +BSSpSearchBSSList( + IN HANDLE hDeviceContext, + IN PBYTE pbyDesireBSSID, + IN PBYTE pbyDesireSSID, + IN CARD_PHY_TYPE ePhyType + ); + +PKnownBSS +BSSpAddrIsInBSSList( + IN HANDLE hDeviceContext, + IN PBYTE abyBSSID, + IN PWLAN_IE_SSID pSSID + ); + +VOID +BSSvClearBSSList( + IN HANDLE hDeviceContext, + IN BOOL bKeepCurrBSSID + ); + +BOOL +BSSbInsertToBSSList( + IN HANDLE hDeviceContext, + IN PBYTE abyBSSIDAddr, + IN QWORD qwTimestamp, + IN WORD wBeaconInterval, + IN WORD wCapInfo, + IN BYTE byCurrChannel, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pSuppRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates, + IN PERPObject psERP, + IN PWLAN_IE_RSN pRSN, + IN PWLAN_IE_RSN_EXT pRSNWPA, + IN PWLAN_IE_COUNTRY pIE_Country, + IN PWLAN_IE_QUIET pIE_Quiet, + IN UINT uIELength, + IN PBYTE pbyIEs, + IN HANDLE pRxPacketContext + ); + + +BOOL +BSSbUpdateToBSSList( + IN HANDLE hDeviceContext, + IN QWORD qwTimestamp, + IN WORD wBeaconInterval, + IN WORD wCapInfo, + IN BYTE byCurrChannel, + IN BOOL bChannelHit, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pSuppRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates, + IN PERPObject psERP, + IN PWLAN_IE_RSN pRSN, + IN PWLAN_IE_RSN_EXT pRSNWPA, + IN PWLAN_IE_COUNTRY pIE_Country, + IN PWLAN_IE_QUIET pIE_Quiet, + IN PKnownBSS pBSSList, + IN UINT uIELength, + IN PBYTE pbyIEs, + IN HANDLE pRxPacketContext + ); + + +BOOL +BSSDBbIsSTAInNodeDB( + IN HANDLE hDeviceContext, + IN PBYTE abyDstAddr, + OUT PUINT puNodeIndex + ); + +VOID +BSSvCreateOneNode( + IN HANDLE hDeviceContext, + OUT PUINT puNodeIndex + ); + +VOID +BSSvUpdateAPNode( + IN HANDLE hDeviceContext, + IN PWORD pwCapInfo, + IN PWLAN_IE_SUPP_RATES pItemRates, + IN PWLAN_IE_SUPP_RATES pExtSuppRates + ); + + +VOID +BSSvSecondCallBack( + IN HANDLE hDeviceContext + ); + +VOID +BSSvUpdateNodeTxCounter( + IN HANDLE hDeviceContext, + IN BYTE byTsr0, + IN BYTE byTsr1, + IN PBYTE pbyBuffer, + IN UINT uFIFOHeaderSize + ); + +VOID +BSSvRemoveOneNode( + IN HANDLE hDeviceContext, + IN UINT uNodeIndex + ); + +VOID +BSSvAddMulticastNode( + IN HANDLE hDeviceContext + ); + + +VOID +BSSvClearNodeDBTable( + IN HANDLE hDeviceContext, + IN UINT uStartIndex + ); + +VOID +BSSvClearAnyBSSJoinRecord( + IN HANDLE hDeviceContext + ); + +#endif //__BSSDB_H__ diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c new file mode 100644 index 00000000000..723f44e0bba --- /dev/null +++ b/drivers/staging/vt6655/card.c @@ -0,0 +1,3126 @@ +/* + * 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: card.c + * Purpose: Provide functions to setup NIC operation mode + * Functions: + * s_vSafeResetTx - Rest Tx + * CARDvSetRSPINF - Set RSPINF + * vUpdateIFS - Update slotTime,SIFS,DIFS, and EIFS + * CARDvUpdateBasicTopRate - Update BasicTopRate + * CARDbAddBasicRate - Add to BasicRateSet + * CARDbSetBasicRate - Set Basic Tx Rate + * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet + * CARDvSetLoopbackMode - Set Loopback mode + * CARDbSoftwareReset - Sortware reset NIC + * CARDqGetTSFOffset - Caculate TSFOffset + * CARDbGetCurrentTSF - Read Current NIC TSF counter + * CARDqGetNextTBTT - Caculate Next Beacon TSF counter + * CARDvSetFirstNextTBTT - Set NIC Beacon time + * CARDvUpdateNextTBTT - Sync. NIC Beacon time + * CARDbRadioPowerOff - Turn Off NIC Radio Power + * CARDbRadioPowerOn - Turn On NIC Radio Power + * CARDbSetWEPMode - Set NIC Wep mode + * CARDbSetTxPower - Set NIC tx power + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-26-2003 Kyle Hsu: Modify the defination type of dwIoBase. + * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). + * + */ + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__VNTWIFI_H__) +#include "vntwifi.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__RC4_H__) +#include "rc4.h" +#endif +#if !defined(__COUNTRY_H__) +#include "country.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif + + + +/*--------------------- Static Definitions -------------------------*/ + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +#define C_SIFS_A 16 // micro sec. +#define C_SIFS_BG 10 + +#define C_EIFS 80 // micro sec. + + +#define C_SLOT_SHORT 9 // micro sec. +#define C_SLOT_LONG 20 + +#define C_CWMIN_A 15 // slot time +#define C_CWMIN_B 31 + +#define C_CWMAX 1023 // slot time + +#define CARD_MAX_CHANNEL_TBL 56 + +#define WAIT_BEACON_TX_DOWN_TMO 3 // Times + +typedef struct tagSChannelTblElement { + BYTE byChannelNumber; + UINT uFrequency; + BOOL bValid; + BYTE byMAP; +}SChannelTblElement, DEF* PSChannelTblElement; + + //1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M +static BYTE abyDefaultSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C}; + //6M, 9M, 12M, 48M +static BYTE abyDefaultExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60}; + //6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M +static BYTE abyDefaultSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + //1M, 2M, 5M, 11M, +static BYTE abyDefaultSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + + +const WORD cwRXBCNTSFOff[MAX_RATE] = +{17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; + +static SChannelTblElement sChannelTbl[CARD_MAX_CHANNEL_TBL+1] = +{ + {0, 0, FALSE, 0}, + {1, 2412, TRUE, 0}, + {2, 2417, TRUE, 0}, + {3, 2422, TRUE, 0}, + {4, 2427, TRUE, 0}, + {5, 2432, TRUE, 0}, + {6, 2437, TRUE, 0}, + {7, 2442, TRUE, 0}, + {8, 2447, TRUE, 0}, + {9, 2452, TRUE, 0}, + {10, 2457, TRUE, 0}, + {11, 2462, TRUE, 0}, + {12, 2467, TRUE, 0}, + {13, 2472, TRUE, 0}, + {14, 2484, TRUE, 0}, + {183, 4915, TRUE, 0}, + {184, 4920, TRUE, 0}, + {185, 4925, TRUE, 0}, + {187, 4935, TRUE, 0}, + {188, 4940, TRUE, 0}, + {189, 4945, TRUE, 0}, + {192, 4960, TRUE, 0}, + {196, 4980, TRUE, 0}, + {7, 5035, TRUE, 0}, + {8, 5040, TRUE, 0}, + {9, 5045, TRUE, 0}, + {11, 5055, TRUE, 0}, + {12, 5060, TRUE, 0}, + {16, 5080, TRUE, 0}, + {34, 5170, TRUE, 0}, + {36, 5180, TRUE, 0}, + {38, 5190, TRUE, 0}, + {40, 5200, TRUE, 0}, + {42, 5210, TRUE, 0}, + {44, 5220, TRUE, 0}, + {46, 5230, TRUE, 0}, + {48, 5240, TRUE, 0}, + {52, 5260, TRUE, 0}, + {56, 5280, TRUE, 0}, + {60, 5300, TRUE, 0}, + {64, 5320, TRUE, 0}, + {100, 5500, TRUE, 0}, + {104, 5520, TRUE, 0}, + {108, 5540, TRUE, 0}, + {112, 5560, TRUE, 0}, + {116, 5580, TRUE, 0}, + {120, 5600, TRUE, 0}, + {124, 5620, TRUE, 0}, + {128, 5640, TRUE, 0}, + {132, 5660, TRUE, 0}, + {136, 5680, TRUE, 0}, + {140, 5700, TRUE, 0}, + {149, 5745, TRUE, 0}, + {153, 5765, TRUE, 0}, + {157, 5785, TRUE, 0}, + {161, 5805, TRUE, 0}, + {165, 5825, TRUE, 0} +}; + + +/************************************************************************ + * The Radar regulation rules for each country + ************************************************************************/ +SCountryTable ChannelRuleTab[CCODE_MAX+1] = +{ +/************************************************************************ + * This table is based on Athero driver rules + ************************************************************************/ +/* Country Available channels, ended with 0 */ +/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 */ +{CCODE_FCC, {'U','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_TELEC, {'J','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 23, 0, 0, 23, 0, 23, 23, 0, 23, 0, 0, 23, 23, 23, 0, 23, 0, 23, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ETSI, {'E','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_RESV3, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV4, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV5, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV6, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV7, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV8, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESV9, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVa, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVb, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVc, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVd, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RESVe, {' ',' '}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALLBAND, {' ',' '}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALBANIA, {'A','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ALGERIA, {'D','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ARGENTINA, {'A','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0} }, +{CCODE_ARMENIA, {'A','M'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_AUSTRALIA, {'A','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_AUSTRIA, {'A','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_AZERBAIJAN, {'A','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BAHRAIN, {'B','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELARUS, {'B','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELGIUM, {'B','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BELIZE, {'B','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BOLIVIA, {'B','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BRAZIL, {'B','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_BRUNEI_DARUSSALAM, {'B','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_BULGARIA, {'B','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 0, 0, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0} }, +{CCODE_CANADA, {'C','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_CHILE, {'C','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17} }, +{CCODE_CHINA, {'C','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_COLOMBIA, {'C','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_COSTA_RICA, {'C','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_CROATIA, {'H','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_CYPRUS, {'C','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_CZECH, {'C','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_DENMARK, {'D','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_DOMINICAN_REPUBLIC, {'D','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_ECUADOR, {'E','C'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_EGYPT, {'E','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_EL_SALVADOR, {'S','V'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ESTONIA, {'E','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_FINLAND, {'F','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_FRANCE, {'F','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GERMANY, {'D','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_GREECE, {'G','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GEORGIA, {'G','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_GUATEMALA, {'G','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_HONDURAS, {'H','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_HONG_KONG, {'H','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_HUNGARY, {'H','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ICELAND, {'I','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_INDIA, {'I','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_INDONESIA, {'I','D'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_IRAN, {'I','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_IRELAND, {'I','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_ITALY, {'I','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_ISRAEL, {'I','L'}, { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JAPAN, {'J','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JORDAN, {'J','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_KAZAKHSTAN, {'K','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_KUWAIT, {'K','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LATVIA, {'L','V'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LEBANON, {'L','B'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LEICHTENSTEIN, {'L','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_LITHUANIA, {'L','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_LUXEMBURG, {'L','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_MACAU, {'M','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_MACEDONIA, {'M','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MALTA, {'M','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_MALAYSIA, {'M','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MEXICO, {'M','X'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_MONACO, {'M','C'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MOROCCO, {'M','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_NETHERLANDS, {'N','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_NEW_ZEALAND, {'N','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 23, 0, 23, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_NORTH_KOREA, {'K','P'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_NORWAY, {'N','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_OMAN, {'O','M'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PAKISTAN, {'P','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PANAMA, {'P','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_PERU, {'P','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_PHILIPPINES, {'P','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_POLAND, {'P','L'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_PORTUGAL, {'P','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_PUERTO_RICO, {'P','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_QATAR, {'Q','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ROMANIA, {'R','O'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_RUSSIA, {'R','U'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SAUDI_ARABIA, {'S','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SINGAPORE, {'S','G'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20} }, +{CCODE_SLOVAKIA, {'S','K'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_SLOVENIA, {'S','I'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SOUTH_AFRICA, {'Z','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SOUTH_KOREA, {'K','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_SPAIN, {'E','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 16, 0, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0} }, +{CCODE_SWEDEN, {'S','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_SWITZERLAND, {'C','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_SYRIA, {'S','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TAIWAN, {'T','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 0} }, +{CCODE_THAILAND, {'T','H'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_TRINIDAD_TOBAGO, {'T','T'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 0, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TUNISIA, {'T','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_TURKEY, {'T','R'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UK, {'G','B'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 20, 0, 20, 0, 20, 20, 20, 20, 20, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0} }, +{CCODE_UKRAINE, {'U','A'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UNITED_ARAB_EMIRATES, {'A','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_UNITED_STATES, {'U','S'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} + , { 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 17, 0, 17, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 30, 30, 30} }, +{CCODE_URUGUAY, {'U','Y'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_UZBEKISTAN, {'U','Z'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_VENEZUELA, {'V','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0} + , { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0} }, +{CCODE_VIETNAM, {'V','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_YEMEN, {'Y','E'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_ZIMBABWE, {'Z','W'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_JAPAN_W52_W53, {'J','J'}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +{CCODE_MAX, {'U','N'}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } +/* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 */ +}; + + +/*--------------------- Static Functions --------------------------*/ + +static +VOID +s_vCaculateOFDMRParameter( + IN BYTE byRate, + IN CARD_PHY_TYPE ePHYType, + OUT PBYTE pbyTxRate, + OUT PBYTE pbyRsvTime + ); + + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +/*--------------------- Export function -------------------------*/ +/************************************************************************ + * Country Channel Valid + * Input: CountryCode, ChannelNum + * ChanneIndex is defined as VT3253 MAC channel: + * 1 = 2.4G channel 1 + * 2 = 2.4G channel 2 + * ... + * 14 = 2.4G channel 14 + * 15 = 4.9G channel 183 + * 16 = 4.9G channel 184 + * ..... + * Output: TRUE if the specified 5GHz band is allowed to be used. + False otherwise. +// 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + +// 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, +// 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + ************************************************************************/ +//2008-8-4 <add> by chester +BOOL +ChannelValid(UINT CountryCode, UINT ChannelIndex) +{ + BOOL bValid; + + bValid = FALSE; + /* + * If Channel Index is invalid, return invalid + */ + if ((ChannelIndex > CB_MAX_CHANNEL) || + (ChannelIndex == 0)) + { + bValid = FALSE; + goto exit; + } + + bValid = sChannelTbl[ChannelIndex].bValid; + +exit: + return (bValid); + +} /* end ChannelValid */ + + +/* + * Description: Caculate TxRate and RsvTime fields for RSPINF in OFDM mode. + * + * Parameters: + * In: + * wRate - Tx Rate + * byPktType - Tx Packet type + * Out: + * pbyTxRate - pointer to RSPINF TxRate field + * pbyRsvTime - pointer to RSPINF RsvTime field + * + * Return Value: none + * + */ +static +VOID +s_vCaculateOFDMRParameter ( + IN BYTE byRate, + IN CARD_PHY_TYPE ePHYType, + OUT PBYTE pbyTxRate, + OUT PBYTE pbyRsvTime + ) +{ + switch (byRate) { + case RATE_6M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9B; + *pbyRsvTime = 44; + } + else { + *pbyTxRate = 0x8B; + *pbyRsvTime = 50; + } + break; + + case RATE_9M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9F; + *pbyRsvTime = 36; + } + else { + *pbyTxRate = 0x8F; + *pbyRsvTime = 42; + } + break; + + case RATE_12M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9A; + *pbyRsvTime = 32; + } + else { + *pbyTxRate = 0x8A; + *pbyRsvTime = 38; + } + break; + + case RATE_18M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9E; + *pbyRsvTime = 28; + } + else { + *pbyTxRate = 0x8E; + *pbyRsvTime = 34; + } + break; + + case RATE_36M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9D; + *pbyRsvTime = 24; + } + else { + *pbyTxRate = 0x8D; + *pbyRsvTime = 30; + } + break; + + case RATE_48M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x98; + *pbyRsvTime = 24; + } + else { + *pbyTxRate = 0x88; + *pbyRsvTime = 30; + } + break; + + case RATE_54M : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x9C; + *pbyRsvTime = 24; + } + else { + *pbyTxRate = 0x8C; + *pbyRsvTime = 30; + } + break; + + case RATE_24M : + default : + if (ePHYType == PHY_TYPE_11A) {//5GHZ + *pbyTxRate = 0x99; + *pbyRsvTime = 28; + } + else { + *pbyTxRate = 0x89; + *pbyRsvTime = 34; + } + break; + } +} + + + +/* + * Description: Set RSPINF + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +static +VOID +s_vSetRSPINF (PSDevice pDevice, CARD_PHY_TYPE ePHYType, PVOID pvSupportRateIEs, PVOID pvExtSupportRateIEs) +{ + BYTE byServ = 0, bySignal = 0; // For CCK + WORD wLen = 0; + BYTE byTxRate = 0, byRsvTime = 0; // For OFDM + + //Set to Page1 + MACvSelectPage1(pDevice->PortOffset); + + //RSPINF_b_1 + BBvCaculateParameter(pDevice, + 14, + VNTWIFIbyGetACKTxRate(RATE_1M, pvSupportRateIEs, pvExtSupportRateIEs), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + ///RSPINF_b_2 + BBvCaculateParameter(pDevice, + 14, + VNTWIFIbyGetACKTxRate(RATE_2M, pvSupportRateIEs, pvExtSupportRateIEs), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_b_5 + BBvCaculateParameter(pDevice, + 14, + VNTWIFIbyGetACKTxRate(RATE_5M, pvSupportRateIEs, pvExtSupportRateIEs), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_b_11 + BBvCaculateParameter(pDevice, + 14, + VNTWIFIbyGetACKTxRate(RATE_11M, pvSupportRateIEs, pvExtSupportRateIEs), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_a_6 + s_vCaculateOFDMRParameter(RATE_6M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_9 + s_vCaculateOFDMRParameter(RATE_9M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_12 + s_vCaculateOFDMRParameter(RATE_12M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_18 + s_vCaculateOFDMRParameter(RATE_18M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_24 + s_vCaculateOFDMRParameter(RATE_24M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_36 + s_vCaculateOFDMRParameter( + VNTWIFIbyGetACKTxRate(RATE_36M, pvSupportRateIEs, pvExtSupportRateIEs), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_48 + s_vCaculateOFDMRParameter( + VNTWIFIbyGetACKTxRate(RATE_48M, pvSupportRateIEs, pvExtSupportRateIEs), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_54 + s_vCaculateOFDMRParameter( + VNTWIFIbyGetACKTxRate(RATE_54M, pvSupportRateIEs, pvExtSupportRateIEs), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_72 + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate,byRsvTime)); + //Set to Page0 + MACvSelectPage0(pDevice->PortOffset); +} + + + + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +BYTE CARDbyGetChannelMapping (PVOID pDeviceHandler, BYTE byChannelNumber, CARD_PHY_TYPE ePhyType) +{ + UINT ii; + + if ((ePhyType == PHY_TYPE_11B) || (ePhyType == PHY_TYPE_11G)) { + return (byChannelNumber); + } + + for(ii = (CB_MAX_CHANNEL_24G + 1); ii <= CB_MAX_CHANNEL; ) { + if (sChannelTbl[ii].byChannelNumber == byChannelNumber) { + return ((BYTE) ii); + } + ii++; + } + return (0); +} + + +BYTE CARDbyGetChannelNumber (PVOID pDeviceHandler, BYTE byChannelIndex) +{ +// PSDevice pDevice = (PSDevice) pDeviceHandler; + return(sChannelTbl[byChannelIndex].byChannelNumber); +} + +/* + * Description: Set NIC media channel + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * uConnectionChannel - Channel to be set + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL CARDbSetChannel (PVOID pDeviceHandler, UINT uConnectionChannel) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BOOL bResult = TRUE; + + + if (pDevice->byCurrentCh == uConnectionChannel) { + return bResult; + } + + if (sChannelTbl[uConnectionChannel].bValid == FALSE) { + return (FALSE); + } + + if ((uConnectionChannel > CB_MAX_CHANNEL_24G) && + (pDevice->eCurrentPHYType != PHY_TYPE_11A)) { + CARDbSetPhyParameter(pDevice, PHY_TYPE_11A, 0, 0, NULL, NULL); + } else if ((uConnectionChannel <= CB_MAX_CHANNEL_24G) && + (pDevice->eCurrentPHYType == PHY_TYPE_11A)) { + CARDbSetPhyParameter(pDevice, PHY_TYPE_11G, 0, 0, NULL, NULL); + } + // clear NAV + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); + + //{{ RobertYu: 20041202 + //// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput + + if ( pDevice->byRFType == RF_AIROHA7230 ) + { + RFbAL7230SelectChannelPostProcess(pDevice->PortOffset, pDevice->byCurrentCh, (BYTE)uConnectionChannel); + } + //}} RobertYu + + + pDevice->byCurrentCh = (BYTE)uConnectionChannel; + bResult &= RFbSelectChannel(pDevice->PortOffset, pDevice->byRFType, (BYTE)uConnectionChannel); + + // Init Synthesizer Table + if (pDevice->bEnablePSMode == TRUE) + RFvWriteWakeProgSyn(pDevice->PortOffset, pDevice->byRFType, uConnectionChannel); + + + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDbSetMediaChannel: %d\n", (BYTE)uConnectionChannel); + BBvSoftwareReset(pDevice->PortOffset); + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + // set HW default power register + MACvSelectPage1(pDevice->PortOffset); + RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK, pDevice->byCurPwr); + RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, pDevice->byCurPwr); + MACvSelectPage0(pDevice->PortOffset); + } + + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { +#ifdef PLICE_DEBUG + //printk("Func:CARDbSetChannel:call RFbSetPower:11B\n"); +#endif + RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); + } else { +#ifdef PLICE_DEBUG + //printk("Func:CARDbSetChannel:call RFbSetPower\n"); +#endif + RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); + } + + return(bResult); +} + + + +/* + * Description: Card Send packet function + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * pPacket - Packet buffer pointer + * ePktType - Packet type + * uLength - Packet length + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +/* +BOOL CARDbSendPacket (PVOID pDeviceHandler, PVOID pPacket, CARD_PKT_TYPE ePktType, UINT uLength) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + if (ePktType == PKT_TYPE_802_11_MNG) { + return TXbTD0Send(pDevice, pPacket, uLength); + } else if (ePktType == PKT_TYPE_802_11_BCN) { + return TXbBeaconSend(pDevice, pPacket, uLength); + } if (ePktType == PKT_TYPE_802_11_DATA) { + return TXbTD1Send(pDevice, pPacket, uLength); + } + + return (TRUE); +} +*/ + + +/* + * Description: Get Card short preamble option value + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: TRUE if short preamble; otherwise FALSE + * + */ +BOOL CARDbIsShortPreamble (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + if (pDevice->byPreambleType == 0) { + return(FALSE); + } + return(TRUE); +} + +/* + * Description: Get Card short slot time option value + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: TRUE if short slot time; otherwise FALSE + * + */ +BOOL CARDbIsShorSlotTime (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + return(pDevice->bShortSlotTime); +} + + +/* + * Description: Update IFS + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +BOOL CARDbSetPhyParameter (PVOID pDeviceHandler, CARD_PHY_TYPE ePHYType, WORD wCapInfo, BYTE byERPField, PVOID pvSupportRateIEs, PVOID pvExtSupportRateIEs) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BYTE byCWMaxMin = 0; + BYTE bySlot = 0; + BYTE bySIFS = 0; + BYTE byDIFS = 0; + BYTE byData; +// PWLAN_IE_SUPP_RATES pRates = NULL; + PWLAN_IE_SUPP_RATES pSupportRates = (PWLAN_IE_SUPP_RATES) pvSupportRateIEs; + PWLAN_IE_SUPP_RATES pExtSupportRates = (PWLAN_IE_SUPP_RATES) pvExtSupportRateIEs; + + + //Set SIFS, DIFS, EIFS, SlotTime, CwMin + if (ePHYType == PHY_TYPE_11A) { + if (pSupportRates == NULL) { + pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesA; + } + if (pDevice->byRFType == RF_AIROHA7230) { + // AL7230 use single PAPE and connect to PAPE_2.4G + MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G); + pDevice->abyBBVGA[0] = 0x20; + pDevice->abyBBVGA[2] = 0x10; + pDevice->abyBBVGA[3] = 0x10; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x1C) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + } + } else if (pDevice->byRFType == RF_UW2452) { + MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A); + pDevice->abyBBVGA[0] = 0x18; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x14) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0x57); + } + } else { + MACvSetBBType(pDevice->PortOffset, BB_TYPE_11A); + } + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x03); + bySlot = C_SLOT_SHORT; + bySIFS = C_SIFS_A; + byDIFS = C_SIFS_A + 2*C_SLOT_SHORT; + byCWMaxMin = 0xA4; + } else if (ePHYType == PHY_TYPE_11B) { + if (pSupportRates == NULL) { + pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesB; + } + MACvSetBBType(pDevice->PortOffset, BB_TYPE_11B); + if (pDevice->byRFType == RF_AIROHA7230) { + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[2] = 0x00; + pDevice->abyBBVGA[3] = 0x00; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x20) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + } + } else if (pDevice->byRFType == RF_UW2452) { + pDevice->abyBBVGA[0] = 0x14; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x18) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0xD3); + } + } + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x02); + bySlot = C_SLOT_LONG; + bySIFS = C_SIFS_BG; + byDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + byCWMaxMin = 0xA5; + } else {// PK_TYPE_11GA & PK_TYPE_11GB + if (pSupportRates == NULL) { + pSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultSuppRatesG; + pExtSupportRates = (PWLAN_IE_SUPP_RATES) abyDefaultExtSuppRatesG; + } + MACvSetBBType(pDevice->PortOffset, BB_TYPE_11G); + if (pDevice->byRFType == RF_AIROHA7230) { + pDevice->abyBBVGA[0] = 0x1C; + pDevice->abyBBVGA[2] = 0x00; + pDevice->abyBBVGA[3] = 0x00; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x20) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + } + } else if (pDevice->byRFType == RF_UW2452) { + pDevice->abyBBVGA[0] = 0x14; + BBbReadEmbeded(pDevice->PortOffset, 0xE7, &byData); + if (byData == 0x18) { + BBbWriteEmbeded(pDevice->PortOffset, 0xE7, pDevice->abyBBVGA[0]); + BBbWriteEmbeded(pDevice->PortOffset, 0xE1, 0xD3); + } + } + BBbWriteEmbeded(pDevice->PortOffset, 0x88, 0x08); + bySIFS = C_SIFS_BG; + if(VNTWIFIbIsShortSlotTime(wCapInfo)) { + bySlot = C_SLOT_SHORT; + byDIFS = C_SIFS_BG + 2*C_SLOT_SHORT; + } else { + bySlot = C_SLOT_LONG; + byDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + } + if (VNTWIFIbyGetMaxSupportRate(pSupportRates, pExtSupportRates) > RATE_11M) { + byCWMaxMin = 0xA4; + } else { + byCWMaxMin = 0xA5; + } + if (pDevice->bProtectMode != VNTWIFIbIsProtectMode(byERPField)) { + pDevice->bProtectMode = VNTWIFIbIsProtectMode(byERPField); + if (pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice->PortOffset); + } else { + MACvDisableProtectMD(pDevice->PortOffset); + } + } + if (pDevice->bBarkerPreambleMd != VNTWIFIbIsBarkerMode(byERPField)) { + pDevice->bBarkerPreambleMd = VNTWIFIbIsBarkerMode(byERPField); + if (pDevice->bBarkerPreambleMd) { + MACvEnableBarkerPreambleMd(pDevice->PortOffset); + } else { + MACvDisableBarkerPreambleMd(pDevice->PortOffset); + } + } + } + + if (pDevice->byRFType == RF_RFMD2959) { + // bcs TX_PE will reserve 3 us + // hardware's processing time here is 2 us. + bySIFS -= 3; + byDIFS -= 3; + //{{ RobertYu: 20041202 + //// TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput + //// MAC will need 2 us to process, so the SIFS, DIFS can be shorter by 2 us. + } + + if (pDevice->bySIFS != bySIFS) { + pDevice->bySIFS = bySIFS; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, pDevice->bySIFS); + } + if (pDevice->byDIFS != byDIFS) { + pDevice->byDIFS = byDIFS; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, pDevice->byDIFS); + } + if (pDevice->byEIFS != C_EIFS) { + pDevice->byEIFS = C_EIFS; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, pDevice->byEIFS); + } + if (pDevice->bySlot != bySlot) { + pDevice->bySlot = bySlot; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, pDevice->bySlot); + if (pDevice->bySlot == C_SLOT_SHORT) { + pDevice->bShortSlotTime = TRUE; + } else { + pDevice->bShortSlotTime = FALSE; + } + BBvSetShortSlotTime(pDevice); + } + if (pDevice->byCWMaxMin != byCWMaxMin) { + pDevice->byCWMaxMin = byCWMaxMin; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, pDevice->byCWMaxMin); + } + if (VNTWIFIbIsShortPreamble(wCapInfo)) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } else { + pDevice->byPreambleType = 0; + } + s_vSetRSPINF(pDevice, ePHYType, pSupportRates, pExtSupportRates); + pDevice->eCurrentPHYType = ePHYType; + // set for NDIS OID_802_11SUPPORTED_RATES + return (TRUE); +} + +/* + * Description: Sync. TSF counter to BSS + * Get TSF offset and write to HW + * + * Parameters: + * In: + * pDevice - The adapter to be sync. + * byRxRate - data rate of receive beacon + * qwBSSTimestamp - Rx BCN's TSF + * qwLocalTSF - Local TSF + * Out: + * none + * + * Return Value: none + * + */ +BOOL CARDbUpdateTSF (PVOID pDeviceHandler, BYTE byRxRate, QWORD qwBSSTimestamp, QWORD qwLocalTSF) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + QWORD qwTSFOffset; + + HIDWORD(qwTSFOffset) = 0; + LODWORD(qwTSFOffset) = 0; + + if ((HIDWORD(qwBSSTimestamp) != HIDWORD(qwLocalTSF)) || + (LODWORD(qwBSSTimestamp) != LODWORD(qwLocalTSF))) { + qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF); + // adjust TSF + // HW's TSF add TSF Offset reg + VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST, LODWORD(qwTSFOffset)); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST + 4, HIDWORD(qwTSFOffset)); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN); + } + return(TRUE); +} + + +/* + * Description: Set NIC TSF counter for first Beacon time + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * pDevice - The adapter to be set. + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: TRUE if succeed; otherwise FALSE + * + */ +BOOL CARDbSetBeaconPeriod (PVOID pDeviceHandler, WORD wBeaconInterval) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT uBeaconInterval = 0; + UINT uLowNextTBTT = 0; + UINT uHighRemain = 0; + UINT uLowRemain = 0; + QWORD qwNextTBTT; + + HIDWORD(qwNextTBTT) = 0; + LODWORD(qwNextTBTT) = 0; + CARDbGetCurrentTSF(pDevice->PortOffset, &qwNextTBTT); //Get Local TSF counter + uBeaconInterval = wBeaconInterval * 1024; + // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval + uLowNextTBTT = (LODWORD(qwNextTBTT) >> 10) << 10; + uLowRemain = (uLowNextTBTT) % uBeaconInterval; + // high dword (mod) bcn + uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwNextTBTT)) + % uBeaconInterval; + uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval; + uLowRemain = uBeaconInterval - uLowRemain; + + // check if carry when add one beacon interval + if ((~uLowNextTBTT) < uLowRemain) { + HIDWORD(qwNextTBTT) ++ ; + } + LODWORD(qwNextTBTT) = uLowNextTBTT + uLowRemain; + + // set HW beacon interval + VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, wBeaconInterval); + pDevice->wBeaconInterval = wBeaconInterval; + // Set NextTBTT + VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT)); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT)); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + + return(TRUE); +} + + + +/* + * Description: Card Stop Hardware Tx + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * ePktType - Packet type to stop + * Out: + * none + * + * Return Value: TRUE if all data packet complete; otherwise FALSE. + * + */ +BOOL CARDbStopTxPacket (PVOID pDeviceHandler, CARD_PKT_TYPE ePktType) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + + if (ePktType == PKT_TYPE_802_11_ALL) { + pDevice->bStopBeacon = TRUE; + pDevice->bStopTx0Pkt = TRUE; + pDevice->bStopDataPkt = TRUE; + } else if (ePktType == PKT_TYPE_802_11_BCN) { + pDevice->bStopBeacon = TRUE; + } else if (ePktType == PKT_TYPE_802_11_MNG) { + pDevice->bStopTx0Pkt = TRUE; + } else if (ePktType == PKT_TYPE_802_11_DATA) { + pDevice->bStopDataPkt = TRUE; + } + + if (pDevice->bStopBeacon == TRUE) { + if (pDevice->bIsBeaconBufReadySet == TRUE) { + if (pDevice->cbBeaconBufReadySetCnt < WAIT_BEACON_TX_DOWN_TMO) { + pDevice->cbBeaconBufReadySetCnt ++; + return(FALSE); + } + } + pDevice->bIsBeaconBufReadySet = FALSE; + pDevice->cbBeaconBufReadySetCnt = 0; + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + } + // wait all TD0 complete + if (pDevice->bStopTx0Pkt == TRUE) { + if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){ + return(FALSE); + } + } + // wait all Data TD complete + if (pDevice->bStopDataPkt == TRUE) { + if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){ + return(FALSE); + } + } + + return(TRUE); +} + + +/* + * Description: Card Start Hardware Tx + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * ePktType - Packet type to start + * Out: + * none + * + * Return Value: TRUE if success; FALSE if failed. + * + */ +BOOL CARDbStartTxPacket (PVOID pDeviceHandler, CARD_PKT_TYPE ePktType) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + + if (ePktType == PKT_TYPE_802_11_ALL) { + pDevice->bStopBeacon = FALSE; + pDevice->bStopTx0Pkt = FALSE; + pDevice->bStopDataPkt = FALSE; + } else if (ePktType == PKT_TYPE_802_11_BCN) { + pDevice->bStopBeacon = FALSE; + } else if (ePktType == PKT_TYPE_802_11_MNG) { + pDevice->bStopTx0Pkt = FALSE; + } else if (ePktType == PKT_TYPE_802_11_DATA) { + pDevice->bStopDataPkt = FALSE; + } + + if ((pDevice->bStopBeacon == FALSE) && + (pDevice->bBeaconBufReady == TRUE) && + (pDevice->eOPMode == OP_MODE_ADHOC)) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + } + + return(TRUE); +} + + + +/* + * Description: Card Set BSSID value + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * pbyBSSID - pointer to BSSID field + * bAdhoc - flag to indicate IBSS + * Out: + * none + * + * Return Value: TRUE if success; FALSE if failed. + * + */ +BOOL CARDbSetBSSID(PVOID pDeviceHandler, PBYTE pbyBSSID, CARD_OP_MODE eOPMode) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + MACvWriteBSSIDAddress(pDevice->PortOffset, pbyBSSID); + MEMvCopy(pDevice->abyBSSID, pbyBSSID, WLAN_BSSID_LEN); + if (eOPMode == OP_MODE_ADHOC) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); + } else { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); + } + if (eOPMode == OP_MODE_AP) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); + } else { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); + } + if (eOPMode == OP_MODE_UNKNOWN) { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID); + pDevice->bBSSIDFilter = FALSE; + pDevice->byRxMode &= ~RCR_BSSID; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); + } else { + if (IS_NULL_ADDRESS(pDevice->abyBSSID) == FALSE) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID); + pDevice->bBSSIDFilter = TRUE; + pDevice->byRxMode |= RCR_BSSID; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: rx_mode = %x\n", pDevice->byRxMode ); + } + // Adopt BSS state in Adapter Device Object + pDevice->eOPMode = eOPMode; + return(TRUE); +} + + +/* + * Description: Card indicate status + * + * Parameters: + * In: + * pDeviceHandler - The adapter to be set + * eStatus - Status + * Out: + * none + * + * Return Value: TRUE if success; FALSE if failed. + * + */ + + + + +/* + * Description: Save Assoc info. contain in assoc. response frame + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wCapabilityInfo - Capability information + * wStatus - Status code + * wAID - Assoc. ID + * uLen - Length of IEs + * pbyIEs - pointer to IEs + * Out: + * none + * + * Return Value: TRUE if succeed; otherwise FALSE + * + */ +BOOL CARDbSetTxDataRate( + PVOID pDeviceHandler, + WORD wDataRate + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + pDevice->wCurrentRate = wDataRate; + return(TRUE); +} + +/*+ + * + * Routine Description: + * Consider to power down when no more packets to tx or rx. + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: TRUE if power down success; otherwise FALSE + * +-*/ +BOOL +CARDbPowerDown( + PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice)pDeviceHandler; + UINT uIdx; + + // check if already in Doze mode + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) + return TRUE; + + // Froce PSEN on + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); + + // check if all TD are empty, + + for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) { + if (pDevice->iTDUsed[uIdx] != 0) + return FALSE; + } + + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Go to Doze ZZZZZZZZZZZZZZZ\n"); + return TRUE; +} + +/* + * Description: Turn off Radio power + * + * Parameters: + * In: + * pDevice - The adapter to be turned off + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL CARDbRadioPowerOff (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BOOL bResult = TRUE; + + if (pDevice->bRadioOff == TRUE) + return TRUE; + + + switch (pDevice->byRFType) { + + case RF_RFMD2959: + MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV); + MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1); + break; + + case RF_AIROHA: + case RF_AL2230S: + case RF_AIROHA7230: //RobertYu:20050104 + MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE2); + MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + break; + + } + + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON); + + BBvSetDeepSleep(pDevice->PortOffset, pDevice->byLocalID); + + pDevice->bRadioOff = TRUE; + //2007-0409-03,<Add> by chester +printk("chester power off\n"); +MACvRegBitsOn(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); //LED issue + return bResult; +} + + +/* + * Description: Turn on Radio power + * + * Parameters: + * In: + * pDevice - The adapter to be turned on + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL CARDbRadioPowerOn (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BOOL bResult = TRUE; +printk("chester power on\n"); + if (pDevice->bRadioControlOff == TRUE){ +if (pDevice->bHWRadioOff == TRUE) printk("chester bHWRadioOff\n"); +if (pDevice->bRadioControlOff == TRUE) printk("chester bRadioControlOff\n"); + return FALSE;} + + if (pDevice->bRadioOff == FALSE) + { +printk("chester pbRadioOff\n"); +return TRUE;} + + BBvExitDeepSleep(pDevice->PortOffset, pDevice->byLocalID); + + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_HOSTCR, HOSTCR_RXON); + + switch (pDevice->byRFType) { + + case RF_RFMD2959: + MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_TXPEINV); + MACvWordRegBitsOff(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE1); + break; + + case RF_AIROHA: + case RF_AL2230S: + case RF_AIROHA7230: //RobertYu:20050104 + MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE2 | + SOFTPWRCTL_SWPE3)); + break; + + } + + pDevice->bRadioOff = FALSE; +// 2007-0409-03,<Add> by chester +printk("chester power on\n"); +MACvRegBitsOff(pDevice->PortOffset, MAC_REG_GPIOCTL0, LED_ACTSET); //LED issue + return bResult; +} + + + +BOOL CARDbRemoveKey (PVOID pDeviceHandler, PBYTE pbyBSSID) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + KeybRemoveAllKey(&(pDevice->sKey), pbyBSSID, pDevice->PortOffset); + return (TRUE); +} + + +/* + * + * Description: + * Add BSSID in PMKID Candidate list. + * + * Parameters: + * In: + * hDeviceContext - device structure point + * pbyBSSID - BSSID address for adding + * wRSNCap - BSS's RSN capability + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +CARDbAdd_PMKID_Candidate ( + IN PVOID pDeviceHandler, + IN PBYTE pbyBSSID, + IN BOOL bRSNCapExist, + IN WORD wRSNCap + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + PPMKID_CANDIDATE pCandidateList; + UINT ii = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + + if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFlush_PMKID_Candidate: 3\n"); + ZERO_MEMORY(&pDevice->gsPMKIDCandidate, sizeof(SPMKIDCandidateEvent)); + } + + for (ii = 0; ii < 6; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02X ", *(pbyBSSID + ii)); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + + // Update Old Candidate + for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) { + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii]; + if (MEMEqualMemory(pCandidateList->BSSID, pbyBSSID, U_ETHER_ADDR_LEN)) { + if ((bRSNCapExist == TRUE) && (wRSNCap & BIT0)) { + pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + return TRUE; + } + } + + // New Candidate + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates]; + if ((bRSNCapExist == TRUE) && (wRSNCap & BIT0)) { + pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + MEMvCopy(pCandidateList->BSSID, pbyBSSID, U_ETHER_ADDR_LEN); + pDevice->gsPMKIDCandidate.NumCandidates++; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + return TRUE; +} + +PVOID +CARDpGetCurrentAddress ( + IN PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + return (pDevice->abyCurrentNetAddr); +} + + + +VOID CARDvInitChannelTable (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BOOL bMultiBand = FALSE; + UINT ii; + + for(ii=1;ii<=CARD_MAX_CHANNEL_TBL;ii++) { + sChannelTbl[ii].bValid = FALSE; + } + + switch (pDevice->byRFType) { + case RF_RFMD2959 : + case RF_AIROHA : + case RF_AL2230S: + case RF_UW2451 : + case RF_VT3226 : + // printk("chester-false\n"); + bMultiBand = FALSE; + break; + case RF_AIROHA7230 : + case RF_UW2452 : + case RF_NOTHING : + default : + bMultiBand = TRUE; + break; + } + + if ((pDevice->dwDiagRefCount != 0) || + (pDevice->b11hEnable == TRUE)) { + if (bMultiBand == TRUE) { + for(ii=0;ii<CARD_MAX_CHANNEL_TBL;ii++) { + sChannelTbl[ii+1].bValid = TRUE; + pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + } + for(ii=0;ii<CHANNEL_MAX_24G;ii++) { + pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + } + } else { + for(ii=0;ii<CHANNEL_MAX_24G;ii++) { +//2008-8-4 <add> by chester + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = TRUE; + pDevice->abyRegPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + pDevice->abyLocalPwr[ii+1] = pDevice->abyCCKDefaultPwr[ii+1]; + } + } + } + } else if (pDevice->byZoneType <= CCODE_MAX) { + if (bMultiBand == TRUE) { + for(ii=0;ii<CARD_MAX_CHANNEL_TBL;ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = TRUE; + pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + } + } + } else { + for(ii=0;ii<CHANNEL_MAX_24G;ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + sChannelTbl[ii+1].bValid = TRUE; + pDevice->abyRegPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + pDevice->abyLocalPwr[ii+1] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + } + } + } + } + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO"Zone=[%d][%c][%c]!!\n",pDevice->byZoneType,ChannelRuleTab[pDevice->byZoneType].chCountryCode[0],ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]); + for(ii=0;ii<CARD_MAX_CHANNEL_TBL;ii++) { + if (pDevice->abyRegPwr[ii+1] == 0) { + pDevice->abyRegPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + } + if (pDevice->abyLocalPwr[ii+1] == 0) { + pDevice->abyLocalPwr[ii+1] = pDevice->abyOFDMDefaultPwr[ii+1]; + } + } +} + + + +/* + * + * Description: + * Start Spectrum Measure defined in 802.11h + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +CARDbStartMeasure ( + IN PVOID pDeviceHandler, + IN PVOID pvMeasureEIDs, + IN UINT uNumOfMeasureEIDs + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + PWLAN_IE_MEASURE_REQ pEID = (PWLAN_IE_MEASURE_REQ) pvMeasureEIDs; + QWORD qwCurrTSF; + QWORD qwStartTSF; + BOOL bExpired = TRUE; + WORD wDuration = 0; + + if ((pEID == NULL) || + (uNumOfMeasureEIDs == 0)) { + return (TRUE); + } + CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF); + if (pDevice->bMeasureInProgress == TRUE) { + pDevice->bMeasureInProgress = FALSE; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR); + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4); + // clear measure control + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + MACvSelectPage0(pDevice->PortOffset); + CARDbSetChannel(pDevice, pDevice->byOrgChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + } + pDevice->uNumOfMeasureEIDs = uNumOfMeasureEIDs; + + do { + pDevice->pCurrMeasureEID = pEID; + pEID++; + pDevice->uNumOfMeasureEIDs--; + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + HIDWORD(qwStartTSF) = HIDWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime))); + LODWORD(qwStartTSF) = LODWORD(*((PQWORD) (pDevice->pCurrMeasureEID->sReq.abyStartTime))); + wDuration = *((PWORD) (pDevice->pCurrMeasureEID->sReq.abyDuration)); + wDuration += 1; // 1 TU for channel switching + + if ((LODWORD(qwStartTSF) == 0) && (HIDWORD(qwStartTSF) == 0)) { + // start imediately by setting start TSF == current TSF + 2 TU + LODWORD(qwStartTSF) = LODWORD(qwCurrTSF) + 2048; + HIDWORD(qwStartTSF) = HIDWORD(qwCurrTSF); + if (LODWORD(qwCurrTSF) > LODWORD(qwStartTSF)) { + HIDWORD(qwStartTSF)++; + } + bExpired = FALSE; + break; + } else { + // start at setting start TSF - 1TU(for channel switching) + if (LODWORD(qwStartTSF) < 1024) { + HIDWORD(qwStartTSF)--; + } + LODWORD(qwStartTSF) -= 1024; + } + + if ((HIDWORD(qwCurrTSF) < HIDWORD(qwStartTSF)) || + ((HIDWORD(qwCurrTSF) == HIDWORD(qwStartTSF)) && + (LODWORD(qwCurrTSF) < LODWORD(qwStartTSF))) + ) { + bExpired = FALSE; + break; + } + VNTWIFIbMeasureReport( pDevice->pMgmt, + FALSE, + pDevice->pCurrMeasureEID, + MEASURE_MODE_LATE, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + } else { + // hardware do not support measure + VNTWIFIbMeasureReport( pDevice->pMgmt, + FALSE, + pDevice->pCurrMeasureEID, + MEASURE_MODE_INCAPABLE, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + } + } while (pDevice->uNumOfMeasureEIDs != 0); + + if (bExpired == FALSE) { + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART, LODWORD(qwStartTSF)); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MSRSTART + 4, HIDWORD(qwStartTSF)); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_MSRDURATION, wDuration); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + MACvSelectPage0(pDevice->PortOffset); + } else { + // all measure start time expired we should complete action + VNTWIFIbMeasureReport( pDevice->pMgmt, + TRUE, + NULL, + 0, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + } + return (TRUE); +} + + +/* + * + * Description: + * Do Channel Switch defined in 802.11h + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +CARDbChannelSwitch ( + IN PVOID pDeviceHandler, + IN BYTE byMode, + IN BYTE byNewChannel, + IN BYTE byCount + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BOOL bResult = TRUE; + + if (byCount == 0) { + bResult = CARDbSetChannel(pDevice, byNewChannel); + VNTWIFIbChannelSwitch(pDevice->pMgmt, byNewChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + return(bResult); + } + pDevice->byChannelSwitchCount = byCount; + pDevice->byNewChannel = byNewChannel; + pDevice->bChannelSwitch = TRUE; + if (byMode == 1) { + bResult=CARDbStopTxPacket(pDevice, PKT_TYPE_802_11_ALL); + } + return (bResult); +} + + +/* + * + * Description: + * Handle Quiet EID defined in 802.11h + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +CARDbSetQuiet ( + IN PVOID pDeviceHandler, + IN BOOL bResetQuiet, + IN BYTE byQuietCount, + IN BYTE byQuietPeriod, + IN WORD wQuietDuration, + IN WORD wQuietOffset + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii = 0; + + if (bResetQuiet == TRUE) { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); + for(ii=0;ii<MAX_QUIET_COUNT;ii++) { + pDevice->sQuiet[ii].bEnable = FALSE; + } + pDevice->uQuietEnqueue = 0; + pDevice->bEnableFirstQuiet = FALSE; + pDevice->bQuietEnable = FALSE; + pDevice->byQuietStartCount = byQuietCount; + } + if (pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable == FALSE) { + pDevice->sQuiet[pDevice->uQuietEnqueue].bEnable = TRUE; + pDevice->sQuiet[pDevice->uQuietEnqueue].byPeriod = byQuietPeriod; + pDevice->sQuiet[pDevice->uQuietEnqueue].wDuration = wQuietDuration; + pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime = (DWORD) byQuietCount; + pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime *= pDevice->wBeaconInterval; + pDevice->sQuiet[pDevice->uQuietEnqueue].dwStartTime += wQuietOffset; + pDevice->uQuietEnqueue++; + pDevice->uQuietEnqueue %= MAX_QUIET_COUNT; + if (pDevice->byQuietStartCount < byQuietCount) { + pDevice->byQuietStartCount = byQuietCount; + } + } else { + // we can not handle Quiet EID more + } + return (TRUE); +} + + +/* + * + * Description: + * Do Quiet, It will called by either ISR (after start) or VNTWIFI (before start) so do not need SPINLOCK + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +CARDbStartQuiet ( + IN PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii = 0; + DWORD dwStartTime = 0xFFFFFFFF; + UINT uCurrentQuietIndex = 0; + DWORD dwNextTime = 0; + DWORD dwGap = 0; + DWORD dwDuration = 0; + + for(ii=0;ii<MAX_QUIET_COUNT;ii++) { + if ((pDevice->sQuiet[ii].bEnable == TRUE) && + (dwStartTime > pDevice->sQuiet[ii].dwStartTime)) { + dwStartTime = pDevice->sQuiet[ii].dwStartTime; + uCurrentQuietIndex = ii; + } + } + if (dwStartTime == 0xFFFFFFFF) { + // no more quiet + pDevice->bQuietEnable = FALSE; + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); + } else { + if (pDevice->bQuietEnable == FALSE) { + // first quiet + pDevice->byQuietStartCount--; + dwNextTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime; + dwNextTime %= pDevice->wBeaconInterval; + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETINIT, (WORD) dwNextTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (WORD) pDevice->sQuiet[uCurrentQuietIndex].wDuration); + if (pDevice->byQuietStartCount == 0) { + pDevice->bEnableFirstQuiet = FALSE; + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); + } else { + pDevice->bEnableFirstQuiet = TRUE; + } + MACvSelectPage0(pDevice->PortOffset); + } else { + if (pDevice->dwCurrentQuietEndTime > pDevice->sQuiet[uCurrentQuietIndex].dwStartTime) { + // overlap with previous Quiet + dwGap = pDevice->dwCurrentQuietEndTime - pDevice->sQuiet[uCurrentQuietIndex].dwStartTime; + if (dwGap >= pDevice->sQuiet[uCurrentQuietIndex].wDuration) { + // return FALSE to indicate next quiet expired, should call this function again + return (FALSE); + } + dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration - dwGap; + dwGap = 0; + } else { + dwGap = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime - pDevice->dwCurrentQuietEndTime; + dwDuration = pDevice->sQuiet[uCurrentQuietIndex].wDuration; + } + // set GAP and Next duration + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETGAP, (WORD) dwGap); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_QUIETDUR, (WORD) dwDuration); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_QUIETRPT); + MACvSelectPage0(pDevice->PortOffset); + } + pDevice->bQuietEnable = TRUE; + pDevice->dwCurrentQuietEndTime = pDevice->sQuiet[uCurrentQuietIndex].dwStartTime; + pDevice->dwCurrentQuietEndTime += pDevice->sQuiet[uCurrentQuietIndex].wDuration; + if (pDevice->sQuiet[uCurrentQuietIndex].byPeriod == 0) { + // not period disable current quiet element + pDevice->sQuiet[uCurrentQuietIndex].bEnable = FALSE; + } else { + // set next period start time + dwNextTime = (DWORD) pDevice->sQuiet[uCurrentQuietIndex].byPeriod; + dwNextTime *= pDevice->wBeaconInterval; + pDevice->sQuiet[uCurrentQuietIndex].dwStartTime = dwNextTime; + } + if (pDevice->dwCurrentQuietEndTime > 0x80010000) { + // decreament all time to avoid wrap around + for(ii=0;ii<MAX_QUIET_COUNT;ii++) { + if (pDevice->sQuiet[ii].bEnable == TRUE) { + pDevice->sQuiet[ii].dwStartTime -= 0x80000000; + } + } + pDevice->dwCurrentQuietEndTime -= 0x80000000; + } + } + return (TRUE); +} + + +/* + * + * Description: + * Set Channel Info of Country + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +CARDvSetCountryInfo ( + IN PVOID pDeviceHandler, + IN CARD_PHY_TYPE ePHYType, + IN PVOID pIE + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii = 0; + UINT uu = 0; + UINT step = 0; + UINT uNumOfCountryInfo = 0; + BYTE byCh = 0; + PWLAN_IE_COUNTRY pIE_Country = (PWLAN_IE_COUNTRY) pIE; + + + uNumOfCountryInfo = (pIE_Country->len - 3); + uNumOfCountryInfo /= 3; + + if (ePHYType == PHY_TYPE_11A) { + pDevice->bCountryInfo5G = TRUE; + for(ii=CB_MAX_CHANNEL_24G+1;ii<=CARD_MAX_CHANNEL_TBL;ii++) { + sChannelTbl[ii].bValid = FALSE; + } + step = 4; + } else { + pDevice->bCountryInfo24G = TRUE; + for(ii=1;ii<=CB_MAX_CHANNEL_24G;ii++) { + sChannelTbl[ii].bValid = FALSE; + } + step = 1; + } + pDevice->abyCountryCode[0] = pIE_Country->abyCountryString[0]; + pDevice->abyCountryCode[1] = pIE_Country->abyCountryString[1]; + pDevice->abyCountryCode[2] = pIE_Country->abyCountryString[2]; + + for(ii=0;ii<uNumOfCountryInfo;ii++) { + for(uu=0;uu<pIE_Country->abyCountryInfo[ii*3+1];uu++) { + byCh = CARDbyGetChannelMapping(pDevice, (BYTE)(pIE_Country->abyCountryInfo[ii*3]+step*uu), ePHYType); + sChannelTbl[byCh].bValid = TRUE; + pDevice->abyRegPwr[byCh] = pIE_Country->abyCountryInfo[ii*3+2]; + } + } +} + +/* + * + * Description: + * Set Local Power Constraint + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +CARDvSetPowerConstraint ( + IN PVOID pDeviceHandler, + IN BYTE byChannel, + IN I8 byPower + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + if (byChannel > CB_MAX_CHANNEL_24G) { + if (pDevice->bCountryInfo5G == TRUE) { + pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower; + } + } else { + if (pDevice->bCountryInfo24G == TRUE) { + pDevice->abyLocalPwr[byChannel] = pDevice->abyRegPwr[byChannel] - byPower; + } + } +} + + +/* + * + * Description: + * Set Local Power Constraint + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +CARDvGetPowerCapability ( + IN PVOID pDeviceHandler, + OUT PBYTE pbyMinPower, + OUT PBYTE pbyMaxPower + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BYTE byDec = 0; + + *pbyMaxPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh]; + byDec = pDevice->abyOFDMPwrTbl[pDevice->byCurrentCh]; + if (pDevice->byRFType == RF_UW2452) { + byDec *= 3; + byDec >>= 1; + } else { + byDec <<= 1; + } + *pbyMinPower = pDevice->abyOFDMDefaultPwr[pDevice->byCurrentCh] - byDec; +} + + +/* + * + * Description: + * Set Support Channels IE defined in 802.11h + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +BYTE +CARDbySetSupportChannels ( + IN PVOID pDeviceHandler, + IN OUT PBYTE pbyIEs + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii; + BYTE byCount; + PWLAN_IE_SUPP_CH pIE = (PWLAN_IE_SUPP_CH) pbyIEs; + PBYTE pbyChTupple; + BYTE byLen = 0; + + + pIE->byElementID = WLAN_EID_SUPP_CH; + pIE->len = 0; + pbyChTupple = pIE->abyChannelTuple; + byLen = 2; + // lower band + byCount = 0; + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[28] == TRUE) { + for (ii=28;ii<36;ii+=2) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == TRUE) { + byCount++; + } + } + *pbyChTupple++ = 34; + *pbyChTupple++ = byCount; + byLen += 2; + } else if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[29] == TRUE) { + for (ii=29;ii<36;ii+=2) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == TRUE) { + byCount++; + } + } + *pbyChTupple++ = 36; + *pbyChTupple++ = byCount; + byLen += 2; + } + // middle band + byCount = 0; + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[36] == TRUE) { + for (ii=36;ii<40;ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == TRUE) { + byCount++; + } + } + *pbyChTupple++ = 52; + *pbyChTupple++ = byCount; + byLen += 2; + } + // higher band + byCount = 0; + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[40] == TRUE) { + for (ii=40;ii<51;ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == TRUE) { + byCount++; + } + } + *pbyChTupple++ = 100; + *pbyChTupple++ = byCount; + byLen += 2; + } else if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[51] == TRUE) { + for (ii=51;ii<56;ii++) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] == TRUE) { + byCount++; + } + } + *pbyChTupple++ = 149; + *pbyChTupple++ = byCount; + byLen += 2; + } + pIE->len += (byLen - 2); + return (byLen); +} + + +/* + * + * Description: + * Get Current Tx Power + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +I8 +CARDbyGetTransmitPower ( + IN PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + return (pDevice->byCurPwrdBm); +} + + +BOOL +CARDbChannelGetList ( + IN UINT uCountryCodeIdx, + OUT PBYTE pbyChannelTable + ) +{ + if (uCountryCodeIdx >= CCODE_MAX) { + return (FALSE); + } + MEMvCopy(pbyChannelTable, ChannelRuleTab[uCountryCodeIdx].bChannelIdxList, CB_MAX_CHANNEL); + return (TRUE); +} + + +VOID +CARDvSetCountryIE( + IN PVOID pDeviceHandler, + IN PVOID pIE + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii; + PWLAN_IE_COUNTRY pIECountry = (PWLAN_IE_COUNTRY) pIE; + + pIECountry->byElementID = WLAN_EID_COUNTRY; + pIECountry->len = 0; + pIECountry->abyCountryString[0] = ChannelRuleTab[pDevice->byZoneType].chCountryCode[0]; + pIECountry->abyCountryString[1] = ChannelRuleTab[pDevice->byZoneType].chCountryCode[1]; + pIECountry->abyCountryString[2] = ' '; + for (ii = CB_MAX_CHANNEL_24G; ii < CB_MAX_CHANNEL; ii++ ) { + if (ChannelRuleTab[pDevice->byZoneType].bChannelIdxList[ii] != 0) { + pIECountry->abyCountryInfo[pIECountry->len++] = sChannelTbl[ii+1].byChannelNumber; + pIECountry->abyCountryInfo[pIECountry->len++] = 1; + pIECountry->abyCountryInfo[pIECountry->len++] = ChannelRuleTab[pDevice->byZoneType].byPower[ii]; + } + } + pIECountry->len += 3; +} + + +BOOL +CARDbGetChannelMapInfo( + IN PVOID pDeviceHandler, + IN UINT uChannelIndex, + OUT PBYTE pbyChannelNumber, + OUT PBYTE pbyMap + ) +{ +// PSDevice pDevice = (PSDevice) pDeviceHandler; + + if (uChannelIndex > CB_MAX_CHANNEL) { + return FALSE; + } + *pbyChannelNumber = sChannelTbl[uChannelIndex].byChannelNumber; + *pbyMap = sChannelTbl[uChannelIndex].byMAP; + return sChannelTbl[uChannelIndex].bValid; +} + + +VOID +CARDvSetChannelMapInfo( + IN PVOID pDeviceHandler, + IN UINT uChannelIndex, + IN BYTE byMap + ) +{ +// PSDevice pDevice = (PSDevice) pDeviceHandler; + + if (uChannelIndex > CB_MAX_CHANNEL) { + return; + } + sChannelTbl[uChannelIndex].byMAP |= byMap; +} + + +VOID +CARDvClearChannelMapInfo( + IN PVOID pDeviceHandler + ) +{ +// PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii = 0; + + for (ii = 1; ii <= CB_MAX_CHANNEL; ii++) { + sChannelTbl[ii].byMAP = 0; + } +} + + +BYTE +CARDbyAutoChannelSelect( + IN PVOID pDeviceHandler, + CARD_PHY_TYPE ePHYType + ) +{ +// PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ii = 0; + BYTE byOptionChannel = 0; + INT aiWeight[CB_MAX_CHANNEL_24G+1] = {-1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + if (ePHYType == PHY_TYPE_11A) { + for(ii=CB_MAX_CHANNEL_24G+1;ii<=CB_MAX_CHANNEL;ii++) { + if (sChannelTbl[ii].bValid == TRUE) { + if (byOptionChannel == 0) { + byOptionChannel = (BYTE) ii; + } + if (sChannelTbl[ii].byMAP == 0) { + return ((BYTE) ii); + } else if (BITbIsBitOff(sChannelTbl[ii].byMAP, 0x08)) { + byOptionChannel = (BYTE) ii; + } + } + } + } else { + byOptionChannel = 0; + for(ii=1;ii<=CB_MAX_CHANNEL_24G;ii++) { + if (sChannelTbl[ii].bValid == TRUE) { + if (sChannelTbl[ii].byMAP == 0) { + aiWeight[ii] += 100; + } else if (BITbIsBitOn(sChannelTbl[ii].byMAP, 0x01)) { + if (ii > 3) { + aiWeight[ii-3] -= 10; + } + if (ii > 2) { + aiWeight[ii-2] -= 20; + } + if (ii > 1) { + aiWeight[ii-1] -= 40; + } + aiWeight[ii] -= 80; + if (ii < CB_MAX_CHANNEL_24G) { + aiWeight[ii+1] -= 40; + } + if (ii < (CB_MAX_CHANNEL_24G - 1)) { + aiWeight[ii+2] -= 20; + } + if (ii < (CB_MAX_CHANNEL_24G - 2)) { + aiWeight[ii+3] -= 10; + } + } + } + } + for(ii=1;ii<=CB_MAX_CHANNEL_24G;ii++) { + if ((sChannelTbl[ii].bValid == TRUE) && + (aiWeight[ii] > aiWeight[byOptionChannel])) { + byOptionChannel = (BYTE) ii; + } + } + } + return (byOptionChannel); +} + + + +//xxx +VOID +CARDvSafeResetTx ( + IN PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT uu; + PSTxDesc pCurrTD; + + // initialize TD index + pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]); + pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]); + + for (uu = 0; uu < TYPE_MAXTD; uu ++) + pDevice->iTDUsed[uu] = 0; + + for (uu = 0; uu < pDevice->sOpts.nTxDescs[0]; uu++) { + pCurrTD = &(pDevice->apTD0Rings[uu]); + pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST; + // init all Tx Packet pointer to NULL + } + for (uu = 0; uu < pDevice->sOpts.nTxDescs[1]; uu++) { + pCurrTD = &(pDevice->apTD1Rings[uu]); + pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST; + // init all Tx Packet pointer to NULL + } + + // set MAC TD pointer + MACvSetCurrTXDescAddr(TYPE_TXDMA0, pDevice->PortOffset, + (pDevice->td0_pool_dma)); + + MACvSetCurrTXDescAddr(TYPE_AC0DMA, pDevice->PortOffset, + (pDevice->td1_pool_dma)); + + // set MAC Beacon TX pointer + MACvSetCurrBCNTxDescAddr(pDevice->PortOffset, + (pDevice->tx_beacon_dma)); + +} + + + +/*+ + * + * Description: + * Reset Rx + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +CARDvSafeResetRx ( + IN PVOID pDeviceHandler + ) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT uu; + PSRxDesc pDesc; + + + + // initialize RD index + pDevice->pCurrRD[0]=&(pDevice->aRD0Ring[0]); + pDevice->pCurrRD[1]=&(pDevice->aRD1Ring[0]); + + // init state, all RD is chip's + for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) { + pDesc =&(pDevice->aRD0Ring[uu]); + pDesc->m_rd0RD0.wResCount = (WORD)(pDevice->rx_buf_sz); + pDesc->m_rd0RD0.f1Owner=OWNED_BY_NIC; + pDesc->m_rd1RD1.wReqCount = (WORD)(pDevice->rx_buf_sz); + } + + // init state, all RD is chip's + for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) { + pDesc =&(pDevice->aRD1Ring[uu]); + pDesc->m_rd0RD0.wResCount = (WORD)(pDevice->rx_buf_sz); + pDesc->m_rd0RD0.f1Owner=OWNED_BY_NIC; + pDesc->m_rd1RD1.wReqCount = (WORD)(pDevice->rx_buf_sz); + } + + pDevice->cbDFCB = CB_MAX_RX_FRAG; + pDevice->cbFreeDFCB = pDevice->cbDFCB; + + // set perPkt mode + MACvRx0PerPktMode(pDevice->PortOffset); + MACvRx1PerPktMode(pDevice->PortOffset); + // set MAC RD pointer + MACvSetCurrRx0DescAddr(pDevice->PortOffset, + pDevice->rd0_pool_dma); + + MACvSetCurrRx1DescAddr(pDevice->PortOffset, + pDevice->rd1_pool_dma); +} + + + + +/* + * Description: Get response Control frame rate in CCK mode + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + * + */ +WORD CARDwGetCCKControlRate(PVOID pDeviceHandler, WORD wRateIdx) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ui = (UINT)wRateIdx; + + while (ui > RATE_1M) { + if (pDevice->wBasicRate & ((WORD)1 << ui)) { + return (WORD)ui; + } + ui --; + } + return (WORD)RATE_1M; +} + +/* + * Description: Get response Control frame rate in OFDM mode + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + * + */ +WORD CARDwGetOFDMControlRate (PVOID pDeviceHandler, WORD wRateIdx) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + UINT ui = (UINT)wRateIdx; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BASIC RATE: %X\n", pDevice->wBasicRate); + + if (!CARDbIsOFDMinBasicRate((PVOID)pDevice)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx); + if (wRateIdx > RATE_24M) + wRateIdx = RATE_24M; + return wRateIdx; + } + while (ui > RATE_11M) { + if (pDevice->wBasicRate & ((WORD)1 << ui)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate : %d\n", ui); + return (WORD)ui; + } + ui --; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CARDwGetOFDMControlRate: 6M\n"); + return (WORD)RATE_24M; +} + + +/* + * Description: Set RSPINF + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +void CARDvSetRSPINF (PVOID pDeviceHandler, CARD_PHY_TYPE ePHYType) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BYTE byServ = 0x00, bySignal = 0x00; //For CCK + WORD wLen = 0x0000; + BYTE byTxRate, byRsvTime; //For OFDM + + //Set to Page1 + MACvSelectPage1(pDevice->PortOffset); + + //RSPINF_b_1 + BBvCaculateParameter(pDevice, + 14, + CARDwGetCCKControlRate((PVOID)pDevice, RATE_1M), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_1, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + ///RSPINF_b_2 + BBvCaculateParameter(pDevice, + 14, + CARDwGetCCKControlRate((PVOID)pDevice, RATE_2M), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_2, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_b_5 + BBvCaculateParameter(pDevice, + 14, + CARDwGetCCKControlRate((PVOID)pDevice, RATE_5M), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_5, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_b_11 + BBvCaculateParameter(pDevice, + 14, + CARDwGetCCKControlRate((PVOID)pDevice, RATE_11M), + PK_TYPE_11B, + &wLen, + &byServ, + &bySignal + ); + + VNSvOutPortD(pDevice->PortOffset + MAC_REG_RSPINF_B_11, MAKEDWORD(wLen,MAKEWORD(bySignal,byServ))); + //RSPINF_a_6 + s_vCaculateOFDMRParameter(RATE_6M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_6, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_9 + s_vCaculateOFDMRParameter(RATE_9M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_9, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_12 + s_vCaculateOFDMRParameter(RATE_12M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_12, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_18 + s_vCaculateOFDMRParameter(RATE_18M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_18, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_24 + s_vCaculateOFDMRParameter(RATE_24M, + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_24, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_36 + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((PVOID)pDevice, RATE_36M), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_36, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_48 + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((PVOID)pDevice, RATE_48M), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_48, MAKEWORD(byTxRate,byRsvTime)); + //RSPINF_a_54 + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((PVOID)pDevice, RATE_54M), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_54, MAKEWORD(byTxRate,byRsvTime)); + + //RSPINF_a_72 + s_vCaculateOFDMRParameter(CARDwGetOFDMControlRate((PVOID)pDevice, RATE_54M), + ePHYType, + &byTxRate, + &byRsvTime); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate,byRsvTime)); + //Set to Page0 + MACvSelectPage0(pDevice->PortOffset); +} + +/* + * Description: Update IFS + * + * Parameters: + * In: + * pDevice - The adapter to be set + * Out: + * none + * + * Return Value: None. + * + */ +void vUpdateIFS (PVOID pDeviceHandler) +{ + //Set SIFS, DIFS, EIFS, SlotTime, CwMin + PSDevice pDevice = (PSDevice) pDeviceHandler; + + BYTE byMaxMin = 0; + if (pDevice->byPacketType==PK_TYPE_11A) {//0000 0000 0000 0000,11a + pDevice->uSlot = C_SLOT_SHORT; + pDevice->uSIFS = C_SIFS_A; + pDevice->uDIFS = C_SIFS_A + 2*C_SLOT_SHORT; + pDevice->uCwMin = C_CWMIN_A; + byMaxMin = 4; + } + else if (pDevice->byPacketType==PK_TYPE_11B) {//0000 0001 0000 0000,11b + pDevice->uSlot = C_SLOT_LONG; + pDevice->uSIFS = C_SIFS_BG; + pDevice->uDIFS = C_SIFS_BG + 2*C_SLOT_LONG; + pDevice->uCwMin = C_CWMIN_B; + byMaxMin = 5; + } + else { // PK_TYPE_11GA & PK_TYPE_11GB + pDevice->uSIFS = C_SIFS_BG; + if (pDevice->bShortSlotTime) { + pDevice->uSlot = C_SLOT_SHORT; + } else { + pDevice->uSlot = C_SLOT_LONG; + } + pDevice->uDIFS = C_SIFS_BG + 2*pDevice->uSlot; + if (pDevice->wBasicRate & 0x0150) { //0000 0001 0101 0000,24M,12M,6M + pDevice->uCwMin = C_CWMIN_A; + byMaxMin = 4; + } + else { + pDevice->uCwMin = C_CWMIN_B; + byMaxMin = 5; + } + } + + pDevice->uCwMax = C_CWMAX; + pDevice->uEIFS = C_EIFS; + if (pDevice->byRFType == RF_RFMD2959) { + // bcs TX_PE will reserve 3 us + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (BYTE)(pDevice->uSIFS - 3)); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (BYTE)(pDevice->uDIFS - 3)); + } else { + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SIFS, (BYTE)pDevice->uSIFS); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_DIFS, (BYTE)pDevice->uDIFS); + } + VNSvOutPortB(pDevice->PortOffset + MAC_REG_EIFS, (BYTE)pDevice->uEIFS); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SLOT, (BYTE)pDevice->uSlot); + byMaxMin |= 0xA0;//1010 1111,C_CWMAX = 1023 + VNSvOutPortB(pDevice->PortOffset + MAC_REG_CWMAXMIN0, (BYTE)byMaxMin); +} + +void CARDvUpdateBasicTopRate (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + BYTE byTopOFDM = RATE_24M, byTopCCK = RATE_1M; + BYTE ii; + + //Determines the highest basic rate. + for (ii = RATE_54M; ii >= RATE_6M; ii --) { + if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) + byTopOFDM = ii; + break; + } + pDevice->byTopOFDMBasicRate = byTopOFDM; + + for (ii = RATE_11M;; ii --) { + if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) + byTopCCK = ii; + break; + if (ii == RATE_1M) + break; + } + pDevice->byTopCCKBasicRate = byTopCCK; +} + + +/* + * Description: Set NIC Tx Basic Rate + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wBasicRate - Basic Rate to be set + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL CARDbAddBasicRate (PVOID pDeviceHandler, WORD wRateIdx) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + WORD wRate = (WORD)(1<<wRateIdx); + + pDevice->wBasicRate |= wRate; + + //Determines the highest basic rate. + CARDvUpdateBasicTopRate((PVOID)pDevice); + + return(TRUE); +} + +BOOL CARDbIsOFDMinBasicRate (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + int ii; + + for (ii = RATE_54M; ii >= RATE_6M; ii --) { + if ((pDevice->wBasicRate) & ((WORD)(1<<ii))) + return TRUE; + } + return FALSE; +} + +BYTE CARDbyGetPktType (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + if (pDevice->byBBType == BB_TYPE_11A || pDevice->byBBType == BB_TYPE_11B) { + return (BYTE)pDevice->byBBType; + } + else if (CARDbIsOFDMinBasicRate((PVOID)pDevice)) { + return PK_TYPE_11GA; + } + else { + return PK_TYPE_11GB; + } +} + +/* + * Description: Set NIC Loopback mode + * + * Parameters: + * In: + * pDevice - The adapter to be set + * wLoopbackMode - Loopback mode to be set + * Out: + * none + * + * Return Value: none + * + */ +void CARDvSetLoopbackMode (DWORD_PTR dwIoBase, WORD wLoopbackMode) +{ + switch(wLoopbackMode) { + case CARD_LB_NONE: + case CARD_LB_MAC: + case CARD_LB_PHY: + break; + default: + ASSERT(FALSE); + break; + } + // set MAC loopback + MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode)); + // set Baseband loopback +} + + +/* + * Description: Software Reset NIC + * + * Parameters: + * In: + * pDevice - The adapter to be reset + * Out: + * none + * + * Return Value: none + * + */ +BOOL CARDbSoftwareReset (PVOID pDeviceHandler) +{ + PSDevice pDevice = (PSDevice) pDeviceHandler; + + // reset MAC + if (!MACbSafeSoftwareReset(pDevice->PortOffset)) + return FALSE; + + return TRUE; +} + + +/* + * Description: Caculate TSF offset of two TSF input + * Get TSF Offset from RxBCN's TSF and local TSF + * + * Parameters: + * In: + * pDevice - The adapter to be sync. + * qwTSF1 - Rx BCN's TSF + * qwTSF2 - Local TSF + * Out: + * none + * + * Return Value: TSF Offset value + * + */ +QWORD CARDqGetTSFOffset (BYTE byRxRate, QWORD qwTSF1, QWORD qwTSF2) +{ + QWORD qwTSFOffset; + WORD wRxBcnTSFOffst= 0;; + + HIDWORD(qwTSFOffset) = 0; + LODWORD(qwTSFOffset) = 0; + wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate%MAX_RATE]; + (qwTSF2).u.dwLowDword += (DWORD)(wRxBcnTSFOffst); + if ((qwTSF2).u.dwLowDword < (DWORD)(wRxBcnTSFOffst)) { + (qwTSF2).u.dwHighDword++; + } + LODWORD(qwTSFOffset) = LODWORD(qwTSF1) - LODWORD(qwTSF2); + if (LODWORD(qwTSF1) < LODWORD(qwTSF2)) { + // if borrow needed + HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2) - 1 ; + } + else { + HIDWORD(qwTSFOffset) = HIDWORD(qwTSF1) - HIDWORD(qwTSF2); + }; + return (qwTSFOffset); +} + + +/* + * Description: Read NIC TSF counter + * Get local TSF counter + * + * Parameters: + * In: + * pDevice - The adapter to be read + * Out: + * qwCurrTSF - Current TSF counter + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL CARDbGetCurrentTSF (DWORD_PTR dwIoBase, PQWORD pqwCurrTSF) +{ + WORD ww; + BYTE byData; + + MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_TFTCTL, &byData); + if (BITbIsBitOff(byData, TFTCTL_TSFCNTRRD)) + break; + } + if (ww == W_MAX_TIMEOUT) + return(FALSE); + VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR, &LODWORD(*pqwCurrTSF)); + VNSvInPortD(dwIoBase + MAC_REG_TSFCNTR + 4, &HIDWORD(*pqwCurrTSF)); + + return(TRUE); +} + + +/* + * Description: Read NIC TSF counter + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * qwTSF - Current TSF counter + * wbeaconInterval - Beacon Interval + * Out: + * qwCurrTSF - Current TSF counter + * + * Return Value: TSF value of next Beacon + * + */ +QWORD CARDqGetNextTBTT (QWORD qwTSF, WORD wBeaconInterval) +{ + + UINT uLowNextTBTT; + UINT uHighRemain, uLowRemain; + UINT uBeaconInterval; + + uBeaconInterval = wBeaconInterval * 1024; + // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval + uLowNextTBTT = (LODWORD(qwTSF) >> 10) << 10; + // low dword (mod) bcn + uLowRemain = (uLowNextTBTT) % uBeaconInterval; +// uHighRemain = ((0x80000000 % uBeaconInterval)* 2 * HIDWORD(qwTSF)) +// % uBeaconInterval; + // high dword (mod) bcn + uHighRemain = (((0xffffffff % uBeaconInterval) + 1) * HIDWORD(qwTSF)) + % uBeaconInterval; + uLowRemain = (uHighRemain + uLowRemain) % uBeaconInterval; + uLowRemain = uBeaconInterval - uLowRemain; + + // check if carry when add one beacon interval + if ((~uLowNextTBTT) < uLowRemain) + HIDWORD(qwTSF) ++ ; + + LODWORD(qwTSF) = uLowNextTBTT + uLowRemain; + + return (qwTSF); +} + + +/* + * Description: Set NIC TSF counter for first Beacon time + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * dwIoBase - IO Base + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + * + */ +void CARDvSetFirstNextTBTT (DWORD_PTR dwIoBase, WORD wBeaconInterval) +{ + + QWORD qwNextTBTT; + + HIDWORD(qwNextTBTT) = 0; + LODWORD(qwNextTBTT) = 0; + CARDbGetCurrentTSF(dwIoBase, &qwNextTBTT); //Get Local TSF counter + qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); + // Set NextTBTT + VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwNextTBTT)); + VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwNextTBTT)); + MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:First Next TBTT[%8xh:%8xh] \n", HIDWORD(qwNextTBTT), LODWORD(qwNextTBTT)); + return; +} + + +/* + * Description: Sync NIC TSF counter for Beacon time + * Get NEXTTBTT and write to HW + * + * Parameters: + * In: + * pDevice - The adapter to be set + * qwTSF - Current TSF counter + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + * + */ +void CARDvUpdateNextTBTT (DWORD_PTR dwIoBase, QWORD qwTSF, WORD wBeaconInterval) +{ + + qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval); + // Set NextTBTT + VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT, LODWORD(qwTSF)); + VNSvOutPortD(dwIoBase + MAC_REG_NEXTTBTT + 4, HIDWORD(qwTSF)); + MACvRegBitsOn(dwIoBase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Card:Update Next TBTT[%8xh:%8xh] \n",(UINT)HIDWORD(qwTSF), (UINT)LODWORD(qwTSF)); + + return; +} + + + + + + + diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h new file mode 100644 index 00000000000..bb292e14b0b --- /dev/null +++ b/drivers/staging/vt6655/card.h @@ -0,0 +1,273 @@ +/* + * 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: card.h + * + * Purpose: Provide functions to setup NIC operation mode + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + + +#ifndef __CARD_H__ +#define __CARD_H__ + +//#if !defined(__DEVICE_H__) +//#include "device.h" +//#endif +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + + +/*--------------------- Export Definitions -------------------------*/ +// +// Loopback mode +// +// LOBYTE is MAC LB mode, HIBYTE is MII LB mode +#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0) +#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0) // PHY must ISO, avoid MAC loopback packet go out +#define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0) + + +#define DEFAULT_MSDU_LIFETIME 512 // ms +#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 // 64us + +#define DEFAULT_MGN_LIFETIME 8 // ms +#define DEFAULT_MGN_LIFETIME_RES_64us 125 // 64us + +#define CB_MAX_CHANNEL_24G 14 +#define CB_MAX_CHANNEL_5G 42 //[20050104] add channel9(5045MHz), 41==>42 +#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G+CB_MAX_CHANNEL_5G) + +typedef enum _CARD_PHY_TYPE { + PHY_TYPE_AUTO, + PHY_TYPE_11B, + PHY_TYPE_11G, + PHY_TYPE_11A +} CARD_PHY_TYPE, *PCARD_PHY_TYPE; + +typedef enum _CARD_PKT_TYPE { + PKT_TYPE_802_11_BCN, + PKT_TYPE_802_11_MNG, + PKT_TYPE_802_11_DATA, + PKT_TYPE_802_11_ALL +} CARD_PKT_TYPE, *PCARD_PKT_TYPE; + +typedef enum _CARD_STATUS_TYPE { + CARD_STATUS_MEDIA_CONNECT, + CARD_STATUS_MEDIA_DISCONNECT, + CARD_STATUS_PMKID +} CARD_STATUS_TYPE, *PCARD_STATUS_TYPE; + +typedef enum _CARD_OP_MODE { + OP_MODE_INFRASTRUCTURE, + OP_MODE_ADHOC, + OP_MODE_AP, + OP_MODE_UNKNOWN +} CARD_OP_MODE, *PCARD_OP_MODE; + + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL ChannelValid(UINT CountryCode, UINT ChannelIndex); +void CARDvSetRSPINF(PVOID pDeviceHandler, CARD_PHY_TYPE ePHYType); +void vUpdateIFS(PVOID pDeviceHandler); +void CARDvUpdateBasicTopRate(PVOID pDeviceHandler); +BOOL CARDbAddBasicRate(PVOID pDeviceHandler, WORD wRateIdx); +BOOL CARDbIsOFDMinBasicRate(PVOID pDeviceHandler); +void CARDvSetLoopbackMode(DWORD_PTR dwIoBase, WORD wLoopbackMode); +BOOL CARDbSoftwareReset(PVOID pDeviceHandler); +void CARDvSetFirstNextTBTT(DWORD_PTR dwIoBase, WORD wBeaconInterval); +void CARDvUpdateNextTBTT(DWORD_PTR dwIoBase, QWORD qwTSF, WORD wBeaconInterval); +BOOL CARDbGetCurrentTSF(DWORD_PTR dwIoBase, PQWORD pqwCurrTSF); +QWORD CARDqGetNextTBTT(QWORD qwTSF, WORD wBeaconInterval); +QWORD CARDqGetTSFOffset(BYTE byRxRate, QWORD qwTSF1, QWORD qwTSF2); +BOOL CARDbSetTxPower(PVOID pDeviceHandler, ULONG ulTxPower); +BYTE CARDbyGetPktType(PVOID pDeviceHandler); +VOID CARDvSafeResetTx(PVOID pDeviceHandler); +VOID CARDvSafeResetRx(PVOID pDeviceHandler); + +//xxx +BOOL CARDbRadioPowerOff(PVOID pDeviceHandler); +BOOL CARDbRadioPowerOn(PVOID pDeviceHandler); +BOOL CARDbSetChannel(PVOID pDeviceHandler, UINT uConnectionChannel); +//BOOL CARDbSendPacket(PVOID pDeviceHandler, PVOID pPacket, CARD_PKT_TYPE ePktType, UINT uLength); +BOOL CARDbIsShortPreamble(PVOID pDeviceHandler); +BOOL CARDbIsShorSlotTime(PVOID pDeviceHandler); +BOOL CARDbSetPhyParameter(PVOID pDeviceHandler, CARD_PHY_TYPE ePHYType, WORD wCapInfo, BYTE byERPField, PVOID pvSupportRateIEs, PVOID pvExtSupportRateIEs); +BOOL CARDbUpdateTSF(PVOID pDeviceHandler, BYTE byRxRate, QWORD qwBSSTimestamp, QWORD qwLocalTSF); +BOOL CARDbStopTxPacket(PVOID pDeviceHandler, CARD_PKT_TYPE ePktType); +BOOL CARDbStartTxPacket(PVOID pDeviceHandler, CARD_PKT_TYPE ePktType); +BOOL CARDbSetBeaconPeriod(PVOID pDeviceHandler, WORD wBeaconInterval); +BOOL CARDbSetBSSID(PVOID pDeviceHandler, PBYTE pbyBSSID, CARD_OP_MODE eOPMode); + +BOOL +CARDbPowerDown( + PVOID pDeviceHandler + ); + +BOOL CARDbSetTxDataRate( + PVOID pDeviceHandler, + WORD wDataRate + ); + + +BOOL CARDbRemoveKey (PVOID pDeviceHandler, PBYTE pbyBSSID); + +BOOL +CARDbAdd_PMKID_Candidate ( + IN PVOID pDeviceHandler, + IN PBYTE pbyBSSID, + IN BOOL bRSNCapExist, + IN WORD wRSNCap + ); + +PVOID +CARDpGetCurrentAddress ( + IN PVOID pDeviceHandler + ); + + +VOID CARDvInitChannelTable(PVOID pDeviceHandler); +BYTE CARDbyGetChannelMapping(PVOID pDeviceHandler, BYTE byChannelNumber, CARD_PHY_TYPE ePhyType); + +BOOL +CARDbStartMeasure ( + IN PVOID pDeviceHandler, + IN PVOID pvMeasureEIDs, + IN UINT uNumOfMeasureEIDs + ); + +BOOL +CARDbChannelSwitch ( + IN PVOID pDeviceHandler, + IN BYTE byMode, + IN BYTE byNewChannel, + IN BYTE byCount + ); + +BOOL +CARDbSetQuiet ( + IN PVOID pDeviceHandler, + IN BOOL bResetQuiet, + IN BYTE byQuietCount, + IN BYTE byQuietPeriod, + IN WORD wQuietDuration, + IN WORD wQuietOffset + ); + +BOOL +CARDbStartQuiet ( + IN PVOID pDeviceHandler + ); + +VOID +CARDvSetCountryInfo ( + IN PVOID pDeviceHandler, + IN CARD_PHY_TYPE ePHYType, + IN PVOID pIE + ); + +VOID +CARDvSetPowerConstraint ( + IN PVOID pDeviceHandler, + IN BYTE byChannel, + IN I8 byPower + ); + +VOID +CARDvGetPowerCapability ( + IN PVOID pDeviceHandler, + OUT PBYTE pbyMinPower, + OUT PBYTE pbyMaxPower + ); + +BYTE +CARDbySetSupportChannels ( + IN PVOID pDeviceHandler, + IN OUT PBYTE pbyIEs + ); + +I8 +CARDbyGetTransmitPower ( + IN PVOID pDeviceHandler + ); + +BOOL +CARDbChannelGetList ( + IN UINT uCountryCodeIdx, + OUT PBYTE pbyChannelTable + ); + +VOID +CARDvSetCountryIE( + IN PVOID pDeviceHandler, + IN PVOID pIE + ); + +BOOL +CARDbGetChannelMapInfo( + IN PVOID pDeviceHandler, + IN UINT uChannelIndex, + OUT PBYTE pbyChannelNumber, + OUT PBYTE pbyMap + ); + +VOID +CARDvSetChannelMapInfo( + IN PVOID pDeviceHandler, + IN UINT uChannelIndex, + IN BYTE byMap + ); + +VOID +CARDvClearChannelMapInfo( + IN PVOID pDeviceHandler + ); + +BYTE +CARDbyAutoChannelSelect( + IN PVOID pDeviceHandler, + CARD_PHY_TYPE ePHYType + ); + +BYTE CARDbyGetChannelNumber(PVOID pDeviceHandler, BYTE byChannelIndex); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __CARD_H__ + + + diff --git a/drivers/staging/vt6655/country.h b/drivers/staging/vt6655/country.h new file mode 100644 index 00000000000..65d1e52916c --- /dev/null +++ b/drivers/staging/vt6655/country.h @@ -0,0 +1,192 @@ +/* + * 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: country.h + * + * Purpose: Country Code information + * + * Author: Lucas Lin + * + * Date: Dec 23, 2004 + * + */ + +#ifndef __COUNTRY_H__ +#define __COUNTRY_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ +/************************************************************************ + * The definition here should be complied with the INF country order + * Please check with VNWL.inf/VNWL64.inf/VNWL*.inf + ************************************************************************/ +typedef enum _COUNTRY_CODE { + CCODE_FCC = 0, + CCODE_TELEC, + CCODE_ETSI, + CCODE_RESV3, + CCODE_RESV4, + CCODE_RESV5, + CCODE_RESV6, + CCODE_RESV7, + CCODE_RESV8, + CCODE_RESV9, + CCODE_RESVa, + CCODE_RESVb, + CCODE_RESVc, + CCODE_RESVd, + CCODE_RESVe, + CCODE_ALLBAND, + CCODE_ALBANIA, + CCODE_ALGERIA, + CCODE_ARGENTINA, + CCODE_ARMENIA, + CCODE_AUSTRALIA, + CCODE_AUSTRIA, + CCODE_AZERBAIJAN, + CCODE_BAHRAIN, + CCODE_BELARUS, + CCODE_BELGIUM, + CCODE_BELIZE, + CCODE_BOLIVIA, + CCODE_BRAZIL, + CCODE_BRUNEI_DARUSSALAM, + CCODE_BULGARIA, + CCODE_CANADA, + CCODE_CHILE, + CCODE_CHINA, + CCODE_COLOMBIA, + CCODE_COSTA_RICA, + CCODE_CROATIA, + CCODE_CYPRUS, + CCODE_CZECH, + CCODE_DENMARK, + CCODE_DOMINICAN_REPUBLIC, + CCODE_ECUADOR, + CCODE_EGYPT, + CCODE_EL_SALVADOR, + CCODE_ESTONIA, + CCODE_FINLAND, + CCODE_FRANCE, + CCODE_GERMANY, + CCODE_GREECE, + CCODE_GEORGIA, + CCODE_GUATEMALA, + CCODE_HONDURAS, + CCODE_HONG_KONG, + CCODE_HUNGARY, + CCODE_ICELAND, + CCODE_INDIA, + CCODE_INDONESIA, + CCODE_IRAN, + CCODE_IRELAND, + CCODE_ITALY, + CCODE_ISRAEL, + CCODE_JAPAN, + CCODE_JORDAN, + CCODE_KAZAKHSTAN, + CCODE_KUWAIT, + CCODE_LATVIA, + CCODE_LEBANON, + CCODE_LEICHTENSTEIN, + CCODE_LITHUANIA, + CCODE_LUXEMBURG, + CCODE_MACAU, + CCODE_MACEDONIA, + CCODE_MALTA, + CCODE_MALAYSIA, + CCODE_MEXICO, + CCODE_MONACO, + CCODE_MOROCCO, + CCODE_NETHERLANDS, + CCODE_NEW_ZEALAND, + CCODE_NORTH_KOREA, + CCODE_NORWAY, + CCODE_OMAN, + CCODE_PAKISTAN, + CCODE_PANAMA, + CCODE_PERU, + CCODE_PHILIPPINES, + CCODE_POLAND, + CCODE_PORTUGAL, + CCODE_PUERTO_RICO, + CCODE_QATAR, + CCODE_ROMANIA, + CCODE_RUSSIA, + CCODE_SAUDI_ARABIA, + CCODE_SINGAPORE, + CCODE_SLOVAKIA, + CCODE_SLOVENIA, + CCODE_SOUTH_AFRICA, + CCODE_SOUTH_KOREA, + CCODE_SPAIN, + CCODE_SWEDEN, + CCODE_SWITZERLAND, + CCODE_SYRIA, + CCODE_TAIWAN, + CCODE_THAILAND, + CCODE_TRINIDAD_TOBAGO, + CCODE_TUNISIA, + CCODE_TURKEY, + CCODE_UK, + CCODE_UKRAINE, + CCODE_UNITED_ARAB_EMIRATES, + CCODE_UNITED_STATES, + CCODE_URUGUAY, + CCODE_UZBEKISTAN, + CCODE_VENEZUELA, + CCODE_VIETNAM, + CCODE_YEMEN, + CCODE_ZIMBABWE, + CCODE_JAPAN_W52_W53, + CCODE_MAX +} COUNTRY_CODE; + +typedef struct tagSCountryTable +{ + BYTE byChannelCountryCode; /* The country code */ + CHAR chCountryCode[2]; + BYTE bChannelIdxList[CB_MAX_CHANNEL]; /* Available channels Index */ + BYTE byPower[CB_MAX_CHANNEL]; +} SCountryTable, DEF* PSCountryTable; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ +extern SCountryTable ChannelRuleTab[CCODE_MAX+1]; + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +/************************************************************************ + * Function prototype + ************************************************************************/ +#endif /* __COUNTRY_H__ */ diff --git a/drivers/staging/vt6655/datarate.c b/drivers/staging/vt6655/datarate.c new file mode 100644 index 00000000000..f58f9636be2 --- /dev/null +++ b/drivers/staging/vt6655/datarate.c @@ -0,0 +1,455 @@ +/* + * 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: datarate.c + * + * Purpose: Handles the auto fallback & data rates functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + * Functions: + * RATEvParseMaxRate - Parsing the highest basic & support rate in rate field of frame + * RATEvTxRateFallBack - Rate fallback Algorithm Implementaion + * RATEuSetIE- Set rate IE field. + * + * Revision History: + * + */ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__DATARATE_H__) +#include "datarate.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__SROM_H__) +#include "srom.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + + + + +/*--------------------- Static Classes ----------------------------*/ + + + extern WORD TxRate_iwconfig; //2008-5-8 <add> by chester +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; +const BYTE acbyIERate[MAX_RATE] = +{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + +#define AUTORATE_TXOK_CNT 0x0400 +#define AUTORATE_TXFAIL_CNT 0x0064 +#define AUTORATE_TIMEOUT 10 + +/*--------------------- Static Functions --------------------------*/ + +VOID s_vResetCounter ( + IN PKnownNodeDB psNodeDBTable + ); + + + +VOID +s_vResetCounter ( + IN PKnownNodeDB psNodeDBTable + ) +{ + BYTE ii; + + // clear statistic counter for auto_rate + for(ii=0;ii<=MAX_RATE;ii++) { + psNodeDBTable->uTxOk[ii] = 0; + psNodeDBTable->uTxFail[ii] = 0; + } +} + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + +/*+ + * + * Description: + * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE + * + * Parameters: + * In: + * BYTE - Rate value in SuppRates IE or ExtSuppRates IE + * Out: + * none + * + * Return Value: RateIdx + * +-*/ +BYTE +DATARATEbyGetRateIdx ( + IN BYTE byRate + ) +{ + BYTE ii; + + //Erase basicRate flag. + byRate = byRate & 0x7F;//0111 1111 + + for (ii = 0; ii < MAX_RATE; ii ++) { + if (acbyIERate[ii] == byRate) + return ii; + } + return 0; +} + + + +/*+ + * + * Routine Description: + * Rate fallback Algorithm Implementaion + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * psNodeDBTable - Pointer to Node Data Base + * Out: + * none + * + * Return Value: none + * +-*/ +#define AUTORATE_TXCNT_THRESHOLD 20 +#define AUTORATE_INC_THRESHOLD 30 + + + + +/*+ + * + * Description: + * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE + * + * Parameters: + * In: + * BYTE - Rate value in SuppRates IE or ExtSuppRates IE + * Out: + * none + * + * Return Value: RateIdx + * +-*/ +WORD +wGetRateIdx( + IN BYTE byRate + ) +{ + WORD ii; + + //Erase basicRate flag. + byRate = byRate & 0x7F;//0111 1111 + + for (ii = 0; ii < MAX_RATE; ii ++) { + if (acbyIERate[ii] == byRate) + return ii; + } + return 0; +} + +/*+ + * + * Description: + * Parsing the highest basic & support rate in rate field of frame. + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * pItemRates - Pointer to Rate field defined in 802.11 spec. + * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec. + * Out: + * pwMaxBasicRate - Maximum Basic Rate + * pwMaxSuppRate - Maximum Supported Rate + * pbyTopCCKRate - Maximum Basic Rate in CCK mode + * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode + * + * Return Value: none + * +-*/ +VOID +RATEvParseMaxRate ( + IN PVOID pDeviceHandler, + IN PWLAN_IE_SUPP_RATES pItemRates, + IN PWLAN_IE_SUPP_RATES pItemExtRates, + IN BOOL bUpdateBasicRate, + OUT PWORD pwMaxBasicRate, + OUT PWORD pwMaxSuppRate, + OUT PWORD pwSuppRate, + OUT PBYTE pbyTopCCKRate, + OUT PBYTE pbyTopOFDMRate + ) +{ +PSDevice pDevice = (PSDevice) pDeviceHandler; +UINT ii; +BYTE byHighSuppRate = 0; +BYTE byRate = 0; +WORD wOldBasicRate = pDevice->wBasicRate; +UINT uRateLen; + + + if (pItemRates == NULL) + return; + + *pwSuppRate = 0; + uRateLen = pItemRates->len; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen); + if (pDevice->eCurrentPHYType != PHY_TYPE_11B) { + if (uRateLen > WLAN_RATES_MAXLEN) + uRateLen = WLAN_RATES_MAXLEN; + } else { + if (uRateLen > WLAN_RATES_MAXLEN_11B) + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + for (ii = 0; ii < uRateLen; ii++) { + byRate = (BYTE)(pItemRates->abyRates[ii]); + if (WLAN_MGMT_IS_BASICRATE(byRate) && + (bUpdateBasicRate == TRUE)) { + // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate + CARDbAddBasicRate((PVOID)pDevice, wGetRateIdx(byRate)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate)); + } + byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F); + if (byHighSuppRate == 0) + byHighSuppRate = byRate; + if (byRate > byHighSuppRate) + byHighSuppRate = byRate; + *pwSuppRate |= (1<<wGetRateIdx(byRate)); + } + if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && + (pDevice->eCurrentPHYType != PHY_TYPE_11B)) { + + UINT uExtRateLen = pItemExtRates->len; + + if (uExtRateLen > WLAN_RATES_MAXLEN) + uExtRateLen = WLAN_RATES_MAXLEN; + + for (ii = 0; ii < uExtRateLen ; ii++) { + byRate = (BYTE)(pItemExtRates->abyRates[ii]); + // select highest basic rate + if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) { + // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate + CARDbAddBasicRate((PVOID)pDevice, wGetRateIdx(byRate)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate)); + } + byRate = (BYTE)(pItemExtRates->abyRates[ii]&0x7F); + if (byHighSuppRate == 0) + byHighSuppRate = byRate; + if (byRate > byHighSuppRate) + byHighSuppRate = byRate; + *pwSuppRate |= (1<<wGetRateIdx(byRate)); + //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", wGetRateIdx(byRate), byRate)); + } + } //if(pItemExtRates != NULL) + + if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((PVOID)pDevice)) { + pDevice->byPacketType = PK_TYPE_11GA; + } + + *pbyTopCCKRate = pDevice->byTopCCKBasicRate; + *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate; + *pwMaxSuppRate = wGetRateIdx(byHighSuppRate); + if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB)) + *pwMaxBasicRate = pDevice->byTopCCKBasicRate; + else + *pwMaxBasicRate = pDevice->byTopOFDMBasicRate; + if (wOldBasicRate != pDevice->wBasicRate) + CARDvSetRSPINF((PVOID)pDevice, pDevice->eCurrentPHYType); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n"); +} + + +/*+ + * + * Routine Description: + * Rate fallback Algorithm Implementaion + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * psNodeDBTable - Pointer to Node Data Base + * Out: + * none + * + * Return Value: none + * +-*/ +#define AUTORATE_TXCNT_THRESHOLD 20 +#define AUTORATE_INC_THRESHOLD 30 + +VOID +RATEvTxRateFallBack ( + IN PVOID pDeviceHandler, + IN PKnownNodeDB psNodeDBTable + ) +{ +PSDevice pDevice = (PSDevice) pDeviceHandler; +WORD wIdxDownRate = 0; +UINT ii; +//DWORD dwRateTable[MAX_RATE] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; +BOOL bAutoRate[MAX_RATE] = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}; +DWORD dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; +DWORD dwThroughput = 0; +WORD wIdxUpRate = 0; +DWORD dwTxDiff = 0; + + if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) { + // Don't do Fallback when scanning Channel + return; + } + + psNodeDBTable->uTimeCount ++; + + if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE]) + dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE]; + + if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) && + (dwTxDiff < AUTORATE_TXFAIL_CNT) && + (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) { + return; + } + + if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) { + psNodeDBTable->uTimeCount = 0; + } + + + for(ii=0;ii<MAX_RATE;ii++) { + if (psNodeDBTable->wSuppRate & (0x0001<<ii)) { + if (bAutoRate[ii] == TRUE) { + wIdxUpRate = (WORD) ii; + } + } else { + bAutoRate[ii] = FALSE; + } + } + + for(ii=0;ii<=psNodeDBTable->wTxDataRate;ii++) { + if ( (psNodeDBTable->uTxOk[ii] != 0) || + (psNodeDBTable->uTxFail[ii] != 0) ) { + dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii]; + if (ii < RATE_11M) { + psNodeDBTable->uTxFail[ii] *= 4; + } + dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]); + } +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n", +// ii, psNodeDBTable->uTxOk[ii], psNodeDBTable->uTxFail[ii], dwThroughputTbl[ii]); + } + dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; + + wIdxDownRate = psNodeDBTable->wTxDataRate; + for(ii = psNodeDBTable->wTxDataRate; ii > 0;) { + ii--; + if ( (dwThroughputTbl[ii] > dwThroughput) && + (bAutoRate[ii]==TRUE) ) { + dwThroughput = dwThroughputTbl[ii]; + wIdxDownRate = (WORD) ii; + } + } + psNodeDBTable->wTxDataRate = wIdxDownRate; + if (psNodeDBTable->uTxOk[MAX_RATE]) { + if (psNodeDBTable->uTxOk[MAX_RATE] > + (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) { + psNodeDBTable->wTxDataRate = wIdxUpRate; + } + }else { // adhoc, if uTxOk =0 & uTxFail = 0 + if (psNodeDBTable->uTxFail[MAX_RATE] == 0) + psNodeDBTable->wTxDataRate = wIdxUpRate; + } +//2008-5-8 <add> by chester +TxRate_iwconfig=psNodeDBTable->wTxDataRate; + s_vResetCounter(psNodeDBTable); +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", psNodeDBTable->wTxDataRate, wIdxUpRate, wIdxDownRate); + + return; + +} + +/*+ + * + * Description: + * This routine is used to assemble available Rate IE. + * + * Parameters: + * In: + * pDevice + * Out: + * + * Return Value: None + * +-*/ +BYTE +RATEuSetIE ( + IN PWLAN_IE_SUPP_RATES pSrcRates, + IN PWLAN_IE_SUPP_RATES pDstRates, + IN UINT uRateLen + ) +{ + UINT ii, uu, uRateCnt = 0; + + if ((pSrcRates == NULL) || (pDstRates == NULL)) + return 0; + + if (pSrcRates->len == 0) + return 0; + + for (ii = 0; ii < uRateLen; ii++) { + for (uu = 0; uu < pSrcRates->len; uu++) { + if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) { + pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu]; + break; + } + } + } + return (BYTE)uRateCnt; +} + diff --git a/drivers/staging/vt6655/datarate.h b/drivers/staging/vt6655/datarate.h new file mode 100644 index 00000000000..5096f3df499 --- /dev/null +++ b/drivers/staging/vt6655/datarate.h @@ -0,0 +1,95 @@ +/* + * 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: datarate.h + * + * Purpose: Handles the auto fallback & data rates functions + * + * Author: Lyndon Chen + * + * Date: July 16, 2002 + * + */ +#ifndef __DATARATE_H__ +#define __DATARATE_H__ + +/*--------------------- Export Definitions -------------------------*/ + +#define FALLBACK_PKT_COLLECT_TR_H 50 // pkts +#define FALLBACK_PKT_COLLECT_TR_L 10 // pkts +#define FALLBACK_POLL_SECOND 5 // 5 sec +#define FALLBACK_RECOVER_SECOND 30 // 30 sec +#define FALLBACK_THRESHOLD 15 // percent +#define UPGRADE_THRESHOLD 5 // percent +#define UPGRADE_CNT_THRD 3 // times +#define RETRY_TIMES_THRD_H 2 // times +#define RETRY_TIMES_THRD_L 1 // times + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Types ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + + +VOID +RATEvParseMaxRate( + IN PVOID pDeviceHandler, + IN PWLAN_IE_SUPP_RATES pItemRates, + IN PWLAN_IE_SUPP_RATES pItemExtRates, + IN BOOL bUpdateBasicRate, + OUT PWORD pwMaxBasicRate, + OUT PWORD pwMaxSuppRate, + OUT PWORD pwSuppRate, + OUT PBYTE pbyTopCCKRate, + OUT PBYTE pbyTopOFDMRate + ); + +VOID +RATEvTxRateFallBack( + IN PVOID pDeviceHandler, + IN PKnownNodeDB psNodeDBTable + ); + +BYTE +RATEuSetIE( + IN PWLAN_IE_SUPP_RATES pSrcRates, + IN PWLAN_IE_SUPP_RATES pDstRates, + IN UINT uRateLen + ); + +WORD +wGetRateIdx( + IN BYTE byRate + ); + + +BYTE +DATARATEbyGetRateIdx( + IN BYTE byRate + ); + + +#endif //__DATARATE_H__ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h new file mode 100644 index 00000000000..c0fc1d3b0a2 --- /dev/null +++ b/drivers/staging/vt6655/desc.h @@ -0,0 +1,697 @@ +/* + * 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: desc.h + * + * Purpose:The header file of descriptor + * + * Revision History: + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + + +#ifndef __DESC_H__ +#define __DESC_H__ + +#include <linux/types.h> +#include <linux/mm.h> + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +// #ifdef PRIVATE_OBJ +//#if !defined(__DEVICE_MODULE_H) +//#include "device_module.h" +//#endif + + + + +/*--------------------- Export Definitions -------------------------*/ + +#define B_OWNED_BY_CHIP 1 // +#define B_OWNED_BY_HOST 0 // + +// +// Bits in the RSR register +// +#define RSR_ADDRBROAD 0x80 // 1000 0000 +#define RSR_ADDRMULTI 0x40 // 0100 0000 +#define RSR_ADDRUNI 0x00 // 0000 0000 +#define RSR_IVLDTYP 0x20 // 0010 0000 , invalid packet type +#define RSR_IVLDLEN 0x10 // 0001 0000 , invalid len (> 2312 byte) +#define RSR_BSSIDOK 0x08 // 0000 1000 +#define RSR_CRCOK 0x04 // 0000 0100 +#define RSR_BCNSSIDOK 0x02 // 0000 0010 +#define RSR_ADDROK 0x01 // 0000 0001 + +// +// Bits in the new RSR register +// +#define NEWRSR_DECRYPTOK 0x10 // 0001 0000 +#define NEWRSR_CFPIND 0x08 // 0000 1000 +#define NEWRSR_HWUTSF 0x04 // 0000 0100 +#define NEWRSR_BCNHITAID 0x02 // 0000 0010 +#define NEWRSR_BCNHITAID0 0x01 // 0000 0001 + +// +// Bits in the TSR0 register +// +#define TSR0_PWRSTS1_2 0xC0 // 1100 0000 +#define TSR0_PWRSTS7 0x20 // 0010 0000 +#define TSR0_NCR 0x1F // 0001 1111 + +// +// Bits in the TSR1 register +// +#define TSR1_TERR 0x80 // 1000 0000 +#define TSR1_PWRSTS4_6 0x70 // 0111 0000 +#define TSR1_RETRYTMO 0x08 // 0000 1000 +#define TSR1_TMO 0x04 // 0000 0100 +#define TSR1_PWRSTS3 0x02 // 0000 0010 +#define ACK_DATA 0x01 // 0000 0000 + +// +// Bits in the TCR register +// +#define EDMSDU 0x04 // 0000 0100 end of sdu +#define TCR_EDP 0x02 // 0000 0010 end of packet +#define TCR_STP 0x01 // 0000 0001 start of packet + +// max transmit or receive buffer size +#define CB_MAX_BUF_SIZE 2900U // max buffer size + // NOTE: must be multiple of 4 +#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE // max Tx buffer size +#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE // max Rx buffer size when not use Multi-RD + +#define CB_BEACON_BUF_SIZE 512U // default beacon buffer size + +#define CB_MAX_RX_DESC 128 // max # of descriptor +#define CB_MIN_RX_DESC 16 // min # of rx descriptor +#define CB_MAX_TX_DESC 64 // max # of descriptor +#define CB_MIN_TX_DESC 16 // min # of tx descriptor + +#define CB_MAX_RECEIVED_PACKETS 16 // max # of received packets at one time + // limit our receive routine to indicating + // this many at a time for 2 reasons: + // 1. driver flow control to protocol layer + // 2. limit the time used in ISR routine + +#define CB_EXTRA_RD_NUM 32 // default # of Extra RD +#define CB_RD_NUM 32 // default # of RD +#define CB_TD_NUM 32 // default # of TD + + +// max number of physical segments +// in a single NDIS packet. Above this threshold, the packet +// is copied into a single physically contiguous buffer +#define CB_MAX_SEGMENT 4 + +#define CB_MIN_MAP_REG_NUM 4 +#define CB_MAX_MAP_REG_NUM CB_MAX_TX_DESC + +#define CB_PROTOCOL_RESERVED_SECTION 16 + + +// if retrys excess 15 times , tx will abort, and +// if tx fifo underflow, tx will fail +// we should try to resend it +#define CB_MAX_TX_ABORT_RETRY 3 + +#ifdef __BIG_ENDIAN + +// WMAC definition FIFO Control +#define FIFOCTL_AUTO_FB_1 0x0010 // 0001 0000 0000 0000 +#define FIFOCTL_AUTO_FB_0 0x0008 // 0000 1000 0000 0000 +#define FIFOCTL_GRPACK 0x0004 // 0000 0100 0000 0000 +#define FIFOCTL_11GA 0x0003 // 0000 0011 0000 0000 +#define FIFOCTL_11GB 0x0002 // 0000 0010 0000 0000 +#define FIFOCTL_11B 0x0001 // 0000 0001 0000 0000 +#define FIFOCTL_11A 0x0000 // 0000 0000 0000 0000 +#define FIFOCTL_RTS 0x8000 // 0000 0000 1000 0000 +#define FIFOCTL_ISDMA0 0x4000 // 0000 0000 0100 0000 +#define FIFOCTL_GENINT 0x2000 // 0000 0000 0010 0000 +#define FIFOCTL_TMOEN 0x1000 // 0000 0000 0001 0000 +#define FIFOCTL_LRETRY 0x0800 // 0000 0000 0000 1000 +#define FIFOCTL_CRCDIS 0x0400 // 0000 0000 0000 0100 +#define FIFOCTL_NEEDACK 0x0200 // 0000 0000 0000 0010 +#define FIFOCTL_LHEAD 0x0100 // 0000 0000 0000 0001 + +//WMAC definition Frag Control +#define FRAGCTL_AES 0x0003 // 0000 0011 0000 0000 +#define FRAGCTL_TKIP 0x0002 // 0000 0010 0000 0000 +#define FRAGCTL_LEGACY 0x0001 // 0000 0001 0000 0000 +#define FRAGCTL_NONENCRYPT 0x0000 // 0000 0000 0000 0000 +//#define FRAGCTL_AC3 0x0C00 // 0000 0000 0000 1100 +//#define FRAGCTL_AC2 0x0800 // 0000 0000 0000 1000 +//#define FRAGCTL_AC1 0x0400 // 0000 0000 0000 0100 +//#define FRAGCTL_AC0 0x0000 // 0000 0000 0000 0000 +#define FRAGCTL_ENDFRAG 0x0300 // 0000 0000 0000 0011 +#define FRAGCTL_MIDFRAG 0x0200 // 0000 0000 0000 0010 +#define FRAGCTL_STAFRAG 0x0100 // 0000 0000 0000 0001 +#define FRAGCTL_NONFRAG 0x0000 // 0000 0000 0000 0000 + +#else + +#define FIFOCTL_AUTO_FB_1 0x1000 // 0001 0000 0000 0000 +#define FIFOCTL_AUTO_FB_0 0x0800 // 0000 1000 0000 0000 +#define FIFOCTL_GRPACK 0x0400 // 0000 0100 0000 0000 +#define FIFOCTL_11GA 0x0300 // 0000 0011 0000 0000 +#define FIFOCTL_11GB 0x0200 // 0000 0010 0000 0000 +#define FIFOCTL_11B 0x0100 // 0000 0001 0000 0000 +#define FIFOCTL_11A 0x0000 // 0000 0000 0000 0000 +#define FIFOCTL_RTS 0x0080 // 0000 0000 1000 0000 +#define FIFOCTL_ISDMA0 0x0040 // 0000 0000 0100 0000 +#define FIFOCTL_GENINT 0x0020 // 0000 0000 0010 0000 +#define FIFOCTL_TMOEN 0x0010 // 0000 0000 0001 0000 +#define FIFOCTL_LRETRY 0x0008 // 0000 0000 0000 1000 +#define FIFOCTL_CRCDIS 0x0004 // 0000 0000 0000 0100 +#define FIFOCTL_NEEDACK 0x0002 // 0000 0000 0000 0010 +#define FIFOCTL_LHEAD 0x0001 // 0000 0000 0000 0001 + +//WMAC definition Frag Control +#define FRAGCTL_AES 0x0300 // 0000 0011 0000 0000 +#define FRAGCTL_TKIP 0x0200 // 0000 0010 0000 0000 +#define FRAGCTL_LEGACY 0x0100 // 0000 0001 0000 0000 +#define FRAGCTL_NONENCRYPT 0x0000 // 0000 0000 0000 0000 +//#define FRAGCTL_AC3 0x000C // 0000 0000 0000 1100 +//#define FRAGCTL_AC2 0x0008 // 0000 0000 0000 1000 +//#define FRAGCTL_AC1 0x0004 // 0000 0000 0000 0100 +//#define FRAGCTL_AC0 0x0000 // 0000 0000 0000 0000 +#define FRAGCTL_ENDFRAG 0x0003 // 0000 0000 0000 0011 +#define FRAGCTL_MIDFRAG 0x0002 // 0000 0000 0000 0010 +#define FRAGCTL_STAFRAG 0x0001 // 0000 0000 0000 0001 +#define FRAGCTL_NONFRAG 0x0000 // 0000 0000 0000 0000 + +#endif // #ifdef __BIG_ENDIAN + +//#define TYPE_AC0DMA 0 +//#define TYPE_TXDMA0 1 +#define TYPE_TXDMA0 0 +#define TYPE_AC0DMA 1 +#define TYPE_ATIMDMA 2 +#define TYPE_SYNCDMA 3 +#define TYPE_MAXTD 2 + +#define TYPE_BEACONDMA 4 + +#define TYPE_RXDMA0 0 +#define TYPE_RXDMA1 1 +#define TYPE_MAXRD 2 + + + +// TD_INFO flags control bit +#define TD_FLAGS_NETIF_SKB 0x01 // check if need release skb +#define TD_FLAGS_PRIV_SKB 0x02 // check if called from private skb(hostap) +#define TD_FLAGS_PS_RETRY 0x04 // check if PS STA frame re-transmit +//#define TD_FLAGS_NETIF_SKB 0x04 + +/*--------------------- Export Types ------------------------------*/ + +// ref_sk_buff is used for mapping the skb structure between pre-built driver-obj & running kernel. +// Since different kernel version (2.4x) may change skb structure, i.e. pre-built driver-obj +// may link to older skb that leads error. + +typedef struct tagDEVICE_RD_INFO { + struct sk_buff* skb; +#ifdef PRIVATE_OBJ + ref_sk_buff ref_skb; +#endif + dma_addr_t skb_dma; + dma_addr_t curr_desc; +} DEVICE_RD_INFO, *PDEVICE_RD_INFO; + +/* +static inline PDEVICE_RD_INFO alloc_rd_info(void) { + PDEVICE_RD_INFO ptr; + if ((ptr = kmalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC)) == NULL) + return NULL; + else { + memset(ptr,0,sizeof(DEVICE_RD_INFO)); + return ptr; + } +} +*/ + +/* +typedef struct tagRDES0 { + WORD wResCount; + WORD wf1Owner ; +// WORD f15Reserved : 15; +// WORD f1Owner : 1; +} __attribute__ ((__packed__)) +SRDES0; +*/ + +#ifdef __BIG_ENDIAN + +typedef struct tagRDES0 { + volatile WORD wResCount; + union { + volatile U16 f15Reserved; + struct { + volatile U8 f8Reserved1; + volatile U8 f1Owner:1; + volatile U8 f7Reserved:7; + } __attribute__ ((__packed__)); + } __attribute__ ((__packed__)); +} __attribute__ ((__packed__)) +SRDES0, *PSRDES0; + +#else + +typedef struct tagRDES0 { + WORD wResCount; + WORD f15Reserved : 15; + WORD f1Owner : 1; +} __attribute__ ((__packed__)) +SRDES0; + + +#endif + +typedef struct tagRDES1 { + WORD wReqCount; + WORD wReserved; +} __attribute__ ((__packed__)) +SRDES1; + +// +// Rx descriptor +// +typedef struct tagSRxDesc { + volatile SRDES0 m_rd0RD0; + volatile SRDES1 m_rd1RD1; + volatile U32 buff_addr; + volatile U32 next_desc; + struct tagSRxDesc *next;//4 bytes + volatile PDEVICE_RD_INFO pRDInfo;//4 bytes + volatile U32 Reserved[2];//8 bytes +} __attribute__ ((__packed__)) +SRxDesc, DEF* PSRxDesc; +typedef const SRxDesc DEF* PCSRxDesc; + +#ifdef __BIG_ENDIAN + +/* +typedef struct tagTDES0 { + volatile BYTE byTSR0; + volatile BYTE byTSR1; + volatile WORD wOwner_Txtime; +// volatile WORD f15Txtime : 15; +// volatile WORD f1Owner:1; +} __attribute__ ((__packed__)) +STDES0; +*/ + +typedef struct tagTDES0 { + volatile BYTE byTSR0; + volatile BYTE byTSR1; + union { + volatile U16 f15Txtime; + struct { + volatile U8 f8Reserved1; + volatile U8 f1Owner:1; + volatile U8 f7Reserved:7; + } __attribute__ ((__packed__)); + } __attribute__ ((__packed__)); +} __attribute__ ((__packed__)) +STDES0, PSTDES0; + +#else + +typedef struct tagTDES0 { + volatile BYTE byTSR0; + volatile BYTE byTSR1; + volatile WORD f15Txtime : 15; + volatile WORD f1Owner:1; +} __attribute__ ((__packed__)) +STDES0; + +#endif + + +typedef struct tagTDES1 { + volatile WORD wReqCount; + volatile BYTE byTCR; + volatile BYTE byReserved; +} __attribute__ ((__packed__)) +STDES1; + + +typedef struct tagDEVICE_TD_INFO{ + struct sk_buff* skb; + PBYTE buf; + dma_addr_t skb_dma; + dma_addr_t buf_dma; + dma_addr_t curr_desc; + DWORD dwReqCount; + DWORD dwHeaderLength; + BYTE byFlags; +} DEVICE_TD_INFO, *PDEVICE_TD_INFO; + +/* +static inline PDEVICE_TD_INFO alloc_td_info(void) { + PDEVICE_TD_INFO ptr; + if ((ptr = kmalloc(sizeof(DEVICE_TD_INFO),GFP_ATOMIC))==NULL) + return NULL; + else { + memset(ptr,0,sizeof(DEVICE_TD_INFO)); + return ptr; + } +} +*/ + +// +// transmit descriptor +// +typedef struct tagSTxDesc { + volatile STDES0 m_td0TD0; + volatile STDES1 m_td1TD1; + volatile U32 buff_addr; + volatile U32 next_desc; + struct tagSTxDesc* next; //4 bytes + volatile PDEVICE_TD_INFO pTDInfo;//4 bytes + volatile U32 Reserved[2];//8 bytes +} __attribute__ ((__packed__)) +STxDesc, DEF* PSTxDesc; +typedef const STxDesc DEF* PCSTxDesc; + + +typedef struct tagSTxSyncDesc { + volatile STDES0 m_td0TD0; + volatile STDES1 m_td1TD1; + volatile DWORD buff_addr; // pointer to logical buffer + volatile DWORD next_desc; // pointer to next logical descriptor + volatile WORD m_wFIFOCtl; + volatile WORD m_wTimeStamp; + struct tagSTxSyncDesc* next; //4 bytes + volatile PDEVICE_TD_INFO pTDInfo;//4 bytes + volatile DWORD m_dwReserved2; +} __attribute__ ((__packed__)) +STxSyncDesc, DEF* PSTxSyncDesc; +typedef const STxSyncDesc DEF* PCSTxSyncDesc; + + +// +// RsvTime buffer header +// +typedef struct tagSRrvTime_gRTS { + WORD wRTSTxRrvTime_ba; + WORD wRTSTxRrvTime_aa; + WORD wRTSTxRrvTime_bb; + WORD wReserved; + WORD wTxRrvTime_b; + WORD wTxRrvTime_a; +}__attribute__ ((__packed__)) +SRrvTime_gRTS, DEF* PSRrvTime_gRTS; +typedef const SRrvTime_gRTS DEF* PCSRrvTime_gRTS; + +typedef struct tagSRrvTime_gCTS { + WORD wCTSTxRrvTime_ba; + WORD wReserved; + WORD wTxRrvTime_b; + WORD wTxRrvTime_a; +}__attribute__ ((__packed__)) +SRrvTime_gCTS, DEF* PSRrvTime_gCTS; +typedef const SRrvTime_gCTS DEF* PCSRrvTime_gCTS; + +typedef struct tagSRrvTime_ab { + WORD wRTSTxRrvTime; + WORD wTxRrvTime; +}__attribute__ ((__packed__)) +SRrvTime_ab, DEF* PSRrvTime_ab; +typedef const SRrvTime_ab DEF* PCSRrvTime_ab; + +typedef struct tagSRrvTime_atim { + WORD wCTSTxRrvTime_ba; + WORD wTxRrvTime_a; +}__attribute__ ((__packed__)) +SRrvTime_atim, DEF* PSRrvTime_atim; +typedef const SRrvTime_atim DEF* PCSRrvTime_atim; + +// +// RTS buffer header +// +typedef struct tagSRTSData { + WORD wFrameControl; + WORD wDurationID; + BYTE abyRA[U_ETHER_ADDR_LEN]; + BYTE abyTA[U_ETHER_ADDR_LEN]; +}__attribute__ ((__packed__)) +SRTSData, DEF* PSRTSData; +typedef const SRTSData DEF* PCSRTSData; + +typedef struct tagSRTS_g { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + BYTE bySignalField_a; + BYTE byServiceField_a; + WORD wTransmitLength_a; + WORD wDuration_ba; + WORD wDuration_aa; + WORD wDuration_bb; + WORD wReserved; + SRTSData Data; +}__attribute__ ((__packed__)) +SRTS_g, DEF* PSRTS_g; +typedef const SRTS_g DEF* PCSRTS_g; + + +typedef struct tagSRTS_g_FB { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + BYTE bySignalField_a; + BYTE byServiceField_a; + WORD wTransmitLength_a; + WORD wDuration_ba; + WORD wDuration_aa; + WORD wDuration_bb; + WORD wReserved; + WORD wRTSDuration_ba_f0; + WORD wRTSDuration_aa_f0; + WORD wRTSDuration_ba_f1; + WORD wRTSDuration_aa_f1; + SRTSData Data; +}__attribute__ ((__packed__)) +SRTS_g_FB, DEF* PSRTS_g_FB; +typedef const SRTS_g_FB DEF* PCSRTS_g_FB; + + +typedef struct tagSRTS_ab { + BYTE bySignalField; + BYTE byServiceField; + WORD wTransmitLength; + WORD wDuration; + WORD wReserved; + SRTSData Data; +}__attribute__ ((__packed__)) +SRTS_ab, DEF* PSRTS_ab; +typedef const SRTS_ab DEF* PCSRTS_ab; + + +typedef struct tagSRTS_a_FB { + BYTE bySignalField; + BYTE byServiceField; + WORD wTransmitLength; + WORD wDuration; + WORD wReserved; + WORD wRTSDuration_f0; + WORD wRTSDuration_f1; + SRTSData Data; +}__attribute__ ((__packed__)) +SRTS_a_FB, DEF* PSRTS_a_FB; +typedef const SRTS_a_FB DEF* PCSRTS_a_FB; + + +// +// CTS buffer header +// +typedef struct tagSCTSData { + WORD wFrameControl; + WORD wDurationID; + BYTE abyRA[U_ETHER_ADDR_LEN]; + WORD wReserved; +}__attribute__ ((__packed__)) +SCTSData, DEF* PSCTSData; + +typedef struct tagSCTS { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + WORD wDuration_ba; + WORD wReserved; + SCTSData Data; +}__attribute__ ((__packed__)) +SCTS, DEF* PSCTS; +typedef const SCTS DEF* PCSCTS; + +typedef struct tagSCTS_FB { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + WORD wDuration_ba; + WORD wReserved; + WORD wCTSDuration_ba_f0; + WORD wCTSDuration_ba_f1; + SCTSData Data; +}__attribute__ ((__packed__)) +SCTS_FB, DEF* PSCTS_FB; +typedef const SCTS_FB DEF* PCSCTS_FB; + + +// +// Tx FIFO header +// +typedef struct tagSTxBufHead { + DWORD adwTxKey[4]; + WORD wFIFOCtl; + WORD wTimeStamp; + WORD wFragCtl; + BYTE byTxPower; + BYTE wReserved; +}__attribute__ ((__packed__)) +STxBufHead, DEF* PSTxBufHead; +typedef const STxBufHead DEF* PCSTxBufHead; + +typedef struct tagSTxShortBufHead { + WORD wFIFOCtl; + WORD wTimeStamp; +}__attribute__ ((__packed__)) +STxShortBufHead, DEF* PSTxShortBufHead; +typedef const STxShortBufHead DEF* PCSTxShortBufHead; + +// +// Tx data header +// +typedef struct tagSTxDataHead_g { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + BYTE bySignalField_a; + BYTE byServiceField_a; + WORD wTransmitLength_a; + WORD wDuration_b; + WORD wDuration_a; + WORD wTimeStampOff_b; + WORD wTimeStampOff_a; +}__attribute__ ((__packed__)) +STxDataHead_g, DEF* PSTxDataHead_g; +typedef const STxDataHead_g DEF* PCSTxDataHead_g; + +typedef struct tagSTxDataHead_g_FB { + BYTE bySignalField_b; + BYTE byServiceField_b; + WORD wTransmitLength_b; + BYTE bySignalField_a; + BYTE byServiceField_a; + WORD wTransmitLength_a; + WORD wDuration_b; + WORD wDuration_a; + WORD wDuration_a_f0; + WORD wDuration_a_f1; + WORD wTimeStampOff_b; + WORD wTimeStampOff_a; +}__attribute__ ((__packed__)) +STxDataHead_g_FB, DEF* PSTxDataHead_g_FB; +typedef const STxDataHead_g_FB DEF* PCSTxDataHead_g_FB; + + +typedef struct tagSTxDataHead_ab { + BYTE bySignalField; + BYTE byServiceField; + WORD wTransmitLength; + WORD wDuration; + WORD wTimeStampOff; +}__attribute__ ((__packed__)) +STxDataHead_ab, DEF* PSTxDataHead_ab; +typedef const STxDataHead_ab DEF* PCSTxDataHead_ab; + + +typedef struct tagSTxDataHead_a_FB { + BYTE bySignalField; + BYTE byServiceField; + WORD wTransmitLength; + WORD wDuration; + WORD wTimeStampOff; + WORD wDuration_f0; + WORD wDuration_f1; +}__attribute__ ((__packed__)) +STxDataHead_a_FB, DEF* PSTxDataHead_a_FB; +typedef const STxDataHead_a_FB DEF* PCSTxDataHead_a_FB; + +// +// MICHDR data header +// +typedef struct tagSMICHDRHead { + DWORD adwHDR0[4]; + DWORD adwHDR1[4]; + DWORD adwHDR2[4]; +}__attribute__ ((__packed__)) +SMICHDRHead, DEF* PSMICHDRHead; +typedef const SMICHDRHead DEF* PCSMICHDRHead; + +typedef struct tagSBEACONCtl { + DWORD BufReady : 1; + DWORD TSF : 15; + DWORD BufLen : 11; + DWORD Reserved : 5; +}__attribute__ ((__packed__)) +SBEACONCtl; + + +typedef struct tagSSecretKey { + DWORD dwLowDword; + BYTE byHighByte; +}__attribute__ ((__packed__)) +SSecretKey; + +typedef struct tagSKeyEntry { + BYTE abyAddrHi[2]; + WORD wKCTL; + BYTE abyAddrLo[4]; + DWORD dwKey0[4]; + DWORD dwKey1[4]; + DWORD dwKey2[4]; + DWORD dwKey3[4]; + DWORD dwKey4[4]; +}__attribute__ ((__packed__)) +SKeyEntry; +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + + +#endif // __DESC_H__ + diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h new file mode 100644 index 00000000000..264d1bb2ff7 --- /dev/null +++ b/drivers/staging/vt6655/device.h @@ -0,0 +1,1063 @@ +/* + * 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: device.h + * + * Purpose: MAC Data structure + * + * Author: Tevin Chen + * + * Date: Mar 17, 1997 + * + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#ifdef MODULE +#ifdef MODVERSIONS +#include <linux/modversions.h> +#endif /* MODVERSIONS */ +#include <linux/module.h> +#endif /* MODULE */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/version.h> +#include <linux/string.h> +#include <linux/wait.h> +#include <linux/if_arp.h> +#include <linux/sched.h> +#include <asm/io.h> +#include <linux/if.h> +//#include <linux/config.h> +#include <asm/uaccess.h> +#include <linux/proc_fs.h> +#include <linux/inetdevice.h> +#include <linux/reboot.h> +#ifdef SIOCETHTOOL +#define DEVICE_ETHTOOL_IOCTL_SUPPORT +#include <linux/ethtool.h> +#else +#undef DEVICE_ETHTOOL_IOCTL_SUPPORT +#endif +/* Include Wireless Extension definition and check version - Jean II */ +#include <linux/wireless.h> +#if WIRELESS_EXT > 12 +#include <net/iw_handler.h> // New driver API +#endif /* WIRELESS_EXT > 12 */ + +//2008-0409-07, <Add> by Einsn Liu +#if WIRELESS_EXT > 17 +#ifndef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +#define WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +#endif +#endif +//2008-4-14<add> by chester for led issue +//#define FOR_LED_ON_NOTEBOOK +// + + + +// device specific +// +#if !defined(_KCOMPAT_H) +#include "kcompat.h" +#endif + +#if !defined(__DEVICE_CONFIG_H) +#include "device_cfg.h" +#endif + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__MIB_H__) +#include "mib.h" +#endif +#if !defined(__SROM_H__) +#include "srom.h" +#endif +#if !defined(__RC4_H__) +#include "rc4.h" +#endif +#if !defined(__TPCI_H__) +#include "tpci.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif + +#if !defined(__KEY_H__) +#include "key.h" +#endif + +#if !defined(__MAC_H__) +#include "mac.h" +#endif + +//PLICE_DEBUG-> +//#define THREAD + +//#define TASK_LET +//PLICE_DEBUG<- + +// #ifdef PRIVATE_OBJ +//#if !defined(__DEVICE_MODULE_H) +//#include "device_module.h" +//#endif + + +/*--------------------- Export Definitions -------------------------*/ + +#define MAC_MAX_CONTEXT_REG (256+128) + +#define MAX_MULTICAST_ADDRESS_NUM 32 +#define MULTICAST_ADDRESS_LIST_SIZE (MAX_MULTICAST_ADDRESS_NUM * U_ETHER_ADDR_LEN) + + +//#define OP_MODE_INFRASTRUCTURE 0 +//#define OP_MODE_ADHOC 1 +//#define OP_MODE_AP 2 + +#define DUPLICATE_RX_CACHE_LENGTH 5 + +#define NUM_KEY_ENTRY 11 + +#define TX_WEP_NONE 0 +#define TX_WEP_OTF 1 +#define TX_WEP_SW 2 +#define TX_WEP_SWOTP 3 +#define TX_WEP_OTPSW 4 +#define TX_WEP_SW232 5 + +#define KEYSEL_WEP40 0 +#define KEYSEL_WEP104 1 +#define KEYSEL_TKIP 2 +#define KEYSEL_CCMP 3 + + + +#define AUTO_FB_NONE 0 +#define AUTO_FB_0 1 +#define AUTO_FB_1 2 + +#define FB_RATE0 0 +#define FB_RATE1 1 + +// Antenna Mode +#define ANT_A 0 +#define ANT_B 1 +#define ANT_DIVERSITY 2 +#define ANT_RXD_TXA 3 +#define ANT_RXD_TXB 4 +#define ANT_UNKNOWN 0xFF + +#define MAXCHECKHANGCNT 4 + +#define BB_VGA_LEVEL 4 +#define BB_VGA_CHANGE_THRESHOLD 16 + + +#ifndef RUN_AT +#define RUN_AT(x) (jiffies+(x)) +#endif + +// DMA related +#define RESERV_AC0DMA 4 + + +// BUILD OBJ mode +#ifdef PRIVATE_OBJ + +#undef dev_kfree_skb +#undef dev_kfree_skb_irq +#undef dev_alloc_skb +#undef kfree +#undef del_timer +#undef init_timer +#undef add_timer +#undef kmalloc +#undef netif_stop_queue +#undef netif_start_queue +#undef netif_wake_queue +#undef netif_queue_stopped +#undef netif_rx +#undef netif_running +#undef udelay +#undef mdelay +#undef eth_type_trans +#undef skb_put +#undef HZ +#undef RUN_AT +#undef pci_alloc_consistent +#undef pci_free_consistent +#undef register_netdevice +#undef register_netdev +#undef unregister_netdevice +#undef unregister_netdev +#undef skb_queue_head_init +#undef skb_queue_tail +#undef skb_queue_empty +#undef free_irq +#undef copy_from_user +#undef copy_to_user +#undef spin_lock_init +#undef pci_map_single +#undef pci_unmap_single + +// redefine kernel dependent fucntion +#define dev_kfree_skb ref_dev_kfree_skb +#define dev_kfree_skb_irq ref_dev_kfree_skb_irq +#define dev_alloc_skb ref_dev_alloc_skb +#define kfree ref_kfree +#define del_timer ref_del_timer +#define init_timer ref_init_timer +#define add_timer ref_add_timer +#define kmalloc ref_kmalloc +#define netif_stop_queue ref_netif_stop_queue +#define netif_start_queue ref_netif_start_queue +#define netif_wake_queue ref_netif_wake_queue +#define netif_queue_stopped ref_netif_queue_stopped +#define netif_rx ref_netif_rx +#define netif_running ref_netif_running +#define udelay ref_udelay +#define mdelay ref_mdelay +#define get_jiffies() ref_get_jiffies() +#define RUN_AT(x) (get_jiffies()+(x)) +#define HZ ref_HZ_tick() +#define eth_type_trans ref_eth_type_trans +#define skb_put ref_skb_put +#define skb_queue_head_init ref_skb_queue_head_init +#define skb_queue_tail ref_skb_queue_tail +#define skb_queue_empty ref_skb_queue_empty + +#define pci_alloc_consistent ref_pci_alloc_consistent +#define pci_free_consistent ref_pci_free_consistent +#define register_netdevice ref_register_netdevice +#define register_netdev ref_register_netdev +#define unregister_netdevice ref_unregister_netdevice +#define unregister_netdev ref_unregister_netdev + +#define free_irq ref_free_irq +#define copy_from_user ref_copy_from_user +#define copy_to_user ref_copy_to_user +#define spin_lock_init ref_spin_lock_init +#define pci_map_single ref_pci_map_single +#define pci_unmap_single ref_pci_unmap_single +#endif + + +#ifdef PRIVATE_OBJ +#undef printk +#define DEVICE_PRT(l, p, args...) {if (l<=msglevel) do {} while (0);} +//#define DEVICE_PRT(l, p, args...) {if (l<=msglevel) printk( p ,##args);} +#else +#define DEVICE_PRT(l, p, args...) {if (l<=msglevel) printk( p ,##args);} +#endif + + +#define AVAIL_TD(p,q) ((p)->sOpts.nTxDescs[(q)]-((p)->iTDUsed[(q)])) + +//PLICE_DEBUG -> +#define NUM 64 +//PLICE_DEUBG <- + + + +/*--------------------- Export Types ------------------------------*/ + + +//0:11A 1:11B 2:11G +typedef enum _VIA_BB_TYPE +{ + BB_TYPE_11A=0, + BB_TYPE_11B, + BB_TYPE_11G +} VIA_BB_TYPE, *PVIA_BB_TYPE; + +//0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate) +typedef enum _VIA_PKT_TYPE +{ + PK_TYPE_11A=0, + PK_TYPE_11B, + PK_TYPE_11GB, + PK_TYPE_11GA +} VIA_PKT_TYPE, *PVIA_PKT_TYPE; + + +typedef enum __device_msg_level { + MSG_LEVEL_ERR=0, //Errors that will cause abnormal operation. + MSG_LEVEL_NOTICE=1, //Some errors need users to be notified. + MSG_LEVEL_INFO=2, //Normal message. + MSG_LEVEL_VERBOSE=3, //Will report all trival errors. + MSG_LEVEL_DEBUG=4 //Only for debug purpose. +} DEVICE_MSG_LEVEL, *PDEVICE_MSG_LEVEL; + +typedef enum __device_init_type { + DEVICE_INIT_COLD=0, // cold init + DEVICE_INIT_RESET, // reset init or Dx to D0 power remain init + DEVICE_INIT_DXPL // Dx to D0 power lost init +} DEVICE_INIT_TYPE, *PDEVICE_INIT_TYPE; + + +//++ NDIS related + +#define MAX_BSSIDINFO_4_PMKID 16 +#define MAX_PMKIDLIST 5 +//Flags for PMKID Candidate list structure +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +// PMKID Structures +typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; + + +typedef enum _NDIS_802_11_WEP_STATUS +{ + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + + +typedef enum _NDIS_802_11_STATUS_TYPE +{ + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; + +//Added new types for PMKID Candidate lists. +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + ULONG Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + + +typedef struct _BSSID_INFO +{ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct tagSPMKID { + ULONG Length; + ULONG BSSIDInfoCount; + BSSID_INFO BSSIDInfo[MAX_BSSIDINFO_4_PMKID]; +} SPMKID, *PSPMKID; + +typedef struct tagSPMKIDCandidateEvent { + NDIS_802_11_STATUS_TYPE StatusType; + ULONG Version; // Version of the structure + ULONG NumCandidates; // No. of pmkid candidates + PMKID_CANDIDATE CandidateList[MAX_PMKIDLIST]; +} SPMKIDCandidateEvent, DEF* PSPMKIDCandidateEvent; + + +//-- + +//++ 802.11h related +#define MAX_QUIET_COUNT 8 + +typedef struct tagSQuietControl { + BOOL bEnable; + DWORD dwStartTime; + BYTE byPeriod; + WORD wDuration; +} SQuietControl, DEF* PSQuietControl; + +//-- +typedef struct __chip_info_tbl{ + CHIP_TYPE chip_id; + char* name; + int io_size; + int nTxQueue; + U32 flags; +} CHIP_INFO, *PCHIP_INFO; + + +typedef enum { + OWNED_BY_HOST=0, + OWNED_BY_NIC=1 +} DEVICE_OWNER_TYPE, *PDEVICE_OWNER_TYPE; + + +// The receive duplicate detection cache entry +typedef struct tagSCacheEntry{ + WORD wFmSequence; + BYTE abyAddr2[U_ETHER_ADDR_LEN]; +} SCacheEntry, *PSCacheEntry; + + +typedef struct tagSCache{ +/* The receive cache is updated circularly. The next entry to be written is + * indexed by the "InPtr". +*/ + UINT uInPtr; // Place to use next + SCacheEntry asCacheEntry[DUPLICATE_RX_CACHE_LENGTH]; +} SCache, *PSCache; + +#define CB_MAX_RX_FRAG 64 +// DeFragment Control Block, used for collecting fragments prior to reassembly +typedef struct tagSDeFragControlBlock +{ + WORD wSequence; + WORD wFragNum; + BYTE abyAddr2[U_ETHER_ADDR_LEN]; + UINT uLifetime; + struct sk_buff* skb; +#ifdef PRIVATE_OBJ + ref_sk_buff ref_skb; +#endif + PBYTE pbyRxBuffer; + UINT cbFrameLength; + BOOL bInUse; +} SDeFragControlBlock, DEF* PSDeFragControlBlock; + + + + +//flags for options +#define DEVICE_FLAGS_IP_ALIGN 0x00000001UL +#define DEVICE_FLAGS_PREAMBLE_TYPE 0x00000002UL +#define DEVICE_FLAGS_OP_MODE 0x00000004UL +#define DEVICE_FLAGS_PS_MODE 0x00000008UL +#define DEVICE_FLAGS_80211h_MODE 0x00000010UL +#define DEVICE_FLAGS_DiversityANT 0x00000020UL + +//flags for driver status +#define DEVICE_FLAGS_OPENED 0x00010000UL +#define DEVICE_FLAGS_WOL_ENABLED 0x00080000UL +//flags for capbilities +#define DEVICE_FLAGS_TX_ALIGN 0x01000000UL +#define DEVICE_FLAGS_HAVE_CAM 0x02000000UL +#define DEVICE_FLAGS_FLOW_CTRL 0x04000000UL + +//flags for MII status +#define DEVICE_LINK_FAIL 0x00000001UL +#define DEVICE_SPEED_10 0x00000002UL +#define DEVICE_SPEED_100 0x00000004UL +#define DEVICE_SPEED_1000 0x00000008UL +#define DEVICE_DUPLEX_FULL 0x00000010UL +#define DEVICE_AUTONEG_ENABLE 0x00000020UL +#define DEVICE_FORCED_BY_EEPROM 0x00000040UL +//for device_set_media_duplex +#define DEVICE_LINK_CHANGE 0x00000001UL + + +//PLICE_DEBUG-> + + +typedef struct _RxManagementQueue +{ + int packet_num; + int head,tail; + PSRxMgmtPacket Q[NUM]; +} RxManagementQueue,*PSRxManagementQueue; + + + +//PLICE_DEBUG<- + + +typedef struct __device_opt { + int nRxDescs0; //Number of RX descriptors0 + int nRxDescs1; //Number of RX descriptors1 + int nTxDescs[2]; //Number of TX descriptors 0, 1 + int int_works; //interrupt limits + int rts_thresh; //rts threshold + int frag_thresh; + int data_rate; + int channel_num; + int short_retry; + int long_retry; + int bbp_type; + U32 flags; +} OPTIONS, *POPTIONS; + + +typedef struct __device_info { + struct __device_info* next; + struct __device_info* prev; + + struct pci_dev* pcid; + +#if CONFIG_PM + u32 pci_state[16]; +#endif + +// netdev + struct net_device* dev; + struct net_device* next_module; + struct net_device_stats stats; + +//dma addr, rx/tx pool + dma_addr_t pool_dma; + dma_addr_t rd0_pool_dma; + dma_addr_t rd1_pool_dma; + + dma_addr_t td0_pool_dma; + dma_addr_t td1_pool_dma; + + dma_addr_t tx_bufs_dma0; + dma_addr_t tx_bufs_dma1; + dma_addr_t tx_beacon_dma; + + PBYTE tx0_bufs; + PBYTE tx1_bufs; + PBYTE tx_beacon_bufs; + + CHIP_TYPE chip_id; + + U32 PortOffset; + DWORD dwIsr; + U32 memaddr; + U32 ioaddr; + U32 io_size; + + BYTE byRevId; + WORD SubSystemID; + WORD SubVendorID; + + int nTxQueues; + volatile int iTDUsed[TYPE_MAXTD]; + + volatile PSTxDesc apCurrTD[TYPE_MAXTD]; + volatile PSTxDesc apTailTD[TYPE_MAXTD]; + + volatile PSTxDesc apTD0Rings; + volatile PSTxDesc apTD1Rings; + + volatile PSRxDesc aRD0Ring; + volatile PSRxDesc aRD1Ring; + volatile PSRxDesc pCurrRD[TYPE_MAXRD]; + SCache sDupRxCache; + + SDeFragControlBlock sRxDFCB[CB_MAX_RX_FRAG]; + UINT cbDFCB; + UINT cbFreeDFCB; + UINT uCurrentDFCBIdx; + + OPTIONS sOpts; + + U32 flags; + + U32 rx_buf_sz; + int multicast_limit; + BYTE byRxMode; + + spinlock_t lock; +//PLICE_DEBUG-> + struct tasklet_struct RxMngWorkItem; + RxManagementQueue rxManeQueue; +//PLICE_DEBUG<- +//PLICE_DEBUG -> + pid_t MLMEThr_pid; + struct completion notify; + struct semaphore mlme_semaphore; +//PLICE_DEBUG <- + + + U32 rx_bytes; + + // Version control + BYTE byLocalID; + BYTE byRFType; + + BYTE byMaxPwrLevel; + BYTE byZoneType; + BOOL bZoneRegExist; + BYTE byOriginalZonetype; + BYTE abyMacContext[MAC_MAX_CONTEXT_REG]; + BOOL bLinkPass; // link status: OK or fail + BYTE abyCurrentNetAddr[U_ETHER_ADDR_LEN]; + + // Adapter statistics + SStatCounter scStatistic; + // 802.11 counter + SDot11Counters s802_11Counter; + + + // 802.11 management + PSMgmtObject pMgmt; + SMgmtObject sMgmtObj; + + // 802.11 MAC specific + UINT uCurrRSSI; + BYTE byCurrSQ; + + DWORD dwTxAntennaSel; + DWORD dwRxAntennaSel; + BYTE byAntennaCount; + BYTE byRxAntennaMode; + BYTE byTxAntennaMode; + BOOL bTxRxAntInv; + + PBYTE pbyTmpBuff; + UINT uSIFS; //Current SIFS + UINT uDIFS; //Current DIFS + UINT uEIFS; //Current EIFS + UINT uSlot; //Current SlotTime + UINT uCwMin; //Current CwMin + UINT uCwMax; //CwMax is fixed on 1023. + // PHY parameter + BYTE bySIFS; + BYTE byDIFS; + BYTE byEIFS; + BYTE bySlot; + BYTE byCWMaxMin; + CARD_PHY_TYPE eCurrentPHYType; + + + VIA_BB_TYPE byBBType; //0: 11A, 1:11B, 2:11G + VIA_PKT_TYPE byPacketType; //0:11a,1:11b,2:11gb(only CCK in BasicRate),3:11ga(OFDM in Basic Rate) + WORD wBasicRate; + BYTE byACKRate; + BYTE byTopOFDMBasicRate; + BYTE byTopCCKBasicRate; + + BYTE byMinChannel; + BYTE byMaxChannel; + UINT uConnectionRate; + + BYTE byPreambleType; + BYTE byShortPreamble; + + WORD wCurrentRate; + WORD wRTSThreshold; + WORD wFragmentationThreshold; + BYTE byShortRetryLimit; + BYTE byLongRetryLimit; + CARD_OP_MODE eOPMode; + BYTE byOpMode; + BOOL bBSSIDFilter; + WORD wMaxTransmitMSDULifetime; + BYTE abyBSSID[U_ETHER_ADDR_LEN]; + BYTE abyDesireBSSID[U_ETHER_ADDR_LEN]; + WORD wCTSDuration; // update while speed change + WORD wACKDuration; // update while speed change + WORD wRTSTransmitLen; // update while speed change + BYTE byRTSServiceField; // update while speed change + BYTE byRTSSignalField; // update while speed change + + DWORD dwMaxReceiveLifetime; // dot11MaxReceiveLifetime + + BOOL bCCK; + BOOL bEncryptionEnable; + BOOL bLongHeader; + BOOL bShortSlotTime; + BOOL bProtectMode; + BOOL bNonERPPresent; + BOOL bBarkerPreambleMd; + + BYTE byERPFlag; + WORD wUseProtectCntDown; + + BOOL bRadioControlOff; + BOOL bRadioOff; + BOOL bEnablePSMode; + WORD wListenInterval; + BOOL bPWBitOn; + WMAC_POWER_MODE ePSMode; + + + // GPIO Radio Control + BYTE byRadioCtl; + BYTE byGPIO; + BOOL bHWRadioOff; + BOOL bPrvActive4RadioOFF; + BOOL bGPIOBlockRead; + + // Beacon releated + WORD wSeqCounter; + WORD wBCNBufLen; + BOOL bBeaconBufReady; + BOOL bBeaconSent; + BOOL bIsBeaconBufReadySet; + UINT cbBeaconBufReadySetCnt; + BOOL bFixRate; + BYTE byCurrentCh; + UINT uScanTime; + + CMD_STATE eCommandState; + + CMD_CODE eCommand; + BOOL bBeaconTx; + + BOOL bStopBeacon; + BOOL bStopDataPkt; + BOOL bStopTx0Pkt; + UINT uAutoReConnectTime; + + // 802.11 counter + + CMD_ITEM eCmdQueue[CMD_Q_SIZE]; + UINT uCmdDequeueIdx; + UINT uCmdEnqueueIdx; + UINT cbFreeCmdQueue; + BOOL bCmdRunning; + BOOL bCmdClear; + + + + BOOL bRoaming; + //WOW + BYTE abyIPAddr[4]; + + ULONG ulTxPower; + NDIS_802_11_WEP_STATUS eEncryptionStatus; + BOOL bTransmitKey; +//2007-0925-01<Add>by MikeLiu +//mike add :save old Encryption + NDIS_802_11_WEP_STATUS eOldEncryptionStatus; + SKeyManagement sKey; + DWORD dwIVCounter; + + QWORD qwPacketNumber; //For CCMP and TKIP as TSC(6 bytes) + UINT uCurrentWEPMode; + + RC4Ext SBox; + BYTE abyPRNG[WLAN_WEPMAX_KEYLEN+3]; + + BYTE byKeyIndex; + UINT uKeyLength; + BYTE abyKey[WLAN_WEP232_KEYLEN]; + + BOOL bAES; + BYTE byCntMeasure; + + // for AP mode + UINT uAssocCount; + BOOL bMoreData; + + // QoS + BOOL bGrpAckPolicy; + + // for OID_802_11_ASSOCIATION_INFORMATION + BOOL bAssocInfoSet; + + + BYTE byAutoFBCtrl; + + BOOL bTxMICFail; + BOOL bRxMICFail; + + + UINT uRATEIdx; + + + // For Update BaseBand VGA Gain Offset + BOOL bUpdateBBVGA; + UINT uBBVGADiffCount; + BYTE byBBVGANew; + BYTE byBBVGACurrent; + BYTE abyBBVGA[BB_VGA_LEVEL]; + LONG ldBmThreshold[BB_VGA_LEVEL]; + + BYTE byBBPreEDRSSI; + BYTE byBBPreEDIndex; + + BOOL bRadioCmd; + DWORD dwDiagRefCount; + + // For FOE Tuning + BYTE byFOETuning; + + // For Auto Power Tunning + + BYTE byAutoPwrTunning; + SHORT sPSetPointCCK; + SHORT sPSetPointOFDMG; + SHORT sPSetPointOFDMA; + LONG lPFormulaOffset; + SHORT sPThreshold; + CHAR cAdjustStep; + CHAR cMinTxAGC; + + // For RF Power table + BYTE byCCKPwr; + BYTE byOFDMPwrG; + BYTE byCurPwr; + I8 byCurPwrdBm; + BYTE abyCCKPwrTbl[CB_MAX_CHANNEL_24G+1]; + BYTE abyOFDMPwrTbl[CB_MAX_CHANNEL+1]; + I8 abyCCKDefaultPwr[CB_MAX_CHANNEL_24G+1]; + I8 abyOFDMDefaultPwr[CB_MAX_CHANNEL+1]; + I8 abyRegPwr[CB_MAX_CHANNEL+1]; + I8 abyLocalPwr[CB_MAX_CHANNEL+1]; + + + // BaseBand Loopback Use + BYTE byBBCR4d; + BYTE byBBCRc9; + BYTE byBBCR88; + BYTE byBBCR09; + + // command timer + struct timer_list sTimerCommand; +#ifdef TxInSleep + struct timer_list sTimerTxData; + ULONG nTxDataTimeCout; + BOOL fTxDataInSleep; + BOOL IsTxDataTrigger; +#endif + +#ifdef WPA_SM_Transtatus + BOOL fWPA_Authened; //is WPA/WPA-PSK or WPA2/WPA2-PSK authen?? +#endif + BYTE byReAssocCount; //mike add:re-association retry times! + BYTE byLinkWaitCount; + + + BYTE abyNodeName[17]; + + BOOL bDiversityRegCtlON; + BOOL bDiversityEnable; + ULONG ulDiversityNValue; + ULONG ulDiversityMValue; + BYTE byTMax; + BYTE byTMax2; + BYTE byTMax3; + ULONG ulSQ3TH; + +// ANT diversity + ULONG uDiversityCnt; + BYTE byAntennaState; + ULONG ulRatio_State0; + ULONG ulRatio_State1; + + //SQ3 functions for antenna diversity + struct timer_list TimerSQ3Tmax1; + struct timer_list TimerSQ3Tmax2; + struct timer_list TimerSQ3Tmax3; + + + ULONG uNumSQ3[MAX_RATE]; + WORD wAntDiversityMaxRate; + + + SEthernetHeader sTxEthHeader; + SEthernetHeader sRxEthHeader; + BYTE abyBroadcastAddr[U_ETHER_ADDR_LEN]; + BYTE abySNAP_RFC1042[U_ETHER_ADDR_LEN]; + BYTE abySNAP_Bridgetunnel[U_ETHER_ADDR_LEN]; + BYTE abyEEPROM[EEP_MAX_CONTEXT_SIZE]; //DWORD alignment + // Pre-Authentication & PMK cache + SPMKID gsPMKID; + SPMKIDCandidateEvent gsPMKIDCandidate; + + + // for 802.11h + BOOL b11hEnable; + BYTE abyCountryCode[3]; + // for 802.11h DFS + UINT uNumOfMeasureEIDs; + PWLAN_IE_MEASURE_REQ pCurrMeasureEID; + BOOL bMeasureInProgress; + BYTE byOrgChannel; + BYTE byOrgRCR; + DWORD dwOrgMAR0; + DWORD dwOrgMAR4; + BYTE byBasicMap; + BYTE byCCAFraction; + BYTE abyRPIs[8]; + DWORD dwRPIs[8]; + BOOL bChannelSwitch; + BYTE byNewChannel; + BYTE byChannelSwitchCount; + BOOL bQuietEnable; + BOOL bEnableFirstQuiet; + BYTE byQuietStartCount; + UINT uQuietEnqueue; + DWORD dwCurrentQuietEndTime; + SQuietControl sQuiet[MAX_QUIET_COUNT]; + // for 802.11h TPC + BOOL bCountryInfo5G; + BOOL bCountryInfo24G; + + WORD wBeaconInterval; + + //WPA supplicant deamon + struct net_device *wpadev; + BOOL bWPADEVUp; + struct sk_buff *skb; +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +/* + BOOL bwextstep0; + BOOL bwextstep1; + BOOL bwextstep2; + BOOL bwextstep3; + */ + UINT bwextcount; + BOOL bWPASuppWextEnabled; +#endif + + //-- +#ifdef HOSTAP + // user space daemon: hostapd, is used for HOSTAP + BOOL bEnableHostapd; + BOOL bEnable8021x; + BOOL bEnableHostWEP; + struct net_device *apdev; + int (*tx_80211)(struct sk_buff *skb, struct net_device *dev); +#endif + UINT uChannel; + BOOL bMACSuspend; + +#ifdef WIRELESS_EXT + struct iw_statistics wstats; // wireless stats +#endif /* WIRELESS_EXT */ + BOOL bCommit; + +} DEVICE_INFO, *PSDevice; + + +//PLICE_DEBUG-> + + + inline static VOID EnQueue (PSDevice pDevice,PSRxMgmtPacket pRxMgmtPacket) +{ + //printk("Enter EnQueue:tail is %d\n",pDevice->rxManeQueue.tail); + if ((pDevice->rxManeQueue.tail+1) % NUM == pDevice->rxManeQueue.head) + { + //printk("Queue is Full,tail is %d\n",pDevice->rxManeQueue.tail); + return ; + } + else + { + pDevice->rxManeQueue.tail = (pDevice->rxManeQueue.tail+1)% NUM; + pDevice->rxManeQueue.Q[pDevice->rxManeQueue.tail] = pRxMgmtPacket; + pDevice->rxManeQueue.packet_num++; + //printk("packet num is %d\n",pDevice->rxManeQueue.packet_num); + } +} + + + + + inline static PSRxMgmtPacket DeQueue (PSDevice pDevice) +{ + PSRxMgmtPacket pRxMgmtPacket; + if (pDevice->rxManeQueue.tail == pDevice->rxManeQueue.head) + { + printk("Queue is Empty\n"); + return NULL; + } + else + { + int x; + //x=pDevice->rxManeQueue.head = (pDevice->rxManeQueue.head+1)%NUM; + pDevice->rxManeQueue.head = (pDevice->rxManeQueue.head+1)%NUM; + x = pDevice->rxManeQueue.head; + //printk("Enter DeQueue:head is %d\n",x); + pRxMgmtPacket = pDevice->rxManeQueue.Q[x]; + pDevice->rxManeQueue.packet_num--; + return pRxMgmtPacket; + } +} + +VOID InitRxManagementQueue(PSDevice pDevice); + + + +//PLICE_DEBUG<- + + + + + + +inline static BOOL device_get_ip(PSDevice pInfo) { + struct in_device* in_dev=(struct in_device*) pInfo->dev->ip_ptr; + struct in_ifaddr* ifa; + + if (in_dev!=NULL) { + ifa=(struct in_ifaddr*) in_dev->ifa_list; + if (ifa!=NULL) { + memcpy(pInfo->abyIPAddr,&ifa->ifa_address,4); + return TRUE; + } + } + return FALSE; +} + + + +static inline PDEVICE_RD_INFO alloc_rd_info(void) { + PDEVICE_RD_INFO ptr; + if ((ptr = (PDEVICE_RD_INFO)kmalloc((int)sizeof(DEVICE_RD_INFO), (int)GFP_ATOMIC)) == NULL) + return NULL; + else { + memset(ptr,0,sizeof(DEVICE_RD_INFO)); + return ptr; + } +} + +static inline PDEVICE_TD_INFO alloc_td_info(void) { + PDEVICE_TD_INFO ptr; + if ((ptr = (PDEVICE_TD_INFO)kmalloc((int)sizeof(DEVICE_TD_INFO), (int)GFP_ATOMIC))==NULL) + return NULL; + else { + memset(ptr,0,sizeof(DEVICE_TD_INFO)); + return ptr; + } +} + +/*--------------------- Export Functions --------------------------*/ + +BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, UINT uNodeIndex); +BOOL device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF); +int Config_FileOperation(PSDevice pDevice,BOOL fwrite,unsigned char *Parameter); +#endif + + diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c new file mode 100644 index 00000000000..bade552ba73 --- /dev/null +++ b/drivers/staging/vt6655/device_main.c @@ -0,0 +1,4153 @@ +/* + * 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: device_main.c + * + * Purpose: driver entry for initial, open, close, tx and rx. + * + * Author: Lyndon Chen + * + * Date: Jan 8, 2003 + * + * Functions: + * + * device_found1 - module initial (insmod) driver entry + * device_remove1 - module remove entry + * device_init_info - device structure resource allocation function + * device_free_info - device structure resource free function + * device_get_pci_info - get allocated pci io/mem resource + * device_print_info - print out resource + * device_open - allocate dma/descripter resource & initial mac/bbp function + * device_xmit - asynchrous data tx function + * device_intr - interrupt handle function + * device_set_multi - set mac filter + * device_ioctl - ioctl entry + * device_close - shutdown mac/bbp & free dma/descripter resource + * device_rx_srv - rx service function + * device_receive_frame - rx data function + * device_alloc_rx_buf - rx buffer pre-allocated function + * device_alloc_frag_buf - rx fragement pre-allocated function + * device_free_tx_buf - free tx buffer function + * device_free_frag_buf- free de-fragement buffer + * device_dma0_tx_80211- tx 802.11 frame via dma0 + * device_dma0_xmit- tx PS bufferred frame via dma0 + * device_init_rd0_ring- initial rd dma0 ring + * device_init_rd1_ring- initial rd dma1 ring + * device_init_td0_ring- initial tx dma0 ring buffer + * device_init_td1_ring- initial tx dma1 ring buffer + * device_init_registers- initial MAC & BBP & RF internal registers. + * device_init_rings- initial tx/rx ring buffer + * device_init_defrag_cb- initial & allocate de-fragement buffer. + * device_free_rings- free all allocated ring buffer + * device_tx_srv- tx interrupt service function + * + * Revision History: + */ +#undef __NO_VERSION__ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__WROUTE_H__) +#include "wroute.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__IOCTL_H__) +#include "ioctl.h" +#endif +#if !defined(__IWCTL_H__) +#include "iwctl.h" +#endif +#if !defined(__DPC_H__) +#include "dpc.h" +#endif +#if !defined(__DATARATE_H__) +#include "datarate.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif + +#include <linux/delay.h> +#include <linux/kthread.h> +// #ifdef PRIVATE_OBJ +//#if !defined(__DEVICE_EXP_H) +//#include "device_exp.h" +//#endif +//#if !defined(__DEVICE_MODULE_H) +//#include "device_module.h" +//#endif + + +// #endif +//#define DEBUG +/*--------------------- Static Definitions -------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel = MSG_LEVEL_INFO; + +//#define PLICE_DEBUG +// +// Define module options +// +#ifndef PRIVATE_OBJ +MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); +#endif + +//PLICE_DEBUG -> + static int mlme_kill; + //static struct task_struct * mlme_task; +//PLICE_DEBUG <- + +#define DEVICE_PARAM(N,D) +/* + static const int N[MAX_UINTS]=OPTION_DEFAULT;\ + MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\ + MODULE_PARM_DESC(N, D); +*/ + +#define RX_DESC_MIN0 16 +#define RX_DESC_MAX0 128 +#define RX_DESC_DEF0 32 +DEVICE_PARAM(RxDescriptors0,"Number of receive descriptors0"); + +#define RX_DESC_MIN1 16 +#define RX_DESC_MAX1 128 +#define RX_DESC_DEF1 32 +DEVICE_PARAM(RxDescriptors1,"Number of receive descriptors1"); + +#define TX_DESC_MIN0 16 +#define TX_DESC_MAX0 128 +#define TX_DESC_DEF0 32 +DEVICE_PARAM(TxDescriptors0,"Number of transmit descriptors0"); + +#define TX_DESC_MIN1 16 +#define TX_DESC_MAX1 128 +#define TX_DESC_DEF1 64 +DEVICE_PARAM(TxDescriptors1,"Number of transmit descriptors1"); + + +#define IP_ALIG_DEF 0 +/* IP_byte_align[] is used for IP header DWORD byte aligned + 0: indicate the IP header won't be DWORD byte aligned.(Default) . + 1: indicate the IP header will be DWORD byte aligned. + In some enviroment, the IP header should be DWORD byte aligned, + or the packet will be droped when we receive it. (eg: IPVS) +*/ +DEVICE_PARAM(IP_byte_align,"Enable IP header dword aligned"); + + +#define INT_WORKS_DEF 20 +#define INT_WORKS_MIN 10 +#define INT_WORKS_MAX 64 + +DEVICE_PARAM(int_works,"Number of packets per interrupt services"); + +#define CHANNEL_MIN 1 +#define CHANNEL_MAX 14 +#define CHANNEL_DEF 6 + +DEVICE_PARAM(Channel, "Channel number"); + + +/* PreambleType[] is the preamble length used for transmit. + 0: indicate allows long preamble type + 1: indicate allows short preamble type +*/ + +#define PREAMBLE_TYPE_DEF 1 + +DEVICE_PARAM(PreambleType, "Preamble Type"); + + +#define RTS_THRESH_MIN 512 +#define RTS_THRESH_MAX 2347 +#define RTS_THRESH_DEF 2347 + +DEVICE_PARAM(RTSThreshold, "RTS threshold"); + + +#define FRAG_THRESH_MIN 256 +#define FRAG_THRESH_MAX 2346 +#define FRAG_THRESH_DEF 2346 + +DEVICE_PARAM(FragThreshold, "Fragmentation threshold"); + + +#define DATA_RATE_MIN 0 +#define DATA_RATE_MAX 13 +#define DATA_RATE_DEF 13 +/* datarate[] index + 0: indicate 1 Mbps 0x02 + 1: indicate 2 Mbps 0x04 + 2: indicate 5.5 Mbps 0x0B + 3: indicate 11 Mbps 0x16 + 4: indicate 6 Mbps 0x0c + 5: indicate 9 Mbps 0x12 + 6: indicate 12 Mbps 0x18 + 7: indicate 18 Mbps 0x24 + 8: indicate 24 Mbps 0x30 + 9: indicate 36 Mbps 0x48 + 10: indicate 48 Mbps 0x60 + 11: indicate 54 Mbps 0x6c + 12: indicate 72 Mbps 0x90 + 13: indicate auto rate +*/ + +DEVICE_PARAM(ConnectionRate, "Connection data rate"); + +#define OP_MODE_DEF 0 + +DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode "); + +/* OpMode[] is used for transmit. + 0: indicate infrastruct mode used + 1: indicate adhoc mode used + 2: indicate AP mode used +*/ + + +/* PSMode[] + 0: indicate disable power saving mode + 1: indicate enable power saving mode +*/ + +#define PS_MODE_DEF 0 + +DEVICE_PARAM(PSMode, "Power saving mode"); + + +#define SHORT_RETRY_MIN 0 +#define SHORT_RETRY_MAX 31 +#define SHORT_RETRY_DEF 8 + + +DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); + +#define LONG_RETRY_MIN 0 +#define LONG_RETRY_MAX 15 +#define LONG_RETRY_DEF 4 + + +DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); + + +/* BasebandType[] baseband type selected + 0: indicate 802.11a type + 1: indicate 802.11b type + 2: indicate 802.11g type +*/ +#define BBP_TYPE_MIN 0 +#define BBP_TYPE_MAX 2 +#define BBP_TYPE_DEF 2 + +DEVICE_PARAM(BasebandType, "baseband type"); + + + +/* 80211hEnable[] + 0: indicate disable 802.11h + 1: indicate enable 802.11h +*/ + +#define X80211h_MODE_DEF 0 + +DEVICE_PARAM(b80211hEnable, "802.11h mode"); + +/* 80211hEnable[] + 0: indicate disable 802.11h + 1: indicate enable 802.11h +*/ + +#define DIVERSITY_ANT_DEF 0 + +DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode"); + + +// +// Static vars definitions +// + + +#ifndef PRIVATE_OBJ +static int device_nics =0; +static PSDevice pDevice_Infos =NULL; +static struct net_device *root_device_dev = NULL; + +static CHIP_INFO chip_info_table[]= { + { VT3253, "VIA Networking Solomon-A/B/G Wireless LAN Adapter ", + 256, 1, DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN }, + {0,NULL} +}; + +static struct pci_device_id device_id_table[] __devinitdata = { +{ 0x1106, 0x3253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[0]}, +{ 0, } +}; +#endif + +/*--------------------- Static Functions --------------------------*/ + +#ifndef PRIVATE_OBJ + +static int device_found1(struct pci_dev *pcid, const struct pci_device_id *ent); +static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, PCHIP_INFO); +static void device_free_info(PSDevice pDevice); +static BOOL device_get_pci_info(PSDevice, struct pci_dev* pcid); +static void device_print_info(PSDevice pDevice); +static struct net_device_stats *device_get_stats(struct net_device *dev); +static void device_init_diversity_timer(PSDevice pDevice); +static int device_open(struct net_device *dev); +static int device_xmit(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t device_intr(int irq, void*dev_instance); +static void device_set_multi(struct net_device *dev); +static int device_close(struct net_device *dev); +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM +static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); +static int viawget_suspend(struct pci_dev *pcid, u32 state); +static int viawget_resume(struct pci_dev *pcid); +struct notifier_block device_notifier = { + notifier_call: device_notify_reboot, + next: NULL, + priority: 0 +}; +#endif +#endif + +#endif // #ifndef PRIVATE_OBJ + +static void device_init_rd0_ring(PSDevice pDevice); +static void device_init_rd1_ring(PSDevice pDevice); +static void device_init_defrag_cb(PSDevice pDevice); +static void device_init_td0_ring(PSDevice pDevice); +static void device_init_td1_ring(PSDevice pDevice); + +#ifndef PRIVATE_OBJ +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev); +#endif +//2008-0714<Add>by Mike Liu +static BOOL device_release_WPADEV(PSDevice pDevice); + +static int ethtool_ioctl(struct net_device *dev, void *useraddr); +static int device_rx_srv(PSDevice pDevice, UINT uIdx); +static int device_tx_srv(PSDevice pDevice, UINT uIdx); +static BOOL device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pDesc); +static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType); +static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc); +static void device_free_td0_ring(PSDevice pDevice); +static void device_free_td1_ring(PSDevice pDevice); +static void device_free_rd0_ring(PSDevice pDevice); +static void device_free_rd1_ring(PSDevice pDevice); +static void device_free_rings(PSDevice pDevice); +static void device_free_frag_buf(PSDevice pDevice); +static int Config_FileGetParameter(UCHAR *string, UCHAR *dest,UCHAR *source); + + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifndef PRIVATE_OBJ + +static char* get_chip_name(int chip_id) { + int i; + for (i=0;chip_info_table[i].name!=NULL;i++) + if (chip_info_table[i].chip_id==chip_id) + break; + return chip_info_table[i].name; +} + +static void __devexit device_remove1(struct pci_dev *pcid) +{ + PSDevice pDevice=pci_get_drvdata(pcid); + + if (pDevice==NULL) + return; + device_free_info(pDevice); + +} + +#endif +/* +static void +device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) { + if (val==-1) + *opt=def; + else if (val<min || val>max) { + DEVICE_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" , + devname,name, min,max); + *opt=def; + } else { + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n", + devname, name, val); + *opt=val; + } +} + +static void +device_set_bool_opt(PU32 opt, int val,BOOL def,U32 flag, char* name,char* devname) { + (*opt)&=(~flag); + if (val==-1) + *opt|=(def ? flag : 0); + else if (val<0 || val>1) { + DEVICE_PRT(MSG_LEVEL_INFO, KERN_NOTICE + "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name); + *opt|=(def ? flag : 0); + } else { + DEVICE_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n", + devname,name , val ? "TRUE" : "FALSE"); + *opt|=(val ? flag : 0); + } +} +*/ +static void +device_get_options(PSDevice pDevice, int index, char* devname) { + + POPTIONS pOpts = &(pDevice->sOpts); + pOpts->nRxDescs0=RX_DESC_DEF0; + pOpts->nRxDescs1=RX_DESC_DEF1; + pOpts->nTxDescs[0]=TX_DESC_DEF0; + pOpts->nTxDescs[1]=TX_DESC_DEF1; +pOpts->flags|=DEVICE_FLAGS_IP_ALIGN; + pOpts->int_works=INT_WORKS_DEF; + pOpts->rts_thresh=RTS_THRESH_DEF; + pOpts->frag_thresh=FRAG_THRESH_DEF; + pOpts->data_rate=DATA_RATE_DEF; + pOpts->channel_num=CHANNEL_DEF; + +pOpts->flags|=DEVICE_FLAGS_PREAMBLE_TYPE; +pOpts->flags|=DEVICE_FLAGS_OP_MODE; +//pOpts->flags|=DEVICE_FLAGS_PS_MODE; + pOpts->short_retry=SHORT_RETRY_DEF; + pOpts->long_retry=LONG_RETRY_DEF; + pOpts->bbp_type=BBP_TYPE_DEF; +pOpts->flags|=DEVICE_FLAGS_80211h_MODE; +pOpts->flags|=DEVICE_FLAGS_DiversityANT; + + +} + +static void +device_set_options(PSDevice pDevice) { + + BYTE abyBroadcastAddr[U_ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + BYTE abySNAP_RFC1042[U_ETHER_ADDR_LEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + BYTE abySNAP_Bridgetunnel[U_ETHER_ADDR_LEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8}; + + + memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, U_ETHER_ADDR_LEN); + memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, U_ETHER_ADDR_LEN); + memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, U_ETHER_ADDR_LEN); + + pDevice->uChannel = pDevice->sOpts.channel_num; + pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh; + pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh; + pDevice->byShortRetryLimit = pDevice->sOpts.short_retry; + pDevice->byLongRetryLimit = pDevice->sOpts.long_retry; + pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME; + pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0; + pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0; + pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0; + pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0; + pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0; + pDevice->uConnectionRate = pDevice->sOpts.data_rate; + if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = TRUE; + pDevice->byBBType = pDevice->sOpts.bbp_type; + pDevice->byPacketType = pDevice->byBBType; + +//PLICE_DEBUG-> + pDevice->byAutoFBCtrl = AUTO_FB_0; + //pDevice->byAutoFBCtrl = AUTO_FB_1; +//PLICE_DEBUG<- +pDevice->bUpdateBBVGA = TRUE; + pDevice->byFOETuning = 0; + pDevice->wCTSDuration = 0; + pDevice->byPreambleType = 0; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uChannel= %d\n",(INT)pDevice->uChannel); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byOpMode= %d\n",(INT)pDevice->byOpMode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ePSMode= %d\n",(INT)pDevice->ePSMode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" wRTSThreshold= %d\n",(INT)pDevice->wRTSThreshold); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortRetryLimit= %d\n",(INT)pDevice->byShortRetryLimit); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byLongRetryLimit= %d\n",(INT)pDevice->byLongRetryLimit); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byPreambleType= %d\n",(INT)pDevice->byPreambleType); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byShortPreamble= %d\n",(INT)pDevice->byShortPreamble); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" uConnectionRate= %d\n",(INT)pDevice->uConnectionRate); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" byBBType= %d\n",(INT)pDevice->byBBType); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->b11hEnable= %d\n",(INT)pDevice->b11hEnable); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pDevice->bDiversityRegCtlON= %d\n",(INT)pDevice->bDiversityRegCtlON); +} + +static VOID s_vCompleteCurrentMeasure (IN PSDevice pDevice, IN BYTE byResult) +{ + UINT ii; + DWORD dwDuration = 0; + BYTE byRPI0 = 0; + + for(ii=1;ii<8;ii++) { + pDevice->dwRPIs[ii] *= 255; + dwDuration |= *((PWORD) (pDevice->pCurrMeasureEID->sReq.abyDuration)); + dwDuration <<= 10; + pDevice->dwRPIs[ii] /= dwDuration; + pDevice->abyRPIs[ii] = (BYTE) pDevice->dwRPIs[ii]; + byRPI0 += pDevice->abyRPIs[ii]; + } + pDevice->abyRPIs[0] = (0xFF - byRPI0); + + if (pDevice->uNumOfMeasureEIDs == 0) { + VNTWIFIbMeasureReport( pDevice->pMgmt, + TRUE, + pDevice->pCurrMeasureEID, + byResult, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + } else { + VNTWIFIbMeasureReport( pDevice->pMgmt, + FALSE, + pDevice->pCurrMeasureEID, + byResult, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + CARDbStartMeasure (pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs); + } + +} + + + +// +// Initialiation of MAC & BBP registers +// + +static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) +{ + UINT ii; + BYTE byValue; + BYTE byValue1; + BYTE byCCKPwrdBm = 0; + BYTE byOFDMPwrdBm = 0; + INT zonetype=0; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + MACbShutdown(pDevice->PortOffset); + BBvSoftwareReset(pDevice->PortOffset); + + if ((InitType == DEVICE_INIT_COLD) || + (InitType == DEVICE_INIT_DXPL)) { + // Do MACbSoftwareReset in MACvInitialize + MACbSoftwareReset(pDevice->PortOffset); + // force CCK + pDevice->bCCK = TRUE; + pDevice->bAES = FALSE; + pDevice->bProtectMode = FALSE; //Only used in 11g type, sync with ERP IE + pDevice->bNonERPPresent = FALSE; + pDevice->bBarkerPreambleMd = FALSE; + pDevice->wCurrentRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_24M; + pDevice->byTopCCKBasicRate = RATE_1M; + + pDevice->byRevId = 0; //Target to IF pin while programming to RF chip. + + // init MAC + MACvInitialize(pDevice->PortOffset); + + // Get Local ID + VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID)); + + spin_lock_irq(&pDevice->lock); + SROMvReadAllContents(pDevice->PortOffset,pDevice->abyEEPROM); + + spin_unlock_irq(&pDevice->lock); + + // Get Channel range + + pDevice->byMinChannel = 1; + pDevice->byMaxChannel = CB_MAX_CHANNEL; + + // Get Antena + byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA); + if (byValue & EEP_ANTINV) + pDevice->bTxRxAntInv = TRUE; + else + pDevice->bTxRxAntInv = FALSE; +#ifdef PLICE_DEBUG + //printk("init_register:TxRxAntInv is %d,byValue is %d\n",pDevice->bTxRxAntInv,byValue); +#endif + + byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + if (byValue == 0) // if not set default is All + byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); +#ifdef PLICE_DEBUG + //printk("init_register:byValue is %d\n",byValue); +#endif + pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51); + pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52); + pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53); + pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54); + pDevice->ulSQ3TH = 0;//(ULONG) SROMbyReadEmbedded(pDevice->PortOffset, 0x55); + pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56); + + if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { + pDevice->byAntennaCount = 2; + pDevice->byTxAntennaMode = ANT_B; + pDevice->dwTxAntennaSel = 1; + pDevice->dwRxAntennaSel = 1; + if (pDevice->bTxRxAntInv == TRUE) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + // chester for antenna +byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA); + // if (pDevice->bDiversityRegCtlON) + if((byValue1&0x08)==0) + pDevice->bDiversityEnable = FALSE;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50); + else + pDevice->bDiversityEnable = TRUE; +#ifdef PLICE_DEBUG + //printk("aux |main antenna: RxAntennaMode is %d\n",pDevice->byRxAntennaMode); +#endif + } else { + pDevice->bDiversityEnable = FALSE; + pDevice->byAntennaCount = 1; + pDevice->dwTxAntennaSel = 0; + pDevice->dwRxAntennaSel = 0; + if (byValue & EEP_ANTENNA_AUX) { + pDevice->byTxAntennaMode = ANT_A; + if (pDevice->bTxRxAntInv == TRUE) + pDevice->byRxAntennaMode = ANT_B; + else + pDevice->byRxAntennaMode = ANT_A; + } else { + pDevice->byTxAntennaMode = ANT_B; + if (pDevice->bTxRxAntInv == TRUE) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + } + } +#ifdef PLICE_DEBUG + //printk("init registers: TxAntennaMode is %d\n",pDevice->byTxAntennaMode); +#endif + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n", + pDevice->bDiversityEnable,(int)pDevice->ulDiversityNValue,(int)pDevice->ulDiversityMValue,pDevice->byTMax,pDevice->byTMax2); + +//#ifdef ZoneType_DefaultSetting +//2008-8-4 <add> by chester +//zonetype initial + pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + if((zonetype=Config_FileOperation(pDevice,FALSE,NULL)) >= 0) { //read zonetype file ok! + if ((zonetype == 0)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] !=0x00)){ //for USA + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :USA\n"); + } + else if((zonetype == 1)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x01)){ //for Japan + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + } + else if((zonetype == 2)&& + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE]!=0x02)){ //for Europe + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Init Zone Type :Europe\n"); + } + +else +{ + if(zonetype!=pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) + printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n",zonetype,pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); + else + printk("Read Zonetype file sucess,use default zonetype setting[%02x]\n",zonetype); + } + } + else + printk("Read Zonetype file fail,use default zonetype setting[%02x]\n",SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE)); + + // Get RFType + pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE); + + if ((pDevice->byRFType & RF_EMU) != 0) { + // force change RevID for VT3253 emu + pDevice->byRevId = 0x80; + } + + pDevice->byRFType &= RF_MASK; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType); + + if (pDevice->bZoneRegExist == FALSE) { + pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType); + + //Init RF module + RFbInit(pDevice); + + //Get Desire Power Value + pDevice->byCurPwr = 0xFF; + pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK); + pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG); + //byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm); + + //byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm); +//printk("CCKPwrdBm is 0x%x,byOFDMPwrdBm is 0x%x\n",byCCKPwrdBm,byOFDMPwrdBm); + // Load power Table + + + for (ii=0;ii<CB_MAX_CHANNEL_24G;ii++) { + pDevice->abyCCKPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (BYTE)(ii + EEP_OFS_CCK_PWR_TBL)); + if (pDevice->abyCCKPwrTbl[ii+1] == 0) { + pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr; + } + pDevice->abyOFDMPwrTbl[ii+1] = SROMbyReadEmbedded(pDevice->PortOffset, (BYTE)(ii + EEP_OFS_OFDM_PWR_TBL)); + if (pDevice->abyOFDMPwrTbl[ii+1] == 0) { + pDevice->abyOFDMPwrTbl[ii+1] = pDevice->byOFDMPwrG; + } + pDevice->abyCCKDefaultPwr[ii+1] = byCCKPwrdBm; + pDevice->abyOFDMDefaultPwr[ii+1] = byOFDMPwrdBm; + } + //2008-8-4 <add> by chester + //recover 12,13 ,14channel for EUROPE by 11 channel + if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&& + (pDevice->byOriginalZonetype == ZoneType_USA)) { + for(ii=11;ii<14;ii++) { + pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; + pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; + + } + } + + + // Load OFDM A Power Table + for (ii=0;ii<CB_MAX_CHANNEL_5G;ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL + pDevice->abyOFDMPwrTbl[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (BYTE)(ii + EEP_OFS_OFDMA_PWR_TBL)); + pDevice->abyOFDMDefaultPwr[ii+CB_MAX_CHANNEL_24G+1] = SROMbyReadEmbedded(pDevice->PortOffset, (BYTE)(ii + EEP_OFS_OFDMA_PWR_dBm)); + } + CARDvInitChannelTable((PVOID)pDevice); + + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN)); + MACvSelectPage0(pDevice->PortOffset); + } + + + // use relative tx timeout and 802.11i D4 + MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); + + // set performance parameter by registry + MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit); + MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit); + + // reset TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); + // enable TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + + // initialize BBP registers + BBbVT3253Init(pDevice); + + if (pDevice->bUpdateBBVGA) { + pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + pDevice->byBBVGANew = pDevice->byBBVGACurrent; + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + } +#ifdef PLICE_DEBUG + //printk("init registers:RxAntennaMode is %x,TxAntennaMode is %x\n",pDevice->byRxAntennaMode,pDevice->byTxAntennaMode); +#endif + BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode); + BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode); + + pDevice->byCurrentCh = 0; + + //pDevice->NetworkType = Ndis802_11Automode; + // Set BB and packet type at the same time. + // Set Short Slot Time, xIFS, and RSPINF. + if (pDevice->uConnectionRate == RATE_AUTO) { + pDevice->wCurrentRate = RATE_54M; + } else { + pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; + } + + // default G Mode + VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G); + VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO); + + pDevice->bRadioOff = FALSE; + + pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL); + pDevice->bHWRadioOff = FALSE; + + if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) { + // Get GPIO + MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); +//2008-4-14 <add> by chester for led issue + #ifdef FOR_LED_ON_NOTEBOOK +if (BITbIsBitOn(pDevice->byGPIO,GPIO0_DATA)){pDevice->bHWRadioOff = TRUE;} +if (BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA)){pDevice->bHWRadioOff = FALSE;} + + } + if ( (pDevice->bRadioControlOff == TRUE)) { + CARDbRadioPowerOff(pDevice); + } +else CARDbRadioPowerOn(pDevice); +#else + if ((BITbIsBitOn(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOff(pDevice->byRadioCtl, EEP_RADIOCTL_INV)) || + (BITbIsBitOff(pDevice->byGPIO,GPIO0_DATA) && BITbIsBitOn(pDevice->byRadioCtl, EEP_RADIOCTL_INV))) { + pDevice->bHWRadioOff = TRUE; + } + } + if ((pDevice->bHWRadioOff == TRUE) || (pDevice->bRadioControlOff == TRUE)) { + CARDbRadioPowerOff(pDevice); + } + +#endif + } + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + // get Permanent network address + SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pDevice->abyCurrentNetAddr[0], + pDevice->abyCurrentNetAddr[1], + pDevice->abyCurrentNetAddr[2], + pDevice->abyCurrentNetAddr[3], + pDevice->abyCurrentNetAddr[4], + pDevice->abyCurrentNetAddr[5]); + + + // reset Tx pointer + CARDvSafeResetRx(pDevice); + // reset Rx pointer + CARDvSafeResetTx(pDevice); + + if (pDevice->byLocalID <= REV_ID_VT3253_A1) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR); + } + + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + + // Turn On Rx DMA + MACvReceive0(pDevice->PortOffset); + MACvReceive1(pDevice->PortOffset); + + // start the adapter + MACvStart(pDevice->PortOffset); + + netif_stop_queue(pDevice->dev); + + +} + + + +static VOID device_init_diversity_timer(PSDevice pDevice) { + + init_timer(&pDevice->TimerSQ3Tmax1); + pDevice->TimerSQ3Tmax1.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax2.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax3); + pDevice->TimerSQ3Tmax3.data = (ULONG)pDevice; + pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack; + pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); + + return; +} + + +static BOOL device_release_WPADEV(PSDevice pDevice) +{ + viawget_wpa_header *wpahdr; + int ii=0; + // wait_queue_head_t Set_wait; + //send device close to wpa_supplicnat layer + if (pDevice->bWPADEVUp==TRUE) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_DEVICECLOSE_MSG; + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; +//2008-4-3 modify by Chester for wpa +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw = pDevice->skb->data; +#endif + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + + //wait release WPADEV + // init_waitqueue_head(&Set_wait); + // wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ); //1s wait + while((pDevice->bWPADEVUp==TRUE)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ/20); //wait 50ms + ii++; + if(ii>20) + break; + } + }; + return TRUE; +} + + +#ifndef PRIVATE_OBJ + +static int +device_found1(struct pci_dev *pcid, const struct pci_device_id *ent) +{ + static BOOL bFirst = TRUE; + struct net_device* dev = NULL; + PCHIP_INFO pChip_info = (PCHIP_INFO)ent->driver_data; + PSDevice pDevice; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + int rc; +#endif +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + // BYTE fake_mac[U_ETHER_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01};//fake MAC address +//#endif + if (device_nics ++>= MAX_UINTS) { + printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics); + return -ENODEV; + } + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + dev = alloc_etherdev(0); +#else + dev = init_etherdev(dev, 0); +#endif + + if (dev == NULL) { + printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n"); + return -ENODEV; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + // Chain it all together + // SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pcid->dev); +#endif + + if (bFirst) { + printk(KERN_NOTICE "%s Ver. %s\n",DEVICE_FULL_DRV_NAM, DEVICE_VERSION); + printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); + bFirst=FALSE; + } + + if (!device_init_info(pcid, &pDevice, pChip_info)) { + return -ENOMEM; + } + pDevice->dev = dev; + pDevice->next_module = root_device_dev; + root_device_dev = dev; + dev->priv = pDevice; + dev->irq = pcid->irq; + + if (pci_enable_device(pcid)) { + device_free_info(pDevice); + return -ENODEV; + } +#ifdef DEBUG + printk("Before get pci_info memaddr is %x\n",pDevice->memaddr); +#endif + if (device_get_pci_info(pDevice,pcid) == FALSE) { + printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n"); + device_free_info(pDevice); + return -ENODEV; + } + +#if 1 + +#ifdef DEBUG + + //pci_read_config_byte(pcid, PCI_BASE_ADDRESS_0, &pDevice->byRevId); + printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n",pDevice->memaddr,pDevice->ioaddr,pDevice->io_size); + { + int i; + U32 bar,len; + u32 address[] = { + PCI_BASE_ADDRESS_0, + PCI_BASE_ADDRESS_1, + PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, + PCI_BASE_ADDRESS_4, + PCI_BASE_ADDRESS_5, + 0}; + for (i=0;address[i];i++) + { + //pci_write_config_dword(pcid,address[i], 0xFFFFFFFF); + pci_read_config_dword(pcid, address[i], &bar); + printk("bar %d is %x\n",i,bar); + if (!bar) + { + printk("bar %d not implemented\n",i); + continue; + } + if (bar & PCI_BASE_ADDRESS_SPACE_IO) { + /* This is IO */ + + len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); + len = len & ~(len - 1); + + printk("IO space: len in IO %x, BAR %d\n", len, i); + } + else + { + len = bar & 0xFFFFFFF0; + len = ~len + 1; + + printk("len in MEM %x, BAR %d\n", len, i); + } + } + } +#endif + + +#endif + +#ifdef DEBUG + //return 0 ; +#endif + pDevice->PortOffset = (DWORD)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size); + //pDevice->PortOffset = (DWORD)ioremap(pDevice->ioaddr & PCI_BASE_ADDRESS_IO_MASK, pDevice->io_size); + + if(pDevice->PortOffset == 0) { + printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n"); + device_free_info(pDevice); + return -ENODEV; + } + + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + rc = pci_request_regions(pcid, DEVICE_NAME); + if (rc) { + printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n"); + device_free_info(pDevice); + return -ENODEV; + } +#else + if (check_region(pDevice->ioaddr, pDevice->io_size)) { + printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n"); + device_free_info(pDevice); + return -ENODEV; + } + request_region(pDevice->ioaddr, pDevice->io_size, DEVICE_NAME); +#endif + + dev->base_addr = pDevice->ioaddr; +#ifdef PLICE_DEBUG + BYTE value; + + VNSvInPortB(pDevice->PortOffset+0x4F, &value); + printk("Before write: value is %x\n",value); + //VNSvInPortB(pDevice->PortOffset+0x3F, 0x00); + VNSvOutPortB(pDevice->PortOffset,value); + VNSvInPortB(pDevice->PortOffset+0x4F, &value); + printk("After write: value is %x\n",value); +#endif + + + +#ifdef IO_MAP + pDevice->PortOffset = pDevice->ioaddr; +#endif + // do reset + if (!MACbSoftwareReset(pDevice->PortOffset)) { + printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n"); + device_free_info(pDevice); + return -ENODEV; + } + // initial to reload eeprom + MACvInitialize(pDevice->PortOffset); + MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr); + + device_get_options(pDevice, device_nics-1, dev->name); + device_set_options(pDevice); + //Mask out the options cannot be set to the chip + pDevice->sOpts.flags &= pChip_info->flags; + + //Enable the chip specified capbilities + pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL); + pDevice->tx_80211 = device_dma0_tx_80211; + pDevice->sMgmtObj.pAdapter = (PVOID)pDevice; + pDevice->pMgmt = &(pDevice->sMgmtObj); + + dev->irq = pcid->irq; + dev->open = device_open; + dev->hard_start_xmit = device_xmit; + dev->stop = device_close; + dev->get_stats = device_get_stats; + dev->set_multicast_list = device_set_multi; + dev->do_ioctl = device_ioctl; + +#ifdef WIRELESS_EXT +//Einsn Modify for ubuntu-7.04 +// dev->wireless_handlers->get_wireless_stats = iwctl_get_wireless_stats; +#if WIRELESS_EXT > 12 + dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def; +// netdev->wireless_handlers = NULL; +#endif /* WIRELESS_EXT > 12 */ +#endif /* WIRELESS_EXT */ + + // #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + // memcpy(pDevice->dev->dev_addr, fake_mac, U_ETHER_ADDR_LEN); //use fake mac address + // #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + rc = register_netdev(dev); + if (rc) + { + printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n"); + device_free_info(pDevice); + return -ENODEV; + } +#endif +//2008-07-21-01<Add>by MikeLiu +//register wpadev + if(wpa_set_wpadev(pDevice, 1)!=0) { + printk("Fail to Register WPADEV?\n"); + unregister_netdev(pDevice->dev); + free_netdev(dev); + kfree(pDevice); + } + device_print_info(pDevice); + pci_set_drvdata(pcid, pDevice); + return 0; + +} + +static void device_print_info(PSDevice pDevice) +{ + struct net_device* dev=pDevice->dev; + + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id)); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + dev->name, + dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], + dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); +#ifdef IO_MAP + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx ",(ULONG) pDevice->ioaddr); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq); +#else + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx Mem=0x%lx ",(ULONG) pDevice->ioaddr,(ULONG) pDevice->PortOffset); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq); +#endif + +} + +static BOOL device_init_info(struct pci_dev* pcid, PSDevice* ppDevice, + PCHIP_INFO pChip_info) { + + PSDevice p; + + *ppDevice = kmalloc(sizeof(DEVICE_INFO),GFP_ATOMIC); + + if (*ppDevice == NULL) + return FALSE; + + memset(*ppDevice,0,sizeof(DEVICE_INFO)); + + if (pDevice_Infos == NULL) { + pDevice_Infos =*ppDevice; + } + else { + for (p=pDevice_Infos;p->next!=NULL;p=p->next) + do {} while (0); + p->next = *ppDevice; + (*ppDevice)->prev = p; + } + + (*ppDevice)->pcid = pcid; + (*ppDevice)->chip_id = pChip_info->chip_id; + (*ppDevice)->io_size = pChip_info->io_size; + (*ppDevice)->nTxQueues = pChip_info->nTxQueue; + (*ppDevice)->multicast_limit =32; + + spin_lock_init(&((*ppDevice)->lock)); + + return TRUE; +} + +static BOOL device_get_pci_info(PSDevice pDevice, struct pci_dev* pcid) { + + U16 pci_cmd; + U8 b; + UINT cis_addr; +#ifdef PLICE_DEBUG + BYTE pci_config[256]; + BYTE value =0x00; + int ii,j; + U16 max_lat=0x0000; + memset(pci_config,0x00,256); +#endif + + pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId); + pci_read_config_word(pcid, PCI_SUBSYSTEM_ID,&pDevice->SubSystemID); + pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID); + pci_read_config_word(pcid, PCI_COMMAND, (u16 *) & (pci_cmd)); + + pci_set_master(pcid); + + pDevice->memaddr = pci_resource_start(pcid,0); + pDevice->ioaddr = pci_resource_start(pcid,1); + +#ifdef DEBUG +// pDevice->ioaddr = pci_resource_start(pcid, 0); +// pDevice->memaddr = pci_resource_start(pcid,1); +#endif + + cis_addr = pci_resource_start(pcid,2); + + pDevice->pcid = pcid; + + pci_read_config_byte(pcid, PCI_REG_COMMAND, &b); + pci_write_config_byte(pcid, PCI_REG_COMMAND, (b|COMMAND_BUSM)); + +#ifdef PLICE_DEBUG + //pci_read_config_word(pcid,PCI_REG_MAX_LAT,&max_lat); + //printk("max lat is %x,SubSystemID is %x\n",max_lat,pDevice->SubSystemID); + //for (ii=0;ii<0xFF;ii++) + //pci_read_config_word(pcid,PCI_REG_MAX_LAT,&max_lat); + //max_lat = 0x20; + //pci_write_config_word(pcid,PCI_REG_MAX_LAT,max_lat); + //pci_read_config_word(pcid,PCI_REG_MAX_LAT,&max_lat); + //printk("max lat is %x\n",max_lat); + + for (ii=0;ii<0xFF;ii++) + { + pci_read_config_byte(pcid,ii,&value); + pci_config[ii] = value; + } + for (ii=0,j=1;ii<0x100;ii++,j++) + { + if (j %16 == 0) + { + printk("%x:",pci_config[ii]); + printk("\n"); + } + else + { + printk("%x:",pci_config[ii]); + } + } +#endif + return TRUE; +} + +static void device_free_info(PSDevice pDevice) { + PSDevice ptr; + struct net_device* dev=pDevice->dev; + + ASSERT(pDevice); +//2008-0714-01<Add>by chester +device_release_WPADEV(pDevice); + +//2008-07-21-01<Add>by MikeLiu +//unregister wpadev + if(wpa_set_wpadev(pDevice, 0)!=0) + printk("unregister wpadev fail?\n"); + + if (pDevice_Infos==NULL) + return; + + for (ptr=pDevice_Infos;ptr && (ptr!=pDevice);ptr=ptr->next) + do {} while (0); + + if (ptr==pDevice) { + if (ptr==pDevice_Infos) + pDevice_Infos=ptr->next; + else + ptr->prev->next=ptr->next; + } + else { + DEVICE_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n"); + return; + } +#ifdef HOSTAP + if (dev) + hostap_set_hostapd(pDevice, 0, 0); +#endif + if (dev) + unregister_netdev(dev); + + if (pDevice->PortOffset) + iounmap((PVOID)pDevice->PortOffset); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + if (pDevice->pcid) + pci_release_regions(pDevice->pcid); + if (dev) + free_netdev(dev); +#else + if (pDevice->ioaddr) + release_region(pDevice->ioaddr,pDevice->io_size); + if (dev) + kfree(dev); +#endif + + if (pDevice->pcid) { + pci_set_drvdata(pDevice->pcid,NULL); + } + kfree(pDevice); + +} +#endif// ifndef PRIVATE_OBJ + +static BOOL device_init_rings(PSDevice pDevice) { + void* vir_pool; + + + /*allocate all RD/TD rings a single pool*/ + vir_pool = pci_alloc_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), + &pDevice->pool_dma); + + if (vir_pool == NULL) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name); + return FALSE; + } + + memset(vir_pool, 0, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) + ); + + pDevice->aRD0Ring = vir_pool; + pDevice->aRD1Ring = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); + + + pDevice->rd0_pool_dma = pDevice->pool_dma; + pDevice->rd1_pool_dma = pDevice->rd0_pool_dma + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); + + pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + &pDevice->tx_bufs_dma0); + + if (pDevice->tx0_bufs == NULL) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name); + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), + vir_pool, pDevice->pool_dma + ); + return FALSE; + } + + memset(pDevice->tx0_bufs, 0, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE + ); + + pDevice->td0_pool_dma = pDevice->rd1_pool_dma + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); + + pDevice->td1_pool_dma = pDevice->td0_pool_dma + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); + + + // vir_pool: pvoid type + pDevice->apTD0Rings = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); + + pDevice->apTD1Rings = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); + + + pDevice->tx1_bufs = pDevice->tx0_bufs + + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; + + + pDevice->tx_beacon_bufs = pDevice->tx1_bufs + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; + + pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs + + CB_BEACON_BUF_SIZE; + + pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 + + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; + + + pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; + + + return TRUE; +} + +static void device_free_rings(PSDevice pDevice) { + + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) + , + pDevice->aRD0Ring, pDevice->pool_dma + ); + + if (pDevice->tx0_bufs) + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + pDevice->tx0_bufs, pDevice->tx_bufs_dma0 + ); +} + +static void device_init_rd0_ring(PSDevice pDevice) { + int i; + dma_addr_t curr = pDevice->rd0_pool_dma; + PSRxDesc pDesc; + + /* Init the RD0 ring entries */ + for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) { + pDesc = &(pDevice->aRD0Ring[i]); + pDesc->pRDInfo = alloc_rd_info(); + ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n", + pDevice->dev->name); + } + pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]); + pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); + } + + pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma); + pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]); +} + + +static void device_init_rd1_ring(PSDevice pDevice) { + int i; + dma_addr_t curr = pDevice->rd1_pool_dma; + PSRxDesc pDesc; + + /* Init the RD1 ring entries */ + for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) { + pDesc = &(pDevice->aRD1Ring[i]); + pDesc->pRDInfo = alloc_rd_info(); + ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n", + pDevice->dev->name); + } + pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]); + pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); + } + + pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma); + pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]); +} + + +static void device_init_defrag_cb(PSDevice pDevice) { + int i; + PSDeFragControlBlock pDeF; + + /* Init the fragment ctl entries */ + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + pDeF = &(pDevice->sRxDFCB[i]); + if (!device_alloc_frag_buf(pDevice, pDeF)) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc frag bufs\n", + pDevice->dev->name); + }; + } + pDevice->cbDFCB = CB_MAX_RX_FRAG; + pDevice->cbFreeDFCB = pDevice->cbDFCB; +} + + + + +static void device_free_rd0_ring(PSDevice pDevice) { + int i; + + for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) { + PSRxDesc pDesc =&(pDevice->aRD0Ring[i]); + PDEVICE_RD_INFO pRDInfo =pDesc->pRDInfo; + + pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma, + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); + + dev_kfree_skb(pRDInfo->skb); + + kfree((PVOID)pDesc->pRDInfo); + } + +} + +static void device_free_rd1_ring(PSDevice pDevice) { + int i; + + + for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) { + PSRxDesc pDesc=&(pDevice->aRD1Ring[i]); + PDEVICE_RD_INFO pRDInfo=pDesc->pRDInfo; + + pci_unmap_single(pDevice->pcid,pRDInfo->skb_dma, + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); + + dev_kfree_skb(pRDInfo->skb); + + kfree((PVOID)pDesc->pRDInfo); + } + +} + +static void device_free_frag_buf(PSDevice pDevice) { + PSDeFragControlBlock pDeF; + int i; + + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + + pDeF = &(pDevice->sRxDFCB[i]); + + if (pDeF->skb) + dev_kfree_skb(pDeF->skb); + + } + +} + +static void device_init_td0_ring(PSDevice pDevice) { + int i; + dma_addr_t curr; + PSTxDesc pDesc; + + curr = pDevice->td0_pool_dma; + for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) { + pDesc = &(pDevice->apTD0Rings[i]); + pDesc->pTDInfo = alloc_td_info(); + ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { + pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ; + pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ; + } + pDesc->next =&(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]); + pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); + } + + pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma); + pDevice->apTailTD[0] = pDevice->apCurrTD[0] =&(pDevice->apTD0Rings[0]); + +} + +static void device_init_td1_ring(PSDevice pDevice) { + int i; + dma_addr_t curr; + PSTxDesc pDesc; + + /* Init the TD ring entries */ + curr=pDevice->td1_pool_dma; + for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr+=sizeof(STxDesc)) { + pDesc=&(pDevice->apTD1Rings[i]); + pDesc->pTDInfo = alloc_td_info(); + ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { + pDesc->pTDInfo->buf=pDevice->tx1_bufs+(i)*PKT_BUF_SZ; + pDesc->pTDInfo->buf_dma=pDevice->tx_bufs_dma1+(i)*PKT_BUF_SZ; + } + pDesc->next=&(pDevice->apTD1Rings[(i+1) % pDevice->sOpts.nTxDescs[1]]); + pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); + } + + pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma); + pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]); +} + + + +static void device_free_td0_ring(PSDevice pDevice) { + int i; + for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) { + PSTxDesc pDesc=&(pDevice->apTD0Rings[i]); + PDEVICE_TD_INFO pTDInfo=pDesc->pTDInfo; + + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) + pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma, + pTDInfo->skb->len, PCI_DMA_TODEVICE); + + if (pTDInfo->skb) + dev_kfree_skb(pTDInfo->skb); + + kfree((PVOID)pDesc->pTDInfo); + } +} + +static void device_free_td1_ring(PSDevice pDevice) { + int i; + + for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) { + PSTxDesc pDesc=&(pDevice->apTD1Rings[i]); + PDEVICE_TD_INFO pTDInfo=pDesc->pTDInfo; + + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) + pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, + pTDInfo->skb->len, PCI_DMA_TODEVICE); + + if (pTDInfo->skb) + dev_kfree_skb(pTDInfo->skb); + + kfree((PVOID)pDesc->pTDInfo); + } + +} + + + +/*-----------------------------------------------------------------*/ + +static int device_rx_srv(PSDevice pDevice, UINT uIdx) { + PSRxDesc pRD; + int works = 0; + + + for (pRD = pDevice->pCurrRD[uIdx]; + pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST; + pRD = pRD->next) { +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works); + if (works++>15) + break; + if (device_receive_frame(pDevice, pRD)) { + if (!device_alloc_rx_buf(pDevice,pRD)) { + DEVICE_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: can not allocate rx buf\n", pDevice->dev->name); + break; + } + } + pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; +#ifdef PRIVATE_OBJ + ref_set_rx_jiffies(pDevice->dev); +#else + pDevice->dev->last_rx = jiffies; +#endif + } + + pDevice->pCurrRD[uIdx]=pRD; + + return works; +} + + +static BOOL device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) { + + PDEVICE_RD_INFO pRDInfo=pRD->pRDInfo; + +#ifdef PRIVATE_OBJ + + pRDInfo->skb=dev_alloc_skb(pDevice->rx_buf_sz); + if (pRDInfo->skb==NULL) + return FALSE; + ref_skb_remap(pDevice->dev, &(pRDInfo->ref_skb), pRDInfo->skb); + pRDInfo->skb_dma = pci_map_single(pDevice->pcid, pRDInfo->ref_skb.tail, pDevice->rx_buf_sz, + PCI_DMA_FROMDEVICE); +#else + + pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); +#ifdef PLICE_DEBUG + //printk("device_alloc_rx_buf:skb is %x\n",pRDInfo->skb); +#endif + if (pRDInfo->skb==NULL) + return FALSE; + ASSERT(pRDInfo->skb); + pRDInfo->skb->dev = pDevice->dev; + pRDInfo->skb_dma = pci_map_single(pDevice->pcid, pRDInfo->skb->tail, pDevice->rx_buf_sz, + PCI_DMA_FROMDEVICE); +#endif + *((PU32) &(pRD->m_rd0RD0)) = 0; + + pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz); + pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; + pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz); + pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma); + + return TRUE; +} + + + +BOOL device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) { + +#ifdef PRIVATE_OBJ + + pDeF->skb=dev_alloc_skb(pDevice->rx_buf_sz); + if (pDeF->skb==NULL) + return FALSE; + ref_skb_remap(pDevice->dev, &(pDeF->ref_skb), pDeF->skb); + +#else + pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDeF->skb == NULL) + return FALSE; + ASSERT(pDeF->skb); + pDeF->skb->dev = pDevice->dev; +#endif + + return TRUE; +} + + + +static int device_tx_srv(PSDevice pDevice, UINT uIdx) { + PSTxDesc pTD; + BOOL bFull=FALSE; + int works = 0; + BYTE byTsr0; + BYTE byTsr1; + UINT uFrameSize, uFIFOHeaderSize; + PSTxBufHead pTxBufHead; + struct net_device_stats* pStats = &pDevice->stats; + struct sk_buff* skb; + UINT uNodeIndex; + PSMgmtObject pMgmt = pDevice->pMgmt; +#ifdef PRIVATE_OBJ + ref_sk_buff ref_skb; +#endif + + + for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] >0; pTD = pTD->next) { + + if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC) + break; + if (works++>15) + break; + + byTsr0 = pTD->m_td0TD0.byTSR0; + byTsr1 = pTD->m_td0TD0.byTSR1; + + //Only the status of first TD in the chain is correct + if (pTD->m_td1TD1.byTCR & TCR_STP) { + + if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) { + uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength; + uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize; + pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf); +#ifdef PRIVATE_OBJ + ref_skb_remap(pDevice->dev, &ref_skb, pTD->pTDInfo->skb); +#endif + // Update the statistics based on the Transmit status + // now, we DO'NT check TSR0_CDH + + STAvUpdateTDStatCounter(&pDevice->scStatistic, + byTsr0, byTsr1, + (PBYTE)(pTD->pTDInfo->buf + uFIFOHeaderSize), + uFrameSize, uIdx); + + + BSSvUpdateNodeTxCounter(pDevice, + byTsr0, byTsr1, + (PBYTE)(pTD->pTDInfo->buf), + uFIFOHeaderSize + ); + + if (BITbIsBitOff(byTsr1, TSR1_TERR)) { + if (byTsr0 != 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n", + (INT)uIdx, byTsr1, byTsr0); + } + if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) { + pDevice->s802_11Counter.TransmittedFragmentCount ++; + } + pStats->tx_packets++; +#ifdef PRIVATE_OBJ + pStats->tx_bytes += *(ref_skb.len); +#else + pStats->tx_bytes += pTD->pTDInfo->skb->len; +#endif + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n", + (INT)uIdx, byTsr1, byTsr0); + pStats->tx_errors++; + pStats->tx_dropped++; + } + } + + if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { + if (pDevice->bEnableHostapd) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n"); +#ifdef PRIVATE_OBJ + ref_skb_remap(pDevice->apdev, &(ref_skb), pTD->pTDInfo->skb); + ref_skb.mac.raw = ref_skb.data; + *(ref_skb.pkt_type) = PACKET_OTHERHOST; + //*(ref_skb.protocol) = htons(ETH_P_802_2); + memset(ref_skb.cb, 0, sizeof(ref_skb.cb)); + netif_rx(ref_skb.skb); +#else + skb = pTD->pTDInfo->skb; + skb->dev = pDevice->apdev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + skb->pkt_type = PACKET_OTHERHOST; + //skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +#endif + } + } + + if (BITbIsBitOn(byTsr1, TSR1_TERR)) { + if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", + (INT)uIdx, byTsr1, byTsr0); + } + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", +// (INT)uIdx, byTsr1, byTsr0); + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && + (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) { + WORD wAID; + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + + skb = pTD->pTDInfo->skb; + if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data), &uNodeIndex)) { + if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); + pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; + // set tx map + wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n" + ,(INT)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt); + pStats->tx_errors--; + pStats->tx_dropped--; + } + } + } + } + device_free_tx_buf(pDevice,pTD); + pDevice->iTDUsed[uIdx]--; + } + } + + + if (uIdx == TYPE_AC0DMA) { + // RESERV_AC0DMA reserved for relay + + if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) { + bFull = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]); + } + if (netif_queue_stopped(pDevice->dev) && (bFull==FALSE)){ + netif_wake_queue(pDevice->dev); + } + } + + + pDevice->apTailTD[uIdx] = pTD; + + return works; +} + + +static void device_error(PSDevice pDevice, WORD status) { + + if (status & ISR_FETALERR) { + DEVICE_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: Hardware fatal error.\n", + pDevice->dev->name); + netif_stop_queue(pDevice->dev); + del_timer(&pDevice->sTimerCommand); + del_timer(&(pDevice->pMgmt->sTimerSecondCallback)); + pDevice->bCmdRunning = FALSE; + MACbShutdown(pDevice->PortOffset); + return; + } + +} + +static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc) { + PDEVICE_TD_INFO pTDInfo=pDesc->pTDInfo; + struct sk_buff* skb=pTDInfo->skb; + + // pre-allocated buf_dma can't be unmapped. + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) { + pci_unmap_single(pDevice->pcid,pTDInfo->skb_dma,skb->len, + PCI_DMA_TODEVICE); + } + + if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) + dev_kfree_skb_irq(skb); + + pTDInfo->skb_dma = 0; + pTDInfo->skb = 0; + pTDInfo->byFlags = 0; +} + + + +//PLICE_DEBUG -> +VOID InitRxManagementQueue(PSDevice pDevice) +{ + pDevice->rxManeQueue.packet_num = 0; + pDevice->rxManeQueue.head = pDevice->rxManeQueue.tail = 0; +} +//PLICE_DEBUG<- + + + + + +//PLICE_DEBUG -> +INT MlmeThread( + void * Context) +{ + PSDevice pDevice = (PSDevice) Context; + PSRxMgmtPacket pRxMgmtPacket; + // int i ; + //complete(&pDevice->notify); +//printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num); + + //printk("Enter MlmeThread,packet _num is %d\n",pDevice->rxManeQueue.packet_num); + //i = 0; +#if 1 + while (1) + { + + //printk("DDDD\n"); + //down(&pDevice->mlme_semaphore); + // pRxMgmtPacket = DeQueue(pDevice); +#if 1 + spin_lock_irq(&pDevice->lock); + while(pDevice->rxManeQueue.packet_num != 0) + { + pRxMgmtPacket = DeQueue(pDevice); + //pDevice; + //DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList); + vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket); + //printk("packet_num is %d\n",pDevice->rxManeQueue.packet_num); + + } + spin_unlock_irq(&pDevice->lock); + if (mlme_kill == 0) + break; + //udelay(200); +#endif + //printk("Before schedule thread jiffies is %x\n",jiffies); + schedule(); + //printk("after schedule thread jiffies is %x\n",jiffies); + if (mlme_kill == 0) + break; + //printk("i is %d\n",i); + } + +#endif + return 0; + +} + + +#ifdef PRIVATE_OBJ + +int __device_open(HANDLE pExDevice) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + +#else + +static int device_open(struct net_device *dev) { + PSDevice pDevice=(PSDevice) dev->priv; + int i; +#endif + pDevice->rx_buf_sz = PKT_BUF_SZ; + if (!device_init_rings(pDevice)) { + return -ENOMEM; + } +//2008-5-13 <add> by chester +#ifndef PRIVATE_OBJ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16) + i=request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev); +#else + i=request_irq(pDevice->pcid->irq, &device_intr, (unsigned long)SA_SHIRQ, dev->name, dev); +#endif + if (i) + return i; +#endif + //printk("DEBUG1\n"); +#ifdef WPA_SM_Transtatus + extern SWPAResult wpa_Result; + memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname)); + wpa_Result.proto = 0; + wpa_Result.key_mgmt = 0; + wpa_Result.eap_type = 0; + wpa_Result.authenticated = FALSE; + pDevice->fWPA_Authened = FALSE; +#endif +DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n"); +device_init_rd0_ring(pDevice); + device_init_rd1_ring(pDevice); + device_init_defrag_cb(pDevice); + device_init_td0_ring(pDevice); + device_init_td1_ring(pDevice); +// VNTWIFIvSet11h(pDevice->pMgmt, pDevice->b11hEnable); + + + if (pDevice->bDiversityRegCtlON) { + device_init_diversity_timer(pDevice); + } + vMgrObjectInit(pDevice); + vMgrTimerInit(pDevice); + +//PLICE_DEBUG-> +#ifdef TASK_LET + tasklet_init (&pDevice->RxMngWorkItem,(void *)MngWorkItem,(unsigned long )pDevice); +#endif +#ifdef THREAD + InitRxManagementQueue(pDevice); + mlme_kill = 0; + mlme_task = kthread_run(MlmeThread,(void *) pDevice, "MLME"); + if (IS_ERR(mlme_task)) { + printk("thread create fail\n"); + return -1; + } + + mlme_kill = 1; +#endif + + + +#if 0 + pDevice->MLMEThr_pid = kernel_thread(MlmeThread, pDevice, CLONE_VM); + if (pDevice->MLMEThr_pid <0 ) + { + printk("unable start thread MlmeThread\n"); + return -1; + } +#endif + + //printk("thread id is %d\n",pDevice->MLMEThr_pid); + //printk("Create thread time is %x\n",jiffies); + //wait_for_completion(&pDevice->notify); + + + + + // if (( SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL)&0x06)==0x04) + // return -ENOMEM; +DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n"); + device_init_registers(pDevice, DEVICE_INIT_COLD); + MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); + memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, U_ETHER_ADDR_LEN); +#ifdef PRIVATE_OBJ + __device_set_multi(pExDevice); +#else + device_set_multi(pDevice->dev); +#endif + + // Init for Key Management + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); + add_timer(&(pDevice->pMgmt->sTimerSecondCallback)); + + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + /* + pDevice->bwextstep0 = FALSE; + pDevice->bwextstep1 = FALSE; + pDevice->bwextstep2 = FALSE; + pDevice->bwextstep3 = FALSE; + */ + pDevice->bwextcount=0; + pDevice->bWPASuppWextEnabled = FALSE; +#endif + pDevice->byReAssocCount = 0; + pDevice->bWPADEVUp = FALSE; + // Patch: if WEP key already set by iwconfig but device not yet open + if ((pDevice->bEncryptionEnable == TRUE) && (pDevice->bTransmitKey == TRUE)) { + KeybSetDefaultKey(&(pDevice->sKey), + (DWORD)(pDevice->byKeyIndex | (1 << 31)), + pDevice->uKeyLength, + NULL, + pDevice->abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID + ); + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + } + +//printk("DEBUG2\n"); + + +DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n"); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) { + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RUN_AP, NULL); + } + else { + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_SSID, NULL); + } + pDevice->flags |=DEVICE_FLAGS_OPENED; + +#ifndef PRIVATE_OBJ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_INC_USE_COUNT; +#endif +#endif + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n"); + return 0; +} + + +#ifdef PRIVATE_OBJ + +int __device_close(HANDLE pExDevice) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + struct net_device *dev = pDevice_info->dev; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + +#else +static int device_close(struct net_device *dev) { + PSDevice pDevice=(PSDevice) dev->priv; +#endif + PSMgmtObject pMgmt = pDevice->pMgmt; + //PLICE_DEBUG-> +#ifdef THREAD + mlme_kill = 0; +#endif +//PLICE_DEBUG<- +//2007-1121-02<Add>by EinsnLiu + if (pDevice->bLinkPass) { + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + mdelay(30); + } +#ifdef TxInSleep + del_timer(&pDevice->sTimerTxData); +#endif + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + if (pDevice->bDiversityRegCtlON) { + del_timer(&pDevice->TimerSQ3Tmax1); + del_timer(&pDevice->TimerSQ3Tmax2); + del_timer(&pDevice->TimerSQ3Tmax3); + } + +#ifdef TASK_LET + tasklet_kill(&pDevice->RxMngWorkItem); +#endif + netif_stop_queue(dev); + pDevice->bCmdRunning = FALSE; + MACbShutdown(pDevice->PortOffset); + MACbSoftwareReset(pDevice->PortOffset); + CARDbRadioPowerOff(pDevice); + + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + device_free_td0_ring(pDevice); + device_free_td1_ring(pDevice); + device_free_rd0_ring(pDevice); + device_free_rd1_ring(pDevice); + device_free_frag_buf(pDevice); + device_free_rings(pDevice); + BSSvClearNodeDBTable(pDevice, 0); + free_irq(dev->irq, dev); + pDevice->flags &=(~DEVICE_FLAGS_OPENED); + //2008-0714-01<Add>by chester +device_release_WPADEV(pDevice); +//PLICE_DEBUG-> + //tasklet_kill(&pDevice->RxMngWorkItem); +//PLICE_DEBUG<- +#ifndef PRIVATE_OBJ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_DEC_USE_COUNT; +#endif +#endif + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n"); + return 0; +} + +#ifdef PRIVATE_OBJ + +int __device_dma0_tx_80211(HANDLE pExDevice, struct sk_buff *skb) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + ref_sk_buff ref_skb; + +#else + + +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { + PSDevice pDevice=dev->priv; +#endif + PBYTE pbMPDU; + UINT cbMPDULen = 0; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n"); + spin_lock_irq(&pDevice->lock); + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pDevice->bStopTx0Pkt == TRUE) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + }; + +#ifdef PRIVATE_OBJ + ref_skb_remap(pDevice->dev, &ref_skb, skb); + cbMPDULen = *(ref_skb.len); + pbMPDU = ref_skb.data; +#else + cbMPDULen = skb->len; + pbMPDU = skb->data; +#endif + + vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen); + + spin_unlock_irq(&pDevice->lock); + + return 0; + +} + + + +BOOL device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, UINT uNodeIndex) { + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxDesc pHeadTD, pLastTD; + UINT cbFrameBodySize; + UINT uMACfragNum; + BYTE byPktTyp; + BOOL bNeedEncryption = FALSE; + PSKeyItem pTransmitKey = NULL; + UINT cbHeaderSize; + UINT ii; + SKeyItem STempKey; +// BYTE byKeyIndex = 0; +#ifdef PRIVATE_OBJ + ref_sk_buff ref_skb; +#endif + + + if (pDevice->bStopTx0Pkt == TRUE) { + dev_kfree_skb_irq(skb); + return FALSE; + }; + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) { + dev_kfree_skb_irq(skb); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n"); + return FALSE; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->uAssocCount == 0) { + dev_kfree_skb_irq(skb); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n"); + return FALSE; + } + } + +#ifdef PRIVATE_OBJ + ref_skb_remap(pDevice->dev, &(ref_skb), skb); +#endif + pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0]; + + pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); + +#ifdef PRIVATE_OBJ + memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(ref_skb.data), U_HEADER_LEN); + cbFrameBodySize = *(ref_skb.len) - U_HEADER_LEN; + +#else + memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), U_HEADER_LEN); + cbFrameBodySize = skb->len - U_HEADER_LEN; +#endif + + // 802.1H + if (ntohs(pDevice->sTxEthHeader.wType) > MAX_DATA_LEN) { + cbFrameBodySize += 8; + } + uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader); + + if ( uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) { + dev_kfree_skb_irq(skb); + return FALSE; + } + byPktTyp = (BYTE)pDevice->byPacketType; + + + if (pDevice->bFixRate) { + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; + } + } else { + if (pDevice->uConnectionRate >= RATE_54M) + pDevice->wCurrentRate = RATE_54M; + else + pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; + } + } + else { + pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + } + + //preamble type + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } + else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate); + + + if (pDevice->wCurrentRate <= RATE_11M) { + byPktTyp = PK_TYPE_11B; + } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + byPktTyp = PK_TYPE_11A; + } else { + if (pDevice->bProtectMode == TRUE) { + byPktTyp = PK_TYPE_11GB; + } else { + byPktTyp = PK_TYPE_11GA; + } + } + + if (pDevice->bEncryptionEnable == TRUE) + bNeedEncryption = TRUE; + + if (pDevice->bEnableHostWEP) { + 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 + ); + } + vGenerateFIFOHeader(pDevice, byPktTyp, pDevice->pbyTmpBuff, bNeedEncryption, + cbFrameBodySize, TYPE_TXDMA0, pHeadTD, + &pDevice->sTxEthHeader, (PBYTE)skb->data, 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; + } + + // Save the information needed by the tx interrupt handler + // to complete the Send request + pLastTD->pTDInfo->skb = skb; + pLastTD->pTDInfo->byFlags = 0; + pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB; + + pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD; + + MACvTransmit0(pDevice->PortOffset); + + + return TRUE; +} + +//TYPE_AC0DMA data tx +#ifdef PRIVATE_OBJ + +int __device_xmit(HANDLE pExDevice, struct sk_buff *skb) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + struct net_device *dev = pDevice_info->dev; + ref_sk_buff ref_skb; + +#else +static int device_xmit(struct sk_buff *skb, struct net_device *dev) { + PSDevice pDevice=dev->priv; + +#endif + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxDesc pHeadTD, pLastTD; + UINT uNodeIndex = 0; + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + WORD wAID; + UINT uMACfragNum = 1; + UINT cbFrameBodySize; + BYTE byPktTyp; + UINT cbHeaderSize; + BOOL bNeedEncryption = FALSE; + PSKeyItem pTransmitKey = NULL; + SKeyItem STempKey; + UINT ii; + BOOL bTKIP_UseGTK = FALSE; + BOOL bNeedDeAuth = FALSE; + PBYTE pbyBSSID; + BOOL bNodeExist = FALSE; + + + + spin_lock_irq(&pDevice->lock); + if (pDevice->bLinkPass == FALSE) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pDevice->bStopDataPkt) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + +#ifdef PRIVATE_OBJ + ref_skb_remap(pDevice->dev, &ref_skb, skb); +#endif + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->uAssocCount == 0) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } +#ifdef PRIVATE_OBJ + if (IS_MULTICAST_ADDRESS((PBYTE)(ref_skb.data))) { +#else + if (IS_MULTICAST_ADDRESS((PBYTE)(skb->data))) { +#endif + uNodeIndex = 0; + bNodeExist = TRUE; + if (pMgmt->sNodeDBTable[0].bPSEnable) { +#ifdef PRIVATE_OBJ + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), ref_skb.skb); +#else + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb); +#endif + pMgmt->sNodeDBTable[0].wEnQueueCnt++; + // set tx map + pMgmt->abyPSTxMap[0] |= byMask[0]; + spin_unlock_irq(&pDevice->lock); + return 0; + } +}else { +#ifdef PRIVATE_OBJ + if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(ref_skb.data), &uNodeIndex)) { +#else + if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data), &uNodeIndex)) { +#endif + if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { +#ifdef PRIVATE_OBJ + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, ref_skb.skb); +#else + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); +#endif + pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; + // set tx map + wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n", + (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + + }else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + bNodeExist = TRUE; + + } + } + + if (bNodeExist == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + } + + pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA]; + + pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); + + +#ifdef PRIVATE_OBJ + memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(ref_skb.data), U_HEADER_LEN); + cbFrameBodySize = *(ref_skb.len) - U_HEADER_LEN; +#else + memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), U_HEADER_LEN); + cbFrameBodySize = skb->len - U_HEADER_LEN; +#endif + // 802.1H + if (ntohs(pDevice->sTxEthHeader.wType) > MAX_DATA_LEN) { + cbFrameBodySize += 8; + } + + + if (pDevice->bEncryptionEnable == TRUE) { + bNeedEncryption = TRUE; + // get Transmit key + do { + if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + pbyBSSID = pDevice->abyBSSID; + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == FALSE) { + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == TRUE) { + bTKIP_UseGTK = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + break; + } + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n"); + break; + } + }else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + + pbyBSSID = pDevice->sTxEthHeader.abyDstAddr; //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n"); + for (ii = 0; ii< 6; ii++) + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n"); + + // get pairwise key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == TRUE) + break; + } + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == FALSE) { + pTransmitKey = NULL; + if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode); + } + else + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode); + } else { + bTKIP_UseGTK = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + } + } while(FALSE); + } + + if (pDevice->bEnableHostWEP) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"acdma0: STA index %d\n", uNodeIndex); + if (pDevice->bEncryptionEnable == TRUE) { + 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)) { + DEVICE_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pTransmitKey != NULL) { + if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) && + (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) { + uMACfragNum = 1; //WEP256 doesn't support fragment + } + } + + byPktTyp = (BYTE)pDevice->byPacketType; + + if (pDevice->bFixRate) { +#ifdef PLICE_DEBUG + printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n",pDevice->eCurrentPHYType,pDevice->uConnectionRate); +#endif + + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (WORD)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 = (WORD)pDevice->uConnectionRate; + + } + } + pDevice->byACKRate = (BYTE) pDevice->wCurrentRate; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + else { + //auto rate + if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { + if (pDevice->eCurrentPHYType != PHY_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } + else { + VNTWIFIvGetTxRate( pDevice->pMgmt, + pDevice->sTxEthHeader.abyDstAddr, + &(pDevice->wCurrentRate), + &(pDevice->byACKRate), + &(pDevice->byTopCCKBasicRate), + &(pDevice->byTopOFDMBasicRate)); + +#if 0 +printk("auto rate:Rate : %d,AckRate:%d,TopCCKRate:%d,TopOFDMRate:%d\n", +pDevice->wCurrentRate,pDevice->byACKRate, +pDevice->byTopCCKBasicRate,pDevice->byTopOFDMBasicRate); + +#endif + +#if 0 + + pDevice->wCurrentRate = 11; + pDevice->byACKRate = 8; + pDevice->byTopCCKBasicRate = 3; + pDevice->byTopOFDMBasicRate = 8; +#endif + + + } + } + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate); + + if (pDevice->wCurrentRate <= RATE_11M) { + byPktTyp = PK_TYPE_11B; + } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + byPktTyp = PK_TYPE_11A; + } else { + if (pDevice->bProtectMode == TRUE) { + byPktTyp = PK_TYPE_11GB; + } else { + byPktTyp = PK_TYPE_11GA; + } + } + +//#ifdef PLICE_DEBUG +// printk("FIX RATE:CurrentRate is %d"); +//#endif + + if (bNeedEncryption == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); + if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) { + bNeedEncryption = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); + if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if (pTransmitKey == NULL) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n"); + } + else { + if (bTKIP_UseGTK == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } + } + + if (pDevice->byCntMeasure == 2) { + bNeedDeAuth = TRUE; + pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++; + } + + if (pDevice->bEnableHostWEP) { + if ((uNodeIndex != 0) && + (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } + } + else { + if (pTransmitKey == NULL) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + } + } + + +#ifdef PRIVATE_OBJ + vGenerateFIFOHeader(pDevice, byPktTyp, pDevice->pbyTmpBuff, bNeedEncryption, + cbFrameBodySize, TYPE_AC0DMA, pHeadTD, + &pDevice->sTxEthHeader, (PBYTE)ref_skb.data, pTransmitKey, uNodeIndex, + &uMACfragNum, + &cbHeaderSize + ); +#else +#ifdef PLICE_DEBUG + //if (skb->len == 98) + //{ + // printk("ping:len is %d\n"); + //} +#endif + vGenerateFIFOHeader(pDevice, byPktTyp, pDevice->pbyTmpBuff, bNeedEncryption, + cbFrameBodySize, TYPE_AC0DMA, pHeadTD, + &pDevice->sTxEthHeader, (PBYTE)skb->data, pTransmitKey, uNodeIndex, + &uMACfragNum, + &cbHeaderSize + ); +#endif + + 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; + } + + // Save the information needed by the tx interrupt handler + // to complete the Send request +#ifdef PRIVATE_OBJ + pLastTD->pTDInfo->skb = ref_skb.skb; +#else + pLastTD->pTDInfo->skb = skb; +#endif + pLastTD->pTDInfo->byFlags = 0; + pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB; +#ifdef TxInSleep + pDevice->nTxDataTimeCout=0; //2008-8-21 chester <add> for send null packet + #endif + if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) { + netif_stop_queue(dev); + } + + pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD; +//#ifdef PLICE_DEBUG + if (pDevice->bFixRate) + { + printk("FixRate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr); + } + else + { + //printk("Auto Rate:Rate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr); + } +//#endif + +{ + BYTE Protocol_Version; //802.1x Authentication + BYTE Packet_Type; //802.1x Authentication + BYTE Descriptor_type; + WORD Key_info; +BOOL bTxeapol_key = FALSE; + Protocol_Version = skb->data[U_HEADER_LEN]; + Packet_Type = skb->data[U_HEADER_LEN+1]; + Descriptor_type = skb->data[U_HEADER_LEN+1+1+2]; + Key_info = (skb->data[U_HEADER_LEN+1+1+2+1] << 8)|(skb->data[U_HEADER_LEN+1+1+2+2]); + if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { + if(((Protocol_Version==1) ||(Protocol_Version==2)) && + (Packet_Type==3)) { //802.1x OR eapol-key challenge frame transfer + bTxeapol_key = TRUE; + if((Descriptor_type==254)||(Descriptor_type==2)) { //WPA or RSN + if(!(Key_info & BIT3) && //group-key challenge + (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key + pDevice->fWPA_Authened = TRUE; + if(Descriptor_type==254) + printk("WPA "); + else + printk("WPA2 "); + printk("Authentication completed!!\n"); + } + } + } + } +} + + MACvTransmitAC0(pDevice->PortOffset); +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0:pDevice->apCurrTD= %p\n", pHeadTD); + +#ifdef PRIVATE_OBJ + ref_set_tx_jiffies(pDevice->dev); +#else + dev->trans_start = jiffies; +#endif + + spin_unlock_irq(&pDevice->lock); + return 0; + +} + +#ifdef PRIVATE_OBJ + +int __device_intr(int irq, HANDLE pExDevice, struct pt_regs *regs) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + + +#else +static irqreturn_t device_intr(int irq, void *dev_instance) { + struct net_device* dev=dev_instance; + PSDevice pDevice=(PSDevice) dev->priv; +#endif + + int max_count=0; + DWORD dwMIBCounter=0; + PSMgmtObject pMgmt = pDevice->pMgmt; + BYTE byOrgPageSel=0; + int handled = 0; + BYTE byData = 0; + int ii= 0; +// BYTE byRSSI; + + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + + if (pDevice->dwIsr == 0) + return IRQ_RETVAL(handled); + + if (pDevice->dwIsr == 0xffffffff) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n"); + return IRQ_RETVAL(handled); + } + /* + // 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI + + if ((BITbIsBitOn(pDevice->dwIsr, ISR_RXDMA0)) && + (pDevice->byLocalID != REV_ID_VT3253_B0) && + (pDevice->bBSSIDFilter == TRUE)) { + // update RSSI + //BBbReadEmbeded(pDevice->PortOffset, 0x3E, &byRSSI); + //pDevice->uCurrRSSI = byRSSI; + } + */ + + handled = 1; + MACvIntDisable(pDevice->PortOffset); + spin_lock_irq(&pDevice->lock); + + //Make sure current page is 0 + VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); + if (byOrgPageSel == 1) { + MACvSelectPage0(pDevice->PortOffset); + } + else + byOrgPageSel = 0; + + MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter); + // TBD.... + // Must do this after doing rx/tx, cause ISR bit is slow + // than RD/TD write back + // update ISR counter + STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter); + while (pDevice->dwIsr != 0) { + + STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); + MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); + + if (pDevice->dwIsr & ISR_FETALERR){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n"); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); + device_error(pDevice, pDevice->dwIsr); + } + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + + if (BITbIsBitOn(pDevice->dwIsr, ISR_MEASURESTART)) { + // 802.11h measure start + pDevice->byOrgChannel = pDevice->byCurrentCh; + VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR)); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR)); + MACvSelectPage1(pDevice->PortOffset); + VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0)); + VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4)); + MACvSelectPage0(pDevice->PortOffset); + //xxxx + // WCMDbFlushCommandQueue(pDevice->pMgmt, TRUE); + if (CARDbSetChannel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == TRUE) { + pDevice->bMeasureInProgress = TRUE; + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byBasicMap = 0; + pDevice->byCCAFraction = 0; + for(ii=0;ii<8;ii++) { + pDevice->dwRPIs[ii] = 0; + } + } else { + // can not measure because set channel fail + // WCMDbResetCommandQueue(pDevice->pMgmt); + // clear measure control + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + } + } + if (BITbIsBitOn(pDevice->dwIsr, ISR_MEASUREEND)) { + // 802.11h measure end + pDevice->bMeasureInProgress = FALSE; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR); + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4); + VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData); + pDevice->byBasicMap |= (byData >> 4); + VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction); + VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData); + // clear measure control + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + MACvSelectPage0(pDevice->PortOffset); + CARDbSetChannel(pDevice, pDevice->byOrgChannel); + // WCMDbResetCommandQueue(pDevice->pMgmt); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + if (BITbIsBitOn(byData, MSRCTL_FINISH)) { + // measure success + s_vCompleteCurrentMeasure(pDevice, 0); + } else { + // can not measure because not ready before end of measure time + s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE); + } + } + if (BITbIsBitOn(pDevice->dwIsr, ISR_QUIETSTART)) { + do { + ; + } while (CARDbStartQuiet(pDevice) == FALSE); + } + } + + if (pDevice->dwIsr & ISR_TBTT) { + if (pDevice->bEnableFirstQuiet == TRUE) { + pDevice->byQuietStartCount--; + if (pDevice->byQuietStartCount == 0) { + pDevice->bEnableFirstQuiet = FALSE; + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); + MACvSelectPage0(pDevice->PortOffset); + } + } + if ((pDevice->bChannelSwitch == TRUE) && + (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) { + pDevice->byChannelSwitchCount--; + if (pDevice->byChannelSwitchCount == 0) { + pDevice->bChannelSwitch = FALSE; + CARDbSetChannel(pDevice, pDevice->byNewChannel); + VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL); + + } + } + if (pDevice->eOPMode == OP_MODE_ADHOC) { + //pDevice->bBeaconSent = FALSE; + } else { + if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == TRUE) && (pDevice->uCurrRSSI != 0)) { + LONG ldBm; + + RFvRSSITodBm(pDevice, (BYTE) pDevice->uCurrRSSI, &ldBm); + for (ii=0;ii<BB_VGA_LEVEL;ii++) { + if (ldBm < pDevice->ldBmThreshold[ii]) { + pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; + break; + } + } + if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { + pDevice->uBBVGADiffCount++; + if (pDevice->uBBVGADiffCount == 1) { + // first VGA diff gain + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount); + } + if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount); + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); + } + } else { + pDevice->uBBVGADiffCount = 1; + } + } + } + + pDevice->bBeaconSent = FALSE; + if (pDevice->bEnablePSMode) { + PSbIsNextTBTTWakeUp((HANDLE)pDevice); + }; + + if ((pDevice->eOPMode == OP_MODE_AP) || + (pDevice->eOPMode == OP_MODE_ADHOC)) { + + MACvOneShotTimer1MicroSec(pDevice->PortOffset, + (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10); + } + + if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) { + // todo adhoc PS mode + }; + + } + + if (pDevice->dwIsr & ISR_BNTX) { + + if (pDevice->eOPMode == OP_MODE_ADHOC) { + pDevice->bIsBeaconBufReadySet = FALSE; + pDevice->cbBeaconBufReadySetCnt = 0; + }; + + if (pDevice->eOPMode == OP_MODE_AP) { + if(pMgmt->byDTIMCount > 0) { + pMgmt->byDTIMCount --; + pMgmt->sNodeDBTable[0].bRxPSPoll = FALSE; + } + else { + if(pMgmt->byDTIMCount == 0) { + // check if mutltcast tx bufferring + pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1; + pMgmt->sNodeDBTable[0].bRxPSPoll = TRUE; + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RX_PSPOLL, NULL); + } + } + } + pDevice->bBeaconSent = TRUE; + + if (pDevice->bChannelSwitch == TRUE) { + pDevice->byChannelSwitchCount--; + if (pDevice->byChannelSwitchCount == 0) { + pDevice->bChannelSwitch = FALSE; + CARDbSetChannel(pDevice, pDevice->byNewChannel); + VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + //VNTWIFIbSendBeacon(pDevice->pMgmt); + CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL); + } + } + + } + + if (pDevice->dwIsr & ISR_RXDMA0) { + max_count += device_rx_srv(pDevice, TYPE_RXDMA0); + } + if (pDevice->dwIsr & ISR_RXDMA1) { + max_count += device_rx_srv(pDevice, TYPE_RXDMA1); + } + if (pDevice->dwIsr & ISR_TXDMA0){ + max_count += device_tx_srv(pDevice, TYPE_TXDMA0); + } + if (pDevice->dwIsr & ISR_AC0DMA){ + max_count += device_tx_srv(pDevice, TYPE_AC0DMA); + } + if (pDevice->dwIsr & ISR_SOFTTIMER) { + + } + if (pDevice->dwIsr & ISR_SOFTTIMER1) { + if (pDevice->eOPMode == OP_MODE_AP) { + if (pDevice->bShortSlotTime) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + else + pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)); + } + bMgrPrepareBeaconToSend(pDevice, pMgmt); + pDevice->byCntMeasure = 0; + } + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + + MACvReceive0(pDevice->PortOffset); + MACvReceive1(pDevice->PortOffset); + + if (max_count>pDevice->sOpts.int_works) + break; + } + + if (byOrgPageSel == 1) { + MACvSelectPage1(pDevice->PortOffset); + } + + spin_unlock_irq(&pDevice->lock); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + return IRQ_RETVAL(handled); +} + + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) +{ + int crc = -1; + + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) { + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + } + return crc; +} + +//2008-8-4 <add> by chester +static int Config_FileGetParameter(UCHAR *string, UCHAR *dest,UCHAR *source) +{ + UCHAR buf1[100]; + int source_len = strlen(source); + + memset(buf1,0,100); + strcat(buf1, string); + strcat(buf1, "="); + source+=strlen(buf1); + + memcpy(dest,source,source_len-strlen(buf1)); + return TRUE; +} + +int Config_FileOperation(PSDevice pDevice,BOOL fwrite,unsigned char *Parameter) { + UCHAR *config_path=CONFIG_PATH; + UCHAR *buffer=NULL; + UCHAR tmpbuffer[20]; + struct file *filp=NULL; + mm_segment_t old_fs = get_fs(); + int oldfsuid=0,oldfsgid=0; + int result=0; + + set_fs (KERNEL_DS); +//Make sure a caller can read or write power as root + oldfsuid=current->fsuid; + oldfsgid=current->fsgid; + current->fsuid = 0; + current->fsgid = 0; + + //open file + filp = filp_open(config_path, O_RDWR, 0); + if (IS_ERR(filp)) { + printk("Config_FileOperation:open file fail?\n"); + result=-1; + goto error2; + } + + if(!(filp->f_op) || !(filp->f_op->read) ||!(filp->f_op->write)) { + printk("file %s cann't readable or writable?\n",config_path); + result = -1; + goto error1; + } + +buffer = (UCHAR *)kmalloc(1024, GFP_KERNEL); +if(buffer==NULL) { + printk("alllocate mem for file fail?\n"); + result = -1; + goto error1; +} + +if(filp->f_op->read(filp, buffer, 1024, &filp->f_pos)<0) { + printk("read file error?\n"); + result = -1; + goto error1; +} + +if(Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer)!=TRUE) { + printk("get parameter error?\n"); + result = -1; + goto error1; +} + +if(memcmp(tmpbuffer,"USA",3)==0) { + result=ZoneType_USA; +} +else if(memcmp(tmpbuffer,"JAPAN",5)==0) { + result=ZoneType_Japan; +} +else if(memcmp(tmpbuffer,"EUROPE",5)==0) { + result=ZoneType_Europe; +} +else { + result = -1; + printk("Unknown Zonetype[%s]?\n",tmpbuffer); +} + +error1: + if(buffer) + kfree(buffer); + + if(filp_close(filp,NULL)) + printk("Config_FileOperation:close file fail\n"); + +error2: + set_fs (old_fs); + current->fsuid=oldfsuid; + current->fsgid=oldfsgid; + + return result; +} + + +#ifdef PRIVATE_OBJ + +void __device_set_multi(HANDLE pExDevice) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + ref_net_device *dev = &(pDevice_info->ref_dev); + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + +#else + +static void device_set_multi(struct net_device *dev) { + PSDevice pDevice = (PSDevice) dev->priv; +#endif + + PSMgmtObject pMgmt = pDevice->pMgmt; + u32 mc_filter[2]; + int i; + struct dev_mc_list *mclist; + + + VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); + +#ifdef PRIVATE_OBJ + if (*(dev->flags) & IFF_PROMISC) { /* Set promiscuous. */ + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: Promiscuous mode enabled.\n", pDevice->dev->name); + +#else + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + DEVICE_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); +#endif + /* Unconditionally log net taps. */ + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST); + } +#ifdef PRIVATE_OBJ + else if ((*(dev->mc_count) > pDevice->multicast_limit) + || (*(dev->flags) & IFF_ALLMULTI)) { +#else + else if ((dev->mc_count > pDevice->multicast_limit) + || (dev->flags & IFF_ALLMULTI)) { +#endif + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } + else { + memset(mc_filter, 0, sizeof(mc_filter)); +#ifdef PRIVATE_OBJ + for (i = 0, mclist = dev->mc_list; mclist && i < *(dev->mc_count); + i++, mclist = mclist->next) { +#else + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { +#endif + int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); + } + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byRxMode &= ~(RCR_UNICAST); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + // If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac. + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + pDevice->byRxMode &= ~(RCR_UNICAST); + } + + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode ); +} + + +#ifdef PRIVATE_OBJ + +struct net_device_stats *__device_get_stats(HANDLE pExDevice) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + +#else +static struct net_device_stats *device_get_stats(struct net_device *dev) { + PSDevice pDevice=(PSDevice) dev->priv; +#endif + + return &pDevice->stats; +} + + +#ifdef PRIVATE_OBJ + +int __device_ioctl(HANDLE pExDevice, struct ifreq *rq, int cmd) { + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + struct net_device *dev = pDevice_info->dev; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + +#else + +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { + PSDevice pDevice = (PSDevice)dev->priv; +#endif + +#ifdef WIRELESS_EXT + struct iwreq *wrq = (struct iwreq *) rq; + int rc =0; +#endif + PSMgmtObject pMgmt = pDevice->pMgmt; + PSCmdRequest pReq; + + + if (pMgmt == NULL) { + rc = -EFAULT; + return rc; + } + + switch(cmd) { + +#ifdef WIRELESS_EXT +//#if WIRELESS_EXT < 13 + + case SIOCGIWNAME: + rc = iwctl_giwname(dev, NULL, (char *)&(wrq->u.name), NULL); + break; + + case SIOCGIWNWID: //0x8b03 support + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + rc = iwctl_giwnwid(dev, NULL, &(wrq->u.nwid), NULL); + #else + rc = -EOPNOTSUPP; + #endif + break; + + // Set frequency/channel + case SIOCSIWFREQ: + rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL); + break; + + // Get frequency/channel + case SIOCGIWFREQ: + rc = iwctl_giwfreq(dev, NULL, &(wrq->u.freq), NULL); + break; + + // Set desired network name (ESSID) + case SIOCSIWESSID: + + { + char essid[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) { + rc = -E2BIG; + break; + } + if (copy_from_user(essid, wrq->u.essid.pointer, + wrq->u.essid.length)) { + rc = -EFAULT; + break; + } + rc = iwctl_siwessid(dev, NULL, + &(wrq->u.essid), essid); + } + break; + + + // Get current network name (ESSID) + case SIOCGIWESSID: + + { + char essid[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.pointer) + rc = iwctl_giwessid(dev, NULL, + &(wrq->u.essid), essid); + if (copy_to_user(wrq->u.essid.pointer, + essid, + wrq->u.essid.length) ) + rc = -EFAULT; + } + break; + + case SIOCSIWAP: + + rc = iwctl_siwap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + + // Get current Access Point (BSSID) + case SIOCGIWAP: + rc = iwctl_giwap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + + // Set desired station name + case SIOCSIWNICKN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n"); + rc = -EOPNOTSUPP; + break; + + // Get current station name + case SIOCGIWNICKN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n"); + rc = -EOPNOTSUPP; + break; + + // Set the desired bit-rate + case SIOCSIWRATE: + rc = iwctl_siwrate(dev, NULL, &(wrq->u.bitrate), NULL); + break; + + // Get the current bit-rate + case SIOCGIWRATE: + + rc = iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL); + break; + + // Set the desired RTS threshold + case SIOCSIWRTS: + + rc = iwctl_siwrts(dev, NULL, &(wrq->u.rts), NULL); + break; + + // Get the current RTS threshold + case SIOCGIWRTS: + + rc = iwctl_giwrts(dev, NULL, &(wrq->u.rts), NULL); + break; + + // Set the desired fragmentation threshold + case SIOCSIWFRAG: + + rc = iwctl_siwfrag(dev, NULL, &(wrq->u.frag), NULL); + break; + + // Get the current fragmentation threshold + case SIOCGIWFRAG: + + rc = iwctl_giwfrag(dev, NULL, &(wrq->u.frag), NULL); + break; + + // Set mode of operation + case SIOCSIWMODE: + rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL); + break; + + // Get mode of operation + case SIOCGIWMODE: + rc = iwctl_giwmode(dev, NULL, &(wrq->u.mode), NULL); + break; + + // Set WEP keys and mode + case SIOCSIWENCODE: + { + char abyKey[WLAN_WEP232_KEYLEN]; + + if (wrq->u.encoding.pointer) { + + + if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) { + rc = -E2BIG; + break; + } + memset(abyKey, 0, WLAN_WEP232_KEYLEN); + if (copy_from_user(abyKey, + wrq->u.encoding.pointer, + wrq->u.encoding.length)) { + rc = -EFAULT; + break; + } + } else if (wrq->u.encoding.length != 0) { + rc = -EINVAL; + break; + } + rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey); + } + break; + + // Get the WEP keys and mode + case SIOCGIWENCODE: + + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + break; + } + { + char abyKey[WLAN_WEP232_KEYLEN]; + + rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey); + if (rc != 0) break; + if (wrq->u.encoding.pointer) { + if (copy_to_user(wrq->u.encoding.pointer, + abyKey, + wrq->u.encoding.length)) + rc = -EFAULT; + } + } + break; + +#if WIRELESS_EXT > 9 + // Get the current Tx-Power + case SIOCGIWTXPOW: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n"); + rc = -EOPNOTSUPP; + break; + + case SIOCSIWTXPOW: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n"); + rc = -EOPNOTSUPP; + break; + +#endif // WIRELESS_EXT > 9 + +#if WIRELESS_EXT > 10 + case SIOCSIWRETRY: + + rc = iwctl_siwretry(dev, NULL, &(wrq->u.retry), NULL); + break; + + case SIOCGIWRETRY: + + rc = iwctl_giwretry(dev, NULL, &(wrq->u.retry), NULL); + break; + +#endif // WIRELESS_EXT > 10 + + // Get range of parameters + case SIOCGIWRANGE: + + { + struct iw_range range; + + rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range); + if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) + rc = -EFAULT; + } + + break; + + case SIOCGIWPOWER: + + rc = iwctl_giwpower(dev, NULL, &(wrq->u.power), NULL); + break; + + + case SIOCSIWPOWER: + + rc = iwctl_siwpower(dev, NULL, &(wrq->u.power), NULL); + break; + + + case SIOCGIWSENS: + + rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL); + break; + + case SIOCSIWSENS: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n"); + rc = -EOPNOTSUPP; + break; + + case SIOCGIWAPLIST: + { + char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))]; + + if (wrq->u.data.pointer) { + rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer); + if (rc == 0) { + if (copy_to_user(wrq->u.data.pointer, + buffer, + (wrq->u.data.length * (sizeof(struct sockaddr) + sizeof(struct iw_quality))) + )) + rc = -EFAULT; + } + } + } + break; + + +#ifdef WIRELESS_SPY + // Set the spy list + case SIOCSIWSPY: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n"); + rc = -EOPNOTSUPP; + break; + + // Get the spy list + case SIOCGIWSPY: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n"); + rc = -EOPNOTSUPP; + break; + +#endif // WIRELESS_SPY + + case SIOCGIWPRIV: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n"); + rc = -EOPNOTSUPP; +/* + if(wrq->u.data.pointer) { + wrq->u.data.length = sizeof(iwctl_private_args) / sizeof( iwctl_private_args[0]); + + if(copy_to_user(wrq->u.data.pointer, + (u_char *) iwctl_private_args, + sizeof(iwctl_private_args))) + rc = -EFAULT; + } +*/ + break; + + +//#endif // WIRELESS_EXT < 13 +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + case SIOCSIWAUTH: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n"); + rc = iwctl_siwauth(dev, NULL, &(wrq->u.param), NULL); + break; + + case SIOCGIWAUTH: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAUTH \n"); + rc = iwctl_giwauth(dev, NULL, &(wrq->u.param), NULL); + break; + + case SIOCSIWGENIE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWGENIE \n"); + rc = iwctl_siwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + + case SIOCGIWGENIE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWGENIE \n"); + rc = iwctl_giwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + + case SIOCSIWENCODEEXT: + { + char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1]; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n"); + if(wrq->u.encoding.pointer){ + memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1); + if(wrq->u.encoding.length > (sizeof(struct iw_encode_ext)+ MAX_KEY_LEN)){ + rc = -E2BIG; + break; + } + if(copy_from_user(extra, wrq->u.encoding.pointer,wrq->u.encoding.length)){ + rc = -EFAULT; + break; + } + }else if(wrq->u.encoding.length != 0){ + rc = -EINVAL; + break; + } + rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra); + } + break; + + case SIOCGIWENCODEEXT: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODEEXT \n"); + rc = iwctl_giwencodeext(dev, NULL, &(wrq->u.encoding), NULL); + break; + + case SIOCSIWMLME: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMLME \n"); + rc = iwctl_siwmlme(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + +#endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +//End Add -- //2008-0409-07, <Add> by Einsn Liu + +#endif // WIRELESS_EXT + + case IOCTL_CMD_TEST: + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EFAULT; + break; + } else { + rc = 0; + } + pReq = (PSCmdRequest)rq; + pReq->wResult = MAGIC_CODE; + break; + + case IOCTL_CMD_SET: + + #ifdef SndEvt_ToAPI + if((((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_EVT) && + !(pDevice->flags & DEVICE_FLAGS_OPENED)) + #else + if (!(pDevice->flags & DEVICE_FLAGS_OPENED) && + (((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_WPA)) + #endif + { + rc = -EFAULT; + break; + } else { + rc = 0; + } + + if (test_and_set_bit( 0, (void*)&(pMgmt->uCmdBusy))) { + return -EBUSY; + } + rc = private_ioctl(pDevice, rq); + clear_bit( 0, (void*)&(pMgmt->uCmdBusy)); + break; + + case IOCTL_CMD_HOSTAPD: + + +#if WIRELESS_EXT > 8 + rc = hostap_ioctl(pDevice, &wrq->u.data); +#else // WIRELESS_EXT > 8 + rc = hostap_ioctl(pDevice, (struct iw_point *) &wrq->u.data); +#endif // WIRELESS_EXT > 8 + break; + + case IOCTL_CMD_WPA: + +#if WIRELESS_EXT > 8 + rc = wpa_ioctl(pDevice, &wrq->u.data); +#else // WIRELESS_EXT > 8 + rc = wpa_ioctl(pDevice, (struct iw_point *) &wrq->u.data); +#endif // WIRELESS_EXT > 8 + break; + + case SIOCETHTOOL: + return ethtool_ioctl(dev, (void *) rq->ifr_data); + // All other calls are currently unsupported + + default: + rc = -EOPNOTSUPP; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd); + + + } + + if (pDevice->bCommit) { + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RUN_AP, NULL); + spin_unlock_irq(&pDevice->lock); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n"); + spin_lock_irq(&pDevice->lock); + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + if(pDevice->bWPASuppWextEnabled !=TRUE) + #endif + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + } + pDevice->bCommit = FALSE; + } + + return rc; +} + + +static int ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1); + strncpy(info.version, DEVICE_VERSION, sizeof(info.version)-1); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +/*------------------------------------------------------------------*/ +#ifndef PRIVATE_OBJ + +MODULE_DEVICE_TABLE(pci, device_id_table); + +static struct pci_driver device_driver = { + name: DEVICE_NAME, + id_table: device_id_table, + probe: device_found1, + remove: device_remove1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + suspend: viawget_suspend, + resume: viawget_resume, +#endif +#endif +}; + +static int __init device_init_module(void) +{ + int ret; + + +// ret=pci_module_init(&device_driver); + //ret = pcie_port_service_register(&device_driver); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + ret = pci_register_driver(&device_driver); +#else + ret = pci_module_init(&device_driver); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + if(ret >= 0) + register_reboot_notifier(&device_notifier); +#endif +#endif + + return ret; +} + +static void __exit device_cleanup_module(void) +{ + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM + unregister_reboot_notifier(&device_notifier); +#endif +#endif + pci_unregister_driver(&device_driver); + +} + +module_init(device_init_module); +module_exit(device_cleanup_module); + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) +#ifdef CONFIG_PM +static int +device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) +{ + struct pci_dev *pdev = NULL; + switch(event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { +#else + pci_for_each_dev(pdev) { +#endif + if(pci_dev_driver(pdev) == &device_driver) { + if (pci_get_drvdata(pdev)) + viawget_suspend(pdev, 3); + } + } + } + return NOTIFY_DONE; +} + +static int +viawget_suspend(struct pci_dev *pcid, u32 state) +{ + int power_status; // to silence the compiler + + PSDevice pDevice=pci_get_drvdata(pcid); + PSMgmtObject pMgmt = pDevice->pMgmt; + + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + pci_save_state(pcid); +#else + pci_save_state(pcid, pDevice->pci_state); +#endif + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->bCmdRunning = FALSE; + MACbShutdown(pDevice->PortOffset); + MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext); + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pci_disable_device(pcid); + power_status = pci_set_power_state(pcid, state); + spin_unlock_irq(&pDevice->lock); + return 0; +} + +static int +viawget_resume(struct pci_dev *pcid) +{ + PSDevice pDevice=pci_get_drvdata(pcid); + PSMgmtObject pMgmt = pDevice->pMgmt; + int power_status; // to silence the compiler + + + power_status = pci_set_power_state(pcid, 0); + power_status = pci_enable_wake(pcid, 0, 0); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + pci_restore_state(pcid); +#else + pci_restore_state(pcid, pDevice->pci_state); +#endif + if (netif_running(pDevice->dev)) { + spin_lock_irq(&pDevice->lock); + MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext); + device_init_registers(pDevice, DEVICE_INIT_DXPL); + if (pMgmt->sNodeDBTable[0].bActive == TRUE) { // Assoc with BSS + pMgmt->sNodeDBTable[0].bActive = FALSE; + pDevice->bLinkPass = FALSE; + if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + // In Adhoc, BSS state set back to started. + pMgmt->eCurrState = WMAC_STATE_STARTED; + } + else { + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + } + init_timer(&pMgmt->sTimerSecondCallback); + init_timer(&pDevice->sTimerCommand); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + } + return 0; +} + +#endif +#endif + +#endif //#ifndef PRIVATE_OBJ + +#ifdef PRIVATE_OBJ + + +int __device_hw_reset(HANDLE pExDevice){ + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + + return MACbSoftwareReset(pDevice_info->port_offset); +} + + +int __device_hw_init(HANDLE pExDevice){ + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice; + + + pDevice = (PSDevice)kmalloc(sizeof(DEVICE_INFO), (int)GFP_ATOMIC); + if (pDevice == NULL) + return FALSE; + + memset(pDevice, 0, sizeof(DEVICE_INFO)); + pDevice_info->pWDevice = pDevice; + pDevice->PortOffset = pDevice_info->port_offset; + pDevice->dev = pDevice_info->dev; + pDevice->pcid = pDevice_info->pcid; + pDevice->chip_id = pDevice_info->chip_id; + pDevice->memaddr = pDevice_info->mem_addr; + pDevice->ioaddr = pDevice_info->io_addr; + pDevice->io_size = pDevice_info->io_size; + pDevice->nTxQueues = pDevice_info->nTxQueues; + pDevice->multicast_limit = pDevice_info->multicast_limit; + pDevice->sMgmtObj.pAdapter = (PVOID)pDevice; + pDevice->pMgmt = &(pDevice->sMgmtObj); + MACvInitialize(pDevice->PortOffset); + device_get_options(pDevice, 0 , pDevice_info->dev->name); + device_set_options(pDevice); + pDevice->sOpts.flags &= pDevice_info->flags; + pDevice->flags = pDevice->sOpts.flags | (pDevice_info->flags & 0xFF000000UL); + spin_lock_init(&(pDevice->lock)); + + return TRUE; +} + + +void __device_read_mac(HANDLE pExDevice, PBYTE dev_addr){ + PSDevice_info pDevice_info = (PSDevice_info)pExDevice; + PSDevice pDevice = (PSDevice)(pDevice_info->pWDevice); + + MACvReadEtherAddress(pDevice->PortOffset, dev_addr); + return; +} + + +#endif + + diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c new file mode 100644 index 00000000000..05366b9754f --- /dev/null +++ b/drivers/staging/vt6655/dpc.c @@ -0,0 +1,1688 @@ +/* + * 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: dpc.c + * + * Purpose: handle dpc rx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * device_receive_frame - Rcv 802.11 frame function + * s_bAPModeRxCtl- AP Rcv frame filer Ctl. + * s_bAPModeRxData- AP Rcv data frame handle + * s_bHandleRxEncryption- Rcv decrypted data via on-fly + * s_bHostWepRxEncryption- Rcv encrypted data via host + * s_byGetRateIdx- get rate index + * s_vGetDASA- get data offset + * s_vProcessRxMACHeader- Rcv 802.11 and translate to 802.3 + * + * Revision History: + * + */ + + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__MICHAEL_H__) +#include "michael.h" +#endif +#if !defined(__TKIP_H__) +#include "tkip.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__WROUTE_H__) +#include "wroute.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif +#if !defined(__AES_H__) +#include "aes_ccmp.h" +#endif + +//#define PLICE_DEBUG + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +const BYTE acbyRxRate[MAX_RATE] = +{2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; + + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +static BYTE s_byGetRateIdx(IN BYTE byRate); + + +static +VOID +s_vGetDASA( + IN PBYTE pbyRxBufferAddr, + OUT PUINT pcbHeaderSize, + OUT PSEthernetHeader psEthHeader + ); + +static +VOID +s_vProcessRxMACHeader ( + IN PSDevice pDevice, + IN PBYTE pbyRxBufferAddr, + IN UINT cbPacketSize, + IN BOOL bIsWEP, + IN BOOL bExtIV, + OUT PUINT pcbHeadSize + ); + +static BOOL s_bAPModeRxCtl( + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN INT iSANodeIndex + ); + +#ifdef PRIVATE_OBJ + +static BOOL s_bAPModeRxData ( + IN PSDevice pDevice, + IN ref_sk_buff* skb, + IN UINT FrameSize, + IN UINT cbHeaderOffset, + IN INT iSANodeIndex, + IN INT iDANodeIndex + ); +#else + +static BOOL s_bAPModeRxData ( + IN PSDevice pDevice, + IN struct sk_buff* skb, + IN UINT FrameSize, + IN UINT cbHeaderOffset, + IN INT iSANodeIndex, + IN INT iDANodeIndex + ); +#endif + + +static BOOL s_bHandleRxEncryption( + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN UINT FrameSize, + IN PBYTE pbyRsr, + OUT PBYTE pbyNewRsr, + OUT PSKeyItem *pKeyOut, + OUT PBOOL pbExtIV, + OUT PWORD pwRxTSC15_0, + OUT PDWORD pdwRxTSC47_16 + ); + +static BOOL s_bHostWepRxEncryption( + + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN UINT FrameSize, + IN PBYTE pbyRsr, + IN BOOL bOnFly, + IN PSKeyItem pKey, + OUT PBYTE pbyNewRsr, + OUT PBOOL pbExtIV, + OUT PWORD pwRxTSC15_0, + OUT PDWORD pdwRxTSC47_16 + + ); + +/*--------------------- Export Variables --------------------------*/ + +/*+ + * + * Description: + * Translate Rcv 802.11 header to 802.3 header with Rx buffer + * + * Parameters: + * In: + * pDevice + * dwRxBufferAddr - Address of Rcv Buffer + * cbPacketSize - Rcv Packet size + * bIsWEP - If Rcv with WEP + * Out: + * pcbHeaderSize - 802.11 header size + * + * Return Value: None + * +-*/ +static +VOID +s_vProcessRxMACHeader ( + IN PSDevice pDevice, + IN PBYTE pbyRxBufferAddr, + IN UINT cbPacketSize, + IN BOOL bIsWEP, + IN BOOL bExtIV, + OUT PUINT pcbHeadSize + ) +{ + PBYTE pbyRxBuffer; + UINT cbHeaderSize = 0; + PWORD pwType; + PS802_11Header pMACHeader; + int ii; + + + pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize); + + s_vGetDASA((PBYTE)pMACHeader, &cbHeaderSize, &pDevice->sRxEthHeader); + + if (bIsWEP) { + if (bExtIV) { + // strip IV&ExtIV , add 8 byte + cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 8); + } else { + // strip IV , add 4 byte + cbHeaderSize += (WLAN_HDR_ADDR3_LEN + 4); + } + } + else { + cbHeaderSize += WLAN_HDR_ADDR3_LEN; + }; + + pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize); + if (IS_ETH_ADDRESS_EQUAL(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) { + cbHeaderSize += 6; + } + else if (IS_ETH_ADDRESS_EQUAL(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { + cbHeaderSize += 6; + pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + if ((*pwType!= TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) { + } + else { + cbHeaderSize -= 8; + pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + if (bIsWEP) { + if (bExtIV) { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV + } else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV + } + } + else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); + } + } + } + else { + cbHeaderSize -= 2; + pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); + if (bIsWEP) { + if (bExtIV) { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 8); // 8 is IV&ExtIV + } else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN - 4); // 4 is IV + } + } + else { + *pwType = htons(cbPacketSize - WLAN_HDR_ADDR3_LEN); + } + } + + cbHeaderSize -= (U_ETHER_ADDR_LEN * 2); + pbyRxBuffer = (PBYTE) (pbyRxBufferAddr + cbHeaderSize); + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) + *pbyRxBuffer++ = pDevice->sRxEthHeader.abyDstAddr[ii]; + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) + *pbyRxBuffer++ = pDevice->sRxEthHeader.abySrcAddr[ii]; + + *pcbHeadSize = cbHeaderSize; +} + + + + +static BYTE s_byGetRateIdx (IN BYTE byRate) +{ + BYTE byRateIdx; + + for (byRateIdx = 0; byRateIdx <MAX_RATE ; byRateIdx++) { + if (acbyRxRate[byRateIdx%MAX_RATE] == byRate) + return byRateIdx; + } + return 0; +} + + +static +VOID +s_vGetDASA ( + IN PBYTE pbyRxBufferAddr, + OUT PUINT pcbHeaderSize, + OUT PSEthernetHeader psEthHeader + ) +{ + UINT cbHeaderSize = 0; + PS802_11Header pMACHeader; + int ii; + + pMACHeader = (PS802_11Header) (pbyRxBufferAddr + cbHeaderSize); + + if ((pMACHeader->wFrameCtl & FC_TODS) == 0) { + if (pMACHeader->wFrameCtl & FC_FROMDS) { + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) { + psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii]; + psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr3[ii]; + } + } + else { + // IBSS mode + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) { + psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr1[ii]; + psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii]; + } + } + } + else { + // Is AP mode.. + if (pMACHeader->wFrameCtl & FC_FROMDS) { + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) { + psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii]; + psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr4[ii]; + cbHeaderSize += 6; + } + } + else { + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) { + psEthHeader->abyDstAddr[ii] = pMACHeader->abyAddr3[ii]; + psEthHeader->abySrcAddr[ii] = pMACHeader->abyAddr2[ii]; + } + } + }; + *pcbHeaderSize = cbHeaderSize; +} + + + + +//PLICE_DEBUG -> + +VOID MngWorkItem(PVOID Context) +{ + PSRxMgmtPacket pRxMgmtPacket; + PSDevice pDevice = (PSDevice) Context; + //printk("Enter MngWorkItem,Queue packet num is %d\n",pDevice->rxManeQueue.packet_num); + spin_lock_irq(&pDevice->lock); + while(pDevice->rxManeQueue.packet_num != 0) + { + pRxMgmtPacket = DeQueue(pDevice); + vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket); + } + spin_unlock_irq(&pDevice->lock); +} + + +//PLICE_DEBUG<- + + + +BOOL +device_receive_frame ( + IN PSDevice pDevice, + IN PSRxDesc pCurrRD + ) +{ + + PDEVICE_RD_INFO pRDInfo = pCurrRD->pRDInfo; +#ifdef PLICE_DEBUG + //printk("device_receive_frame:pCurrRD is %x,pRDInfo is %x\n",pCurrRD,pCurrRD->pRDInfo); +#endif + struct net_device_stats* pStats=&pDevice->stats; +#ifdef PRIVATE_OBJ + ref_sk_buff* skb; +#else + struct sk_buff* skb; +#endif + PSMgmtObject pMgmt = pDevice->pMgmt; + PSRxMgmtPacket pRxPacket = &(pDevice->pMgmt->sRxPacket); + PS802_11Header p802_11Header; + PBYTE pbyRsr; + PBYTE pbyNewRsr; + PBYTE pbyRSSI; + PQWORD pqwTSFTime; + PWORD pwFrameSize; + PBYTE pbyFrame; + BOOL bDeFragRx = FALSE; + BOOL bIsWEP = FALSE; + UINT cbHeaderOffset; + UINT FrameSize; + WORD wEtherType = 0; + INT iSANodeIndex = -1; + INT iDANodeIndex = -1; + UINT ii; + UINT cbIVOffset; + BOOL bExtIV = FALSE; + PBYTE pbyRxSts; + PBYTE pbyRxRate; + PBYTE pbySQ; + UINT cbHeaderSize; + PSKeyItem pKey = NULL; + WORD wRxTSC15_0 = 0; + DWORD dwRxTSC47_16 = 0; + SKeyItem STempKey; + // 802.11h RPI + DWORD dwDuration = 0; + LONG ldBm = 0; + LONG ldBmThreshold = 0; + PS802_11Header pMACHeader; + BOOL bRxeapol_key = FALSE; + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- device_receive_frame---\n"); +#ifdef PRIVATE_OBJ + skb = &(pRDInfo->ref_skb); +#else + + skb = pRDInfo->skb; +#endif + + +//PLICE_DEBUG-> +#if 1 + pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); +#endif +//PLICE_DEBUG<- + pwFrameSize = (PWORD)(skb->data + 2); + FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount); + + // Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR + // Min (ACK): 10HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR + if ((FrameSize > 2364)||(FrameSize <= 32)) { + // Frame Size error drop this packet. + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 1 \n"); + return FALSE; + } + + pbyRxSts = (PBYTE) (skb->data); + pbyRxRate = (PBYTE) (skb->data + 1); + pbyRsr = (PBYTE) (skb->data + FrameSize - 1); + pbyRSSI = (PBYTE) (skb->data + FrameSize - 2); + pbyNewRsr = (PBYTE) (skb->data + FrameSize - 3); + pbySQ = (PBYTE) (skb->data + FrameSize - 4); + pqwTSFTime = (PQWORD) (skb->data + FrameSize - 12); + pbyFrame = (PBYTE)(skb->data + 4); + + // get packet size + FrameSize = cpu_to_le16(*pwFrameSize); + + if ((FrameSize > 2346)|(FrameSize < 14)) { // Max: 2312Payload + 30HD +4CRC + // Min: 14 bytes ACK + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 2 \n"); + return FALSE; + } +//PLICE_DEBUG-> +#if 1 + // update receive statistic counter + STAvUpdateRDStatCounter(&pDevice->scStatistic, + *pbyRsr, + *pbyNewRsr, + *pbyRxRate, + pbyFrame, + FrameSize); + +#endif + + pMACHeader=(PS802_11Header)((PBYTE) (skb->data)+8); +//PLICE_DEBUG<- + if (pDevice->bMeasureInProgress == TRUE) { + if ((*pbyRsr & RSR_CRCOK) != 0) { + pDevice->byBasicMap |= 0x01; + } + dwDuration = (FrameSize << 4); + dwDuration /= acbyRxRate[*pbyRxRate%MAX_RATE]; + if (*pbyRxRate <= RATE_11M) { + if (BITbIsBitOn(*pbyRxSts, 0x01)) { + // long preamble + dwDuration += 192; + } else { + // short preamble + dwDuration += 96; + } + } else { + dwDuration += 16; + } + RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); + ldBmThreshold = -57; + for (ii = 7; ii > 0;) { + if (ldBm > ldBmThreshold) { + break; + } + ldBmThreshold -= 5; + ii--; + } + pDevice->dwRPIs[ii] += dwDuration; + return FALSE; + } + + if (!IS_MULTICAST_ADDRESS(pbyFrame) && !IS_BROADCAST_ADDRESS(pbyFrame)) { + if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header) (skb->data + 4))) { + pDevice->s802_11Counter.FrameDuplicateCount++; + return FALSE; + } + } + + + // Use for TKIP MIC + s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader); + + // filter packet send from myself + if (IS_ETH_ADDRESS_EQUAL((PBYTE)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr)) + return FALSE; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { + if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { + p802_11Header = (PS802_11Header) (pbyFrame); + // get SA NodeIndex + if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(p802_11Header->abyAddr2), &iSANodeIndex)) { +#ifdef PRIVATE_OBJ + pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = get_jiffies(); +#else + pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; +#endif + pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; + } + } + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex) == TRUE) { + return FALSE; + } + } + if (IS_FC_WEP(pbyFrame)) { + BOOL bRxDecryOK = FALSE; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); + bIsWEP = TRUE; + if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) { + pKey = &STempKey; + pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite; + pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex; + pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength; + pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16; + pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0; + memcpy(pKey->abyKey, + &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0], + pKey->uKeyLength + ); + + bRxDecryOK = s_bHostWepRxEncryption(pDevice, + pbyFrame, + FrameSize, + pbyRsr, + pMgmt->sNodeDBTable[iSANodeIndex].bOnFly, + pKey, + pbyNewRsr, + &bExtIV, + &wRxTSC15_0, + &dwRxTSC47_16); + } else { + bRxDecryOK = s_bHandleRxEncryption(pDevice, + pbyFrame, + FrameSize, + pbyRsr, + pbyNewRsr, + &pKey, + &bExtIV, + &wRxTSC15_0, + &dwRxTSC47_16); + } + + if (bRxDecryOK) { + if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); + if ( (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || + (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + pDevice->s802_11Counter.TKIPICVErrors++; + } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) { + pDevice->s802_11Counter.CCMPDecryptErrors++; + } else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_WEP)) { +// pDevice->s802_11Counter.WEPICVErrorCount.QuadPart++; + } + } + return FALSE; + } + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); + return FALSE; + } + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) + FrameSize -= 8; // Message Integrity Code + else + FrameSize -= 4; // 4 is ICV + } + + + // + // RX OK + // + //remove the CRC length + FrameSize -= U_CRC_LEN; + + if ((BITbIsAllBitsOff(*pbyRsr, (RSR_ADDRBROAD | RSR_ADDRMULTI))) && // unicast address + (IS_FRAGMENT_PKT((skb->data+4))) + ) { + // defragment + bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header) (skb->data+4), FrameSize, bIsWEP, bExtIV); + pDevice->s802_11Counter.ReceivedFragmentCount++; + if (bDeFragRx) { + // defrag complete +#ifdef PRIVATE_OBJ + skb = &(pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].ref_skb); +#else + skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; +#endif + FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; + + } + else { + return FALSE; + } + } + + +// Management & Control frame Handle + if ((IS_TYPE_DATA((skb->data+4))) == FALSE) { + // Handle Control & Manage Frame + + if (IS_TYPE_MGMT((skb->data+4))) { + PBYTE pbyData1; + PBYTE pbyData2; + + pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4); + pRxPacket->cbMPDULen = FrameSize; + pRxPacket->uRSSI = *pbyRSSI; + pRxPacket->bySQ = *pbySQ; + HIDWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(HIDWORD(*pqwTSFTime)); + LODWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(LODWORD(*pqwTSFTime)); + if (bIsWEP) { + // strip IV + pbyData1 = WLAN_HDR_A3_DATA_PTR(skb->data+4); + pbyData2 = WLAN_HDR_A3_DATA_PTR(skb->data+4) + 4; + for (ii = 0; ii < (FrameSize - 4); ii++) { + *pbyData1 = *pbyData2; + pbyData1++; + pbyData2++; + } + } + pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); + pRxPacket->byRxChannel = (*pbyRxSts) >> 2; +//PLICE_DEBUG-> +//EnQueue(pDevice,pRxPacket); + +#ifdef THREAD + EnQueue(pDevice,pRxPacket); + + //printk("enque time is %x\n",jiffies); + //up(&pDevice->mlme_semaphore); + //Enque (pDevice->FirstRecvMngList,pDevice->LastRecvMngList,pMgmt); +#else + +#ifdef TASK_LET + EnQueue(pDevice,pRxPacket); + tasklet_schedule(&pDevice->RxMngWorkItem); +#else +//printk("RxMan\n"); + vMgrRxManagePacket((HANDLE)pDevice, pDevice->pMgmt, pRxPacket); + //tasklet_schedule(&pDevice->RxMngWorkItem); +#endif + +#endif +//PLICE_DEBUG<- + //vMgrRxManagePacket((HANDLE)pDevice, pDevice->pMgmt, pRxPacket); + // hostap Deamon handle 802.11 management + if (pDevice->bEnableHostapd) { + skb->dev = pDevice->apdev; +#ifdef PRIVATE_OBJ + ref_skb_add_offset(skb->skb, 4); + ref_skb_set_dev(pDevice->apdev, skb->skb); + skb_put(skb->skb, FrameSize); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + *(skb->pkt_type) = PACKET_OTHERHOST; + *(skb->protocol) = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb->skb); +#else + skb->data += 4; + skb->tail += 4; + skb_put(skb, FrameSize); +#if LINUX_VERSION_CODE > KERNEL_VERSION (2,6,21) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +#endif + return TRUE; + } + } + else { + // Control Frame + }; + return FALSE; + } + else { + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + //In AP mode, hw only check addr1(BSSID or RA) if equal to local MAC. + if (BITbIsBitOff(*pbyRsr, RSR_BSSIDOK)) { + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return FALSE; + } + } + else { + // discard DATA packet while not associate || BSSID error + if ((pDevice->bLinkPass == FALSE) || + BITbIsBitOff(*pbyRsr, RSR_BSSIDOK)) { + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return FALSE; + } + + //mike add:station mode check eapol-key challenge---> + { + BYTE Protocol_Version; //802.1x Authentication + BYTE Packet_Type; //802.1x Authentication + if (bIsWEP) + cbIVOffset = 8; + else + cbIVOffset = 0; + wEtherType = (skb->data[cbIVOffset + 8 + 24 + 6] << 8) | + skb->data[cbIVOffset + 8 + 24 + 6 + 1]; + Protocol_Version = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1]; + Packet_Type = skb->data[cbIVOffset + 8 + 24 + 6 + 1 +1+1]; + if (wEtherType == ETH_P_PAE) { //Protocol Type in LLC-Header + if(((Protocol_Version==1) ||(Protocol_Version==2)) && + (Packet_Type==3)) { //802.1x OR eapol-key challenge frame receive + bRxeapol_key = TRUE; + } + } + } + //mike add:station mode check eapol-key challenge<--- + } + } + +// Data frame Handle + + if (pDevice->bEnablePSMode) { + if (IS_FC_MOREDATA((skb->data+4))) { + if (BITbIsBitOn(*pbyRsr, RSR_ADDROK)) { + //PSbSendPSPOLL((PSDevice)pDevice); + } + } + else { + if (pDevice->pMgmt->bInTIMWake == TRUE) { + pDevice->pMgmt->bInTIMWake = FALSE; + } + } + }; + + // Now it only supports 802.11g Infrastructure Mode, and support rate must up to 54 Mbps + if (pDevice->bDiversityEnable && (FrameSize>50) && + (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && + (pDevice->bLinkPass == TRUE)) { + //printk("device_receive_frame: RxRate is %d\n",*pbyRxRate); + BBvAntennaDiversity(pDevice, s_byGetRateIdx(*pbyRxRate), 0); + } + + + if (pDevice->byLocalID != REV_ID_VT3253_B1) { + pDevice->uCurrRSSI = *pbyRSSI; + } + pDevice->byCurrSQ = *pbySQ; + + if ((*pbyRSSI != 0) && + (pMgmt->pCurrBSS!=NULL)) { + RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm); + // Moniter if RSSI is too strong. + pMgmt->pCurrBSS->byRSSIStatCnt++; + pMgmt->pCurrBSS->byRSSIStatCnt %= RSSI_STAT_COUNT; + pMgmt->pCurrBSS->ldBmAverage[pMgmt->pCurrBSS->byRSSIStatCnt] = ldBm; + for(ii=0;ii<RSSI_STAT_COUNT;ii++) { + if (pMgmt->pCurrBSS->ldBmAverage[ii] != 0) { + pMgmt->pCurrBSS->ldBmMAX = max(pMgmt->pCurrBSS->ldBmAverage[ii], ldBm); + } + } + } + + // ----------------------------------------------- + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnable8021x == TRUE)){ + BYTE abyMacHdr[24]; + + // Only 802.1x packet incoming allowed + if (bIsWEP) + cbIVOffset = 8; + else + cbIVOffset = 0; + wEtherType = (skb->data[cbIVOffset + 4 + 24 + 6] << 8) | + skb->data[cbIVOffset + 4 + 24 + 6 + 1]; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wEtherType = %04x \n", wEtherType); + if (wEtherType == ETH_P_PAE) { + skb->dev = pDevice->apdev; + + if (bIsWEP == TRUE) { + // strip IV header(8) + memcpy(&abyMacHdr[0], (skb->data + 4), 24); + memcpy((skb->data + 4 + cbIVOffset), &abyMacHdr[0], 24); + } +#ifdef PRIVATE_OBJ + ref_skb_add_offset(skb->skb, (cbIVOffset + 4)); + ref_skb_set_dev(pDevice->apdev, skb->skb); + skb_put(skb->skb, FrameSize); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + *(skb->pkt_type) = PACKET_OTHERHOST; + *(skb->protocol) = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb->skb); +#else + skb->data += (cbIVOffset + 4); + skb->tail += (cbIVOffset + 4); + skb_put(skb, FrameSize); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + skb->mac_header = skb->data; +#else + skb->mac.raw = skb->data; +#endif + + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +#endif + return TRUE; + +} + // check if 802.1x authorized + if (!(pMgmt->sNodeDBTable[iSANodeIndex].dwFlags & WLAN_STA_AUTHORIZED)) + return FALSE; + } + + + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + if (bIsWEP) { + FrameSize -= 8; //MIC + } + } + + //-------------------------------------------------------------------------------- + // Soft MIC + if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP)) { + if (bIsWEP) { + PDWORD pdwMIC_L; + PDWORD pdwMIC_R; + DWORD dwMIC_Priority; + DWORD dwMICKey0 = 0, dwMICKey1 = 0; + DWORD dwLocalMIC_L = 0; + DWORD dwLocalMIC_R = 0; + viawget_wpa_header *wpahdr; + + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28])); + } + else { + if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20])); + } else if ((pKey->dwKeyIndex & BIT28) == 0) { + dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[16])); + dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[20])); + } else { + dwMICKey0 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[24])); + dwMICKey1 = cpu_to_le32(*(PDWORD)(&pKey->abyKey[28])); + } + } + + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((PBYTE)&(pDevice->sRxEthHeader.abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + // 4 is Rcv buffer header, 24 is MAC Header, and 8 is IV and Ext IV. + MIC_vAppend((PBYTE)(skb->data + 4 + WLAN_HDR_ADDR3_LEN + 8), + FrameSize - WLAN_HDR_ADDR3_LEN - 8); + MIC_vGetMIC(&dwLocalMIC_L, &dwLocalMIC_R); + MIC_vUnInit(); + + pdwMIC_L = (PDWORD)(skb->data + 4 + FrameSize); + pdwMIC_R = (PDWORD)(skb->data + 4 + FrameSize + 4); + //DBG_PRN_GRP12(("RxL: %lx, RxR: %lx\n", *pdwMIC_L, *pdwMIC_R)); + //DBG_PRN_GRP12(("LocalL: %lx, LocalR: %lx\n", dwLocalMIC_L, dwLocalMIC_R)); + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwMICKey0= %lx,dwMICKey1= %lx \n", dwMICKey0, dwMICKey1); + + + if ((cpu_to_le32(*pdwMIC_L) != dwLocalMIC_L) || (cpu_to_le32(*pdwMIC_R) != dwLocalMIC_R) || + (pDevice->bRxMICFail == TRUE)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC comparison is fail!\n"); + pDevice->bRxMICFail = FALSE; + //pDevice->s802_11Counter.TKIPLocalMICFailures.QuadPart++; + pDevice->s802_11Counter.TKIPLocalMICFailures++; + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + +//2008-0409-07, <Add> by Einsn Liu + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //send event to wpa_supplicant + //if(pDevice->bWPADevEnable == TRUE) + { + union iwreq_data wrqu; + struct iw_michaelmicfailure ev; + int keyidx = pbyFrame[cbHeaderSize+3] >> 6; //top two-bits + memset(&ev, 0, sizeof(ev)); + ev.flags = keyidx & IW_MICFAILURE_KEY_ID; + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC) && + (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { + ev.flags |= IW_MICFAILURE_PAIRWISE; + } else { + ev.flags |= IW_MICFAILURE_GROUP; + } + + ev.src_addr.sa_family = ARPHRD_ETHER; + memcpy(ev.src_addr.sa_data, pMACHeader->abyAddr2, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(ev); + wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); + + } + #endif + if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC) && + (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) { + //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR; + wpahdr->type = VIAWGET_PTK_MIC_MSG; + } else { + //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_GROUP_ERROR; + wpahdr->type = VIAWGET_GTK_MIC_MSG; + } + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw=pDevice->skb->data; +#endif + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + }; + + return FALSE; + + } + } + } //---end of SOFT MIC----------------------------------------------------------------------- + + // ++++++++++ Reply Counter Check +++++++++++++ + + if ((pKey != NULL) && ((pKey->byCipherSuite == KEY_CTL_TKIP) || + (pKey->byCipherSuite == KEY_CTL_CCMP))) { + if (bIsWEP) { + WORD wLocalTSC15_0 = 0; + DWORD dwLocalTSC47_16 = 0; + ULONGLONG RSC = 0; + // endian issues + RSC = *((ULONGLONG *) &(pKey->KeyRSC)); + wLocalTSC15_0 = (WORD) RSC; + dwLocalTSC47_16 = (DWORD) (RSC>>16); + + RSC = dwRxTSC47_16; + RSC <<= 16; + RSC += wRxTSC15_0; + MEMvCopy(&(pKey->KeyRSC), &RSC, sizeof(QWORD)); + + if ( (pDevice->sMgmtObj.eCurrMode == WMAC_MODE_ESS_STA) && + (pDevice->sMgmtObj.eCurrState == WMAC_STATE_ASSOC)) { + // check RSC + if ( (wRxTSC15_0 < wLocalTSC15_0) && + (dwRxTSC47_16 <= dwLocalTSC47_16) && + !((dwRxTSC47_16 == 0) && (dwLocalTSC47_16 == 0xFFFFFFFF))) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC is illegal~~!\n "); + if (pKey->byCipherSuite == KEY_CTL_TKIP) + //pDevice->s802_11Counter.TKIPReplays.QuadPart++; + pDevice->s802_11Counter.TKIPReplays++; + else + //pDevice->s802_11Counter.CCMPReplays.QuadPart++; + pDevice->s802_11Counter.CCMPReplays++; + + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return FALSE; + } + } + } + } // ----- End of Reply Counter Check -------------------------- + + + + if ((pKey != NULL) && (bIsWEP)) { +// pDevice->s802_11Counter.DecryptSuccessCount.QuadPart++; + } + + + s_vProcessRxMACHeader(pDevice, (PBYTE)(skb->data+4), FrameSize, bIsWEP, bExtIV, &cbHeaderOffset); + FrameSize -= cbHeaderOffset; + cbHeaderOffset += 4; // 4 is Rcv buffer header + + // Null data, framesize = 14 + if (FrameSize < 15) + return FALSE; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (s_bAPModeRxData(pDevice, + skb, + FrameSize, + cbHeaderOffset, + iSANodeIndex, + iDANodeIndex + ) == FALSE) { + + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return FALSE; + } + +// if(pDevice->bRxMICFail == FALSE) { +// for (ii =0; ii < 100; ii++) +// printk(" %02x", *(skb->data + ii)); +// printk("\n"); +// } + + } + +#ifdef PRIVATE_OBJ + ref_skb_add_offset(skb->skb, cbHeaderOffset); + skb_put(skb->skb, FrameSize); + *(skb->protocol)=eth_type_trans(skb->skb, skb->dev); + +#else + skb->data += cbHeaderOffset; + skb->tail += cbHeaderOffset; + skb_put(skb, FrameSize); + skb->protocol=eth_type_trans(skb, skb->dev); +#endif + + + //drop frame not met IEEE 802.3 +/* + if (pDevice->flags & DEVICE_FLAGS_VAL_PKT_LEN) { +#ifdef PRIVATE_OBJ + if ((*(skb->protocol)==htons(ETH_P_802_3)) && + (*(skb->len)!=htons(skb->mac.ethernet->h_proto))) { +#else + if ((skb->protocol==htons(ETH_P_802_3)) && + (skb->len!=htons(skb->mac.ethernet->h_proto))) { +#endif + pStats->rx_length_errors++; + pStats->rx_dropped++; + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + } + return FALSE; + } + } +*/ + +#ifdef PRIVATE_OBJ + *(skb->ip_summed)=CHECKSUM_NONE; + pStats->rx_bytes +=*(skb->len); + pStats->rx_packets++; + netif_rx(skb->skb); +#else + skb->ip_summed=CHECKSUM_NONE; + pStats->rx_bytes +=skb->len; + pStats->rx_packets++; + netif_rx(skb); +#endif + + if (bDeFragRx) { + if (!device_alloc_frag_buf(pDevice, &pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx])) { + DEVICE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc more frag bufs\n", + pDevice->dev->name); + } + return FALSE; + } + return TRUE; +} + + +static BOOL s_bAPModeRxCtl ( + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN INT iSANodeIndex + ) +{ + PS802_11Header p802_11Header; + CMD_STATUS Status; + PSMgmtObject pMgmt = pDevice->pMgmt; + + + if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { + + p802_11Header = (PS802_11Header) (pbyFrame); + if (!IS_TYPE_MGMT(pbyFrame)) { + + // Data & PS-Poll packet + // check frame class + if (iSANodeIndex > 0) { + // frame class 3 fliter & checking + if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_AUTH) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + (PBYTE)(p802_11Header->abyAddr2), + (WLAN_MGMT_REASON_CLASS2_NONAUTH), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 1\n"); + return TRUE; + }; + if (pMgmt->sNodeDBTable[iSANodeIndex].eNodeState < NODE_ASSOC) { + // send deassoc notification + // reason = (7) class 3 received from nonassoc sta + vMgrDisassocBeginSta(pDevice, + pMgmt, + (PBYTE)(p802_11Header->abyAddr2), + (WLAN_MGMT_REASON_CLASS3_NONASSOC), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDisassocBeginSta 2\n"); + return TRUE; + }; + + if (pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable) { + // delcare received ps-poll event + if (IS_CTL_PSPOLL(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = TRUE; + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RX_PSPOLL, NULL); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 1\n"); + } + else { + // check Data PS state + // if PW bit off, send out all PS bufferring packets. + if (!IS_FC_POWERMGT(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = FALSE; + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = TRUE; + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RX_PSPOLL, NULL); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 2\n"); + } + } + } + else { + if (IS_FC_POWERMGT(pbyFrame)) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = TRUE; + // Once if STA in PS state, enable multicast bufferring + pMgmt->sNodeDBTable[0].bPSEnable = TRUE; + } + else { + // clear all pending PS frame. + if (pMgmt->sNodeDBTable[iSANodeIndex].wEnQueueCnt > 0) { + pMgmt->sNodeDBTable[iSANodeIndex].bPSEnable = FALSE; + pMgmt->sNodeDBTable[iSANodeIndex].bRxPSPoll = TRUE; + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RX_PSPOLL, NULL); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: WLAN_CMD_RX_PSPOLL 3\n"); + + } + } + } + } + else { + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + (PBYTE)(p802_11Header->abyAddr2), + (WLAN_MGMT_REASON_CLASS2_NONAUTH), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: send vMgrDeAuthenBeginSta 3\n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BSSID:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr3[0], + p802_11Header->abyAddr3[1], + p802_11Header->abyAddr3[2], + p802_11Header->abyAddr3[3], + p802_11Header->abyAddr3[4], + p802_11Header->abyAddr3[5] + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR2:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr2[0], + p802_11Header->abyAddr2[1], + p802_11Header->abyAddr2[2], + p802_11Header->abyAddr2[3], + p802_11Header->abyAddr2[4], + p802_11Header->abyAddr2[5] + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ADDR1:%02x-%02x-%02x=%02x-%02x-%02x \n", + p802_11Header->abyAddr1[0], + p802_11Header->abyAddr1[1], + p802_11Header->abyAddr1[2], + p802_11Header->abyAddr1[3], + p802_11Header->abyAddr1[4], + p802_11Header->abyAddr1[5] + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc: wFrameCtl= %x\n", p802_11Header->wFrameCtl ); + VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dpc:pDevice->byRxMode = %x\n", pDevice->byRxMode ); + return TRUE; + } + } + } + return FALSE; + +} + +static BOOL s_bHandleRxEncryption ( + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN UINT FrameSize, + IN PBYTE pbyRsr, + OUT PBYTE pbyNewRsr, + OUT PSKeyItem *pKeyOut, + OUT PBOOL pbExtIV, + OUT PWORD pwRxTSC15_0, + OUT PDWORD pdwRxTSC47_16 + ) +{ + UINT PayloadLen = FrameSize; + PBYTE pbyIV; + BYTE byKeyIdx; + PSKeyItem pKey = NULL; + BYTE byDecMode = KEY_CTL_WEP; + PSMgmtObject pMgmt = pDevice->pMgmt; + + + *pwRxTSC15_0 = 0; + *pdwRxTSC47_16 = 0; + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && + WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + pbyIV += 6; // 6 is 802.11 address4 + PayloadLen -= 6; + } + byKeyIdx = (*(pbyIV+3) & 0xc0); + byKeyIdx >>= 6; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { + if (((*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) && + (pDevice->pMgmt->byCSSPK != KEY_CTL_NONE)) { + // unicast pkt use pairwise key + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt\n"); + if (KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, 0xFFFFFFFF, &pKey) == TRUE) { + if (pDevice->pMgmt->byCSSPK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pDevice->pMgmt->byCSSPK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"unicast pkt: %d, %p\n", byDecMode, pKey); + } else { + // use group key + KeybGetKey(&(pDevice->sKey), pDevice->abyBSSID, byKeyIdx, &pKey); + if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"group pkt: %d, %d, %p\n", byKeyIdx, byDecMode, pKey); + } + } + // our WEP only support Default Key + if (pKey == NULL) { + // use default group key + KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, byKeyIdx, &pKey); + if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + } + *pKeyOut = pKey; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode); + + if (pKey == NULL) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey == NULL\n"); + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == TRUE) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + return FALSE; + } + if (byDecMode != pKey->byCipherSuite) { + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == TRUE) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + *pKeyOut = NULL; + return FALSE; + } + if (byDecMode == KEY_CTL_WEP) { + // handle WEP + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || + (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE)) { + // Software WEP + // 1. 3253A + // 2. WEP 256 + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc + MEMvCopy(pDevice->abyPRNG, pbyIV, 3); + MEMvCopy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); + + if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + } + } + } else if ((byDecMode == KEY_CTL_TKIP) || + (byDecMode == KEY_CTL_CCMP)) { + // TKIP/AES + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { + *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); + + if ((byDecMode == KEY_CTL_TKIP) && + (pDevice->byLocalID <= REV_ID_VT3253_A1)) { + // Software TKIP + // 1. 3253 A + PS802_11Header pMACHeader = (PS802_11Header) (pbyFrame); + TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); + if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); + } + } + }// end of TKIP/AES + + if ((*(pbyIV+3) & 0x20) != 0) + *pbExtIV = TRUE; + return TRUE; +} + + +static BOOL s_bHostWepRxEncryption ( + IN PSDevice pDevice, + IN PBYTE pbyFrame, + IN UINT FrameSize, + IN PBYTE pbyRsr, + IN BOOL bOnFly, + IN PSKeyItem pKey, + OUT PBYTE pbyNewRsr, + OUT PBOOL pbExtIV, + OUT PWORD pwRxTSC15_0, + OUT PDWORD pdwRxTSC47_16 + ) +{ + UINT PayloadLen = FrameSize; + PBYTE pbyIV; + BYTE byKeyIdx; + BYTE byDecMode = KEY_CTL_WEP; + PS802_11Header pMACHeader; + + + + *pwRxTSC15_0 = 0; + *pdwRxTSC47_16 = 0; + + pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN; + if ( WLAN_GET_FC_TODS(*(PWORD)pbyFrame) && + WLAN_GET_FC_FROMDS(*(PWORD)pbyFrame) ) { + pbyIV += 6; // 6 is 802.11 address4 + PayloadLen -= 6; + } + byKeyIdx = (*(pbyIV+3) & 0xc0); + byKeyIdx >>= 6; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\nKeyIdx: %d\n", byKeyIdx); + + + if (pDevice->pMgmt->byCSSGK == KEY_CTL_TKIP) + byDecMode = KEY_CTL_TKIP; + else if (pDevice->pMgmt->byCSSGK == KEY_CTL_CCMP) + byDecMode = KEY_CTL_CCMP; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"AES:%d %d %d\n", pDevice->pMgmt->byCSSPK, pDevice->pMgmt->byCSSGK, byDecMode); + + if (byDecMode != pKey->byCipherSuite) { + if (byDecMode == KEY_CTL_WEP) { +// pDevice->s802_11Counter.WEPUndecryptableCount.QuadPart++; + } else if (pDevice->bLinkPass == TRUE) { +// pDevice->s802_11Counter.DecryptFailureCount.QuadPart++; + } + return FALSE; + } + + if (byDecMode == KEY_CTL_WEP) { + // handle WEP + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP \n"); + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || + (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE) || + (bOnFly == FALSE)) { + // Software WEP + // 1. 3253A + // 2. WEP 256 + // 3. NotOnFly + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 4 + 4); // 24 is 802.11 header,4 is IV, 4 is crc + MEMvCopy(pDevice->abyPRNG, pbyIV, 3); + MEMvCopy(pDevice->abyPRNG + 3, pKey->abyKey, pKey->uKeyLength); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyIV+4, pbyIV+4, PayloadLen); + + if (ETHbIsBufferCrc32Ok(pbyIV+4, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + } + } + } else if ((byDecMode == KEY_CTL_TKIP) || + (byDecMode == KEY_CTL_CCMP)) { + // TKIP/AES + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { + *pwRxTSC15_0 = cpu_to_le16(*(PWORD)pbyIV); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"TSC0_15: %x\n", *pwRxTSC15_0); + + if (byDecMode == KEY_CTL_TKIP) { + if ((pDevice->byLocalID <= REV_ID_VT3253_A1) || (bOnFly == FALSE)) { + // Software TKIP + // 1. 3253 A + // 2. NotOnFly + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_TKIP \n"); + pMACHeader = (PS802_11Header) (pbyFrame); + TKIPvMixKey(pKey->abyKey, pMACHeader->abyAddr2, *pwRxTSC15_0, *pdwRxTSC47_16, pDevice->abyPRNG); + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyIV+8, pbyIV+8, PayloadLen); + if (ETHbIsBufferCrc32Ok(pbyIV+8, PayloadLen)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV OK!\n"); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV FAIL!!!\n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PayloadLen = %d\n", PayloadLen); + } + } + } + + if (byDecMode == KEY_CTL_CCMP) { + if (bOnFly == FALSE) { + // Software CCMP + // NotOnFly + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"soft KEY_CTL_CCMP\n"); + if (AESbGenCCMP(pKey->abyKey, pbyFrame, FrameSize)) { + *pbyNewRsr |= NEWRSR_DECRYPTOK; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC compare OK!\n"); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"CCMP MIC fail!\n"); + } + } + } + + }// end of TKIP/AES + + if ((*(pbyIV+3) & 0x20) != 0) + *pbExtIV = TRUE; + return TRUE; +} + + + + +#ifdef PRIVATE_OBJ + +static BOOL s_bAPModeRxData ( + IN PSDevice pDevice, + IN ref_sk_buff* skb, + IN UINT FrameSize, + IN UINT cbHeaderOffset, + IN INT iSANodeIndex, + IN INT iDANodeIndex + ) + +#else + +static BOOL s_bAPModeRxData ( + IN PSDevice pDevice, + IN struct sk_buff* skb, + IN UINT FrameSize, + IN UINT cbHeaderOffset, + IN INT iSANodeIndex, + IN INT iDANodeIndex + ) +#endif +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + BOOL bRelayAndForward = FALSE; + BOOL bRelayOnly = FALSE; + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + WORD wAID; +#ifdef PRIVATE_OBJ + struct sk_buff* tmp_skb; + ref_sk_buff s_ref_skb; + ref_sk_buff* skbcpy = &s_ref_skb; +#else + struct sk_buff* skbcpy = NULL; +#endif + + + + if (FrameSize > CB_MAX_BUF_SIZE) + return FALSE; + // check DA + if(IS_MULTICAST_ADDRESS((PBYTE)(skb->data+cbHeaderOffset))) { + if (pMgmt->sNodeDBTable[0].bPSEnable) { + +#ifdef PRIVATE_OBJ + tmp_skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + skbcpy = &s_ref_skb; + ref_skb_remap(pDevice->dev, skbcpy, tmp_skb); +#else + skbcpy = dev_alloc_skb((int)pDevice->rx_buf_sz); +#endif + // if any node in PS mode, buffer packet until DTIM. + if (skbcpy == NULL) { + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "relay multicast no skb available \n"); + } + else { + skbcpy->dev = pDevice->dev; +#ifdef PRIVATE_OBJ + *(skbcpy->len) = FrameSize; + memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize); + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy->skb); +#else + skbcpy->len = FrameSize; + memcpy(skbcpy->data, skb->data+cbHeaderOffset, FrameSize); + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skbcpy); +#endif + pMgmt->sNodeDBTable[0].wEnQueueCnt++; + // set tx map + pMgmt->abyPSTxMap[0] |= byMask[0]; + } + } + else { + bRelayAndForward = TRUE; + } + } + else { + // check if relay + if (BSSDBbIsSTAInNodeDB(pMgmt, (PBYTE)(skb->data+cbHeaderOffset), &iDANodeIndex)) { + if (pMgmt->sNodeDBTable[iDANodeIndex].eNodeState >= NODE_ASSOC) { + if (pMgmt->sNodeDBTable[iDANodeIndex].bPSEnable) { + // queue this skb until next PS tx, and then release. + +#ifdef PRIVATE_OBJ + ref_skb_add_offset(skb->skb, cbHeaderOffset); + skb_put(skb->skb, FrameSize); + skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb->skb); +#else + skb->data += cbHeaderOffset; + skb->tail += cbHeaderOffset; + skb_put(skb, FrameSize); + skb_queue_tail(&pMgmt->sNodeDBTable[iDANodeIndex].sTxPSQueue, skb); +#endif + pMgmt->sNodeDBTable[iDANodeIndex].wEnQueueCnt++; + wAID = pMgmt->sNodeDBTable[iDANodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "relay: index= %d, pMgmt->abyPSTxMap[%d]= %d\n", + iDANodeIndex, (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); + return TRUE; + } + else { + bRelayOnly = TRUE; + } + } + }; + } + + if (bRelayOnly || bRelayAndForward) { + // relay this packet right now + if (bRelayAndForward) + iDANodeIndex = 0; + + if ((pDevice->uAssocCount > 1) && (iDANodeIndex >= 0)) { + ROUTEbRelay(pDevice, (PBYTE)(skb->data + cbHeaderOffset), FrameSize, (UINT)iDANodeIndex); + } + + if (bRelayOnly) + return FALSE; + } + // none associate, don't forward + if (pDevice->uAssocCount == 0) + return FALSE; + + return TRUE; +} + diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h new file mode 100644 index 00000000000..68447c44dc2 --- /dev/null +++ b/drivers/staging/vt6655/dpc.h @@ -0,0 +1,75 @@ +/* + * 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: whdr.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + + +#ifndef __DPC_H__ +#define __DPC_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +BOOL +device_receive_frame ( + IN PSDevice pDevice, + IN PSRxDesc pCurrRD + ); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + +VOID MngWorkItem(PVOID Context); +#endif // __RXTX_H__ + + + diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c new file mode 100644 index 00000000000..134de869cb8 --- /dev/null +++ b/drivers/staging/vt6655/hostap.c @@ -0,0 +1,907 @@ +/* + * 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: hostap.c + * + * Purpose: handle hostap deamon ioctl input/out functions + * + * Author: Lyndon Chen + * + * Date: Oct. 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + + +#define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 +#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0 +#define HOSTAP_CRYPT_FLAG_PERMANENT BIT1 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 +#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 +#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Functions --------------------------*/ + + + + +/*--------------------- Export Variables --------------------------*/ + + +/* + * Description: + * register net_device (AP) for hostap deamon + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked) +{ + struct net_device *dev = pDevice->dev; + int ret; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name); + +#ifdef PRIVATE_OBJ + pDevice->apdev = ref_init_apdev(dev); + + if (pDevice->apdev == NULL) + return -ENOMEM; + + if (rtnl_locked) + ret = register_netdevice(pDevice->apdev); + else + ret = register_netdev(pDevice->apdev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n", + dev->name); + return -1; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n", + dev->name, pDevice->apdev->name); + +#else + pDevice->apdev = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (pDevice->apdev == NULL) + return -ENOMEM; + memset(pDevice->apdev, 0, sizeof(struct net_device)); + + pDevice->apdev->priv = pDevice; + memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN); + pDevice->apdev->hard_start_xmit = pDevice->tx_80211; + pDevice->apdev->type = ARPHRD_IEEE80211; + + pDevice->apdev->base_addr = dev->base_addr; + pDevice->apdev->irq = dev->irq; + pDevice->apdev->mem_start = dev->mem_start; + pDevice->apdev->mem_end = dev->mem_end; + sprintf(pDevice->apdev->name, "%sap", dev->name); + if (rtnl_locked) + ret = register_netdevice(pDevice->apdev); + else + ret = register_netdev(pDevice->apdev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n", + dev->name); + return -1; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n", + dev->name, pDevice->apdev->name); + + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); +#endif + + return 0; +} + +/* + * Description: + * unregister net_device(AP) + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked) +{ + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name); + + if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) { + if (rtnl_locked) + unregister_netdevice(pDevice->apdev); + else + unregister_netdev(pDevice->apdev); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->apdev->name); + } + kfree(pDevice->apdev); + pDevice->apdev = NULL; + pDevice->bEnable8021x = FALSE; + pDevice->bEnableHostWEP = FALSE; + pDevice->bEncryptionEnable = FALSE; + +//4.2007-0118-03,<Add> by EinsnLiu +//execute some clear work +pDevice->pMgmt->byCSSPK=KEY_CTL_NONE; +pDevice->pMgmt->byCSSGK=KEY_CTL_NONE; +KeyvInitTable(&pDevice->sKey,pDevice->PortOffset); + + return 0; +} + + +/* + * Description: + * Set enable/disable hostapd mode + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +int hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked) +{ + if (val < 0 || val > 1) + return -EINVAL; + + if (pDevice->bEnableHostapd == val) + return 0; + + pDevice->bEnableHostapd = val; + + if (val) + return hostap_enable_hostapd(pDevice, rtnl_locked); + else + return hostap_disable_hostapd(pDevice, rtnl_locked); +} + + +/* + * Description: + * remove station function supported for hostap deamon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_remove_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + UINT uNodeIndex; + + + if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + return -ENOENT; + } + return 0; +} + +/* + * Description: + * add a station from hostap deamon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_add_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + + if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex); + } + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability; +// TODO listenInterval +// pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = 1; + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = FALSE; + pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates; + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; + // set max basic rate + pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M; + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo); + + pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)param->u.add_sta.aid; +#ifdef PRIVATE_OBJ + pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = get_jiffies(); +#else + pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies; +#endif + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + param->sta_addr[0], + param->sta_addr[1], + param->sta_addr[2], + param->sta_addr[3], + param->sta_addr[4], + param->sta_addr[5] + ) ; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + + return 0; +} + +/* + * Description: + * get station info + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int hostap_get_info_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { +#ifdef PRIVATE_OBJ + param->u.get_info_sta.inactive_sec = + (get_jiffies() - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ; +#else + param->u.get_info_sta.inactive_sec = + (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ; +#endif + //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts; + } + else { + return -ENOENT; + } + + return 0; +} + +/* + * Description: + * reset txexec + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * TURE, FALSE + * + * Return Value: + * + */ +/* +static int hostap_reset_txexc_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0; + } + else { + return -ENOENT; + } + + return 0; +} +*/ + +/* + * Description: + * set station flag + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_flags_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or; + pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n", + (UINT)pMgmt->sNodeDBTable[uNodeIndex].dwFlags); + } + else { + return -ENOENT; + } + + return 0; +} + + + +/* + * Description: + * set generic element (wpa ie) + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_generic_element(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + + + + memcpy( pMgmt->abyWPAIE, + param->u.generic_elem.data, + param->u.generic_elem.len + ); + + pMgmt->wWPAIELen = param->u.generic_elem.len; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->wWPAIELen = %d\n", pMgmt->wWPAIELen); + + // disable wpa + if (pMgmt->wWPAIELen == 0) { + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " No WPAIE, Disable WPA \n"); + } else { + // enable wpa + if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) || + (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) { + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n"); + } else + return -EINVAL; + } + + return 0; +} + +/* + * Description: + * flush station nodes table. + * + * Parameters: + * In: + * pDevice - + * Out: + * + * Return Value: + * + */ + +static void hostap_flush_sta(PSDevice pDevice) +{ + // reserved node index =0 for multicast node. + BSSvClearNodeDBTable(pDevice, 1); + pDevice->uAssocCount = 0; + + return; +} + +/* + * Description: + * set each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_encryption(PSDevice pDevice, + struct viawget_hostapd_param *param, + int param_len) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + DWORD dwKeyIndex = 0; + BYTE abyKey[MAX_KEY_LEN]; + BYTE abySeq[MAX_KEY_LEN]; + NDIS_802_11_KEY_RSC KeyRSC; + BYTE byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + int iNodeIndex = -1; + int ii; + BOOL bKeyTableFull = FALSE; + WORD wKeyCtl = 0; + + + param->u.crypt.err = 0; +/* + if (param_len != + (int) ((char *) param->u.crypt.key - (char *) param) + + param->u.crypt.key_len) + return -EINVAL; +*/ + + if (param->u.crypt.alg > WPA_ALG_CCMP) + return -EINVAL; + + + if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n"); + return -EINVAL; + } + + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + if (param->u.crypt.idx >= MAX_GROUP_KEY) + return -EINVAL; + iNodeIndex = 0; + + } else { + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg); + + if (param->u.crypt.alg == WPA_ALG_NONE) { + + if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == TRUE) { + if (KeybRemoveKey(&(pDevice->sKey), + param->sta_addr, + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex, + pDevice->PortOffset) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n"); + } + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + } + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0; + memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + 0, + MAX_KEY_LEN + ); + + return ret; + } + + memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len); + // copy to node key tbl + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len; + memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + param->u.crypt.key, + param->u.crypt.key_len + ); + + dwKeyIndex = (DWORD)(param->u.crypt.idx); + if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->bTransmitKey = TRUE; + dwKeyIndex |= (1 << 31); + } + + if (param->u.crypt.alg == WPA_ALG_WEP) { + + if ((pDevice->bEnable8021x == FALSE) || (iNodeIndex == 0)) { + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.crypt.key_len, + NULL, + abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID); + + } else { + // 8021x enable, individual key + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(&(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex & ~(USE_KEYRSC), + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + bKeyTableFull = TRUE; + } + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = TRUE; + pMgmt->byCSSPK = KEY_CTL_WEP; + pMgmt->byCSSGK = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + return ret; + } + + if (param->u.crypt.seq) { + memcpy(&abySeq, param->u.crypt.seq, 8); + for (ii = 0 ; ii < 8 ; ii++) { + KeyRSC |= (abySeq[ii] << (ii * 8)); + } + dwKeyIndex |= 1 << 29; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC; + } + + if (param->u.crypt.alg == WPA_ALG_TKIP) { + if (param->u.crypt.key_len != MAX_KEY_LEN) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + byKeyDecMode = KEY_CTL_TKIP; + pMgmt->byCSSPK = KEY_CTL_TKIP; + pMgmt->byCSSGK = KEY_CTL_TKIP; + } + + if (param->u.crypt.alg == WPA_ALG_CCMP) { + if ((param->u.crypt.key_len != AES_KEY_LEN) || + (pDevice->byLocalID <= REV_ID_VT3253_A1)) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + byKeyDecMode = KEY_CTL_CCMP; + pMgmt->byCSSPK = KEY_CTL_CCMP; + pMgmt->byCSSGK = KEY_CTL_CCMP; + } + + + if (iNodeIndex == 0) { + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex, + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID); + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(&(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex, + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + bKeyTableFull = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n"); + } + + } + + if (bKeyTableFull == TRUE) { + wKeyCtl &= 0x7F00; // clear all key control filed + wKeyCtl |= (byKeyDecMode << 4); + wKeyCtl |= (byKeyDecMode); + wKeyCtl |= 0x0044; // use group key for all address + wKeyCtl |= 0x4000; // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int + MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID); + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx, + param->u.crypt.key_len ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4] + ); + + // set wep key + pDevice->bEncryptionEnable = TRUE; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + + return ret; +} + + + +/* + * Description: + * get each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_get_encryption(PSDevice pDevice, + struct viawget_hostapd_param *param, + int param_len) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + int ii; + int iNodeIndex =0; + + + param->u.crypt.err = 0; + + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + iNodeIndex = 0; + } else { + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex); + memset(param->u.crypt.seq, 0, 8); + for (ii = 0 ; ii < 8 ; ii++) { + param->u.crypt.seq[ii] = (BYTE)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8); + } + + return ret; +} + + +/* + * Description: + * hostap_ioctl main function supported for hostap deamon. + * + * Parameters: + * In: + * pDevice - + * iw_point - + * Out: + * + * Return Value: + * + */ + +int hostap_ioctl(PSDevice pDevice, struct iw_point *p) +{ + struct viawget_hostapd_param *param; + int ret = 0; + int ap_ioctl = 0; + + if (p->length < sizeof(struct viawget_hostapd_param) || + p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct viawget_hostapd_param *) kmalloc((int)p->length, (int)GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + ret = -EFAULT; + goto out; + } + + switch (param->cmd) { + case VIAWGET_HOSTAPD_SET_ENCRYPTION: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_set_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_ENCRYPTION: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_get_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n"); + return -EOPNOTSUPP; + break; + case VIAWGET_HOSTAPD_FLUSH: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n"); + spin_lock_irq(&pDevice->lock); + hostap_flush_sta(pDevice); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_ADD_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_add_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_REMOVE_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_remove_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_INFO_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n"); + ret = hostap_get_info_sta(pDevice, param); + ap_ioctl = 1; + break; +/* + case VIAWGET_HOSTAPD_RESET_TXEXC_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n"); + ret = hostap_reset_txexc_sta(pDevice, param); + break; +*/ + case VIAWGET_HOSTAPD_SET_FLAGS_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n"); + ret = hostap_set_flags_sta(pDevice, param); + break; + + case VIAWGET_HOSTAPD_MLME: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n"); + ret = hostap_set_generic_element(pDevice, param); + break; + + case VIAWGET_HOSTAPD_SCAN_REQ: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_STA_CLEAR_STATS: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n"); + return -EOPNOTSUPP; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_ioctl: unknown cmd=%d\n", + (int)param->cmd); + return -EOPNOTSUPP; + break; + } + + + if ((ret == 0) && ap_ioctl) { + if (copy_to_user(p->pointer, param, p->length)) { + ret = -EFAULT; + goto out; + } + } + + out: + if (param != NULL) + kfree(param); + + return ret; +} + diff --git a/drivers/staging/vt6655/hostap.h b/drivers/staging/vt6655/hostap.h new file mode 100644 index 00000000000..1fcb2f0788b --- /dev/null +++ b/drivers/staging/vt6655/hostap.h @@ -0,0 +1,94 @@ +/* + * 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: hostap.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2003 + * + */ + + +#ifndef __HOSTAP_H__ +#define __HOSTAP_H__ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +#if WIRELESS_EXT < 9 +struct iw_point { + caddr_t pointer; + __u16 length; + __u16 flags; +}; +#endif /* WIRELESS_EXT < 9 */ + +#define WLAN_RATE_1M BIT0 +#define WLAN_RATE_2M BIT1 +#define WLAN_RATE_5M5 BIT2 +#define WLAN_RATE_11M BIT3 +#define WLAN_RATE_6M BIT4 +#define WLAN_RATE_9M BIT5 +#define WLAN_RATE_12M BIT6 +#define WLAN_RATE_18M BIT7 +#define WLAN_RATE_24M BIT8 +#define WLAN_RATE_36M BIT9 +#define WLAN_RATE_48M BIT10 +#define WLAN_RATE_54M BIT11 + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ + +#ifndef ARPHRD_IEEE80211 +#define ARPHRD_IEEE80211 801 +#endif + +int hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked); +int hostap_ioctl(PSDevice pDevice, struct iw_point *p); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __HOSTAP_H__ + + + diff --git a/drivers/staging/vt6655/ioctl.c b/drivers/staging/vt6655/ioctl.c new file mode 100644 index 00000000000..4869107a2bc --- /dev/null +++ b/drivers/staging/vt6655/ioctl.c @@ -0,0 +1,775 @@ +/* + * 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: ioctl.c + * + * Purpose: private ioctl functions + * + * Author: Lyndon Chen + * + * Date: Auguest 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__IOCTL_H__) +#include "ioctl.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Functions --------------------------*/ + +#ifdef WPA_SM_Transtatus + SWPAResult wpa_Result; +#endif + + +/*--------------------- Export Variables --------------------------*/ + +int private_ioctl(PSDevice pDevice, struct ifreq *rq) { + + PSCmdRequest pReq = (PSCmdRequest)rq; + PSMgmtObject pMgmt = pDevice->pMgmt; + int result = 0; + PWLAN_IE_SSID pItemSSID; + SCmdBSSJoin sJoinCmd; + SCmdZoneTypeSet sZoneTypeCmd; + SCmdScan sScanCmd; + SCmdStartAP sStartAPCmd; + SCmdSetWEP sWEPCmd; + SCmdValue sValue; + SBSSIDList sList; + SNodeList sNodeList; + PSBSSIDList pList; + PSNodeList pNodeList; + UINT cbListCount; + PKnownBSS pBSS; + PKnownNodeDB pNode; + UINT ii, jj; + SCmdLinkStatus sLinkStatus; + BYTE abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; + BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + DWORD dwKeyIndex= 0; + BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + LONG ldBm; + + + pReq->wResult = 0; + + switch(pReq->wCmdCode) { + + case WLAN_CMD_BSS_SCAN: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin \n"); + if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) { + result = -EFAULT; + break; + }; + + pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid; + if (pItemSSID->len != 0) { + memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); + } + + if (pDevice->bMACSuspend == TRUE) { + if (pDevice->bRadioOff == TRUE) + CARDbRadioPowerOn(pDevice); + vMgrTimerInit(pDevice); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + add_timer(&pMgmt->sTimerSecondCallback); + pDevice->bMACSuspend = FALSE; + } + spin_lock_irq(&pDevice->lock); + if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0) + BSSvClearBSSList((HANDLE)pDevice, FALSE); + else + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + + if (pItemSSID->len != 0) + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID); + else + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + spin_unlock_irq(&pDevice->lock); + break; + + case WLAN_CMD_ZONETYPE_SET: + //mike add :cann't support. + result=-EOPNOTSUPP; + break; + + if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) { + result = -EFAULT; + break; + }; + + if(sZoneTypeCmd.bWrite==TRUE) { + //////write zonetype + if(sZoneTypeCmd.ZoneType == ZoneType_USA) { + //set to USA + printk("set_ZoneType:USA\n"); + } + else if(sZoneTypeCmd.ZoneType == ZoneType_Japan) { + //set to Japan + printk("set_ZoneType:Japan\n"); + } + else if(sZoneTypeCmd.ZoneType == ZoneType_Europe) { + //set to Europe + printk("set_ZoneType:Europe\n"); + } + } + else { + ///////read zonetype + BYTE zonetype=0; + + + if(zonetype == 0x00) { //USA + sZoneTypeCmd.ZoneType = ZoneType_USA; + } + else if(zonetype == 0x01) { //Japan + sZoneTypeCmd.ZoneType = ZoneType_Japan; + } + else if(zonetype == 0x02) { //Europe + sZoneTypeCmd.ZoneType = ZoneType_Europe; + } + else { //Unknow ZoneType + printk("Error:ZoneType[%x] Unknown ???\n",zonetype); + result = -EFAULT; + break; + } + if (copy_to_user(pReq->data, &sZoneTypeCmd, sizeof(SCmdZoneTypeSet))) { + result = -EFAULT; + break; + }; + } + + break; + + case WLAN_CMD_BSS_JOIN: + + if (pDevice->bMACSuspend == TRUE) { + if (pDevice->bRadioOff == TRUE) + CARDbRadioPowerOn(pDevice); + vMgrTimerInit(pDevice); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + add_timer(&pMgmt->sTimerSecondCallback); + pDevice->bMACSuspend = FALSE; + } + + if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) { + result = -EFAULT; + break; + }; + + pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid; + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); + if (sJoinCmd.wBSSType == ADHOC) { + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n"); + } + else { + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n"); + } + if (sJoinCmd.bPSEnable == TRUE) { + pDevice->ePSMode = WMAC_POWER_FAST; +// pDevice->ePSMode = WMAC_POWER_MAX; + pMgmt->wListenInterval = 2; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n"); + } + else { + pDevice->ePSMode = WMAC_POWER_CAM; + pMgmt->wListenInterval = 1; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off \n"); + } + + if (sJoinCmd.bShareKeyAuth == TRUE){ + pMgmt->bShareKeyAlgorithm = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n"); + } + else { + pMgmt->bShareKeyAlgorithm = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n"); + } + pDevice->uChannel = sJoinCmd.uChannel; + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + pMgmt->eCurrState = WMAC_STATE_IDLE; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + break; + + case WLAN_CMD_SET_WEP: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key. \n"); + memset(&sWEPCmd, 0 ,sizeof(SCmdSetWEP)); + if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) { + result = -EFAULT; + break; + }; + if (sWEPCmd.bEnableWep != TRUE) { + pDevice->bEncryptionEnable = FALSE; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + MACvDisableDefaultKey(pDevice->PortOffset); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable. \n"); + break; + } + + for (ii = 0; ii < WLAN_WEP_NKEYS; ii ++) { + if (sWEPCmd.bWepKeyAvailable[ii]) { + if (ii == sWEPCmd.byKeyIndex) + //2006-1123-02,<Modify> by EinsnLiu + //Evaluate the "dwKeyIndex" error + // dwKeyIndex |= (1 << 31); + dwKeyIndex =ii|(1 << 31); + else + dwKeyIndex = ii; + + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex, + sWEPCmd.auWepKeyLength[ii], + NULL, + (PBYTE)&sWEPCmd.abyWepKey[ii][0], + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID); + } + } + pDevice->byKeyIndex = sWEPCmd.byKeyIndex; + pDevice->bTransmitKey = TRUE; + pDevice->bEncryptionEnable = TRUE; + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + + break; + + case WLAN_CMD_GET_LINK: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status. \n"); + + memset(sLinkStatus.abySSID, 0 , WLAN_SSID_MAXLEN + 1); + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) + sLinkStatus.wBSSType = ADHOC; + else + sLinkStatus.wBSSType = INFRA; + + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) + sLinkStatus.byState = ADHOC_JOINTED; + else + sLinkStatus.byState = ADHOC_STARTED; + + sLinkStatus.uChannel = pMgmt->uCurrChannel; + if (pDevice->bLinkPass == TRUE) { + sLinkStatus.bLink = TRUE; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len); + memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Link Success ! \n"); + } + else { + sLinkStatus.bLink = FALSE; + } + if (copy_to_user(pReq->data, &sLinkStatus, sizeof(SCmdLinkStatus))) { + result = -EFAULT; + break; + }; + + break; + + case WLAN_CMD_GET_LISTLEN: + cbListCount = 0; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) + continue; + cbListCount++; + }; + sList.uItem = cbListCount; + if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) { + result = -EFAULT; + break; + }; + pReq->wResult = 0; + break; + + case WLAN_CMD_GET_LIST: + if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) { + result = -EFAULT; + break; + }; + pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC); + if (pList == NULL) { + result = -ENOMEM; + break; + } + pList->uItem = sList.uItem; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) { + pBSS = &(pMgmt->sBSSList[jj]); + if (pBSS->bActive) { + pList->sBSSIDList[ii].uChannel = pBSS->uChannel; + pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval; + pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo; +// pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; + RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); + pList->sBSSIDList[ii].uRSSI = (UINT)ldBm; + memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN); + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1); + memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len); + if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) { + pList->sBSSIDList[ii].byNetType = INFRA; + } + else { + pList->sBSSIDList[ii].byNetType = ADHOC; + } + if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) { + pList->sBSSIDList[ii].bWEPOn = TRUE; + } + else { + pList->sBSSIDList[ii].bWEPOn = FALSE; + } + ii ++; + if (ii >= pList->uItem) + break; + } + } + + if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) { + result = -EFAULT; + break; + }; + kfree(pList); + pReq->wResult = 0; + break; + + case WLAN_CMD_GET_MIB: + if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) { + result = -EFAULT; + break; + }; + break; + + case WLAN_CMD_GET_STAT: + if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) { + result = -EFAULT; + break; + }; + break; + case WLAN_CMD_STOP_MAC: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n"); + netif_stop_queue(pDevice->dev); + + spin_lock_irq(&pDevice->lock); + if (pDevice->bRadioOff == FALSE) { + CARDbRadioPowerOff(pDevice); + } + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + pDevice->bCmdRunning = FALSE; + pDevice->bMACSuspend = TRUE; + MACvIntDisable(pDevice->PortOffset); + spin_unlock_irq(&pDevice->lock); + + break; + + case WLAN_CMD_START_MAC: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n"); + + if (pDevice->bMACSuspend == TRUE) { + if (pDevice->bRadioOff == TRUE) + CARDbRadioPowerOn(pDevice); + vMgrTimerInit(pDevice); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + add_timer(&pMgmt->sTimerSecondCallback); + pDevice->bMACSuspend = FALSE; + } + break; + + case WLAN_CMD_SET_HOSTAPD: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n"); + + if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { + result = -EFAULT; + break; + }; + if (sValue.dwValue == 1) { + if (hostap_set_hostapd(pDevice, 1, 1) == 0){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n"); + } + else { + result = -EFAULT; + break; + } + } + else { + hostap_set_hostapd(pDevice, 0, 1); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n"); + } + + break; + + case WLAN_CMD_SET_HOSTAPD_STA: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n"); + + break; + case WLAN_CMD_SET_802_1X: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n"); + if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { + result = -EFAULT; + break; + }; + + if (sValue.dwValue == 1) { + pDevice->bEnable8021x = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n"); + } + else { + pDevice->bEnable8021x = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n"); + } + + break; + + + case WLAN_CMD_SET_HOST_WEP: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n"); + if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { + result = -EFAULT; + break; + }; + + if (sValue.dwValue == 1) { + pDevice->bEnableHostWEP = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n"); + } + else { + pDevice->bEnableHostWEP = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n"); + } + + break; + + case WLAN_CMD_SET_WPA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n"); + + if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) { + result = -EFAULT; + break; + }; + if (sValue.dwValue == 1) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n"); + memcpy(pDevice->wpadev->dev_addr, pDevice->dev->dev_addr, U_ETHER_ADDR_LEN); + pDevice->bWPADEVUp = TRUE; + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n"); + pDevice->bWPADEVUp = FALSE; + } + + break; + + case WLAN_CMD_AP_START: + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n"); + if (pDevice->bRadioOff == TRUE) { + CARDbRadioPowerOn(pDevice); + vMgrTimerInit(pDevice); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + add_timer(&pMgmt->sTimerSecondCallback); + } + if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) { + result = -EFAULT; + break; + }; + + if (sStartAPCmd.wBSSType == AP) { + pMgmt->eConfigMode = WMAC_CONFIG_AP; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n"); + result = -EFAULT; + break; + } + + + if (sStartAPCmd.wBBPType == PHY80211g) { + pMgmt->byAPBBType = PHY_TYPE_11G; + } + else if (sStartAPCmd.wBBPType == PHY80211a) { + pMgmt->byAPBBType = PHY_TYPE_11A; + } + else { + pMgmt->byAPBBType = PHY_TYPE_11B; + } + + pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid; + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN); + + if ((sStartAPCmd.uChannel > 0)&&(sStartAPCmd.uChannel <= 14)) + pDevice->uChannel = sStartAPCmd.uChannel; + + if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000)) + pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt; + else + pMgmt->wIBSSBeaconPeriod = 100; + + if (sStartAPCmd.bShareKeyAuth == TRUE){ + pMgmt->bShareKeyAlgorithm = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key \n"); + } + else { + pMgmt->bShareKeyAlgorithm = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System \n"); + } + memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6); + + if (sStartAPCmd.byBasicRate & BIT3) { + pMgmt->abyIBSSSuppRates[2] |= BIT7; + pMgmt->abyIBSSSuppRates[3] |= BIT7; + pMgmt->abyIBSSSuppRates[4] |= BIT7; + pMgmt->abyIBSSSuppRates[5] |= BIT7; + }else if (sStartAPCmd.byBasicRate & BIT2) { + pMgmt->abyIBSSSuppRates[2] |= BIT7; + pMgmt->abyIBSSSuppRates[3] |= BIT7; + pMgmt->abyIBSSSuppRates[4] |= BIT7; + }else if (sStartAPCmd.byBasicRate & BIT1) { + pMgmt->abyIBSSSuppRates[2] |= BIT7; + pMgmt->abyIBSSSuppRates[3] |= BIT7; + }else if (sStartAPCmd.byBasicRate & BIT1) { + pMgmt->abyIBSSSuppRates[2] |= BIT7; + }else { + //default 1,2M + pMgmt->abyIBSSSuppRates[2] |= BIT7; + pMgmt->abyIBSSSuppRates[3] |= BIT7; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n", + pMgmt->abyIBSSSuppRates[2], + pMgmt->abyIBSSSuppRates[3], + pMgmt->abyIBSSSuppRates[4], + pMgmt->abyIBSSSuppRates[5] + ); + + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_RUN_AP, NULL); + spin_unlock_irq(&pDevice->lock); + break; + + case WLAN_CMD_GET_NODE_CNT: + + cbListCount = 0; + pNode = &(pMgmt->sNodeDBTable[0]); + for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { + pNode = &(pMgmt->sNodeDBTable[ii]); + if (!pNode->bActive) + continue; + cbListCount++; + }; + + sNodeList.uItem = cbListCount; + if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) { + result = -EFAULT; + break; + }; + pReq->wResult = 0; + break; + + case WLAN_CMD_GET_NODE_LIST: + + if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) { + result = -EFAULT; + break; + }; + pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC); + if (pNodeList == NULL) { + result = -ENOMEM; + break; + } + pNodeList->uItem = sNodeList.uItem; + pNode = &(pMgmt->sNodeDBTable[0]); + for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) { + pNode = &(pMgmt->sNodeDBTable[ii]); + if (pNode->bActive) { + pNodeList->sNodeList[jj].wAID = pNode->wAID; + memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN); + pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate; + pNodeList->sNodeList[jj].wInActiveCount = (WORD)pNode->uInActiveCount; + pNodeList->sNodeList[jj].wEnQueueCnt = (WORD)pNode->wEnQueueCnt; + pNodeList->sNodeList[jj].wFlags = (WORD)pNode->dwFlags; + pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable; + pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex; + pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength; + memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + pNodeList->sNodeList[jj].abyWepKey[0], + pNodeList->sNodeList[jj].abyWepKey[1], + pNodeList->sNodeList[jj].abyWepKey[2], + pNodeList->sNodeList[jj].abyWepKey[3], + pNodeList->sNodeList[jj].abyWepKey[4] + ); + pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback; + pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures; + pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts; + pNodeList->sNodeList[jj].wFailureRatio = (WORD)pNode->uFailureRatio; + jj ++; + if (jj >= pNodeList->uItem) + break; + } + }; + if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) { + result = -EFAULT; + break; + }; + kfree(pNodeList); + pReq->wResult = 0; + break; + +#ifdef WPA_SM_Transtatus + case 0xFF: + memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname)); + wpa_Result.proto = 0; + wpa_Result.key_mgmt = 0; + wpa_Result.eap_type = 0; + wpa_Result.authenticated = FALSE; + pDevice->fWPA_Authened = FALSE; + if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) { + result = -EFAULT; + break; + } + + if(wpa_Result.authenticated==TRUE) { + #ifdef SndEvt_ToAPI + { + union iwreq_data wrqu; + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG; + wrqu.data.length =pItemSSID->len; + wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID); + } + #endif + pDevice->fWPA_Authened = TRUE; //is sucessful peer to wpa_Result.authenticated? +} + + //printk("get private wpa_supplicant announce WPA SM\n"); + //printk("wpa-->ifname=%s\n",wpa_Result.ifname); + //printk("wpa-->proto=%d\n",wpa_Result.proto); + //printk("wpa-->key-mgmt=%d\n",wpa_Result.key_mgmt); + //printk("wpa-->eap_type=%d\n",wpa_Result.eap_type); + //printk("wpa-->authenticated is %s\n",(wpa_Result.authenticated==TRUE)?"TRUE":"FALSE"); + + pReq->wResult = 0; + break; +#endif + + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not support..\n"); + } + + return result; +} + +/* +VOID +vConfigWEPKey ( + IN PSDevice pDevice, + IN DWORD dwKeyIndex, + IN PBYTE pbyKey, + IN ULONG uKeyLength + ) +{ + int ii; + + + ZERO_MEMORY(&pDevice->abyWepKey[dwKeyIndex][0], WLAN_WEPMAX_KEYLEN); + MEMvCopy(&pDevice->abyWepKey[dwKeyIndex][0], pbyKey, uKeyLength); + + pDevice->bWepKeyAvailable[dwKeyIndex] = TRUE; + pDevice->auWepKeyLength[dwKeyIndex] = uKeyLength; + + MACvSetDefaultKeyEntry(pDevice->PortOffset, uKeyLength, dwKeyIndex, + (PDWORD) &(pDevice->abyWepKey[dwKeyIndex][0]), pDevice->byLocalID); + + if (pDevice->eEncryptionStatus < Ndis802_11EncryptionNotSupported) { + for(ii=0; ii<MAX_GROUP_KEY; ii++) { + if ((pDevice->bWepKeyAvailable[ii] == TRUE) && + (pDevice->auWepKeyLength[ii] == WLAN_WEP232_KEYLEN)) { + pDevice->uCurrentWEPMode = TX_WEP_SW232; + MACvDisableDefaultKey(pDevice->PortOffset); + break; + } + } + if ((ii == MAX_GROUP_KEY) && + (pDevice->eEncryptionStatus < Ndis802_11EncryptionNotSupported)) { + MACvEnableDefaultKey(pDevice->PortOffset, pDevice->byLocalID); + } + } +} +*/ diff --git a/drivers/staging/vt6655/ioctl.h b/drivers/staging/vt6655/ioctl.h new file mode 100644 index 00000000000..9c6816eab46 --- /dev/null +++ b/drivers/staging/vt6655/ioctl.h @@ -0,0 +1,74 @@ +/* + * 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: hostap.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2003 + * + */ + + +#ifndef __IOCTL_H__ +#define __IOCTL_H__ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +int private_ioctl(PSDevice pDevice, struct ifreq *rq); + +/* +VOID vConfigWEPKey ( + IN PSDevice pDevice, + IN DWORD dwKeyIndex, + IN PBYTE pbyKey, + IN ULONG uKeyLength + ); +*/ + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __IOCTL_H__ + + + diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c new file mode 100644 index 00000000000..160baf0abc0 --- /dev/null +++ b/drivers/staging/vt6655/iwctl.c @@ -0,0 +1,2453 @@ +/* + * 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: iwctl.c + * + * Purpose: wireless ext & ioctl functions + * + * Author: Lyndon Chen + * + * Date: July 5, 2006 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__IOCTL_H__) +#include "ioctl.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif + +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#endif + +#if WIRELESS_EXT > 12 +#include <net/iw_handler.h> +#endif +extern WORD TxRate_iwconfig;//2008-5-8 <add> by chester + +/*--------------------- Static Definitions -------------------------*/ + +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +#define SUPPORTED_WIRELESS_EXT 18 +#else +#define SUPPORTED_WIRELESS_EXT 17 +#endif + +#ifdef WIRELESS_EXT + +static const long frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484, + 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980, + 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240, + 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, + 5700, 5745, 5765, 5785, 5805, 5825 + }; + +#endif + + +/*--------------------- Static Classes ----------------------------*/ + + +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + + +/*--------------------- Static Variables --------------------------*/ +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +#ifdef WIRELESS_EXT + +#if WIRELESS_EXT > 12 + +struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) +{ + PSDevice pDevice = dev->priv; + long ldBm; + pDevice->wstats.status = pDevice->eOPMode; + #ifdef Calcu_LinkQual + #if 0 + if(pDevice->byBBType == BB_TYPE_11B) { + if(pDevice->byCurrSQ > 120) + pDevice->scStatistic.LinkQuality = 100; + else + pDevice->scStatistic.LinkQuality = pDevice->byCurrSQ*100/120; + } + else if(pDevice->byBBType == BB_TYPE_11G) { + if(pDevice->byCurrSQ < 20) + pDevice->scStatistic.LinkQuality = 100; + else if(pDevice->byCurrSQ >96) + pDevice->scStatistic.LinkQuality = 0; + else + pDevice->scStatistic.LinkQuality = (96-pDevice->byCurrSQ)*100/76; + } + if(pDevice->bLinkPass !=TRUE) + pDevice->scStatistic.LinkQuality = 0; + #endif + if(pDevice->scStatistic.LinkQuality > 100) + pDevice->scStatistic.LinkQuality = 100; + pDevice->wstats.qual.qual =(BYTE) pDevice->scStatistic.LinkQuality; + #else + pDevice->wstats.qual.qual = pDevice->byCurrSQ; + #endif + RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm); + pDevice->wstats.qual.level = ldBm; + //pDevice->wstats.qual.level = 0x100 - pDevice->uCurrRSSI; + pDevice->wstats.qual.noise = 0; + pDevice->wstats.qual.updated = 1; + pDevice->wstats.discard.nwid = 0; + pDevice->wstats.discard.code = 0; + pDevice->wstats.discard.fragment = 0; + pDevice->wstats.discard.retries = (U32)pDevice->scStatistic.dwTsrErr; + pDevice->wstats.discard.misc = 0; + pDevice->wstats.miss.beacon = 0; + + return &pDevice->wstats; +} + +#endif + + + +/*------------------------------------------------------------------*/ + + +static int iwctl_commit(struct net_device *dev, + struct iw_request_info *info, + void *wrq, + char *extra) +{ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWCOMMIT \n"); + + return 0; + +} + +/* + * Wireless Handler : get protocol name + */ + +int iwctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *wrq, + char *extra) +{ + strcpy(wrq, "802.11-a/b/g"); + return 0; +} + +int iwctl_giwnwid(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + //wrq->value = 0x100; + //wrq->disabled = 0; + //wrq->fixed = 1; + //return 0; + return -EOPNOTSUPP; +} +#if WIRELESS_EXT > 13 + +/* + * Wireless Handler : set scan + */ + +int iwctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + struct iw_scan_req *req = (struct iw_scan_req *)extra; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + PWLAN_IE_SSID pItemSSID=NULL; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSCAN \n"); + + +if(pDevice->byReAssocCount > 0) { //reject scan when re-associating! +//send scan event to wpa_Supplicant + union iwreq_data wrqu; + printk("wireless_send_event--->SIOCGIWSCAN(scan done)\n"); + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL); + return 0; +} + + spin_lock_irq(&pDevice->lock); + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + +//mike add: active scan OR passive scan OR desire_ssid scan + if(wrq->length == sizeof(struct iw_scan_req)) { + if (wrq->flags & IW_SCAN_THIS_ESSID) { //desire_ssid scan + memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)abyScanSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len); + if (pItemSSID->abySSID[req->essid_len - 1] == '\0') { + if(req->essid_len>0) + pItemSSID->len = req->essid_len - 1; + } + else + pItemSSID->len = req->essid_len; + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + printk("SIOCSIWSCAN:[desired_ssid=%s,len=%d]\n",((PWLAN_IE_SSID)abyScanSSID)->abySSID, + ((PWLAN_IE_SSID)abyScanSSID)->len); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, abyScanSSID); + spin_unlock_irq(&pDevice->lock); + + return 0; + } + else if(req->scan_type == IW_SCAN_TYPE_PASSIVE) { //passive scan + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + } + } + else { //active scan + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + } + + pMgmt->eScanType = WMAC_SCAN_PASSIVE; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + spin_unlock_irq(&pDevice->lock); + + return 0; +} + + +/* + * Wireless Handler : get scan results + */ + +int iwctl_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + int ii, jj, kk; + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PKnownBSS pBSS; + PWLAN_IE_SSID pItemSSID; + PWLAN_IE_SUPP_RATES pSuppRates, pExtSuppRates; + char *current_ev = extra; + char *end_buf = extra + IW_SCAN_MAX_DATA; + char *current_val = NULL; + struct iw_event iwe; + long ldBm; +#if WIRELESS_EXT > 14 + char buf[MAX_WPA_IE_LEN * 2 + 30]; +#endif /* WIRELESS_EXT > 14 */ + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN \n"); + + if (pMgmt->eScanState == WMAC_IS_SCANNING) { + // In scanning.. + return -EAGAIN; + } + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) { + if (current_ev >= end_buf) + break; + pBSS = &(pMgmt->sBSSList[jj]); + if (pBSS->bActive) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + #else + current_ev = iwe_stream_add_event(current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + #endif + //ADD ssid + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + iwe.u.data.length = pItemSSID->len; + iwe.u.data.flags = 1; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID); + #else + current_ev = iwe_stream_add_point(current_ev,end_buf, &iwe, pItemSSID->abySSID); + #endif + //ADD mode + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) { + iwe.u.mode = IW_MODE_INFRA; + } + else { + iwe.u.mode = IW_MODE_ADHOC; + } + iwe.len = IW_EV_UINT_LEN; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + #else + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + #endif + //ADD frequency + pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates; + pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = pBSS->uChannel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + #else + current_ev = iwe_stream_add_event(current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + #endif + + + //2008-0409-04, <Add> by Einsn Liu + { + int f = (int)pBSS->uChannel - 1; + if(f < 0)f = 0; + iwe.u.freq.m = frequency_list[f] * 100000; + iwe.u.freq.e = 1; + } + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + #else + current_ev = iwe_stream_add_event(current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + #endif + //ADD quality + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm); + iwe.u.qual.level = ldBm; + iwe.u.qual.noise = 0; +//2008-0409-01, <Add> by Einsn Liu + if(-ldBm<50){ + iwe.u.qual.qual = 100; + }else if(-ldBm > 90) { + iwe.u.qual.qual = 0; + }else { + iwe.u.qual.qual=(40-(-ldBm-50))*100/40; + } + iwe.u.qual.updated=7; + + // iwe.u.qual.qual = 0; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + #else + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + #endif + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) { + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + }else { + iwe.u.data.flags = IW_ENCODE_DISABLED; + } + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID); + #else + current_ev = iwe_stream_add_point(current_ev,end_buf, &iwe, pItemSSID->abySSID); + #endif + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + current_val = current_ev + IW_EV_LCP_LEN; + + for (kk = 0 ; kk < 12 ; kk++) { + if (pSuppRates->abyRates[kk] == 0) + break; + // Bit rate given in 500 kb/s units (+ 0x80) + iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + #else + current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + #endif + } + for (kk = 0 ; kk < 8 ; kk++) { + if (pExtSuppRates->abyRates[kk] == 0) + break; + // Bit rate given in 500 kb/s units (+ 0x80) + iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + #else + current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + #endif + } + + if((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + +#if WIRELESS_EXT > 14 + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval); + iwe.u.data.length = strlen(buf); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, buf); + #else + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + #endif + +#if WIRELESS_EXT > 17 + if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pBSS->wWPALen; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byWPAIE); + #else + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, pBSS->byWPAIE); + #endif + } + + if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pBSS->wRSNLen; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byRSNIE); + #else + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, pBSS->byRSNIE); + #endif + } + +#else // WIRELESS_EXT > 17 + if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) { + u8 *p = buf; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + p += sprintf(p, "wpa_ie="); + for (ii = 0; ii < pBSS->wWPALen; ii++) { + p += sprintf(p, "%02x", pBSS->byWPAIE[ii]); + } + iwe.u.data.length = strlen(buf); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, buf); + #else + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + #endif + } + + + if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) { + u8 *p = buf; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + p += sprintf(p, "rsn_ie="); + for (ii = 0; ii < pBSS->wRSNLen; ii++) { + p += sprintf(p, "%02x", pBSS->byRSNIE[ii]); + } + iwe.u.data.length = strlen(buf); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) //mike add + current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, buf); + #else + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + #endif + } +#endif +#endif + } + }// for + + wrq->length = current_ev - extra; + return 0; + +} + +#endif /* WIRELESS_EXT > 13 */ + + +/* + * Wireless Handler : set frequence or channel + */ + +int iwctl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + int rc = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ \n"); + + // If setting by frequency, convert to a channel + if((wrq->e == 1) && + (wrq->m >= (int) 2.412e8) && + (wrq->m <= (int) 2.487e8)) { + int f = wrq->m / 100000; + int c = 0; + while((c < 14) && (f != frequency_list[c])) + c++; + wrq->e = 0; + wrq->m = c + 1; + } + // Setting by channel number + if((wrq->m > 14) || (wrq->e > 0)) + rc = -EOPNOTSUPP; + else { + int channel = wrq->m; + if((channel < 1) || (channel > 14)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: New channel value of %d is invalid!\n", dev->name, wrq->m); + rc = -EINVAL; + } else { + // Yes ! We can set it !!! + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set to channel = %d\n", channel); + pDevice->uChannel = channel; + //2007-0207-04,<Add> by EinsnLiu + //Make change effect at once + pDevice->bCommit = TRUE; + } + } + + return rc; +} + +/* + * Wireless Handler : get frequence or channel + */ + +int iwctl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ \n"); + +#ifdef WEXT_USECHANNELS + wrq->m = (int)pMgmt->uCurrChannel; + wrq->e = 0; +#else + { + int f = (int)pMgmt->uCurrChannel - 1; + if(f < 0) + f = 0; + wrq->m = frequency_list[f] * 100000; + wrq->e = 1; + } +#endif + + return 0; +} + +/* + * Wireless Handler : set operation mode + */ + +int iwctl_siwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *wmode, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int rc = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE \n"); + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Can't set operation mode, hostapd is running \n"); + return rc; + } + + switch(*wmode) { + + case IW_MODE_ADHOC: + if (pMgmt->eConfigMode != WMAC_CONFIG_IBSS_STA) { + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + pDevice->bCommit = TRUE; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n"); + break; + case IW_MODE_AUTO: + case IW_MODE_INFRA: + if (pMgmt->eConfigMode != WMAC_CONFIG_ESS_STA) { + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + pDevice->bCommit = TRUE; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n"); + break; + case IW_MODE_MASTER: + + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + rc = -EOPNOTSUPP; + break; + + if (pMgmt->eConfigMode != WMAC_CONFIG_AP) { + pMgmt->eConfigMode = WMAC_CONFIG_AP; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + pDevice->bCommit = TRUE; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n"); + break; + + case IW_MODE_REPEAT: + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + rc = -EOPNOTSUPP; + break; + default: + rc = -EINVAL; + } + + return rc; +} + +/* + * Wireless Handler : get operation mode + */ + +int iwctl_giwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *wmode, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE \n"); + // If not managed, assume it's ad-hoc + switch (pMgmt->eConfigMode) { + case WMAC_CONFIG_ESS_STA: + *wmode = IW_MODE_INFRA; + break; + case WMAC_CONFIG_IBSS_STA: + *wmode = IW_MODE_ADHOC; + break; + case WMAC_CONFIG_AUTO: + *wmode = IW_MODE_INFRA; + break; + case WMAC_CONFIG_AP: + *wmode = IW_MODE_MASTER; + break; + default: + *wmode = IW_MODE_ADHOC; + } + + return 0; +} + + +/* + * Wireless Handler : get capability range + */ + +int iwctl_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + struct iw_range *range = (struct iw_range *) extra; + int i,k; + BYTE abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90}; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRANGE \n"); + if (wrq->pointer) { + wrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + range->min_nwid = 0x0000; + range->max_nwid = 0x0000; + range->num_channels = 14; + // Should be based on cap_rid.country to give only + // what the current card support + k = 0; + for(i = 0; i < 14; i++) { + range->freq[k].i = i + 1; // List index + range->freq[k].m = frequency_list[i] * 100000; + range->freq[k++].e = 1; // Values in table in MHz -> * 10^5 * 10 + } + range->num_frequency = k; + // Hum... Should put the right values there + #ifdef Calcu_LinkQual + range->max_qual.qual = 100; + #else + range->max_qual.qual = 255; + #endif + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->sensitivity = 255; + + for(i = 0 ; i < 13 ; i++) { + range->bitrate[i] = abySupportedRates[i] * 500000; + if(range->bitrate[i] == 0) + break; + } + range->num_bitrates = i; + + // Set an indication of the max TCP throughput + // in bit/s that we can expect using this interface. + // May be use for QoS stuff... Jean II + if(i > 2) + range->throughput = 5 * 1000 * 1000; + else + range->throughput = 1.5 * 1000 * 1000; + + range->min_rts = 0; + range->max_rts = 2312; + range->min_frag = 256; + range->max_frag = 2312; + + + // the encoding capabilities + range->num_encoding_sizes = 3; + // 64(40) bits WEP + range->encoding_size[0] = 5; + // 128(104) bits WEP + range->encoding_size[1] = 13; + // 256 bits for WPA-PSK + range->encoding_size[2] = 32; + // 4 keys are allowed + range->max_encoding_tokens = 4; + +#if WIRELESS_EXT > 17 + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif + +#if WIRELESS_EXT > 9 + range->min_pmp = 0; + range->max_pmp = 1000000;// 1 secs + range->min_pmt = 0; + range->max_pmt = 1000000;// 1 secs + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + + // Transmit Power - values are in mW + + range->txpower[0] = 100; + range->num_txpower = 1; + range->txpower_capa = IW_TXPOW_MWATT; +#endif // WIRELESS_EXT > 9 +#if WIRELESS_EXT > 10 + range->we_version_source = SUPPORTED_WIRELESS_EXT; + range->we_version_compiled = WIRELESS_EXT; + range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = IW_RETRY_LIFETIME; + range->min_retry = 1; + range->max_retry = 65535; + range->min_r_time = 1024; + range->max_r_time = 65535 * 1024; +#endif // WIRELESS_EXT > 10 +#if WIRELESS_EXT > 11 + // Experimental measurements - boundary 11/5.5 Mb/s + // Note : with or without the (local->rssi), results + // are somewhat different. - Jean II + range->avg_qual.qual = 6; + range->avg_qual.level = 176; // -80 dBm + range->avg_qual.noise = 0; +#endif // WIRELESS_EXT > 11 + } + + + return 0; +} + + +/* + * Wireless Handler : set ap mac address + */ + +int iwctl_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int rc = 0; + BYTE ZeroBSSID[WLAN_BSSID_LEN]={0x00,0x00,0x00,0x00,0x00,0x00}; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAP \n"); +if (pMgmt->eScanState == WMAC_IS_SCANNING) { + // In scanning.. + printk("SIOCSIWAP(??)-->In scanning...\n"); + // return -EAGAIN; + } + if (wrq->sa_family != ARPHRD_ETHER) + rc = -EINVAL; + else { + memset(pMgmt->abyDesireBSSID, 0xFF, 6); + memcpy(pMgmt->abyDesireBSSID, wrq->sa_data, 6); + //2008-0409-05, <Add> by Einsn Liu + if((pDevice->bLinkPass == TRUE) && + (memcmp(pMgmt->abyDesireBSSID, pMgmt->abyCurrBSSID, 6)== 0)){ + return rc; + } + //mike :add + if ((IS_BROADCAST_ADDRESS(pMgmt->abyDesireBSSID)) || + (memcmp(pMgmt->abyDesireBSSID, ZeroBSSID, 6) == 0)){ + printk("SIOCSIWAP:invalid desired BSSID return!\n"); + return rc; + } + //mike add: if desired AP is hidden ssid(there are two same BSSID in list), + // then ignore,because you don't known which one to be connect with?? + { + UINT ii , uSameBssidNum=0; + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive && + IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID,pMgmt->abyDesireBSSID)) { + uSameBssidNum++; + } + } + if(uSameBssidNum >= 2) { //hit: desired AP is in hidden ssid mode!!! + printk("SIOCSIWAP:ignore for desired AP in hidden mode\n"); + return rc; + } + } + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + pDevice->bCommit = TRUE; + } + } + return rc; +} + +/* + * Wireless Handler : get ap mac address + */ + +int iwctl_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP \n"); + + memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6); + //2008-0410,<Modify> by Einsn Liu + if ((pDevice->bLinkPass == FALSE) && (pMgmt->eCurrMode != WMAC_MODE_ESS_AP)) + memset(wrq->sa_data, 0, 6); + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6); + } + + wrq->sa_family = ARPHRD_ETHER; + + return 0; + +} + + +/* + * Wireless Handler : get ap list + */ + +int iwctl_giwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + int ii,jj, rc = 0; + struct sockaddr sock[IW_MAX_AP]; + struct iw_quality qual[IW_MAX_AP]; + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST \n"); + // Only super-user can see AP list + + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + return rc; + } + + if (wrq->pointer) { + + PKnownBSS pBSS = &(pMgmt->sBSSList[0]); + + for (ii = 0, jj= 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) + continue; + if ( jj >= IW_MAX_AP) + break; + memcpy(sock[jj].sa_data, pBSS->abyBSSID, 6); + sock[jj].sa_family = ARPHRD_ETHER; + qual[jj].level = pBSS->uRSSI; + qual[jj].qual = qual[jj].noise = 0; + qual[jj].updated = 2; + jj++; + } + + wrq->flags = 1; // Should be define'd + wrq->length = jj; + memcpy(extra, sock, sizeof(struct sockaddr)*jj); + memcpy(extra + sizeof(struct sockaddr)*jj, qual, sizeof(struct iw_quality)*jj); + } + + return rc; +} + + +/* + * Wireless Handler : set essid + */ + +int iwctl_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PWLAN_IE_SSID pItemSSID; + //2008-0409-05, <Add> by Einsn Liu + BYTE len; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWESSID \n"); + pDevice->fWPA_Authened = FALSE; +if (pMgmt->eScanState == WMAC_IS_SCANNING) { + // In scanning.. + printk("SIOCSIWESSID(??)-->In scanning...\n"); + // return -EAGAIN; + } + // Check if we asked for `any' + if(wrq->flags == 0) { + // Just send an empty SSID list + // Just send an empty SSID list + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memset(pMgmt->abyDesireBSSID, 0xFF,6); + printk("set essid to 'any' \n"); + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //Unknown desired AP,so here need not associate?? + //if(pDevice->bWPASuppWextEnabled == TRUE) { + return 0; + // } + #endif + } else { + // Set the SSID + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + memcpy(pItemSSID->abySSID, extra, wrq->length); + if (pItemSSID->abySSID[wrq->length - 1] == '\0') { + if(wrq->length>0) + pItemSSID->len = wrq->length - 1; + } + else + pItemSSID->len = wrq->length; + printk("set essid to %s \n",pItemSSID->abySSID); + //2008-0409-05, <Add> by Einsn Liu + len=(pItemSSID->len > ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len)?pItemSSID->len:((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len; + if((pDevice->bLinkPass == TRUE) && + (memcmp(pItemSSID->abySSID,((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID,len)==0)) + return 0; + + //mike:need clear desiredBSSID + if(pItemSSID->len==0) { + memset(pMgmt->abyDesireBSSID, 0xFF,6); + return 0; + } + +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //Wext wil order another command of siwap to link with desired AP, + //so here need not associate?? + if(pDevice->bWPASuppWextEnabled == TRUE) { + /*******search if in hidden ssid mode ****/ + { + PKnownBSS pCurr = NULL; + BYTE abyTmpDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + UINT ii , uSameBssidNum=0; + + memset(abyTmpDesireSSID,0,sizeof(abyTmpDesireSSID)); + memcpy(abyTmpDesireSSID,pMgmt->abyDesireSSID,sizeof(abyTmpDesireSSID)); + pCurr = BSSpSearchBSSList(pDevice, + NULL, + abyTmpDesireSSID, + pMgmt->eConfigPHYMode + ); + + if (pCurr == NULL){ + printk("SIOCSIWESSID:hidden ssid site survey before associate.......\n"); + vResetCommandTimer((HANDLE) pDevice); + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID); + } + else { //mike:to find out if that desired SSID is a hidden-ssid AP , + // by means of judging if there are two same BSSID exist in list ? + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive && + IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { + uSameBssidNum++; + } + } + if(uSameBssidNum >= 2) { //hit: desired AP is in hidden ssid mode!!! + printk("SIOCSIWESSID:hidden ssid directly associate.......\n"); + vResetCommandTimer((HANDLE) pDevice); + pMgmt->eScanType = WMAC_SCAN_PASSIVE; //this scan type,you'll submit scan result! + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, pMgmt->abyDesireSSID); + } + } + } + return 0; + } + #endif + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID); +/* + #if WIRELESS_EXT < 21 + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO " SIOCSIWESSID1 \n"); + pItemSSID->len = wrq->length - 1; + #else + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO " SIOCSIWESSID2 \n"); + pItemSSID->len = wrq->length; + #endif + */ + } + + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + pDevice->bCommit = TRUE; + } + + + return 0; +} + + +/* + * Wireless Handler : get essid + */ + +int iwctl_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + PWLAN_IE_SSID pItemSSID; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID \n"); + + // Note : if wrq->u.data.flags != 0, we should + // get the relevant SSID from the SSID list... + + // Get the current SSID + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + //pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + memcpy(extra, pItemSSID->abySSID , pItemSSID->len); + extra[pItemSSID->len] = '\0'; + wrq->length = pItemSSID->len + 1; + //2008-0409-03, <Add> by Einsn Liu + #if WIRELESS_EXT < 21 + wrq->length = pItemSSID->len + 1; + #else + wrq->length = pItemSSID->len; + #endif + wrq->flags = 1; // active + + + return 0; +} + +/* + * Wireless Handler : set data rate + */ + +int iwctl_siwrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + int rc = 0; + u8 brate = 0; + int i; + BYTE abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90}; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n"); + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EINVAL; + return rc; + } + + // First : get a valid bit rate value + + // Which type of value + if((wrq->value < 13) && + (wrq->value >= 0)) { + // Setting by rate index + // Find value in the magic rate table + brate = wrq->value; + } else { + // Setting by frequency value + u8 normvalue = (u8) (wrq->value/500000); + + // Check if rate is valid + for(i = 0 ; i < 13 ; i++) { + if(normvalue == abySupportedRates[i]) { + brate = i; + break; + } + } + } + // -1 designed the max rate (mostly auto mode) + if(wrq->value == -1) { + // Get the highest available rate + for(i = 0 ; i < 13 ; i++) { + if(abySupportedRates[i] == 0) + break; + } + if(i != 0) + brate = i - 1; + + } + // Check that it is valid + // brate is index of abySupportedRates[] + if(brate > 13 ) { + rc = -EINVAL; + return rc; + } + + // Now, check if we want a fixed or auto value + if(wrq->fixed != 0) { + // Fixed mode + // One rate, fixed + printk("Rate Fix\n"); + pDevice->bFixRate = TRUE; + if ((pDevice->byBBType == BB_TYPE_11B)&& (brate > 3)) { + + pDevice->uConnectionRate = 3; + } + else { + pDevice->uConnectionRate = brate; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate); + } + + } + else { + pDevice->bFixRate = FALSE; + pDevice->uConnectionRate = 13; + printk("auto rate:connection_rate is 13\n"); +} + + return rc; +} + +/* + * Wireless Handler : get data rate + */ + +int iwctl_giwrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; +//2007-0118-05,<Mark> by EinsnLiu +//Mark the unnecessary sentences. +// PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE \n"); + { + BYTE abySupportedRates[13]= {0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90}; + int brate = 0; +//2008-5-8 <modify> by chester +if(pDevice->bLinkPass){ +if(pDevice->bFixRate == TRUE){ + if (pDevice->uConnectionRate < 13) { + brate = abySupportedRates[pDevice->uConnectionRate]; + }else { + if (pDevice->byBBType == BB_TYPE_11B) + brate = 0x16; + if (pDevice->byBBType == BB_TYPE_11G) + brate = 0x6C; + if (pDevice->byBBType == BB_TYPE_11A) + brate = 0x6C; + } +} +else +{ + + brate = abySupportedRates[TxRate_iwconfig]; +} +} +else brate =0; +//2007-0118-05,<Mark> by EinsnLiu +//Mark the unnecessary sentences. +/* + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->byBBType == BB_TYPE_11B) + brate = 0x16; + if (pDevice->byBBType == BB_TYPE_11G) + brate = 0x6C; + if (pDevice->byBBType == BB_TYPE_11A) + brate = 0x6C; + } +*/ + +// if (pDevice->uConnectionRate == 13) +// brate = abySupportedRates[pDevice->wCurrentRate]; + wrq->value = brate * 500000; + // If more than one rate, set auto + if (pDevice->bFixRate == TRUE) + wrq->fixed = TRUE; + } + + + return 0; +} + + + +/* + * Wireless Handler : set rts threshold + */ + +int iwctl_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + int rc = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRTS \n"); + + { + int rthr = wrq->value; + if(wrq->disabled) + rthr = 2312; + if((rthr < 0) || (rthr > 2312)) { + rc = -EINVAL; + }else { + pDevice->wRTSThreshold = rthr; + } + } + + return 0; +} + +/* + * Wireless Handler : get rts + */ + +int iwctl_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS \n"); + wrq->value = pDevice->wRTSThreshold; + wrq->disabled = (wrq->value >= 2312); + wrq->fixed = 1; + + return 0; +} + +/* + * Wireless Handler : set fragment threshold + */ + +int iwctl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + int rc = 0; + int fthr = wrq->value; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG \n"); + + + if (wrq->disabled) + fthr = 2312; + if((fthr < 256) || (fthr > 2312)) { + rc = -EINVAL; + }else { + fthr &= ~0x1; // Get an even value + pDevice->wFragmentationThreshold = (u16)fthr; + } + + return rc; +} + +/* + * Wireless Handler : get fragment threshold + */ + +int iwctl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG \n"); + wrq->value = pDevice->wFragmentationThreshold; + wrq->disabled = (wrq->value >= 2312); + wrq->fixed = 1; + + return 0; +} + + + +/* + * Wireless Handler : set retry threshold + */ +int iwctl_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + int rc = 0; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY \n"); + + if (wrq->disabled) { + rc = -EINVAL; + return rc; + } + + if (wrq->flags & IW_RETRY_LIMIT) { + if(wrq->flags & IW_RETRY_MAX) + pDevice->byLongRetryLimit = wrq->value; + else if (wrq->flags & IW_RETRY_MIN) + pDevice->byShortRetryLimit = wrq->value; + else { + // No modifier : set both + pDevice->byShortRetryLimit = wrq->value; + pDevice->byLongRetryLimit = wrq->value; + } + } + if (wrq->flags & IW_RETRY_LIFETIME) { + pDevice->wMaxTransmitMSDULifetime = wrq->value; + } + + + return rc; +} + +/* + * Wireless Handler : get retry threshold + */ +int iwctl_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY \n"); + wrq->disabled = 0; // Can't be disabled + + // Note : by default, display the min retry number + if((wrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + wrq->flags = IW_RETRY_LIFETIME; + wrq->value = (int)pDevice->wMaxTransmitMSDULifetime; //ms + } else if((wrq->flags & IW_RETRY_MAX)) { + wrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + wrq->value = (int)pDevice->byLongRetryLimit; + } else { + wrq->flags = IW_RETRY_LIMIT; + wrq->value = (int)pDevice->byShortRetryLimit; + if((int)pDevice->byShortRetryLimit != (int)pDevice->byLongRetryLimit) + wrq->flags |= IW_RETRY_MIN; + } + + + return 0; +} + + +/* + * Wireless Handler : set encode mode + */ +int iwctl_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + DWORD dwKeyIndex = (DWORD)(wrq->flags & IW_ENCODE_INDEX); + int ii,uu, rc = 0; + int index = (wrq->flags & IW_ENCODE_INDEX); + +//2007-0207-07,<Modify> by EinsnLiu +//There are some problems when using iwconfig encode/key command to set the WEP key. +//I almost rewrite this function. +//now it support:(assume the wireless interface's name is eth0) +//iwconfig eth0 key [1] 1122334455 open /*set key stirng to index 1,and driver using key index is set to 1*/ +//iwconfig eth0 key [3] /*set driver using key index to 3,the key string no change */ +//iwconfig eth0 key 1122334455 /*set key string to driver using index*/ +//iwconfig eth0 key restricted /*enable share key*/ + + PSKeyTable pkeytab; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n"); + +if((wrq->flags & IW_ENCODE_DISABLED)==0){ + //Not disable encryption + + if (dwKeyIndex > WLAN_WEP_NKEYS) { + rc = -EINVAL; + return rc; + } + + if(dwKeyIndex<1&&((wrq->flags&IW_ENCODE_NOKEY)==0)){//set default key + if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){ + dwKeyIndex=pDevice->byKeyIndex; + } + else dwKeyIndex=0; + }else dwKeyIndex--; + + + // Check the size of the key + if (wrq->length > WLAN_WEP232_KEYLEN) { + rc = -EINVAL; + return rc; + } + + if(wrq->length>0){//have key + + if (wrq->length == WLAN_WEP232_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n"); + } + else if (wrq->length == WLAN_WEP104_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n"); + } + else if (wrq->length == WLAN_WEP40_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex); + }else {//no support length + rc = -EINVAL; + return rc; + } + memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN); + memcpy(pDevice->abyKey, extra, wrq->length); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: "); + for (ii = 0; ii < wrq->length; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]); + } + + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + KeybSetDefaultKey(&(pDevice->sKey), + (DWORD)(dwKeyIndex | (1 << 31)), + wrq->length, + NULL, + pDevice->abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID + ); + spin_unlock_irq(&pDevice->lock); + } + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->uKeyLength = wrq->length; + pDevice->bTransmitKey = TRUE; + pDevice->bEncryptionEnable = TRUE; + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + + }else if(index>0){ + //when the length is 0 the request only changes the default transmit key index + //check the new key has a non zero lenget + if(pDevice->bEncryptionEnable==FALSE) + { + rc = -EINVAL; + return rc; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Just set Default key Index:\n"); + pkeytab=&(pDevice->sKey.KeyTable[MAX_KEY_TABLE-1]); + if(pkeytab->GroupKey[(BYTE)dwKeyIndex].uKeyLength==0){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Default key len is 0\n"); + rc = -EINVAL; + return rc; + } + pDevice->byKeyIndex =(BYTE)dwKeyIndex; + pkeytab->dwGTKeyIndex =dwKeyIndex | (1 << 31); + pkeytab->GroupKey[(BYTE)dwKeyIndex].dwKeyIndex=dwKeyIndex | (1 << 31); + } + +}else {//disable the key + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n"); + if(pDevice->bEncryptionEnable==FALSE) + return 0; + pMgmt->bShareKeyAlgorithm = FALSE; + pDevice->bEncryptionEnable = FALSE; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + for(uu=0;uu<MAX_KEY_TABLE;uu++) + MACvDisableKeyEntry(pDevice->PortOffset, uu); + spin_unlock_irq(&pDevice->lock); + } +} +//End Modify,Einsn + +/* + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n"); + + // Check the size of the key + if (wrq->length > WLAN_WEP232_KEYLEN) { + rc = -EINVAL; + return rc; + } + + if (dwKeyIndex > WLAN_WEP_NKEYS) { + rc = -EINVAL; + return rc; + } + + if (dwKeyIndex > 0) + dwKeyIndex--; + + // Send the key to the card + if (wrq->length > 0) { + + if (wrq->length == WLAN_WEP232_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 232 bit wep key\n"); + } + else if (wrq->length == WLAN_WEP104_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 104 bit wep key\n"); + } + else if (wrq->length == WLAN_WEP40_KEYLEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set 40 bit wep key, index= %d\n", (int)dwKeyIndex); + } + memset(pDevice->abyKey, 0, WLAN_WEP232_KEYLEN); + memcpy(pDevice->abyKey, extra, wrq->length); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyKey: "); + for (ii = 0; ii < wrq->length; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pDevice->abyKey[ii]); + } + + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + KeybSetDefaultKey(&(pDevice->sKey), + (DWORD)(pDevice->byKeyIndex | (1 << 31)), + pDevice->uKeyLength, + NULL, + pDevice->abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID + ); + spin_unlock_irq(&pDevice->lock); + } + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->uKeyLength = wrq->length; + pDevice->bTransmitKey = TRUE; + pDevice->bEncryptionEnable = TRUE; + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + + // Do we want to just set the transmit key index ? + if ( index < 4 ) { + pDevice->byKeyIndex = index; + } + else if(!wrq->flags & IW_ENCODE_MODE) { + rc = -EINVAL; + return rc; + } + } + // Read the flags + if(wrq->flags & IW_ENCODE_DISABLED){ + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable WEP function\n"); + pMgmt->bShareKeyAlgorithm = FALSE; + pDevice->bEncryptionEnable = FALSE; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + if (pDevice->flags & DEVICE_FLAGS_OPENED) { + spin_lock_irq(&pDevice->lock); + for(uu=0;uu<MAX_KEY_TABLE;uu++) + MACvDisableKeyEntry(pDevice->PortOffset, uu); + spin_unlock_irq(&pDevice->lock); + } + } +*/ + + if(wrq->flags & IW_ENCODE_RESTRICTED) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & ShareKey System\n"); + pMgmt->bShareKeyAlgorithm = TRUE; + } + if(wrq->flags & IW_ENCODE_OPEN) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable WEP & Open System\n"); + pMgmt->bShareKeyAlgorithm = FALSE; + } + return rc; +} + +/* + * Wireless Handler : get encode mode + */ + /* +int iwctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int rc = 0; + char abyKey[WLAN_WEP232_KEYLEN]; + UINT index = (UINT)(wrq->flags & IW_ENCODE_INDEX); + PSKeyItem pKey = NULL; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); +//2007-0207-06,<Add> by EinsnLiu +//the key index in iwconfig is 1-4 when our driver is 0-3 +//so it can't be used directly. +//if the index is 0,we should used the index set by driver. + if (index > WLAN_WEP_NKEYS) { + rc = -EINVAL; + return rc; + } + if(index<1){//set default key + if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){ + index=pDevice->byKeyIndex; + } + else index=0; + }else index--; +//End Add,Einsn + + memset(abyKey, 0, sizeof(abyKey)); + // Check encryption mode + wrq->flags = IW_ENCODE_NOKEY; + // Is WEP enabled ??? + if (pDevice->bEncryptionEnable) + wrq->flags |= IW_ENCODE_ENABLED; + else + wrq->flags |= IW_ENCODE_DISABLED; + + if (pMgmt->bShareKeyAlgorithm) + wrq->flags |= IW_ENCODE_RESTRICTED; + else + wrq->flags |= IW_ENCODE_OPEN; + + if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (BYTE)index , &pKey)){ + wrq->length = pKey->uKeyLength; + memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); +//2007-0207-06,<Modify> by EinsnLiu +//only get key success need to copy data +//index should +1. +//there is not necessary to return -EINVAL when get key failed +//if return -EINVAL,the encryption item can't be display by the command "iwconfig". + wrq->flags |= index+1; + memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); + } + + //else { + // rc = -EINVAL; + // return rc; + // } + + +//End Modify,Einsn + + return 0; +} +*/ + +//2008-0409-06, <Add> by Einsn Liu + +int iwctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + char abyKey[WLAN_WEP232_KEYLEN]; + + UINT index = (UINT)(wrq->flags & IW_ENCODE_INDEX); + PSKeyItem pKey = NULL; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n"); + + if (index > WLAN_WEP_NKEYS) { + return -EINVAL; + } + if(index<1){//get default key + if(pDevice->byKeyIndex<WLAN_WEP_NKEYS){ + index=pDevice->byKeyIndex; + } else + index=0; + }else + index--; + + memset(abyKey, 0, WLAN_WEP232_KEYLEN); + // Check encryption mode + wrq->flags = IW_ENCODE_NOKEY; + // Is WEP enabled ??? + if (pDevice->bEncryptionEnable) + wrq->flags |= IW_ENCODE_ENABLED; + else + wrq->flags |= IW_ENCODE_DISABLED; + + if (pMgmt->bShareKeyAlgorithm) + wrq->flags |= IW_ENCODE_RESTRICTED; + else + wrq->flags |= IW_ENCODE_OPEN; + wrq->length=0; + + if((index==0)&&(pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled|| + pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)){//get wpa pairwise key + if (KeybGetKey(&(pDevice->sKey),pMgmt->abyCurrBSSID, 0xffffffff, &pKey)){ + wrq->length = pKey->uKeyLength; + memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); + memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); + } + }else if (KeybGetKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, (BYTE)index , &pKey)){ + wrq->length = pKey->uKeyLength; + memcpy(abyKey, pKey->abyKey, pKey->uKeyLength); + memcpy(extra, abyKey, WLAN_WEP232_KEYLEN); + } + + wrq->flags |= index+1; + + return 0; +} + +/* + * Wireless Handler : set power mode + */ +int iwctl_siwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int rc = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER \n"); + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EINVAL; + return rc; + } + + if (wrq->disabled) { + pDevice->ePSMode = WMAC_POWER_CAM; + PSvDisablePowerSaving(pDevice); + return rc; + } + if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + pDevice->ePSMode = WMAC_POWER_FAST; + PSvEnablePowerSaving((HANDLE)pDevice, pMgmt->wListenInterval); + + } else if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { + pDevice->ePSMode = WMAC_POWER_FAST; + PSvEnablePowerSaving((HANDLE)pDevice, pMgmt->wListenInterval); + } + switch (wrq->flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n"); + rc = -EINVAL; + break; + case IW_POWER_ALL_R: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n"); + rc = -EINVAL; + case IW_POWER_ON: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n"); + break; + default: + rc = -EINVAL; + } + + return rc; +} + +/* + * Wireless Handler : get power mode + */ +int iwctl_giwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int mode = pDevice->ePSMode; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER \n"); + + + if ((wrq->disabled = (mode == WMAC_POWER_CAM))) + return 0; + + if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10); + wrq->flags = IW_POWER_TIMEOUT; + } else { + wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10); + wrq->flags = IW_POWER_PERIOD; + } + wrq->flags |= IW_POWER_ALL_R; + + return 0; +} + + +/* + * Wireless Handler : get Sensitivity + */ +int iwctl_giwsens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + long ldBm; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS \n"); + if (pDevice->bLinkPass == TRUE) { + RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm); + wrq->value = ldBm; + } + else { + wrq->value = 0; + }; + wrq->disabled = (wrq->value == 0); + wrq->fixed = 1; + + + return 0; +} + +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + +int iwctl_siwauth(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int ret=0; + static int wpa_version=0; //must be static to save the last value,einsn liu + static int pairwise=0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n"); + switch (wrq->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wpa_version = wrq->value; + if(wrq->value == IW_AUTH_WPA_VERSION_DISABLED) { + printk("iwctl_siwauth:set WPADEV to disable at 1??????\n"); + //pDevice->bWPADevEnable = FALSE; + } + else if(wrq->value == IW_AUTH_WPA_VERSION_WPA) { + printk("iwctl_siwauth:set WPADEV to WPA1******\n"); + } + else { + printk("iwctl_siwauth:set WPADEV to WPA2******\n"); + } + //pDevice->bWPASuppWextEnabled =TRUE; + break; + case IW_AUTH_CIPHER_PAIRWISE: + pairwise = wrq->value; + + if(pairwise == IW_AUTH_CIPHER_CCMP){ + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + }else if(pairwise == IW_AUTH_CIPHER_TKIP){ + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + }else if(pairwise == IW_AUTH_CIPHER_WEP40||pairwise == IW_AUTH_CIPHER_WEP104){ + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + }else if(pairwise == IW_AUTH_CIPHER_NONE){ + //do nothing,einsn liu + }else pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + + break; + case IW_AUTH_CIPHER_GROUP: + if(wpa_version == IW_AUTH_WPA_VERSION_DISABLED) + break; + if(pairwise == IW_AUTH_CIPHER_NONE){ + if(wrq->value == IW_AUTH_CIPHER_CCMP){ + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + }else { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } + } + break; + case IW_AUTH_KEY_MGMT: + + if(wpa_version == IW_AUTH_WPA_VERSION_WPA2){ + if(wrq->value == IW_AUTH_KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + else pMgmt->eAuthenMode = WMAC_AUTH_WPA2; + }else if(wpa_version == IW_AUTH_WPA_VERSION_WPA){ + if(wrq->value == 0){ + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + }else if(wrq->value == IW_AUTH_KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + else pMgmt->eAuthenMode = WMAC_AUTH_WPA; + } + + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + break; /* FIXME */ + case IW_AUTH_DROP_UNENCRYPTED: + break; + case IW_AUTH_80211_AUTH_ALG: + if(wrq->value==IW_AUTH_ALG_OPEN_SYSTEM){ + pMgmt->bShareKeyAlgorithm=FALSE; + }else if(wrq->value==IW_AUTH_ALG_SHARED_KEY){ + pMgmt->bShareKeyAlgorithm=TRUE; + } + break; + case IW_AUTH_WPA_ENABLED: + //pDevice->bWPADevEnable = !! wrq->value; + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case IW_AUTH_ROAMING_CONTROL: + ret = -EOPNOTSUPP; + break; + case IW_AUTH_PRIVACY_INVOKED: + pDevice->bEncryptionEnable = !!wrq->value; + if(pDevice->bEncryptionEnable == FALSE){ + wpa_version = 0; + pairwise = 0; + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + pMgmt->bShareKeyAlgorithm = FALSE; + pMgmt->eAuthenMode = FALSE; + //pDevice->bWPADevEnable = FALSE; + } + + break; + default: + ret = -EOPNOTSUPP; + break; + } +/* + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_version = %d\n",wpa_version); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise = %d\n",pairwise); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->eEncryptionStatus = %d\n",pDevice->eEncryptionStatus); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->eAuthenMode = %d\n",pMgmt->eAuthenMode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pMgmt->bShareKeyAlgorithm = %s\n",pMgmt->bShareKeyAlgorithm?"TRUE":"FALSE"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bEncryptionEnable = %s\n",pDevice->bEncryptionEnable?"TRUE":"FALSE"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->bWPADevEnable = %s\n",pDevice->bWPADevEnable?"TRUE":"FALSE"); +*/ + return ret; +} + + +int iwctl_giwauth(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) +{ + return -EOPNOTSUPP; +} + + + +int iwctl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int ret=0; + + if(wrq->length){ + if ((wrq->length < 2) || (extra[1]+2 != wrq->length)) { + ret = -EINVAL; + goto out; + } + if(wrq->length > MAX_WPA_IE_LEN){ + ret = -ENOMEM; + goto out; + } + memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); + if(copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){ + ret = -EFAULT; + goto out; + } + pMgmt->wWPAIELen = wrq->length; + }else { + memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); + pMgmt->wWPAIELen = 0; + } + + out://not completely ...not necessary in wpa_supplicant 0.5.8 + return 0; +} + +int iwctl_giwgenie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + int ret=0; + int space = wrq->length; + + wrq->length = 0; + if(pMgmt->wWPAIELen > 0){ + wrq->length = pMgmt->wWPAIELen; + if(pMgmt->wWPAIELen <= space){ + if(copy_to_user(extra, pMgmt->abyWPAIE, pMgmt->wWPAIELen)){ + ret = -EFAULT; + } + }else + ret = -E2BIG; + } + + return ret; +} + + +int iwctl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; + struct viawget_wpa_param *param=NULL; +//original member + wpa_alg alg_name; + u8 addr[6]; + int key_idx, set_tx; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + u8 key[64]; + size_t seq_len,key_len=0; +// + // int ii; + u8 *buf; + size_t blen; + u8 key_array[64]; + int ret=0; + +printk("SIOCSIWENCODEEXT...... \n"); + +blen = sizeof(*param); +buf = kmalloc((int)blen, (int)GFP_KERNEL); +if (buf == NULL) + return -ENOMEM; +memset(buf, 0, blen); +param = (struct viawget_wpa_param *) buf; + +//recover alg_name +switch (ext->alg) { + case IW_ENCODE_ALG_NONE: + alg_name = WPA_ALG_NONE; + break; + case IW_ENCODE_ALG_WEP: + alg_name = WPA_ALG_WEP; + break; + case IW_ENCODE_ALG_TKIP: + alg_name = WPA_ALG_TKIP; + break; + case IW_ENCODE_ALG_CCMP: + alg_name = WPA_ALG_CCMP; + break; + default: + printk("Unknown alg = %d\n",ext->alg); + ret= -ENOMEM; + goto error; + } +//recover addr + memcpy(addr, ext->addr.sa_data, ETH_ALEN); +//recover key_idx + key_idx = (wrq->flags&IW_ENCODE_INDEX) - 1; +//recover set_tx +if(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + set_tx = 1; +//recover seq,seq_len + if(ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + seq_len=IW_ENCODE_SEQ_MAX_SIZE; + memcpy(seq, ext->rx_seq, seq_len); + } +//recover key,key_len +if(ext->key_len) { + key_len=ext->key_len; + memcpy(key, &ext->key[0], key_len); + } + +memset(key_array, 0, 64); +if ( key_len > 0) { + memcpy(key_array, key, key_len); + if (key_len == 32) { + // notice ! the oder + memcpy(&key_array[16], &key[24], 8); + memcpy(&key_array[24], &key[16], 8); + } + } + +/**************Translate iw_encode_ext to viawget_wpa_param****************/ +memcpy(param->addr, addr, ETH_ALEN); +param->u.wpa_key.alg_name = (int)alg_name; +param->u.wpa_key.set_tx = set_tx; +param->u.wpa_key.key_index = key_idx; +param->u.wpa_key.key_len = key_len; +param->u.wpa_key.key = (u8 *)key_array; +param->u.wpa_key.seq = (u8 *)seq; +param->u.wpa_key.seq_len = seq_len; + +#if 0 +int ii; +printk("param->u.wpa_key.alg_name =%d\n",param->u.wpa_key.alg_name); +printk("param->addr=%02x:%02x:%02x:%02x:%02x:%02x\n", + param->addr[0],param->addr[1],param->addr[2], + param->addr[3],param->addr[4],param->addr[5]); +printk("param->u.wpa_key.set_tx =%d\n",param->u.wpa_key.set_tx); +printk("param->u.wpa_key.key_index =%d\n",param->u.wpa_key.key_index); +printk("param->u.wpa_key.key_len =%d\n",param->u.wpa_key.key_len); +printk("param->u.wpa_key.key ="); +for(ii=0;ii<param->u.wpa_key.key_len;ii++) + printk("%02x:",param->u.wpa_key.key[ii]); + printk("\n"); +printk("param->u.wpa_key.seq_len =%d\n",param->u.wpa_key.seq_len); +printk("param->u.wpa_key.seq ="); +for(ii=0;ii<param->u.wpa_key.seq_len;ii++) + printk("%02x:",param->u.wpa_key.seq[ii]); + printk("\n"); + +printk("...........\n"); +#endif +//****set if current action is Network Manager count?? +//****this method is so foolish,but there is no other way??? +if(param->u.wpa_key.alg_name == WPA_ALG_NONE) { + if(param->u.wpa_key.key_index ==0) { + pDevice->bwextcount++; + } + if((pDevice->bwextcount == 1)&&(param->u.wpa_key.key_index ==1)) { + pDevice->bwextcount++; + } + if((pDevice->bwextcount ==2)&&(param->u.wpa_key.key_index ==2)) { + pDevice->bwextcount++; + } + if((pDevice->bwextcount ==3)&&(param->u.wpa_key.key_index ==3)) { + pDevice->bwextcount++; + } + } +if( pDevice->bwextcount == 4) { + printk("SIOCSIWENCODEEXT:Enable WPA WEXT SUPPORT!!!!!\n"); + pDevice->bwextcount=0; + pDevice->bWPASuppWextEnabled = TRUE; + } +//****** + + spin_lock_irq(&pDevice->lock); + ret = wpa_set_keys(pDevice, param, TRUE); + spin_unlock_irq(&pDevice->lock); + +error: +kfree(param); + return ret; +} + + + +int iwctl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra) +{ + return -EOPNOTSUPP;; +} + +int iwctl_siwmlme(struct net_device *dev, + struct iw_request_info * info, + struct iw_point *wrq, + char *extra) +{ + PSDevice pDevice = (PSDevice)dev->priv; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + //u16 reason = cpu_to_le16(mlme->reason_code); + int ret = 0; + + if(memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)){ + ret = -EINVAL; + return ret; + } + switch(mlme->cmd){ + case IW_MLME_DEAUTH: + //this command seems to be not complete,please test it --einsnliu + //bScheduleCommand((HANDLE) pDevice, WLAN_CMD_DEAUTH, (PBYTE)&reason); + break; + case IW_MLME_DISASSOC: + if(pDevice->bLinkPass == TRUE){ + printk("iwctl_siwmlme--->send DISASSOCIATE\n"); + //clear related flags + memset(pMgmt->abyDesireBSSID, 0xFF,6); + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + } + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; + +} + +#endif + + +/*------------------------------------------------------------------*/ +/* + * Structures to export the Wireless Handlers + */ + + +#if WIRELESS_EXT > 12 + +/* +static const iw_handler iwctl_handler[] = +{ + (iw_handler) iwctl_commit, // SIOCSIWCOMMIT + (iw_handler) iwctl_giwname, // SIOCGIWNAME + (iw_handler) NULL, // SIOCSIWNWID + (iw_handler) NULL, // SIOCGIWNWID + (iw_handler) iwctl_siwfreq, // SIOCSIWFREQ + (iw_handler) iwctl_giwfreq, // SIOCGIWFREQ + (iw_handler) iwctl_siwmode, // SIOCSIWMODE + (iw_handler) iwctl_giwmode, // SIOCGIWMODE + (iw_handler) NULL, // SIOCSIWSENS + (iw_handler) iwctl_giwsens, // SIOCGIWSENS + (iw_handler) NULL, // SIOCSIWRANGE + (iw_handler) iwctl_giwrange, // SIOCGIWRANGE + (iw_handler) NULL, // SIOCSIWPRIV + (iw_handler) NULL, // SIOCGIWPRIV + (iw_handler) NULL, // SIOCSIWSTATS + (iw_handler) NULL, // SIOCGIWSTATS + (iw_handler) NULL, // SIOCSIWSPY + (iw_handler) NULL, // SIOCGIWSPY + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) iwctl_siwap, // SIOCSIWAP + (iw_handler) iwctl_giwap, // SIOCGIWAP + (iw_handler) NULL, // -- hole -- 0x16 + (iw_handler) iwctl_giwaplist, // SIOCGIWAPLIST +#if WIRELESS_EXT > 13 + (iw_handler) iwctl_siwscan, // SIOCSIWSCAN + (iw_handler) iwctl_giwscan, // SIOCGIWSCAN +#else + (iw_handler) NULL, + (iw_handler) NULL, +#endif + (iw_handler) iwctl_siwessid, // SIOCSIWESSID + (iw_handler) iwctl_giwessid, // SIOCGIWESSID + (iw_handler) NULL, // SIOCSIWNICKN + (iw_handler) NULL, // SIOCGIWNICKN + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) iwctl_siwrate, // SIOCSIWRATE 0x20 + (iw_handler) iwctl_giwrate, // SIOCGIWRATE + (iw_handler) iwctl_siwrts, // SIOCSIWRTS + (iw_handler) iwctl_giwrts, // SIOCGIWRTS + (iw_handler) iwctl_siwfrag, // SIOCSIWFRAG + (iw_handler) iwctl_giwfrag, // SIOCGIWFRAG + (iw_handler) NULL, // SIOCSIWTXPOW + (iw_handler) NULL, // SIOCGIWTXPOW + (iw_handler) iwctl_siwretry, // SIOCSIWRETRY + (iw_handler) iwctl_giwretry, // SIOCGIWRETRY + (iw_handler) iwctl_siwencode, // SIOCSIWENCODE + (iw_handler) iwctl_giwencode, // SIOCGIWENCODE + (iw_handler) iwctl_siwpower, // SIOCSIWPOWER + (iw_handler) iwctl_giwpower, // SIOCGIWPOWER +#if WIRELESS_EXT > 17 + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) iwctl_siwgenie, // SIOCSIWGENIE + (iw_handler) iwctl_giwgenie, // SIOCGIWGENIE + (iw_handler) iwctl_siwauth, // SIOCSIWAUTH + (iw_handler) iwctl_giwauth, // SIOCGIWAUTH + (iw_handler) iwctl_siwencodeext, // SIOCSIWENCODEEXT + (iw_handler) iwctl_giwencodeext, // SIOCGIWENCODEEXT + (iw_handler) NULL, // SIOCSIWPMKSA + (iw_handler) NULL, // -- hole -- +#endif // WIRELESS_EXT > 17 + +}; +*/ + +static const iw_handler iwctl_handler[] = +{ + (iw_handler) iwctl_commit, // SIOCSIWCOMMIT + (iw_handler) NULL, // SIOCGIWNAME + (iw_handler) NULL, // SIOCSIWNWID + (iw_handler) NULL, // SIOCGIWNWID + (iw_handler) NULL, // SIOCSIWFREQ + (iw_handler) NULL, // SIOCGIWFREQ + (iw_handler) NULL, // SIOCSIWMODE + (iw_handler) NULL, // SIOCGIWMODE + (iw_handler) NULL, // SIOCSIWSENS + (iw_handler) NULL, // SIOCGIWSENS + (iw_handler) NULL, // SIOCSIWRANGE + (iw_handler) iwctl_giwrange, // SIOCGIWRANGE + (iw_handler) NULL, // SIOCSIWPRIV + (iw_handler) NULL, // SIOCGIWPRIV + (iw_handler) NULL, // SIOCSIWSTATS + (iw_handler) NULL, // SIOCGIWSTATS + (iw_handler) NULL, // SIOCSIWSPY + (iw_handler) NULL, // SIOCGIWSPY + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // SIOCSIWAP + (iw_handler) NULL, // SIOCGIWAP + (iw_handler) NULL, // -- hole -- 0x16 + (iw_handler) NULL, // SIOCGIWAPLIST +#if WIRELESS_EXT > 13 + (iw_handler) iwctl_siwscan, // SIOCSIWSCAN + (iw_handler) iwctl_giwscan, // SIOCGIWSCAN +#else + (iw_handler) NULL, + (iw_handler) NULL, +#endif + (iw_handler) NULL, // SIOCSIWESSID + (iw_handler) NULL, // SIOCGIWESSID + (iw_handler) NULL, // SIOCSIWNICKN + (iw_handler) NULL, // SIOCGIWNICKN + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // SIOCSIWRATE 0x20 + (iw_handler) NULL, // SIOCGIWRATE + (iw_handler) NULL, // SIOCSIWRTS + (iw_handler) NULL, // SIOCGIWRTS + (iw_handler) NULL, // SIOCSIWFRAG + (iw_handler) NULL, // SIOCGIWFRAG + (iw_handler) NULL, // SIOCSIWTXPOW + (iw_handler) NULL, // SIOCGIWTXPOW + (iw_handler) NULL, // SIOCSIWRETRY + (iw_handler) NULL, // SIOCGIWRETRY + (iw_handler) NULL, // SIOCSIWENCODE + (iw_handler) NULL, // SIOCGIWENCODE + (iw_handler) NULL, // SIOCSIWPOWER + (iw_handler) NULL, // SIOCGIWPOWER + +//2008-0409-07, <Add> by Einsn Liu +#if WIRELESS_EXT > 17 + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // -- hole -- + (iw_handler) NULL, // SIOCSIWGENIE + (iw_handler) NULL, // SIOCGIWGENIE + (iw_handler) NULL, // SIOCSIWAUTH + (iw_handler) NULL, // SIOCGIWAUTH + (iw_handler) NULL, // SIOCSIWENCODEEXT + (iw_handler) NULL, // SIOCGIWENCODEEXT + (iw_handler) NULL, // SIOCSIWPMKSA + (iw_handler) NULL, // -- hole -- +#endif // WIRELESS_EXT > 17 +}; + + +static const iw_handler iwctl_private_handler[] = +{ + NULL, // SIOCIWFIRSTPRIV +}; + + +struct iw_priv_args iwctl_private_args[] = { +{ IOCTL_CMD_SET, + IW_PRIV_TYPE_CHAR | 1024, 0, + "set"}, +}; + + + +const struct iw_handler_def iwctl_handler_def = +{ +#if WIRELESS_EXT > 16 + .get_wireless_stats = &iwctl_get_wireless_stats, +#endif + .num_standard = sizeof(iwctl_handler)/sizeof(iw_handler), +// .num_private = sizeof(iwctl_private_handler)/sizeof(iw_handler), +// .num_private_args = sizeof(iwctl_private_args)/sizeof(struct iw_priv_args), + .num_private = 0, + .num_private_args = 0, + .standard = (iw_handler *) iwctl_handler, +// .private = (iw_handler *) iwctl_private_handler, +// .private_args = (struct iw_priv_args *)iwctl_private_args, + .private = NULL, + .private_args = NULL, +}; + + +#endif // WIRELESS_EXT > 12 + + +#endif // WIRELESS_EXT diff --git a/drivers/staging/vt6655/iwctl.h b/drivers/staging/vt6655/iwctl.h new file mode 100644 index 00000000000..07554e14d5f --- /dev/null +++ b/drivers/staging/vt6655/iwctl.h @@ -0,0 +1,332 @@ +/* + * 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: iwctl.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2004 + * + */ + + +#ifndef __IWCTL_H__ +#define __IWCTL_H__ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +#if WIRELESS_EXT < 18 + + +#define SIOCSIWMLME 0x8B16 +#define SIOCSIWGENIE 0x8B30 + +// WPA : Authentication mode parameters +#define SIOCSIWAUTH 0x8B32 +#define SIOCGIWAUTH 0x8B33 + +// WPA : Extended version of encoding configuration +#define SIOCSIWENCODEEXT 0x8B34 +#define SIOCGIWENCODEEXT 0x8B35 + +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 + +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 + +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 + +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +#define IW_AUTH_ROAMING_ENABLE 0 +#define IW_AUTH_ROAMING_DISABLE 1 + +#define IW_ENCODE_SEQ_MAX_SIZE 8 + +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 + + +struct iw_encode_ext +{ + __u32 ext_flags; // IW_ENCODE_EXT_* + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; // LSB first + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; // LSB first + struct sockaddr addr; // ff:ff:ff:ff:ff:ff for broadcast/multicast + // (group) keys or unicast address for + // individual keys + __u16 alg; // IW_ENCODE_ALG_* + __u16 key_len; + __u8 key[0]; +}; + + +struct iw_mlme +{ + __u16 cmd; /* IW_MLME_* */ + __u16 reason_code; + struct sockaddr addr; +}; + +#endif // WIRELESS_EXT < 18 + + + +#ifdef WIRELESS_EXT + +struct iw_statistics *iwctl_get_wireless_stats (struct net_device *dev); + + +int iwctl_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *wrq, + char *extra); + +int iwctl_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + + +int iwctl_giwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *wmode, + char *extra); + +int iwctl_siwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *wmode, + char *extra); + +int iwctl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *wrq, + char *extra); + +int iwctl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *wrq, + char *extra); + +int iwctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *wrq, + char *extra); + +int iwctl_giwnwid(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra) ; + +int iwctl_giwsens(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *wrq, + char *extra); + +int iwctl_giwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwrate(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + + +int iwctl_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +int iwctl_siwauth(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_giwauth(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, + char *extra); + +int iwctl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_giwgenie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *wrq, + char *extra); + +int iwctl_siwmlme(struct net_device *dev, + struct iw_request_info * info, + struct iw_point *wrq, + char *extra); +#endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + + +#endif + +#if WIRELESS_EXT > 12 +extern const struct iw_handler_def iwctl_handler_def; +extern const struct iw_priv_args iwctl_private_args; +#else +struct iw_request_info {}; +#endif //WIRELESS_EXT > 12 + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __IWCTL_H__ + + + diff --git a/drivers/staging/vt6655/kcompat.h b/drivers/staging/vt6655/kcompat.h new file mode 100644 index 00000000000..693939df667 --- /dev/null +++ b/drivers/staging/vt6655/kcompat.h @@ -0,0 +1,302 @@ +/* + * 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: kcompat.h + * + * Purpose: define kernel compatibility header + * + * Author: Lyndon Chen + * + * Date: Apr 8, 2002 + * + */ +#ifndef _KCOMPAT_H +#define _KCOMPAT_H + +#include <linux/version.h> + +#ifndef __init +#define __init +#endif + +#ifndef __exit +#define __exit +#endif + +#ifndef __devexit +#define __devexit +#endif + +#ifndef __devinitdata +#define __devinitdata +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(license) +#endif + +#ifndef MOD_INC_USE_COUNT +#define MOD_INC_USE_COUNT do {} while (0) +#endif + +#ifndef MOD_DEC_USE_COUNT +#define MOD_DEC_USE_COUNT do {} while (0) +#endif + +#ifndef HAVE_NETDEV_PRIV +#define netdev_priv(dev) (dev->priv) +#endif + +#ifndef IRQ_RETVAL +typedef void irqreturn_t; + +#ifdef PRIVATE_OBJ +#define IRQ_RETVAL(x) (int)x +#else +#define IRQ_RETVAL(x) +#endif + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) + +typedef unsigned long dma_addr_t; +typedef struct wait_queue *wait_queue_head_t; +#define init_waitqueue_head(x) *(x)=NULL +#define set_current_state(status) { current->state = (status); mb(); } + +#ifdef MODULE + +#define module_init(fn) int init_module (void) { return fn(); } +#define module_exit(fn) void cleanup_module(void) { return fn(); } + +#else /* MODULE */ + +#define module_init(fn) int e100_probe (void) { return fn(); } +#define module_exit(fn) /* NOTHING */ + +#endif /* MODULE */ + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) + +#ifdef MODVERSIONS +#include <linux/modversions.h> +#endif + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <asm/io.h> + +#define pci_resource_start(dev, bar) \ + (((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_SPACE_IO) ? \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_IO_MASK) : \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_MEM_MASK)) + +static inline int pci_enable_device(struct pci_dev *dev) +{ + 1112 + return 0; +} +#define __constant_cpu_to_le32 cpu_to_le32 +#define __constant_cpu_to_le16 cpu_to_le16 + +#define PCI_DMA_TODEVICE 1 +#define PCI_DMA_FROMDEVICE 2 + +extern inline void *pci_alloc_consistent (struct pci_dev *dev, + size_t size, + dma_addr_t *dma_handle) { + void *vaddr = kmalloc(size, GFP_ATOMIC); + if(vaddr != NULL) { + *dma_handle = virt_to_bus(vaddr); + } + return vaddr; +} + +#define pci_dma_sync_single(dev,dma_handle,size,direction) do{} while(0) +#define pci_dma_supported(dev, addr_mask) (1) +#define pci_free_consistent(dev, size, cpu_addr, dma_handle) kfree(cpu_addr) +#define pci_map_single(dev, addr, size, direction) virt_to_bus(addr) +#define pci_unmap_single(dev, dma_handle, size, direction) do{} while(0) + + +#define spin_lock_bh spin_lock_irq +#define spin_unlock_bh spin_unlock_irq +#define del_timer_sync(timer) del_timer(timer) +#define net_device device + +#define netif_start_queue(dev) ( clear_bit(0, &(dev)->tbusy)) +#define netif_stop_queue(dev) ( set_bit(0, &(dev)->tbusy)) +#define netif_wake_queue(dev) { clear_bit(0, &(dev)->tbusy); \ + mark_bh(NET_BH); } +#define netif_running(dev) ( test_bit(0, &(dev)->start)) +#define netif_queue_stopped(dev) ( test_bit(0, &(dev)->tbusy)) + +#define netif_device_attach(dev) \ + do{ (dev)->start = 1; netif_start_queue(dev); } while (0) +#define netif_device_detach(dev) \ + do{ (dev)->start = 0; netif_stop_queue(dev); } while (0) + +#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb) + +#define netif_carrier_on(dev) do {} while (0) +#define netif_carrier_off(dev) do {} while (0) + + +#define PCI_ANY_ID (~0U) + +struct pci_device_id { + unsigned int vendor, device; + unsigned int subvendor, subdevice; + unsigned int class, classmask; + unsigned long driver_data; +}; + +#define MODULE_DEVICE_TABLE(bus, dev_table) +#define PCI_MAX_NUM_NICS 256 + +struct pci_driver { + char *name; + struct pci_device_id *id_table; + int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); + void (*remove)(struct pci_dev *dev); + void (*suspend)(struct pci_dev *dev); + void (*resume)(struct pci_dev *dev); + struct pci_dev *pcimap[PCI_MAX_NUM_NICS]; +}; + +static inline int pci_module_init(struct pci_driver *drv) +{ + struct pci_dev *pdev; + struct pci_device_id *pcid; + uint16_t subvendor, subdevice; + int board_count = 0; + + /* walk the global pci device list looking for matches */ + for (pdev = pci_devices; pdev && (board_count < PCI_MAX_NUM_NICS); pdev = pdev->next) { + + pcid = &drv->id_table[0]; + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subdevice); + + while (pcid->vendor != 0) { + if (((pcid->vendor == pdev->vendor) || (pcid->vendor == PCI_ANY_ID)) && + ((pcid->device == pdev->device) || (pcid->device == PCI_ANY_ID)) && + ((pcid->subvendor == subvendor) || (pcid->subvendor == PCI_ANY_ID)) && + ((pcid->subdevice == subdevice) || (pcid->subdevice == PCI_ANY_ID))) { + + if (drv->probe(pdev, pcid) == 0) { + drv->pcimap[board_count] = pdev; + board_count++; + } + break; + } + pcid++; + } + } + + if (board_count < PCI_MAX_NUM_NICS) { + drv->pcimap[board_count] = NULL; + } + + return (board_count > 0) ? 0 : -ENODEV; +} + +static inline void pci_unregister_driver(struct pci_driver *drv) +{ + int i; + + for (i = 0; i < PCI_MAX_NUM_NICS; i++) { + if (!drv->pcimap[i]) + break; + + drv->remove(drv->pcimap[i]); + } +} + + +#define pci_set_drvdata(pcid, data) + +#define pci_get_drvdata(pcid) ({ \ + PSDevice pInfo; \ + for (pInfo = pDevice_Infos; \ + pInfo; pInfo = pInfo->next) { \ + if (pInfo->pcid == pcid) \ + break; \ + } \ + pInfo; }) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) + +#define skb_linearize(skb, gfp_mask) ({ \ + struct sk_buff *tmp_skb; \ + tmp_skb = skb; \ + skb = skb_copy(tmp_skb, gfp_mask); \ + dev_kfree_skb_irq(tmp_skb); }) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) */ + +#ifndef MODULE_LICESEN +#define MODULE_LICESEN(x) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) + +#include <linux/types.h> +#include <linux/pci.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,2) +static inline int pci_set_power_state(struct pci_dev* pcid, int state) { return 0; } +#endif + +#define PMCSR 0xe0 +#define PM_ENABLE_BIT 0x0100 +#define PM_CLEAR_BIT 0x8000 +#define PM_STATE_MASK 0xFFFC +#define PM_STATE_D1 0x0001 + +static inline int +pci_enable_wake(struct pci_dev *dev, u32 state, int enable) +{ + u16 p_state; + + pci_read_config_word(dev, PMCSR, &p_state); + pci_write_config_word(dev, PMCSR, p_state | PM_CLEAR_BIT); + + if (enable == 0) { + p_state &= ~PM_ENABLE_BIT; + } else { + p_state |= PM_ENABLE_BIT; + } + p_state &= PM_STATE_MASK; + p_state |= state; + + pci_write_config_word(dev, PMCSR, p_state); + + return 0; +} +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) */ + +#endif + diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c new file mode 100644 index 00000000000..168ebd3be94 --- /dev/null +++ b/drivers/staging/vt6655/key.c @@ -0,0 +1,836 @@ +/* + * 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: key.c + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + * Functions: + * KeyvInitTable - Init Key management table + * KeybGetKey - Get Key from table + * KeybSetKey - Set Key to table + * KeybRemoveKey - Remove Key from table + * KeybGetTransmitKey - Get Transmit Key from table + * + * Revision History: + * + */ + + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +static VOID +s_vCheckKeyTableValid (PSKeyManagement pTable, DWORD_PTR dwIoBase) +{ + int i; + + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + (pTable->KeyTable[i].PairwiseKey.bKeyValid == FALSE) && + (pTable->KeyTable[i].GroupKey[0].bKeyValid == FALSE) && + (pTable->KeyTable[i].GroupKey[1].bKeyValid == FALSE) && + (pTable->KeyTable[i].GroupKey[2].bKeyValid == FALSE) && + (pTable->KeyTable[i].GroupKey[3].bKeyValid == FALSE) + ) { + pTable->KeyTable[i].bInUse = FALSE; + pTable->KeyTable[i].wKeyCtl = 0; + pTable->KeyTable[i].bSoftWEP = FALSE; + MACvDisableKeyEntry(dwIoBase, i); + } + } +} + + +/*--------------------- Export Functions --------------------------*/ + + +/* + * Description: Init Key management table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * Out: + * none + * + * Return Value: none + * + */ +VOID KeyvInitTable (PSKeyManagement pTable, DWORD_PTR dwIoBase) +{ + int i; + int jj; + + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].bInUse = FALSE; + pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; + pTable->KeyTable[i].PairwiseKey.pvKeyTable = (PVOID)&pTable->KeyTable[i]; + for (jj=0; jj < MAX_GROUP_KEY; jj++) { + pTable->KeyTable[i].GroupKey[jj].bKeyValid = FALSE; + pTable->KeyTable[i].GroupKey[jj].pvKeyTable = (PVOID)&pTable->KeyTable[i]; + } + pTable->KeyTable[i].wKeyCtl = 0; + pTable->KeyTable[i].dwGTKeyIndex = 0; + pTable->KeyTable[i].bSoftWEP = FALSE; + MACvDisableKeyEntry(dwIoBase, i); + } +} + + +/* + * Description: Get Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key Index (0xFFFFFFFF means pairwise key) + * Out: + * pKey - Key return + * + * Return Value: TRUE if found otherwise FALSE + * + */ +BOOL KeybGetKey ( + IN PSKeyManagement pTable, + IN PBYTE pbyBSSID, + IN DWORD dwKeyIndex, + OUT PSKeyItem *pKey + ) +{ + int i; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetKey() \n"); + + *pKey = NULL; + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + if (dwKeyIndex == 0xFFFFFFFF) { + if (pTable->KeyTable[i].PairwiseKey.bKeyValid == TRUE) { + *pKey = &(pTable->KeyTable[i].PairwiseKey); + return (TRUE); + } + else { + return (FALSE); + } + } else if (dwKeyIndex < MAX_GROUP_KEY) { + if (pTable->KeyTable[i].GroupKey[dwKeyIndex].bKeyValid == TRUE) { + *pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex]); + return (TRUE); + } + else { + return (FALSE); + } + } + else { + return (FALSE); + } + } + } + return (FALSE); +} + + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +BOOL KeybSetKey ( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ) +{ + int i,j; + UINT ii; + PSKeyItem pKey; + UINT uKeyIdx; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); + + j = (MAX_KEY_TABLE-1); + for (i=0;i<(MAX_KEY_TABLE-1);i++) { + if ((pTable->KeyTable[i].bInUse == FALSE) && + (j == (MAX_KEY_TABLE-1))) { + // found empty table + j = i; + } + if ((pTable->KeyTable[i].bInUse == TRUE) && + IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + // found table already exist + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + // Pairwise key + pKey = &(pTable->KeyTable[i].PairwiseKey); + pTable->KeyTable[i].wKeyCtl &= 0xFFF0; // clear pairwise key control filed + pTable->KeyTable[i].wKeyCtl |= byKeyDecMode; + uKeyIdx = 4; // use HW key entry 4 for pairwise key + } else { + // Group key + if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) + return (FALSE); + pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + } + pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = TRUE; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + MEMvCopy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey, byLocalID); + + if ((dwKeyIndex & USE_KEYRSC) == 0) { + // RSC set by NIC + ZERO_MEMORY(&(pKey->KeyRSC), sizeof(QWORD)); + } + else { + MEMvCopy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD)); + } + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", pKey->uKeyLength); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + + return (TRUE); + } + } + if (j < (MAX_KEY_TABLE-1)) { + MEMvCopy(pTable->KeyTable[j].abyBSSID,pbyBSSID,U_ETHER_ADDR_LEN); + pTable->KeyTable[j].bInUse = TRUE; + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + // Pairwise key + pKey = &(pTable->KeyTable[j].PairwiseKey); + pTable->KeyTable[j].wKeyCtl &= 0xFFF0; // clear pairwise key control filed + pTable->KeyTable[j].wKeyCtl |= byKeyDecMode; + uKeyIdx = 4; // use HW key entry 4 for pairwise key + } else { + // Group key + if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) + return (FALSE); + pKey = &(pTable->KeyTable[j].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); + } + pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[j].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + } + pTable->KeyTable[j].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = TRUE; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + MEMvCopy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[j].wKeyCtl, j, uKeyIdx, pbyBSSID, (PDWORD)pKey->abyKey, byLocalID); + + if ((dwKeyIndex & USE_KEYRSC) == 0) { + // RSC set by NIC + ZERO_MEMORY(&(pKey->KeyRSC), sizeof(QWORD)); + } + else { + MEMvCopy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD)); + } + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(N): \n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%02x ", pKey->abyKey[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + + return (TRUE); + } + return (FALSE); +} + + +/* + * Description: Remove Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * dwKeyIndex - Key Index (reference to NDIS DDK) + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +BOOL KeybRemoveKey ( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, + DWORD_PTR dwIoBase + ) +{ + int i; + + if (IS_BROADCAST_ADDRESS(pbyBSSID)) { + // dealte all key + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; + } + s_vCheckKeyTableValid(pTable, dwIoBase); + return TRUE; + } + else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { + for (i=0;i<MAX_KEY_TABLE;i++) { + pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = FALSE; + if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { + // remove Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = 0; + } + } + s_vCheckKeyTableValid(pTable, dwIoBase); + return TRUE; + } + else { + return FALSE; + } + } + + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; + s_vCheckKeyTableValid(pTable, dwIoBase); + return (TRUE); + } + else if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { + pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = FALSE; + if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[i].dwGTKeyIndex & 0x7FFFFFFF)) { + // remove Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = 0; + } + s_vCheckKeyTableValid(pTable, dwIoBase); + return (TRUE); + } + else { + return (FALSE); + } + } + } + return (FALSE); +} + + +/* + * Description: Remove Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +BOOL KeybRemoveAllKey ( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD_PTR dwIoBase + ) +{ + int i,u; + + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + pTable->KeyTable[i].PairwiseKey.bKeyValid = FALSE; + for(u=0;u<MAX_GROUP_KEY;u++) { + pTable->KeyTable[i].GroupKey[u].bKeyValid = FALSE; + } + pTable->KeyTable[i].dwGTKeyIndex = 0; + s_vCheckKeyTableValid(pTable, dwIoBase); + return (TRUE); + } + } + return (FALSE); +} + +/* + * Description: Remove WEP Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +VOID KeyvRemoveWEPKey ( + PSKeyManagement pTable, + DWORD dwKeyIndex, + DWORD_PTR dwIoBase + ) +{ + + if ((dwKeyIndex & 0x000000FF) < MAX_GROUP_KEY) { + if (pTable->KeyTable[MAX_KEY_TABLE-1].bInUse == TRUE) { + if (pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].byCipherSuite == KEY_CTL_WEP) { + pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF].bKeyValid = FALSE; + if ((dwKeyIndex & 0x7FFFFFFF) == (pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex & 0x7FFFFFFF)) { + // remove Group transmit key + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = 0; + } + } + } + s_vCheckKeyTableValid(pTable, dwIoBase); + } + return; +} + +VOID KeyvRemoveAllWEPKey ( + PSKeyManagement pTable, + DWORD_PTR dwIoBase + ) +{ + int i; + + for(i=0;i<MAX_GROUP_KEY;i++) { + KeyvRemoveWEPKey(pTable, i, dwIoBase); + } +} + +/* + * Description: Get Transmit Key from table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * pbyBSSID - BSSID of Key + * Out: + * pKey - Key return + * + * Return Value: TRUE if found otherwise FALSE + * + */ +BOOL KeybGetTransmitKey ( + IN PSKeyManagement pTable, + IN PBYTE pbyBSSID, + IN DWORD dwKeyType, + OUT PSKeyItem *pKey + ) +{ + int i, ii; + + *pKey = NULL; + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + IS_ETH_ADDRESS_EQUAL(pTable->KeyTable[i].abyBSSID,pbyBSSID)) { + + if (dwKeyType == PAIRWISE_KEY) { + + if (pTable->KeyTable[i].PairwiseKey.bKeyValid == TRUE) { + *pKey = &(pTable->KeyTable[i].PairwiseKey); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PAIRWISE_KEY: KeyTable.abyBSSID: "); + for (ii = 0; ii < 6; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + + return (TRUE); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"PairwiseKey.bKeyValid == FALSE\n"); + return (FALSE); + } + } // End of Type == PAIRWISE + else { + if (pTable->KeyTable[i].dwGTKeyIndex == 0) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: dwGTKeyIndex == 0 !!!\n"); + return FALSE; + } + if (pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)].bKeyValid == TRUE) { + *pKey = &(pTable->KeyTable[i].GroupKey[(pTable->KeyTable[i].dwGTKeyIndex&0x000000FF)]); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybGetTransmitKey:"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GROUP_KEY: KeyTable.abyBSSID\n"); + for (ii = 0; ii < 6; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); + + return (TRUE); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GroupKey.bKeyValid == FALSE\n"); + return (FALSE); + } + } // End of Type = GROUP + } // BSSID match + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ERROR: NO Match BSSID !!! "); + for (ii = 0; ii < 6; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(pbyBSSID+ii)); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + return (FALSE); +} + + +/* + * Description: Check Pairewise Key + * + * Parameters: + * In: + * pTable - Pointer to Key table + * Out: + * none + * + * Return Value: TRUE if found otherwise FALSE + * + */ +BOOL KeybCheckPairewiseKey ( + IN PSKeyManagement pTable, + OUT PSKeyItem *pKey + ) +{ + int i; + + *pKey = NULL; + for (i=0;i<MAX_KEY_TABLE;i++) { + if ((pTable->KeyTable[i].bInUse == TRUE) && + (pTable->KeyTable[i].PairwiseKey.bKeyValid == TRUE)) { + *pKey = &(pTable->KeyTable[i].PairwiseKey); + return (TRUE); + } + } + return (FALSE); +} + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +BOOL KeybSetDefaultKey ( + PSKeyManagement pTable, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ) +{ + UINT ii; + PSKeyItem pKey; + UINT uKeyIdx; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetDefaultKey: %1x, %d \n", (int)dwKeyIndex, (int)uKeyLength); + + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key + return (FALSE); + } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { + return (FALSE); + } + + pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = TRUE; + for(ii=0;ii<U_ETHER_ADDR_LEN;ii++) + pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF; + + // Group key + pKey = &(pTable->KeyTable[MAX_KEY_TABLE-1].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); + + } + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= (byKeyDecMode); + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x0044; // use group key for all address + uKeyIdx = (dwKeyIndex & 0x000000FF); + + if ((uKeyLength == WLAN_WEP232_KEYLEN) && + (byKeyDecMode == KEY_CTL_WEP)) { + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0x4000; // disable on-fly disable address match + pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP = TRUE; + } else { + if (pTable->KeyTable[MAX_KEY_TABLE-1].bSoftWEP == FALSE) + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl |= 0xC000; // enable on-fly disable address match + } + + pKey->bKeyValid = TRUE; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + MEMvCopy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl, MAX_KEY_TABLE-1, uKeyIdx, pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID, (PDWORD)pKey->abyKey, byLocalID); + + if ((dwKeyIndex & USE_KEYRSC) == 0) { + // RSC set by NIC + ZERO_MEMORY(&(pKey->KeyRSC), sizeof(QWORD)); + } else { + MEMvCopy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD)); + } + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n", pKey->bKeyValid); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n", (int)pKey->uKeyLength); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: \n"); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x", pKey->abyKey[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); + + return (TRUE); +} + + +/* + * Description: Set Key to table + * + * Parameters: + * In: + * pTable - Pointer to Key table + * dwKeyIndex - Key index (reference to NDIS DDK) + * uKeyLength - Key length + * KeyRSC - Key RSC + * pbyKey - Pointer to key + * Out: + * none + * + * Return Value: TRUE if success otherwise FALSE + * + */ +BOOL KeybSetAllGroupKey ( + PSKeyManagement pTable, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ) +{ + int i; + UINT ii; + PSKeyItem pKey; + UINT uKeyIdx; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); + + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key + return (FALSE); + } else if ((dwKeyIndex & 0x000000FF) >= MAX_GROUP_KEY) { + return (FALSE); + } + + for (i=0; i < MAX_KEY_TABLE-1; i++) { + if (pTable->KeyTable[i].bInUse == TRUE) { + // found table already exist + // Group key + pKey = &(pTable->KeyTable[i].GroupKey[dwKeyIndex & 0x000000FF]); + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); + pTable->KeyTable[i].wKeyCtl |= 0x0040; // use group key for group address + uKeyIdx = (dwKeyIndex & 0x000000FF); + + pTable->KeyTable[i].wKeyCtl |= 0x8000; // enable on-fly + + pKey->bKeyValid = TRUE; + pKey->uKeyLength = uKeyLength; + pKey->dwKeyIndex = dwKeyIndex; + pKey->byCipherSuite = byKeyDecMode; + MEMvCopy(pKey->abyKey, pbyKey, uKeyLength); + if (byKeyDecMode == KEY_CTL_WEP) { + if (uKeyLength == WLAN_WEP40_KEYLEN) + pKey->abyKey[15] &= 0x7F; + if (uKeyLength == WLAN_WEP104_KEYLEN) + pKey->abyKey[15] |= 0x80; + } + MACvSetKeyEntry(dwIoBase, pTable->KeyTable[i].wKeyCtl, i, uKeyIdx, pTable->KeyTable[i].abyBSSID, (PDWORD)pKey->abyKey, byLocalID); + + if ((dwKeyIndex & USE_KEYRSC) == 0) { + // RSC set by NIC + ZERO_MEMORY(&(pKey->KeyRSC), sizeof(QWORD)); + } + else { + MEMvCopy(&(pKey->KeyRSC), pKeyRSC, sizeof(QWORD)); + } + pKey->dwTSC47_16 = 0; + pKey->wTSC15_0 = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KeybSetKey(R): \n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->bKeyValid: %d\n ", pKey->bKeyValid); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->uKeyLength: %d\n ", (int)pKey->uKeyLength); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->abyKey: "); + for (ii = 0; ii < pKey->uKeyLength; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", pKey->abyKey[ii]); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + + //DBG_PRN_GRP12(("pKey->dwTSC47_16: %lX\n ", pKey->dwTSC47_16)); + //DBG_PRN_GRP12(("pKey->wTSC15_0: %X\n ", pKey->wTSC15_0)); + //DBG_PRN_GRP12(("pKey->dwKeyIndex: %lX\n ", pKey->dwKeyIndex)); + + } // (pTable->KeyTable[i].bInUse == TRUE) + } + return (TRUE); +} diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h new file mode 100644 index 00000000000..9c7d335ea08 --- /dev/null +++ b/drivers/staging/vt6655/key.h @@ -0,0 +1,202 @@ +/* + * 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: key.h + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + */ + + +#ifndef __KEY_H__ +#define __KEY_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +#if !defined(__TETHER_H__) +#include "tether.h" +#endif + +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define MAX_GROUP_KEY 4 +#define MAX_KEY_TABLE 11 +#define MAX_KEY_LEN 32 +#define AES_KEY_LEN 16 + + +#define AUTHENTICATOR_KEY 0x10000000 +#define USE_KEYRSC 0x20000000 +#define PAIRWISE_KEY 0x40000000 +#define TRANSMIT_KEY 0x80000000 + +#define GROUP_KEY 0x00000000 + +#define KEY_CTL_WEP 0x00 +#define KEY_CTL_NONE 0x01 +#define KEY_CTL_TKIP 0x02 +#define KEY_CTL_CCMP 0x03 +#define KEY_CTL_INVALID 0xFF + + +typedef struct tagSKeyItem +{ + BOOL bKeyValid; + ULONG uKeyLength; + BYTE abyKey[MAX_KEY_LEN]; + QWORD KeyRSC; + DWORD dwTSC47_16; + WORD wTSC15_0; + BYTE byCipherSuite; + BYTE byReserved0; + DWORD dwKeyIndex; + PVOID pvKeyTable; +} SKeyItem, DEF* PSKeyItem; //64 + +typedef struct tagSKeyTable +{ + BYTE abyBSSID[U_ETHER_ADDR_LEN]; //6 + BYTE byReserved0[2]; //8 + SKeyItem PairwiseKey; + SKeyItem GroupKey[MAX_GROUP_KEY]; //64*5 = 320, 320+8=328 + DWORD dwGTKeyIndex; // GroupTransmitKey Index + BOOL bInUse; + //2006-1116-01,<Modify> by NomadZhao + //WORD wKeyCtl; + //BOOL bSoftWEP; + BOOL bSoftWEP; + WORD wKeyCtl; // for address of wKeyCtl at align 4 + + BYTE byReserved1[6]; +} SKeyTable, DEF* PSKeyTable; //348 + +typedef struct tagSKeyManagement +{ + SKeyTable KeyTable[MAX_KEY_TABLE]; +} SKeyManagement, DEF* PSKeyManagement; + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID KeyvInitTable(PSKeyManagement pTable, DWORD_PTR dwIoBase); + +BOOL KeybGetKey( + IN PSKeyManagement pTable, + IN PBYTE pbyBSSID, + IN DWORD dwKeyIndex, + OUT PSKeyItem *pKey + ); + +BOOL KeybSetKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ); + +BOOL KeybSetDefaultKey( + PSKeyManagement pTable, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ); + +BOOL KeybRemoveKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, + DWORD_PTR dwIoBase + ); + +BOOL KeybGetTransmitKey( + IN PSKeyManagement pTable, + IN PBYTE pbyBSSID, + IN DWORD dwKeyType, + OUT PSKeyItem *pKey + ); + +BOOL KeybCheckPairewiseKey( + IN PSKeyManagement pTable, + OUT PSKeyItem *pKey + ); + +BOOL KeybRemoveAllKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD_PTR dwIoBase + ); + +VOID KeyvRemoveWEPKey( + PSKeyManagement pTable, + DWORD dwKeyIndex, + DWORD_PTR dwIoBase + ); + +VOID KeyvRemoveAllWEPKey( + PSKeyManagement pTable, + DWORD_PTR dwIoBase + ); + +BOOL KeybSetAllGroupKey ( + PSKeyManagement pTable, + DWORD dwKeyIndex, + ULONG uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode, + DWORD_PTR dwIoBase, + BYTE byLocalID + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ + +#endif /* __cplusplus */ + + +#endif // __KEY_H__ + diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c new file mode 100644 index 00000000000..0283ed3bedd --- /dev/null +++ b/drivers/staging/vt6655/mac.c @@ -0,0 +1,1752 @@ +/* + * 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: mac.c + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * MACvReadAllRegs - Read All MAC Registers to buffer + * MACbIsRegBitsOn - Test if All test Bits On + * MACbIsRegBitsOff - Test if All test Bits Off + * MACbIsIntDisable - Test if MAC interrupt disable + * MACbyReadMultiAddr - Read Multicast Address Mask Pattern + * MACvWriteMultiAddr - Write Multicast Address Mask Pattern + * MACvSetMultiAddrByHash - Set Multicast Address Mask by Hash value + * MACvResetMultiAddrByHash - Clear Multicast Address Mask by Hash value + * MACvSetRxThreshold - Set Rx Threshold value + * MACvGetRxThreshold - Get Rx Threshold value + * MACvSetTxThreshold - Set Tx Threshold value + * MACvGetTxThreshold - Get Tx Threshold value + * MACvSetDmaLength - Set Dma Length value + * MACvGetDmaLength - Get Dma Length value + * MACvSetShortRetryLimit - Set 802.11 Short Retry limit + * MACvGetShortRetryLimit - Get 802.11 Short Retry limit + * MACvSetLongRetryLimit - Set 802.11 Long Retry limit + * MACvGetLongRetryLimit - Get 802.11 Long Retry limit + * MACvSetLoopbackMode - Set MAC Loopback Mode + * MACbIsInLoopbackMode - Test if MAC in Loopback mode + * MACvSetPacketFilter - Set MAC Address Filter + * MACvSaveContext - Save Context of MAC Registers + * MACvRestoreContext - Restore Context of MAC Registers + * MACbCompareContext - Compare if values of MAC Registers same as Context + * MACbSoftwareReset - Software Reset MAC + * MACbSafeRxOff - Turn Off MAC Rx + * MACbSafeTxOff - Turn Off MAC Tx + * MACbSafeStop - Stop MAC function + * MACbShutdown - Shut down MAC + * MACvInitialize - Initialize MAC + * MACvSetCurrRxDescAddr - Set Rx Descriptos Address + * MACvSetCurrTx0DescAddr - Set Tx0 Descriptos Address + * MACvSetCurrTx1DescAddr - Set Tx1 Descriptos Address + * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC + * + * Revision History: + * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53 + * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()& MACvEnableBusSusEn() + * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry + * + */ + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + + +WORD TxRate_iwconfig;//2008-5-8 <add> by chester +/*--------------------- Static Definitions -------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: + * Read All MAC Registers to buffer + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyMacRegs - buffer to read + * + * Return Value: none + * + */ +VOID MACvReadAllRegs (DWORD_PTR dwIoBase, PBYTE pbyMacRegs) +{ + int ii; + + // read page0 register + for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) { + VNSvInPortB(dwIoBase + ii, pbyMacRegs); + pbyMacRegs++; + } + + MACvSelectPage1(dwIoBase); + + // read page1 register + for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) { + VNSvInPortB(dwIoBase + ii, pbyMacRegs); + pbyMacRegs++; + } + + MACvSelectPage0(dwIoBase); + +} + +/* + * Description: + * Test if all test bits on + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byRegOfs - Offset of MAC Register + * byTestBits - Test bits + * Out: + * none + * + * Return Value: TRUE if all test bits On; otherwise FALSE + * + */ +BOOL MACbIsRegBitsOn (DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOn(byData, byTestBits); +} + +/* + * Description: + * Test if all test bits off + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byRegOfs - Offset of MAC Register + * byTestBits - Test bits + * Out: + * none + * + * Return Value: TRUE if all test bits Off; otherwise FALSE + * + */ +BOOL MACbIsRegBitsOff (DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits) +{ + BYTE byData; + + VNSvInPortB(dwIoBase + byRegOfs, &byData); + return BITbIsAllBitsOff(byData, byTestBits); +} + +/* + * Description: + * Test if MAC interrupt disable + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if interrupt is disable; otherwise FALSE + * + */ +BOOL MACbIsIntDisable (DWORD_PTR dwIoBase) +{ + DWORD dwData; + + VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData); + if (dwData != 0) + return FALSE; + + return TRUE; +} + +/* + * Description: + * Read MAC Multicast Address Mask + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * uByteidx - Index of Mask + * Out: + * none + * + * Return Value: Mask Value read + * + */ +BYTE MACbyReadMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx) +{ + BYTE byData; + + MACvSelectPage1(dwIoBase); + VNSvInPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, &byData); + MACvSelectPage0(dwIoBase); + return byData; +} + +/* + * Description: + * Write MAC Multicast Address Mask + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * uByteidx - Index of Mask + * byData - Mask Value to write + * Out: + * none + * + * Return Value: none + * + */ +VOID MACvWriteMultiAddr (DWORD_PTR dwIoBase, UINT uByteIdx, BYTE byData) +{ + MACvSelectPage1(dwIoBase); + VNSvOutPortB(dwIoBase + MAC_REG_MAR0 + uByteIdx, byData); + MACvSelectPage0(dwIoBase); +} + +/* + * Description: + * Set this hash index into multicast address register bit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byHashIdx - Hash index to set + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetMultiAddrByHash (DWORD_PTR dwIoBase, BYTE byHashIdx) +{ + UINT uByteIdx; + BYTE byBitMask; + BYTE byOrgValue; + + // calculate byte position + uByteIdx = byHashIdx / 8; + ASSERT(uByteIdx < 8); + // calculate bit position + byBitMask = 1; + byBitMask <<= (byHashIdx % 8); + // turn on the bit + byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx); + MACvWriteMultiAddr(dwIoBase, uByteIdx, (BYTE)(byOrgValue | byBitMask)); +} + +/* + * Description: + * Reset this hash index into multicast address register bit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byHashIdx - Hash index to clear + * Out: + * none + * + * Return Value: none + * + */ +void MACvResetMultiAddrByHash (DWORD_PTR dwIoBase, BYTE byHashIdx) +{ + UINT uByteIdx; + BYTE byBitMask; + BYTE byOrgValue; + + // calculate byte position + uByteIdx = byHashIdx / 8; + ASSERT(uByteIdx < 8); + // calculate bit position + byBitMask = 1; + byBitMask <<= (byHashIdx % 8); + // turn off the bit + byOrgValue = MACbyReadMultiAddr(dwIoBase, uByteIdx); + MACvWriteMultiAddr(dwIoBase, uByteIdx, (BYTE)(byOrgValue & (~byBitMask))); +} + +/* + * Description: + * Set Rx Threshold + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byThreshold - Threshold Value + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetRxThreshold (DWORD_PTR dwIoBase, BYTE byThreshold) +{ + BYTE byOrgValue; + + ASSERT(byThreshold < 4); + + // set FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue); + byOrgValue = (byOrgValue & 0xCF) | (byThreshold << 4); + VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue); +} + +/* + * Description: + * Get Rx Threshold + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyThreshold- Threshold Value Get + * + * Return Value: none + * + */ +void MACvGetRxThreshold (DWORD_PTR dwIoBase, PBYTE pbyThreshold) +{ + // get FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold); + *pbyThreshold = (*pbyThreshold >> 4) & 0x03; +} + +/* + * Description: + * Set Tx Threshold + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byThreshold - Threshold Value + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetTxThreshold (DWORD_PTR dwIoBase, BYTE byThreshold) +{ + BYTE byOrgValue; + + ASSERT(byThreshold < 4); + + // set FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue); + byOrgValue = (byOrgValue & 0xF3) | (byThreshold << 2); + VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue); +} + +/* + * Description: + * Get Tx Threshold + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyThreshold- Threshold Value Get + * + * Return Value: none + * + */ +void MACvGetTxThreshold (DWORD_PTR dwIoBase, PBYTE pbyThreshold) +{ + // get FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyThreshold); + *pbyThreshold = (*pbyThreshold >> 2) & 0x03; +} + +/* + * Description: + * Set Dma Length + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byDmaLength - Dma Length Value + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetDmaLength (DWORD_PTR dwIoBase, BYTE byDmaLength) +{ + BYTE byOrgValue; + + ASSERT(byDmaLength < 4); + + // set FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, &byOrgValue); + byOrgValue = (byOrgValue & 0xFC) | byDmaLength; + VNSvOutPortB(dwIoBase + MAC_REG_FCR0, byOrgValue); +} + +/* + * Description: + * Get Dma Length + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyDmaLength- Dma Length Value Get + * + * Return Value: none + * + */ +void MACvGetDmaLength (DWORD_PTR dwIoBase, PBYTE pbyDmaLength) +{ + // get FCR0 + VNSvInPortB(dwIoBase + MAC_REG_FCR0, pbyDmaLength); + *pbyDmaLength &= 0x03; +} + +/* + * Description: + * Set 802.11 Short Retry Limit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byRetryLimit- Retry Limit + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetShortRetryLimit (DWORD_PTR dwIoBase, BYTE byRetryLimit) +{ + // set SRT + VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit); +} + +/* + * Description: + * Get 802.11 Short Retry Limit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyRetryLimit - Retry Limit Get + * + * Return Value: none + * + */ +void MACvGetShortRetryLimit (DWORD_PTR dwIoBase, PBYTE pbyRetryLimit) +{ + // get SRT + VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit); +} + +/* + * Description: + * Set 802.11 Long Retry Limit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byRetryLimit- Retry Limit + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetLongRetryLimit (DWORD_PTR dwIoBase, BYTE byRetryLimit) +{ + // set LRT + VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit); +} + +/* + * Description: + * Get 802.11 Long Retry Limit + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyRetryLimit - Retry Limit Get + * + * Return Value: none + * + */ +void MACvGetLongRetryLimit (DWORD_PTR dwIoBase, PBYTE pbyRetryLimit) +{ + // get LRT + VNSvInPortB(dwIoBase + MAC_REG_LRT, pbyRetryLimit); +} + +/* + * Description: + * Set MAC Loopback mode + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * byLoopbackMode - Loopback Mode + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetLoopbackMode (DWORD_PTR dwIoBase, BYTE byLoopbackMode) +{ + BYTE byOrgValue; + + ASSERT(byLoopbackMode < 3); + byLoopbackMode <<= 6; + // set TCR + VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue); + byOrgValue = byOrgValue & 0x3F; + byOrgValue = byOrgValue | byLoopbackMode; + VNSvOutPortB(dwIoBase + MAC_REG_TEST, byOrgValue); +} + +/* + * Description: + * Test if MAC in Loopback mode + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if in Loopback mode; otherwise FALSE + * + */ +BOOL MACbIsInLoopbackMode (DWORD_PTR dwIoBase) +{ + BYTE byOrgValue; + + VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue); + if (BITbIsAnyBitsOn(byOrgValue, (TEST_LBINT | TEST_LBEXT))) + return TRUE; + return FALSE; +} + +/* + * Description: + * Set MAC Address filter + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * wFilterType - Filter Type + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetPacketFilter (DWORD_PTR dwIoBase, WORD wFilterType) +{ + BYTE byOldRCR; + BYTE byNewRCR = 0; + + // if only in DIRECTED mode, multicast-address will set to zero, + // but if other mode exist (e.g. PROMISCUOUS), multicast-address + // will be open + if (BITbIsBitOn(wFilterType, PKT_TYPE_DIRECTED)) { + // set multicast address to accept none + MACvSelectPage1(dwIoBase); + VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0L); + VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(DWORD), 0L); + MACvSelectPage0(dwIoBase); + } + + if (BITbIsAnyBitsOn(wFilterType, PKT_TYPE_PROMISCUOUS | PKT_TYPE_ALL_MULTICAST)) { + // set multicast address to accept all + MACvSelectPage1(dwIoBase); + VNSvOutPortD(dwIoBase + MAC_REG_MAR0, 0xFFFFFFFFL); + VNSvOutPortD(dwIoBase + MAC_REG_MAR0 + sizeof(DWORD), 0xFFFFFFFFL); + MACvSelectPage0(dwIoBase); + } + + if (BITbIsBitOn(wFilterType, PKT_TYPE_PROMISCUOUS)) { + + byNewRCR |= (RCR_RXALLTYPE | RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST); + + byNewRCR &= ~RCR_BSSID; + } + + if (BITbIsAnyBitsOn(wFilterType, (PKT_TYPE_ALL_MULTICAST | PKT_TYPE_MULTICAST))) + byNewRCR |= RCR_MULTICAST; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_BROADCAST)) + byNewRCR |= RCR_BROADCAST; + + if (BITbIsBitOn(wFilterType, PKT_TYPE_ERROR_CRC)) + byNewRCR |= RCR_ERRCRC; + + VNSvInPortB(dwIoBase + MAC_REG_RCR, &byOldRCR); + if (byNewRCR != byOldRCR) { + // Modify the Receive Command Register + VNSvOutPortB(dwIoBase + MAC_REG_RCR, byNewRCR); + } +} + +/* + * Description: + * Save MAC registers to context buffer + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * pbyCxtBuf - Context buffer + * + * Return Value: none + * + */ +void MACvSaveContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +{ + int ii; + + // read page0 register + for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE0; ii++) { + VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + ii)); + } + + MACvSelectPage1(dwIoBase); + + // read page1 register + for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) { + VNSvInPortB((dwIoBase + ii), (pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii)); + } + + MACvSelectPage0(dwIoBase); +} + +/* + * Description: + * Restore MAC registers from context buffer + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * pbyCxtBuf - Context buffer + * Out: + * none + * + * Return Value: none + * + */ +VOID MACvRestoreContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +{ + int ii; + + MACvSelectPage1(dwIoBase); + // restore page1 + for (ii = 0; ii < MAC_MAX_CONTEXT_SIZE_PAGE1; ii++) { + VNSvOutPortB((dwIoBase + ii), *(pbyCxtBuf + MAC_MAX_CONTEXT_SIZE_PAGE0 + ii)); + } + MACvSelectPage0(dwIoBase); + + // restore RCR,TCR,IMR... + for (ii = MAC_REG_RCR; ii < MAC_REG_ISR; ii++) { + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + } + // restore MAC Config. + for (ii = MAC_REG_LRT; ii < MAC_REG_PAGE1SEL; ii++) { + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + } + VNSvOutPortB(dwIoBase + MAC_REG_CFG, *(pbyCxtBuf + MAC_REG_CFG)); + + // restore PS Config. + for (ii = MAC_REG_PSCFG; ii < MAC_REG_BBREGCTL; ii++) { + VNSvOutPortB(dwIoBase + ii, *(pbyCxtBuf + ii)); + } + + // restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR + VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, *(PDWORD)(pbyCxtBuf + MAC_REG_TXDMAPTR0)); + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, *(PDWORD)(pbyCxtBuf + MAC_REG_AC0DMAPTR)); + VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, *(PDWORD)(pbyCxtBuf + MAC_REG_BCNDMAPTR)); + + + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR0)); + + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR1)); + +} + +/* + * Description: + * Compare if MAC registers same as context buffer + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * pbyCxtBuf - Context buffer + * Out: + * none + * + * Return Value: TRUE if all values are the same; otherwise FALSE + * + */ +BOOL MACbCompareContext (DWORD_PTR dwIoBase, PBYTE pbyCxtBuf) +{ + DWORD dwData; + + // compare MAC context to determine if this is a power lost init, + // return TRUE for power remaining init, return FALSE for power lost init + + // compare CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR + VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, &dwData); + if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_TXDMAPTR0)) { + return FALSE; + } + + VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, &dwData); + if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_AC0DMAPTR)) { + return FALSE; + } + + VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, &dwData); + if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR0)) { + return FALSE; + } + + VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, &dwData); + if (dwData != *(PDWORD)(pbyCxtBuf + MAC_REG_RXDMAPTR1)) { + return FALSE; + } + + + return TRUE; +} + +/* + * Description: + * Software Reset MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if Reset Success; otherwise FALSE + * + */ +BOOL MACbSoftwareReset (DWORD_PTR dwIoBase) +{ + BYTE byData; + WORD ww; + + // turn on HOSTCR_SOFTRST, just write 0x01 to reset + //MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_SOFTRST); + VNSvOutPortB(dwIoBase+ MAC_REG_HOSTCR, 0x01); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData); + if (BITbIsBitOff(byData, HOSTCR_SOFTRST)) + break; + } + if (ww == W_MAX_TIMEOUT) + return FALSE; + return TRUE; + +} + +/* + * Description: + * save some important register's value, then do reset, then restore register's value + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL MACbSafeSoftwareReset (DWORD_PTR dwIoBase) +{ + BYTE abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1]; + BOOL bRetVal; + + // PATCH.... + // save some important register's value, then do + // reset, then restore register's value + + // save MAC context + MACvSaveContext(dwIoBase, abyTmpRegData); + // do reset + bRetVal = MACbSoftwareReset(dwIoBase); + //BBvSoftwareReset(pDevice->PortOffset); + // restore MAC context, except CR0 + MACvRestoreContext(dwIoBase, abyTmpRegData); + + return bRetVal; +} + +/* + * Description: + * Trun Off MAC Rx + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL MACbSafeRxOff (DWORD_PTR dwIoBase) +{ + WORD ww; + DWORD dwData; + BYTE byData; + + // turn off wow temp for turn off Rx safely + + // Clear RX DMA0,1 + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_CLRRUN); + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_CLRRUN); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData); + if (BITbIsAllBitsOff(dwData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x10); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x10)\n"); + return(FALSE); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData); + if (BITbIsAllBitsOff(dwData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x11); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x11)\n"); + return(FALSE); + } + + // try to safe shutdown RX + MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON); + // W_MAX_TIMEOUT is the timeout period + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData); + if (BITbIsAllBitsOff(byData, HOSTCR_RXONST)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x12); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x12)\n"); + return(FALSE); + } + return TRUE; +} + +/* + * Description: + * Trun Off MAC Tx + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL MACbSafeTxOff (DWORD_PTR dwIoBase) +{ + WORD ww; + DWORD dwData; + BYTE byData; + + // Clear TX DMA + //Tx0 + VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_CLRRUN); + //AC0 + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_CLRRUN); + + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData); + if (BITbIsAllBitsOff(dwData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x20); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x20)\n"); + return(FALSE); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData); + if (BITbIsAllBitsOff(dwData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x21); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x21)\n"); + return(FALSE); + } + + // try to safe shutdown TX + MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON); + + // W_MAX_TIMEOUT is the timeout period + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_HOSTCR, &byData); + if (BITbIsAllBitsOff(byData, HOSTCR_TXONST)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x24); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x24)\n"); + return(FALSE); + } + return TRUE; +} + +/* + * Description: + * Stop MAC function + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL MACbSafeStop (DWORD_PTR dwIoBase) +{ + MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); + + if (MACbSafeRxOff(dwIoBase) == FALSE) { + DBG_PORT80(0xA1); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" MACbSafeRxOff == FALSE)\n"); + MACbSafeSoftwareReset(dwIoBase); + return FALSE; + } + if (MACbSafeTxOff(dwIoBase) == FALSE) { + DBG_PORT80(0xA2); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" MACbSafeTxOff == FALSE)\n"); + MACbSafeSoftwareReset(dwIoBase); + return FALSE; + } + + MACvRegBitsOff(dwIoBase, MAC_REG_HOSTCR, HOSTCR_MACEN); + + return TRUE; +} + +/* + * Description: + * Shut Down MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL MACbShutdown (DWORD_PTR dwIoBase) +{ + // disable MAC IMR + MACvIntDisable(dwIoBase); + MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL); + // stop the adapter + if (!MACbSafeStop(dwIoBase)) { + MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + return FALSE; + } + MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + return TRUE; +} + +/* + * Description: + * Initialize MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * Out: + * none + * + * Return Value: none + * + */ +void MACvInitialize (DWORD_PTR dwIoBase) +{ + // clear sticky bits + MACvClearStckDS(dwIoBase); + // disable force PME-enable + VNSvOutPortB(dwIoBase + MAC_REG_PMC1, PME_OVR); + // only 3253 A + /* + MACvPwrEvntDisable(dwIoBase); + // clear power status + VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPSR0, 0x0F0F); + */ + + // do reset + MACbSoftwareReset(dwIoBase); + + // issue AUTOLD in EECSR to reload eeprom + //MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD); + // wait until EEPROM loading complete + //while (TRUE) { + // U8 u8Data; + // VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &u8Data); + // if (BITbIsBitOff(u8Data, I2MCSR_AUTOLD)) + // break; + //} + + // reset TSF counter + VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); + // enable TSF counter + VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + + + // set packet filter + // receive directed and broadcast address + + MACvSetPacketFilter(dwIoBase, PKT_TYPE_DIRECTED | PKT_TYPE_BROADCAST); + +} + +/* + * Description: + * Set the chip with current rx descriptor address + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * dwCurrDescAddr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetCurrRx0DescAddr (DWORD_PTR dwIoBase, DWORD dwCurrDescAddr) +{ +WORD ww; +BYTE byData; +BYTE byOrgDMACtl; + + VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byOrgDMACtl); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0+2, DMACTL_RUN); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL0, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x13); + } + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); + } +} + +/* + * Description: + * Set the chip with current rx descriptor address + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * dwCurrDescAddr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetCurrRx1DescAddr (DWORD_PTR dwIoBase, DWORD dwCurrDescAddr) +{ +WORD ww; +BYTE byData; +BYTE byOrgDMACtl; + + VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byOrgDMACtl); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1+2, DMACTL_RUN); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_RXDMACTL1, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x14); + } + VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN); + } +} + +/* + * Description: + * Set the chip with current tx0 descriptor address + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * dwCurrDescAddr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetCurrTx0DescAddrEx (DWORD_PTR dwIoBase, DWORD dwCurrDescAddr) +{ +WORD ww; +BYTE byData; +BYTE byOrgDMACtl; + + VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byOrgDMACtl); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x25); + } + VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN); + } +} + +/* + * Description: + * Set the chip with current AC0 descriptor address + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * dwCurrDescAddr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ + //TxDMA1 = AC0DMA +void MACvSetCurrAC0DescAddrEx (DWORD_PTR dwIoBase, DWORD dwCurrDescAddr) +{ +WORD ww; +BYTE byData; +BYTE byOrgDMACtl; + + VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byOrgDMACtl); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN); + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x26); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x26)\n"); + } + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr); + if (BITbIsAllBitsOn(byOrgDMACtl, DMACTL_RUN)) { + VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); + } +} + + + +void MACvSetCurrTXDescAddr (int iTxType, DWORD_PTR dwIoBase, DWORD dwCurrDescAddr) +{ + if(iTxType == TYPE_AC0DMA){ + MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr); + }else if(iTxType == TYPE_TXDMA0){ + MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr); + } +} + +/* + * Description: + * Micro Second Delay via MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * uDelay - Delay time (timer resolution is 4 us) + * Out: + * none + * + * Return Value: none + * + */ +VOID MACvTimer0MicroSDelay (DWORD_PTR dwIoBase, UINT uDelay) +{ +BYTE byValue; +UINT uu,ii; + + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); + VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelay); + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE)); + for(ii=0;ii<66;ii++) { // assume max PCI clock is 66Mhz + for (uu = 0; uu < uDelay; uu++) { + VNSvInPortB(dwIoBase + MAC_REG_TMCTL0, &byValue); + if ((byValue == 0) || + (BITbIsAllBitsOn(byValue, TMCTL_TSUSP))) { + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); + return; + } + } + } + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); + +} + +/* + * Description: + * Micro Second One shot timer via MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * uDelay - Delay time + * Out: + * none + * + * Return Value: none + * + */ +void MACvOneShotTimer0MicroSec (DWORD_PTR dwIoBase, UINT uDelayTime) +{ + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, 0); + VNSvOutPortD(dwIoBase + MAC_REG_TMDATA0, uDelayTime); + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL0, (TMCTL_TMD | TMCTL_TE)); +} + +/* + * Description: + * Micro Second One shot timer via MAC + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * uDelay - Delay time + * Out: + * none + * + * Return Value: none + * + */ +void MACvOneShotTimer1MicroSec (DWORD_PTR dwIoBase, UINT uDelayTime) +{ + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0); + VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime); + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE)); +} + + +void MACvSetMISCFifo (DWORD_PTR dwIoBase, WORD wOffset, DWORD dwData) +{ + if (wOffset > 273) + return; + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); +} + + +BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, UINT idx) +{ +BYTE byData; +UINT ww = 0; + + if (idx == TYPE_TXDMA0) { + VNSvOutPortB(dwIoBase + MAC_REG_TXDMACTL0+2, DMACTL_RUN); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_TXDMACTL0, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + } else if (idx == TYPE_AC0DMA) { + VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL+2, DMACTL_RUN); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_AC0DMACTL, &byData); + if (BITbIsAllBitsOff(byData, DMACTL_RUN)) + break; + } + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x29); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x29)\n"); + return FALSE; + } + return TRUE; +} + +void MACvClearBusSusInd (DWORD_PTR dwIoBase) +{ + DWORD dwOrgValue; + UINT ww; + // check if BcnSusInd enabled + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); + if(BITbIsBitOff(dwOrgValue, EnCFG_BcnSusInd)) + return; + //Set BcnSusClr + dwOrgValue = dwOrgValue | EnCFG_BcnSusClr; + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); + if(BITbIsBitOff(dwOrgValue, EnCFG_BcnSusInd)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x33); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n"); + } +} + +void MACvEnableBusSusEn (DWORD_PTR dwIoBase) +{ + BYTE byOrgValue; + DWORD dwOrgValue; + UINT ww; + // check if BcnSusInd enabled + VNSvInPortB(dwIoBase + MAC_REG_CFG , &byOrgValue); + + //Set BcnSusEn + byOrgValue = byOrgValue | CFG_BCNSUSEN; + VNSvOutPortB(dwIoBase + MAC_REG_ENCFG, byOrgValue); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); + if(BITbIsBitOn(dwOrgValue, EnCFG_BcnSusInd)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x34); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x34)\n"); + } +} + +BOOL MACbFlushSYNCFifo (DWORD_PTR dwIoBase) +{ + BYTE byOrgValue; + UINT ww; + // Read MACCR + VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue); + + // Set SYNCFLUSH + byOrgValue = byOrgValue | MACCR_SYNCFLUSH; + VNSvOutPortB(dwIoBase + MAC_REG_MACCR, byOrgValue); + + // Check if SyncFlushOK + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_MACCR , &byOrgValue); + if(BITbIsBitOn(byOrgValue, MACCR_SYNCFLUSHOK)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x35); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n"); + } + return TRUE; +} + +BOOL MACbPSWakeup (DWORD_PTR dwIoBase) +{ + BYTE byOrgValue; + UINT ww; + // Read PSCTL + if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) { + return TRUE; + } + // Disable PS + MACvRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PSEN); + + // Check if SyncFlushOK + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortB(dwIoBase + MAC_REG_PSCTL , &byOrgValue); + if(BITbIsBitOn(byOrgValue, PSCTL_WAKEDONE)) + break; + } + if (ww == W_MAX_TIMEOUT) { + DBG_PORT80(0x36); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" DBG_PORT80(0x33)\n"); + return FALSE; + } + return TRUE; +} + +/* + * Description: + * Set the Key by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ + +void MACvSetKeyEntry (DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, UINT uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID) +{ +WORD wOffset; +DWORD dwData; +int ii; + + if (byLocalID <= 1) + return; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetKeyEntry\n"); + wOffset = MISCFIFO_KEYETRY0; + wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + dwData = 0; + dwData |= wKeyCtl; + dwData <<= 16; + dwData |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl); + + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + wOffset++; + + dwData = 0; + dwData |= *(pbyAddr+3); + dwData <<= 8; + dwData |= *(pbyAddr+2); + dwData <<= 8; + dwData |= *(pbyAddr+1); + dwData <<= 8; + dwData |= *(pbyAddr+0); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData); + + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + wOffset++; + + wOffset += (uKeyIdx * 4); + for (ii=0;ii<4;ii++) { + // alway push 128 bits + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"3.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + } +} + + + +/* + * Description: + * Disable the Key Entry by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvDisableKeyEntry (DWORD_PTR dwIoBase, UINT uEntryIdx) +{ +WORD wOffset; + + wOffset = MISCFIFO_KEYETRY0; + wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, 0); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); +} + + +/* + * Description: + * Set the default Key (KeyEntry[10]) by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ + +void MACvSetDefaultKeyEntry (DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID) +{ +WORD wOffset; +DWORD dwData; +int ii; + + if (byLocalID <= 1) + return; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetDefaultKeyEntry\n"); + wOffset = MISCFIFO_KEYETRY0; + wOffset += (10 * MISCFIFO_KEYENTRYSIZE); + + wOffset++; + wOffset++; + wOffset += (uKeyIdx * 4); + // alway push 128 bits + for (ii=0; ii<3; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + } + dwData = *pdwKey; + if (uKeyLen == WLAN_WEP104_KEYLEN) { + dwData |= 0x80000000; + } + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+3); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"End. wOffset: %d, Data: %lX\n", wOffset+3, dwData); + +} + + +/* + * Description: + * Enable default Key (KeyEntry[10]) by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +/* +void MACvEnableDefaultKey (DWORD_PTR dwIoBase, BYTE byLocalID) +{ +WORD wOffset; +DWORD dwData; + + + if (byLocalID <= 1) + return; + + wOffset = MISCFIFO_KEYETRY0; + wOffset += (10 * MISCFIFO_KEYENTRYSIZE); + + dwData = 0xC0440000; + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvEnableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData); + +} +*/ + +/* + * Description: + * Disable default Key (KeyEntry[10]) by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvDisableDefaultKey (DWORD_PTR dwIoBase) +{ +WORD wOffset; +DWORD dwData; + + + wOffset = MISCFIFO_KEYETRY0; + wOffset += (10 * MISCFIFO_KEYENTRYSIZE); + + dwData = 0x0; + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvDisableDefaultKey: wOffset: %d, Data: %lX\n", wOffset, dwData); +} + +/* + * Description: + * Set the default TKIP Group Key (KeyEntry[10]) by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetDefaultTKIPKeyEntry (DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID) +{ +WORD wOffset; +DWORD dwData; +int ii; + + if (byLocalID <= 1) + return; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetDefaultTKIPKeyEntry\n"); + wOffset = MISCFIFO_KEYETRY0; + // Kyle test : change offset from 10 -> 0 + wOffset += (10 * MISCFIFO_KEYENTRYSIZE); + + dwData = 0xC0660000; + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + wOffset++; + + dwData = 0; + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + wOffset++; + + wOffset += (uKeyIdx * 4); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, idx:%d\n", wOffset, *pdwKey, uKeyIdx); + // alway push 128 bits + for (ii=0; ii<4; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2.(%d) wOffset: %d, Data: %lX\n", ii, wOffset+ii, *pdwKey); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset+ii); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, *pdwKey++); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + } + +} + + + +/* + * Description: + * Set the Key Control by MISCFIFO + * + * Parameters: + * In: + * dwIoBase - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ + +void MACvSetDefaultKeyCtl (DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, BYTE byLocalID) +{ +WORD wOffset; +DWORD dwData; + + if (byLocalID <= 1) + return; + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MACvSetKeyEntry\n"); + wOffset = MISCFIFO_KEYETRY0; + wOffset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + dwData = 0; + dwData |= wKeyCtl; + dwData <<= 16; + dwData |= 0xffff; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData, wKeyCtl); + + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); + +} + diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h new file mode 100644 index 00000000000..edb70965d4d --- /dev/null +++ b/drivers/staging/vt6655/mac.h @@ -0,0 +1,1166 @@ +/* + * 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: mac.h + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * Revision History: + * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53. + * 09-03-2003 Bryan YC Fan: Add MACvDisableProtectMD & MACvEnableProtectMD + * + */ + +#ifndef __MAC_H__ +#define __MAC_H__ + + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__UPC_H__) +#include "upc.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +// +// Registers in the MAC +// +#define MAC_MAX_CONTEXT_SIZE_PAGE0 256 +#define MAC_MAX_CONTEXT_SIZE_PAGE1 128 +#define MAC_MAX_CONTEXT_SIZE MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1 + +// Registers not related to 802.11b +#define MAC_REG_BCFG0 0x00 +#define MAC_REG_BCFG1 0x01 +#define MAC_REG_FCR0 0x02 +#define MAC_REG_FCR1 0x03 +#define MAC_REG_BISTCMD 0x04 +#define MAC_REG_BISTSR0 0x05 +#define MAC_REG_BISTSR1 0x06 +#define MAC_REG_BISTSR2 0x07 +#define MAC_REG_I2MCSR 0x08 +#define MAC_REG_I2MTGID 0x09 +#define MAC_REG_I2MTGAD 0x0A +#define MAC_REG_I2MCFG 0x0B +#define MAC_REG_I2MDIPT 0x0C +#define MAC_REG_I2MDOPT 0x0E +#define MAC_REG_PMC0 0x10 +#define MAC_REG_PMC1 0x11 +#define MAC_REG_STICKHW 0x12 +#define MAC_REG_LOCALID 0x14 +#define MAC_REG_TESTCFG 0x15 +#define MAC_REG_JUMPER0 0x16 +#define MAC_REG_JUMPER1 0x17 +#define MAC_REG_TMCTL0 0x18 +#define MAC_REG_TMCTL1 0x19 +#define MAC_REG_TMDATA0 0x1C +// MAC Parameter related +#define MAC_REG_LRT 0x20 // +#define MAC_REG_SRT 0x21 // +#define MAC_REG_SIFS 0x22 // +#define MAC_REG_DIFS 0x23 // +#define MAC_REG_EIFS 0x24 // +#define MAC_REG_SLOT 0x25 // +#define MAC_REG_BI 0x26 // +#define MAC_REG_CWMAXMIN0 0x28 // +#define MAC_REG_LINKOFFTOTM 0x2A +#define MAC_REG_SWTMOT 0x2B +#define MAC_REG_MIBCNTR 0x2C +#define MAC_REG_RTSOKCNT 0x2C +#define MAC_REG_RTSFAILCNT 0x2D +#define MAC_REG_ACKFAILCNT 0x2E +#define MAC_REG_FCSERRCNT 0x2F +// TSF Related +#define MAC_REG_TSFCNTR 0x30 // +#define MAC_REG_NEXTTBTT 0x38 // +#define MAC_REG_TSFOFST 0x40 // +#define MAC_REG_TFTCTL 0x48 // +// WMAC Control/Status Related +#define MAC_REG_ENCFG 0x4C // +#define MAC_REG_PAGE1SEL 0x4F // +#define MAC_REG_CFG 0x50 // +#define MAC_REG_TEST 0x52 // +#define MAC_REG_HOSTCR 0x54 // +#define MAC_REG_MACCR 0x55 // +#define MAC_REG_RCR 0x56 // +#define MAC_REG_TCR 0x57 // +#define MAC_REG_IMR 0x58 // +#define MAC_REG_ISR 0x5C +// Power Saving Related +#define MAC_REG_PSCFG 0x60 // +#define MAC_REG_PSCTL 0x61 // +#define MAC_REG_PSPWRSIG 0x62 // +#define MAC_REG_BBCR13 0x63 +#define MAC_REG_AIDATIM 0x64 +#define MAC_REG_PWBT 0x66 +#define MAC_REG_WAKEOKTMR 0x68 +#define MAC_REG_CALTMR 0x69 +#define MAC_REG_SYNSPACCNT 0x6A +#define MAC_REG_WAKSYNOPT 0x6B +// Baseband/IF Control Group +#define MAC_REG_BBREGCTL 0x6C // +#define MAC_REG_CHANNEL 0x6D +#define MAC_REG_BBREGADR 0x6E +#define MAC_REG_BBREGDATA 0x6F +#define MAC_REG_IFREGCTL 0x70 // +#define MAC_REG_IFDATA 0x71 // +#define MAC_REG_ITRTMSET 0x74 // +#define MAC_REG_PAPEDELAY 0x77 // +#define MAC_REG_SOFTPWRCTL 0x78 // +#define MAC_REG_GPIOCTL0 0x7A // +#define MAC_REG_GPIOCTL1 0x7B // + +// MAC DMA Related Group +#define MAC_REG_TXDMACTL0 0x7C // +#define MAC_REG_TXDMAPTR0 0x80 // +#define MAC_REG_AC0DMACTL 0x84 // +#define MAC_REG_AC0DMAPTR 0x88 // +#define MAC_REG_BCNDMACTL 0x8C // +#define MAC_REG_BCNDMAPTR 0x90 // +#define MAC_REG_RXDMACTL0 0x94 // +#define MAC_REG_RXDMAPTR0 0x98 // +#define MAC_REG_RXDMACTL1 0x9C // +#define MAC_REG_RXDMAPTR1 0xA0 // +#define MAC_REG_SYNCDMACTL 0xA4 // +#define MAC_REG_SYNCDMAPTR 0xA8 +#define MAC_REG_ATIMDMACTL 0xAC +#define MAC_REG_ATIMDMAPTR 0xB0 +// MiscFF PIO related +#define MAC_REG_MISCFFNDEX 0xB4 +#define MAC_REG_MISCFFCTL 0xB6 +#define MAC_REG_MISCFFDATA 0xB8 +// Extend SW Timer +#define MAC_REG_TMDATA1 0xBC +// WOW Related Group +#define MAC_REG_WAKEUPEN0 0xC0 +#define MAC_REG_WAKEUPEN1 0xC1 +#define MAC_REG_WAKEUPSR0 0xC2 +#define MAC_REG_WAKEUPSR1 0xC3 +#define MAC_REG_WAKE128_0 0xC4 +#define MAC_REG_WAKE128_1 0xD4 +#define MAC_REG_WAKE128_2 0xE4 +#define MAC_REG_WAKE128_3 0xF4 + +/////////////// Page 1 /////////////////// +#define MAC_REG_CRC_128_0 0x04 +#define MAC_REG_CRC_128_1 0x06 +#define MAC_REG_CRC_128_2 0x08 +#define MAC_REG_CRC_128_3 0x0A +// MAC Configuration Group +#define MAC_REG_PAR0 0x0C +#define MAC_REG_PAR4 0x10 +#define MAC_REG_BSSID0 0x14 +#define MAC_REG_BSSID4 0x18 +#define MAC_REG_MAR0 0x1C +#define MAC_REG_MAR4 0x20 +// MAC RSPPKT INFO Group +#define MAC_REG_RSPINF_B_1 0x24 +#define MAC_REG_RSPINF_B_2 0x28 +#define MAC_REG_RSPINF_B_5 0x2C +#define MAC_REG_RSPINF_B_11 0x30 +#define MAC_REG_RSPINF_A_6 0x34 +#define MAC_REG_RSPINF_A_9 0x36 +#define MAC_REG_RSPINF_A_12 0x38 +#define MAC_REG_RSPINF_A_18 0x3A +#define MAC_REG_RSPINF_A_24 0x3C +#define MAC_REG_RSPINF_A_36 0x3E +#define MAC_REG_RSPINF_A_48 0x40 +#define MAC_REG_RSPINF_A_54 0x42 +#define MAC_REG_RSPINF_A_72 0x44 + +// 802.11h relative +#define MAC_REG_QUIETINIT 0x60 +#define MAC_REG_QUIETGAP 0x62 +#define MAC_REG_QUIETDUR 0x64 +#define MAC_REG_MSRCTL 0x66 +#define MAC_REG_MSRBBSTS 0x67 +#define MAC_REG_MSRSTART 0x68 +#define MAC_REG_MSRDURATION 0x70 +#define MAC_REG_CCAFRACTION 0x72 +#define MAC_REG_PWRCCK 0x73 +#define MAC_REG_PWROFDM 0x7C + + +// +// Bits in the BCFG0 register +// +#define BCFG0_PERROFF 0x40 +#define BCFG0_MRDMDIS 0x20 +#define BCFG0_MRDLDIS 0x10 +#define BCFG0_MWMEN 0x08 +#define BCFG0_VSERREN 0x02 +#define BCFG0_LATMEN 0x01 + +// +// Bits in the BCFG1 register +// +#define BCFG1_CFUNOPT 0x80 +#define BCFG1_CREQOPT 0x40 +#define BCFG1_DMA8 0x10 +#define BCFG1_ARBITOPT 0x08 +#define BCFG1_PCIMEN 0x04 +#define BCFG1_MIOEN 0x02 +#define BCFG1_CISDLYEN 0x01 + +// Bits in RAMBIST registers +#define BISTCMD_TSTPAT5 0x00 // +#define BISTCMD_TSTPATA 0x80 // +#define BISTCMD_TSTERR 0x20 // +#define BISTCMD_TSTPATF 0x18 // +#define BISTCMD_TSTPAT0 0x10 // +#define BISTCMD_TSTMODE 0x04 // +#define BISTCMD_TSTITTX 0x03 // +#define BISTCMD_TSTATRX 0x02 // +#define BISTCMD_TSTATTX 0x01 // +#define BISTCMD_TSTRX 0x00 // +#define BISTSR0_BISTGO 0x01 // +#define BISTSR1_TSTSR 0x01 // +#define BISTSR2_CMDPRTEN 0x02 // +#define BISTSR2_RAMTSTEN 0x01 // + +// +// Bits in the I2MCFG EEPROM register +// +#define I2MCFG_BOUNDCTL 0x80 +#define I2MCFG_WAITCTL 0x20 +#define I2MCFG_SCLOECTL 0x10 +#define I2MCFG_WBUSYCTL 0x08 +#define I2MCFG_NORETRY 0x04 +#define I2MCFG_I2MLDSEQ 0x02 +#define I2MCFG_I2CMFAST 0x01 + +// +// Bits in the I2MCSR EEPROM register +// +#define I2MCSR_EEMW 0x80 +#define I2MCSR_EEMR 0x40 +#define I2MCSR_AUTOLD 0x08 +#define I2MCSR_NACK 0x02 +#define I2MCSR_DONE 0x01 + +// +// Bits in the PMC1 register +// +#define SPS_RST 0x80 +#define PCISTIKY 0x40 +#define PME_OVR 0x02 + +// +// Bits in the STICKYHW register +// +#define STICKHW_DS1_SHADOW 0x02 +#define STICKHW_DS0_SHADOW 0x01 + +// +// Bits in the TMCTL register +// +#define TMCTL_TSUSP 0x04 +#define TMCTL_TMD 0x02 +#define TMCTL_TE 0x01 + +// +// Bits in the TFTCTL register +// +#define TFTCTL_HWUTSF 0x80 // +#define TFTCTL_TBTTSYNC 0x40 +#define TFTCTL_HWUTSFEN 0x20 +#define TFTCTL_TSFCNTRRD 0x10 // +#define TFTCTL_TBTTSYNCEN 0x08 // +#define TFTCTL_TSFSYNCEN 0x04 // +#define TFTCTL_TSFCNTRST 0x02 // +#define TFTCTL_TSFCNTREN 0x01 // + +// +// Bits in the EnhanceCFG register +// +#define EnCFG_BarkerPream 0x00020000 +#define EnCFG_NXTBTTCFPSTR 0x00010000 +//#define EnCFG_TXLMT3UPDATE 0x00008000 +//#define EnCFG_TXLMT2UPDATE 0x00004000 +//#define EnCFG_TXLMT1UPDATE 0x00002000 +//#define EnCFG_TXLMT3EN 0x00001000 +//#define EnCFG_TXLMT2EN 0x00000800 +//#define EnCFG_TXLMT1EN 0x00000400 +#define EnCFG_BcnSusClr 0x00000200 +#define EnCFG_BcnSusInd 0x00000100 +//#define EnCFG_CWOFF1 0x00000080 +#define EnCFG_CFP_ProtectEn 0x00000040 +#define EnCFG_ProtectMd 0x00000020 +#define EnCFG_HwParCFP 0x00000010 +//#define EnCFG_QOS 0x00000008 +#define EnCFG_CFNULRSP 0x00000004 +#define EnCFG_BBType_MASK 0x00000003 +#define EnCFG_BBType_g 0x00000002 +#define EnCFG_BBType_b 0x00000001 +#define EnCFG_BBType_a 0x00000000 + +// +// Bits in the Page1Sel register +// +#define PAGE1_SEL 0x01 + +// +// Bits in the CFG register +// +#define CFG_TKIPOPT 0x80 +#define CFG_RXDMAOPT 0x40 +#define CFG_TMOT_SW 0x20 +#define CFG_TMOT_HWLONG 0x10 +#define CFG_TMOT_HW 0x00 +#define CFG_CFPENDOPT 0x08 +#define CFG_BCNSUSEN 0x04 +#define CFG_NOTXTIMEOUT 0x02 +#define CFG_NOBUFOPT 0x01 + +// +// Bits in the TEST register +// +#define TEST_LBEXT 0x80 // +#define TEST_LBINT 0x40 // +#define TEST_LBNONE 0x00 // +#define TEST_SOFTINT 0x20 // +#define TEST_CONTTX 0x10 // +#define TEST_TXPE 0x08 // +#define TEST_NAVDIS 0x04 // +#define TEST_NOCTS 0x02 // +#define TEST_NOACK 0x01 // + +// +// Bits in the HOSTCR register +// +#define HOSTCR_TXONST 0x80 // +#define HOSTCR_RXONST 0x40 // +#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc +#define HOSTCR_AP 0x10 // Port Type 1 = AP +#define HOSTCR_TXON 0x08 //0000 1000 +#define HOSTCR_RXON 0x04 //0000 0100 +#define HOSTCR_MACEN 0x02 //0000 0010 +#define HOSTCR_SOFTRST 0x01 //0000 0001 + +// +// Bits in the MACCR register +// +#define MACCR_SYNCFLUSHOK 0x04 // +#define MACCR_SYNCFLUSH 0x02 // +#define MACCR_CLRNAV 0x01 // + +// Bits in the MAC_REG_GPIOCTL0 register +// +#define LED_ACTSET 0x01 // +#define LED_RFOFF 0x02 // +#define LED_NOCONNECT 0x04 // +// +// Bits in the RCR register +// +#define RCR_SSID 0x80 +#define RCR_RXALLTYPE 0x40 // +#define RCR_UNICAST 0x20 // +#define RCR_BROADCAST 0x10 // +#define RCR_MULTICAST 0x08 // +#define RCR_WPAERR 0x04 // +#define RCR_ERRCRC 0x02 // +#define RCR_BSSID 0x01 // + +// +// Bits in the TCR register +// +#define TCR_SYNCDCFOPT 0x02 // +#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable + +// +// Bits in the IMR register +// +#define IMR_MEASURESTART 0x80000000 // +#define IMR_QUIETSTART 0x20000000 // +#define IMR_RADARDETECT 0x10000000 // +#define IMR_MEASUREEND 0x08000000 // +#define IMR_SOFTTIMER1 0x00200000 // +//#define IMR_SYNCFLUSHOK 0x00100000 // +//#define IMR_ATIMEND 0x00080000 //0000 1000 0000 0000 0000 0000 +//#define IMR_CFPEND 0x00040000 //0000 0100 0000 0000 0000 0000 +//#define IMR_AC3DMA 0x00020000 //0000 0010 0000 0000 0000 0000 +//#define IMR_AC2DMA 0x00010000 //0000 0001 0000 0000 0000 0000 +//#define IMR_AC1DMA 0x00008000 //0000 0000 1000 0000 0000 0000 +//#define IMR_SYNCTX 0x00004000 //0000 0000 0100 0000 0000 0000 +//#define IMR_ATIMTX 0x00002000 //0000 0000 0010 0000 0000 0000 +#define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 +#define IMR_RXNOBUF 0x00000800 // +#define IMR_MIBNEARFULL 0x00000400 // +#define IMR_SOFTINT 0x00000200 // +#define IMR_FETALERR 0x00000100 // +#define IMR_WATCHDOG 0x00000080 // +#define IMR_SOFTTIMER 0x00000040 // +#define IMR_GPIO 0x00000020 // +#define IMR_TBTT 0x00000010 // +#define IMR_RXDMA0 0x00000008 // +#define IMR_BNTX 0x00000004 // +#define IMR_AC0DMA 0x00000002 // +#define IMR_TXDMA0 0x00000001 // + + +// +// Bits in the ISR register +// + +#define ISR_MEASURESTART 0x80000000 // +#define ISR_QUIETSTART 0x20000000 // +#define ISR_RADARDETECT 0x10000000 // +#define ISR_MEASUREEND 0x08000000 // +#define ISR_SOFTTIMER1 0x00200000 // +//#define ISR_SYNCFLUSHOK 0x00100000 //0001 0000 0000 0000 0000 0000 +//#define ISR_ATIMEND 0x00080000 //0000 1000 0000 0000 0000 0000 +//#define ISR_CFPEND 0x00040000 //0000 0100 0000 0000 0000 0000 +//#define ISR_AC3DMA 0x00020000 //0000 0010 0000 0000 0000 0000 +//#define ISR_AC2DMA 0x00010000 //0000 0001 0000 0000 0000 0000 +//#define ISR_AC1DMA 0x00008000 //0000 0000 1000 0000 0000 0000 +//#define ISR_SYNCTX 0x00004000 //0000 0000 0100 0000 0000 0000 +//#define ISR_ATIMTX 0x00002000 //0000 0000 0010 0000 0000 0000 +#define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 +#define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 +#define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 +#define ISR_SOFTINT 0x00000200 // +#define ISR_FETALERR 0x00000100 // +#define ISR_WATCHDOG 0x00000080 // +#define ISR_SOFTTIMER 0x00000040 // +#define ISR_GPIO 0x00000020 // +#define ISR_TBTT 0x00000010 // +#define ISR_RXDMA0 0x00000008 // +#define ISR_BNTX 0x00000004 // +#define ISR_AC0DMA 0x00000002 // +#define ISR_TXDMA0 0x00000001 // + + +// +// Bits in the PSCFG register +// +#define PSCFG_PHILIPMD 0x40 // +#define PSCFG_WAKECALEN 0x20 // +#define PSCFG_WAKETMREN 0x10 // +#define PSCFG_BBPSPROG 0x08 // +#define PSCFG_WAKESYN 0x04 // +#define PSCFG_SLEEPSYN 0x02 // +#define PSCFG_AUTOSLEEP 0x01 // + +// +// Bits in the PSCTL register +// +#define PSCTL_WAKEDONE 0x20 // +#define PSCTL_PS 0x10 // +#define PSCTL_GO2DOZE 0x08 // +#define PSCTL_LNBCN 0x04 // +#define PSCTL_ALBCN 0x02 // +#define PSCTL_PSEN 0x01 // + +// +// Bits in the PSPWSIG register +// +#define PSSIG_WPE3 0x80 // +#define PSSIG_WPE2 0x40 // +#define PSSIG_WPE1 0x20 // +#define PSSIG_WRADIOPE 0x10 // +#define PSSIG_SPE3 0x08 // +#define PSSIG_SPE2 0x04 // +#define PSSIG_SPE1 0x02 // +#define PSSIG_SRADIOPE 0x01 // + +// +// Bits in the BBREGCTL register +// +#define BBREGCTL_DONE 0x04 // +#define BBREGCTL_REGR 0x02 // +#define BBREGCTL_REGW 0x01 // + +// +// Bits in the IFREGCTL register +// +#define IFREGCTL_DONE 0x04 // +#define IFREGCTL_IFRF 0x02 // +#define IFREGCTL_REGW 0x01 // + +// +// Bits in the SOFTPWRCTL register +// +#define SOFTPWRCTL_RFLEOPT 0x0800 // +#define SOFTPWRCTL_TXPEINV 0x0200 // +#define SOFTPWRCTL_SWPECTI 0x0100 // +#define SOFTPWRCTL_SWPAPE 0x0020 // +#define SOFTPWRCTL_SWCALEN 0x0010 // +#define SOFTPWRCTL_SWRADIO_PE 0x0008 // +#define SOFTPWRCTL_SWPE2 0x0004 // +#define SOFTPWRCTL_SWPE1 0x0002 // +#define SOFTPWRCTL_SWPE3 0x0001 // + +// +// Bits in the GPIOCTL1 register +// +#define GPIO1_DATA1 0x20 // +#define GPIO1_MD1 0x10 // +#define GPIO1_DATA0 0x02 // +#define GPIO1_MD0 0x01 // + +// +// Bits in the DMACTL register +// +#define DMACTL_CLRRUN 0x00080000 // +#define DMACTL_RUN 0x00000008 // +#define DMACTL_WAKE 0x00000004 // +#define DMACTL_DEAD 0x00000002 // +#define DMACTL_ACTIVE 0x00000001 // +// +// Bits in the RXDMACTL0 register +// +#define RX_PERPKT 0x00000100 // +#define RX_PERPKTCLR 0x01000000 // +// +// Bits in the BCNDMACTL register +// +#define BEACON_READY 0x01 // +// +// Bits in the MISCFFCTL register +// +#define MISCFFCTL_WRITE 0x0001 // + + +// +// Bits in WAKEUPEN0 +// +#define WAKEUPEN0_DIRPKT 0x10 +#define WAKEUPEN0_LINKOFF 0x08 +#define WAKEUPEN0_ATIMEN 0x04 +#define WAKEUPEN0_TIMEN 0x02 +#define WAKEUPEN0_MAGICEN 0x01 + +// +// Bits in WAKEUPEN1 +// +#define WAKEUPEN1_128_3 0x08 +#define WAKEUPEN1_128_2 0x04 +#define WAKEUPEN1_128_1 0x02 +#define WAKEUPEN1_128_0 0x01 + +// +// Bits in WAKEUPSR0 +// +#define WAKEUPSR0_DIRPKT 0x10 +#define WAKEUPSR0_LINKOFF 0x08 +#define WAKEUPSR0_ATIMEN 0x04 +#define WAKEUPSR0_TIMEN 0x02 +#define WAKEUPSR0_MAGICEN 0x01 + +// +// Bits in WAKEUPSR1 +// +#define WAKEUPSR1_128_3 0x08 +#define WAKEUPSR1_128_2 0x04 +#define WAKEUPSR1_128_1 0x02 +#define WAKEUPSR1_128_0 0x01 + +// +// Bits in the MAC_REG_GPIOCTL register +// +#define GPIO0_MD 0x01 // +#define GPIO0_DATA 0x02 // +#define GPIO0_INTMD 0x04 // +#define GPIO1_MD 0x10 // +#define GPIO1_DATA 0x20 // + + +// +// Bits in the MSRCTL register +// +#define MSRCTL_FINISH 0x80 +#define MSRCTL_READY 0x40 +#define MSRCTL_RADARDETECT 0x20 +#define MSRCTL_EN 0x10 +#define MSRCTL_QUIETTXCHK 0x08 +#define MSRCTL_QUIETRPT 0x04 +#define MSRCTL_QUIETINT 0x02 +#define MSRCTL_QUIETEN 0x01 +// +// Bits in the MSRCTL1 register +// +#define MSRCTL1_TXPWR 0x08 +#define MSRCTL1_CSAPAREN 0x04 +#define MSRCTL1_TXPAUSE 0x01 + + +// Loopback mode +#define MAC_LB_EXT 0x02 // +#define MAC_LB_INTERNAL 0x01 // +#define MAC_LB_NONE 0x00 // + +// Ethernet address filter type +#define PKT_TYPE_NONE 0x00 // turn off receiver +#define PKT_TYPE_ALL_MULTICAST 0x80 +#define PKT_TYPE_PROMISCUOUS 0x40 +#define PKT_TYPE_DIRECTED 0x20 // obselete, directed address is always accepted +#define PKT_TYPE_BROADCAST 0x10 +#define PKT_TYPE_MULTICAST 0x08 +#define PKT_TYPE_ERROR_WPA 0x04 +#define PKT_TYPE_ERROR_CRC 0x02 +#define PKT_TYPE_BSSID 0x01 + +#define Default_BI 0x200 + + +// MiscFIFO Offset +#define MISCFIFO_KEYETRY0 32 +#define MISCFIFO_KEYENTRYSIZE 22 +#define MISCFIFO_SYNINFO_IDX 10 +#define MISCFIFO_SYNDATA_IDX 11 +#define MISCFIFO_SYNDATASIZE 21 + +// enabled mask value of irq +#define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \ + IMR_RXDMA1 | \ + IMR_RXNOBUF | \ + IMR_MIBNEARFULL | \ + IMR_SOFTINT | \ + IMR_FETALERR | \ + IMR_WATCHDOG | \ + IMR_SOFTTIMER | \ + IMR_GPIO | \ + IMR_TBTT | \ + IMR_RXDMA0 | \ + IMR_BNTX | \ + IMR_AC0DMA | \ + IMR_TXDMA0) + +// max time out delay time +#define W_MAX_TIMEOUT 0xFFF0U // + +// wait time within loop +#define CB_DELAY_LOOP_WAIT 10 // 10ms + +// +// revision id +// +#define REV_ID_VT3253_A0 0x00 +#define REV_ID_VT3253_A1 0x01 +#define REV_ID_VT3253_B0 0x08 +#define REV_ID_VT3253_B1 0x09 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +#define MACvRegBitsOn(dwIoBase, byRegOfs, byBits) \ +{ \ + BYTE byData; \ + VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits)); \ +} + +#define MACvWordRegBitsOn(dwIoBase, byRegOfs, wBits) \ +{ \ + WORD wData; \ + VNSvInPortW(dwIoBase + byRegOfs, &wData); \ + VNSvOutPortW(dwIoBase + byRegOfs, wData | (wBits)); \ +} + +#define MACvDWordRegBitsOn(dwIoBase, byRegOfs, dwBits) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + byRegOfs, &dwData); \ + VNSvOutPortD(dwIoBase + byRegOfs, dwData | (dwBits)); \ +} + +#define MACvRegBitsOnEx(dwIoBase, byRegOfs, byMask, byBits) \ +{ \ + BYTE byData; \ + VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + byData &= byMask; \ + VNSvOutPortB(dwIoBase + byRegOfs, byData | (byBits)); \ +} + +#define MACvRegBitsOff(dwIoBase, byRegOfs, byBits) \ +{ \ + BYTE byData; \ + VNSvInPortB(dwIoBase + byRegOfs, &byData); \ + VNSvOutPortB(dwIoBase + byRegOfs, byData & ~(byBits)); \ +} + +#define MACvWordRegBitsOff(dwIoBase, byRegOfs, wBits) \ +{ \ + WORD wData; \ + VNSvInPortW(dwIoBase + byRegOfs, &wData); \ + VNSvOutPortW(dwIoBase + byRegOfs, wData & ~(wBits)); \ +} + +#define MACvDWordRegBitsOff(dwIoBase, byRegOfs, dwBits) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + byRegOfs, &dwData); \ + VNSvOutPortD(dwIoBase + byRegOfs, dwData & ~(dwBits)); \ +} + +#define MACvGetCurrRx0DescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR0, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvGetCurrRx1DescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_RXDMAPTR1, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvGetCurrTx0DescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_TXDMAPTR0, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvGetCurrAC0DescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_AC0DMAPTR, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvGetCurrSyncDescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_SYNCDMAPTR, \ + (PDWORD)pdwCurrDescAddr); \ +} + +#define MACvGetCurrATIMDescAddr(dwIoBase, pdwCurrDescAddr) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR, \ + (PDWORD)pdwCurrDescAddr); \ +} \ + +// set the chip with current BCN tx descriptor address +#define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, \ + dwCurrDescAddr); \ +} + +// set the chip with current BCN length +#define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength) \ +{ \ + VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2, \ + wCurrBCNLength); \ +} + +#define MACvReadBSSIDAddress(dwIoBase, pbyEtherAddr) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0, \ + (PBYTE)pbyEtherAddr); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 1, \ + pbyEtherAddr + 1); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 2, \ + pbyEtherAddr + 2); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 3, \ + pbyEtherAddr + 3); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 4, \ + pbyEtherAddr + 4); \ + VNSvInPortB(dwIoBase + MAC_REG_BSSID0 + 5, \ + pbyEtherAddr + 5); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} + +#define MACvWriteBSSIDAddress(dwIoBase, pbyEtherAddr) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0, \ + *(pbyEtherAddr)); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 1, \ + *(pbyEtherAddr + 1)); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 2, \ + *(pbyEtherAddr + 2)); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 3, \ + *(pbyEtherAddr + 3)); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 4, \ + *(pbyEtherAddr + 4)); \ + VNSvOutPortB(dwIoBase + MAC_REG_BSSID0 + 5, \ + *(pbyEtherAddr + 5)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} + +#define MACvReadEtherAddress(dwIoBase, pbyEtherAddr) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0, \ + (PBYTE)pbyEtherAddr); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 1, \ + pbyEtherAddr + 1); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 2, \ + pbyEtherAddr + 2); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 3, \ + pbyEtherAddr + 3); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 4, \ + pbyEtherAddr + 4); \ + VNSvInPortB(dwIoBase + MAC_REG_PAR0 + 5, \ + pbyEtherAddr + 5); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} + + +#define MACvWriteEtherAddress(dwIoBase, pbyEtherAddr) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0, \ + *pbyEtherAddr); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 1, \ + *(pbyEtherAddr + 1)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 2, \ + *(pbyEtherAddr + 2)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 3, \ + *(pbyEtherAddr + 3)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 4, \ + *(pbyEtherAddr + 4)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAR0 + 5, \ + *(pbyEtherAddr + 5)); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} + + +#define MACvClearISR(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_ISR, IMR_MASK_VALUE); \ +} + +#define MACvStart(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_HOSTCR, \ + (HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON)); \ +} + +#define MACvRx0PerPktMode(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKT); \ +} + +#define MACvRx0BufferFillMode(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, RX_PERPKTCLR); \ +} + +#define MACvRx1PerPktMode(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKT); \ +} + +#define MACvRx1BufferFillMode(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, RX_PERPKTCLR); \ +} + +#define MACvRxOn(dwIoBase) \ +{ \ + MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_RXON); \ +} + +#define MACvReceive0(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL0, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); \ + } \ +} + +#define MACvReceive1(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_RXDMACTL1, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_RXDMACTL1, DMACTL_RUN); \ + } \ +} + +#define MACvTxOn(dwIoBase) \ +{ \ + MACvRegBitsOn(dwIoBase, MAC_REG_HOSTCR, HOSTCR_TXON); \ +} + +#define MACvTransmit0(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_TXDMACTL0, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_TXDMACTL0, DMACTL_RUN); \ + } \ +} + +#define MACvTransmitAC0(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_AC0DMACTL, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); \ + } \ +} + +#define MACvTransmitSYNC(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_SYNCDMACTL, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_SYNCDMACTL, DMACTL_RUN); \ + } \ +} + +#define MACvTransmitATIM(dwIoBase) \ +{ \ + DWORD dwData; \ + VNSvInPortD(dwIoBase + MAC_REG_ATIMDMACTL, &dwData); \ + if (dwData & DMACTL_RUN) { \ + VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_WAKE);\ + } \ + else { \ + VNSvOutPortD(dwIoBase + MAC_REG_ATIMDMACTL, DMACTL_RUN); \ + } \ +} + +#define MACvTransmitBCN(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_BCNDMACTL, BEACON_READY); \ +} + +#define MACvClearStckDS(dwIoBase) \ +{ \ + BYTE byOrgValue; \ + VNSvInPortB(dwIoBase + MAC_REG_STICKHW, &byOrgValue); \ + byOrgValue = byOrgValue & 0xFC; \ + VNSvOutPortB(dwIoBase + MAC_REG_STICKHW, byOrgValue); \ +} + +#define MACvReadISR(dwIoBase, pdwValue) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_ISR, pdwValue); \ +} + +#define MACvWriteISR(dwIoBase, dwValue) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_ISR, dwValue); \ +} + +#define MACvIntEnable(dwIoBase, dwMask) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_IMR, dwMask); \ +} + +#define MACvIntDisable(dwIoBase) \ +{ \ + VNSvOutPortD(dwIoBase + MAC_REG_IMR, 0); \ +} + +#define MACvSelectPage0(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} +#define MACvSelectPage1(dwIoBase) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ +} + +#define MACvReadMIBCounter(dwIoBase, pdwCounter) \ +{ \ + VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR , pdwCounter); \ +} + +#define MACvPwrEvntDisable(dwIoBase) \ +{ \ + VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000); \ +} + +#define MACvEnableProtectMD(dwIoBase) \ +{ \ + DWORD dwOrgValue; \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + dwOrgValue = dwOrgValue | EnCFG_ProtectMd; \ + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ +} + +#define MACvDisableProtectMD(dwIoBase) \ +{ \ + DWORD dwOrgValue; \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd; \ + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ +} + +#define MACvEnableBarkerPreambleMd(dwIoBase) \ +{ \ + DWORD dwOrgValue; \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + dwOrgValue = dwOrgValue | EnCFG_BarkerPream; \ + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ +} + +#define MACvDisableBarkerPreambleMd(dwIoBase) \ +{ \ + DWORD dwOrgValue; \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream; \ + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ +} + +#define MACvSetBBType(dwIoBase, byTyp) \ +{ \ + DWORD dwOrgValue; \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK; \ + dwOrgValue = dwOrgValue | (DWORD) byTyp; \ + VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ +} + +#define MACvReadATIMW(dwIoBase, pwCounter) \ +{ \ + VNSvInPortW(dwIoBase + MAC_REG_AIDATIM , pwCounter); \ +} + +#define MACvWriteATIMW(dwIoBase, wCounter) \ +{ \ + VNSvOutPortW(dwIoBase + MAC_REG_AIDATIM , wCounter); \ +} + +#define MACvWriteCRC16_128(dwIoBase, byRegOfs, wCRC) \ +{ \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1); \ + VNSvOutPortW(dwIoBase + byRegOfs, wCRC); \ + VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 0); \ +} + +#define MACvGPIOIn(dwIoBase, pbyValue) \ +{ \ + VNSvInPortB(dwIoBase + MAC_REG_GPIOCTL1, pbyValue); \ +} + +#define MACvSetRFLE_LatchBase(dwIoBase) \ +{ \ + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT); \ +} + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +extern WORD TxRate_iwconfig;//2008-5-8 <add> by chester +VOID MACvReadAllRegs(DWORD_PTR dwIoBase, PBYTE pbyMacRegs); + +BOOL MACbIsRegBitsOn(DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits); +BOOL MACbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byRegOfs, BYTE byTestBits); + +BOOL MACbIsIntDisable(DWORD_PTR dwIoBase); + +BYTE MACbyReadMultiAddr(DWORD_PTR dwIoBase, UINT uByteIdx); +VOID MACvWriteMultiAddr(DWORD_PTR dwIoBase, UINT uByteIdx, BYTE byData); +VOID MACvSetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); +VOID MACvResetMultiAddrByHash(DWORD_PTR dwIoBase, BYTE byHashIdx); + +VOID MACvSetRxThreshold(DWORD_PTR dwIoBase, BYTE byThreshold); +VOID MACvGetRxThreshold(DWORD_PTR dwIoBase, PBYTE pbyThreshold); + +VOID MACvSetTxThreshold(DWORD_PTR dwIoBase, BYTE byThreshold); +VOID MACvGetTxThreshold(DWORD_PTR dwIoBase, PBYTE pbyThreshold); + +VOID MACvSetDmaLength(DWORD_PTR dwIoBase, BYTE byDmaLength); +VOID MACvGetDmaLength(DWORD_PTR dwIoBase, PBYTE pbyDmaLength); + +VOID MACvSetShortRetryLimit(DWORD_PTR dwIoBase, BYTE byRetryLimit); +VOID MACvGetShortRetryLimit(DWORD_PTR dwIoBase, PBYTE pbyRetryLimit); + +VOID MACvSetLongRetryLimit(DWORD_PTR dwIoBase, BYTE byRetryLimit); +VOID MACvGetLongRetryLimit(DWORD_PTR dwIoBase, PBYTE pbyRetryLimit); + +VOID MACvSetLoopbackMode(DWORD_PTR dwIoBase, BYTE byLoopbackMode); +BOOL MACbIsInLoopbackMode(DWORD_PTR dwIoBase); + +VOID MACvSetPacketFilter(DWORD_PTR dwIoBase, WORD wFilterType); + +VOID MACvSaveContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); +VOID MACvRestoreContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); +BOOL MACbCompareContext(DWORD_PTR dwIoBase, PBYTE pbyCxtBuf); + +BOOL MACbSoftwareReset(DWORD_PTR dwIoBase); +BOOL MACbSafeSoftwareReset(DWORD_PTR dwIoBase); +BOOL MACbSafeRxOff(DWORD_PTR dwIoBase); +BOOL MACbSafeTxOff(DWORD_PTR dwIoBase); +BOOL MACbSafeStop(DWORD_PTR dwIoBase); +BOOL MACbShutdown(DWORD_PTR dwIoBase); +VOID MACvInitialize(DWORD_PTR dwIoBase); +VOID MACvSetCurrRx0DescAddr(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrRx1DescAddr(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrTXDescAddr(int iTxType, DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrTx0DescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrAC0DescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrSyncDescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +VOID MACvSetCurrATIMDescAddrEx(DWORD_PTR dwIoBase, DWORD dwCurrDescAddr); +void MACvTimer0MicroSDelay(DWORD_PTR dwIoBase, UINT uDelay); +void MACvOneShotTimer0MicroSec(DWORD_PTR dwIoBase, UINT uDelayTime); +void MACvOneShotTimer1MicroSec(DWORD_PTR dwIoBase, UINT uDelayTime); + +void MACvSetMISCFifo(DWORD_PTR dwIoBase, WORD wOffset, DWORD dwData); + +BOOL MACbTxDMAOff (DWORD_PTR dwIoBase, UINT idx); + +void MACvClearBusSusInd(DWORD_PTR dwIoBase); +void MACvEnableBusSusEn(DWORD_PTR dwIoBase); + +BOOL MACbFlushSYNCFifo(DWORD_PTR dwIoBase); +BOOL MACbPSWakeup(DWORD_PTR dwIoBase); + +void MACvSetKeyEntry(DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, UINT uKeyIdx, PBYTE pbyAddr, PDWORD pdwKey, BYTE byLocalID); +void MACvDisableKeyEntry(DWORD_PTR dwIoBase, UINT uEntryIdx); +void MACvSetDefaultKeyEntry(DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID); +//void MACvEnableDefaultKey(DWORD_PTR dwIoBase, BYTE byLocalID); +void MACvDisableDefaultKey(DWORD_PTR dwIoBase); +void MACvSetDefaultTKIPKeyEntry(DWORD_PTR dwIoBase, UINT uKeyLen, UINT uKeyIdx, PDWORD pdwKey, BYTE byLocalID); +void MACvSetDefaultKeyCtl(DWORD_PTR dwIoBase, WORD wKeyCtl, UINT uEntryIdx, BYTE byLocalID); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + +#endif // __MAC_H__ + diff --git a/drivers/staging/vt6655/mib.c b/drivers/staging/vt6655/mib.c new file mode 100644 index 00000000000..3f06de141a8 --- /dev/null +++ b/drivers/staging/vt6655/mib.c @@ -0,0 +1,616 @@ +/* + * 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: mib.c + * + * Purpose: Implement MIB Data Structure + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * STAvClearAllCounter - Clear All MIB Counter + * STAvUpdateIstStatCounter - Update ISR statistic counter + * STAvUpdateRDStatCounter - Update Rx statistic counter + * STAvUpdateRDStatCounterEx - Update Rx statistic counter and copy rcv data + * STAvUpdateTDStatCounter - Update Tx statistic counter + * STAvUpdateTDStatCounterEx - Update Tx statistic counter and copy tx data + * STAvUpdate802_11Counter - Update 802.11 mib counter + * + * Revision History: + * + */ + + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__MIB_H__) +#include "mib.h" +#endif +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + +/* + * Description: Clear All Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * Out: + * none + * + * Return Value: none + * + */ +void STAvClearAllCounter (PSStatCounter pStatistic) +{ + // set memory to zero + ZERO_MEMORY(pStatistic, sizeof(SStatCounter)); +} + + +/* + * Description: Update Isr Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * wisr - Interrupt status + * Out: + * none + * + * Return Value: none + * + */ +void STAvUpdateIsrStatCounter (PSStatCounter pStatistic, DWORD dwIsr) +{ + /**********************/ + /* ABNORMAL interrupt */ + /**********************/ + // not any IMR bit invoke irq + + if (dwIsr == 0) { + pStatistic->ISRStat.dwIsrUnknown++; + return; + } + +//Added by Kyle + if (BITbIsBitOn(dwIsr, ISR_TXDMA0)) // ISR, bit0 + pStatistic->ISRStat.dwIsrTx0OK++; // TXDMA0 successful + + if (BITbIsBitOn(dwIsr, ISR_AC0DMA)) // ISR, bit1 + pStatistic->ISRStat.dwIsrAC0TxOK++; // AC0DMA successful + + if (BITbIsBitOn(dwIsr, ISR_BNTX)) // ISR, bit2 + pStatistic->ISRStat.dwIsrBeaconTxOK++; // BeaconTx successful + + if (BITbIsBitOn(dwIsr, ISR_RXDMA0)) // ISR, bit3 + pStatistic->ISRStat.dwIsrRx0OK++; // Rx0 successful + + if (BITbIsBitOn(dwIsr, ISR_TBTT)) // ISR, bit4 + pStatistic->ISRStat.dwIsrTBTTInt++; // TBTT successful + + if (BITbIsBitOn(dwIsr, ISR_SOFTTIMER)) // ISR, bit6 + pStatistic->ISRStat.dwIsrSTIMERInt++; + + if (BITbIsBitOn(dwIsr, ISR_WATCHDOG)) // ISR, bit7 + pStatistic->ISRStat.dwIsrWatchDog++; + + if (BITbIsBitOn(dwIsr, ISR_FETALERR)) // ISR, bit8 + pStatistic->ISRStat.dwIsrUnrecoverableError++; + + if (BITbIsBitOn(dwIsr, ISR_SOFTINT)) // ISR, bit9 + pStatistic->ISRStat.dwIsrSoftInterrupt++; // software interrupt + + if (BITbIsBitOn(dwIsr, ISR_MIBNEARFULL)) // ISR, bit10 + pStatistic->ISRStat.dwIsrMIBNearfull++; + + if (BITbIsBitOn(dwIsr, ISR_RXNOBUF)) // ISR, bit11 + pStatistic->ISRStat.dwIsrRxNoBuf++; // Rx No Buff + + if (BITbIsBitOn(dwIsr, ISR_RXDMA1)) // ISR, bit12 + pStatistic->ISRStat.dwIsrRx1OK++; // Rx1 successful + +// if (BITbIsBitOn(dwIsr, ISR_ATIMTX)) // ISR, bit13 +// pStatistic->ISRStat.dwIsrATIMTxOK++; // ATIMTX successful + +// if (BITbIsBitOn(dwIsr, ISR_SYNCTX)) // ISR, bit14 +// pStatistic->ISRStat.dwIsrSYNCTxOK++; // SYNCTX successful + +// if (BITbIsBitOn(dwIsr, ISR_CFPEND)) // ISR, bit18 +// pStatistic->ISRStat.dwIsrCFPEnd++; + +// if (BITbIsBitOn(dwIsr, ISR_ATIMEND)) // ISR, bit19 +// pStatistic->ISRStat.dwIsrATIMEnd++; + +// if (BITbIsBitOn(dwIsr, ISR_SYNCFLUSHOK)) // ISR, bit20 +// pStatistic->ISRStat.dwIsrSYNCFlushOK++; + + if (BITbIsBitOn(dwIsr, ISR_SOFTTIMER1)) // ISR, bit21 + pStatistic->ISRStat.dwIsrSTIMER1Int++; + +} + + +/* + * Description: Update Rx Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * byRSR - Rx Status + * byNewRSR - Rx Status + * pbyBuffer - Rx Buffer + * cbFrameLength - Rx Length + * Out: + * none + * + * Return Value: none + * + */ +void STAvUpdateRDStatCounter (PSStatCounter pStatistic, + BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, + PBYTE pbyBuffer, UINT cbFrameLength) +{ + //need change + PS802_11Header pHeader = (PS802_11Header)pbyBuffer; + + if (BITbIsBitOn(byRSR, RSR_ADDROK)) + pStatistic->dwRsrADDROk++; + if (BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->dwRsrCRCOk++; + + pStatistic->ullRsrOK++; + + if (cbFrameLength >= U_ETHER_ADDR_LEN) { + // update counters in case that successful transmit + if (BITbIsBitOn(byRSR, RSR_ADDRBROAD)) { + pStatistic->ullRxBroadcastFrames++; + pStatistic->ullRxBroadcastBytes += (ULONGLONG)cbFrameLength; + } + else if (BITbIsBitOn(byRSR, RSR_ADDRMULTI)) { + pStatistic->ullRxMulticastFrames++; + pStatistic->ullRxMulticastBytes += (ULONGLONG)cbFrameLength; + } + else { + pStatistic->ullRxDirectedFrames++; + pStatistic->ullRxDirectedBytes += (ULONGLONG)cbFrameLength; + } + } + } + + if(byRxRate==22) { + pStatistic->CustomStat.ullRsr11M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr11MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"11M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr11M, (INT)pStatistic->CustomStat.ullRsr11MCRCOk, byRSR); + } + else if(byRxRate==11) { + pStatistic->CustomStat.ullRsr5M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr5MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 5M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr5M, (INT)pStatistic->CustomStat.ullRsr5MCRCOk, byRSR); + } + else if(byRxRate==4) { + pStatistic->CustomStat.ullRsr2M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr2MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 2M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr2M, (INT)pStatistic->CustomStat.ullRsr2MCRCOk, byRSR); + } + else if(byRxRate==2){ + pStatistic->CustomStat.ullRsr1M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr1MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 1M: ALL[%d], OK[%d]:[%02x]\n", (INT)pStatistic->CustomStat.ullRsr1M, (INT)pStatistic->CustomStat.ullRsr1MCRCOk, byRSR); + } + else if(byRxRate==12){ + pStatistic->CustomStat.ullRsr6M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr6MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 6M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr6M, (INT)pStatistic->CustomStat.ullRsr6MCRCOk); + } + else if(byRxRate==18){ + pStatistic->CustomStat.ullRsr9M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr9MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" 9M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr9M, (INT)pStatistic->CustomStat.ullRsr9MCRCOk); + } + else if(byRxRate==24){ + pStatistic->CustomStat.ullRsr12M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr12MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"12M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr12M, (INT)pStatistic->CustomStat.ullRsr12MCRCOk); + } + else if(byRxRate==36){ + pStatistic->CustomStat.ullRsr18M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr18MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"18M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr18M, (INT)pStatistic->CustomStat.ullRsr18MCRCOk); + } + else if(byRxRate==48){ + pStatistic->CustomStat.ullRsr24M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr24MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"24M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr24M, (INT)pStatistic->CustomStat.ullRsr24MCRCOk); + } + else if(byRxRate==72){ + pStatistic->CustomStat.ullRsr36M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr36MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"36M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr36M, (INT)pStatistic->CustomStat.ullRsr36MCRCOk); + } + else if(byRxRate==96){ + pStatistic->CustomStat.ullRsr48M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr48MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"48M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr48M, (INT)pStatistic->CustomStat.ullRsr48MCRCOk); + } + else if(byRxRate==108){ + pStatistic->CustomStat.ullRsr54M++; + if(BITbIsBitOn(byRSR, RSR_CRCOK)) { + pStatistic->CustomStat.ullRsr54MCRCOk++; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"54M: ALL[%d], OK[%d]\n", (INT)pStatistic->CustomStat.ullRsr54M, (INT)pStatistic->CustomStat.ullRsr54MCRCOk); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown: Total[%d], CRCOK[%d]\n", (INT)pStatistic->dwRsrRxPacket+1, (INT)pStatistic->dwRsrCRCOk); + } + + if (BITbIsBitOn(byRSR, RSR_BSSIDOK)) + pStatistic->dwRsrBSSIDOk++; + + if (BITbIsBitOn(byRSR, RSR_BCNSSIDOK)) + pStatistic->dwRsrBCNSSIDOk++; + if (BITbIsBitOn(byRSR, RSR_IVLDLEN)) //invalid len (> 2312 byte) + pStatistic->dwRsrLENErr++; + if (BITbIsBitOn(byRSR, RSR_IVLDTYP)) //invalid packet type + pStatistic->dwRsrTYPErr++; + if (BITbIsBitOn(byRSR, (RSR_IVLDTYP | RSR_IVLDLEN))) + pStatistic->dwRsrErr++; + + if (BITbIsBitOn(byNewRSR, NEWRSR_DECRYPTOK)) + pStatistic->dwNewRsrDECRYPTOK++; + if (BITbIsBitOn(byNewRSR, NEWRSR_CFPIND)) + pStatistic->dwNewRsrCFP++; + if (BITbIsBitOn(byNewRSR, NEWRSR_HWUTSF)) + pStatistic->dwNewRsrUTSF++; + if (BITbIsBitOn(byNewRSR, NEWRSR_BCNHITAID)) + pStatistic->dwNewRsrHITAID++; + if (BITbIsBitOn(byNewRSR, NEWRSR_BCNHITAID0)) + pStatistic->dwNewRsrHITAID0++; + + // increase rx packet count + pStatistic->dwRsrRxPacket++; + pStatistic->dwRsrRxOctet += cbFrameLength; + + + if (IS_TYPE_DATA(pbyBuffer)) { + pStatistic->dwRsrRxData++; + } else if (IS_TYPE_MGMT(pbyBuffer)){ + pStatistic->dwRsrRxManage++; + } else if (IS_TYPE_CONTROL(pbyBuffer)){ + pStatistic->dwRsrRxControl++; + } + + if (BITbIsBitOn(byRSR, RSR_ADDRBROAD)) + pStatistic->dwRsrBroadcast++; + else if (BITbIsBitOn(byRSR, RSR_ADDRMULTI)) + pStatistic->dwRsrMulticast++; + else + pStatistic->dwRsrDirected++; + + if (WLAN_GET_FC_MOREFRAG(pHeader->wFrameCtl)) + pStatistic->dwRsrRxFragment++; + + if (cbFrameLength < MIN_PACKET_LEN + 4) { + pStatistic->dwRsrRunt++; + } + else if (cbFrameLength == MIN_PACKET_LEN + 4) { + pStatistic->dwRsrRxFrmLen64++; + } + else if ((65 <= cbFrameLength) && (cbFrameLength <= 127)) { + pStatistic->dwRsrRxFrmLen65_127++; + } + else if ((128 <= cbFrameLength) && (cbFrameLength <= 255)) { + pStatistic->dwRsrRxFrmLen128_255++; + } + else if ((256 <= cbFrameLength) && (cbFrameLength <= 511)) { + pStatistic->dwRsrRxFrmLen256_511++; + } + else if ((512 <= cbFrameLength) && (cbFrameLength <= 1023)) { + pStatistic->dwRsrRxFrmLen512_1023++; + } + else if ((1024 <= cbFrameLength) && (cbFrameLength <= MAX_PACKET_LEN + 4)) { + pStatistic->dwRsrRxFrmLen1024_1518++; + } else if (cbFrameLength > MAX_PACKET_LEN + 4) { + pStatistic->dwRsrLong++; + } + +} + + + +/* + * Description: Update Rx Statistic Counter and copy Rx buffer + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * byRSR - Rx Status + * byNewRSR - Rx Status + * pbyBuffer - Rx Buffer + * cbFrameLength - Rx Length + * Out: + * none + * + * Return Value: none + * + */ + +void +STAvUpdateRDStatCounterEx ( + PSStatCounter pStatistic, + BYTE byRSR, + BYTE byNewRSR, + BYTE byRxRate, + PBYTE pbyBuffer, + UINT cbFrameLength + ) +{ + STAvUpdateRDStatCounter( + pStatistic, + byRSR, + byNewRSR, + byRxRate, + pbyBuffer, + cbFrameLength + ); + + // rx length + pStatistic->dwCntRxFrmLength = cbFrameLength; + // rx pattern, we just see 10 bytes for sample + MEMvCopy(pStatistic->abyCntRxPattern, (PBYTE)pbyBuffer, 10); +} + + +/* + * Description: Update Tx Statistic Counter + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * byTSR0 - Tx Status + * byTSR1 - Tx Status + * pbyBuffer - Tx Buffer + * cbFrameLength - Tx Length + * uIdx - Index of Tx DMA + * Out: + * none + * + * Return Value: none + * + */ +void +STAvUpdateTDStatCounter ( + PSStatCounter pStatistic, + BYTE byTSR0, + BYTE byTSR1, + PBYTE pbyBuffer, + UINT cbFrameLength, + UINT uIdx + ) +{ + PWLAN_80211HDR_A4 pHeader; + PBYTE pbyDestAddr; + BYTE byTSR0_NCR = byTSR0 & TSR0_NCR; + + + + pHeader = (PWLAN_80211HDR_A4) pbyBuffer; + if (WLAN_GET_FC_TODS(pHeader->wFrameCtl) == 0) { + pbyDestAddr = &(pHeader->abyAddr1[0]); + } + else { + pbyDestAddr = &(pHeader->abyAddr3[0]); + } + // increase tx packet count + pStatistic->dwTsrTxPacket[uIdx]++; + pStatistic->dwTsrTxOctet[uIdx] += cbFrameLength; + + if (byTSR0_NCR != 0) { + pStatistic->dwTsrRetry[uIdx]++; + pStatistic->dwTsrTotalRetry[uIdx] += byTSR0_NCR; + + if (byTSR0_NCR == 1) + pStatistic->dwTsrOnceRetry[uIdx]++; + else + pStatistic->dwTsrMoreThanOnceRetry[uIdx]++; + } + + if ((byTSR1&(TSR1_TERR|TSR1_RETRYTMO|TSR1_TMO|ACK_DATA)) == 0) { + pStatistic->ullTsrOK[uIdx]++; + pStatistic->CustomStat.ullTsrAllOK = + (pStatistic->ullTsrOK[TYPE_AC0DMA] + pStatistic->ullTsrOK[TYPE_TXDMA0]); + // update counters in case that successful transmit + if (IS_BROADCAST_ADDRESS(pbyDestAddr)) { + pStatistic->ullTxBroadcastFrames[uIdx]++; + pStatistic->ullTxBroadcastBytes[uIdx] += (ULONGLONG)cbFrameLength; + } + else if (IS_MULTICAST_ADDRESS(pbyDestAddr)) { + pStatistic->ullTxMulticastFrames[uIdx]++; + pStatistic->ullTxMulticastBytes[uIdx] += (ULONGLONG)cbFrameLength; + } + else { + pStatistic->ullTxDirectedFrames[uIdx]++; + pStatistic->ullTxDirectedBytes[uIdx] += (ULONGLONG)cbFrameLength; + } + } + else { + if (BITbIsBitOn(byTSR1, TSR1_TERR)) + pStatistic->dwTsrErr[uIdx]++; + if (BITbIsBitOn(byTSR1, TSR1_RETRYTMO)) + pStatistic->dwTsrRetryTimeout[uIdx]++; + if (BITbIsBitOn(byTSR1, TSR1_TMO)) + pStatistic->dwTsrTransmitTimeout[uIdx]++; + if (BITbIsBitOn(byTSR1, ACK_DATA)) + pStatistic->dwTsrACKData[uIdx]++; + } + + if (IS_BROADCAST_ADDRESS(pbyDestAddr)) + pStatistic->dwTsrBroadcast[uIdx]++; + else if (IS_MULTICAST_ADDRESS(pbyDestAddr)) + pStatistic->dwTsrMulticast[uIdx]++; + else + pStatistic->dwTsrDirected[uIdx]++; + +} + + +/* + * Description: Update Tx Statistic Counter and copy Tx buffer + * + * Parameters: + * In: + * pStatistic - Pointer to Statistic Counter Data Structure + * pbyBuffer - Tx Buffer + * cbFrameLength - Tx Length + * Out: + * none + * + * Return Value: none + * + */ +void +STAvUpdateTDStatCounterEx ( + PSStatCounter pStatistic, + PBYTE pbyBuffer, + DWORD cbFrameLength + ) +{ + UINT uPktLength; + + uPktLength = (UINT)cbFrameLength; + + // tx length + pStatistic->dwCntTxBufLength = uPktLength; + // tx pattern, we just see 16 bytes for sample + MEMvCopy(pStatistic->abyCntTxPattern, pbyBuffer, 16); +} + + +/* + * Description: Update 802.11 mib counter + * + * Parameters: + * In: + * p802_11Counter - Pointer to 802.11 mib counter + * pStatistic - Pointer to Statistic Counter Data Structure + * dwCounter - hardware counter for 802.11 mib + * Out: + * none + * + * Return Value: none + * + */ +void +STAvUpdate802_11Counter( + PSDot11Counters p802_11Counter, + PSStatCounter pStatistic, + DWORD dwCounter + ) +{ + //p802_11Counter->TransmittedFragmentCount + p802_11Counter->MulticastTransmittedFrameCount = (ULONGLONG) (pStatistic->dwTsrBroadcast[TYPE_AC0DMA] + + pStatistic->dwTsrBroadcast[TYPE_TXDMA0] + + pStatistic->dwTsrMulticast[TYPE_AC0DMA] + + pStatistic->dwTsrMulticast[TYPE_TXDMA0]); + p802_11Counter->FailedCount = (ULONGLONG) (pStatistic->dwTsrErr[TYPE_AC0DMA] + pStatistic->dwTsrErr[TYPE_TXDMA0]); + p802_11Counter->RetryCount = (ULONGLONG) (pStatistic->dwTsrRetry[TYPE_AC0DMA] + pStatistic->dwTsrRetry[TYPE_TXDMA0]); + p802_11Counter->MultipleRetryCount = (ULONGLONG) (pStatistic->dwTsrMoreThanOnceRetry[TYPE_AC0DMA] + + pStatistic->dwTsrMoreThanOnceRetry[TYPE_TXDMA0]); + //p802_11Counter->FrameDuplicateCount + p802_11Counter->RTSSuccessCount += (ULONGLONG) (dwCounter & 0x000000ff); + p802_11Counter->RTSFailureCount += (ULONGLONG) ((dwCounter & 0x0000ff00) >> 8); + p802_11Counter->ACKFailureCount += (ULONGLONG) ((dwCounter & 0x00ff0000) >> 16); + p802_11Counter->FCSErrorCount += (ULONGLONG) ((dwCounter & 0xff000000) >> 24); + //p802_11Counter->ReceivedFragmentCount + p802_11Counter->MulticastReceivedFrameCount = (ULONGLONG) (pStatistic->dwRsrBroadcast + + pStatistic->dwRsrMulticast); +} + +/* + * Description: Clear 802.11 mib counter + * + * Parameters: + * In: + * p802_11Counter - Pointer to 802.11 mib counter + * Out: + * none + * + * Return Value: none + * + */ +void +STAvClear802_11Counter(PSDot11Counters p802_11Counter) +{ + // set memory to zero + ZERO_MEMORY(p802_11Counter, sizeof(SDot11Counters)); +} diff --git a/drivers/staging/vt6655/mib.h b/drivers/staging/vt6655/mib.h new file mode 100644 index 00000000000..b4e1c4a19a7 --- /dev/null +++ b/drivers/staging/vt6655/mib.h @@ -0,0 +1,399 @@ +/* + * 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: mib.h + * + * Purpose: Implement MIB Data Structure + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __MIB_H__ +#define __MIB_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif + + + +//#define ULONGLONG ULONG + +/*--------------------- Export Definitions -------------------------*/ +// +// 802.11 counter +// + +typedef struct tagSDot11Counters { + ULONG Length; // Length of structure + ULONGLONG TransmittedFragmentCount; + ULONGLONG MulticastTransmittedFrameCount; + ULONGLONG FailedCount; + ULONGLONG RetryCount; + ULONGLONG MultipleRetryCount; + ULONGLONG RTSSuccessCount; + ULONGLONG RTSFailureCount; + ULONGLONG ACKFailureCount; + ULONGLONG FrameDuplicateCount; + ULONGLONG ReceivedFragmentCount; + ULONGLONG MulticastReceivedFrameCount; + ULONGLONG FCSErrorCount; + ULONGLONG TKIPLocalMICFailures; + ULONGLONG TKIPRemoteMICFailures; + ULONGLONG TKIPICVErrors; + ULONGLONG TKIPCounterMeasuresInvoked; + ULONGLONG TKIPReplays; + ULONGLONG CCMPFormatErrors; + ULONGLONG CCMPReplays; + ULONGLONG CCMPDecryptErrors; + ULONGLONG FourWayHandshakeFailures; +// ULONGLONG WEPUndecryptableCount; +// ULONGLONG WEPICVErrorCount; +// ULONGLONG DecryptSuccessCount; +// ULONGLONG DecryptFailureCount; +} SDot11Counters, DEF* PSDot11Counters; + + +// +// MIB2 counter +// +typedef struct tagSMib2Counter { + LONG ifIndex; + TCHAR ifDescr[256]; // max size 255 plus zero ending + // e.g. "interface 1" + LONG ifType; + LONG ifMtu; + DWORD ifSpeed; + BYTE ifPhysAddress[U_ETHER_ADDR_LEN]; + LONG ifAdminStatus; + LONG ifOperStatus; + DWORD ifLastChange; + DWORD ifInOctets; + DWORD ifInUcastPkts; + DWORD ifInNUcastPkts; + DWORD ifInDiscards; + DWORD ifInErrors; + DWORD ifInUnknownProtos; + DWORD ifOutOctets; + DWORD ifOutUcastPkts; + DWORD ifOutNUcastPkts; + DWORD ifOutDiscards; + DWORD ifOutErrors; + DWORD ifOutQLen; + DWORD ifSpecific; +} SMib2Counter, DEF* PSMib2Counter; + +// Value in the ifType entry +//#define ETHERNETCSMACD 6 // +#define WIRELESSLANIEEE80211b 6 // + +// Value in the ifAdminStatus/ifOperStatus entry +#define UP 1 // +#define DOWN 2 // +#define TESTING 3 // + + +// +// RMON counter +// +typedef struct tagSRmonCounter { + LONG etherStatsIndex; + DWORD etherStatsDataSource; + DWORD etherStatsDropEvents; + DWORD etherStatsOctets; + DWORD etherStatsPkts; + DWORD etherStatsBroadcastPkts; + DWORD etherStatsMulticastPkts; + DWORD etherStatsCRCAlignErrors; + DWORD etherStatsUndersizePkts; + DWORD etherStatsOversizePkts; + DWORD etherStatsFragments; + DWORD etherStatsJabbers; + DWORD etherStatsCollisions; + DWORD etherStatsPkt64Octets; + DWORD etherStatsPkt65to127Octets; + DWORD etherStatsPkt128to255Octets; + DWORD etherStatsPkt256to511Octets; + DWORD etherStatsPkt512to1023Octets; + DWORD etherStatsPkt1024to1518Octets; + DWORD etherStatsOwners; + DWORD etherStatsStatus; +} SRmonCounter, DEF* PSRmonCounter; + +// +// Custom counter +// +typedef struct tagSCustomCounters { + ULONG Length; + + ULONGLONG ullTsrAllOK; + + ULONGLONG ullRsr11M; + ULONGLONG ullRsr5M; + ULONGLONG ullRsr2M; + ULONGLONG ullRsr1M; + + ULONGLONG ullRsr11MCRCOk; + ULONGLONG ullRsr5MCRCOk; + ULONGLONG ullRsr2MCRCOk; + ULONGLONG ullRsr1MCRCOk; + + ULONGLONG ullRsr54M; + ULONGLONG ullRsr48M; + ULONGLONG ullRsr36M; + ULONGLONG ullRsr24M; + ULONGLONG ullRsr18M; + ULONGLONG ullRsr12M; + ULONGLONG ullRsr9M; + ULONGLONG ullRsr6M; + + ULONGLONG ullRsr54MCRCOk; + ULONGLONG ullRsr48MCRCOk; + ULONGLONG ullRsr36MCRCOk; + ULONGLONG ullRsr24MCRCOk; + ULONGLONG ullRsr18MCRCOk; + ULONGLONG ullRsr12MCRCOk; + ULONGLONG ullRsr9MCRCOk; + ULONGLONG ullRsr6MCRCOk; + +} SCustomCounters, DEF* PSCustomCounters; + + +// +// Custom counter +// +typedef struct tagSISRCounters { + ULONG Length; + + DWORD dwIsrTx0OK; + DWORD dwIsrAC0TxOK; + DWORD dwIsrBeaconTxOK; + DWORD dwIsrRx0OK; + DWORD dwIsrTBTTInt; + DWORD dwIsrSTIMERInt; + DWORD dwIsrWatchDog; + DWORD dwIsrUnrecoverableError; + DWORD dwIsrSoftInterrupt; + DWORD dwIsrMIBNearfull; + DWORD dwIsrRxNoBuf; + + DWORD dwIsrUnknown; // unknown interrupt count + + DWORD dwIsrRx1OK; + DWORD dwIsrATIMTxOK; + DWORD dwIsrSYNCTxOK; + DWORD dwIsrCFPEnd; + DWORD dwIsrATIMEnd; + DWORD dwIsrSYNCFlushOK; + DWORD dwIsrSTIMER1Int; + ///////////////////////////////////// +} SISRCounters, DEF* PSISRCounters; + + +// Value in the etherStatsStatus entry +#define VALID 1 // +#define CREATE_REQUEST 2 // +#define UNDER_CREATION 3 // +#define INVALID 4 // + +//#define MAX_RATE 12 +// +// statistic counter +// +typedef struct tagSStatCounter { + // + // ISR status count + // + + + // RSR status count + // + DWORD dwRsrFrmAlgnErr; + DWORD dwRsrErr; + DWORD dwRsrCRCErr; + DWORD dwRsrCRCOk; + DWORD dwRsrBSSIDOk; + DWORD dwRsrADDROk; + DWORD dwRsrBCNSSIDOk; + DWORD dwRsrLENErr; + DWORD dwRsrTYPErr; + + DWORD dwNewRsrDECRYPTOK; + DWORD dwNewRsrCFP; + DWORD dwNewRsrUTSF; + DWORD dwNewRsrHITAID; + DWORD dwNewRsrHITAID0; + + DWORD dwRsrLong; + DWORD dwRsrRunt; + + DWORD dwRsrRxControl; + DWORD dwRsrRxData; + DWORD dwRsrRxManage; + + DWORD dwRsrRxPacket; + DWORD dwRsrRxOctet; + DWORD dwRsrBroadcast; + DWORD dwRsrMulticast; + DWORD dwRsrDirected; + // 64-bit OID + ULONGLONG ullRsrOK; + + // for some optional OIDs (64 bits) and DMI support + ULONGLONG ullRxBroadcastBytes; + ULONGLONG ullRxMulticastBytes; + ULONGLONG ullRxDirectedBytes; + ULONGLONG ullRxBroadcastFrames; + ULONGLONG ullRxMulticastFrames; + ULONGLONG ullRxDirectedFrames; + + DWORD dwRsrRxFragment; + DWORD dwRsrRxFrmLen64; + DWORD dwRsrRxFrmLen65_127; + DWORD dwRsrRxFrmLen128_255; + DWORD dwRsrRxFrmLen256_511; + DWORD dwRsrRxFrmLen512_1023; + DWORD dwRsrRxFrmLen1024_1518; + + // TSR status count + // + DWORD dwTsrTotalRetry[TYPE_MAXTD]; // total collision retry count + DWORD dwTsrOnceRetry[TYPE_MAXTD]; // this packet only occur one collision + DWORD dwTsrMoreThanOnceRetry[TYPE_MAXTD]; // this packet occur more than one collision + DWORD dwTsrRetry[TYPE_MAXTD]; // this packet has ever occur collision, + // that is (dwTsrOnceCollision0 + dwTsrMoreThanOnceCollision0) + DWORD dwTsrACKData[TYPE_MAXTD]; + DWORD dwTsrErr[TYPE_MAXTD]; + DWORD dwAllTsrOK[TYPE_MAXTD]; + DWORD dwTsrRetryTimeout[TYPE_MAXTD]; + DWORD dwTsrTransmitTimeout[TYPE_MAXTD]; + + DWORD dwTsrTxPacket[TYPE_MAXTD]; + DWORD dwTsrTxOctet[TYPE_MAXTD]; + DWORD dwTsrBroadcast[TYPE_MAXTD]; + DWORD dwTsrMulticast[TYPE_MAXTD]; + DWORD dwTsrDirected[TYPE_MAXTD]; + + // RD/TD count + DWORD dwCntRxFrmLength; + DWORD dwCntTxBufLength; + + BYTE abyCntRxPattern[16]; + BYTE abyCntTxPattern[16]; + + + + // Software check.... + DWORD dwCntRxDataErr; // rx buffer data software compare CRC err count + DWORD dwCntDecryptErr; // rx buffer data software compare CRC err count + DWORD dwCntRxICVErr; // rx buffer data software compare CRC err count + UINT idxRxErrorDesc[TYPE_MAXRD]; // index for rx data error RD + + // 64-bit OID + ULONGLONG ullTsrOK[TYPE_MAXTD]; + + // for some optional OIDs (64 bits) and DMI support + ULONGLONG ullTxBroadcastFrames[TYPE_MAXTD]; + ULONGLONG ullTxMulticastFrames[TYPE_MAXTD]; + ULONGLONG ullTxDirectedFrames[TYPE_MAXTD]; + ULONGLONG ullTxBroadcastBytes[TYPE_MAXTD]; + ULONGLONG ullTxMulticastBytes[TYPE_MAXTD]; + ULONGLONG ullTxDirectedBytes[TYPE_MAXTD]; + +// DWORD dwTxRetryCount[8]; + // + // ISR status count + // + SISRCounters ISRStat; + + SCustomCounters CustomStat; + + #ifdef Calcu_LinkQual + //Tx count: + ULONG TxNoRetryOkCount; //success tx no retry ! + ULONG TxRetryOkCount; //sucess tx but retry ! + ULONG TxFailCount; //fail tx ? + //Rx count: + ULONG RxOkCnt; //sucess rx ! + ULONG RxFcsErrCnt; //fail rx ? + //statistic + ULONG SignalStren; + ULONG LinkQuality; + #endif +} SStatCounter, DEF* PSStatCounter; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +void STAvClearAllCounter(PSStatCounter pStatistic); + +void STAvUpdateIsrStatCounter(PSStatCounter pStatistic, DWORD dwIsr); + +void STAvUpdateRDStatCounter(PSStatCounter pStatistic, + BYTE byRSR, BYTE byNewRSR, BYTE byRxRate, + PBYTE pbyBuffer, UINT cbFrameLength); + +void STAvUpdateRDStatCounterEx(PSStatCounter pStatistic, + BYTE byRSR, BYTE byNewRsr, BYTE byRxRate, + PBYTE pbyBuffer, UINT cbFrameLength); + +void STAvUpdateTDStatCounter(PSStatCounter pStatistic, + BYTE byTSR0, BYTE byTSR1, + PBYTE pbyBuffer, UINT cbFrameLength, UINT uIdx ); + +void STAvUpdateTDStatCounterEx( + PSStatCounter pStatistic, + PBYTE pbyBuffer, + DWORD cbFrameLength + ); + +void STAvUpdate802_11Counter( + PSDot11Counters p802_11Counter, + PSStatCounter pStatistic, + DWORD dwCounter + ); + +void STAvClear802_11Counter(PSDot11Counters p802_11Counter); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __MIB_H__ + + + diff --git a/drivers/staging/vt6655/michael.c b/drivers/staging/vt6655/michael.c new file mode 100644 index 00000000000..7bda4c19e90 --- /dev/null +++ b/drivers/staging/vt6655/michael.c @@ -0,0 +1,188 @@ +/* + * 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: michael.cpp + * + * Purpose: The implementation of LIST data structure. + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + * Functions: + * s_dwGetUINT32 - Convert from BYTE[] to DWORD in a portable way + * s_vPutUINT32 - Convert from DWORD to BYTE[] in a portable way + * s_vClear - Reset the state to the empty message. + * s_vSetKey - Set the key. + * MIC_vInit - Set the key. + * s_vAppendByte - Append the byte to our word-sized buffer. + * MIC_vAppend - call s_vAppendByte. + * MIC_vGetMIC - Append the minimum padding and call s_vAppendByte. + * + * Revision History: + * + */ + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MICHAEL_H__) +#include "michael.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ +/* +static DWORD s_dwGetUINT32(BYTE * p); // Get DWORD from 4 bytes LSByte first +static VOID s_vPutUINT32(BYTE* p, DWORD val); // Put DWORD into 4 bytes LSByte first +*/ +static VOID s_vClear(void); // Clear the internal message, + // resets the object to the state just after construction. +static VOID s_vSetKey(DWORD dwK0, DWORD dwK1); +static VOID s_vAppendByte(BYTE b); // Add a single byte to the internal message + +/*--------------------- Export Variables --------------------------*/ +static DWORD L, R; // Current state + +static DWORD K0, K1; // Key +static DWORD M; // Message accumulator (single word) +static UINT nBytesInM; // # bytes in M + +/*--------------------- Export Functions --------------------------*/ + +/* +static DWORD s_dwGetUINT32 (BYTE * p) +// Convert from BYTE[] to DWORD in a portable way +{ + DWORD res = 0; + UINT i; + for(i=0; i<4; i++ ) + { + res |= (*p++) << (8*i); + } + return res; +} + +static VOID s_vPutUINT32 (BYTE* p, DWORD val) +// Convert from DWORD to BYTE[] in a portable way +{ + UINT i; + for(i=0; i<4; i++ ) + { + *p++ = (BYTE) (val & 0xff); + val >>= 8; + } +} +*/ + +static VOID s_vClear (void) +{ + // Reset the state to the empty message. + L = K0; + R = K1; + nBytesInM = 0; + M = 0; +} + +static VOID s_vSetKey (DWORD dwK0, DWORD dwK1) +{ + // Set the key + K0 = dwK0; + K1 = dwK1; + // and reset the message + s_vClear(); +} + +static VOID s_vAppendByte (BYTE b) +{ + // Append the byte to our word-sized buffer + M |= b << (8*nBytesInM); + nBytesInM++; + // Process the word if it is full. + if( nBytesInM >= 4 ) + { + L ^= M; + R ^= ROL32( L, 17 ); + L += R; + R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); + L += R; + R ^= ROL32( L, 3 ); + L += R; + R ^= ROR32( L, 2 ); + L += R; + // Clear the buffer + M = 0; + nBytesInM = 0; + } +} + +VOID MIC_vInit (DWORD dwK0, DWORD dwK1) +{ + // Set the key + s_vSetKey(dwK0, dwK1); +} + + +VOID MIC_vUnInit (void) +{ + // Wipe the key material + K0 = 0; + K1 = 0; + + // And the other fields as well. + //Note that this sets (L,R) to (K0,K1) which is just fine. + s_vClear(); +} + +VOID MIC_vAppend (PBYTE src, UINT nBytes) +{ + // This is simple + while (nBytes > 0) + { + s_vAppendByte(*src++); + nBytes--; + } +} + +VOID MIC_vGetMIC (PDWORD pdwL, PDWORD pdwR) +{ + // Append the minimum padding + s_vAppendByte(0x5a); + s_vAppendByte(0); + s_vAppendByte(0); + s_vAppendByte(0); + s_vAppendByte(0); + // and then zeroes until the length is a multiple of 4 + while( nBytesInM != 0 ) + { + s_vAppendByte(0); + } + // The s_vAppendByte function has already computed the result. + *pdwL = L; + *pdwR = R; + // Reset to the empty message. + s_vClear(); +} + diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h new file mode 100644 index 00000000000..62a24a6083a --- /dev/null +++ b/drivers/staging/vt6655/michael.h @@ -0,0 +1,62 @@ +/* + * 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: Michael.h + * + * Purpose: Reference implementation for Michael + * written by Niels Ferguson + * + * Author: Kyle Hsu + * + * Date: Jan 2, 2003 + * + */ + + +#ifndef __MICHAEL_H__ +#define __MICHAEL_H__ + +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +VOID MIC_vInit(DWORD dwK0, DWORD dwK1); + +VOID MIC_vUnInit(void); + +// Append bytes to the message to be MICed +VOID MIC_vAppend(PBYTE src, UINT nBytes); + +// Get the MIC result. Destination should accept 8 bytes of result. +// This also resets the message to empty. +VOID MIC_vGetMIC(PDWORD pdwL, PDWORD pdwR); + +/*--------------------- Export Macros ------------------------------*/ + +// Rotation functions on 32 bit values +#define ROL32( A, n ) \ + ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +#endif //__MICHAEL_H__ + + diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c new file mode 100644 index 00000000000..edd8336712a --- /dev/null +++ b/drivers/staging/vt6655/power.c @@ -0,0 +1,441 @@ +/* + * 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: power.c + * + * Purpose: Handles 802.11 power managment functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + * Functions: + * PSvEnablePowerSaving - Enable Power Saving Mode + * PSvDiasblePowerSaving - Disable Power Saving Mode + * PSbConsiderPowerDown - Decide if we can Power Down + * PSvSendPSPOLL - Send PS-POLL packet + * PSbSendNullPacket - Send Null packet + * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon + * + * Revision History: + * + */ + + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif + + + + +/*--------------------- Static Definitions -------------------------*/ + + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +/*--------------------- Static Functions --------------------------*/ + + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + +/*+ + * + * Routine Description: + * Enable hw power saving functions + * + * Return Value: + * None. + * +-*/ + + +VOID +PSvEnablePowerSaving( + IN HANDLE hDeviceContext, + IN WORD wListenInterval + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + WORD wAID = pMgmt->wCurrAID | BIT14 | BIT15; + + // set period of power up before TBTT + VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT); + if (pDevice->eOPMode != OP_MODE_ADHOC) { + // set AID + VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID); + } else { + // set ATIM Window + MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); + } + // Set AutoSleep + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + // Set HWUTSF + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + + if (wListenInterval >= 2) { + // clear always listen beacon + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + //pDevice->wCFG &= ~CFG_ALB; + // first time set listen next beacon + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); + pMgmt->wCountToWakeUp = wListenInterval; + } + else { + // always listen beacon + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + //pDevice->wCFG |= CFG_ALB; + pMgmt->wCountToWakeUp = 0; + } + + // enable power saving hw function + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); + pDevice->bEnablePSMode = TRUE; + + if (pDevice->eOPMode == OP_MODE_ADHOC) { +// bMgrPrepareBeaconToSend((HANDLE)pDevice, pMgmt); + } + // We don't send null pkt in ad hoc mode since beacon will handle this. + else if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) { + PSbSendNullPacket(pDevice); + } + pDevice->bPWBitOn = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable... \n"); + return; +} + + + + + + +/*+ + * + * Routine Description: + * Disable hw power saving functions + * + * Return Value: + * None. + * +-*/ + +VOID +PSvDisablePowerSaving( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; +// PSMgmtObject pMgmt = pDevice->pMgmt; + + // disable power saving hw function + MACbPSWakeup(pDevice->PortOffset); + //clear AutoSleep + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + //clear HWUTSF + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + // set always listen beacon + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + + pDevice->bEnablePSMode = FALSE; + + if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) { + PSbSendNullPacket(pDevice); + } + pDevice->bPWBitOn = FALSE; + return; +} + + +/*+ + * + * Routine Description: + * Consider to power down when no more packets to tx or rx. + * + * Return Value: + * TRUE, if power down success + * FALSE, if fail +-*/ + + +BOOL +PSbConsiderPowerDown( + IN HANDLE hDeviceContext, + IN BOOL bCheckRxDMA, + IN BOOL bCheckCountToWakeUp + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uIdx; + + // check if already in Doze mode + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) + return TRUE; + + if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) { + // check if in TIM wake period + if (pMgmt->bInTIMWake) + return FALSE; + } + + // check scan state + if (pDevice->bCmdRunning) + return FALSE; + + // Froce PSEN on + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); + + // check if all TD are empty, + for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) { + if (pDevice->iTDUsed[uIdx] != 0) + return FALSE; + } + + // check if rx isr is clear + if (bCheckRxDMA && + ((pDevice->dwIsr& ISR_RXDMA0) != 0) && + ((pDevice->dwIsr & ISR_RXDMA1) != 0)){ + return FALSE; + }; + + if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) { + if (bCheckCountToWakeUp && + (pMgmt->wCountToWakeUp == 0 || pMgmt->wCountToWakeUp == 1)) { + return FALSE; + } + } + + // no Tx, no Rx isr, now go to Doze + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_GO2DOZE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n"); + return TRUE; +} + + + +/*+ + * + * Routine Description: + * Send PS-POLL packet + * + * Return Value: + * None. + * +-*/ + + + +VOID +PSvSendPSPOLL( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxMgmtPacket pTxPacket = NULL; + + + memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN); + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + pTxPacket->p80211Header->sA2.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_CTL) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PSPOLL) | + WLAN_SET_FC_PWRMGT(0) + )); + pTxPacket->p80211Header->sA2.wDurationID = pMgmt->wCurrAID | BIT14 | BIT15; + memcpy(pTxPacket->p80211Header->sA2.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA2.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + pTxPacket->cbMPDULen = WLAN_HDR_ADDR2_LEN; + pTxPacket->cbPayloadLen = 0; + // send the frame + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n"); + } + else { +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet success..\n"); + }; + + return; +} + + + +/*+ + * + * Routine Description: + * Send NULL packet to AP for notification power state of STA + * + * Return Value: + * None. + * +-*/ +BOOL +PSbSendNullPacket( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSTxMgmtPacket pTxPacket = NULL; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uIdx; + + + if (pDevice->bLinkPass == FALSE) { + return FALSE; + } + #ifdef TxInSleep + if ((pDevice->bEnablePSMode == FALSE) && + (pDevice->fTxDataInSleep == FALSE)){ + return FALSE; + } +#else + if (pDevice->bEnablePSMode == FALSE) { + return FALSE; + } +#endif + if (pDevice->bEnablePSMode) { + for (uIdx = 0; uIdx < TYPE_MAXTD; uIdx ++) { + if (pDevice->iTDUsed[uIdx] != 0) + return FALSE; + } + } + + memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN); + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool; + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + + if (pDevice->bEnablePSMode) { + + pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) | + WLAN_SET_FC_PWRMGT(1) + )); + } + else { + pTxPacket->p80211Header->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL) | + WLAN_SET_FC_PWRMGT(0) + )); + } + + if(pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) { + pTxPacket->p80211Header->sA3.wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_TODS(1)); + } + + memcpy(pTxPacket->p80211Header->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy(pTxPacket->p80211Header->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + pTxPacket->cbMPDULen = WLAN_HDR_ADDR3_LEN; + pTxPacket->cbPayloadLen = 0; + // send the frame + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n"); + return FALSE; + } + else { + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet success....\n"); + } + + + return TRUE ; +} + +/*+ + * + * Routine Description: + * Check if Next TBTT must wake up + * + * Return Value: + * None. + * +-*/ + +BOOL +PSbIsNextTBTTWakeUp( + IN HANDLE hDeviceContext + ) +{ + + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + BOOL bWakeUp = FALSE; + + if (pMgmt->wListenInterval >= 2) { + if (pMgmt->wCountToWakeUp == 0) { + pMgmt->wCountToWakeUp = pMgmt->wListenInterval; + } + + pMgmt->wCountToWakeUp --; + + if (pMgmt->wCountToWakeUp == 1) { + // Turn on wake up to listen next beacon + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); + bWakeUp = TRUE; + } + + } + + return bWakeUp; +} + diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h new file mode 100644 index 00000000000..a01e7e9aaf6 --- /dev/null +++ b/drivers/staging/vt6655/power.h @@ -0,0 +1,85 @@ +/* + * 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: power.h + * + * Purpose: Handles 802.11 power managment functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + */ + +#ifndef __POWER_H__ +#define __POWER_H__ + + +/*--------------------- Export Definitions -------------------------*/ +#define C_PWBT 1000 // micro sec. power up before TBTT +#define PS_FAST_INTERVAL 1 // Fast power saving listen interval +#define PS_MAX_INTERVAL 4 // MAX power saving listen interval + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Types ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + +// IN PSDevice pDevice +// IN PSDevice hDeviceContext + +BOOL +PSbConsiderPowerDown( + IN HANDLE hDeviceContext, + IN BOOL bCheckRxDMA, + IN BOOL bCheckCountToWakeUp + ); + +VOID +PSvDisablePowerSaving( + IN HANDLE hDeviceContext + ); + +VOID +PSvEnablePowerSaving( + IN HANDLE hDeviceContext, + IN WORD wListenInterval + ); + +VOID +PSvSendPSPOLL( + IN HANDLE hDeviceContext + ); + +BOOL +PSbSendNullPacket( + IN HANDLE hDeviceContext + ); + +BOOL +PSbIsNextTBTTWakeUp( + IN HANDLE hDeviceContext + ); + +#endif //__POWER_H__ diff --git a/drivers/staging/vt6655/rc4.c b/drivers/staging/vt6655/rc4.c new file mode 100644 index 00000000000..0345e3247f4 --- /dev/null +++ b/drivers/staging/vt6655/rc4.c @@ -0,0 +1,86 @@ +/* + * File: rc4.c + * + * 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. + * + * Purpose: + * + * Functions: + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + */ + +#if !defined(__RC4_H__) +#include "rc4.h" +#endif + +VOID rc4_init(PRC4Ext pRC4, PBYTE pbyKey, UINT cbKey_len) +{ + UINT ust1, ust2; + UINT keyindex; + UINT stateindex; + PBYTE pbyst; + UINT idx; + + pbyst = pRC4->abystate; + pRC4->ux = 0; + pRC4->uy = 0; + for (idx = 0; idx < 256; idx++) + pbyst[idx] = (BYTE)idx; + keyindex = 0; + stateindex = 0; + for (idx = 0; idx < 256; idx++) { + ust1 = pbyst[idx]; + stateindex = (stateindex + pbyKey[keyindex] + ust1) & 0xff; + ust2 = pbyst[stateindex]; + pbyst[stateindex] = (BYTE)ust1; + pbyst[idx] = (BYTE)ust2; + if (++keyindex >= cbKey_len) + keyindex = 0; + } +} + +UINT rc4_byte(PRC4Ext pRC4) +{ + UINT ux; + UINT uy; + UINT ustx, usty; + PBYTE pbyst; + + pbyst = pRC4->abystate; + ux = (pRC4->ux + 1) & 0xff; + ustx = pbyst[ux]; + uy = (ustx + pRC4->uy) & 0xff; + usty = pbyst[uy]; + pRC4->ux = ux; + pRC4->uy = uy; + pbyst[uy] = (BYTE)ustx; + pbyst[ux] = (BYTE)usty; + + return pbyst[(ustx + usty) & 0xff]; +} + +VOID rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, + PBYTE pbySrc, UINT cbData_len) +{ + UINT ii; + for (ii = 0; ii < cbData_len; ii++) + pbyDest[ii] = (BYTE)(pbySrc[ii] ^ rc4_byte(pRC4)); +} diff --git a/drivers/staging/vt6655/rc4.h b/drivers/staging/vt6655/rc4.h new file mode 100644 index 00000000000..4e3ccc559c8 --- /dev/null +++ b/drivers/staging/vt6655/rc4.h @@ -0,0 +1,51 @@ +/* + * File: rc4.h + * + * 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. + * + * Purpose: + * + * Functions: + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: Sep 4, 2002 + * + */ + +#ifndef __RC4_H__ +#define __RC4_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ +/*--------------------- Export Types ------------------------------*/ +typedef struct { + UINT ux; + UINT uy; + BYTE abystate[256]; +} RC4Ext, DEF* PRC4Ext; + +VOID rc4_init(PRC4Ext pRC4, PBYTE pbyKey, UINT cbKey_len); +UINT rc4_byte(PRC4Ext pRC4); +void rc4_encrypt(PRC4Ext pRC4, PBYTE pbyDest, PBYTE pbySrc, UINT cbData_len); + +#endif //__RC4_H__ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c new file mode 100644 index 00000000000..9d4e3eb7c8e --- /dev/null +++ b/drivers/staging/vt6655/rf.c @@ -0,0 +1,1283 @@ +/* + * 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: rf.c + * + * Purpose: rf function code + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + * Functions: + * IFRFbWriteEmbeded - Embeded write RF register via MAC + * + * Revision History: + * + */ +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__SROM_H__) +#include "srom.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +//static int msglevel =MSG_LEVEL_INFO; + +#define BY_RF2959_REG_LEN 23 //24bits +#define CB_RF2959_INIT_SEQ 15 +#define SWITCH_CHANNEL_DELAY_RF2959 200 //us +#define RF2959_PWR_IDX_LEN 32 + +#define BY_MA2825_REG_LEN 23 //24bit +#define CB_MA2825_INIT_SEQ 13 +#define SWITCH_CHANNEL_DELAY_MA2825 200 //us +#define MA2825_PWR_IDX_LEN 31 + +#define BY_AL2230_REG_LEN 23 //24bit +#define CB_AL2230_INIT_SEQ 15 +#define SWITCH_CHANNEL_DELAY_AL2230 200 //us +#define AL2230_PWR_IDX_LEN 64 + + +#define BY_UW2451_REG_LEN 23 +#define CB_UW2451_INIT_SEQ 6 +#define SWITCH_CHANNEL_DELAY_UW2451 200 //us +#define UW2451_PWR_IDX_LEN 25 + +//{{ RobertYu: 20041118 +#define BY_MA2829_REG_LEN 23 //24bit +#define CB_MA2829_INIT_SEQ 13 +#define SWITCH_CHANNEL_DELAY_MA2829 200 //us +#define MA2829_PWR_IDX_LEN 64 +//}} RobertYu + +//{{ RobertYu:20050103 +#define BY_AL7230_REG_LEN 23 //24bit +#define CB_AL7230_INIT_SEQ 16 +#define SWITCH_CHANNEL_DELAY_AL7230 200 //us +#define AL7230_PWR_IDX_LEN 64 +//}} RobertYu + +//{{ RobertYu: 20041210 +#define BY_UW2452_REG_LEN 23 +#define CB_UW2452_INIT_SEQ 5 //RoberYu:20050113, Rev0.2 Programming Guide(remove R3, so 6-->5) +#define SWITCH_CHANNEL_DELAY_UW2452 100 //us +#define UW2452_PWR_IDX_LEN 64 +//}} RobertYu + +#define BY_VT3226_REG_LEN 23 +#define CB_VT3226_INIT_SEQ 12 +#define SWITCH_CHANNEL_DELAY_VT3226 200 //us +#define VT3226_PWR_IDX_LEN 16 + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + + + +const DWORD dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { + 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // + 0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW + }; + +const DWORD dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { + 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz + 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz + 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz + 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz + 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz + 0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz + 0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M + }; + +const DWORD dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz + 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz + 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz + 0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M + }; + +DWORD dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { + 0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04043900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04044900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04045900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04046900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04047900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04048900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04049900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0404F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04050900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04051900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04052900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04053900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04054900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04055900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04056900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04057900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04058900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04059900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0405F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04060900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04061900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04062900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04063900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04064900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04065900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04066900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04067900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04068900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04069900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0406F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04070900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04071900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04072900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04073900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04074900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04075900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04076900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04077900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04078900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x04079900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407A900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407C900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407D900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407E900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, + 0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW + }; + +//{{ RobertYu:20050104 +// 40MHz reference frequency +// Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. +const DWORD dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { + 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a + 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a + 0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2 + 0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 5FDFA3 + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11b/g // Need modify for 11a + //0x802B4500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B45 + // RoberYu:20050113, Rev0.47 Regsiter Setting Guide + 0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B55 + 0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 860207 + 0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: E0600A + 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) + //0x00093C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C + // RoberYu:20050113, Rev0.47 Regsiter Setting Guide + 0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C + 0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11a: 12BACF + }; + +const DWORD dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g + 0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g + 0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g + 0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11a // Need modify for 11b/g + 0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g, RoberYu:20050113 + 0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g + 0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g + 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) + 0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g + 0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, + 0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11b/g + }; + + +const DWORD dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { + 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 + 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19) + 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20) + 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21) + 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + + 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23) + 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24) + 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25) + 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26) + 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27) + 0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28) + 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29) + 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30) + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32) + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33) + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34) + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35) + 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36) + 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37) + 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38) + 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39) + 0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40) + + 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41) + 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42) + 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43) + 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44) + 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45) + 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46) + 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47) + 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48) + 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49) + 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50) + 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51) + 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52) + 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53) + 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54) + 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55) + 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56) + }; + +const DWORD dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { + 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz + 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz + 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz + 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz + 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz + 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz + 0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16) + 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17) + 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19) + 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24) + 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25) + 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28) + 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30) + 0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32) + 0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34) + 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48) + 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49) + 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50) + 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51) + 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52) + 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53) + 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54) + 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55) + 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56) + }; + +const DWORD dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz + 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz + + // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22) + + // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, + // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50) + 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55) + 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56) + }; +//}} RobertYu + + + + +/*--------------------- Static Functions --------------------------*/ + + + + +/* + * Description: AIROHA IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL s_bAL7230Init (DWORD_PTR dwIoBase) +{ + int ii; + BOOL bResult; + + bResult = TRUE; + + //3-wire control for normal mode + VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); + + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | + SOFTPWRCTL_TXPEINV)); + BBvPowerSaveModeOFF(dwIoBase); //RobertYu:20050106, have DC value for Calibration + + for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[ii]); + + // PLL On + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + //Calibration + MACvTimer0MicroSDelay(dwIoBase, 150);//150us + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:active, RCK:diable + MACvTimer0MicroSDelay(dwIoBase, 30);//30us + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); //TXDCOC:diable, RCK:active + MACvTimer0MicroSDelay(dwIoBase, 30);//30us + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); //TXDCOC:diable, RCK:diable + + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | + SOFTPWRCTL_SWPE2 | + SOFTPWRCTL_SWPECTI | + SOFTPWRCTL_TXPEINV)); + + BBvPowerSaveModeON(dwIoBase); // RobertYu:20050106 + + // PE1: TX_ON, PE2: RX_ON, PE3: PLLON + //3-wire control for power saving mode + VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000 + + return bResult; +} + +// Need to Pull PLLON low when writing channel registers through 3-wire interface +BOOL s_bAL7230SelectChannel (DWORD_PTR dwIoBase, BYTE byChannel) +{ + BOOL bResult; + + bResult = TRUE; + + // PLLON Off + MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable0[byChannel-1]); //Reg0 + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable1[byChannel-1]); //Reg1 + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL7230ChannelTable2[byChannel-1]); //Reg4 + + // PLLOn On + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + // Set Channel[7] = 0 to tell H/W channel is changing now. + VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); + MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230); + // Set Channel[7] = 1 to tell H/W channel change is done. + VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); + + return bResult; +} + +/* + * Description: Select channel with UW2452 chip + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + + +//{{ RobertYu: 20041210 +/* + * Description: UW2452 IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + + + +//}} RobertYu +//////////////////////////////////////////////////////////////////////////////// + +/* + * Description: VT3226 IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +/* + * Description: Select channel with VT3226 chip + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + + + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: Write to IF/RF, by embeded programming + * + * Parameters: + * In: + * dwIoBase - I/O base address + * dwData - data to write + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL IFRFbWriteEmbeded (DWORD_PTR dwIoBase, DWORD dwData) +{ + WORD ww; + DWORD dwValue; + + VNSvOutPortD(dwIoBase + MAC_REG_IFREGCTL, dwData); + + // W_MAX_TIMEOUT is the timeout period + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + VNSvInPortD(dwIoBase + MAC_REG_IFREGCTL, &dwValue); + if (BITbIsBitOn(dwValue, IFREGCTL_DONE)) + break; + } + + if (ww == W_MAX_TIMEOUT) { +// DBG_PORT80_ALWAYS(0x32); + return FALSE; + } + return TRUE; +} + + + +/* + * Description: RFMD RF2959 IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +/* + * Description: Select channel with RFMD 2959 chip + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +/* + * Description: AIROHA IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL RFbAL2230Init (DWORD_PTR dwIoBase) +{ + int ii; + BOOL bResult; + + bResult = TRUE; + + //3-wire control for normal mode + VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); + + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPECTI | + SOFTPWRCTL_TXPEINV)); +//2008-8-21 chester <add> + // PLL Off + + MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + + + //patch abnormal AL2230 frequency output +//2008-8-21 chester <add> + IFRFbWriteEmbeded(dwIoBase, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + + + for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL2230InitTable[ii]); +//2008-8-21 chester <add> +MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us + + // PLL On + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + MACvTimer0MicroSDelay(dwIoBase, 150);//150us + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + MACvTimer0MicroSDelay(dwIoBase, 30);//30us + bResult &= IFRFbWriteEmbeded(dwIoBase, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + MACvTimer0MicroSDelay(dwIoBase, 30);//30us + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); + + MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | + SOFTPWRCTL_SWPE2 | + SOFTPWRCTL_SWPECTI | + SOFTPWRCTL_TXPEINV)); + + //3-wire control for power saving mode + VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000 + + return bResult; +} + +BOOL RFbAL2230SelectChannel (DWORD_PTR dwIoBase, BYTE byChannel) +{ + BOOL bResult; + + bResult = TRUE; + + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL2230ChannelTable0[byChannel-1]); + bResult &= IFRFbWriteEmbeded (dwIoBase, dwAL2230ChannelTable1[byChannel-1]); + + // Set Channel[7] = 0 to tell H/W channel is changing now. + VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); + MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230); + // Set Channel[7] = 1 to tell H/W channel change is done. + VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); + + return bResult; +} + +/* + * Description: UW2451 IFRF chip init function + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + + +/* + * Description: Select channel with UW2451 chip + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +/* + * Description: Set sleep mode to UW2451 chip + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +/* + * Description: RF init function + * + * Parameters: + * In: + * byBBType + * byRFType + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL RFbInit ( + IN PSDevice pDevice + ) +{ +BOOL bResult = TRUE; + switch (pDevice->byRFType) { + case RF_AIROHA : + case RF_AL2230S: + pDevice->byMaxPwrLevel = AL2230_PWR_IDX_LEN; + bResult = RFbAL2230Init(pDevice->PortOffset); + break; + case RF_AIROHA7230 : + pDevice->byMaxPwrLevel = AL7230_PWR_IDX_LEN; + bResult = s_bAL7230Init(pDevice->PortOffset); + break; + case RF_NOTHING : + bResult = TRUE; + break; + default : + bResult = FALSE; + break; + } + return bResult; +} + +/* + * Description: RF ShutDown function + * + * Parameters: + * In: + * byBBType + * byRFType + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL RFbShutDown ( + IN PSDevice pDevice + ) +{ +BOOL bResult = TRUE; + + switch (pDevice->byRFType) { + case RF_AIROHA7230 : + bResult = IFRFbWriteEmbeded (pDevice->PortOffset, 0x1ABAEF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW); + break; + default : + bResult = TRUE; + break; + } + return bResult; +} + +/* + * Description: Select channel + * + * Parameters: + * In: + * byRFType + * byChannel - Channel number + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL RFbSelectChannel (DWORD_PTR dwIoBase, BYTE byRFType, BYTE byChannel) +{ +BOOL bResult = TRUE; + switch (byRFType) { + + case RF_AIROHA : + case RF_AL2230S: + bResult = RFbAL2230SelectChannel(dwIoBase, byChannel); + break; + //{{ RobertYu: 20050104 + case RF_AIROHA7230 : + bResult = s_bAL7230SelectChannel(dwIoBase, byChannel); + break; + //}} RobertYu + case RF_NOTHING : + bResult = TRUE; + break; + default: + bResult = FALSE; + break; + } + return bResult; +} + +/* + * Description: Write WakeProgSyn + * + * Parameters: + * In: + * dwIoBase - I/O base address + * uChannel - channel number + * bySleepCnt - SleepProgSyn count + * + * Return Value: None. + * + */ +BOOL RFvWriteWakeProgSyn (DWORD_PTR dwIoBase, BYTE byRFType, UINT uChannel) +{ + int ii; + BYTE byInitCount = 0; + BYTE bySleepCount = 0; + + VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, 0); + switch (byRFType) { + case RF_AIROHA: + case RF_AL2230S: + + if (uChannel > CB_MAX_CHANNEL_24G) + return FALSE; + + byInitCount = CB_AL2230_INIT_SEQ + 2; // Init Reg + Channel Reg (2) + bySleepCount = 0; + if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) { + return FALSE; + } + + for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++ ) { + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]); + } + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]); + ii ++; + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]); + break; + + //{{ RobertYu: 20050104 + // Need to check, PLLON need to be low for channel setting + case RF_AIROHA7230: + byInitCount = CB_AL7230_INIT_SEQ + 3; // Init Reg + Channel Reg (3) + bySleepCount = 0; + if (byInitCount > (MISCFIFO_SYNDATASIZE - bySleepCount)) { + return FALSE; + } + + if (uChannel <= CB_MAX_CHANNEL_24G) + { + for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++ ) { + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]); + } + } + else + { + for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++ ) { + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]); + } + } + + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]); + ii ++; + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]); + ii ++; + MACvSetMISCFifo(dwIoBase, (WORD)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]); + break; + //}} RobertYu + + case RF_NOTHING : + return TRUE; + break; + + default: + return FALSE; + break; + } + + MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (DWORD)MAKEWORD(bySleepCount, byInitCount)); + + return TRUE; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * dwIoBase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL RFbSetPower ( + IN PSDevice pDevice, + IN UINT uRATE, + IN UINT uCH + ) +{ +BOOL bResult = TRUE; +BYTE byPwr = 0; +BYTE byDec = 0; +BYTE byPwrdBm = 0; + + if (pDevice->dwDiagRefCount != 0) { + return TRUE; + } + if ((uCH < 1) || (uCH > CB_MAX_CHANNEL)) { + return FALSE; + } + + switch (uRATE) { + case RATE_1M: + case RATE_2M: + case RATE_5M: + case RATE_11M: + byPwr = pDevice->abyCCKPwrTbl[uCH]; + byPwrdBm = pDevice->abyCCKDefaultPwr[uCH]; +//PLICE_DEBUG-> + //byPwr+=5; +//PLICE_DEBUG <- + +//printk("Rate <11:byPwr is %d\n",byPwr); + break; + case RATE_6M: + case RATE_9M: + case RATE_18M: + byPwr = pDevice->abyOFDMPwrTbl[uCH]; + if (pDevice->byRFType == RF_UW2452) { + byDec = byPwr + 14; + } else { + byDec = byPwr + 10; + } + if (byDec >= pDevice->byMaxPwrLevel) { + byDec = pDevice->byMaxPwrLevel-1; + } + if (pDevice->byRFType == RF_UW2452) { + byPwrdBm = byDec - byPwr; + byPwrdBm /= 3; + } else { + byPwrdBm = byDec - byPwr; + byPwrdBm >>= 1; + } + byPwrdBm += pDevice->abyOFDMDefaultPwr[uCH]; + byPwr = byDec; +//PLICE_DEBUG-> + //byPwr+=5; +//PLICE_DEBUG<- + +//printk("Rate <24:byPwr is %d\n",byPwr); + break; + case RATE_24M: + case RATE_36M: + case RATE_48M: + case RATE_54M: + byPwr = pDevice->abyOFDMPwrTbl[uCH]; + byPwrdBm = pDevice->abyOFDMDefaultPwr[uCH]; +//PLICE_DEBUG-> + //byPwr+=5; +//PLICE_DEBUG<- +//printk("Rate < 54:byPwr is %d\n",byPwr); + break; + } + +#if 0 + + // 802.11h TPC + if (pDevice->bLinkPass == TRUE) { + // do not over local constraint + if (byPwrdBm > pDevice->abyLocalPwr[uCH]) { + pDevice->byCurPwrdBm = pDevice->abyLocalPwr[uCH]; + byDec = byPwrdBm - pDevice->abyLocalPwr[uCH]; + if (pDevice->byRFType == RF_UW2452) { + byDec *= 3; + } else { + byDec <<= 1; + } + if (byPwr > byDec) { + byPwr -= byDec; + } else { + byPwr = 0; + } + } else { + pDevice->byCurPwrdBm = byPwrdBm; + } + } else { + // do not over regulatory constraint + if (byPwrdBm > pDevice->abyRegPwr[uCH]) { + pDevice->byCurPwrdBm = pDevice->abyRegPwr[uCH]; + byDec = byPwrdBm - pDevice->abyRegPwr[uCH]; + if (pDevice->byRFType == RF_UW2452) { + byDec *= 3; + } else { + byDec <<= 1; + } + if (byPwr > byDec) { + byPwr -= byDec; + } else { + byPwr = 0; + } + } else { + pDevice->byCurPwrdBm = byPwrdBm; + } + } +#endif + +// if (pDevice->byLocalID <= REV_ID_VT3253_B1) { + if (pDevice->byCurPwr == byPwr) { + return TRUE; + } + bResult = RFbRawSetPower(pDevice, byPwr, uRATE); +// } + if (bResult == TRUE) { + pDevice->byCurPwr = byPwr; + } + return bResult; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * dwIoBase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ + +BOOL RFbRawSetPower ( + IN PSDevice pDevice, + IN BYTE byPwr, + IN UINT uRATE + ) +{ +BOOL bResult = TRUE; +DWORD dwMax7230Pwr = 0; + + if (byPwr >= pDevice->byMaxPwrLevel) { + return (FALSE); + } + switch (pDevice->byRFType) { + + case RF_AIROHA : + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); + if (uRATE <= RATE_11M) { + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + } else { + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + } + break; + + + case RF_AL2230S : + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwAL2230PowerTable[byPwr]); + if (uRATE <= RATE_11M) { + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + }else { + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + } + + break; + + case RF_AIROHA7230: + // 0x080F1B00 for 3 wire control TxGain(D10) and 0x31 as TX Gain value + dwMax7230Pwr = 0x080C0B00 | ( (byPwr) << 12 ) | + (BY_AL7230_REG_LEN << 3 ) | IFREGCTL_REGW; + + bResult &= IFRFbWriteEmbeded(pDevice->PortOffset, dwMax7230Pwr); + break; + + + default : + break; + } + return bResult; +} + +/*+ + * + * Routine Description: + * Translate RSSI to dBm + * + * Parameters: + * In: + * pDevice - The adapter to be translated + * byCurrRSSI - RSSI to be translated + * Out: + * pdwdbm - Translated dbm number + * + * Return Value: none + * +-*/ +VOID +RFvRSSITodBm ( + IN PSDevice pDevice, + IN BYTE byCurrRSSI, + OUT PLONG pldBm + ) +{ + BYTE byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03); + LONG b = (byCurrRSSI & 0x3F); + LONG a = 0; + BYTE abyAIROHARF[4] = {0, 18, 0, 40}; + + switch (pDevice->byRFType) { + case RF_AIROHA: + case RF_AL2230S: + case RF_AIROHA7230: //RobertYu: 20040104 + a = abyAIROHARF[byIdx]; + break; + default: + break; + } + + *pldBm = -1 * (a + b * 2); +} + +//////////////////////////////////////////////////////////////////////////////// +//{{ RobertYu: 20050104 + + +// Post processing for the 11b/g and 11a. +// for save time on changing Reg2,3,5,7,10,12,15 +BOOL RFbAL7230SelectChannelPostProcess (DWORD_PTR dwIoBase, BYTE byOldChannel, BYTE byNewChannel) +{ + BOOL bResult; + + bResult = TRUE; + + // if change between 11 b/g and 11a need to update the following register + // Channel Index 1~14 + + if( (byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G) ) + { + // Change from 2.4G to 5G + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[2]); //Reg2 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[3]); //Reg3 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[5]); //Reg5 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[7]); //Reg7 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[10]);//Reg10 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[12]);//Reg12 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTableAMode[15]);//Reg15 + } + else if( (byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G) ) + { + // change from 5G to 2.4G + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[2]); //Reg2 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[3]); //Reg3 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[5]); //Reg5 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[7]); //Reg7 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[10]);//Reg10 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[12]);//Reg12 + bResult &= IFRFbWriteEmbeded(dwIoBase, dwAL7230InitTable[15]);//Reg15 + } + + return bResult; +} + + +//}} RobertYu +//////////////////////////////////////////////////////////////////////////////// + diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h new file mode 100644 index 00000000000..05fe17b2cfb --- /dev/null +++ b/drivers/staging/vt6655/rf.h @@ -0,0 +1,118 @@ +/* + * 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: rf.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + */ + + +#ifndef __RF_H__ +#define __RF_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +/*--------------------- Export Definitions -------------------------*/ +// +// Baseband RF pair definition in eeprom (Bits 6..0) +// +#define RF_RFMD2959 0x01 +#define RF_MAXIMAG 0x02 +#define RF_AIROHA 0x03 + +//#define RF_GCT5103 0x04 +#define RF_UW2451 0x05 +#define RF_MAXIMG 0x06 +#define RF_MAXIM2829 0x07 // RobertYu: 20041118 +#define RF_UW2452 0x08 // RobertYu: 20041210 +#define RF_AIROHA7230 0x0a // RobertYu: 20050104 +#define RF_UW2453 0x0b + +#define RF_VT3226 0x09 +#define RF_AL2230S 0x0e + +#define RF_NOTHING 0x7E +#define RF_EMU 0x80 +#define RF_MASK 0x7F + +#define ZONE_FCC 0 +#define ZONE_MKK1 1 +#define ZONE_ETSI 2 +#define ZONE_IC 3 +#define ZONE_SPAIN 4 +#define ZONE_FRANCE 5 +#define ZONE_MKK 6 +#define ZONE_ISRAEL 7 + +//[20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 +#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 //Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 +#define CB_UW2452_CHANNEL_5G_HIGH 41 //[20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL IFRFbWriteEmbeded(DWORD_PTR dwIoBase, DWORD dwData); +BOOL RFbSelectChannel(DWORD_PTR dwIoBase, BYTE byRFType, BYTE byChannel); +BOOL RFbInit ( + IN PSDevice pDevice + ); +BOOL RFvWriteWakeProgSyn(DWORD_PTR dwIoBase, BYTE byRFType, UINT uChannel); +BOOL RFbSetPower(PSDevice pDevice, UINT uRATE, UINT uCH); +BOOL RFbRawSetPower( + IN PSDevice pDevice, + IN BYTE byPwr, + IN UINT uRATE + ); + +VOID +RFvRSSITodBm( + IN PSDevice pDevice, + IN BYTE byCurrRSSI, + OUT PLONG pldBm + ); + +//{{ RobertYu: 20050104 +BOOL RFbAL7230SelectChannelPostProcess(DWORD_PTR dwIoBase, BYTE byOldChannel, BYTE byNewChannel); +//}} RobertYu + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __RF_H__ + + + diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c new file mode 100644 index 00000000000..c8a4a5533c7 --- /dev/null +++ b/drivers/staging/vt6655/rxtx.c @@ -0,0 +1,3269 @@ +/* + * 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: rxtx.c + * + * Purpose: handle WMAC/802.3/802.11 rx & tx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * s_vGenerateTxParameter - Generate tx dma requried parameter. + * vGenerateMACHeader - Translate 802.3 to 802.11 header + * cbGetFragCount - Caculate fragement number count + * csBeacon_xmit - beacon tx function + * csMgmt_xmit - management tx function + * s_cbFillTxBufHead - fulfill tx dma buffer header + * s_uGetDataDuration - get tx data required duration + * s_uFillDataHead- fulfill tx data duration header + * s_uGetRTSCTSDuration- get rtx/cts requried duration + * s_uGetRTSCTSRsvTime- get rts/cts reserved time + * s_uGetTxRsvTime- get frame reserved time + * s_vFillCTSHead- fulfill CTS ctl header + * s_vFillFragParameter- Set fragement ctl parameter. + * s_vFillRTSHead- fulfill RTS ctl header + * s_vFillTxKey- fulfill tx encrypt key + * s_vSWencryption- Software encrypt header + * vDMA0_tx_80211- tx 802.11 frame via dma0 + * vGenerateFIFOHeader- Generate tx FIFO ctl header + * + * Revision History: + * + */ + + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__MICHAEL_H__) +#include "michael.h" +#endif +#if !defined(__TKIP_H__) +#include "tkip.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__WROUTE_H__) +#include "wroute.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +#define PLICE_DEBUG + + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ +#define CRITICAL_PACKET_LEN 256 // if packet size < 256 -> in-direct send + // packet size >= 256 -> direct send + +const WORD wTimeStampOff[2][MAX_RATE] = { + {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble + {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble + }; + +const WORD wFB_Opt0[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0 + {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1 + }; +const WORD wFB_Opt1[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0 + {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1 + }; + + +#define RTSDUR_BB 0 +#define RTSDUR_BA 1 +#define RTSDUR_AA 2 +#define CTSDUR_BA 3 +#define RTSDUR_BA_F0 4 +#define RTSDUR_AA_F0 5 +#define RTSDUR_BA_F1 6 +#define RTSDUR_AA_F1 7 +#define CTSDUR_BA_F0 8 +#define CTSDUR_BA_F1 9 +#define DATADUR_B 10 +#define DATADUR_A 11 +#define DATADUR_A_F0 12 +#define DATADUR_A_F1 13 + +/*--------------------- Static Functions --------------------------*/ + + + +static +VOID +s_vFillTxKey( + IN PSDevice pDevice, + IN PBYTE pbyBuf, + IN PBYTE pbyIVHead, + IN PSKeyItem pTransmitKey, + IN PBYTE pbyHdrBuf, + IN WORD wPayloadLen, + OUT PBYTE pMICHDR + ); + + + +static +VOID +s_vFillRTSHead( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pvRTS, + IN UINT cbFrameLength, + IN BOOL bNeedAck, + IN BOOL bDisCRC, + IN PSEthernetHeader psEthHeader, + IN WORD wCurrentRate, + IN BYTE byFBOption + ); + +static +VOID +s_vGenerateTxParameter( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pTxBufHead, + IN PVOID pvRrvTime, + IN PVOID pvRTS, + IN PVOID pvCTS, + IN UINT cbFrameSize, + IN BOOL bNeedACK, + IN UINT uDMAIdx, + IN PSEthernetHeader psEthHeader, + IN WORD wCurrentRate + ); + + + +static void s_vFillFragParameter( + IN PSDevice pDevice, + IN PBYTE pbyBuffer, + IN UINT uTxType, + IN PVOID pvtdCurr, + IN WORD wFragType, + IN UINT cbReqCount + ); + + +static +UINT +s_cbFillTxBufHead ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PBYTE pbyTxBufferAddr, + IN UINT cbFrameBodySize, + IN UINT uDMAIdx, + IN PSTxDesc pHeadTD, + IN PSEthernetHeader psEthHeader, + IN PBYTE pPacket, + IN BOOL bNeedEncrypt, + IN PSKeyItem pTransmitKey, + IN UINT uNodeIndex, + OUT PUINT puMACfragNum + ); + + +static +UINT +s_uFillDataHead ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pTxDataHead, + IN UINT cbFrameLength, + IN UINT uDMAIdx, + IN BOOL bNeedAck, + IN UINT uFragIdx, + IN UINT cbLastFragmentSize, + IN UINT uMACfragNum, + IN BYTE byFBOption, + IN WORD wCurrentRate + ); + + +/*--------------------- Export Variables --------------------------*/ + + + +static +VOID +s_vFillTxKey ( + IN PSDevice pDevice, + IN PBYTE pbyBuf, + IN PBYTE pbyIVHead, + IN PSKeyItem pTransmitKey, + IN PBYTE pbyHdrBuf, + IN WORD wPayloadLen, + OUT PBYTE pMICHDR + ) +{ + PDWORD pdwIV = (PDWORD) pbyIVHead; + PDWORD pdwExtIV = (PDWORD) ((PBYTE)pbyIVHead+4); + WORD wValue; + PS802_11Header pMACHeader = (PS802_11Header)pbyHdrBuf; + DWORD dwRevIVCounter; + BYTE byKeyIndex = 0; + + + + //Fill TXKEY + if (pTransmitKey == NULL) + return; + + dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter); + *pdwIV = pDevice->dwIVCounter; + byKeyIndex = pTransmitKey->dwKeyIndex & 0xf; + + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){ + MEMvCopy(pDevice->abyPRNG, (PBYTE)&(dwRevIVCounter), 3); + MEMvCopy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + } else { + MEMvCopy(pbyBuf, (PBYTE)&(dwRevIVCounter), 3); + MEMvCopy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) { + MEMvCopy(pbyBuf+8, (PBYTE)&(dwRevIVCounter), 3); + MEMvCopy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength); + } + MEMvCopy(pDevice->abyPRNG, pbyBuf, 16); + } + // Append IV after Mac Header + *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111 + *pdwIV |= (byKeyIndex << 30); + *pdwIV = cpu_to_le32(*pdwIV); + pDevice->dwIVCounter++; + if (pDevice->dwIVCounter > WEP_IV_MASK) { + pDevice->dwIVCounter = 0; + } + } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + pTransmitKey->wTSC15_0++; + if (pTransmitKey->wTSC15_0 == 0) { + pTransmitKey->dwTSC47_16++; + } + TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + MEMvCopy(pbyBuf, pDevice->abyPRNG, 16); + // Make IV + MEMvCopy(pdwIV, pDevice->abyPRNG, 3); + + *(pbyIVHead+3) = (BYTE)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + // Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); + + } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + pTransmitKey->wTSC15_0++; + if (pTransmitKey->wTSC15_0 == 0) { + pTransmitKey->dwTSC47_16++; + } + MEMvCopy(pbyBuf, pTransmitKey->abyKey, 16); + + // Make IV + *pdwIV = 0; + *(pbyIVHead+3) = (BYTE)(((byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + *pdwIV |= cpu_to_le16((WORD)(pTransmitKey->wTSC15_0)); + //Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); + + //Fill MICHDR0 + *pMICHDR = 0x59; + *((PBYTE)(pMICHDR+1)) = 0; // TxPriority + MEMvCopy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6); + *((PBYTE)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((PBYTE)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16)); + *((PBYTE)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((PBYTE)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16)); + *((PBYTE)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0); + *((PBYTE)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0); + *((PBYTE)(pMICHDR+14)) = HIBYTE(wPayloadLen); + *((PBYTE)(pMICHDR+15)) = LOBYTE(wPayloadLen); + + //Fill MICHDR1 + *((PBYTE)(pMICHDR+16)) = 0; // HLEN[15:8] + if (pDevice->bLongHeader) { + *((PBYTE)(pMICHDR+17)) = 28; // HLEN[7:0] + } else { + *((PBYTE)(pMICHDR+17)) = 22; // HLEN[7:0] + } + wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F); + MEMvCopy(pMICHDR+18, (PBYTE)&wValue, 2); // MSKFRACTL + MEMvCopy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6); + MEMvCopy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6); + + //Fill MICHDR2 + MEMvCopy(pMICHDR+32, &(pMACHeader->abyAddr3[0]), 6); + wValue = pMACHeader->wSeqCtl; + wValue &= 0x000F; + wValue = cpu_to_le16(wValue); + MEMvCopy(pMICHDR+38, (PBYTE)&wValue, 2); // MSKSEQCTL + if (pDevice->bLongHeader) { + MEMvCopy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6); + } + } +} + + +static +VOID +s_vSWencryption ( + IN PSDevice pDevice, + IN PSKeyItem pTransmitKey, + IN PBYTE pbyPayloadHead, + IN WORD wPayloadSize + ) +{ + UINT cbICVlen = 4; + DWORD dwICV = 0xFFFFFFFFL; + PDWORD pdwICV; + + if (pTransmitKey == NULL) + return; + + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + //======================================================================= + // Append ICV after payload + dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) + pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); + // finally, we must invert dwCRC to get the correct answer + *pdwICV = cpu_to_le32(~dwICV); + // RC4 encryption + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3); + rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); + //======================================================================= + } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + //======================================================================= + //Append ICV after payload + dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) + pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); + // finally, we must invert dwCRC to get the correct answer + *pdwICV = cpu_to_le32(~dwICV); + // RC4 encryption + rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); + rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); + //======================================================================= + } +} + + + + +/*byPktTyp : PK_TYPE_11A 0 + PK_TYPE_11B 1 + PK_TYPE_11GB 2 + PK_TYPE_11GA 3 +*/ +static +UINT +s_uGetTxRsvTime ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN UINT cbFrameLength, + IN WORD wRate, + IN BOOL bNeedAck + ) +{ + UINT uDataTime, uAckTime; + + uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, cbFrameLength, wRate); +#ifdef PLICE_DEBUG + //printk("s_uGetTxRsvTime is %d\n",uDataTime); +#endif + if (byPktTyp == PK_TYPE_11B) {//llb,CCK mode + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, (WORD)pDevice->byTopCCKBasicRate); + } else {//11g 2.4G OFDM mode & 11a 5G OFDM mode + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, (WORD)pDevice->byTopOFDMBasicRate); + } + + if (bNeedAck) { + return (uDataTime + pDevice->uSIFS + uAckTime); + } + else { + return uDataTime; + } +} + +//byFreqType: 0=>5GHZ 1=>2.4GHZ +static +UINT +s_uGetRTSCTSRsvTime ( + IN PSDevice pDevice, + IN BYTE byRTSRsvType, + IN BYTE byPktTyp, + IN UINT cbFrameLength, + IN WORD wCurrentRate + ) +{ + UINT uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; + + uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; + + + uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, cbFrameLength, wCurrentRate); + if (byRTSRsvType == 0) { //RTSTxRrvTime_bb + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 20, pDevice->byTopCCKBasicRate); + uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopCCKBasicRate); + } + else if (byRTSRsvType == 1){ //RTSTxRrvTime_ba, only in 2.4GHZ + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 20, pDevice->byTopCCKBasicRate); + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopCCKBasicRate); + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopOFDMBasicRate); + } + else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa + uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 20, pDevice->byTopOFDMBasicRate); + uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopOFDMBasicRate); + } + else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopCCKBasicRate); + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktTyp, 14, pDevice->byTopOFDMBasicRate); + uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS; + return uRrvTime; + } + + //RTSRrvTime + uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS; + return uRrvTime; +} + +//byFreqType 0: 5GHz, 1:2.4Ghz +static +UINT +s_uGetDataDuration ( + IN PSDevice pDevice, + IN BYTE byDurType, + IN UINT cbFrameLength, + IN BYTE byPktType, + IN WORD wRate, + IN BOOL bNeedAck, + IN UINT uFragIdx, + IN UINT cbLastFragmentSize, + IN UINT uMACfragNum, + IN BYTE byFBOption + ) +{ + BOOL bLastFrag = 0; + UINT uAckTime =0, uNextPktTime = 0; + + + + if (uFragIdx == (uMACfragNum-1)) { + bLastFrag = 1; + } + + + switch (byDurType) { + + case DATADUR_B: //DATADUR_B + if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag + if (bNeedAck) { + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else {//First Frag or Mid Frag + if (uFragIdx == (uMACfragNum-2)) { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + } + if (bNeedAck) { + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A: //DATADUR_A + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else {//First Frag or Mid Frag + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + } + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A_F0: //DATADUR_A_F0 + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else { //First Frag or Mid Frag + if (byFBOption == AUTO_FB_0) { + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + } else { // (byFBOption == AUTO_FB_1) + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + } + + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + case DATADUR_A_F1: //DATADUR_A_F1 + if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime); + } else { + return 0; + } + } + else { //First Frag or Mid Frag + if (byFBOption == AUTO_FB_0) { + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + + } else { // (byFBOption == AUTO_FB_1) + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + if(uFragIdx == (uMACfragNum-2)){ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else { + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + } + if(bNeedAck){ + uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + return (pDevice->uSIFS + uAckTime + uNextPktTime); + } else { + return (pDevice->uSIFS + uNextPktTime); + } + } + break; + + default: + break; + } + + ASSERT(FALSE); + return 0; +} + + +//byFreqType: 0=>5GHZ 1=>2.4GHZ +static +UINT +s_uGetRTSCTSDuration ( + IN PSDevice pDevice, + IN BYTE byDurType, + IN UINT cbFrameLength, + IN BYTE byPktType, + IN WORD wRate, + IN BOOL bNeedAck, + IN BYTE byFBOption + ) +{ + UINT uCTSTime = 0, uDurTime = 0; + + + switch (byDurType) { + + case RTSDUR_BB: //RTSDuration_bb + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA: //RTSDuration_ba + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_AA: //RTSDuration_aa + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case CTSDUR_BA: //CTSDuration_ba + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA_F0: //RTSDuration_ba_f0 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_AA_F0: //RTSDuration_aa_f0 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_BA_F1: //RTSDuration_ba_f1 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + case RTSDUR_AA_F1: //RTSDuration_aa_f1 + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + case CTSDUR_BA_F0: //CTSDuration_ba_f0 + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); + } + break; + + case CTSDUR_BA_F1: //CTSDuration_ba_f1 + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); + } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); + } + break; + + default: + break; + } + + return uDurTime; + +} + + + +static +UINT +s_uFillDataHead ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pTxDataHead, + IN UINT cbFrameLength, + IN UINT uDMAIdx, + IN BOOL bNeedAck, + IN UINT uFragIdx, + IN UINT cbLastFragmentSize, + IN UINT uMACfragNum, + IN BYTE byFBOption, + IN WORD wCurrentRate + ) +{ + WORD wLen = 0x0000; + + if (pTxDataHead == NULL) { + return 0; + } + + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + if (byFBOption == AUTO_FB_NONE) { + PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + //Get Duration and TimeStamp + pBuf->wDuration_a = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, + byPktTyp, wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); //1: 2.4GHz + pBuf->wDuration_b = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, + PK_TYPE_11B, pDevice->byTopCCKBasicRate, + bNeedAck, uFragIdx, cbLastFragmentSize, + uMACfragNum, byFBOption)); //1: 2.4 + + pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]); + + return (pBuf->wDuration_a); + } else { + // Auto Fallback + PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + //Get Duration and TimeStamp + pBuf->wDuration_a = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz + pBuf->wDuration_b = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, + pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz + pBuf->wDuration_a_f0 = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz + pBuf->wDuration_a_f1 = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //1: 2.4GHz + + pBuf->wTimeStampOff_a = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + pBuf->wTimeStampOff_b = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]); + + return (pBuf->wDuration_a); + } //if (byFBOption == AUTO_FB_NONE) + } + else if (byPktTyp == PK_TYPE_11A) { + if ((byFBOption != AUTO_FB_NONE)) { + // Auto Fallback + PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration and TimeStampOff + + pBuf->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz + pBuf->wDuration_f0 = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz + pBuf->wDuration_f1 = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); //0: 5GHz + pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + return (pBuf->wDuration); + } else { + PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration and TimeStampOff + + pBuf->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); + + pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + return (pBuf->wDuration); + } + } + else { + PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration and TimeStampOff + pBuf->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktTyp, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); + pBuf->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + return (pBuf->wDuration); + } + return 0; +} + + +static +VOID +s_vFillRTSHead ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pvRTS, + IN UINT cbFrameLength, + IN BOOL bNeedAck, + IN BOOL bDisCRC, + IN PSEthernetHeader psEthHeader, + IN WORD wCurrentRate, + IN BYTE byFBOption + ) +{ + UINT uRTSFrameLen = 20; + WORD wLen = 0x0000; + + // dummy code, only to avoid compiler warning message + UNREFERENCED_PARAMETER(bNeedAck); + + if (pvRTS == NULL) + return; + + if (bDisCRC) { + // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame, + // in this case we need to decrease its length by 4. + uRTSFrameLen -= 4; + } + + // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account. + // Otherwise, we need to modified codes for them. + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + if (byFBOption == AUTO_FB_NONE) { + PSRTS_g pBuf = (PSRTS_g)pvRTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData + pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + + pBuf->Data.wDurationID = pBuf->wDuration_aa; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + } + } + else { + PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) + ); + pBuf->wTransmitLength_a = cpu_to_le16(wLen); + + //Get Duration + pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData + pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData + pBuf->wRTSDuration_ba_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_aa_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_ba_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData + pBuf->wRTSDuration_aa_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData + pBuf->Data.wDurationID = pBuf->wDuration_aa; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + } + + } // if (byFBOption == AUTO_FB_NONE) + } + else if (byPktTyp == PK_TYPE_11A) { + if (byFBOption == AUTO_FB_NONE) { + PSRTS_ab pBuf = (PSRTS_ab)pvRTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + } + + } + else { + PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData + pBuf->wRTSDuration_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData + pBuf->wRTSDuration_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0: + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + } + } + } + else if (byPktTyp == PK_TYPE_11B) { + PSRTS_ab pBuf = (PSRTS_ab)pvRTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) + ); + pBuf->wTransmitLength = cpu_to_le16(wLen); + //Get Duration + pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData + pBuf->Data.wDurationID = pBuf->wDuration; + //Get RTS Frame body + pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 + + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + } + } +} + +static +VOID +s_vFillCTSHead ( + IN PSDevice pDevice, + IN UINT uDMAIdx, + IN BYTE byPktTyp, + IN PVOID pvCTS, + IN UINT cbFrameLength, + IN BOOL bNeedAck, + IN BOOL bDisCRC, + IN WORD wCurrentRate, + IN BYTE byFBOption + ) +{ + UINT uCTSFrameLen = 14; + WORD wLen = 0x0000; + + if (pvCTS == NULL) { + return; + } + + if (bDisCRC) { + // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame, + // in this case we need to decrease its length by 4. + uCTSFrameLen -= 4; + } + + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) { + // Auto Fall back + PSCTS_FB pBuf = (PSCTS_FB)pvCTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + + + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + + pBuf->wDuration_ba = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wDuration_ba += pDevice->wCTSDuration; + pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); + //Get CTSDuration_ba_f0 + pBuf->wCTSDuration_ba_f0 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration; + pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0); + //Get CTSDuration_ba_f1 + pBuf->wCTSDuration_ba_f1 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration; + pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1); + //Get CTS Frame body + pBuf->Data.wDurationID = pBuf->wDuration_ba; + pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 + pBuf->Data.wReserved = 0x0000; + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), U_ETHER_ADDR_LEN); + + } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) + PSCTS pBuf = (PSCTS)pvCTS; + //Get SignalField,ServiceField,Length + BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, + (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) + ); + pBuf->wTransmitLength_b = cpu_to_le16(wLen); + //Get CTSDuration_ba + pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktTyp, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data + pBuf->wDuration_ba += pDevice->wCTSDuration; + pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); + + //Get CTS Frame body + pBuf->Data.wDurationID = pBuf->wDuration_ba; + pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 + pBuf->Data.wReserved = 0x0000; + MEMvCopy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), U_ETHER_ADDR_LEN); + } + } +} + + + + + + +/*+ + * + * Description: + * Generate FIFO control for MAC & Baseband controller + * + * Parameters: + * In: + * pDevice - Pointer to adpater + * pTxDataHead - Transmit Data Buffer + * pTxBufHead - pTxBufHead + * pvRrvTime - pvRrvTime + * pvRTS - RTS Buffer + * pCTS - CTS Buffer + * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) + * bNeedACK - If need ACK + * uDescIdx - Desc Index + * Out: + * none + * + * Return Value: none + * +-*/ +// UINT cbFrameSize,//Hdr+Payload+FCS +static +VOID +s_vGenerateTxParameter ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PVOID pTxBufHead, + IN PVOID pvRrvTime, + IN PVOID pvRTS, + IN PVOID pvCTS, + IN UINT cbFrameSize, + IN BOOL bNeedACK, + IN UINT uDMAIdx, + IN PSEthernetHeader psEthHeader, + IN WORD wCurrentRate + ) +{ + UINT cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24 + WORD wFifoCtl; + BOOL bDisCRC = FALSE; + BYTE byFBOption = AUTO_FB_NONE; +// WORD wCurrentRate = pDevice->wCurrentRate; + + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n"); + PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead; + pFifoHead->wReserved = wCurrentRate; + wFifoCtl = pFifoHead->wFIFOCtl; + + if (wFifoCtl & FIFOCTL_CRCDIS) { + bDisCRC = TRUE; + } + + if (wFifoCtl & FIFOCTL_AUTO_FB_0) { + byFBOption = AUTO_FB_0; + } + else if (wFifoCtl & FIFOCTL_AUTO_FB_1) { + byFBOption = AUTO_FB_1; + } + + if (pDevice->bLongHeader) + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; + + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + + if (pvRTS != NULL) { //RTS_need + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime; + pBuf->wRTSTxRrvTime_aa = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktTyp, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz + pBuf->wRTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 1, byPktTyp, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz + pBuf->wRTSTxRrvTime_bb = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktTyp, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz + pBuf->wTxRrvTime_a = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, byPktTyp, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM + pBuf->wTxRrvTime_b = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktTyp, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else {//RTS_needless, PCF mode + + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime; + pBuf->wTxRrvTime_a = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktTyp, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM + pBuf->wTxRrvTime_b = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK + pBuf->wCTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 3, byPktTyp, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz + } + + + //Fill CTS + s_vFillCTSHead(pDevice, uDMAIdx, byPktTyp, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); + } + } + else if (byPktTyp == PK_TYPE_11A) { + + if (pvRTS != NULL) {//RTS_need, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktTyp, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz + pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktTyp, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktTyp, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else if (pvRTS == NULL) {//RTS_needless, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM + } + } + } + else if (byPktTyp == PK_TYPE_11B) { + + if ((pvRTS != NULL)) {//RTS_need, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktTyp, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz + pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK + } + //Fill RTS + s_vFillRTSHead(pDevice, byPktTyp, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } + else { //RTS_needless, non PCF mode + //Fill RsvTime + if (pvRrvTime) { + PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; + pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK + } + } + } + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n"); +} +/* + PBYTE pbyBuffer,//point to pTxBufHead + WORD wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last + UINT cbFragmentSize,//Hdr+payoad+FCS +*/ +static +VOID +s_vFillFragParameter( + IN PSDevice pDevice, + IN PBYTE pbyBuffer, + IN UINT uTxType, + IN PVOID pvtdCurr, + IN WORD wFragType, + IN UINT cbReqCount + ) +{ + PSTxBufHead pTxBufHead = (PSTxBufHead) pbyBuffer; + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vFillFragParameter...\n"); + + if (uTxType == TYPE_SYNCDMA) { + //PSTxSyncDesc ptdCurr = (PSTxSyncDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx); + PSTxSyncDesc ptdCurr = (PSTxSyncDesc)pvtdCurr; + + //Set FIFOCtl & TimeStamp in TxSyncDesc + ptdCurr->m_wFIFOCtl = pTxBufHead->wFIFOCtl; + ptdCurr->m_wTimeStamp = pTxBufHead->wTimeStamp; + //Set TSR1 & ReqCount in TxDescHead + ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((WORD)(cbReqCount)); + if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation + ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU); + } + else { + ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP); + } + } + else { + //PSTxDesc ptdCurr = (PSTxDesc)s_pvGetTxDescHead(pDevice, uTxType, uCurIdx); + PSTxDesc ptdCurr = (PSTxDesc)pvtdCurr; + //Set TSR1 & ReqCount in TxDescHead + ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((WORD)(cbReqCount)); + if (wFragType == FRAGCTL_ENDFRAG) { //Last Fragmentation + ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU); + } + else { + ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP); + } + } + + pTxBufHead->wFragCtl |= (WORD)wFragType;//0x0001; //0000 0000 0000 0001 + + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vFillFragParameter END\n"); +} + +static +UINT +s_cbFillTxBufHead ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PBYTE pbyTxBufferAddr, + IN UINT cbFrameBodySize, + IN UINT uDMAIdx, + IN PSTxDesc pHeadTD, + IN PSEthernetHeader psEthHeader, + IN PBYTE pPacket, + IN BOOL bNeedEncrypt, + IN PSKeyItem pTransmitKey, + IN UINT uNodeIndex, + OUT PUINT puMACfragNum + ) +{ + UINT cbMACHdLen; + UINT cbFrameSize; + UINT cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + UINT cbFragPayloadSize; + UINT cbLastFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + UINT cbLastFragPayloadSize; + UINT uFragIdx; + PBYTE pbyPayloadHead; + PBYTE pbyIVHead; + PBYTE pbyMacHdr; + WORD wFragType; //00:Non-Frag, 01:Start, 10:Mid, 11:Last + UINT uDuration; + PBYTE pbyBuffer; +// UINT uKeyEntryIdx = NUM_KEY_ENTRY+1; +// BYTE byKeySel = 0xFF; + UINT cbIVlen = 0; + UINT cbICVlen = 0; + UINT cbMIClen = 0; + UINT cbFCSlen = 4; + UINT cb802_1_H_len = 0; + UINT uLength = 0; + UINT uTmpLen = 0; +// BYTE abyTmp[8]; +// DWORD dwCRC; + UINT cbMICHDR = 0; + DWORD dwMICKey0, dwMICKey1; + DWORD dwMIC_Priority; + PDWORD pdwMIC_L; + PDWORD pdwMIC_R; + DWORD dwSafeMIC_L, dwSafeMIC_R; //Fix "Last Frag Size" < "MIC length". + BOOL bMIC2Frag = FALSE; + UINT uMICFragLen = 0; + UINT uMACfragNum = 1; + UINT uPadding = 0; + UINT cbReqCount = 0; + + BOOL bNeedACK; + BOOL bRTS; + BOOL bIsAdhoc; + PBYTE pbyType; + PSTxDesc ptdCurr; + PSTxBufHead psTxBufHd = (PSTxBufHead) pbyTxBufferAddr; +// UINT tmpDescIdx; + UINT cbHeaderLength = 0; + PVOID pvRrvTime; + PSMICHDRHead pMICHDR; + PVOID pvRTS; + PVOID pvCTS; + PVOID pvTxDataHd; + WORD wTxBufSize; // FFinfo size + UINT uTotalCopyLength = 0; + BYTE byFBOption = AUTO_FB_NONE; + BOOL bIsWEP256 = FALSE; + PSMgmtObject pMgmt = pDevice->pMgmt; + + + pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; + + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_cbFillTxBufHead...\n"); + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + + if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + bNeedACK = FALSE; + } + else { + bNeedACK = TRUE; + } + bIsAdhoc = TRUE; + } + else { + // MSDUs in Infra mode always need ACK + bNeedACK = TRUE; + bIsAdhoc = FALSE; + } + + if (pDevice->bLongHeader) + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; + else + cbMACHdLen = WLAN_HDR_ADDR3_LEN; + + + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL)) { + if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + cbIVlen = 4; + cbICVlen = 4; + if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN) { + bIsWEP256 = TRUE; + } + } + if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + } + if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + cbMICHDR = sizeof(SMICHDRHead); + } + if (pDevice->byLocalID > REV_ID_VT3253_A1) { + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMACHdLen%4); + uPadding %= 4; + } + } + + + cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen; + + if ((bNeedACK == FALSE) || + (cbFrameSize < pDevice->wRTSThreshold) || + ((cbFrameSize >= pDevice->wFragmentationThreshold) && (pDevice->wFragmentationThreshold <= pDevice->wRTSThreshold)) + ) { + bRTS = FALSE; + } + else { + bRTS = TRUE; + psTxBufHd->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY); + } + // + // Use for AUTO FALL BACK + // + if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_0) { + byFBOption = AUTO_FB_0; + } + else if (psTxBufHd->wFIFOCtl & FIFOCTL_AUTO_FB_1) { + byFBOption = AUTO_FB_1; + } + + ////////////////////////////////////////////////////// + //Set RrvTime/RTS/CTS Buffer + wTxBufSize = sizeof(STxBufHead); + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) {//802.11g packet + + if (byFBOption == AUTO_FB_NONE) { + if (bRTS == TRUE) {//RTS_need + pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); + pvRTS = (PSRTS_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g) + sizeof(STxDataHead_g); + } + else { //RTS_needless + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); + } + } else { + // Auto Fall Back + if (bRTS == TRUE) {//RTS_need + pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); + pvRTS = (PSRTS_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB) + sizeof(STxDataHead_g_FB); + } + else { //RTS_needless + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB)); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB) + sizeof(STxDataHead_g_FB); + } + } // Auto Fall Back + } + else {//802.11a/b packet + + if (byFBOption == AUTO_FB_NONE) { + if (bRTS == TRUE) { + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = (PSRTS_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab)); + cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab) + sizeof(STxDataHead_ab); + } + else { //RTS_needless, need MICHDR + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); + } + } else { + // Auto Fall Back + if (bRTS == TRUE) {//RTS_need + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = (PSRTS_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB)); + cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB) + sizeof(STxDataHead_a_FB); + } + else { //RTS_needless + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_a_FB); + } + } // Auto Fall Back + } + ZERO_MEMORY((PVOID)(pbyTxBufferAddr + wTxBufSize), (cbHeaderLength - wTxBufSize)); + +////////////////////////////////////////////////////////////////// + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + if (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + } + else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) { + dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + } + else { + dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[24]); + dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[28]); + } + // DO Software Michael + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + } + +/////////////////////////////////////////////////////////////////// + + pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderLength); + pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen); + pbyIVHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding); + + if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == TRUE) && (bIsWEP256 == FALSE)) { + // Fragmentation + // FragThreshold = Fragment size(Hdr+(IV)+fragment payload+(MIC)+(ICV)+FCS) + cbFragmentSize = pDevice->wFragmentationThreshold; + cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen; + //FragNum = (FrameSize-(Hdr+FCS))/(Fragment Size -(Hrd+FCS))) + uMACfragNum = (WORD) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize); + cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize; + if (cbLastFragPayloadSize == 0) { + cbLastFragPayloadSize = cbFragPayloadSize; + } else { + uMACfragNum++; + } + //[Hdr+(IV)+last fragment payload+(MIC)+(ICV)+FCS] + cbLastFragmentSize = cbMACHdLen + cbLastFragPayloadSize + cbIVlen + cbICVlen + cbFCSlen; + + for (uFragIdx = 0; uFragIdx < uMACfragNum; uFragIdx ++) { + if (uFragIdx == 0) { + //========================= + // Start Fragmentation + //========================= + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Start Fragmentation...\n"); + wFragType = FRAGCTL_STAFRAG; + + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, (PVOID)psTxBufHd, pvRrvTime, pvRTS, pvCTS, + cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate); + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK, + uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate); + // Generate TX MAC Header + vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncrypt, + wFragType, uDMAIdx, uFragIdx); + + if (bNeedEncrypt == TRUE) { + //Fill TXKEY + s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFragPayloadSize, (PBYTE)pMICHDR); + //Fill IV(ExtIV,RSNHDR) + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + } + + + // 802.1H + if (ntohs(psEthHeader->wType) > MAX_DATA_LEN) { + if ((psEthHeader->wType == TYPE_PKT_IPX) || + (psEthHeader->wType == cpu_to_le16(0xF380))) { + MEMvCopy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); + } + else { + MEMvCopy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); + } + pbyType = (PBYTE) (pbyPayloadHead + 6); + MEMvCopy(pbyType, &(psEthHeader->wType), sizeof(WORD)); + cb802_1_H_len = 8; + } + + cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize; + //--------------------------- + // S/W or H/W Encryption + //--------------------------- + //Fill MICHDR + //if (pDevice->bAES) { + // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); + //} + //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (PVOID)psTxBufHd, byKeySel, + // pbyPayloadHead, (WORD)cbFragPayloadSize, uDMAIdx); + + + + //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; + pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; + + uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len; + //copy TxBufferHeader + MacHeader to desc + MEMvCopy(pbyBuffer, (PVOID)psTxBufHd, uLength); + + // Copy the Packet into a tx Buffer + MEMvCopy((pbyBuffer + uLength), (pPacket + 14), (cbFragPayloadSize - cb802_1_H_len)); + + + uTotalCopyLength += cbFragPayloadSize - cb802_1_H_len; + + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Start MIC: %d\n", cbFragPayloadSize); + MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFragPayloadSize); + + } + + //--------------------------- + // S/W Encryption + //--------------------------- + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { + if (bNeedEncrypt) { + s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len), (WORD)cbFragPayloadSize); + cbReqCount += cbICVlen; + } + } + + ptdCurr = (PSTxDesc)pHeadTD; + //-------------------- + //1.Set TSR1 & ReqCount in TxDescHead + //2.Set FragCtl in TxBufferHead + //3.Set Frame Control + //4.Set Sequence Control + //5.Get S/W generate FCS + //-------------------- + s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (PVOID)ptdCurr, wFragType, cbReqCount); + + ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding; + ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; + ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; + ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); + pDevice->iTDUsed[uDMAIdx]++; + pHeadTD = ptdCurr->next; + } + else if (uFragIdx == (uMACfragNum-1)) { + //========================= + // Last Fragmentation + //========================= + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last Fragmentation...\n"); + //tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx]; + + wFragType = FRAGCTL_ENDFRAG; + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, (PVOID)psTxBufHd, pvRrvTime, pvRTS, pvCTS, + cbLastFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate); + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbLastFragmentSize, uDMAIdx, bNeedACK, + uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate); + + // Generate TX MAC Header + vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncrypt, + wFragType, uDMAIdx, uFragIdx); + + if (bNeedEncrypt == TRUE) { + //Fill TXKEY + s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbLastFragPayloadSize, (PBYTE)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + + } + + + cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbLastFragPayloadSize; + //--------------------------- + // S/W or H/W Encryption + //--------------------------- + + + + pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; + //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; + + uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen; + + //copy TxBufferHeader + MacHeader to desc + MEMvCopy(pbyBuffer, (PVOID)psTxBufHd, uLength); + + // Copy the Packet into a tx Buffer + if (bMIC2Frag == FALSE) { + + MEMvCopy((pbyBuffer + uLength), + (pPacket + 14 + uTotalCopyLength), + (cbLastFragPayloadSize - cbMIClen) + ); + //TODO check uTmpLen ! + uTmpLen = cbLastFragPayloadSize - cbMIClen; + + } + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen:%d, cbLastFragPayloadSize:%d, uTmpLen:%d\n", + uMICFragLen, cbLastFragPayloadSize, uTmpLen); + + if (bMIC2Frag == FALSE) { + if (uTmpLen != 0) + MIC_vAppend((pbyBuffer + uLength), uTmpLen); + pdwMIC_L = (PDWORD)(pbyBuffer + uLength + uTmpLen); + pdwMIC_R = (PDWORD)(pbyBuffer + uLength + uTmpLen + 4); + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Last MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); + } else { + if (uMICFragLen >= 4) { + MEMvCopy((pbyBuffer + uLength), ((PBYTE)&dwSafeMIC_R + (uMICFragLen - 4)), + (cbMIClen - uMICFragLen)); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen >= 4: %X, %d\n", + *(PBYTE)((PBYTE)&dwSafeMIC_R + (uMICFragLen - 4)), + (cbMIClen - uMICFragLen)); + + } else { + MEMvCopy((pbyBuffer + uLength), ((PBYTE)&dwSafeMIC_L + uMICFragLen), + (4 - uMICFragLen)); + MEMvCopy((pbyBuffer + uLength + (4 - uMICFragLen)), &dwSafeMIC_R, 4); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"LAST: uMICFragLen < 4: %X, %d\n", + *(PBYTE)((PBYTE)&dwSafeMIC_R + uMICFragLen - 4), + (cbMIClen - uMICFragLen)); + } + /* + for (ii = 0; ii < cbLastFragPayloadSize + 8 + 24; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii - 8 - 24))); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n"); + */ + } + MIC_vUnInit(); + } else { + ASSERT(uTmpLen == (cbLastFragPayloadSize - cbMIClen)); + } + + + //--------------------------- + // S/W Encryption + //--------------------------- + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { + if (bNeedEncrypt) { + s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (WORD)cbLastFragPayloadSize); + cbReqCount += cbICVlen; + } + } + + ptdCurr = (PSTxDesc)pHeadTD; + + //-------------------- + //1.Set TSR1 & ReqCount in TxDescHead + //2.Set FragCtl in TxBufferHead + //3.Set Frame Control + //4.Set Sequence Control + //5.Get S/W generate FCS + //-------------------- + + + s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (PVOID)ptdCurr, wFragType, cbReqCount); + + ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding; + ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; + ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; + ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); + pDevice->iTDUsed[uDMAIdx]++; + pHeadTD = ptdCurr->next; + + } + else { + //========================= + // Middle Fragmentation + //========================= + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Middle Fragmentation...\n"); + //tmpDescIdx = (uDescIdx + uFragIdx) % pDevice->cbTD[uDMAIdx]; + + wFragType = FRAGCTL_MIDFRAG; + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, (PVOID)psTxBufHd, pvRrvTime, pvRTS, pvCTS, + cbFragmentSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate); + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbFragmentSize, uDMAIdx, bNeedACK, + uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption, pDevice->wCurrentRate); + + // Generate TX MAC Header + vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncrypt, + wFragType, uDMAIdx, uFragIdx); + + + if (bNeedEncrypt == TRUE) { + //Fill TXKEY + s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFragPayloadSize, (PBYTE)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + } + + cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cbFragPayloadSize; + //--------------------------- + // S/W or H/W Encryption + //--------------------------- + //Fill MICHDR + //if (pDevice->bAES) { + // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFragPayloadSize); + //} + //cbReqCount += s_uDoEncryption(pDevice, psEthHeader, (PVOID)psTxBufHd, byKeySel, + // pbyPayloadHead, (WORD)cbFragPayloadSize, uDMAIdx); + + + pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; + //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][tmpDescIdx].pbyVAddr; + + + uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen; + + //copy TxBufferHeader + MacHeader to desc + MEMvCopy(pbyBuffer, (PVOID)psTxBufHd, uLength); + + // Copy the Packet into a tx Buffer + MEMvCopy((pbyBuffer + uLength), + (pPacket + 14 + uTotalCopyLength), + cbFragPayloadSize + ); + uTmpLen = cbFragPayloadSize; + + uTotalCopyLength += uTmpLen; + + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + + MIC_vAppend((pbyBuffer + uLength), uTmpLen); + + if (uTmpLen < cbFragPayloadSize) { + bMIC2Frag = TRUE; + uMICFragLen = cbFragPayloadSize - uTmpLen; + ASSERT(uMICFragLen < cbMIClen); + + pdwMIC_L = (PDWORD)(pbyBuffer + uLength + uTmpLen); + pdwMIC_R = (PDWORD)(pbyBuffer + uLength + uTmpLen + 4); + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + dwSafeMIC_L = *pdwMIC_L; + dwSafeMIC_R = *pdwMIC_R; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIDDLE: uMICFragLen:%d, cbFragPayloadSize:%d, uTmpLen:%d\n", + uMICFragLen, cbFragPayloadSize, uTmpLen); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MIC in Middle frag [%d]\n", uMICFragLen); + /* + for (ii = 0; ii < uMICFragLen; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength + uTmpLen) + ii))); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + */ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Middle frag len: %d\n", uTmpLen); + /* + for (ii = 0; ii < uTmpLen; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii))); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n\n"); + */ + + } else { + ASSERT(uTmpLen == (cbFragPayloadSize)); + } + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { + if (bNeedEncrypt) { + s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength), (WORD)cbFragPayloadSize); + cbReqCount += cbICVlen; + } + } + + ptdCurr = (PSTxDesc)pHeadTD; + + //-------------------- + //1.Set TSR1 & ReqCount in TxDescHead + //2.Set FragCtl in TxBufferHead + //3.Set Frame Control + //4.Set Sequence Control + //5.Get S/W generate FCS + //-------------------- + + s_vFillFragParameter(pDevice, pbyBuffer, uDMAIdx, (PVOID)ptdCurr, wFragType, cbReqCount); + + ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding; + ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; + ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; + ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); + pDevice->iTDUsed[uDMAIdx]++; + pHeadTD = ptdCurr->next; + } + } // for (uMACfragNum) + } + else { + //========================= + // No Fragmentation + //========================= + //DEVICE_PRTGRP03(("No Fragmentation...\n")); + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n"); + wFragType = FRAGCTL_NONFRAG; + + //Set FragCtl in TxBufferHead + psTxBufHd->wFragCtl |= (WORD)wFragType; + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, (PVOID)psTxBufHd, pvRrvTime, pvRTS, pvCTS, + cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, pDevice->wCurrentRate); + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, + 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate); + + // Generate TX MAC Header + vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncrypt, + wFragType, uDMAIdx, 0); + + if (bNeedEncrypt == TRUE) { + //Fill TXKEY + s_vFillTxKey(pDevice, (PBYTE)(psTxBufHd->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + } + + // 802.1H + if (ntohs(psEthHeader->wType) > MAX_DATA_LEN) { + if ((psEthHeader->wType == TYPE_PKT_IPX) || + (psEthHeader->wType == cpu_to_le16(0xF380))) { + MEMvCopy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_Bridgetunnel[0], 6); + } + else { + MEMvCopy((PBYTE) (pbyPayloadHead), &pDevice->abySNAP_RFC1042[0], 6); + } + pbyType = (PBYTE) (pbyPayloadHead + 6); + MEMvCopy(pbyType, &(psEthHeader->wType), sizeof(WORD)); + cb802_1_H_len = 8; + } + + cbReqCount = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen); + //--------------------------- + // S/W or H/W Encryption + //--------------------------- + //Fill MICHDR + //if (pDevice->bAES) { + // DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Fill MICHDR...\n"); + // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, pbyMacHdr, (WORD)cbFrameBodySize); + //} + + pbyBuffer = (PBYTE)pHeadTD->pTDInfo->buf; + //pbyBuffer = (PBYTE)pDevice->aamTxBuf[uDMAIdx][uDescIdx].pbyVAddr; + + uLength = cbHeaderLength + cbMACHdLen + uPadding + cbIVlen + cb802_1_H_len; + + //copy TxBufferHeader + MacHeader to desc + MEMvCopy(pbyBuffer, (PVOID)psTxBufHd, uLength); + + // Copy the Packet into a tx Buffer + MEMvCopy((pbyBuffer + uLength), + (pPacket + 14), + cbFrameBodySize - cb802_1_H_len + ); + + if ((bNeedEncrypt == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)){ + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Length:%d, %d\n", cbFrameBodySize - cb802_1_H_len, uLength); + /* + for (ii = 0; ii < (cbFrameBodySize - cb802_1_H_len); ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *((PBYTE)((pbyBuffer + uLength) + ii))); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + */ + + MIC_vAppend((pbyBuffer + uLength - cb802_1_H_len), cbFrameBodySize); + + pdwMIC_L = (PDWORD)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize); + pdwMIC_R = (PDWORD)(pbyBuffer + uLength - cb802_1_H_len + cbFrameBodySize + 4); + + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + MIC_vUnInit(); + + + if (pDevice->bTxMICFail == TRUE) { + *pdwMIC_L = 0; + *pdwMIC_R = 0; + pDevice->bTxMICFail = FALSE; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); +/* + for (ii = 0; ii < 8; ii++) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%02x ", *(((PBYTE)(pdwMIC_L) + ii))); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); +*/ + + } + + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)){ + if (bNeedEncrypt) { + s_vSWencryption(pDevice, pTransmitKey, (pbyBuffer + uLength - cb802_1_H_len), + (WORD)(cbFrameBodySize + cbMIClen)); + cbReqCount += cbICVlen; + } + } + + + ptdCurr = (PSTxDesc)pHeadTD; + + ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding; + ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; + ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; + ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); + //Set TSR1 & ReqCount in TxDescHead + ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU); + ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((WORD)(cbReqCount)); + + pDevice->iTDUsed[uDMAIdx]++; + + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" ptdCurr->m_dwReserved0[%d] ptdCurr->m_dwReserved1[%d].\n", ptdCurr->pTDInfo->dwReqCount, ptdCurr->pTDInfo->dwHeaderLength); +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cbHeaderLength[%d]\n", cbHeaderLength); + + } + *puMACfragNum = uMACfragNum; + //DEVICE_PRTGRP03(("s_cbFillTxBufHead END\n")); + return cbHeaderLength; +} + + +VOID +vGenerateFIFOHeader ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PBYTE pbyTxBufferAddr, + IN BOOL bNeedEncrypt, + IN UINT cbPayloadSize, + IN UINT uDMAIdx, + IN PSTxDesc pHeadTD, + IN PSEthernetHeader psEthHeader, + IN PBYTE pPacket, + IN PSKeyItem pTransmitKey, + IN UINT uNodeIndex, + OUT PUINT puMACfragNum, + OUT PUINT pcbHeaderSize + ) +{ + UINT wTxBufSize; // FFinfo size + BOOL bNeedACK; + BOOL bIsAdhoc; + WORD cbMacHdLen; + PSTxBufHead pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; + + wTxBufSize = sizeof(STxBufHead); + + ZERO_MEMORY(pTxBufHead, wTxBufSize); + //Set FIFOCTL_NEEDACK + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + bNeedACK = FALSE; + pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); + } + else { + bNeedACK = TRUE; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + } + bIsAdhoc = TRUE; + } + else { + // MSDUs in Infra mode always need ACK + bNeedACK = TRUE; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + bIsAdhoc = FALSE; + } + + + pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; + pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); + + //Set FIFOCTL_LHEAD + if (pDevice->bLongHeader) + pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD; + + //Set FIFOCTL_GENINT + + pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT; + + + //Set FIFOCTL_ISDMA0 + if (TYPE_TXDMA0 == uDMAIdx) { + pTxBufHead->wFIFOCtl |= FIFOCTL_ISDMA0; + } + + //Set FRAGCTL_MACHDCNT + if (pDevice->bLongHeader) { + cbMacHdLen = WLAN_HDR_ADDR3_LEN + 6; + } else { + cbMacHdLen = WLAN_HDR_ADDR3_LEN; + } + pTxBufHead->wFragCtl |= cpu_to_le16((WORD)(cbMacHdLen << 10)); + + //Set packet type + if (byPktTyp == PK_TYPE_11A) {//0000 0000 0000 0000 + ; + } + else if (byPktTyp == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + } + else if (byPktTyp == PK_TYPE_11GB) {//0000 0010 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; + } + else if (byPktTyp == PK_TYPE_11GA) {//0000 0011 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; + } + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + + //Set Auto Fallback Ctl + if (pDevice->wCurrentRate >= RATE_18M) { + if (pDevice->byAutoFBCtrl == AUTO_FB_0) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0; + } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1; + } + } + + //Set FRAGCTL_WEPTYP + pDevice->bAES = FALSE; + + //Set FRAGCTL_WEPTYP + if (pDevice->byLocalID > REV_ID_VT3253_A1) { + if ((bNeedEncrypt) && (pTransmitKey != NULL)) { //WEP enabled + if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + } + else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104 + if (pTransmitKey->uKeyLength != WLAN_WEP232_KEYLEN) + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP + pTxBufHead->wFragCtl |= FRAGCTL_AES; + } + } + } + +#ifdef PLICE_DEBUG + //printk("Func:vGenerateFIFOHeader:TxDataRate is %d,TxPower is %d\n",pDevice->wCurrentRate,pDevice->byCurPwr); + + //if (pDevice->wCurrentRate <= 3) + //{ + // RFbRawSetPower(pDevice,36,pDevice->wCurrentRate); + //} + //else + + RFbSetPower(pDevice, pDevice->wCurrentRate, pDevice->byCurrentCh); +#endif + //if (pDevice->wCurrentRate == 3) + //pDevice->byCurPwr = 46; + pTxBufHead->byTxPower = pDevice->byCurPwr; + + + + +/* + if(pDevice->bEnableHostWEP) + pTxBufHead->wFragCtl &= ~(FRAGCTL_TKIP | FRAGCTL_LEGACY |FRAGCTL_AES); +*/ + *pcbHeaderSize = s_cbFillTxBufHead(pDevice, byPktTyp, pbyTxBufferAddr, cbPayloadSize, + uDMAIdx, pHeadTD, psEthHeader, pPacket, bNeedEncrypt, + pTransmitKey, uNodeIndex, puMACfragNum); + + return; +} + + + + +/*+ + * + * Description: + * Translate 802.3 to 802.11 header + * + * Parameters: + * In: + * pDevice - Pointer to adpater + * dwTxBufferAddr - Transmit Buffer + * pPacket - Packet from upper layer + * cbPacketSize - Transmit Data Length + * Out: + * pcbHeadSize - Header size of MAC&Baseband control and 802.11 Header + * pcbAppendPayload - size of append payload for 802.1H translation + * + * Return Value: none + * +-*/ + +VOID +vGenerateMACHeader ( + IN PSDevice pDevice, + IN PBYTE pbyBufferAddr, + IN WORD wDuration, + IN PSEthernetHeader psEthHeader, + IN BOOL bNeedEncrypt, + IN WORD wFragType, + IN UINT uDMAIdx, + IN UINT uFragIdx + ) +{ + PS802_11Header pMACHeader = (PS802_11Header)pbyBufferAddr; + + ZERO_MEMORY(pMACHeader, (sizeof(S802_11Header))); //- sizeof(pMACHeader->dwIV))); + + if (uDMAIdx == TYPE_ATIMDMA) { + pMACHeader->wFrameCtl = TYPE_802_11_ATIM; + } else { + pMACHeader->wFrameCtl = TYPE_802_11_DATA; + } + + if (pDevice->eOPMode == OP_MODE_AP) { + MEMvCopy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr2[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + pMACHeader->wFrameCtl |= FC_FROMDS; + } + else { + if (pDevice->eOPMode == OP_MODE_ADHOC) { + MEMvCopy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr3[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + } + else { + MEMvCopy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(pMACHeader->abyAddr1[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); + pMACHeader->wFrameCtl |= FC_TODS; + } + } + + if (bNeedEncrypt) + pMACHeader->wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_ISWEP(1)); + + pMACHeader->wDurationID = cpu_to_le16(wDuration); + + if (pDevice->bLongHeader) { + PWLAN_80211HDR_A4 pMACA4Header = (PWLAN_80211HDR_A4) pbyBufferAddr; + pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS); + MEMvCopy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN); + } + pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); + + //Set FragNumber in Sequence Control + pMACHeader->wSeqCtl |= cpu_to_le16((WORD)uFragIdx); + + if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) { + pDevice->wSeqCounter++; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + } + + if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag + pMACHeader->wFrameCtl |= FC_MOREFRAG; + } +} + + + + + + +CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { + + PSTxDesc pFrstTD; + BYTE byPktTyp; + PBYTE pbyTxBufferAddr; + PVOID pvRTS; + PSCTS pCTS; + PVOID pvTxDataHd; + UINT uDuration; + UINT cbReqCount; + PS802_11Header pMACHeader; + UINT cbHeaderSize; + UINT cbFrameBodySize; + BOOL bNeedACK; + BOOL bIsPSPOLL = FALSE; + PSTxBufHead pTxBufHead; + UINT cbFrameSize; + UINT cbIVlen = 0; + UINT cbICVlen = 0; + UINT cbMIClen = 0; + UINT cbFCSlen = 4; + UINT uPadding = 0; + WORD wTxBufSize; + UINT cbMacHdLen; + SEthernetHeader sEthHeader; + PVOID pvRrvTime; + PVOID pMICHDR; + PSMgmtObject pMgmt = pDevice->pMgmt; + WORD wCurrentRate = RATE_1M; + + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) { + return CMD_STATUS_RESOURCES; + } + + pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0]; + pbyTxBufferAddr = (PBYTE)pFrstTD->pTDInfo->buf; + cbFrameBodySize = pPacket->cbPayloadLen; + pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; + wTxBufSize = sizeof(STxBufHead); + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + wCurrentRate = RATE_6M; + byPktTyp = PK_TYPE_11A; + } else { + wCurrentRate = RATE_1M; + byPktTyp = PK_TYPE_11B; + } + + // SetPower will cause error power TX state for OFDM Date packet in TX buffer. + // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. + // And cmd timer will wait data pkt TX finish before scanning so it's OK + // to set power here. + if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) { + + RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); + } else { + RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); + } + pTxBufHead->byTxPower = pDevice->byCurPwr; + //+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++ + if (pDevice->byFOETuning) { + if ((pPacket->p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) { + wCurrentRate = RATE_24M; + byPktTyp = PK_TYPE_11GA; + } + } + + //Set packet type + if (byPktTyp == PK_TYPE_11A) {//0000 0000 0000 0000 + pTxBufHead->wFIFOCtl = 0; + } + else if (byPktTyp == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + } + else if (byPktTyp == PK_TYPE_11GB) {//0000 0010 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; + } + else if (byPktTyp == PK_TYPE_11GA) {//0000 0011 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; + } + + pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; + pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); + + + if (IS_MULTICAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0])) || + IS_BROADCAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0]))) { + bNeedACK = FALSE; + } + else { + bNeedACK = TRUE; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + }; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { + + pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; + //Set Preamble type always long + //pDevice->byPreambleType = PREAMBLE_LONG; + // probe-response don't retry + //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { + // bNeedACK = FALSE; + // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); + //} + } + + pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); + + if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { + bIsPSPOLL = TRUE; + cbMacHdLen = WLAN_HDR_ADDR2_LEN; + } else { + cbMacHdLen = WLAN_HDR_ADDR3_LEN; + } + + //Set FRAGCTL_MACHDCNT + pTxBufHead->wFragCtl |= cpu_to_le16((WORD)(cbMacHdLen << 10)); + + // Notes: + // Although spec says MMPDU can be fragmented; In most case, + // no one will send a MMPDU under fragmentation. With RTS may occur. + pDevice->bAES = FALSE; //Set FRAGCTL_WEPTYP + + if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { + cbIVlen = 4; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + //We need to get seed here for filling TxKey entry. + //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + pTxBufHead->wFragCtl |= FRAGCTL_AES; + pDevice->bAES = TRUE; + } + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMacHdLen%4); + uPadding %= 4; + } + + cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen; + + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() + + //Set RrvTime/RTS/CTS Buffer + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) {//802.11g packet + + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = NULL; + pvRTS = NULL; + pCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS) + sizeof(STxDataHead_g); + } + else { // 802.11a/b packet + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = NULL; + pvRTS = NULL; + pCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + sizeof(STxDataHead_ab); + } + + ZERO_MEMORY((PVOID)(pbyTxBufferAddr + wTxBufSize), (cbHeaderSize - wTxBufSize)); + + MEMvCopy(&(sEthHeader.abyDstAddr[0]), &(pPacket->p80211Header->sA3.abyAddr1[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(sEthHeader.abySrcAddr[0]), &(pPacket->p80211Header->sA3.abyAddr2[0]), U_ETHER_ADDR_LEN); + //========================= + // No Fragmentation + //========================= + pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG; + + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS, + cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate); + + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, + 0, 0, 1, AUTO_FB_NONE, wCurrentRate); + + pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize); + + cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize; + + if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { + PBYTE pbyIVHead; + PBYTE pbyPayloadHead; + PBYTE pbyBSSID; + PSKeyItem pTransmitKey = NULL; + + pbyIVHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding); + pbyPayloadHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen); + + //Fill TXKEY + //Kyle: Need fix: TKIP and AES did't encryt Mnt Packet. + //s_vFillTxKey(pDevice, (PBYTE)pTxBufHead->adwTxKey, NULL); + + //Fill IV(ExtIV,RSNHDR) + //s_vFillPrePayload(pDevice, pbyIVHead, NULL); + //--------------------------- + // S/W or H/W Encryption + //--------------------------- + //Fill MICHDR + //if (pDevice->bAES) { + // s_vFillMICHDR(pDevice, (PBYTE)pMICHDR, (PBYTE)pMACHeader, (WORD)cbFrameBodySize); + //} + do { + if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && + (pDevice->bLinkPass == TRUE)) { + pbyBSSID = pDevice->abyBSSID; + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == FALSE) { + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); + break; + } + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n"); + break; + } + } + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == FALSE) { + pTransmitKey = NULL; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); + } + } while(FALSE); + //Fill TXKEY + s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + (PBYTE)pMACHeader, (WORD)cbFrameBodySize, NULL); + + MEMvCopy(pMACHeader, pPacket->p80211Header, cbMacHdLen); + MEMvCopy(pbyPayloadHead, ((PBYTE)(pPacket->p80211Header) + cbMacHdLen), + cbFrameBodySize); + } + else { + // Copy the Packet into a tx Buffer + MEMvCopy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + } + + pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + if (bIsPSPOLL) { + // The MAC will automatically replace the Duration-field of MAC header by Duration-field + // of FIFO control header. + // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is + // in the same place of other packet's Duration-field). + // And it will cause Cisco-AP to issue Disassociation-packet + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + } else { + ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); + } + } + + + // first TD is the only TD + //Set TSR1 & ReqCount in TxDescHead + pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU); + pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma; + pFrstTD->m_td1TD1.wReqCount = cpu_to_le16((WORD)(cbReqCount)); + pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma); + pFrstTD->pTDInfo->byFlags = 0; + + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) { + // Disable PS + MACbPSWakeup(pDevice->PortOffset); + } + pDevice->bPWBitOn = FALSE; + + wmb(); + pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC; + wmb(); + + pDevice->iTDUsed[TYPE_TXDMA0]++; + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n"); + } + + pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next; +#ifdef PLICE_DEBUG + //printk("SCAN:CurrentRate is %d,TxPower is %d\n",wCurrentRate,pTxBufHead->byTxPower); +#endif + +#ifdef TxInSleep + pDevice->nTxDataTimeCout=0; //2008-8-21 chester <add> for send null packet + #endif + + // Poll Transmit the adapter + MACvTransmit0(pDevice->PortOffset); + + return CMD_STATUS_PENDING; + +} + + +CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket) { + + BYTE byPktTyp; + PBYTE pbyBuffer = (PBYTE)pDevice->tx_beacon_bufs; + UINT cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; + UINT cbHeaderSize = 0; + WORD wTxBufSize = sizeof(STxShortBufHead); + PSTxShortBufHead pTxBufHead = (PSTxShortBufHead) pbyBuffer; + PSTxDataHead_ab pTxDataHead = (PSTxDataHead_ab) (pbyBuffer + wTxBufSize); + PS802_11Header pMACHeader; + WORD wCurrentRate; + WORD wLen = 0x0000; + + + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + wCurrentRate = RATE_6M; + byPktTyp = PK_TYPE_11A; + } else { + wCurrentRate = RATE_2M; + byPktTyp = PK_TYPE_11B; + } + + //Set Preamble type always long + pDevice->byPreambleType = PREAMBLE_LONG; + + //Set FIFOCTL_GENINT + + pTxBufHead->wFIFOCtl |= FIFOCTL_GENINT; + + + //Set packet type & Get Duration + if (byPktTyp == PK_TYPE_11A) {//0000 0000 0000 0000 + pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, byPktTyp, + wCurrentRate, FALSE, 0, 0, 1, AUTO_FB_NONE)); + } + else if (byPktTyp == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, byPktTyp, + wCurrentRate, FALSE, 0, 0, 1, AUTO_FB_NONE)); + } + + BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, byPktTyp, + (PWORD)&(wLen), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) + ); + pTxDataHead->wTransmitLength = cpu_to_le16(wLen); + //Get TimeStampOff + pTxDataHead->wTimeStampOff = cpu_to_le16(wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]); + cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab); + + //Generate Beacon Header + pMACHeader = (PS802_11Header)(pbyBuffer + cbHeaderSize); + MEMvCopy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); + + pMACHeader->wDurationID = 0; + pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + // Set Beacon buffer length + pDevice->wBCNBufLen = pPacket->cbMPDULen + cbHeaderSize; + + MACvSetCurrBCNTxDescAddr(pDevice->PortOffset, (pDevice->tx_beacon_dma)); + + MACvSetCurrBCNLength(pDevice->PortOffset, pDevice->wBCNBufLen); + // Set auto Transmit on + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + // Poll Transmit the adapter + MACvTransmitBCN(pDevice->PortOffset); + + return CMD_STATUS_PENDING; +} + + + +UINT +cbGetFragCount ( + IN PSDevice pDevice, + IN PSKeyItem pTransmitKey, + IN UINT cbFrameBodySize, + IN PSEthernetHeader psEthHeader + ) +{ + UINT cbMACHdLen; + UINT cbFrameSize; + UINT cbFragmentSize; //Hdr+(IV)+payoad+(MIC)+(ICV)+FCS + UINT cbFragPayloadSize; + UINT cbLastFragPayloadSize; + UINT cbIVlen = 0; + UINT cbICVlen = 0; + UINT cbMIClen = 0; + UINT cbFCSlen = 4; + UINT uMACfragNum = 1; + BOOL bNeedACK; + + + + if ((pDevice->eOPMode == OP_MODE_ADHOC) || + (pDevice->eOPMode == OP_MODE_AP)) { + if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || + IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { + bNeedACK = FALSE; + } + else { + bNeedACK = TRUE; + } + } + else { + // MSDUs in Infra mode always need ACK + bNeedACK = TRUE; + } + + if (pDevice->bLongHeader) + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; + else + cbMACHdLen = WLAN_HDR_ADDR3_LEN; + + + if (pDevice->bEncryptionEnable == TRUE) { + + if (pTransmitKey == NULL) { + if ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) || + (pDevice->pMgmt->eAuthenMode < WMAC_AUTH_WPA)) { + cbIVlen = 4; + cbICVlen = 4; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + } + } else if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { + cbIVlen = 4; + cbICVlen = 4; + } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + } + } + + cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen; + + if ((cbFrameSize > pDevice->wFragmentationThreshold) && (bNeedACK == TRUE)) { + // Fragmentation + cbFragmentSize = pDevice->wFragmentationThreshold; + cbFragPayloadSize = cbFragmentSize - cbMACHdLen - cbIVlen - cbICVlen - cbFCSlen; + uMACfragNum = (WORD) ((cbFrameBodySize + cbMIClen) / cbFragPayloadSize); + cbLastFragPayloadSize = (cbFrameBodySize + cbMIClen) % cbFragPayloadSize; + if (cbLastFragPayloadSize == 0) { + cbLastFragPayloadSize = cbFragPayloadSize; + } else { + uMACfragNum++; + } + } + return uMACfragNum; +} + + +VOID +vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDULen) { + + PSTxDesc pFrstTD; + BYTE byPktTyp; + PBYTE pbyTxBufferAddr; + PVOID pvRTS; + PVOID pvCTS; + PVOID pvTxDataHd; + UINT uDuration; + UINT cbReqCount; + PS802_11Header pMACHeader; + UINT cbHeaderSize; + UINT cbFrameBodySize; + BOOL bNeedACK; + BOOL bIsPSPOLL = FALSE; + PSTxBufHead pTxBufHead; + UINT cbFrameSize; + UINT cbIVlen = 0; + UINT cbICVlen = 0; + UINT cbMIClen = 0; + UINT cbFCSlen = 4; + UINT uPadding = 0; + UINT cbMICHDR = 0; + UINT uLength = 0; + DWORD dwMICKey0, dwMICKey1; + DWORD dwMIC_Priority; + PDWORD pdwMIC_L; + PDWORD pdwMIC_R; + WORD wTxBufSize; + UINT cbMacHdLen; + SEthernetHeader sEthHeader; + PVOID pvRrvTime; + PVOID pMICHDR; + PSMgmtObject pMgmt = pDevice->pMgmt; + WORD wCurrentRate = RATE_1M; + PUWLAN_80211HDR p80211Header; + UINT uNodeIndex = 0; + BOOL bNodeExist = FALSE; + SKeyItem STempKey; + PSKeyItem pTransmitKey = NULL; + PBYTE pbyIVHead; + PBYTE pbyPayloadHead; + PBYTE pbyMacHdr; + + UINT cbExtSuppRate = 0; +// PWLAN_IE pItem; + + + pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; + + if(cbMPDULen <= WLAN_HDR_ADDR3_LEN) { + cbFrameBodySize = 0; + } + else { + cbFrameBodySize = cbMPDULen - WLAN_HDR_ADDR3_LEN; + } + p80211Header = (PUWLAN_80211HDR)pbMPDU; + + + pFrstTD = pDevice->apCurrTD[TYPE_TXDMA0]; + pbyTxBufferAddr = (PBYTE)pFrstTD->pTDInfo->buf; + pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; + wTxBufSize = sizeof(STxBufHead); + memset(pTxBufHead, 0, wTxBufSize); + + if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + wCurrentRate = RATE_6M; + byPktTyp = PK_TYPE_11A; + } else { + wCurrentRate = RATE_1M; + byPktTyp = PK_TYPE_11B; + } + + // SetPower will cause error power TX state for OFDM Date packet in TX buffer. + // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. + // And cmd timer will wait data pkt TX finish before scanning so it's OK + // to set power here. + if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) { + RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); + } else { + RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); + } + pTxBufHead->byTxPower = pDevice->byCurPwr; + + //+++++++++++++++++++++ Patch VT3253 A1 performance +++++++++++++++++++++++++++ + if (pDevice->byFOETuning) { + if ((p80211Header->sA3.wFrameCtl & TYPE_DATE_NULL) == TYPE_DATE_NULL) { + wCurrentRate = RATE_24M; + byPktTyp = PK_TYPE_11GA; + } + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x \n", p80211Header->sA3.wFrameCtl); + + //Set packet type + if (byPktTyp == PK_TYPE_11A) {//0000 0000 0000 0000 + pTxBufHead->wFIFOCtl = 0; + } + else if (byPktTyp == PK_TYPE_11B) {//0000 0001 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11B; + } + else if (byPktTyp == PK_TYPE_11GB) {//0000 0010 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; + } + else if (byPktTyp == PK_TYPE_11GA) {//0000 0011 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; + } + + pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; + pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); + + + if (IS_MULTICAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0])) || + IS_BROADCAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0]))) { + bNeedACK = FALSE; + if (pDevice->bEnableHostWEP) { + uNodeIndex = 0; + bNodeExist = TRUE; + }; + } + else { + if (pDevice->bEnableHostWEP) { + if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, (PBYTE)(p80211Header->sA3.abyAddr1), &uNodeIndex)) + bNodeExist = TRUE; + }; + bNeedACK = TRUE; + pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; + }; + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { + + pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; + //Set Preamble type always long + //pDevice->byPreambleType = PREAMBLE_LONG; + + // probe-response don't retry + //if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { + // bNeedACK = FALSE; + // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); + //} + } + + pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); + + if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { + bIsPSPOLL = TRUE; + cbMacHdLen = WLAN_HDR_ADDR2_LEN; + } else { + cbMacHdLen = WLAN_HDR_ADDR3_LEN; + } + + // hostapd deamon ext support rate patch + if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { + + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) { + cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN; + } + + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) { + cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + } + + if (cbExtSuppRate >0) { + cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES; + } + } + + + //Set FRAGCTL_MACHDCNT + pTxBufHead->wFragCtl |= cpu_to_le16((WORD)cbMacHdLen << 10); + + // Notes: + // Although spec says MMPDU can be fragmented; In most case, + // no one will send a MMPDU under fragmentation. With RTS may occur. + pDevice->bAES = FALSE; //Set FRAGCTL_WEPTYP + + + if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { + cbIVlen = 4; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + cbIVlen = 8;//IV+ExtIV + cbMIClen = 8; + cbICVlen = 4; + pTxBufHead->wFragCtl |= FRAGCTL_TKIP; + //We need to get seed here for filling TxKey entry. + //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, + // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); + } + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + cbIVlen = 8;//RSN Header + cbICVlen = 8;//MIC + cbMICHDR = sizeof(SMICHDRHead); + pTxBufHead->wFragCtl |= FRAGCTL_AES; + pDevice->bAES = TRUE; + } + //MAC Header should be padding 0 to DW alignment. + uPadding = 4 - (cbMacHdLen%4); + uPadding %= 4; + } + + cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate; + + //Set FIFOCTL_GrpAckPolicy + if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 + pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; + } + //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() + + + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) {//802.11g packet + + pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); + pvRTS = NULL; + pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); + pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); + + } + else {//802.11a/b packet + + pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); + pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); + cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); + + } + + ZERO_MEMORY((PVOID)(pbyTxBufferAddr + wTxBufSize), (cbHeaderSize - wTxBufSize)); + MEMvCopy(&(sEthHeader.abyDstAddr[0]), &(p80211Header->sA3.abyAddr1[0]), U_ETHER_ADDR_LEN); + MEMvCopy(&(sEthHeader.abySrcAddr[0]), &(p80211Header->sA3.abyAddr2[0]), U_ETHER_ADDR_LEN); + //========================= + // No Fragmentation + //========================= + pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG; + + + //Fill FIFO,RrvTime,RTS,and CTS + s_vGenerateTxParameter(pDevice, byPktTyp, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS, + cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, wCurrentRate); + + //Fill DataHead + uDuration = s_uFillDataHead(pDevice, byPktTyp, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, + 0, 0, 1, AUTO_FB_NONE, wCurrentRate); + + pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize); + + cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate; + + pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderSize); + pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen); + pbyIVHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding); + + // Copy the Packet into a tx Buffer + memcpy(pbyMacHdr, pbMPDU, cbMacHdLen); + + // version set to 0, patch for hostapd deamon + pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc); + memcpy(pbyPayloadHead, (pbMPDU + cbMacHdLen), cbFrameBodySize); + + // replace support rate, patch for hostapd deamon( only support 11M) + if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { + if (cbExtSuppRate != 0) { + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) + memcpy((pbyPayloadHead + cbFrameBodySize), + pMgmt->abyCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) + memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN, + pMgmt->abyCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + } + + // Set wep + if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { + + if (pDevice->bEnableHostWEP) { + 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 + ); + } + + if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { + + dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); + dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); + + // DO Software Michael + MIC_vInit(dwMICKey0, dwMICKey1); + MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + + uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; + + MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize); + + pdwMIC_L = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize); + pdwMIC_R = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4); + + MIC_vGetMIC(pdwMIC_L, pdwMIC_R); + MIC_vUnInit(); + + if (pDevice->bTxMICFail == TRUE) { + *pdwMIC_L = 0; + *pdwMIC_R = 0; + pDevice->bTxMICFail = FALSE; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); + + } + + + s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); + + if (pDevice->bEnableHostWEP) { + pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; + pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; + } + + if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { + s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (WORD)(cbFrameBodySize + cbMIClen)); + } + } + + pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); + pDevice->wSeqCounter++ ; + if (pDevice->wSeqCounter > 0x0fff) + pDevice->wSeqCounter = 0; + + + if (bIsPSPOLL) { + // The MAC will automatically replace the Duration-field of MAC header by Duration-field + // of FIFO control header. + // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is + // in the same place of other packet's Duration-field). + // And it will cause Cisco-AP to issue Disassociation-packet + if (byPktTyp == PK_TYPE_11GB || byPktTyp == PK_TYPE_11GA) { + ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(p80211Header->sA2.wDurationID); + ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(p80211Header->sA2.wDurationID); + } else { + ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(p80211Header->sA2.wDurationID); + } + } + + + // first TD is the only TD + //Set TSR1 & ReqCount in TxDescHead + pFrstTD->pTDInfo->skb = skb; + pFrstTD->m_td1TD1.byTCR = (TCR_STP | TCR_EDP | EDMSDU); + pFrstTD->pTDInfo->skb_dma = pFrstTD->pTDInfo->buf_dma; + pFrstTD->m_td1TD1.wReqCount = cpu_to_le16(cbReqCount); + pFrstTD->buff_addr = cpu_to_le32(pFrstTD->pTDInfo->skb_dma); + pFrstTD->pTDInfo->byFlags = 0; + pFrstTD->pTDInfo->byFlags |= TD_FLAGS_PRIV_SKB; + + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) { + // Disable PS + MACbPSWakeup(pDevice->PortOffset); + } + pDevice->bPWBitOn = FALSE; + + wmb(); + pFrstTD->m_td0TD0.f1Owner = OWNED_BY_NIC; + wmb(); + + pDevice->iTDUsed[TYPE_TXDMA0]++; + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 1) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " available td0 <= 1\n"); + } + + pDevice->apCurrTD[TYPE_TXDMA0] = pFrstTD->next; + + // Poll Transmit the adapter + MACvTransmit0(pDevice->PortOffset); + + return; +} + + diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h new file mode 100644 index 00000000000..3e85264e284 --- /dev/null +++ b/drivers/staging/vt6655/rxtx.h @@ -0,0 +1,132 @@ +/* + * 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: whdr.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + + +#ifndef __RXTX_H__ +#define __RXTX_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +/* +VOID vGenerateMACHeader( + IN PSDevice pDevice, + IN DWORD dwTxBufferAddr, + IN PBYTE pbySkbData, + IN UINT cbPacketSize, + IN BOOL bDMA0Used, + OUT PUINT pcbHeadSize, + OUT PUINT pcbAppendPayload + ); + +VOID vProcessRxMACHeader ( + IN PSDevice pDevice, + IN DWORD dwRxBufferAddr, + IN UINT cbPacketSize, + IN BOOL bIsWEP, + OUT PUINT pcbHeadSize + ); +*/ + + +VOID +vGenerateMACHeader ( + IN PSDevice pDevice, + IN PBYTE pbyBufferAddr, + IN WORD wDuration, + IN PSEthernetHeader psEthHeader, + IN BOOL bNeedEncrypt, + IN WORD wFragType, + IN UINT uDMAIdx, + IN UINT uFragIdx + ); + + +UINT +cbGetFragCount( + IN PSDevice pDevice, + IN PSKeyItem pTransmitKey, + IN UINT cbFrameBodySize, + IN PSEthernetHeader psEthHeader + ); + + +VOID +vGenerateFIFOHeader ( + IN PSDevice pDevice, + IN BYTE byPktTyp, + IN PBYTE pbyTxBufferAddr, + IN BOOL bNeedEncrypt, + IN UINT cbPayloadSize, + IN UINT uDMAIdx, + IN PSTxDesc pHeadTD, + IN PSEthernetHeader psEthHeader, + IN PBYTE pPacket, + IN PSKeyItem pTransmitKey, + IN UINT uNodeIndex, + OUT PUINT puMACfragNum, + OUT PUINT pcbHeaderSize + ); + + +VOID vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb, PBYTE pbMPDU, UINT cbMPDULen); +CMD_STATUS csMgmt_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); +CMD_STATUS csBeacon_xmit(PSDevice pDevice, PSTxMgmtPacket pPacket); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __RXTX_H__ + + + diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c new file mode 100644 index 00000000000..655d6859370 --- /dev/null +++ b/drivers/staging/vt6655/srom.c @@ -0,0 +1,437 @@ +/* + * 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: srom.c + * + * Purpose:Implement functions to access eeprom + * + * Author: Jerry Chen + * + * Date: Jan 29, 2003 + * + * Functions: + * SROMbyReadEmbedded - Embedded read eeprom via MAC + * SROMbWriteEmbedded - Embedded write eeprom via MAC + * SROMvRegBitsOn - Set Bits On in eeprom + * SROMvRegBitsOff - Clear Bits Off in eeprom + * SROMbIsRegBitsOn - Test if Bits On in eeprom + * SROMbIsRegBitsOff - Test if Bits Off in eeprom + * SROMvReadAllContents - Read all contents in eeprom + * SROMvWriteAllContents - Write all contents in eeprom + * SROMvReadEtherAddress - Read Ethernet Address in eeprom + * SROMvWriteEtherAddress - Write Ethernet Address in eeprom + * SROMvReadSubSysVenId - Read Sub_VID and Sub_SysId in eeprom + * SROMbAutoLoad - Auto Load eeprom to MAC register + * + * Revision History: + * + */ + + +#if !defined(__UPC_H__) +#include "upc.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__SROM_H__) +#include "srom.h" +#endif + + + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + + +/* + * Description: Read a byte from EEPROM, by MAC I2C + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * Out: + * none + * + * Return Value: data read + * + */ +BYTE SROMbyReadEmbedded(DWORD_PTR dwIoBase, BYTE byContntOffset) +{ + WORD wDelay, wNoACK; + BYTE byWait; + BYTE byData; + BYTE byOrg; + + byData = 0xFF; + VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg); + // turn off hardware retry for getting NACK + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY))); + for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) { + VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID); + VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset); + + // issue read command + VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMR); + // wait DONE be set + for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) { + VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait); + if (BITbIsAnyBitsOn(byWait, (I2MCSR_DONE | I2MCSR_NACK))) + break; + PCAvDelayByIO(CB_DELAY_LOOP_WAIT); + } + if ((wDelay < W_MAX_TIMEOUT) && + (BITbIsBitOff(byWait, I2MCSR_NACK))) { + break; + } + } + VNSvInPortB(dwIoBase + MAC_REG_I2MDIPT, &byData); + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg); + return byData; +} + + +/* + * Description: Write a byte to EEPROM, by MAC I2C + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * wData - data to write + * Out: + * none + * + * Return Value: TRUE if succeeded; FALSE if failed. + * + */ +BOOL SROMbWriteEmbedded (DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byData) +{ + WORD wDelay, wNoACK; + BYTE byWait; + + BYTE byOrg; + + VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg); + // turn off hardware retry for getting NACK + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg & (~I2MCFG_NORETRY))); + for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) { + VNSvOutPortB(dwIoBase + MAC_REG_I2MTGID, EEP_I2C_DEV_ID); + VNSvOutPortB(dwIoBase + MAC_REG_I2MTGAD, byContntOffset); + VNSvOutPortB(dwIoBase + MAC_REG_I2MDOPT, byData); + + // issue write command + VNSvOutPortB(dwIoBase + MAC_REG_I2MCSR, I2MCSR_EEMW); + // wait DONE be set + for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) { + VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait); + if (BITbIsAnyBitsOn(byWait, (I2MCSR_DONE | I2MCSR_NACK))) + break; + PCAvDelayByIO(CB_DELAY_LOOP_WAIT); + } + + if ((wDelay < W_MAX_TIMEOUT) && + (BITbIsBitOff(byWait, I2MCSR_NACK))) { + break; + } + } + if (wNoACK == W_MAX_I2CRETRY) { + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg); + return FALSE; + } + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg); + return TRUE; +} + + +/* + * Description: Turn bits on in eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * byBits - bits to turn on + * Out: + * none + * + * Return Value: none + * + */ +void SROMvRegBitsOn (DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byBits) +{ + BYTE byOrgData; + + byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset); + SROMbWriteEmbedded(dwIoBase, byContntOffset,(BYTE)(byOrgData | byBits)); +} + + +/* + * Description: Turn bits off in eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * byBits - bits to turn off + * Out: + * none + * + */ +void SROMvRegBitsOff (DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byBits) +{ + BYTE byOrgData; + + byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset); + SROMbWriteEmbedded(dwIoBase, byContntOffset,(BYTE)(byOrgData & (~byBits))); +} + + +/* + * Description: Test if bits on in eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * byTestBits - bits to test + * Out: + * none + * + * Return Value: TRUE if all test bits on; otherwise FALSE + * + */ +BOOL SROMbIsRegBitsOn (DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits) +{ + BYTE byOrgData; + + byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset); + return BITbIsAllBitsOn(byOrgData, byTestBits); +} + + +/* + * Description: Test if bits off in eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * byContntOffset - address of EEPROM + * byTestBits - bits to test + * Out: + * none + * + * Return Value: TRUE if all test bits off; otherwise FALSE + * + */ +BOOL SROMbIsRegBitsOff (DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits) +{ + BYTE byOrgData; + + byOrgData = SROMbyReadEmbedded(dwIoBase, byContntOffset); + return BITbIsAllBitsOff(byOrgData, byTestBits); +} + + +/* + * Description: Read all contents of eeprom to buffer + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * pbyEepromRegs - EEPROM content Buffer + * + * Return Value: none + * + */ +void SROMvReadAllContents (DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) +{ + int ii; + + // ii = Rom Address + for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { + *pbyEepromRegs = SROMbyReadEmbedded(dwIoBase,(BYTE) ii); + pbyEepromRegs++; + } +} + + +/* + * Description: Write all contents of buffer to eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * pbyEepromRegs - EEPROM content Buffer + * Out: + * none + * + * Return Value: none + * + */ +void SROMvWriteAllContents (DWORD_PTR dwIoBase, PBYTE pbyEepromRegs) +{ + int ii; + + // ii = Rom Address + for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { + SROMbWriteEmbedded(dwIoBase,(BYTE) ii, *pbyEepromRegs); + pbyEepromRegs++; + } +} + + +/* + * Description: Read Ethernet Address from eeprom to buffer + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * pbyEtherAddress - Ethernet Address buffer + * + * Return Value: none + * + */ +void SROMvReadEtherAddress (DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) +{ + BYTE ii; + + // ii = Rom Address + for (ii = 0; ii < U_ETHER_ADDR_LEN; ii++) { + *pbyEtherAddress = SROMbyReadEmbedded(dwIoBase, ii); + pbyEtherAddress++; + } +} + + +/* + * Description: Write Ethernet Address from buffer to eeprom + * + * Parameters: + * In: + * dwIoBase - I/O base address + * pbyEtherAddress - Ethernet Address buffer + * Out: + * none + * + * Return Value: none + * + */ +void SROMvWriteEtherAddress (DWORD_PTR dwIoBase, PBYTE pbyEtherAddress) +{ + BYTE ii; + + // ii = Rom Address + for (ii = 0; ii < U_ETHER_ADDR_LEN; ii++) { + SROMbWriteEmbedded(dwIoBase, ii, *pbyEtherAddress); + pbyEtherAddress++; + } +} + + +/* + * Description: Read Sub_VID and Sub_SysId from eeprom to buffer + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * pdwSubSysVenId - Sub_VID and Sub_SysId read + * + * Return Value: none + * + */ +void SROMvReadSubSysVenId (DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId) +{ + PBYTE pbyData; + + pbyData = (PBYTE)pdwSubSysVenId; + // sub vendor + *pbyData = SROMbyReadEmbedded(dwIoBase, 6); + *(pbyData+1) = SROMbyReadEmbedded(dwIoBase, 7); + // sub system + *(pbyData+2) = SROMbyReadEmbedded(dwIoBase, 8); + *(pbyData+3) = SROMbyReadEmbedded(dwIoBase, 9); +} + +/* + * Description: Auto Load EEPROM to MAC register + * + * Parameters: + * In: + * dwIoBase - I/O base address + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL SROMbAutoLoad (DWORD_PTR dwIoBase) +{ + BYTE byWait; + int ii; + + BYTE byOrg; + + VNSvInPortB(dwIoBase + MAC_REG_I2MCFG, &byOrg); + // turn on hardware retry + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, (byOrg | I2MCFG_NORETRY)); + + MACvRegBitsOn(dwIoBase, MAC_REG_I2MCSR, I2MCSR_AUTOLD); + + // ii = Rom Address + for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { + MACvTimer0MicroSDelay(dwIoBase, CB_EEPROM_READBYTE_WAIT); + VNSvInPortB(dwIoBase + MAC_REG_I2MCSR, &byWait); + if (BITbIsBitOff(byWait, I2MCSR_AUTOLD)) + break; + } + + VNSvOutPortB(dwIoBase + MAC_REG_I2MCFG, byOrg); + + if (ii == EEP_MAX_CONTEXT_SIZE) + return FALSE; + return TRUE; +} + + diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h new file mode 100644 index 00000000000..a4ca5f0b196 --- /dev/null +++ b/drivers/staging/vt6655/srom.h @@ -0,0 +1,179 @@ +/* + * 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: srom.h + * + * Purpose: Implement functions to access eeprom + * + * Author: Jerry Chen + * + * Date: Jan 29, 2003 + * + */ + + +#ifndef __SROM_H__ +#define __SROM_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + + +#define EEP_MAX_CONTEXT_SIZE 256 + +#define CB_EEPROM_READBYTE_WAIT 900 //us + +#define W_MAX_I2CRETRY 0x0fff + +// +// Contents in the EEPROM +// + +#define EEP_OFS_PAR 0x00 // physical address +#define EEP_OFS_ANTENNA 0x16 +#define EEP_OFS_RADIOCTL 0x17 +#define EEP_OFS_RFTYPE 0x1B // for select RF +#define EEP_OFS_MINCHANNEL 0x1C // Min Channel # +#define EEP_OFS_MAXCHANNEL 0x1D // Max Channel # +#define EEP_OFS_SIGNATURE 0x1E // +#define EEP_OFS_ZONETYPE 0x1F // +#define EEP_OFS_RFTABLE 0x20 // RF POWER TABLE +#define EEP_OFS_PWR_CCK 0x20 +#define EEP_OFS_SETPT_CCK 0x21 +#define EEP_OFS_PWR_OFDMG 0x23 +#define EEP_OFS_SETPT_OFDMG 0x24 +#define EEP_OFS_PWR_FORMULA_OST 0x26 // +#define EEP_OFS_MAJOR_VER 0x2E +#define EEP_OFS_MINOR_VER 0x2F +#define EEP_OFS_CCK_PWR_TBL 0x30 +#define EEP_OFS_CCK_PWR_dBm 0x3F +#define EEP_OFS_OFDM_PWR_TBL 0x40 +#define EEP_OFS_OFDM_PWR_dBm 0x4F +//{{ RobertYu: 20041124 +#define EEP_OFS_SETPT_OFDMA 0x4E +#define EEP_OFS_OFDMA_PWR_TBL 0x50 +//}} +#define EEP_OFS_OFDMA_PWR_dBm 0xD2 + + +//----------need to remove -------------------- +#define EEP_OFS_BBTAB_LEN 0x70 // BB Table Length +#define EEP_OFS_BBTAB_ADR 0x71 // BB Table Offset +#define EEP_OFS_CHECKSUM 0xFF // reserved area for baseband 28h ~ 78h + +#define EEP_I2C_DEV_ID 0x50 // EEPROM device address on the I2C bus + + +// +// Bits in EEP_OFS_ANTENNA +// +#define EEP_ANTENNA_MAIN 0x01 +#define EEP_ANTENNA_AUX 0x02 +#define EEP_ANTINV 0x04 + +// +// Bits in EEP_OFS_RADIOCTL +// +#define EEP_RADIOCTL_ENABLE 0x80 +#define EEP_RADIOCTL_INV 0x01 + + + +/*--------------------- Export Types ------------------------------*/ + +// AT24C02 eeprom contents +// 2048 bits = 256 bytes = 128 words +// +typedef struct tagSSromReg { + BYTE abyPAR[6]; // 0x00 (WORD) + + WORD wSUB_VID; // 0x03 (WORD) + WORD wSUB_SID; + + BYTE byBCFG0; // 0x05 (WORD) + BYTE byBCFG1; + + BYTE byFCR0; // 0x06 (WORD) + BYTE byFCR1; + BYTE byPMC0; // 0x07 (WORD) + BYTE byPMC1; + BYTE byMAXLAT; // 0x08 (WORD) + BYTE byMINGNT; + BYTE byCFG0; // 0x09 (WORD) + BYTE byCFG1; + WORD wCISPTR; // 0x0A (WORD) + WORD wRsv0; // 0x0B (WORD) + WORD wRsv1; // 0x0C (WORD) + BYTE byBBPAIR; // 0x0D (WORD) + BYTE byRFTYPE; + BYTE byMinChannel; // 0x0E (WORD) + BYTE byMaxChannel; + BYTE bySignature; // 0x0F (WORD) + BYTE byCheckSum; + + BYTE abyReserved0[96]; // 0x10 (WORD) + BYTE abyCIS[128]; // 0x80 (WORD) +} SSromReg, DEF* PSSromReg; + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +BYTE SROMbyReadEmbedded(DWORD_PTR dwIoBase, BYTE byContntOffset); +BOOL SROMbWriteEmbedded(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byData); + +void SROMvRegBitsOn(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byBits); +void SROMvRegBitsOff(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byBits); + +BOOL SROMbIsRegBitsOn(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits); +BOOL SROMbIsRegBitsOff(DWORD_PTR dwIoBase, BYTE byContntOffset, BYTE byTestBits); + +void SROMvReadAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs); +void SROMvWriteAllContents(DWORD_PTR dwIoBase, PBYTE pbyEepromRegs); + +void SROMvReadEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress); +void SROMvWriteEtherAddress(DWORD_PTR dwIoBase, PBYTE pbyEtherAddress); + +VOID SROMvReadSubSysVenId(DWORD_PTR dwIoBase, PDWORD pdwSubSysVenId); + +BOOL SROMbAutoLoad (DWORD_PTR dwIoBase); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __EEPROM_H__ + + diff --git a/drivers/staging/vt6655/tbit.h b/drivers/staging/vt6655/tbit.h new file mode 100644 index 00000000000..7c3a82e9b60 --- /dev/null +++ b/drivers/staging/vt6655/tbit.h @@ -0,0 +1,78 @@ +/* + * 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: tbit.h + * + * Purpose: Bit routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + + +#ifndef __TBIT_H__ +#define __TBIT_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +// test single bit on +#define BITbIsBitOn(tData, tTestBit) \ + (((tData) & (tTestBit)) != 0) + +// test single bit off +#define BITbIsBitOff(tData, tTestBit) \ + (((tData) & (tTestBit)) == 0) + + +#define BITbIsAllBitsOn(tData, tTestBit) \ + (((tData) & (tTestBit)) == (tTestBit)) + +#define BITbIsAllBitsOff(tData, tTestBit) \ + (((tData) & (tTestBit)) == 0) + +#define BITbIsAnyBitsOn(tData, tTestBit) \ + (((tData) & (tTestBit)) != 0) + +#define BITbIsAnyBitsOff(tData, tTestBit) \ + (((tData) & (tTestBit)) != (tTestBit)) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + +#endif // __TBIT_H__ + + + diff --git a/drivers/staging/vt6655/tcrc.c b/drivers/staging/vt6655/tcrc.c new file mode 100644 index 00000000000..b70080c267c --- /dev/null +++ b/drivers/staging/vt6655/tcrc.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2003 VIA Networking, 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: tcrc.c + * + * Purpose: Implement functions to caculate CRC + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * CRCdwCrc32 - + * CRCdwGetCrc32 - + * CRCdwGetCrc32Ex - + * + * Revision History: + * + */ + + +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif + + + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +// 32-bit CRC table +static const DWORD s_adwCrc32Table[256] = { + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, + 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, + 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, + 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, + 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, + 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, + 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, + 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, + 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, + 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, + 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, + 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, + 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, + 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, + 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, + 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, + 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, + 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, + 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, + 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, + 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, + 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, + 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, + 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, + 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, + 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, + 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, + 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, + 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, + 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, + 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, + 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, + 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, + 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, + 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, + 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, + 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, + 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, + 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, + 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, + 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, + 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, + 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, + 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, + 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, + 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, + 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL +}; + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + + + +/*+ + * + * Description: + * Generate a CRC-32 from the data stream + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * dwCrcSeed - Seed for CRC32 + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +DWORD CRCdwCrc32 (PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed) +{ + DWORD dwCrc; + + dwCrc = dwCrcSeed; + while (cbByte--) { + dwCrc = s_adwCrc32Table[(BYTE)((dwCrc ^ (*pbyData)) & 0xFF)] ^ (dwCrc >> 8); + pbyData++; + } + + return dwCrc; +} + + +/*+ + * + * Description: + * To test CRC generator, input 8 bytes packet + * -- 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x00 + * the generated CRC should be + * -- 0xff 0xff 0xff 0xff + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +DWORD CRCdwGetCrc32 (PBYTE pbyData, UINT cbByte) +{ + return ~CRCdwCrc32(pbyData, cbByte, 0xFFFFFFFFL); +} + + +/*+ + * + * Description: + * + * NOTE.... Because CRCdwGetCrc32Ex() is an iteration function, + * this means we will use the output of CRCdwGetCrc32Ex() + * to be a new argument to do next CRCdwGetCrc32Ex() calculation. + * Thus, the final result must be inverted to be the + * correct answer. + * + * Parameters: + * In: + * pbyData - the data stream + * cbByte - the length of the stream + * Out: + * none + * + * Return Value: CRC-32 + * +-*/ +DWORD CRCdwGetCrc32Ex(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC) +{ + return CRCdwCrc32(pbyData, cbByte, dwPreCRC); +} + + diff --git a/drivers/staging/vt6655/tcrc.h b/drivers/staging/vt6655/tcrc.h new file mode 100644 index 00000000000..ebea22ed2da --- /dev/null +++ b/drivers/staging/vt6655/tcrc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003 VIA Networking, 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: tcrc.h + * + * Purpose: Implement functions to caculate CRC + * + * Author: Tevin Chen + * + * Date: Jan. 28, 1997 + * + */ + + +#ifndef __TCRC_H__ +#define __TCRC_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +DWORD CRCdwCrc32(PBYTE pbyData, UINT cbByte, DWORD dwCrcSeed); +DWORD CRCdwGetCrc32(PBYTE pbyData, UINT cbByte); +DWORD CRCdwGetCrc32Ex(PBYTE pbyData, UINT cbByte, DWORD dwPreCRC); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __TCRC_H__ + + + diff --git a/drivers/staging/vt6655/test b/drivers/staging/vt6655/test new file mode 100644 index 00000000000..039f7d71c53 --- /dev/null +++ b/drivers/staging/vt6655/test @@ -0,0 +1,9 @@ +KSP := /lib/modules/$(shell uname -r)/build \ + /usr/src/linux-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ +# /usr/src/kernel-headers-$(shell uname -r) \ +# /usr/src/kernel-source-$(shell uname -r) \ +# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ +# /usr/src/linux /home/plice +test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) +KSP := $(foreach dir, $(KSP), $(test_dir))
\ No newline at end of file diff --git a/drivers/staging/vt6655/tether.c b/drivers/staging/vt6655/tether.c new file mode 100644 index 00000000000..fd69423fe14 --- /dev/null +++ b/drivers/staging/vt6655/tether.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2003 VIA Networking, 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: tether.c + * + * Purpose: + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * ETHbyGetHashIndexByCrc32 - Caculate multicast hash value by CRC32 + * ETHbIsBufferCrc32Ok - Check CRC value of the buffer if Ok or not + * + * Revision History: + * + */ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif + + + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + + +/* + * Description: Caculate multicast hash value by CRC32 + * + * Parameters: + * In: + * pbyMultiAddr - Multicast Address + * Out: + * none + * + * Return Value: Hash value + * + */ +BYTE ETHbyGetHashIndexByCrc32 (PBYTE pbyMultiAddr) +{ + int ii; + BYTE byTmpHash; + BYTE byHash = 0; + + // get the least 6-bits from CRC generator + byTmpHash = (BYTE)(CRCdwCrc32(pbyMultiAddr, U_ETHER_ADDR_LEN, + 0xFFFFFFFFL) & 0x3F); + // reverse most bit to least bit + for (ii = 0; ii < (sizeof(byTmpHash) * 8); ii++) { + byHash <<= 1; + if (BITbIsBitOn(byTmpHash, 0x01)) + byHash |= 1; + byTmpHash >>= 1; + } + + // adjust 6-bits to the right most + return (byHash >> 2); +} + + +/* + * Description: Check CRC value of the buffer if Ok or not + * + * Parameters: + * In: + * pbyBuffer - pointer of buffer (normally is rx buffer) + * cbFrameLength - length of buffer, including CRC portion + * Out: + * none + * + * Return Value: TRUE if ok; FALSE if error. + * + */ +BOOL ETHbIsBufferCrc32Ok (PBYTE pbyBuffer, UINT cbFrameLength) +{ + DWORD dwCRC; + + dwCRC = CRCdwGetCrc32(pbyBuffer, cbFrameLength - 4); + if (cpu_to_le32(*((PDWORD)(pbyBuffer + cbFrameLength - 4))) != dwCRC) { + return FALSE; + } + return TRUE; +} + diff --git a/drivers/staging/vt6655/tether.h b/drivers/staging/vt6655/tether.h new file mode 100644 index 00000000000..920a8bb6835 --- /dev/null +++ b/drivers/staging/vt6655/tether.h @@ -0,0 +1,256 @@ +/* + * 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: tether.h + * + * Purpose: + * + * Author: Tevin Chen + * + * Date: Jan. 28, 1997 + * + */ + + + +#ifndef __TETHER_H__ +#define __TETHER_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + + +/*--------------------- Export Definitions -------------------------*/ +// +// constants +// +#define U_ETHER_ADDR_LEN 6 // Ethernet address length +#define U_TYPE_LEN 2 // +#define U_CRC_LEN 4 // +#define U_HEADER_LEN (U_ETHER_ADDR_LEN * 2 + U_TYPE_LEN) +#define U_ETHER_ADDR_STR_LEN (U_ETHER_ADDR_LEN * 2 + 1) + // Ethernet address string length + +#define MIN_DATA_LEN 46 // min data length +#define MAX_DATA_LEN 1500 // max data length + +#define MIN_PACKET_LEN (MIN_DATA_LEN + U_HEADER_LEN) + // 60 + // min total packet length (tx) +#define MAX_PACKET_LEN (MAX_DATA_LEN + U_HEADER_LEN) + // 1514 + // max total packet length (tx) + +#define MAX_LOOKAHEAD_SIZE MAX_PACKET_LEN + +#define U_MULTI_ADDR_LEN 8 // multicast address length + + +#ifdef __BIG_ENDIAN + +#define TYPE_PKT_IP 0x0800 // +#define TYPE_PKT_ARP 0x0806 // +#define TYPE_PKT_RARP 0x8035 // +#define TYPE_PKT_IPX 0x8137 // +#define TYPE_PKT_802_1x 0x888e +#define TYPE_PKT_PreAuth 0x88C7 + +#define TYPE_PKT_PING_M_REQ 0x8011 // master reguest +#define TYPE_PKT_PING_S_GNT 0x8022 // slave grant +#define TYPE_PKT_PING_M 0x8077 // pingpong master packet +#define TYPE_PKT_PING_S 0x8088 // pingpong slave packet +#define TYPE_PKT_WOL_M_REQ 0x8033 // WOL waker request +#define TYPE_PKT_WOL_S_GNT 0x8044 // WOL sleeper grant +#define TYPE_MGMT_PROBE_RSP 0x5000 +#define TYPE_PKT_VNT_DIAG 0x8011 // Diag Pkt +#define TYPE_PKT_VNT_PER 0x8888 // Diag PER Pkt +// +// wFrameCtl field in the S802_11Header +// +// NOTE.... +// in network byte order, high byte is going first +#define FC_TODS 0x0001 +#define FC_FROMDS 0x0002 +#define FC_MOREFRAG 0x0004 +#define FC_RETRY 0x0008 +#define FC_POWERMGT 0x0010 +#define FC_MOREDATA 0x0020 +#define FC_WEP 0x0040 +#define TYPE_802_11_ATIM 0x9000 + +#define TYPE_802_11_DATA 0x0800 +#define TYPE_802_11_CTL 0x0400 +#define TYPE_802_11_MGMT 0x0000 +#define TYPE_802_11_MASK 0x0C00 +#define TYPE_SUBTYPE_MASK 0xFC00 +#define TYPE_802_11_NODATA 0x4000 +#define TYPE_DATE_NULL 0x4800 + +#define TYPE_CTL_PSPOLL 0xa400 +#define TYPE_CTL_RTS 0xb400 +#define TYPE_CTL_CTS 0xc400 +#define TYPE_CTL_ACK 0xd400 + + +//#define WEP_IV_MASK 0xFFFFFF00 + +#else //if LITTLE_ENDIAN +// +// wType field in the SEthernetHeader +// +// NOTE.... +// in network byte order, high byte is going first +#define TYPE_PKT_IP 0x0008 // +#define TYPE_PKT_ARP 0x0608 // +#define TYPE_PKT_RARP 0x3580 // +#define TYPE_PKT_IPX 0x3781 // + +#define TYPE_PKT_802_1x 0x8e88 +#define TYPE_PKT_PreAuth 0xC788 + +#define TYPE_PKT_PING_M_REQ 0x1180 // master reguest +#define TYPE_PKT_PING_S_GNT 0x2280 // slave grant +#define TYPE_PKT_PING_M 0x7780 // pingpong master packet +#define TYPE_PKT_PING_S 0x8880 // pingpong slave packet +#define TYPE_PKT_WOL_M_REQ 0x3380 // WOL waker request +#define TYPE_PKT_WOL_S_GNT 0x4480 // WOL sleeper grant +#define TYPE_MGMT_PROBE_RSP 0x0050 +#define TYPE_PKT_VNT_DIAG 0x1180 // Diag Pkt +#define TYPE_PKT_VNT_PER 0x8888 // Diag PER Pkt +// +// wFrameCtl field in the S802_11Header +// +// NOTE.... +// in network byte order, high byte is going first +#define FC_TODS 0x0100 +#define FC_FROMDS 0x0200 +#define FC_MOREFRAG 0x0400 +#define FC_RETRY 0x0800 +#define FC_POWERMGT 0x1000 +#define FC_MOREDATA 0x2000 +#define FC_WEP 0x4000 +#define TYPE_802_11_ATIM 0x0090 + +#define TYPE_802_11_DATA 0x0008 +#define TYPE_802_11_CTL 0x0004 +#define TYPE_802_11_MGMT 0x0000 +#define TYPE_802_11_MASK 0x000C +#define TYPE_SUBTYPE_MASK 0x00FC +#define TYPE_802_11_NODATA 0x0040 +#define TYPE_DATE_NULL 0x0048 + +#define TYPE_CTL_PSPOLL 0x00a4 +#define TYPE_CTL_RTS 0x00b4 +#define TYPE_CTL_CTS 0x00c4 +#define TYPE_CTL_ACK 0x00d4 + + +//#define WEP_IV_MASK 0x00FFFFFF + +#endif //#ifdef __BIG_ENDIAN + +#define WEP_IV_MASK 0x00FFFFFF + +/*--------------------- Export Types ------------------------------*/ +// +// Ethernet packet +// +typedef struct tagSEthernetHeader { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wType; +}__attribute__ ((__packed__)) +SEthernetHeader, DEF* PSEthernetHeader; + + +// +// 802_3 packet +// +typedef struct tagS802_3Header { + BYTE abyDstAddr[U_ETHER_ADDR_LEN]; + BYTE abySrcAddr[U_ETHER_ADDR_LEN]; + WORD wLen; +}__attribute__ ((__packed__)) +S802_3Header, DEF* PS802_3Header; + +// +// 802_11 packet +// +typedef struct tagS802_11Header { + WORD wFrameCtl; + WORD wDurationID; + BYTE abyAddr1[U_ETHER_ADDR_LEN]; + BYTE abyAddr2[U_ETHER_ADDR_LEN]; + BYTE abyAddr3[U_ETHER_ADDR_LEN]; + WORD wSeqCtl; + BYTE abyAddr4[U_ETHER_ADDR_LEN]; +}__attribute__ ((__packed__)) +S802_11Header, DEF* PS802_11Header; + +/*--------------------- Export Macros ------------------------------*/ +// Frame type macro + +#define IS_MULTICAST_ADDRESS(pbyEtherAddr) \ + ((*(PBYTE)(pbyEtherAddr) & 0x01) == 1) + +#define IS_BROADCAST_ADDRESS(pbyEtherAddr) ( \ + (*(PDWORD)(pbyEtherAddr) == 0xFFFFFFFFL) && \ + (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0xFFFF) \ +) + +#define IS_NULL_ADDRESS(pbyEtherAddr) ( \ + (*(PDWORD)(pbyEtherAddr) == 0L) && \ + (*(PWORD)((PBYTE)(pbyEtherAddr) + 4) == 0) \ +) + +#define IS_ETH_ADDRESS_EQUAL(pbyAddr1, pbyAddr2) ( \ + (*(PDWORD)(pbyAddr1) == *(PDWORD)(pbyAddr2)) && \ + (*(PWORD)((PBYTE)(pbyAddr1) + 4) == \ + *(PWORD)((PBYTE)(pbyAddr2) + 4)) \ +) + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +BYTE ETHbyGetHashIndexByCrc32(PBYTE pbyMultiAddr); +//BYTE ETHbyGetHashIndexByCrc(PBYTE pbyMultiAddr); +BOOL ETHbIsBufferCrc32Ok(PBYTE pbyBuffer, UINT cbFrameLength); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __TETHER_H__ + + + diff --git a/drivers/staging/vt6655/tkip.c b/drivers/staging/vt6655/tkip.c new file mode 100644 index 00000000000..2ded8420c39 --- /dev/null +++ b/drivers/staging/vt6655/tkip.c @@ -0,0 +1,284 @@ +/* + * 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: tkip.c + * + * Purpose: Implement functions for 802.11i TKIP + * + * Author: Jerry Chen + * + * Date: Mar. 11, 2003 + * + * Functions: + * TKIPvMixKey - Get TKIP RC4 Key from TK,TA, and TSC + * + * Revision History: + * + */ + + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__TKIP_H__) +#include "tkip.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/* The Sbox is reduced to 2 16-bit wide tables, each with 256 entries. */ +/* The 2nd table is the same as the 1st but with the upper and lower */ +/* bytes swapped. To allow an endian tolerant implementation, the byte */ +/* halves have been expressed independently here. */ +const BYTE TKIP_Sbox_Lower[256] = { + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +const BYTE TKIP_Sbox_Upper[256] = { + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + + +//STKIPKeyManagement sTKIPKeyTable[MAX_TKIP_KEY]; + +/*--------------------- Static Functions --------------------------*/ +unsigned int tkip_sbox(unsigned int index); +unsigned int rotr1(unsigned int a); + +/*--------------------- Export Variables --------------------------*/ + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ +unsigned int tkip_sbox(unsigned int index) +{ + unsigned int index_low; + unsigned int index_high; + unsigned int left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = TKIP_Sbox_Lower[index_low] + (TKIP_Sbox_Upper[index_low] * 256); + right = TKIP_Sbox_Upper[index_high] + (TKIP_Sbox_Lower[index_high] * 256); + + return (left ^ right); +}; + + +unsigned int rotr1(unsigned int a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) { + b = (a >> 1) | 0x8000; + } else { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + + +/* + * Description: Caculate RC4Key fom TK, TA, and TSC + * + * Parameters: + * In: + * pbyTKey - TKey + * pbyTA - TA + * dwTSC - TSC + * Out: + * pbyRC4Key - RC4Key + * + * Return Value: none + * + */ +VOID TKIPvMixKey( + PBYTE pbyTKey, + PBYTE pbyTA, + WORD wTSC15_0, + DWORD dwTSC47_16, + PBYTE pbyRC4Key + ) +{ + unsigned int p1k[5]; +// unsigned int ttak0, ttak1, ttak2, ttak3, ttak4; + unsigned int tsc0, tsc1, tsc2; + unsigned int ppk0, ppk1, ppk2, ppk3, ppk4, ppk5; + unsigned long int pnl,pnh; + + int i, j; + + pnl = wTSC15_0; + pnh = dwTSC47_16; + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (unsigned int)(pbyTA[0] + (pbyTA[1]*256)); + p1k[3] = (unsigned int)(pbyTA[2] + (pbyTA[3]*256)); + p1k[4] = (unsigned int)(pbyTA[4] + (pbyTA[5]*256)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) { + j = 2*(i & 1); + p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536 )) % 65536; + p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536 )) % 65536; + p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536 )) % 65536; + p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536 )) % 65536; + p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536 )) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536); + ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536); + ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536); + ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536); + ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536); + ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + pbyRC4Key[0] = (tsc2 >> 8) % 256; + pbyRC4Key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + pbyRC4Key[2] = tsc2 % 256; + pbyRC4Key[3] = ((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) >> 1) % 256; + + pbyRC4Key[4] = ppk0 % 256; + pbyRC4Key[5] = (ppk0 >> 8) % 256; + + pbyRC4Key[6] = ppk1 % 256; + pbyRC4Key[7] = (ppk1 >> 8) % 256; + + pbyRC4Key[8] = ppk2 % 256; + pbyRC4Key[9] = (ppk2 >> 8) % 256; + + pbyRC4Key[10] = ppk3 % 256; + pbyRC4Key[11] = (ppk3 >> 8) % 256; + + pbyRC4Key[12] = ppk4 % 256; + pbyRC4Key[13] = (ppk4 >> 8) % 256; + + pbyRC4Key[14] = ppk5 % 256; + pbyRC4Key[15] = (ppk5 >> 8) % 256; +} diff --git a/drivers/staging/vt6655/tkip.h b/drivers/staging/vt6655/tkip.h new file mode 100644 index 00000000000..dc8382b6701 --- /dev/null +++ b/drivers/staging/vt6655/tkip.h @@ -0,0 +1,76 @@ +/* + * 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: tkip.h + * + * Purpose: Implement functions for 802.11i TKIP + * + * Author: Jerry Chen + * + * Date: Mar. 11, 2003 + * + */ + + +#ifndef __TKIP_H__ +#define __TKIP_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +#if !defined(__TETHER_H__) +#include "tether.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ +#define TKIP_KEY_LEN 16 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID TKIPvMixKey( + PBYTE pbyTKey, + PBYTE pbyTA, + WORD wTSC15_0, + DWORD dwTSC47_16, + PBYTE pbyRC4Key + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __TKIP_H__ + + + diff --git a/drivers/staging/vt6655/tmacro.h b/drivers/staging/vt6655/tmacro.h new file mode 100644 index 00000000000..3d932a258dd --- /dev/null +++ b/drivers/staging/vt6655/tmacro.h @@ -0,0 +1,152 @@ +/* + * 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: tmacro.h + * + * Purpose: define basic common types and macros + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + + +#ifndef __TMACRO_H__ +#define __TMACRO_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + + +/****** Common helper macros ***********************************************/ + +#if !defined(LONIBBLE) +#define LONIBBLE(b) ((BYTE)(b) & 0x0F) +#endif +#if !defined(HINIBBLE) +#define HINIBBLE(b) ((BYTE)(((WORD)(b) >> 4) & 0x0F)) +#endif + +#if !defined(LOBYTE) +#define LOBYTE(w) ((BYTE)(w)) +#endif +#if !defined(HIBYTE) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) +#endif + +#if !defined(LOWORD) +#define LOWORD(d) ((WORD)(d)) +#endif +#if !defined(HIWORD) +#define HIWORD(d) ((WORD)((((DWORD)(d)) >> 16) & 0xFFFF)) +#endif + +#define LODWORD(q) ((q).u.dwLowDword) +#define HIDWORD(q) ((q).u.dwHighDword) + + + +#if !defined(MAKEBYTE) +#define MAKEBYTE(ln, hn) ((BYTE)(((BYTE)(ln) & 0x0F) | ((BYTE)(hn) << 4))) +#endif +#if !defined(MAKEWORD) +#define MAKEWORD(lb, hb) ((WORD)(((BYTE)(lb)) | (((WORD)((BYTE)(hb))) << 8))) +#endif +#if !defined(MAKEDWORD) +#define MAKEDWORD(lw, hw) ((DWORD)(((WORD)(lw)) | (((DWORD)((WORD)(hw))) << 16))) +#endif +#if !defined(MAKEQWORD) +#define MAKEQWORD(ld, hd, pq) {pq->u.dwLowDword = ld; pq->u.dwHighDword = hd;} +#endif + +#if !defined(MAKELONG) +#define MAKELONG(low, high) ((LONG)(((WORD)(low)) | (((DWORD)((WORD)(high))) << 16))) +#endif + + + +// Bytes Reverse: big endian to little endian convert +#if !defined(REVWORD) +#define REVWORD(w) ((WORD)( ((WORD)(w) >> 8) | ((WORD)(w) << 8) )) +#endif +#if !defined(REVDWORD) +#define REVDWORD(d) (MAKEDWORD(MAKEWORD(HIBYTE(HIWORD(d)),LOBYTE(HIWORD(d))),MAKEWORD(HIBYTE(LOWORD(d)),LOBYTE(LOWORD(d))))) +#endif + +/* map to known network names */ +/* +#define ntohs(x) REVWORD(x) +#define ntohl(x) REVDWORD(x) +#define htons(x) REVWORD(x) +#define htonl(x) REVDWORD(x) +*/ + + +/* +#ifndef NOMINMAX +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#endif // NOMINMAX +*/ + + + +/****** Misc macros ********************************************************/ + +// get the field offset in the type(struct, class, ...) +#define OFFSET(type, field) ((int)(&((type NEAR*)1)->field)-1) + + +/* string equality shorthand */ +#define STR_EQ(x, y) (strcmp(x, y) == 0) +#define STR_NE(x, y) (strcmp(x, y) != 0) + + +// calculate element # of array +#define ELEMENT_NUM(array) (sizeof(array) / sizeof(array[0])) +//#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + + +// null statement +#define NULL_FUNC() + + +/* Since not all compilers support structure assignment, the ASSIGN() + * macro is used. This controls how it's actually implemented. + */ +#ifdef NOSTRUCTASSIGN /* Version for old compilers that don't support it */ +#define ASSIGN(a,b) memcpy((char *)&(a),(char *)&(b),sizeof(b); +#else /* Version for compilers that do */ +#define ASSIGN(a,b) ((a) = (b)) +#endif + + + + +#endif // __TMACRO_H__ + + diff --git a/drivers/staging/vt6655/tpci.h b/drivers/staging/vt6655/tpci.h new file mode 100644 index 00000000000..4a1c8ed75ca --- /dev/null +++ b/drivers/staging/vt6655/tpci.h @@ -0,0 +1,117 @@ +/* + * 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: tpci.h + * + * Purpose: PCI routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + + +#ifndef __TPCI_H__ +#define __TPCI_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + + +/*--------------------- Export Definitions -------------------------*/ +#define MAX_PCI_BUS 4 // max. # of PCI bus that we support +#define MAX_PCI_DEVICE 32 // max. # of PCI devices + + +// +// Registers in the PCI configuration space +// +#define PCI_REG_VENDOR_ID 0x00 // +#define PCI_REG_DEVICE_ID 0x02 // +#define PCI_REG_COMMAND 0x04 // +#define PCI_REG_STATUS 0x06 // +#define PCI_REG_REV_ID 0x08 // +#define PCI_REG_CLASS_CODE 0x09 // +#define PCI_REG_CACHELINE_SIZE 0x0C // +#define PCI_REG_LAT_TIMER 0x0D // +#define PCI_REG_HDR_TYPE 0x0E // +#define PCI_REG_BIST 0x0F // + +#define PCI_REG_BAR0 0x10 // +#define PCI_REG_BAR1 0x14 // +#define PCI_REG_BAR2 0x18 // +#define PCI_REG_CARDBUS_CIS_PTR 0x28 // + +#define PCI_REG_SUB_VEN_ID 0x2C // +#define PCI_REG_SUB_SYS_ID 0x2E // +#define PCI_REG_EXP_ROM_BAR 0x30 // +#define PCI_REG_CAP 0x34 // + +#define PCI_REG_INT_LINE 0x3C // +#define PCI_REG_INT_PIN 0x3D // +#define PCI_REG_MIN_GNT 0x3E // +#define PCI_REG_MAX_LAT 0x3F // + +#define PCI_REG_MAX_SIZE 0x100 // maximun total PCI registers + + +// +// Bits in the COMMAND register +// +#define COMMAND_BUSM 0x04 // +#define COMMAND_WAIT 0x80 // + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +// macro MAKE Bus Dev Fun ID into WORD +#define MAKE_BDF_TO_WORD(byBusId, byDevId, byFunId) \ + MAKEWORD( \ + ((((BYTE)(byDevId)) & 0x1F) << 3) + \ + (((BYTE)(byFunId)) & 0x07), \ + (byBusId) \ + ) + +#define GET_BUSID(wBusDevFunId) \ + HIBYTE(wBusDevFunId) + +#define GET_DEVID(wBusDevFunId) \ + (LOBYTE(wBusDevFunId) >> 3) + +#define GET_FUNID(wBusDevFunId) \ + (LOBYTE(wBusDevFunId) & 0x07) + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + + +#endif // __TPCI_H__ + + diff --git a/drivers/staging/vt6655/umem.h b/drivers/staging/vt6655/umem.h new file mode 100644 index 00000000000..2c3eafa038e --- /dev/null +++ b/drivers/staging/vt6655/umem.h @@ -0,0 +1,75 @@ +/* + * 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: umem.h + * + * Purpose: Define Memory macros + * + * Author: Tevin Chen + * + * Date: Mar 17, 1997 + * + */ + + +#ifndef __UMEM_H__ +#define __UMEM_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ +// 4-byte memory tag +#define MEM_TAG 'mTEW' + +// Macros used for memory allocation and deallocation. + + + +#define ZERO_MEMORY(Destination,Length) { \ + memset((PVOID)(Destination), \ + 0, \ + (ULONG)(Length) \ + ); \ +} + +#define MEMvCopy(pvDest, pvSource, uCount) { \ + memcpy((PVOID)(pvDest), \ + (PVOID)(pvSource), \ + (ULONG)(uCount) \ + ); \ +} + + +#define MEMEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length))) +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + + +#endif // __UMEM_H__ + + diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h new file mode 100644 index 00000000000..113fc2c88c1 --- /dev/null +++ b/drivers/staging/vt6655/upc.h @@ -0,0 +1,171 @@ +/* + * 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: upc.h + * + * Purpose: Macros to access device + * + * Author: Tevin Chen + * + * Date: Mar 17, 1997 + * + */ + + +#ifndef __UPC_H__ +#define __UPC_H__ + +#if !defined(DEVICE_H) +#include "device.h" +#endif +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + + +// +// For IO mapped +// + +#ifdef IO_MAP + +#define VNSvInPortB(dwIOAddress, pbyData) { \ + *(pbyData) = inb(dwIOAddress); \ +} + + +#define VNSvInPortW(dwIOAddress, pwData) { \ + *(pwData) = inw(dwIOAddress); \ +} + +#define VNSvInPortD(dwIOAddress, pdwData) { \ + *(pdwData) = inl(dwIOAddress); \ +} + + +#define VNSvOutPortB(dwIOAddress, byData) { \ + outb(byData, dwIOAddress); \ +} + + +#define VNSvOutPortW(dwIOAddress, wData) { \ + outw(wData, dwIOAddress); \ +} + +#define VNSvOutPortD(dwIOAddress, dwData) { \ + outl(dwData, dwIOAddress); \ +} + +#else + +// +// For memory mapped IO +// + + +#define VNSvInPortB(dwIOAddress, pbyData) { \ + volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress)); \ + *(pbyData) = readb(pbyAddr); \ +} + + +#define VNSvInPortW(dwIOAddress, pwData) { \ + volatile WORD* pwAddr = ((PWORD)(dwIOAddress)); \ + *(pwData) = readw(pwAddr); \ +} + +#define VNSvInPortD(dwIOAddress, pdwData) { \ + volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress)); \ + *(pdwData) = readl(pdwAddr); \ +} + + +#define VNSvOutPortB(dwIOAddress, byData) { \ + volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress)); \ + writeb((BYTE)byData, pbyAddr); \ +} + + +#define VNSvOutPortW(dwIOAddress, wData) { \ + volatile WORD* pwAddr = ((PWORD)(dwIOAddress)); \ + writew((WORD)wData, pwAddr); \ +} + +#define VNSvOutPortD(dwIOAddress, dwData) { \ + volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress)); \ + writel((DWORD)dwData, pdwAddr); \ +} + +#endif + + +// +// ALWAYS IO-Mapped IO when in 16-bit/32-bit environment +// +#define PCBvInPortB(dwIOAddress, pbyData) { \ + *(pbyData) = inb(dwIOAddress); \ +} + +#define PCBvInPortW(dwIOAddress, pwData) { \ + *(pwData) = inw(dwIOAddress); \ +} + +#define PCBvInPortD(dwIOAddress, pdwData) { \ + *(pdwData) = inl(dwIOAddress); \ +} + +#define PCBvOutPortB(dwIOAddress, byData) { \ + outb(byData, dwIOAddress); \ +} + +#define PCBvOutPortW(dwIOAddress, wData) { \ + outw(wData, dwIOAddress); \ +} + +#define PCBvOutPortD(dwIOAddress, dwData) { \ + outl(dwData, dwIOAddress); \ +} + + +#define PCAvDelayByIO(uDelayUnit) { \ + BYTE byData; \ + ULONG ii; \ + \ + if (uDelayUnit <= 50) { \ + udelay(uDelayUnit); \ + } \ + else { \ + for (ii = 0; ii < (uDelayUnit); ii++) \ + byData = inb(0x61); \ + } \ +} + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + + + +#endif // __UPC_H__ + diff --git a/drivers/staging/vt6655/vntconfiguration.dat b/drivers/staging/vt6655/vntconfiguration.dat new file mode 100644 index 00000000000..0064ddce7c1 --- /dev/null +++ b/drivers/staging/vt6655/vntconfiguration.dat @@ -0,0 +1 @@ +ZONETYPE=EUROPE
\ No newline at end of file diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c new file mode 100644 index 00000000000..58a1ba0eac0 --- /dev/null +++ b/drivers/staging/vt6655/vntwifi.c @@ -0,0 +1,832 @@ +/* + * 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: vntwifi.c + * + * Purpose: export functions for vntwifi lib + * + * Functions: + * + * Revision History: + * + * Author: Yiching Chen + * + * Date: feb. 2, 2005 + * + */ + +#if !defined(__VNTWIFI_H__) +#include "vntwifi.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif + + +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__IEEE11h_H__) +#include "IEEE11h.h" +#endif +#if !defined(__COUNTRY_H__) +#include "country.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__DATARATE_H__) +#include "datarate.h" +#endif +//#define PLICE_DEBUG + +/*--------------------- Static Definitions -------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +//static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/*+ + * + * Description: + * Set Operation Mode + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * eOPMode - Opreation Mode + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +VNTWIFIvSetOPMode ( + IN PVOID pMgmtHandle, + IN WMAC_CONFIG_MODE eOPMode + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + pMgmt->eConfigMode = eOPMode; +} + + +/*+ + * + * Description: + * Set Operation Mode + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * wBeaconPeriod - Beacon Period + * wATIMWindow - ATIM window + * uChannel - channel number + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +VNTWIFIvSetIBSSParameter ( + IN PVOID pMgmtHandle, + IN WORD wBeaconPeriod, + IN WORD wATIMWindow, + IN UINT uChannel + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + pMgmt->wIBSSBeaconPeriod = wBeaconPeriod; + pMgmt->wIBSSATIMWindow = wATIMWindow; + pMgmt->uIBSSChannel = uChannel; +} + +/*+ + * + * Description: + * Get current SSID + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * Out: + * none + * + * Return Value: current SSID pointer. + * +-*/ +PWLAN_IE_SSID +VNTWIFIpGetCurrentSSID ( + IN PVOID pMgmtHandle + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + return((PWLAN_IE_SSID) pMgmt->abyCurrSSID); +} + +/*+ + * + * Description: + * Get current link channel + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * Out: + * none + * + * Return Value: current Channel. + * +-*/ +UINT +VNTWIFIpGetCurrentChannel ( + IN PVOID pMgmtHandle + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + if (pMgmtHandle != NULL) { + return (pMgmt->uCurrChannel); + } + return 0; +} + +/*+ + * + * Description: + * Get current Assoc ID + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * Out: + * none + * + * Return Value: current Assoc ID + * +-*/ +WORD +VNTWIFIwGetAssocID ( + IN PVOID pMgmtHandle + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + return(pMgmt->wCurrAID); +} + + + +/*+ + * + * Description: + * This routine return max support rate of IES + * + * Parameters: + * In: + * pSupportRateIEs + * pExtSupportRateIEs + * + * Out: + * + * Return Value: max support rate + * +-*/ +BYTE +VNTWIFIbyGetMaxSupportRate ( + IN PWLAN_IE_SUPP_RATES pSupportRateIEs, + IN PWLAN_IE_SUPP_RATES pExtSupportRateIEs + ) +{ + BYTE byMaxSupportRate = RATE_1M; + BYTE bySupportRate = RATE_1M; + UINT ii = 0; + + if (pSupportRateIEs) { + for (ii = 0; ii < pSupportRateIEs->len; ii++) { + bySupportRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]); + if (bySupportRate > byMaxSupportRate) { + byMaxSupportRate = bySupportRate; + } + } + } + if (pExtSupportRateIEs) { + for (ii = 0; ii < pExtSupportRateIEs->len; ii++) { + bySupportRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]); + if (bySupportRate > byMaxSupportRate) { + byMaxSupportRate = bySupportRate; + } + } + } + + return byMaxSupportRate; +} + +/*+ + * + * Description: + * This routine return data rate of ACK packtet + * + * Parameters: + * In: + * byRxDataRate + * pSupportRateIEs + * pExtSupportRateIEs + * + * Out: + * + * Return Value: max support rate + * +-*/ +BYTE +VNTWIFIbyGetACKTxRate ( + IN BYTE byRxDataRate, + IN PWLAN_IE_SUPP_RATES pSupportRateIEs, + IN PWLAN_IE_SUPP_RATES pExtSupportRateIEs + ) +{ + BYTE byMaxAckRate; + BYTE byBasicRate; + UINT ii; + + if (byRxDataRate <= RATE_11M) { + byMaxAckRate = RATE_1M; + } else { + // 24M is mandatory for 802.11a and 802.11g + byMaxAckRate = RATE_24M; + } + if (pSupportRateIEs) { + for (ii = 0; ii < pSupportRateIEs->len; ii++) { + if (pSupportRateIEs->abyRates[ii] & 0x80) { + byBasicRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]); + if ((byBasicRate <= byRxDataRate) && + (byBasicRate > byMaxAckRate)) { + byMaxAckRate = byBasicRate; + } + } + } + } + if (pExtSupportRateIEs) { + for (ii = 0; ii < pExtSupportRateIEs->len; ii++) { + if (pExtSupportRateIEs->abyRates[ii] & 0x80) { + byBasicRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]); + if ((byBasicRate <= byRxDataRate) && + (byBasicRate > byMaxAckRate)) { + byMaxAckRate = byBasicRate; + } + } + } + } + + return byMaxAckRate; +} + +/*+ + * + * Description: + * Set Authentication Mode + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * eAuthMode - Authentication mode + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +VNTWIFIvSetAuthenticationMode ( + IN PVOID pMgmtHandle, + IN WMAC_AUTHENTICATION_MODE eAuthMode + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + pMgmt->eAuthenMode = eAuthMode; + if ((eAuthMode == WMAC_AUTH_SHAREKEY) || + (eAuthMode == WMAC_AUTH_AUTO)) { + pMgmt->bShareKeyAlgorithm = TRUE; + } else { + pMgmt->bShareKeyAlgorithm = FALSE; + } +} + +/*+ + * + * Description: + * Set Encryption Mode + * + * Parameters: + * In: + * pMgmtHandle - pointer to management object + * eAuthMode - Authentication mode + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +VNTWIFIvSetEncryptionMode ( + IN PVOID pMgmtHandle, + IN WMAC_ENCRYPTION_MODE eEncryptionMode + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + pMgmt->eEncryptionMode = eEncryptionMode; + if ((eEncryptionMode == WMAC_ENCRYPTION_WEPEnabled) || + (eEncryptionMode == WMAC_ENCRYPTION_TKIPEnabled) || + (eEncryptionMode == WMAC_ENCRYPTION_AESEnabled) ) { + pMgmt->bPrivacyInvoked = TRUE; + } else { + pMgmt->bPrivacyInvoked = FALSE; + } +} + + + +BOOL +VNTWIFIbConfigPhyMode ( + IN PVOID pMgmtHandle, + IN CARD_PHY_TYPE ePhyType + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + if ((ePhyType != PHY_TYPE_AUTO) && + (ePhyType != pMgmt->eCurrentPHYMode)) { + if (CARDbSetPhyParameter(pMgmt->pAdapter, ePhyType, 0, 0, NULL, NULL)==TRUE) { + pMgmt->eCurrentPHYMode = ePhyType; + } else { + return(FALSE); + } + } + pMgmt->eConfigPHYMode = ePhyType; + return(TRUE); +} + + +VOID +VNTWIFIbGetConfigPhyMode ( + IN PVOID pMgmtHandle, + OUT PVOID pePhyType + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + if ((pMgmt != NULL) && (pePhyType != NULL)) { + *(PCARD_PHY_TYPE)pePhyType = pMgmt->eConfigPHYMode; + } +} + +/*+ + * + * Description: + * Clear BSS List Database except current assoc BSS + * + * Parameters: + * In: + * pMgmtHandle - Management Object structure + * bLinkPass - Current Link status + * Out: + * + * Return Value: None. + * +-*/ + + +/*+ + * + * Description: + * Query BSS List in management database + * + * Parameters: + * In: + * pMgmtHandle - Management Object structure + * Out: + * puBSSCount - BSS count + * pvFirstBSS - pointer to first BSS + * + * Return Value: None. + * +-*/ + +VOID +VNTWIFIvQueryBSSList ( + IN PVOID pMgmtHandle, + OUT PUINT puBSSCount, + OUT PVOID *pvFirstBSS + ) +{ + UINT ii = 0; + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + PKnownBSS pBSS = NULL; + UINT uCount = 0; + + *pvFirstBSS = NULL; + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) { + continue; + } + if (*pvFirstBSS == NULL) { + *pvFirstBSS = &(pMgmt->sBSSList[ii]); + } + uCount++; + } + *puBSSCount = uCount; +} + + + + +VOID +VNTWIFIvGetNextBSS ( + IN PVOID pMgmtHandle, + IN PVOID pvCurrentBSS, + OUT PVOID *pvNextBSS + ) +{ + PKnownBSS pBSS = (PKnownBSS) pvCurrentBSS; + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + *pvNextBSS = NULL; + + while (*pvNextBSS == NULL) { + pBSS++; + if (pBSS > &(pMgmt->sBSSList[MAX_BSS_NUM])) { + return; + } + if (pBSS->bActive == TRUE) { + *pvNextBSS = pBSS; + return; + } + } +} + + + + + +/*+ + * + * Description: + * Update Tx attemps, Tx failure counter in Node DB + * + * In: + * Out: + * none + * + * Return Value: none + * +-*/ +VOID +VNTWIFIvUpdateNodeTxCounter( + IN PVOID pMgmtHandle, + IN PBYTE pbyDestAddress, + IN BOOL bTxOk, + IN WORD wRate, + IN PBYTE pbyTxFailCount + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + UINT uNodeIndex = 0; + UINT ii; + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + if (BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex) == FALSE) { + return; + } + } + pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts++; + if (bTxOk == TRUE) { + // transmit success, TxAttempts at least plus one + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; + pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wRate]++; + } else { + pMgmt->sNodeDBTable[uNodeIndex].uTxFailures++; + } + pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += pbyTxFailCount[MAX_RATE]; + for(ii=0;ii<MAX_RATE;ii++) { + pMgmt->sNodeDBTable[uNodeIndex].uTxFail[ii] += pbyTxFailCount[ii]; + } + return; +} + + +VOID +VNTWIFIvGetTxRate( + IN PVOID pMgmtHandle, + IN PBYTE pbyDestAddress, + OUT PWORD pwTxDataRate, + OUT PBYTE pbyACKRate, + OUT PBYTE pbyCCKBasicRate, + OUT PBYTE pbyOFDMBasicRate + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + UINT uNodeIndex = 0; + WORD wTxDataRate = RATE_1M; + BYTE byACKRate = RATE_1M; + BYTE byCCKBasicRate = RATE_1M; + BYTE byOFDMBasicRate = RATE_24M; + PWLAN_IE_SUPP_RATES pSupportRateIEs = NULL; + PWLAN_IE_SUPP_RATES pExtSupportRateIEs = NULL; + + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || + (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + // Adhoc Tx rate decided from node DB + if(BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex)) { + wTxDataRate = (pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate); + pSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrSuppRates); + pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrExtSuppRates); + } else { + if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) { + wTxDataRate = RATE_2M; + } else { + wTxDataRate = RATE_24M; + } + pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates; + pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates; + } + } else { // Infrastructure: rate decided from AP Node, index = 0 + + wTxDataRate = (pMgmt->sNodeDBTable[0].wTxDataRate); +#ifdef PLICE_DEBUG + printk("GetTxRate:AP MAC is %02x:%02x:%02x:%02x:%02x:%02x,TxRate is %d\n", + pMgmt->sNodeDBTable[0].abyMACAddr[0],pMgmt->sNodeDBTable[0].abyMACAddr[1], + pMgmt->sNodeDBTable[0].abyMACAddr[2],pMgmt->sNodeDBTable[0].abyMACAddr[3], + pMgmt->sNodeDBTable[0].abyMACAddr[4],pMgmt->sNodeDBTable[0].abyMACAddr[5],wTxDataRate); +#endif + + + pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates; + pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates; + } + byACKRate = VNTWIFIbyGetACKTxRate( (BYTE) wTxDataRate, + pSupportRateIEs, + pExtSupportRateIEs + ); + if (byACKRate > (BYTE) wTxDataRate) { + byACKRate = (BYTE) wTxDataRate; + } + byCCKBasicRate = VNTWIFIbyGetACKTxRate( RATE_11M, + pSupportRateIEs, + pExtSupportRateIEs + ); + byOFDMBasicRate = VNTWIFIbyGetACKTxRate(RATE_54M, + pSupportRateIEs, + pExtSupportRateIEs + ); + *pwTxDataRate = wTxDataRate; + *pbyACKRate = byACKRate; + *pbyCCKBasicRate = byCCKBasicRate; + *pbyOFDMBasicRate = byOFDMBasicRate; + return; +} + +BYTE +VNTWIFIbyGetKeyCypher( + IN PVOID pMgmtHandle, + IN BOOL bGroupKey + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; + + if (bGroupKey == TRUE) { + return (pMgmt->byCSSGK); + } else { + return (pMgmt->byCSSPK); + } +} + + +/* +BOOL +VNTWIFIbInit( + IN PVOID pAdapterHandler, + OUT PVOID *pMgmtHandler + ) +{ + + PSMgmtObject pMgmt = NULL; + UINT ii; + + + pMgmt = (PSMgmtObject)kmalloc(sizeof(SMgmtObject), (int)GFP_ATOMIC); + if (pMgmt == NULL) { + *pMgmtHandler = NULL; + return FALSE; + } + + memset(pMgmt, 0, sizeof(SMgmtObject)); + pMgmt->pAdapter = (PVOID) pAdapterHandler; + + // should initial MAC address abyMACAddr + for(ii=0;ii<WLAN_BSSID_LEN;ii++) { + pMgmt->abyDesireBSSID[ii] = 0xFF; + } + pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0]; + pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0]; + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_NONE; + pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; + + pMgmt->cbFreeCmdQueue = CMD_Q_SIZE; + pMgmt->uCmdDequeueIdx = 0; + pMgmt->uCmdEnqueueIdx = 0; + pMgmt->eCommandState = WLAN_CMD_STATE_IDLE; + pMgmt->bCmdStop = FALSE; + pMgmt->bCmdRunning = FALSE; + + *pMgmtHandler = pMgmt; + return TRUE; +} +*/ + + + +BOOL +VNTWIFIbSetPMKIDCache ( + IN PVOID pMgmtObject, + IN ULONG ulCount, + IN PVOID pPMKIDInfo + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + + if (ulCount > MAX_PMKID_CACHE) { + return (FALSE); + } + pMgmt->gsPMKIDCache.BSSIDInfoCount = ulCount; + MEMvCopy(pMgmt->gsPMKIDCache.BSSIDInfo, pPMKIDInfo, (ulCount*sizeof(PMKIDInfo))); + return (TRUE); +} + + + +WORD +VNTWIFIwGetMaxSupportRate( + IN PVOID pMgmtObject + ) +{ + WORD wRate = RATE_54M; + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + + for(wRate = RATE_54M; wRate > RATE_1M; wRate--) { + if (BITbIsBitOn(pMgmt->sNodeDBTable[0].wSuppRate, (1<<wRate))) { + return (wRate); + } + } + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11A) { + return (RATE_6M); + } else { + return (RATE_1M); + } +} + + +VOID +VNTWIFIvSet11h ( + IN PVOID pMgmtObject, + IN BOOL b11hEnable + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + + pMgmt->b11hEnable = b11hEnable; +} + +BOOL +VNTWIFIbMeasureReport( + IN PVOID pMgmtObject, + IN BOOL bEndOfReport, + IN PVOID pvMeasureEID, + IN BYTE byReportMode, + IN BYTE byBasicMap, + IN BYTE byCCAFraction, + IN PBYTE pbyRPIs + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + PBYTE pbyCurrentEID = (PBYTE) (pMgmt->pCurrMeasureEIDRep); + + //spin_lock_irq(&pDevice->lock); + if ((pvMeasureEID != NULL) && + (pMgmt->uLengthOfRepEIDs < (WLAN_A3FR_MAXLEN - sizeof(MEASEURE_REP) - sizeof(WLAN_80211HDR_A3) - 3)) + ) { + pMgmt->pCurrMeasureEIDRep->byElementID = WLAN_EID_MEASURE_REP; + pMgmt->pCurrMeasureEIDRep->len = 3; + pMgmt->pCurrMeasureEIDRep->byToken = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byToken; + pMgmt->pCurrMeasureEIDRep->byMode = byReportMode; + pMgmt->pCurrMeasureEIDRep->byType = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byType; + switch (pMgmt->pCurrMeasureEIDRep->byType) { + case MEASURE_TYPE_BASIC : + pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_BASIC); + MEMvCopy( &(pMgmt->pCurrMeasureEIDRep->sRep.sBasic), + &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), + sizeof(MEASEURE_REQ)); + pMgmt->pCurrMeasureEIDRep->sRep.sBasic.byMap = byBasicMap; + break; + case MEASURE_TYPE_CCA : + pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_CCA); + MEMvCopy( &(pMgmt->pCurrMeasureEIDRep->sRep.sCCA), + &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), + sizeof(MEASEURE_REQ)); + pMgmt->pCurrMeasureEIDRep->sRep.sCCA.byCCABusyFraction = byCCAFraction; + break; + case MEASURE_TYPE_RPI : + pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_RPI); + MEMvCopy( &(pMgmt->pCurrMeasureEIDRep->sRep.sRPI), + &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), + sizeof(MEASEURE_REQ)); + MEMvCopy(pMgmt->pCurrMeasureEIDRep->sRep.sRPI.abyRPIdensity, pbyRPIs, 8); + break; + default : + break; + } + pbyCurrentEID += (2 + pMgmt->pCurrMeasureEIDRep->len); + pMgmt->uLengthOfRepEIDs += (2 + pMgmt->pCurrMeasureEIDRep->len); + pMgmt->pCurrMeasureEIDRep = (PWLAN_IE_MEASURE_REP) pbyCurrentEID; + } + if (bEndOfReport == TRUE) { + IEEE11hbMSRRepTx(pMgmt); + } + //spin_unlock_irq(&pDevice->lock); + return (TRUE); +} + + +BOOL +VNTWIFIbChannelSwitch( + IN PVOID pMgmtObject, + IN BYTE byNewChannel + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + + //spin_lock_irq(&pDevice->lock); + pMgmt->uCurrChannel = byNewChannel; + pMgmt->bSwitchChannel = FALSE; + //spin_unlock_irq(&pDevice->lock); + return TRUE; +} + +/* +BOOL +VNTWIFIbRadarPresent( + IN PVOID pMgmtObject, + IN BYTE byChannel + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (byChannel == (BYTE) pMgmt->uCurrChannel) && + (pMgmt->bSwitchChannel != TRUE) && + (pMgmt->b11hEnable == TRUE)) { + if (IS_ETH_ADDRESS_EQUAL(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) { + pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(BYTE) pMgmt->uCurrChannel); + pMgmt->bSwitchChannel = TRUE; + } + BEACONbSendBeacon(pMgmt); + CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10); + } + return TRUE; +} +*/ + diff --git a/drivers/staging/vt6655/vntwifi.h b/drivers/staging/vt6655/vntwifi.h new file mode 100644 index 00000000000..3e620a72621 --- /dev/null +++ b/drivers/staging/vt6655/vntwifi.h @@ -0,0 +1,330 @@ +/* + * 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: vntwifi.h + * + * Purpose: export VNT Host WiFi library function + * + * Author: Yiching Chen + * + * Date: Jan 7, 2004 + * + */ + +#ifndef __VNTWIFI_H__ +#define __VNTWIFI_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ +#define RATE_1M 0 +#define RATE_2M 1 +#define RATE_5M 2 +#define RATE_11M 3 +#define RATE_6M 4 +#define RATE_9M 5 +#define RATE_12M 6 +#define RATE_18M 7 +#define RATE_24M 8 +#define RATE_36M 9 +#define RATE_48M 10 +#define RATE_54M 11 +#define RATE_AUTO 12 +#define MAX_RATE 12 + +// key CipherSuite +#define KEY_CTL_WEP 0x00 +#define KEY_CTL_NONE 0x01 +#define KEY_CTL_TKIP 0x02 +#define KEY_CTL_CCMP 0x03 +#define KEY_CTL_INVALID 0xFF + +#define CHANNEL_MAX_24G 14 + +#define MAX_BSS_NUM 42 + +#define MAX_PMKID_CACHE 16 + +// Pre-configured Authenticaiton Mode (from XP) +typedef enum tagWMAC_AUTHENTICATION_MODE { + + WMAC_AUTH_OPEN, + WMAC_AUTH_SHAREKEY, + WMAC_AUTH_AUTO, + WMAC_AUTH_WPA, + WMAC_AUTH_WPAPSK, + WMAC_AUTH_WPANONE, + WMAC_AUTH_WPA2, + WMAC_AUTH_WPA2PSK, + WMAC_AUTH_MAX // Not a real mode, defined as upper bound + +} WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE; + +typedef enum tagWMAC_ENCRYPTION_MODE { + + WMAC_ENCRYPTION_WEPEnabled, + WMAC_ENCRYPTION_WEPDisabled, + WMAC_ENCRYPTION_WEPKeyAbsent, + WMAC_ENCRYPTION_WEPNotSupported, + WMAC_ENCRYPTION_TKIPEnabled, + WMAC_ENCRYPTION_TKIPKeyAbsent, + WMAC_ENCRYPTION_AESEnabled, + WMAC_ENCRYPTION_AESKeyAbsent + +} WMAC_ENCRYPTION_MODE, *PWMAC_ENCRYPTION_MODE; + +// Pre-configured Mode (from XP) + +typedef enum tagWMAC_CONFIG_MODE { + + WMAC_CONFIG_ESS_STA = 0, + WMAC_CONFIG_IBSS_STA, + WMAC_CONFIG_AUTO, + WMAC_CONFIG_AP + +} WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE; + + + +typedef enum tagWMAC_POWER_MODE { + + WMAC_POWER_CAM, + WMAC_POWER_FAST, + WMAC_POWER_MAX + +} WMAC_POWER_MODE, *PWMAC_POWER_MODE; + +#define VNTWIFIbIsShortSlotTime(wCapInfo) \ + WLAN_GET_CAP_INFO_SHORTSLOTTIME(wCapInfo) \ + +#define VNTWIFIbIsProtectMode(byERP) \ + ((byERP & WLAN_EID_ERP_USE_PROTECTION) != 0) \ + +#define VNTWIFIbIsBarkerMode(byERP) \ + ((byERP & WLAN_EID_ERP_BARKER_MODE) != 0) \ + +#define VNTWIFIbIsShortPreamble(wCapInfo) \ + WLAN_GET_CAP_INFO_SHORTPREAMBLE(wCapInfo) \ + +#define VNTWIFIbIsEncryption(wCapInfo) \ + WLAN_GET_CAP_INFO_PRIVACY(wCapInfo) \ + +#define VNTWIFIbIsESS(wCapInfo) \ + WLAN_GET_CAP_INFO_ESS(wCapInfo) \ + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Types ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + + +VOID +VNTWIFIvSetIBSSParameter ( + IN PVOID pMgmtHandle, + IN WORD wBeaconPeriod, + IN WORD wATIMWindow, + IN UINT uChannel + ); + +VOID +VNTWIFIvSetOPMode ( + IN PVOID pMgmtHandle, + IN WMAC_CONFIG_MODE eOPMode + ); + +PWLAN_IE_SSID +VNTWIFIpGetCurrentSSID( + IN PVOID pMgmtHandle + ); + +UINT +VNTWIFIpGetCurrentChannel( + IN PVOID pMgmtHandle + ); + +WORD +VNTWIFIwGetAssocID ( + IN PVOID pMgmtHandle + ); + +BYTE +VNTWIFIbyGetMaxSupportRate ( + IN PWLAN_IE_SUPP_RATES pSupportRateIEs, + IN PWLAN_IE_SUPP_RATES pExtSupportRateIEs + ); + +BYTE +VNTWIFIbyGetACKTxRate ( + IN BYTE byRxDataRate, + IN PWLAN_IE_SUPP_RATES pSupportRateIEs, + IN PWLAN_IE_SUPP_RATES pExtSupportRateIEs + ); + +VOID +VNTWIFIvSetAuthenticationMode ( + IN PVOID pMgmtHandle, + IN WMAC_AUTHENTICATION_MODE eAuthMode + ); + +VOID +VNTWIFIvSetEncryptionMode ( + IN PVOID pMgmtHandle, + IN WMAC_ENCRYPTION_MODE eEncryptionMode + ); + + +BOOL +VNTWIFIbConfigPhyMode( + IN PVOID pMgmtHandle, + IN CARD_PHY_TYPE ePhyType + ); + +VOID +VNTWIFIbGetConfigPhyMode( + IN PVOID pMgmtHandle, + OUT PVOID pePhyType + ); + +VOID +VNTWIFIvQueryBSSList( + IN PVOID pMgmtHandle, + OUT PUINT puBSSCount, + OUT PVOID *pvFirstBSS + ); + + + + +VOID +VNTWIFIvGetNextBSS ( + IN PVOID pMgmtHandle, + IN PVOID pvCurrentBSS, + OUT PVOID *pvNextBSS + ); + + + +VOID +VNTWIFIvUpdateNodeTxCounter( + IN PVOID pMgmtHandle, + IN PBYTE pbyDestAddress, + IN BOOL bTxOk, + IN WORD wRate, + IN PBYTE pbyTxFailCount + ); + + +VOID +VNTWIFIvGetTxRate( + IN PVOID pMgmtHandle, + IN PBYTE pbyDestAddress, + OUT PWORD pwTxDataRate, + OUT PBYTE pbyACKRate, + OUT PBYTE pbyCCKBasicRate, + OUT PBYTE pbyOFDMBasicRate + ); +/* +BOOL +VNTWIFIbInit( + IN PVOID pAdapterHandler, + OUT PVOID *pMgmtHandler + ); +*/ + +BYTE +VNTWIFIbyGetKeyCypher( + IN PVOID pMgmtHandle, + IN BOOL bGroupKey + ); + + + + +BOOL +VNTWIFIbSetPMKIDCache ( + IN PVOID pMgmtObject, + IN ULONG ulCount, + IN PVOID pPMKIDInfo + ); + +BOOL +VNTWIFIbCommandRunning ( + IN PVOID pMgmtObject + ); + +WORD +VNTWIFIwGetMaxSupportRate( + IN PVOID pMgmtObject + ); + +// for 802.11h +VOID +VNTWIFIvSet11h ( + IN PVOID pMgmtObject, + IN BOOL b11hEnable + ); + +BOOL +VNTWIFIbMeasureReport( + IN PVOID pMgmtObject, + IN BOOL bEndOfReport, + IN PVOID pvMeasureEID, + IN BYTE byReportMode, + IN BYTE byBasicMap, + IN BYTE byCCAFraction, + IN PBYTE pbyRPIs + ); + +BOOL +VNTWIFIbChannelSwitch( + IN PVOID pMgmtObject, + IN BYTE byNewChannel + ); +/* +BOOL +VNTWIFIbRadarPresent( + IN PVOID pMgmtObject, + IN BYTE byChannel + ); +*/ + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif //__VNTWIFI_H__ diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c new file mode 100644 index 00000000000..92563bd011b --- /dev/null +++ b/drivers/staging/vt6655/wcmd.c @@ -0,0 +1,1178 @@ + /* + * 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: wcmd.c + * + * Purpose: Handles the management command interface functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2003 + * + * Functions: + * s_vProbeChannel - Active scan channel + * s_MgrMakeProbeRequest - Make ProbeRequest packet + * CommandTimer - Timer function to handle command + * s_bCommandComplete - Command Complete function + * bScheduleCommand - Push Command and wait Command Scheduler to do + * vCommandTimer- Command call back functions + * vCommandTimerWait- Call back timer + * bClearBSSID_SCAN- Clear BSSID_SCAN cmd in CMD Queue + * + * Revision History: + * + */ + + + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +//DavidWang +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; +/*--------------------- Static Functions --------------------------*/ + +static +VOID +s_vProbeChannel( + IN PSDevice pDevice + ); + + +static +PSTxMgmtPacket +s_MgrMakeProbeRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pScanBSSID, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + +static +BOOL +s_bCommandComplete ( + PSDevice pDevice + ); + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + +/* + * Description: + * Stop AdHoc beacon during scan process + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: none + * + */ +static +void +vAdHocBeaconStop(PSDevice pDevice) +{ + + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + BOOL bStop; + + /* + * temporarily stop Beacon packet for AdHoc Server + * if all of the following coditions are met: + * (1) STA is in AdHoc mode + * (2) VT3253 is programmed as automatic Beacon Transmitting + * (3) One of the following conditions is met + * (3.1) AdHoc channel is in B/G band and the + * current scan channel is in A band + * or + * (3.2) AdHoc channel is in A mode + */ + bStop = FALSE; + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) + { + if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) && + (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) + { + bStop = TRUE; + } + if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G) + { + bStop = TRUE; + } + } + + if (bStop) + { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + } + +} + +/* + * Description: + * Restart AdHoc beacon after scan process complete + * + * Parameters: + * In: + * pDevice - Pointer to the adapter + * Out: + * none + * + * Return Value: none + * + */ +static +void +vAdHocBeaconRestart(PSDevice pDevice) +{ + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + + /* + * Restart Beacon packet for AdHoc Server + * if all of the following coditions are met: + * (1) STA is in AdHoc mode + * (2) VT3253 is programmed as automatic Beacon Transmitting + */ + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->eCurrState >= WMAC_STATE_STARTED)) + { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + } + +} + + + + +/*+ + * + * Routine Description: + * Prepare and send probe request management frames. + * + * + * Return Value: + * none. + * +-*/ + +static +VOID +s_vProbeChannel( + IN PSDevice pDevice + ) +{ + //1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M + BYTE abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C}; + BYTE abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60}; + //6M, 9M, 12M, 48M + BYTE abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + BYTE abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; + PBYTE pbyRate; + PSTxMgmtPacket pTxPacket; + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT ii; + + + if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + pbyRate = &abyCurrSuppRatesA[0]; + } else if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + pbyRate = &abyCurrSuppRatesB[0]; + } else { + pbyRate = &abyCurrSuppRatesG[0]; + } + // build an assocreq frame and send it + pTxPacket = s_MgrMakeProbeRequest + ( + pDevice, + pMgmt, + pMgmt->abyScanBSSID, + (PWLAN_IE_SSID)pMgmt->abyScanSSID, + (PWLAN_IE_SUPP_RATES)pbyRate, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG + ); + + if (pTxPacket != NULL ){ + for (ii = 0; ii < 2 ; ii++) { + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request sending fail.. \n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request is sending.. \n"); + } + } + } + +} + + + + +/*+ + * + * Routine Description: + * Constructs an probe request frame + * + * + * Return Value: + * A ptr to Tx frame or NULL on allocation failue + * +-*/ + + +PSTxMgmtPacket +s_MgrMakeProbeRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pScanBSSID, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_PROBEREQ sFrame; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_PROBEREQ_FR_MAXLEN; + vMgrEncodeProbeRequest(&sFrame); + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN); + // Copy the SSID, pSSID->len=0 indicate broadcast SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN); + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + // Copy the extension rate set + if (pDevice->eCurrentPHYType == PHY_TYPE_11G) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + + + +VOID +vCommandTimerWait( + IN HANDLE hDeviceContext, + IN UINT MSecond + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; + // RUN_AT :1 msec ~= (HZ/1024) + pDevice->sTimerCommand.expires = (UINT)RUN_AT((MSecond * HZ) >> 10); + add_timer(&pDevice->sTimerCommand); + return; +} + + + +VOID +vCommandTimer ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + PWLAN_IE_SSID pItemSSIDCurr; + CMD_STATUS Status; + UINT ii; + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + struct sk_buff *skb; + + + if (pDevice->dwDiagRefCount != 0) + return; + if (pDevice->bCmdRunning != TRUE) + return; + + spin_lock_irq(&pDevice->lock); + + switch ( pDevice->eCommandState ) { + + case WLAN_CMD_SCAN_START: + + pDevice->byReAssocCount = 0; + if (pDevice->bRadioOff == TRUE) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + s_bCommandComplete(pDevice); + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP); + spin_unlock_irq(&pDevice->lock); + return; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SCAN_START\n"); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID; + // wait all Data TD complete + if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){ + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((HANDLE)pDevice, 10); + return; + }; + + if (pMgmt->uScanChannel == 0 ) { + pMgmt->uScanChannel = pDevice->byMinChannel; + // Set Baseband to be more sensitive. + + } + if (pMgmt->uScanChannel > pDevice->byMaxChannel) { + pMgmt->eScanState = WMAC_NO_SCANNING; + + // Set Baseband's sensitivity back. + // Set channel back + CARDbSetChannel(pMgmt->pAdapter, pMgmt->uCurrChannel); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC); + } else { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE); + } + vAdHocBeaconRestart(pDevice); + s_bCommandComplete(pDevice); + + } else { +//2008-8-4 <add> by chester + if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel); + s_bCommandComplete(pDevice); + return; + } +//printk("chester-pMgmt->uScanChannel=%d,pDevice->byMaxChannel=%d\n",pMgmt->uScanChannel,pDevice->byMaxChannel); + if (pMgmt->uScanChannel == pDevice->byMinChannel) { + //pMgmt->eScanType = WMAC_SCAN_ACTIVE; + pMgmt->abyScanBSSID[0] = 0xFF; + pMgmt->abyScanBSSID[1] = 0xFF; + pMgmt->abyScanBSSID[2] = 0xFF; + pMgmt->abyScanBSSID[3] = 0xFF; + pMgmt->abyScanBSSID[4] = 0xFF; + pMgmt->abyScanBSSID[5] = 0xFF; + pItemSSID->byElementID = WLAN_EID_SSID; + // clear bssid list + // BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + pMgmt->eScanState = WMAC_IS_SCANNING; + + } + + vAdHocBeaconStop(pDevice); + + if (CARDbSetChannel(pMgmt->pAdapter, pMgmt->uScanChannel) == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SCAN Channel: %d\n", pMgmt->uScanChannel); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SET SCAN Channel Fail: %d\n", pMgmt->uScanChannel); + } + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_UNKNOWN); +// printk("chester-mxch=%d\n",pDevice->byMaxChannel); + // printk("chester-ch=%d\n",pMgmt->uScanChannel); + pMgmt->uScanChannel++; +//2008-8-4 <modify> by chester + if (!ChannelValid(pDevice->byZoneType, pMgmt->uScanChannel) && + pMgmt->uScanChannel <= pDevice->byMaxChannel ){ + pMgmt->uScanChannel=pDevice->byMaxChannel+1; + pMgmt->eCommandState = WLAN_CMD_SCAN_END; + + } + + + if ((pMgmt->b11hEnable == FALSE) || + (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) { + s_vProbeChannel(pDevice); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((HANDLE)pDevice, WCMD_ACTIVE_SCAN_TIME); + return; + } else { + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((HANDLE)pDevice, WCMD_PASSIVE_SCAN_TIME); + return; + } + + } + + break; + + case WLAN_CMD_SCAN_END: + + // Set Baseband's sensitivity back. + // Set channel back + CARDbSetChannel(pMgmt->pAdapter, pMgmt->uCurrChannel); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Scanning, set back to channel: [%d]\n", pMgmt->uCurrChannel); + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC); + } else { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_INFRASTRUCTURE); + } + + pMgmt->eScanState = WMAC_NO_SCANNING; + vAdHocBeaconRestart(pDevice); +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + if(pMgmt->eScanType == WMAC_SCAN_PASSIVE) + {//send scan event to wpa_Supplicant + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL); + } +#endif + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_DISASSOCIATE_START : + pDevice->byReAssocCount = 0; + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState != WMAC_STATE_ASSOC)) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n"); + // reason = 8 : disassoc because sta has left + vMgrDisassocBeginSta((HANDLE)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status); + pDevice->bLinkPass = FALSE; + // unlock command busy + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + pItemSSID->len = 0; + memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->sNodeDBTable[0].bActive = FALSE; +// pDevice->bBeaconBufReady = FALSE; + } + netif_stop_queue(pDevice->dev); + pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT; + // wait all Control TD complete + if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){ + vCommandTimerWait((HANDLE)pDevice, 10); + spin_unlock_irq(&pDevice->lock); + return; + }; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" CARDbRadioPowerOff\n"); + //2008-09-02 <mark> by chester + // CARDbRadioPowerOff(pDevice); + s_bCommandComplete(pDevice); + break; + + case WLAN_DISASSOCIATE_WAIT : + // wait all Control TD complete + if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){ + vCommandTimerWait((HANDLE)pDevice, 10); + spin_unlock_irq(&pDevice->lock); + return; + }; +//2008-09-02 <mark> by chester + // CARDbRadioPowerOff(pDevice); + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_SSID_START: + pDevice->byReAssocCount = 0; + if (pDevice->bRadioOff == TRUE) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } +//printk("chester-currmode=%d\n",pMgmt->eCurrMode); +printk("chester-abyDesireSSID=%s\n",((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID); + //memcpy(pMgmt->abyAdHocSSID,pMgmt->abyDesireSSID, + //((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: desire ssid = %s\n", pItemSSID->abySSID); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID); + + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n"); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSID->len =%d\n",pItemSSID->len); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" pItemSSIDCurr->len = %d\n",pItemSSIDCurr->len); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" desire ssid = %s\n", pItemSSID->abySSID); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" curr ssid = %s\n", pItemSSIDCurr->abySSID); + } + + if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)&& (pMgmt->eCurrState == WMAC_STATE_JOINTED))) { + + if (pItemSSID->len == pItemSSIDCurr->len) { + if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) { + s_bCommandComplete(pDevice); + spin_unlock_irq(&pDevice->lock); + return; + } + } + + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + } + // set initial state + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + PSvDisablePowerSaving((HANDLE)pDevice); + BSSvClearNodeDBTable(pDevice, 0); + + vMgrJoinBSSBegin((HANDLE)pDevice, &Status); + // if Infra mode + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) { + + // Call mgr to begin the deauthentication + // reason = (3) beacuse sta has left ESS + if (pMgmt->eCurrState>= WMAC_STATE_AUTH) { + vMgrDeAuthenBeginSta((HANDLE)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status); + } + // Call mgr to begin the authentication + vMgrAuthenBeginSta((HANDLE)pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + pDevice->byLinkWaitCount = 0; + pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT; + vCommandTimerWait((HANDLE)pDevice, AUTHENTICATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n"); + return; + } + } + // if Adhoc mode + else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + if (pMgmt->eCurrState == WMAC_STATE_JOINTED) { + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pDevice->bLinkPass = TRUE; + + pMgmt->sNodeDBTable[0].bActive = TRUE; + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + bClearBSSID_SCAN(pDevice); + } + else { + // start own IBSS + vMgrCreateOwnIBSS((HANDLE)pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " WLAN_CMD_IBSS_CREATE fail ! \n"); + }; + BSSvAddMulticastNode(pDevice); + } + } + // if SSID not found + else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) { + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA || + pMgmt->eConfigMode == WMAC_CONFIG_AUTO) { + // start own IBSS + vMgrCreateOwnIBSS((HANDLE)pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO" WLAN_CMD_IBSS_CREATE fail ! \n"); + }; + BSSvAddMulticastNode(pDevice); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pDevice->bLinkPass = TRUE; + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n"); + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + + } + } + s_bCommandComplete(pDevice); + break; + + case WLAN_AUTHENTICATE_WAIT : + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_AUTHENTICATE_WAIT\n"); + if (pMgmt->eCurrState == WMAC_STATE_AUTH) { + // Call mgr to begin the association + pDevice->byLinkWaitCount = 0; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_AUTH\n"); + vMgrAssocBeginSta((HANDLE)pDevice, pMgmt, &Status); + if (Status == CMD_STATUS_SUCCESS) { + pDevice->byLinkWaitCount = 0; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState = WLAN_ASSOCIATE_WAIT\n"); + pDevice->eCommandState = WLAN_ASSOCIATE_WAIT; + vCommandTimerWait((HANDLE)pDevice, ASSOCIATE_TIMEOUT); + spin_unlock_irq(&pDevice->lock); + return; + } + } + + else if(pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) { + printk("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n"); + } + else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if authenticated_frame delay! + pDevice->byLinkWaitCount ++; + printk("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((HANDLE)pDevice, AUTHENTICATE_TIMEOUT/2); + return; + } + pDevice->byLinkWaitCount = 0; + #if 0 + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated:AUTHENTICATE_WAIT_timeout)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + #endif + s_bCommandComplete(pDevice); + break; + + case WLAN_ASSOCIATE_WAIT : + if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCurrState == WMAC_STATE_ASSOC\n"); + if (pDevice->ePSMode != WMAC_POWER_CAM) { + PSvEnablePowerSaving((HANDLE)pDevice, pMgmt->wListenInterval); + } + if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA) { + KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset); + } + pDevice->bLinkPass = TRUE; + pDevice->byLinkWaitCount = 0; + pDevice->byReAssocCount = 0; + bClearBSSID_SCAN(pDevice); + if (pDevice->byFOETuning) { + BBvSetFOE(pDevice->PortOffset); + PSbSendNullPacket(pDevice); + } + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + #ifdef TxInSleep + if(pDevice->IsTxDataTrigger != FALSE) { //TxDataTimer is not triggered at the first time + // printk("Re-initial TxDataTimer****\n"); + del_timer(&pDevice->sTimerTxData); + init_timer(&pDevice->sTimerTxData); + pDevice->sTimerTxData.data = (ULONG)pDevice; + pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + pDevice->fTxDataInSleep = FALSE; + pDevice->nTxDataTimeCout = 0; + } + else { + // printk("mike:-->First time triger TimerTxData InSleep\n"); + } + pDevice->IsTxDataTrigger = TRUE; + add_timer(&pDevice->sTimerTxData); + #endif + } + else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { + printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); + } + else if(pDevice->byLinkWaitCount <= 4){ //mike add:wait another 2 sec if associated_frame delay! + pDevice->byLinkWaitCount ++; + printk("WLAN_ASSOCIATE_WAIT:wait %d times!!\n",pDevice->byLinkWaitCount); + spin_unlock_irq(&pDevice->lock); + vCommandTimerWait((HANDLE)pDevice, ASSOCIATE_TIMEOUT/2); + return; + } + pDevice->byLinkWaitCount = 0; + #if 0 + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated:ASSOCIATE_WAIT_timeout)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + #endif + + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_AP_MODE_START : + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n"); + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + del_timer(&pMgmt->sTimerSecondCallback); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pDevice->bLinkPass = FALSE; + if (pDevice->bEnableHostWEP == TRUE) + BSSvClearNodeDBTable(pDevice, 1); + else + BSSvClearNodeDBTable(pDevice, 0); + pDevice->uAssocCount = 0; + pMgmt->eCurrState = WMAC_STATE_IDLE; + pDevice->bFixRate = FALSE; + + vMgrCreateOwnIBSS((HANDLE)pDevice, &Status); + if (Status != CMD_STATUS_SUCCESS){ + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " vMgrCreateOwnIBSS fail ! \n"); + }; + // alway turn off unicast bit + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST); + pDevice->byRxMode &= ~RCR_UNICAST; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wcmd: rx_mode = %x\n", pDevice->byRxMode ); + BSSvAddMulticastNode(pDevice); + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pDevice->bLinkPass = TRUE; + add_timer(&pMgmt->sTimerSecondCallback); + } + s_bCommandComplete(pDevice); + break; + + case WLAN_CMD_TX_PSPACKET_START : + // DTIM Multicast tx + if (pMgmt->sNodeDBTable[0].bRxPSPoll) { + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) { + pMgmt->abyPSTxMap[0] &= ~byMask[0]; + pDevice->bMoreData = FALSE; + } + else { + pDevice->bMoreData = TRUE; + } + if (!device_dma0_xmit(pDevice, skb, 0)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Multicast ps tx fail \n"); + } + pMgmt->sNodeDBTable[0].wEnQueueCnt--; + } + }; + + // PS nodes tx + for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) { + if (pMgmt->sNodeDBTable[ii].bActive && + pMgmt->sNodeDBTable[ii].bRxPSPoll) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d Enqueu Cnt= %d\n", + ii, pMgmt->sNodeDBTable[ii].wEnQueueCnt); + while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) { + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + pDevice->bMoreData = FALSE; + } + else { + pDevice->bMoreData = TRUE; + } + if (!device_dma0_xmit(pDevice, skb, ii)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "sta ps tx fail \n"); + } + pMgmt->sNodeDBTable[ii].wEnQueueCnt--; + // check if sta ps enable, wait next pspoll + // if sta ps disable, send all pending buffers. + if (pMgmt->sNodeDBTable[ii].bPSEnable) + break; + } + if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) { + // clear tx map + pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &= + ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7]; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Index=%d PS queue clear \n", ii); + } + pMgmt->sNodeDBTable[ii].bRxPSPoll = FALSE; + } + } + + s_bCommandComplete(pDevice); + break; + + + case WLAN_CMD_RADIO_START : + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_RADIO_START\n"); + if (pDevice->bRadioCmd == TRUE) + CARDbRadioPowerOn(pDevice); + else + CARDbRadioPowerOff(pDevice); + + s_bCommandComplete(pDevice); + break; + + + case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE : + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_CHECK_BBSENSITIVITY_START\n"); + // wait all TD complete + if (pDevice->iTDUsed[TYPE_AC0DMA] != 0){ + vCommandTimerWait((HANDLE)pDevice, 10); + spin_unlock_irq(&pDevice->lock); + return; + } + if (pDevice->iTDUsed[TYPE_TXDMA0] != 0){ + vCommandTimerWait((HANDLE)pDevice, 10); + spin_unlock_irq(&pDevice->lock); + return; + } + pDevice->byBBVGACurrent = pDevice->byBBVGANew; + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent); + s_bCommandComplete(pDevice); + break; + + default : + s_bCommandComplete(pDevice); + break; + + } //switch + spin_unlock_irq(&pDevice->lock); + return; + +} + + +static +BOOL +s_bCommandComplete ( + PSDevice pDevice + ) +{ + PWLAN_IE_SSID pSSID; + BOOL bRadioCmd = FALSE; + //WORD wDeAuthenReason = 0; + BOOL bForceSCAN = TRUE; + PSMgmtObject pMgmt = pDevice->pMgmt; + + + pDevice->eCommandState = WLAN_CMD_IDLE; + if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) { + //Command Queue Empty + pDevice->bCmdRunning = FALSE; + return TRUE; + } + else { + pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd; + pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID; + bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd; + bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN; + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue++; + pDevice->bCmdRunning = TRUE; + switch ( pDevice->eCommand ) { + case WLAN_CMD_BSSID_SCAN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_BSSID_SCAN\n"); + pDevice->eCommandState = WLAN_CMD_SCAN_START; + pMgmt->uScanChannel = 0; + if (pSSID->len != 0) { + MEMvCopy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + } else { + memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + } +/* + if ((bForceSCAN == FALSE) && (pDevice->bLinkPass == TRUE)) { + if ((pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) && + (MEMEqualMemory(pSSID->abySSID, ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, pSSID->len))) { + pDevice->eCommandState = WLAN_CMD_IDLE; + } + } +*/ + break; + case WLAN_CMD_SSID: + pDevice->eCommandState = WLAN_CMD_SSID_START; + if (pSSID->len > WLAN_SSID_MAXLEN) + pSSID->len = WLAN_SSID_MAXLEN; + if (pSSID->len != 0) + MEMvCopy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState= WLAN_CMD_SSID_START\n"); + break; + case WLAN_CMD_DISASSOCIATE: + pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START; + break; + case WLAN_CMD_RX_PSPOLL: + pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START; + break; + case WLAN_CMD_RUN_AP: + pDevice->eCommandState = WLAN_CMD_AP_MODE_START; + break; + case WLAN_CMD_RADIO: + pDevice->eCommandState = WLAN_CMD_RADIO_START; + pDevice->bRadioCmd = bRadioCmd; + break; + case WLAN_CMD_CHANGE_BBSENSITIVITY: + pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE; + break; + + default: + break; + + } + + vCommandTimerWait((HANDLE)pDevice, 0); + } + + return TRUE; +} + + + +BOOL bScheduleCommand ( + IN HANDLE hDeviceContext, + IN CMD_CODE eCommand, + IN PBYTE pbyItem0 + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + + if (pDevice->cbFreeCmdQueue == 0) { + return (FALSE); + } + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand; + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = TRUE; + memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + + if (pbyItem0 != NULL) { + switch (eCommand) { + + case WLAN_CMD_BSSID_SCAN: + MEMvCopy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = FALSE; + break; + + case WLAN_CMD_SSID: + MEMvCopy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, + pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + break; + + case WLAN_CMD_DISASSOCIATE: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((PBOOL)pbyItem0); + break; +/* + case WLAN_CMD_DEAUTH: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].wDeAuthenReason = *((PWORD)pbyItem0); + break; +*/ + + case WLAN_CMD_RX_PSPOLL: + break; + + case WLAN_CMD_RADIO: + pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((PBOOL)pbyItem0); + break; + + case WLAN_CMD_CHANGE_BBSENSITIVITY: + pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE; + break; + + default: + break; + } + } + + ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE); + pDevice->cbFreeCmdQueue--; + + if (pDevice->bCmdRunning == FALSE) { + s_bCommandComplete(pDevice); + } + else { + } + return (TRUE); + +} + +/* + * Description: + * Clear BSSID_SCAN cmd in CMD Queue + * + * Parameters: + * In: + * hDeviceContext - Pointer to the adapter + * eCommand - Command + * Out: + * none + * + * Return Value: TRUE if success; otherwise FALSE + * + */ +BOOL bClearBSSID_SCAN ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + UINT uCmdDequeueIdx = pDevice->uCmdDequeueIdx; + UINT ii; + + if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) { + for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii ++) { + if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN) + pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE; + ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE); + if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx) + break; + } + } + return TRUE; +} + +//mike add:reset command timer +VOID +vResetCommandTimer( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + //delete timer + del_timer(&pDevice->sTimerCommand); + //init timer + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; + pDevice->sTimerCommand.expires = RUN_AT(HZ); + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->eCommandState = WLAN_CMD_IDLE; + pDevice->bCmdRunning = FALSE; + pDevice->bCmdClear = FALSE; +} + + +#ifdef TxInSleep +VOID +BSSvSecondTxData( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + pDevice->nTxDataTimeCout++; + + if(pDevice->nTxDataTimeCout<4) //don't tx data if timer less than 40s + { + // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__, + // (int)pDevice->nTxDataTimeCout); + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + add_timer(&pDevice->sTimerTxData); + return; + } + + spin_lock_irq(&pDevice->lock); + #if 1 + if(((pDevice->bLinkPass ==TRUE)&&(pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking + (pDevice->fWPA_Authened == TRUE)) { //wpa linking + #else + if(pDevice->bLinkPass ==TRUE) { + #endif + + // printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__); + pDevice->fTxDataInSleep = TRUE; + PSbSendNullPacket(pDevice); //send null packet + pDevice->fTxDataInSleep = FALSE; + } + spin_unlock_irq(&pDevice->lock); + + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + add_timer(&pDevice->sTimerTxData); + return; +} +#endif + diff --git a/drivers/staging/vt6655/wcmd.h b/drivers/staging/vt6655/wcmd.h new file mode 100644 index 00000000000..8c6bbc49f0b --- /dev/null +++ b/drivers/staging/vt6655/wcmd.h @@ -0,0 +1,151 @@ +/* + * 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: wcmd.h + * + * Purpose: Handles the management command interface functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + */ + +#ifndef __WCMD_H__ +#define __WCMD_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif + +/*--------------------- Export Definitions -------------------------*/ + + + +#define AUTHENTICATE_TIMEOUT 1000 //ms +#define ASSOCIATE_TIMEOUT 1000 //ms + +// Command code +typedef enum tagCMD_CODE { + WLAN_CMD_BSSID_SCAN, + WLAN_CMD_SSID, + WLAN_CMD_DISASSOCIATE, + WLAN_CMD_DEAUTH, + WLAN_CMD_RX_PSPOLL, + WLAN_CMD_RADIO, + WLAN_CMD_CHANGE_BBSENSITIVITY, + WLAN_CMD_SETPOWER, + WLAN_CMD_TBTT_WAKEUP, + WLAN_CMD_BECON_SEND, + WLAN_CMD_CHANGE_ANTENNA, + WLAN_CMD_REMOVE_ALLKEY, + WLAN_CMD_MAC_DISPOWERSAVING, + WLAN_CMD_11H_CHSW, + WLAN_CMD_RUN_AP +} CMD_CODE, DEF* PCMD_CODE; + +#define CMD_Q_SIZE 32 + + +// Command code +typedef enum tagCMD_STATUS { + + CMD_STATUS_SUCCESS, + CMD_STATUS_FAILURE, + CMD_STATUS_RESOURCES, + CMD_STATUS_TIMEOUT, + CMD_STATUS_PENDING + +} CMD_STATUS, DEF* PCMD_STATUS; + + +typedef struct tagCMD_ITEM { + CMD_CODE eCmd; + BYTE abyCmdDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + BOOL bNeedRadioOFF; + WORD wDeAuthenReason; + BOOL bRadioCmd; + BOOL bForceSCAN; +} CMD_ITEM, DEF* PCMD_ITEM; + +// Command state +typedef enum tagCMD_STATE { + WLAN_CMD_SCAN_START, + WLAN_CMD_SCAN_END, + WLAN_CMD_DISASSOCIATE_START, + WLAN_CMD_SSID_START, + WLAN_AUTHENTICATE_WAIT, + WLAN_ASSOCIATE_WAIT, + WLAN_DISASSOCIATE_WAIT, + WLAN_CMD_TX_PSPACKET_START, + WLAN_CMD_AP_MODE_START, + WLAN_CMD_RADIO_START, + WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE, + WLAN_CMD_IDLE +} CMD_STATE, DEF* PCMD_STATE; + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Types ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + +VOID +vResetCommandTimer( + IN HANDLE hDeviceContext + ); + +VOID +vCommandTimer ( + IN HANDLE hDeviceContext + ); + +BOOL bClearBSSID_SCAN( + IN HANDLE hDeviceContext + ); + +BOOL +bScheduleCommand( + IN HANDLE hDeviceContext, + IN CMD_CODE eCommand, + IN PBYTE pbyItem0 + ); + +VOID +vCommandTimerWait( + IN HANDLE hDeviceContext, + IN UINT MSecond + ); +#ifdef TxInSleep +VOID +BSSvSecondTxData( + IN HANDLE hDeviceContext + ); +#endif +#endif //__WCMD_H__ diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c new file mode 100644 index 00000000000..b4fecc2ed55 --- /dev/null +++ b/drivers/staging/vt6655/wctl.c @@ -0,0 +1,261 @@ +/* + * 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: + * + */ + + +#if !defined(__WCTL_H__) +#include "wctl.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif + +/*--------------------- 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) +{ + UINT uIndex; + UINT 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) && + (IS_ETH_ADDRESS_EQUAL (&(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]), U_ETHER_ADDR_LEN); + 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 + * + */ +UINT WCTLuSearchDFCB (PSDevice pDevice, PS802_11Header pMACHeader) +{ +UINT ii; + + for(ii=0;ii<pDevice->cbDFCB;ii++) { + if ((pDevice->sRxDFCB[ii].bInUse == TRUE) && + (IS_ETH_ADDRESS_EQUAL (&(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 + * + */ +UINT WCTLuInsertDFCB (PSDevice pDevice, PS802_11Header pMACHeader) +{ +UINT 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]), U_ETHER_ADDR_LEN); + 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, UINT cbFrameLength, BOOL bWEP, BOOL bExtIV) +{ +UINT 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 +#ifdef PRIVATE_OBJ + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].ref_skb.data + 4); +#else + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer = (PBYTE) (pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb->data + 4); +#endif + 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++; + //DEVICE_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, ((PBYTE) (pMACHeader) + uHeaderSize), (cbFrameLength - uHeaderSize)); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength += (cbFrameLength - uHeaderSize); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].pbyRxBuffer += (cbFrameLength - uHeaderSize); + pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].wFragNum++; + //DEVICE_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; + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Last pDevice->uCurrentDFCBIdx= %d\n", pDevice->uCurrentDFCBIdx); + return(TRUE); + } + return(FALSE); + } +} + + diff --git a/drivers/staging/vt6655/wctl.h b/drivers/staging/vt6655/wctl.h new file mode 100644 index 00000000000..f75ca59f6c6 --- /dev/null +++ b/drivers/staging/vt6655/wctl.h @@ -0,0 +1,127 @@ +/* + * 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.h + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + + +#ifndef __WCTL_H__ +#define __WCTL_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + +#define IS_TYPE_DATA(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_DATA) + +#define IS_TYPE_MGMT(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_MGMT) + +#define IS_TYPE_CONTROL(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_802_11_MASK) == TYPE_802_11_CTL) + +#define IS_FC_MOREDATA(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREDATA) == FC_MOREDATA) + +#define IS_FC_POWERMGT(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_POWERMGT) == FC_POWERMGT) + +#define IS_FC_RETRY(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_RETRY) == FC_RETRY) + +#define IS_FC_WEP(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_WEP) == FC_WEP) + +#ifdef __BIG_ENDIAN + +#define IS_FRAGMENT_PKT(pMACHeader) \ + (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) | \ + ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) != 0)) + +#define IS_FIRST_FRAGMENT_PKT(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x0F00) == 0) + +#else + +#define IS_FRAGMENT_PKT(pMACHeader) \ + (((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) != 0) | \ + ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) != 0)) + +#define IS_FIRST_FRAGMENT_PKT(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wSeqCtl & 0x000F) == 0) + +#endif//#ifdef __BIG_ENDIAN + +#define IS_LAST_FRAGMENT_PKT(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & FC_MOREFRAG) == 0) + +#define IS_CTL_PSPOLL(pMACHeader) \ + ((((PS802_11Header) pMACHeader)->wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) + + +#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) { \ + if ((uVar) >= ((uModulo) - 1)) \ + (uVar) = 0; \ + else \ + (uVar)++; \ +} + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader); +BOOL WCTLbHandleFragment(PSDevice pDevice, PS802_11Header pMACHeader, UINT cbFrameLength, BOOL bWEP, BOOL bExtIV); +UINT WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader); +UINT WCTLuInsertDFCB(PSDevice pDevice, PS802_11Header pMACHeader); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __WCTL_H__ + + + diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c new file mode 100644 index 00000000000..c5f52e990bd --- /dev/null +++ b/drivers/staging/vt6655/wmgr.c @@ -0,0 +1,5100 @@ +/* + * 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: wmgr.c + * + * Purpose: Handles the 802.11 management functions + * + * Author: Lyndon Chen + * + * Date: May 8, 2002 + * + * Functions: + * nsMgrObjectInitial - Initialize Management Objet data structure + * vMgrObjectReset - Reset Management Objet data structure + * vMgrAssocBeginSta - Start associate function + * vMgrReAssocBeginSta - Start reassociate function + * vMgrDisassocBeginSta - Start disassociate function + * s_vMgrRxAssocRequest - Handle Rcv associate_request + * s_vMgrRxAssocResponse - Handle Rcv associate_response + * vMrgAuthenBeginSta - Start authentication function + * vMgrDeAuthenDeginSta - Start deauthentication function + * s_vMgrRxAuthentication - Handle Rcv authentication + * s_vMgrRxAuthenSequence_1 - Handle Rcv authentication sequence 1 + * s_vMgrRxAuthenSequence_2 - Handle Rcv authentication sequence 2 + * s_vMgrRxAuthenSequence_3 - Handle Rcv authentication sequence 3 + * s_vMgrRxAuthenSequence_4 - Handle Rcv authentication sequence 4 + * s_vMgrRxDisassociation - Handle Rcv disassociation + * s_vMgrRxBeacon - Handle Rcv Beacon + * vMgrCreateOwnIBSS - Create ad_hoc IBSS or AP BSS + * vMgrJoinBSSBegin - Join BSS function + * s_vMgrSynchBSS - Synch & adopt BSS parameters + * s_MgrMakeBeacon - Create Baecon frame + * s_MgrMakeProbeResponse - Create Probe Response frame + * s_MgrMakeAssocRequest - Create Associate Request frame + * s_MgrMakeReAssocRequest - Create ReAssociate Request frame + * s_vMgrRxProbeResponse - Handle Rcv probe_response + * s_vMrgRxProbeRequest - Handle Rcv probe_request + * bMgrPrepareBeaconToSend - Prepare Beacon frame + * s_vMgrLogStatus - Log 802.11 Status + * vMgrRxManagePacket - Rcv management frame dispatch function + * s_vMgrFormatTIM- Assember TIM field of beacon + * vMgrTimerInit- Initial 1-sec and command call back funtions + * + * Revision History: + * + */ + + +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TBIT_H__) +#include "tbit.h" +#endif +#if !defined(__DESC_H__) +#include "desc.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__POWER_H__) +#include "power.h" +#endif +#if !defined(__DATARATE_H__) +#include "datarate.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__WPA_H__) +#include "wpa.h" +#endif +#if !defined(__RF_H__) +#include "rf.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif + +#define PLICE_DEBUG + +/*--------------------- Static Definitions -------------------------*/ + + + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +/*--------------------- Static Functions --------------------------*/ +//2008-8-4 <add> by chester +static BOOL ChannelExceedZoneType( + IN PSDevice pDevice, + IN BYTE byCurrChannel + ); +// Association/diassociation functions +static +PSTxMgmtPacket +s_MgrMakeAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pDAddr, + IN WORD wCurrCapInfo, + IN WORD wListenInterval, + IN PWLAN_IE_SSID pCurrSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + +static +VOID +s_vMgrRxAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN UINT uNodeIndex + ); + +static +PSTxMgmtPacket +s_MgrMakeReAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pDAddr, + IN WORD wCurrCapInfo, + IN WORD wListenInterval, + IN PWLAN_IE_SSID pCurrSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + +static +VOID +s_vMgrRxAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN BOOL bReAssocType + ); + +static +VOID +s_vMgrRxDisassociation( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +// Authentication/deauthen functions +static +VOID +s_vMgrRxAuthenSequence_1( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ); + +static +VOID +s_vMgrRxAuthenSequence_2( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ); + +static +VOID +s_vMgrRxAuthenSequence_3( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ); + +static +VOID +s_vMgrRxAuthenSequence_4( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ); + +static +VOID +s_vMgrRxAuthentication( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +static +VOID +s_vMgrRxDeauthentication( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +// Scan functions +// probe request/response functions +static +VOID +s_vMgrRxProbeRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +static +VOID +s_vMgrRxProbeResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +// beacon functions +static +VOID +s_vMgrRxBeacon( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN BOOL bInScan + ); + +static +VOID +s_vMgrFormatTIM( + IN PSMgmtObject pMgmt, + IN PWLAN_IE_TIM pTIM + ); + +static +PSTxMgmtPacket +s_MgrMakeBeacon( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wCurrBeaconPeriod, + IN UINT uCurrChannel, + IN WORD wCurrATIMWinodw, + IN PWLAN_IE_SSID pCurrSSID, + IN PBYTE pCurrBSSID, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + + +// Association response +static +PSTxMgmtPacket +s_MgrMakeAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wAssocStatus, + IN WORD wAssocAID, + IN PBYTE pDstAddr, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + +// ReAssociation response +static +PSTxMgmtPacket +s_MgrMakeReAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wAssocStatus, + IN WORD wAssocAID, + IN PBYTE pDstAddr, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ); + +// Probe response +static +PSTxMgmtPacket +s_MgrMakeProbeResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wCurrBeaconPeriod, + IN UINT uCurrChannel, + IN WORD wCurrATIMWinodw, + IN PBYTE pDstAddr, + IN PWLAN_IE_SSID pCurrSSID, + IN PBYTE pCurrBSSID, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates, + IN BYTE byPHYType + ); + +// received status +static +VOID +s_vMgrLogStatus( + IN PSMgmtObject pMgmt, + IN WORD wStatus + ); + + +static +VOID +s_vMgrSynchBSS ( + IN PSDevice pDevice, + IN UINT uBSSMode, + IN PKnownBSS pCurr, + OUT PCMD_STATUS pStatus + ); + + +static BOOL +s_bCipherMatch ( + IN PKnownBSS pBSSNode, + IN NDIS_802_11_ENCRYPTION_STATUS EncStatus, + OUT PBYTE pbyCCSPK, + OUT PBYTE pbyCCSGK + ); + + + static VOID Encyption_Rebuild( + IN PSDevice pDevice, + IN PKnownBSS pCurr + ); +/* +static +VOID +s_vProbeChannel( + IN PSDevice pDevice + ); + +static +VOID +s_vListenChannel( + IN PSDevice pDevice + ); + +static +PSTxMgmtPacket +s_MgrMakeProbeRequest( + IN PSMgmtObject pMgmt, + IN PBYTE pScanBSSID, + IN PWLAN_IE_SSID pSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates + ); +*/ + + + +/*--------------------- Export Variables --------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + +/*+ + * + * Routine Description: + * Allocates and initializes the Management object. + * + * Return Value: + * Ndis_staus. + * +-*/ + +VOID +vMgrObjectInit( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + int ii; + + + pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0]; + pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0]; + pMgmt->uCurrChannel = pDevice->uChannel; + for(ii=0;ii<WLAN_BSSID_LEN;ii++) { + pMgmt->abyDesireBSSID[ii] = 0xFF; + } + pMgmt->sAssocInfo.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + //memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN +1); + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_NONE; + pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; + BSSvClearBSSList((HANDLE)pDevice, FALSE); + + return; +} + +/*+ + * + * Routine Description: + * Initializes timer object + * + * Return Value: + * Ndis_staus. + * +-*/ + +void +vMgrTimerInit( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + + + init_timer(&pMgmt->sTimerSecondCallback); + pMgmt->sTimerSecondCallback.data = (ULONG)pDevice; + pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack; + pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ); + + init_timer(&pDevice->sTimerCommand); + pDevice->sTimerCommand.data = (ULONG)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer; + pDevice->sTimerCommand.expires = RUN_AT(HZ); + + #ifdef TxInSleep + init_timer(&pDevice->sTimerTxData); + pDevice->sTimerTxData.data = (ULONG)pDevice; + pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; + pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback + pDevice->fTxDataInSleep = FALSE; + pDevice->IsTxDataTrigger = FALSE; + pDevice->nTxDataTimeCout = 0; + #endif + + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + + return; +} + + + +/*+ + * + * Routine Description: + * Reset the management object structure. + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrObjectReset( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + pDevice->bEnablePSMode = FALSE; + // TODO: timer + + return; +} + + +/*+ + * + * Routine Description: + * Start the station association procedure. Namely, send an + * association request frame to the AP. + * + * Return Value: + * None. + * +-*/ + + +VOID +vMgrAssocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSTxMgmtPacket pTxPacket; + + + pMgmt->wCurrCapInfo = 0; + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + // always allow receive short preamble + //if (pDevice->byPreambleType == 1) { + // pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + //} + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (pMgmt->wListenInterval == 0) + pMgmt->wListenInterval = 1; // at least one. + + // ERP Phy (802.11g) should support short preamble. + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (CARDbIsShorSlotTime(pMgmt->pAdapter) == TRUE) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + } + } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { + if (CARDbIsShortPreamble(pMgmt->pAdapter) == TRUE) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } + } + if (pMgmt->b11hEnable == TRUE) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); + + /* build an assocreq frame and send it */ + pTxPacket = s_MgrMakeAssocRequest + ( + pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + pMgmt->wCurrCapInfo, + pMgmt->wListenInterval, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + /* send the frame */ + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING) { + pMgmt->eCurrState = WMAC_STATE_ASSOCPENDING; + *pStatus = CMD_STATUS_SUCCESS; + } + } + else + *pStatus = CMD_STATUS_RESOURCES; + + return ; +} + + +/*+ + * + * Routine Description: + * Start the station re-association procedure. + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrReAssocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSTxMgmtPacket pTxPacket; + + + + pMgmt->wCurrCapInfo = 0; + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + + //if (pDevice->byPreambleType == 1) { + // pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + //} + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + + if (pMgmt->wListenInterval == 0) + pMgmt->wListenInterval = 1; // at least one. + + + // ERP Phy (802.11g) should support short preamble. + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + if (CARDbIsShorSlotTime(pMgmt->pAdapter) == TRUE) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + } + } else if (pMgmt->eCurrentPHYMode == PHY_TYPE_11B) { + if (CARDbIsShortPreamble(pMgmt->pAdapter) == TRUE) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } + } + if (pMgmt->b11hEnable == TRUE) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); + + + pTxPacket = s_MgrMakeReAssocRequest + ( + pDevice, + pMgmt, + pMgmt->abyCurrBSSID, + pMgmt->wCurrCapInfo, + pMgmt->wListenInterval, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + /* send the frame */ + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx failed.\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Reassociation tx sending.\n"); + } + } + + + return ; +} + +/*+ + * + * Routine Description: + * Send an dis-association request frame to the AP. + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDisassocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PBYTE abyDestAddress, + IN WORD wReason, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_DISASSOC sFrame; + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DISASSOC_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + + // Setup the sFrame structure + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_DISASSOC_FR_MAXLEN; + + // format fixed field frame structure + vMgrEncodeDisassociation(&sFrame); + + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DISASSOC) + )); + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + // Set reason code + *(sFrame.pwReason) = cpu_to_le16(wReason); + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + // send the frame + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING) { + pMgmt->eCurrState = WMAC_STATE_IDLE; + *pStatus = CMD_STATUS_SUCCESS; + }; + + return; +} + + + +/*+ + * + * Routine Description:(AP function) + * Handle incoming station association request frames. + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN UINT uNodeIndex + ) +{ + WLAN_FR_ASSOCREQ sFrame; + CMD_STATUS Status; + PSTxMgmtPacket pTxPacket; + WORD wAssocStatus = 0; + WORD wAssocAID = 0; + UINT uRateLen = WLAN_RATES_MAXLEN; + BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) + return; + // node index not found + if (!uNodeIndex) + return; + + //check if node is authenticated + //decode the frame + memset(&sFrame, 0, sizeof(WLAN_FR_ASSOCREQ)); + memset(abyCurrSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + memset(abyCurrExtSuppRates, 0, WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + + vMgrDecodeAssocRequest(&sFrame); + + if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval); + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = + WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? TRUE : FALSE; + // Todo: check sta basic rate, if ap can't support, set status code + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + uRateLen); + abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + if (pDevice->eCurrentPHYType == PHY_TYPE_11G) { + abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + uRateLen); + } else { + abyCurrExtSuppRates[1] = 0; + } + + + RATEvParseMaxRate((PVOID)pDevice, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + FALSE, // do not change our basic rate + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; +#ifdef PLICE_DEBUG + printk("RxAssocRequest:wTxDataRate is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate); +#endif + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = + WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)uNodeIndex; + wAssocStatus = WLAN_MGMT_STATUS_SUCCESS; + wAssocAID = (WORD)uNodeIndex; + // check if ERP support + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = TRUE; + + if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) { + // B only STA join + pDevice->bProtectMode = TRUE; + pDevice->bNonERPPresent = TRUE; + } + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == FALSE) { + pDevice->bBarkerPreambleMd = TRUE; + } + + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Associate AID= %d \n", wAssocAID); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ) ; + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + }//else { TODO: received STA under state1 handle } + else { + return; + } + + + // assoc response reply.. + pTxPacket = s_MgrMakeAssocResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + wAssocStatus, + wAssocAID, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + if (pTxPacket != NULL ){ + + if (pDevice->bEnableHostapd) { + return; + } + /* send the frame */ + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx failed\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Assoc response tx sending..\n"); + } + + } + + return; +} + + +/*+ + * + * Description:(AP function) + * Handle incoming station re-association request frames. + * + * Parameters: + * In: + * pMgmt - Management Object structure + * pRxPacket - Received Packet + * Out: + * none + * + * Return Value: None. + * +-*/ + +static +VOID +s_vMgrRxReAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN UINT uNodeIndex + ) +{ + WLAN_FR_REASSOCREQ sFrame; + CMD_STATUS Status; + PSTxMgmtPacket pTxPacket; + WORD wAssocStatus = 0; + WORD wAssocAID = 0; + UINT uRateLen = WLAN_RATES_MAXLEN; + BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) + return; + // node index not found + if (!uNodeIndex) + return; + //check if node is authenticated + //decode the frame + memset(&sFrame, 0, sizeof(WLAN_FR_REASSOCREQ)); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeReassocRequest(&sFrame); + + if (pMgmt->sNodeDBTable[uNodeIndex].eNodeState >= NODE_AUTH) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = cpu_to_le16(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = cpu_to_le16(*sFrame.pwListenInterval); + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = + WLAN_GET_FC_PWRMGT(sFrame.pHdr->sA3.wFrameCtl) ? TRUE : FALSE; + // Todo: check sta basic rate, if ap can't support, set status code + + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + uRateLen); + abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + if (pDevice->eCurrentPHYType == PHY_TYPE_11G) { + abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pExtSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + uRateLen); + } else { + abyCurrExtSuppRates[1] = 0; + } + + + RATEvParseMaxRate((PVOID)pDevice, + (PWLAN_IE_SUPP_RATES)abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRates, + FALSE, // do not change our basic rate + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; +#ifdef PLICE_DEBUG + printk("RxReAssocRequest:TxDataRate is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate); +#endif + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = + WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)uNodeIndex; + wAssocStatus = WLAN_MGMT_STATUS_SUCCESS; + wAssocAID = (WORD)uNodeIndex; + + // if suppurt ERP + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = TRUE; + + if (pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate <= RATE_11M) { + // B only STA join + pDevice->bProtectMode = TRUE; + pDevice->bNonERPPresent = TRUE; + } + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble == FALSE) { + pDevice->bBarkerPreambleMd = TRUE; + } + + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Rx ReAssociate AID= %d \n", wAssocAID); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ) ; + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + + } + + + // assoc response reply.. + pTxPacket = s_MgrMakeReAssocResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + wAssocStatus, + wAssocAID, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if (pTxPacket != NULL ){ + /* send the frame */ + if (pDevice->bEnableHostapd) { + return; + } + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx failed\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:ReAssoc response tx sending..\n"); + } + } + return; +} + + +/*+ + * + * Routine Description: + * Handle incoming association response frames. + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN BOOL bReAssocType + ) +{ + WLAN_FR_ASSOCRESP sFrame; + PWLAN_IE_SSID pItemSSID; + PBYTE pbyIEs; + viawget_wpa_header *wpahdr; + + + + if (pMgmt->eCurrState == WMAC_STATE_ASSOCPENDING || + pMgmt->eCurrState == WMAC_STATE_ASSOC) { + + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + // decode the frame + vMgrDecodeAssocResponse(&sFrame); + if ((sFrame.pwCapInfo == 0) || + (sFrame.pwStatus == 0) || + (sFrame.pwAid == 0) || + (sFrame.pSuppRates == 0)){ + DBG_PORT80(0xCC); + return; + }; + + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.Capabilities = *(sFrame.pwCapInfo); + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.StatusCode = *(sFrame.pwStatus); + pMgmt->sAssocInfo.AssocInfo.ResponseFixedIEs.AssociationId = *(sFrame.pwAid); + pMgmt->sAssocInfo.AssocInfo.AvailableResponseFixedIEs |= 0x07; + + pMgmt->sAssocInfo.AssocInfo.ResponseIELength = sFrame.len - 24 - 6; + pMgmt->sAssocInfo.AssocInfo.OffsetResponseIEs = pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs + pMgmt->sAssocInfo.AssocInfo.RequestIELength; + pbyIEs = pMgmt->sAssocInfo.abyIEs; + pbyIEs += pMgmt->sAssocInfo.AssocInfo.RequestIELength; + memcpy(pbyIEs, (sFrame.pBuf + 24 +6), pMgmt->sAssocInfo.AssocInfo.ResponseIELength); + + // save values and set current BSS state + if (cpu_to_le16((*(sFrame.pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + // set AID + pMgmt->wCurrAID = cpu_to_le16((*(sFrame.pwAid))); + if ( (pMgmt->wCurrAID >> 14) != (BIT0 | BIT1) ) + { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "AID from AP, has two msb clear.\n"); + }; + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Association Successful, AID=%d.\n", pMgmt->wCurrAID & ~(BIT14|BIT15)); + pMgmt->eCurrState = WMAC_STATE_ASSOC; + BSSvUpdateAPNode((HANDLE)pDevice, sFrame.pwCapInfo, sFrame.pSuppRates, sFrame.pExtSuppRates); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "Link with AP(SSID): %s\n", pItemSSID->abySSID); + pDevice->bLinkPass = TRUE; + pDevice->uBBVGADiffCount = 0; + if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { + if(skb_tailroom(pDevice->skb) <(sizeof(viawget_wpa_header)+pMgmt->sAssocInfo.AssocInfo.ResponseIELength+ + pMgmt->sAssocInfo.AssocInfo.RequestIELength)) { //data room not enough + dev_kfree_skb(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + } + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_ASSOC_MSG; + wpahdr->resp_ie_len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength; + wpahdr->req_ie_len = pMgmt->sAssocInfo.AssocInfo.RequestIELength; + memcpy(pDevice->skb->data + sizeof(viawget_wpa_header), pMgmt->sAssocInfo.abyIEs, wpahdr->req_ie_len); + memcpy(pDevice->skb->data + sizeof(viawget_wpa_header) + wpahdr->req_ie_len, + pbyIEs, + wpahdr->resp_ie_len + ); + skb_put(pDevice->skb, sizeof(viawget_wpa_header) + wpahdr->resp_ie_len + wpahdr->req_ie_len); + pDevice->skb->dev = pDevice->wpadev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw = pDevice->skb->data; +#endif + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + } + +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //if(pDevice->bWPADevEnable == TRUE) + { + BYTE buf[512]; + size_t len; + union iwreq_data wrqu; + int we_event; + + memset(buf, 0, 512); + + len = pMgmt->sAssocInfo.AssocInfo.RequestIELength; + if(len) { + memcpy(buf, pMgmt->sAssocInfo.abyIEs, len); + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.data.length = len; + we_event = IWEVASSOCREQIE; + wireless_send_event(pDevice->dev, we_event, &wrqu, buf); + } + + memset(buf, 0, 512); + len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength; + + if(len) { + memcpy(buf, pbyIEs, len); + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.data.length = len; + we_event = IWEVASSOCRESPIE; + wireless_send_event(pDevice->dev, we_event, &wrqu, buf); + } + + + memset(&wrqu, 0, sizeof (wrqu)); + memcpy(wrqu.ap_addr.sa_data, &pMgmt->abyCurrBSSID[0], ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } +#endif //#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +//End Add -- //2008-0409-07, <Add> by Einsn Liu + } + else { + if (bReAssocType) { + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + else { + // jump back to the auth state and indicate the error + pMgmt->eCurrState = WMAC_STATE_AUTH; + } + s_vMgrLogStatus(pMgmt,cpu_to_le16((*(sFrame.pwStatus)))); + } + + } + +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +//need clear flags related to Networkmanager + + pDevice->bwextcount = 0; + pDevice->bWPASuppWextEnabled = FALSE; +#endif + + +if(pMgmt->eCurrState == WMAC_STATE_ASSOC) + timer_expire(pDevice->sTimerCommand, 0); + return; +} + + + +/*+ + * + * Routine Description: + * Start the station authentication procedure. Namely, send an + * authentication frame to the AP. + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrAuthenBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + WLAN_FR_AUTHEN sFrame; + PSTxMgmtPacket pTxPacket = NULL; + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + vMgrEncodeAuthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_SHAREDKEY); + else + *(sFrame.pwAuthAlgorithm) = cpu_to_le16(WLAN_AUTH_ALG_OPENSYSTEM); + + *(sFrame.pwAuthSequence) = cpu_to_le16(1); + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING){ + pMgmt->eCurrState = WMAC_STATE_AUTHPENDING; + *pStatus = CMD_STATUS_SUCCESS; + } + + return ; +} + + + +/*+ + * + * Routine Description: + * Start the station(AP) deauthentication procedure. Namely, send an + * deauthentication frame to the AP or Sta. + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrDeAuthenBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PBYTE abyDestAddress, + IN WORD wReason, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + WLAN_FR_DEAUTHEN sFrame; + PSTxMgmtPacket pTxPacket = NULL; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_DEAUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_DEAUTHEN_FR_MAXLEN; + vMgrEncodeDeauthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DEAUTHEN) + )); + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyDestAddress, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *(sFrame.pwReason) = cpu_to_le16(wReason); // deauthen. bcs left BSS + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + *pStatus = csMgmt_xmit(pDevice, pTxPacket); + if (*pStatus == CMD_STATUS_PENDING){ + *pStatus = CMD_STATUS_SUCCESS; + } + + + return ; +} + + +/*+ + * + * Routine Description: + * Handle incoming authentication frames. + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxAuthentication( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + WLAN_FR_AUTHEN sFrame; + + // we better be an AP or a STA in AUTHPENDING otherwise ignore + if (!(pMgmt->eCurrMode == WMAC_MODE_ESS_AP || + pMgmt->eCurrState == WMAC_STATE_AUTHPENDING)) { + return; + } + + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeAuthen(&sFrame); + switch (cpu_to_le16((*(sFrame.pwAuthSequence )))){ + case 1: + //AP funciton + s_vMgrRxAuthenSequence_1(pDevice,pMgmt, &sFrame); + break; + case 2: + s_vMgrRxAuthenSequence_2(pDevice, pMgmt, &sFrame); + break; + case 3: + //AP funciton + s_vMgrRxAuthenSequence_3(pDevice, pMgmt, &sFrame); + break; + case 4: + s_vMgrRxAuthenSequence_4(pDevice, pMgmt, &sFrame); + break; + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Auth Sequence error, seq = %d\n", + cpu_to_le16((*(sFrame.pwAuthSequence)))); + break; + } + return; +} + + + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 1. Currently + * assumes we're an AP. So far, no one appears to use authentication + * in Ad-Hoc mode. + * + * Return Value: + * None. + * +-*/ + + +static +VOID +s_vMgrRxAuthenSequence_1( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + UINT uNodeIndex; + WLAN_FR_AUTHEN sFrame; + PSKeyItem pTransmitKey; + + // Insert a Node entry + if (!BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) { + BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex); + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, pFrame->pHdr->sA3.abyAddr2, + WLAN_ADDR_LEN); + } + + if (pMgmt->bShareKeyAlgorithm) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_KNOWN; + pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 1; + } + else { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH; + } + + // send auth reply + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + // insert values + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(0) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(2); + + if (cpu_to_le16(*(pFrame->pwAuthAlgorithm)) == WLAN_AUTH_ALG_SHAREDKEY) { + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + else + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG); + } + else { + if (pMgmt->bShareKeyAlgorithm) + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG); + else + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + } + + if (pMgmt->bShareKeyAlgorithm && + (cpu_to_le16(*(sFrame.pwStatus)) == WLAN_MGMT_STATUS_SUCCESS)) { + + sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len); + sFrame.len += WLAN_CHALLENGE_IE_LEN; + sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE; + sFrame.pChallenge->len = WLAN_CHALLENGE_LEN; + memset(pMgmt->abyChallenge, 0, WLAN_CHALLENGE_LEN); + // get group key + if(KeybGetTransmitKey(&(pDevice->sKey), pDevice->abyBroadcastAddr, GROUP_KEY, &pTransmitKey) == TRUE) { + rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength+3); + rc4_encrypt(&pDevice->SBox, pMgmt->abyChallenge, pMgmt->abyChallenge, WLAN_CHALLENGE_LEN); + } + memcpy(sFrame.pChallenge->abyChallenge, pMgmt->abyChallenge , WLAN_CHALLENGE_LEN); + } + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (pDevice->bEnableHostapd) { + return; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx.. \n"); + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_1 tx failed.\n"); + } + return; +} + + + +/*+ + * + * Routine Description: + * Handles incoming auth frames with sequence number 2. Currently + * assumes we're a station. + * + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxAuthenSequence_2( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ) +{ + WLAN_FR_AUTHEN sFrame; + PSTxMgmtPacket pTxPacket = NULL; + + + switch (cpu_to_le16((*(pFrame->pwAuthAlgorithm)))) + { + case WLAN_AUTH_ALG_OPENSYSTEM: + if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Successful.\n"); + pMgmt->eCurrState = WMAC_STATE_AUTH; + timer_expire(pDevice->sTimerCommand, 0); + } + else { + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Failed.\n"); + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus)))); + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + if (pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) { +// spin_unlock_irq(&pDevice->lock); +// vCommandTimerWait((HANDLE)pDevice, 0); +// spin_lock_irq(&pDevice->lock); + } + + break; + + case WLAN_AUTH_ALG_SHAREDKEY: + + if (cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS) { + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + // insert values + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(1) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(3); + *(sFrame.pwStatus) = cpu_to_le16(WLAN_MGMT_STATUS_SUCCESS); + sFrame.pChallenge = (PWLAN_IE_CHALLENGE)(sFrame.pBuf + sFrame.len); + sFrame.len += WLAN_CHALLENGE_IE_LEN; + sFrame.pChallenge->byElementID = WLAN_EID_CHALLENGE; + sFrame.pChallenge->len = WLAN_CHALLENGE_LEN; + memcpy( sFrame.pChallenge->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN); + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx failed.\n"); + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Auth_reply sequence_2 tx ...\n"); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:rx Auth_reply sequence_2 status error ...\n"); + if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) { +// spin_unlock_irq(&pDevice->lock); +// vCommandTimerWait((HANDLE)pDevice, 0); +// spin_lock_irq(&pDevice->lock); + } + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus)))); + } + break; + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt: rx auth.seq = 2 unknown AuthAlgorithm=%d\n", cpu_to_le16((*(pFrame->pwAuthAlgorithm)))); + break; + } + return; +} + + + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 3. Currently + * assumes we're an AP. This function assumes the frame has + * already been successfully decrypted. + * + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxAuthenSequence_3( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + UINT uStatusCode = 0 ; + UINT uNodeIndex = 0; + WLAN_FR_AUTHEN sFrame; + + if (!WLAN_GET_FC_ISWEP(pFrame->pHdr->sA3.wFrameCtl)) { + uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL; + goto reply; + } + if (BSSDBbIsSTAInNodeDB(pMgmt, pFrame->pHdr->sA3.abyAddr2, &uNodeIndex)) { + if (pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence != 1) { + uStatusCode = WLAN_MGMT_STATUS_RX_AUTH_NOSEQ; + goto reply; + } + if (memcmp(pMgmt->abyChallenge, pFrame->pChallenge->abyChallenge, WLAN_CHALLENGE_LEN) != 0) { + uStatusCode = WLAN_MGMT_STATUS_CHALLENGE_FAIL; + goto reply; + } + } + else { + uStatusCode = WLAN_MGMT_STATUS_UNSPEC_FAILURE; + goto reply; + } + + if (uNodeIndex) { + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_AUTH; + pMgmt->sNodeDBTable[uNodeIndex].byAuthSequence = 0; + } + uStatusCode = WLAN_MGMT_STATUS_SUCCESS; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Challenge text check ok..\n"); + +reply: + // send auth reply + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_AUTHEN_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_AUTHEN_FR_MAXLEN; + // format buffer structure + vMgrEncodeAuthen(&sFrame); + /* insert values */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_AUTHEN)| + WLAN_SET_FC_ISWEP(0) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pFrame->pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + *(sFrame.pwAuthAlgorithm) = *(pFrame->pwAuthAlgorithm); + *(sFrame.pwAuthSequence) = cpu_to_le16(4); + *(sFrame.pwStatus) = cpu_to_le16(uStatusCode); + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + // send the frame + if (pDevice->bEnableHostapd) { + return; + } + if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Authreq_reply sequence_4 tx failed.\n"); + } + return; + +} + + + +/*+ + * + * Routine Description: + * Handles incoming authen frames with sequence 4 + * + * + * Return Value: + * None. + * +-*/ +static +VOID +s_vMgrRxAuthenSequence_4( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PWLAN_FR_AUTHEN pFrame + ) +{ + + if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){ + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Successful.\n"); + pMgmt->eCurrState = WMAC_STATE_AUTH; + timer_expire(pDevice->sTimerCommand, 0); + } + else{ + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Failed.\n"); + s_vMgrLogStatus(pMgmt, cpu_to_le16((*(pFrame->pwStatus))) ); + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + + if ( pDevice->eCommandState == WLAN_AUTHENTICATE_WAIT ) { +// spin_unlock_irq(&pDevice->lock); +// vCommandTimerWait((HANDLE)pDevice, 0); +// spin_lock_irq(&pDevice->lock); + } + +} + +/*+ + * + * Routine Description: + * Handles incoming disassociation frames + * + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxDisassociation( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + WLAN_FR_DISASSOC sFrame; + UINT uNodeIndex = 0; +// CMD_STATUS CmdStatus; + viawget_wpa_header *wpahdr; + + if ( pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){ + // if is acting an AP.. + // a STA is leaving this BSS.. + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx disassoc, sta not found\n"); + } + } + else if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ){ + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeDisassociation(&sFrame); + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason))); + //TODO: do something let upper layer know or + //try to send associate packet again because of inactivity timeout + // if (pMgmt->eCurrState == WMAC_STATE_ASSOC) { + // vMgrReAssocBeginSta((PSDevice)pDevice, pMgmt, &CmdStatus); + // }; + if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_DISASSOC_MSG; + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw = pDevice->skb->data; +#endif + + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + }; + + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disassociated)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + + } + /* else, ignore it */ + + return; +} + + +/*+ + * + * Routine Description: + * Handles incoming deauthentication frames + * + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxDeauthentication( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + WLAN_FR_DEAUTHEN sFrame; + UINT uNodeIndex = 0; + viawget_wpa_header *wpahdr; + + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){ + //Todo: + // if is acting an AP.. + // a STA is leaving this BSS.. + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Rx deauth, sta not found\n"); + } + } + else { + if (pMgmt->eCurrMode == WMAC_MODE_ESS_STA ) { + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeDeauthen(&sFrame); + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason)))); + // TODO: update BSS list for specific BSSID if pre-authentication case + if (IS_ETH_ADDRESS_EQUAL(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) { + if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) { + pMgmt->sNodeDBTable[0].bActive = FALSE; + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + pDevice->bLinkPass = FALSE; + } + }; + + if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_DISASSOC_MSG; + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + pDevice->skb->mac_header = pDevice->skb->data; +#else + pDevice->skb->mac.raw = pDevice->skb->data; +#endif + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + }; + + #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + // if(pDevice->bWPASuppWextEnabled == TRUE) + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof (wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + printk("wireless_send_event--->SIOCGIWAP(disauthen)\n"); + wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL); + } + #endif + + } + /* else, ignore it. TODO: IBSS authentication service + would be implemented here */ + }; + return; +} + + +//2008-8-4 <add> by chester +/*+ + * + * Routine Description: + * check if current channel is match ZoneType. + *for USA:1~11; + * Japan:1~13; + * Europe:1~13 + * Return Value: + * True:exceed; + * False:normal case +-*/ +static BOOL +ChannelExceedZoneType( + IN PSDevice pDevice, + IN BYTE byCurrChannel + ) +{ + BOOL exceed=FALSE; + + switch(pDevice->byZoneType) { + case 0x00: //USA:1~11 + if((byCurrChannel<1) ||(byCurrChannel>11)) + exceed = TRUE; + break; + case 0x01: //Japan:1~13 + case 0x02: //Europe:1~13 + if((byCurrChannel<1) ||(byCurrChannel>13)) + exceed = TRUE; + break; + default: //reserve for other zonetype + break; + } + + return exceed; +} + + +/*+ + * + * Routine Description: + * Handles and analysis incoming beacon frames. + * + * + * Return Value: + * None. + * +-*/ + +static +VOID +s_vMgrRxBeacon( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket, + IN BOOL bInScan + ) +{ + + PKnownBSS pBSSList; + WLAN_FR_BEACON sFrame; + QWORD qwTSFOffset; + BOOL bIsBSSIDEqual = FALSE; + BOOL bIsSSIDEqual = FALSE; + BOOL bTSFLargeDiff = FALSE; + BOOL bTSFOffsetPostive = FALSE; + BOOL bUpdateTSF = FALSE; + BOOL bIsAPBeacon = FALSE; + BOOL bIsChannelEqual = FALSE; + UINT uLocateByteIndex; + BYTE byTIMBitOn = 0; + WORD wAIDNumber = 0; + UINT uNodeIndex; + QWORD qwTimestamp, qwLocalTSF; + QWORD qwCurrTSF; + WORD wStartIndex = 0; + WORD wAIDIndex = 0; + BYTE byCurrChannel = pRxPacket->byRxChannel; + ERPObject sERP; + UINT uRateLen = WLAN_RATES_MAXLEN; + BOOL bChannelHit = FALSE; + BOOL bUpdatePhyParameter = FALSE; + BYTE byIEChannel = 0; + + + memset(&sFrame, 0, sizeof(WLAN_FR_BEACON)); + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + + // decode the beacon frame + vMgrDecodeBeacon(&sFrame); + + if ((sFrame.pwBeaconInterval == 0) || + (sFrame.pwCapInfo == 0) || + (sFrame.pSSID == 0) || + (sFrame.pSuppRates == 0) ) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx beacon frame error\n"); + return; + }; + + + if (sFrame.pDSParms != NULL) { + if (byCurrChannel > CB_MAX_CHANNEL_24G) { + // channel remapping to + byIEChannel = CARDbyGetChannelMapping(pDevice, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A); + } else { + byIEChannel = sFrame.pDSParms->byCurrChannel; + } + if (byCurrChannel != byIEChannel) { + // adjust channel info. bcs we rcv adjcent channel pakckets + bChannelHit = FALSE; + byCurrChannel = byIEChannel; + } + } else { + // no DS channel info + bChannelHit = TRUE; + } +//2008-0730-01<Add>by MikeLiu +if(ChannelExceedZoneType(pDevice,byCurrChannel)==TRUE) + return; + + if (sFrame.pERP != NULL) { + sERP.byERP = sFrame.pERP->byContext; + sERP.bERPExist = TRUE; + + } else { + sERP.bERPExist = FALSE; + sERP.byERP = 0; + } + + pBSSList = BSSpAddrIsInBSSList((HANDLE)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID); + if (pBSSList == NULL) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon/insert: RxChannel = : %d\n", byCurrChannel); + BSSbInsertToBSSList((HANDLE)pDevice, + sFrame.pHdr->sA3.abyAddr3, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of beacon + (HANDLE)pRxPacket + ); + } + else { +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"update bcn: RxChannel = : %d\n", byCurrChannel); + BSSbUpdateToBSSList((HANDLE)pDevice, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + bChannelHit, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + pBSSList, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of probresponse + (HANDLE)pRxPacket + ); + + } + + if (bInScan) { + return; + } + + if(byCurrChannel == (BYTE)pMgmt->uCurrChannel) + bIsChannelEqual = TRUE; + + if (bIsChannelEqual && (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { + + // if rx beacon without ERP field + if (sERP.bERPExist) { + if (WLAN_GET_ERP_USE_PROTECTION(sERP.byERP)){ + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD; + } + } + else { + pDevice->byERPFlag |= WLAN_SET_ERP_USE_PROTECTION(1); + pDevice->wUseProtectCntDown = USE_PROTECT_PERIOD; + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + if(!WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo)) + pDevice->byERPFlag |= WLAN_SET_ERP_BARKER_MODE(1); + if(!sERP.bERPExist) + pDevice->byERPFlag |= WLAN_SET_ERP_NONERP_PRESENT(1); + } + + // set to MAC&BBP + if (WLAN_GET_ERP_USE_PROTECTION(pDevice->byERPFlag)){ + if (!pDevice->bProtectMode) { + MACvEnableProtectMD(pDevice->PortOffset); + pDevice->bProtectMode = TRUE; + } + } + } + + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) + return; + + // check if BSSID the same + if (memcmp(sFrame.pHdr->sA3.abyAddr3, + pMgmt->abyCurrBSSID, + WLAN_BSSID_LEN) == 0) { + + bIsBSSIDEqual = TRUE; + +// 2008-05-21 <add> by Richardtai + pDevice->uCurrRSSI = pRxPacket->uRSSI; + pDevice->byCurrSQ = pRxPacket->bySQ; + + if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) { + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BCN:Wake Count= [%d]\n", pMgmt->wCountToWakeUp); + } + } + // check if SSID the same + if (sFrame.pSSID->len == ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) { + if (memcmp(sFrame.pSSID->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, + sFrame.pSSID->len + ) == 0) { + bIsSSIDEqual = TRUE; + }; + } + + if ((WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)== TRUE) && + (bIsBSSIDEqual == TRUE) && + (bIsSSIDEqual == TRUE) && + (pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + // add state check to prevent reconnect fail since we'll receive Beacon + + bIsAPBeacon = TRUE; + + if (pBSSList != NULL) { + + // Compare PHY paramater setting + if (pMgmt->wCurrCapInfo != pBSSList->wCapInfo) { + bUpdatePhyParameter = TRUE; + pMgmt->wCurrCapInfo = pBSSList->wCapInfo; + } + if (sFrame.pERP != NULL) { + if ((sFrame.pERP->byElementID == WLAN_EID_ERP) && + (pMgmt->byERPContext != sFrame.pERP->byContext)) { + bUpdatePhyParameter = TRUE; + pMgmt->byERPContext = sFrame.pERP->byContext; + } + } + // + // Basic Rate Set may change dynamiclly + // + if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abySuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + uRateLen); + pMgmt->abyCurrExtSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pBSSList->abyExtSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + uRateLen); + RATEvParseMaxRate( (PVOID)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + TRUE, + &(pMgmt->sNodeDBTable[0].wMaxBasicRate), + &(pMgmt->sNodeDBTable[0].wMaxSuppRate), + &(pMgmt->sNodeDBTable[0].wSuppRate), + &(pMgmt->sNodeDBTable[0].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[0].byTopOFDMBasicRate) + ); +#ifdef PLICE_DEBUG + //printk("RxBeacon:MaxSuppRate is %d\n",pMgmt->sNodeDBTable[0].wMaxSuppRate); +#endif + if (bUpdatePhyParameter == TRUE) { + CARDbSetPhyParameter( pMgmt->pAdapter, + pMgmt->eCurrentPHYMode, + pMgmt->wCurrCapInfo, + pMgmt->byERPContext, + pMgmt->abyCurrSuppRates, + pMgmt->abyCurrExtSuppRates + ); + } + if (sFrame.pIE_PowerConstraint != NULL) { + CARDvSetPowerConstraint(pMgmt->pAdapter, + (BYTE) pBSSList->uChannel, + sFrame.pIE_PowerConstraint->byPower + ); + } + if (sFrame.pIE_CHSW != NULL) { + CARDbChannelSwitch( pMgmt->pAdapter, + sFrame.pIE_CHSW->byMode, + CARDbyGetChannelMapping(pMgmt->pAdapter, sFrame.pIE_CHSW->byMode, pMgmt->eCurrentPHYMode), + sFrame.pIE_CHSW->byCount + ); + + } else if (bIsChannelEqual == FALSE) { + CARDbSetChannel(pMgmt->pAdapter, pBSSList->uChannel); + } + } + } + +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Beacon 2 \n"); + // check if CF field exisit + if (WLAN_GET_CAP_INFO_ESS(*sFrame.pwCapInfo)) { + if (sFrame.pCFParms->wCFPDurRemaining > 0) { + // TODO: deal with CFP period to set NAV + }; + }; + + HIDWORD(qwTimestamp) = cpu_to_le32(HIDWORD(*sFrame.pqwTimestamp)); + LODWORD(qwTimestamp) = cpu_to_le32(LODWORD(*sFrame.pqwTimestamp)); + HIDWORD(qwLocalTSF) = HIDWORD(pRxPacket->qwLocalTSF); + LODWORD(qwLocalTSF) = LODWORD(pRxPacket->qwLocalTSF); + + // check if beacon TSF larger or small than our local TSF + if (HIDWORD(qwTimestamp) == HIDWORD(qwLocalTSF)) { + if (LODWORD(qwTimestamp) >= LODWORD(qwLocalTSF)) { + bTSFOffsetPostive = TRUE; + } + else { + bTSFOffsetPostive = FALSE; + } + } + else if (HIDWORD(qwTimestamp) > HIDWORD(qwLocalTSF)) { + bTSFOffsetPostive = TRUE; + } + else if (HIDWORD(qwTimestamp) < HIDWORD(qwLocalTSF)) { + bTSFOffsetPostive = FALSE; + }; + + if (bTSFOffsetPostive) { + qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwTimestamp), (qwLocalTSF)); + } + else { + qwTSFOffset = CARDqGetTSFOffset(pRxPacket->byRxRate, (qwLocalTSF), (qwTimestamp)); + } + + if (HIDWORD(qwTSFOffset) != 0 || + (LODWORD(qwTSFOffset) > TRIVIAL_SYNC_DIFFERENCE )) { + bTSFLargeDiff = TRUE; + } + + + // if infra mode + if (bIsAPBeacon == TRUE) { + + // Infra mode: Local TSF always follow AP's TSF if Difference huge. + if (bTSFLargeDiff) + bUpdateTSF = TRUE; + + if ((pDevice->bEnablePSMode == TRUE) &&(sFrame.pTIM != 0)) { + + // deal with DTIM, analysis TIM + pMgmt->bMulticastTIM = WLAN_MGMT_IS_MULTICAST_TIM(sFrame.pTIM->byBitMapCtl) ? TRUE : FALSE ; + pMgmt->byDTIMCount = sFrame.pTIM->byDTIMCount; + pMgmt->byDTIMPeriod = sFrame.pTIM->byDTIMPeriod; + wAIDNumber = pMgmt->wCurrAID & ~(BIT14|BIT15); + + // check if AID in TIM field bit on + // wStartIndex = N1 + wStartIndex = WLAN_MGMT_GET_TIM_OFFSET(sFrame.pTIM->byBitMapCtl) << 1; + // AIDIndex = N2 + wAIDIndex = (wAIDNumber >> 3); + if ((wAIDNumber > 0) && (wAIDIndex >= wStartIndex)) { + uLocateByteIndex = wAIDIndex - wStartIndex; + // len = byDTIMCount + byDTIMPeriod + byDTIMPeriod + byVirtBitMap[0~250] + if (sFrame.pTIM->len >= (uLocateByteIndex + 4)) { + byTIMBitOn = (0x01) << ((wAIDNumber) % 8); + pMgmt->bInTIM = sFrame.pTIM->byVirtBitMap[uLocateByteIndex] & byTIMBitOn ? TRUE : FALSE; + } + else { + pMgmt->bInTIM = FALSE; + }; + } + else { + pMgmt->bInTIM = FALSE; + }; + + if (pMgmt->bInTIM || + (pMgmt->bMulticastTIM && (pMgmt->byDTIMCount == 0))) { + pMgmt->bInTIMWake = TRUE; + // send out ps-poll packet +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN:In TIM\n"); + if (pMgmt->bInTIM) { + PSvSendPSPOLL((PSDevice)pDevice); +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN:PS-POLL sent..\n"); + }; + + } + else { + pMgmt->bInTIMWake = FALSE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Not In TIM..\n"); + if (pDevice->bPWBitOn == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Send Null Packet\n"); + if (PSbSendNullPacket(pDevice)) + pDevice->bPWBitOn = TRUE; + } + if(PSbConsiderPowerDown(pDevice, FALSE, FALSE)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "BCN: Power down now...\n"); + }; + } + + } + + } + // if adhoc mode + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && !bIsAPBeacon && bIsChannelEqual) { + if (bIsBSSIDEqual) { + // Use sNodeDBTable[0].uInActiveCount as IBSS beacons received count. + if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + + // adhoc mode:TSF updated only when beacon larger then local TSF + if (bTSFLargeDiff && bTSFOffsetPostive && + (pMgmt->eCurrState == WMAC_STATE_JOINTED)) + bUpdateTSF = TRUE; + + // During dpc, already in spinlocked. + if (BSSDBbIsSTAInNodeDB(pMgmt, sFrame.pHdr->sA3.abyAddr2, &uNodeIndex)) { + + // Update the STA, (Techically the Beacons of all the IBSS nodes + // should be identical, but that's not happening in practice. + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + RATEvParseMaxRate( (PVOID)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, + TRUE, + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].uInActiveCount = 0; + } + else { + // Todo, initial Node content + BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex); + + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + RATEvParseMaxRate( (PVOID)pDevice, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, + TRUE, + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].wSuppRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopCCKBasicRate), + &(pMgmt->sNodeDBTable[uNodeIndex].byTopOFDMBasicRate) + ); + + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, sFrame.pHdr->sA3.abyAddr2, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = WLAN_GET_CAP_INFO_SHORTPREAMBLE(*sFrame.pwCapInfo); + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; +#ifdef PLICE_DEBUG + //if (uNodeIndex == 0) + { + printk("s_vMgrRxBeacon:TxDataRate is %d,Index is %d\n",pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate,uNodeIndex); + } +#endif +/* + pMgmt->sNodeDBTable[uNodeIndex].bShortSlotTime = WLAN_GET_CAP_INFO_SHORTSLOTTIME(*sFrame.pwCapInfo); + if(pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate > RATE_11M) + pMgmt->sNodeDBTable[uNodeIndex].bERPExist = TRUE; +*/ + } + + // if other stations jointed, indicate connect to upper layer.. + if (pMgmt->eCurrState == WMAC_STATE_STARTED) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Current IBSS State: [Started]........to: [Jointed] \n"); + pMgmt->eCurrState = WMAC_STATE_JOINTED; + pDevice->bLinkPass = TRUE; + if (netif_queue_stopped(pDevice->dev)){ + netif_wake_queue(pDevice->dev); + } + pMgmt->sNodeDBTable[0].bActive = TRUE; + pMgmt->sNodeDBTable[0].uInActiveCount = 0; + + }; + } + else if (bIsSSIDEqual) { + + // See other adhoc sta with the same SSID but BSSID is different. + // adpot this vars only when TSF larger then us. + if (bTSFLargeDiff && bTSFOffsetPostive) { + // we don't support ATIM under adhoc mode + // if ( sFrame.pIBSSParms->wATIMWindow == 0) { + // adpot this vars + // TODO: check sFrame cap if privacy on, and support rate syn + memcpy(pMgmt->abyCurrBSSID, sFrame.pHdr->sA3.abyAddr3, WLAN_BSSID_LEN); + memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + pMgmt->wCurrATIMWindow = cpu_to_le16(sFrame.pIBSSParms->wATIMWindow); + pMgmt->wCurrBeaconPeriod = cpu_to_le16(*sFrame.pwBeaconInterval); + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)sFrame.pSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + // set HW beacon interval and re-synchronizing.... + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rejoining to Other Adhoc group with same SSID........\n"); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_BI, pMgmt->wCurrBeaconPeriod); + CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, qwLocalTSF); + CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod); + // Turn off bssid filter to avoid filter others adhoc station which bssid is different. + MACvWriteBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID); + + CARDbSetPhyParameter ( pMgmt->pAdapter, + pMgmt->eCurrentPHYMode, + pMgmt->wCurrCapInfo, + pMgmt->byERPContext, + pMgmt->abyCurrSuppRates, + pMgmt->abyCurrExtSuppRates); + + + // MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_BSSID); + // set highest basic rate + // s_vSetHighestBasicRate(pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates); + // Prepare beacon frame + bMgrPrepareBeaconToSend((HANDLE)pDevice, pMgmt); + // } + }; + } + }; + // endian issue ??? + // Update TSF + if (bUpdateTSF) { + CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF); + CARDbUpdateTSF(pDevice, pRxPacket->byRxRate, qwTimestamp, pRxPacket->qwLocalTSF); + CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF); + CARDvUpdateNextTBTT(pDevice->PortOffset, qwTimestamp, pMgmt->wCurrBeaconPeriod); + } + + return; +} + + + +/*+ + * + * Routine Description: + * Instructs the hw to create a bss using the supplied + * attributes. Note that this implementation only supports Ad-Hoc + * BSS creation. + * + * + * Return Value: + * CMD_STATUS + * +-*/ +VOID +vMgrCreateOwnIBSS( + IN HANDLE hDeviceContext, + OUT PCMD_STATUS pStatus + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + WORD wMaxBasicRate; + WORD wMaxSuppRate; + BYTE byTopCCKBasicRate; + BYTE byTopOFDMBasicRate; + QWORD qwCurrTSF; + UINT ii; + BYTE abyRATE[] = {0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, 0x0C, 0x12, 0x18, 0x60}; + BYTE abyCCK_RATE[] = {0x82, 0x84, 0x8B, 0x96}; + BYTE abyOFDM_RATE[] = {0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + WORD wSuppRate; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Create Basic Service Set .......\n"); + + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) && + (pDevice->eEncryptionStatus != Ndis802_11Encryption2Enabled) && + (pDevice->eEncryptionStatus != Ndis802_11Encryption3Enabled)) { + // encryption mode error + *pStatus = CMD_STATUS_FAILURE; + return; + } + } + + pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + pMgmt->abyCurrExtSuppRates[0] = WLAN_EID_EXTSUPP_RATES; + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + pMgmt->eCurrentPHYMode = pMgmt->byAPBBType; + } else { + if (pDevice->byBBType == BB_TYPE_11G) + pMgmt->eCurrentPHYMode = PHY_TYPE_11G; + if (pDevice->byBBType == BB_TYPE_11B) + pMgmt->eCurrentPHYMode = PHY_TYPE_11B; + if (pDevice->byBBType == BB_TYPE_11A) + pMgmt->eCurrentPHYMode = PHY_TYPE_11A; + } + + if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) { + pMgmt->abyCurrSuppRates[1] = WLAN_RATES_MAXLEN_11B; + pMgmt->abyCurrExtSuppRates[1] = 0; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii]; + } else { + pMgmt->abyCurrSuppRates[1] = 8; + pMgmt->abyCurrExtSuppRates[1] = 0; + for (ii = 0; ii < 8; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyRATE[ii]; + } + + + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + pMgmt->abyCurrSuppRates[1] = 8; + pMgmt->abyCurrExtSuppRates[1] = 4; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyCCK_RATE[ii]; + for (ii = 4; ii < 8; ii++) + pMgmt->abyCurrSuppRates[2+ii] = abyOFDM_RATE[ii-4]; + for (ii = 0; ii < 4; ii++) + pMgmt->abyCurrExtSuppRates[2+ii] = abyOFDM_RATE[ii+4]; + } + + + // Disable Protect Mode + pDevice->bProtectMode = 0; + MACvDisableProtectMD(pDevice->PortOffset); + + pDevice->bBarkerPreambleMd = 0; + MACvDisableBarkerPreambleMd(pDevice->PortOffset); + + // Kyle Test 2003.11.04 + + // set HW beacon interval + if (pMgmt->wIBSSBeaconPeriod == 0) + pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; + + + CARDbGetCurrentTSF(pDevice->PortOffset, &qwCurrTSF); + // clear TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); + // enable TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + + // set Next TBTT + CARDvSetFirstNextTBTT(pDevice->PortOffset, pMgmt->wIBSSBeaconPeriod); + + pMgmt->uIBSSChannel = pDevice->uChannel; + + if (pMgmt->uIBSSChannel == 0) + pMgmt->uIBSSChannel = DEFAULT_IBSS_CHANNEL; + + + // set basic rate + + RATEvParseMaxRate((PVOID)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, TRUE, + &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + pMgmt->eCurrMode = WMAC_MODE_ESS_AP; + } + + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + MEMvCopy(pMgmt->abyIBSSDFSOwner, pDevice->abyCurrentNetAddr, 6); + pMgmt->byIBSSDFSRecovery = 10; + pMgmt->eCurrMode = WMAC_MODE_IBSS_STA; + } + + // Adopt pre-configured IBSS vars to current vars + pMgmt->eCurrState = WMAC_STATE_STARTED; + pMgmt->wCurrBeaconPeriod = pMgmt->wIBSSBeaconPeriod; + pMgmt->uCurrChannel = pMgmt->uIBSSChannel; + pMgmt->wCurrATIMWindow = pMgmt->wIBSSATIMWindow; + MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); + pDevice->uCurrRSSI = 0; + pDevice->byCurrSQ = 0; + //memcpy(pMgmt->abyDesireSSID,pMgmt->abyAdHocSSID, + // ((PWLAN_IE_SSID)pMgmt->abyAdHocSSID)->len + WLAN_IEHDR_LEN); + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyCurrSSID, + pMgmt->abyDesireSSID, + ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->len + WLAN_IEHDR_LEN + ); + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + // AP mode BSSID = MAC addr + memcpy(pMgmt->abyCurrBSSID, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO"AP beacon created BSSID:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + + // BSSID selected must be randomized as spec 11.1.3 + pMgmt->abyCurrBSSID[5] = (BYTE) (LODWORD(qwCurrTSF)& 0x000000ff); + pMgmt->abyCurrBSSID[4] = (BYTE)((LODWORD(qwCurrTSF)& 0x0000ff00) >> 8); + pMgmt->abyCurrBSSID[3] = (BYTE)((LODWORD(qwCurrTSF)& 0x00ff0000) >> 16); + pMgmt->abyCurrBSSID[2] = (BYTE)((LODWORD(qwCurrTSF)& 0x00000ff0) >> 4); + pMgmt->abyCurrBSSID[1] = (BYTE)((LODWORD(qwCurrTSF)& 0x000ff000) >> 12); + pMgmt->abyCurrBSSID[0] = (BYTE)((LODWORD(qwCurrTSF)& 0x0ff00000) >> 20); + pMgmt->abyCurrBSSID[5] ^= pMgmt->abyMACAddr[0]; + pMgmt->abyCurrBSSID[4] ^= pMgmt->abyMACAddr[1]; + pMgmt->abyCurrBSSID[3] ^= pMgmt->abyMACAddr[2]; + pMgmt->abyCurrBSSID[2] ^= pMgmt->abyMACAddr[3]; + pMgmt->abyCurrBSSID[1] ^= pMgmt->abyMACAddr[4]; + pMgmt->abyCurrBSSID[0] ^= pMgmt->abyMACAddr[5]; + pMgmt->abyCurrBSSID[0] &= ~IEEE_ADDR_GROUP; + pMgmt->abyCurrBSSID[0] |= IEEE_ADDR_UNIVERSAL; + + + DEVICE_PRT(MSG_LEVEL_INFO, KERN_INFO"Adhoc beacon created bssid:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); + } + + // Set Capability Info + pMgmt->wCurrCapInfo = 0; + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_ESS(1); + pMgmt->byDTIMPeriod = DEFAULT_DTIM_PERIOD; + pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1; + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_IBSS(1); + } + + if (pDevice->bEncryptionEnable) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + pMgmt->byCSSPK = KEY_CTL_CCMP; + pMgmt->byCSSGK = KEY_CTL_CCMP; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + pMgmt->byCSSPK = KEY_CTL_TKIP; + pMgmt->byCSSGK = KEY_CTL_TKIP; + } else { + pMgmt->byCSSPK = KEY_CTL_NONE; + pMgmt->byCSSGK = KEY_CTL_WEP; + } + } else { + pMgmt->byCSSPK = KEY_CTL_WEP; + pMgmt->byCSSGK = KEY_CTL_WEP; + } + }; + + pMgmt->byERPContext = 0; + +// memcpy(pDevice->abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_AP); + } else { + CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, OP_MODE_ADHOC); + } + + CARDbSetPhyParameter( pMgmt->pAdapter, + pMgmt->eCurrentPHYMode, + pMgmt->wCurrCapInfo, + pMgmt->byERPContext, + pMgmt->abyCurrSuppRates, + pMgmt->abyCurrExtSuppRates + ); + + CARDbSetBeaconPeriod(pMgmt->pAdapter, pMgmt->wIBSSBeaconPeriod); + // set channel and clear NAV + CARDbSetChannel(pMgmt->pAdapter, pMgmt->uIBSSChannel); + pMgmt->uCurrChannel = pMgmt->uIBSSChannel; + + if (CARDbIsShortPreamble(pMgmt->pAdapter)) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTPREAMBLE(1); + } else { + pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SHORTPREAMBLE(1)); + } + + if ((pMgmt->b11hEnable == TRUE) && + (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SPECTRUMMNG(1); + } else { + pMgmt->wCurrCapInfo &= (~WLAN_SET_CAP_INFO_SPECTRUMMNG(1)); + } + + pMgmt->eCurrState = WMAC_STATE_STARTED; + // Prepare beacon to send + if (bMgrPrepareBeaconToSend((HANDLE)pDevice, pMgmt)) { + *pStatus = CMD_STATUS_SUCCESS; + } + + return ; +} + + + +/*+ + * + * Routine Description: + * Instructs wmac to join a bss using the supplied attributes. + * The arguments may the BSSID or SSID and the rest of the + * attributes are obtained from the scan result of known bss list. + * + * + * Return Value: + * None. + * +-*/ + +VOID +vMgrJoinBSSBegin( + IN HANDLE hDeviceContext, + OUT PCMD_STATUS pStatus + ) +{ + + PSDevice pDevice = (PSDevice)hDeviceContext; + PSMgmtObject pMgmt = pDevice->pMgmt; + PKnownBSS pCurr = NULL; + UINT ii, uu; + PWLAN_IE_SUPP_RATES pItemRates = NULL; + PWLAN_IE_SUPP_RATES pItemExtRates = NULL; + PWLAN_IE_SSID pItemSSID; + UINT uRateLen = WLAN_RATES_MAXLEN; + WORD wMaxBasicRate = RATE_1M; + WORD wMaxSuppRate = RATE_1M; + WORD wSuppRate; + BYTE byTopCCKBasicRate = RATE_1M; + BYTE byTopOFDMBasicRate = RATE_1M; + + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + if (pMgmt->sBSSList[ii].bActive == TRUE) + break; + } + + if (ii == MAX_BSS_NUM) { + *pStatus = CMD_STATUS_RESOURCES; + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "BSS finding:BSS list is empty.\n"); + return; + }; + + // memset(pMgmt->abyDesireBSSID, 0, WLAN_BSSID_LEN); + // Search known BSS list for prefer BSSID or SSID + + pCurr = BSSpSearchBSSList(pDevice, + pMgmt->abyDesireBSSID, + pMgmt->abyDesireSSID, + pMgmt->eConfigPHYMode + ); + + if (pCurr == NULL){ + *pStatus = CMD_STATUS_RESOURCES; + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Scanning [%s] not found, disconnected !\n", pItemSSID->abySSID); + return; + }; + + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP(BSS) finding:Found a AP(BSS)..\n"); + if (WLAN_GET_CAP_INFO_ESS(cpu_to_le16(pCurr->wCapInfo))){ + + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPA)||(pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)) { + + // patch for CISCO migration mode +/* + if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No match RSN info. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } +*/ + } + +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + //if(pDevice->bWPASuppWextEnabled == TRUE) + Encyption_Rebuild(pDevice, pCurr); +#endif + // Infrastructure BSS + s_vMgrSynchBSS(pDevice, + WMAC_MODE_ESS_STA, + pCurr, + pStatus + ); + + if (*pStatus == CMD_STATUS_SUCCESS){ + + // Adopt this BSS state vars in Mgmt Object + pMgmt->uCurrChannel = pCurr->uChannel; + + memset(pMgmt->abyCurrSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + memset(pMgmt->abyCurrExtSuppRates, 0 , WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1); + + if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) { + uRateLen = WLAN_RATES_MAXLEN_11B; + } + + pItemRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates; + pItemExtRates = (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates; + + // Parse Support Rate IE + pItemRates->byElementID = WLAN_EID_SUPP_RATES; + pItemRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates, + pItemRates, + uRateLen); + + // Parse Extension Support Rate IE + pItemExtRates->byElementID = WLAN_EID_EXTSUPP_RATES; + pItemExtRates->len = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abyExtSuppRates, + pItemExtRates, + uRateLen); + // Stuffing Rate IE + if ((pItemExtRates->len > 0) && (pItemRates->len < 8)) { + for (ii = 0; ii < (UINT)(8 - pItemRates->len); ) { + pItemRates->abyRates[pItemRates->len + ii] = pItemExtRates->abyRates[ii]; + ii ++; + if (pItemExtRates->len <= ii) + break; + } + pItemRates->len += (BYTE)ii; + if (pItemExtRates->len - ii > 0) { + pItemExtRates->len -= (BYTE)ii; + for (uu = 0; uu < pItemExtRates->len; uu ++) { + pItemExtRates->abyRates[uu] = pItemExtRates->abyRates[uu + ii]; + } + } else { + pItemExtRates->len = 0; + } + } + + RATEvParseMaxRate((PVOID)pDevice, pItemRates, pItemExtRates, TRUE, + &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + + // TODO: deal with if wCapInfo the privacy is on, but station WEP is off + // TODO: deal with if wCapInfo the PS-Pollable is on. + pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval; + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + + pMgmt->eCurrMode = WMAC_MODE_ESS_STA; + + pMgmt->eCurrState = WMAC_STATE_JOINTED; + // Adopt BSS state in Adapter Device Object + //pDevice->byOpMode = OP_MODE_INFRASTRUCTURE; +// memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + + // Add current BSS to Candidate list + // This should only works for WPA2 BSS, and WPA2 BSS check must be done before. + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + BOOL bResult = bAdd_PMKID_Candidate((HANDLE)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate: 1(%d)\n", bResult); + if (bResult == FALSE) { + vFlush_PMKID_Candidate((HANDLE)pDevice); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFlush_PMKID_Candidate: 4\n"); + bAdd_PMKID_Candidate((HANDLE)pDevice, pMgmt->abyCurrBSSID, &pCurr->sRSNCapObj); + } + } + + // Preamble type auto-switch: if AP can receive short-preamble cap, + // we can turn on too. + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join ESS\n"); + + + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"End of Join AP -- A/B/G Action\n"); + } + else { + pMgmt->eCurrState = WMAC_STATE_IDLE; + }; + + + } + else { + // ad-hoc mode BSS + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + + if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (WPA_SearchRSN(0, WPA_TKIP, pCurr) == FALSE) { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (WPA_SearchRSN(0, WPA_AESCCMP, pCurr) == FALSE) { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } else { + // encryption mode error + pMgmt->eCurrState = WMAC_STATE_IDLE; + return; + } + } + + s_vMgrSynchBSS(pDevice, + WMAC_MODE_IBSS_STA, + pCurr, + pStatus + ); + + if (*pStatus == CMD_STATUS_SUCCESS){ + // Adopt this BSS state vars in Mgmt Object + // TODO: check if CapInfo privacy on, but we don't.. + pMgmt->uCurrChannel = pCurr->uChannel; + + + // Parse Support Rate IE + pMgmt->abyCurrSuppRates[0] = WLAN_EID_SUPP_RATES; + pMgmt->abyCurrSuppRates[1] = RATEuSetIE((PWLAN_IE_SUPP_RATES)pCurr->abySuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + WLAN_RATES_MAXLEN_11B); + // set basic rate + RATEvParseMaxRate((PVOID)pDevice, (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + NULL, TRUE, &wMaxBasicRate, &wMaxSuppRate, &wSuppRate, + &byTopCCKBasicRate, &byTopOFDMBasicRate); + + pMgmt->wCurrCapInfo = pCurr->wCapInfo; + pMgmt->wCurrBeaconPeriod = pCurr->wBeaconInterval; + memset(pMgmt->abyCurrSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN); + memcpy(pMgmt->abyCurrBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + memcpy(pMgmt->abyCurrSSID, pCurr->abySSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN); +// pMgmt->wCurrATIMWindow = pCurr->wATIMWindow; + MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); + pMgmt->eCurrMode = WMAC_MODE_IBSS_STA; + + pMgmt->eCurrState = WMAC_STATE_STARTED; + // Adopt BSS state in Adapter Device Object + //pDevice->byOpMode = OP_MODE_ADHOC; +// pDevice->bLinkPass = TRUE; +// memcpy(pDevice->abyBSSID, pCurr->abyBSSID, WLAN_BSSID_LEN); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Join IBSS ok:%02x-%02x-%02x-%02x-%02x-%02x \n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5] + ); + // Preamble type auto-switch: if AP can receive short-preamble cap, + // and if registry setting is short preamble we can turn on too. + + // Prepare beacon + bMgrPrepareBeaconToSend((HANDLE)pDevice, pMgmt); + } + else { + pMgmt->eCurrState = WMAC_STATE_IDLE; + }; + }; + return; +} + + + +/*+ + * + * Routine Description: + * Set HW to synchronize a specific BSS from known BSS list. + * + * + * Return Value: + * PCM_STATUS + * +-*/ +static +VOID +s_vMgrSynchBSS ( + IN PSDevice pDevice, + IN UINT uBSSMode, + IN PKnownBSS pCurr, + OUT PCMD_STATUS pStatus + ) +{ + CARD_PHY_TYPE ePhyType = PHY_TYPE_11B; + PSMgmtObject pMgmt = pDevice->pMgmt; +// int ii; + //1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M + BYTE abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C}; + BYTE abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60}; + //6M, 9M, 12M, 48M + BYTE abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; + BYTE abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16}; + + + *pStatus = CMD_STATUS_FAILURE; + + if (s_bCipherMatch(pCurr, + pDevice->eEncryptionStatus, + &(pMgmt->byCSSPK), + &(pMgmt->byCSSGK)) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "s_bCipherMatch Fail .......\n"); + return; + } + + pMgmt->pCurrBSS = pCurr; + + // if previous mode is IBSS. + if(pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_BCNDMACTL, BEACON_READY); + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); + } + + // Init the BSS informations + pDevice->bCCK = TRUE; + pDevice->bProtectMode = FALSE; + MACvDisableProtectMD(pDevice->PortOffset); + pDevice->bBarkerPreambleMd = FALSE; + MACvDisableBarkerPreambleMd(pDevice->PortOffset); + pDevice->bNonERPPresent = FALSE; + pDevice->byPreambleType = 0; + pDevice->wBasicRate = 0; + // Set Basic Rate + CARDbAddBasicRate((PVOID)pDevice, RATE_1M); + // calculate TSF offset + // TSF Offset = Received Timestamp TSF - Marked Local's TSF + CARDbUpdateTSF(pDevice, pCurr->byRxRate, pCurr->qwBSSTimestamp, pCurr->qwLocalTSF); + + CARDbSetBeaconPeriod(pDevice, pCurr->wBeaconInterval); + + // set Next TBTT + // Next TBTT = ((local_current_TSF / beacon_interval) + 1 ) * beacon_interval + CARDvSetFirstNextTBTT(pDevice->PortOffset, pCurr->wBeaconInterval); + + // set BSSID + MACvWriteBSSIDAddress(pDevice->PortOffset, pCurr->abyBSSID); + + MACvReadBSSIDAddress(pDevice->PortOffset, pMgmt->abyCurrBSSID); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:set CurrBSSID address = %02x-%02x-%02x=%02x-%02x-%02x\n", + pMgmt->abyCurrBSSID[0], + pMgmt->abyCurrBSSID[1], + pMgmt->abyCurrBSSID[2], + pMgmt->abyCurrBSSID[3], + pMgmt->abyCurrBSSID[4], + pMgmt->abyCurrBSSID[5]); + + if (pCurr->eNetworkTypeInUse == PHY_TYPE_11A) { + if ((pMgmt->eConfigPHYMode == PHY_TYPE_11A) || + (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) { + ePhyType = PHY_TYPE_11A; + } else { + return; + } + } else if (pCurr->eNetworkTypeInUse == PHY_TYPE_11B) { + if ((pMgmt->eConfigPHYMode == PHY_TYPE_11B) || + (pMgmt->eConfigPHYMode == PHY_TYPE_11G) || + (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) { + ePhyType = PHY_TYPE_11B; + } else { + return; + } + } else { + if ((pMgmt->eConfigPHYMode == PHY_TYPE_11G) || + (pMgmt->eConfigPHYMode == PHY_TYPE_AUTO)) { + ePhyType = PHY_TYPE_11G; + } else if (pMgmt->eConfigPHYMode == PHY_TYPE_11B) { + ePhyType = PHY_TYPE_11B; + } else { + return; + } + } + + if (ePhyType == PHY_TYPE_11A) { + MEMvCopy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesA[0], sizeof(abyCurrSuppRatesA)); + pMgmt->abyCurrExtSuppRates[1] = 0; + } else if (ePhyType == PHY_TYPE_11B) { + MEMvCopy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesB[0], sizeof(abyCurrSuppRatesB)); + pMgmt->abyCurrExtSuppRates[1] = 0; + } else { + MEMvCopy(pMgmt->abyCurrSuppRates, &abyCurrSuppRatesG[0], sizeof(abyCurrSuppRatesG)); + MEMvCopy(pMgmt->abyCurrExtSuppRates, &abyCurrExtSuppRatesG[0], sizeof(abyCurrExtSuppRatesG)); + } + + + if (WLAN_GET_CAP_INFO_ESS(pCurr->wCapInfo)) { + CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_INFRASTRUCTURE); + // Add current BSS to Candidate list + // This should only works for WPA2 BSS, and WPA2 BSS check must be done before. + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + CARDbAdd_PMKID_Candidate(pMgmt->pAdapter, pMgmt->abyCurrBSSID, pCurr->sRSNCapObj.bRSNCapExist, pCurr->sRSNCapObj.wRSNCap); + } + } else { + CARDbSetBSSID(pMgmt->pAdapter, pCurr->abyBSSID, OP_MODE_ADHOC); + } + + if (CARDbSetPhyParameter( pMgmt->pAdapter, + ePhyType, + pCurr->wCapInfo, + pCurr->sERP.byERP, + pMgmt->abyCurrSuppRates, + pMgmt->abyCurrExtSuppRates + ) != TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Phy Mode Fail [%d]\n", ePhyType); + return; + } + // set channel and clear NAV + if (CARDbSetChannel(pMgmt->pAdapter, pCurr->uChannel) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "<----s_bSynchBSS Set Channel [%d]\n", pCurr->uChannel); + return; + } + +/* + for (ii=0;ii<BB_VGA_LEVEL;ii++) { + if (pCurr->ldBmMAX< pDevice->ldBmThreshold[ii]) { + pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; + break; + } + } + + if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RSSI[%d] NewGain[%d] OldGain[%d] \n", + (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent); + printk("RSSI[%d] NewGain[%d] OldGain[%d] \n", + (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent); + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); + } + printk("ldBmMAX[%d] NewGain[%d] OldGain[%d] \n", + (int)pCurr->ldBmMAX, pDevice->byBBVGANew, pDevice->byBBVGACurrent); +*/ + pMgmt->uCurrChannel = pCurr->uChannel; + pMgmt->eCurrentPHYMode = ePhyType; + pMgmt->byERPContext = pCurr->sERP.byERP; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Sync:Set to channel = [%d]\n", (INT)pCurr->uChannel); + + + *pStatus = CMD_STATUS_SUCCESS; + + + return; +}; + +//mike add: fix NetworkManager 0.7.0 hidden ssid mode in WPA encryption +// ,need reset eAuthenMode and eEncryptionStatus + static VOID Encyption_Rebuild( + IN PSDevice pDevice, + IN PKnownBSS pCurr + ) + { + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + // UINT ii , uSameBssidNum=0; + + // for (ii = 0; ii < MAX_BSS_NUM; ii++) { + // if (pMgmt->sBSSList[ii].bActive && + // IS_ETH_ADDRESS_EQUAL(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) { + // uSameBssidNum++; + // } + // } + // if( uSameBssidNum>=2) { //we only check AP in hidden sssid mode + if ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || //networkmanager 0.7.0 does not give the pairwise-key selsection, + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { // so we need re-selsect it according to real pairwise-key info. + if(pCurr->bWPAValid == TRUE) { //WPA-PSK + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + if(pCurr->abyPKType[0] == WPA_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP + printk("Encyption_Rebuild--->ssid reset config to [WPAPSK-TKIP]\n"); + } + else if(pCurr->abyPKType[0] == WPA_AESCCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; //AES + printk("Encyption_Rebuild--->ssid reset config to [WPAPSK-AES]\n"); + } + } + else if(pCurr->bWPA2Valid == TRUE) { //WPA2-PSK + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; //TKIP + printk("Encyption_Rebuild--->ssid reset config to [WPA2PSK-TKIP]\n"); + } + else if(pCurr->abyCSSPK[0] == WLAN_11i_CSS_CCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; //AES + printk("Encyption_Rebuild--->ssid reset config to [WPA2PSK-AES]\n"); + } + } + } + // } + return; + } + + +/*+ + * + * Routine Description: + * Format TIM field + * + * + * Return Value: + * VOID + * +-*/ + +static +VOID +s_vMgrFormatTIM( + IN PSMgmtObject pMgmt, + IN PWLAN_IE_TIM pTIM + ) +{ + BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + BYTE byMap; + UINT ii, jj; + BOOL bStartFound = FALSE; + BOOL bMulticast = FALSE; + WORD wStartIndex = 0; + WORD wEndIndex = 0; + + + // Find size of partial virtual bitmap + for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) { + byMap = pMgmt->abyPSTxMap[ii]; + if (!ii) { + // Mask out the broadcast bit which is indicated separately. + bMulticast = (byMap & byMask[0]) != 0; + if(bMulticast) { + pMgmt->sNodeDBTable[0].bRxPSPoll = TRUE; + } + byMap = 0; + } + if (byMap) { + if (!bStartFound) { + bStartFound = TRUE; + wStartIndex = ii; + } + wEndIndex = ii; + } + }; + + + // Round start index down to nearest even number + wStartIndex &= ~BIT0; + + // Round end index up to nearest even number + wEndIndex = ((wEndIndex + 1) & ~BIT0); + + // Size of element payload + + pTIM->len = 3 + (wEndIndex - wStartIndex) + 1; + + // Fill in the Fixed parts of the TIM + pTIM->byDTIMCount = pMgmt->byDTIMCount; + pTIM->byDTIMPeriod = pMgmt->byDTIMPeriod; + pTIM->byBitMapCtl = (bMulticast ? TIM_MULTICAST_MASK : 0) | + (((wStartIndex >> 1) << 1) & TIM_BITMAPOFFSET_MASK); + + // Append variable part of TIM + + for (ii = wStartIndex, jj =0 ; ii <= wEndIndex; ii++, jj++) { + pTIM->byVirtBitMap[jj] = pMgmt->abyPSTxMap[ii]; + } + + // Aid = 0 don't used. + pTIM->byVirtBitMap[0] &= ~BIT0; +} + + +/*+ + * + * Routine Description: + * Constructs an Beacon frame( Ad-hoc mode) + * + * + * Return Value: + * PTR to frame; or NULL on allocation failue + * +-*/ + +static +PSTxMgmtPacket +s_MgrMakeBeacon( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wCurrBeaconPeriod, + IN UINT uCurrChannel, + IN WORD wCurrATIMWinodw, + IN PWLAN_IE_SSID pCurrSSID, + IN PBYTE pCurrBSSID, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_BEACON sFrame; + BYTE abyBroadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + PBYTE pbyBuffer; + UINT uLength = 0; + PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; + UINT ii; + + // prepare beacon frame + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_BEACON_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + // Setup the sFrame structure. + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_BEACON_FR_MAXLEN; + vMgrEncodeBeacon(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_BEACON) + )); + + if (pDevice->bEnablePSMode) { + sFrame.pHdr->sA3.wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_PWRMGT(1)); + } + + memcpy( sFrame.pHdr->sA3.abyAddr1, abyBroadcastAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN); + *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod); + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + // Copy SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, + pCurrSSID, + ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN + ); + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + // DS parameter + if (pDevice->eCurrentPHYType != PHY_TYPE_11A) { + sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (1) + WLAN_IEHDR_LEN; + sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS; + sFrame.pDSParms->len = 1; + sFrame.pDSParms->byCurrChannel = (BYTE)uCurrChannel; + } + // TIM field + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + sFrame.pTIM = (PWLAN_IE_TIM)(sFrame.pBuf + sFrame.len); + sFrame.pTIM->byElementID = WLAN_EID_TIM; + s_vMgrFormatTIM(pMgmt, sFrame.pTIM); + sFrame.len += (WLAN_IEHDR_LEN + sFrame.pTIM->len); + } + + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + + // IBSS parameter + sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (2) + WLAN_IEHDR_LEN; + sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS; + sFrame.pIBSSParms->len = 2; + sFrame.pIBSSParms->wATIMWindow = wCurrATIMWinodw; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + /* RSN parameter */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 12; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x04;//AES + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x02;//TKIP + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) + sFrame.pRSNWPA->abyMulticast[3] = 0x01;//WEP40 + else + sFrame.pRSNWPA->abyMulticast[3] = 0x00;//NONE + + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 0; + // Auth Key Management Suite + *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + sFrame.pRSNWPA->len +=2; + + // RSN Capabilites + *((PWORD)(sFrame.pBuf + sFrame.len + sFrame.pRSNWPA->len))=0; + sFrame.pRSNWPA->len +=2; + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + } + } + + if ((pMgmt->b11hEnable == TRUE) && + (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { + // Country IE + pbyBuffer = (PBYTE)(sFrame.pBuf + sFrame.len); + CARDvSetCountryIE(pMgmt->pAdapter, pbyBuffer); + CARDvSetCountryInfo(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer); + uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN; + pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN); + // Power Constrain IE + ((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT; + ((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1; + ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0; + pbyBuffer += (1) + WLAN_IEHDR_LEN; + uLength += (1) + WLAN_IEHDR_LEN; + if (pMgmt->bSwitchChannel == TRUE) { + // Channel Switch IE + ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH; + ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3; + ((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1; + ((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = CARDbyGetChannelNumber(pMgmt->pAdapter, pMgmt->byNewChannel); + ((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0; + pbyBuffer += (3) + WLAN_IEHDR_LEN; + uLength += (3) + WLAN_IEHDR_LEN; + } + // TPC report + ((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP; + ((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2; + ((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); + ((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0; + pbyBuffer += (2) + WLAN_IEHDR_LEN; + uLength += (2) + WLAN_IEHDR_LEN; + // IBSS DFS + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) { + pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer; + pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS; + pIBSSDFS->len = 7; + MEMvCopy( pIBSSDFS->abyDFSOwner, + pMgmt->abyIBSSDFSOwner, + 6); + pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery; + pbyBuffer += (7) + WLAN_IEHDR_LEN; + uLength += (7) + WLAN_IEHDR_LEN; + for(ii=CB_MAX_CHANNEL_24G+1; ii<=CB_MAX_CHANNEL; ii++ ) { + if (CARDbGetChannelMapInfo(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == TRUE) { + pbyBuffer += 2; + uLength += 2; + pIBSSDFS->len += 2; + } + } + } + sFrame.len += uLength; + } + + if (pMgmt->eCurrentPHYMode == PHY_TYPE_11G) { + sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len); + sFrame.len += 1 + WLAN_IEHDR_LEN; + sFrame.pERP->byElementID = WLAN_EID_ERP; + sFrame.pERP->len = 1; + sFrame.pERP->byContext = 0; + if (pDevice->bProtectMode == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; + if (pDevice->bNonERPPresent == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; + if (pDevice->bBarkerPreambleMd == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; + } + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + MEMvCopy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + // hostapd wpa/wpa2 IE + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == TRUE)) { + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pMgmt->wWPAIELen != 0) { + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen); + sFrame.len += pMgmt->wWPAIELen; + } + } + } + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + + + + +/*+ + * + * Routine Description: + * Constructs an Prob-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failue + * +-*/ + + + + +PSTxMgmtPacket +s_MgrMakeProbeResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wCurrBeaconPeriod, + IN UINT uCurrChannel, + IN WORD wCurrATIMWinodw, + IN PBYTE pDstAddr, + IN PWLAN_IE_SSID pCurrSSID, + IN PBYTE pCurrBSSID, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates, + IN BYTE byPHYType + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_PROBERESP sFrame; + PBYTE pbyBuffer; + UINT uLength = 0; + PWLAN_IE_IBSS_DFS pIBSSDFS = NULL; + UINT ii; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBERESP_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + // Setup the sFrame structure. + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_PROBERESP_FR_MAXLEN; + vMgrEncodeProbeResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBERESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pCurrBSSID, WLAN_BSSID_LEN); + *sFrame.pwBeaconInterval = cpu_to_le16(wCurrBeaconPeriod); + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + + if (byPHYType == BB_TYPE_11B) { + *sFrame.pwCapInfo &= cpu_to_le16((WORD)~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1))); + } + + // Copy SSID + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, + pCurrSSID, + ((PWLAN_IE_SSID)pCurrSSID)->len + WLAN_IEHDR_LEN + ); + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + // DS parameter + if (pDevice->eCurrentPHYType != PHY_TYPE_11A) { + sFrame.pDSParms = (PWLAN_IE_DS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (1) + WLAN_IEHDR_LEN; + sFrame.pDSParms->byElementID = WLAN_EID_DS_PARMS; + sFrame.pDSParms->len = 1; + sFrame.pDSParms->byCurrChannel = (BYTE)uCurrChannel; + } + + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) { + // IBSS parameter + sFrame.pIBSSParms = (PWLAN_IE_IBSS_PARMS)(sFrame.pBuf + sFrame.len); + sFrame.len += (2) + WLAN_IEHDR_LEN; + sFrame.pIBSSParms->byElementID = WLAN_EID_IBSS_PARMS; + sFrame.pIBSSParms->len = 2; + sFrame.pIBSSParms->wATIMWindow = 0; + } + if (pDevice->eCurrentPHYType == PHY_TYPE_11G) { + sFrame.pERP = (PWLAN_IE_ERP)(sFrame.pBuf + sFrame.len); + sFrame.len += 1 + WLAN_IEHDR_LEN; + sFrame.pERP->byElementID = WLAN_EID_ERP; + sFrame.pERP->len = 1; + sFrame.pERP->byContext = 0; + if (pDevice->bProtectMode == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_USE_PROTECTION; + if (pDevice->bNonERPPresent == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_NONERP_PRESENT; + if (pDevice->bBarkerPreambleMd == TRUE) + sFrame.pERP->byContext |= WLAN_EID_ERP_BARKER_MODE; + } + + if ((pMgmt->b11hEnable == TRUE) && + (pMgmt->eCurrentPHYMode == PHY_TYPE_11A)) { + // Country IE + pbyBuffer = (PBYTE)(sFrame.pBuf + sFrame.len); + CARDvSetCountryIE(pMgmt->pAdapter, pbyBuffer); + CARDvSetCountryInfo(pMgmt->pAdapter, PHY_TYPE_11A, pbyBuffer); + uLength += ((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN; + pbyBuffer += (((PWLAN_IE_COUNTRY) pbyBuffer)->len + WLAN_IEHDR_LEN); + // Power Constrain IE + ((PWLAN_IE_PW_CONST) pbyBuffer)->byElementID = WLAN_EID_PWR_CONSTRAINT; + ((PWLAN_IE_PW_CONST) pbyBuffer)->len = 1; + ((PWLAN_IE_PW_CONST) pbyBuffer)->byPower = 0; + pbyBuffer += (1) + WLAN_IEHDR_LEN; + uLength += (1) + WLAN_IEHDR_LEN; + if (pMgmt->bSwitchChannel == TRUE) { + // Channel Switch IE + ((PWLAN_IE_CH_SW) pbyBuffer)->byElementID = WLAN_EID_CH_SWITCH; + ((PWLAN_IE_CH_SW) pbyBuffer)->len = 3; + ((PWLAN_IE_CH_SW) pbyBuffer)->byMode = 1; + ((PWLAN_IE_CH_SW) pbyBuffer)->byChannel = CARDbyGetChannelNumber(pMgmt->pAdapter, pMgmt->byNewChannel); + ((PWLAN_IE_CH_SW) pbyBuffer)->byCount = 0; + pbyBuffer += (3) + WLAN_IEHDR_LEN; + uLength += (3) + WLAN_IEHDR_LEN; + } + // TPC report + ((PWLAN_IE_TPC_REP) pbyBuffer)->byElementID = WLAN_EID_TPC_REP; + ((PWLAN_IE_TPC_REP) pbyBuffer)->len = 2; + ((PWLAN_IE_TPC_REP) pbyBuffer)->byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); + ((PWLAN_IE_TPC_REP) pbyBuffer)->byLinkMargin = 0; + pbyBuffer += (2) + WLAN_IEHDR_LEN; + uLength += (2) + WLAN_IEHDR_LEN; + // IBSS DFS + if (pMgmt->eCurrMode != WMAC_MODE_ESS_AP) { + pIBSSDFS = (PWLAN_IE_IBSS_DFS) pbyBuffer; + pIBSSDFS->byElementID = WLAN_EID_IBSS_DFS; + pIBSSDFS->len = 7; + MEMvCopy( pIBSSDFS->abyDFSOwner, + pMgmt->abyIBSSDFSOwner, + 6); + pIBSSDFS->byDFSRecovery = pMgmt->byIBSSDFSRecovery; + pbyBuffer += (7) + WLAN_IEHDR_LEN; + uLength += (7) + WLAN_IEHDR_LEN; + for(ii=CB_MAX_CHANNEL_24G+1; ii<=CB_MAX_CHANNEL; ii++ ) { + if (CARDbGetChannelMapInfo(pMgmt->pAdapter, ii, pbyBuffer, pbyBuffer+1) == TRUE) { + pbyBuffer += 2; + uLength += 2; + pIBSSDFS->len += 2; + } + } + } + sFrame.len += uLength; + } + + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + MEMvCopy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // hostapd wpa/wpa2 IE + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && (pDevice->bEnableHostapd == TRUE)) { + if (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) { + if (pMgmt->wWPAIELen != 0) { + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + memcpy(sFrame.pRSN, pMgmt->abyWPAIE, pMgmt->wWPAIELen); + sFrame.len += pMgmt->wWPAIELen; + } + } + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + + +/*+ + * + * Routine Description: + * Constructs an association request frame + * + * + * Return Value: + * A ptr to frame or NULL on allocation failue + * +-*/ + + +PSTxMgmtPacket +s_MgrMakeAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pDAddr, + IN WORD wCurrCapInfo, + IN WORD wListenInterval, + IN PWLAN_IE_SSID pCurrSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_ASSOCREQ sFrame; + PBYTE pbyIEs; + PBYTE pbyRSN; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + // Setup the sFrame structure. + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_ASSOCREQ_FR_MAXLEN; + // format fixed field frame structure + vMgrEncodeAssocRequest(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + // Set the capibility and listen interval + *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); + *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); + + // sFrame.len point to end of fixed field + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + + pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN; + pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pbyIEs = pMgmt->sAssocInfo.abyIEs; + MEMvCopy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN; + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + if ((pDevice->eCurrentPHYType == PHY_TYPE_11B) && (pCurrRates->len > 4)) + sFrame.len += 4 + WLAN_IEHDR_LEN; + else + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + + // Copy the extension rate set + if ((pDevice->eCurrentPHYType == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + + pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN; + + // for 802.11h + if (pMgmt->b11hEnable == TRUE) { + if (sFrame.pCurrPowerCap == NULL) { + sFrame.pCurrPowerCap = (PWLAN_IE_PW_CAP)(sFrame.pBuf + sFrame.len); + sFrame.len += (2 + WLAN_IEHDR_LEN); + sFrame.pCurrPowerCap->byElementID = WLAN_EID_PWR_CAPABILITY; + sFrame.pCurrPowerCap->len = 2; + CARDvGetPowerCapability(pMgmt->pAdapter, + &(sFrame.pCurrPowerCap->byMinPower), + &(sFrame.pCurrPowerCap->byMaxPower) + ); + } + if (sFrame.pCurrSuppCh == NULL) { + sFrame.pCurrSuppCh = (PWLAN_IE_SUPP_CH)(sFrame.pBuf + sFrame.len); + sFrame.len += CARDbySetSupportChannels(pMgmt->pAdapter,(PBYTE)sFrame.pCurrSuppCh); + } + } + + if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) && + (pMgmt->pCurrBSS != NULL)) { + /* WPA IE */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 16; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE; + } + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 1; + sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00; + sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50; + sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; + } + // Auth Key Management Suite + pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + *pbyRSN++=0x01; + *pbyRSN++=0x00; + *pbyRSN++=0x00; + *pbyRSN++=0x50; + *pbyRSN++=0xf2; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) { + *pbyRSN++=WPA_AUTH_PSK; + } + else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) { + *pbyRSN++=WPA_AUTH_IEEE802_1X; + } + else { + *pbyRSN++=WPA_NONE; + } + sFrame.pRSNWPA->len +=6; + + // RSN Capabilites + *pbyRSN++=0x00; + *pbyRSN++=0x00; + sFrame.pRSNWPA->len +=2; + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + + } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && + (pMgmt->pCurrBSS != NULL)) { + UINT ii; + PWORD pwPMKID; + + // WPA IE + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + sFrame.pRSN->byElementID = WLAN_EID_RSN; + sFrame.pRSN->len = 6; //Version(2)+GK(4) + sFrame.pRSN->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSN->abyRSN[0] = 0x00; + sFrame.pRSN->abyRSN[1] = 0x0F; + sFrame.pRSN->abyRSN[2] = 0xAC; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP; + } else { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; + } + + // Pairwise Key Cipher Suite + sFrame.pRSN->abyRSN[4] = 1; + sFrame.pRSN->abyRSN[5] = 0; + sFrame.pRSN->abyRSN[6] = 0x00; + sFrame.pRSN->abyRSN[7] = 0x0F; + sFrame.pRSN->abyRSN[8] = 0xAC; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP; + } else if (pMgmt->byCSSPK == KEY_CTL_NONE) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; + } else { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; + } + sFrame.pRSN->len += 6; + + // Auth Key Management Suite + sFrame.pRSN->abyRSN[10] = 1; + sFrame.pRSN->abyRSN[11] = 0; + sFrame.pRSN->abyRSN[12] = 0x00; + sFrame.pRSN->abyRSN[13] = 0x0F; + sFrame.pRSN->abyRSN[14] = 0xAC; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X; + } else { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; + } + sFrame.pRSN->len +=6; + + // RSN Capabilites + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == TRUE) { + MEMvCopy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); + } else { + sFrame.pRSN->abyRSN[16] = 0; + sFrame.pRSN->abyRSN[17] = 0; + } + sFrame.pRSN->len +=2; + + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == TRUE) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + // RSN PMKID + pbyRSN = &sFrame.pRSN->abyRSN[18]; + pwPMKID = (PWORD)pbyRSN; // Point to PMKID count + *pwPMKID = 0; // Initialize PMKID count + pbyRSN += 2; // Point to PMKID list + for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { + if (MEMEqualMemory(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, U_ETHER_ADDR_LEN)) { + (*pwPMKID) ++; + MEMvCopy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16); + pbyRSN += 16; + } + } + if (*pwPMKID != 0) { + sFrame.pRSN->len += (2 + (*pwPMKID)*16); + } + } + + sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN; + } + + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + return pTxPacket; +} + + + + + + + + +/*+ + * + * Routine Description: + * Constructs an re-association request frame + * + * + * Return Value: + * A ptr to frame or NULL on allocation failue + * +-*/ + + +PSTxMgmtPacket +s_MgrMakeReAssocRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PBYTE pDAddr, + IN WORD wCurrCapInfo, + IN WORD wListenInterval, + IN PWLAN_IE_SSID pCurrSSID, + IN PWLAN_IE_SUPP_RATES pCurrRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_REASSOCREQ sFrame; + PBYTE pbyIEs; + PBYTE pbyRSN; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset( pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_REASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + /* Setup the sFrame structure. */ + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCREQ_FR_MAXLEN; + + // format fixed field frame structure + vMgrEncodeReassocRequest(&sFrame); + + /* Setup the header */ + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCREQ) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + /* Set the capibility and listen interval */ + *(sFrame.pwCapInfo) = cpu_to_le16(wCurrCapInfo); + *(sFrame.pwListenInterval) = cpu_to_le16(wListenInterval); + + memcpy(sFrame.pAddrCurrAP, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + /* Copy the SSID */ + /* sFrame.len point to end of fixed field */ + sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrSSID->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSSID, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + + pMgmt->sAssocInfo.AssocInfo.RequestIELength = pCurrSSID->len + WLAN_IEHDR_LEN; + pMgmt->sAssocInfo.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pbyIEs = pMgmt->sAssocInfo.abyIEs; + MEMvCopy(pbyIEs, pCurrSSID, pCurrSSID->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrSSID->len + WLAN_IEHDR_LEN; + + /* Copy the rate set */ + /* sFrame.len point to end of SSID */ + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + + // Copy the extension rate set + if ((pMgmt->eCurrentPHYMode == PHY_TYPE_11G) && (pCurrExtSuppRates->len > 0)) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN); + } + + pMgmt->sAssocInfo.AssocInfo.RequestIELength += pCurrRates->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN); + pbyIEs += pCurrRates->len + WLAN_IEHDR_LEN; + + if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE)) && + (pMgmt->pCurrBSS != NULL)) { + /* WPA IE */ + sFrame.pRSNWPA = (PWLAN_IE_RSN_EXT)(sFrame.pBuf + sFrame.len); + sFrame.pRSNWPA->byElementID = WLAN_EID_RSN_WPA; + sFrame.pRSNWPA->len = 16; + sFrame.pRSNWPA->abyOUI[0] = 0x00; + sFrame.pRSNWPA->abyOUI[1] = 0x50; + sFrame.pRSNWPA->abyOUI[2] = 0xf2; + sFrame.pRSNWPA->abyOUI[3] = 0x01; + sFrame.pRSNWPA->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSNWPA->abyMulticast[0] = 0x00; + sFrame.pRSNWPA->abyMulticast[1] = 0x50; + sFrame.pRSNWPA->abyMulticast[2] = 0xf2; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSNWPA->abyMulticast[3] = pMgmt->pCurrBSS->byGKType; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->abyMulticast[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->abyMulticast[3] = WPA_NONE; + } + // Pairwise Key Cipher Suite + sFrame.pRSNWPA->wPKCount = 1; + sFrame.pRSNWPA->PKSList[0].abyOUI[0] = 0x00; + sFrame.pRSNWPA->PKSList[0].abyOUI[1] = 0x50; + sFrame.pRSNWPA->PKSList[0].abyOUI[2] = 0xf2; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_AESCCMP; + } else { + sFrame.pRSNWPA->PKSList[0].abyOUI[3] = WPA_NONE; + } + // Auth Key Management Suite + pbyRSN = (PBYTE)(sFrame.pBuf + sFrame.len + 2 + sFrame.pRSNWPA->len); + *pbyRSN++=0x01; + *pbyRSN++=0x00; + *pbyRSN++=0x00; + *pbyRSN++=0x50; + *pbyRSN++=0xf2; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) { + *pbyRSN++=WPA_AUTH_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA) { + *pbyRSN++=WPA_AUTH_IEEE802_1X; + } else { + *pbyRSN++=WPA_NONE; + } + sFrame.pRSNWPA->len +=6; + + // RSN Capabilites + *pbyRSN++=0x00; + *pbyRSN++=0x00; + sFrame.pRSNWPA->len +=2; + sFrame.len += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, sFrame.pRSNWPA, sFrame.pRSNWPA->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSNWPA->len + WLAN_IEHDR_LEN; + + } else if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && + (pMgmt->pCurrBSS != NULL)) { + UINT ii; + PWORD pwPMKID; + + /* WPA IE */ + sFrame.pRSN = (PWLAN_IE_RSN)(sFrame.pBuf + sFrame.len); + sFrame.pRSN->byElementID = WLAN_EID_RSN; + sFrame.pRSN->len = 6; //Version(2)+GK(4) + sFrame.pRSN->wVersion = 1; + //Group Key Cipher Suite + sFrame.pRSN->abyRSN[0] = 0x00; + sFrame.pRSN->abyRSN[1] = 0x0F; + sFrame.pRSN->abyRSN[2] = 0xAC; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + sFrame.pRSN->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_CCMP; + } else { + sFrame.pRSN->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; + } + + // Pairwise Key Cipher Suite + sFrame.pRSN->abyRSN[4] = 1; + sFrame.pRSN->abyRSN[5] = 0; + sFrame.pRSN->abyRSN[6] = 0x00; + sFrame.pRSN->abyRSN[7] = 0x0F; + sFrame.pRSN->abyRSN[8] = 0xAC; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_CCMP; + } else if (pMgmt->byCSSPK == KEY_CTL_NONE) { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; + } else { + sFrame.pRSN->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; + } + sFrame.pRSN->len += 6; + + // Auth Key Management Suite + sFrame.pRSN->abyRSN[10] = 1; + sFrame.pRSN->abyRSN[11] = 0; + sFrame.pRSN->abyRSN[12] = 0x00; + sFrame.pRSN->abyRSN[13] = 0x0F; + sFrame.pRSN->abyRSN[14] = 0xAC; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_802_1X; + } else { + sFrame.pRSN->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; + } + sFrame.pRSN->len +=6; + + // RSN Capabilites + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == TRUE) { + MEMvCopy(&sFrame.pRSN->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); + } else { + sFrame.pRSN->abyRSN[16] = 0; + sFrame.pRSN->abyRSN[17] = 0; + } + sFrame.pRSN->len +=2; + + if ((pDevice->gsPMKID.BSSIDInfoCount > 0) && (pDevice->bRoaming == TRUE) && (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + // RSN PMKID + pbyRSN = &sFrame.pRSN->abyRSN[18]; + pwPMKID = (PWORD)pbyRSN; // Point to PMKID count + *pwPMKID = 0; // Initialize PMKID count + pbyRSN += 2; // Point to PMKID list + for (ii = 0; ii < pDevice->gsPMKID.BSSIDInfoCount; ii++) { + if (MEMEqualMemory(&pDevice->gsPMKID.BSSIDInfo[ii].BSSID[0], pMgmt->abyCurrBSSID, U_ETHER_ADDR_LEN)) { + (*pwPMKID) ++; + MEMvCopy(pbyRSN, pDevice->gsPMKID.BSSIDInfo[ii].PMKID, 16); + pbyRSN += 16; + } + } + if (*pwPMKID != 0) { + sFrame.pRSN->len += (2 + (*pwPMKID)*16); + } + } + + sFrame.len += sFrame.pRSN->len + WLAN_IEHDR_LEN; + // copy to AssocInfo. for OID_802_11_ASSOCIATION_INFORMATION + pMgmt->sAssocInfo.AssocInfo.RequestIELength += sFrame.pRSN->len + WLAN_IEHDR_LEN; + MEMvCopy(pbyIEs, sFrame.pRSN, sFrame.pRSN->len + WLAN_IEHDR_LEN); + pbyIEs += sFrame.pRSN->len + WLAN_IEHDR_LEN; + } + + + /* Adjust the length fields */ + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + + +/*+ + * + * Routine Description: + * Constructs an assoc-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failue + * +-*/ + + +PSTxMgmtPacket +s_MgrMakeAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wAssocStatus, + IN WORD wAssocAID, + IN PBYTE pDstAddr, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_ASSOCRESP sFrame; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + // Setup the sFrame structure + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; + vMgrEncodeAssocResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ASSOCRESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + *sFrame.pwStatus = cpu_to_le16(wAssocStatus); + *sFrame.pwAid = cpu_to_le16((WORD)(wAssocAID | BIT14 | BIT15)); + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + MEMvCopy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + +/*+ + * + * Routine Description: + * Constructs an reassoc-response frame + * + * + * Return Value: + * PTR to frame; or NULL on allocation failue + * +-*/ + + +PSTxMgmtPacket +s_MgrMakeReAssocResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN WORD wCurrCapInfo, + IN WORD wAssocStatus, + IN WORD wAssocAID, + IN PBYTE pDstAddr, + IN PWLAN_IE_SUPP_RATES pCurrSuppRates, + IN PWLAN_IE_SUPP_RATES pCurrExtSuppRates + ) +{ + PSTxMgmtPacket pTxPacket = NULL; + WLAN_FR_REASSOCRESP sFrame; + + + pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; + memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_ASSOCREQ_FR_MAXLEN); + pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket)); + // Setup the sFrame structure + sFrame.pBuf = (PBYTE)pTxPacket->p80211Header; + sFrame.len = WLAN_REASSOCRESP_FR_MAXLEN; + vMgrEncodeReassocResponse(&sFrame); + // Setup the header + sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16( + ( + WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_REASSOCRESP) + )); + memcpy( sFrame.pHdr->sA3.abyAddr1, pDstAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN); + memcpy( sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); + + *sFrame.pwCapInfo = cpu_to_le16(wCurrCapInfo); + *sFrame.pwStatus = cpu_to_le16(wAssocStatus); + *sFrame.pwAid = cpu_to_le16((WORD)(wAssocAID | BIT14 | BIT15)); + + // Copy the rate set + sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN; + memcpy(sFrame.pSuppRates, + pCurrSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrSuppRates)->len + WLAN_IEHDR_LEN + ); + + if (((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len != 0) { + sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len); + sFrame.len += ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN; + MEMvCopy(sFrame.pExtSuppRates, + pCurrExtSuppRates, + ((PWLAN_IE_SUPP_RATES)pCurrExtSuppRates)->len + WLAN_IEHDR_LEN + ); + } + + // Adjust the length fields + pTxPacket->cbMPDULen = sFrame.len; + pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN; + + return pTxPacket; +} + + +/*+ + * + * Routine Description: + * Handles probe response management frames. + * + * + * Return Value: + * none. + * +-*/ + +static +VOID +s_vMgrRxProbeResponse( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + PKnownBSS pBSSList = NULL; + WLAN_FR_PROBERESP sFrame; + BYTE byCurrChannel = pRxPacket->byRxChannel; + ERPObject sERP; + BYTE byIEChannel = 0; + BOOL bChannelHit = TRUE; + + + memset(&sFrame, 0, sizeof(WLAN_FR_PROBERESP)); + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeProbeResponse(&sFrame); + + if ((sFrame.pqwTimestamp == 0) || + (sFrame.pwBeaconInterval == 0) || + (sFrame.pwCapInfo == 0) || + (sFrame.pSSID == 0) || + (sFrame.pSuppRates == 0)) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p] \n", pRxPacket->p80211Header); + DBG_PORT80(0xCC); + return; + }; + + if(sFrame.pSSID->len == 0) + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rx Probe resp: SSID len = 0 \n"); + + if (sFrame.pDSParms != 0) { + if (byCurrChannel > CB_MAX_CHANNEL_24G) { + // channel remapping to + byIEChannel = CARDbyGetChannelMapping(pMgmt->pAdapter, sFrame.pDSParms->byCurrChannel, PHY_TYPE_11A); + } else { + byIEChannel = sFrame.pDSParms->byCurrChannel; + } + if (byCurrChannel != byIEChannel) { + // adjust channel info. bcs we rcv adjcent channel pakckets + bChannelHit = FALSE; + byCurrChannel = byIEChannel; + } + } else { + // no DS channel info + bChannelHit = TRUE; + } + +//2008-0730-01<Add>by MikeLiu +if(ChannelExceedZoneType(pDevice,byCurrChannel)==TRUE) + return; + + if (sFrame.pERP != NULL) { + sERP.byERP = sFrame.pERP->byContext; + sERP.bERPExist = TRUE; + } else { + sERP.bERPExist = FALSE; + sERP.byERP = 0; + } + + + // update or insert the bss + pBSSList = BSSpAddrIsInBSSList((HANDLE)pDevice, sFrame.pHdr->sA3.abyAddr3, sFrame.pSSID); + if (pBSSList) { + BSSbUpdateToBSSList((HANDLE)pDevice, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + bChannelHit, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + pBSSList, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of probresponse + (HANDLE)pRxPacket + ); + } + else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Probe resp/insert: RxChannel = : %d\n", byCurrChannel); + BSSbInsertToBSSList((HANDLE)pDevice, + sFrame.pHdr->sA3.abyAddr3, + *sFrame.pqwTimestamp, + *sFrame.pwBeaconInterval, + *sFrame.pwCapInfo, + byCurrChannel, + sFrame.pSSID, + sFrame.pSuppRates, + sFrame.pExtSuppRates, + &sERP, + sFrame.pRSN, + sFrame.pRSNWPA, + sFrame.pIE_Country, + sFrame.pIE_Quiet, + sFrame.len - WLAN_HDR_ADDR3_LEN, + sFrame.pHdr->sA4.abyAddr4, // payload of beacon + (HANDLE)pRxPacket + ); + } + return; + +} + +/*+ + * + * Routine Description:(AP)or(Ad-hoc STA) + * Handles probe request management frames. + * + * + * Return Value: + * none. + * +-*/ + + +static +VOID +s_vMgrRxProbeRequest( + IN PSDevice pDevice, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + WLAN_FR_PROBEREQ sFrame; + CMD_STATUS Status; + PSTxMgmtPacket pTxPacket; + BYTE byPHYType = BB_TYPE_11B; + + // STA in Ad-hoc mode: when latest TBTT beacon transmit success, + // STA have to response this request. + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || + ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && pDevice->bBeaconSent)) { + + memset(&sFrame, 0, sizeof(WLAN_FR_PROBEREQ)); + // decode the frame + sFrame.len = pRxPacket->cbMPDULen; + sFrame.pBuf = (PBYTE)pRxPacket->p80211Header; + vMgrDecodeProbeRequest(&sFrame); +/* + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe request rx:MAC addr:%02x-%02x-%02x=%02x-%02x-%02x \n", + sFrame.pHdr->sA3.abyAddr2[0], + sFrame.pHdr->sA3.abyAddr2[1], + sFrame.pHdr->sA3.abyAddr2[2], + sFrame.pHdr->sA3.abyAddr2[3], + sFrame.pHdr->sA3.abyAddr2[4], + sFrame.pHdr->sA3.abyAddr2[5] + ); +*/ + if (sFrame.pSSID->len != 0) { + if (sFrame.pSSID->len != ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) + return; + if (memcmp(sFrame.pSSID->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->abySSID, + ((PWLAN_IE_SSID)pMgmt->abyCurrSSID)->len) != 0) { + return; + } + } + + if ((sFrame.pSuppRates->len > 4) || (sFrame.pExtSuppRates != NULL)) { + byPHYType = BB_TYPE_11G; + } + + // Probe response reply.. + pTxPacket = s_MgrMakeProbeResponse + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + pMgmt->wCurrBeaconPeriod, + pMgmt->uCurrChannel, + 0, + sFrame.pHdr->sA3.abyAddr2, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PBYTE)pMgmt->abyCurrBSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates, + byPHYType + ); + if (pTxPacket != NULL ){ + /* send the frame */ + Status = csMgmt_xmit(pDevice, pTxPacket); + if (Status != CMD_STATUS_PENDING) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx failed\n"); + } + else { +// DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Mgt:Probe response tx sending..\n"); + } + } + } + + return; +} + + + + + +/*+ + * + * Routine Description: + * + * Entry point for the reception and handling of 802.11 management + * frames. Makes a determination of the frame type and then calls + * the appropriate function. + * + * + * Return Value: + * none. + * +-*/ + + +VOID +vMgrRxManagePacket( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + BOOL bInScan = FALSE; + UINT uNodeIndex = 0; + NODE_STATE eNodeState = 0; + CMD_STATUS Status; + + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (BSSDBbIsSTAInNodeDB(pMgmt, pRxPacket->p80211Header->sA3.abyAddr2, &uNodeIndex)) + eNodeState = pMgmt->sNodeDBTable[uNodeIndex].eNodeState; + } + + switch( WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) ){ + + case WLAN_FSTYPE_ASSOCREQ: + // Frame Clase = 2 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocreq\n"); + if (eNodeState < NODE_AUTH) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 1\n"); + } + else { + s_vMgrRxAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex); + } + break; + + case WLAN_FSTYPE_ASSOCRESP: + // Frame Clase = 2 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp1\n"); + s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, FALSE); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx assocresp2\n"); + break; + + case WLAN_FSTYPE_REASSOCREQ: + // Frame Clase = 2 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocreq\n"); + // Todo: reassoc + if (eNodeState < NODE_AUTH) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 2\n"); + + } + s_vMgrRxReAssocRequest(pDevice, pMgmt, pRxPacket, uNodeIndex); + break; + + case WLAN_FSTYPE_REASSOCRESP: + // Frame Clase = 2 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx reassocresp\n"); + s_vMgrRxAssocResponse(pDevice, pMgmt, pRxPacket, TRUE); + break; + + case WLAN_FSTYPE_PROBEREQ: + // Frame Clase = 0 + //DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx probereq\n"); + s_vMgrRxProbeRequest(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_PROBERESP: + // Frame Clase = 0 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx proberesp\n"); + + s_vMgrRxProbeResponse(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_BEACON: + // Frame Clase = 0 + // DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx beacon\n"); + if (pMgmt->eScanState != WMAC_NO_SCANNING) { + bInScan = TRUE; + }; + s_vMgrRxBeacon(pDevice, pMgmt, pRxPacket, bInScan); + break; + + case WLAN_FSTYPE_ATIM: + // Frame Clase = 1 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx atim\n"); + break; + + case WLAN_FSTYPE_DISASSOC: + // Frame Clase = 2 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx disassoc\n"); + if (eNodeState < NODE_AUTH) { + // send deauth notification + // reason = (6) class 2 received from nonauth sta + vMgrDeAuthenBeginSta(pDevice, + pMgmt, + pRxPacket->p80211Header->sA3.abyAddr2, + (6), + &Status + ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wmgr: send vMgrDeAuthenBeginSta 3\n"); + } + s_vMgrRxDisassociation(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_AUTHEN: + // Frame Clase = 1 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx authen\n"); + s_vMgrRxAuthentication(pDevice, pMgmt, pRxPacket); + break; + + case WLAN_FSTYPE_DEAUTHEN: + // Frame Clase = 1 + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx deauthen\n"); + s_vMgrRxDeauthentication(pDevice, pMgmt, pRxPacket); + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx unknown mgmt\n"); + } + + return; +} + + + + +/*+ + * + * Routine Description: + * + * + * Prepare beacon to send + * + * Return Value: + * TRUE if success; FALSE if failed. + * +-*/ +BOOL +bMgrPrepareBeaconToSend( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PSTxMgmtPacket pTxPacket; + +// pDevice->bBeaconBufReady = FALSE; + if (pDevice->bEncryptionEnable || pDevice->bEnable8021x){ + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_PRIVACY(1); + } + else { + pMgmt->wCurrCapInfo &= ~WLAN_SET_CAP_INFO_PRIVACY(1); + } + pTxPacket = s_MgrMakeBeacon + ( + pDevice, + pMgmt, + pMgmt->wCurrCapInfo, + pMgmt->wCurrBeaconPeriod, + pMgmt->uCurrChannel, + pMgmt->wCurrATIMWindow, //0, + (PWLAN_IE_SSID)pMgmt->abyCurrSSID, + (PBYTE)pMgmt->abyCurrBSSID, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates, + (PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates + ); + + if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && + (pMgmt->abyCurrBSSID[0] == 0)) + return FALSE; + + csBeacon_xmit(pDevice, pTxPacket); + + return TRUE; +} + + + + +/*+ + * + * Routine Description: + * + * Log a warning message based on the contents of the Status + * Code field of an 802.11 management frame. Defines are + * derived from 802.11-1997 SPEC. + * + * Return Value: + * none. + * +-*/ +static +VOID +s_vMgrLogStatus( + IN PSMgmtObject pMgmt, + IN WORD wStatus + ) +{ + switch( wStatus ){ + case WLAN_MGMT_STATUS_UNSPEC_FAILURE: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Unspecified error.\n"); + break; + case WLAN_MGMT_STATUS_CAPS_UNSUPPORTED: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Can't support all requested capabilities.\n"); + break; + case WLAN_MGMT_STATUS_REASSOC_NO_ASSOC: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Reassoc denied, can't confirm original Association.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_UNSPEC: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, undefine in spec\n"); + break; + case WLAN_MGMT_STATUS_UNSUPPORTED_AUTHALG: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Peer doesn't support authen algorithm.\n"); + break; + case WLAN_MGMT_STATUS_RX_AUTH_NOSEQ: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen frame received out of sequence.\n"); + break; + case WLAN_MGMT_STATUS_CHALLENGE_FAIL: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, challenge failure.\n"); + break; + case WLAN_MGMT_STATUS_AUTH_TIMEOUT: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Authen rejected, timeout waiting for next frame.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_BUSY: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, AP too busy.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_RATES: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we haven't enough basic rates.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_SHORTPREAMBLE: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support short preamble.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_PBCC: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support PBCC.\n"); + break; + case WLAN_MGMT_STATUS_ASSOC_DENIED_AGILITY: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Status code == Assoc denied, we do not support channel agility.\n"); + break; + default: + DEVICE_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Unknown status code %d.\n", wStatus); + break; + } +} + + +/* + * + * Description: + * Add BSSID in PMKID Candidate list. + * + * Parameters: + * In: + * hDeviceContext - device structure point + * pbyBSSID - BSSID address for adding + * wRSNCap - BSS's RSN capability + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +bAdd_PMKID_Candidate ( + IN HANDLE hDeviceContext, + IN PBYTE pbyBSSID, + IN PSRSNCapObject psRSNCapObj + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + PPMKID_CANDIDATE pCandidateList; + UINT ii = 0; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"bAdd_PMKID_Candidate START: (%d)\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + + if ((pDevice == NULL) || (pbyBSSID == NULL) || (psRSNCapObj == NULL)) + return FALSE; + + if (pDevice->gsPMKIDCandidate.NumCandidates >= MAX_PMKIDLIST) + return FALSE; + + + + // Update Old Candidate + for (ii = 0; ii < pDevice->gsPMKIDCandidate.NumCandidates; ii++) { + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[ii]; + if (MEMEqualMemory(pCandidateList->BSSID, pbyBSSID, U_ETHER_ADDR_LEN)) { + if ((psRSNCapObj->bRSNCapExist == TRUE) && (psRSNCapObj->wRSNCap & BIT0)) { + pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + return TRUE; + } + } + + // New Candidate + pCandidateList = &pDevice->gsPMKIDCandidate.CandidateList[pDevice->gsPMKIDCandidate.NumCandidates]; + if ((psRSNCapObj->bRSNCapExist == TRUE) && (psRSNCapObj->wRSNCap & BIT0)) { + pCandidateList->Flags |= NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; + } else { + pCandidateList->Flags &= ~(NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED); + } + MEMvCopy(pCandidateList->BSSID, pbyBSSID, U_ETHER_ADDR_LEN); + pDevice->gsPMKIDCandidate.NumCandidates++; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"NumCandidates:%d\n", (int)pDevice->gsPMKIDCandidate.NumCandidates); + return TRUE; +} + +/* + * + * Description: + * Flush PMKID Candidate list. + * + * Parameters: + * In: + * hDeviceContext - device structure point + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +vFlush_PMKID_Candidate ( + IN HANDLE hDeviceContext + ) +{ + PSDevice pDevice = (PSDevice)hDeviceContext; + + if (pDevice == NULL) + return; + + ZERO_MEMORY(&pDevice->gsPMKIDCandidate, sizeof(SPMKIDCandidateEvent)); +} + +static BOOL +s_bCipherMatch ( + IN PKnownBSS pBSSNode, + IN NDIS_802_11_ENCRYPTION_STATUS EncStatus, + OUT PBYTE pbyCCSPK, + OUT PBYTE pbyCCSGK + ) +{ + BYTE byMulticastCipher = KEY_CTL_INVALID; + BYTE byCipherMask = 0x00; + int i; + + if (pBSSNode == NULL) + return FALSE; + + // check cap. of BSS + + if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (EncStatus == Ndis802_11Encryption1Enabled)) { + // default is WEP only + byMulticastCipher = KEY_CTL_WEP; + } + + if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (pBSSNode->bWPA2Valid == TRUE) && + ((EncStatus == Ndis802_11Encryption3Enabled)||(EncStatus == Ndis802_11Encryption2Enabled))) { + + //WPA2 + // check Group Key Cipher + if ((pBSSNode->byCSSGK == WLAN_11i_CSS_WEP40) || + (pBSSNode->byCSSGK == WLAN_11i_CSS_WEP104)) { + byMulticastCipher = KEY_CTL_WEP; + } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_TKIP) { + byMulticastCipher = KEY_CTL_TKIP; + } else if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) { + byMulticastCipher = KEY_CTL_CCMP; + } else { + byMulticastCipher = KEY_CTL_INVALID; + } + + // check Pairwise Key Cipher + for(i=0;i<pBSSNode->wCSSPKCount;i++) { + if ((pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP40) || + (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_WEP104)) { + // this should not happen as defined 802.11i + byCipherMask |= 0x01; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_CCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyCSSPK[i] == WLAN_11i_CSS_USE_GROUP) { + // use group key only ignore all others + byCipherMask = 0; + i = pBSSNode->wCSSPKCount; + } + } + } else if ((WLAN_GET_CAP_INFO_PRIVACY(pBSSNode->wCapInfo) != 0) && + (pBSSNode->bWPAValid == TRUE) && + ((EncStatus == Ndis802_11Encryption3Enabled)||(EncStatus == Ndis802_11Encryption2Enabled))) { + + //WPA + // check Group Key Cipher + if ((pBSSNode->byGKType == WPA_WEP40) || + (pBSSNode->byGKType == WPA_WEP104)) { + byMulticastCipher = KEY_CTL_WEP; + } else if (pBSSNode->byGKType == WPA_TKIP) { + byMulticastCipher = KEY_CTL_TKIP; + } else if (pBSSNode->byGKType == WPA_AESCCMP) { + byMulticastCipher = KEY_CTL_CCMP; + } else { + byMulticastCipher = KEY_CTL_INVALID; + } + + // check Pairwise Key Cipher + for(i=0;i<pBSSNode->wPKCount;i++) { + if (pBSSNode->abyPKType[i] == WPA_TKIP) { + byCipherMask |= 0x02; + } else if (pBSSNode->abyPKType[i] == WPA_AESCCMP) { + byCipherMask |= 0x04; + } else if (pBSSNode->abyPKType[i] == WPA_NONE) { + // use group key only ignore all others + byCipherMask = 0; + i = pBSSNode->wPKCount; + } + } + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%d, %d, %d, %d, EncStatus:%d\n", + byMulticastCipher, byCipherMask, pBSSNode->bWPAValid, pBSSNode->bWPA2Valid, EncStatus); + + // mask our cap. with BSS + if (EncStatus == Ndis802_11Encryption1Enabled) { + // For supporting Cisco migration mode, don't care pairwise key cipher + if ((byMulticastCipher == KEY_CTL_WEP) && + (byCipherMask == 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_NONE; + return TRUE; + } else { + return FALSE; + } + + } else if (EncStatus == Ndis802_11Encryption2Enabled) { + if ((byMulticastCipher == KEY_CTL_TKIP) && + (byCipherMask == 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_NONE; + return TRUE; + } else if ((byMulticastCipher == KEY_CTL_WEP) && + ((byCipherMask & 0x02) != 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_TKIP; + return TRUE; + } else if ((byMulticastCipher == KEY_CTL_TKIP) && + ((byCipherMask & 0x02) != 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_TKIP; + return TRUE; + } else { + return FALSE; + } + } else if (EncStatus == Ndis802_11Encryption3Enabled) { + if ((byMulticastCipher == KEY_CTL_CCMP) && + (byCipherMask == 0)) { + // When CCMP is enable, "Use group cipher suite" shall not be a valid option. + return FALSE; + } else if ((byMulticastCipher == KEY_CTL_WEP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_WEP; + *pbyCCSPK = KEY_CTL_CCMP; + return TRUE; + } else if ((byMulticastCipher == KEY_CTL_TKIP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_TKIP; + *pbyCCSPK = KEY_CTL_CCMP; + return TRUE; + } else if ((byMulticastCipher == KEY_CTL_CCMP) && + ((byCipherMask & 0x04) != 0)) { + *pbyCCSGK = KEY_CTL_CCMP; + *pbyCCSPK = KEY_CTL_CCMP; + return TRUE; + } else { + return FALSE; + } + } + return TRUE; +} + + diff --git a/drivers/staging/vt6655/wmgr.h b/drivers/staging/vt6655/wmgr.h new file mode 100644 index 00000000000..5b526ab2d91 --- /dev/null +++ b/drivers/staging/vt6655/wmgr.h @@ -0,0 +1,521 @@ +/* + * 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: wmgr.h + * + * Purpose: + * + * Author: lyndon chen + * + * Date: Jan 2, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#ifndef __WMGR_H__ +#define __WMGR_H__ + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__WCMD_H__) +#include "wcmd.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__WPA2_H__) +#include "wpa2.h" +#endif +#if !defined(__VNTWIFI_H__) +#include "vntwifi.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + + + +// Scan time +#define PROBE_DELAY 100 // (us) +#define SWITCH_CHANNEL_DELAY 200 // (us) +#define WLAN_SCAN_MINITIME 25 // (ms) +#define WLAN_SCAN_MAXTIME 100 // (ms) +#define TRIVIAL_SYNC_DIFFERENCE 0 // (us) +#define DEFAULT_IBSS_BI 100 // (ms) + +#define WCMD_ACTIVE_SCAN_TIME 50 //(ms) +#define WCMD_PASSIVE_SCAN_TIME 100 //(ms) + + +#define DEFAULT_MSDU_LIFETIME 512 // ms +#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 // 64us + +#define DEFAULT_MGN_LIFETIME 8 // ms +#define DEFAULT_MGN_LIFETIME_RES_64us 125 // 64us + +#define MAKE_BEACON_RESERVED 10 //(us) + + +#define TIM_MULTICAST_MASK 0x01 +#define TIM_BITMAPOFFSET_MASK 0xFE +#define DEFAULT_DTIM_PERIOD 1 + +#define AP_LONG_RETRY_LIMIT 4 + +#define DEFAULT_IBSS_CHANNEL 6 //2.4G + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Types ------------------------------*/ +#define timer_expire(timer,next_tick) mod_timer(&timer, RUN_AT(next_tick)) +typedef void (*TimerFunction)(ULONG); + + +//+++ NDIS related + +typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; +typedef struct _NDIS_802_11_AI_REQFI +{ + USHORT Capabilities; + USHORT ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI +{ + USHORT Capabilities; + USHORT StatusCode; + USHORT AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION +{ + ULONG Length; + USHORT AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + ULONG RequestIELength; + ULONG OffsetRequestIEs; + USHORT AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + ULONG ResponseIELength; + ULONG OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + + + +typedef struct tagSAssocInfo { + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + BYTE abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN]; + // store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION + ULONG RequestIELength; + BYTE abyReqIEs[WLAN_BEACON_FR_MAXLEN]; +} SAssocInfo, DEF* PSAssocInfo; +//--- + + +/* +typedef enum tagWMAC_AUTHENTICATION_MODE { + + + WMAC_AUTH_OPEN, + WMAC_AUTH_SHAREKEY, + WMAC_AUTH_AUTO, + WMAC_AUTH_WPA, + WMAC_AUTH_WPAPSK, + WMAC_AUTH_WPANONE, + WMAC_AUTH_WPA2, + WMAC_AUTH_WPA2PSK, + WMAC_AUTH_MAX // Not a real mode, defined as upper bound + + +} WMAC_AUTHENTICATION_MODE, *PWMAC_AUTHENTICATION_MODE; +*/ + + +// Pre-configured Mode (from XP) +/* +typedef enum tagWMAC_CONFIG_MODE { + WMAC_CONFIG_ESS_STA, + WMAC_CONFIG_IBSS_STA, + WMAC_CONFIG_AUTO, + WMAC_CONFIG_AP + +} WMAC_CONFIG_MODE, *PWMAC_CONFIG_MODE; +*/ + +typedef enum tagWMAC_SCAN_TYPE { + + WMAC_SCAN_ACTIVE, + WMAC_SCAN_PASSIVE, + WMAC_SCAN_HYBRID + +} WMAC_SCAN_TYPE, *PWMAC_SCAN_TYPE; + + +typedef enum tagWMAC_SCAN_STATE { + + WMAC_NO_SCANNING, + WMAC_IS_SCANNING, + WMAC_IS_PROBEPENDING + +} WMAC_SCAN_STATE, *PWMAC_SCAN_STATE; + + + +// Notes: +// Basic Service Set state explained as following: +// WMAC_STATE_IDLE : no BSS is selected (Adhoc or Infra) +// WMAC_STATE_STARTED : no BSS is selected, start own IBSS (Adhoc only) +// WMAC_STATE_JOINTED : BSS is selected and synchronized (Adhoc or Infra) +// WMAC_STATE_AUTHPENDING : Authentication pending (Infra) +// WMAC_STATE_AUTH : Authenticated (Infra) +// WMAC_STATE_ASSOCPENDING : Association pending (Infra) +// WMAC_STATE_ASSOC : Associated (Infra) + +typedef enum tagWMAC_BSS_STATE { + + WMAC_STATE_IDLE, + WMAC_STATE_STARTED, + WMAC_STATE_JOINTED, + WMAC_STATE_AUTHPENDING, + WMAC_STATE_AUTH, + WMAC_STATE_ASSOCPENDING, + WMAC_STATE_ASSOC + +} WMAC_BSS_STATE, *PWMAC_BSS_STATE; + +// WMAC selected running mode +typedef enum tagWMAC_CURRENT_MODE { + + WMAC_MODE_STANDBY, + WMAC_MODE_ESS_STA, + WMAC_MODE_IBSS_STA, + WMAC_MODE_ESS_AP + +} WMAC_CURRENT_MODE, *PWMAC_CURRENT_MODE; + +/* +typedef enum tagWMAC_POWER_MODE { + + WMAC_POWER_CAM, + WMAC_POWER_FAST, + WMAC_POWER_MAX + +} WMAC_POWER_MODE, *PWMAC_POWER_MODE; +*/ + + +// Tx Managment Packet descriptor +typedef struct tagSTxMgmtPacket { + + PUWLAN_80211HDR p80211Header; + UINT cbMPDULen; + UINT cbPayloadLen; + +} STxMgmtPacket, DEF* PSTxMgmtPacket; + + +// Rx Managment Packet descriptor +typedef struct tagSRxMgmtPacket { + + PUWLAN_80211HDR p80211Header; + QWORD qwLocalTSF; + UINT cbMPDULen; + UINT cbPayloadLen; + UINT uRSSI; + BYTE bySQ; + BYTE byRxRate; + BYTE byRxChannel; + +} SRxMgmtPacket, DEF* PSRxMgmtPacket; + + + +typedef struct tagSMgmtObject +{ + + PVOID pAdapter; + // MAC address + BYTE abyMACAddr[WLAN_ADDR_LEN]; + + // Configuration Mode + WMAC_CONFIG_MODE eConfigMode; // MAC pre-configed mode + CARD_PHY_TYPE eCurrentPHYMode; + CARD_PHY_TYPE eConfigPHYMode; + + + // Operation state variables + WMAC_CURRENT_MODE eCurrMode; // MAC current connection mode + WMAC_BSS_STATE eCurrState; // MAC current BSS state + + PKnownBSS pCurrBSS; + BYTE byCSSGK; + BYTE byCSSPK; + +// BYTE abyNewSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; +// BYTE abyNewExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN]; + + // Current state vars + UINT uCurrChannel; + BYTE abyCurrSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE abyCurrExtSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE abyCurrSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + BYTE abyCurrBSSID[WLAN_BSSID_LEN]; + WORD wCurrCapInfo; + WORD wCurrAID; + WORD wCurrATIMWindow; + WORD wCurrBeaconPeriod; + BOOL bIsDS; + BYTE byERPContext; + + CMD_STATE eCommandState; + UINT uScanChannel; + + // Desire joinning BSS vars + BYTE abyDesireSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + BYTE abyDesireBSSID[WLAN_BSSID_LEN]; + + // Adhoc or AP configuration vars + //BYTE abyAdHocSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + WORD wIBSSBeaconPeriod; + WORD wIBSSATIMWindow; + UINT uIBSSChannel; + BYTE abyIBSSSuppRates[WLAN_IEHDR_LEN + WLAN_RATES_MAXLEN + 1]; + BYTE byAPBBType; + BYTE abyWPAIE[MAX_WPA_IE_LEN]; + WORD wWPAIELen; + + UINT uAssocCount; + BOOL bMoreData; + + // Scan state vars + WMAC_SCAN_STATE eScanState; + WMAC_SCAN_TYPE eScanType; + UINT uScanStartCh; + UINT uScanEndCh; + WORD wScanSteps; + UINT uScanBSSType; + // Desire scannig vars + BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1]; + BYTE abyScanBSSID[WLAN_BSSID_LEN]; + + // Privacy + WMAC_AUTHENTICATION_MODE eAuthenMode; + WMAC_ENCRYPTION_MODE eEncryptionMode; + BOOL bShareKeyAlgorithm; + BYTE abyChallenge[WLAN_CHALLENGE_LEN]; + BOOL bPrivacyInvoked; + + // Received beacon state vars + BOOL bInTIM; + BOOL bMulticastTIM; + BYTE byDTIMCount; + BYTE byDTIMPeriod; + + // Power saving state vars + WMAC_POWER_MODE ePSMode; + WORD wListenInterval; + WORD wCountToWakeUp; + BOOL bInTIMWake; + PBYTE pbyPSPacketPool; + BYTE byPSPacketPool[sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN]; + BOOL bRxBeaconInTBTTWake; + BYTE abyPSTxMap[MAX_NODE_NUM + 1]; + + // managment command related + UINT uCmdBusy; + UINT uCmdHostAPBusy; + + // managment packet pool + PBYTE pbyMgmtPacketPool; + BYTE byMgmtPacketPool[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; + + + // One second callback timer + struct timer_list sTimerSecondCallback; + + // Temporarily Rx Mgmt Packet Descriptor + SRxMgmtPacket sRxPacket; + + // link list of known bss's (scan results) + KnownBSS sBSSList[MAX_BSS_NUM]; + + + + // table list of known node + // sNodeDBList[0] is reserved for AP under Infra mode + // sNodeDBList[0] is reserved for Multicast under adhoc/AP mode + KnownNodeDB sNodeDBTable[MAX_NODE_NUM + 1]; + + + + // WPA2 PMKID Cache + SPMKIDCache gsPMKIDCache; + BOOL bRoaming; + + // rate fall back vars + + + + // associate info + SAssocInfo sAssocInfo; + + + // for 802.11h + BOOL b11hEnable; + BOOL bSwitchChannel; + BYTE byNewChannel; + PWLAN_IE_MEASURE_REP pCurrMeasureEIDRep; + UINT uLengthOfRepEIDs; + BYTE abyCurrentMSRReq[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; + BYTE abyCurrentMSRRep[sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN]; + BYTE abyIECountry[WLAN_A3FR_MAXLEN]; + BYTE abyIBSSDFSOwner[6]; + BYTE byIBSSDFSRecovery; + + struct sk_buff skb; + +} SMgmtObject, DEF *PSMgmtObject; + + +/*--------------------- Export Macros ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ + + +void +vMgrObjectInit( + IN HANDLE hDeviceContext + ); + +void +vMgrTimerInit( + IN HANDLE hDeviceContext + ); + +VOID +vMgrObjectReset( + IN HANDLE hDeviceContext + ); + +void +vMgrAssocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrReAssocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrDisassocBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PBYTE abyDestAddress, + IN WORD wReason, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrAuthenBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrCreateOwnIBSS( + IN HANDLE hDeviceContext, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrJoinBSSBegin( + IN HANDLE hDeviceContext, + OUT PCMD_STATUS pStatus + ); + +VOID +vMgrRxManagePacket( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PSRxMgmtPacket pRxPacket + ); + +/* +VOID +vMgrScanBegin( + IN HANDLE hDeviceContext, + OUT PCMD_STATUS pStatus + ); +*/ + +VOID +vMgrDeAuthenBeginSta( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt, + IN PBYTE abyDestAddress, + IN WORD wReason, + OUT PCMD_STATUS pStatus + ); + +BOOL +bMgrPrepareBeaconToSend( + IN HANDLE hDeviceContext, + IN PSMgmtObject pMgmt + ); + + +BOOL +bAdd_PMKID_Candidate ( + IN HANDLE hDeviceContext, + IN PBYTE pbyBSSID, + IN PSRSNCapObject psRSNCapObj + ); + +VOID +vFlush_PMKID_Candidate ( + IN HANDLE hDeviceContext + ); + +#endif // __WMGR_H__ diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c new file mode 100644 index 00000000000..8b4e7fc31ef --- /dev/null +++ b/drivers/staging/vt6655/wpa.c @@ -0,0 +1,339 @@ +/* + * 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: wpa.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * WPA_ParseRSN - Parse RSN IE. + * + * Revision History: + * + * Author: Kyle Hsu + * + * Date: July 14, 2003 + * + */ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__TMACRO_H__) +#include "tmacro.h" +#endif +#if !defined(__TETHER_H__) +#include "tether.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__WPA_H__) +#include "wpa.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif + + +/*--------------------- Static Variables --------------------------*/ +static int msglevel =MSG_LEVEL_INFO; + +const BYTE abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 }; +const BYTE abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 }; +const BYTE abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 }; +const BYTE abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 }; +const BYTE abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 }; +const BYTE abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 }; + + +/*+ + * + * Description: + * Clear RSN information in BSSList. + * + * Parameters: + * In: + * pBSSList - BSS list. + * Out: + * none + * + * Return Value: none. + * +-*/ + +VOID +WPA_ClearRSN ( + IN PKnownBSS pBSSList + ) +{ + int ii; + pBSSList->byGKType = WPA_TKIP; + for (ii=0; ii < 4; ii ++) + pBSSList->abyPKType[ii] = WPA_TKIP; + pBSSList->wPKCount = 0; + for (ii=0; ii < 4; ii ++) + pBSSList->abyAuthType[ii] = WPA_AUTH_IEEE802_1X; + pBSSList->wAuthCount = 0; + pBSSList->byDefaultK_as_PK = 0; + pBSSList->byReplayIdx = 0; + pBSSList->sRSNCapObj.bRSNCapExist = FALSE; + pBSSList->sRSNCapObj.wRSNCap = 0; + pBSSList->bWPAValid = FALSE; +} + + +/*+ + * + * Description: + * Parse RSN IE. + * + * Parameters: + * In: + * pBSSList - BSS list. + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +WPA_ParseRSN ( + IN PKnownBSS pBSSList, + IN PWLAN_IE_RSN_EXT pRSN + ) +{ + PWLAN_IE_RSN_AUTH pIE_RSN_Auth = NULL; + int i, j, m, n = 0; + PBYTE pbyCaps; + + WPA_ClearRSN(pBSSList); + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA_ParseRSN: [%d]\n", pRSN->len); + + // information element header makes sense + if ((pRSN->len >= 6) // oui1(4)+ver(2) + && (pRSN->byElementID == WLAN_EID_RSN_WPA) && MEMEqualMemory(pRSN->abyOUI, abyOUI01, 4) + && (pRSN->wVersion == 1)) { + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal RSN\n"); + // update each variable if pRSN is long enough to contain the variable + if (pRSN->len >= 10) //oui1(4)+ver(2)+GKSuite(4) + { + if (MEMEqualMemory(pRSN->abyMulticast, abyOUI01, 4)) + pBSSList->byGKType = WPA_WEP40; + else if (MEMEqualMemory(pRSN->abyMulticast, abyOUI02, 4)) + pBSSList->byGKType = WPA_TKIP; + else if (MEMEqualMemory(pRSN->abyMulticast, abyOUI03, 4)) + pBSSList->byGKType = WPA_AESWRAP; + else if (MEMEqualMemory(pRSN->abyMulticast, abyOUI04, 4)) + pBSSList->byGKType = WPA_AESCCMP; + else if (MEMEqualMemory(pRSN->abyMulticast, abyOUI05, 4)) + pBSSList->byGKType = WPA_WEP104; + else + // any vendor checks here + pBSSList->byGKType = WPA_NONE; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byGKType: %x\n", pBSSList->byGKType); + } + + if (pRSN->len >= 12) //oui1(4)+ver(2)+GKS(4)+PKSCnt(2) + { + j = 0; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d, sizeof(pBSSList->abyPKType): %d\n", pRSN->wPKCount, sizeof(pBSSList->abyPKType)); + for(i = 0; (i < pRSN->wPKCount) && (j < sizeof(pBSSList->abyPKType)/sizeof(BYTE)); i++) { + if(pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) + if (MEMEqualMemory(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) + pBSSList->abyPKType[j++] = WPA_NONE; + else if (MEMEqualMemory(pRSN->PKSList[i].abyOUI, abyOUI02, 4)) + pBSSList->abyPKType[j++] = WPA_TKIP; + else if (MEMEqualMemory(pRSN->PKSList[i].abyOUI, abyOUI03, 4)) + pBSSList->abyPKType[j++] = WPA_AESWRAP; + else if (MEMEqualMemory(pRSN->PKSList[i].abyOUI, abyOUI04, 4)) + pBSSList->abyPKType[j++] = WPA_AESCCMP; + else + // any vendor checks here + ; + } + else + break; + //DBG_PRN_GRP14(("abyPKType[%d]: %X\n", j-1, pBSSList->abyPKType[j-1])); + } //for + pBSSList->wPKCount = (WORD)j; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wPKCount: %d\n", pBSSList->wPKCount); + } + + m = pRSN->wPKCount; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"m: %d\n", m); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+m*4: %d\n", 14+m*4); + + if (pRSN->len >= 14+m*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2) + // overlay IE_RSN_Auth structure into correct place + pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI; + j = 0; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d, sizeof(pBSSList->abyAuthType): %d\n", + pIE_RSN_Auth->wAuthCount, sizeof(pBSSList->abyAuthType)); + for(i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < sizeof(pBSSList->abyAuthType)/sizeof(BYTE)); i++) { + if(pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) + if (MEMEqualMemory(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4)) + pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X; + else if (MEMEqualMemory(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI02, 4)) + pBSSList->abyAuthType[j++] = WPA_AUTH_PSK; + else + // any vendor checks here + ; + } + else + break; + //DBG_PRN_GRP14(("abyAuthType[%d]: %X\n", j-1, pBSSList->abyAuthType[j-1])); + } + if(j > 0) + pBSSList->wAuthCount = (WORD)j; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAuthCount: %d\n", pBSSList->wAuthCount); + } + + if (pIE_RSN_Auth != NULL) { + + n = pIE_RSN_Auth->wAuthCount; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"n: %d\n", n); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"14+4+(m+n)*4: %d\n", 14+4+(m+n)*4); + + if(pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2) + pbyCaps = (PBYTE)pIE_RSN_Auth->AuthKSList[n].abyOUI; + pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG; + pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS); + pBSSList->sRSNCapObj.bRSNCapExist = TRUE; + pBSSList->sRSNCapObj.wRSNCap = *(PWORD)pbyCaps; + //DBG_PRN_GRP14(("pbyCaps: %X\n", *pbyCaps)); + //DBG_PRN_GRP14(("byDefaultK_as_PK: %X\n", pBSSList->byDefaultK_as_PK)); + //DBG_PRN_GRP14(("byReplayIdx: %X\n", pBSSList->byReplayIdx)); + } + } + pBSSList->bWPAValid = TRUE; + } +} + +/*+ + * + * Description: + * Search RSN information in BSSList. + * + * Parameters: + * In: + * byCmd - Search type + * byEncrypt- Encrcypt Type + * pBSSList - BSS list + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +WPA_SearchRSN ( + BYTE byCmd, + BYTE byEncrypt, + IN PKnownBSS pBSSList + ) +{ + int ii; + BYTE byPKType = WPA_NONE; + + if (pBSSList->bWPAValid == FALSE) + return FALSE; + + switch(byCmd) { + case 0: + + if (byEncrypt != pBSSList->byGKType) + return FALSE; + + if (pBSSList->wPKCount > 0) { + for (ii = 0; ii < pBSSList->wPKCount; ii ++) { + if (pBSSList->abyPKType[ii] == WPA_AESCCMP) + byPKType = WPA_AESCCMP; + else if ((pBSSList->abyPKType[ii] == WPA_TKIP) && (byPKType != WPA_AESCCMP)) + byPKType = WPA_TKIP; + else if ((pBSSList->abyPKType[ii] == WPA_WEP40) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) + byPKType = WPA_WEP40; + else if ((pBSSList->abyPKType[ii] == WPA_WEP104) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) + byPKType = WPA_WEP104; + } + if (byEncrypt != byPKType) + return FALSE; + } + return TRUE; +// if (pBSSList->wAuthCount > 0) +// for (ii=0; ii < pBSSList->wAuthCount; ii ++) +// if (byAuth == pBSSList->abyAuthType[ii]) +// break; + break; + + default: + break; + } + return FALSE; +} + +/*+ + * + * Description: + * Check if RSN IE makes sense. + * + * Parameters: + * In: + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +BOOL +WPAb_Is_RSN ( + IN PWLAN_IE_RSN_EXT pRSN + ) +{ + if (pRSN == NULL) + return FALSE; + + if ((pRSN->len >= 6) && // oui1(4)+ver(2) + (pRSN->byElementID == WLAN_EID_RSN_WPA) && MEMEqualMemory(pRSN->abyOUI, abyOUI01, 4) && + (pRSN->wVersion == 1)) { + return TRUE; + } + else + return FALSE; +} + diff --git a/drivers/staging/vt6655/wpa.h b/drivers/staging/vt6655/wpa.h new file mode 100644 index 00000000000..8000a37c6fc --- /dev/null +++ b/drivers/staging/vt6655/wpa.h @@ -0,0 +1,98 @@ +/* + * 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: wpa.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with WPA informations. + * + * Author: Kyle Hsu + * + * Date: Jul 14, 2003 + * + */ + +#ifndef __WPA_H__ +#define __WPA_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif + + +/*--------------------- Export Definitions -------------------------*/ + +#define WPA_NONE 0 +#define WPA_WEP40 1 +#define WPA_TKIP 2 +#define WPA_AESWRAP 3 +#define WPA_AESCCMP 4 +#define WPA_WEP104 5 +#define WPA_AUTH_IEEE802_1X 1 +#define WPA_AUTH_PSK 2 + +#define WPA_GROUPFLAG 0x02 +#define WPA_REPLAYBITSSHIFT 2 +#define WPA_REPLAYBITS 0x03 + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +WPA_ClearRSN( + IN PKnownBSS pBSSList + ); + +VOID +WPA_ParseRSN( + IN PKnownBSS pBSSList, + IN PWLAN_IE_RSN_EXT pRSN + ); + +BOOL +WPA_SearchRSN( + BYTE byCmd, + BYTE byEncrypt, + IN PKnownBSS pBSSList + ); + +BOOL +WPAb_Is_RSN( + IN PWLAN_IE_RSN_EXT pRSN + ); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __WPA_H__ diff --git a/drivers/staging/vt6655/wpa2.c b/drivers/staging/vt6655/wpa2.c new file mode 100644 index 00000000000..e2fdb331069 --- /dev/null +++ b/drivers/staging/vt6655/wpa2.c @@ -0,0 +1,373 @@ +/* + * 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: wpa2.c + * + * Purpose: Handles the Basic Service Set & Node Database functions + * + * Functions: + * + * Revision History: + * + * Author: Yiching Chen + * + * Date: Oct. 4, 2004 + * + */ +#if !defined(__WPA2_H__) +#include "wpa2.h" +#endif +#if !defined(__UMEM_H__) +#include "umem.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif + + +/*--------------------- Static Definitions -------------------------*/ +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +const BYTE abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; +const BYTE abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +const BYTE abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; +const BYTE abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; +const BYTE abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; + +const BYTE abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; +const BYTE abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; + + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/*+ + * + * Description: + * Clear RSN information in BSSList. + * + * Parameters: + * In: + * pBSSNode - BSS list. + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +WPA2_ClearRSN ( + IN PKnownBSS pBSSNode + ) +{ + int ii; + + pBSSNode->bWPA2Valid = FALSE; + + pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; + for (ii=0; ii < 4; ii ++) + pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP; + pBSSNode->wCSSPKCount = 1; + for (ii=0; ii < 4; ii ++) + pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X; + pBSSNode->wAKMSSAuthCount = 1; + pBSSNode->sRSNCapObj.bRSNCapExist = FALSE; + pBSSNode->sRSNCapObj.wRSNCap = 0; +} + +/*+ + * + * Description: + * Parse RSN IE. + * + * Parameters: + * In: + * pBSSNode - BSS list. + * pRSN - Pointer to the RSN IE. + * Out: + * none + * + * Return Value: none. + * +-*/ +VOID +WPA2vParseRSN ( + IN PKnownBSS pBSSNode, + IN PWLAN_IE_RSN pRSN + ) +{ + int i, j; + WORD m = 0, n = 0; + PBYTE pbyOUI; + BOOL bUseGK = FALSE; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len); + + WPA2_ClearRSN(pBSSNode); + + if (pRSN->len == 2) { // ver(2) + if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) { + pBSSNode->bWPA2Valid = TRUE; + } + return; + } + + if (pRSN->len < 6) { // ver(2) + GK(4) + // invalid CSS, P802.11i/D10.0, p31 + return; + } + + // information element header makes sense + if ((pRSN->byElementID == WLAN_EID_RSN) && + (pRSN->wVersion == 1)) { + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal 802.11i RSN\n"); + + pbyOUI = &(pRSN->abyRSN[0]); + if (MEMEqualMemory(pbyOUI, abyOUIWEP40, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40; + else if (MEMEqualMemory(pbyOUI, abyOUITKIP, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP; + else if (MEMEqualMemory(pbyOUI, abyOUICCMP, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; + else if (MEMEqualMemory(pbyOUI, abyOUIWEP104, 4)) + pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104; + else if (MEMEqualMemory(pbyOUI, abyOUIGK, 4)) { + // invalid CSS, P802.11i/D10.0, p32 + return; + } else + // any vendor checks here + pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"802.11i CSS: %X\n", pBSSNode->byCSSGK); + + if (pRSN->len == 6) { + pBSSNode->bWPA2Valid = TRUE; + return; + } + + if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2) + pBSSNode->wCSSPKCount = *((PWORD) &(pRSN->abyRSN[4])); + j = 0; + pbyOUI = &(pRSN->abyRSN[6]); + + for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(BYTE)); i++) { + + if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i) + if (MEMEqualMemory(pbyOUI, abyOUIGK, 4)) { + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP; + bUseGK = TRUE; + } else if (MEMEqualMemory(pbyOUI, abyOUIWEP40, 4)) { + // Invialid CSS, continue to parsing + } else if (MEMEqualMemory(pbyOUI, abyOUITKIP, 4)) { + if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP) + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP; + else + ; // Invialid CSS, continue to parsing + } else if (MEMEqualMemory(pbyOUI, abyOUICCMP, 4)) { + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP; + } else if (MEMEqualMemory(pbyOUI, abyOUIWEP104, 4)) { + // Invialid CSS, continue to parsing + } else { + // any vendor checks here + pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN; + } + pbyOUI += 4; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]); + } else + break; + } //for + + if (bUseGK == TRUE) { + if (j != 1) { + // invalid CSS, This should be only PK CSS. + return; + } + if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) { + // invalid CSS, If CCMP is enable , PK can't be CSSGK. + return; + } + } + if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) { + // invalid CSS, No valid PK. + return; + } + pBSSNode->wCSSPKCount = (WORD)j; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount); + } + + m = *((PWORD) &(pRSN->abyRSN[4])); + + if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2) + pBSSNode->wAKMSSAuthCount = *((PWORD) &(pRSN->abyRSN[6+4*m]));; + j = 0; + pbyOUI = &(pRSN->abyRSN[8+4*m]); + for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(BYTE)); i++) { + if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i) + if (MEMEqualMemory(pbyOUI, abyOUI8021X, 4)) + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X; + else if (MEMEqualMemory(pbyOUI, abyOUIPSK, 4)) + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK; + else + // any vendor checks here + pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]); + } else + break; + } + pBSSNode->wAKMSSAuthCount = (WORD)j; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount); + + n = *((PWORD) &(pRSN->abyRSN[6+4*m]));; + if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2) + pBSSNode->sRSNCapObj.bRSNCapExist = TRUE; + pBSSNode->sRSNCapObj.wRSNCap = *((PWORD) &(pRSN->abyRSN[8+4*m+4*n])); + } + } + //ignore PMKID lists bcs only (Re)Assocrequest has this field + pBSSNode->bWPA2Valid = TRUE; + } +} + + +/*+ + * + * Description: + * Set WPA IEs + * + * Parameters: + * In: + * pMgmtHandle - Pointer to management object + * Out: + * pRSNIEs - Pointer to the RSN IE to set. + * + * Return Value: length of IEs. + * +-*/ +UINT +WPA2uSetIEs( + IN PVOID pMgmtHandle, + OUT PWLAN_IE_RSN pRSNIEs + ) +{ + PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; + PBYTE pbyBuffer = NULL; + UINT ii = 0; + PWORD pwPMKID = NULL; + + if (pRSNIEs == NULL) { + return(0); + } + if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && + (pMgmt->pCurrBSS != NULL)) { + /* WPA2 IE */ + pbyBuffer = (PBYTE) pRSNIEs; + pRSNIEs->byElementID = WLAN_EID_RSN; + pRSNIEs->len = 6; //Version(2)+GK(4) + pRSNIEs->wVersion = 1; + //Group Key Cipher Suite + pRSNIEs->abyRSN[0] = 0x00; + pRSNIEs->abyRSN[1] = 0x0F; + pRSNIEs->abyRSN[2] = 0xAC; + if (pMgmt->byCSSGK == KEY_CTL_WEP) { + pRSNIEs->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; + } else if (pMgmt->byCSSGK == KEY_CTL_TKIP) { + pRSNIEs->abyRSN[3] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSGK == KEY_CTL_CCMP) { + pRSNIEs->abyRSN[3] = WLAN_11i_CSS_CCMP; + } else { + pRSNIEs->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; + } + + // Pairwise Key Cipher Suite + pRSNIEs->abyRSN[4] = 1; + pRSNIEs->abyRSN[5] = 0; + pRSNIEs->abyRSN[6] = 0x00; + pRSNIEs->abyRSN[7] = 0x0F; + pRSNIEs->abyRSN[8] = 0xAC; + if (pMgmt->byCSSPK == KEY_CTL_TKIP) { + pRSNIEs->abyRSN[9] = WLAN_11i_CSS_TKIP; + } else if (pMgmt->byCSSPK == KEY_CTL_CCMP) { + pRSNIEs->abyRSN[9] = WLAN_11i_CSS_CCMP; + } else if (pMgmt->byCSSPK == KEY_CTL_NONE) { + pRSNIEs->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; + } else { + pRSNIEs->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; + } + pRSNIEs->len += 6; + + // Auth Key Management Suite + pRSNIEs->abyRSN[10] = 1; + pRSNIEs->abyRSN[11] = 0; + pRSNIEs->abyRSN[12] = 0x00; + pRSNIEs->abyRSN[13] = 0x0F; + pRSNIEs->abyRSN[14] = 0xAC; + if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) { + pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_PSK; + } else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) { + pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_802_1X; + } else { + pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; + } + pRSNIEs->len +=6; + + // RSN Capabilites + if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == TRUE) { + MEMvCopy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); + } else { + pRSNIEs->abyRSN[16] = 0; + pRSNIEs->abyRSN[17] = 0; + } + pRSNIEs->len +=2; + + if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) && + (pMgmt->bRoaming == TRUE) && + (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { + // RSN PMKID + pwPMKID = (PWORD)(&pRSNIEs->abyRSN[18]); // Point to PMKID count + *pwPMKID = 0; // Initialize PMKID count + pbyBuffer = &pRSNIEs->abyRSN[20]; // Point to PMKID list + for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) { + if (MEMEqualMemory(&pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyBSSID[0], pMgmt->abyCurrBSSID, U_ETHER_ADDR_LEN)) { + (*pwPMKID) ++; + MEMvCopy(pbyBuffer, pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyPMKID, 16); + pbyBuffer += 16; + } + } + if (*pwPMKID != 0) { + pRSNIEs->len += (2 + (*pwPMKID)*16); + } else { + pbyBuffer = &pRSNIEs->abyRSN[18]; + } + } + return(pRSNIEs->len + WLAN_IEHDR_LEN); + } + return(0); +} diff --git a/drivers/staging/vt6655/wpa2.h b/drivers/staging/vt6655/wpa2.h new file mode 100644 index 00000000000..bda045b313b --- /dev/null +++ b/drivers/staging/vt6655/wpa2.h @@ -0,0 +1,100 @@ +/* + * 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: wpa2.h + * + * Purpose: Defines the macros, types, and functions for dealing + * with WPA2 informations. + * + * Author: Yiching Chen + * + * Date: Oct. 4, 2004 + * + */ + +#ifndef __WPA2_H__ +#define __WPA2_H__ + + +#if !defined(__TTYPE_H__) +#include "ttype.h" +#endif +#if !defined(__80211MGR_H__) +#include "80211mgr.h" +#endif +#if !defined(__80211HDR_H__) +#include "80211hdr.h" +#endif +#if !defined(__BSSDB_H__) +#include "bssdb.h" +#endif +#if !defined(__VNTWIFI_H__) +#include "vntwifi.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + +typedef struct tagsPMKIDInfo { + BYTE abyBSSID[6]; + BYTE abyPMKID[16]; +} PMKIDInfo, *PPMKIDInfo; + +typedef struct tagSPMKIDCache { + ULONG BSSIDInfoCount; + PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; +} SPMKIDCache, *PSPMKIDCache; + + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Functions --------------------------*/ +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +VOID +WPA2_ClearRSN ( + IN PKnownBSS pBSSNode + ); + +VOID +WPA2vParseRSN ( + IN PKnownBSS pBSSNode, + IN PWLAN_IE_RSN pRSN + ); + +UINT +WPA2uSetIEs( + IN PVOID pMgmtHandle, + OUT PWLAN_IE_RSN pRSNIEs + ); + + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + +#endif // __WPA2_H__ diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c new file mode 100644 index 00000000000..ee7109d1b8e --- /dev/null +++ b/drivers/staging/vt6655/wpactl.c @@ -0,0 +1,1014 @@ +/* + * 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: wpactl.c + * + * Purpose: handle wpa supplicant ioctl input/out functions + * + * Author: Lyndon Chen + * + * Date: Oct. 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#if !defined(__WMGR_H__) +#include "wmgr.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif +//2008-0717-05, <Add> by James +#if !defined(__RF_H__) +#include "rf.h" +#endif + +/*--------------------- Static Definitions -------------------------*/ + +#define VIAWGET_WPA_MAX_BUF_SIZE 1024 + + + +static const int frequency_list[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Functions --------------------------*/ + + + + +/*--------------------- Export Variables --------------------------*/ + + +static void wpadev_setup(struct net_device *dev) +{ + dev->type = ARPHRD_IEEE80211; + dev->hard_header_len = ETH_HLEN; + dev->mtu = 2048; + dev->addr_len = ETH_ALEN; + dev->tx_queue_len = 1000; + + memset(dev->broadcast,0xFF, ETH_ALEN); + + dev->flags = IFF_BROADCAST|IFF_MULTICAST; +} + + + +/* + * Description: + * register netdev for wpa supplicant deamon + * + * Parameters: + * In: + * pDevice - + * enable - + * Out: + * + * Return Value: + * + */ + +static int wpa_init_wpadev(PSDevice pDevice) +{ + struct net_device *dev = pDevice->dev; + int ret=0; + + pDevice->wpadev = alloc_netdev(0, "vntwpa", wpadev_setup); + if (pDevice->wpadev == NULL) + return -ENOMEM; + + pDevice->wpadev->priv = pDevice; + memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, U_ETHER_ADDR_LEN); + pDevice->wpadev->base_addr = dev->base_addr; + pDevice->wpadev->irq = dev->irq; + pDevice->wpadev->mem_start = dev->mem_start; + pDevice->wpadev->mem_end = dev->mem_end; + ret = register_netdev(pDevice->wpadev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n", + dev->name); + free_netdev(pDevice->wpadev); + return -1; + } + + if (pDevice->skb == NULL) { + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDevice->skb == NULL) + return -ENOMEM; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n", + dev->name, pDevice->wpadev->name); + + return 0; +} + + +/* + * Description: + * unregister net_device (wpadev) + * + * Parameters: + * In: + * pDevice - + * Out: + * + * Return Value: + * + */ + +static int wpa_release_wpadev(PSDevice pDevice) +{ + + if (pDevice->skb) { + dev_kfree_skb(pDevice->skb); + pDevice->skb = NULL; + } + + if (pDevice->wpadev) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->wpadev->name); + unregister_netdev(pDevice->wpadev); + free_netdev(pDevice->wpadev); + pDevice->wpadev = NULL; + } + + return 0; +} + + + + + +/* + * Description: + * Set enable/disable dev for wpa supplicant deamon + * + * Parameters: + * In: + * pDevice - + * val - + * Out: + * + * Return Value: + * + */ + +int wpa_set_wpadev(PSDevice pDevice, int val) +{ + + + if (val) + return wpa_init_wpadev(pDevice); + else + return wpa_release_wpadev(pDevice); +} + + +/* + * Description: + * Set WPA algorithm & keys + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel) +{ + struct viawget_wpa_param *param=ctx; + PSMgmtObject pMgmt = pDevice->pMgmt; + DWORD dwKeyIndex = 0; + BYTE abyKey[MAX_KEY_LEN]; + BYTE abySeq[MAX_KEY_LEN]; + QWORD KeyRSC; +// NDIS_802_11_KEY_RSC KeyRSC; + BYTE byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + int uu, ii; + + + if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) + return -EINVAL; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name); + if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + pDevice->bEncryptionEnable = FALSE; + pDevice->byKeyIndex = 0; + pDevice->bTransmitKey = FALSE; + KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset); + for (uu=0; uu<MAX_KEY_TABLE; uu++) { + MACvDisableKeyEntry(pDevice->PortOffset, uu); + } + return ret; + } + + //spin_unlock_irq(&pDevice->lock); + if(param->u.wpa_key.key && fcpfkernel) { + memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); + } + else { + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.key && + copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len)){ + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } +spin_lock_irq(&pDevice->lock); + } + + dwKeyIndex = (DWORD)(param->u.wpa_key.key_index); + + if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { + if (dwKeyIndex > 3) { + return -EINVAL; + } + else { + if (param->u.wpa_key.set_tx) { + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->bTransmitKey = TRUE; + dwKeyIndex |= (1 << 31); + } + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.wpa_key.key_len, + NULL, + abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID); + + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = TRUE; + return ret; + } + + //spin_unlock_irq(&pDevice->lock); + if(param->u.wpa_key.seq && fcpfkernel) { + memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); + } + else { + spin_unlock_irq(&pDevice->lock); + if (param->u.wpa_key.seq && + copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len)){ + + spin_lock_irq(&pDevice->lock); + return -EINVAL; + } +spin_lock_irq(&pDevice->lock); +} + + if (param->u.wpa_key.seq_len > 0) { + for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { + if (ii < 4) + LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8)); + else + HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8)); + //KeyRSC |= (abySeq[ii] << (ii * 8)); + } + dwKeyIndex |= 1 << 29; + } + + if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); + return -EINVAL; + } + + if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + } + + if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + } + + if (param->u.wpa_key.set_tx) + dwKeyIndex |= (1 << 31); + + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) + byKeyDecMode = KEY_CTL_CCMP; + else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) + byKeyDecMode = KEY_CTL_TKIP; + else + byKeyDecMode = KEY_CTL_WEP; + + // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled + if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { + if (param->u.wpa_key.key_len == MAX_KEY_LEN) + byKeyDecMode = KEY_CTL_TKIP; + else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { + if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) + byKeyDecMode = KEY_CTL_WEP; + } + + + // Check TKIP key length + if ((byKeyDecMode == KEY_CTL_TKIP) && + (param->u.wpa_key.key_len != MAX_KEY_LEN)) { + // TKIP Key must be 256 bits + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n")); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n"); + return -EINVAL; + } + // Check AES key length + if ((byKeyDecMode == KEY_CTL_CCMP) && + (param->u.wpa_key.key_len != AES_KEY_LEN)) { + // AES Key must be 128 bits + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n")); + return -EINVAL; + } + + // spin_lock_irq(&pDevice->lock); + if (IS_BROADCAST_ADDRESS(¶m->addr[0]) || (param->addr == NULL)) { + // If IS_BROADCAST_ADDRESS, set the key as every key entry's group key. + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); + + if ((KeybSetAllGroupKey(&(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) && + (KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) ) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); + + } else { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n")); + // spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); + // BSSID not 0xffffffffffff + // Pairwise Key can't be WEP + if (byKeyDecMode == KEY_CTL_WEP) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + + dwKeyIndex |= (1 << 30); // set pairwise key + if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + if (KeybSetKey(&(pDevice->sKey), + ¶m->addr[0], + dwKeyIndex, + param->u.wpa_key.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); + + } else { + // Key Table Full + if (IS_ETH_ADDRESS_EQUAL(¶m->addr[0], pDevice->abyBSSID)) { + //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + + } else { + // Save Key and configure just before associate/reassociate to BSSID + // we do not implement now + //spin_unlock_irq(&pDevice->lock); + return -EINVAL; + } + } + } // BSSID not 0xffffffffffff + if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { + pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index; + pDevice->bTransmitKey = TRUE; + } + pDevice->bEncryptionEnable = TRUE; + //spin_unlock_irq(&pDevice->lock); + +/* + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4] + ); +*/ + + return ret; + +} + + +/* + * Description: + * enable wpa auth & mode + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_wpa(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + pMgmt->bShareKeyAlgorithm = FALSE; + + return ret; +} + + + + + /* + * Description: + * set disassociate + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_disassociate(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + spin_lock_irq(&pDevice->lock); + if (pDevice->bLinkPass) { + if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6)) + bScheduleCommand((HANDLE)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + } + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + + +/* + * Description: + * enable scan process + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_scan(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + int ret = 0; + + spin_lock_irq(&pDevice->lock); + BSSvClearBSSList((HANDLE)pDevice, pDevice->bLinkPass); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, NULL); + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + + +/* + * Description: + * get bssid + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_bssid(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + + memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID , 6); + + return ret; + +} + + +/* + * Description: + * get bssid + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_ssid(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + int ret = 0; + + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID; + + memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID , pItemSSID->len); + param->u.wpa_associate.ssid_len = pItemSSID->len; + + return ret; +} + + + +/* + * Description: + * get scan results + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_get_scan(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + struct viawget_scan_result *scan_buf; + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + PKnownBSS pBSS; + PBYTE pBuf; + int ret = 0; + u16 count = 0; + u16 ii, jj; +#if 1 + + PBYTE ptempBSS; + + + + ptempBSS = kmalloc(sizeof(KnownBSS), (int)GFP_ATOMIC); + + if (ptempBSS == NULL) { + + printk("bubble sort kmalloc memory fail@@@\n"); + + ret = -ENOMEM; + + return ret; + + } + + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + + for(jj=0;jj<MAX_BSS_NUM-ii-1;jj++) { + + if((pMgmt->sBSSList[jj].bActive!=TRUE) || + + ((pMgmt->sBSSList[jj].uRSSI>pMgmt->sBSSList[jj+1].uRSSI) &&(pMgmt->sBSSList[jj+1].bActive!=FALSE))) { + + memcpy(ptempBSS,&pMgmt->sBSSList[jj],sizeof(KnownBSS)); + + memcpy(&pMgmt->sBSSList[jj],&pMgmt->sBSSList[jj+1],sizeof(KnownBSS)); + + memcpy(&pMgmt->sBSSList[jj+1],ptempBSS,sizeof(KnownBSS)); + + } + + } + + }; + + kfree(ptempBSS); + + // printk("bubble sort result:\n"); + + //for (ii = 0; ii < MAX_BSS_NUM; ii++) + + // printk("%d [%s]:RSSI=%d\n",ii,((PWLAN_IE_SSID)(pMgmt->sBSSList[ii].abySSID))->abySSID, + + // pMgmt->sBSSList[ii].uRSSI); + + #endif + +//******mike:bubble sort by stronger RSSI*****// + + + + + count = 0; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0; ii < MAX_BSS_NUM; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (!pBSS->bActive) + continue; + count++; + }; + + pBuf = kmalloc(sizeof(struct viawget_scan_result) * count, (int)GFP_ATOMIC); + + if (pBuf == NULL) { + ret = -ENOMEM; + return ret; + } + memset(pBuf, 0, sizeof(struct viawget_scan_result) * count); + scan_buf = (struct viawget_scan_result *)pBuf; + pBSS = &(pMgmt->sBSSList[0]); + for (ii = 0, jj = 0; ii < MAX_BSS_NUM ; ii++) { + pBSS = &(pMgmt->sBSSList[ii]); + if (pBSS->bActive) { + if (jj >= count) + break; + memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN); + pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID; + memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len); + scan_buf->ssid_len = pItemSSID->len; + scan_buf->freq = frequency_list[pBSS->uChannel-1]; + scan_buf->caps = pBSS->wCapInfo; + //scan_buf->caps = pBSS->wCapInfo; + //scan_buf->qual = + //scan_buf->noise = + //scan_buf->level = + //scan_buf->maxrate = + if (pBSS->wWPALen != 0) { + scan_buf->wpa_ie_len = pBSS->wWPALen; + memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen); + } + if (pBSS->wRSNLen != 0) { + scan_buf->rsn_ie_len = pBSS->wRSNLen; + memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen); + } + scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result)); + jj ++; + } + } + + if (jj < count) + count = jj; + + if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count)) { + ret = -EFAULT; + }; + param->u.scan_results.scan_count = count; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count) + + kfree(pBuf); + return ret; +} + + + +/* + * Description: + * set associate with AP + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int wpa_set_associate(PSDevice pDevice, + struct viawget_wpa_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + PWLAN_IE_SSID pItemSSID; + BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + BYTE abyWPAIE[64]; + int ret = 0; + BOOL bWepEnabled=FALSE; + + // set key type & algorithm + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); + + + if (param->u.wpa_associate.wpa_ie && + copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) + return -EINVAL; + + if (param->u.wpa_associate.mode == 1) + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; + else + pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA; + // set ssid + memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); + pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID; + pItemSSID->byElementID = WLAN_EID_SSID; + pItemSSID->len = param->u.wpa_associate.ssid_len; + memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len); + // set bssid + if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) + memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); +else +{ + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID); +} + + if (param->u.wpa_associate.wpa_ie_len == 0) { + if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY) + pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; + else + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + } else if (abyWPAIE[0] == RSN_INFO_ELEM) { + if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; + else + pMgmt->eAuthenMode = WMAC_AUTH_WPA2; + } else { + if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE) + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK) + pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; + else + pMgmt->eAuthenMode = WMAC_AUTH_WPA; + } + + switch (param->u.wpa_associate.pairwise_suite) { + case CIPHER_CCMP: + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + break; + case CIPHER_TKIP: + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + break; + case CIPHER_WEP40: + case CIPHER_WEP104: + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + bWepEnabled=TRUE; + break; + case CIPHER_NONE: + if (param->u.wpa_associate.group_suite == CIPHER_CCMP) + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + else + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + break; + default: + pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + }; + +//DavidWang add for WPA_supplicant support open/share mode + + if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; + pMgmt->bShareKeyAlgorithm = TRUE; + } + else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { + if(!bWepEnabled) pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + //pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + //pMgmt->bShareKeyAlgorithm = FALSE; //20080717-06,<Modify> by chester//Fix Open mode, WEP encrytion + } +//mike save old encryption status + pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus; + + if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled) + pDevice->bEncryptionEnable = TRUE; + else + pDevice->bEncryptionEnable = FALSE; +if (!((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) || + ((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bWepEnabled==TRUE))) ) //DavidWang //20080717-06,<Modify> by chester//Not to initial WEP + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); + spin_lock_irq(&pDevice->lock); + pDevice->bLinkPass = FALSE; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); + //20080701-02,<Add> by Mike Liu +/*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/ +{ + PKnownBSS pCurr = NULL; + pCurr = BSSpSearchBSSList(pDevice, + pMgmt->abyDesireBSSID, + pMgmt->abyDesireSSID, + pMgmt->eConfigPHYMode + ); + + if (pCurr == NULL){ + printk("wpa_set_associate---->hidden mode site survey before associate.......\n"); + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + }; +} +/****************************************************************/ + bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + + return ret; +} + + +/* + * Description: + * wpa_ioctl main function supported for wpa supplicant + * + * Parameters: + * In: + * pDevice - + * iw_point - + * Out: + * + * Return Value: + * + */ + +int wpa_ioctl(PSDevice pDevice, struct iw_point *p) +{ + struct viawget_wpa_param *param; + int ret = 0; + int wpa_ioctl = 0; + + if (p->length < sizeof(struct viawget_wpa_param) || + p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct viawget_wpa_param *) kmalloc((int)p->length, (int)GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + ret = -EFAULT; + goto out; + } + + switch (param->cmd) { + case VIAWGET_SET_WPA: + ret = wpa_set_wpa(pDevice, param); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n"); + break; + + case VIAWGET_SET_KEY: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n"); + spin_lock_irq(&pDevice->lock); + ret = wpa_set_keys(pDevice, param, FALSE); + spin_unlock_irq(&pDevice->lock); + break; + + case VIAWGET_SET_SCAN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n"); + ret = wpa_set_scan(pDevice, param); + break; + + case VIAWGET_GET_SCAN: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n"); + ret = wpa_get_scan(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_GET_SSID: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n"); + ret = wpa_get_ssid(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_GET_BSSID: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n"); + ret = wpa_get_bssid(pDevice, param); + wpa_ioctl = 1; + break; + + case VIAWGET_SET_ASSOCIATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n"); + ret = wpa_set_associate(pDevice, param); + break; + + case VIAWGET_SET_DISASSOCIATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n"); + ret = wpa_set_disassociate(pDevice, param); + break; + + case VIAWGET_SET_DROP_UNENCRYPT: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n"); + break; + + case VIAWGET_SET_DEAUTHENTICATE: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n"); + break; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n", + param->cmd); + return -EOPNOTSUPP; + break; + } + + if ((ret == 0) && wpa_ioctl) { + if (copy_to_user(p->pointer, param, p->length)) { + ret = -EFAULT; + goto out; + } + } + +out: + if (param != NULL) + kfree(param); + + return ret; +} + diff --git a/drivers/staging/vt6655/wpactl.h b/drivers/staging/vt6655/wpactl.h new file mode 100644 index 00000000000..9e788978530 --- /dev/null +++ b/drivers/staging/vt6655/wpactl.h @@ -0,0 +1,89 @@ +/* + * 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: wpactl.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: March 1, 2005 + * + */ + + +#ifndef __WPACTL_H__ +#define __WPACTL_H__ + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +#if !defined(__IOWPA_H__) +#include "iowpa.h" +#endif +#endif + +/*--------------------- Export Definitions -------------------------*/ + + +//WPA related + +typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; +typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, + CIPHER_WEP104 } wpa_cipher; +typedef enum { KEY_MGMT_802_1X, KEY_MGMT_CCKM,KEY_MGMT_PSK, KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; + +#define AUTH_ALG_OPEN_SYSTEM 0x01 +#define AUTH_ALG_SHARED_KEY 0x02 +#define AUTH_ALG_LEAP 0x04 + +#define GENERIC_INFO_ELEM 0xdd +#define RSN_INFO_ELEM 0x30 + + + +typedef ULONGLONG NDIS_802_11_KEY_RSC; + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +int wpa_set_wpadev(PSDevice pDevice, int val); +int wpa_ioctl(PSDevice pDevice, struct iw_point *p); +int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __WPACL_H__ + + + diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c new file mode 100644 index 00000000000..219ae21654e --- /dev/null +++ b/drivers/staging/vt6655/wroute.c @@ -0,0 +1,211 @@ +/* + * 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: + * + */ + + +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__TCRC_H__) +#include "tcrc.h" +#endif +#if !defined(__RXTX_H__) +#include "rxtx.h" +#endif +#if !defined(__WROUTE_H__) +#include "wroute.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +/*--------------------- 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: + * TURE, FALSE + * + * Return Value: TRUE if packet duplicate; otherwise FALSE + * + */ +BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, UINT uDataLen, UINT uNodeIndex) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxDesc pHeadTD, pLastTD; + UINT cbFrameBodySize; + UINT uMACfragNum; + BYTE byPktTyp; + BOOL bNeedEncryption = FALSE; + SKeyItem STempKey; + PSKeyItem pTransmitKey = NULL; + UINT cbHeaderSize; + UINT ii; + PBYTE pbyBSSID; + + + + + if (AVAIL_TD(pDevice, TYPE_AC0DMA)<=0) { + DEVICE_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, (PBYTE)pbySkbData, U_HEADER_LEN); + + cbFrameBodySize = uDataLen - U_HEADER_LEN; + + if (ntohs(pDevice->sTxEthHeader.wType) > MAX_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; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode); + } else { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); + } + } + + if (pDevice->bEnableHostWEP) { + if (uNodeIndex >= 0) { + 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; + } + byPktTyp = (BYTE)pDevice->byPacketType; + + if (pDevice->bFixRate) { + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (WORD)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 = (WORD)pDevice->uConnectionRate; + } + } + } + else { + pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + } + + if (pDevice->wCurrentRate <= RATE_11M) + byPktTyp = PK_TYPE_11B; + + vGenerateFIFOHeader(pDevice, byPktTyp, 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; +} + + + diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h new file mode 100644 index 00000000000..ea5f5896e9b --- /dev/null +++ b/drivers/staging/vt6655/wroute.h @@ -0,0 +1,65 @@ +/* + * 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.h + * + * Purpose: + * + * Author: Lyndon Chen + * + * Date: May 21, 2003 + * + */ + + +#ifndef __WROUTE_H__ +#define __WROUTE_H__ + + +#if !defined(__DEVICE_H__) +#include "device.h" +#endif + + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +#ifdef __cplusplus +extern "C" { /* Assume C declarations for C++ */ +#endif /* __cplusplus */ + +BOOL ROUTEbRelay (PSDevice pDevice, PBYTE pbySkbData, UINT uDataLen, UINT uNodeIndex); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif /* __cplusplus */ + + + + +#endif // __WROUTE_H__ + + + |