⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5212_misc.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5212_misc.c,v 1.3 2006/10/13 07:10:49 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5212#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#ifdef AH_DEBUG#include "ah_desc.h"			/* NB: for HAL_PHYERR* */#endif#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#ifdef AH_SUPPORT_AR5311#include "ar5212/ar5311reg.h"#endif#define	AR_NUM_GPIO	6		/* 6 GPIO pins */#define	AR_GPIOD_MASK	0x0000002F	/* GPIO data reg r/w mask */#define	ANT_SWITCH_TABLE1	AR_PHY(88)#define	ANT_SWITCH_TABLE2	AR_PHY(89)extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);voidar5212GetMacAddress(struct ath_hal *ah, u_int8_t *mac){	struct ath_hal_5212 *ahp = AH5212(ah);	OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);}HAL_BOOLar5212SetMacAddress(struct ath_hal *ah, const u_int8_t *mac){	struct ath_hal_5212 *ahp = AH5212(ah);	OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);	return AH_TRUE;}voidar5212GetBssIdMask(struct ath_hal *ah, u_int8_t *mask){	struct ath_hal_5212 *ahp = AH5212(ah);	OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);}HAL_BOOLar5212SetBssIdMask(struct ath_hal *ah, const u_int8_t *mask){	struct ath_hal_5212 *ahp = AH5212(ah);	/* save it since it must be rewritten on reset */	OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);	OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));	OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));	return AH_TRUE;}/* * Attempt to change the cards operating regulatory domain to the given value * Returns: A_EINVAL for an unsupported regulatory domain. *          A_HARDWARE for an unwritable EEPROM or bad EEPROM version */HAL_BOOLar5212SetRegulatoryDomain(struct ath_hal *ah,	u_int16_t regDomain, HAL_STATUS *status){	struct ath_hal_5212 *ahp = AH5212(ah);	HAL_STATUS ecode;	if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {		ecode = HAL_EINVAL;		goto bad;	}	if (ahp->ah_eeprotect & AR_EEPROM_PROTECT_WP_128_191) {		ecode = HAL_EEWRITE;		goto bad;	}#ifdef AH_SUPPORT_WRITE_REGDOMAIN	if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {		HALDEBUG(ah, "%s: set regulatory domain to %u (0x%x)\n",			__func__, regDomain, regDomain);		AH_PRIVATE(ah)->ah_currentRD = regDomain;		return AH_TRUE;	}#endif	ecode = HAL_EIO;bad:	if (status)		*status = ecode;	return AH_FALSE;}/* * Return the wireless modes (a,b,g,t) supported by hardware. * * This value is what is actually supported by the hardware * and is unaffected by regulatory/country code settings. * */u_intar5212GetWirelessModes(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	u_int mode = 0;	if (ahp->ah_Amode) {		mode = HAL_MODE_11A;		if (!ahp->ah_turbo5Disable)			mode |= HAL_MODE_TURBO | HAL_MODE_108A;#ifdef AH_SUPPORT_AR5416			if (IS_5416(ah)) {			mode |= HAL_MODE_11NA;		}#endif	}	if (ahp->ah_Bmode)		mode |= HAL_MODE_11B;	if (ahp->ah_Gmode &&	    AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {		mode |= HAL_MODE_11G;		if (!ahp->ah_turbo2Disable) 			mode |= HAL_MODE_108G;#ifdef AH_SUPPORT_AR5416			if (IS_5416(ah)) {			mode |= HAL_MODE_11NG;		}#endif	}	return mode;}/* * Accessor to get rfkill info from private EEPROM structures */HAL_BOOLar5212GetRfKill(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	if (ahp->ah_rfKill) {		u_int16_t rfsilent;		if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &rfsilent))			return AH_FALSE;		ahp->ah_gpioSelect = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);		ahp->ah_polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);		ahp->ah_eepEnabled = AH_TRUE;	} else {		ahp->ah_gpioSelect = 0;		ahp->ah_polarity = 0;		ahp->ah_eepEnabled = AH_FALSE;	}	return (ahp->ah_rfKill != 0);}/* * Set the interrupt and GPIO values so the ISR can disable RF * on a switch signal.  Assumes GPIO port and interrupt polarity * are set prior to call. */voidar5212EnableRfKill(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	/* Ignore for Owl */	if (IS_5416(ah))		return;	/*	 * Configure the desired GPIO port for input	 * and enable baseband rf silence.	 */	ath_hal_gpioCfgInput(ah, ahp->ah_gpioSelect);	OS_REG_WRITE(ah, AR_PHY(0), OS_REG_READ(ah, AR_PHY(0)) | 0x00002000);	/*	 * If radio disable switch connection to GPIO bit x is enabled	 * program GPIO interrupt.	 * If rfkill bit on eeprom is 1, setupeeprommap routine has already	 * verified that it is a later version of eeprom, it has a place for	 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware	 * connection is present.	 */	ahp->ah_gpioBit = ath_hal_gpioGet(ah, ahp->ah_gpioSelect);	ath_hal_gpioSetIntr(ah, ahp->ah_gpioSelect,		(ahp->ah_gpioBit != ahp->ah_polarity));}/* * Change the LED blinking pattern to correspond to the connectivity */voidar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state){	static const u_int32_t ledbits[8] = {		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */		AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/		AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,		AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND,	};	OS_REG_WRITE(ah, AR_PCICFG,		(OS_REG_READ(ah, AR_PCICFG) &~			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE))		| ledbits[state & 0x7]	);}/* * Change association related fields programmed into the hardware. * Writing a valid BSSID to the hardware effectively enables the hardware * to synchronize its TSF to the correct beacons and receive frames coming * from that BSSID. It is called by the SME JOIN operation. */voidar5212WriteAssocid(struct ath_hal *ah, const u_int8_t *bssid, u_int16_t assocId){	struct ath_hal_5212 *ahp = AH5212(ah);	/* XXX save bssid for possible re-use on reset */	OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |				     ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));	/*	 * XXX WAR for a hardware bug in Oahu. Write a 0 associd to prevent	 * hardware from parsing beyond end of TIM element. It will avoid	 * sending spurious PS-polls. Beacon/TIM processing done in software	 */	OS_REG_RMW_FIELD(ah, AR_BSS_ID1, AR_BSS_ID1_AID, 0);}/* * Get the current hardware tsf for stamlme */u_int64_tar5212GetTsf64(struct ath_hal *ah){	u_int64_t tsf;	/* XXX sync multi-word read? */	tsf = OS_REG_READ(ah, AR_TSF_U32);	tsf = (tsf << 32) | OS_REG_READ(ah, AR_TSF_L32);	return tsf;}/* * Get the current hardware tsf for stamlme */u_int32_tar5212GetTsf32(struct ath_hal *ah){	return OS_REG_READ(ah, AR_TSF_L32);}/* * Reset the current hardware tsf for stamlme. */voidar5212ResetTsf(struct ath_hal *ah){	u_int32_t val = OS_REG_READ(ah, AR_BEACON);	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);	/*	 * workaround for hw bug! when resetting the TSF, write twice to the	 * corresponding register; each write to the RESET_TSF bit toggles	 * the internal signal to cause a reset of the TSF - but if the signal	 * is left high, it will reset the TSF on the next chip reset also!	 * writing the bit an even number of times fixes this issue	 */	OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);}/* * Set or clear hardware basic rate bit * Set hardware basic rate set if basic rate is found * and basic rate is equal or less than 2Mbps */voidar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs){	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;	u_int32_t reg;	u_int8_t xset;	int i;	if (chan == AH_NULL || !IS_CHAN_CCK(chan))		return;	xset = 0;	for (i = 0; i < rs->rs_count; i++) {		u_int8_t rset = rs->rs_rates[i];		/* Basic rate defined? */		if ((rset & 0x80) && (rset &= 0x7f) >= xset)			xset = rset;	}	/*	 * Set the h/w bit to reflect whether or not the basic	 * rate is found to be equal or less than 2Mbps.	 */	reg = OS_REG_READ(ah, AR_STA_ID1);	if (xset && xset/2 <= 2)		OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);	else		OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);}/* * Grab a semi-random value from hardware registers - may not * change often */u_int32_tar5212GetRandomSeed(struct ath_hal *ah){	u_int32_t nf;	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;	if (nf & 0x100)		nf = 0 - ((nf ^ 0x1ff) + 1);	return (OS_REG_READ(ah, AR_TSF_U32) ^		OS_REG_READ(ah, AR_TSF_L32) ^ nf);}/* * Detect if our card is present */HAL_BOOLar5212DetectCardPresent(struct ath_hal *ah){	u_int16_t macVersion, macRev;	u_int32_t v;	/*	 * Read the Silicon Revision register and compare that	 * to what we read at attach time.  If the same, we say	 * a card/device is present.	 */	v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;	macVersion = v >> AR_SREV_ID_S;	macRev = v & AR_SREV_REVISION;	return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&		AH_PRIVATE(ah)->ah_macRev == macRev);}/* * Update MIB Counters */voidar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats){	stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);	stats->rts_bad	  += OS_REG_READ(ah, AR_RTS_FAIL);	stats->fcs_bad	  += OS_REG_READ(ah, AR_FCS_FAIL);	stats->rts_good	  += OS_REG_READ(ah, AR_RTS_OK);	stats->beacons	  += OS_REG_READ(ah, AR_BEACON_CNT);}/* * Detect if the HW supports spreading a CCK signal on channel 14 */HAL_BOOLar5212IsJapanChannelSpreadSupported(struct ath_hal *ah){	return AH_TRUE;}/* * Get the rssi of frame curently being received. */u_int32_tar5212GetCurRssi(struct ath_hal *ah){	return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);}u_intar5212GetDefAntenna(struct ath_hal *ah){   	return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);}   voidar5212SetDefAntenna(struct ath_hal *ah, u_int antenna){	OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));}HAL_BOOLar5212SetAntennaSwitch(struct ath_hal *ah,	HAL_ANT_SETTING settings, HAL_CHANNEL *chan){	struct ath_hal_5212 *ahp = AH5212(ah);	u_int32_t antSwitchA, antSwitchB;	int ix;	u_int8_t opt;	opt = (settings & HAL_ANT_OPT_MASK) >> HAL_ANT_OPT_SHIFT;	switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {	case CHANNEL_A:		ix = 0; break;	case CHANNEL_B:		ix = 1; break;	case CHANNEL_PUREG:	ix = 2; break;	default:		HALDEBUG(ah, "%s: invalid channel flags 0x%x\n",			__func__, chan->channelFlags);		return AH_FALSE;	}	antSwitchA =  (ahp->ah_antennaControl[1][ix] &~ opt)		   | ((ahp->ah_antennaControl[2][ix] &~ opt) << 6)		   | ((ahp->ah_antennaControl[3][ix] &~ opt) << 12) 		   | ((ahp->ah_antennaControl[4][ix] &~ opt) << 18)		   | ((ahp->ah_antennaControl[5][ix] &~ opt) << 24)		   ;	antSwitchB =  (ahp->ah_antennaControl[6][ix] &~ opt)		   | ((ahp->ah_antennaControl[7][ix] &~ opt) << 6)		   | ((ahp->ah_antennaControl[8][ix] &~ opt) << 12)		   | ((ahp->ah_antennaControl[9][ix] &~ opt) << 18)		   | ((ahp->ah_antennaControl[10][ix] &~ opt) << 24)		   ;	/*	 * For fixed antenna, give the same setting for both switch banks	 */	switch (settings & 0x0f) {	case HAL_ANT_FIXED_A:		antSwitchB = antSwitchA;		break;	case HAL_ANT_FIXED_B:		antSwitchA = antSwitchB;		break;	case HAL_ANT_VARIABLE:		break;	default:		HALDEBUG(ah, "%s: bad antenna setting %u\n",			__func__, settings);		return AH_FALSE;	}	ahp->ah_diversityControl = settings;	OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);	OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);	return AH_TRUE;}HAL_BOOLar5212IsSleepAfterBeaconBroken(struct ath_hal *ah){	return AH_TRUE;}HAL_BOOLar5212SetSlotTime(struct ath_hal *ah, u_int us){	struct ath_hal_5212 *ahp = AH5212(ah);	if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {		HALDEBUG(ah, "%s: bad slot time %u\n", __func__, us);		ahp->ah_slottime = (u_int) -1;	/* restore default handling */		return AH_FALSE;	} else {		/* convert to system clocks */		OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));		ahp->ah_slottime = us;		return AH_TRUE;	}}u_intar5212GetSlotTime(struct ath_hal *ah){	u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;	return ath_hal_mac_usec(ah, clks);	/* convert from system clocks */}HAL_BOOLar5212SetAckTimeout(struct ath_hal *ah, u_int us){	struct ath_hal_5212 *ahp = AH5212(ah);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -