📄 radio.c
字号:
if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 1))); b43legacy_phy_write(dev, 0x0015, 0xEFB0); udelay(10); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 0))); b43legacy_phy_write(dev, 0x0015, 0xFFF0); udelay(20); tmp1 += b43legacy_phy_read(dev, 0x002D); b43legacy_phy_write(dev, 0x0058, 0x0000); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 1))); b43legacy_phy_write(dev, 0x0015, 0xAFB0); } tmp1++; tmp1 >>= 9; udelay(10); b43legacy_phy_write(dev, 0x0058, 0x0000); for (i = 0; i < 16; i++) { b43legacy_radio_write16(dev, 0x0078, (flip_4bit(i) << 1) | 0x0020); backup[13] = b43legacy_radio_read16(dev, 0x0078); udelay(10); for (j = 0; j < 16; j++) { b43legacy_phy_write(dev, 0x005A, 0x0D80); b43legacy_phy_write(dev, 0x0059, 0xC810); b43legacy_phy_write(dev, 0x0058, 0x000D); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 1))); b43legacy_phy_write(dev, 0x0015, 0xAFB0); udelay(10); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 1))); b43legacy_phy_write(dev, 0x0015, 0xEFB0); udelay(10); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 0))); b43legacy_phy_write(dev, 0x0015, 0xFFF0); udelay(10); tmp2 += b43legacy_phy_read(dev, 0x002D); b43legacy_phy_write(dev, 0x0058, 0x0000); if (phy->gmode) b43legacy_phy_write(dev, 0x0812, b43legacy_get_812_value(dev, LPD(1, 0, 1))); b43legacy_phy_write(dev, 0x0015, 0xAFB0); } tmp2++; tmp2 >>= 8; if (tmp1 < tmp2) break; } /* Restore the registers */ b43legacy_phy_write(dev, 0x0015, backup[1]); b43legacy_radio_write16(dev, 0x0051, backup[14]); b43legacy_radio_write16(dev, 0x0052, backup[15]); b43legacy_radio_write16(dev, 0x0043, backup[0]); b43legacy_phy_write(dev, 0x005A, backup[16]); b43legacy_phy_write(dev, 0x0059, backup[17]); b43legacy_phy_write(dev, 0x0058, backup[18]); b43legacy_write16(dev, 0x03E6, backup[11]); if (phy->analog != 0) b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[12]); b43legacy_phy_write(dev, 0x0035, backup[10]); b43legacy_radio_selectchannel(dev, phy->channel, 1); if (phy->type == B43legacy_PHYTYPE_B) { b43legacy_phy_write(dev, 0x0030, backup[2]); b43legacy_write16(dev, 0x03EC, backup[3]); } else { if (phy->gmode) { b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, (b43legacy_read16(dev, B43legacy_MMIO_PHY_RADIO) & 0x7FFF)); b43legacy_phy_write(dev, 0x0811, backup[4]); b43legacy_phy_write(dev, 0x0812, backup[5]); b43legacy_phy_write(dev, 0x0814, backup[6]); b43legacy_phy_write(dev, 0x0815, backup[7]); b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, backup[8]); b43legacy_phy_write(dev, 0x0802, backup[9]); if (phy->rev > 1) { b43legacy_phy_write(dev, 0x080F, backup[19]); b43legacy_phy_write(dev, 0x0810, backup[20]); } } } if (i >= 15) ret = backup[13]; return ret;}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 b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev){ static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; u16 tmp = b43legacy_radio_read16(dev, 0x001E); int i; int j; for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (tmp == (data_high[i] | data_low[j])) { b43legacy_phy_write(dev, 0x0069, (i - j) << 8 | 0x00C0); return; } } }}int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, u8 channel, int synthetic_pu_workaround){ struct b43legacy_phy *phy = &dev->phy; if (channel == 0xFF) { switch (phy->type) { case B43legacy_PHYTYPE_B: case B43legacy_PHYTYPE_G: channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG; break; default: B43legacy_WARN_ON(1); } }/* TODO: Check if channel is valid - return -EINVAL if not */ if (synthetic_pu_workaround) b43legacy_synth_pu_workaround(dev, channel); b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, channel2freq_bg(channel)); if (channel == 14) { if (dev->dev->bus->sprom.r1.country_code == 5) /* JAPAN) */ b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, B43legacy_UCODEFLAGS_OFFSET, b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, B43legacy_UCODEFLAGS_OFFSET) & ~(1 << 7)); else b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, B43legacy_UCODEFLAGS_OFFSET, b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, B43legacy_UCODEFLAGS_OFFSET) | (1 << 7)); b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT) | (1 << 11)); } else b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT) & 0xF7BF); phy->channel = channel; /*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states * that 2000 usecs might suffice. */ msleep(8); return 0;}void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val){ u16 tmp; val <<= 8; tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0022) & 0xFCFF; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0022, tmp | val); tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x03A8) & 0xFCFF; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x03A8, tmp | val); tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0054) & 0xFCFF; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0054, tmp | val);}/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */static u16 b43legacy_get_txgain_base_band(u16 txpower){ u16 ret; B43legacy_WARN_ON(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 b43legacy_get_txgain_freq_power_amp(u16 txpower){ u16 ret; B43legacy_WARN_ON(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 b43legacy_get_txgain_dac(u16 txpower){ u16 ret; B43legacy_WARN_ON(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 b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower){ struct b43legacy_phy *phy = &dev->phy; u16 pamp; u16 base; u16 dac; u16 ilt; txpower = limit_value(txpower, 0, 63); pamp = b43legacy_get_txgain_freq_power_amp(txpower); pamp <<= 5; pamp &= 0x00E0; b43legacy_phy_write(dev, 0x0019, pamp); base = b43legacy_get_txgain_base_band(txpower); base &= 0x000F; b43legacy_phy_write(dev, 0x0017, base | 0x0020); ilt = b43legacy_ilt_read(dev, 0x3001); ilt &= 0x0007; dac = b43legacy_get_txgain_dac(txpower); dac <<= 3; dac |= ilt; b43legacy_ilt_write(dev, 0x3001, dac); phy->txpwr_offset = txpower; /* TODO: FuncPlaceholder (Adjust BB loft cancel) */}void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev, u16 baseband_attenuation, u16 radio_attenuation, u16 txpower){ struct b43legacy_phy *phy = &dev->phy; if (baseband_attenuation == 0xFFFF) baseband_attenuation = phy->bbatt; if (radio_attenuation == 0xFFFF) radio_attenuation = phy->rfatt; if (txpower == 0xFFFF) txpower = phy->txctl1; phy->bbatt = baseband_attenuation; phy->rfatt = radio_attenuation; phy->txctl1 = txpower; B43legacy_WARN_ON(baseband_attenuation > 11); if (phy->radio_rev < 6) B43legacy_WARN_ON(radio_attenuation > 9); else B43legacy_WARN_ON(radio_attenuation > 31); B43legacy_WARN_ON(txpower > 7); b43legacy_phy_set_baseband_attenuation(dev, baseband_attenuation); b43legacy_radio_write16(dev, 0x0043, radio_attenuation); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0064, radio_attenuation); if (phy->radio_ver == 0x2050) b43legacy_radio_write16(dev, 0x0052, (b43legacy_radio_read16(dev, 0x0052) & ~0x0070) | ((txpower << 4) & 0x0070)); /* FIXME: The spec is very weird and unclear here. */ if (phy->type == B43legacy_PHYTYPE_G) b43legacy_phy_lo_adjust(dev, 0);}u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) return 0; return 2;}u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; u16 att = 0xFFFF; switch (phy->radio_ver) { case 0x2053: switch (phy->radio_rev) { case 1: att = 6; break; } break; case 0x2050: switch (phy->radio_rev) { case 0: att = 5; break; case 1: if (phy->type == B43legacy_PHYTYPE_G) { if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x421 && dev->dev->bus->boardinfo.rev >= 30) att = 3; else if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x416) att = 3; else att = 1; } else { if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x421 && dev->dev->bus->boardinfo.rev >= 30) att = 7; else att = 6; } break; case 2: if (phy->type == B43legacy_PHYTYPE_G) { if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x421 && dev->dev->bus->boardinfo.rev >= 30) att = 3; else if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x416) att = 5; else if (dev->dev->bus->chip_id == 0x4320) att = 4; else att = 3; } else att = 6; break; case 3: att = 5; break; case 4: case 5: att = 1; break; case 6: case 7: att = 5; break; case 8: att = 0x1A; break; case 9: default: att = 5; } } if (is_bcm_board_vendor(dev) && dev->dev->bus->boardinfo.type == 0x421) { if (dev->dev->bus->boardinfo.rev < 0x43) att = 2; else if (dev->dev->bus->boardinfo.rev < 0x51) att = 3; } if (att == 0xFFFF) att = 5; return att;}u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; if (phy->radio_ver != 0x2050) return 0; if (phy->radio_rev == 1) return 3; if (phy->radio_rev < 6) return 2; if (phy->radio_rev == 8) return 1; return 0;}void b43legacy_radio_turn_on(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; int err; u8 channel; might_sleep(); if (phy->radio_on) return; switch (phy->type) { case B43legacy_PHYTYPE_B: case B43legacy_PHYTYPE_G: b43legacy_phy_write(dev, 0x0015, 0x8000); b43legacy_phy_write(dev, 0x0015, 0xCC00); b43legacy_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000)); if (phy->radio_off_context.valid) { /* Restore the RFover values. */ b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, phy->radio_off_context.rfover); b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, phy->radio_off_context.rfoverval); phy->radio_off_context.valid = 0; } channel = phy->channel; err = b43legacy_radio_selectchannel(dev, B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1); err |= b43legacy_radio_selectchannel(dev, channel, 0); B43legacy_WARN_ON(err); break; default: B43legacy_BUG_ON(1); } phy->radio_on = 1; b43legacy_leds_update(dev, 0);}void b43legacy_radio_turn_off(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) { u16 rfover, rfoverval; rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER); rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL); phy->radio_off_context.rfover = rfover; phy->radio_off_context.rfoverval = rfoverval; phy->radio_off_context.valid = 1; b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C); b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, rfoverval & 0xFF73); } else b43legacy_phy_write(dev, 0x0015, 0xAA00); phy->radio_on = 0; b43legacydbg(dev->wl, "Radio initialized\n"); b43legacy_leds_update(dev, 0);}void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; switch (phy->type) { case B43legacy_PHYTYPE_B: case B43legacy_PHYTYPE_G: b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058, 0x7F7F); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a, 0x7F7F); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070, 0x7F7F); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072, 0x7F7F); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -