rtl8187_dev.c
来自「linux 内核源代码」· C语言 代码 · 共 827 行 · 第 1/2 页
C
827 行
* changes, as this has be seen to causes problems and the * card will stop work until next reset */ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg | RTL818X_TX_CONF_LOOPBACK_MAC); msleep(10); rtl8225_rf_set_channel(dev, channel); msleep(10); rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);}static int rtl8187_start(struct ieee80211_hw *dev){ struct rtl8187_priv *priv = dev->priv; u32 reg; int ret; ret = rtl8187_init_hw(dev); if (ret) return ret; rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); rtl8187_init_urbs(dev); reg = RTL818X_RX_CONF_ONLYERLPKT | RTL818X_RX_CONF_RX_AUTORESETPHY | RTL818X_RX_CONF_BSSID | RTL818X_RX_CONF_MGMT | RTL818X_RX_CONF_DATA | (7 << 13 /* RX FIFO threshold NONE */) | (7 << 10 /* MAX RX DMA */) | RTL818X_RX_CONF_BROADCAST | RTL818X_RX_CONF_NICMAC; priv->rx_conf = reg; rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT; reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); reg = RTL818X_TX_CONF_CW_MIN | (7 << 21 /* MAX TX DMA */) | RTL818X_TX_CONF_NO_ICV; rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); reg = rtl818x_ioread8(priv, &priv->map->CMD); reg |= RTL818X_CMD_TX_ENABLE; reg |= RTL818X_CMD_RX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); return 0;}static void rtl8187_stop(struct ieee80211_hw *dev){ struct rtl8187_priv *priv = dev->priv; struct rtl8187_rx_info *info; struct sk_buff *skb; u32 reg; rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); reg = rtl818x_ioread8(priv, &priv->map->CMD); reg &= ~RTL818X_CMD_TX_ENABLE; reg &= ~RTL818X_CMD_RX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); rtl8225_rf_stop(dev); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); while ((skb = skb_dequeue(&priv->rx_queue))) { info = (struct rtl8187_rx_info *)skb->cb; usb_kill_urb(info->urb); kfree_skb(skb); } return;}static int rtl8187_add_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf){ struct rtl8187_priv *priv = dev->priv; int i; if (priv->mode != IEEE80211_IF_TYPE_MNTR) return -EOPNOTSUPP; switch (conf->type) { case IEEE80211_IF_TYPE_STA: priv->mode = conf->type; break; default: return -EOPNOTSUPP; } rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->MAC[i], ((u8 *)conf->mac_addr)[i]); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); return 0;}static void rtl8187_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf){ struct rtl8187_priv *priv = dev->priv; priv->mode = IEEE80211_IF_TYPE_MNTR;}static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf){ struct rtl8187_priv *priv = dev->priv; rtl8187_set_channel(dev, conf->channel); rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); } else { rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); } rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); return 0;}static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id, struct ieee80211_if_conf *conf){ struct rtl8187_priv *priv = dev->priv; int i; priv->if_id = if_id; for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); if (is_valid_ether_addr(conf->bssid)) rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); else rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); return 0;}static void rtl8187_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, int mc_count, struct dev_addr_list *mclist){ struct rtl8187_priv *priv = dev->priv; if (changed_flags & FIF_FCSFAIL) priv->rx_conf ^= RTL818X_RX_CONF_FCS; if (changed_flags & FIF_CONTROL) priv->rx_conf ^= RTL818X_RX_CONF_CTRL; if (changed_flags & FIF_OTHER_BSS) priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; if (*total_flags & FIF_ALLMULTI || mc_count > 0) priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; else priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; *total_flags = 0; if (priv->rx_conf & RTL818X_RX_CONF_FCS) *total_flags |= FIF_FCSFAIL; if (priv->rx_conf & RTL818X_RX_CONF_CTRL) *total_flags |= FIF_CONTROL; if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) *total_flags |= FIF_OTHER_BSS; if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) *total_flags |= FIF_ALLMULTI; rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);}static const struct ieee80211_ops rtl8187_ops = { .tx = rtl8187_tx, .start = rtl8187_start, .stop = rtl8187_stop, .add_interface = rtl8187_add_interface, .remove_interface = rtl8187_remove_interface, .config = rtl8187_config, .config_interface = rtl8187_config_interface, .configure_filter = rtl8187_configure_filter,};static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom){ struct ieee80211_hw *dev = eeprom->data; struct rtl8187_priv *priv = dev->priv; u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;}static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom){ struct ieee80211_hw *dev = eeprom->data; struct rtl8187_priv *priv = dev->priv; u8 reg = RTL818X_EEPROM_CMD_PROGRAM; if (eeprom->reg_data_in) reg |= RTL818X_EEPROM_CMD_WRITE; if (eeprom->reg_data_out) reg |= RTL818X_EEPROM_CMD_READ; if (eeprom->reg_data_clock) reg |= RTL818X_EEPROM_CMD_CK; if (eeprom->reg_chip_select) reg |= RTL818X_EEPROM_CMD_CS; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); udelay(10);}static int __devinit rtl8187_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *udev = interface_to_usbdev(intf); struct ieee80211_hw *dev; struct rtl8187_priv *priv; struct eeprom_93cx6 eeprom; struct ieee80211_channel *channel; u16 txpwr, reg; int err, i; DECLARE_MAC_BUF(mac); dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); if (!dev) { printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n"); return -ENOMEM; } priv = dev->priv; SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); priv->udev = udev; usb_get_dev(udev); skb_queue_head_init(&priv->rx_queue); memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); priv->map = (struct rtl818x_csr *)0xFF00; priv->modes[0].mode = MODE_IEEE80211G; priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); priv->modes[0].rates = priv->rates; priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); priv->modes[0].channels = priv->channels; priv->modes[1].mode = MODE_IEEE80211B; priv->modes[1].num_rates = 4; priv->modes[1].rates = priv->rates; priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); priv->modes[1].channels = priv->channels; priv->mode = IEEE80211_IF_TYPE_MNTR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); dev->queues = 1; dev->max_rssi = 65; dev->max_signal = 64; for (i = 0; i < 2; i++) if ((err = ieee80211_register_hwmode(dev, &priv->modes[i]))) goto err_free_dev; eeprom.data = dev; eeprom.register_read = rtl8187_eeprom_register_read; eeprom.register_write = rtl8187_eeprom_register_write; if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) eeprom.width = PCI_EEPROM_WIDTH_93C66; else eeprom.width = PCI_EEPROM_WIDTH_93C46; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); udelay(10); eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, (__le16 __force *)dev->wiphy->perm_addr, 3); if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " "generated MAC address\n"); random_ether_addr(dev->wiphy->perm_addr); } channel = priv->channels; for (i = 0; i < 3; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, &txpwr); (*channel++).val = txpwr & 0xFF; (*channel++).val = txpwr >> 8; } for (i = 0; i < 2; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, &txpwr); (*channel++).val = txpwr & 0xFF; (*channel++).val = txpwr >> 8; } for (i = 0; i < 2; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, &txpwr); (*channel++).val = txpwr & 0xFF; (*channel++).val = txpwr >> 8; } eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, &priv->txpwr_base); reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1; rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1); /* 0 means asic B-cut, we should use SW 3 wire * bit-by-bit banging for radio. 1 means we can use * USB specific request to write radio registers */ priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3; rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl8225_write(dev, 0, 0x1B7); if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700) priv->rf_init = rtl8225_rf_init; else priv->rf_init = rtl8225z2_rf_init; rtl8225_write(dev, 0, 0x0B7); err = ieee80211_register_hw(dev); if (err) { printk(KERN_ERR "rtl8187: Cannot register device\n"); goto err_free_dev; } printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), priv->asic_rev, priv->rf_init == rtl8225_rf_init ? "rtl8225" : "rtl8225z2"); return 0; err_free_dev: ieee80211_free_hw(dev); usb_set_intfdata(intf, NULL); usb_put_dev(udev); return err;}static void __devexit rtl8187_disconnect(struct usb_interface *intf){ struct ieee80211_hw *dev = usb_get_intfdata(intf); struct rtl8187_priv *priv; if (!dev) return; ieee80211_unregister_hw(dev); priv = dev->priv; usb_put_dev(interface_to_usbdev(intf)); ieee80211_free_hw(dev);}static struct usb_driver rtl8187_driver = { .name = KBUILD_MODNAME, .id_table = rtl8187_table, .probe = rtl8187_probe, .disconnect = rtl8187_disconnect,};static int __init rtl8187_init(void){ return usb_register(&rtl8187_driver);}static void __exit rtl8187_exit(void){ usb_deregister(&rtl8187_driver);}module_init(rtl8187_init);module_exit(rtl8187_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?