📄 main.c
字号:
* register-overflow duration to complete the operation. */ if (dev->dev->id.revision >= 3) { u32 lo = (tsf & 0x00000000FFFFFFFFULL); u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, 0); mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_HIGH, hi); mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, lo); } else { u16 v0 = (tsf & 0x000000000000FFFFULL); u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; b43legacy_write16(dev, B43legacy_MMIO_TSF_0, 0); mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_3, v3); mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_2, v2); mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_1, v1); mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_0, v0); }}void b43legacy_tsf_write(struct b43legacy_wldev *dev, u64 tsf){ b43legacy_time_lock(dev); b43legacy_tsf_write_locked(dev, tsf); b43legacy_time_unlock(dev);}staticvoid b43legacy_macfilter_set(struct b43legacy_wldev *dev, u16 offset, const u8 *mac){ static const u8 zero_addr[ETH_ALEN] = { 0 }; u16 data; if (!mac) mac = zero_addr; offset |= 0x0020; b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_CONTROL, offset); data = mac[0]; data |= mac[1] << 8; b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data); data = mac[2]; data |= mac[3] << 8; b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data); data = mac[4]; data |= mac[5] << 8; b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data);}static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev){ static const u8 zero_addr[ETH_ALEN] = { 0 }; const u8 *mac = dev->wl->mac_addr; const u8 *bssid = dev->wl->bssid; u8 mac_bssid[ETH_ALEN * 2]; int i; u32 tmp; if (!bssid) bssid = zero_addr; if (!mac) mac = zero_addr; b43legacy_macfilter_set(dev, B43legacy_MACFILTER_BSSID, bssid); memcpy(mac_bssid, mac, ETH_ALEN); memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); /* Write our MAC address and BSSID to template ram */ for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) { tmp = (u32)(mac_bssid[i + 0]); tmp |= (u32)(mac_bssid[i + 1]) << 8; tmp |= (u32)(mac_bssid[i + 2]) << 16; tmp |= (u32)(mac_bssid[i + 3]) << 24; b43legacy_ram_write(dev, 0x20 + i, tmp); b43legacy_ram_write(dev, 0x78 + i, tmp); b43legacy_ram_write(dev, 0x478 + i, tmp); }}static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev){ b43legacy_write_mac_bssid_templates(dev); b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, dev->wl->mac_addr);}static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, u16 slot_time){ /* slot_time is in usec. */ if (dev->phy.type != B43legacy_PHYTYPE_G) return; b43legacy_write16(dev, 0x684, 510 + slot_time); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0010, slot_time);}static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev){ b43legacy_set_slot_time(dev, 9); dev->short_slot = 1;}static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev){ b43legacy_set_slot_time(dev, 20); dev->short_slot = 0;}/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. * Returns the _previously_ enabled IRQ mask. */static inline u32 b43legacy_interrupt_enable(struct b43legacy_wldev *dev, u32 mask){ u32 old_mask; old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask | mask); return old_mask;}/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. * Returns the _previously_ enabled IRQ mask. */static inline u32 b43legacy_interrupt_disable(struct b43legacy_wldev *dev, u32 mask){ u32 old_mask; old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask & ~mask); return old_mask;}/* Synchronize IRQ top- and bottom-half. * IRQs must be masked before calling this. * This must not be called with the irq_lock held. */static void b43legacy_synchronize_irq(struct b43legacy_wldev *dev){ synchronize_irq(dev->dev->irq); tasklet_kill(&dev->isr_tasklet);}/* DummyTransmission function, as documented on * http://bcm-specs.sipsolutions.net/DummyTransmission */void b43legacy_dummy_transmission(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; unsigned int i; unsigned int max_loop; u16 value; u32 buffer[5] = { 0x00000000, 0x00D40000, 0x00000000, 0x01000000, 0x00000000, }; switch (phy->type) { case B43legacy_PHYTYPE_B: case B43legacy_PHYTYPE_G: max_loop = 0xFA; buffer[0] = 0x000B846E; break; default: B43legacy_BUG_ON(1); return; } for (i = 0; i < 5; i++) b43legacy_ram_write(dev, i * 4, buffer[i]); /* dummy read follows */ b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); b43legacy_write16(dev, 0x0568, 0x0000); b43legacy_write16(dev, 0x07C0, 0x0000); b43legacy_write16(dev, 0x050C, 0x0000); b43legacy_write16(dev, 0x0508, 0x0000); b43legacy_write16(dev, 0x050A, 0x0000); b43legacy_write16(dev, 0x054C, 0x0000); b43legacy_write16(dev, 0x056A, 0x0014); b43legacy_write16(dev, 0x0568, 0x0826); b43legacy_write16(dev, 0x0500, 0x0000); b43legacy_write16(dev, 0x0502, 0x0030); if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) b43legacy_radio_write16(dev, 0x0051, 0x0017); for (i = 0x00; i < max_loop; i++) { value = b43legacy_read16(dev, 0x050E); if (value & 0x0080) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = b43legacy_read16(dev, 0x050E); if (value & 0x0400) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = b43legacy_read16(dev, 0x0690); if (!(value & 0x0100)) break; udelay(10); } if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) b43legacy_radio_write16(dev, 0x0051, 0x0037);}/* Turn the Analog ON/OFF */static void b43legacy_switch_analog(struct b43legacy_wldev *dev, int on){ b43legacy_write16(dev, B43legacy_MMIO_PHY0, on ? 0 : 0xF4);}void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags){ u32 tmslow; u32 macctl; flags |= B43legacy_TMSLOW_PHYCLKEN; flags |= B43legacy_TMSLOW_PHYRESET; ssb_device_enable(dev->dev, flags); msleep(2); /* Wait for the PLL to turn on. */ /* Now take the PHY out of Reset again */ tmslow = ssb_read32(dev->dev, SSB_TMSLOW); tmslow |= SSB_TMSLOW_FGC; tmslow &= ~B43legacy_TMSLOW_PHYRESET; ssb_write32(dev->dev, SSB_TMSLOW, tmslow); ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ msleep(1); tmslow &= ~SSB_TMSLOW_FGC; ssb_write32(dev->dev, SSB_TMSLOW, tmslow); ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ msleep(1); /* Turn Analog ON */ b43legacy_switch_analog(dev, 1); macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); macctl &= ~B43legacy_MACCTL_GMODE; if (flags & B43legacy_TMSLOW_GMODE) { macctl |= B43legacy_MACCTL_GMODE; dev->phy.gmode = 1; } else dev->phy.gmode = 0; macctl |= B43legacy_MACCTL_IHR_ENABLED; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);}static void handle_irq_transmit_status(struct b43legacy_wldev *dev){ u32 v0; u32 v1; u16 tmp; struct b43legacy_txstatus stat; while (1) { v0 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0); if (!(v0 & 0x00000001)) break; v1 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1); stat.cookie = (v0 >> 16); stat.seq = (v1 & 0x0000FFFF); stat.phy_stat = ((v1 & 0x00FF0000) >> 16); tmp = (v0 & 0x0000FFFF); stat.frame_count = ((tmp & 0xF000) >> 12); stat.rts_count = ((tmp & 0x0F00) >> 8); stat.supp_reason = ((tmp & 0x001C) >> 2); stat.pm_indicated = !!(tmp & 0x0080); stat.intermediate = !!(tmp & 0x0040); stat.for_ampdu = !!(tmp & 0x0020); stat.acked = !!(tmp & 0x0002); b43legacy_handle_txstatus(dev, &stat); }}static void drain_txstatus_queue(struct b43legacy_wldev *dev){ u32 dummy; if (dev->dev->id.revision < 5) return; /* Read all entries from the microcode TXstatus FIFO * and throw them away. */ while (1) { dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0); if (!(dummy & 0x00000001)) break; dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1); }}static u32 b43legacy_jssi_read(struct b43legacy_wldev *dev){ u32 val = 0; val = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x40A); val <<= 16; val |= b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x408); return val;}static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi){ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x408, (jssi & 0x0000FFFF)); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x40A, (jssi & 0xFFFF0000) >> 16);}static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev){ b43legacy_jssi_write(dev, 0x7F7F7F7F); b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD) | (1 << 4)); B43legacy_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);}static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev){ /* Top half of Link Quality calculation. */ if (dev->noisecalc.calculation_running) return; dev->noisecalc.channel_at_start = dev->phy.channel; dev->noisecalc.calculation_running = 1; dev->noisecalc.nr_samples = 0; b43legacy_generate_noise_sample(dev);}static void handle_irq_noise(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; u16 tmp; u8 noise[4]; u8 i; u8 j; s32 average; /* Bottom half of Link Quality calculation. */ B43legacy_WARN_ON(!dev->noisecalc.calculation_running); if (dev->noisecalc.channel_at_start != phy->channel) goto drop_calculation; *((__le32 *)noise) = cpu_to_le32(b43legacy_jssi_read(dev)); if (noise[0] == 0x7F || noise[1] == 0x7F || noise[2] == 0x7F || noise[3] == 0x7F) goto generate_new; /* Get the noise samples. */ B43legacy_WARN_ON(dev->noisecalc.nr_samples >= 8); i = dev->noisecalc.nr_samples; noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]]; dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]]; dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]]; dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]]; dev->noisecalc.nr_samples++; if (dev->noisecalc.nr_samples == 8) { /* Calculate the Link Quality by the noise samples. */ average = 0; for (i = 0; i < 8; i++) { for (j = 0; j < 4; j++) average += dev->noisecalc.samples[i][j]; } average /= (8 * 4); average *= 125; average += 64; average /= 128; tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x40C); tmp = (tmp / 128) & 0x1F; if (tmp >= 8) average += 2; else average -= 25; if (tmp == 8) average -= 72; else average -= 48; dev->stats.link_noise = average;drop_calculation: dev->noisecalc.calculation_running = 0; return; }generate_new: b43legacy_generate_noise_sample(dev);}static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev){ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) { /* TODO: PS TBTT */ } else { if (1/*FIXME: the last PSpoll frame was sent successfully */) b43legacy_power_saving_ctl_bits(dev, -1, -1); } dev->reg124_set_0x4 = 0; if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) dev->reg124_set_0x4 = 1;}static void handle_irq_atim_end(struct b43legacy_wldev *dev){ if (!dev->reg124_set_0x4) /*FIXME rename this variable*/ return; b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD) | 0x4);}static void handle_irq_pmq(struct b43legacy_wldev *dev){ u32 tmp; /* TODO: AP mode. */ while (1) { tmp = b43legacy_read32(dev, B43legacy_MMIO_PS_STATUS); if (!(tmp & 0x00000008)) break; } /* 16bit write is odd, but correct. */ b43legacy_write16(dev, B43legacy_MMIO_PS_STATUS, 0x0002);}static void b43legacy_write_template_common(struct b43legacy_wldev *dev, const u8 *data, u16 size, u16 ram_offset, u16 shm_size_offset, u8 rate){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -