static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2800pci_eepromregister_read; eeprom.register_write = rt2800pci_eepromregister_write; switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE)) { case 0: eeprom.width = PCI_EEPROM_WIDTH_93C46; break; case 1: eeprom.width = PCI_EEPROM_WIDTH_93C66; break; default: eeprom.width = PCI_EEPROM_WIDTH_93C86; break; } eeprom.reg_data_in = 0; eeprom.reg_data_out = 0; eeprom.reg_data_clock = 0; eeprom.reg_chip_select = 0; eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, EEPROM_SIZE / sizeof(u16)); }
/* * Device probe functions. */ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; rt2x00pci_register_read(rt2x00dev, CSR21, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2400pci_eepromregister_read; eeprom.register_write = rt2400pci_eepromregister_write; eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; eeprom.reg_data_in = 0; eeprom.reg_data_out = 0; eeprom.reg_data_clock = 0; eeprom.reg_chip_select = 0; eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, EEPROM_SIZE / sizeof(u16)); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { DECLARE_MAC_BUF(macbuf); random_ether_addr(mac); EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); if (word == 0xffff) { ERROR(rt2x00dev, "Invalid EEPROM data detected.\n"); return -EINVAL; } return 0; }
static int __devinit rtl8180_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct ieee80211_hw *dev; struct rtl8180_priv *priv; unsigned long mem_addr, mem_len; unsigned int io_addr, io_len; int err, i; struct eeprom_93cx6 eeprom; const char *chip_name, *rf_name = NULL; u32 reg; u16 eeprom_val; err = pci_enable_device(pdev); if (err) { printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n", pci_name(pdev)); return err; } err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n", pci_name(pdev)); return err; } io_addr = pci_resource_start(pdev, 0); io_len = pci_resource_len(pdev, 0); mem_addr = pci_resource_start(pdev, 1); mem_len = pci_resource_len(pdev, 1); if (mem_len < sizeof(struct rtl818x_csr) || io_len < sizeof(struct rtl818x_csr)) { printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n", pci_name(pdev)); err = -ENOMEM; goto err_free_reg; } if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) || (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) { printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", pci_name(pdev)); goto err_free_reg; } pci_set_master(pdev); dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops); if (!dev) { printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n", pci_name(pdev)); err = -ENOMEM; goto err_free_reg; } priv = dev->priv; priv->pdev = pdev; dev->max_rates = 2; SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); priv->map = pci_iomap(pdev, 1, mem_len); if (!priv->map) priv->map = pci_iomap(pdev, 0, io_len); if (!priv->map) { printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n", pci_name(pdev)); goto err_free_dev; } BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); priv->band.band = IEEE80211_BAND_2GHZ; priv->band.channels = priv->channels; priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = 4; dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; dev->queues = 1; dev->max_signal = 65; reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg &= RTL818X_TX_CONF_HWVER_MASK; switch (reg) { case RTL818X_TX_CONF_R8180_ABCD: chip_name = "RTL8180"; break; case RTL818X_TX_CONF_R8180_F: chip_name = "RTL8180vF"; break; case RTL818X_TX_CONF_R8185_ABC: chip_name = "RTL8185"; break; case RTL818X_TX_CONF_R8185_D: chip_name = "RTL8185vD"; break; default: printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", pci_name(pdev), reg >> 25); goto err_iounmap; } priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; if (priv->r8185) { priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); pci_try_set_mwi(pdev); } eeprom.data = dev; eeprom.register_read = rtl8180_eeprom_register_read; eeprom.register_write = rtl8180_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_PROGRAM); rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); udelay(10); eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); eeprom_val &= 0xFF; switch (eeprom_val) { case 1: rf_name = "Intersil"; break; case 2: rf_name = "RFMD"; break; case 3: priv->rf = &sa2400_rf_ops; break; case 4: priv->rf = &max2820_rf_ops; break; case 5: priv->rf = &grf5101_rf_ops; break; case 9: priv->rf = rtl8180_detect_rf(dev); break; case 10: rf_name = "RTL8255"; break; default: printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", pci_name(pdev), eeprom_val); goto err_iounmap; } if (!priv->rf) { printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n", pci_name(pdev), rf_name); goto err_iounmap; } eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); priv->csthreshold = eeprom_val >> 8; if (!priv->r8185) { __le32 anaparam; eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); priv->anaparam = le32_to_cpu(anaparam); eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); } eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3); if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" " randomly generated MAC addr\n", pci_name(pdev)); random_ether_addr(dev->wiphy->perm_addr); } /* CCK TX power */ for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr); priv->channels[i].hw_value = txpwr & 0xFF; priv->channels[i + 1].hw_value = txpwr >> 8; } /* OFDM TX power */ if (priv->r8185) { for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; priv->channels[i + 1].hw_value |= txpwr & 0xFF00; } } rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); spin_lock_init(&priv->lock); err = ieee80211_register_hw(dev); if (err) { printk(KERN_ERR "%s (rtl8180): Cannot register device\n", pci_name(pdev)); goto err_iounmap; } printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", wiphy_name(dev->wiphy), dev->wiphy->perm_addr, chip_name, priv->rf->name); return 0; err_iounmap: iounmap(priv->map); err_free_dev: pci_set_drvdata(pdev, NULL); ieee80211_free_hw(dev); err_free_reg: pci_release_regions(pdev); pci_disable_device(pdev); return err; }
static int adm8211_read_eeprom(struct ieee80211_hw *dev) { struct adm8211_priv *priv = dev->priv; unsigned int words, i; struct ieee80211_chan_range chan_range; u16 cr49; struct eeprom_93cx6 eeprom = { .data = priv, .register_read = adm8211_eeprom_register_read, .register_write = adm8211_eeprom_register_write }; if (ADM8211_CSR_READ(CSR_TEST0) & ADM8211_CSR_TEST0_EPTYP) { /* 256 * 16-bit = 512 bytes */ eeprom.width = PCI_EEPROM_WIDTH_93C66; words = 256; } else { /* 64 * 16-bit = 128 bytes */ eeprom.width = PCI_EEPROM_WIDTH_93C46; words = 64; } priv->eeprom_len = words * 2; priv->eeprom = kmalloc(priv->eeprom_len, GFP_KERNEL); if (!priv->eeprom) return -ENOMEM; eeprom_93cx6_multiread(&eeprom, 0, (__le16 *)priv->eeprom, words); cr49 = le16_to_cpu(priv->eeprom->cr49); priv->rf_type = (cr49 >> 3) & 0x7; switch (priv->rf_type) { case ADM8211_TYPE_INTERSIL: case ADM8211_TYPE_RFMD: case ADM8211_TYPE_MARVEL: case ADM8211_TYPE_AIROHA: case ADM8211_TYPE_ADMTEK: break; default: if (priv->pdev->revision < ADM8211_REV_CA) priv->rf_type = ADM8211_TYPE_RFMD; else priv->rf_type = ADM8211_TYPE_AIROHA; printk(KERN_WARNING "%s (adm8211): Unknown RFtype %d\n", pci_name(priv->pdev), (cr49 >> 3) & 0x7); } priv->bbp_type = cr49 & 0x7; switch (priv->bbp_type) { case ADM8211_TYPE_INTERSIL: case ADM8211_TYPE_RFMD: case ADM8211_TYPE_MARVEL: case ADM8211_TYPE_AIROHA: case ADM8211_TYPE_ADMTEK: break; default: if (priv->pdev->revision < ADM8211_REV_CA) priv->bbp_type = ADM8211_TYPE_RFMD; else priv->bbp_type = ADM8211_TYPE_ADMTEK; printk(KERN_WARNING "%s (adm8211): Unknown BBPtype: %d\n", pci_name(priv->pdev), cr49 >> 3); } if (priv->eeprom->country_code >= ARRAY_SIZE(cranges)) { printk(KERN_WARNING "%s (adm8211): Invalid country code (%d)\n", pci_name(priv->pdev), priv->eeprom->country_code); chan_range = cranges[2]; } else chan_range = cranges[priv->eeprom->country_code]; printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n", pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max); BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels)); memcpy(priv->channels, adm8211_channels, sizeof(priv->channels)); priv->band.channels = priv->channels; priv->band.n_channels = ARRAY_SIZE(adm8211_channels); priv->band.bitrates = adm8211_rates; priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates); for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++) if (i < chan_range.min || i > chan_range.max) priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED; switch (priv->eeprom->specific_bbptype) { case ADM8211_BBP_RFMD3000: case ADM8211_BBP_RFMD3002: case ADM8211_BBP_ADM8011: priv->specific_bbptype = priv->eeprom->specific_bbptype; break; default: if (priv->pdev->revision < ADM8211_REV_CA) priv->specific_bbptype = ADM8211_BBP_RFMD3000; else priv->specific_bbptype = ADM8211_BBP_ADM8011; printk(KERN_WARNING "%s (adm8211): Unknown specific BBP: %d\n", pci_name(priv->pdev), priv->eeprom->specific_bbptype); } switch (priv->eeprom->specific_rftype) { case ADM8211_RFMD2948: case ADM8211_RFMD2958: case ADM8211_RFMD2958_RF3000_CONTROL_POWER: case ADM8211_MAX2820: case ADM8211_AL2210L: priv->transceiver_type = priv->eeprom->specific_rftype; break; default: if (priv->pdev->revision == ADM8211_REV_BA) priv->transceiver_type = ADM8211_RFMD2958_RF3000_CONTROL_POWER; else if (priv->pdev->revision == ADM8211_REV_CA) priv->transceiver_type = ADM8211_AL2210L; else if (priv->pdev->revision == ADM8211_REV_AB) priv->transceiver_type = ADM8211_RFMD2948; printk(KERN_WARNING "%s (adm8211): Unknown transceiver: %d\n", pci_name(priv->pdev), priv->eeprom->specific_rftype); break; } printk(KERN_DEBUG "%s (adm8211): RFtype=%d BBPtype=%d Specific BBP=%d " "Transceiver=%d\n", pci_name(priv->pdev), priv->rf_type, priv->bbp_type, priv->specific_bbptype, priv->transceiver_type); return 0; }