📄 main.c
字号:
ctl |= B43legacy_MACCTL_INFRA; if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) ctl |= B43legacy_MACCTL_AP; else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) ctl &= ~B43legacy_MACCTL_INFRA; if (wl->filter_flags & FIF_CONTROL) ctl |= B43legacy_MACCTL_KEEP_CTL; if (wl->filter_flags & FIF_FCSFAIL) ctl |= B43legacy_MACCTL_KEEP_BAD; if (wl->filter_flags & FIF_PLCPFAIL) ctl |= B43legacy_MACCTL_KEEP_BADPLCP; if (wl->filter_flags & FIF_PROMISC_IN_BSS) ctl |= B43legacy_MACCTL_PROMISC; if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) ctl |= B43legacy_MACCTL_BEACPROMISC; /* Workaround: On old hardware the HW-MAC-address-filter * doesn't work properly, so always run promisc in filter * it in software. */ if (dev->dev->id.revision <= 4) ctl |= B43legacy_MACCTL_PROMISC; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, ctl); cfp_pretbtt = 2; if ((ctl & B43legacy_MACCTL_INFRA) && !(ctl & B43legacy_MACCTL_AP)) { if (dev->dev->bus->chip_id == 0x4306 && dev->dev->bus->chip_rev == 3) cfp_pretbtt = 100; else cfp_pretbtt = 50; } b43legacy_write16(dev, 0x612, cfp_pretbtt);}static void b43legacy_rate_memory_write(struct b43legacy_wldev *dev, u16 rate, int is_ofdm){ u16 offset; if (is_ofdm) { offset = 0x480; offset += (b43legacy_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; } else { offset = 0x4C0; offset += (b43legacy_plcp_get_ratecode_cck(rate) & 0x000F) * 2; } b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, offset + 0x20, b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, offset));}static void b43legacy_rate_memory_init(struct b43legacy_wldev *dev){ switch (dev->phy.type) { case B43legacy_PHYTYPE_G: b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_6MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_12MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_18MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_24MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_36MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_48MB, 1); b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_54MB, 1); /* fallthrough */ case B43legacy_PHYTYPE_B: b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_1MB, 0); b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_2MB, 0); b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_5MB, 0); b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_11MB, 0); break; default: B43legacy_BUG_ON(1); }}/* Set the TX-Antenna for management frames sent by firmware. */static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev, int antenna){ u16 ant = 0; u16 tmp; switch (antenna) { case B43legacy_ANTENNA0: ant |= B43legacy_TX4_PHY_ANT0; break; case B43legacy_ANTENNA1: ant |= B43legacy_TX4_PHY_ANT1; break; case B43legacy_ANTENNA_AUTO: ant |= B43legacy_TX4_PHY_ANTLAST; break; default: B43legacy_BUG_ON(1); } /* FIXME We also need to set the other flags of the PHY control * field somewhere. */ /* For Beacons */ tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_BEACPHYCTL); tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_BEACPHYCTL, tmp); /* For ACK/CTS */ tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_ACKCTSPHYCTL); tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_ACKCTSPHYCTL, tmp); /* For Probe Resposes */ tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_PRPHYCTL); tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, B43legacy_SHM_SH_PRPHYCTL, tmp);}/* Returns TRUE, if the radio is enabled in hardware. */static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev){ if (dev->phy.rev >= 3) { if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) return 1; } return 0;}/* This is the opposite of b43legacy_chip_init() */static void b43legacy_chip_exit(struct b43legacy_wldev *dev){ b43legacy_radio_turn_off(dev); if (!modparam_noleds) b43legacy_leds_exit(dev); b43legacy_gpio_cleanup(dev); /* firmware is released later */}/* Initialize the chip * http://bcm-specs.sipsolutions.net/ChipInit */static int b43legacy_chip_init(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; int err; int tmp; u32 value32; u16 value16; b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, B43legacy_SBF_CORE_READY | B43legacy_SBF_400); err = b43legacy_request_firmware(dev); if (err) goto out; err = b43legacy_upload_microcode(dev); if (err) goto out; /* firmware is released later */ err = b43legacy_gpio_init(dev); if (err) goto out; /* firmware is released later */ err = b43legacy_upload_initvals(dev); if (err) goto err_gpio_cleanup; b43legacy_radio_turn_on(dev); b43legacy_write16(dev, 0x03E6, 0x0000); err = b43legacy_phy_init(dev); if (err) goto err_radio_off; /* Select initial Interference Mitigation. */ tmp = phy->interfmode; phy->interfmode = B43legacy_INTERFMODE_NONE; b43legacy_radio_set_interference_mitigation(dev, tmp); b43legacy_phy_set_antenna_diversity(dev); b43legacy_mgmtframe_txantenna(dev, B43legacy_ANTENNA_DEFAULT); if (phy->type == B43legacy_PHYTYPE_B) { value16 = b43legacy_read16(dev, 0x005E); value16 |= 0x0004; b43legacy_write16(dev, 0x005E, value16); } b43legacy_write32(dev, 0x0100, 0x01000000); if (dev->dev->id.revision < 5) b43legacy_write32(dev, 0x010C, 0x01000000); value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); value32 &= ~B43legacy_SBF_MODE_NOTADHOC; b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); value32 |= B43legacy_SBF_MODE_NOTADHOC; b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); if (b43legacy_using_pio(dev)) { b43legacy_write32(dev, 0x0210, 0x00000100); b43legacy_write32(dev, 0x0230, 0x00000100); b43legacy_write32(dev, 0x0250, 0x00000100); b43legacy_write32(dev, 0x0270, 0x00000100); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0034, 0x0000); } /* Probe Response Timeout value */ /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0074, 0x0000); /* Initially set the wireless operation mode. */ b43legacy_adjust_opmode(dev); if (dev->dev->id.revision < 3) { b43legacy_write16(dev, 0x060E, 0x0000); b43legacy_write16(dev, 0x0610, 0x8000); b43legacy_write16(dev, 0x0604, 0x0000); b43legacy_write16(dev, 0x0606, 0x0200); } else { b43legacy_write32(dev, 0x0188, 0x80000000); b43legacy_write32(dev, 0x018C, 0x02000000); } b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, 0x00004000); b43legacy_write32(dev, B43legacy_MMIO_DMA0_IRQ_MASK, 0x0001DC00); b43legacy_write32(dev, B43legacy_MMIO_DMA1_IRQ_MASK, 0x0000DC00); b43legacy_write32(dev, B43legacy_MMIO_DMA2_IRQ_MASK, 0x0000DC00); b43legacy_write32(dev, B43legacy_MMIO_DMA3_IRQ_MASK, 0x0001DC00); b43legacy_write32(dev, B43legacy_MMIO_DMA4_IRQ_MASK, 0x0000DC00); b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00); value32 = ssb_read32(dev->dev, SSB_TMSLOW); value32 |= 0x00100000; ssb_write32(dev->dev, SSB_TMSLOW, value32); b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY, dev->dev->bus->chipco.fast_pwrup_delay); B43legacy_WARN_ON(err != 0); b43legacydbg(dev->wl, "Chip initialized\n");out: return err;err_radio_off: b43legacy_radio_turn_off(dev);err_gpio_cleanup: b43legacy_gpio_cleanup(dev); goto out;}static void b43legacy_periodic_every120sec(struct b43legacy_wldev *dev){ struct b43legacy_phy *phy = &dev->phy; if (phy->type != B43legacy_PHYTYPE_G || phy->rev < 2) return; b43legacy_mac_suspend(dev); b43legacy_phy_lo_g_measure(dev); b43legacy_mac_enable(dev);}static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev){ b43legacy_phy_lo_mark_all_unused(dev); if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) { b43legacy_mac_suspend(dev); b43legacy_calc_nrssi_slope(dev); b43legacy_mac_enable(dev); }}static void b43legacy_periodic_every30sec(struct b43legacy_wldev *dev){ /* Update device statistics. */ b43legacy_calculate_link_quality(dev);}static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev){ b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */}static void b43legacy_periodic_every1sec(struct b43legacy_wldev *dev){ bool radio_hw_enable; /* check if radio hardware enabled status changed */ radio_hw_enable = b43legacy_is_hw_radio_enabled(dev); if (unlikely(dev->radio_hw_enable != radio_hw_enable)) { dev->radio_hw_enable = radio_hw_enable; b43legacyinfo(dev->wl, "Radio hardware status changed to %s\n", (radio_hw_enable) ? "enabled" : "disabled"); b43legacy_leds_update(dev, 0); }}static void do_periodic_work(struct b43legacy_wldev *dev){ unsigned int state; state = dev->periodic_state; if (state % 120 == 0) b43legacy_periodic_every120sec(dev); if (state % 60 == 0) b43legacy_periodic_every60sec(dev); if (state % 30 == 0) b43legacy_periodic_every30sec(dev); if (state % 15 == 0) b43legacy_periodic_every15sec(dev); b43legacy_periodic_every1sec(dev);}/* Estimate a "Badness" value based on the periodic work * state-machine state. "Badness" is worse (bigger), if the * periodic work will take longer. */static int estimate_periodic_work_badness(unsigned int state){ int badness = 0; if (state % 120 == 0) /* every 120 sec */ badness += 10; if (state % 60 == 0) /* every 60 sec */ badness += 5; if (state % 30 == 0) /* every 30 sec */ badness += 1; if (state % 15 == 0) /* every 15 sec */ badness += 1;#define BADNESS_LIMIT 4 return badness;}static void b43legacy_periodic_work_handler(struct work_struct *work){ struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev, periodic_work.work); unsigned long flags; unsigned long delay; u32 savedirqs = 0; int badness; mutex_lock(&dev->wl->mutex); if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED)) goto out; if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP)) goto out_requeue; badness = estimate_periodic_work_badness(dev->periodic_state); if (badness > BADNESS_LIMIT) { spin_lock_irqsave(&dev->wl->irq_lock, flags); /* Suspend TX as we don't want to transmit packets while * we recalibrate the hardware. */ b43legacy_tx_suspend(dev); savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); /* Periodic work will take a long time, so we want it to * be preemtible and release the spinlock. */ spin_unlock_irqrestore(&dev->wl->irq_lock, flags); b43legacy_synchronize_irq(dev); do_periodic_work(dev); spin_lock_irqsave(&dev->wl->irq_lock, flags); b43legacy_interrupt_enable(dev, savedirqs); b43legacy_tx_resume(dev); mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } else { /* Take the global driver lock. This will lock any operation. */ spin_lock_irqsave(&dev->wl->irq_lock, flags); do_periodic_work(dev); mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } dev->periodic_state++;out_requeue: if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else delay = round_jiffies_relative(HZ); queue_delayed_work(dev->wl->hw->workqueue, &dev->periodic_work, delay);out: mutex_unlock(&dev->wl->mutex);}static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev){ struct delayed_work *work = &dev->periodic_work; dev->periodic_state = 0; INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler); queue_delayed_work(dev->wl->hw->workqueue, work, 0);}/* Validate access to the chip (SHM) */static int b43legacy_validate_chipaccess(struct b43legacy_wldev *dev){ u32 value; u32 shm_backup; shm_backup = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0); b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0xAA5555AA); if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) != 0xAA5555AA) goto error; b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0x55AAAA55); if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) != 0x55AAAA55) goto error; b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, shm_backup); value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); if ((value | B43legacy_MACCTL_GMODE) != (B43legacy_MACCTL_GMODE | B43legacy_MACCTL_IHR_ENABLED)) goto error; value = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); if (value) goto error; return 0;error: b43legacyerr(dev->wl, "Failed to validate the chipaccess\n"); return -ENODEV;}static void b43legacy_security_init(struct b43legacy_wldev *dev){ dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20; B43legacy_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key)); dev->ktp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0056); /* KTP is a word address, but we address SHM bytewise. * So multiply by two. */ dev->ktp *= 2; if (dev->dev->id.revision >= 5) /* Number of RCMTA address slots */ b43legacy_write16(dev, B43legacy_MMIO_RCMTA_COUNT, dev->max_nr_keys - 8);}static int b43legacy_rng_read(struct hwrng *rng, u32 *data){ struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv; unsigned long flags; /* Don't take wl->mutex here, as it could deadlock with * hwrng internal lock
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -