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

📄 bcm43xx_radio.c

📁 无线网卡驱动,有很好的参考价值,在linux_2.6.21下可以直接使用,如果在其他平台,可以参考移植
💻 C
📖 第 1 页 / 共 4 页
字号:
		bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);		break;	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)			break;		radio->aci_enable = 1;		phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);		phy_stacksave(BCM43xx_PHY_G_CRS);		if (phy->rev < 2) {			phy_stacksave(0x0406);		} else {			phy_stacksave(0x04C0);			phy_stacksave(0x04C1);		}		phy_stacksave(0x0033);		phy_stacksave(0x04A7);		phy_stacksave(0x04A3);		phy_stacksave(0x04A9);		phy_stacksave(0x04AA);		phy_stacksave(0x04AC);		phy_stacksave(0x0493);		phy_stacksave(0x04A1);		phy_stacksave(0x04A0);		phy_stacksave(0x04A2);		phy_stacksave(0x048A);		phy_stacksave(0x04A8);		phy_stacksave(0x04AB);		if (phy->rev == 2) {			phy_stacksave(0x04AD);			phy_stacksave(0x04AE);		} else if (phy->rev >= 3) {			phy_stacksave(0x04AD);			phy_stacksave(0x0415);			phy_stacksave(0x0416);			phy_stacksave(0x0417);			ilt_stacksave(0x1A00 + 0x2);			ilt_stacksave(0x1A00 + 0x3);		}		phy_stacksave(0x042B);		phy_stacksave(0x048C);		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)				  & ~0x1000);		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)				   & 0xFFFC) | 0x0002);		bcm43xx_phy_write(bcm, 0x0033, 0x0800);		bcm43xx_phy_write(bcm, 0x04A3, 0x2027);		bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);		bcm43xx_phy_write(bcm, 0x0493, 0x287A);		bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);		bcm43xx_phy_write(bcm, 0x04AC, 0x287A);		bcm43xx_phy_write(bcm, 0x04A0,				  (bcm43xx_phy_read(bcm, 0x04A0)				   & 0xFFC0) | 0x001A);		bcm43xx_phy_write(bcm, 0x04A7, 0x000D);		if (phy->rev < 2) {			bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);		} else if (phy->rev == 2) {			bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);			bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);		} else {			bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);			bcm43xx_phy_write(bcm, 0x04C1, 0x0059);		}		bcm43xx_phy_write(bcm, 0x04A1,		                  (bcm43xx_phy_read(bcm, 0x04A1)				   & 0xC0FF) | 0x1800);		bcm43xx_phy_write(bcm, 0x04A1,		                  (bcm43xx_phy_read(bcm, 0x04A1)				   & 0xFFC0) | 0x0015);		bcm43xx_phy_write(bcm, 0x04A8,		                  (bcm43xx_phy_read(bcm, 0x04A8)				   & 0xCFFF) | 0x1000);		bcm43xx_phy_write(bcm, 0x04A8,		                  (bcm43xx_phy_read(bcm, 0x04A8)				   & 0xF0FF) | 0x0A00);		bcm43xx_phy_write(bcm, 0x04AB,		                  (bcm43xx_phy_read(bcm, 0x04AB)				   & 0xCFFF) | 0x1000);		bcm43xx_phy_write(bcm, 0x04AB,		                  (bcm43xx_phy_read(bcm, 0x04AB)				   & 0xF0FF) | 0x0800);		bcm43xx_phy_write(bcm, 0x04AB,		                  (bcm43xx_phy_read(bcm, 0x04AB)				   & 0xFFCF) | 0x0010);		bcm43xx_phy_write(bcm, 0x04AB,		                  (bcm43xx_phy_read(bcm, 0x04AB)				   & 0xFFF0) | 0x0005);		bcm43xx_phy_write(bcm, 0x04A8,		                  (bcm43xx_phy_read(bcm, 0x04A8)				   & 0xFFCF) | 0x0010);		bcm43xx_phy_write(bcm, 0x04A8,		                  (bcm43xx_phy_read(bcm, 0x04A8)				   & 0xFFF0) | 0x0006);		bcm43xx_phy_write(bcm, 0x04A2,		                  (bcm43xx_phy_read(bcm, 0x04A2)				   & 0xF0FF) | 0x0800);		bcm43xx_phy_write(bcm, 0x04A0,				  (bcm43xx_phy_read(bcm, 0x04A0)				   & 0xF0FF) | 0x0500);		bcm43xx_phy_write(bcm, 0x04A2,				  (bcm43xx_phy_read(bcm, 0x04A2)				   & 0xFFF0) | 0x000B);		if (phy->rev >= 3) {			bcm43xx_phy_write(bcm, 0x048A,					  bcm43xx_phy_read(bcm, 0x048A)					  & ~0x8000);			bcm43xx_phy_write(bcm, 0x0415,					  (bcm43xx_phy_read(bcm, 0x0415)					   & 0x8000) | 0x36D8);			bcm43xx_phy_write(bcm, 0x0416,					  (bcm43xx_phy_read(bcm, 0x0416)					   & 0x8000) | 0x36D8);			bcm43xx_phy_write(bcm, 0x0417,					  (bcm43xx_phy_read(bcm, 0x0417)					   & 0xFE00) | 0x016D);		} else {			bcm43xx_phy_write(bcm, 0x048A,					  bcm43xx_phy_read(bcm, 0x048A)					  | 0x1000);			bcm43xx_phy_write(bcm, 0x048A,					  (bcm43xx_phy_read(bcm, 0x048A)					   & 0x9FFF) | 0x2000);			tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,						   BCM43xx_UCODEFLAGS_OFFSET);			if (!(tmp32 & 0x800)) {				tmp32 |= 0x800;				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,						    BCM43xx_UCODEFLAGS_OFFSET,						    tmp32);			}		}		if (phy->rev >= 2) {			bcm43xx_phy_write(bcm, 0x042B,					  bcm43xx_phy_read(bcm, 0x042B)					  | 0x0800);		}		bcm43xx_phy_write(bcm, 0x048C,				  (bcm43xx_phy_read(bcm, 0x048C)				   & 0xF0FF) | 0x0200);		if (phy->rev == 2) {			bcm43xx_phy_write(bcm, 0x04AE,					  (bcm43xx_phy_read(bcm, 0x04AE)					   & 0xFF00) | 0x007F);			bcm43xx_phy_write(bcm, 0x04AD,					  (bcm43xx_phy_read(bcm, 0x04AD)					   & 0x00FF) | 0x1300);		} else if (phy->rev >= 6) {			bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);			bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);			bcm43xx_phy_write(bcm, 0x04AD,					  bcm43xx_phy_read(bcm, 0x04AD)					  & 0x00FF);		}		bcm43xx_calc_nrssi_slope(bcm);		break;	default:		assert(0);	}}static voidbcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,					      int mode){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u32 tmp32;	u32 *stack = radio->interfstack;	switch (mode) {	case BCM43xx_RADIO_INTERFMODE_NONWLAN:		if (phy->rev != 1) {			bcm43xx_phy_write(bcm, 0x042B,			                  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,			                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);			break;		}		phy_stackrestore(0x0078);		bcm43xx_calc_nrssi_threshold(bcm);		phy_stackrestore(0x0406);		bcm43xx_phy_write(bcm, 0x042B,				  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);		if (!bcm->bad_frames_preempt) {			bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,					  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)					  & ~(1 << 11));		}		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);		phy_stackrestore(0x04A0);		phy_stackrestore(0x04A1);		phy_stackrestore(0x04A2);		phy_stackrestore(0x04A8);		phy_stackrestore(0x04AB);		phy_stackrestore(0x04A7);		phy_stackrestore(0x04A3);		phy_stackrestore(0x04A9);		phy_stackrestore(0x0493);		phy_stackrestore(0x04AA);		phy_stackrestore(0x04AC);		break;	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))			break;		radio->aci_enable = 0;		phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);		phy_stackrestore(BCM43xx_PHY_G_CRS);		phy_stackrestore(0x0033);		phy_stackrestore(0x04A3);		phy_stackrestore(0x04A9);		phy_stackrestore(0x0493);		phy_stackrestore(0x04AA);		phy_stackrestore(0x04AC);		phy_stackrestore(0x04A0);		phy_stackrestore(0x04A7);		if (phy->rev >= 2) {			phy_stackrestore(0x04C0);			phy_stackrestore(0x04C1);		} else			phy_stackrestore(0x0406);		phy_stackrestore(0x04A1);		phy_stackrestore(0x04AB);		phy_stackrestore(0x04A8);		if (phy->rev == 2) {			phy_stackrestore(0x04AD);			phy_stackrestore(0x04AE);		} else if (phy->rev >= 3) {			phy_stackrestore(0x04AD);			phy_stackrestore(0x0415);			phy_stackrestore(0x0416);			phy_stackrestore(0x0417);			ilt_stackrestore(0x1A00 + 0x2);			ilt_stackrestore(0x1A00 + 0x3);		}		phy_stackrestore(0x04A2);		phy_stackrestore(0x04A8);		phy_stackrestore(0x042B);		phy_stackrestore(0x048C);		tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,					   BCM43xx_UCODEFLAGS_OFFSET);		if (tmp32 & 0x800) {			tmp32 &= ~0x800;			bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,					    BCM43xx_UCODEFLAGS_OFFSET,					    tmp32);		}		bcm43xx_calc_nrssi_slope(bcm);		break;	default:		assert(0);	}}#undef phy_stacksave#undef phy_stackrestore#undef radio_stacksave#undef radio_stackrestore#undef ilt_stacksave#undef ilt_stackrestoreint bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,					      int mode){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	int currentmode;	if ((phy->type != BCM43xx_PHYTYPE_G) ||	    (phy->rev == 0) ||	    (!phy->connected))		return -ENODEV;	radio->aci_wlan_automatic = 0;	switch (mode) {	case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:		radio->aci_wlan_automatic = 1;		if (radio->aci_enable)			mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;		else			mode = BCM43xx_RADIO_INTERFMODE_NONE;		break;	case BCM43xx_RADIO_INTERFMODE_NONE:	case BCM43xx_RADIO_INTERFMODE_NONWLAN:	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		break;	default:		return -EINVAL;	}	currentmode = radio->interfmode;	if (currentmode == mode)		return 0;	if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)		bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);	if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {		radio->aci_enable = 0;		radio->aci_hw_rssi = 0;	} else		bcm43xx_radio_interference_mitigation_enable(bcm, mode);	radio->interfmode = mode;	return 0;}u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm){	u16 reg, index, ret;	reg = bcm43xx_radio_read16(bcm, 0x0060);	index = (reg & 0x001E) >> 1;	ret = rcc_table[index] << 1;	ret |= (reg & 0x0001);	ret |= 0x0020;	return ret;}u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 backup[19] = { 0 };	u16 ret;	u16 i, j;	u32 tmp1 = 0, tmp2 = 0;	backup[0] = bcm43xx_radio_read16(bcm, 0x0043);	backup[14] = bcm43xx_radio_read16(bcm, 0x0051);	backup[15] = bcm43xx_radio_read16(bcm, 0x0052);	backup[1] = bcm43xx_phy_read(bcm, 0x0015);	backup[16] = bcm43xx_phy_read(bcm, 0x005A);	backup[17] = bcm43xx_phy_read(bcm, 0x0059);	backup[18] = bcm43xx_phy_read(bcm, 0x0058);	if (phy->type == BCM43xx_PHYTYPE_B) {		backup[2] = bcm43xx_phy_read(bcm, 0x0030);		backup[3] = bcm43xx_read16(bcm, 0x03EC);		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);	} else {		if (phy->connected) {			backup[4] = bcm43xx_phy_read(bcm, 0x0811);			backup[5] = bcm43xx_phy_read(bcm, 0x0812);			backup[6] = bcm43xx_phy_read(bcm, 0x0814);			backup[7] = bcm43xx_phy_read(bcm, 0x0815);			backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);			backup[9] = bcm43xx_phy_read(bcm, 0x0802);			bcm43xx_phy_write(bcm, 0x0814,			                  (bcm43xx_phy_read(bcm, 0x0814) | 0x0003));			bcm43xx_phy_write(bcm, 0x0815,			                  (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC));				bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,			                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF));			bcm43xx_phy_write(bcm, 0x0802,			                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));			bcm43xx_phy_write(bcm, 0x0811, 0x01B3);			bcm43xx_phy_write(bcm, 0x0812, 0x0FB2);		}		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,		                (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));	}	backup[10] = bcm43xx_phy_read(bcm, 0x0035);	bcm43xx_phy_write(bcm, 0x0035,	                  (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));	backup[11] = bcm43xx_read16(bcm, 0x03E6);	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);	// Initialization	if (phy->analog == 0) {		bcm43xx_write16(bcm, 0x03E6, 0x0122);	} else {		if (phy->analog >= 2)			bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003)					& 0xFFBF) | 0x0040);		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));	}	ret = bcm43xx_radio_calibrationvalue(bcm);	if (phy->type == BCM43xx_PHYTYPE_B)		bcm43xx_radio_write16(bcm, 0x0078, 0x0026);	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);	bcm43xx_phy_write(bcm, 0x002B, 0x1403);	if (phy->connected)		bcm43xx_phy_write(bcm, 0x0812, 0x00B2);	bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);	bcm43xx_radio_write16(bcm, 0x0051,	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);	bcm43xx_radio_write16(bcm, 0x0043,			      (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 0x0009);	bcm43xx_phy_write(bcm, 0x0058, 0x0000);	for (i = 0; i < 16; i++) {		bcm43xx_phy_write(bcm, 0x005A, 0x0480);		bcm43xx_phy_write(bcm, 0x0059, 0xC810);		bcm43xx_phy_write(bcm, 0x0058, 0x000D);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);		udelay(10);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);		bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);		udelay(10);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);		bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);		udelay(10);		tmp1 += bcm43xx_phy_read(bcm, 0x002D);		bcm43xx_phy_write(bcm, 0x0058, 0x0000);		if (phy->connected)			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);	}	tmp1++;	tmp1 >>= 9;	udelay(10);	bcm43xx_phy_write(bcm, 0x0058, 0x0000);	for (i = 0; i < 16; i++) {		bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);		backup[13] = bcm43xx_radio_read16(bcm, 0x0078);		udelay(10);		for (j = 0; j < 16; j++) {			bcm43xx_phy_write(bcm, 0x005A, 0x0D80);			bcm43xx_phy_write(bcm, 0x0059, 0xC810);			bcm43xx_phy_write(bcm, 0x0058, 0x000D);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);			udelay(10);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);			bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);			udelay(10);			if (phy->connected)				bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */			bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);			udelay(10);			tmp2 += bcm43xx_phy_read(bcm, 0x002D);			bcm43xx_phy_write(bcm, 0x0058, 0x0000);			if (phy->connected)				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->analog != 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);

⌨️ 快捷键说明

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