📄 main.c
字号:
(ssb_read32(gpiodev, B43_GPIO_CONTROL) & mask) | set); return 0;}/* Turn off all GPIO stuff. Call this on module unload, for example. */static void b43_gpio_cleanup(struct b43_wldev *dev){ struct ssb_bus *bus = dev->dev->bus; struct ssb_device *gpiodev, *pcidev = NULL;#ifdef CONFIG_SSB_DRIVER_PCICORE pcidev = bus->pcicore.dev;#endif gpiodev = bus->chipco.dev ? : pcidev; if (!gpiodev) return; ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);}/* http://bcm-specs.sipsolutions.net/EnableMac */void b43_mac_enable(struct b43_wldev *dev){ dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); B43_WARN_ON(irqs_disabled()); if (dev->mac_suspended == 0) { b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) | B43_MACCTL_ENABLED); b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_MAC_SUSPENDED); /* Commit writes */ b43_read32(dev, B43_MMIO_MACCTL); b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); b43_power_saving_ctl_bits(dev, 0); /* Re-enable IRQs. */ spin_lock_irq(&dev->wl->irq_lock); b43_interrupt_enable(dev, dev->irq_savedstate); spin_unlock_irq(&dev->wl->irq_lock); }}/* http://bcm-specs.sipsolutions.net/SuspendMAC */void b43_mac_suspend(struct b43_wldev *dev){ int i; u32 tmp; might_sleep(); B43_WARN_ON(irqs_disabled()); B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { /* Mask IRQs before suspending MAC. Otherwise * the MAC stays busy and won't suspend. */ spin_lock_irq(&dev->wl->irq_lock); tmp = b43_interrupt_disable(dev, B43_IRQ_ALL); spin_unlock_irq(&dev->wl->irq_lock); b43_synchronize_irq(dev); dev->irq_savedstate = tmp; b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) & ~B43_MACCTL_ENABLED); /* force pci to flush the write */ b43_read32(dev, B43_MMIO_MACCTL); for (i = 40; i; i--) { tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (tmp & B43_IRQ_MAC_SUSPENDED) goto out; msleep(1); } b43err(dev->wl, "MAC suspend failed\n"); }out: dev->mac_suspended++;}static void b43_adjust_opmode(struct b43_wldev *dev){ struct b43_wl *wl = dev->wl; u32 ctl; u16 cfp_pretbtt; ctl = b43_read32(dev, B43_MMIO_MACCTL); /* Reset status to STA infrastructure mode. */ ctl &= ~B43_MACCTL_AP; ctl &= ~B43_MACCTL_KEEP_CTL; ctl &= ~B43_MACCTL_KEEP_BADPLCP; ctl &= ~B43_MACCTL_KEEP_BAD; ctl &= ~B43_MACCTL_PROMISC; ctl &= ~B43_MACCTL_BEACPROMISC; ctl |= B43_MACCTL_INFRA; if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) ctl |= B43_MACCTL_AP; else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) ctl &= ~B43_MACCTL_INFRA; if (wl->filter_flags & FIF_CONTROL) ctl |= B43_MACCTL_KEEP_CTL; if (wl->filter_flags & FIF_FCSFAIL) ctl |= B43_MACCTL_KEEP_BAD; if (wl->filter_flags & FIF_PLCPFAIL) ctl |= B43_MACCTL_KEEP_BADPLCP; if (wl->filter_flags & FIF_PROMISC_IN_BSS) ctl |= B43_MACCTL_PROMISC; if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) ctl |= B43_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 |= B43_MACCTL_PROMISC; b43_write32(dev, B43_MMIO_MACCTL, ctl); cfp_pretbtt = 2; if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) { if (dev->dev->bus->chip_id == 0x4306 && dev->dev->bus->chip_rev == 3) cfp_pretbtt = 100; else cfp_pretbtt = 50; } b43_write16(dev, 0x612, cfp_pretbtt);}static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm){ u16 offset; if (is_ofdm) { offset = 0x480; offset += (b43_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; } else { offset = 0x4C0; offset += (b43_plcp_get_ratecode_cck(rate) & 0x000F) * 2; } b43_shm_write16(dev, B43_SHM_SHARED, offset + 0x20, b43_shm_read16(dev, B43_SHM_SHARED, offset));}static void b43_rate_memory_init(struct b43_wldev *dev){ switch (dev->phy.type) { case B43_PHYTYPE_A: case B43_PHYTYPE_G: b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_24MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_36MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_48MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_54MB, 1); if (dev->phy.type == B43_PHYTYPE_A) break; /* fallthrough */ case B43_PHYTYPE_B: b43_rate_memory_write(dev, B43_CCK_RATE_1MB, 0); b43_rate_memory_write(dev, B43_CCK_RATE_2MB, 0); b43_rate_memory_write(dev, B43_CCK_RATE_5MB, 0); b43_rate_memory_write(dev, B43_CCK_RATE_11MB, 0); break; default: B43_WARN_ON(1); }}/* Set the TX-Antenna for management frames sent by firmware. */static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna){ u16 ant = 0; u16 tmp; switch (antenna) { case B43_ANTENNA0: ant |= B43_TX4_PHY_ANT0; break; case B43_ANTENNA1: ant |= B43_TX4_PHY_ANT1; break; case B43_ANTENNA_AUTO: ant |= B43_TX4_PHY_ANTLAST; break; default: B43_WARN_ON(1); } /* FIXME We also need to set the other flags of the PHY control field somewhere. */ /* For Beacons */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp); /* For ACK/CTS */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL); tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp); /* For Probe Resposes */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL); tmp = (tmp & ~B43_TX4_PHY_ANT) | ant; b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);}/* This is the opposite of b43_chip_init() */static void b43_chip_exit(struct b43_wldev *dev){ b43_radio_turn_off(dev, 1); b43_gpio_cleanup(dev); /* firmware is released later */}/* Initialize the chip * http://bcm-specs.sipsolutions.net/ChipInit */static int b43_chip_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; int err, tmp; u32 value32; u16 value16; b43_write32(dev, B43_MMIO_MACCTL, B43_MACCTL_PSM_JMP0 | B43_MACCTL_IHR_ENABLED); err = b43_request_firmware(dev); if (err) goto out; err = b43_upload_microcode(dev); if (err) goto out; /* firmware is released later */ err = b43_gpio_init(dev); if (err) goto out; /* firmware is released later */ err = b43_upload_initvals(dev); if (err) goto err_gpio_clean; b43_radio_turn_on(dev); b43_write16(dev, 0x03E6, 0x0000); err = b43_phy_init(dev); if (err) goto err_radio_off; /* Select initial Interference Mitigation. */ tmp = phy->interfmode; phy->interfmode = B43_INTERFMODE_NONE; b43_radio_set_interference_mitigation(dev, tmp); b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT); b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); if (phy->type == B43_PHYTYPE_B) { value16 = b43_read16(dev, 0x005E); value16 |= 0x0004; b43_write16(dev, 0x005E, value16); } b43_write32(dev, 0x0100, 0x01000000); if (dev->dev->id.revision < 5) b43_write32(dev, 0x010C, 0x01000000); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) & ~B43_MACCTL_INFRA); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) | B43_MACCTL_INFRA); if (b43_using_pio(dev)) { b43_write32(dev, 0x0210, 0x00000100); b43_write32(dev, 0x0230, 0x00000100); b43_write32(dev, 0x0250, 0x00000100); b43_write32(dev, 0x0270, 0x00000100); b43_shm_write16(dev, B43_SHM_SHARED, 0x0034, 0x0000); } /* Probe Response Timeout value */ /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000); /* Initially set the wireless operation mode. */ b43_adjust_opmode(dev); if (dev->dev->id.revision < 3) { b43_write16(dev, 0x060E, 0x0000); b43_write16(dev, 0x0610, 0x8000); b43_write16(dev, 0x0604, 0x0000); b43_write16(dev, 0x0606, 0x0200); } else { b43_write32(dev, 0x0188, 0x80000000); b43_write32(dev, 0x018C, 0x02000000); } b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00); value32 = ssb_read32(dev->dev, SSB_TMSLOW); value32 |= 0x00100000; ssb_write32(dev->dev, SSB_TMSLOW, value32); b43_write16(dev, B43_MMIO_POWERUP_DELAY, dev->dev->bus->chipco.fast_pwrup_delay); err = 0; b43dbg(dev->wl, "Chip initialized\n");out: return err;err_radio_off: b43_radio_turn_off(dev, 1);err_gpio_clean: b43_gpio_cleanup(dev); return err;}static void b43_periodic_every120sec(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (phy->type != B43_PHYTYPE_G || phy->rev < 2) return; b43_mac_suspend(dev); b43_lo_g_measure(dev); b43_mac_enable(dev); if (b43_has_hardware_pctl(phy)) b43_lo_g_ctl_mark_all_unused(dev);}static void b43_periodic_every60sec(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (!b43_has_hardware_pctl(phy)) b43_lo_g_ctl_mark_all_unused(dev); if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) { b43_mac_suspend(dev); b43_calc_nrssi_slope(dev); if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { u8 old_chan = phy->channel; /* VCO Calibration */ if (old_chan >= 8) b43_radio_selectchannel(dev, 1, 0); else b43_radio_selectchannel(dev, 13, 0); b43_radio_selectchannel(dev, old_chan, 0); } b43_mac_enable(dev); }}static void b43_periodic_every30sec(struct b43_wldev *dev){ /* Update device statistics. */ b43_calculate_link_quality(dev);}static void b43_periodic_every15sec(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (phy->type == B43_PHYTYPE_G) { //TODO: update_aci_moving_average if (phy->aci_enable && phy->aci_wlan_automatic) { b43_mac_suspend(dev); if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) { if (0 /*TODO: bunch of conditions */ ) { b43_radio_set_interference_mitigation (dev, B43_INTERFMODE_MANUALWLAN); } } else if (1 /*TODO*/) { /* if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) { b43_radio_set_interference_mitigation(dev, B43_INTERFMODE_NONE); } */ } b43_mac_enable(dev); } else if (phy->interfmode == B43_INTERFMODE_NONWLAN && phy->rev == 1) { //TODO: implement rev1 workaround } } b43_phy_xmitpower(dev); //FIXME: unless scanning? //TODO for APHY (temperature?)}static void do_periodic_work(struct b43_wldev *dev){ unsigned int state; state = dev->periodic_state; if (state % 8 == 0) b43_periodic_every120sec(dev); if (state % 4 == 0) b43_periodic_every60sec(dev); if (state % 2 == 0) b43_periodic_every30sec(dev); b43_periodic_every15sec(dev);}/* Periodic work locking policy: * The whole periodic work handler is protected by * wl->mutex. If another lock is needed somewhere in the * pwork callchain, it's aquired in-place, where it's needed. */static void b43_periodic_work_handler(struct work_struct *work){ struct b43_wldev *dev = container_of(work, struct b43_wldev, periodic_work.work); struct b43_wl *wl = dev->wl; unsigned long delay; mutex_lock(&wl->mutex); if (unlikely(b43_status(dev) != B43_STAT_STARTED)) goto out; if (b43_debug(dev, B43_DBG_PWORK_STOP)) goto out_requeue; do_periodic_work(dev); dev->periodic_state++;out_requeue: if (b43_debug(dev, B43_DBG_PWORK_FAST)) delay = msecs_to_jiffies(50); else delay = round_jiffies_relative(HZ * 15); queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);out: mutex_unlock(&wl->mutex);}static void b43_periodic_tasks_setup(struct b43_wldev *dev){ struct delayed_work *work = &dev->periodic_work; dev->periodic_state = 0; INIT_DELAYED_WORK(work, b43_periodic_work_handler); queue_delayed_work(dev->wl->hw->workqueue, work, 0);}/* Validate access to the chip (SHM) */static int b43_validate_chipaccess(struct b43_wldev *dev){ u32 value; u32 shm_backup; shm_backup = b43_shm_read32(dev, B43_SHM_SHARED, 0); b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA); if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) goto error; b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0x55AAAA55) goto error; b43_shm_write32(dev, B43_SHM_SHARED, 0, shm_backup); value = b43_read32(dev, B43_MMIO_MACCTL); if ((value | B43_MACCTL_GMODE) != (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED)) goto error; value = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (value) goto error; return 0; error: b43err(dev->wl, "Failed to validate the chipaccess\n"); return -ENODEV;}static void b43_security_init(struct b43_wldev *dev){ dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20; B43_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key)); dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP); /* KTP is a word address, but we address SHM bytewise. * So multiply
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -