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

📄 bcm43xx_radio.c

📁 博通的bcm43xx系列Minipci接口无线网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef stack_restore# undef stack_restore#endif#define stack_save(value)  \	do {							\	 	assert(i < ARRAY_SIZE(radio->interfstack));	\		stack[i++] = (value);				\	} while (0)#define stack_restore()  \	({							\	 	assert(i < ARRAY_SIZE(radio->interfstack));	\	 	stack[i++];					\	})static voidbcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,					     int mode){	struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	int i = 0;	u16 *stack = radio->interfstack;	u16 tmp, flipped;	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;		}		tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);		flipped = flip_4bit(tmp);		if ((flipped >> 1) >= 4)			tmp = flipped - 3;		tmp = flip_4bit(tmp);		bcm43xx_radio_write16(bcm, 0x0078, tmp << 1);		bcm43xx_calc_nrssi_threshold(bcm);		if (bcm->current_core->rev < 5) {			stack_save(bcm43xx_phy_read(bcm, 0x0406));			bcm43xx_phy_write(bcm, 0x0406, 0x7E28);		} else {			stack_save(bcm43xx_phy_read(bcm, 0x04C0));			stack_save(bcm43xx_phy_read(bcm, 0x04C1));			bcm43xx_phy_write(bcm, 0x04C0, 0x3E04);			bcm43xx_phy_write(bcm, 0x04C1, 0x0640);		}		bcm43xx_phy_write(bcm, 0x042B,		                  bcm43xx_phy_read(bcm, 0x042B) | 0x0800);		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,		                  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);		stack_save(bcm43xx_phy_read(bcm, 0x04A0));		bcm43xx_phy_write(bcm, 0x04A0,		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);		stack_save(bcm43xx_phy_read(bcm, 0x04A1));		bcm43xx_phy_write(bcm, 0x04A1,				  (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);		stack_save(bcm43xx_phy_read(bcm, 0x04A2));		bcm43xx_phy_write(bcm, 0x04A2,				  (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);		stack_save(bcm43xx_phy_read(bcm, 0x04A8));		bcm43xx_phy_write(bcm, 0x04A8,				  (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403);		stack_save(bcm43xx_phy_read(bcm, 0x04AB));		bcm43xx_phy_write(bcm, 0x04AB,				  (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504);		stack_save(bcm43xx_phy_read(bcm, 0x04A7));		bcm43xx_phy_write(bcm, 0x04A7, 0x0002);		stack_save(bcm43xx_phy_read(bcm, 0x04A3));		bcm43xx_phy_write(bcm, 0x04A3, 0x287A);		stack_save(bcm43xx_phy_read(bcm, 0x04A9));		bcm43xx_phy_write(bcm, 0x04A9, 0x2027);		stack_save(bcm43xx_phy_read(bcm, 0x0493));		bcm43xx_phy_write(bcm, 0x0493, 0x32F5);		stack_save(bcm43xx_phy_read(bcm, 0x04AA));		bcm43xx_phy_write(bcm, 0x04AA, 0x2027);		stack_save(bcm43xx_phy_read(bcm, 0x04AC));		bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);		break;	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800)			break;		radio->aci_enable = 1;		stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD));		stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS));		if (bcm->current_core->rev < 5) {			stack_save(bcm43xx_phy_read(bcm, 0x0406));		} else {			stack_save(bcm43xx_phy_read(bcm, 0x04C0));			stack_save(bcm43xx_phy_read(bcm, 0x04C1));		}		stack_save(bcm43xx_phy_read(bcm, 0x0033));		stack_save(bcm43xx_phy_read(bcm, 0x04A7));		stack_save(bcm43xx_phy_read(bcm, 0x04A3));		stack_save(bcm43xx_phy_read(bcm, 0x04A9));		stack_save(bcm43xx_phy_read(bcm, 0x04AA));		stack_save(bcm43xx_phy_read(bcm, 0x04AC));		stack_save(bcm43xx_phy_read(bcm, 0x0493));		stack_save(bcm43xx_phy_read(bcm, 0x04A1));		stack_save(bcm43xx_phy_read(bcm, 0x04A0));		stack_save(bcm43xx_phy_read(bcm, 0x04A2));		stack_save(bcm43xx_phy_read(bcm, 0x048A));		stack_save(bcm43xx_phy_read(bcm, 0x04A8));		stack_save(bcm43xx_phy_read(bcm, 0x04AB));		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF);		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002);		bcm43xx_phy_write(bcm, 0x04A7, 0x0800);		bcm43xx_phy_write(bcm, 0x04A3, 0x287A);		bcm43xx_phy_write(bcm, 0x04A9, 0x2027);		bcm43xx_phy_write(bcm, 0x0493, 0x32F5);		bcm43xx_phy_write(bcm, 0x04AA, 0x2027);		bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);		bcm43xx_phy_write(bcm, 0x04A0,				  (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A);		if (bcm->current_core->rev < 5) {			bcm43xx_phy_write(bcm, 0x0406, 0x280D);		} else {			bcm43xx_phy_write(bcm, 0x04C0, 0x0640);			bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);		}		bcm43xx_phy_write(bcm, 0x04A1,		                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800);		bcm43xx_phy_write(bcm, 0x04A1,		                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016);		bcm43xx_phy_write(bcm, 0x04A2,		                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900);		bcm43xx_phy_write(bcm, 0x04A0,		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700);		bcm43xx_phy_write(bcm, 0x04A2,		                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D);		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) | 0x0006);		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 = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	int i = 0;	u16 *stack = radio->interfstack;	u16 tmp, flipped;	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;		}		tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);		flipped = flip_4bit(tmp);		if ((flipped >> 1) >= 0x000C)			tmp = flipped + 3;		tmp = flip_4bit(tmp);		bcm43xx_radio_write16(bcm, 0x0078, tmp << 1);		bcm43xx_calc_nrssi_threshold(bcm);		if (bcm->current_core->rev < 5) {			bcm43xx_phy_write(bcm, 0x0406, stack_restore());		} else {			bcm43xx_phy_write(bcm, 0x04C0, stack_restore());			bcm43xx_phy_write(bcm, 0x04C1, stack_restore());		}		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);		bcm43xx_phy_write(bcm, 0x04A0, stack_restore());		bcm43xx_phy_write(bcm, 0x04A1, stack_restore());		bcm43xx_phy_write(bcm, 0x04A2, stack_restore());		bcm43xx_phy_write(bcm, 0x04A8, stack_restore());		bcm43xx_phy_write(bcm, 0x04AB, stack_restore());		bcm43xx_phy_write(bcm, 0x04A7, stack_restore());		bcm43xx_phy_write(bcm, 0x04A3, stack_restore());		bcm43xx_phy_write(bcm, 0x04A9, stack_restore());		bcm43xx_phy_write(bcm, 0x0493, stack_restore());		bcm43xx_phy_write(bcm, 0x04AA, stack_restore());		bcm43xx_phy_write(bcm, 0x04AC, stack_restore());		break;	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:		if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800)			break;		radio->aci_enable = 0;		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore());		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore());		if (bcm->current_core->rev < 5) {			bcm43xx_phy_write(bcm, 0x0406, stack_restore());		} else {			bcm43xx_phy_write(bcm, 0x04C0, stack_restore());			bcm43xx_phy_write(bcm, 0x04C1, stack_restore());		}		bcm43xx_phy_write(bcm, 0x0033, stack_restore());		bcm43xx_phy_write(bcm, 0x04A7, stack_restore());		bcm43xx_phy_write(bcm, 0x04A3, stack_restore());		bcm43xx_phy_write(bcm, 0x04A9, stack_restore());		bcm43xx_phy_write(bcm, 0x04AA, stack_restore());		bcm43xx_phy_write(bcm, 0x04AC, stack_restore());		bcm43xx_phy_write(bcm, 0x0493, stack_restore());		bcm43xx_phy_write(bcm, 0x04A1, stack_restore());		bcm43xx_phy_write(bcm, 0x04A0, stack_restore());		bcm43xx_phy_write(bcm, 0x04A2, stack_restore());		bcm43xx_phy_write(bcm, 0x04A8, stack_restore());		bcm43xx_phy_write(bcm, 0x04AB, stack_restore());		bcm43xx_calc_nrssi_slope(bcm);		break;	default:		assert(0);	}}#undef stack_save#undef stack_restoreint bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,					      int mode){	struct bcm43xx_phyinfo *phy = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	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 = bcm->current_core->phy;	struct bcm43xx_radioinfo *radio = bcm->current_core->radio;	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->version == 0) {		bcm43xx_write16(bcm, 0x03E6, 0x0122);	} else {		if (phy->version >= 2)			bcm43xx_write16(bcm, 0x03E6, 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, 0x0003);	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) | 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)

⌨️ 快捷键说明

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