diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2008-12-02 17:17:51 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2008-12-02 17:17:51 +0000 |
commit | 177bc7cdf9729872d5425640690365a452801f0e (patch) | |
tree | 217e07ab9c100762df61f487f25bd969530c99ab /sys/dev/pci/if_iwn.c | |
parent | 6fddb7d84e7cd152c09e1587420a3acbe44505de (diff) |
Add code for 5150 support (not tested since I don't have the hardware and
because it requires a specific firmware that Intel has not released yet.)
Fix crystal calibration for 5000 Series.
Diffstat (limited to 'sys/dev/pci/if_iwn.c')
-rw-r--r-- | sys/dev/pci/if_iwn.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 6f6c33b9180..9c3c1cb8634 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwn.c,v 1.40 2008/11/25 22:20:11 damien Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.41 2008/12/02 17:17:50 damien Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -71,6 +71,8 @@ static const struct pci_matchid iwn_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_4965AGN_2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5100AGN_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5100AGN_2 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5150AGN_1 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5150AGN_2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5300AGN_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5300AGN_2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5350AGN_1 }, @@ -252,7 +254,6 @@ static const struct iwn_hal iwn4965_hal = { iwn4965_tx_done, iwn4965_ampdu_tx_start, iwn4965_ampdu_tx_stop, - "iwn-4965", &iwn4965_sensitivity_limits, IWN4965_NTXQUEUES, IWN4965_ID_BROADCAST, @@ -280,7 +281,6 @@ static const struct iwn_hal iwn5000_hal = { iwn5000_tx_done, iwn5000_ampdu_tx_start, iwn5000_ampdu_tx_stop, - "iwn-5000", &iwn5000_sensitivity_limits, IWN5000_NTXQUEUES, IWN5000_ID_BROADCAST, @@ -508,6 +508,7 @@ iwn_hal_attach(struct iwn_softc *sc) switch (sc->hw_type) { case IWN_HW_REV_TYPE_4965: sc->sc_hal = &iwn4965_hal; + sc->fwname = "iwn-4965"; sc->critical_temp = IWN_CTOK(110); sc->txantmsk = IWN_ANT_A | IWN_ANT_B; sc->rxantmsk = IWN_ANT_ABC; @@ -516,6 +517,7 @@ iwn_hal_attach(struct iwn_softc *sc) break; case IWN_HW_REV_TYPE_5100: sc->sc_hal = &iwn5000_hal; + sc->fwname = "iwn-5000"; sc->critical_temp = 110; sc->txantmsk = IWN_ANT_B; sc->rxantmsk = IWN_ANT_A | IWN_ANT_B; @@ -524,7 +526,8 @@ iwn_hal_attach(struct iwn_softc *sc) break; case IWN_HW_REV_TYPE_5150: sc->sc_hal = &iwn5000_hal; - sc->critical_temp = IWN_CTOK(110); + sc->fwname = "iwn-5150"; + /* NB: critical temperature will be read from EEPROM. */ sc->txantmsk = IWN_ANT_A; sc->rxantmsk = IWN_ANT_A | IWN_ANT_B; sc->ntxchains = 1; @@ -533,6 +536,7 @@ iwn_hal_attach(struct iwn_softc *sc) case IWN_HW_REV_TYPE_5300: case IWN_HW_REV_TYPE_5350: sc->sc_hal = &iwn5000_hal; + sc->fwname = "iwn-5000"; sc->critical_temp = 110; sc->txantmsk = sc->rxantmsk = IWN_ANT_ABC; sc->ntxchains = sc->nrxchains = 3; @@ -1258,12 +1262,13 @@ iwn4965_print_power_group(struct iwn_softc *sc, int i) void iwn5000_read_eeprom(struct iwn_softc *sc) { + int32_t temp, volt, delta; uint32_t base, addr; uint16_t val; int i; /* Read regulatory domain (4 ASCII characters.) */ - iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, sizeof val); + iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2); base = letoh16(val); iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN, sc->eeprom_domain, 4); @@ -1274,12 +1279,25 @@ iwn5000_read_eeprom(struct iwn_softc *sc) iwn_read_eeprom_channels(sc, i, addr); } - /* Read crystal calibration. */ - iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, sizeof val); + iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2); base = letoh16(val); - iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL, - &sc->eeprom_crystal, sizeof (uint32_t)); - DPRINTF(("crystal calibration 0x%08x\n", sc->eeprom_crystal)); + if (sc->hw_type == IWN_HW_REV_TYPE_5150) { + /* Compute critical temperature (in Kelvin.) */ + iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2); + temp = letoh16(val); + iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2); + volt = letoh16(val); + delta = temp - (volt / -5); + sc->critical_temp = (IWN_CTOK(110) - delta) * -5; + DPRINTF(("temp=%d volt=%d delta=%dK\n", + temp, volt, delta)); + } else { + /* Read crystal calibration. */ + iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL, + &sc->eeprom_crystal, sizeof (uint32_t)); + DPRINTF(("crystal calibration 0x%08x\n", + letoh32(sc->eeprom_crystal))); + } } void @@ -1746,11 +1764,7 @@ void iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc) { struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1); - u_int idx, len; - - /* No initial calibration required for 5150! */ - if (sc->hw_type == IWN_HW_REV_TYPE_5150) - return; + int len, idx = -1; /* Runtime firmware should not send such a notification. */ if (!(sc->sc_flags & IWN_FLAG_FIRST_BOOT)) @@ -1762,22 +1776,27 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc) BUS_DMASYNC_POSTREAD); switch (calib->code) { + case IWN5000_PHY_CALIB_DC: + if (sc->hw_type == IWN_HW_REV_TYPE_5150) + idx = 0; + break; case IWN5000_PHY_CALIB_LO: - idx = 0; + idx = 1; break; case IWN5000_PHY_CALIB_TX_IQ: - idx = 1; + idx = 2; break; case IWN5000_PHY_CALIB_TX_IQ_PERD: - idx = 2; + if (sc->hw_type != IWN_HW_REV_TYPE_5150) + idx = 3; break; case IWN5000_PHY_CALIB_BASE_BAND: - idx = 3; + idx = 4; break; - default: - /* Ignore other results. */ - return; } + if (idx == -1) /* Ignore other results. */ + return; + /* Save calibration result. */ if (sc->calibcmd[idx].buf != NULL) free(sc->calibcmd[idx].buf, M_DEVBUF); @@ -4343,7 +4362,7 @@ iwn5000_send_calibration(struct iwn_softc *sc) { int idx, error; - for (idx = 0; idx < 4; idx++) { + for (idx = 0; idx < 5; idx++) { if (sc->calibcmd[idx].buf == NULL) continue; /* No results available. */ DPRINTF(("send calibration result idx=%d len=%d\n", @@ -4707,9 +4726,9 @@ iwn_read_firmware(struct iwn_softc *sc) int error; /* Read firmware image from filesystem. */ - if ((error = loadfirmware(hal->fwname, &fw->data, &size)) != 0) { + if ((error = loadfirmware(sc->fwname, &fw->data, &size)) != 0) { printf("%s: error, %d, could not read firmware %s\n", - sc->sc_dev.dv_xname, error, hal->fwname); + sc->sc_dev.dv_xname, error, sc->fwname); return error; } if (size < sizeof (*hdr)) { |