Commit 66101de1 authored by Pavel Machek's avatar Pavel Machek Committed by Greg Kroah-Hartman

Staging: add w35und wifi driver

This is driver for w35und usb wifi -- also in kohjinsha
subnotebook. It should work well enough to associate and ping, but it
obviously needs to be rewritten two more times...

OTOH worst horrors (like embedded wifi stack) should have been fixed
already...
Signed-off-by: default avatarPavel Machek <pavel@suse.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4d7b5c7f
......@@ -35,4 +35,6 @@ source "drivers/staging/go7007/Kconfig"
source "drivers/staging/usbip/Kconfig"
source "drivers/staging/winbond/Kconfig"
endif # STAGING
......@@ -6,3 +6,4 @@ obj-$(CONFIG_SXG) += sxg/
obj-$(CONFIG_ME4000) += me4000/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
config W35UND
tristate "Winbond driver"
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL && !4KSTACKS
default n
---help---
This is highly experimental driver for winbond wifi card on some Kohjinsha notebooks
Check http://code.google.com/p/winbondport/ for new version
DRIVER_DIR=./linux
w35und-objs := $(DRIVER_DIR)/wbusb.o $(DRIVER_DIR)/wb35reg.o $(DRIVER_DIR)/wb35rx.o $(DRIVER_DIR)/wb35tx.o \
mds.o \
mlmetxrx.o \
mto.o \
phy_calibration.o \
reg.o \
rxisr.o \
sme_api.o \
wbhal.o \
wblinux.o \
obj-$(CONFIG_W35UND) += w35und.o
TODO:
- sparse cleanups
- checkpatch cleanups
- kerneldoc cleanups
- remove typedefs
- remove unused ioctls
- use cfg80211 for regulatory stuff
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
Pavel Machek <pavel@suse.cz>
//
// ADAPTER.H -
// Windows NDIS global variable 'Adapter' typedef
//
#define MAX_ANSI_STRING 40
typedef struct WB32_ADAPTER
{
u32 AdapterIndex; // 20060703.4 Add for using pAdapterContext global Adapter point
WB_LOCALDESCRIPT sLocalPara; // Myself connected parameters
PWB_BSSDESCRIPTION asBSSDescriptElement;
MLME_FRAME sMlmeFrame; // connect to peerSTA parameters
MTO_PARAMETERS sMtoPara; // MTO_struct ...
hw_data_t sHwData; //For HAL
MDS Mds;
WBLINUX WbLinux;
struct iw_statistics iw_stats;
u8 LinkName[MAX_ANSI_STRING];
} WB32_ADAPTER, ADAPTER, *PWB32_ADAPTER, *PADAPTER;
//
// BSS descriptor DataBase management global function
//
void vBSSdescriptionInit(PWB32_ADAPTER Adapter);
void vBSSfoundList(PWB32_ADAPTER Adapter);
u8 boChanFilter(PWB32_ADAPTER Adapter, u8 ChanNo);
u16 wBSSallocateEntry(PWB32_ADAPTER Adapter);
u16 wBSSGetEntry(PWB32_ADAPTER Adapter);
void vSimpleHouseKeeping(PWB32_ADAPTER Adapter);
u16 wBSShouseKeeping(PWB32_ADAPTER Adapter);
void ClearBSSdescpt(PWB32_ADAPTER Adapter, u16 i);
u16 wBSSfindBssID(PWB32_ADAPTER Adapter, u8 *pbBssid);
u16 wBSSfindDedicateCandidate(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid, u8 *pbBssid);
u16 wBSSfindMACaddr(PWB32_ADAPTER Adapter, u8 *pbMacAddr);
u16 wBSSsearchMACaddr(PWB32_ADAPTER Adapter, u8 *pbMacAddr, u8 band);
u16 wBSSaddScanData(PWB32_ADAPTER, u16, psRXDATA);
u16 wBSSUpdateScanData(PWB32_ADAPTER Adapter, u16 wBssIdx, psRXDATA psRcvData);
u16 wBSScreateIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData);
void DesiredRate2BSSdescriptor(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData,
u8 *pBasicRateSet, u8 BasicRateCount,
u8 *pOperationRateSet, u8 OperationRateCount);
void DesiredRate2InfoElement(PWB32_ADAPTER Adapter, u8 *addr, u16 *iFildOffset,
u8 *pBasicRateSet, u8 BasicRateCount,
u8 *pOperationRateSet, u8 OperationRateCount);
void BSSAddIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData);
unsigned char boCmpMacAddr( PUCHAR, PUCHAR );
unsigned char boCmpSSID(struct SSID_Element *psSSID1, struct SSID_Element *psSSID2);
u16 wBSSfindSSID(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid);
u16 wRoamingQuery(PWB32_ADAPTER Adapter);
void vRateToBitmap(PWB32_ADAPTER Adapter, u16 index);
u8 bRateToBitmapIndex(PWB32_ADAPTER Adapter, u8 bRate);
u8 bBitmapToRate(u8 i);
unsigned char boIsERPsta(PWB32_ADAPTER Adapter, u16 i);
unsigned char boCheckConnect(PWB32_ADAPTER Adapter);
unsigned char boCheckSignal(PWB32_ADAPTER Adapter);
void AddIBSSIe(PWB32_ADAPTER Adapter,PWB_BSSDESCRIPTION psDesData );//added by ws for WPA_None06/01/04
void BssScanUpToDate(PWB32_ADAPTER Adapter);
void BssUpToDate(PWB32_ADAPTER Adapter);
void RateSort(u8 *RateArray, u8 num, u8 mode);
void RateReSortForSRate(PWB32_ADAPTER Adapter, u8 *RateArray, u8 num);
void Assemble_IE(PWB32_ADAPTER Adapter, u16 wBssIdx);
void SetMaxTxRate(PWB32_ADAPTER Adapter);
void CreateWpaIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
struct Association_Request_Frame_Body* msgBody, u16 iMSindex); //added by WS 05/14/05
#ifdef _WPA2_
void CreateRsnIE(PWB32_ADAPTER Adapter, u16* iFildOffset, PUCHAR msg, struct Management_Frame* msgHeader,
struct Association_Request_Frame_Body* msgBody, u16 iMSindex);//added by WS 05/14/05
u16 SearchPmkid(PWB32_ADAPTER Adapter, struct Management_Frame* msgHeader,
struct PMKID_Information_Element * AssoReq_PMKID );
#endif
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// bssdscpt.c
// BSS descriptor data base
// history :
//
// Description:
// BSS descriptor data base will store the information of the stations at the
// surrounding environment. The first entry( psBSS(0) ) will not be used and the
// second one( psBSS(1) ) will be used for the broadcast address.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#define MAX_ACC_RSSI_COUNT 10
#define MAX_ACC_RSSI_COUNT 6
///////////////////////////////////////////////////////////////////////////
//
// BSS Description set Element , to store scan received Beacon information
//
// Our's differs slightly from the specs. The specify a PHY_Parameter_Set.
// Since we're only doing a DS design right now, we just have a DS structure.
//////////////////////////////////////////////////////////////////////////////
typedef struct BSSDescriptionElement
{
u32 SlotValid;
u32 PowerSaveMode;
RXLAYER1 RxLayer1;
u8 abPeerAddress[ MAC_ADDR_LENGTH + 2 ]; // peer MAC Address associated with this session. 6-OCTET value
u32 dwBgScanStamp; // BgScan Sequence Counter stamp, record psROAM->dwScanCounter.
u16 Beacon_Period;
u16 wATIM_Window;
u8 abBssID[ MAC_ADDR_LENGTH + 2 ]; // 6B
u8 bBssType;
u8 DTIM_Period; // 1 octet usually from TIM element, if present
u8 boInTimerHandler;
u8 boERP; // analysis ERP or (extended) supported rate element
u8 Timestamp[8];
u8 BasicRate[32];
u8 OperationalRate[32];
u32 dwBasicRateBitmap; //bit map, retrieve from SupportedRateSet
u32 dwOperationalRateBitmap; //bit map, retrieve from SupportedRateSet and
// ExtendedSupportedRateSet
// For RSSI calculating
u32 HalRssi[MAX_ACC_RSSI_COUNT]; // Encode. It must use MACRO of HAL to get the LNA and AGC data
u32 HalRssiIndex;
////From beacon/probe response
struct SSID_Element SSID; // 34B
u8 reserved_1[ 2 ];
struct Capability_Information_Element CapabilityInformation; // 2B
u8 reserved_2[ 2 ];
struct CF_Parameter_Set_Element CF_Parameter_Set; // 8B
struct IBSS_Parameter_Set_Element IBSS_Parameter_Set; // 4B
struct TIM_Element TIM_Element_Set; // 256B
struct DS_Parameter_Set_Element DS_Parameter_Set; // 3B
u8 reserved_3;
struct ERP_Information_Element ERP_Information_Set; // 3B
u8 reserved_4;
struct Supported_Rates_Element SupportedRateSet; // 10B
u8 reserved_5[2];
struct Extended_Supported_Rates_Element ExtendedSupportedRateSet; // 257B
u8 reserved_6[3];
u8 band;
u8 reserved_7[3];
// for MLME module
u16 wState; // the current state of the system
u16 wIndex; // THIS BSS element entry index
void* psAdapter; // pointer to THIS Adapter
OS_TIMER nTimer; // MLME timer
// Authentication
u16 wAuthAlgo; // peer MAC MLME use Auth algorithm, default OPEN_AUTH
u16 wAuthSeqNum; // current local MAC sendout AuthReq sequence number
u8 auth_challengeText[128];
////For XP:
u32 ies_len; // information element length
u8 ies[256]; // information element
////For WPA
u8 RsnIe_Type[2]; //added by ws for distinguish WPA and WPA2 05/14/04
u8 RsnIe_len;
u8 Rsn_Num;
// to record the rsn cipher suites,addded by ws 09/05/04
SUITE_SELECTOR group_cipher; // 4B
SUITE_SELECTOR pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT];
SUITE_SELECTOR auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT];
u16 pairwise_key_cipher_suite_count;
u16 auth_key_mgt_suite_count;
u8 pairwise_key_cipher_suite_selected;
u8 auth_key_mgt_suite_selected;
u8 reserved_8[2];
struct RSN_Capability_Element rsn_capabilities; // 2B
u8 reserved_9[2];
//to record the rsn cipher suites for WPA2
#ifdef _WPA2_
u32 pre_auth; //added by WS for distinguish for 05/04/04
SUITE_SELECTOR wpa2_group_cipher; // 4B
SUITE_SELECTOR wpa2_pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT];
SUITE_SELECTOR wpa2_auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT];
u16 wpa2_pairwise_key_cipher_suite_count;
u16 wpa2_auth_key_mgt_suite_count;
u8 wpa2_pairwise_key_cipher_suite_selected;
u8 wpa2_auth_key_mgt_suite_selected;
u8 reserved_10[2];
struct RSN_Capability_Element wpa2_rsn_capabilities; // 2B
u8 reserved_11[2];
#endif //endif _WPA2_
//For Replay protection
// u8 PairwiseTSC[6];
// u8 GroupTSC[6];
////For up-to-date
u32 ScanTimeStamp; //for the decision whether the station/AP(may exist at
//different channels) has left. It must be detected by
//scanning. Local device may connected or disconnected.
u32 BssTimeStamp; //Only for the decision whether the station/AP(exist in
//the same channel, and no scanning) if local device has
//connected successfully.
// 20061108 Add for storing WPS_IE. [E id][Length][OUI][Data]
u8 WPS_IE_Data[MAX_IE_APPEND_SIZE];
u16 WPS_IE_length;
u16 WPS_IE_length_tmp; // For verify there is an WPS_IE in Beacon or probe response
} WB_BSSDESCRIPTION, *PWB_BSSDESCRIPTION;
#define wBSSConnectedSTA(Adapter) \
((u16)(Adapter)->sLocalPara.wConnectedSTAindex)
#define psBSS(i) (&(Adapter->asBSSDescriptElement[(i)]))
// 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) )
typedef struct tkip
{
u32 K0, K1; // Key
union
{
struct // Current state
{
u32 L;
u32 R;
};
u8 LR[8];
};
union
{
u32 M; // Message accumulator (single word)
u8 Mb[4];
};
s32 bytes_in_M; // # bytes in M
} tkip_t;
//void _append_data( PUCHAR pData, u16 size, tkip_t *p );
void Mds_MicGet( void* Adapter, void* pRxLayer1, PUCHAR pKey, PUCHAR pMic );
void Mds_MicFill( void* Adapter, void* pDes, PUCHAR XmitBufAddress );
#ifndef __GL_80211_H__
#define __GL_80211_H__
/****************** CONSTANT AND MACRO SECTION ******************************/
/* BSS Type */
enum {
WLAN_BSSTYPE_INFRASTRUCTURE = 0,
WLAN_BSSTYPE_INDEPENDENT,
WLAN_BSSTYPE_ANY_BSS,
};
/* Preamble_Type, see <SFS-802.11G-MIB-203> */
typedef enum preamble_type {
WLAN_PREAMBLE_TYPE_SHORT,
WLAN_PREAMBLE_TYPE_LONG,
} preamble_type_e;
/* Slot_Time_Type, see <SFS-802.11G-MIB-208> */
typedef enum slot_time_type {
WLAN_SLOT_TIME_TYPE_LONG,
WLAN_SLOT_TIME_TYPE_SHORT,
} slot_time_type_e;
/*--------------------------------------------------------------------------*/
/* Encryption Mode */
typedef enum {
WEP_DISABLE = 0,
WEP_64,
WEP_128,
ENCRYPT_DISABLE,
ENCRYPT_WEP,
ENCRYPT_WEP_NOKEY,
ENCRYPT_TKIP,
ENCRYPT_TKIP_NOKEY,
ENCRYPT_CCMP,
ENCRYPT_CCMP_NOKEY,
} encryption_mode_e;
typedef enum _WLAN_RADIO {
WLAN_RADIO_ON,
WLAN_RADIO_OFF,
WLAN_RADIO_MAX, // not a real type, defined as an upper bound
} WLAN_RADIO;
typedef struct _WLAN_RADIO_STATUS {
WLAN_RADIO HWStatus;
WLAN_RADIO SWStatus;
} WLAN_RADIO_STATUS;
//----------------------------------------------------------------------------
// 20041021 1.1.81.1000 ybjiang
// add for radio notification
typedef
void (*RADIO_NOTIFICATION_HANDLER)(
void *Data,
void *RadioStatusBuffer,
u32 RadioStatusBufferLen
);
typedef struct _WLAN_RADIO_NOTIFICATION
{
RADIO_NOTIFICATION_HANDLER RadioChangeHandler;
void *Data;
} WLAN_RADIO_NOTIFICATION;
//----------------------------------------------------------------------------
// 20041102 1.1.91.1000 ybjiang
// add for OID_802_11_CUST_REGION_CAPABILITIES and OID_802_11_OID_REGION
typedef enum _WLAN_REGION_CODE
{
WLAN_REGION_UNKNOWN,
WLAN_REGION_EUROPE,
WLAN_REGION_JAPAN,
WLAN_REGION_USA,
WLAN_REGION_FRANCE,
WLAN_REGION_SPAIN,
WLAN_REGION_ISRAEL,
WLAN_REGION_MAX, // not a real type, defined as an upper bound
} WLAN_REGION_CODE;
#define REGION_NAME_MAX_LENGTH 256
typedef struct _WLAN_REGION_CHANNELS
{
u32 Length;
u32 NameLength;
u8 Name[REGION_NAME_MAX_LENGTH];
WLAN_REGION_CODE Code;
u32 Frequency[1];
} WLAN_REGION_CHANNELS;
typedef struct _WLAN_REGION_CAPABILITIES
{
u32 NumberOfItems;
WLAN_REGION_CHANNELS Region[1];
} WLAN_REGION_CAPABILITIES;
typedef struct _region_name_map {
WLAN_REGION_CODE region;
u8 *name;
u32 *channels;
} region_name_map;
/*--------------------------------------------------------------------------*/
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
// TODO: 0627 kevin
#define MIC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
#define MICSTR "%02X %02X %02X %02X %02X %02X %02X %02X"
#define MICKEY2STR(a) MIC2STR(a)
#define MICKEYSTR MICSTR
#endif /* __GL_80211_H__ */
/*** end of file ***/
//============================================================================
// IOCTLS.H -
//
// Description:
// Define the IOCTL codes.
//
// Revision history:
// --------------------------------------------------------------------------
//
// Copyright (c) 2002-2004 Winbond Electronics Corp. All rights reserved.
//=============================================================================
#ifndef _IOCTLS_H
#define _IOCTLS_H
// PD43 Keep it - Used with the Win33 application
// #include <winioctl.h>
//========================================================
// 20040108 ADD the follow for test
//========================================================
#define INFORMATION_LENGTH sizeof(unsigned int)
#define WB32_IOCTL_INDEX 0x0900 //­×§ďĽHŤKŹŰŽe//
#define Wb32_RegisterRead CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 0, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_RegisterWrite CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 1, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_SendPacket CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 2, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_QuerySendResult CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 3, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_SetFragmentThreshold CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 4, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_SetLinkStatus CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 5, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_SetBulkIn CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 6, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb32_LoopbackTest CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 7, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_EEPromRead CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 8, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_EEPromWrite CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 9, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_FlashReadData CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 10, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_FlashWrite CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 11, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_FlashWriteBurst CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 12, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_TxBurstStart CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 13, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_TxBurstStop CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 14, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define Wb35_TxBurstStatus CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB32_IOCTL_INDEX + 15, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// For IOCTL interface
//================================================
#define LINKNAME_STRING "\\DosDevices\\W35UND"
#define NTDEVICE_STRING "\\Device\\W35UND"
#define APPLICATION_LINK "\\\\.\\W35UND"
#define WB_IOCTL_INDEX 0x0800
#define WB_IOCTL_TS_INDEX WB_IOCTL_INDEX + 60
#define WB_IOCTL_DUT_INDEX WB_IOCTL_TS_INDEX + 40
//=============================================================================
// IOCTLS defined for DUT (Device Under Test)
// IOCTL_WB_802_11_DUT_MAC_ADDRESS
// Query: Return the dot11StationID
// Set : Set the dot11StationID. Demo only.
//
#define IOCTL_WB_802_11_DUT_MAC_ADDRESS CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 1, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_BSS_DESCRIPTION
// Query: Return the info. of the current connected BSS.
// Set : None.
//
#define IOCTL_WB_802_11_DUT_BSS_DESCRIPTION CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 2, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_TX_RATE
// Query: Return the current transmission rate.
// Set : Set the transmission rate of the Tx packets.
//
#define IOCTL_WB_802_11_DUT_TX_RATE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 3, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_CURRENT_STA_STATE
// Query: Return the current STA state. (WB_STASTATE type)
// Set : None.
//
#define IOCTL_WB_802_11_DUT_CURRENT_STA_STATE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 4, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
/////////// 10/31/02' Added /////////////////////
// IOCTL_WB_802_11_DUT_START_IBSS_REQUEST
// Query: None.
// Set : Start a new IBSS
//
#define IOCTL_WB_802_11_DUT_START_IBSS_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 5, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_JOIN_REQUEST
// Query: None.
// Set : Synchronize with the selected BSS
//
#define IOCTL_WB_802_11_DUT_JOIN_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 6, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_AUTHEN_REQUEST
// Query: None.
// Set : Authenticate with the BSS
//
#define IOCTL_WB_802_11_DUT_AUTHEN_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 7, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST
// Query: None.
// Set : DeAuthenticate withe the BSS
//
#define IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 8, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_ASSOC_REQUEST
// Query: None.
// Set : Associate withe the BSS
//
#define IOCTL_WB_802_11_DUT_ASSOC_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 9, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_REASSOC_REQUEST
// Query: None.
// Set : ReAssociate withe the BSS
//
#define IOCTL_WB_802_11_DUT_REASSOC_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 10, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_DISASSOC_REQUEST
// Query: None.
// Set : DisAssociate withe the BSS
//
#define IOCTL_WB_802_11_DUT_DISASSOC_REQUEST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 11, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_FRAG_THRESHOLD
// Query: Return the dot11FragmentThreshold
// Set : Set the dot11FragmentThreshold
//
#define IOCTL_WB_802_11_DUT_FRAG_THRESHOLD CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 12, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_RTS_THRESHOLD
// Query: Return the dot11RTSThreshold
// Set : Set the dot11RTSThresold
//
#define IOCTL_WB_802_11_DUT_RTS_THRESHOLD CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 13, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_WEP_KEYMODE
// Query: Get the WEP key mode.
// Set : Set the WEP key mode: disable/64 bits/128 bits
//
#define IOCTL_WB_802_11_DUT_WEP_KEYMODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 14, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_WEP_KEYVALUE
// Query: None.
// Set : fill in the WEP key value
//
#define IOCTL_WB_802_11_DUT_WEP_KEYVALUE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 15, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_RESET
// Query: None.
// Set : Reset S/W and H/W
//
#define IOCTL_WB_802_11_DUT_RESET CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 16, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_POWER_SAVE
// Query: None.
// Set : Set Power Save Mode
//
#define IOCTL_WB_802_11_DUT_POWER_SAVE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 17, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN
// Query: None.
// Set :
//
#define IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 18, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_BSSID_LIST
// Query: Return the BSS info of BSSs in the last scanning process
// Set : None.
//
#define IOCTL_WB_802_11_DUT_BSSID_LIST CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 19, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_STATISTICS
// Query: Return the statistics of Tx/Rx.
// Set : None.
//
#define IOCTL_WB_802_11_DUT_STATISTICS CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 20, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_ACCEPT_BEACON
// Query: Return the current mode to accept beacon or not.
// Set : Enable or disable allowing the HW-MAC to pass the beacon to the SW-MAC
// Arguments: unsigned char
//
#define IOCTL_WB_802_11_DUT_ACCEPT_BEACON CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 21, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_ROAMING
// Query: Return the roaming function status
// Set : Enable/Disable the roaming function.
#define IOCTL_WB_802_11_DUT_ROAMING CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 22, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_DTO
// Query: Return the DTO(Data Throughput Optimization)
// function status (TRUE or FALSE)
// Set : Enable/Disable the DTO function.
//
#define IOCTL_WB_802_11_DUT_DTO CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 23, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY
// Query: Return the antenna diversity status. (TRUE/ON or FALSE/OFF)
// Set : Enable/Disable the antenna diversity.
//
#define IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 24, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
//-------------- new added for a+b+g ---------------------
// IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE
// Query: Return the MAC operation mode. (MODE_802_11_BG, MODE_802_11_A,
// MODE_802_11_ABG, MODE_802_11_BG_IBSS)
// Set : Set the MAC operation mode.
//
#define IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 25, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED
// Query: Return the current tx rate which follows the definition in spec. (for
// example, 5.5M => 0x0b)
// Set : None
//
#define IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 26, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_PREAMBLE_MODE
// Query: Return the preamble mode. (auto or long)
// Set : Set the preamble mode.
//
#define IOCTL_WB_802_11_DUT_PREAMBLE_MODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 27, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_SLOT_TIME_MODE
// Query: Return the slot time mode. (auto or long)
// Set : Set the slot time mode.
//
#define IOCTL_WB_802_11_DUT_SLOT_TIME_MODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 28, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
//------------------------------------------------------------------
// IOCTL_WB_802_11_DUT_ADVANCE_STATUS
// Query:
// Set : NONE
//
#define IOCTL_WB_802_11_DUT_ADVANCE_STATUS CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 29, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_TX_RATE_MODE
// Query: Return the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX)
// Set : Set the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX)
//
#define IOCTL_WB_802_11_DUT_TX_RATE_MODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 30, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_DTO_PARA
// Query: Return the DTO parameters
// Set : Set the DTO parameters
//
#define IOCTL_WB_802_11_DUT_DTO_PARA CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 31, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_EVENT_LOG
// Query: Return event log
// Set : Reset event log
//
#define IOCTL_WB_802_11_DUT_EVENT_LOG CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 32, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_CWMIN
// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS)
// Set : Set CWMin value
//
#define IOCTL_WB_802_11_DUT_CWMIN CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 33, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_DUT_CWMAX
// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS)
// Set : Set CWMax value
//
#define IOCTL_WB_802_11_DUT_CWMAX CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_DUT_INDEX + 34, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
//==========================================================
// IOCTLs for Testing
// IOCTL_WB_802_11_TS_SET_CXX_REG
// Query: None
// Set : Write the value to one of Cxx register.
//
#define IOCTL_WB_802_11_TS_SET_CXX_REG CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 0, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_TS_GET_CXX_REG
// Query: Return the value of the Cxx register.
// Set : Write the reg no. (0x00, 0x04, 0x08 etc)
//
#define IOCTL_WB_802_11_TS_GET_CXX_REG CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 1, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_TS_SET_DXX_REG
// Query: None
// Set : Write the value to one of Dxx register.
//
#define IOCTL_WB_802_11_TS_SET_DXX_REG CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 2, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// IOCTL_WB_802_11_TS_GET_DXX_REG
// Query: Return the value of the Dxx register.
// Set : Write the reg no. (0x00, 0x04, 0x08 etc)
//
#define IOCTL_WB_802_11_TS_GET_DXX_REG CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 3, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
//============================================================
// [TS]
#define IOCTL_WB_802_11_TS_TX_RATE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 4, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_CURRENT_CHANNEL CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 5, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_ENABLE_SEQNO CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 6, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_ENALBE_ACKEDPACKET CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 7, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_INHIBIT_CRC CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 8, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_RESET_RCV_COUNTER CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 9, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_SET_TX_TRIGGER CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 10, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_FAILED_TX_COUNT CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 11, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// [TS1]
#define IOCTL_WB_802_11_TS_TX_POWER CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 12, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_MODE_ENABLE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 13, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_MODE_DISABLE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 14, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_ANTENNA CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 15, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_ADAPTER_INFO CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 16, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_MAC_ADDRESS CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 17, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_BSSID CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 18, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_RF_PARAMETER CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 19, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_FILTER CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 20, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_CALIBRATION CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 21, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_BSS_MODE CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 22, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_SET_SSID CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 23, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_IBSS_CHANNEL CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 24, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
// set/query the slot time value(short or long slot time)
#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 25, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 25, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#define IOCTL_WB_802_11_TS_RX_STATISTICS CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
WB_IOCTL_TS_INDEX + 26, \
METHOD_BUFFERED, \
FILE_ANY_ACCESS)
#endif // #ifndef _IOCTLS_H
//
// common.h
//
// This file contains the OS dependant definition and function.
// Every OS has this file individual.
//
#define DebugUsbdStatusInformation( _A )
#ifndef COMMON_DEF
#define COMMON_DEF
#include <linux/version.h>
#include <linux/usb.h>
#include <linux/kernel.h> //need for kernel alert
#include <linux/autoconf.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/slab.h> //memory allocate
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>//need for init and exit modules marco
#include <linux/ctype.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/wireless.h>
#include <linux/if_arp.h>
#include <asm/uaccess.h>
#include <net/iw_handler.h>
#include <linux/skbuff.h>
//#define DEBUG_ENABLED 1
//===============================================================
// Common type definition
//===============================================================
typedef u8* PUCHAR;
typedef s8* PCHAR;
typedef u8* PBOOLEAN;
typedef u16* PUSHORT;
typedef u32* PULONG;
typedef s16* PSHORT;
//===========================================
#define IGNORE 2
#define SUCCESS 1
#define FAILURE 0
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
// PD43 20021108
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define STATUS_MEDIA_CONNECT 1
#define STATUS_MEDIA_DISCONNECT 0
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
typedef struct urb * PURB;
//==================================================================================================
// Common function definition
//==================================================================================================
#ifndef abs
#define abs(_T) ((_T) < 0 ? -_T : _T)
#endif
#define DEBUG_ENABLED
#define ETH_LENGTH_OF_ADDRESS 6
#ifdef DEBUG_ENABLED
#define WBDEBUG( _M ) printk _M
#else
#define WBDEBUG( _M ) 0
#endif
#define OS_DISCONNECTED 0
#define OS_CONNECTED 1
#define OS_EVENT_INDICATE( _A, _B, _F )
#define OS_PMKID_STATUS_EVENT( _A )
/* Uff, no, longs are not atomic on all architectures Linux
* supports. This should really use atomic_t */
#define OS_ATOMIC u32
#define OS_ATOMIC_READ( _A, _V ) _V
#define OS_ATOMIC_INC( _A, _V ) EncapAtomicInc( _A, (void*)_V )
#define OS_ATOMIC_DEC( _A, _V ) EncapAtomicDec( _A, (void*)_V )
#define OS_MEMORY_CLEAR( _A, _S ) memset( (PUCHAR)_A,0,_S)
#define OS_MEMORY_COMPARE( _A, _B, _S ) (memcmp(_A,_B,_S)? 0 : 1) // Definition is reverse with Ndis 1: the same 0: different
#define OS_SPIN_LOCK spinlock_t
#define OS_SPIN_LOCK_ALLOCATE( _S ) spin_lock_init( _S );
#define OS_SPIN_LOCK_FREE( _S )
#define OS_SPIN_LOCK_ACQUIRED( _S ) spin_lock_irq( _S )
#define OS_SPIN_LOCK_RELEASED( _S ) spin_unlock_irq( _S );
#define OS_TIMER struct timer_list
#define OS_TIMER_INITIAL( _T, _F, _P ) \
{ \
init_timer( _T ); \
(_T)->function = (void *)_F##_1a; \
(_T)->data = (unsigned long)_P; \
}
// _S : Millisecond
// 20060420 At least 1 large than jiffies
#define OS_TIMER_SET( _T, _S ) \
{ \
(_T)->expires = jiffies + ((_S*HZ+999)/1000);\
add_timer( _T ); \
}
#define OS_TIMER_CANCEL( _T, _B ) del_timer_sync( _T )
#define OS_TIMER_GET_SYS_TIME( _T ) (*_T=jiffies)
#endif // COMMON_DEF
//
// Winbond WLAN System Configuration defines
//
//=====================================================================
// Current directory is Linux
// The definition WB_LINUX is a keyword for this OS
//=====================================================================
#ifndef SYS_DEF_H
#define SYS_DEF_H
#define WB_LINUX
#define WB_LINUX_WPA_PSK
//#define _IBSS_BEACON_SEQ_STICK_
#define _USE_FALLBACK_RATE_
//#define ANTDIV_DEFAULT_ON
#define _WPA2_ // 20061122 It's needed for current Linux driver
#ifndef _WPA_PSK_DEBUG
#undef _WPA_PSK_DEBUG
#endif
// debug print options, mark what debug you don't need
#ifdef FULL_DEBUG
#define _PE_STATE_DUMP_
#define _PE_TX_DUMP_
#define _PE_RX_DUMP_
#define _PE_OID_DUMP_
#define _PE_DTO_DUMP_
#define _PE_REG_DUMP_
#define _PE_USB_INI_DUMP_
#endif
#include "common.h" // Individual file depends on OS
#include "../wb35_ver.h"
#include "../mac_structures.h"
#include "../ds_tkip.h"
#include "../localpara.h"
#include "../sme_s.h"
#include "../scan_s.h"
#include "../mds_s.h"
#include "../mlme_s.h"
#include "../bssdscpt.h"
#include "../sme_api.h"
#include "../gl_80211.h"
#include "../mto.h"
#include "../wblinux_s.h"
#include "../wbhal_s.h"
#include "../adapter.h"
#include "../mlme_mib.h"
#include "../mds_f.h"
#include "../bss_f.h"
#include "../mlmetxrx_f.h"
#include "../mto_f.h"
#include "../wbhal_f.h"
#include "../wblinux_f.h"
// Kernel Timer resolution, NDIS is 10ms, 10000us
#define MIN_TIMEOUT_VAL (10) //ms
#endif
#include "sysdef.h"
extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency);
// TRUE : read command process successfully
// FALSE : register not support
// RegisterNo : start base
// pRegisterData : data point
// NumberOfData : number of register data
// Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
// NO_INCREMENT - Function will write data into the same register
unsigned char
Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PURB pUrb = NULL;
PREG_QUEUE pRegQueue = NULL;
u16 UrbSize;
struct usb_ctrlrequest *dr;
u16 i, DataSize = NumberOfData*4;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
// Trying to use burst write function if use new hardware
UrbSize = sizeof(REG_QUEUE) + DataSize + sizeof(struct usb_ctrlrequest);
OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
pUrb = wb_usb_alloc_urb(0);
if( pUrb && pRegQueue ) {
pRegQueue->DIRECT = 2;// burst write register
pRegQueue->INDEX = RegisterNo;
pRegQueue->pBuffer = (PULONG)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
memcpy( pRegQueue->pBuffer, pRegisterData, DataSize );
//the function for reversing register data from little endian to big endian
for( i=0; i<NumberOfData ; i++ )
pRegQueue->pBuffer[i] = cpu_to_le32( pRegQueue->pBuffer[i] );
dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE) + DataSize);
dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
dr->bRequest = 0x04; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16( Flag ); // 0: Register number auto-increment, 1: No auto increment
dr->wIndex = cpu_to_le16( RegisterNo );
dr->wLength = cpu_to_le16( DataSize );
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->pRegFirst == NULL)
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
return TRUE;
} else {
if (pUrb)
usb_free_urb(pUrb);
if (pRegQueue)
kfree(pRegQueue);
return FALSE;
}
return FALSE;
}
void
Wb35Reg_Update(phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
switch (RegisterNo) {
case 0x3b0: pWb35Reg->U1B0 = RegisterValue; break;
case 0x3bc: pWb35Reg->U1BC_LEDConfigure = RegisterValue; break;
case 0x400: pWb35Reg->D00_DmaControl = RegisterValue; break;
case 0x800: pWb35Reg->M00_MacControl = RegisterValue; break;
case 0x804: pWb35Reg->M04_MulticastAddress1 = RegisterValue; break;
case 0x808: pWb35Reg->M08_MulticastAddress2 = RegisterValue; break;
case 0x824: pWb35Reg->M24_MacControl = RegisterValue; break;
case 0x828: pWb35Reg->M28_MacControl = RegisterValue; break;
case 0x82c: pWb35Reg->M2C_MacControl = RegisterValue; break;
case 0x838: pWb35Reg->M38_MacControl = RegisterValue; break;
case 0x840: pWb35Reg->M40_MacControl = RegisterValue; break;
case 0x844: pWb35Reg->M44_MacControl = RegisterValue; break;
case 0x848: pWb35Reg->M48_MacControl = RegisterValue; break;
case 0x84c: pWb35Reg->M4C_MacStatus = RegisterValue; break;
case 0x860: pWb35Reg->M60_MacControl = RegisterValue; break;
case 0x868: pWb35Reg->M68_MacControl = RegisterValue; break;
case 0x870: pWb35Reg->M70_MacControl = RegisterValue; break;
case 0x874: pWb35Reg->M74_MacControl = RegisterValue; break;
case 0x878: pWb35Reg->M78_ERPInformation = RegisterValue; break;
case 0x87C: pWb35Reg->M7C_MacControl = RegisterValue; break;
case 0x880: pWb35Reg->M80_MacControl = RegisterValue; break;
case 0x884: pWb35Reg->M84_MacControl = RegisterValue; break;
case 0x888: pWb35Reg->M88_MacControl = RegisterValue; break;
case 0x898: pWb35Reg->M98_MacControl = RegisterValue; break;
case 0x100c: pWb35Reg->BB0C = RegisterValue; break;
case 0x102c: pWb35Reg->BB2C = RegisterValue; break;
case 0x1030: pWb35Reg->BB30 = RegisterValue; break;
case 0x103c: pWb35Reg->BB3C = RegisterValue; break;
case 0x1048: pWb35Reg->BB48 = RegisterValue; break;
case 0x104c: pWb35Reg->BB4C = RegisterValue; break;
case 0x1050: pWb35Reg->BB50 = RegisterValue; break;
case 0x1054: pWb35Reg->BB54 = RegisterValue; break;
case 0x1058: pWb35Reg->BB58 = RegisterValue; break;
case 0x105c: pWb35Reg->BB5C = RegisterValue; break;
case 0x1060: pWb35Reg->BB60 = RegisterValue; break;
}
}
// TRUE : read command process successfully
// FALSE : register not support
unsigned char
Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
int ret = -1;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
RegisterValue = cpu_to_le32(RegisterValue);
// update the register by send usb message------------------------------------
pWb35Reg->SyncIoPause = 1;
// 20060717.5 Wait until EP0VM stop
while (pWb35Reg->EP0vm_state != VM_STOP)
OS_SLEEP(10000);
// Sync IoCallDriver
pWb35Reg->EP0vm_state = VM_RUNNING;
ret = usb_control_msg( pHwData->WbUsb.udev,
usb_sndctrlpipe( pHwData->WbUsb.udev, 0 ),
0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x0,RegisterNo, &RegisterValue, 4, HZ*100 );
pWb35Reg->EP0vm_state = VM_STOP;
pWb35Reg->SyncIoPause = 0;
Wb35Reg_EP0VM_start(pHwData);
if (ret < 0) {
#ifdef _PE_REG_DUMP_
WBDEBUG(("EP0 Write register usb message sending error\n"));
#endif
pHwData->SurpriseRemove = 1; // 20060704.2
return FALSE;
}
return TRUE;
}
// TRUE : read command process successfully
// FALSE : register not support
unsigned char
Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
struct usb_ctrlrequest *dr;
PURB pUrb = NULL;
PREG_QUEUE pRegQueue = NULL;
u16 UrbSize;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
// update the register by send urb request------------------------------------
UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
pUrb = wb_usb_alloc_urb(0);
if (pUrb && pRegQueue) {
pRegQueue->DIRECT = 1;// burst write register
pRegQueue->INDEX = RegisterNo;
pRegQueue->VALUE = cpu_to_le32(RegisterValue);
pRegQueue->RESERVED_VALID = FALSE;
dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
dr->wIndex = cpu_to_le16(RegisterNo);
dr->wLength = cpu_to_le16(4);
// Enter the sending queue
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
OS_SPIN_LOCK_ACQUIRED(&pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->pRegFirst == NULL)
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
return TRUE;
} else {
if (pUrb)
usb_free_urb(pUrb);
kfree(pRegQueue);
return FALSE;
}
}
//This command will be executed with a user defined value. When it completes,
//this value is useful. For example, hal_set_current_channel will use it.
// TRUE : read command process successfully
// FALSE : register not support
unsigned char
Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue,
PCHAR pValue, s8 Len)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
struct usb_ctrlrequest *dr;
PURB pUrb = NULL;
PREG_QUEUE pRegQueue = NULL;
u16 UrbSize;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
// update the register by send urb request------------------------------------
UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
OS_MEMORY_ALLOC((void* *) &pRegQueue, UrbSize );
pUrb = wb_usb_alloc_urb(0);
if (pUrb && pRegQueue) {
pRegQueue->DIRECT = 1;// burst write register
pRegQueue->INDEX = RegisterNo;
pRegQueue->VALUE = cpu_to_le32(RegisterValue);
//NOTE : Users must guarantee the size of value will not exceed the buffer size.
memcpy(pRegQueue->RESERVED, pValue, Len);
pRegQueue->RESERVED_VALID = TRUE;
dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
dr->wIndex = cpu_to_le16(RegisterNo);
dr->wLength = cpu_to_le16(4);
// Enter the sending queue
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
OS_SPIN_LOCK_ACQUIRED (&pWb35Reg->EP0VM_spin_lock );
if( pWb35Reg->pRegFirst == NULL )
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
OS_SPIN_LOCK_RELEASED ( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start(pHwData);
return TRUE;
} else {
if (pUrb)
usb_free_urb(pUrb);
kfree(pRegQueue);
return FALSE;
}
}
// TRUE : read command process successfully
// FALSE : register not support
// pRegisterValue : It must be a resident buffer due to asynchronous read register.
unsigned char
Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PULONG pltmp = pRegisterValue;
int ret = -1;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
// Read the register by send usb message------------------------------------
pWb35Reg->SyncIoPause = 1;
// 20060717.5 Wait until EP0VM stop
while (pWb35Reg->EP0vm_state != VM_STOP)
OS_SLEEP(10000);
pWb35Reg->EP0vm_state = VM_RUNNING;
ret = usb_control_msg( pHwData->WbUsb.udev,
usb_rcvctrlpipe(pHwData->WbUsb.udev, 0),
0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
0x0, RegisterNo, pltmp, 4, HZ*100 );
*pRegisterValue = cpu_to_le32(*pltmp);
pWb35Reg->EP0vm_state = VM_STOP;
Wb35Reg_Update( pHwData, RegisterNo, *pRegisterValue );
pWb35Reg->SyncIoPause = 0;
Wb35Reg_EP0VM_start( pHwData );
if (ret < 0) {
#ifdef _PE_REG_DUMP_
WBDEBUG(("EP0 Read register usb message sending error\n"));
#endif
pHwData->SurpriseRemove = 1; // 20060704.2
return FALSE;
}
return TRUE;
}
// TRUE : read command process successfully
// FALSE : register not support
// pRegisterValue : It must be a resident buffer due to asynchronous read register.
unsigned char
Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
struct usb_ctrlrequest * dr;
PURB pUrb;
PREG_QUEUE pRegQueue;
u16 UrbSize;
// Module shutdown
if (pHwData->SurpriseRemove)
return FALSE;
// update the variable by send Urb to read register ------------------------------------
UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
pUrb = wb_usb_alloc_urb(0);
if( pUrb && pRegQueue )
{
pRegQueue->DIRECT = 0;// read register
pRegQueue->INDEX = RegisterNo;
pRegQueue->pBuffer = pRegisterValue;
dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
dr->bRequestType = USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN;
dr->bRequest = 0x01; // USB or vendor-defined request code, burst mode
dr->wValue = cpu_to_le16(0x0);
dr->wIndex = cpu_to_le16 (RegisterNo);
dr->wLength = cpu_to_le16 (4);
// Enter the sending queue
pRegQueue->Next = NULL;
pRegQueue->pUsbReq = dr;
pRegQueue->pUrb = pUrb;
OS_SPIN_LOCK_ACQUIRED ( &pWb35Reg->EP0VM_spin_lock );
if( pWb35Reg->pRegFirst == NULL )
pWb35Reg->pRegFirst = pRegQueue;
else
pWb35Reg->pRegLast->Next = pRegQueue;
pWb35Reg->pRegLast = pRegQueue;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
// Start EP0VM
Wb35Reg_EP0VM_start( pHwData );
return TRUE;
} else {
if (pUrb)
usb_free_urb( pUrb );
kfree(pRegQueue);
return FALSE;
}
}
void
Wb35Reg_EP0VM_start( phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Reg->RegFireCount) == 1) {
pWb35Reg->EP0vm_state = VM_RUNNING;
Wb35Reg_EP0VM(pHwData);
} else
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
}
void
Wb35Reg_EP0VM(phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PURB pUrb;
struct usb_ctrlrequest *dr;
PULONG pBuffer;
int ret = -1;
PREG_QUEUE pRegQueue;
if (pWb35Reg->SyncIoPause)
goto cleanup;
if (pHwData->SurpriseRemove)
goto cleanup;
// Get the register data and send to USB through Irp
OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
if (!pRegQueue)
goto cleanup;
// Get an Urb, send it
pUrb = (PURB)pRegQueue->pUrb;
dr = pRegQueue->pUsbReq;
pUrb = pRegQueue->pUrb;
pBuffer = pRegQueue->pBuffer;
if (pRegQueue->DIRECT == 1) // output
pBuffer = &pRegQueue->VALUE;
usb_fill_control_urb( pUrb, pHwData->WbUsb.udev,
REG_DIRECTION(pHwData->WbUsb.udev,pRegQueue),
(PUCHAR)dr,pBuffer,cpu_to_le16(dr->wLength),
Wb35Reg_EP0VM_complete, (void*)pHwData);
pWb35Reg->EP0vm_state = VM_RUNNING;
ret = wb_usb_submit_urb( pUrb );
if (ret < 0) {
#ifdef _PE_REG_DUMP_
WBDEBUG(("EP0 Irp sending error\n"));
#endif
goto cleanup;
}
return;
cleanup:
pWb35Reg->EP0vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
}
void
Wb35Reg_EP0VM_complete(PURB pUrb)
{
phw_data_t pHwData = (phw_data_t)pUrb->context;
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PREG_QUEUE pRegQueue;
// Variable setting
pWb35Reg->EP0vm_state = VM_COMPLETED;
pWb35Reg->EP0VM_status = pUrb->status;
if (pHwData->SurpriseRemove) { // Let WbWlanHalt to handle surprise remove
pWb35Reg->EP0vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
} else {
// Complete to send, remove the URB from the first
OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
if (pRegQueue == pWb35Reg->pRegLast)
pWb35Reg->pRegLast = NULL;
pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
if (pWb35Reg->EP0VM_status) {
#ifdef _PE_REG_DUMP_
WBDEBUG(("EP0 IoCompleteRoutine return error\n"));
DebugUsbdStatusInformation( pWb35Reg->EP0VM_status );
#endif
pWb35Reg->EP0vm_state = VM_STOP;
pHwData->SurpriseRemove = 1;
} else {
// Success. Update the result
// Start the next send
Wb35Reg_EP0VM(pHwData);
}
kfree(pRegQueue);
}
usb_free_urb(pUrb);
}
void
Wb35Reg_destroy(phw_data_t pHwData)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PURB pUrb;
PREG_QUEUE pRegQueue;
Uxx_power_off_procedure(pHwData);
// Wait for Reg operation completed
do {
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
} while (pWb35Reg->EP0vm_state != VM_STOP);
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
// Release all the data in RegQueue
OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
while (pRegQueue) {
if (pRegQueue == pWb35Reg->pRegLast)
pWb35Reg->pRegLast = NULL;
pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
pUrb = pRegQueue->pUrb;
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
if (pUrb) {
usb_free_urb(pUrb);
kfree(pRegQueue);
} else {
#ifdef _PE_REG_DUMP_
WBDEBUG(("EP0 queue release error\n"));
#endif
}
OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
pRegQueue = pWb35Reg->pRegFirst;
}
OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
// Free resource
OS_SPIN_LOCK_FREE( &pWb35Reg->EP0VM_spin_lock );
}
//====================================================================================
// The function can be run in passive-level only.
//====================================================================================
unsigned char Wb35Reg_initial(phw_data_t pHwData)
{
PWB35REG pWb35Reg=&pHwData->Wb35Reg;
u32 ltmp;
u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval;
// Spin lock is acquired for read and write IRP command
OS_SPIN_LOCK_ALLOCATE( &pWb35Reg->EP0VM_spin_lock );
// Getting RF module type from EEPROM ------------------------------------
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x080d0000 ); // Start EEPROM access + Read + address(0x0d)
Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
//Update RF module type and determine the PHY type by inf or EEPROM
pWb35Reg->EEPROMPhyType = (u8)( ltmp & 0xff );
// 0 V MAX2825, 1 V MAX2827, 2 V MAX2828, 3 V MAX2829
// 16V AL2230, 17 - AL7230, 18 - AL2230S
// 32 Reserved
// 33 - W89RF242(TxVGA 0~19), 34 - W89RF242(TxVGA 0~34)
if (pWb35Reg->EEPROMPhyType != RF_DECIDE_BY_INF) {
if( (pWb35Reg->EEPROMPhyType == RF_MAXIM_2825) ||
(pWb35Reg->EEPROMPhyType == RF_MAXIM_2827) ||
(pWb35Reg->EEPROMPhyType == RF_MAXIM_2828) ||
(pWb35Reg->EEPROMPhyType == RF_MAXIM_2829) ||
(pWb35Reg->EEPROMPhyType == RF_MAXIM_V1) ||
(pWb35Reg->EEPROMPhyType == RF_AIROHA_2230) ||
(pWb35Reg->EEPROMPhyType == RF_AIROHA_2230S) ||
(pWb35Reg->EEPROMPhyType == RF_AIROHA_7230) ||
(pWb35Reg->EEPROMPhyType == RF_WB_242) ||
(pWb35Reg->EEPROMPhyType == RF_WB_242_1))
pHwData->phy_type = pWb35Reg->EEPROMPhyType;
}
// Power On procedure running. The relative parameter will be set according to phy_type
Uxx_power_on_procedure( pHwData );
// Reading MAC address
Uxx_ReadEthernetAddress( pHwData );
// Read VCO trim for RF parameter
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08200000 );
Wb35Reg_ReadSync( pHwData, 0x03b4, &VCO_trim );
// Read Antenna On/Off of software flag
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08210000 );
Wb35Reg_ReadSync( pHwData, 0x03b4, &SoftwareSet );
// Read TXVGA
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08100000 );
Wb35Reg_ReadSync( pHwData, 0x03b4, &TxVga );
// Get Scan interval setting from EEPROM offset 0x1c
Wb35Reg_WriteSync( pHwData, 0x03b4, 0x081d0000 );
Wb35Reg_ReadSync( pHwData, 0x03b4, &Region_ScanInterval );
// Update Ethernet address
memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS );
// Update software variable
pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff);
TxVga &= 0x000000ff;
pHwData->PowerIndexFromEEPROM = (u8)TxVga;
pHwData->VCO_trim = (u8)VCO_trim & 0xff;
if (pHwData->VCO_trim == 0xff)
pHwData->VCO_trim = 0x28;
pWb35Reg->EEPROMRegion = (u8)(Region_ScanInterval>>8); // 20060720
if( pWb35Reg->EEPROMRegion<1 || pWb35Reg->EEPROMRegion>6 )
pWb35Reg->EEPROMRegion = REGION_AUTO;
//For Get Tx VGA from EEPROM 20060315.5 move here
GetTxVgaFromEEPROM( pHwData );
// Set Scan Interval
pHwData->Scan_Interval = (u8)(Region_ScanInterval & 0xff) * 10;
if ((pHwData->Scan_Interval == 2550) || (pHwData->Scan_Interval < 10)) // Is default setting 0xff * 10
pHwData->Scan_Interval = SCAN_MAX_CHNL_TIME;
// Initial register
RFSynthesizer_initial(pHwData);
BBProcessor_initial(pHwData); // Async write, must wait until complete
Wb35Reg_phy_calibration(pHwData);
Mxx_initial(pHwData);
Dxx_initial(pHwData);
if (pHwData->SurpriseRemove)
return FALSE;
else
return TRUE; // Initial fail
}
//===================================================================================
// CardComputeCrc --
//
// Description:
// Runs the AUTODIN II CRC algorithm on buffer Buffer of length, Length.
//
// Arguments:
// Buffer - the input buffer
// Length - the length of Buffer
//
// Return Value:
// The 32-bit CRC value.
//
// Note:
// This is adapted from the comments in the assembly language
// version in _GENREQ.ASM of the DWB NE1000/2000 driver.
//==================================================================================
u32
CardComputeCrc(PUCHAR Buffer, u32 Length)
{
u32 Crc, Carry;
u32 i, j;
u8 CurByte;
Crc = 0xffffffff;
for (i = 0; i < Length; i++) {
CurByte = Buffer[i];
for (j = 0; j < 8; j++) {
Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
Crc <<= 1;
CurByte >>= 1;
if (Carry) {
Crc =(Crc ^ 0x04c11db6) | Carry;
}
}
}
return Crc;
}
//==================================================================
// BitReverse --
// Reverse the bits in the input argument, dwData, which is
// regarded as a string of bits with the length, DataLength.
//
// Arguments:
// dwData :
// DataLength :
//
// Return:
// The converted value.
//==================================================================
u32 BitReverse( u32 dwData, u32 DataLength)
{
u32 HalfLength, i, j;
u32 BitA, BitB;
if ( DataLength <= 0) return 0; // No conversion is done.
dwData = dwData & (0xffffffff >> (32 - DataLength));
HalfLength = DataLength / 2;
for ( i = 0, j = DataLength-1 ; i < HalfLength; i++, j--)
{
BitA = GetBit( dwData, i);
BitB = GetBit( dwData, j);
if (BitA && !BitB) {
dwData = ClearBit( dwData, i);
dwData = SetBit( dwData, j);
} else if (!BitA && BitB) {
dwData = SetBit( dwData, i);
dwData = ClearBit( dwData, j);
} else
{
// Do nothing since these two bits are of the save values.
}
}
return dwData;
}
void Wb35Reg_phy_calibration( phw_data_t pHwData )
{
u32 BB3c, BB54;
if ((pHwData->phy_type == RF_WB_242) ||
(pHwData->phy_type == RF_WB_242_1)) {
phy_calibration_winbond ( pHwData, 2412 ); // Sync operation
Wb35Reg_ReadSync( pHwData, 0x103c, &BB3c );
Wb35Reg_ReadSync( pHwData, 0x1054, &BB54 );
pHwData->BB3c_cal = BB3c;
pHwData->BB54_cal = BB54;
RFSynthesizer_initial(pHwData);
BBProcessor_initial(pHwData); // Async operation
Wb35Reg_WriteSync( pHwData, 0x103c, BB3c );
Wb35Reg_WriteSync( pHwData, 0x1054, BB54 );
}
}
//====================================
// Interface function declare
//====================================
unsigned char Wb35Reg_initial( phw_data_t pHwData );
void Uxx_power_on_procedure( phw_data_t pHwData );
void Uxx_power_off_procedure( phw_data_t pHwData );
void Uxx_ReadEthernetAddress( phw_data_t pHwData );
void Dxx_initial( phw_data_t pHwData );
void Mxx_initial( phw_data_t pHwData );
void RFSynthesizer_initial( phw_data_t pHwData );
//void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, s8 Channel );
void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel );
void BBProcessor_initial( phw_data_t pHwData );
void BBProcessor_RateChanging( phw_data_t pHwData, u8 rate ); // 20060613.1
//void RF_RateChanging( phw_data_t pHwData, u8 rate ); // 20060626.5.c Add
u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex );
u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetMaxim2825Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetAiroha2230Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetAiroha7230Power( phw_data_t, u8 index );
u8 RFSynthesizer_SetWinbond242Power( phw_data_t, u8 index );
void GetTxVgaFromEEPROM( phw_data_t pHwData );
void EEPROMTxVgaAdjust( phw_data_t pHwData ); // 20060619.5 Add
#define RFWriteControlData( _A, _V ) Wb35Reg_Write( _A, 0x0864, _V )
void Wb35Reg_destroy( phw_data_t pHwData );
unsigned char Wb35Reg_Read( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
unsigned char Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterValue );
unsigned char Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
unsigned char Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
unsigned char Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData,
u16 RegisterNo,
u32 RegisterValue,
PCHAR pValue,
s8 Len);
unsigned char Wb35Reg_BurstWrite( phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag );
void Wb35Reg_EP0VM( phw_data_t pHwData );
void Wb35Reg_EP0VM_start( phw_data_t pHwData );
void Wb35Reg_EP0VM_complete( PURB pUrb );
u32 BitReverse( u32 dwData, u32 DataLength);
void CardGetMulticastBit( u8 Address[MAC_ADDR_LENGTH], u8 *Byte, u8 *Value );
u32 CardComputeCrc( PUCHAR Buffer, u32 Length );
void Wb35Reg_phy_calibration( phw_data_t pHwData );
void Wb35Reg_Update( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue );
unsigned char adjust_TXVGA_for_iq_mag( phw_data_t pHwData );
//=======================================================================================
/*
HAL setting function
========================================
|Uxx| |Dxx| |Mxx| |BB| |RF|
========================================
| |
Wb35Reg_Read Wb35Reg_Write
----------------------------------------
WbUsb_CallUSBDASync supplied By WbUsb module
*/
//=======================================================================================
#define GetBit( dwData, i) ( dwData & (0x00000001 << i))
#define SetBit( dwData, i) ( dwData | (0x00000001 << i))
#define ClearBit( dwData, i) ( dwData & ~(0x00000001 << i))
#define IGNORE_INCREMENT 0
#define AUTO_INCREMENT 0
#define NO_INCREMENT 1
#define REG_DIRECTION(_x,_y) ((_y)->DIRECT ==0 ? usb_rcvctrlpipe(_x,0) : usb_sndctrlpipe(_x,0))
#define REG_BUF_SIZE(_x) ((_x)->bRequest== 0x04 ? cpu_to_le16((_x)->wLength) : 4)
// 20060613.2 Add the follow definition
#define BB48_DEFAULT_AL2230_11B 0x0033447c
#define BB4C_DEFAULT_AL2230_11B 0x0A00FEFF
#define BB48_DEFAULT_AL2230_11G 0x00332C1B
#define BB4C_DEFAULT_AL2230_11G 0x0A00FEFF
#define BB48_DEFAULT_WB242_11B 0x00292315 //backoff 2dB
#define BB4C_DEFAULT_WB242_11B 0x0800FEFF //backoff 2dB
//#define BB48_DEFAULT_WB242_11B 0x00201B11 //backoff 4dB
//#define BB4C_DEFAULT_WB242_11B 0x0600FF00 //backoff 4dB
#define BB48_DEFAULT_WB242_11G 0x00453B24
#define BB4C_DEFAULT_WB242_11G 0x0E00FEFF
//====================================
// Default setting for Mxx
//====================================
#define DEFAULT_CWMIN 31 //(M2C) CWmin. Its value is in the range 0-31.
#define DEFAULT_CWMAX 1023 //(M2C) CWmax. Its value is in the range 0-1023.
#define DEFAULT_AID 1 //(M34) AID. Its value is in the range 1-2007.
#ifdef _USE_FALLBACK_RATE_
#define DEFAULT_RATE_RETRY_LIMIT 2 //(M38) as named
#else
#define DEFAULT_RATE_RETRY_LIMIT 7 //(M38) as named
#endif
#define DEFAULT_LONG_RETRY_LIMIT 7 //(M38) LongRetryLimit. Its value is in the range 0-15.
#define DEFAULT_SHORT_RETRY_LIMIT 7 //(M38) ShortRetryLimit. Its value is in the range 0-15.
#define DEFAULT_PIFST 25 //(M3C) PIFS Time. Its value is in the range 0-65535.
#define DEFAULT_EIFST 354 //(M3C) EIFS Time. Its value is in the range 0-1048575.
#define DEFAULT_DIFST 45 //(M3C) DIFS Time. Its value is in the range 0-65535.
#define DEFAULT_SIFST 5 //(M3C) SIFS Time. Its value is in the range 0-65535.
#define DEFAULT_OSIFST 10 //(M3C) Original SIFS Time. Its value is in the range 0-15.
#define DEFAULT_ATIMWD 0 //(M40) ATIM Window. Its value is in the range 0-65535.
#define DEFAULT_SLOT_TIME 20 //(M40) ($) SlotTime. Its value is in the range 0-255.
#define DEFAULT_MAX_TX_MSDU_LIFE_TIME 512 //(M44) MaxTxMSDULifeTime. Its value is in the range 0-4294967295.
#define DEFAULT_BEACON_INTERVAL 500 //(M48) Beacon Interval. Its value is in the range 0-65535.
#define DEFAULT_PROBE_DELAY_TIME 200 //(M48) Probe Delay Time. Its value is in the range 0-65535.
#define DEFAULT_PROTOCOL_VERSION 0 //(M4C)
#define DEFAULT_MAC_POWER_STATE 2 //(M4C) 2: MAC at power active
#define DEFAULT_DTIM_ALERT_TIME 0
typedef struct _REG_QUEUE
{
struct urb *pUrb;
void* pUsbReq;
void* Next;
union
{
u32 VALUE;
PULONG pBuffer;
};
u8 RESERVED[4];// space reserved for communication
u16 INDEX; // For storing the register index
u8 RESERVED_VALID; //Indicate whether the RESERVED space is valid at this command.
u8 DIRECT; // 0:In 1:Out
} REG_QUEUE, *PREG_QUEUE;
//====================================
// Internal variable for module
//====================================
#define MAX_SQ3_FILTER_SIZE 5
typedef struct _WB35REG
{
//============================
// Register Bank backup
//============================
u32 U1B0; //bit16 record the h/w radio on/off status
u32 U1BC_LEDConfigure;
u32 D00_DmaControl;
u32 M00_MacControl;
union {
struct {
u32 M04_MulticastAddress1;
u32 M08_MulticastAddress2;
};
u8 Multicast[8]; // contents of card multicast registers
};
u32 M24_MacControl;
u32 M28_MacControl;
u32 M2C_MacControl;
u32 M38_MacControl;
u32 M3C_MacControl; // 20060214 backup only
u32 M40_MacControl;
u32 M44_MacControl; // 20060214 backup only
u32 M48_MacControl; // 20060214 backup only
u32 M4C_MacStatus;
u32 M60_MacControl; // 20060214 backup only
u32 M68_MacControl; // 20060214 backup only
u32 M70_MacControl; // 20060214 backup only
u32 M74_MacControl; // 20060214 backup only
u32 M78_ERPInformation;//930206.2.b
u32 M7C_MacControl; // 20060214 backup only
u32 M80_MacControl; // 20060214 backup only
u32 M84_MacControl; // 20060214 backup only
u32 M88_MacControl; // 20060214 backup only
u32 M98_MacControl; // 20060214 backup only
//[20040722 WK]
//Baseband register
u32 BB0C; // Used for LNA calculation
u32 BB2C; //
u32 BB30; //11b acquisition control register
u32 BB3C;
u32 BB48; // 20051221.1.a 20060613.1 Fix OBW issue of 11b/11g rate
u32 BB4C; // 20060613.1 Fix OBW issue of 11b/11g rate
u32 BB50; //mode control register
u32 BB54;
u32 BB58; //IQ_ALPHA
u32 BB5C; // For test
u32 BB60; // for WTO read value
//-------------------
// VM
//-------------------
OS_SPIN_LOCK EP0VM_spin_lock; // 4B
u32 EP0VM_status;//$$
PREG_QUEUE pRegFirst;
PREG_QUEUE pRegLast;
OS_ATOMIC RegFireCount;
// Hardware status
u8 EP0vm_state;
u8 mac_power_save;
u8 EEPROMPhyType; // 0 ~ 15 for Maxim (0 ĄV MAX2825, 1 ĄV MAX2827, 2 ĄV MAX2828, 3 ĄV MAX2829),
// 16 ~ 31 for Airoha (16 ĄV AL2230, 11 - AL7230)
// 32 ~ Reserved
// 33 ~ 47 For WB242 ( 33 - WB242, 34 - WB242 with new Txvga 0.5 db step)
// 48 ~ 255 ARE RESERVED.
u8 EEPROMRegion; //Region setting in EEPROM
u32 SyncIoPause; // If user use the Sync Io to access Hw, then pause the async access
u8 LNAValue[4]; //Table for speed up running
u32 SQ3_filter[MAX_SQ3_FILTER_SIZE];
u32 SQ3_index;
} WB35REG, *PWB35REG;
//============================================================================
// Copyright (c) 1996-2002 Winbond Electronic Corporation
//
// Module Name:
// Wb35Rx.c
//
// Abstract:
// Processing the Rx message from down layer
//
//============================================================================
#include "sysdef.h"
void Wb35Rx_start(phw_data_t pHwData)
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
// Allow only one thread to run into the Wb35Rx() function
if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Rx->RxFireCounter) == 1) {
pWb35Rx->EP3vm_state = VM_RUNNING;
Wb35Rx(pHwData);
} else
OS_ATOMIC_DEC(pHwData->Adapter, &pWb35Rx->RxFireCounter);
}
// This function cannot reentrain
void Wb35Rx( phw_data_t pHwData )
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
PUCHAR pRxBufferAddress;
PURB pUrb = (PURB)pWb35Rx->RxUrb;
int retv;
u32 RxBufferId;
//
// Issuing URB
//
do {
if (pHwData->SurpriseRemove || pHwData->HwStop)
break;
if (pWb35Rx->rx_halt)
break;
// Get RxBuffer's ID
RxBufferId = pWb35Rx->RxBufferId;
if (!pWb35Rx->RxOwner[RxBufferId]) {
// It's impossible to run here.
#ifdef _PE_RX_DUMP_
WBDEBUG(("Rx driver fifo unavailable\n"));
#endif
break;
}
// Update buffer point, then start to bulkin the data from USB
pWb35Rx->RxBufferId++;
pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
pWb35Rx->CurrentRxBufferId = RxBufferId;
if (1 != OS_MEMORY_ALLOC((void* *)&pWb35Rx->pDRx, MAX_USB_RX_BUFFER)) {
printk("w35und: Rx memory alloc failed\n");
break;
}
pRxBufferAddress = pWb35Rx->pDRx;
usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
pRxBufferAddress, MAX_USB_RX_BUFFER,
Wb35Rx_Complete, pHwData);
pWb35Rx->EP3vm_state = VM_RUNNING;
retv = wb_usb_submit_urb(pUrb);
if (retv != 0) {
printk("Rx URB sending error\n");
break;
}
return;
} while(FALSE);
// VM stop
pWb35Rx->EP3vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
}
void Wb35Rx_Complete(PURB pUrb)
{
phw_data_t pHwData = pUrb->context;
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
PUCHAR pRxBufferAddress;
u32 SizeCheck;
u16 BulkLength;
u32 RxBufferId;
R00_DESCRIPTOR R00;
// Variable setting
pWb35Rx->EP3vm_state = VM_COMPLETED;
pWb35Rx->EP3VM_status = pUrb->status;//Store the last result of Irp
do {
RxBufferId = pWb35Rx->CurrentRxBufferId;
pRxBufferAddress = pWb35Rx->pDRx;
BulkLength = (u16)pUrb->actual_length;
// The IRP is completed
pWb35Rx->EP3vm_state = VM_COMPLETED;
if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
break;
if (pWb35Rx->rx_halt)
break;
// Start to process the data only in successful condition
pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
// The URB is completed, check the result
if (pWb35Rx->EP3VM_status != 0) {
#ifdef _PE_USB_STATE_DUMP_
WBDEBUG(("EP3 IoCompleteRoutine return error\n"));
DebugUsbdStatusInformation( pWb35Rx->EP3VM_status );
#endif
pWb35Rx->EP3vm_state = VM_STOP;
break;
}
// 20060220 For recovering. check if operating in single USB mode
if (!HAL_USB_MODE_BURST(pHwData)) {
SizeCheck = R00.R00_receive_byte_count; //20060926 anson's endian
if ((SizeCheck & 0x03) > 0)
SizeCheck -= 4;
SizeCheck = (SizeCheck + 3) & ~0x03;
SizeCheck += 12; // 8 + 4 badbeef
if ((BulkLength > 1600) ||
(SizeCheck > 1600) ||
(BulkLength != SizeCheck) ||
(BulkLength == 0)) { // Add for fail Urb
pWb35Rx->EP3vm_state = VM_STOP;
pWb35Rx->Ep3ErrorCount2++;
}
}
// Indicating the receiving data
pWb35Rx->ByteReceived += BulkLength;
pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
if (!pWb35Rx->RxOwner[ RxBufferId ])
Wb35Rx_indicate(pHwData);
kfree(pWb35Rx->pDRx);
// Do the next receive
Wb35Rx(pHwData);
return;
} while(FALSE);
pWb35Rx->RxOwner[ RxBufferId ] = 1; // Set the owner to hardware
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
pWb35Rx->EP3vm_state = VM_STOP;
}
//=====================================================================================
unsigned char Wb35Rx_initial(phw_data_t pHwData)
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
// Initial the Buffer Queue
Wb35Rx_reset_descriptor( pHwData );
pWb35Rx->RxUrb = wb_usb_alloc_urb(0);
return (!!pWb35Rx->RxUrb);
}
void Wb35Rx_stop(phw_data_t pHwData)
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
// Canceling the Irp if already sends it out.
if (pWb35Rx->EP3vm_state == VM_RUNNING) {
usb_unlink_urb( pWb35Rx->RxUrb ); // Only use unlink, let Wb35Rx_destroy to free them
#ifdef _PE_RX_DUMP_
WBDEBUG(("EP3 Rx stop\n"));
#endif
}
}
// Needs process context
void Wb35Rx_destroy(phw_data_t pHwData)
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
do {
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
} while (pWb35Rx->EP3vm_state != VM_STOP);
OS_SLEEP(10000); // Delay for waiting function exit 940623.1.b
if (pWb35Rx->RxUrb)
usb_free_urb( pWb35Rx->RxUrb );
#ifdef _PE_RX_DUMP_
WBDEBUG(("Wb35Rx_destroy OK\n"));
#endif
}
void Wb35Rx_reset_descriptor( phw_data_t pHwData )
{
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
u32 i;
pWb35Rx->ByteReceived = 0;
pWb35Rx->RxProcessIndex = 0;
pWb35Rx->RxBufferId = 0;
pWb35Rx->EP3vm_state = VM_STOP;
pWb35Rx->rx_halt = 0;
// Initial the Queue. The last buffer is reserved for used if the Rx resource is unavailable.
for( i=0; i<MAX_USB_RX_BUFFER_NUMBER; i++ )
pWb35Rx->RxOwner[i] = 1;
}
void Wb35Rx_adjust(PDESCRIPTOR pRxDes)
{
PULONG pRxBufferAddress;
u32 DecryptionMethod;
u32 i;
u16 BufferSize;
DecryptionMethod = pRxDes->R01.R01_decryption_method;
pRxBufferAddress = pRxDes->buffer_address[0];
BufferSize = pRxDes->buffer_size[0];
// Adjust the last part of data. Only data left
BufferSize -= 4; // For CRC-32
if (DecryptionMethod)
BufferSize -= 4;
if (DecryptionMethod == 3) // For CCMP
BufferSize -= 4;
// Adjust the IV field which after 802.11 header and ICV field.
if (DecryptionMethod == 1) // For WEP
{
for( i=6; i>0; i-- )
pRxBufferAddress[i] = pRxBufferAddress[i-1];
pRxDes->buffer_address[0] = pRxBufferAddress + 1;
BufferSize -= 4; // 4 byte for IV
}
else if( DecryptionMethod ) // For TKIP and CCMP
{
for (i=7; i>1; i--)
pRxBufferAddress[i] = pRxBufferAddress[i-2];
pRxDes->buffer_address[0] = pRxBufferAddress + 2;//Update the descriptor, shift 8 byte
BufferSize -= 8; // 8 byte for IV + ICV
}
pRxDes->buffer_size[0] = BufferSize;
}
extern void packet_came(char *pRxBufferAddress, int PacketSize);
u16 Wb35Rx_indicate(phw_data_t pHwData)
{
DESCRIPTOR RxDes;
PWB35RX pWb35Rx = &pHwData->Wb35Rx;
PUCHAR pRxBufferAddress;
u16 PacketSize;
u16 stmp, BufferSize, stmp2 = 0;
u32 RxBufferId;
// Only one thread be allowed to run into the following
do {
RxBufferId = pWb35Rx->RxProcessIndex;
if (pWb35Rx->RxOwner[ RxBufferId ]) //Owner by VM
break;
pWb35Rx->RxProcessIndex++;
pWb35Rx->RxProcessIndex %= MAX_USB_RX_BUFFER_NUMBER;
pRxBufferAddress = pWb35Rx->pDRx;
BufferSize = pWb35Rx->RxBufferSize[ RxBufferId ];
// Parse the bulkin buffer
while (BufferSize >= 4) {
if ((cpu_to_le32(*(PULONG)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
break;
// Get the R00 R01 first
RxDes.R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
PacketSize = (u16)RxDes.R00.R00_receive_byte_count;
RxDes.R01.value = le32_to_cpu(*((PULONG)(pRxBufferAddress+4)));
// For new DMA 4k
if ((PacketSize & 0x03) > 0)
PacketSize -= 4;
// Basic check for Rx length. Is length valid?
if (PacketSize > MAX_PACKET_SIZE) {
#ifdef _PE_RX_DUMP_
WBDEBUG(("Serious ERROR : Rx data size too long, size =%d\n", PacketSize));
#endif
pWb35Rx->EP3vm_state = VM_STOP;
pWb35Rx->Ep3ErrorCount2++;
break;
}
// Start to process Rx buffer
// RxDes.Descriptor_ID = RxBufferId; // Due to synchronous indicate, the field doesn't necessary to use.
BufferSize -= 8; //subtract 8 byte for 35's USB header length
pRxBufferAddress += 8;
RxDes.buffer_address[0] = pRxBufferAddress;
RxDes.buffer_size[0] = PacketSize;
RxDes.buffer_number = 1;
RxDes.buffer_start_index = 0;
RxDes.buffer_total_size = RxDes.buffer_size[0];
Wb35Rx_adjust(&RxDes);
packet_came(pRxBufferAddress, PacketSize);
// Move RxBuffer point to the next
stmp = PacketSize + 3;
stmp &= ~0x03; // 4n alignment
pRxBufferAddress += stmp;
BufferSize -= stmp;
stmp2 += stmp;
}
// Reclaim resource
pWb35Rx->RxOwner[ RxBufferId ] = 1;
} while(TRUE);
return stmp2;
}
//====================================
// Interface function declare
//====================================
void Wb35Rx_reset_descriptor( phw_data_t pHwData );
unsigned char Wb35Rx_initial( phw_data_t pHwData );
void Wb35Rx_destroy( phw_data_t pHwData );
void Wb35Rx_stop( phw_data_t pHwData );
u16 Wb35Rx_indicate( phw_data_t pHwData );
void Wb35Rx_adjust( PDESCRIPTOR pRxDes );
void Wb35Rx_start( phw_data_t pHwData );
void Wb35Rx( phw_data_t pHwData );
void Wb35Rx_Complete( PURB pUrb );
//============================================================================
// wb35rx.h --
//============================================================================
// Definition for this module used
#define MAX_USB_RX_BUFFER 4096 // This parameter must be 4096 931130.4.f
#define MAX_USB_RX_BUFFER_NUMBER ETHERNET_RX_DESCRIPTORS // Maximum 254, 255 is RESERVED ID
#define RX_INTERFACE 0 // Interface 1
#define RX_PIPE 2 // Pipe 3
#define MAX_PACKET_SIZE 1600 //1568 // 8 + 1532 + 4 + 24(IV EIV MIC ICV CRC) for check DMA data 931130.4.g
#define RX_END_TAG 0x0badbeef
//====================================
// Internal variable for module
//====================================
typedef struct _WB35RX
{
u32 ByteReceived;// For calculating throughput of BulkIn
OS_ATOMIC RxFireCounter;// Does Wb35Rx module fire?
u8 RxBuffer[ MAX_USB_RX_BUFFER_NUMBER ][ ((MAX_USB_RX_BUFFER+3) & ~0x03 ) ];
u16 RxBufferSize[ ((MAX_USB_RX_BUFFER_NUMBER+1) & ~0x01) ];
u8 RxOwner[ ((MAX_USB_RX_BUFFER_NUMBER+3) & ~0x03 ) ];//Ownership of buffer 0: SW 1:HW
u32 RxProcessIndex;//The next index to process
u32 RxBufferId;
u32 EP3vm_state;
u32 rx_halt; // For VM stopping
u16 MoreDataSize;
u16 PacketSize;
u32 CurrentRxBufferId; // For complete routine usage
u32 Rx3UrbCancel;
u32 LastR1; // For RSSI reporting
struct urb * RxUrb;
u32 Ep3ErrorCount2; // 20060625.1 Usbd for Rx DMA error count
int EP3VM_status;
PUCHAR pDRx;
} WB35RX, *PWB35RX;
//============================================================================
// Copyright (c) 1996-2002 Winbond Electronic Corporation
//
// Module Name:
// Wb35Tx.c
//
// Abstract:
// Processing the Tx message and put into down layer
//
//============================================================================
#include "sysdef.h"
unsigned char
Wb35Tx_get_tx_buffer(phw_data_t pHwData, PUCHAR *pBuffer )
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
*pBuffer = pWb35Tx->TxBuffer[0];
return TRUE;
}
void Wb35Tx_start(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
// Allow only one thread to run into function
if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Tx->TxFireCounter) == 1) {
pWb35Tx->EP4vm_state = VM_RUNNING;
Wb35Tx(pHwData);
} else
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
}
void Wb35Tx(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
PADAPTER Adapter = pHwData->Adapter;
PUCHAR pTxBufferAddress;
PMDS pMds = &Adapter->Mds;
struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
int retv;
u32 SendIndex;
if (pHwData->SurpriseRemove || pHwData->HwStop)
goto cleanup;
if (pWb35Tx->tx_halt)
goto cleanup;
// Ownership checking
SendIndex = pWb35Tx->TxSendIndex;
if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
goto cleanup;
pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
//
// Issuing URB
//
usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
Wb35Tx_complete, pHwData);
pWb35Tx->EP4vm_state = VM_RUNNING;
retv = wb_usb_submit_urb( pUrb );
if (retv<0) {
printk("EP4 Tx Irp sending error\n");
goto cleanup;
}
// Check if driver needs issue Irp for EP2
pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
if (pWb35Tx->TxFillCount > 12)
Wb35Tx_EP2VM_start( pHwData );
pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
return;
cleanup:
pWb35Tx->EP4vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
}
void Wb35Tx_complete(struct urb * pUrb)
{
phw_data_t pHwData = pUrb->context;
PADAPTER Adapter = (PADAPTER)pHwData->Adapter;
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
PMDS pMds = &Adapter->Mds;
printk("wb35: tx complete\n");
// Variable setting
pWb35Tx->EP4vm_state = VM_COMPLETED;
pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
pWb35Tx->TxSendIndex++;
pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
do {
if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
break;
if (pWb35Tx->tx_halt)
break;
// The URB is completed, check the result
if (pWb35Tx->EP4VM_status != 0) {
printk("URB submission failed\n");
pWb35Tx->EP4vm_state = VM_STOP;
break; // Exit while(FALSE);
}
Mds_Tx(Adapter);
Wb35Tx(pHwData);
return;
} while(FALSE);
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
pWb35Tx->EP4vm_state = VM_STOP;
}
void Wb35Tx_reset_descriptor( phw_data_t pHwData )
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
pWb35Tx->TxSendIndex = 0;
pWb35Tx->tx_halt = 0;
}
unsigned char Wb35Tx_initial(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
pWb35Tx->Tx4Urb = wb_usb_alloc_urb(0);
if (!pWb35Tx->Tx4Urb)
return FALSE;
pWb35Tx->Tx2Urb = wb_usb_alloc_urb(0);
if (!pWb35Tx->Tx2Urb)
{
usb_free_urb( pWb35Tx->Tx4Urb );
return FALSE;
}
return TRUE;
}
//======================================================
void Wb35Tx_stop(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
// Trying to canceling the Trp of EP2
if (pWb35Tx->EP2vm_state == VM_RUNNING)
usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
#ifdef _PE_TX_DUMP_
WBDEBUG(("EP2 Tx stop\n"));
#endif
// Trying to canceling the Irp of EP4
if (pWb35Tx->EP4vm_state == VM_RUNNING)
usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
#ifdef _PE_TX_DUMP_
WBDEBUG(("EP4 Tx stop\n"));
#endif
}
//======================================================
void Wb35Tx_destroy(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
// Wait for VM stop
do {
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
} while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
if (pWb35Tx->Tx4Urb)
usb_free_urb( pWb35Tx->Tx4Urb );
if (pWb35Tx->Tx2Urb)
usb_free_urb( pWb35Tx->Tx2Urb );
#ifdef _PE_TX_DUMP_
WBDEBUG(("Wb35Tx_destroy OK\n"));
#endif
}
void Wb35Tx_CurrentTime(phw_data_t pHwData, u32 TimeCount)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
unsigned char Trigger = FALSE;
if (pWb35Tx->TxTimer > TimeCount)
Trigger = TRUE;
else if (TimeCount > (pWb35Tx->TxTimer+500))
Trigger = TRUE;
if (Trigger) {
pWb35Tx->TxTimer = TimeCount;
Wb35Tx_EP2VM_start( pHwData );
}
}
void Wb35Tx_EP2VM_start(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
// Allow only one thread to run into function
if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Tx->TxResultCount ) == 1) {
pWb35Tx->EP2vm_state = VM_RUNNING;
Wb35Tx_EP2VM( pHwData );
}
else
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
}
void Wb35Tx_EP2VM(phw_data_t pHwData)
{
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
int retv;
do {
if (pHwData->SurpriseRemove || pHwData->HwStop)
break;
if (pWb35Tx->tx_halt)
break;
//
// Issuing URB
//
usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
pWb35Tx->EP2vm_state = VM_RUNNING;
retv = wb_usb_submit_urb( pUrb );
if(retv < 0) {
#ifdef _PE_TX_DUMP_
WBDEBUG(("EP2 Tx Irp sending error\n"));
#endif
break;
}
return;
} while(FALSE);
pWb35Tx->EP2vm_state = VM_STOP;
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
}
void Wb35Tx_EP2VM_complete(struct urb * pUrb)
{
phw_data_t pHwData = pUrb->context;
T02_DESCRIPTOR T02, TSTATUS;
PADAPTER Adapter = (PADAPTER)pHwData->Adapter;
PWB35TX pWb35Tx = &pHwData->Wb35Tx;
PULONG pltmp = (PULONG)pWb35Tx->EP2_buf;
u32 i;
u16 InterruptInLength;
// Variable setting
pWb35Tx->EP2vm_state = VM_COMPLETED;
pWb35Tx->EP2VM_status = pUrb->status;
do {
// For Linux 2.4. Interrupt will always trigger
if( pHwData->SurpriseRemove || pHwData->HwStop ) // Let WbWlanHalt to handle surprise remove
break;
if( pWb35Tx->tx_halt )
break;
//The Urb is completed, check the result
if (pWb35Tx->EP2VM_status != 0) {
WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
pWb35Tx->EP2vm_state= VM_STOP;
break; // Exit while(FALSE);
}
// Update the Tx result
InterruptInLength = pUrb->actual_length;
// Modify for minimum memory access and DWORD alignment.
T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
InterruptInLength >>= 2; // InterruptInLength/4
for (i=1; i<=InterruptInLength; i++) {
T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
TSTATUS.value = T02.value; //20061009 anson's endian
Mds_SendComplete( Adapter, &TSTATUS );
T02.value = cpu_to_le32(pltmp[i]) >> 8;
}
return;
} while(FALSE);
OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
pWb35Tx->EP2vm_state = VM_STOP;
}
//====================================
// Interface function declare
//====================================
unsigned char Wb35Tx_initial( phw_data_t pHwData );
void Wb35Tx_destroy( phw_data_t pHwData );
unsigned char Wb35Tx_get_tx_buffer( phw_data_t pHwData, PUCHAR *pBuffer );
void Wb35Tx_EP2VM( phw_data_t pHwData );
void Wb35Tx_EP2VM_start( phw_data_t pHwData );
void Wb35Tx_EP2VM_complete( PURB purb );
void Wb35Tx_start( phw_data_t pHwData );
void Wb35Tx_stop( phw_data_t pHwData );
void Wb35Tx( phw_data_t pHwData );
void Wb35Tx_complete( PURB purb );
void Wb35Tx_reset_descriptor( phw_data_t pHwData );
void Wb35Tx_CurrentTime( phw_data_t pHwData, u32 TimeCount );
//====================================
// IS89C35 Tx related definition
//====================================
#define TX_INTERFACE 0 // Interface 1
#define TX_PIPE 3 // endpoint 4
#define TX_INTERRUPT 1 // endpoint 2
#define MAX_INTERRUPT_LENGTH 64 // It must be 64 for EP2 hardware
//====================================
// Internal variable for module
//====================================
typedef struct _WB35TX
{
// For Tx buffer
u8 TxBuffer[ MAX_USB_TX_BUFFER_NUMBER ][ MAX_USB_TX_BUFFER ];
// For Interrupt pipe
u8 EP2_buf[MAX_INTERRUPT_LENGTH];
OS_ATOMIC TxResultCount;// For thread control of EP2 931130.4.m
OS_ATOMIC TxFireCounter;// For thread control of EP4 931130.4.n
u32 ByteTransfer;
u32 TxSendIndex;// The next index of Mds array to be sent
u32 EP2vm_state; // for EP2vm state
u32 EP4vm_state; // for EP4vm state
u32 tx_halt; // Stopping VM
struct urb * Tx4Urb;
struct urb * Tx2Urb;
int EP2VM_status;
int EP4VM_status;
u32 TxFillCount; // 20060928
u32 TxTimer; // 20060928 Add if sending packet not great than 13
} WB35TX, *PWB35TX;
/*
* Copyright 2008 Pavel Machek <pavel@suse.cz>
*
* Distribute under GPLv2.
*/
#include "sysdef.h"
#include <net/mac80211.h>
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
//============================================================
// vendor ID and product ID can into here for others
//============================================================
static struct usb_device_id Id_Table[] =
{
{USB_DEVICE( 0x0416, 0x0035 )},
{USB_DEVICE( 0x18E8, 0x6201 )},
{USB_DEVICE( 0x18E8, 0x6206 )},
{USB_DEVICE( 0x18E8, 0x6217 )},
{USB_DEVICE( 0x18E8, 0x6230 )},
{USB_DEVICE( 0x18E8, 0x6233 )},
{USB_DEVICE( 0x1131, 0x2035 )},
{ }
};
MODULE_DEVICE_TABLE(usb, Id_Table);
static struct usb_driver wb35_driver = {
.name = "w35und",
.probe = wb35_probe,
.disconnect = wb35_disconnect,
.id_table = Id_Table,
};
static const struct ieee80211_rate wbsoft_rates[] = {
{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
};
static const struct ieee80211_channel wbsoft_channels[] = {
{ .center_freq = 2412},
};
int wbsoft_enabled;
struct ieee80211_hw *my_dev;
PADAPTER my_adapter;
static int wbsoft_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
printk("wbsoft_add interface called\n");
return 0;
}
static void wbsoft_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
printk("wbsoft_remove interface called\n");
}
static int wbsoft_nop(void)
{
printk("wbsoft_nop called\n");
return 0;
}
static void wbsoft_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_mc_list *mclist)
{
unsigned int bit_nr, new_flags;
u32 mc_filter[2];
int i;
new_flags = 0;
if (*total_flags & FIF_PROMISC_IN_BSS) {
new_flags |= FIF_PROMISC_IN_BSS;
mc_filter[1] = mc_filter[0] = ~0;
} else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {
new_flags |= FIF_ALLMULTI;
mc_filter[1] = mc_filter[0] = ~0;
} else {
mc_filter[1] = mc_filter[0] = 0;
for (i = 0; i < mc_count; i++) {
if (!mclist)
break;
printk("Should call ether_crc here\n");
//bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
bit_nr = 0;
bit_nr &= 0x3F;
mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
mclist = mclist->next;
}
}
dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
*total_flags = new_flags;
}
static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
char *buffer = kmalloc(skb->len, GFP_ATOMIC);
printk("Sending frame %d bytes\n", skb->len);
memcpy(buffer, skb->data, skb->len);
if (1 == MLMESendFrame(my_adapter, buffer, skb->len, FRAME_TYPE_802_11_MANAGEMENT))
printk("frame sent ok (%d bytes)?\n", skb->len);
return NETDEV_TX_OK;
}
static int wbsoft_start(struct ieee80211_hw *dev)
{
wbsoft_enabled = 1;
printk("wbsoft_start called\n");
return 0;
}
static int wbsoft_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
ChanInfo ch;
printk("wbsoft_config called\n");
ch.band = 1;
ch.ChanNo = 1; /* Should use channel_num, or something, as that is already pre-translated */
hal_set_current_channel(&my_adapter->sHwData, ch);
hal_set_beacon_period(&my_adapter->sHwData, conf->beacon_int);
// hal_set_cap_info(&my_adapter->sHwData, ?? );
// hal_set_ssid(phw_data_t pHwData, PUCHAR pssid, u8 ssid_len); ??
hal_set_accept_broadcast(&my_adapter->sHwData, 1);
hal_set_accept_promiscuous(&my_adapter->sHwData, 1);
hal_set_accept_multicast(&my_adapter->sHwData, 1);
hal_set_accept_beacon(&my_adapter->sHwData, 1);
hal_set_radio_mode(&my_adapter->sHwData, 0);
//hal_set_antenna_number( phw_data_t pHwData, u8 number )
//hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex)
// hal_start_bss(&my_adapter->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ??
//void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
// u8 length, unsigned char basic_rate_set)
return 0;
}
static int wbsoft_config_interface(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
printk("wbsoft_config_interface called\n");
return 0;
}
static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
{
printk("wbsoft_get_tsf called\n");
return 0;
}
static const struct ieee80211_ops wbsoft_ops = {
.tx = wbsoft_tx,
.start = wbsoft_start, /* Start can be pretty much empty as we do WbWLanInitialize() during probe? */
.stop = wbsoft_nop,
.add_interface = wbsoft_add_interface,
.remove_interface = wbsoft_remove_interface,
.config = wbsoft_config,
.config_interface = wbsoft_config_interface,
.configure_filter = wbsoft_configure_filter,
.get_stats = wbsoft_nop,
.get_tx_stats = wbsoft_nop,
.get_tsf = wbsoft_get_tsf,
// conf_tx: hal_set_cwmin()/hal_set_cwmax;
};
struct wbsoft_priv {
};
int __init wb35_init(void)
{
printk("[w35und]driver init\n");
return usb_register(&wb35_driver);
}
void __exit wb35_exit(void)
{
printk("[w35und]driver exit\n");
usb_deregister( &wb35_driver );
}
module_init(wb35_init);
module_exit(wb35_exit);
// Usb kernel subsystem will call this function when a new device is plugged into.
int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
{
PADAPTER Adapter;
PWBLINUX pWbLinux;
PWBUSB pWbUsb;
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
int i, ret = -1;
u32 ltmp;
struct usb_device *udev = interface_to_usbdev(intf);
usb_get_dev(udev);
printk("[w35und]wb35_probe ->\n");
do {
for (i=0; i<(sizeof(Id_Table)/sizeof(struct usb_device_id)); i++ ) {
if ((udev->descriptor.idVendor == Id_Table[i].idVendor) &&
(udev->descriptor.idProduct == Id_Table[i].idProduct)) {
printk("[w35und]Found supported hardware\n");
break;
}
}
if ((i == (sizeof(Id_Table)/sizeof(struct usb_device_id)))) {
#ifdef _PE_USB_INI_DUMP_
WBDEBUG(("[w35und] This is not the one we are interested about\n"));
#endif
return -ENODEV;
}
// 20060630.2 Check the device if it already be opened
ret = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
0x0, 0x400, &ltmp, 4, HZ*100 );
if( ret < 0 )
break;
ltmp = cpu_to_le32(ltmp);
if (ltmp) // Is already initialized?
break;
Adapter = kzalloc(sizeof(ADAPTER), GFP_KERNEL);
my_adapter = Adapter;
pWbLinux = &Adapter->WbLinux;
pWbUsb = &Adapter->sHwData.WbUsb;
pWbUsb->udev = udev;
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
if (endpoint[2].wMaxPacketSize == 512) {
printk("[w35und] Working on USB 2.0\n");
pWbUsb->IsUsb20 = 1;
}
if (!WbWLanInitialize(Adapter)) {
printk("[w35und]WbWLanInitialize fail\n");
break;
}
{
struct wbsoft_priv *priv;
struct ieee80211_hw *dev;
int res;
dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
if (!dev) {
printk("w35und: ieee80211 alloc failed\n" );
BUG();
}
my_dev = dev;
SET_IEEE80211_DEV(dev, &udev->dev);
{
phw_data_t pHwData = &Adapter->sHwData;
unsigned char dev_addr[MAX_ADDR_LEN];
hal_get_permanent_address(pHwData, dev_addr);
SET_IEEE80211_PERM_ADDR(dev, dev_addr);
}
dev->extra_tx_headroom = 12; /* FIXME */
dev->flags = 0;
dev->channel_change_time = 1000;
// dev->max_rssi = 100;
dev->queues = 1;
static struct ieee80211_supported_band band;
band.channels = wbsoft_channels;
band.n_channels = ARRAY_SIZE(wbsoft_channels);
band.bitrates = wbsoft_rates;
band.n_bitrates = ARRAY_SIZE(wbsoft_rates);
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band;
#if 0
wbsoft_modes[0].num_channels = 1;
wbsoft_modes[0].channels = wbsoft_channels;
wbsoft_modes[0].mode = MODE_IEEE80211B;
wbsoft_modes[0].num_rates = ARRAY_SIZE(wbsoft_rates);
wbsoft_modes[0].rates = wbsoft_rates;
res = ieee80211_register_hwmode(dev, &wbsoft_modes[0]);
BUG_ON(res);
#endif
res = ieee80211_register_hw(dev);
BUG_ON(res);
}
usb_set_intfdata( intf, Adapter );
printk("[w35und] _probe OK\n");
return 0;
} while(FALSE);
return -ENOMEM;
}
void packet_came(char *pRxBufferAddress, int PacketSize)
{
struct sk_buff *skb;
struct ieee80211_rx_status rx_status = {0};
if (!wbsoft_enabled)
return;
skb = dev_alloc_skb(PacketSize);
if (!skb) {
printk("Not enough memory for packet, FIXME\n");
return;
}
memcpy(skb_put(skb, PacketSize),
pRxBufferAddress,
PacketSize);
/*
rx_status.rate = 10;
rx_status.channel = 1;
rx_status.freq = 12345;
rx_status.phymode = MODE_IEEE80211B;
*/
ieee80211_rx_irqsafe(my_dev, skb, &rx_status);
}
unsigned char
WbUsb_initial(phw_data_t pHwData)
{
return 1;
}
void
WbUsb_destroy(phw_data_t pHwData)
{
}
int wb35_open(struct net_device *netdev)
{
PADAPTER Adapter = (PADAPTER)netdev->priv;
phw_data_t pHwData = &Adapter->sHwData;
netif_start_queue(netdev);
//TODO : put here temporarily
hal_set_accept_broadcast(pHwData, 1); // open accept broadcast
return 0;
}
int wb35_close(struct net_device *netdev)
{
netif_stop_queue(netdev);
return 0;
}
void wb35_disconnect(struct usb_interface *intf)
{
PWBLINUX pWbLinux;
PADAPTER Adapter = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
pWbLinux = &Adapter->WbLinux;
// Card remove
WbWlanHalt(Adapter);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Copyright (c) 1996-2004 Winbond Electronic Corporation
//
// Module Name:
// wbusb_f.h
//
// Abstract:
// Linux driver.
//
// Author:
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int wb35_open(struct net_device *netdev);
int wb35_close(struct net_device *netdev);
unsigned char WbUsb_initial(phw_data_t pHwData);
void WbUsb_destroy(phw_data_t pHwData);
unsigned char WbWLanInitialize(PADAPTER Adapter);
#define WbUsb_Stop( _A )
int wb35_probe(struct usb_interface *intf,const struct usb_device_id *id_table);
void wb35_disconnect(struct usb_interface *intf);
#define wb_usb_submit_urb(_A) usb_submit_urb(_A, GFP_ATOMIC)
#define wb_usb_alloc_urb(_A) usb_alloc_urb(_A, GFP_ATOMIC)
#define WbUsb_CheckForHang( _P )
#define WbUsb_DetectStart( _P, _I )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Copyright (c) 1996-2004 Winbond Electronic Corporation
//
// Module Name:
// wbusb_s.h
//
// Abstract:
// Linux driver.
//
// Author:
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define OS_SLEEP( _MT ) { set_current_state(TASK_INTERRUPTIBLE); \
schedule_timeout( _MT*HZ/1000000 ); }
//---------------------------------------------------------------------------
// RW_CONTEXT --
//
// Used to track driver-generated io irps
//---------------------------------------------------------------------------
typedef struct _RW_CONTEXT
{
void* pHwData;
PURB pUrb;
void* pCallBackFunctionParameter;
} RW_CONTEXT, *PRW_CONTEXT;
#define DRIVER_AUTHOR "Original by: Jeff Lee<YY_Lee@issc.com.tw> Adapted to 2.6.x by Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>"
#define DRIVER_DESC "IS89C35 802.11bg WLAN USB Driver"
typedef struct _WBUSB {
u32 IsUsb20;
struct usb_device *udev;
u32 DetectCount;
} WBUSB, *PWBUSB;
//=============================================================
// LocalPara.h -
//=============================================================
//Define the local ability
#define LOCAL_DEFAULT_BEACON_PERIOD 100 //ms
#define LOCAL_DEFAULT_ATIM_WINDOW 0
#define LOCAL_DEFAULT_ERP_CAPABILITY 0x0431 //0x0001: ESS
//0x0010: Privacy
//0x0020: short preamble
//0x0400: short slot time
#define LOCAL_DEFAULT_LISTEN_INTERVAL 5
//#define LOCAL_DEFAULT_24_CHANNEL_NUM 11 // channel 1..11
#define LOCAL_DEFAULT_24_CHANNEL_NUM 13 // channel 1..13
#define LOCAL_DEFAULT_5_CHANNEL_NUM 8 // channel 36..64
#define LOCAL_USA_24_CHANNEL_NUM 11
#define LOCAL_USA_5_CHANNEL_NUM 12
#define LOCAL_EUROPE_24_CHANNEL_NUM 13
#define LOCAL_EUROPE_5_CHANNEL_NUM 19
#define LOCAL_JAPAN_24_CHANNEL_NUM 14
#define LOCAL_JAPAN_5_CHANNEL_NUM 11
#define LOCAL_UNKNOWN_24_CHANNEL_NUM 14
#define LOCAL_UNKNOWN_5_CHANNEL_NUM 34 //not include 165
#define psLOCAL (&(Adapter->sLocalPara))
#define MODE_802_11_BG 0
#define MODE_802_11_A 1
#define MODE_802_11_ABG 2
#define MODE_802_11_BG_IBSS 3
#define MODE_802_11_B 4
#define MODE_AUTO 255
#define BAND_TYPE_DSSS 0
#define BAND_TYPE_OFDM_24 1
#define BAND_TYPE_OFDM_5 2
//refer Bitmap2RateValue table
#define LOCAL_ALL_SUPPORTED_RATES_BITMAP 0x130c1a66 //the bitmap value of all the H/W supported rates
//1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
#define LOCAL_OFDM_SUPPORTED_RATES_BITMAP 0x130c1240 //the bitmap value of all the H/W supported rates
//except to non-OFDM rates
//6, 9, 12, 18, 24, 36, 48, 54
#define LOCAL_11B_SUPPORTED_RATE_BITMAP 0x826
#define LOCAL_11B_BASIC_RATE_BITMAP 0x826
#define LOCAL_11B_OPERATION_RATE_BITMAP 0x826
#define LOCAL_11G_BASIC_RATE_BITMAP 0x826 //1, 2, 5.5, 11
#define LOCAL_11G_OPERATION_RATE_BITMAP 0x130c1240 //6, 9, 12, 18, 24, 36, 48, 54
#define LOCAL_11A_BASIC_RATE_BITMAP 0x01001040 //6, 12, 24
#define LOCAL_11A_OPERATION_RATE_BITMAP 0x120c0200 //9, 18, 36, 48, 54
#define PWR_ACTIVE 0
#define PWR_SAVE 1
#define PWR_TX_IDLE_CYCLE 6
//bPreambleMode and bSlotTimeMode
#define AUTO_MODE 0
#define LONG_MODE 1
//Region definition
#define REGION_AUTO 0xff
#define REGION_UNKNOWN 0
#define REGION_EUROPE 1 //ETSI
#define REGION_JAPAN 2 //MKK
#define REGION_USA 3 //FCC
#define REGION_FRANCE 4 //FRANCE
#define REGION_SPAIN 5 //SPAIN
#define REGION_ISRAEL 6 //ISRAEL
//#define REGION_CANADA 7 //IC
#define MAX_BSS_DESCRIPT_ELEMENT 32
#define MAX_PMKID_CandidateList 16
//High byte : Event number, low byte : reason
//Event definition
//-- SME/MLME event
#define EVENT_RCV_DEAUTH 0x0100
#define EVENT_JOIN_FAIL 0x0200
#define EVENT_AUTH_FAIL 0x0300
#define EVENT_ASSOC_FAIL 0x0400
#define EVENT_LOST_SIGNAL 0x0500
#define EVENT_BSS_DESCRIPT_LACK 0x0600
#define EVENT_COUNTERMEASURE 0x0700
#define EVENT_JOIN_FILTER 0x0800
//-- TX/RX event
#define EVENT_RX_BUFF_UNAVAILABLE 0x4100
#define EVENT_CONNECT 0x8100
#define EVENT_DISCONNECT 0x8200
#define EVENT_SCAN_REQ 0x8300
//Reason of Event
#define EVENT_REASON_FILTER_BASIC_RATE 0x0001
#define EVENT_REASON_FILTER_PRIVACY 0x0002
#define EVENT_REASON_FILTER_AUTH_MODE 0x0003
#define EVENT_REASON_TIMEOUT 0x00ff
// 20061108 WPS IE buffer
#define MAX_IE_APPEND_SIZE 256 + 4 // Due to [E id][Length][OUI][Data] may 257 bytes
typedef struct _EVENTLOG
{
u16 Count; //Total count from start
u16 index; //Buffer index, 0 ~ 63
u32 EventValue[64]; //BYTE 3~2 : count, BYTE 1 : Event, BYTE 0 : reason
} Event_Log, *pEvent_Log;
typedef struct _ChanInfo
{
u8 band;
u8 ChanNo;
} ChanInfo, *pChanInfo;
typedef struct _CHAN_LIST
{
u16 Count;
ChanInfo Channel[50]; // 100B
} CHAN_LIST, *psCHAN_LIST;
typedef struct _RadioOff
{
u8 boHwRadioOff;
u8 boSwRadioOff;
} RadioOff, *psRadioOff;
//===========================================================================
typedef struct LOCAL_PARA
{
u8 PermanentAddress[ MAC_ADDR_LENGTH + 2 ]; // read from EPROM, manufacture set for each NetCard
u8 ThisMacAddress[ MAC_ADDR_LENGTH + 2 ]; // the driver will use actually.
u32 MTUsize; // Ind to Uplayer, Max transmission unit size
u8 region_INF; //region setting from INF
u8 region; //real region setting of the device
u8 Reserved_1[2];
//// power-save variables
u8 iPowerSaveMode; // 0 indicates it is on, 1 indicates it is off
u8 ShutDowned;
u8 ATIMmode;
u8 ExcludeUnencrypted;
u16 CheckCountForPS; //Unit ime count for the decision to enter PS mode
u8 boHasTxActivity; //tx activity has occurred
u8 boMacPsValid; //Power save mode obtained from H/W is valid or not
//// Rate
u8 TxRateMode; // Initial, input from Registry, may be updated by GUI
//Tx Rate Mode: auto(DTO on), max, 1M, 2M, ..
u8 CurrentTxRate; // The current Tx rate
u8 CurrentTxRateForMng; // The current Tx rate for management frames
// It will be decided before connection succeeds.
u8 CurrentTxFallbackRate;
//for Rate handler
u8 BRateSet[32]; //basic rate set
u8 SRateSet[32]; //support rate set
u8 NumOfBRate;
u8 NumOfSRate;
u8 NumOfDsssRateInSRate; //number of DSSS rates in supported rate set
u8 reserved1;
u32 dwBasicRateBitmap; //bit map of basic rates
u32 dwSupportRateBitmap; //bit map of all support rates including
//basic and operational rates
////For SME/MLME handler
u16 wOldSTAindex; // valid when boHandover=TRUE, store old connected STA index
u16 wConnectedSTAindex; // Index of peerly connected AP or IBSS in
// the descriptionset.
u16 Association_ID; // The Association ID in the (Re)Association
// Response frame.
u16 ListenInterval; // The listen interval when SME invoking MLME_
// (Re)Associate_Request().
RadioOff RadioOffStatus;
u8 Reserved0[2];
u8 boMsRadioOff; // Ndis demands to be true when set Disassoc. OID and be false when set SSID OID.
u8 boAntennaDiversity; //TRUE/ON or FALSE/OFF
u8 bAntennaNo; //which antenna
u8 bConnectFlag; //the connect status flag for roaming task
u8 RoamStatus;
u8 reserved7[3];
ChanInfo CurrentChan; //Current channel no. and channel band. It may be changed by scanning.
u8 boHandover; // Roaming, Hnadover to other AP.
u8 boCCAbusy;
u16 CWMax; // It may not be the real value that H/W used
u8 CWMin; // 255: set according to 802.11 spec.
u8 reserved2;
//11G:
u8 bMacOperationMode; // operation in 802.11b or 802.11g
u8 bSlotTimeMode; //AUTO, s32
u8 bPreambleMode; //AUTO, s32
u8 boNonERPpresent;
u8 boProtectMechanism; // H/W will take the necessary action based on this variable
u8 boShortPreamble; // H/W will take the necessary action based on this variable
u8 boShortSlotTime; // H/W will take the necessary action based on this variable
u8 reserved_3;
u32 RSN_IE_Bitmap; //added by WS
u32 RSN_OUI_Type; //added by WS
//For the BSSID
u8 HwBssid[MAC_ADDR_LENGTH + 2];
u32 HwBssidValid;
//For scan list
u8 BssListCount; //Total count of valid descriptor indexes
u8 boReceiveUncorrectInfo; //important settings in beacon/probe resp. have been changed
u8 NoOfJoinerInIbss;
u8 reserved_4;
u8 BssListIndex[ (MAX_BSS_DESCRIPT_ELEMENT+3) & ~0x03 ]; //Store the valid descriptor indexes obtained from scannings
u8 JoinerInIbss[ (MAX_BSS_DESCRIPT_ELEMENT+3) & ~0x03 ]; //save the BssDescriptor index in this
//IBSS. The index 0 is local descriptor
//(psLOCAL->wConnectedSTAindex).
//If CONNECTED : NoOfJoinerInIbss >=2
// else : NoOfJoinerInIbss <=1
//// General Statistics, count at Rx_handler or Tx_callback interrupt handler
u64 GS_XMIT_OK; // Good Frames Transmitted
u64 GS_RCV_OK; // Good Frames Received
u32 GS_RCV_ERROR; // Frames received with crc error
u32 GS_XMIT_ERROR; // Bad Frames Transmitted
u32 GS_RCV_NO_BUFFER; // Receive Buffer underrun
u32 GS_XMIT_ONE_COLLISION; // one collision
u32 GS_XMIT_MORE_COLLISIONS;// more collisions
//================================================================
// Statistics (no matter whether it had done successfully) -wkchen
//================================================================
u32 _NumRxMSDU;
u32 _NumTxMSDU;
u32 _dot11WEPExcludedCount;
u32 _dot11WEPUndecryptableCount;
u32 _dot11FrameDuplicateCount;
ChanInfo IbssChanSetting; // 2B. Start IBSS Channel setting by registry or WWU.
u8 reserved_5[2]; //It may not be used after considering RF type,
//region and modulation type.
CHAN_LIST sSupportChanList; // 86B. It will be obtained according to RF type and region
u8 reserved_6[2]; //two variables are for wep key error detection added by ws 02/02/04
u32 bWepKeyError;
u32 bToSelfPacketReceived;
u32 WepKeyDetectTimerCount;
Event_Log EventLog;
u16 SignalLostTh;
u16 SignalRoamTh;
// 20061108 WPS IE Append
u8 IE_Append_data[MAX_IE_APPEND_SIZE];
u16 IE_Append_size;
u16 reserved_7;
} WB_LOCALDESCRIPT, *PWB_LOCALDESCRIPT;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// MAC_Structures.h
//
// This file contains the definitions and data structures used by SW-MAC.
//
// Revision Histoy
//=================
// 0.1 2002 UN00
// 0.2 20021004 PD43 CCLiu6
// 20021018 PD43 CCLiu6
// Add enum_TxRate type
// Modify enum_STAState type
// 0.3 20021023 PE23 CYLiu update MAC session struct
// 20021108
// 20021122 PD43 Austin
// Deleted some unused.
// 20021129 PD43 Austin
// 20030617 increase the 802.11g definition
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifndef _MAC_Structures_H_
#define _MAC_Structures_H_
//=========================================================
// Some miscellaneous definitions
//-----
#define MAX_CHANNELS 30
#define MAC_ADDR_LENGTH 6
#define MAX_WEP_KEY_SIZE 16 // 128 bits
#define MAX_802_11_FRAGMENT_NUMBER 10 // By spec
//========================================================
// 802.11 Frame define
//-----
#define MASK_PROTOCOL_VERSION_TYPE 0x0F
#define MASK_FRAGMENT_NUMBER 0x000F
#define SEQUENCE_NUMBER_SHIFT 4
#define DIFFER_11_TO_3 18
#define DOT_11_MAC_HEADER_SIZE 24
#define DOT_11_SNAP_SIZE 6
#define DOT_11_DURATION_OFFSET 2
#define DOT_11_SEQUENCE_OFFSET 22 //Sequence control offset
#define DOT_11_TYPE_OFFSET 30 //The start offset of 802.11 Frame//
#define DOT_11_DATA_OFFSET 24
#define DOT_11_DA_OFFSET 4
#define DOT_3_TYPE_ARP 0x80F3
#define DOT_3_TYPE_IPX 0x8137
#define DOT_3_TYPE_OFFSET 12
#define ETHERNET_HEADER_SIZE 14
#define MAX_ETHERNET_PACKET_SIZE 1514
//----- management : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
#define MAC_SUBTYPE_MNGMNT_ASSOC_REQUEST 0x00
#define MAC_SUBTYPE_MNGMNT_ASSOC_RESPONSE 0x10
#define MAC_SUBTYPE_MNGMNT_REASSOC_REQUEST 0x20
#define MAC_SUBTYPE_MNGMNT_REASSOC_RESPONSE 0x30
#define MAC_SUBTYPE_MNGMNT_PROBE_REQUEST 0x40
#define MAC_SUBTYPE_MNGMNT_PROBE_RESPONSE 0x50
#define MAC_SUBTYPE_MNGMNT_BEACON 0x80
#define MAC_SUBTYPE_MNGMNT_ATIM 0x90
#define MAC_SUBTYPE_MNGMNT_DISASSOCIATION 0xA0
#define MAC_SUBTYPE_MNGMNT_AUTHENTICATION 0xB0
#define MAC_SUBTYPE_MNGMNT_DEAUTHENTICATION 0xC0
//----- control : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
#define MAC_SUBTYPE_CONTROL_PSPOLL 0xA4
#define MAC_SUBTYPE_CONTROL_RTS 0xB4
#define MAC_SUBTYPE_CONTROL_CTS 0xC4
#define MAC_SUBTYPE_CONTROL_ACK 0xD4
#define MAC_SUBTYPE_CONTROL_CFEND 0xE4
#define MAC_SUBTYPE_CONTROL_CFEND_CFACK 0xF4
//----- data : Type of Bits (2, 3) and Subtype of Bits (4, 5, 6, 7)
#define MAC_SUBTYPE_DATA 0x08
#define MAC_SUBTYPE_DATA_CFACK 0x18
#define MAC_SUBTYPE_DATA_CFPOLL 0x28
#define MAC_SUBTYPE_DATA_CFACK_CFPOLL 0x38
#define MAC_SUBTYPE_DATA_NULL 0x48
#define MAC_SUBTYPE_DATA_CFACK_NULL 0x58
#define MAC_SUBTYPE_DATA_CFPOLL_NULL 0x68
#define MAC_SUBTYPE_DATA_CFACK_CFPOLL_NULL 0x78
//----- Frame Type of Bits (2, 3)
#define MAC_TYPE_MANAGEMENT 0x00
#define MAC_TYPE_CONTROL 0x04
#define MAC_TYPE_DATA 0x08
//----- definitions for Management Frame Element ID (1 BYTE)
#define ELEMENT_ID_SSID 0
#define ELEMENT_ID_SUPPORTED_RATES 1
#define ELEMENT_ID_FH_PARAMETER_SET 2
#define ELEMENT_ID_DS_PARAMETER_SET 3
#define ELEMENT_ID_CF_PARAMETER_SET 4
#define ELEMENT_ID_TIM 5
#define ELEMENT_ID_IBSS_PARAMETER_SET 6
// 7~15 reserverd
#define ELEMENT_ID_CHALLENGE_TEXT 16
// 17~31 reserved for challenge text extension
// 32~255 reserved
//-- 11G --
#define ELEMENT_ID_ERP_INFORMATION 42
#define ELEMENT_ID_EXTENDED_SUPPORTED_RATES 50
//-- WPA --
#define ELEMENT_ID_RSN_WPA 221
#ifdef _WPA2_
#define ELEMENT_ID_RSN_WPA2 48
#endif //endif WPA2
#define WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT ((u16) 6)
#define WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT ((u16) 2)
#ifdef WB_LINUX
#define UNALIGNED
#endif
//========================================================
typedef enum enum_PowerManagementMode
{
ACTIVE = 0,
POWER_SAVE
} WB_PM_Mode, *PWB_PM_MODE;
//===================================================================
// Reason Code (Table 18): indicate the reason of DisAssoc, DeAuthen
// length of ReasonCode is 2 Octs.
//===================================================================
#define REASON_REASERED 0
#define REASON_UNSPECIDIED 1
#define REASON_PREAUTH_INVALID 2
#define DEAUTH_REASON_LEFT_BSS 3
#define DISASS_REASON_AP_INACTIVE 4
#define DISASS_REASON_AP_BUSY 5
#define REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
#define REASON_CLASS3_FRAME_FROM_NONASSO_STA 7
#define DISASS_REASON_LEFT_BSS 8
#define REASON_NOT_AUTH_YET 9
//802.11i define
#define REASON_INVALID_IE 13
#define REASON_MIC_ERROR 14
#define REASON_4WAY_HANDSHAKE_TIMEOUT 15
#define REASON_GROUPKEY_UPDATE_TIMEOUT 16
#define REASON_IE_DIFF_4WAY_ASSOC 17
#define REASON_INVALID_MULTICAST_CIPHER 18
#define REASON_INVALID_UNICAST_CIPHER 19
#define REASON_INVALID_AKMP 20
#define REASON_UNSUPPORTED_RSNIE_VERSION 21
#define REASON_INVALID_RSNIE_CAPABILITY 22
#define REASON_802_1X_AUTH_FAIL 23
#define REASON_CIPHER_REJECT_PER_SEC_POLICY 14
/*
//===========================================================
// enum_MMPDUResultCode --
// Status code (2 Octs) in the MMPDU's frame body. Table.19
//
//===========================================================
enum enum_MMPDUResultCode
{
// SUCCESS = 0, // Redefined
UNSPECIFIED_FAILURE = 1,
// 2 - 9 Reserved
NOT_SUPPROT_CAPABILITIES = 10,
//REASSOCIATION_DENIED
//
REASSOC_DENIED_UNABLE_CFM_ASSOC_EXIST = 11,
//ASSOCIATION_DENIED_NOT_IN_STANDARD
//
ASSOC_DENIED_REASON_NOT_IN_STANDARD = 12,
PEER_NOT_SUPPORT_AUTH_ALGORITHM = 13,
AUTH_SEQNUM_OUT_OF_EXPECT = 14,
AUTH_REJECT_REASON_CHALLENGE_FAIL = 15,
AUTH_REJECT_REASON_WAIT_TIMEOUT = 16,
ASSOC_DENIED_REASON_AP_BUSY = 17,
ASSOC_DENIED_REASON_NOT_SUPPORT_BASIC_RATE = 18
} WB_MMPDURESULTCODE, *PWB_MMPDURESULTCODE;
*/
//===========================================================
// enum_TxRate --
// Define the transmission constants based on W89C32 MAC
// target specification.
//===========================================================
typedef enum enum_TxRate
{
TXRATE_1M = 0,
TXRATE_2MLONG = 2,
TXRATE_2MSHORT = 3,
TXRATE_55MLONG = 4,
TXRATE_55MSHORT = 5,
TXRATE_11MLONG = 6,
TXRATE_11MSHORT = 7,
TXRATE_AUTO = 255 // PD43 20021108
} WB_TXRATE, *PWB_TXRATE;
#define RATE_BITMAP_1M 1
#define RATE_BITMAP_2M 2
#define RATE_BITMAP_5dot5M 5
#define RATE_BITMAP_6M 6
#define RATE_BITMAP_9M 9
#define RATE_BITMAP_11M 11
#define RATE_BITMAP_12M 12
#define RATE_BITMAP_18M 18
#define RATE_BITMAP_22M 22
#define RATE_BITMAP_24M 24
#define RATE_BITMAP_33M 17
#define RATE_BITMAP_36M 19
#define RATE_BITMAP_48M 25
#define RATE_BITMAP_54M 28
#define RATE_AUTO 0
#define RATE_1M 2
#define RATE_2M 4
#define RATE_5dot5M 11
#define RATE_6M 12
#define RATE_9M 18
#define RATE_11M 22
#define RATE_12M 24
#define RATE_18M 36
#define RATE_22M 44
#define RATE_24M 48
#define RATE_33M 66
#define RATE_36M 72
#define RATE_48M 96
#define RATE_54M 108
#define RATE_MAX 255
//CAPABILITY
#define CAPABILITY_ESS_BIT 0x0001
#define CAPABILITY_IBSS_BIT 0x0002
#define CAPABILITY_CF_POLL_BIT 0x0004
#define CAPABILITY_CF_POLL_REQ_BIT 0x0008
#define CAPABILITY_PRIVACY_BIT 0x0010
#define CAPABILITY_SHORT_PREAMBLE_BIT 0x0020
#define CAPABILITY_PBCC_BIT 0x0040
#define CAPABILITY_CHAN_AGILITY_BIT 0x0080
#define CAPABILITY_SHORT_SLOT_TIME_BIT 0x0400
#define CAPABILITY_DSSS_OFDM_BIT 0x2000
struct Capability_Information_Element
{
union
{
u16 __attribute__ ((packed)) wValue;
#ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
struct _Capability
{
//-- 11G --
u8 Reserved3 : 2;
u8 DSSS_OFDM : 1;
u8 Reserved2 : 2;
u8 Short_Slot_Time : 1;
u8 Reserved1 : 2;
u8 Channel_Agility : 1;
u8 PBCC : 1;
u8 ShortPreamble : 1;
u8 CF_Privacy : 1;
u8 CF_Poll_Request : 1;
u8 CF_Pollable : 1;
u8 IBSS : 1;
u8 ESS : 1;
} __attribute__ ((packed)) Capability;
#else
struct _Capability
{
u8 ESS : 1;
u8 IBSS : 1;
u8 CF_Pollable : 1;
u8 CF_Poll_Request : 1;
u8 CF_Privacy : 1;
u8 ShortPreamble : 1;
u8 PBCC : 1;
u8 Channel_Agility : 1;
u8 Reserved1 : 2;
//-- 11G --
u8 Short_Slot_Time : 1;
u8 Reserved2 : 2;
u8 DSSS_OFDM : 1;
u8 Reserved3 : 2;
} __attribute__ ((packed)) Capability;
#endif
}__attribute__ ((packed)) ;
}__attribute__ ((packed));
struct FH_Parameter_Set_Element
{
u8 Element_ID;
u8 Length;
u8 Dwell_Time[2];
u8 Hop_Set;
u8 Hop_Pattern;
u8 Hop_Index;
};
struct DS_Parameter_Set_Element
{
u8 Element_ID;
u8 Length;
u8 Current_Channel;
};
struct Supported_Rates_Element
{
u8 Element_ID;
u8 Length;
u8 SupportedRates[8];
}__attribute__ ((packed));
struct SSID_Element
{
u8 Element_ID;
u8 Length;
u8 SSID[32];
}__attribute__ ((packed)) ;
struct CF_Parameter_Set_Element
{
u8 Element_ID;
u8 Length;
u8 CFP_Count;
u8 CFP_Period;
u8 CFP_MaxDuration[2]; // in Time Units
u8 CFP_DurRemaining[2]; // in time units
};
struct TIM_Element
{
u8 Element_ID;
u8 Length;
u8 DTIM_Count;
u8 DTIM_Period;
u8 Bitmap_Control;
u8 Partial_Virtual_Bitmap[251];
};
struct IBSS_Parameter_Set_Element
{
u8 Element_ID;
u8 Length;
u8 ATIM_Window[2];
};
struct Challenge_Text_Element
{
u8 Element_ID;
u8 Length;
u8 Challenge_Text[253];
};
struct PHY_Parameter_Set_Element
{
// int aSlotTime;
// int aSifsTime;
s32 aCCATime;
s32 aRxTxTurnaroundTime;
s32 aTxPLCPDelay;
s32 RxPLCPDelay;
s32 aRxTxSwitchTime;
s32 aTxRampOntime;
s32 aTxRampOffTime;
s32 aTxRFDelay;
s32 aRxRFDelay;
s32 aAirPropagationTime;
s32 aMACProcessingDelay;
s32 aPreambleLength;
s32 aPLCPHeaderLength;
s32 aMPDUDurationFactor;
s32 aMPDUMaxLength;
// int aCWmin;
// int aCWmax;
};
//-- 11G --
struct ERP_Information_Element
{
u8 Element_ID;
u8 Length;
#ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
u8 Reserved:5; //20060926 add by anson
u8 Barker_Preamble_Mode:1;
u8 Use_Protection:1;
u8 NonERP_Present:1;
#else
u8 NonERP_Present:1;
u8 Use_Protection:1;
u8 Barker_Preamble_Mode:1;
u8 Reserved:5;
#endif
};
struct Extended_Supported_Rates_Element
{
u8 Element_ID;
u8 Length;
u8 ExtendedSupportedRates[255];
}__attribute__ ((packed));
//WPA(802.11i draft 3.0)
#define VERSION_WPA 1
#ifdef _WPA2_
#define VERSION_WPA2 1
#endif //end def _WPA2_
#define OUI_WPA 0x00F25000 //WPA2.0 OUI=00:50:F2, the MSB is reserved for suite type
#ifdef _WPA2_
#define OUI_WPA2 0x00AC0F00 // for wpa2 change to 0x00ACOF04 by Ws 26/04/04
#endif //end def _WPA2_
#define OUI_WPA_ADDITIONAL 0x01
#define WLAN_MIN_RSN_WPA_LENGTH 6 //added by ws 09/10/04
#ifdef _WPA2_
#define WLAN_MIN_RSN_WPA2_LENGTH 2 // Fix to 2 09/14/05
#endif //end def _WPA2_
#define oui_wpa (u32)(OUI_WPA|OUI_WPA_ADDITIONAL)
#define WPA_OUI_BIG ((u32) 0x01F25000)//added by ws 09/23/04
#define WPA_OUI_LITTLE ((u32) 0x01F25001)//added by ws 09/23/04
#define WPA_WPS_OUI cpu_to_le32(0x04F25000) // 20061108 For WPS. It's little endian. Big endian is 0x0050F204
//-----WPA2-----
#ifdef _WPA2_
#define WPA2_OUI_BIG ((u32)0x01AC0F00)
#define WPA2_OUI_LITTLE ((u32)0x01AC0F01)
#endif //end def _WPA2_
//Authentication suite
#define OUI_AUTH_WPA_NONE 0x00 //for WPA_NONE
#define OUI_AUTH_8021X 0x01
#define OUI_AUTH_PSK 0x02
//Cipher suite
#define OUI_CIPHER_GROUP_KEY 0x00 //added by ws 05/21/04
#define OUI_CIPHER_WEP_40 0x01
#define OUI_CIPHER_TKIP 0x02
#define OUI_CIPHER_CCMP 0x04
#define OUI_CIPHER_WEP_104 0x05
typedef struct _SUITE_SELECTOR_
{
union
{
u8 Value[4];
struct _SUIT_
{
u8 OUI[3];
u8 Type;
}SuitSelector;
};
}SUITE_SELECTOR;
//-- WPA --
struct RSN_Information_Element
{
u8 Element_ID;
u8 Length;
UNALIGNED SUITE_SELECTOR OuiWPAAdditional;//WPA version 2.0 additional field, and should be 00:50:F2:01
u16 Version;
SUITE_SELECTOR GroupKeySuite;
u16 PairwiseKeySuiteCount;
SUITE_SELECTOR PairwiseKeySuite[1];
}__attribute__ ((packed));
struct RSN_Auth_Sub_Information_Element
{
u16 AuthKeyMngtSuiteCount;
SUITE_SELECTOR AuthKeyMngtSuite[1];
}__attribute__ ((packed));
//-- WPA2 --
struct RSN_Capability_Element
{
union
{
u16 __attribute__ ((packed)) wValue;
#ifdef _BIG_ENDIAN_ //20060927 add by anson's endian
struct _RSN_Capability
{
u16 __attribute__ ((packed)) Reserved2 : 8; // 20051201
u16 __attribute__ ((packed)) Reserved1 : 2;
u16 __attribute__ ((packed)) GTK_Replay_Counter : 2;
u16 __attribute__ ((packed)) PTK_Replay_Counter : 2;
u16 __attribute__ ((packed)) No_Pairwise : 1;
u16 __attribute__ ((packed)) Pre_Auth : 1;
}__attribute__ ((packed)) RSN_Capability;
#else
struct _RSN_Capability
{
u16 __attribute__ ((packed)) Pre_Auth : 1;
u16 __attribute__ ((packed)) No_Pairwise : 1;
u16 __attribute__ ((packed)) PTK_Replay_Counter : 2;
u16 __attribute__ ((packed)) GTK_Replay_Counter : 2;
u16 __attribute__ ((packed)) Reserved1 : 2;
u16 __attribute__ ((packed)) Reserved2 : 8; // 20051201
}__attribute__ ((packed)) RSN_Capability;
#endif
}__attribute__ ((packed)) ;
}__attribute__ ((packed)) ;
#ifdef _WPA2_
typedef struct _PMKID
{
u8 pValue[16];
}PMKID;
struct WPA2_RSN_Information_Element
{
u8 Element_ID;
u8 Length;
u16 Version;
SUITE_SELECTOR GroupKeySuite;
u16 PairwiseKeySuiteCount;
SUITE_SELECTOR PairwiseKeySuite[1];
}__attribute__ ((packed));
struct WPA2_RSN_Auth_Sub_Information_Element
{
u16 AuthKeyMngtSuiteCount;
SUITE_SELECTOR AuthKeyMngtSuite[1];
}__attribute__ ((packed));
struct PMKID_Information_Element
{
u16 PMKID_Count;
PMKID pmkid [16] ;
}__attribute__ ((packed));
#endif //enddef _WPA2_
//============================================================
// MAC Frame structure (different type) and subfield structure
//============================================================
struct MAC_frame_control
{
u8 mac_frame_info; // a combination of the [Protocol Version, Control Type, Control Subtype]
#ifdef _BIG_ENDIAN_ //20060927 add by anson's endian
u8 order:1;
u8 WEP:1;
u8 more_data:1;
u8 pwr_mgt:1;
u8 retry:1;
u8 more_frag:1;
u8 from_ds:1;
u8 to_ds:1;
#else
u8 to_ds:1;
u8 from_ds:1;
u8 more_frag:1;
u8 retry:1;
u8 pwr_mgt:1;
u8 more_data:1;
u8 WEP:1;
u8 order:1;
#endif
} __attribute__ ((packed));
struct Management_Frame {
struct MAC_frame_control frame_control; // 2B, ToDS,FromDS,MoreFrag,MoreData,Order=0
u16 duration;
u8 DA[MAC_ADDR_LENGTH]; // Addr1
u8 SA[MAC_ADDR_LENGTH]; // Addr2
u8 BSSID[MAC_ADDR_LENGTH]; // Addr3
u16 Sequence_Control;
// Management Frame Body <= 325 bytes
// FCS 4 bytes
}__attribute__ ((packed));
// SW-MAC don't Tx/Rx Control-Frame, HW-MAC do it.
struct Control_Frame {
struct MAC_frame_control frame_control; // ToDS,FromDS,MoreFrag,Retry,MoreData,WEP,Order=0
u16 duration;
u8 RA[MAC_ADDR_LENGTH];
u8 TA[MAC_ADDR_LENGTH];
u16 FCS;
}__attribute__ ((packed));
struct Data_Frame {
struct MAC_frame_control frame_control;
u16 duration;
u8 Addr1[MAC_ADDR_LENGTH];
u8 Addr2[MAC_ADDR_LENGTH];
u8 Addr3[MAC_ADDR_LENGTH];
u16 Sequence_Control;
u8 Addr4[MAC_ADDR_LENGTH]; // only exist when ToDS=FromDS=1
// Data Frame Body <= 2312
// FCS
}__attribute__ ((packed));
struct Disassociation_Frame_Body
{
u16 reasonCode;
}__attribute__ ((packed));
struct Association_Request_Frame_Body
{
u16 capability_information;
u16 listenInterval;
u8 Current_AP_Address[MAC_ADDR_LENGTH];//for reassociation only
// SSID (2+32 bytes)
// Supported_Rates (2+8 bytes)
}__attribute__ ((packed));
struct Association_Response_Frame_Body
{
u16 capability_information;
u16 statusCode;
u16 Association_ID;
struct Supported_Rates_Element supportedRates;
}__attribute__ ((packed));
/*struct Reassociation_Request_Frame_Body
{
u16 capability_information;
u16 listenInterval;
u8 Current_AP_Address[MAC_ADDR_LENGTH];
// SSID (2+32 bytes)
// Supported_Rates (2+8 bytes)
};*/
// eliminated by WS 07/22/04 comboined with associateion request frame.
struct Reassociation_Response_Frame_Body
{
u16 capability_information;
u16 statusCode;
u16 Association_ID;
struct Supported_Rates_Element supportedRates;
}__attribute__ ((packed));
struct Deauthentication_Frame_Body
{
u16 reasonCode;
}__attribute__ ((packed));
struct Probe_Response_Frame_Body
{
u16 Timestamp;
u16 Beacon_Interval;
u16 Capability_Information;
// SSID
// Supported_Rates
// PHY parameter Set (DS Parameters)
// CF parameter Set
// IBSS parameter Set
}__attribute__ ((packed));
struct Authentication_Frame_Body
{
u16 algorithmNumber;
u16 sequenceNumber;
u16 statusCode;
// NB: don't include ChallengeText in this structure
// struct Challenge_Text_Element sChallengeTextElement; // wkchen added
}__attribute__ ((packed));
#endif // _MAC_Structure_H_
#include "os_common.h"
void
Mds_reset_descriptor(PADAPTER Adapter)
{
PMDS pMds = &Adapter->Mds;
pMds->TxPause = 0;
pMds->TxThreadCount = 0;
pMds->TxFillIndex = 0;
pMds->TxDesIndex = 0;
pMds->ScanTxPause = 0;
memset(pMds->TxOwner, 0, ((MAX_USB_TX_BUFFER_NUMBER + 3) & ~0x03));
}
unsigned char
Mds_initial(PADAPTER Adapter)
{
PMDS pMds = &Adapter->Mds;
pMds->TxPause = FALSE;
pMds->TxRTSThreshold = DEFAULT_RTSThreshold;
pMds->TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
vRxTimerInit(Adapter);//for WPA countermeasure
return hal_get_tx_buffer( &Adapter->sHwData, &pMds->pTxBuffer );
}
void
Mds_Destroy(PADAPTER Adapter)
{
vRxTimerStop(Adapter);
}
void
Mds_Tx(PADAPTER Adapter)
{
phw_data_t pHwData = &Adapter->sHwData;
PMDS pMds = &Adapter->Mds;
DESCRIPTOR TxDes;
PDESCRIPTOR pTxDes = &TxDes;
PUCHAR XmitBufAddress;
u16 XmitBufSize, PacketSize, stmp, CurrentSize, FragmentThreshold;
u8 FillIndex, TxDesIndex, FragmentCount, FillCount;
unsigned char BufferFilled = FALSE, MICAdd = 0;
if (pMds->TxPause)
return;
if (!hal_driver_init_OK(pHwData))
return;
//Only one thread can be run here
if (!OS_ATOMIC_INC( Adapter, &pMds->TxThreadCount) == 1)
goto cleanup;
// Start to fill the data
do {
FillIndex = pMds->TxFillIndex;
if (pMds->TxOwner[FillIndex]) { // Is owned by software 0:Yes 1:No
#ifdef _PE_TX_DUMP_
WBDEBUG(("[Mds_Tx] Tx Owner is H/W.\n"));
#endif
break;
}
XmitBufAddress = pMds->pTxBuffer + (MAX_USB_TX_BUFFER * FillIndex); //Get buffer
XmitBufSize = 0;
FillCount = 0;
do {
PacketSize = Adapter->sMlmeFrame.len;
if (!PacketSize)
break;
//For Check the buffer resource
FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
//931130.5.b
FragmentCount = PacketSize/FragmentThreshold + 1;
stmp = PacketSize + FragmentCount*32 + 8;//931130.5.c 8:MIC
if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER) {
printk("[Mds_Tx] Excess max tx buffer.\n");
break; // buffer is not enough
}
//
// Start transmitting
//
BufferFilled = TRUE;
/* Leaves first u8 intact */
memset((PUCHAR)pTxDes + 1, 0, sizeof(DESCRIPTOR) - 1);
TxDesIndex = pMds->TxDesIndex;//Get the current ID
pTxDes->Descriptor_ID = TxDesIndex;
pMds->TxDesFrom[ TxDesIndex ] = 2;//Storing the information of source comming from
pMds->TxDesIndex++;
pMds->TxDesIndex %= MAX_USB_TX_DESCRIPTOR;
MLME_GetNextPacket( Adapter, pTxDes );
// Copy header. 8byte USB + 24byte 802.11Hdr. Set TxRate, Preamble type
Mds_HeaderCopy( Adapter, pTxDes, XmitBufAddress );
// For speed up Key setting
if (pTxDes->EapFix) {
#ifdef _PE_TX_DUMP_
WBDEBUG(("35: EPA 4th frame detected. Size = %d\n", PacketSize));
#endif
pHwData->IsKeyPreSet = 1;
}
// Copy (fragment) frame body, and set USB, 802.11 hdr flag
CurrentSize = Mds_BodyCopy(Adapter, pTxDes, XmitBufAddress);
// Set RTS/CTS and Normal duration field into buffer
Mds_DurationSet(Adapter, pTxDes, XmitBufAddress);
//
// Calculation MIC from buffer which maybe fragment, then fill into temporary address 8 byte
// 931130.5.e
if (MICAdd)
Mds_MicFill( Adapter, pTxDes, XmitBufAddress );
//Shift to the next address
XmitBufSize += CurrentSize;
XmitBufAddress += CurrentSize;
#ifdef _IBSS_BEACON_SEQ_STICK_
if ((XmitBufAddress[ DOT_11_DA_OFFSET+8 ] & 0xfc) != MAC_SUBTYPE_MNGMNT_PROBE_REQUEST) // +8 for USB hdr
#endif
pMds->TxToggle = TRUE;
// Get packet to transmit completed, 1:TESTSTA 2:MLME 3: Ndis data
MLME_SendComplete(Adapter, 0, TRUE);
// Software TSC count 20060214
pMds->TxTsc++;
if (pMds->TxTsc == 0)
pMds->TxTsc_2++;
FillCount++; // 20060928
} while (HAL_USB_MODE_BURST(pHwData)); // End of multiple MSDU copy loop. FALSE = single TRUE = multiple sending
// Move to the next one, if necessary
if (BufferFilled) {
// size setting
pMds->TxBufferSize[ FillIndex ] = XmitBufSize;
// 20060928 set Tx count
pMds->TxCountInBuffer[FillIndex] = FillCount;
// Set owner flag
pMds->TxOwner[FillIndex] = 1;
pMds->TxFillIndex++;
pMds->TxFillIndex %= MAX_USB_TX_BUFFER_NUMBER;
BufferFilled = FALSE;
} else
break;
if (!PacketSize) // No more pk for transmitting
break;
} while(TRUE);
//
// Start to send by lower module
//
if (!pHwData->IsKeyPreSet)
Wb35Tx_start(pHwData);
cleanup:
OS_ATOMIC_DEC( Adapter, &pMds->TxThreadCount );
}
void
Mds_SendComplete(PADAPTER Adapter, PT02_DESCRIPTOR pT02)
{
PMDS pMds = &Adapter->Mds;
phw_data_t pHwData = &Adapter->sHwData;
u8 PacketId = (u8)pT02->T02_Tx_PktID;
unsigned char SendOK = TRUE;
u8 RetryCount, TxRate;
if (pT02->T02_IgnoreResult) // Don't care the result
return;
if (pT02->T02_IsLastMpdu) {
//TODO: DTO -- get the retry count and fragment count
// Tx rate
TxRate = pMds->TxRate[ PacketId ][ 0 ];
RetryCount = (u8)pT02->T02_MPDU_Cnt;
if (pT02->value & FLAG_ERROR_TX_MASK) {
SendOK = FALSE;
if (pT02->T02_transmit_abort || pT02->T02_out_of_MaxTxMSDULiftTime) {
//retry error
pHwData->dto_tx_retry_count += (RetryCount+1);
//[for tx debug]
if (RetryCount<7)
pHwData->tx_retry_count[RetryCount] += RetryCount;
else
pHwData->tx_retry_count[7] += RetryCount;
#ifdef _PE_STATE_DUMP_
WBDEBUG(("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count));
#endif
MTO_SetTxCount(Adapter, TxRate, RetryCount);
}
pHwData->dto_tx_frag_count += (RetryCount+1);
//[for tx debug]
if (pT02->T02_transmit_abort_due_to_TBTT)
pHwData->tx_TBTT_start_count++;
if (pT02->T02_transmit_without_encryption_due_to_wep_on_false)
pHwData->tx_WepOn_false_count++;
if (pT02->T02_discard_due_to_null_wep_key)
pHwData->tx_Null_key_count++;
} else {
if (pT02->T02_effective_transmission_rate)
pHwData->tx_ETR_count++;
MTO_SetTxCount(Adapter, TxRate, RetryCount);
}
// Clear send result buffer
pMds->TxResult[ PacketId ] = 0;
} else
pMds->TxResult[ PacketId ] |= ((u16)(pT02->value & 0x0ffff));
}
void
Mds_HeaderCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
{
PMDS pMds = &Adapter->Mds;
PUCHAR src_buffer = pDes->buffer_address[0];//931130.5.g
PT00_DESCRIPTOR pT00;
PT01_DESCRIPTOR pT01;
u16 stmp;
u8 i, ctmp1, ctmp2, ctmpf;
u16 FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
stmp = pDes->buffer_total_size;
//
// Set USB header 8 byte
//
pT00 = (PT00_DESCRIPTOR)TargetBuffer;
TargetBuffer += 4;
pT01 = (PT01_DESCRIPTOR)TargetBuffer;
TargetBuffer += 4;
pT00->value = 0;// Clear
pT01->value = 0;// Clear
pT00->T00_tx_packet_id = pDes->Descriptor_ID;// Set packet ID
pT00->T00_header_length = 24;// Set header length
pT01->T01_retry_abort_ebable = 1;//921013 931130.5.h
// Key ID setup
pT01->T01_wep_id = 0;
FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; //Do not fragment
// Copy full data, the 1'st buffer contain all the data 931130.5.j
memcpy( TargetBuffer, src_buffer, DOT_11_MAC_HEADER_SIZE );// Copy header
pDes->buffer_address[0] = src_buffer + DOT_11_MAC_HEADER_SIZE;
pDes->buffer_total_size -= DOT_11_MAC_HEADER_SIZE;
pDes->buffer_size[0] = pDes->buffer_total_size;
// Set fragment threshold
FragmentThreshold -= (DOT_11_MAC_HEADER_SIZE + 4);
pDes->FragmentThreshold = FragmentThreshold;
// Set more frag bit
TargetBuffer[1] |= 0x04;// Set more frag bit
//
// Set tx rate
//
stmp = *(PUSHORT)(TargetBuffer+30); // 2n alignment address
//Use basic rate
ctmp1 = ctmpf = CURRENT_TX_RATE_FOR_MNG;
pDes->TxRate = ctmp1;
#ifdef _PE_TX_DUMP_
WBDEBUG(("Tx rate =%x\n", ctmp1));
#endif
pT01->T01_modulation_type = (ctmp1%3) ? 0 : 1;
for( i=0; i<2; i++ ) {
if( i == 1 )
ctmp1 = ctmpf;
pMds->TxRate[pDes->Descriptor_ID][i] = ctmp1; // backup the ta rate and fall back rate
if( ctmp1 == 108) ctmp2 = 7;
else if( ctmp1 == 96 ) ctmp2 = 6; // Rate convert for USB
else if( ctmp1 == 72 ) ctmp2 = 5;
else if( ctmp1 == 48 ) ctmp2 = 4;
else if( ctmp1 == 36 ) ctmp2 = 3;
else if( ctmp1 == 24 ) ctmp2 = 2;
else if( ctmp1 == 18 ) ctmp2 = 1;
else if( ctmp1 == 12 ) ctmp2 = 0;
else if( ctmp1 == 22 ) ctmp2 = 3;
else if( ctmp1 == 11 ) ctmp2 = 2;
else if( ctmp1 == 4 ) ctmp2 = 1;
else ctmp2 = 0; // if( ctmp1 == 2 ) or default
if( i == 0 )
pT01->T01_transmit_rate = ctmp2;
else
pT01->T01_fall_back_rate = ctmp2;
}
//
// Set preamble type
//
if ((pT01->T01_modulation_type == 0) && (pT01->T01_transmit_rate == 0)) // RATE_1M
pDes->PreambleMode = WLAN_PREAMBLE_TYPE_LONG;
else
pDes->PreambleMode = CURRENT_PREAMBLE_MODE;
pT01->T01_plcp_header_length = pDes->PreambleMode; // Set preamble
}
// The function return the 4n size of usb pk
u16
Mds_BodyCopy(PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer)
{
PT00_DESCRIPTOR pT00;
PMDS pMds = &Adapter->Mds;
PUCHAR buffer, src_buffer, pctmp;
u16 Size = 0;
u16 SizeLeft, CopySize, CopyLeft, stmp;
u8 buf_index, FragmentCount = 0;
// Copy fragment body
buffer = TargetBuffer; // shift 8B usb + 24B 802.11
SizeLeft = pDes->buffer_total_size;
buf_index = pDes->buffer_start_index;
pT00 = (PT00_DESCRIPTOR)buffer;
while (SizeLeft) {
pT00 = (PT00_DESCRIPTOR)buffer;
CopySize = SizeLeft;
if (SizeLeft > pDes->FragmentThreshold) {
CopySize = pDes->FragmentThreshold;
pT00->T00_frame_length = 24 + CopySize;//Set USB length
} else
pT00->T00_frame_length = 24 + SizeLeft;//Set USB length
SizeLeft -= CopySize;
// 1 Byte operation
pctmp = (PUCHAR)( buffer + 8 + DOT_11_SEQUENCE_OFFSET );
*pctmp &= 0xf0;
*pctmp |= FragmentCount;//931130.5.m
if( !FragmentCount )
pT00->T00_first_mpdu = 1;
buffer += 32; // 8B usb + 24B 802.11 header
Size += 32;
// Copy into buffer
stmp = CopySize + 3;
stmp &= ~0x03;//4n Alignment
Size += stmp;// Current 4n offset of mpdu
while (CopySize) {
// Copy body
src_buffer = pDes->buffer_address[buf_index];
CopyLeft = CopySize;
if (CopySize >= pDes->buffer_size[buf_index]) {
CopyLeft = pDes->buffer_size[buf_index];
// Get the next buffer of descriptor
buf_index++;
buf_index %= MAX_DESCRIPTOR_BUFFER_INDEX;
} else {
PUCHAR pctmp = pDes->buffer_address[buf_index];
pctmp += CopySize;
pDes->buffer_address[buf_index] = pctmp;
pDes->buffer_size[buf_index] -= CopySize;
}
memcpy(buffer, src_buffer, CopyLeft);
buffer += CopyLeft;
CopySize -= CopyLeft;
}
// 931130.5.n
if (pMds->MicAdd) {
if (!SizeLeft) {
pMds->MicWriteAddress[ pMds->MicWriteIndex ] = buffer - pMds->MicAdd;
pMds->MicWriteSize[ pMds->MicWriteIndex ] = pMds->MicAdd;
pMds->MicAdd = 0;
}
else if( SizeLeft < 8 ) //931130.5.p
{
pMds->MicAdd = SizeLeft;
pMds->MicWriteAddress[ pMds->MicWriteIndex ] = buffer - ( 8 - SizeLeft );
pMds->MicWriteSize[ pMds->MicWriteIndex ] = 8 - SizeLeft;
pMds->MicWriteIndex++;
}
}
// Does it need to generate the new header for next mpdu?
if (SizeLeft) {
buffer = TargetBuffer + Size; // Get the next 4n start address
memcpy( buffer, TargetBuffer, 32 );//Copy 8B USB +24B 802.11
pT00 = (PT00_DESCRIPTOR)buffer;
pT00->T00_first_mpdu = 0;
}
FragmentCount++;
}
pT00->T00_last_mpdu = 1;
pT00->T00_IsLastMpdu = 1;
buffer = (PUCHAR)pT00 + 8; // +8 for USB hdr
buffer[1] &= ~0x04; // Clear more frag bit of 802.11 frame control
pDes->FragmentCount = FragmentCount; // Update the correct fragment number
return Size;
}
void
Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR buffer )
{
PT00_DESCRIPTOR pT00;
PT01_DESCRIPTOR pT01;
u16 Duration, NextBodyLen, OffsetSize;
u8 Rate, i;
unsigned char CTS_on = FALSE, RTS_on = FALSE;
PT00_DESCRIPTOR pNextT00;
u16 BodyLen;
unsigned char boGroupAddr = FALSE;
OffsetSize = pDes->FragmentThreshold + 32 + 3;
OffsetSize &= ~0x03;
Rate = pDes->TxRate >> 1;
if (!Rate)
Rate = 1;
pT00 = (PT00_DESCRIPTOR)buffer;
pT01 = (PT01_DESCRIPTOR)(buffer+4);
pNextT00 = (PT00_DESCRIPTOR)(buffer+OffsetSize);
if( buffer[ DOT_11_DA_OFFSET+8 ] & 0x1 ) // +8 for USB hdr
boGroupAddr = TRUE;
//========================================
// Set RTS/CTS mechanism
//========================================
if (!boGroupAddr)
{
//NOTE : If the protection mode is enabled and the MSDU will be fragmented,
// the tx rates of MPDUs will all be DSSS rates. So it will not use
// CTS-to-self in this case. CTS-To-self will only be used when without
// fragmentation. -- 20050112
BodyLen = (u16)pT00->T00_frame_length; //include 802.11 header
BodyLen += 4; //CRC
if( BodyLen >= CURRENT_RTS_THRESHOLD )
RTS_on = TRUE; // Using RTS
else
{
if( pT01->T01_modulation_type ) // Is using OFDM
{
if( CURRENT_PROTECT_MECHANISM ) // Is using protect
CTS_on = TRUE; // Using CTS
}
}
}
if( RTS_on || CTS_on )
{
if( pT01->T01_modulation_type) // Is using OFDM
{
//CTS duration
// 2 SIFS + DATA transmit time + 1 ACK
// ACK Rate : 24 Mega bps
// ACK frame length = 14 bytes
Duration = 2*DEFAULT_SIFSTIME +
2*PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
((BodyLen*8 + 22 + Rate*4 - 1)/(Rate*4))*Tsym +
((112 + 22 + 95)/96)*Tsym;
}
else //DSSS
{
//CTS duration
// 2 SIFS + DATA transmit time + 1 ACK
// Rate : ?? Mega bps
// ACK frame length = 14 bytes
if( pT01->T01_plcp_header_length ) //long preamble
Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
else
Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
Duration += ( ((BodyLen + 14)*8 + Rate-1) / Rate +
DEFAULT_SIFSTIME*2 );
}
if( RTS_on )
{
if( pT01->T01_modulation_type ) // Is using OFDM
{
//CTS + 1 SIFS + CTS duration
//CTS Rate : 24 Mega bps
//CTS frame length = 14 bytes
Duration += (DEFAULT_SIFSTIME +
PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
((112 + 22 + 95)/96)*Tsym);
}
else
{
//CTS + 1 SIFS + CTS duration
//CTS Rate : ?? Mega bps
//CTS frame length = 14 bytes
if( pT01->T01_plcp_header_length ) //long preamble
Duration += LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
else
Duration += SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
Duration += ( ((112 + Rate-1) / Rate) + DEFAULT_SIFSTIME );
}
}
// Set the value into USB descriptor
pT01->T01_add_rts = RTS_on ? 1 : 0;
pT01->T01_add_cts = CTS_on ? 1 : 0;
pT01->T01_rts_cts_duration = Duration;
}
//=====================================
// Fill the more fragment descriptor
//=====================================
if( boGroupAddr )
Duration = 0;
else
{
for( i=pDes->FragmentCount-1; i>0; i-- )
{
NextBodyLen = (u16)pNextT00->T00_frame_length;
NextBodyLen += 4; //CRC
if( pT01->T01_modulation_type )
{
//OFDM
// data transmit time + 3 SIFS + 2 ACK
// Rate : ??Mega bps
// ACK frame length = 14 bytes, tx rate = 24M
Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION * 3;
Duration += (((NextBodyLen*8 + 22 + Rate*4 - 1)/(Rate*4)) * Tsym +
(((2*14)*8 + 22 + 95)/96)*Tsym +
DEFAULT_SIFSTIME*3);
}
else
{
//DSSS
// data transmit time + 2 ACK + 3 SIFS
// Rate : ??Mega bps
// ACK frame length = 14 bytes
//TODO :
if( pT01->T01_plcp_header_length ) //long preamble
Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
else
Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
Duration += ( ((NextBodyLen + (2*14))*8 + Rate-1) / Rate +
DEFAULT_SIFSTIME*3 );
}
((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
//----20061009 add by anson's endian
pNextT00->value = cpu_to_le32(pNextT00->value);
pT01->value = cpu_to_le32( pT01->value );
//----end 20061009 add by anson's endian
buffer += OffsetSize;
pT01 = (PT01_DESCRIPTOR)(buffer+4);
if (i != 1) //The last fragment will not have the next fragment
pNextT00 = (PT00_DESCRIPTOR)(buffer+OffsetSize);
}
//=====================================
// Fill the last fragment descriptor
//=====================================
if( pT01->T01_modulation_type )
{
//OFDM
// 1 SIFS + 1 ACK
// Rate : 24 Mega bps
// ACK frame length = 14 bytes
Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION;
//The Tx rate of ACK use 24M
Duration += (((112 + 22 + 95)/96)*Tsym + DEFAULT_SIFSTIME );
}
else
{
// DSSS
// 1 ACK + 1 SIFS
// Rate : ?? Mega bps
// ACK frame length = 14 bytes(112 bits)
if( pT01->T01_plcp_header_length ) //long preamble
Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
else
Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
Duration += ( (112 + Rate-1)/Rate + DEFAULT_SIFSTIME );
}
}
((PUSHORT)buffer)[5] = cpu_to_le16(Duration);// 4 USHOR for skip 8B USB, 2USHORT=FC + Duration
pT00->value = cpu_to_le32(pT00->value);
pT01->value = cpu_to_le32(pT01->value);
//--end 20061009 add
}
void MDS_EthernetPacketReceive( PADAPTER Adapter, PRXLAYER1 pRxLayer1 )
{
OS_RECEIVE_PACKET_INDICATE( Adapter, pRxLayer1 );
}
unsigned char Mds_initial( PADAPTER Adapter );
void Mds_Destroy( PADAPTER Adapter );
void Mds_Tx( PADAPTER Adapter );
void Mds_HeaderCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
u16 Mds_BodyCopy( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
void Mds_DurationSet( PADAPTER Adapter, PDESCRIPTOR pDes, PUCHAR TargetBuffer );
void Mds_SendComplete( PADAPTER Adapter, PT02_DESCRIPTOR pT02 );
void Mds_MpduProcess( PADAPTER Adapter, PDESCRIPTOR pRxDes );
void Mds_reset_descriptor( PADAPTER Adapter );
extern void DataDmp(u8 *pdata, u32 len, u32 offset);
void vRxTimerInit(PWB32_ADAPTER Adapter);
void vRxTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
void RxTimerHandler_1a( PADAPTER Adapter);
void vRxTimerStop(PWB32_ADAPTER Adapter);
void RxTimerHandler( void* SystemSpecific1,
PWB32_ADAPTER Adapter,
void* SystemSpecific2,
void* SystemSpecific3);
// For Asynchronous indicating. The routine collocates with USB.
void Mds_MsduProcess( PWB32_ADAPTER Adapter, PRXLAYER1 pRxLayer1, u8 SlotIndex);
// For data frame sending 20060802
u16 MDS_GetPacketSize( PADAPTER Adapter );
void MDS_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
void MDS_GetNextPacketComplete( PADAPTER Adapter, PDESCRIPTOR pDes );
void MDS_SendResult( PADAPTER Adapter, u8 PacketId, unsigned char SendOK );
void MDS_EthernetPacketReceive( PADAPTER Adapter, PRXLAYER1 pRxLayer1 );
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define MAX_USB_TX_DESCRIPTOR 15 // IS89C35 ability
#define MAX_USB_TX_BUFFER_NUMBER 4 // Virtual pre-buffer number of MAX_USB_TX_BUFFER
#define MAX_USB_TX_BUFFER 4096 // IS89C35 ability 4n alignment is required for hardware
#define MDS_EVENT_INDICATE( _A, _B, _F ) OS_EVENT_INDICATE( _A, _B, _F )
#define AUTH_REQUEST_PAIRWISE_ERROR 0 // _F flag setting
#define AUTH_REQUEST_GROUP_ERROR 1 // _F flag setting
// For variable setting
#define CURRENT_BSS_TYPE psBSS(psLOCAL->wConnectedSTAindex)->bBssType
#define CURRENT_WEP_MODE psSME->_dot11PrivacyInvoked
#define CURRENT_BSSID psBSS(psLOCAL->wConnectedSTAindex)->abBssID
#define CURRENT_DESIRED_WPA_ENABLE ((psSME->bDesiredAuthMode==WPA_AUTH)||(psSME->bDesiredAuthMode==WPAPSK_AUTH))
#ifdef _WPA2_
#define CURRENT_DESIRED_WPA2_ENABLE ((psSME->bDesiredAuthMode==WPA2_AUTH)||(psSME->bDesiredAuthMode==WPA2PSK_AUTH))
#endif //end def _WPA2_
#define CURRENT_PAIRWISE_KEY_OK psSME->pairwise_key_ok
//[20040712 WS]
#define CURRENT_GROUP_KEY_OK psSME->group_key_ok
#define CURRENT_PAIRWISE_KEY psSME->tx_mic_key
#define CURRENT_GROUP_KEY psSME->group_tx_mic_key
#define CURRENT_ENCRYPT_STATUS psSME->encrypt_status
#define CURRENT_WEP_ID Adapter->sSmePara._dot11WEPDefaultKeyID
#define CURRENT_CONTROL_PORT_BLOCK ( psSME->wpa_ok!=1 || (Adapter->Mds.boCounterMeasureBlock==1 && (CURRENT_ENCRYPT_STATUS==ENCRYPT_TKIP)) )
#define CURRENT_FRAGMENT_THRESHOLD (Adapter->Mds.TxFragmentThreshold & ~0x1)
#define CURRENT_PREAMBLE_MODE psLOCAL->boShortPreamble?WLAN_PREAMBLE_TYPE_SHORT:WLAN_PREAMBLE_TYPE_LONG
#define CURRENT_LINK_ON OS_LINK_STATUS
#define CURRENT_TX_RATE Adapter->sLocalPara.CurrentTxRate
#define CURRENT_FALL_BACK_TX_RATE Adapter->sLocalPara.CurrentTxFallbackRate
#define CURRENT_TX_RATE_FOR_MNG Adapter->sLocalPara.CurrentTxRateForMng
#define CURRENT_PROTECT_MECHANISM psLOCAL->boProtectMechanism
#define CURRENT_RTS_THRESHOLD Adapter->Mds.TxRTSThreshold
#define MIB_GS_XMIT_OK_INC Adapter->sLocalPara.GS_XMIT_OK++
#define MIB_GS_RCV_OK_INC Adapter->sLocalPara.GS_RCV_OK++
#define MIB_GS_XMIT_ERROR_INC Adapter->sLocalPara.GS_XMIT_ERROR
//---------- TX -----------------------------------
#define ETHERNET_TX_DESCRIPTORS MAX_USB_TX_BUFFER_NUMBER
//---------- RX ------------------------------------
#define ETHERNET_RX_DESCRIPTORS 8 //It's not necessary to allocate more than 2 in sync indicate
//================================================================
// Configration default value
//================================================================
#define DEFAULT_MULTICASTLISTMAX 32 // standard
#define DEFAULT_TX_BURSTLENGTH 3 // 32 Longwords
#define DEFAULT_RX_BURSTLENGTH 3 // 32 Longwords
#define DEFAULT_TX_THRESHOLD 0 // Full Packet
#define DEFAULT_RX_THRESHOLD 0 // Full Packet
#define DEFAULT_MAXTXRATE 6 // 11 Mbps (Long)
#define DEFAULT_CHANNEL 3 // Chennel 3
#define DEFAULT_RTSThreshold 2347 // Disable RTS
//#define DEFAULT_PME 1 // Enable
#define DEFAULT_PME 0 // Disable
#define DEFAULT_SIFSTIME 10
#define DEFAULT_ACKTIME_1ML 304 // 148+44+112 911220 by LCC
#define DEFAULT_ACKTIME_2ML 248 // 148+44+56 911220 by LCC
#define DEFAULT_FRAGMENT_THRESHOLD 2346 // No fragment
#define DEFAULT_PREAMBLE_LENGTH 72
#define DEFAULT_PLCPHEADERTIME_LENGTH 24
/*------------------------------------------------------------------------
0.96 sec since time unit of the R03 for the current, W89C32 is about 60ns
instead of 960 ns. This shall be fixed in the future W89C32
-------------------------------------------------------------------------*/
#define DEFAULT_MAX_RECEIVE_TIME 16440000
#define RX_BUF_SIZE 2352 // 600 // For 301 must be multiple of 8
#define MAX_RX_DESCRIPTORS 18 // Rx Layer 2
#define MAX_BUFFER_QUEUE 8 // The value is always equal 8 due to NDIS_PACKET's MiniportReserved field size
// For brand-new rx system
#define MDS_ID_IGNORE ETHERNET_RX_DESCRIPTORS
// For Tx Packet status classify
#define PACKET_FREE_TO_USE 0
#define PACKET_COME_FROM_NDIS 0x08
#define PACKET_COME_FROM_MLME 0x80
#define PACKET_SEND_COMPLETE 0xff
typedef struct _MDS
{
// For Tx usage
u8 TxOwner[ ((MAX_USB_TX_BUFFER_NUMBER + 3) & ~0x03) ];
PUCHAR pTxBuffer;
u16 TxBufferSize[ ((MAX_USB_TX_BUFFER_NUMBER + 1) & ~0x01) ];
u8 TxDesFrom[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ];//931130.4.u // 1: MLME 2: NDIS control 3: NDIS data
u8 TxCountInBuffer[ ((MAX_USB_TX_DESCRIPTOR + 3) & ~0x03) ]; // 20060928
u8 TxFillIndex;//the next index of TxBuffer can be used
u8 TxDesIndex;//The next index of TxDes can be used
u8 ScanTxPause; //data Tx pause because the scanning is progressing, but probe request Tx won't.
u8 TxPause;//For pause the Mds_Tx modult
OS_ATOMIC TxThreadCount;//For thread counting 931130.4.v
//950301 delete due to HW
// OS_ATOMIC TxConcurrentCount;//931130.4.w
u16 TxResult[ ((MAX_USB_TX_DESCRIPTOR + 1) & ~0x01) ];//Collect the sending result of Mpdu
u8 MicRedundant[8]; // For tmp use
PUCHAR MicWriteAddress[2]; //The start address to fill the Mic, use 2 point due to Mic maybe fragment
u16 MicWriteSize[2]; //931130.4.x
u16 MicAdd; // If want to add the Mic, this variable equal to 8
u16 MicWriteIndex;//The number of MicWriteAddress 931130.4.y
u8 TxRate[ ((MAX_USB_TX_DESCRIPTOR+1)&~0x01) ][2]; // [0] current tx rate, [1] fall back rate
u8 TxInfo[ ((MAX_USB_TX_DESCRIPTOR+1)&~0x01) ]; //Store information for callback function
//WKCHEN added for scanning mechanism
u8 TxToggle; //It is TRUE if there are tx activities in some time interval
u8 Reserved_[3];
//---------- for Tx Parameter
u16 TxFragmentThreshold; // For frame body only
u16 TxRTSThreshold;
u32 MaxReceiveTime;//911220.3 Add
// depend on OS,
u32 MulticastListNo;
u32 PacketFilter; // Setting by NDIS, the current packet filter in use.
u8 MulticastAddressesArray[DEFAULT_MULTICASTLISTMAX][MAC_ADDR_LENGTH];
//COUNTERMEASURE
u8 bMICfailCount;
u8 boCounterMeasureBlock;
u8 reserved_4[2];
//NDIS_MINIPORT_TIMER nTimer;
OS_TIMER nTimer;
u32 TxTsc; // 20060214
u32 TxTsc_2; // 20060214
} MDS, *PMDS;
typedef struct _RxBuffer
{
PUCHAR pBufferAddress; // Pointer the received data buffer.
u16 BufferSize;
u8 RESERVED;
u8 BufferIndex;// Only 1 byte
} RXBUFFER, *PRXBUFFER;
//
// Reveive Layer 1 Format.
//----------------------------
typedef struct _RXLAYER1
{
u16 SequenceNumber; // The sequence number of the last received packet.
u16 BufferTotalSize;
u32 InUsed;
u32 DecryptionMethod; // The desired defragment number of the next incoming packet.
u8 DeFragmentNumber;
u8 FrameType;
u8 TypeEncapsulated;
u8 BufferNumber;
u32 FirstFrameArrivedTime;
RXBUFFER BufferQueue[ MAX_BUFFER_QUEUE ];
u8 LastFrameType; // 20061004 for fix intel 3945 's bug
u8 RESERVED[3]; //@@ anson
/////////////////////////////////////////////////////////////////////////////////////////////
// For brand-new Rx system
u8 ReservedBuffer[ 2400 ];//If Buffer ID is reserved one, it must copy the data into this area
PUCHAR ReservedBufferPoint;// Point to the next availabe address of reserved buffer
}RXLAYER1, * PRXLAYER1;
//============================================================================
// MLMEMIB.H -
//
// Description:
// Get and Set some of MLME MIB attributes.
//
// Revision history:
// --------------------------------------------------------------------------
// 20030117 PD43 Austin Liu
// Initial release
//
// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
//============================================================================
#ifndef _MLME_MIB_H
#define _MLME_MIB_H
//============================================================================
// MLMESetExcludeUnencrypted --
//
// Description:
// Set the dot11ExcludeUnencrypted value.
//
// Arguments:
// Adapter - The pointer to the miniport adapter context.
// ExUnencrypted - unsigned char type. The value to be set.
//
// Return values:
// None.
//============================================================================
#define MLMESetExcludeUnencrypted(Adapter, ExUnencrypted) \
{ \
(Adapter)->sLocalPara.ExcludeUnencrypted = ExUnencrypted; \
}
//============================================================================
// MLMEGetExcludeUnencrypted --
//
// Description:
// Get the dot11ExcludeUnencrypted value.
//
// Arguments:
// Adapter - The pointer to the miniport adapter context.
//
// Return values:
// unsigned char type. The current dot11ExcludeUnencrypted value.
//============================================================================
#define MLMEGetExcludeUnencrypted(Adapter) ((unsigned char) (Adapter)->sLocalPara.ExcludeUnencrypted)
//============================================================================
// MLMESetMaxReceiveLifeTime --
//
// Description:
// Set the dot11MaxReceiveLifeTime value.
//
// Arguments:
// Adapter - The pointer to the miniport adapter context.
// ReceiveLifeTime- u32 type. The value to be set.
//
// Return values:
// None.
//============================================================================
#define MLMESetMaxReceiveLifeTime(Adapter, ReceiveLifeTime) \
{ \
(Adapter)->Mds.MaxReceiveTime = ReceiveLifeTime; \
}
//============================================================================
// MLMESetMaxReceiveLifeTime --
//
// Description:
// Get the dot11MaxReceiveLifeTime value.
//
// Arguments:
// Adapter - The pointer to the miniport adapter context.
//
// Return values:
// u32 type. The current dot11MaxReceiveLifeTime value.
//============================================================================
#define MLMEGetMaxReceiveLifeTime(Adapter) ((u32) (Adapter)->Mds.MaxReceiveTime)
#endif
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Mlme.h
// Define the related definitions of MLME module
// history -- 01/14/03' created
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define AUTH_REJECT_REASON_CHALLENGE_FAIL 1
//====== the state of MLME module
#define INACTIVE 0x0
#define IDLE_SCAN 0x1
//====== the state of MLME/ESS module
#define STATE_1 0x2
#define AUTH_REQ 0x3
#define AUTH_WEP 0x4
#define STATE_2 0x5
#define ASSOC_REQ 0x6
#define STATE_3 0x7
//====== the state of MLME/IBSS module
#define IBSS_JOIN_SYNC 0x8
#define IBSS_AUTH_REQ 0x9
#define IBSS_AUTH_CHANLGE 0xa
#define IBSS_AUTH_WEP 0xb
#define IBSS_AUTH_IND 0xc
#define IBSS_STATE_2 0xd
//=========================================
//depend on D5C(MAC timing control 03 register): MaxTxMSDULifeTime default 0x80000us
#define AUTH_FAIL_TIMEOUT 550
#define ASSOC_FAIL_TIMEOUT 550
#define REASSOC_FAIL_TIMEOUT 550
//
// MLME task global CONSTANTS, STRUCTURE, variables
//
/////////////////////////////////////////////////////////////
// enum_ResultCode --
// Result code returned from MLME to SME.
//
/////////////////////////////////////////////////////////////
// PD43 20030829 Modifiled
//#define SUCCESS 0
#define MLME_SUCCESS 0 //follow spec.
#define INVALID_PARAMETERS 1 //Not following spec.
#define NOT_SUPPPORTED 2
#define TIMEOUT 3
#define TOO_MANY_SIMULTANEOUS_REQUESTS 4
#define REFUSED 5
#define BSS_ALREADY_STARTED_OR_JOINED 6
#define TRANSMIT_FRAME_FAIL 7
#define NO_BSS_FOUND 8
#define RETRY 9
#define GIVE_UP 10
#define OPEN_AUTH 0
#define SHARE_AUTH 1
#define ANY_AUTH 2
#define WPA_AUTH 3 //for WPA
#define WPAPSK_AUTH 4
#define WPANONE_AUTH 5
///////////////////////////////////////////// added by ws 04/19/04
#ifdef _WPA2_
#define WPA2_AUTH 6//for WPA2
#define WPA2PSK_AUTH 7
#endif //end def _WPA2_
//////////////////////////////////////////////////////////////////
//define the msg type of MLME module
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------
//from SME
#define MLMEMSG_AUTH_REQ 0x0b
#define MLMEMSG_DEAUTH_REQ 0x0c
#define MLMEMSG_ASSOC_REQ 0x0d
#define MLMEMSG_REASSOC_REQ 0x0e
#define MLMEMSG_DISASSOC_REQ 0x0f
#define MLMEMSG_START_IBSS_REQ 0x10
#define MLMEMSG_IBSS_NET_CFM 0x11
//from RX :
#define MLMEMSG_RCV_MLMEFRAME 0x20
#define MLMEMSG_RCV_ASSOCRSP 0x22
#define MLMEMSG_RCV_REASSOCRSP 0x24
#define MLMEMSG_RCV_DISASSOC 0x2b
#define MLMEMSG_RCV_AUTH 0x2c
#define MLMEMSG_RCV_DEAUTH 0x2d
//from TX callback
#define MLMEMSG_TX_CALLBACK 0x40
#define MLMEMSG_ASSOCREQ_CALLBACK 0x41
#define MLMEMSG_REASSOCREQ_CALLBACK 0x43
#define MLMEMSG_DISASSOC_CALLBACK 0x4a
#define MLMEMSG_AUTH_CALLBACK 0x4c
#define MLMEMSG_DEAUTH_CALLBACK 0x4d
//#define MLMEMSG_JOIN_FAIL 4
//#define MLMEMSG_AUTHEN_FAIL 18
#define MLMEMSG_TIMEOUT 0x50
///////////////////////////////////////////////////////////////////////////
//Global data structures
#define MAX_NUM_TX_MMPDU 2
#define MAX_MMPDU_SIZE 1512
#define MAX_NUM_RX_MMPDU 6
///////////////////////////////////////////////////////////////////////////
//MACRO
#define boMLME_InactiveState(_AA_) (_AA_->wState==INACTIVE)
#define boMLME_IdleScanState(_BB_) (_BB_->wState==IDLE_SCAN)
#define boMLME_FoundSTAinfo(_CC_) (_CC_->wState>=IDLE_SCAN)
typedef struct _MLME_FRAME
{
//NDIS_PACKET MLME_Packet;
PCHAR pMMPDU;
u16 len;
u8 DataType;
u8 IsInUsed;
OS_SPIN_LOCK MLMESpinLock;
u8 TxMMPDU[MAX_NUM_TX_MMPDU][MAX_MMPDU_SIZE];
u8 TxMMPDUInUse[ (MAX_NUM_TX_MMPDU+3) & ~0x03 ];
u16 wNumTxMMPDU;
u16 wNumTxMMPDUDiscarded;
u8 RxMMPDU[MAX_NUM_RX_MMPDU][MAX_MMPDU_SIZE];
u8 SaveRxBufSlotInUse[ (MAX_NUM_RX_MMPDU+3) & ~0x03 ];
u16 wNumRxMMPDU;
u16 wNumRxMMPDUDiscarded;
u16 wNumRxMMPDUInMLME; // Number of the Rx MMPDU
u16 reserved_1; // in MLME.
// excluding the discarded
} MLME_FRAME, *psMLME_FRAME;
typedef struct _AUTHREQ {
u8 peerMACaddr[MAC_ADDR_LENGTH];
u16 wAuthAlgorithm;
} MLME_AUTHREQ_PARA, *psMLME_AUTHREQ_PARA;
struct _Reason_Code {
u8 peerMACaddr[MAC_ADDR_LENGTH];
u16 wReasonCode;
};
typedef struct _Reason_Code MLME_DEAUTHREQ_PARA, *psMLME_DEAUTHREQ_PARA;
typedef struct _Reason_Code MLME_DISASSOCREQ_PARA, *psMLME_DISASSOCREQ_PARA;
typedef struct _ASSOCREQ {
u8 PeerSTAAddr[MAC_ADDR_LENGTH];
u16 CapabilityInfo;
u16 ListenInterval;
}__attribute__ ((packed)) MLME_ASSOCREQ_PARA, *psMLME_ASSOCREQ_PARA;
typedef struct _REASSOCREQ {
u8 NewAPAddr[MAC_ADDR_LENGTH];
u16 CapabilityInfo;
u16 ListenInterval;
}__attribute__ ((packed)) MLME_REASSOCREQ_PARA, *psMLME_REASSOCREQ_PARA;
typedef struct _MLMECALLBACK {
u8 *psFramePtr;
u8 bResult;
} MLME_TXCALLBACK, *psMLME_TXCALLBACK;
typedef struct _RXDATA
{
s32 FrameLength;
u8 __attribute__ ((packed)) *pbFramePtr;
}__attribute__ ((packed)) RXDATA, *psRXDATA;
//============================================================================
// Module Name:
// MLMETxRx.C
//
// Description:
// The interface between MDS (MAC Data Service) and MLME.
//
// Revision History:
// --------------------------------------------------------------------------
// 200209 UN20 Jennifer Xu
// Initial Release
// 20021108 PD43 Austin Liu
// 20030117 PD43 Austin Liu
// Deleted MLMEReturnPacket and MLMEProcThread()
//
// Copyright (c) 1996-2002 Winbond Electronics Corp. All Rights Reserved.
//============================================================================
#include "os_common.h"
void MLMEResetTxRx(PWB32_ADAPTER Adapter)
{
s32 i;
// Reset the interface between MDS and MLME
for (i = 0; i < MAX_NUM_TX_MMPDU; i++)
Adapter->sMlmeFrame.TxMMPDUInUse[i] = FALSE;
for (i = 0; i < MAX_NUM_RX_MMPDU; i++)
Adapter->sMlmeFrame.SaveRxBufSlotInUse[i] = FALSE;
Adapter->sMlmeFrame.wNumRxMMPDUInMLME = 0;
Adapter->sMlmeFrame.wNumRxMMPDUDiscarded = 0;
Adapter->sMlmeFrame.wNumRxMMPDU = 0;
Adapter->sMlmeFrame.wNumTxMMPDUDiscarded = 0;
Adapter->sMlmeFrame.wNumTxMMPDU = 0;
Adapter->sLocalPara.boCCAbusy = FALSE;
Adapter->sLocalPara.iPowerSaveMode = PWR_ACTIVE; // Power active
}
//=============================================================================
// Function:
// MLMEGetMMPDUBuffer()
//
// Description:
// Return the pointer to an available data buffer with
// the size MAX_MMPDU_SIZE for a MMPDU.
//
// Arguments:
// Adapter - pointer to the miniport adapter context.
//
// Return value:
// NULL : No available data buffer available
// Otherwise: Pointer to the data buffer
//=============================================================================
/* FIXME: Should this just be replaced with kmalloc() and kfree()? */
u8 *MLMEGetMMPDUBuffer(PWB32_ADAPTER Adapter)
{
s32 i;
u8 *returnVal;
for (i = 0; i< MAX_NUM_TX_MMPDU; i++) {
if (Adapter->sMlmeFrame.TxMMPDUInUse[i] == FALSE)
break;
}
if (i >= MAX_NUM_TX_MMPDU) return NULL;
returnVal = (u8 *)&(Adapter->sMlmeFrame.TxMMPDU[i]);
Adapter->sMlmeFrame.TxMMPDUInUse[i] = TRUE;
return returnVal;
}
//=============================================================================
u8 MLMESendFrame(PWB32_ADAPTER Adapter, u8 *pMMPDU, u16 len, u8 DataType)
/* DataType : FRAME_TYPE_802_11_MANAGEMENT, FRAME_TYPE_802_11_MANAGEMENT_CHALLENGE,
FRAME_TYPE_802_11_DATA */
{
if (Adapter->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
Adapter->sMlmeFrame.wNumTxMMPDUDiscarded++;
return FALSE;
}
Adapter->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
// Keep information for sending
Adapter->sMlmeFrame.pMMPDU = pMMPDU;
Adapter->sMlmeFrame.DataType = DataType;
// len must be the last setting due to QUERY_SIZE_SECOND of Mds
Adapter->sMlmeFrame.len = len;
Adapter->sMlmeFrame.wNumTxMMPDU++;
// H/W will enter power save by set the register. S/W don't send null frame
//with PWRMgt bit enbled to enter power save now.
// Transmit NDIS packet
Mds_Tx(Adapter);
return TRUE;
}
void
MLME_GetNextPacket(PADAPTER Adapter, PDESCRIPTOR pDes)
{
#define DESCRIPTOR_ADD_BUFFER( _D, _A, _S ) \
{\
_D->InternalUsed = _D->buffer_start_index + _D->buffer_number; \
_D->InternalUsed %= MAX_DESCRIPTOR_BUFFER_INDEX; \
_D->buffer_address[ _D->InternalUsed ] = _A; \
_D->buffer_size[ _D->InternalUsed ] = _S; \
_D->buffer_total_size += _S; \
_D->buffer_number++;\
}
DESCRIPTOR_ADD_BUFFER( pDes, Adapter->sMlmeFrame.pMMPDU, Adapter->sMlmeFrame.len );
pDes->Type = Adapter->sMlmeFrame.DataType;
}
void MLMEfreeMMPDUBuffer(PWB32_ADAPTER Adapter, PCHAR pData)
{
int i;
// Reclaim the data buffer
for (i = 0; i < MAX_NUM_TX_MMPDU; i++) {
if (pData == (PCHAR)&(Adapter->sMlmeFrame.TxMMPDU[i]))
break;
}
if (Adapter->sMlmeFrame.TxMMPDUInUse[i])
Adapter->sMlmeFrame.TxMMPDUInUse[i] = FALSE;
else {
// Something wrong
// PD43 Add debug code here???
}
}
void
MLME_SendComplete(PADAPTER Adapter, u8 PacketID, unsigned char SendOK)
{
MLME_TXCALLBACK TxCallback;
// Reclaim the data buffer
Adapter->sMlmeFrame.len = 0;
MLMEfreeMMPDUBuffer( Adapter, Adapter->sMlmeFrame.pMMPDU );
TxCallback.bResult = MLME_SUCCESS;
// Return resource
Adapter->sMlmeFrame.IsInUsed = PACKET_FREE_TO_USE;
}
//================================================================
// MLMETxRx.H --
//
// Functions defined in MLMETxRx.c.
//
// Copyright (c) 2002 Winbond Electrics Corp. All Rights Reserved.
//================================================================
#ifndef _MLMETXRX_H
#define _MLMETXRX_H
void
MLMEProcThread(
PWB32_ADAPTER Adapter
);
void MLMEResetTxRx( PWB32_ADAPTER Adapter);
u8 *
MLMEGetMMPDUBuffer(
PWB32_ADAPTER Adapter
);
void MLMEfreeMMPDUBuffer( PWB32_ADAPTER Adapter, PCHAR pData);
void MLME_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
u8 MLMESendFrame( PWB32_ADAPTER Adapter,
u8 *pMMPDU,
u16 len,
u8 DataType);
void
MLME_SendComplete( PWB32_ADAPTER Adapter, u8 PacketID, unsigned char SendOK );
void
MLMERcvFrame(
PWB32_ADAPTER Adapter,
PRXBUFFER pRxBufferArray,
u8 NumOfBuffer,
u8 ReturnSlotIndex
);
void
MLMEReturnPacket(
PWB32_ADAPTER Adapter,
PUCHAR pRxBufer
);
#ifdef _IBSS_BEACON_SEQ_STICK_
s8 SendBCNullData(PWB32_ADAPTER Adapter, u16 wIdx);
#endif
#endif
//============================================================================
// MTO.C -
//
// Description:
// MAC Throughput Optimization for W89C33 802.11g WLAN STA.
//
// The following MIB attributes or internal variables will be affected
// while the MTO is being executed:
// dot11FragmentationThreshold,
// dot11RTSThreshold,
// transmission rate and PLCP preamble type,
// CCA mode,
// antenna diversity.
//
// Revision history:
// --------------------------------------------------------------------------
// 20031227 UN20 Pete Chao
// First draft
// 20031229 Turbo copy from PD43
// 20040210 Kevin revised
// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
//============================================================================
// LA20040210_DTO kevin
#include "os_common.h"
// Declare SQ3 to rate and fragmentation threshold table
// Declare fragmentation thresholds table
#define MTO_MAX_SQ3_LEVELS 14
#define MTO_MAX_FRAG_TH_LEVELS 5
#define MTO_MAX_DATA_RATE_LEVELS 12
u16 MTO_Frag_Th_Tbl[MTO_MAX_FRAG_TH_LEVELS] =
{
256, 384, 512, 768, 1536
};
u8 MTO_SQ3_Level[MTO_MAX_SQ3_LEVELS] =
{
0, 26, 30, 32, 34, 35, 37, 42, 44, 46, 54, 62, 78, 81
};
u8 MTO_SQ3toRate[MTO_MAX_SQ3_LEVELS] =
{
0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
u8 MTO_SQ3toFrag[MTO_MAX_SQ3_LEVELS] =
{
0, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
// One Exchange Time table
//
u16 MTO_One_Exchange_Time_Tbl_l[MTO_MAX_FRAG_TH_LEVELS][MTO_MAX_DATA_RATE_LEVELS] =
{
{ 2554, 1474, 822, 0, 0, 636, 0, 0, 0, 0, 0, 0},
{ 3578, 1986, 1009, 0, 0, 729, 0, 0, 0, 0, 0, 0},
{ 4602, 2498, 1195, 0, 0, 822, 0, 0, 0, 0, 0, 0},
{ 6650, 3522, 1567, 0, 0, 1009, 0, 0, 0, 0, 0, 0},
{12794, 6594, 2684, 0, 0, 1567, 0, 0, 0, 0, 0, 0}
};
u16 MTO_One_Exchange_Time_Tbl_s[MTO_MAX_FRAG_TH_LEVELS][MTO_MAX_DATA_RATE_LEVELS] =
{
{ 0, 1282, 630, 404, 288, 444, 232, 172, 144, 116, 100, 96},
{ 0, 1794, 817, 572, 400, 537, 316, 228, 188, 144, 124, 116},
{ 0, 2306, 1003, 744, 516, 630, 400, 288, 228, 172, 144, 136},
{ 0, 3330, 1375, 1084, 744, 817, 572, 400, 316, 228, 188, 172},
{ 0, 6402, 2492, 2108, 1424, 1375, 1084, 740, 572, 400, 316, 284}
};
#define MTO_ONE_EXCHANGE_TIME(preamble_type, frag_th_lvl, data_rate_lvl) \
(preamble_type) ? MTO_One_Exchange_Time_Tbl_s[frag_th_lvl][data_rate_lvl] : \
MTO_One_Exchange_Time_Tbl_l[frag_th_lvl][data_rate_lvl]
// Declare data rate table
//The following table will be changed at anytime if the opration rate supported by AP don't
//match the table
u8 MTO_Data_Rate_Tbl[MTO_MAX_DATA_RATE_LEVELS] =
{
2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
};
//The Stardard_Data_Rate_Tbl and Level2PerTbl table is used to indirectly retreive PER
//information from Rate_PER_TBL
//The default settings is AP can support full rate set.
static u8 Stardard_Data_Rate_Tbl[MTO_MAX_DATA_RATE_LEVELS] =
{
2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
};
static u8 Level2PerTbl[MTO_MAX_DATA_RATE_LEVELS] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
//How many kind of tx rate can be supported by AP
//DTO will change Rate between MTO_Data_Rate_Tbl[0] and MTO_Data_Rate_Tbl[MTO_DataRateAvailableLevel-1]
static u8 MTO_DataRateAvailableLevel = MTO_MAX_DATA_RATE_LEVELS;
//Smoothed PER table for each different RATE based on packet length of 1514
static int Rate_PER_TBL[91][MTO_MAX_DATA_RATE_LEVELS] = {
// 1M 2M 5.5M 11M 6M 9M 12M 18M 24M 36M 48M 54M
/* 0% */{ 93, 177, 420, 538, 690, 774, 1001, 1401, 1768, 2358, 2838, 3039},
/* 1% */{ 92, 176, 416, 533, 683, 767, 992, 1389, 1752, 2336, 2811, 3010},
/* 2% */{ 91, 174, 412, 528, 675, 760, 983, 1376, 1735, 2313, 2783, 2979},
/* 3% */{ 90, 172, 407, 523, 667, 753, 973, 1363, 1719, 2290, 2755, 2948},
/* 4% */{ 90, 170, 403, 518, 659, 746, 964, 1350, 1701, 2266, 2726, 2916},
/* 5% */{ 89, 169, 398, 512, 651, 738, 954, 1336, 1684, 2242, 2696, 2884},
/* 6% */{ 88, 167, 394, 507, 643, 731, 944, 1322, 1666, 2217, 2665, 2851},
/* 7% */{ 87, 165, 389, 502, 635, 723, 935, 1308, 1648, 2192, 2634, 2817},
/* 8% */{ 86, 163, 384, 497, 626, 716, 924, 1294, 1629, 2166, 2602, 2782},
/* 9% */{ 85, 161, 380, 491, 618, 708, 914, 1279, 1611, 2140, 2570, 2747},
/* 10% */{ 84, 160, 375, 486, 609, 700, 904, 1265, 1591, 2113, 2537, 2711},
/* 11% */{ 83, 158, 370, 480, 600, 692, 894, 1250, 1572, 2086, 2503, 2675},
/* 12% */{ 82, 156, 365, 475, 592, 684, 883, 1234, 1552, 2059, 2469, 2638},
/* 13% */{ 81, 154, 360, 469, 583, 676, 872, 1219, 1532, 2031, 2435, 2600},
/* 14% */{ 80, 152, 355, 464, 574, 668, 862, 1204, 1512, 2003, 2400, 2562},
/* 15% */{ 79, 150, 350, 458, 565, 660, 851, 1188, 1492, 1974, 2365, 2524},
/* 16% */{ 78, 148, 345, 453, 556, 652, 840, 1172, 1471, 1945, 2329, 2485},
/* 17% */{ 77, 146, 340, 447, 547, 643, 829, 1156, 1450, 1916, 2293, 2446},
/* 18% */{ 76, 144, 335, 441, 538, 635, 818, 1140, 1429, 1887, 2256, 2406},
/* 19% */{ 75, 143, 330, 436, 529, 627, 807, 1124, 1408, 1857, 2219, 2366},
/* 20% */{ 74, 141, 325, 430, 520, 618, 795, 1107, 1386, 1827, 2182, 2326},
/* 21% */{ 73, 139, 320, 424, 510, 610, 784, 1091, 1365, 1797, 2145, 2285},
/* 22% */{ 72, 137, 314, 418, 501, 601, 772, 1074, 1343, 1766, 2107, 2244},
/* 23% */{ 71, 135, 309, 412, 492, 592, 761, 1057, 1321, 1736, 2069, 2203},
/* 24% */{ 70, 133, 304, 407, 482, 584, 749, 1040, 1299, 1705, 2031, 2161},
/* 25% */{ 69, 131, 299, 401, 473, 575, 738, 1023, 1277, 1674, 1992, 2120},
/* 26% */{ 68, 129, 293, 395, 464, 566, 726, 1006, 1254, 1642, 1953, 2078},
/* 27% */{ 67, 127, 288, 389, 454, 557, 714, 989, 1232, 1611, 1915, 2035},
/* 28% */{ 66, 125, 283, 383, 445, 549, 703, 972, 1209, 1579, 1876, 1993},
/* 29% */{ 65, 123, 278, 377, 436, 540, 691, 955, 1187, 1548, 1836, 1951},
/* 30% */{ 64, 121, 272, 371, 426, 531, 679, 937, 1164, 1516, 1797, 1908},
/* 31% */{ 63, 119, 267, 365, 417, 522, 667, 920, 1141, 1484, 1758, 1866},
/* 32% */{ 62, 117, 262, 359, 407, 513, 655, 902, 1118, 1453, 1719, 1823},
/* 33% */{ 61, 115, 256, 353, 398, 504, 643, 885, 1095, 1421, 1679, 1781},
/* 34% */{ 60, 113, 251, 347, 389, 495, 631, 867, 1072, 1389, 1640, 1738},
/* 35% */{ 59, 111, 246, 341, 379, 486, 619, 850, 1049, 1357, 1600, 1695},
/* 36% */{ 58, 108, 240, 335, 370, 477, 607, 832, 1027, 1325, 1561, 1653},
/* 37% */{ 57, 106, 235, 329, 361, 468, 595, 815, 1004, 1293, 1522, 1610},
/* 38% */{ 56, 104, 230, 323, 351, 459, 584, 797, 981, 1261, 1483, 1568},
/* 39% */{ 55, 102, 224, 317, 342, 450, 572, 780, 958, 1230, 1443, 1526},
/* 40% */{ 54, 100, 219, 311, 333, 441, 560, 762, 935, 1198, 1404, 1484},
/* 41% */{ 53, 98, 214, 305, 324, 432, 548, 744, 912, 1166, 1366, 1442},
/* 42% */{ 52, 96, 209, 299, 315, 423, 536, 727, 889, 1135, 1327, 1400},
/* 43% */{ 51, 94, 203, 293, 306, 414, 524, 709, 866, 1104, 1289, 1358},
/* 44% */{ 50, 92, 198, 287, 297, 405, 512, 692, 844, 1072, 1250, 1317},
/* 45% */{ 49, 90, 193, 281, 288, 396, 500, 675, 821, 1041, 1212, 1276},
/* 46% */{ 48, 88, 188, 275, 279, 387, 488, 657, 799, 1011, 1174, 1236},
/* 47% */{ 47, 86, 183, 269, 271, 378, 476, 640, 777, 980, 1137, 1195},
/* 48% */{ 46, 84, 178, 262, 262, 369, 464, 623, 754, 949, 1100, 1155},
/* 49% */{ 45, 82, 173, 256, 254, 360, 452, 606, 732, 919, 1063, 1116},
/* 50% */{ 44, 80, 168, 251, 245, 351, 441, 589, 710, 889, 1026, 1076},
/* 51% */{ 43, 78, 163, 245, 237, 342, 429, 572, 689, 860, 990, 1038},
/* 52% */{ 42, 76, 158, 239, 228, 333, 417, 555, 667, 830, 955, 999},
/* 53% */{ 41, 74, 153, 233, 220, 324, 406, 538, 645, 801, 919, 961},
/* 54% */{ 40, 72, 148, 227, 212, 315, 394, 522, 624, 773, 884, 924},
/* 55% */{ 39, 70, 143, 221, 204, 307, 383, 505, 603, 744, 850, 887},
/* 56% */{ 38, 68, 138, 215, 196, 298, 371, 489, 582, 716, 816, 851},
/* 57% */{ 37, 67, 134, 209, 189, 289, 360, 473, 562, 688, 783, 815},
/* 58% */{ 36, 65, 129, 203, 181, 281, 349, 457, 541, 661, 750, 780},
/* 59% */{ 35, 63, 124, 197, 174, 272, 338, 441, 521, 634, 717, 745},
/* 60% */{ 34, 61, 120, 192, 166, 264, 327, 425, 501, 608, 686, 712},
/* 61% */{ 33, 59, 115, 186, 159, 255, 316, 409, 482, 582, 655, 678},
/* 62% */{ 32, 57, 111, 180, 152, 247, 305, 394, 462, 556, 624, 646},
/* 63% */{ 31, 55, 107, 174, 145, 238, 294, 379, 443, 531, 594, 614},
/* 64% */{ 30, 53, 102, 169, 138, 230, 283, 364, 425, 506, 565, 583},
/* 65% */{ 29, 52, 98, 163, 132, 222, 273, 349, 406, 482, 536, 553},
/* 66% */{ 28, 50, 94, 158, 125, 214, 262, 334, 388, 459, 508, 523},
/* 67% */{ 27, 48, 90, 152, 119, 206, 252, 320, 370, 436, 481, 495},
/* 68% */{ 26, 46, 86, 147, 113, 198, 242, 306, 353, 413, 455, 467},
/* 69% */{ 26, 44, 82, 141, 107, 190, 231, 292, 336, 391, 429, 440},
/* 70% */{ 25, 43, 78, 136, 101, 182, 221, 278, 319, 370, 405, 414},
/* 71% */{ 24, 41, 74, 130, 95, 174, 212, 265, 303, 350, 381, 389},
/* 72% */{ 23, 39, 71, 125, 90, 167, 202, 252, 287, 329, 358, 365},
/* 73% */{ 22, 37, 67, 119, 85, 159, 192, 239, 271, 310, 335, 342},
/* 74% */{ 21, 36, 63, 114, 80, 151, 183, 226, 256, 291, 314, 320},
/* 75% */{ 20, 34, 60, 109, 75, 144, 174, 214, 241, 273, 294, 298},
/* 76% */{ 19, 32, 57, 104, 70, 137, 164, 202, 227, 256, 274, 278},
/* 77% */{ 18, 31, 53, 99, 66, 130, 155, 190, 213, 239, 256, 259},
/* 78% */{ 17, 29, 50, 94, 62, 122, 146, 178, 200, 223, 238, 241},
/* 79% */{ 16, 28, 47, 89, 58, 115, 138, 167, 187, 208, 222, 225},
/* 80% */{ 16, 26, 44, 84, 54, 109, 129, 156, 175, 194, 206, 209},
/* 81% */{ 15, 24, 41, 79, 50, 102, 121, 146, 163, 180, 192, 194},
/* 82% */{ 14, 23, 39, 74, 47, 95, 113, 136, 151, 167, 178, 181},
/* 83% */{ 13, 21, 36, 69, 44, 89, 105, 126, 140, 155, 166, 169},
/* 84% */{ 12, 20, 33, 64, 41, 82, 97, 116, 130, 144, 155, 158},
/* 85% */{ 11, 19, 31, 60, 39, 76, 89, 107, 120, 134, 145, 149},
/* 86% */{ 11, 17, 29, 55, 36, 70, 82, 98, 110, 125, 136, 140},
/* 87% */{ 10, 16, 26, 51, 34, 64, 75, 90, 102, 116, 128, 133},
/* 88% */{ 9, 14, 24, 46, 32, 58, 68, 81, 93, 108, 121, 128},
/* 89% */{ 8, 13, 22, 42, 31, 52, 61, 74, 86, 102, 116, 124},
/* 90% */{ 7, 12, 21, 37, 29, 46, 54, 66, 79, 96, 112, 121}
};
#define RSSIBUF_NUM 10
#define RSSI2RATE_SIZE 9
static TXRETRY_REC TxRateRec={MTO_MAX_DATA_RATE_LEVELS - 1, 0}; //new record=>TxRateRec
static int TxRetryRate;
//static int SQ3, BSS_PK_CNT, NIDLESLOT, SLOT_CNT, INTERF_CNT, GAP_CNT, DS_EVM;
static s32 RSSIBuf[RSSIBUF_NUM]={-70, -70, -70, -70, -70, -70, -70, -70, -70, -70};
static s32 RSSISmoothed=-700;
static int RSSIBufIndex=0;
static u8 max_rssi_rate;
static int rate_tbl[13] = {0,1,2,5,11,6,9,12,18,24,36,48,54};
//[WKCHEN]static core_data_t *pMTOcore_data=NULL;
static int TotalTxPkt = 0;
static int TotalTxPktRetry = 0;
static int TxPktPerAnt[3] = {0,0,0};
static int RXRSSIANT[3] ={-70,-70,-70};
static int TxPktRetryPerAnt[3] = {0,0,0};
//static int TxDominateFlag=FALSE;
static u8 old_antenna[4]={1 ,0 ,1 ,0};
static int retryrate_rec[MTO_MAX_DATA_RATE_LEVELS];//this record the retry rate at different data rate
static int PeriodTotalTxPkt = 0;
static int PeriodTotalTxPktRetry = 0;
typedef struct
{
s32 RSSI;
u8 TxRate;
}RSSI2RATE;
static RSSI2RATE RSSI2RateTbl[RSSI2RATE_SIZE] =
{
{-740, 108}, // 54M
{-760, 96}, // 48M
{-820, 72}, // 36M
{-850, 48}, // 24M
{-870, 36}, // 18M
{-890, 24}, // 12M
{-900, 12}, // 6M
{-920, 11}, // 5.5M
{-950, 4}, // 2M
};
static u8 untogglecount;
static u8 last_rate_ant; //this is used for antenna backoff-hh
u8 boSparseTxTraffic = FALSE;
void MTO_Init(MTO_FUNC_INPUT);
void AntennaToggleInitiator(MTO_FUNC_INPUT);
void AntennaToggleState(MTO_FUNC_INPUT);
void TxPwrControl(MTO_FUNC_INPUT);
void GetFreshAntennaData(MTO_FUNC_INPUT);
void TxRateReductionCtrl(MTO_FUNC_INPUT);
/** 1.1.31.1000 Turbo modify */
//void MTO_SetDTORateRange(int type);
void MTO_SetDTORateRange(MTO_FUNC_INPUT, u8 *pRateArray, u8 ArraySize);
void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index);
void MTO_TxFailed(MTO_FUNC_INPUT);
void SmoothRSSI(s32 new_rssi);
void hal_get_dto_para(MTO_FUNC_INPUT, char *buffer);
u8 CalcNewRate(MTO_FUNC_INPUT, u8 old_rate, u32 retry_cnt, u32 tx_frag_cnt);
u8 GetMaxRateLevelFromRSSI(void);
u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT);
int Divide(int a, int b);
void multiagc(MTO_FUNC_INPUT, u8 high_gain_mode);
//===========================================================================
// MTO_Init --
//
// Description:
// Set DTO Tx Rate Scope because different AP could have different Rate set.
// After our staion join with AP, LM core will call this function to initialize
// Tx Rate table.
//
// Arguments:
// pRateArray - The pointer to the Tx Rate Array by the following order
// - 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
// - DTO won't check whether rate order is invalid or not
// ArraySize - The array size to indicate how many tx rate we can choose
//
// sample code:
// {
// u8 RateArray[4] = {2, 4, 11, 22};
// MTO_SetDTORateRange(RateArray, 4);
// }
//
// Return Value:
// None
//============================================================================
void MTO_SetDTORateRange(MTO_FUNC_INPUT,u8 *pRateArray, u8 ArraySize)
{
u8 i, j=0;
for(i=0;i<ArraySize;i++)
{
if(pRateArray[i] == 22)
break;
}
if(i < ArraySize) //we need adjust the order of rate list because 11Mbps rate exists
{
for(;i>0;i--)
{
if(pRateArray[i-1] <= 11)
break;
pRateArray[i] = pRateArray[i-1];
}
pRateArray[i] = 22;
MTO_OFDM_RATE_LEVEL() = i;
}
else
{
for(i=0; i<ArraySize; i++)
{
if (pRateArray[i] >= 12)
break;
}
MTO_OFDM_RATE_LEVEL() = i;
}
for(i=0;i<ArraySize;i++)
{
MTO_Data_Rate_Tbl[i] = pRateArray[i];
for(;j<MTO_MAX_DATA_RATE_LEVELS;j++)
{
if(Stardard_Data_Rate_Tbl[j] == pRateArray[i])
break;
}
Level2PerTbl[i] = j;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[MTO]:Op Rate[%d]: %d\n",i, MTO_Data_Rate_Tbl[i]));
#endif
}
MTO_DataRateAvailableLevel = ArraySize;
if( MTO_DATA().RatePolicy ) // 0 means that no registry setting
{
if( MTO_DATA().RatePolicy == 1 )
TxRateRec.tx_rate = 0; //ascent
else
TxRateRec.tx_rate = MTO_DataRateAvailableLevel -1 ; //descent
}
else
{
if( MTO_INITTXRATE_MODE )
TxRateRec.tx_rate = 0; //ascent
else
TxRateRec.tx_rate = MTO_DataRateAvailableLevel -1 ; //descent
}
TxRateRec.tx_retry_rate = 0;
//set default rate for initial use
MTO_RATE_LEVEL() = TxRateRec.tx_rate;
MTO_FALLBACK_RATE_LEVEL() = MTO_RATE_LEVEL();
}
//===========================================================================
// MTO_Init --
//
// Description:
// Initialize MTO parameters.
//
// This function should be invoked during system initialization.
//
// Arguments:
// Adapter - The pointer to the Miniport Adapter Context
//
// Return Value:
// None
//============================================================================
void MTO_Init(MTO_FUNC_INPUT)
{
int i;
//WBDEBUG(("[MTO] -> MTO_Init()\n"));
//[WKCHEN]pMTOcore_data = pcore_data;
// 20040510 Turbo add for global variable
MTO_TMR_CNT() = 0;
MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
MTO_TX_RATE_REDUCTION_STATE() = RATE_CHGSTATE_IDLE;
MTO_BACKOFF_TMR() = 0;
MTO_LAST_RATE() = 11;
MTO_CO_EFFICENT() = 0;
//MTO_TH_FIXANT() = MTO_DEFAULT_TH_FIXANT;
MTO_TH_CNT() = MTO_DEFAULT_TH_CNT;
MTO_TH_SQ3() = MTO_DEFAULT_TH_SQ3;
MTO_TH_IDLE_SLOT() = MTO_DEFAULT_TH_IDLE_SLOT;
MTO_TH_PR_INTERF() = MTO_DEFAULT_TH_PR_INTERF;
MTO_TMR_AGING() = MTO_DEFAULT_TMR_AGING;
MTO_TMR_PERIODIC() = MTO_DEFAULT_TMR_PERIODIC;
//[WKCHEN]MTO_CCA_MODE_SETUP()= (u8) hal_get_cca_mode(MTO_HAL());
//[WKCHEN]MTO_CCA_MODE() = MTO_CCA_MODE_SETUP();
//MTO_PREAMBLE_TYPE() = MTO_PREAMBLE_LONG;
MTO_PREAMBLE_TYPE() = MTO_PREAMBLE_SHORT; // for test
MTO_ANT_SEL() = hal_get_antenna_number(MTO_HAL());
MTO_ANT_MAC() = MTO_ANT_SEL();
MTO_CNT_ANT(0) = 0;
MTO_CNT_ANT(1) = 0;
MTO_SQ_ANT(0) = 0;
MTO_SQ_ANT(1) = 0;
MTO_ANT_DIVERSITY() = MTO_ANTENNA_DIVERSITY_ON;
//CardSet_AntennaDiversity(Adapter, MTO_ANT_DIVERSITY());
//PLMESetAntennaDiversity( Adapter, MTO_ANT_DIVERSITY());
MTO_AGING_TIMEOUT() = 0;//MTO_TMR_AGING() / MTO_TMR_PERIODIC();
// The following parameters should be initialized to the values set by user
//
//MTO_RATE_LEVEL() = 10;
MTO_RATE_LEVEL() = 0;
MTO_FALLBACK_RATE_LEVEL() = MTO_RATE_LEVEL();
MTO_FRAG_TH_LEVEL() = 4;
/** 1.1.23.1000 Turbo modify from -1 to +1
MTO_RTS_THRESHOLD() = MTO_FRAG_TH() - 1;
MTO_RTS_THRESHOLD_SETUP() = MTO_FRAG_TH() - 1;
*/
MTO_RTS_THRESHOLD() = MTO_FRAG_TH() + 1;
MTO_RTS_THRESHOLD_SETUP() = MTO_FRAG_TH() + 1;
// 1.1.23.1000 Turbo add for mto change preamble from 0 to 1
MTO_RATE_CHANGE_ENABLE() = 1;
MTO_FRAG_CHANGE_ENABLE() = 0; // 1.1.29.1000 Turbo add don't support frag
//The default valud of ANTDIV_DEFAULT_ON will be decided by EEPROM
//#ifdef ANTDIV_DEFAULT_ON
//MTO_ANT_DIVERSITY_ENABLE() = 1;
//#else
//MTO_ANT_DIVERSITY_ENABLE() = 0;
//#endif
MTO_POWER_CHANGE_ENABLE() = 1;
MTO_PREAMBLE_CHANGE_ENABLE()= 1;
MTO_RTS_CHANGE_ENABLE() = 0; // 1.1.29.1000 Turbo add don't support frag
// 20040512 Turbo add
//old_antenna[0] = 1;
//old_antenna[1] = 0;
//old_antenna[2] = 1;
//old_antenna[3] = 0;
for (i=0;i<MTO_MAX_DATA_RATE_LEVELS;i++)
retryrate_rec[i]=5;
MTO_TXFLOWCOUNT() = 0;
//--------- DTO threshold parameters -------------
//MTOPARA_PERIODIC_CHECK_CYCLE() = 50;
MTOPARA_PERIODIC_CHECK_CYCLE() = 10;
MTOPARA_RSSI_TH_FOR_ANTDIV() = 10;
MTOPARA_TXCOUNT_TH_FOR_CALC_RATE() = 50;
MTOPARA_TXRATE_INC_TH() = 10;
MTOPARA_TXRATE_DEC_TH() = 30;
MTOPARA_TXRATE_EQ_TH() = 40;
MTOPARA_TXRATE_BACKOFF() = 12;
MTOPARA_TXRETRYRATE_REDUCE() = 6;
if ( MTO_TXPOWER_FROM_EEPROM == 0xff)
{
switch( MTO_HAL()->phy_type)
{
case RF_AIROHA_2230:
case RF_AIROHA_2230S: // 20060420 Add this
MTOPARA_TXPOWER_INDEX() = 46; // MAX-8 // @@ Only for AL 2230
break;
case RF_AIROHA_7230:
MTOPARA_TXPOWER_INDEX() = 49;
break;
case RF_WB_242:
MTOPARA_TXPOWER_INDEX() = 10;
break;
case RF_WB_242_1:
MTOPARA_TXPOWER_INDEX() = 24; // ->10 20060316.1 modify
break;
}
}
else //follow the setting from EEPROM
MTOPARA_TXPOWER_INDEX() = MTO_TXPOWER_FROM_EEPROM;
hal_set_rf_power(MTO_HAL(), (u8)MTOPARA_TXPOWER_INDEX());
//------------------------------------------------
// For RSSI turning 20060808.4 Cancel load from EEPROM
MTO_DATA().RSSI_high = -41;
MTO_DATA().RSSI_low = -60;
}
//---------------------------------------------------------------------------//
static u32 DTO_Rx_Info[13][3];
static u32 DTO_RxCRCFail_Info[13][3];
static u32 AntennaToggleBkoffTimer=5;
typedef struct{
int RxRate;
int RxRatePkts;
int index;
}RXRATE_ANT;
RXRATE_ANT RxRatePeakAnt[3];
#define ANT0 0
#define ANT1 1
#define OLD_ANT 2
void SearchPeakRxRate(int index)
{
int i;
RxRatePeakAnt[index].RxRatePkts=0;
//Find out the best rx rate which is used on different antenna
for(i=1;i<13;i++)
{
if(DTO_Rx_Info[i][index] > (u32) RxRatePeakAnt[index].RxRatePkts)
{
RxRatePeakAnt[index].RxRatePkts = DTO_Rx_Info[i][index];
RxRatePeakAnt[index].RxRate = rate_tbl[i];
RxRatePeakAnt[index].index = i;
}
}
}
void ResetDTO_RxInfo(int index, MTO_FUNC_INPUT)
{
int i;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("ResetDTOrx\n"));
#endif
for(i=0;i<13;i++)
DTO_Rx_Info[i][index] = MTO_HAL()->rx_ok_count[i];
for(i=0;i<13;i++)
DTO_RxCRCFail_Info[i][index] = MTO_HAL()->rx_err_count[i];
TotalTxPkt = 0;
TotalTxPktRetry = 0;
}
void GetDTO_RxInfo(int index, MTO_FUNC_INPUT)
{
int i;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("GetDTOrx\n"));
#endif
//PDEBUG(("[MTO]:DTO_Rx_Info[%d]=%d, rx_ok_count=%d\n", index, DTO_Rx_Info[0][index], phw_data->rx_ok_count[0]));
for(i=0;i<13;i++)
DTO_Rx_Info[i][index] = abs(MTO_HAL()->rx_ok_count[i] - DTO_Rx_Info[i][index]);
if(DTO_Rx_Info[0][index]==0) DTO_Rx_Info[0][index] = 1;
for(i=0;i<13;i++)
DTO_RxCRCFail_Info[i][index] = MTO_HAL()->rx_err_count[i] - DTO_RxCRCFail_Info[i][index];
TxPktPerAnt[index] = TotalTxPkt;
TxPktRetryPerAnt[index] = TotalTxPktRetry;
TotalTxPkt = 0;
TotalTxPktRetry = 0;
}
void OutputDebugInfo(int index1, int index2)
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:Total Rx (%d)\t\t(%d) \n ", DTO_Rx_Info[0][index1], DTO_Rx_Info[0][index2]));
WBDEBUG(("[HHDTO]:RECEIVE RSSI: (%d)\t\t(%d) \n ", RXRSSIANT[index1], RXRSSIANT[index2]));
WBDEBUG(("[HHDTO]:TX packet correct rate: (%d)%%\t\t(%d)%% \n ",Divide(TxPktPerAnt[index1]*100,TxPktRetryPerAnt[index1]), Divide(TxPktPerAnt[index2]*100,TxPktRetryPerAnt[index2])));
#endif
{
int tmp1, tmp2;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:Total Tx (%d)\t\t(%d) \n ", TxPktPerAnt[index1], TxPktPerAnt[index2]));
WBDEBUG(("[HHDTO]:Total Tx retry (%d)\t\t(%d) \n ", TxPktRetryPerAnt[index1], TxPktRetryPerAnt[index2]));
#endif
tmp1 = TxPktPerAnt[index1] + DTO_Rx_Info[0][index1];
tmp2 = TxPktPerAnt[index2] + DTO_Rx_Info[0][index2];
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:Total Tx+RX (%d)\t\t(%d) \n ", tmp1, tmp2));
#endif
}
}
unsigned char TxDominate(int index)
{
int tmp;
tmp = TxPktPerAnt[index] + DTO_Rx_Info[0][index];
if(Divide(TxPktPerAnt[index]*100, tmp) > 40)
return TRUE;
else
return FALSE;
}
unsigned char CmpTxRetryRate(int index1, int index2)
{
int tx_retry_rate1, tx_retry_rate2;
tx_retry_rate1 = Divide((TxPktRetryPerAnt[index1] - TxPktPerAnt[index1])*100, TxPktRetryPerAnt[index1]);
tx_retry_rate2 = Divide((TxPktRetryPerAnt[index2] - TxPktPerAnt[index2])*100, TxPktRetryPerAnt[index2]);
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[MTO]:TxRetry Ant0: (%d%%) Ant1: (%d%%) \n ", tx_retry_rate1, tx_retry_rate2));
#endif
if(tx_retry_rate1 > tx_retry_rate2)
return TRUE;
else
return FALSE;
}
void GetFreshAntennaData(MTO_FUNC_INPUT)
{
u8 x;
x = hal_get_antenna_number(MTO_HAL());
//hal_get_bss_pk_cnt(MTO_HAL());
//hal_get_est_sq3(MTO_HAL(), 1);
old_antenna[0] = x;
//if this is the function for timer
ResetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
if(AntennaToggleBkoffTimer)
AntennaToggleBkoffTimer--;
if (abs(last_rate_ant-MTO_RATE_LEVEL())>1) //backoff timer reset
AntennaToggleBkoffTimer=0;
if (MTO_ANT_DIVERSITY() != MTO_ANTENNA_DIVERSITY_ON ||
MTO_ANT_DIVERSITY_ENABLE() != 1)
AntennaToggleBkoffTimer=1;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:**last data rate=%d,now data rate=%d**antenna toggle timer=%d",last_rate_ant,MTO_RATE_LEVEL(),AntennaToggleBkoffTimer));
#endif
last_rate_ant=MTO_RATE_LEVEL();
if(AntennaToggleBkoffTimer==0)
{
MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT0;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:===state is starting==for antenna toggle==="));
#endif
}
else
MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
if ((MTO_BACKOFF_TMR()!=0)&&(MTO_RATE_LEVEL()>MTO_DataRateAvailableLevel - 3))
{
MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:===the data rate is %d (good)and will not toogle ===",MTO_DATA_RATE()>>1));
#endif
}
}
int WB_PCR[2]; //packet correct rate
void AntennaToggleState(MTO_FUNC_INPUT)
{
int decideantflag = 0;
u8 x;
s32 rssi;
if(MTO_ANT_DIVERSITY_ENABLE() != 1)
return;
x = hal_get_antenna_number(MTO_HAL());
switch(MTO_TOGGLE_STATE())
{
//Missing.....
case TOGGLE_STATE_IDLE:
case TOGGLE_STATE_BKOFF:
break;;
case TOGGLE_STATE_WAIT0://========
GetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
RXRSSIANT[x] = rssi;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO] **wait0==== Collecting Ant%d--rssi=%d\n", x,RXRSSIANT[x]));
#endif
//change antenna and reset the data at changed antenna
x = (~x) & 0x01;
MTO_ANT_SEL() = x;
hal_set_antenna_number(MTO_HAL(), MTO_ANT_SEL());
LOCAL_ANTENNA_NO() = x;
MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT1;//go to wait1
ResetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
break;
case TOGGLE_STATE_WAIT1://=====wait1
//MTO_CNT_ANT(x) = hal_get_bss_pk_cnt(MTO_HAL());
//RXRSSIANT[x] = hal_get_rssi(MTO_HAL());
sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
RXRSSIANT[x] = rssi;
GetDTO_RxInfo(x, MTO_FUNC_INPUT_DATA);
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO] **wait1==== Collecting Ant%d--rssi=%d\n", x,RXRSSIANT[x]));
#endif
MTO_TOGGLE_STATE() = TOGGLE_STATE_MAKEDESISION;
break;
case TOGGLE_STATE_MAKEDESISION:
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:Ant--0-----------------1---\n"));
OutputDebugInfo(ANT0,ANT1);
#endif
//PDEBUG(("[HHDTO] **decision====\n "));
//=====following is the decision produrce
//
// first: compare the rssi if difference >10
// select the larger one
// ,others go to second
// second: comapre the tx+rx packet count if difference >100
// use larger total packets antenna
// third::compare the tx PER if packets>20
// if difference >5% using the bigger one
//
// fourth:compare the RX PER if packets>20
// if PER difference <5%
// using old antenna
//
//
if (abs(RXRSSIANT[ANT0]-RXRSSIANT[ANT1]) > MTOPARA_RSSI_TH_FOR_ANTDIV())//====rssi_th
{
if (RXRSSIANT[ANT0]>RXRSSIANT[ANT1])
{
decideantflag=1;
MTO_ANT_MAC() = ANT0;
}
else
{
decideantflag=1;
MTO_ANT_MAC() = ANT1;
}
#ifdef _PE_DTO_DUMP_
WBDEBUG(("Select antenna by RSSI\n"));
#endif
}
else if (abs(TxPktPerAnt[ANT0] + DTO_Rx_Info[0][ANT0]-TxPktPerAnt[ANT1]-DTO_Rx_Info[0][ANT1])<50)//=====total packet_th
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("Total tx/rx is close\n"));
#endif
if (TxDominate(ANT0) && TxDominate(ANT1))
{
if ((TxPktPerAnt[ANT0]>10) && (TxPktPerAnt[ANT1]>10))//====tx packet_th
{
WB_PCR[ANT0]=Divide(TxPktPerAnt[ANT0]*100,TxPktRetryPerAnt[ANT0]);
WB_PCR[ANT1]=Divide(TxPktPerAnt[ANT1]*100,TxPktRetryPerAnt[ANT1]);
if (abs(WB_PCR[ANT0]-WB_PCR[ANT1])>5)// tx PER_th
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("Decide by Tx correct rate\n"));
#endif
if (WB_PCR[ANT0]>WB_PCR[ANT1])
{
decideantflag=1;
MTO_ANT_MAC() = ANT0;
}
else
{
decideantflag=1;
MTO_ANT_MAC() = ANT1;
}
}
else
{
decideantflag=0;
untogglecount++;
MTO_ANT_MAC() = old_antenna[0];
}
}
else
{
decideantflag=0;
MTO_ANT_MAC() = old_antenna[0];
}
}
else if ((DTO_Rx_Info[0][ANT0]>10)&&(DTO_Rx_Info[0][ANT1]>10))//rx packet th
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("Decide by Rx\n"));
#endif
if (abs(DTO_Rx_Info[0][ANT0] - DTO_Rx_Info[0][ANT1])>50)
{
if (DTO_Rx_Info[0][ANT0] > DTO_Rx_Info[0][ANT1])
{
decideantflag=1;
MTO_ANT_MAC() = ANT0;
}
else
{
decideantflag=1;
MTO_ANT_MAC() = ANT1;
}
}
else
{
decideantflag=0;
untogglecount++;
MTO_ANT_MAC() = old_antenna[0];
}
}
else
{
decideantflag=0;
MTO_ANT_MAC() = old_antenna[0];
}
}
else if ((TxPktPerAnt[ANT0]+DTO_Rx_Info[0][ANT0])>(TxPktPerAnt[ANT1]+DTO_Rx_Info[0][ANT1]))//use more packekts
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("decide by total tx/rx : ANT 0\n"));
#endif
decideantflag=1;
MTO_ANT_MAC() = ANT0;
}
else
{
#ifdef _PE_DTO_DUMP_
WBDEBUG(("decide by total tx/rx : ANT 1\n"));
#endif
decideantflag=1;
MTO_ANT_MAC() = ANT1;
}
//this is force ant toggle
if (decideantflag==1)
untogglecount=0;
untogglecount=untogglecount%4;
if (untogglecount==3) //change antenna
MTO_ANT_MAC() = ((~old_antenna[0]) & 0x1);
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:==================untoggle-count=%d",untogglecount));
#endif
//PDEBUG(("[HHDTO] **********************************DTO ENABLE=%d",MTO_ANT_DIVERSITY_ENABLE()));
if(MTO_ANT_DIVERSITY_ENABLE() == 1)
{
MTO_ANT_SEL() = MTO_ANT_MAC();
hal_set_antenna_number(MTO_HAL(), MTO_ANT_SEL());
LOCAL_ANTENNA_NO() = MTO_ANT_SEL();
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO] ==decision==*******antflag=%d******************selected antenna=%d\n",decideantflag,MTO_ANT_SEL()));
#endif
}
if (decideantflag)
{
old_antenna[3]=old_antenna[2];//store antenna info
old_antenna[2]=old_antenna[1];
old_antenna[1]=old_antenna[0];
old_antenna[0]= MTO_ANT_MAC();
}
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:**old antenna=[%d][%d][%d][%d]\n",old_antenna[0],old_antenna[1],old_antenna[2],old_antenna[3]));
#endif
if (old_antenna[0]!=old_antenna[1])
AntennaToggleBkoffTimer=0;
else if (old_antenna[1]!=old_antenna[2])
AntennaToggleBkoffTimer=1;
else if (old_antenna[2]!=old_antenna[3])
AntennaToggleBkoffTimer=2;
else
AntennaToggleBkoffTimer=4;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTO]:**back off timer=%d",AntennaToggleBkoffTimer));
#endif
ResetDTO_RxInfo(MTO_ANT_MAC(), MTO_FUNC_INPUT_DATA);
if (AntennaToggleBkoffTimer==0 && decideantflag)
MTO_TOGGLE_STATE() = TOGGLE_STATE_WAIT0;
else
MTO_TOGGLE_STATE() = TOGGLE_STATE_IDLE;
break;
}
}
void multiagc(MTO_FUNC_INPUT, u8 high_gain_mode )
{
s32 rssi;
hw_data_t *pHwData = MTO_HAL();
sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
if( (RF_WB_242 == pHwData->phy_type) ||
(RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
{
if (high_gain_mode==1)
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
//hw_set_dxx_reg(phw_data, 0x20, 0x06C43440);
Wb35Reg_Write( pHwData, 0x100C, 0xF2F32232 ); // 940916 0xf8f52230 );
Wb35Reg_Write( pHwData, 0x1020, 0x04cb3440 ); // 940915 0x06C43440
}
else if (high_gain_mode==0)
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xEEEE000D);
//hw_set_dxx_reg(phw_data, 0x20, 0x06c41440);
Wb35Reg_Write( pHwData, 0x100C, 0xEEEE000D );
Wb35Reg_Write( pHwData, 0x1020, 0x04cb1440 ); // 940915 0x06c41440
}
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[HHDTOAGC] **rssi=%d, high gain mode=%d", rssi, high_gain_mode));
#endif
}
}
void TxPwrControl(MTO_FUNC_INPUT)
{
s32 rssi;
hw_data_t *pHwData = MTO_HAL();
sme_get_rssi(MTO_FUNC_INPUT_DATA, &rssi);
if( (RF_WB_242 == pHwData->phy_type) ||
(RF_WB_242_1 == pHwData->phy_type) ) // 20060619.5 Add
{
static u8 high_gain_mode; //this is for winbond RF switch LNA
//using different register setting
if (high_gain_mode==1)
{
if( rssi > MTO_DATA().RSSI_high )
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
//hw_set_dxx_reg(phw_data, 0x20, 0x05541640);
high_gain_mode=0;
}
else
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xf8f51830);
//hw_set_dxx_reg(phw_data, 0x20, 0x05543E40);
high_gain_mode=1;
}
}
else //if (high_gain_mode==0)
{
if( rssi < MTO_DATA().RSSI_low )
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xf8f51830);
//hw_set_dxx_reg(phw_data, 0x20, 0x05543E40);
high_gain_mode=1;
}
else
{
//hw_set_dxx_reg(phw_data, 0x0C, 0xf8f52230);
//hw_set_dxx_reg(phw_data, 0x20, 0x05541640);
high_gain_mode=0;
}
}
// Always high gain 20051014. Using the initial value only.
multiagc(MTO_FUNC_INPUT_DATA, high_gain_mode);
}
}
u8 CalcNewRate(MTO_FUNC_INPUT, u8 old_rate, u32 retry_cnt, u32 tx_frag_cnt)
{
int i;
u8 new_rate;
u32 retry_rate;
int TxThrouput1, TxThrouput2, TxThrouput3, BestThroupht;
if(tx_frag_cnt < MTOPARA_TXCOUNT_TH_FOR_CALC_RATE()) //too few packets transmit
{
return 0xff;
}
retry_rate = Divide(retry_cnt * 100, tx_frag_cnt);
if(retry_rate > 90) retry_rate = 90; //always truncate to 90% due to lookup table size
#ifdef _PE_DTO_DUMP_
WBDEBUG(("##### Current level =%d, Retry count =%d, Frag count =%d\n",
old_rate, retry_cnt, tx_frag_cnt));
WBDEBUG(("*##* Retry rate =%d, throughput =%d\n",
retry_rate, Rate_PER_TBL[retry_rate][old_rate]));
WBDEBUG(("TxRateRec.tx_rate =%d, Retry rate = %d, throughput = %d\n",
TxRateRec.tx_rate, TxRateRec.tx_retry_rate,
Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]]));
WBDEBUG(("old_rate-1 =%d, Retry rate = %d, throughput = %d\n",
old_rate-1, retryrate_rec[old_rate-1],
Rate_PER_TBL[retryrate_rec[old_rate-1]][old_rate-1]));
WBDEBUG(("old_rate+1 =%d, Retry rate = %d, throughput = %d\n",
old_rate+1, retryrate_rec[old_rate+1],
Rate_PER_TBL[retryrate_rec[old_rate+1]][old_rate+1]));
#endif
//following is for record the retry rate at the different data rate
if (abs(retry_rate-retryrate_rec[old_rate])<50)//---the per TH
retryrate_rec[old_rate] = retry_rate; //update retry rate
else
{
for (i=0;i<MTO_DataRateAvailableLevel;i++) //reset all retry rate
retryrate_rec[i]=0;
retryrate_rec[old_rate] = retry_rate;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("Reset retry rate table\n"));
#endif
}
if(TxRateRec.tx_rate > old_rate) //Decrease Tx Rate
{
TxThrouput1 = Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]];
TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
if(TxThrouput1 > TxThrouput2)
{
new_rate = TxRateRec.tx_rate;
BestThroupht = TxThrouput1;
}
else
{
new_rate = old_rate;
BestThroupht = TxThrouput2;
}
if((old_rate > 0) &&(retry_rate>MTOPARA_TXRATE_DEC_TH())) //Min Rate
{
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate-1]][Level2PerTbl[old_rate-1]];
if(BestThroupht < TxThrouput3)
{
new_rate = old_rate - 1;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("--------\n"));
#endif
BestThroupht = TxThrouput3;
}
}
}
else if(TxRateRec.tx_rate < old_rate) //Increase Tx Rate
{
TxThrouput1 = Rate_PER_TBL[TxRateRec.tx_retry_rate][Level2PerTbl[TxRateRec.tx_rate]];
TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
if(TxThrouput1 > TxThrouput2)
{
new_rate = TxRateRec.tx_rate;
BestThroupht = TxThrouput1;
}
else
{
new_rate = old_rate;
BestThroupht = TxThrouput2;
}
if ((old_rate < MTO_DataRateAvailableLevel - 1)&&(retry_rate<MTOPARA_TXRATE_INC_TH()))
{
//TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
if (retryrate_rec[old_rate+1] > MTOPARA_TXRETRYRATE_REDUCE())
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]-MTOPARA_TXRETRYRATE_REDUCE()][Level2PerTbl[old_rate+1]];
else
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
if(BestThroupht < TxThrouput3)
{
new_rate = old_rate + 1;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("++++++++++\n"));
#endif
BestThroupht = TxThrouput3;
}
}
}
else //Tx Rate no change
{
TxThrouput2 = Rate_PER_TBL[retry_rate][Level2PerTbl[old_rate]];
new_rate = old_rate;
BestThroupht = TxThrouput2;
if (retry_rate <MTOPARA_TXRATE_EQ_TH()) //th for change higher rate
{
if(old_rate < MTO_DataRateAvailableLevel - 1)
{
//TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
if (retryrate_rec[old_rate+1] > MTOPARA_TXRETRYRATE_REDUCE())
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]-MTOPARA_TXRETRYRATE_REDUCE()][Level2PerTbl[old_rate+1]];
else
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate+1]][Level2PerTbl[old_rate+1]];
if(BestThroupht < TxThrouput3)
{
new_rate = old_rate + 1;
BestThroupht = TxThrouput3;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("=++++++++++\n"));
#endif
}
}
}
else
if(old_rate > 0) //Min Rate
{
TxThrouput3 = Rate_PER_TBL[retryrate_rec[old_rate-1]][Level2PerTbl[old_rate-1]];
if(BestThroupht < TxThrouput3)
{
new_rate = old_rate - 1;
#ifdef _PE_DTO_DUMP_
WBDEBUG(("=--------\n"));
#endif
BestThroupht = TxThrouput3;
}
}
}
if (!LOCAL_IS_IBSS_MODE())
{
max_rssi_rate = GetMaxRateLevelFromRSSI();
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[MTO]:RSSI2Rate=%d\n", MTO_Data_Rate_Tbl[max_rssi_rate]));
#endif
if(new_rate > max_rssi_rate)
new_rate = max_rssi_rate;
}
//save new rate;
TxRateRec.tx_rate = old_rate;
TxRateRec.tx_retry_rate = (u8) retry_rate;
TxRetryRate = retry_rate;
return new_rate;
}
void SmoothRSSI(s32 new_rssi)
{
RSSISmoothed = RSSISmoothed + new_rssi - RSSIBuf[RSSIBufIndex];
RSSIBuf[RSSIBufIndex] = new_rssi;
RSSIBufIndex = (RSSIBufIndex + 1) % 10;
}
u8 GetMaxRateLevelFromRSSI(void)
{
u8 i;
u8 TxRate;
for(i=0;i<RSSI2RATE_SIZE;i++)
{
if(RSSISmoothed > RSSI2RateTbl[i].RSSI)
break;
}
#ifdef _PE_DTO_DUMP_
WBDEBUG(("[MTO]:RSSI=%d\n", Divide(RSSISmoothed, 10)));
#endif
if(i < RSSI2RATE_SIZE)
TxRate = RSSI2RateTbl[i].TxRate;
else
TxRate = 2; //divided by 2 = 1Mbps
for(i=MTO_DataRateAvailableLevel-1;i>0;i--)
{
if(TxRate >=MTO_Data_Rate_Tbl[i])
break;
}
return i;
}
//===========================================================================
// Description:
// If we enable DTO, we will ignore the tx count with different tx rate from
// DTO rate. This is because when we adjust DTO tx rate, there could be some
// packets in the tx queue with previous tx rate
void MTO_SetTxCount(MTO_FUNC_INPUT, u8 tx_rate, u8 index)
{
MTO_TXFLOWCOUNT()++;
if ((MTO_ENABLE==1) && (MTO_RATE_CHANGE_ENABLE()==1))
{
if(tx_rate == MTO_DATA_RATE())
{
if (index == 0)
{
if (boSparseTxTraffic)
MTO_HAL()->dto_tx_frag_count += MTOPARA_PERIODIC_CHECK_CYCLE();
else
MTO_HAL()->dto_tx_frag_count += 1;
}
else
{
if (index<8)
{
MTO_HAL()->dto_tx_retry_count += index;
MTO_HAL()->dto_tx_frag_count += (index+1);
}
else
{
MTO_HAL()->dto_tx_retry_count += 7;
MTO_HAL()->dto_tx_frag_count += 7;
}
}
}
else if(MTO_DATA_RATE()>48 && tx_rate ==48)
{//ALFRED
if (index<3) //for reduciing data rate scheme ,
//do not calcu different data rate
//3 is the reducing data rate at retry
{
MTO_HAL()->dto_tx_retry_count += index;
MTO_HAL()->dto_tx_frag_count += (index+1);
}
else
{
MTO_HAL()->dto_tx_retry_count += 3;
MTO_HAL()->dto_tx_frag_count += 3;
}
}
}
else
{
MTO_HAL()->dto_tx_retry_count += index;
MTO_HAL()->dto_tx_frag_count += (index+1);
}
TotalTxPkt ++;
TotalTxPktRetry += (index+1);
PeriodTotalTxPkt ++;
PeriodTotalTxPktRetry += (index+1);
}
u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT)
{
return MTO_DATA_FALLBACK_RATE();
}
//===========================================================================
// MTO_TxFailed --
//
// Description:
// Failure of transmitting a packet indicates that certain MTO parmeters
// may need to be adjusted. This function is called when NIC just failed
// to transmit a packet or when MSDULifeTime expired.
//
// Arguments:
// Adapter - The pointer to the Miniport Adapter Context
//
// Return Value:
// None
//============================================================================
void MTO_TxFailed(MTO_FUNC_INPUT)
{
return;
}
int Divide(int a, int b)
{
if (b==0) b=1;
return a/b;
}
//==================================================================
// MTO.H
//
// Revision history
//=================================
// 20030110 UN20 Pete Chao
// Initial Release
//
// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved.
//==================================================================
#ifndef __MTO_H__
#define __MTO_H__
#define MTO_DEFAULT_TH_CNT 5
#define MTO_DEFAULT_TH_SQ3 112 //OLD IS 13 reference JohnXu
#define MTO_DEFAULT_TH_IDLE_SLOT 15
#define MTO_DEFAULT_TH_PR_INTERF 30
#define MTO_DEFAULT_TMR_AGING 25 // unit: slot time 10 reference JohnXu
#define MTO_DEFAULT_TMR_PERIODIC 5 // unit: slot time
#define MTO_ANTENNA_DIVERSITY_OFF 0
#define MTO_ANTENNA_DIVERSITY_ON 1
// LA20040210_DTO kevin
//#define MTO_PREAMBLE_LONG 0
//#define MTO_PREAMBLE_SHORT 1
#define MTO_PREAMBLE_LONG WLAN_PREAMBLE_TYPE_LONG
#define MTO_PREAMBLE_SHORT WLAN_PREAMBLE_TYPE_SHORT
typedef enum {
TOGGLE_STATE_IDLE = 0,
TOGGLE_STATE_WAIT0 = 1,
TOGGLE_STATE_WAIT1 = 2,
TOGGLE_STATE_MAKEDESISION = 3,
TOGGLE_STATE_BKOFF = 4
} TOGGLE_STATE;
typedef enum {
RATE_CHGSTATE_IDLE = 0,
RATE_CHGSTATE_CALCULATE = 1,
RATE_CHGSTATE_BACKOFF = 2
} TX_RATE_REDUCTION_STATE;
//============================================================================
// struct _MTOParameters --
//
// Defines the parameters used in the MAC Throughput Optimization algorithm
//============================================================================
typedef struct _MTO_PARAMETERS
{
u8 Th_Fixant;
u8 Th_Cnt;
u8 Th_SQ3;
u8 Th_IdleSlot;
u16 Tmr_Aging;
u8 Th_PrInterf;
u8 Tmr_Periodic;
//--------- wkchen added -------------
u32 TxFlowCount; //to judge what kind the tx flow(sparse or busy) is
//------------------------------------------------
//--------- DTO threshold parameters -------------
u16 DTO_PeriodicCheckCycle;
u16 DTO_RssiThForAntDiv;
u16 DTO_TxCountThForCalcNewRate;
u16 DTO_TxRateIncTh;
u16 DTO_TxRateDecTh;
u16 DTO_TxRateEqTh;
u16 DTO_TxRateBackOff;
u16 DTO_TxRetryRateReduce;
u16 DTO_TxPowerIndex; //0 ~ 31
u16 reserved_1;
//------------------------------------------------
u8 PowerChangeEnable;
u8 AntDiversityEnable;
u8 Ant_mac;
u8 Ant_div;
u8 CCA_Mode;
u8 CCA_Mode_Setup;
u8 Preamble_Type;
u8 PreambleChangeEnable;
u8 DataRateLevel;
u8 DataRateChangeEnable;
u8 FragThresholdLevel;
u8 FragThresholdChangeEnable;
u16 RTSThreshold;
u16 RTSThreshold_Setup;
u32 AvgIdleSlot;
u32 Pr_Interf;
u32 AvgGapBtwnInterf;
u8 RTSChangeEnable;
u8 Ant_sel;
u8 aging_timeout;
u8 reserved_2;
u32 Cnt_Ant[2];
u32 SQ_Ant[2];
// 20040510 remove from globe vairable
u32 TmrCnt;
u32 BackoffTmr;
TOGGLE_STATE ToggleState;
TX_RATE_REDUCTION_STATE TxRateReductionState;
u8 Last_Rate;
u8 Co_efficent;
u8 FallbackRateLevel;
u8 OfdmRateLevel;
u8 RatePolicy;
u8 reserved_3[3];
// For RSSI turning
s32 RSSI_high;
s32 RSSI_low;
} MTO_PARAMETERS, *PMTO_PARAMETERS;
#define MTO_FUNC_INPUT PWB32_ADAPTER Adapter
#define MTO_FUNC_INPUT_DATA Adapter
#define MTO_DATA() (Adapter->sMtoPara)
#define MTO_HAL() (&Adapter->sHwData)
#define MTO_SET_PREAMBLE_TYPE(x) // 20040511 Turbo mark LM_PREAMBLE_TYPE(&pcore_data->lm_data) = (x)
#define MTO_ENABLE (Adapter->sLocalPara.TxRateMode == RATE_AUTO)
#define MTO_TXPOWER_FROM_EEPROM (Adapter->sHwData.PowerIndexFromEEPROM)
#define LOCAL_ANTENNA_NO() (Adapter->sLocalPara.bAntennaNo)
#define LOCAL_IS_CONNECTED() (Adapter->sLocalPara.wConnectedSTAindex != 0)
#define LOCAL_IS_IBSS_MODE() (Adapter->asBSSDescriptElement[Adapter->sLocalPara.wConnectedSTAindex].bBssType == IBSS_NET)
#define MTO_INITTXRATE_MODE (Adapter->sHwData.SoftwareSet&0x2) //bit 1
// 20040510 Turbo add
#define MTO_TMR_CNT() MTO_DATA().TmrCnt
#define MTO_TOGGLE_STATE() MTO_DATA().ToggleState
#define MTO_TX_RATE_REDUCTION_STATE() MTO_DATA().TxRateReductionState
#define MTO_BACKOFF_TMR() MTO_DATA().BackoffTmr
#define MTO_LAST_RATE() MTO_DATA().Last_Rate
#define MTO_CO_EFFICENT() MTO_DATA().Co_efficent
#define MTO_TH_CNT() MTO_DATA().Th_Cnt
#define MTO_TH_SQ3() MTO_DATA().Th_SQ3
#define MTO_TH_IDLE_SLOT() MTO_DATA().Th_IdleSlot
#define MTO_TH_PR_INTERF() MTO_DATA().Th_PrInterf
#define MTO_TMR_AGING() MTO_DATA().Tmr_Aging
#define MTO_TMR_PERIODIC() MTO_DATA().Tmr_Periodic
#define MTO_POWER_CHANGE_ENABLE() MTO_DATA().PowerChangeEnable
#define MTO_ANT_DIVERSITY_ENABLE() Adapter->sLocalPara.boAntennaDiversity
#define MTO_ANT_MAC() MTO_DATA().Ant_mac
#define MTO_ANT_DIVERSITY() MTO_DATA().Ant_div
#define MTO_CCA_MODE() MTO_DATA().CCA_Mode
#define MTO_CCA_MODE_SETUP() MTO_DATA().CCA_Mode_Setup
#define MTO_PREAMBLE_TYPE() MTO_DATA().Preamble_Type
#define MTO_PREAMBLE_CHANGE_ENABLE() MTO_DATA().PreambleChangeEnable
#define MTO_RATE_LEVEL() MTO_DATA().DataRateLevel
#define MTO_FALLBACK_RATE_LEVEL() MTO_DATA().FallbackRateLevel
#define MTO_OFDM_RATE_LEVEL() MTO_DATA().OfdmRateLevel
#define MTO_RATE_CHANGE_ENABLE() MTO_DATA().DataRateChangeEnable
#define MTO_FRAG_TH_LEVEL() MTO_DATA().FragThresholdLevel
#define MTO_FRAG_CHANGE_ENABLE() MTO_DATA().FragThresholdChangeEnable
#define MTO_RTS_THRESHOLD() MTO_DATA().RTSThreshold
#define MTO_RTS_CHANGE_ENABLE() MTO_DATA().RTSChangeEnable
#define MTO_RTS_THRESHOLD_SETUP() MTO_DATA().RTSThreshold_Setup
#define MTO_AVG_IDLE_SLOT() MTO_DATA().AvgIdleSlot
#define MTO_PR_INTERF() MTO_DATA().Pr_Interf
#define MTO_AVG_GAP_BTWN_INTERF() MTO_DATA().AvgGapBtwnInterf
#define MTO_ANT_SEL() MTO_DATA().Ant_sel
#define MTO_CNT_ANT(x) MTO_DATA().Cnt_Ant[(x)]
#define MTO_SQ_ANT(x) MTO_DATA().SQ_Ant[(x)]
#define MTO_AGING_TIMEOUT() MTO_DATA().aging_timeout
#define MTO_TXFLOWCOUNT() MTO_DATA().TxFlowCount
//--------- DTO threshold parameters -------------
#define MTOPARA_PERIODIC_CHECK_CYCLE() MTO_DATA().DTO_PeriodicCheckCycle
#define MTOPARA_RSSI_TH_FOR_ANTDIV() MTO_DATA().DTO_RssiThForAntDiv
#define MTOPARA_TXCOUNT_TH_FOR_CALC_RATE() MTO_DATA().DTO_TxCountThForCalcNewRate
#define MTOPARA_TXRATE_INC_TH() MTO_DATA().DTO_TxRateIncTh
#define MTOPARA_TXRATE_DEC_TH() MTO_DATA().DTO_TxRateDecTh
#define MTOPARA_TXRATE_EQ_TH() MTO_DATA().DTO_TxRateEqTh
#define MTOPARA_TXRATE_BACKOFF() MTO_DATA().DTO_TxRateBackOff
#define MTOPARA_TXRETRYRATE_REDUCE() MTO_DATA().DTO_TxRetryRateReduce
#define MTOPARA_TXPOWER_INDEX() MTO_DATA().DTO_TxPowerIndex
//------------------------------------------------
extern u8 MTO_Data_Rate_Tbl[];
extern u16 MTO_Frag_Th_Tbl[];
#define MTO_DATA_RATE() MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
#define MTO_DATA_FALLBACK_RATE() MTO_Data_Rate_Tbl[MTO_FALLBACK_RATE_LEVEL()] //next level
#define MTO_FRAG_TH() MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
typedef struct {
u8 tx_rate;
u8 tx_retry_rate;
} TXRETRY_REC;
typedef struct _STATISTICS_INFO {
u32 Rate54M;
u32 Rate48M;
u32 Rate36M;
u32 Rate24M;
u32 Rate18M;
u32 Rate12M;
u32 Rate9M;
u32 Rate6M;
u32 Rate11MS;
u32 Rate11ML;
u32 Rate55MS;
u32 Rate55ML;
u32 Rate2MS;
u32 Rate2ML;
u32 Rate1M;
u32 Rate54MOK;
u32 Rate48MOK;
u32 Rate36MOK;
u32 Rate24MOK;
u32 Rate18MOK;
u32 Rate12MOK;
u32 Rate9MOK;
u32 Rate6MOK;
u32 Rate11MSOK;
u32 Rate11MLOK;
u32 Rate55MSOK;
u32 Rate55MLOK;
u32 Rate2MSOK;
u32 Rate2MLOK;
u32 Rate1MOK;
u32 SQ3;
s32 RSSIAVG;
s32 RSSIMAX;
s32 TXRATE;
s32 TxRetryRate;
s32 BSS_PK_CNT;
s32 NIDLESLOT;
s32 SLOT_CNT;
s32 INTERF_CNT;
s32 GAP_CNT;
s32 DS_EVM;
s32 RcvBeaconNum;
s32 RXRATE;
s32 RxBytes;
s32 TxBytes;
s32 Antenna;
} STATISTICS_INFO, *PSTATISTICS_INFO;
#endif //__MTO_H__
extern void MTO_Init(PWB32_ADAPTER);
extern void MTO_PeriodicTimerExpired(PWB32_ADAPTER);
extern void MTO_SetDTORateRange(PWB32_ADAPTER, u8 *, u8);
extern u8 MTO_GetTxRate(MTO_FUNC_INPUT, u32 fpdu_len);
extern u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT);
extern void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index);
#include "linux/sysdef.h"
/*
* phy_302_calibration.c
*
* Copyright (C) 2002, 2005 Winbond Electronics Corp.
*
* modification history
* ---------------------------------------------------------------------------
* 0.01.001, 2003-04-16, Kevin created
*
*/
/****************** INCLUDE FILES SECTION ***********************************/
#include "os_common.h"
#include "phy_calibration.h"
/****************** DEBUG CONSTANT AND MACRO SECTION ************************/
/****************** LOCAL CONSTANT AND MACRO SECTION ************************/
#define LOOP_TIMES 20
#define US 1000//MICROSECOND
#define AG_CONST 0.6072529350
#define FIXED(X) ((s32)((X) * 32768.0))
#define DEG2RAD(X) 0.017453 * (X)
/****************** LOCAL TYPE DEFINITION SECTION ***************************/
typedef s32 fixed; /* 16.16 fixed-point */
static const fixed Angles[]=
{
FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)),
FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)),
FIXED(DEG2RAD(0.895174)),FIXED(DEG2RAD(0.447614)),FIXED(DEG2RAD(0.223811)),
FIXED(DEG2RAD(0.111906)),FIXED(DEG2RAD(0.055953)),FIXED(DEG2RAD(0.027977))
};
/****************** LOCAL FUNCTION DECLARATION SECTION **********************/
//void _phy_rf_write_delay(hw_data_t *phw_data);
//void phy_init_rf(hw_data_t *phw_data);
/****************** FUNCTION DEFINITION SECTION *****************************/
s32 _s13_to_s32(u32 data)
{
u32 val;
val = (data & 0x0FFF);
if ((data & BIT(12)) != 0)
{
val |= 0xFFFFF000;
}
return ((s32) val);
}
u32 _s32_to_s13(s32 data)
{
u32 val;
if (data > 4095)
{
data = 4095;
}
else if (data < -4096)
{
data = -4096;
}
val = data & 0x1FFF;
return val;
}
/****************************************************************************/
s32 _s4_to_s32(u32 data)
{
s32 val;
val = (data & 0x0007);
if ((data & BIT(3)) != 0)
{
val |= 0xFFFFFFF8;
}
return val;
}
u32 _s32_to_s4(s32 data)
{
u32 val;
if (data > 7)
{
data = 7;
}
else if (data < -8)
{
data = -8;
}
val = data & 0x000F;
return val;
}
/****************************************************************************/
s32 _s5_to_s32(u32 data)
{
s32 val;
val = (data & 0x000F);
if ((data & BIT(4)) != 0)
{
val |= 0xFFFFFFF0;
}
return val;
}
u32 _s32_to_s5(s32 data)
{
u32 val;
if (data > 15)
{
data = 15;
}
else if (data < -16)
{
data = -16;
}
val = data & 0x001F;
return val;
}
/****************************************************************************/
s32 _s6_to_s32(u32 data)
{
s32 val;
val = (data & 0x001F);
if ((data & BIT(5)) != 0)
{
val |= 0xFFFFFFE0;
}
return val;
}
u32 _s32_to_s6(s32 data)
{
u32 val;
if (data > 31)
{
data = 31;
}
else if (data < -32)
{
data = -32;
}
val = data & 0x003F;
return val;
}
/****************************************************************************/
s32 _s9_to_s32(u32 data)
{
s32 val;
val = data & 0x00FF;
if ((data & BIT(8)) != 0)
{
val |= 0xFFFFFF00;
}
return val;
}
u32 _s32_to_s9(s32 data)
{
u32 val;
if (data > 255)
{
data = 255;
}
else if (data < -256)
{
data = -256;
}
val = data & 0x01FF;
return val;
}
/****************************************************************************/
s32 _floor(s32 n)
{
if (n > 0)
{
n += 5;
}
else
{
n -= 5;
}
return (n/10);
}
/****************************************************************************/
// The following code is sqare-root function.
// sqsum is the input and the output is sq_rt;
// The maximum of sqsum = 2^27 -1;
u32 _sqrt(u32 sqsum)
{
u32 sq_rt;
int g0, g1, g2, g3, g4;
int seed;
int next;
int step;
g4 = sqsum / 100000000;
g3 = (sqsum - g4*100000000) /1000000;
g2 = (sqsum - g4*100000000 - g3*1000000) /10000;
g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) /100;
g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
next = g4;
step = 0;
seed = 0;
while (((seed+1)*(step+1)) <= next)
{
step++;
seed++;
}
sq_rt = seed * 10000;
next = (next-(seed*step))*100 + g3;
step = 0;
seed = 2 * seed * 10;
while (((seed+1)*(step+1)) <= next)
{
step++;
seed++;
}
sq_rt = sq_rt + step * 1000;
next = (next - seed * step) * 100 + g2;
seed = (seed + step) * 10;
step = 0;
while (((seed+1)*(step+1)) <= next)
{
step++;
seed++;
}
sq_rt = sq_rt + step * 100;
next = (next - seed * step) * 100 + g1;
seed = (seed + step) * 10;
step = 0;
while (((seed+1)*(step+1)) <= next)
{
step++;
seed++;
}
sq_rt = sq_rt + step * 10;
next = (next - seed* step) * 100 + g0;
seed = (seed + step) * 10;
step = 0;
while (((seed+1)*(step+1)) <= next)
{
step++;
seed++;
}
sq_rt = sq_rt + step;
return sq_rt;
}
/****************************************************************************/
void _sin_cos(s32 angle, s32 *sin, s32 *cos)
{
fixed X, Y, TargetAngle, CurrAngle;
unsigned Step;
X=FIXED(AG_CONST); // AG_CONST * cos(0)
Y=0; // AG_CONST * sin(0)
TargetAngle=abs(angle);
CurrAngle=0;
for (Step=0; Step < 12; Step++)
{
fixed NewX;
if(TargetAngle > CurrAngle)
{
NewX=X - (Y >> Step);
Y=(X >> Step) + Y;
X=NewX;
CurrAngle += Angles[Step];
}
else
{
NewX=X + (Y >> Step);
Y=-(X >> Step) + Y;
X=NewX;
CurrAngle -= Angles[Step];
}
}
if (angle > 0)
{
*cos = X;
*sin = Y;
}
else
{
*cos = X;
*sin = -Y;
}
}
void _reset_rx_cal(hw_data_t *phw_data)
{
u32 val;
hw_get_dxx_reg(phw_data, 0x54, &val);
if (phw_data->revision == 0x2002) // 1st-cut
{
val &= 0xFFFF0000;
}
else // 2nd-cut
{
val &= 0x000003FF;
}
hw_set_dxx_reg(phw_data, 0x54, val);
}
// ************for winbond calibration*********
//
//
//
// *********************************************
void _rxadc_dc_offset_cancellation_winbond(hw_data_t *phw_data, u32 frequency)
{
u32 reg_agc_ctrl3;
u32 reg_a_acq_ctrl;
u32 reg_b_acq_ctrl;
u32 val;
PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
phy_init_rf(phw_data);
// set calibration channel
if( (RF_WB_242 == phw_data->phy_type) ||
(RF_WB_242_1 == phw_data->phy_type) ) // 20060619.5 Add
{
if ((frequency >= 2412) && (frequency <= 2484))
{
// w89rf242 change frequency to 2390Mhz
PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
}
}
else
{
}
// reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel
hw_get_dxx_reg(phw_data, 0x5C, &val);
val &= ~(0x03FF);
hw_set_dxx_reg(phw_data, 0x5C, val);
// reset the TX and RX IQ calibration data
hw_set_dxx_reg(phw_data, 0x3C, 0);
hw_set_dxx_reg(phw_data, 0x54, 0);
hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
// a. Disable AGC
hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
reg_agc_ctrl3 &= ~BIT(2);
reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
val |= MASK_AGC_FIX_GAIN;
hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
// b. Turn off BB RX
hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, &reg_a_acq_ctrl);
reg_a_acq_ctrl |= MASK_AMER_OFF_REG;
hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl);
hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, &reg_b_acq_ctrl);
reg_b_acq_ctrl |= MASK_BMER_OFF_REG;
hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl);
// c. Make sure MAC is in receiving mode
// d. Turn ON ADC calibration
// - ADC calibrator is triggered by this signal rising from 0 to 1
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
val &= ~MASK_ADC_DC_CAL_STR;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
val |= MASK_ADC_DC_CAL_STR;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
pa_stall_execution(US); // *MUST* wait for a while
// e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]"
#ifdef _DEBUG
hw_get_dxx_reg(phw_data, REG_OFFSET_READ, &val);
PHY_DEBUG(("[CAL] REG_OFFSET_READ = 0x%08X\n", val));
PHY_DEBUG(("[CAL] ** adc_dc_cal_i = %d (0x%04X)\n",
_s9_to_s32(val&0x000001FF), val&0x000001FF));
PHY_DEBUG(("[CAL] ** adc_dc_cal_q = %d (0x%04X)\n",
_s9_to_s32((val&0x0003FE00)>>9), (val&0x0003FE00)>>9));
#endif
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
val &= ~MASK_ADC_DC_CAL_STR;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val);
// f. Turn on BB RX
//hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, &reg_a_acq_ctrl);
reg_a_acq_ctrl &= ~MASK_AMER_OFF_REG;
hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl);
//hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, &reg_b_acq_ctrl);
reg_b_acq_ctrl &= ~MASK_BMER_OFF_REG;
hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl);
// g. Enable AGC
//hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val);
reg_agc_ctrl3 |= BIT(2);
reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
}
////////////////////////////////////////////////////////
void _txidac_dc_offset_cancellation_winbond(hw_data_t *phw_data)
{
u32 reg_agc_ctrl3;
u32 reg_mode_ctrl;
u32 reg_dc_cancel;
s32 iqcal_image_i;
s32 iqcal_image_q;
u32 sqsum;
s32 mag_0;
s32 mag_1;
s32 fix_cancel_dc_i = 0;
u32 val;
int loop;
PHY_DEBUG(("[CAL] -> [2]_txidac_dc_offset_cancellation()\n"));
// a. Set to "TX calibration mode"
//0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
//0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
//0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
//0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
//0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
// a. Disable AGC
hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
reg_agc_ctrl3 &= ~BIT(2);
reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
val |= MASK_AGC_FIX_GAIN;
hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
// b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
// mode=2, tone=0
//reg_mode_ctrl |= (MASK_CALIB_START|2);
// mode=2, tone=1
//reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2));
// mode=2, tone=2
reg_mode_ctrl |= (MASK_CALIB_START|2|(2<<2));
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
for (loop = 0; loop < LOOP_TIMES; loop++)
{
PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
// c.
// reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel
reg_dc_cancel &= ~(0x03FF);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
mag_0 = (s32) _sqrt(sqsum);
PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
mag_0, iqcal_image_i, iqcal_image_q));
// d.
reg_dc_cancel |= (1 << CANCEL_DC_I_SHIFT);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
mag_1 = (s32) _sqrt(sqsum);
PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
mag_1, iqcal_image_i, iqcal_image_q));
// e. Calculate the correct DC offset cancellation value for I
if (mag_0 != mag_1)
{
fix_cancel_dc_i = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
}
else
{
if (mag_0 == mag_1)
{
PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n"));
}
fix_cancel_dc_i = 0;
}
PHY_DEBUG(("[CAL] ** fix_cancel_dc_i = %d (0x%04X)\n",
fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i)));
if ((abs(mag_1-mag_0)*6) > mag_0)
{
break;
}
}
if ( loop >= 19 )
fix_cancel_dc_i = 0;
reg_dc_cancel &= ~(0x03FF);
reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT);
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
// g.
reg_mode_ctrl &= ~MASK_CALIB_START;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
}
///////////////////////////////////////////////////////
void _txqdac_dc_offset_cacellation_winbond(hw_data_t *phw_data)
{
u32 reg_agc_ctrl3;
u32 reg_mode_ctrl;
u32 reg_dc_cancel;
s32 iqcal_image_i;
s32 iqcal_image_q;
u32 sqsum;
s32 mag_0;
s32 mag_1;
s32 fix_cancel_dc_q = 0;
u32 val;
int loop;
PHY_DEBUG(("[CAL] -> [3]_txqdac_dc_offset_cacellation()\n"));
//0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
//0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
//0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
//0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
//0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
hw_set_dxx_reg(phw_data, 0x58, 0x30303030); // IQ_Alpha Changed
// a. Disable AGC
hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
reg_agc_ctrl3 &= ~BIT(2);
reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
val |= MASK_AGC_FIX_GAIN;
hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
// a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
//reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
reg_mode_ctrl &= ~(MASK_IQCAL_MODE);
reg_mode_ctrl |= (MASK_CALIB_START|3);
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
for (loop = 0; loop < LOOP_TIMES; loop++)
{
PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
// b.
// reset cancel_dc_q[4:0] in register DC_Cancel
reg_dc_cancel &= ~(0x001F);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
pa_stall_execution(US);
iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
mag_0 = _sqrt(sqsum);
PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
mag_0, iqcal_image_i, iqcal_image_q));
// c.
reg_dc_cancel |= (1 << CANCEL_DC_Q_SHIFT);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
pa_stall_execution(US);
hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
pa_stall_execution(US);
iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
mag_1 = _sqrt(sqsum);
PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
mag_1, iqcal_image_i, iqcal_image_q));
// d. Calculate the correct DC offset cancellation value for I
if (mag_0 != mag_1)
{
fix_cancel_dc_q = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
}
else
{
if (mag_0 == mag_1)
{
PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n"));
}
fix_cancel_dc_q = 0;
}
PHY_DEBUG(("[CAL] ** fix_cancel_dc_q = %d (0x%04X)\n",
fix_cancel_dc_q, _s32_to_s5(fix_cancel_dc_q)));
if ((abs(mag_1-mag_0)*6) > mag_0)
{
break;
}
}
if ( loop >= 19 )
fix_cancel_dc_q = 0;
reg_dc_cancel &= ~(0x001F);
reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT);
hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
// f.
reg_mode_ctrl &= ~MASK_CALIB_START;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
}
//20060612.1.a 20060718.1 Modify
u8 _tx_iq_calibration_loop_winbond(hw_data_t *phw_data,
s32 a_2_threshold,
s32 b_2_threshold)
{
u32 reg_mode_ctrl;
s32 iq_mag_0_tx;
s32 iqcal_tone_i0;
s32 iqcal_tone_q0;
s32 iqcal_tone_i;
s32 iqcal_tone_q;
u32 sqsum;
s32 rot_i_b;
s32 rot_q_b;
s32 tx_cal_flt_b[4];
s32 tx_cal[4];
s32 tx_cal_reg[4];
s32 a_2, b_2;
s32 sin_b, sin_2b;
s32 cos_b, cos_2b;
s32 divisor;
s32 temp1, temp2;
u32 val;
u16 loop;
s32 iqcal_tone_i_avg,iqcal_tone_q_avg;
u8 verify_count;
int capture_time;
PHY_DEBUG(("[CAL] -> _tx_iq_calibration_loop()\n"));
PHY_DEBUG(("[CAL] ** a_2_threshold = %d\n", a_2_threshold));
PHY_DEBUG(("[CAL] ** b_2_threshold = %d\n", b_2_threshold));
verify_count = 0;
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
loop = LOOP_TIMES;
while (loop > 0)
{
PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
iqcal_tone_i_avg=0;
iqcal_tone_q_avg=0;
if( !hw_set_dxx_reg(phw_data, 0x3C, 0x00) ) // 20060718.1 modify
return 0;
for(capture_time=0;capture_time<10;capture_time++)
{
// a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
// enable "IQ alibration Mode II"
reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
reg_mode_ctrl &= ~MASK_IQCAL_MODE;
reg_mode_ctrl |= (MASK_CALIB_START|0x02);
reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2);
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
// b.
hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
pa_stall_execution(US);
iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF);
iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n",
iqcal_tone_i0, iqcal_tone_q0));
sqsum = iqcal_tone_i0*iqcal_tone_i0 +
iqcal_tone_q0*iqcal_tone_q0;
iq_mag_0_tx = (s32) _sqrt(sqsum);
PHY_DEBUG(("[CAL] ** iq_mag_0_tx=%d\n", iq_mag_0_tx));
// c. Set "calib_start" to 0x0
reg_mode_ctrl &= ~MASK_CALIB_START;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
// d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to
// enable "IQ alibration Mode II"
//hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
reg_mode_ctrl &= ~MASK_IQCAL_MODE;
reg_mode_ctrl |= (MASK_CALIB_START|0x03);
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
// e.
hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
pa_stall_execution(US);
iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
iqcal_tone_i, iqcal_tone_q));
if( capture_time == 0)
{
continue;
}
else
{
iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time;
iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time;
}
}
iqcal_tone_i = iqcal_tone_i_avg;
iqcal_tone_q = iqcal_tone_q_avg;
rot_i_b = (iqcal_tone_i * iqcal_tone_i0 +
iqcal_tone_q * iqcal_tone_q0) / 1024;
rot_q_b = (iqcal_tone_i * iqcal_tone_q0 * (-1) +
iqcal_tone_q * iqcal_tone_i0) / 1024;
PHY_DEBUG(("[CAL] ** rot_i_b = %d, rot_q_b = %d\n",
rot_i_b, rot_q_b));
// f.
divisor = ((iq_mag_0_tx * iq_mag_0_tx * 2)/1024 - rot_i_b) * 2;
if (divisor == 0)
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n"));
PHY_DEBUG(("[CAL] ** divisor=0 to calculate EPS and THETA !!\n"));
PHY_DEBUG(("[CAL] ******************************************\n"));
break;
}
a_2 = (rot_i_b * 32768) / divisor;
b_2 = (rot_q_b * (-32768)) / divisor;
PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2));
PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2));
phw_data->iq_rsdl_gain_tx_d2 = a_2;
phw_data->iq_rsdl_phase_tx_d2 = b_2;
//if ((abs(a_2) < 150) && (abs(b_2) < 100))
//if ((abs(a_2) < 200) && (abs(b_2) < 200))
if ((abs(a_2) < a_2_threshold) && (abs(b_2) < b_2_threshold))
{
verify_count++;
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n"));
PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count));
PHY_DEBUG(("[CAL] ******************************************\n"));
if (verify_count > 2)
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION (EPS,THETA) OK !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
return 0;
}
continue;
}
else
{
verify_count = 0;
}
_sin_cos(b_2, &sin_b, &cos_b);
_sin_cos(b_2*2, &sin_2b, &cos_2b);
PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b));
PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b));
if (cos_2b == 0)
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n"));
PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n"));
PHY_DEBUG(("[CAL] ******************************************\n"));
break;
}
// 1280 * 32768 = 41943040
temp1 = (41943040/cos_2b)*cos_b;
//temp2 = (41943040/cos_2b)*sin_b*(-1);
if (phw_data->revision == 0x2002) // 1st-cut
{
temp2 = (41943040/cos_2b)*sin_b*(-1);
}
else // 2nd-cut
{
temp2 = (41943040*4/cos_2b)*sin_b*(-1);
}
tx_cal_flt_b[0] = _floor(temp1/(32768+a_2));
tx_cal_flt_b[1] = _floor(temp2/(32768+a_2));
tx_cal_flt_b[2] = _floor(temp2/(32768-a_2));
tx_cal_flt_b[3] = _floor(temp1/(32768-a_2));
PHY_DEBUG(("[CAL] ** tx_cal_flt_b[0] = %d\n", tx_cal_flt_b[0]));
PHY_DEBUG(("[CAL] tx_cal_flt_b[1] = %d\n", tx_cal_flt_b[1]));
PHY_DEBUG(("[CAL] tx_cal_flt_b[2] = %d\n", tx_cal_flt_b[2]));
PHY_DEBUG(("[CAL] tx_cal_flt_b[3] = %d\n", tx_cal_flt_b[3]));
tx_cal[2] = tx_cal_flt_b[2];
tx_cal[2] = tx_cal[2] +3;
tx_cal[1] = tx_cal[2];
tx_cal[3] = tx_cal_flt_b[3] - 128;
tx_cal[0] = -tx_cal[3]+1;
PHY_DEBUG(("[CAL] tx_cal[0] = %d\n", tx_cal[0]));
PHY_DEBUG(("[CAL] tx_cal[1] = %d\n", tx_cal[1]));
PHY_DEBUG(("[CAL] tx_cal[2] = %d\n", tx_cal[2]));
PHY_DEBUG(("[CAL] tx_cal[3] = %d\n", tx_cal[3]));
//if ((tx_cal[0] == 0) && (tx_cal[1] == 0) &&
// (tx_cal[2] == 0) && (tx_cal[3] == 0))
//{
// PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n"));
// PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION COMPLETE !!\n"));
// PHY_DEBUG(("[CAL] ******************************************\n"));
// return 0;
//}
// g.
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28);
tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24);
tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20);
tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val));
tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
}
PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0]));
PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1]));
PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2]));
PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3]));
if (phw_data->revision == 0x2002) // 1st-cut
{
if (((tx_cal_reg[0]==7) || (tx_cal_reg[0]==(-8))) &&
((tx_cal_reg[3]==7) || (tx_cal_reg[3]==(-8))))
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
break;
}
}
else // 2nd-cut
{
if (((tx_cal_reg[0]==31) || (tx_cal_reg[0]==(-32))) &&
((tx_cal_reg[3]==31) || (tx_cal_reg[3]==(-32))))
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
break;
}
}
tx_cal[0] = tx_cal[0] + tx_cal_reg[0];
tx_cal[1] = tx_cal[1] + tx_cal_reg[1];
tx_cal[2] = tx_cal[2] + tx_cal_reg[2];
tx_cal[3] = tx_cal[3] + tx_cal_reg[3];
PHY_DEBUG(("[CAL] ** apply tx_cal[0] = %d\n", tx_cal[0]));
PHY_DEBUG(("[CAL] apply tx_cal[1] = %d\n", tx_cal[1]));
PHY_DEBUG(("[CAL] apply tx_cal[2] = %d\n", tx_cal[2]));
PHY_DEBUG(("[CAL] apply tx_cal[3] = %d\n", tx_cal[3]));
if (phw_data->revision == 0x2002) // 1st-cut
{
val &= 0x0000FFFF;
val |= ((_s32_to_s4(tx_cal[0]) << 28)|
(_s32_to_s4(tx_cal[1]) << 24)|
(_s32_to_s4(tx_cal[2]) << 20)|
(_s32_to_s4(tx_cal[3]) << 16));
hw_set_dxx_reg(phw_data, 0x54, val);
PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val));
return 0;
}
else // 2nd-cut
{
val &= 0x000003FF;
val |= ((_s32_to_s5(tx_cal[0]) << 27)|
(_s32_to_s6(tx_cal[1]) << 21)|
(_s32_to_s6(tx_cal[2]) << 15)|
(_s32_to_s5(tx_cal[3]) << 10));
hw_set_dxx_reg(phw_data, 0x3C, val);
PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION = 0x%08X\n", val));
return 0;
}
// i. Set "calib_start" to 0x0
reg_mode_ctrl &= ~MASK_CALIB_START;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
loop--;
}
return 1;
}
void _tx_iq_calibration_winbond(hw_data_t *phw_data)
{
u32 reg_agc_ctrl3;
#ifdef _DEBUG
s32 tx_cal_reg[4];
#endif
u32 reg_mode_ctrl;
u32 val;
u8 result;
PHY_DEBUG(("[CAL] -> [4]_tx_iq_calibration()\n"));
//0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits
phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
//0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit
phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); // 20060612.1.a 0x1905D6);
//0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized
phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); //0x24C60A (high temperature)
//0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized
phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); // 20060612.1.a 0x06890C);
//0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode
phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
//; [BB-chip]: Calibration (6f).Send test pattern
//; [BB-chip]: Calibration (6g). Search RXGCL optimal value
//; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table
//phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
OS_SLEEP(30000); // 20060612.1.a 30ms delay. Add the follow 2 lines
//To adjust TXVGA to fit iq_mag_0 range from 1250 ~ 1750
adjust_TXVGA_for_iq_mag( phw_data );
// a. Disable AGC
hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
reg_agc_ctrl3 &= ~BIT(2);
reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
val |= MASK_AGC_FIX_GAIN;
hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
result = _tx_iq_calibration_loop_winbond(phw_data, 150, 100);
if (result > 0)
{
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
val &= 0x0000FFFF;
hw_set_dxx_reg(phw_data, 0x54, val);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
val &= 0x000003FF;
hw_set_dxx_reg(phw_data, 0x3C, val);
}
result = _tx_iq_calibration_loop_winbond(phw_data, 300, 200);
if (result > 0)
{
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
val &= 0x0000FFFF;
hw_set_dxx_reg(phw_data, 0x54, val);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
val &= 0x000003FF;
hw_set_dxx_reg(phw_data, 0x3C, val);
}
result = _tx_iq_calibration_loop_winbond(phw_data, 500, 400);
if (result > 0)
{
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
val &= 0x0000FFFF;
hw_set_dxx_reg(phw_data, 0x54, val);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
val &= 0x000003FF;
hw_set_dxx_reg(phw_data, 0x3C, val);
}
result = _tx_iq_calibration_loop_winbond(phw_data, 700, 500);
if (result > 0)
{
PHY_DEBUG(("[CAL] ** <_tx_iq_calibration> **************\n"));
PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION FAILURE !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
val &= 0x0000FFFF;
hw_set_dxx_reg(phw_data, 0x54, val);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
val &= 0x000003FF;
hw_set_dxx_reg(phw_data, 0x3C, val);
}
}
}
}
}
// i. Set "calib_start" to 0x0
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
reg_mode_ctrl &= ~MASK_CALIB_START;
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
// g. Enable AGC
//hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val);
reg_agc_ctrl3 |= BIT(2);
reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
#ifdef _DEBUG
if (phw_data->revision == 0x2002) // 1st-cut
{
hw_get_dxx_reg(phw_data, 0x54, &val);
PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28);
tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24);
tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20);
tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16);
}
else // 2nd-cut
{
hw_get_dxx_reg(phw_data, 0x3C, &val);
PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val));
tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
}
PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0]));
PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1]));
PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2]));
PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3]));
#endif
// for test - BEN
// RF Control Override
}
/////////////////////////////////////////////////////////////////////////////////////////
u8 _rx_iq_calibration_loop_winbond(hw_data_t *phw_data, u16 factor, u32 frequency)
{
u32 reg_mode_ctrl;
s32 iqcal_tone_i;
s32 iqcal_tone_q;
s32 iqcal_image_i;
s32 iqcal_image_q;
s32 rot_tone_i_b;
s32 rot_tone_q_b;
s32 rot_image_i_b;
s32 rot_image_q_b;
s32 rx_cal_flt_b[4];
s32 rx_cal[4];
s32 rx_cal_reg[4];
s32 a_2, b_2;
s32 sin_b, sin_2b;
s32 cos_b, cos_2b;
s32 temp1, temp2;
u32 val;
u16 loop;
u32 pwr_tone;
u32 pwr_image;
u8 verify_count;
s32 iqcal_tone_i_avg,iqcal_tone_q_avg;
s32 iqcal_image_i_avg,iqcal_image_q_avg;
u16 capture_time;
PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration_loop()\n"));
PHY_DEBUG(("[CAL] ** factor = %d\n", factor));
// RF Control Override
hw_get_cxx_reg(phw_data, 0x80, &val);
val |= BIT(19);
hw_set_cxx_reg(phw_data, 0x80, val);
// RF_Ctrl
hw_get_cxx_reg(phw_data, 0xE4, &val);
val |= BIT(0);
hw_set_cxx_reg(phw_data, 0xE4, val);
PHY_DEBUG(("[CAL] ** RF_CTRL(0xE4) = 0x%08X", val));
hw_set_dxx_reg(phw_data, 0x58, 0x44444444); // IQ_Alpha
// b.
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
verify_count = 0;
//for (loop = 0; loop < 1; loop++)
//for (loop = 0; loop < LOOP_TIMES; loop++)
loop = LOOP_TIMES;
while (loop > 0)
{
PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
iqcal_tone_i_avg=0;
iqcal_tone_q_avg=0;
iqcal_image_i_avg=0;
iqcal_image_q_avg=0;
capture_time=0;
for(capture_time=0; capture_time<10; capture_time++)
{
// i. Set "calib_start" to 0x0
reg_mode_ctrl &= ~MASK_CALIB_START;
if( !hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl) )//20060718.1 modify
return 0;
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US);
reg_mode_ctrl &= ~MASK_IQCAL_MODE;
reg_mode_ctrl |= (MASK_CALIB_START|0x1);
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
pa_stall_execution(US); //Should be read out after 450us
// c.
hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
iqcal_tone_i, iqcal_tone_q));
hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val));
iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n",
iqcal_image_i, iqcal_image_q));
if( capture_time == 0)
{
continue;
}
else
{
iqcal_image_i_avg=( iqcal_image_i_avg*(capture_time-1) +iqcal_image_i)/capture_time;
iqcal_image_q_avg=( iqcal_image_q_avg*(capture_time-1) +iqcal_image_q)/capture_time;
iqcal_tone_i_avg=( iqcal_tone_i_avg*(capture_time-1) +iqcal_tone_i)/capture_time;
iqcal_tone_q_avg=( iqcal_tone_q_avg*(capture_time-1) +iqcal_tone_q)/capture_time;
}
}
iqcal_image_i = iqcal_image_i_avg;
iqcal_image_q = iqcal_image_q_avg;
iqcal_tone_i = iqcal_tone_i_avg;
iqcal_tone_q = iqcal_tone_q_avg;
// d.
rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i +
iqcal_tone_q * iqcal_tone_q) / 1024;
rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) +
iqcal_tone_q * iqcal_tone_i) / 1024;
rot_image_i_b = (iqcal_image_i * iqcal_tone_i -
iqcal_image_q * iqcal_tone_q) / 1024;
rot_image_q_b = (iqcal_image_i * iqcal_tone_q +
iqcal_image_q * iqcal_tone_i) / 1024;
PHY_DEBUG(("[CAL] ** rot_tone_i_b = %d\n", rot_tone_i_b));
PHY_DEBUG(("[CAL] ** rot_tone_q_b = %d\n", rot_tone_q_b));
PHY_DEBUG(("[CAL] ** rot_image_i_b = %d\n", rot_image_i_b));
PHY_DEBUG(("[CAL] ** rot_image_q_b = %d\n", rot_image_q_b));
// f.
if (rot_tone_i_b == 0)
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n"));
PHY_DEBUG(("[CAL] ** rot_tone_i_b=0 to calculate EPS and THETA !!\n"));
PHY_DEBUG(("[CAL] ******************************************\n"));
break;
}
a_2 = (rot_image_i_b * 32768) / rot_tone_i_b -
phw_data->iq_rsdl_gain_tx_d2;
b_2 = (rot_image_q_b * 32768) / rot_tone_i_b -
phw_data->iq_rsdl_phase_tx_d2;
PHY_DEBUG(("[CAL] ** iq_rsdl_gain_tx_d2 = %d\n", phw_data->iq_rsdl_gain_tx_d2));
PHY_DEBUG(("[CAL] ** iq_rsdl_phase_tx_d2= %d\n", phw_data->iq_rsdl_phase_tx_d2));
PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2));
PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2));
_sin_cos(b_2, &sin_b, &cos_b);
_sin_cos(b_2*2, &sin_2b, &cos_2b);
PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b));
PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b));
if (cos_2b == 0)
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n"));
PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n"));
PHY_DEBUG(("[CAL] ******************************************\n"));
break;
}
// 1280 * 32768 = 41943040
temp1 = (41943040/cos_2b)*cos_b;
//temp2 = (41943040/cos_2b)*sin_b*(-1);
if (phw_data->revision == 0x2002) // 1st-cut
{
temp2 = (41943040/cos_2b)*sin_b*(-1);
}
else // 2nd-cut
{
temp2 = (41943040*4/cos_2b)*sin_b*(-1);
}
rx_cal_flt_b[0] = _floor(temp1/(32768+a_2));
rx_cal_flt_b[1] = _floor(temp2/(32768-a_2));
rx_cal_flt_b[2] = _floor(temp2/(32768+a_2));
rx_cal_flt_b[3] = _floor(temp1/(32768-a_2));
PHY_DEBUG(("[CAL] ** rx_cal_flt_b[0] = %d\n", rx_cal_flt_b[0]));
PHY_DEBUG(("[CAL] rx_cal_flt_b[1] = %d\n", rx_cal_flt_b[1]));
PHY_DEBUG(("[CAL] rx_cal_flt_b[2] = %d\n", rx_cal_flt_b[2]));
PHY_DEBUG(("[CAL] rx_cal_flt_b[3] = %d\n", rx_cal_flt_b[3]));
rx_cal[0] = rx_cal_flt_b[0] - 128;
rx_cal[1] = rx_cal_flt_b[1];
rx_cal[2] = rx_cal_flt_b[2];
rx_cal[3] = rx_cal_flt_b[3] - 128;
PHY_DEBUG(("[CAL] ** rx_cal[0] = %d\n", rx_cal[0]));
PHY_DEBUG(("[CAL] rx_cal[1] = %d\n", rx_cal[1]));
PHY_DEBUG(("[CAL] rx_cal[2] = %d\n", rx_cal[2]));
PHY_DEBUG(("[CAL] rx_cal[3] = %d\n", rx_cal[3]));
// e.
pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q);
pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor;
PHY_DEBUG(("[CAL] ** pwr_tone = %d\n", pwr_tone));
PHY_DEBUG(("[CAL] ** pwr_image = %d\n", pwr_image));
if (pwr_tone > pwr_image)
{
verify_count++;
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *************\n"));
PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count));
PHY_DEBUG(("[CAL] ******************************************\n"));
if (verify_count > 2)
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION OK !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
return 0;
}
continue;
}
// g.
hw_get_dxx_reg(phw_data, 0x54, &val);
PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
if (phw_data->revision == 0x2002) // 1st-cut
{
rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12);
rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8);
rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4);
rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F));
}
else // 2nd-cut
{
rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
}
PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0]));
PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1]));
PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2]));
PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3]));
if (phw_data->revision == 0x2002) // 1st-cut
{
if (((rx_cal_reg[0]==7) || (rx_cal_reg[0]==(-8))) &&
((rx_cal_reg[3]==7) || (rx_cal_reg[3]==(-8))))
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
break;
}
}
else // 2nd-cut
{
if (((rx_cal_reg[0]==31) || (rx_cal_reg[0]==(-32))) &&
((rx_cal_reg[3]==31) || (rx_cal_reg[3]==(-32))))
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n"));
PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
break;
}
}
rx_cal[0] = rx_cal[0] + rx_cal_reg[0];
rx_cal[1] = rx_cal[1] + rx_cal_reg[1];
rx_cal[2] = rx_cal[2] + rx_cal_reg[2];
rx_cal[3] = rx_cal[3] + rx_cal_reg[3];
PHY_DEBUG(("[CAL] ** apply rx_cal[0] = %d\n", rx_cal[0]));
PHY_DEBUG(("[CAL] apply rx_cal[1] = %d\n", rx_cal[1]));
PHY_DEBUG(("[CAL] apply rx_cal[2] = %d\n", rx_cal[2]));
PHY_DEBUG(("[CAL] apply rx_cal[3] = %d\n", rx_cal[3]));
hw_get_dxx_reg(phw_data, 0x54, &val);
if (phw_data->revision == 0x2002) // 1st-cut
{
val &= 0x0000FFFF;
val |= ((_s32_to_s4(rx_cal[0]) << 12)|
(_s32_to_s4(rx_cal[1]) << 8)|
(_s32_to_s4(rx_cal[2]) << 4)|
(_s32_to_s4(rx_cal[3])));
hw_set_dxx_reg(phw_data, 0x54, val);
}
else // 2nd-cut
{
val &= 0x000003FF;
val |= ((_s32_to_s5(rx_cal[0]) << 27)|
(_s32_to_s6(rx_cal[1]) << 21)|
(_s32_to_s6(rx_cal[2]) << 15)|
(_s32_to_s5(rx_cal[3]) << 10));
hw_set_dxx_reg(phw_data, 0x54, val);
if( loop == 3 )
return 0;
}
PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val));
loop--;
}
return 1;
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void _rx_iq_calibration_winbond(hw_data_t *phw_data, u32 frequency)
{
// figo 20050523 marked thsi flag for can't compile for relesase
#ifdef _DEBUG
s32 rx_cal_reg[4];
u32 val;
#endif
u8 result;
PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration()\n"));
// a. Set RFIC to "RX calibration mode"
//; ----- Calibration (7). RX path IQ imbalance calibration loop
// 0x01 0xFFBFC2 ; 3FEFF ; Calibration (7a). enable RX IQ calibration loop circuits
phy_set_rf_data(phw_data, 1, (1<<24)|0xEFBFC2);
// 0x0B 0x1A01D6 ; 06817 ; Calibration (7b). enable RX I/Q cal loop SW1 circuit
phy_set_rf_data(phw_data, 11, (11<<24)|0x1A05D6);
//0x05 0x24848A ; 09212 ; Calibration (7c). setting TX-VGA gain (TXGCH) to 2 --> to be optimized
phy_set_rf_data(phw_data, 5, (5<<24)| phw_data->txvga_setting_for_cal);
//0x06 0x06840C ; 01A10 ; Calibration (7d). RXGCH=00; RXGCL=010 000 (RXVGA) --> to be optimized
phy_set_rf_data(phw_data, 6, (6<<24)|0x06834C);
//0x00 0xFFF1C0 ; 3F7C7 ; Calibration (7e). turn on IQ imbalance/Test mode
phy_set_rf_data(phw_data, 0, (0<<24)|0xFFF1C0);
// ; [BB-chip]: Calibration (7f). Send test pattern
// ; [BB-chip]: Calibration (7g). Search RXGCL optimal value
// ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table
result = _rx_iq_calibration_loop_winbond(phw_data, 12589, frequency);
if (result > 0)
{
_reset_rx_cal(phw_data);
result = _rx_iq_calibration_loop_winbond(phw_data, 7943, frequency);
if (result > 0)
{
_reset_rx_cal(phw_data);
result = _rx_iq_calibration_loop_winbond(phw_data, 5011, frequency);
if (result > 0)
{
PHY_DEBUG(("[CAL] ** <_rx_iq_calibration> **************\n"));
PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION FAILURE !!\n"));
PHY_DEBUG(("[CAL] **************************************\n"));
_reset_rx_cal(phw_data);
}
}
}
#ifdef _DEBUG
hw_get_dxx_reg(phw_data, 0x54, &val);
PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val));
if (phw_data->revision == 0x2002) // 1st-cut
{
rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12);
rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8);
rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4);
rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F));
}
else // 2nd-cut
{
rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27);
rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21);
rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15);
rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10);
}
PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0]));
PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1]));
PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2]));
PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3]));
#endif
}
////////////////////////////////////////////////////////////////////////
void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency)
{
u32 reg_mode_ctrl;
u32 iq_alpha;
PHY_DEBUG(("[CAL] -> phy_calibration_winbond()\n"));
// 20040701 1.1.25.1000 kevin
hw_get_cxx_reg(phw_data, 0x80, &mac_ctrl);
hw_get_cxx_reg(phw_data, 0xE4, &rf_ctrl);
hw_get_dxx_reg(phw_data, 0x58, &iq_alpha);
_rxadc_dc_offset_cancellation_winbond(phw_data, frequency);
//_txidac_dc_offset_cancellation_winbond(phw_data);
//_txqdac_dc_offset_cacellation_winbond(phw_data);
_tx_iq_calibration_winbond(phw_data);
_rx_iq_calibration_winbond(phw_data, frequency);
//------------------------------------------------------------------------
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE|MASK_CALIB_START); // set when finish
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
// i. Set RFIC to "Normal mode"
hw_set_cxx_reg(phw_data, 0x80, mac_ctrl);
hw_set_cxx_reg(phw_data, 0xE4, rf_ctrl);
hw_set_dxx_reg(phw_data, 0x58, iq_alpha);
//------------------------------------------------------------------------
phy_init_rf(phw_data);
}
//===========================
void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value )
{
u32 ltmp=0;
switch( pHwData->phy_type )
{
case RF_MAXIM_2825:
case RF_MAXIM_V1: // 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331)
ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
break;
case RF_MAXIM_2827:
ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
break;
case RF_MAXIM_2828:
ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
break;
case RF_MAXIM_2829:
ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse( value, 18 );
break;
case RF_AIROHA_2230:
case RF_AIROHA_2230S: // 20060420 Add this
ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse( value, 20 );
break;
case RF_AIROHA_7230:
ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
break;
case RF_WB_242:
case RF_WB_242_1: // 20060619.5 Add
ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse( value, 24 );
break;
}
Wb35Reg_WriteSync( pHwData, 0x0864, ltmp );
}
// 20060717 modify as Bruce's mail
unsigned char adjust_TXVGA_for_iq_mag(hw_data_t *phw_data)
{
int init_txvga = 0;
u32 reg_mode_ctrl;
u32 val;
s32 iqcal_tone_i0;
s32 iqcal_tone_q0;
u32 sqsum;
s32 iq_mag_0_tx;
u8 reg_state;
int current_txvga;
reg_state = 0;
for( init_txvga=0; init_txvga<10; init_txvga++)
{
current_txvga = ( 0x24C40A|(init_txvga<<6) );
phy_set_rf_data(phw_data, 5, ((5<<24)|current_txvga) );
phw_data->txvga_setting_for_cal = current_txvga;
//pa_stall_execution(30000);//Sleep(30);
OS_SLEEP(30000); // 20060612.1.a
if( !hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl) ) // 20060718.1 modify
return FALSE;
PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
// a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
// enable "IQ alibration Mode II"
reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
reg_mode_ctrl &= ~MASK_IQCAL_MODE;
reg_mode_ctrl |= (MASK_CALIB_START|0x02);
reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2);
hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
//pa_stall_execution(US);
OS_SLEEP(1); // 20060612.1.a
//pa_stall_execution(300);//Sleep(30);
OS_SLEEP(300); // 20060612.1.a
// b.
hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val));
//pa_stall_execution(US);
//pa_stall_execution(300);//Sleep(30);
OS_SLEEP(300); // 20060612.1.a
iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF);
iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n",
iqcal_tone_i0, iqcal_tone_q0));
sqsum = iqcal_tone_i0*iqcal_tone_i0 + iqcal_tone_q0*iqcal_tone_q0;
iq_mag_0_tx = (s32) _sqrt(sqsum);
PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx));
if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 )
break;
else if(iq_mag_0_tx > 1750)
{
init_txvga=-2;
continue;
}
else
continue;
}
if( iq_mag_0_tx>=700 && iq_mag_0_tx<=1750 )
return TRUE;
else
return FALSE;
}
// 20031229 Turbo add
#define REG_AGC_CTRL1 0x1000
#define REG_AGC_CTRL2 0x1004
#define REG_AGC_CTRL3 0x1008
#define REG_AGC_CTRL4 0x100C
#define REG_AGC_CTRL5 0x1010
#define REG_AGC_CTRL6 0x1014
#define REG_AGC_CTRL7 0x1018
#define REG_AGC_CTRL8 0x101C
#define REG_AGC_CTRL9 0x1020
#define REG_AGC_CTRL10 0x1024
#define REG_CCA_CTRL 0x1028
#define REG_A_ACQ_CTRL 0x102C
#define REG_B_ACQ_CTRL 0x1030
#define REG_A_TXRX_CTRL 0x1034
#define REG_B_TXRX_CTRL 0x1038
#define REG_A_TX_COEF3 0x103C
#define REG_A_TX_COEF2 0x1040
#define REG_A_TX_COEF1 0x1044
#define REG_B_TX_COEF2 0x1048
#define REG_B_TX_COEF1 0x104C
#define REG_MODE_CTRL 0x1050
#define REG_CALIB_DATA 0x1054
#define REG_IQ_ALPHA 0x1058
#define REG_DC_CANCEL 0x105C
#define REG_WTO_READ 0x1060
#define REG_OFFSET_READ 0x1064
#define REG_CALIB_READ1 0x1068
#define REG_CALIB_READ2 0x106C
#define REG_A_FREQ_EST 0x1070
// 20031101 Turbo add
#define MASK_AMER_OFF_REG BIT(31)
#define MASK_BMER_OFF_REG BIT(31)
#define MASK_LNA_FIX_GAIN (BIT(3)|BIT(4))
#define MASK_AGC_FIX BIT(1)
#define MASK_AGC_FIX_GAIN 0xFF00
#define MASK_ADC_DC_CAL_STR BIT(10)
#define MASK_CALIB_START BIT(4)
#define MASK_IQCAL_TONE_SEL (BIT(3)|BIT(2))
#define MASK_IQCAL_MODE (BIT(1)|BIT(0))
#define MASK_TX_CAL_0 0xF0000000
#define TX_CAL_0_SHIFT 28
#define MASK_TX_CAL_1 0x0F000000
#define TX_CAL_1_SHIFT 24
#define MASK_TX_CAL_2 0x00F00000
#define TX_CAL_2_SHIFT 20
#define MASK_TX_CAL_3 0x000F0000
#define TX_CAL_3_SHIFT 16
#define MASK_RX_CAL_0 0x0000F000
#define RX_CAL_0_SHIFT 12
#define MASK_RX_CAL_1 0x00000F00
#define RX_CAL_1_SHIFT 8
#define MASK_RX_CAL_2 0x000000F0
#define RX_CAL_2_SHIFT 4
#define MASK_RX_CAL_3 0x0000000F
#define RX_CAL_3_SHIFT 0
#define MASK_CANCEL_DC_I 0x3E0
#define CANCEL_DC_I_SHIFT 5
#define MASK_CANCEL_DC_Q 0x01F
#define CANCEL_DC_Q_SHIFT 0
// LA20040210 kevin
//#define MASK_ADC_DC_CAL_I(x) (((x)&0x1FE00)>>9)
//#define MASK_ADC_DC_CAL_Q(x) ((x)&0x1FF)
#define MASK_ADC_DC_CAL_I(x) (((x)&0x0003FE00)>>9)
#define MASK_ADC_DC_CAL_Q(x) ((x)&0x000001FF)
// LA20040210 kevin (Turbo has wrong definition)
//#define MASK_IQCAL_TONE_I 0x7FFC000
//#define SHIFT_IQCAL_TONE_I(x) ((x)>>13)
//#define MASK_IQCAL_TONE_Q 0x1FFF
//#define SHIFT_IQCAL_TONE_Q(x) ((x)>>0)
#define MASK_IQCAL_TONE_I 0x00001FFF
#define SHIFT_IQCAL_TONE_I(x) ((x)>>0)
#define MASK_IQCAL_TONE_Q 0x03FFE000
#define SHIFT_IQCAL_TONE_Q(x) ((x)>>13)
// LA20040210 kevin (Turbo has wrong definition)
//#define MASK_IQCAL_IMAGE_I 0x7FFC000
//#define SHIFT_IQCAL_IMAGE_I(x) ((x)>>13)
//#define MASK_IQCAL_IMAGE_Q 0x1FFF
//#define SHIFT_IQCAL_IMAGE_Q(x) ((x)>>0)
//#define MASK_IQCAL_IMAGE_I 0x00001FFF
//#define SHIFT_IQCAL_IMAGE_I(x) ((x)>>0)
//#define MASK_IQCAL_IMAGE_Q 0x03FFE000
//#define SHIFT_IQCAL_IMAGE_Q(x) ((x)>>13)
void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value );
#define phy_init_rf( _A ) //RFSynthesizer_initial( _A )
This source diff could not be displayed because it is too large. You can view the blob instead.
#include "os_common.h"
void vRxTimerInit(PWB32_ADAPTER Adapter)
{
OS_TIMER_INITIAL(&(Adapter->Mds.nTimer), (void*) RxTimerHandler, (void*) Adapter);
}
void vRxTimerStart(PWB32_ADAPTER Adapter, int timeout_value)
{
if (timeout_value<MIN_TIMEOUT_VAL)
timeout_value=MIN_TIMEOUT_VAL;
OS_TIMER_SET( &(Adapter->Mds.nTimer), timeout_value );
}
void vRxTimerStop(PWB32_ADAPTER Adapter)
{
OS_TIMER_CANCEL( &(Adapter->Mds.nTimer), 0 );
}
void RxTimerHandler_1a( PADAPTER Adapter)
{
RxTimerHandler(NULL, Adapter, NULL, NULL);
}
void RxTimerHandler(void* SystemSpecific1, PWB32_ADAPTER Adapter,
void* SystemSpecific2, void* SystemSpecific3)
{
WARN_ON(1);
}
//
// SCAN task global CONSTANTS, STRUCTURES, variables
//
//////////////////////////////////////////////////////////////////////////
//define the msg type of SCAN module
#define SCANMSG_SCAN_REQ 0x01
#define SCANMSG_BEACON 0x02
#define SCANMSG_PROBE_RESPONSE 0x03
#define SCANMSG_TIMEOUT 0x04
#define SCANMSG_TXPROBE_FAIL 0x05
#define SCANMSG_ENABLE_BGSCAN 0x06
#define SCANMSG_STOP_SCAN 0x07
// BSS Type =>conform to
// IBSS : ToDS/FromDS = 00
// Infrastructure : ToDS/FromDS = 01
#define IBSS_NET 0
#define ESS_NET 1
#define ANYBSS_NET 2
// Scan Type
#define ACTIVE_SCAN 0
#define PASSIVE_SCAN 1
///////////////////////////////////////////////////////////////////////////
//Global data structures, Initial Scan & Background Scan
typedef struct _SCAN_REQ_PARA //mandatory parameters for SCAN request
{
u32 ScanType; //passive/active scan
CHAN_LIST sChannelList; // 86B
u8 reserved_1[2];
struct SSID_Element sSSID; // 34B. scan only for this SSID
u8 reserved_2[2];
} SCAN_REQ_PARA, *psSCAN_REQ_PARA;
typedef struct _SCAN_PARAMETERS
{
u16 wState;
u16 iCurrentChannelIndex;
SCAN_REQ_PARA sScanReq;
u8 BSSID[MAC_ADDR_LENGTH + 2]; //scan only for this BSSID
u32 BssType; //scan only for this BSS type
//struct SSID_Element sSSID; //scan only for this SSID
u16 ProbeDelay;
u16 MinChannelTime;
u16 MaxChannelTime;
u16 reserved_1;
s32 iBgScanPeriod; // XP: 5 sec
u8 boBgScan; // Wb: enable BG scan, For XP, this value must be FALSE
u8 boFastScan; // Wb: reserved
u8 boCCAbusy; // Wb: HWMAC CCA busy status
u8 reserved_2;
//NDIS_MINIPORT_TIMER nTimer;
OS_TIMER nTimer;
u32 ScanTimeStamp; //Increase 1 per background scan(1 minute)
u32 BssTimeStamp; //Increase 1 per connect status check
u32 RxNumPerAntenna[2]; //
u8 AntennaToggle; //
u8 boInTimerHandler;
u8 boTimerActive; // Wb: reserved
u8 boSave;
u32 BScanEnable; // Background scan enable. Default is On
} SCAN_PARAMETERS, *psSCAN_PARAMETERS;
// Encapsulate 'Adapter' data structure
#define psSCAN (&(Adapter->sScanPara))
#define psSCANREQ (&(Adapter->sScanPara.sScanReq))
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// scan.h
// Define the related definitions of scan module
// history -- 01/14/03' created
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Define the state of scan module
#define SCAN_INACTIVE 0
#define WAIT_PROBE_DELAY 1
#define WAIT_RESPONSE_MIN 2
#define WAIT_RESPONSE_MAX_ACTIVE 3
#define WAIT_BEACON_MAX_PASSIVE 4
#define SCAN_COMPLETE 5
#define BG_SCAN 6
#define BG_SCANNING 7
// The value will load from EEPROM
// If 0xff is set in EEPOM, the driver will use SCAN_MAX_CHNL_TIME instead.
// The definition is in WbHal.h
// #define SCAN_MAX_CHNL_TIME (50)
// static functions
//static void ScanTimerHandler(PWB32_ADAPTER Adapter);
//static void vScanTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
//static void vScanTimerStop(PWB32_ADAPTER Adapter);
//------------------------------------------------------------------------------------
// sme_api.c
//
// Copyright(C) 2002 Winbond Electronics Corp.
//
//
//------------------------------------------------------------------------------------
#include "os_common.h"
s8 sme_get_rssi(void *pcore_data, s32 *prssi)
{
BUG();
}
/*
* sme_api.h
*
* Copyright(C) 2002 Winbond Electronics Corp.
*
* modification history
* ---------------------------------------------------------------------------
* 1.00.001, 2003-04-21, Kevin created
* 1.00.002, 2003-05-14, PD43 & PE20 modified
*
*/
#ifndef __SME_API_H__
#define __SME_API_H__
/****************** INCLUDE FILES SECTION ***********************************/
//#include "GL\gl_core.h"
/****************** CONSTANT AND MACRO SECTION ******************************/
#define _INLINE __inline
#define MEDIA_STATE_DISCONNECTED 0
#define MEDIA_STATE_CONNECTED 1
//ARRAY CHECK
#define MAX_POWER_TO_DB 32
/****************** TYPE DEFINITION SECTION *********************************/
/****************** EXPORTED FUNCTION DECLARATION SECTION *******************/
// OID_802_11_BSSID
s8 sme_get_bssid(void *pcore_data, u8 *pbssid);
s8 sme_get_desired_bssid(void *pcore_data, u8 *pbssid);//Not use
s8 sme_set_desired_bssid(void *pcore_data, u8 *pbssid);
// OID_802_11_SSID
s8 sme_get_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);
s8 sme_get_desired_ssid(void *pcore_data, u8 *pssid, u8 *pssid_len);// Not use
s8 sme_set_desired_ssid(void *pcore_data, u8 *pssid, u8 ssid_len);
// OID_802_11_INFRASTRUCTURE_MODE
s8 sme_get_bss_type(void *pcore_data, u8 *pbss_type);
s8 sme_get_desired_bss_type(void *pcore_data, u8 *pbss_type);//Not use
s8 sme_set_desired_bss_type(void *pcore_data, u8 bss_type);
// OID_802_11_FRAGMENTATION_THRESHOLD
s8 sme_get_fragment_threshold(void *pcore_data, u32 *pthreshold);
s8 sme_set_fragment_threshold(void *pcore_data, u32 threshold);
// OID_802_11_RTS_THRESHOLD
s8 sme_get_rts_threshold(void *pcore_data, u32 *pthreshold);
s8 sme_set_rts_threshold(void *pcore_data, u32 threshold);
// OID_802_11_RSSI
s8 sme_get_rssi(void *pcore_data, s32 *prssi);
// OID_802_11_CONFIGURATION
s8 sme_get_beacon_period(void *pcore_data, u16 *pbeacon_period);
s8 sme_set_beacon_period(void *pcore_data, u16 beacon_period);
s8 sme_get_atim_window(void *pcore_data, u16 *patim_window);
s8 sme_set_atim_window(void *pcore_data, u16 atim_window);
s8 sme_get_current_channel(void *pcore_data, u8 *pcurrent_channel);
s8 sme_get_current_band(void *pcore_data, u8 *pcurrent_band);
s8 sme_set_current_channel(void *pcore_data, u8 current_channel);
// OID_802_11_BSSID_LIST
s8 sme_get_scan_bss_count(void *pcore_data, u8 *pcount);
s8 sme_get_scan_bss(void *pcore_data, u8 index, void **ppbss);
s8 sme_get_connected_bss(void *pcore_data, void **ppbss_now);
// OID_802_11_AUTHENTICATION_MODE
s8 sme_get_auth_mode(void *pcore_data, u8 *pauth_mode);
s8 sme_set_auth_mode(void *pcore_data, u8 auth_mode);
// OID_802_11_WEP_STATUS / OID_802_11_ENCRYPTION_STATUS
s8 sme_get_wep_mode(void *pcore_data, u8 *pwep_mode);
s8 sme_set_wep_mode(void *pcore_data, u8 wep_mode);
//s8 sme_get_encryption_status(void *pcore_data, u8 *pstatus);
//s8 sme_set_encryption_status(void *pcore_data, u8 status);
// ???????????????????????????????????????
// OID_GEN_VENDOR_ID
// OID_802_3_PERMANENT_ADDRESS
s8 sme_get_permanent_mac_addr(void *pcore_data, u8 *pmac_addr);
// OID_802_3_CURRENT_ADDRESS
s8 sme_get_current_mac_addr(void *pcore_data, u8 *pmac_addr);
// OID_802_11_NETWORK_TYPE_IN_USE
s8 sme_get_network_type_in_use(void *pcore_data, u8 *ptype);
s8 sme_set_network_type_in_use(void *pcore_data, u8 type);
// OID_802_11_SUPPORTED_RATES
s8 sme_get_supported_rate(void *pcore_data, u8 *prates);
// OID_802_11_ADD_WEP
//12/29/03' wkchen
s8 sme_set_add_wep(void *pcore_data, u32 key_index, u32 key_len,
u8 *Address, u8 *key);
// OID_802_11_REMOVE_WEP
s8 sme_set_remove_wep(void *pcre_data, u32 key_index);
// OID_802_11_DISASSOCIATE
s8 sme_set_disassociate(void *pcore_data);
// OID_802_11_POWER_MODE
s8 sme_get_power_mode(void *pcore_data, u8 *pmode);
s8 sme_set_power_mode(void *pcore_data, u8 mode);
// OID_802_11_BSSID_LIST_SCAN
s8 sme_set_bssid_list_scan(void *pcore_data, void *pscan_para);
// OID_802_11_RELOAD_DEFAULTS
s8 sme_set_reload_defaults(void *pcore_data, u8 reload_type);
// The following SME API functions are used for WPA
//
// Mandatory OIDs for WPA
//
// OID_802_11_ADD_KEY
//s8 sme_set_add_key(void *pcore_data, NDIS_802_11_KEY *pkey);
// OID_802_11_REMOVE_KEY
//s8 sme_set_remove_key(void *pcore_data, NDIS_802_11_REMOVE_KEY *pkey);
// OID_802_11_ASSOCIATION_INFORMATION
//s8 sme_set_association_information(void *pcore_data,
// NDIS_802_11_ASSOCIATION_INFORMATION *pinfo);
// OID_802_11_TEST
//s8 sme_set_test(void *pcore_data, NDIS_802_11_TEST *ptest_data);
//--------------------------------------------------------------------------//
/*
// The left OIDs
// OID_802_11_NETWORK_TYPES_SUPPORTED
// OID_802_11_TX_POWER_LEVEL
// OID_802_11_RSSI_TRIGGER
// OID_802_11_NUMBER_OF_ANTENNAS
// OID_802_11_RX_ANTENNA_SELECTED
// OID_802_11_TX_ANTENNA_SELECTED
// OID_802_11_STATISTICS
// OID_802_11_DESIRED_RATES
// OID_802_11_PRIVACY_FILTER
*/
/*------------------------- none-standard ----------------------------------*/
s8 sme_get_connect_status(void *pcore_data, u8 *pstatus);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//s8 sme_get_scan_type(void *pcore_data, u8 *pscan_type);
//s8 sme_set_scan_type(void *pcore_data, u8 scan_type);
//s8 sme_get_scan_channel_list(void *pcore_data, u8 *pscan_type);
//s8 sme_set_scan_channel_list(void *pcore_data, u8 scan_type);
void sme_get_encryption_status(void *pcore_data, u8 *EncryptStatus);
void sme_set_encryption_status(void *pcore_data, u8 EncryptStatus);
s8 sme_add_key(void *pcore_data,
u32 key_index,
u8 key_len,
u8 key_type,
u8 *key_bssid,
//u8 *key_rsc,
u8 *ptx_tsc,
u8 *prx_tsc,
u8 *key_material);
void sme_remove_default_key(void *pcore_data, int index);
void sme_remove_mapping_key(void *pcore_data, u8 *pmac_addr);
void sme_clear_all_mapping_key(void *pcore_data);
void sme_clear_all_default_key(void *pcore_data);
s8 sme_set_preamble_mode(void *pcore_data, u8 mode);
s8 sme_get_preamble_mode(void *pcore_data, u8 *mode);
s8 sme_get_preamble_type(void *pcore_data, u8 *type);
s8 sme_set_slottime_mode(void *pcore_data, u8 mode);
s8 sme_get_slottime_mode(void *pcore_data, u8 *mode);
s8 sme_get_slottime_type(void *pcore_data, u8 *type);
s8 sme_set_txrate_policy(void *pcore_data, u8 policy);
s8 sme_get_txrate_policy(void *pcore_data, u8 *policy);
s8 sme_get_cwmin_value(void *pcore_data, u8 *cwmin);
s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax);
s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff);
s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff);
s8 sme_get_radio_mode(void *pcore_data, psRadioOff pRadioOffData);
s8 sme_set_radio_mode(void *pcore_data, RadioOff RadioOffData);
void sme_get_tx_power_level(void *pcore_data, u32 *TxPower);
u8 sme_set_tx_power_level(void *pcore_data, u32 TxPower);
void sme_get_antenna_count(void *pcore_data, u32 *AntennaCount);
void sme_get_rx_antenna(void *pcore_data, u32 *RxAntenna);
u8 sme_set_rx_antenna(void *pcore_data, u32 RxAntenna);
void sme_get_tx_antenna(void *pcore_data, u32 *TxAntenna);
s8 sme_set_tx_antenna(void *pcore_data, u32 TxAntenna);
s8 sme_set_IBSS_chan(void *pcore_data, ChanInfo chan);
//20061108 WPS
s8 sme_set_IE_append(void *pcore_data, PUCHAR buffer, u16 buf_len);
//================== Local functions ======================
//#ifdef _HSINCHU
//void drv_translate_rssi(); // HW RSSI bit -> NDIS RSSI representation
//void drv_translate_bss_description(); // Local bss desc -> NDIS bss desc
//void drv_translate_channel(u8 NetworkType, u8 ChannelNumber, u32 *freq); // channel number -> channel /freq.
//#endif _HSINCHU
//
static const u32 PowerDbToMw[] =
{
56, //mW, MAX - 0, 17.5 dbm
40, //mW, MAX - 1, 16.0 dbm
30, //mW, MAX - 2, 14.8 dbm
20, //mW, MAX - 3, 13.0 dbm
15, //mW, MAX - 4, 11.8 dbm
12, //mW, MAX - 5, 10.6 dbm
9, //mW, MAX - 6, 9.4 dbm
7, //mW, MAX - 7, 8.3 dbm
5, //mW, MAX - 8, 6.4 dbm
4, //mW, MAX - 9, 5.3 dbm
3, //mW, MAX - 10, 4.0 dbm
2, //mW, MAX - 11, ? dbm
2, //mW, MAX - 12, ? dbm
2, //mW, MAX - 13, ? dbm
2, //mW, MAX - 14, ? dbm
2, //mW, MAX - 15, ? dbm
2, //mW, MAX - 16, ? dbm
2, //mW, MAX - 17, ? dbm
2, //mW, MAX - 18, ? dbm
1, //mW, MAX - 19, ? dbm
1, //mW, MAX - 20, ? dbm
1, //mW, MAX - 21, ? dbm
1, //mW, MAX - 22, ? dbm
1, //mW, MAX - 23, ? dbm
1, //mW, MAX - 24, ? dbm
1, //mW, MAX - 25, ? dbm
1, //mW, MAX - 26, ? dbm
1, //mW, MAX - 27, ? dbm
1, //mW, MAX - 28, ? dbm
1, //mW, MAX - 29, ? dbm
1, //mW, MAX - 30, ? dbm
1 //mW, MAX - 31, ? dbm
};
#endif /* __SME_API_H__ */
//
// SME_S.H -
// SME task global CONSTANTS, STRUCTURES, variables
//
//////////////////////////////////////////////////////////////////////////
//define the msg type of SME module
// 0x00~0x1F : MSG from GUI dispatch
// 0x20~0x3F : MSG from MLME
// 0x40~0x5F : MSG from SCAN
// 0x60~0x6F : MSG from TX/RX
// 0x70~0x7F : MSG from ROAMING
// 0x80~0x8F : MSG from ISR
// 0x90 : MSG TimeOut
// from GUI
#define SMEMSG_SCAN_REQ 0x01
//#define SMEMSG_PASSIVE_SCAN_REQ 0x02
#define SMEMSG_JOIN_REQ 0x03
#define SMEMSG_START_IBSS 0x04
#define SMEMSG_DISCONNECT_REQ 0x05
#define SMEMSG_AUTHEN_REQ 0x06
#define SMEMSG_DEAUTHEN_REQ 0x07
#define SMEMSG_ASSOC_REQ 0x08
#define SMEMSG_REASSOC_REQ 0x09
#define SMEMSG_DISASSOC_REQ 0x0a
#define SMEMSG_POWERSAVE_REQ 0x0b
// from MLME
#define SMEMSG_AUTHEN_CFM 0x21
#define SMEMSG_AUTHEN_IND 0x22
#define SMEMSG_ASSOC_CFM 0x23
#define SMEMSG_DEAUTHEN_IND 0x24
#define SMEMSG_DISASSOC_IND 0x25
// from SCAN
#define SMEMSG_SCAN_CFM 0x41
#define SMEMSG_START_IBSS_CFM 0x42
// from MTO, function call to set SME parameters
// 0x60~0x6F : MSG from TX/RX
//#define SMEMSG_IBSS_JOIN_UPDATE_BSSID 0x61
#define SMEMSG_COUNTERMEASURE_MICFAIL_TIMEOUT 0x62
#define SMEMSG_COUNTERMEASURE_BLOCK_TIMEOUT 0x63
// from ROAMING
#define SMEMSG_HANDOVER_JOIN_REQ 0x71
#define SMEMSG_END_ROAMING 0x72
#define SMEMSG_SCAN_JOIN_REQ 0x73
// from ISR
#define SMEMSG_TSF_SYNC_IND 0x81
// from TimeOut
#define SMEMSG_TIMEOUT 0x91
#define MAX_PMKID_Accunt 16
//@added by ws 04/22/05
#define Cipher_Disabled 0
#define Cipher_Wep 1
#define Cipher_Tkip 2
#define Cipher_Ccmp 4
///////////////////////////////////////////////////////////////////////////
//Constants
///////////////////////////////////////////////////////////////////////////
//Global data structures
#define NUMOFWEPENTRIES 64
typedef enum _WEPKeyMode
{
WEPKEY_DISABLED = 0,
WEPKEY_64 = 1,
WEPKEY_128 = 2
} WEPKEYMODE, *pWEPKEYMODE;
#ifdef _WPA2_
typedef struct _BSSInfo
{
u8 PreAuthBssID[6];
PMKID pmkid_value;
}BSSID_Info;
typedef struct _PMKID_Table //added by ws 05/05/04
{
u32 Length;
u32 BSSIDInfoCount;
BSSID_Info BSSIDInfo[16];
} PMKID_Table;
#endif //end def _WPA2_
#define MAX_BASIC_RATE_SET 15
#define MAX_OPT_RATE_SET MAX_BASIC_RATE_SET
typedef struct _SME_PARAMETERS
{
u16 wState;
u8 boDUTmode;
u8 bDesiredPowerSave;
// SME timer and timeout value
//NDIS_MINIPORT_TIMER nTimer;
OS_TIMER nTimer;
u8 boInTimerHandler;
u8 boAuthRetryActive;
u8 reserved_0[2];
u32 AuthenRetryTimerVal; // NOTE: Assoc don't fail timeout
u32 JoinFailTimerVal; // 10*Beacon-Interval
//Rates
u8 BSSBasicRateSet[(MAX_BASIC_RATE_SET + 3) & ~0x03 ]; // BSS basic rate set
u8 OperationalRateSet[(MAX_OPT_RATE_SET + 3) & ~0x03 ]; // Operational rate set
u8 NumOfBSSBasicRate;
u8 NumOfOperationalRate;
u8 reserved_1[2];
u32 BasicRateBitmap;
u32 OpRateBitmap;
// System parameters Set by GUI
//-------------------- start IBSS parameter ---------------------------//
u32 boStartIBSS; //Start IBSS toggle
u16 wBeaconPeriod;
u16 wATIM_Window;
ChanInfo IbssChan; // 2B //channel setting when start IBSS
u8 reserved_2[2];
// Join related
u16 wDesiredJoinBSS; // BSS index which desire to join
u8 boJoinReq; //Join request toggle
u8 bDesiredBSSType; //for Join request
u16 wCapabilityInfo; // Used when invoking the MLME_Associate_request().
u16 wNonERPcapabilityInfo;
struct SSID_Element sDesiredSSID; // 34 B
u8 reserved_3[2];
u8 abDesiredBSSID[MAC_ADDR_LENGTH + 2];
u8 bJoinScanCount; // the time of scan-join action need to do
u8 bDesiredAuthMode; // AUTH_OPEN_SYSTEM or AUTH_SHARED_KEY
u8 reserved_4[2];
// Encryption parameters
u8 _dot11PrivacyInvoked;
u8 _dot11PrivacyOptionImplemented;
u8 reserved_5[2];
//@ ws added
u8 DesiredEncrypt;
u8 encrypt_status; //ENCRYPT_DISABLE, ENCRYPT_WEP, ENCRYPT_WEP_NOKEY, ENCRYPT_TKIP, ...
u8 key_length;
u8 pairwise_key_ok;
u8 group_key_ok;
u8 wpa_ok; // indicate the control port of 802.1x is open or close
u8 pairwise_key_type;
u8 group_key_type;
u32 _dot11WEPDefaultKeyID;
u8 tx_mic_key[8]; // TODO: 0627 kevin-TKIP
u8 rx_mic_key[8]; // TODO: 0627 kevin-TKIP
u8 group_tx_mic_key[8];
u8 group_rx_mic_key[8];
// #ifdef _WPA_
u8 AssocReqVarIE[200];
u8 AssocRespVarIE[200];
u16 AssocReqVarLen;
u16 AssocRespVarLen;
u8 boReassoc; //use assoc. or reassoc.
u8 reserved_6[3];
u16 AssocRespCapability;
u16 AssocRespStatus;
// #endif
#ifdef _WPA2_
u8 PmkIdTable[256];
u32 PmkidTableIndex;
#endif //end def _WPA2_
} SME_PARAMETERS, *PSME_PARAMETERS;
#define psSME (&(Adapter->sSmePara))
#define wSMEGetCurrentSTAState(Adapter) ((u16)(Adapter)->sSmePara.wState)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// SmeModule.h
// Define the related definitions of SME module
// history -- 01/14/03' created
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Define the state of SME module
#define DISABLED 0
#define INIT_SCAN 1
#define SCAN_READY 2
#define START_IBSS 3
#define JOIN_PENDING 4
#define JOIN_CFM 5
#define AUTHENTICATE_PENDING 6
#define AUTHENTICATED 7
#define CONNECTED 8
//#define EAP_STARTING 9
//#define EAPOL_AUTHEN_PENDING 10
//#define SECURE_CONNECTED 11
// Static function
//
// Only define one of follow
//
#ifdef WB_WIN
#define VER_FILEVERSION 1,00,47,00
#define VER_FILEVERSION_STR "1.00.47.00"
#define WB32_DRIVER_MAJOR_VERSION 0x0100
#define WB32_DRIVER_MINOR_VERSION 0x4700
#endif
#ifdef WB_CE
#define VER_FILEVERSION 2,00,47,00
#define VER_FILEVERSION_STR "2.00.47.00"
#define WB32_DRIVER_MAJOR_VERSION 0x0200
#define WB32_DRIVER_MINOR_VERSION 0x4700
#endif
#ifdef WB_LINUX
#define VER_FILEVERSION 3,00,47,00
#define VER_FILEVERSION_STR "3.00.47.00"
#define WB32_DRIVER_MAJOR_VERSION 0x0300
#define WB32_DRIVER_MINOR_VERSION 0x4700
#endif
#include "os_common.h"
void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
{
if( pHwData->SurpriseRemove ) return;
memcpy( current_address, pHwData->CurrentMacAddress, ETH_LENGTH_OF_ADDRESS );
}
void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address )
{
u32 ltmp[2];
if( pHwData->SurpriseRemove ) return;
memcpy( pHwData->CurrentMacAddress, current_address, ETH_LENGTH_OF_ADDRESS );
ltmp[0]= cpu_to_le32( *(PULONG)pHwData->CurrentMacAddress );
ltmp[1]= cpu_to_le32( *(PULONG)(pHwData->CurrentMacAddress + 4) ) & 0xffff;
Wb35Reg_BurstWrite( pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT );
}
void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address )
{
if( pHwData->SurpriseRemove ) return;
memcpy( pethernet_address, pHwData->PermanentMacAddress, 6 );
}
u8 hal_init_hardware(phw_data_t pHwData, PWB32_ADAPTER Adapter)
{
u16 SoftwareSet;
pHwData->Adapter = Adapter;
// Initial the variable
pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME; // Setting Rx maximum MSDU life time
pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; // Setting default fragment threshold
if (WbUsb_initial(pHwData)) {
pHwData->InitialResource = 1;
if( Wb35Reg_initial(pHwData)) {
pHwData->InitialResource = 2;
if (Wb35Tx_initial(pHwData)) {
pHwData->InitialResource = 3;
if (Wb35Rx_initial(pHwData)) {
pHwData->InitialResource = 4;
OS_TIMER_INITIAL( &pHwData->LEDTimer, hal_led_control, pHwData );
OS_TIMER_SET( &pHwData->LEDTimer, 1000 ); // 20060623
//
// For restrict to vendor's hardware
//
SoftwareSet = hal_software_set( pHwData );
#ifdef Vendor2
// Try to make sure the EEPROM contain
SoftwareSet >>= 8;
if( SoftwareSet != 0x82 )
return FALSE;
#endif
Wb35Rx_start( pHwData );
Wb35Tx_EP2VM_start( pHwData );
return TRUE;
}
}
}
}
pHwData->SurpriseRemove = 1;
return FALSE;
}
void hal_halt(phw_data_t pHwData, void *ppa_data)
{
switch( pHwData->InitialResource )
{
case 4:
case 3: OS_TIMER_CANCEL( &pHwData->LEDTimer, &cancel );
OS_SLEEP(100000); // Wait for Timer DPC exit 940623.2
Wb35Rx_destroy( pHwData ); // Release the Rx
case 2: Wb35Tx_destroy( pHwData ); // Release the Tx
case 1: Wb35Reg_destroy( pHwData ); // Release the Wb35 Regisster resources
WbUsb_destroy( pHwData );// Release the WbUsb
}
}
//---------------------------------------------------------------------------------------------------
void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
u8 length, unsigned char basic_rate_set)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
u32 tmp, tmp1;
u8 Rate[12]={ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
u8 SupportedRate[16];
u8 i, j, k, Count1, Count2, Byte;
if( pHwData->SurpriseRemove ) return;
if (basic_rate_set) {
pWb35Reg->M28_MacControl &= ~0x000fff00;
tmp1 = 0x00000100;
} else {
pWb35Reg->M28_MacControl &= ~0xfff00000;
tmp1 = 0x00100000;
}
tmp = 0;
for (i=0; i<length; i++) {
Byte = pbss_rates[i] & 0x7f;
for (j=0; j<12; j++) {
if( Byte == Rate[j] )
break;
}
if (j < 12)
tmp |= (tmp1<<j);
}
pWb35Reg->M28_MacControl |= tmp;
Wb35Reg_Write( pHwData, 0x0828, pWb35Reg->M28_MacControl );
// 930206.2.c M78 setting
j = k = Count1 = Count2 = 0;
memset( SupportedRate, 0, 16 );
tmp = 0x00100000;
tmp1 = 0x00000100;
for (i=0; i<12; i++) { // Get the supported rate
if (tmp & pWb35Reg->M28_MacControl) {
SupportedRate[j] = Rate[i];
if (tmp1 & pWb35Reg->M28_MacControl)
SupportedRate[j] |= 0x80;
if (k)
Count2++;
else
Count1++;
j++;
}
if (i==4 && k==0) {
if( !(pWb35Reg->M28_MacControl & 0x000ff000) ) // if basic rate in 11g domain)
{
k = 1;
j = 8;
}
}
tmp <<= 1;
tmp1 <<= 1;
}
// Fill data into support rate until buffer full
//---20060926 add by anson's endian
for (i=0; i<4; i++)
*(PULONG)(SupportedRate+(i<<2)) = cpu_to_le32( *(PULONG)(SupportedRate+(i<<2)) );
//--- end 20060926 add by anson's endian
Wb35Reg_BurstWrite( pHwData,0x087c, (PULONG)SupportedRate, 4, AUTO_INCREMENT );
pWb35Reg->M7C_MacControl = ((PULONG)SupportedRate)[0];
pWb35Reg->M80_MacControl = ((PULONG)SupportedRate)[1];
pWb35Reg->M84_MacControl = ((PULONG)SupportedRate)[2];
pWb35Reg->M88_MacControl = ((PULONG)SupportedRate)[3];
// Fill length
tmp = Count1<<28 | Count2<<24;
pWb35Reg->M78_ERPInformation &= ~0xff000000;
pWb35Reg->M78_ERPInformation |= tmp;
Wb35Reg_Write( pHwData, 0x0878, pWb35Reg->M78_ERPInformation );
}
//---------------------------------------------------------------------------------------------------
void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period )
{
u32 tmp;
if( pHwData->SurpriseRemove ) return;
pHwData->BeaconPeriod = beacon_period;
tmp = pHwData->BeaconPeriod << 16;
tmp |= pHwData->ProbeDelay;
Wb35Reg_Write( pHwData, 0x0848, tmp );
}
void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove )
return;
printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
RFSynthesizer_SwitchingChannel( pHwData, channel );// Switch channel
pHwData->Channel = channel.ChanNo;
pHwData->band = channel.band;
#ifdef _PE_STATE_DUMP_
WBDEBUG(("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band));
#endif
pWb35Reg->M28_MacControl &= ~0xff; // Clean channel information field
pWb35Reg->M28_MacControl |= channel.ChanNo;
Wb35Reg_WriteWithCallbackValue( pHwData, 0x0828, pWb35Reg->M28_MacControl,
(PCHAR)&channel, sizeof(ChanInfo));
}
//---------------------------------------------------------------------------------------------------
void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel )
{
hal_set_current_channel_ex( pHwData, channel );
}
//---------------------------------------------------------------------------------------------------
void hal_get_current_channel( phw_data_t pHwData, ChanInfo *channel )
{
channel->ChanNo = pHwData->Channel;
channel->band = pHwData->band;
}
//---------------------------------------------------------------------------------------------------
void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return;
pWb35Reg->M00_MacControl &= ~0x02000000;//The HW value
if (enable)
pWb35Reg->M00_MacControl |= 0x02000000;//The HW value
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
}
//for wep key error detection, we need to accept broadcast packets to be received temporary.
void hal_set_accept_promiscuous( phw_data_t pHwData, u8 enable)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if (pHwData->SurpriseRemove) return;
if (enable) {
pWb35Reg->M00_MacControl |= 0x00400000;
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
} else {
pWb35Reg->M00_MacControl&=~0x00400000;
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
}
}
void hal_set_accept_multicast( phw_data_t pHwData, u8 enable )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return;
pWb35Reg->M00_MacControl &= ~0x01000000;//The HW value
if (enable) pWb35Reg->M00_MacControl |= 0x01000000;//The HW value
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
}
void hal_set_accept_beacon( phw_data_t pHwData, u8 enable )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return;
// 20040108 debug
if( !enable )//Due to SME and MLME are not suitable for 35
return;
pWb35Reg->M00_MacControl &= ~0x04000000;//The HW value
if( enable )
pWb35Reg->M00_MacControl |= 0x04000000;//The HW value
Wb35Reg_Write( pHwData, 0x0800, pWb35Reg->M00_MacControl );
}
//---------------------------------------------------------------------------------------------------
void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
u8 Byte, Bit;
if( pHwData->SurpriseRemove ) return;
//Erases and refills the card multicast registers. Used when an address
// has been deleted and all bits must be recomputed.
pWb35Reg->M04_MulticastAddress1 = 0;
pWb35Reg->M08_MulticastAddress2 = 0;
while( number )
{
number--;
CardGetMulticastBit( (address+(number*ETH_LENGTH_OF_ADDRESS)), &Byte, &Bit);
pWb35Reg->Multicast[Byte] |= Bit;
}
// Updating register
Wb35Reg_BurstWrite( pHwData, 0x0804, (PULONG)pWb35Reg->Multicast, 2, AUTO_INCREMENT );
}
//---------------------------------------------------------------------------------------------------
u8 hal_get_accept_beacon( phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return 0;
if( pWb35Reg->M00_MacControl & 0x04000000 )
return 1;
else
return 0;
}
unsigned char hal_reset_hardware( phw_data_t pHwData, void* ppa )
{
// Not implement yet
return TRUE;
}
void hal_stop( phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
pHwData->Wb35Rx.rx_halt = 1;
Wb35Rx_stop( pHwData );
pHwData->Wb35Tx.tx_halt = 1;
Wb35Tx_stop( pHwData );
pWb35Reg->D00_DmaControl &= ~0xc0000000;//Tx Off, Rx Off
Wb35Reg_Write( pHwData, 0x0400, pWb35Reg->D00_DmaControl );
WbUsb_Stop( pHwData ); // 20051230 Add.4
}
unsigned char hal_idle(phw_data_t pHwData)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
PWBUSB pWbUsb = &pHwData->WbUsb;
if( !pHwData->SurpriseRemove && ( pWbUsb->DetectCount || pWb35Reg->EP0vm_state!=VM_STOP ) )
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------------------------------
void hal_set_cwmin( phw_data_t pHwData, u8 cwin_min )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return;
pHwData->cwmin = cwin_min;
pWb35Reg->M2C_MacControl &= ~0x7c00; //bit 10 ~ 14
pWb35Reg->M2C_MacControl |= (pHwData->cwmin<<10);
Wb35Reg_Write( pHwData, 0x082c, pWb35Reg->M2C_MacControl );
}
s32 hal_get_rssi( phw_data_t pHwData, u32 *HalRssiArry, u8 Count )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
R01_DESCRIPTOR r01;
s32 ltmp = 0, tmp;
u8 i;
if( pHwData->SurpriseRemove ) return -200;
if( Count > MAX_ACC_RSSI_COUNT ) // Because the TS may use this funtion
Count = MAX_ACC_RSSI_COUNT;
// RSSI = C1 + C2 * (agc_state[7:0] + offset_map(lna_state[1:0]))
// C1 = -195, C2 = 0.66 = 85/128
for (i=0; i<Count; i++)
{
r01.value = HalRssiArry[i];
tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
ltmp += tmp;
}
ltmp /= Count;
if( pHwData->phy_type == RF_AIROHA_2230 ) ltmp -= 5; // 10;
if( pHwData->phy_type == RF_AIROHA_2230S ) ltmp -= 5; // 10; 20060420 Add this
//if( ltmp < -200 ) ltmp = -200;
if( ltmp < -110 ) ltmp = -110;// 1.0.24.0 For NJRC
return ltmp;
}
//----------------------------------------------------------------------------------------------------
s32 hal_get_rssi_bss( phw_data_t pHwData, u16 idx, u8 Count )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
R01_DESCRIPTOR r01;
s32 ltmp = 0, tmp;
u8 i, j;
PADAPTER Adapter = pHwData->Adapter;
// u32 *HalRssiArry = psBSS(idx)->HalRssi;
if( pHwData->SurpriseRemove ) return -200;
if( Count > MAX_ACC_RSSI_COUNT ) // Because the TS may use this funtion
Count = MAX_ACC_RSSI_COUNT;
// RSSI = C1 + C2 * (agc_state[7:0] + offset_map(lna_state[1:0]))
// C1 = -195, C2 = 0.66 = 85/128
#if 0
for (i=0; i<Count; i++)
{
r01.value = HalRssiArry[i];
tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
ltmp += tmp;
}
#else
if (psBSS(idx)->HalRssiIndex == 0)
psBSS(idx)->HalRssiIndex = MAX_ACC_RSSI_COUNT;
j = (u8)psBSS(idx)->HalRssiIndex-1;
for (i=0; i<Count; i++)
{
r01.value = psBSS(idx)->HalRssi[j];
tmp = ((( r01.R01_AGC_state + pWb35Reg->LNAValue[r01.R01_LNA_state]) * 85 ) >>7 ) - 195;
ltmp += tmp;
if (j == 0)
{
j = MAX_ACC_RSSI_COUNT;
}
j--;
}
#endif
ltmp /= Count;
if( pHwData->phy_type == RF_AIROHA_2230 ) ltmp -= 5; // 10;
if( pHwData->phy_type == RF_AIROHA_2230S ) ltmp -= 5; // 10; 20060420 Add this
//if( ltmp < -200 ) ltmp = -200;
if( ltmp < -110 ) ltmp = -110;// 1.0.24.0 For NJRC
return ltmp;
}
//---------------------------------------------------------------------------
void hal_led_control_1a( phw_data_t pHwData )
{
hal_led_control( NULL, pHwData, NULL, NULL );
}
void hal_led_control( void* S1, phw_data_t pHwData, void* S3, void* S4 )
{
PADAPTER Adapter = pHwData->Adapter;
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
u8 LEDgray[20] = { 0,3,4,6,8,10,11,12,13,14,15,14,13,12,11,10,8,6,4,2 };
u8 LEDgray2[30] = { 7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,15,14,13,12,11,10,9,8 };
u32 TimeInterval = 500, ltmp, ltmp2;
ltmp=0;
if( pHwData->SurpriseRemove ) return;
if( pHwData->LED_control ) {
ltmp2 = pHwData->LED_control & 0xff;
if( ltmp2 == 5 ) // 5 is WPS mode
{
TimeInterval = 100;
ltmp2 = (pHwData->LED_control>>8) & 0xff;
switch( ltmp2 )
{
case 1: // [0.2 On][0.1 Off]...
pHwData->LED_Blinking %= 3;
ltmp = 0x1010; // Led 1 & 0 Green and Red
if( pHwData->LED_Blinking == 2 ) // Turn off
ltmp = 0;
break;
case 2: // [0.1 On][0.1 Off]...
pHwData->LED_Blinking %= 2;
ltmp = 0x0010; // Led 0 red color
if( pHwData->LED_Blinking ) // Turn off
ltmp = 0;
break;
case 3: // [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]...
pHwData->LED_Blinking %= 15;
ltmp = 0x0010; // Led 0 red color
if( (pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking%2) ) // Turn off 0.6 sec
ltmp = 0;
break;
case 4: // [300 On][ off ]
ltmp = 0x1000; // Led 1 Green color
if( pHwData->LED_Blinking >= 3000 )
ltmp = 0; // led maybe on after 300sec * 32bit counter overlap.
break;
}
pHwData->LED_Blinking++;
pWb35Reg->U1BC_LEDConfigure = ltmp;
if( LEDSet != 7 ) // Only 111 mode has 2 LEDs on PCB.
{
pWb35Reg->U1BC_LEDConfigure |= (ltmp &0xff)<<8; // Copy LED result to each LED control register
pWb35Reg->U1BC_LEDConfigure |= (ltmp &0xff00)>>8;
}
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
}
}
else if( pHwData->CurrentRadioSw || pHwData->CurrentRadioHw ) // If radio off
{
if( pWb35Reg->U1BC_LEDConfigure & 0x1010 )
{
pWb35Reg->U1BC_LEDConfigure &= ~0x1010;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
}
}
else
{
switch( LEDSet )
{
case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
if( !pHwData->LED_LinkOn ) // Blink only if not Link On
{
// Blinking if scanning is on progress
if( pHwData->LED_Scanning )
{
if( pHwData->LED_Blinking == 0 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 On
pHwData->LED_Blinking = 1;
TimeInterval = 300;
}
else
{
pWb35Reg->U1BC_LEDConfigure &= ~0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
pHwData->LED_Blinking = 0;
TimeInterval = 300;
}
}
else
{
//Turn Off LED_0
if( pWb35Reg->U1BC_LEDConfigure & 0x10 )
{
pWb35Reg->U1BC_LEDConfigure &= ~0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
}
}
}
else
{
// Turn On LED_0
if( (pWb35Reg->U1BC_LEDConfigure & 0x10) == 0 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
}
}
break;
case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing
if( !pHwData->LED_LinkOn ) // Blink only if not Link On
{
// Blinking if scanning is on progress
if( pHwData->LED_Scanning )
{
if( pHwData->LED_Blinking == 0 )
{
pWb35Reg->U1BC_LEDConfigure &= ~0xf;
pWb35Reg->U1BC_LEDConfigure |= 0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 On
pHwData->LED_Blinking = 1;
TimeInterval = 300;
}
else
{
pWb35Reg->U1BC_LEDConfigure &= ~0x1f;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
pHwData->LED_Blinking = 0;
TimeInterval = 300;
}
}
else
{
// 20060901 Gray blinking if in disconnect state and not scanning
ltmp = pWb35Reg->U1BC_LEDConfigure;
pWb35Reg->U1BC_LEDConfigure &= ~0x1f;
if( LEDgray2[(pHwData->LED_Blinking%30)] )
{
pWb35Reg->U1BC_LEDConfigure |= 0x10;
pWb35Reg->U1BC_LEDConfigure |= LEDgray2[ (pHwData->LED_Blinking%30) ];
}
pHwData->LED_Blinking++;
if( pWb35Reg->U1BC_LEDConfigure != ltmp )
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
TimeInterval = 100;
}
}
else
{
// Turn On LED_0
if( (pWb35Reg->U1BC_LEDConfigure & 0x10) == 0 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_0 Off
}
}
break;
case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing
if( !pHwData->LED_LinkOn ) // Blink only if not Link On
{
// Blinking if scanning is on progress
if( pHwData->LED_Scanning )
{
if( pHwData->LED_Blinking == 0 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x1000;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
pHwData->LED_Blinking = 1;
TimeInterval = 300;
}
else
{
pWb35Reg->U1BC_LEDConfigure &= ~0x1000;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 Off
pHwData->LED_Blinking = 0;
TimeInterval = 300;
}
}
else
{
//Turn Off LED_1
if( pWb35Reg->U1BC_LEDConfigure & 0x1000 )
{
pWb35Reg->U1BC_LEDConfigure &= ~0x1000;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 Off
}
}
}
else
{
// Is transmitting/receiving ??
if( (OS_CURRENT_RX_BYTE( Adapter ) != pHwData->RxByteCountLast ) ||
(OS_CURRENT_TX_BYTE( Adapter ) != pHwData->TxByteCountLast ) )
{
if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x3000 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x3000;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
}
// Update variable
pHwData->RxByteCountLast = OS_CURRENT_RX_BYTE( Adapter );
pHwData->TxByteCountLast = OS_CURRENT_TX_BYTE( Adapter );
TimeInterval = 200;
}
else
{
// Turn On LED_1 and blinking if transmitting/receiving
if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x1000 )
{
pWb35Reg->U1BC_LEDConfigure &= ~0x3000;
pWb35Reg->U1BC_LEDConfigure |= 0x1000;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure ); // LED_1 On
}
}
}
break;
default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active
if( (pWb35Reg->U1BC_LEDConfigure & 0x3000) != 0x3000 )
{
pWb35Reg->U1BC_LEDConfigure |= 0x3000;// LED_1 is always on and event enable
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
}
if( pHwData->LED_Blinking )
{
// Gray blinking
pWb35Reg->U1BC_LEDConfigure &= ~0x0f;
pWb35Reg->U1BC_LEDConfigure |= 0x10;
pWb35Reg->U1BC_LEDConfigure |= LEDgray[ (pHwData->LED_Blinking-1)%20 ];
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
pHwData->LED_Blinking += 2;
if( pHwData->LED_Blinking < 40 )
TimeInterval = 100;
else
{
pHwData->LED_Blinking = 0; // Stop blinking
pWb35Reg->U1BC_LEDConfigure &= ~0x0f;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
}
break;
}
if( pHwData->LED_LinkOn )
{
if( !(pWb35Reg->U1BC_LEDConfigure & 0x10) ) // Check the LED_0
{
//Try to turn ON LED_0 after gray blinking
pWb35Reg->U1BC_LEDConfigure |= 0x10;
pHwData->LED_Blinking = 1; //Start blinking
TimeInterval = 50;
}
}
else
{
if( pWb35Reg->U1BC_LEDConfigure & 0x10 ) // Check the LED_0
{
pWb35Reg->U1BC_LEDConfigure &= ~0x10;
Wb35Reg_Write( pHwData, 0x03bc, pWb35Reg->U1BC_LEDConfigure );
}
}
break;
}
//20060828.1 Active send null packet to avoid AP disconnect
if( pHwData->LED_LinkOn )
{
pHwData->NullPacketCount += TimeInterval;
if( pHwData->NullPacketCount >= DEFAULT_NULL_PACKET_COUNT )
{
pHwData->NullPacketCount = 0;
}
}
}
pHwData->time_count += TimeInterval;
Wb35Tx_CurrentTime( pHwData, pHwData->time_count ); // 20060928 add
OS_TIMER_SET( &pHwData->LEDTimer, TimeInterval ); // 20060623.1
}
void hal_set_phy_type( phw_data_t pHwData, u8 PhyType )
{
pHwData->phy_type = PhyType;
}
void hal_get_phy_type( phw_data_t pHwData, u8 *PhyType )
{
*PhyType = pHwData->phy_type;
}
void hal_reset_counter( phw_data_t pHwData )
{
pHwData->dto_tx_retry_count = 0;
pHwData->dto_tx_frag_count = 0;
memset( pHwData->tx_retry_count, 0, 8);
}
void hal_set_radio_mode( phw_data_t pHwData, unsigned char radio_off)
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return;
if (radio_off) //disable Baseband receive off
{
pHwData->CurrentRadioSw = 1; // off
pWb35Reg->M24_MacControl &= 0xffffffbf;
}
else
{
pHwData->CurrentRadioSw = 0; // on
pWb35Reg->M24_MacControl |= 0x00000040;
}
Wb35Reg_Write( pHwData, 0x0824, pWb35Reg->M24_MacControl );
}
u8 hal_get_antenna_number( phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if ((pWb35Reg->BB2C & BIT(11)) == 0)
return 0;
else
return 1;
}
void hal_set_antenna_number( phw_data_t pHwData, u8 number )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if (number == 1) {
pWb35Reg->BB2C |= BIT(11);
} else {
pWb35Reg->BB2C &= ~BIT(11);
}
Wb35Reg_Write( pHwData, 0x102c, pWb35Reg->BB2C );
#ifdef _PE_STATE_DUMP_
WBDEBUG(("Current antenna number : %d\n", number));
#endif
}
//----------------------------------------------------------------------------------------------------
//0 : radio on; 1: radio off
u8 hal_get_hw_radio_off( phw_data_t pHwData )
{
PWB35REG pWb35Reg = &pHwData->Wb35Reg;
if( pHwData->SurpriseRemove ) return 1;
//read the bit16 of register U1B0
Wb35Reg_Read( pHwData, 0x3b0, &pWb35Reg->U1B0 );
if ((pWb35Reg->U1B0 & 0x00010000)) {
pHwData->CurrentRadioHw = 1;
return 1;
} else {
pHwData->CurrentRadioHw = 0;
return 0;
}
}
unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue )
{
if( number < 0x1000 )
number += 0x1000;
return Wb35Reg_ReadSync( pHwData, number, pValue );
}
unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value )
{
unsigned char ret;
if( number < 0x1000 )
number += 0x1000;
ret = Wb35Reg_WriteSync( pHwData, number, value );
return ret;
}
void hal_scan_status_indicate(phw_data_t pHwData, unsigned char IsOnProgress)
{
if( pHwData->SurpriseRemove ) return;
pHwData->LED_Scanning = IsOnProgress ? 1 : 0;
}
void hal_system_power_change(phw_data_t pHwData, u32 PowerState)
{
if( PowerState != 0 )
{
pHwData->SurpriseRemove = 1;
if( pHwData->WbUsb.IsUsb20 )
hal_stop( pHwData );
}
else
{
if( !pHwData->WbUsb.IsUsb20 )
hal_stop( pHwData );
}
}
void hal_surprise_remove( phw_data_t pHwData )
{
PADAPTER Adapter = pHwData->Adapter;
if (OS_ATOMIC_INC( Adapter, &pHwData->SurpriseRemoveCount ) == 1) {
#ifdef _PE_STATE_DUMP_
WBDEBUG(("Calling hal_surprise_remove\n"));
#endif
OS_STOP( Adapter );
}
}
void hal_rate_change( phw_data_t pHwData ) // Notify the HAL rate is changing 20060613.1
{
PADAPTER Adapter = pHwData->Adapter;
u8 rate = CURRENT_TX_RATE;
BBProcessor_RateChanging( pHwData, rate );
}
void hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex)
{
RFSynthesizer_SetPowerIndex( pHwData, PowerIndex );
}
unsigned char hal_set_LED(phw_data_t pHwData, u32 Mode) // 20061108 for WPS led control
{
pHwData->LED_Blinking = 0;
pHwData->LED_control = Mode;
OS_TIMER_SET( &pHwData->LEDTimer, 10 ); // 20060623
return TRUE;
}
//=====================================================================
// Device related include
//=====================================================================
#ifdef WB_LINUX
#include "linux/wbusb_f.h"
#include "linux/wb35reg_f.h"
#include "linux/wb35tx_f.h"
#include "linux/wb35rx_f.h"
#else
#include "wbusb_f.h"
#include "wb35reg_f.h"
#include "wb35tx_f.h"
#include "wb35rx_f.h"
#endif
//====================================================================================
// Function declaration
//====================================================================================
void hal_remove_mapping_key( phw_data_t pHwData, PUCHAR pmac_addr );
void hal_remove_default_key( phw_data_t pHwData, u32 index );
unsigned char hal_set_mapping_key( phw_data_t Adapter, PUCHAR pmac_addr, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
unsigned char hal_set_default_key( phw_data_t Adapter, u8 index, u8 null_key, u8 wep_on, PUCHAR ptx_tsc, PUCHAR prx_tsc, u8 key_type, u8 key_len, PUCHAR pkey_data );
void hal_clear_all_default_key( phw_data_t pHwData );
void hal_clear_all_group_key( phw_data_t pHwData );
void hal_clear_all_mapping_key( phw_data_t pHwData );
void hal_clear_all_key( phw_data_t pHwData );
void hal_get_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
void hal_set_ethernet_address( phw_data_t pHwData, PUCHAR current_address );
void hal_get_permanent_address( phw_data_t pHwData, PUCHAR pethernet_address );
unsigned char hal_init_hardware( phw_data_t pHwData, PADAPTER Adapter );
void hal_set_power_save_mode( phw_data_t pHwData, unsigned char power_save, unsigned char wakeup, unsigned char dtim );
void hal_get_power_save_mode( phw_data_t pHwData, PBOOLEAN pin_pwr_save );
void hal_set_slot_time( phw_data_t pHwData, u8 type );
#define hal_set_atim_window( _A, _ATM )
void hal_set_rates( phw_data_t pHwData, PUCHAR pbss_rates, u8 length, unsigned char basic_rate_set );
#define hal_set_basic_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, TRUE )
#define hal_set_op_rates( _A, _R, _L ) hal_set_rates( _A, _R, _L, FALSE )
void hal_start_bss( phw_data_t pHwData, u8 mac_op_mode );
void hal_join_request( phw_data_t pHwData, u8 bss_type ); // 0:BSS STA 1:IBSS STA//
void hal_stop_sync_bss( phw_data_t pHwData );
void hal_resume_sync_bss( phw_data_t pHwData);
void hal_set_aid( phw_data_t pHwData, u16 aid );
void hal_set_bssid( phw_data_t pHwData, PUCHAR pbssid );
void hal_get_bssid( phw_data_t pHwData, PUCHAR pbssid );
void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period );
void hal_set_listen_interval( phw_data_t pHwData, u16 listen_interval );
void hal_set_cap_info( phw_data_t pHwData, u16 capability_info );
void hal_set_ssid( phw_data_t pHwData, PUCHAR pssid, u8 ssid_len );
void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel );
void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel );
void hal_get_current_channel( phw_data_t pHwData, ChanInfo *channel );
void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable );
void hal_set_accept_multicast( phw_data_t pHwData, u8 enable );
void hal_set_accept_beacon( phw_data_t pHwData, u8 enable );
void hal_set_multicast_address( phw_data_t pHwData, PUCHAR address, u8 number );
u8 hal_get_accept_beacon( phw_data_t pHwData );
void hal_stop( phw_data_t pHwData );
void hal_halt( phw_data_t pHwData, void *ppa_data );
void hal_start_tx0( phw_data_t pHwData );
void hal_set_phy_type( phw_data_t pHwData, u8 PhyType );
void hal_get_phy_type( phw_data_t pHwData, u8 *PhyType );
unsigned char hal_reset_hardware( phw_data_t pHwData, void* ppa );
void hal_set_cwmin( phw_data_t pHwData, u8 cwin_min );
#define hal_get_cwmin( _A ) ( (_A)->cwmin )
void hal_set_cwmax( phw_data_t pHwData, u16 cwin_max );
#define hal_get_cwmax( _A ) ( (_A)->cwmax )
void hal_set_rsn_wpa( phw_data_t pHwData, u32 * RSN_IE_Bitmap , u32 * RSN_OUI_type , unsigned char bDesiredAuthMode);
//s32 hal_get_rssi( phw_data_t pHwData, u32 HalRssi );
s32 hal_get_rssi( phw_data_t pHwData, u32 *HalRssiArry, u8 Count );
s32 hal_get_rssi_bss( phw_data_t pHwData, u16 idx, u8 Count );
void hal_set_connect_info( phw_data_t pHwData, unsigned char boConnect );
u8 hal_get_est_sq3( phw_data_t pHwData, u8 Count );
void hal_led_control_1a( phw_data_t pHwData );
void hal_led_control( void* S1, phw_data_t pHwData, void* S3, void* S4 );
void hal_set_rf_power( phw_data_t pHwData, u8 PowerIndex ); // 20060621 Modify
void hal_reset_counter( phw_data_t pHwData );
void hal_set_radio_mode( phw_data_t pHwData, unsigned char boValue);
void hal_descriptor_indicate( phw_data_t pHwData, PDESCRIPTOR pDes );
u8 hal_get_antenna_number( phw_data_t pHwData );
void hal_set_antenna_number( phw_data_t pHwData, u8 number );
u32 hal_get_bss_pk_cnt( phw_data_t pHwData );
#define hal_get_region_from_EEPROM( _A ) ( (_A)->Wb35Reg.EEPROMRegion )
void hal_set_accept_promiscuous ( phw_data_t pHwData, u8 enable);
#define hal_get_tx_buffer( _A, _B ) Wb35Tx_get_tx_buffer( _A, _B )
u8 hal_get_hw_radio_off ( phw_data_t pHwData );
#define hal_software_set( _A ) (_A->SoftwareSet)
#define hal_driver_init_OK( _A ) (_A->IsInitOK)
#define hal_rssi_boundary_high( _A ) (_A->RSSI_high)
#define hal_rssi_boundary_low( _A ) (_A->RSSI_low)
#define hal_scan_interval( _A ) (_A->Scan_Interval)
void hal_scan_status_indicate( phw_data_t pHwData, u8 status); // 0: complete, 1: in progress
void hal_system_power_change( phw_data_t pHwData, u32 PowerState ); // 20051230 -=D0 1=D1 ..
void hal_surprise_remove( phw_data_t pHwData );
#define PHY_DEBUG( msg, args... )
void hal_rate_change( phw_data_t pHwData ); // Notify the HAL rate is changing 20060613.1
unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, PULONG pValue );
unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value );
#define hal_get_time_count( _P ) (_P->time_count/10) // return 100ms count
#define hal_detect_error( _P ) (_P->WbUsb.DetectCount)
unsigned char hal_set_LED( phw_data_t pHwData, u32 Mode ); // 20061108 for WPS led control
//-------------------------------------------------------------------------
// The follow function is unused for IS89C35
//-------------------------------------------------------------------------
#define hal_disable_interrupt(_A)
#define hal_enable_interrupt(_A)
#define hal_get_interrupt_type( _A)
#define hal_get_clear_interrupt(_A)
#define hal_ibss_disconnect(_A) hal_stop_sync_bss(_A)
#define hal_join_request_stop(_A)
unsigned char hal_idle( phw_data_t pHwData );
#define pa_stall_execution( _A ) //OS_SLEEP( 1 )
#define hw_get_cxx_reg( _A, _B, _C )
#define hw_set_cxx_reg( _A, _B, _C )
#define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (PULONG)_C )
#define hw_set_dxx_reg( _A, _B, _C ) hal_set_dxx_reg( _A, _B, (u32)_C )
//[20040722 WK]
#define HAL_LED_SET_MASK 0x001c //20060901 Extend
#define HAL_LED_SET_SHIFT 2
//supported RF type
#define RF_MAXIM_2825 0
#define RF_MAXIM_2827 1
#define RF_MAXIM_2828 2
#define RF_MAXIM_2829 3
#define RF_MAXIM_V1 15
#define RF_AIROHA_2230 16
#define RF_AIROHA_7230 17
#define RF_AIROHA_2230S 18 // 20060420 Add this
// #define RF_RFMD_2959 32 // 20060626 Remove all about RFMD
#define RF_WB_242 33
#define RF_WB_242_1 34 // 20060619.5 Add
#define RF_DECIDE_BY_INF 255
//----------------------------------------------------------------
// The follow define connect to upper layer
// User must modify for connection between HAL and upper layer
//----------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////////////////
//================================================================================================
// Common define
//================================================================================================
#define HAL_USB_MODE_BURST( _H ) (_H->SoftwareSet & 0x20 ) // Bit 5 20060901 Modify
// Scan interval
#define SCAN_MAX_CHNL_TIME (50)
// For TxL2 Frame typr recognise
#define FRAME_TYPE_802_3_DATA 0
#define FRAME_TYPE_802_11_MANAGEMENT 1
#define FRAME_TYPE_802_11_MANAGEMENT_CHALLENGE 2
#define FRAME_TYPE_802_11_CONTROL 3
#define FRAME_TYPE_802_11_DATA 4
#define FRAME_TYPE_PROMISCUOUS 5
// The follow definition is used for convert the frame--------------------
#define DOT_11_SEQUENCE_OFFSET 22 //Sequence control offset
#define DOT_3_TYPE_OFFSET 12
#define DOT_11_MAC_HEADER_SIZE 24
#define DOT_11_SNAP_SIZE 6
#define DOT_11_TYPE_OFFSET 30 //The start offset of 802.11 Frame. Type encapsulatuin.
#define DEFAULT_SIFSTIME 10
#define DEFAULT_FRAGMENT_THRESHOLD 2346 // No fragment
#define DEFAULT_MSDU_LIFE_TIME 0xffff
#define LONG_PREAMBLE_PLUS_PLCPHEADER_TIME (144+48)
#define SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME (72+24)
#define PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION (16+4+6)
#define Tsym 4
// Frame Type of Bits (2, 3)---------------------------------------------
#define MAC_TYPE_MANAGEMENT 0x00
#define MAC_TYPE_CONTROL 0x04
#define MAC_TYPE_DATA 0x08
#define MASK_FRAGMENT_NUMBER 0x000F
#define SEQUENCE_NUMBER_SHIFT 4
#define HAL_WOL_TYPE_WAKEUP_FRAME 0x01
#define HAL_WOL_TYPE_MAGIC_PACKET 0x02
// 20040106 ADDED
#define HAL_KEYTYPE_WEP40 0
#define HAL_KEYTYPE_WEP104 1
#define HAL_KEYTYPE_TKIP 2 // 128 bit key
#define HAL_KEYTYPE_AES_CCMP 3 // 128 bit key
// For VM state
enum {
VM_STOP = 0,
VM_RUNNING,
VM_COMPLETED
};
// Be used for 802.11 mac header
typedef struct _MAC_FRAME_CONTROL {
u8 mac_frame_info; // this is a combination of the protovl version, type and subtype
u8 to_ds:1;
u8 from_ds:1;
u8 more_frag:1;
u8 retry:1;
u8 pwr_mgt:1;
u8 more_data:1;
u8 WEP:1;
u8 order:1;
} MAC_FRAME_CONTROL, *PMAC_FRAME_CONTROL;
//-----------------------------------------------------
// Normal Key table format
//-----------------------------------------------------
// The order of KEY index is MAPPING_KEY_START_INDEX > GROUP_KEY_START_INDEX
#define MAX_KEY_TABLE 24 // 24 entry for storing key data
#define GROUP_KEY_START_INDEX 4
#define MAPPING_KEY_START_INDEX 8
typedef struct _KEY_TABLE
{
u32 DW0_Valid:1;
u32 DW0_NullKey:1;
u32 DW0_Security_Mode:2;//0:WEP 40 bit 1:WEP 104 bit 2:TKIP 128 bit 3:CCMP 128 bit
u32 DW0_WEPON:1;
u32 DW0_RESERVED:11;
u32 DW0_Address1:16;
u32 DW1_Address2;
u32 DW2_RxSequenceCount1;
u32 DW3_RxSequenceCount2:16;
u32 DW3_RESERVED:16;
u32 DW4_TxSequenceCount1;
u32 DW5_TxSequenceCount2:16;
u32 DW5_RESERVED:16;
} KEY_TABLE, *PKEY_TABLE;
//--------------------------------------------------------
// Descriptor
//--------------------------------------------------------
#define MAX_DESCRIPTOR_BUFFER_INDEX 8 // Have to multiple of 2
//#define FLAG_ERROR_TX_MASK cpu_to_le32(0x000000bf) //20061009 marked by anson's endian
#define FLAG_ERROR_TX_MASK 0x000000bf //20061009 anson's endian
//#define FLAG_ERROR_RX_MASK 0x00000c3f
//#define FLAG_ERROR_RX_MASK cpu_to_le32(0x0000083f) //20061009 marked by anson's endian
//Don't care replay error,
//it is handled by S/W
#define FLAG_ERROR_RX_MASK 0x0000083f //20060926 anson's endian
#define FLAG_BAND_RX_MASK 0x10000000 //Bit 28
typedef struct _R00_DESCRIPTOR
{
union
{
u32 value;
#ifdef _BIG_ENDIAN_ //20060926 anson's endian
struct
{
u32 R00_packet_or_buffer_status:1;
u32 R00_packet_in_fifo:1;
u32 R00_RESERVED:2;
u32 R00_receive_byte_count:12;
u32 R00_receive_time_index:16;
};
#else
struct
{
u32 R00_receive_time_index:16;
u32 R00_receive_byte_count:12;
u32 R00_RESERVED:2;
u32 R00_packet_in_fifo:1;
u32 R00_packet_or_buffer_status:1;
};
#endif
};
} R00_DESCRIPTOR, *PR00_DESCRIPTOR;
typedef struct _T00_DESCRIPTOR
{
union
{
u32 value;
#ifdef _BIG_ENDIAN_ //20061009 anson's endian
struct
{
u32 T00_first_mpdu:1; // for hardware use
u32 T00_last_mpdu:1; // for hardware use
u32 T00_IsLastMpdu:1;// 0: not 1:Yes for software used
u32 T00_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
u32 T00_RESERVED_ID:2;//3 bit ID reserved
u32 T00_tx_packet_id:4;//930519.4.e 930810.3.c
u32 T00_RESERVED:4;
u32 T00_header_length:6;
u32 T00_frame_length:12;
};
#else
struct
{
u32 T00_frame_length:12;
u32 T00_header_length:6;
u32 T00_RESERVED:4;
u32 T00_tx_packet_id:4;//930519.4.e 930810.3.c
u32 T00_RESERVED_ID:2;//3 bit ID reserved
u32 T00_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
u32 T00_IsLastMpdu:1;// 0: not 1:Yes for software used
u32 T00_last_mpdu:1; // for hardware use
u32 T00_first_mpdu:1; // for hardware use
};
#endif
};
} T00_DESCRIPTOR, *PT00_DESCRIPTOR;
typedef struct _R01_DESCRIPTOR
{
union
{
u32 value;
#ifdef _BIG_ENDIAN_ //20060926 add by anson's endian
struct
{
u32 R01_RESERVED:3;
u32 R01_mod_type:1;
u32 R01_pre_type:1;
u32 R01_data_rate:3;
u32 R01_AGC_state:8;
u32 R01_LNA_state:2;
u32 R01_decryption_method:2;
u32 R01_mic_error:1;
u32 R01_replay:1;
u32 R01_broadcast_frame:1;
u32 R01_multicast_frame:1;
u32 R01_directed_frame:1;
u32 R01_receive_frame_antenna_selection:1;
u32 R01_frame_receive_during_atim_window:1;
u32 R01_protocol_version_error:1;
u32 R01_authentication_frame_icv_error:1;
u32 R01_null_key_to_authentication_frame:1;
u32 R01_icv_error:1;
u32 R01_crc_error:1;
};
#else
struct
{
u32 R01_crc_error:1;
u32 R01_icv_error:1;
u32 R01_null_key_to_authentication_frame:1;
u32 R01_authentication_frame_icv_error:1;
u32 R01_protocol_version_error:1;
u32 R01_frame_receive_during_atim_window:1;
u32 R01_receive_frame_antenna_selection:1;
u32 R01_directed_frame:1;
u32 R01_multicast_frame:1;
u32 R01_broadcast_frame:1;
u32 R01_replay:1;
u32 R01_mic_error:1;
u32 R01_decryption_method:2;
u32 R01_LNA_state:2;
u32 R01_AGC_state:8;
u32 R01_data_rate:3;
u32 R01_pre_type:1;
u32 R01_mod_type:1;
u32 R01_RESERVED:3;
};
#endif
};
} R01_DESCRIPTOR, *PR01_DESCRIPTOR;
typedef struct _T01_DESCRIPTOR
{
union
{
u32 value;
#ifdef _BIG_ENDIAN_ //20061009 anson's endian
struct
{
u32 T01_rts_cts_duration:16;
u32 T01_fall_back_rate:3;
u32 T01_add_rts:1;
u32 T01_add_cts:1;
u32 T01_modulation_type:1;
u32 T01_plcp_header_length:1;
u32 T01_transmit_rate:3;
u32 T01_wep_id:2;
u32 T01_add_challenge_text:1;
u32 T01_inhibit_crc:1;
u32 T01_loop_back_wep_mode:1;
u32 T01_retry_abort_ebable:1;
};
#else
struct
{
u32 T01_retry_abort_ebable:1;
u32 T01_loop_back_wep_mode:1;
u32 T01_inhibit_crc:1;
u32 T01_add_challenge_text:1;
u32 T01_wep_id:2;
u32 T01_transmit_rate:3;
u32 T01_plcp_header_length:1;
u32 T01_modulation_type:1;
u32 T01_add_cts:1;
u32 T01_add_rts:1;
u32 T01_fall_back_rate:3;
u32 T01_rts_cts_duration:16;
};
#endif
};
} T01_DESCRIPTOR, *PT01_DESCRIPTOR;
typedef struct _T02_DESCRIPTOR
{
union
{
u32 value;
#ifdef _BIG_ENDIAN_ //20061009 add by anson's endian
struct
{
u32 T02_IsLastMpdu:1;// The same mechanism with T00 setting
u32 T02_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
u32 T02_RESERVED_ID:2;// The same mechanism with T00 setting
u32 T02_Tx_PktID:4;
u32 T02_MPDU_Cnt:4;
u32 T02_RTS_Cnt:4;
u32 T02_RESERVED:7;
u32 T02_transmit_complete:1;
u32 T02_transmit_abort_due_to_TBTT:1;
u32 T02_effective_transmission_rate:1;
u32 T02_transmit_without_encryption_due_to_wep_on_false:1;
u32 T02_discard_due_to_null_wep_key:1;
u32 T02_RESERVED_1:1;
u32 T02_out_of_MaxTxMSDULiftTime:1;
u32 T02_transmit_abort:1;
u32 T02_transmit_fail:1;
};
#else
struct
{
u32 T02_transmit_fail:1;
u32 T02_transmit_abort:1;
u32 T02_out_of_MaxTxMSDULiftTime:1;
u32 T02_RESERVED_1:1;
u32 T02_discard_due_to_null_wep_key:1;
u32 T02_transmit_without_encryption_due_to_wep_on_false:1;
u32 T02_effective_transmission_rate:1;
u32 T02_transmit_abort_due_to_TBTT:1;
u32 T02_transmit_complete:1;
u32 T02_RESERVED:7;
u32 T02_RTS_Cnt:4;
u32 T02_MPDU_Cnt:4;
u32 T02_Tx_PktID:4;
u32 T02_RESERVED_ID:2;// The same mechanism with T00 setting
u32 T02_IgnoreResult:1;// The same mechanism with T00 setting. 050111 Modify for TS
u32 T02_IsLastMpdu:1;// The same mechanism with T00 setting
};
#endif
};
} T02_DESCRIPTOR, *PT02_DESCRIPTOR;
typedef struct _DESCRIPTOR { // Skip length = 8 DWORD
// ID for descriptor ---, The field doesn't be cleard in the operation of Descriptor definition
u8 Descriptor_ID;
//----------------------The above region doesn't be cleared by DESCRIPTOR_RESET------
u8 RESERVED[3];
u16 FragmentThreshold;
u8 InternalUsed;//Only can be used by operation of descriptor definition
u8 Type;// 0: 802.3 1:802.11 data frame 2:802.11 management frame
u8 PreambleMode;// 0: short 1:long
u8 TxRate;
u8 FragmentCount;
u8 EapFix; // For speed up key install
// For R00 and T00 ----------------------------------------------
union
{
R00_DESCRIPTOR R00;
T00_DESCRIPTOR T00;
};
// For R01 and T01 ----------------------------------------------
union
{
R01_DESCRIPTOR R01;
T01_DESCRIPTOR T01;
};
// For R02 and T02 ----------------------------------------------
union
{
u32 R02;
T02_DESCRIPTOR T02;
};
// For R03 and T03 ----------------------------------------------
// For software used
union
{
u32 R03;
u32 T03;
struct
{
u8 buffer_number;
u8 buffer_start_index;
u16 buffer_total_size;
};
};
// For storing the buffer
u16 buffer_size[ MAX_DESCRIPTOR_BUFFER_INDEX ];
void* buffer_address[ MAX_DESCRIPTOR_BUFFER_INDEX ];//931130.4.q
} DESCRIPTOR, *PDESCRIPTOR;
#define DEFAULT_NULL_PACKET_COUNT 180000 //20060828.1 Add. 180 seconds
#define MAX_TXVGA_EEPROM 9 //How many word(u16) of EEPROM will be used for TxVGA
#define MAX_RF_PARAMETER 32
typedef struct _TXVGA_FOR_50 {
u8 ChanNo;
u8 TxVgaValue;
} TXVGA_FOR_50;
//=====================================================================
// Device related include
//=====================================================================
#include "linux/wbusb_s.h"
#include "linux/wb35reg_s.h"
#include "linux/wb35tx_s.h"
#include "linux/wb35rx_s.h"
// For Hal using ==================================================================
typedef struct _HW_DATA_T
{
// For compatible with 33
u32 revision;
u32 BB3c_cal; // The value for Tx calibration comes from EEPROM
u32 BB54_cal; // The value for Rx calibration comes from EEPROM
// For surprise remove
u32 SurpriseRemove; // 0: Normal 1: Surprise remove
u8 InitialResource;
u8 IsKeyPreSet;
u8 CalOneTime; // 20060630.1
u8 VCO_trim;
// For Fix 1'st DMA bug
u32 FragCount;
u32 DMAFix; //V1_DMA_FIX The variable can be removed if driver want to save mem space for V2.
//=======================================================================================
// For USB driver, hal need more variables. Due to
// 1. NDIS-WDM operation
// 2. The SME, MLME and OLD MDS need Adapter structure, but the driver under HAL doesn't
// have that parameter when receiving and indicating packet.
// The MDS must input the Adapter pointer as the second parameter of hal_init_hardware.
// The function usage is different than PCI driver.
//=======================================================================================
void* Adapter;
//===============================================
// Definition for MAC address
//===============================================
u8 PermanentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are stored in EEPROM. + 2 to 8-byte alignment
u8 CurrentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are in used. + 2 to 8-byte alignment
//=====================================================================
// Definition for 802.11
//=====================================================================
PUCHAR bssid_pointer; // Used by hal_get_bssid for return value
u8 bssid[8];// Only 6 byte will be used. 8 byte is required for read buffer
u8 ssid[32];// maximum ssid length is 32 byte
u16 AID;
u8 ssid_length;
u8 Channel;
u16 ListenInterval;
u16 CapabilityInformation;
u16 BeaconPeriod;
u16 ProbeDelay;
u8 bss_type;// 0: IBSS_NET or 1:ESS_NET
u8 preamble;// 0: short preamble, 1: long preamble
u8 slot_time_select;// 9 or 20 value
u8 phy_type;// Phy select
u32 phy_para[MAX_RF_PARAMETER];
u32 phy_number;
u32 CurrentRadioSw; // 20060320.2 0:On 1:Off
u32 CurrentRadioHw; // 20060825 0:On 1:Off
PUCHAR power_save_point; // Used by hal_get_power_save_mode for return value
u8 cwmin;
u8 desired_power_save;
u8 dtim;// Is running dtim
u8 mapping_key_replace_index;//In Key table, the next index be replaced 931130.4.r
u16 MaxReceiveLifeTime;
u16 FragmentThreshold;
u16 FragmentThreshold_tmp;
u16 cwmax;
u8 Key_slot[MAX_KEY_TABLE][8]; //Ownership record for key slot. For Alignment
u32 Key_content[MAX_KEY_TABLE][12]; // 10DW for each entry + 2 for burst command( Off and On valid bit)
u8 CurrentDefaultKeyIndex;
u32 CurrentDefaultKeyLength;
//========================================================================
// Variable for each module
//========================================================================
WBUSB WbUsb; // Need WbUsb.h
WB35REG Wb35Reg; // Need Wb35Reg.h
WB35TX Wb35Tx; // Need Wb35Tx.h
WB35RX Wb35Rx; // Need Wb35Rx.h
OS_TIMER LEDTimer;// For LED
u32 LEDpoint;// For LED
u32 dto_tx_retry_count; // LA20040210_DTO kevin
u32 dto_tx_frag_count; // LA20040210_DTO kevin
u32 rx_ok_count[13]; // index=0: total rx ok
//u32 rx_ok_bytes[13]; // index=0, total rx ok bytes
u32 rx_err_count[13]; // index=0: total rx err
//for Tx debug
u32 tx_TBTT_start_count;
u32 tx_ETR_count;
u32 tx_WepOn_false_count;
u32 tx_Null_key_count;
u32 tx_retry_count[8];
u8 PowerIndexFromEEPROM; // For 2412MHz
u8 power_index;
u8 IsWaitJoinComplete; // TRUE: set join request
u8 band;
u16 SoftwareSet;
u16 Reserved_s;
u32 IsInitOK; // 0: Driver starting 1: Driver init OK
// For Phy calibration
s32 iq_rsdl_gain_tx_d2;
s32 iq_rsdl_phase_tx_d2;
u32 txvga_setting_for_cal; // 20060703.1 Add
u8 TxVgaSettingInEEPROM[ (((MAX_TXVGA_EEPROM*2)+3) & ~0x03) ]; // 20060621 For backup EEPROM value
u8 TxVgaFor24[16]; // Max is 14, 2 for alignment
TXVGA_FOR_50 TxVgaFor50[36]; // 35 channels in 5G. 35x2 = 70 byte. 2 for alignments
u16 Scan_Interval;
u16 RESERVED6;
// LED control
u32 LED_control;
// LED_control 4 byte: Gray_Led_1[3] Gray_Led_0[2] Led[1] Led[0]
// Gray_Led
// For Led gray setting
// Led
// 0: normal control, LED behavior will decide by EEPROM setting
// 1: Turn off specific LED
// 2: Always on specific LED
// 3: slow blinking specific LED
// 4: fast blinking specific LED
// 5: WPS led control is set. Led0 is Red, Led1 id Green
// Led[1] is parameter for WPS LED mode
// // 1:InProgress 2: Error 3: Session overlap 4: Success 20061108 control
u32 LED_LinkOn; //Turn LED on control
u32 LED_Scanning; // Let LED in scan process control
u32 LED_Blinking; // Temp variable for shining
u32 RxByteCountLast;
u32 TxByteCountLast;
s32 SurpriseRemoveCount;
// For global timer
u32 time_count;//TICK_TIME_100ms 1 = 100ms
// For error recover
u32 HwStop;
// 20060828.1 for avoid AP disconnect
u32 NullPacketCount;
} hw_data_t, *phw_data_t;
// The mapping of Rx and Tx descriptor field
typedef struct _HAL_RATE
{
// DSSS
u32 RESERVED_0;
u32 NumRate2MS;
u32 NumRate55MS;
u32 NumRate11MS;
u32 RESERVED_1[4];
u32 NumRate1M;
u32 NumRate2ML;
u32 NumRate55ML;
u32 NumRate11ML;
u32 RESERVED_2[4];
// OFDM
u32 NumRate6M;
u32 NumRate9M;
u32 NumRate12M;
u32 NumRate18M;
u32 NumRate24M;
u32 NumRate36M;
u32 NumRate48M;
u32 NumRate54M;
} HAL_RATE, *PHAL_RATE;
//============================================================================
// Copyright (c) 1996-2005 Winbond Electronic Corporation
//
// Module Name:
// wblinux.c
//
// Abstract:
// Linux releated routines
//
//============================================================================
#include "os_common.h"
u32
WBLINUX_MemoryAlloc(void* *VirtualAddress, u32 Length)
{
*VirtualAddress = kzalloc( Length, GFP_ATOMIC ); //GFP_KERNEL is not suitable
if (*VirtualAddress == NULL)
return 0;
return 1;
}
s32
EncapAtomicInc(PADAPTER Adapter, void* pAtomic)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
u32 ltmp;
PULONG pltmp = (PULONG)pAtomic;
OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
(*pltmp)++;
ltmp = (*pltmp);
OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
return ltmp;
}
s32
EncapAtomicDec(PADAPTER Adapter, void* pAtomic)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
u32 ltmp;
PULONG pltmp = (PULONG)pAtomic;
OS_SPIN_LOCK_ACQUIRED( &pWbLinux->AtomicSpinLock );
(*pltmp)--;
ltmp = (*pltmp);
OS_SPIN_LOCK_RELEASED( &pWbLinux->AtomicSpinLock );
return ltmp;
}
unsigned char
WBLINUX_Initial(PADAPTER Adapter)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
OS_SPIN_LOCK_ALLOCATE( &pWbLinux->SpinLock );
OS_SPIN_LOCK_ALLOCATE( &pWbLinux->AtomicSpinLock );
return TRUE;
}
void
WBLinux_ReceivePacket(PADAPTER Adapter, PRXLAYER1 pRxLayer1)
{
BUG();
}
void
WBLINUX_GetNextPacket(PADAPTER Adapter, PDESCRIPTOR pDes)
{
BUG();
}
void
WBLINUX_GetNextPacketCompleted(PADAPTER Adapter, PDESCRIPTOR pDes)
{
BUG();
}
void
WBLINUX_Destroy(PADAPTER Adapter)
{
WBLINUX_stop( Adapter );
OS_SPIN_LOCK_FREE( &pWbNdis->SpinLock );
#ifdef _PE_USB_INI_DUMP_
WBDEBUG(("[w35und] unregister_netdev!\n"));
#endif
}
void
WBLINUX_stop( PADAPTER Adapter )
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
struct sk_buff *pSkb;
if (OS_ATOMIC_INC( Adapter, &pWbLinux->ThreadCount ) == 1) {
// Shutdown module immediately
pWbLinux->shutdown = 1;
while (pWbLinux->skb_array[ pWbLinux->skb_GetIndex ]) {
// Trying to free the un-sending packet
pSkb = pWbLinux->skb_array[ pWbLinux->skb_GetIndex ];
pWbLinux->skb_array[ pWbLinux->skb_GetIndex ] = NULL;
if( in_irq() )
dev_kfree_skb_irq( pSkb );
else
dev_kfree_skb( pSkb );
pWbLinux->skb_GetIndex++;
pWbLinux->skb_GetIndex %= WBLINUX_PACKET_ARRAY_SIZE;
}
#ifdef _PE_STATE_DUMP_
WBDEBUG(( "[w35und] SKB_RELEASE OK\n" ));
#endif
}
OS_ATOMIC_DEC( Adapter, &pWbLinux->ThreadCount );
}
void
WbWlanHalt( PADAPTER Adapter )
{
//---------------------
Adapter->sLocalPara.ShutDowned = TRUE;
Mds_Destroy( Adapter );
// Turn off Rx and Tx hardware ability
hal_stop( &Adapter->sHwData );
#ifdef _PE_USB_INI_DUMP_
WBDEBUG(("[w35und] Hal_stop O.K.\n"));
#endif
OS_SLEEP(100000);// Waiting Irp completed
// Destroy the NDIS module
WBLINUX_Destroy( Adapter );
// Halt the HAL
hal_halt(&Adapter->sHwData, NULL);
}
unsigned char
WbWLanInitialize(PADAPTER Adapter)
{
phw_data_t pHwData;
PUCHAR pMacAddr, pMacAddr2;
u32 InitStep = 0;
u8 EEPROM_region;
u8 HwRadioOff;
do {
//
// Setting default value for Linux
//
Adapter->sLocalPara.region_INF = REGION_AUTO;
Adapter->sLocalPara.TxRateMode = RATE_AUTO;
psLOCAL->bMacOperationMode = MODE_802_11_BG; // B/G mode
Adapter->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
Adapter->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
hal_set_phy_type( &Adapter->sHwData, RF_WB_242_1 );
Adapter->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
psLOCAL->bPreambleMode = AUTO_MODE;
Adapter->sLocalPara.RadioOffStatus.boSwRadioOff = FALSE;
pHwData = &Adapter->sHwData;
hal_set_phy_type( pHwData, RF_DECIDE_BY_INF );
//
// Initial each module and variable
//
if (!WBLINUX_Initial(Adapter)) {
#ifdef _PE_USB_INI_DUMP_
WBDEBUG(("[w35und]WBNDIS initialization failed\n"));
#endif
break;
}
// Initial Software variable
Adapter->sLocalPara.ShutDowned = FALSE;
//added by ws for wep key error detection
Adapter->sLocalPara.bWepKeyError= FALSE;
Adapter->sLocalPara.bToSelfPacketReceived = FALSE;
Adapter->sLocalPara.WepKeyDetectTimerCount= 2 * 100; /// 2 seconds
// Initial USB hal
InitStep = 1;
pHwData = &Adapter->sHwData;
if (!hal_init_hardware(pHwData, Adapter))
break;
EEPROM_region = hal_get_region_from_EEPROM( pHwData );
if (EEPROM_region != REGION_AUTO)
psLOCAL->region = EEPROM_region;
else {
if (psLOCAL->region_INF != REGION_AUTO)
psLOCAL->region = psLOCAL->region_INF;
else
psLOCAL->region = REGION_USA; //default setting
}
// Get Software setting flag from hal
Adapter->sLocalPara.boAntennaDiversity = FALSE;
if (hal_software_set(pHwData) & 0x00000001)
Adapter->sLocalPara.boAntennaDiversity = TRUE;
//
// For TS module
//
InitStep = 2;
// For MDS module
InitStep = 3;
Mds_initial(Adapter);
//=======================================
// Initialize the SME, SCAN, MLME, ROAM
//=======================================
InitStep = 4;
InitStep = 5;
InitStep = 6;
// If no user-defined address in the registry, use the addresss "burned" on the NIC instead.
pMacAddr = Adapter->sLocalPara.ThisMacAddress;
pMacAddr2 = Adapter->sLocalPara.PermanentAddress;
hal_get_permanent_address( pHwData, Adapter->sLocalPara.PermanentAddress );// Reading ethernet address from EEPROM
if (OS_MEMORY_COMPARE(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH )) // Is equal
{
memcpy( pMacAddr, pMacAddr2, MAC_ADDR_LENGTH );
} else {
// Set the user define MAC address
hal_set_ethernet_address( pHwData, Adapter->sLocalPara.ThisMacAddress );
}
//get current antenna
psLOCAL->bAntennaNo = hal_get_antenna_number(pHwData);
#ifdef _PE_STATE_DUMP_
WBDEBUG(("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo));
#endif
hal_get_hw_radio_off( pHwData );
// Waiting for HAL setting OK
while (!hal_idle(pHwData))
OS_SLEEP(10000);
MTO_Init(Adapter);
HwRadioOff = hal_get_hw_radio_off( pHwData );
psLOCAL->RadioOffStatus.boHwRadioOff = !!HwRadioOff;
hal_set_radio_mode( pHwData, (unsigned char)(psLOCAL->RadioOffStatus.boSwRadioOff || psLOCAL->RadioOffStatus.boHwRadioOff) );
hal_driver_init_OK(pHwData) = 1; // Notify hal that the driver is ready now.
//set a tx power for reference.....
// sme_set_tx_power_level(Adapter, 12); FIXME?
return TRUE;
}
while(FALSE);
switch (InitStep) {
case 5:
case 4:
case 3: Mds_Destroy( Adapter );
case 2:
case 1: WBLINUX_Destroy( Adapter );
hal_halt( pHwData, NULL );
case 0: break;
}
return FALSE;
}
void WBLINUX_ConnectStatus(PADAPTER Adapter, u32 flag)
{
PWBLINUX pWbLinux = &Adapter->WbLinux;
pWbLinux->LinkStatus = flag; // OS_DISCONNECTED or OS_CONNECTED
}
//=========================================================================
// Copyright (c) 1996-2004 Winbond Electronic Corporation
//
// wblinux_f.h
//
u32 WBLINUX_MemoryAlloc( void* *VirtualAddress, u32 Length );
s32 EncapAtomicInc( PADAPTER Adapter, void* pAtomic );
s32 EncapAtomicDec( PADAPTER Adapter, void* pAtomic );
void WBLinux_ReceivePacket( PADAPTER Adapter, PRXLAYER1 pRxLayer1 );
unsigned char WBLINUX_Initial( PADAPTER Adapter );
int wb35_start_xmit(struct sk_buff *skb, struct net_device *netdev );
void WBLINUX_GetNextPacket( PADAPTER Adapter, PDESCRIPTOR pDes );
void WBLINUX_GetNextPacketCompleted( PADAPTER Adapter, PDESCRIPTOR pDes );
void WBLINUX_stop( PADAPTER Adapter );
void WBLINUX_Destroy( PADAPTER Adapter );
void wb35_set_multicast( struct net_device *netdev );
struct net_device_stats * wb35_netdev_stats( struct net_device *netdev );
void WBLINUX_stop( PADAPTER Adapter );
void WbWlanHalt( PADAPTER Adapter );
void WBLINUX_ConnectStatus( PADAPTER Adapter, u32 flag );
//============================================================
// wblinux_s.h
//
#define OS_MEMORY_ALLOC( _V, _S ) WBLINUX_MemoryAlloc( _V, _S )
#define OS_LINK_STATUS (Adapter->WbLinux.LinkStatus == OS_CONNECTED)
#define OS_SET_SHUTDOWN( _A ) _A->WbLinux.shutdown=1
#define OS_SET_RESUME( _A ) _A->WbLinux.shutdown=0
#define OS_CONNECT_STATUS_INDICATE( _A, _F ) WBLINUX_ConnectStatus( _A, _F )
#define OS_DISCONNECTED 0
#define OS_CONNECTED 1
#define OS_STOP( _A ) WBLINUX_stop( _A )
#define OS_CURRENT_RX_BYTE( _A ) _A->WbLinux.RxByteCount
#define OS_CURRENT_TX_BYTE( _A ) _A->WbLinux.TxByteCount
#define OS_EVENT_INDICATE( _A, _B, _F )
#define OS_PMKID_STATUS_EVENT( _A )
#define OS_RECEIVE_PACKET_INDICATE( _A, _D ) WBLinux_ReceivePacket( _A, _D )
#define OS_RECEIVE_802_1X_PACKET_INDICATE( _A, _D ) EAP_ReceivePacket( _A, _D )
#define OS_GET_PACKET( _A, _D ) WBLINUX_GetNextPacket( _A, _D )
#define OS_GET_PACKET_COMPLETE( _A, _D ) WBLINUX_GetNextPacketCompleted( _A, _D )
#define OS_SEND_RESULT( _A, _ID, _R )
#define WBLINUX_PACKET_ARRAY_SIZE (ETHERNET_TX_DESCRIPTORS*4)
typedef struct _WBLINUX
{
OS_SPIN_LOCK AtomicSpinLock;
OS_SPIN_LOCK SpinLock;
u32 shutdown;
OS_ATOMIC ThreadCount;
u32 LinkStatus; // OS_DISCONNECTED or OS_CONNECTED
u32 RxByteCount;
u32 TxByteCount;
struct sk_buff *skb_array[ WBLINUX_PACKET_ARRAY_SIZE ];
struct sk_buff *packet_return;
s32 skb_SetIndex;
s32 skb_GetIndex;
s32 netif_state_stop; // 1: stop 0: normal
} WBLINUX, *PWBLINUX;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment