diff options
Diffstat (limited to 'sys/dev/pci/if_iwn.c')
-rw-r--r-- | sys/dev/pci/if_iwn.c | 114 |
1 files changed, 84 insertions, 30 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 6ab337672e4..75754651bba 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.46 2009/01/26 19:18:52 damien Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.47 2009/02/15 08:58:22 damien Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -76,7 +76,17 @@ static const struct pci_matchid iwn_devices[] = { { 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 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5350AGN_2 } + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_5350AGN_2 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6000_1 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6000_2 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6000_3 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6000_4 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_1 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_2 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_3 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6050_4 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_100_1 }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_100_2 } }; int iwn_match(struct device *, void *, void *); @@ -190,14 +200,15 @@ int iwn_set_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); void iwn_delete_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); +#ifndef IEEE80211_NO_HT int iwn_ampdu_rx_start(struct ieee80211com *, - struct ieee80211_node *, uint8_t, uint16_t); + struct ieee80211_node *, uint8_t); void iwn_ampdu_rx_stop(struct ieee80211com *, - struct ieee80211_node *, uint8_t, uint16_t); + struct ieee80211_node *, uint8_t); int iwn_ampdu_tx_start(struct ieee80211com *, - struct ieee80211_node *, uint8_t, uint16_t); + struct ieee80211_node *, uint8_t); void iwn_ampdu_tx_stop(struct ieee80211com *, - struct ieee80211_node *, uint8_t, uint16_t); + struct ieee80211_node *, uint8_t); void iwn4965_ampdu_tx_start(struct iwn_softc *, struct ieee80211_node *, uint8_t, uint16_t); void iwn4965_ampdu_tx_stop(struct iwn_softc *, @@ -206,6 +217,7 @@ void iwn5000_ampdu_tx_start(struct iwn_softc *, struct ieee80211_node *, uint8_t, uint16_t); void iwn5000_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t); +#endif int iwn5000_query_calibration(struct iwn_softc *); int iwn5000_send_calibration(struct iwn_softc *); int iwn4965_post_alive(struct iwn_softc *); @@ -252,8 +264,10 @@ static const struct iwn_hal iwn4965_hal = { iwn4965_set_gains, iwn4965_add_node, iwn4965_tx_done, +#ifndef IEEE80211_NO_HT iwn4965_ampdu_tx_start, iwn4965_ampdu_tx_stop, +#endif &iwn4965_sensitivity_limits, IWN4965_NTXQUEUES, IWN4965_ID_BROADCAST, @@ -279,8 +293,10 @@ static const struct iwn_hal iwn5000_hal = { iwn5000_set_gains, iwn5000_add_node, iwn5000_tx_done, +#ifndef IEEE80211_NO_HT iwn5000_ampdu_tx_start, iwn5000_ampdu_tx_stop, +#endif &iwn5000_sensitivity_limits, IWN5000_NTXQUEUES, IWN5000_ID_BROADCAST, @@ -470,6 +486,12 @@ iwn_attach(struct device *parent, struct device *self, void *aux) ic->ic_updateedca = iwn_updateedca; ic->ic_set_key = iwn_set_key; ic->ic_delete_key = iwn_delete_key; +#ifndef IEEE80211_NO_HT + ic->ic_ampdu_rx_start = iwn_ampdu_rx_start; + ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop; + ic->ic_ampdu_tx_start = iwn_ampdu_tx_start; + ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop; +#endif /* Override 802.11 state transition machine. */ sc->sc_newstate = ic->ic_newstate; @@ -541,6 +563,33 @@ iwn_hal_attach(struct iwn_softc *sc) sc->txantmsk = sc->rxantmsk = IWN_ANT_ABC; sc->ntxchains = sc->nrxchains = 3; break; + case IWN_HW_REV_TYPE_100: + sc->sc_hal = &iwn5000_hal; + sc->fwname = "iwn-100"; + sc->critical_temp = 110; + sc->txantmsk = IWN_ANT_A; + sc->rxantmsk = IWN_ANT_A | IWN_ANT_B; + sc->ntxchains = 1; + sc->nrxchains = 2; + break; + case IWN_HW_REV_TYPE_6000: + sc->sc_hal = &iwn5000_hal; + sc->fwname = "iwn-6000"; + sc->critical_temp = 110; + sc->txantmsk = IWN_ANT_ABC; + sc->rxantmsk = IWN_ANT_ABC; + sc->ntxchains = 3; + sc->nrxchains = 3; + break; + case IWN_HW_REV_TYPE_6050: + sc->sc_hal = &iwn5000_hal; + sc->fwname = "iwn-6050"; + sc->critical_temp = 110; + sc->txantmsk = IWN_ANT_ABC; + sc->rxantmsk = IWN_ANT_ABC; + sc->ntxchains = 3; + sc->nrxchains = 3; + break; default: printf(": adapter type %d not supported\n", sc->hw_type); return NULL; @@ -3437,6 +3486,10 @@ iwn5000_init_gains(struct iwn_softc *sc) { struct iwn_phy_calib cmd; + if (sc->hw_type == IWN_HW_REV_TYPE_6000 || + sc->hw_type == IWN_HW_REV_TYPE_6050) + return 0; + memset(&cmd, 0, sizeof cmd); cmd.code = IWN5000_PHY_CALIB_RESET_NOISE_GAIN; cmd.ngroups = 1; @@ -3484,6 +3537,10 @@ iwn5000_set_gains(struct iwn_softc *sc) struct iwn_phy_calib_gain cmd; int i, delta; + if (sc->hw_type == IWN_HW_REV_TYPE_6000 || + sc->hw_type == IWN_HW_REV_TYPE_6050) + return 0; + memset(&cmd, 0, sizeof cmd); cmd.code = IWN5000_PHY_CALIB_NOISE_GAIN; cmd.ngroups = 1; @@ -4158,14 +4215,16 @@ iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, (void)hal->add_node(sc, &node, 1); } +#ifndef IEEE80211_NO_HT /* - * This function is called by upper layer when a ADDBA request is received + * This function is called by upper layer when an ADDBA request is received * from another STA and before the ADDBA response is sent. */ int iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, - uint8_t tid, uint16_t ssn) + uint8_t tid) { + struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; struct iwn_node *wn = (void *)ni; struct iwn_node_info node; @@ -4175,18 +4234,19 @@ iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, node.control = IWN_NODE_UPDATE; node.flags = IWN_FLAG_SET_ADDBA; node.addba_tid = tid; - node.addba_ssn = htole16(ssn); - DPRINTFN(2, ("ADDBA RA=%d TID=%d SSN=%d\n", wn->id, tid, ssn)); + node.addba_ssn = htole16(ba->ba_winstart); + DPRINTFN(2, ("ADDBA RA=%d TID=%d SSN=%d\n", wn->id, tid, + ba->ba_winstart)); return sc->sc_hal->add_node(sc, &node, 1); } /* * This function is called by upper layer on teardown of an HT-immediate - * Block Ack (eg. uppon receipt of a DELBA frame.) + * Block Ack agreement (eg. uppon receipt of a DELBA frame.) */ void iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, - uint8_t tid, uint16_t ssn) + uint8_t tid) { struct iwn_softc *sc = ic->ic_softc; struct iwn_node *wn = (void *)ni; @@ -4202,13 +4262,14 @@ iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, } /* - * This function is called by upper layer when a ADDBA response is received + * This function is called by upper layer when an ADDBA response is received * from another STA. */ int iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni, - uint8_t tid, uint16_t ssn) + uint8_t tid) { + struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; const struct iwn_hal *hal = sc->sc_hal; struct iwn_node *wn = (void *)ni; @@ -4228,20 +4289,21 @@ iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni, if ((error = iwn_nic_lock(sc)) != 0) return error; - hal->ampdu_tx_start(sc, ni, tid, ssn); + hal->ampdu_tx_start(sc, ni, tid, ba->ba_winstart); iwn_nic_unlock(sc); return 0; } void iwn_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, - uint8_t tid, uint16_t ssn) + uint8_t tid) { + struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid]; struct iwn_softc *sc = ic->ic_softc; if (iwn_nic_lock(sc) != 0) return; - sc->sc_hal->ampdu_tx_stop(sc, tid, ssn); + sc->sc_hal->ampdu_tx_stop(sc, tid, ba->ba_winstart); iwn_nic_unlock(sc); } @@ -4364,6 +4426,7 @@ iwn5000_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn) iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), IWN5000_TXQ_STATUS_INACTIVE | iwn_tid2fifo[tid]); } +#endif /* !IEEE80211_NO_HT */ /* * Query calibration tables from the initialization firmware. We do this @@ -4873,7 +4936,10 @@ iwn5000_apm_init(struct iwn_softc *sc) /* Enable HAP to move adapter from L1a to L0s. */ IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_HAP_WAKE_L1A); - IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT); + + if (sc->hw_type != IWN_HW_REV_TYPE_6000 && + sc->hw_type != IWN_HW_REV_TYPE_6050) + IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT); if ((error = iwn_clock_wait(sc)) != 0) return error; @@ -4919,18 +4985,6 @@ int iwn4965_nic_config(struct iwn_softc *sc) { pcireg_t reg; - uint8_t rev; - - reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_CLASS_REG); - rev = PCI_REVISION(reg); - if ((rev & 0x80) && (rev & 0x7f) < 8) { - reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, - sc->sc_cap_off + PCI_PCIE_DCSR); - /* Clear PCIe "Enable No Snoop" bit. */ - reg &= ~PCI_PCIE_DCSR_ENA_NO_SNOOP; - pci_conf_write(sc->sc_pct, sc->sc_pcitag, - sc->sc_cap_off + PCI_PCIE_DCSR, reg); - } /* Retrieve PCIe Active State Power Management (ASPM). */ reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, |