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

📄 bcm43xx_radio.c

📁 无线网卡驱动,有很好的参考价值,在linux_2.6.21下可以直接使用,如果在其他平台,可以参考移植
💻 C
📖 第 1 页 / 共 4 页
字号:
	bcm43xx_phy_write(bcm, 0x0814, backup[3]);	bcm43xx_phy_write(bcm, 0x0815, backup[4]);	bcm43xx_phy_write(bcm, 0x005A, backup[5]);	bcm43xx_phy_write(bcm, 0x0059, backup[6]);	bcm43xx_phy_write(bcm, 0x0058, backup[7]);	bcm43xx_phy_write(bcm, 0x000A, backup[8]);	bcm43xx_phy_write(bcm, 0x0003, backup[9]);	bcm43xx_radio_write16(bcm, 0x0043, backup[11]);	bcm43xx_radio_write16(bcm, 0x007A, backup[10]);	bcm43xx_phy_write(bcm, 0x0802,			  bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);	bcm43xx_phy_write(bcm, 0x0429,			  bcm43xx_phy_read(bcm, 0x0429) | 0x8000);	bcm43xx_set_original_gains(bcm);	if (phy->rev >= 6) {		bcm43xx_phy_write(bcm, 0x0801, backup[16]);		bcm43xx_phy_write(bcm, 0x0060, backup[17]);		bcm43xx_phy_write(bcm, 0x0014, backup[18]);		bcm43xx_phy_write(bcm, 0x0478, backup[19]);	}	bcm43xx_phy_write(bcm, 0x0001, backup[0]);	bcm43xx_phy_write(bcm, 0x0812, backup[2]);	bcm43xx_phy_write(bcm, 0x0811, backup[1]);}void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 backup[18] = { 0 };	u16 tmp;	s16 nrssi0, nrssi1;	switch (phy->type) {	case BCM43xx_PHYTYPE_B:		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);		backup[3] = bcm43xx_phy_read(bcm, 0x0030);		backup[4] = bcm43xx_phy_read(bcm, 0x0026);		backup[5] = bcm43xx_phy_read(bcm, 0x0015);		backup[6] = bcm43xx_phy_read(bcm, 0x002A);		backup[7] = bcm43xx_phy_read(bcm, 0x0020);		backup[8] = bcm43xx_phy_read(bcm, 0x005A);		backup[9] = bcm43xx_phy_read(bcm, 0x0059);		backup[10] = bcm43xx_phy_read(bcm, 0x0058);		backup[11] = bcm43xx_read16(bcm, 0x03E2);		backup[12] = bcm43xx_read16(bcm, 0x03E6);		backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);		tmp  = bcm43xx_radio_read16(bcm, 0x007A);		tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;		bcm43xx_radio_write16(bcm, 0x007A, tmp);		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);		bcm43xx_write16(bcm, 0x03EC, 0x7F7F);		bcm43xx_phy_write(bcm, 0x0026, 0x0000);		bcm43xx_phy_write(bcm, 0x0015,				  bcm43xx_phy_read(bcm, 0x0015) | 0x0020);		bcm43xx_phy_write(bcm, 0x002A, 0x08A3);		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);		nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);		if (phy->analog >= 2) {			bcm43xx_write16(bcm, 0x03E6, 0x0040);		} else if (phy->analog == 0) {			bcm43xx_write16(bcm, 0x03E6, 0x0122);		} else {			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);		}		bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);		bcm43xx_phy_write(bcm, 0x0015, 0xF330);		bcm43xx_radio_write16(bcm, 0x005A, 0x0060);		bcm43xx_radio_write16(bcm, 0x0043,				      bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);		bcm43xx_phy_write(bcm, 0x005A, 0x0480);		bcm43xx_phy_write(bcm, 0x0059, 0x0810);		bcm43xx_phy_write(bcm, 0x0058, 0x000D);		udelay(20);		nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);		bcm43xx_phy_write(bcm, 0x0030, backup[3]);		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);		bcm43xx_write16(bcm, 0x03E2, backup[11]);		bcm43xx_phy_write(bcm, 0x0026, backup[4]);		bcm43xx_phy_write(bcm, 0x0015, backup[5]);		bcm43xx_phy_write(bcm, 0x002A, backup[6]);		bcm43xx_synth_pu_workaround(bcm, radio->channel);		if (phy->analog != 0)			bcm43xx_write16(bcm, 0x03F4, backup[13]);		bcm43xx_phy_write(bcm, 0x0020, backup[7]);		bcm43xx_phy_write(bcm, 0x005A, backup[8]);		bcm43xx_phy_write(bcm, 0x0059, backup[9]);		bcm43xx_phy_write(bcm, 0x0058, backup[10]);		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);		if (nrssi0 == nrssi1)			radio->nrssislope = 0x00010000;		else 			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);		if (nrssi0 <= -4) {			radio->nrssi[0] = nrssi0;			radio->nrssi[1] = nrssi1;		}		break;	case BCM43xx_PHYTYPE_G:		if (radio->revision >= 9)			return;		if (radio->revision == 8)			bcm43xx_calc_nrssi_offset(bcm);		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);		backup[7] = bcm43xx_read16(bcm, 0x03E2);		bcm43xx_write16(bcm, 0x03E2,				bcm43xx_read16(bcm, 0x03E2) | 0x8000);		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);		backup[3] = bcm43xx_phy_read(bcm, 0x0015);		backup[4] = bcm43xx_phy_read(bcm, 0x005A);		backup[5] = bcm43xx_phy_read(bcm, 0x0059);		backup[6] = bcm43xx_phy_read(bcm, 0x0058);		backup[8] = bcm43xx_read16(bcm, 0x03E6);		backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);		if (phy->rev >= 3) {			backup[10] = bcm43xx_phy_read(bcm, 0x002E);			backup[11] = bcm43xx_phy_read(bcm, 0x002F);			backup[12] = bcm43xx_phy_read(bcm, 0x080F);			backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);			backup[14] = bcm43xx_phy_read(bcm, 0x0801);			backup[15] = bcm43xx_phy_read(bcm, 0x0060);			backup[16] = bcm43xx_phy_read(bcm, 0x0014);			backup[17] = bcm43xx_phy_read(bcm, 0x0478);			bcm43xx_phy_write(bcm, 0x002E, 0);			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);			switch (phy->rev) {			case 4: case 6: case 7:				bcm43xx_phy_write(bcm, 0x0478,						  bcm43xx_phy_read(bcm, 0x0478)						  | 0x0100);				bcm43xx_phy_write(bcm, 0x0801,						  bcm43xx_phy_read(bcm, 0x0801)						  | 0x0040);				break;			case 3: case 5:				bcm43xx_phy_write(bcm, 0x0801,						  bcm43xx_phy_read(bcm, 0x0801)						  & 0xFFBF);				break;			}			bcm43xx_phy_write(bcm, 0x0060,					  bcm43xx_phy_read(bcm, 0x0060)					  | 0x0040);			bcm43xx_phy_write(bcm, 0x0014,					  bcm43xx_phy_read(bcm, 0x0014)					  | 0x0200);		}		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);		bcm43xx_set_all_gains(bcm, 0, 8, 0);		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);		if (phy->rev >= 2) {			bcm43xx_phy_write(bcm, 0x0811,					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);			bcm43xx_phy_write(bcm, 0x0812,					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);		}		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);		udelay(20);		nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);		if (nrssi0 >= 0x0020)			nrssi0 -= 0x0040;		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);		if (phy->analog >= 2) {			bcm43xx_phy_write(bcm, 0x0003,					  (bcm43xx_phy_read(bcm, 0x0003)					   & 0xFF9F) | 0x0040);		}		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,				bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)				| 0x2000);		bcm43xx_radio_write16(bcm, 0x007A,				      bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);		bcm43xx_phy_write(bcm, 0x0015, 0xF330);		if (phy->rev >= 2) {			bcm43xx_phy_write(bcm, 0x0812,					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);			bcm43xx_phy_write(bcm, 0x0811,					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);		}		bcm43xx_set_all_gains(bcm, 3, 0, 1);		if (radio->revision == 8) {			bcm43xx_radio_write16(bcm, 0x0043, 0x001F);		} else {			tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;			bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);			tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;			bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);		}		bcm43xx_phy_write(bcm, 0x005A, 0x0480);		bcm43xx_phy_write(bcm, 0x0059, 0x0810);		bcm43xx_phy_write(bcm, 0x0058, 0x000D);		udelay(20);		nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);		if (nrssi1 >= 0x0020)			nrssi1 -= 0x0040;		if (nrssi0 == nrssi1)			radio->nrssislope = 0x00010000;		else			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);		if (nrssi0 >= -4) {			radio->nrssi[0] = nrssi1;			radio->nrssi[1] = nrssi0;		}		if (phy->rev >= 3) {			bcm43xx_phy_write(bcm, 0x002E, backup[10]);			bcm43xx_phy_write(bcm, 0x002F, backup[11]);			bcm43xx_phy_write(bcm, 0x080F, backup[12]);			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);		}		if (phy->rev >= 2) {			bcm43xx_phy_write(bcm, 0x0812,					  bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);			bcm43xx_phy_write(bcm, 0x0811,					  bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);		}		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);		bcm43xx_write16(bcm, 0x03E2, backup[7]);		bcm43xx_write16(bcm, 0x03E6, backup[8]);		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);		bcm43xx_phy_write(bcm, 0x0015, backup[3]);		bcm43xx_phy_write(bcm, 0x005A, backup[4]);		bcm43xx_phy_write(bcm, 0x0059, backup[5]);		bcm43xx_phy_write(bcm, 0x0058, backup[6]);		bcm43xx_synth_pu_workaround(bcm, radio->channel);		bcm43xx_phy_write(bcm, 0x0802,				  bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));		bcm43xx_set_original_gains(bcm);		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);		if (phy->rev >= 3) {			bcm43xx_phy_write(bcm, 0x0801, backup[14]);			bcm43xx_phy_write(bcm, 0x0060, backup[15]);			bcm43xx_phy_write(bcm, 0x0014, backup[16]);			bcm43xx_phy_write(bcm, 0x0478, backup[17]);		}		bcm43xx_nrssi_mem_update(bcm);		bcm43xx_calc_nrssi_threshold(bcm);		break;	default:		assert(0);	}}void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	s32 threshold;	s32 a, b;	s16 tmp16;	u16 tmp_u16;	switch (phy->type) {	case BCM43xx_PHYTYPE_B: {		if (radio->version != 0x2050)			return;		if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))			return;		if (radio->revision >= 6) {			threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;			threshold += 20 * (radio->nrssi[0] + 1);			threshold /= 40;		} else			threshold = radio->nrssi[1] - 5;		threshold = limit_value(threshold, 0, 0x3E);		bcm43xx_phy_read(bcm, 0x0020); /* dummy read */		bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);		if (radio->revision >= 6) {			bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);			bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);			bcm43xx_phy_write(bcm, 0x0085, 0x0A09);			bcm43xx_phy_write(bcm, 0x0084, 0x0808);			bcm43xx_phy_write(bcm, 0x0083, 0x0808);			bcm43xx_phy_write(bcm, 0x0082, 0x0604);			bcm43xx_phy_write(bcm, 0x0081, 0x0302);			bcm43xx_phy_write(bcm, 0x0080, 0x0100);		}		break;	}	case BCM43xx_PHYTYPE_G:		if (!phy->connected ||		    !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {			tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);			if (tmp16 >= 0x20)				tmp16 -= 0x40;			if (tmp16 < 3) {				bcm43xx_phy_write(bcm, 0x048A,						  (bcm43xx_phy_read(bcm, 0x048A)						   & 0xF000) | 0x09EB);			} else {				bcm43xx_phy_write(bcm, 0x048A,						  (bcm43xx_phy_read(bcm, 0x048A)						   & 0xF000) | 0x0AED);			}		} else {			if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {				a = 0xE;				b = 0xA;			} else if (!radio->aci_wlan_automatic && radio->aci_enable) {				a = 0x13;				b = 0x12;			} else {				a = 0xE;				b = 0x11;			}			a = a * (radio->nrssi[1] - radio->nrssi[0]);			a += (radio->nrssi[0] << 6);			if (a < 32)				a += 31;			else				a += 32;			a = a >> 6;			a = limit_value(a, -31, 31);			b = b * (radio->nrssi[1] - radio->nrssi[0]);			b += (radio->nrssi[0] << 6);			if (b < 32)				b += 31;			else				b += 32;			b = b >> 6;			b = limit_value(b, -31, 31);			tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;			tmp_u16 |= ((u32)b & 0x0000003F);			tmp_u16 |= (((u32)a & 0x0000003F) << 6);			bcm43xx_phy_write(bcm, 0x048A, tmp_u16);		}		break;	default:		assert(0);	}}/* Stack implementation to save/restore values from the * interference mitigation code. * It is save to restore values in random order. */static void _stack_save(u32 *_stackptr, size_t *stackidx,			u8 id, u16 offset, u16 value){	u32 *stackptr = &(_stackptr[*stackidx]);	assert((offset & 0xE000) == 0x0000);	assert((id & 0xF8) == 0x00);	*stackptr = offset;	*stackptr |= ((u32)id) << 13;	*stackptr |= ((u32)value) << 16;	(*stackidx)++;	assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);}static u16 _stack_restore(u32 *stackptr,			  u8 id, u16 offset){	size_t i;	assert((offset & 0xE000) == 0x0000);	assert((id & 0xF8) == 0x00);	for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {		if ((*stackptr & 0x00001FFF) != offset)			continue;		if (((*stackptr & 0x00007000) >> 13) != id)			continue;		return ((*stackptr & 0xFFFF0000) >> 16);	}	assert(0);	return 0;}#define phy_stacksave(offset)					\	do {							\		_stack_save(stack, &stackidx, 0x1, (offset),	\			    bcm43xx_phy_read(bcm, (offset)));	\	} while (0)#define phy_stackrestore(offset)				\	do {							\		bcm43xx_phy_write(bcm, (offset),		\				  _stack_restore(stack, 0x1,	\					  	 (offset)));	\	} while (0)#define radio_stacksave(offset)						\	do {								\		_stack_save(stack, &stackidx, 0x2, (offset),		\			    bcm43xx_radio_read16(bcm, (offset)));	\	} while (0)#define radio_stackrestore(offset)					\	do {								\		bcm43xx_radio_write16(bcm, (offset),			\				      _stack_restore(stack, 0x2,	\						     (offset)));	\	} while (0)#define ilt_stacksave(offset)					\	do {							\		_stack_save(stack, &stackidx, 0x3, (offset),	\			    bcm43xx_ilt_read(bcm, (offset)));	\	} while (0)#define ilt_stackrestore(offset)				\	do {							\		bcm43xx_ilt_write(bcm, (offset),		\				  _stack_restore(stack, 0x3,	\						 (offset)));	\	} while (0)static voidbcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,					     int mode){	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);	u16 tmp, flipped;	u32 tmp32;	size_t stackidx = 0;	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;		}		radio_stacksave(0x0078);		tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);		flipped = flip_4bit(tmp);		if (flipped < 10 && flipped >= 8)			flipped = 7;		else if (flipped >= 10)			flipped -= 3;		flipped = flip_4bit(flipped);		flipped = (flipped << 1) | 0x0020;		bcm43xx_radio_write16(bcm, 0x0078, flipped);		bcm43xx_calc_nrssi_threshold(bcm);		phy_stacksave(0x0406);		bcm43xx_phy_write(bcm, 0x0406, 0x7E28);		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);		phy_stacksave(0x04A0);		bcm43xx_phy_write(bcm, 0x04A0,		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);		phy_stacksave(0x04A1);		bcm43xx_phy_write(bcm, 0x04A1,				  (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);		phy_stacksave(0x04A2);		bcm43xx_phy_write(bcm, 0x04A2,				  (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);		phy_stacksave(0x04A8);		bcm43xx_phy_write(bcm, 0x04A8,				  (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);		phy_stacksave(0x04AB);		bcm43xx_phy_write(bcm, 0x04AB,				  (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);		phy_stacksave(0x04A7);		bcm43xx_phy_write(bcm, 0x04A7, 0x0002);		phy_stacksave(0x04A3);		bcm43xx_phy_write(bcm, 0x04A3, 0x287A);		phy_stacksave(0x04A9);		bcm43xx_phy_write(bcm, 0x04A9, 0x2027);		phy_stacksave(0x0493);		bcm43xx_phy_write(bcm, 0x0493, 0x32F5);		phy_stacksave(0x04AA);		bcm43xx_phy_write(bcm, 0x04AA, 0x2027);		phy_stacksave(0x04AC);

⌨️ 快捷键说明

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