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

📄 bcm43xx_radio.c

📁 博通的bcm43xx系列Minipci接口无线网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);		}		tmp2++;		tmp2 >>= 8;		if (tmp1 < tmp2)			break;	}	/* Restore the registers */	bcm43xx_phy_write(bcm, 0x0015, backup[1]);	bcm43xx_radio_write16(bcm, 0x0051, backup[14]);	bcm43xx_radio_write16(bcm, 0x0052, backup[15]);	bcm43xx_radio_write16(bcm, 0x0043, backup[0]);	bcm43xx_phy_write(bcm, 0x005A, backup[16]);	bcm43xx_phy_write(bcm, 0x0059, backup[17]);	bcm43xx_phy_write(bcm, 0x0058, backup[18]);	bcm43xx_write16(bcm, 0x03E6, backup[11]);	if (phy->version != 0)		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);	bcm43xx_phy_write(bcm, 0x0035, backup[10]);	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);	if (phy->type == BCM43xx_PHYTYPE_B) {		bcm43xx_phy_write(bcm, 0x0030, backup[2]);		bcm43xx_write16(bcm, 0x03EC, backup[3]);	} else {		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,				(bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));		if (phy->connected) {			bcm43xx_phy_write(bcm, 0x0811, backup[4]);			bcm43xx_phy_write(bcm, 0x0812, backup[5]);			bcm43xx_phy_write(bcm, 0x0814, backup[6]);			bcm43xx_phy_write(bcm, 0x0815, backup[7]);			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);			bcm43xx_phy_write(bcm, 0x0802, backup[9]);		}	}	if (i >= 15)		ret = backup[13];	return ret;}void bcm43xx_radio_init2060(struct bcm43xx_private *bcm){	int err;	bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);	bcm43xx_radio_write16(bcm, 0x0005, 0x0008);	bcm43xx_radio_write16(bcm, 0x0009, 0x0040);	bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);	bcm43xx_radio_write16(bcm, 0x0032, 0x008F);	bcm43xx_radio_write16(bcm, 0x0006, 0x008F);	bcm43xx_radio_write16(bcm, 0x0034, 0x008F);	bcm43xx_radio_write16(bcm, 0x002C, 0x0007);	bcm43xx_radio_write16(bcm, 0x0082, 0x0080);	bcm43xx_radio_write16(bcm, 0x0080, 0x0000);	bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);	udelay(400);	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);	udelay(400);	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);	bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);	bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);	bcm43xx_phy_write(bcm, 0x0069, 0x07BE);	bcm43xx_phy_write(bcm, 0x006A, 0x0000);	err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);	assert(err == 0);	udelay(1000);}static inlineu16 freq_r3A_value(u16 frequency){	u16 value;	if (frequency < 5091)		value = 0x0040;	else if (frequency < 5321)		value = 0x0000;	else if (frequency < 5806)		value = 0x0080;	else		value = 0x0040;	return value;}void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm){	static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };	static const u8 data_low[5]  = { 0x00, 0x01, 0x05, 0x06, 0x0A };	u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);	int i, j;		for (i = 0; i < 5; i++) {		for (j = 0; j < 5; j++) {			if (tmp == (data_high[i] << 4 | data_low[j])) {				bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);				return;			}		}	}}int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,				u8 channel,				int synthetic_pu_workaround){	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	u16 r8, tmp;	u16 freq;	if ((radio->manufact == 0x17F) &&	    (radio->version == 0x2060) &&	    (radio->revision == 1)) {		if (channel > 200)			return -EINVAL;		freq = channel2freq_a(channel);		r8 = bcm43xx_radio_read16(bcm, 0x0008);		bcm43xx_write16(bcm, 0x03F0, freq);		bcm43xx_radio_write16(bcm, 0x0008, r8);		TODO();//TODO: write max channel TX power? to Radio 0x2D		tmp = bcm43xx_radio_read16(bcm, 0x002E);		tmp &= 0x0080;		TODO();//TODO: OR tmp with the Power out estimation for this channel?		bcm43xx_radio_write16(bcm, 0x002E, tmp);		if (freq >= 4920 && freq <= 5500) {			/* 			 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;			 *    = (freq * 0.025862069			 */			r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */		}		bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);		bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);		bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);		bcm43xx_radio_write16(bcm, 0x0022,				      (bcm43xx_radio_read16(bcm, 0x0022)				       & 0x000F) | (r8 << 4));		bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));		bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));		bcm43xx_radio_write16(bcm, 0x0008,				      (bcm43xx_radio_read16(bcm, 0x0008)				       & 0x00F0) | (r8 << 4));		bcm43xx_radio_write16(bcm, 0x0029,				      (bcm43xx_radio_read16(bcm, 0x0029)				       & 0xFF0F) | 0x00B0);		bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);		bcm43xx_radio_write16(bcm, 0x0036, 0x0085);		bcm43xx_radio_write16(bcm, 0x003A,				      (bcm43xx_radio_read16(bcm, 0x003A)				       & 0xFF20) | freq_r3A_value(freq));		bcm43xx_radio_write16(bcm, 0x003D,				      bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);		bcm43xx_radio_write16(bcm, 0x0081,				      (bcm43xx_radio_read16(bcm, 0x0081)				       & 0xFF7F) | 0x0080);		bcm43xx_radio_write16(bcm, 0x0035,				      bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);		bcm43xx_radio_write16(bcm, 0x0035,				      (bcm43xx_radio_read16(bcm, 0x0035)				       & 0xFFEF) | 0x0010);		bcm43xx_radio_set_tx_iq(bcm);		TODO();	//TODO:	TSSI2dbm workaround		bcm43xx_phy_xmitpower(bcm);//FIXME correct?	} else {		if ((channel < 1) || (channel > 14))			return -EINVAL;		if (synthetic_pu_workaround)			bcm43xx_synth_pu_workaround(bcm, channel);		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,				channel2freq_bg(channel));		if (channel == 14) {			if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,						    BCM43xx_UCODEFLAGS_OFFSET,						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,								       BCM43xx_UCODEFLAGS_OFFSET)						    & ~(1 << 7));			} else {				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,						    BCM43xx_UCODEFLAGS_OFFSET,						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,								       BCM43xx_UCODEFLAGS_OFFSET)						    | (1 << 7));			}			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)					| (1 << 11));		} else {			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)					& 0xF7BF);		}	}	radio->channel = channel;	//XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states	//     that 2000 usecs might suffice.	udelay(8000);	return 0;}void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val){	u16 tmp;	val <<= 8;	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);}/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */static u16 bcm43xx_get_txgain_base_band(u16 txpower){	u16 ret;	assert(txpower <= 63);	if (txpower >= 54)		ret = 2;	else if (txpower >= 49)		ret = 4;	else if (txpower >= 44)		ret = 5;	else		ret = 6;	return ret;}/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower){	u16 ret;	assert(txpower <= 63);	if (txpower >= 32)		ret = 0;	else if (txpower >= 25)		ret = 1;	else if (txpower >= 20)		ret = 2;	else if (txpower >= 12)		ret = 3;	else		ret = 4;	return ret;}/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */static u16 bcm43xx_get_txgain_dac(u16 txpower){	u16 ret;	assert(txpower <= 63);	if (txpower >= 54)		ret = txpower - 53;	else if (txpower >= 49)		ret = txpower - 42;	else if (txpower >= 44)		ret = txpower - 37;	else if (txpower >= 32)		ret = txpower - 32;	else if (txpower >= 25)		ret = txpower - 20;	else if (txpower >= 20)		ret = txpower - 13;	else if (txpower >= 12)		ret = txpower - 8;	else		ret = txpower;	return ret;}void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower){	u16 pamp, base, dac, ilt;	txpower = limit_value(txpower, 0, 63);	pamp = bcm43xx_get_txgain_freq_power_amp(txpower);	pamp <<= 5;	pamp &= 0x00E0;	bcm43xx_phy_write(bcm, 0x0019, pamp);	base = bcm43xx_get_txgain_base_band(txpower);	base &= 0x000F;	bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);	ilt = bcm43xx_ilt_read(bcm, 0x3001);	ilt &= 0x0007;	dac = bcm43xx_get_txgain_dac(txpower);	dac <<= 3;	dac |= ilt;	bcm43xx_ilt_write(bcm, 0x3001, dac);	bcm->current_core->radio->txpower[0] = txpower;	TODO();	//TODO: FuncPlaceholder (Adjust BB loft cancel)}void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,                                 u16 baseband_attenuation, u16 radio_attenuation,                                 u16 txpower){	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	if (baseband_attenuation == 0xFFFF)		baseband_attenuation = radio->txpower[0];	else		radio->txpower[0] = baseband_attenuation;	if (radio_attenuation == 0xFFFF)		radio_attenuation = radio->txpower[1];	else		radio->txpower[1] = radio_attenuation;	if (txpower == 0xFFFF)		txpower = radio->txpower[2];	else		radio->txpower[2] = txpower;	assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);	if (radio->revision < 6)		assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);	else		assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);	assert(/*txpower >= 0 &&*/ txpower <= 7);	bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);	bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);	if (radio->version == 0x2050) {		bcm43xx_radio_write16(bcm, 0x0052,		                      (bcm43xx_radio_read16(bcm, 0x0052) & 0xFF8F)				       | (txpower << 4));	}	if (phy->type == BCM43xx_PHYTYPE_G)		bcm43xx_phy_lo_adjust(bcm, 0);}void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	int err;	if (radio->enabled)		return;	switch (phy->type) {	case BCM43xx_PHYTYPE_A:		bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);		bcm43xx_radio_write16(bcm, 0x0005, 0x0008);		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);		bcm43xx_radio_init2060(bcm);			break;	case BCM43xx_PHYTYPE_B:	case BCM43xx_PHYTYPE_G:		bcm43xx_phy_write(bcm, 0x0015, 0x8000);		bcm43xx_phy_write(bcm, 0x0015, 0xCC00);		bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));		err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);		assert(err == 0);		break;	default:		assert(0);	}	radio->enabled = 1;	dprintk(KERN_INFO PFX "Radio turned on\n");}	void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	if (phy->type == BCM43xx_PHYTYPE_A) {		bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);		bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);	}	if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {		bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);		bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);	} else		bcm43xx_phy_write(bcm, 0x0015, 0xAA00);	radio->enabled = 0;	dprintk(KERN_INFO PFX "Radio turned off\n");}void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm){	switch (bcm->current_core->phy->type) {	case BCM43xx_PHYTYPE_A:		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);		break;	case BCM43xx_PHYTYPE_B:	case BCM43xx_PHYTYPE_G:		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);		break;	}}

⌨️ 快捷键说明

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