diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_iwn.c | 128 | ||||
-rw-r--r-- | sys/dev/pci/if_iwnreg.h | 37 | ||||
-rw-r--r-- | sys/dev/pci/pcidevs | 4 |
3 files changed, 118 insertions, 51 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 45b779e477c..ff74ab75ecf 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.77 2009/11/04 17:46:52 damien Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.78 2009/11/08 11:54:48 damien Exp $ */ /*- * Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr> @@ -83,9 +83,7 @@ static const struct pci_matchid iwn_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6000_IPA_2 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6050_2X2_1 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6050_2X2_2 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6050_3X3_1 }, - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6050_3X3_2 } + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WIFI_LINK_6050_2X2_2 } }; int iwn_match(struct device *, void *, void *); @@ -141,6 +139,10 @@ void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); +#ifndef IEEE80211_NO_HT +void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *, + struct iwn_rx_data *); +#endif void iwn5000_rx_calib_results(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *, @@ -477,13 +479,35 @@ iwn_attach(struct device *parent, struct device *self, void *aux) IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_PMGT; /* power saving supported */ - /* Set supported rates. */ +#ifndef IEEE80211_NO_HT + /* Set HT capabilities. */ + ic->ic_htcaps = +#if IWN_RBUF_SIZE == 8192 + IEEE80211_HTCAP_AMSDU7935 | +#endif + IEEE80211_HTCAP_SMPS_DIS | + IEEE80211_HTCAP_CBW20_40 | + IEEE80211_HTCAP_SGI20 | + IEEE80211_HTCAP_SGI40; + if (sc->hw_type != IWN_HW_REV_TYPE_4965) + ic->ic_htcaps |= IEEE80211_HTCAP_GF; +#endif /* !IEEE80211_NO_HT */ + + /* Set supported legacy rates. */ ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; if (sc->sc_flags & IWN_FLAG_HAS_5GHZ) { ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a; } +#ifndef IEEE80211_NO_HT + /* Set supported HT rates. */ + ic->ic_sup_mcs[0] = 0xff; + if (sc->nrxchains > 1) + ic->ic_sup_mcs[1] = 0xff; + if (sc->nrxchains > 2) + ic->ic_sup_mcs[2] = 0xff; +#endif /* IBSS channel undefined for now. */ ic->ic_ibss_chan = &ic->ic_channels[0]; @@ -584,7 +608,6 @@ iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid) sc->rxchainmask = IWN_ANT_AB; break; case IWN_HW_REV_TYPE_6000: - case IWN_HW_REV_TYPE_6050: sc->sc_hal = &iwn5000_hal; sc->limits = &iwn6000_sensitivity_limits; sc->fwname = "iwn-6000"; @@ -595,17 +618,19 @@ iwn_hal_attach(struct iwn_softc *sc, pci_product_id_t pid) sc->txchainmask = IWN_ANT_BC; sc->rxchainmask = IWN_ANT_BC; break; - case PCI_PRODUCT_INTEL_WIFI_LINK_6050_2X2_1: - case PCI_PRODUCT_INTEL_WIFI_LINK_6050_2X2_2: - sc->txchainmask = IWN_ANT_AB; - sc->rxchainmask = IWN_ANT_AB; - break; default: sc->txchainmask = IWN_ANT_ABC; sc->rxchainmask = IWN_ANT_ABC; break; } break; + case IWN_HW_REV_TYPE_6050: + sc->sc_hal = &iwn5000_hal; + sc->limits = &iwn6000_sensitivity_limits; + sc->fwname = "iwn-6000"; + sc->txchainmask = IWN_ANT_AB; + sc->rxchainmask = IWN_ANT_AB; + break; default: printf(": adapter type %d not supported\n", sc->hw_type); return NULL; @@ -1321,6 +1346,13 @@ iwn_read_eeprom(struct iwn_softc *sc) DPRINTF(("%s found\n", (sc->sc_flags & IWN_FLAG_HAS_OTPROM) ? "OTPROM" : "EEPROM")); + /* Adapter has to be powered on for EEPROM access to work. */ + if ((error = iwn_apm_init(sc)) != 0) { + printf("%s: could not power ON adapter\n", + sc->sc_dev.dv_xname); + return error; + } + if ((IWN_READ(sc, IWN_EEPROM_GP) & 0x7) == 0) { printf("%s: bad ROM signature\n", sc->sc_dev.dv_xname); return EIO; @@ -1330,14 +1362,6 @@ iwn_read_eeprom(struct iwn_softc *sc) sc->sc_dev.dv_xname, error); return error; } - - /* Adapter has to be powered on for EEPROM access to work. */ - if ((error = iwn_apm_init(sc)) != 0) { - printf("%s: could not power ON adapter\n", - sc->sc_dev.dv_xname); - return error; - } - if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) { if ((error = iwn_init_otprom(sc)) != 0) { printf("%s: could not initialize OTPROM\n", @@ -1555,7 +1579,11 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc) iwn_read_prom_data(sc, base + IWN6000_EEPROM_ENHINFO, enhinfo, sizeof enhinfo); + memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr); for (i = 0; i < nitems(enhinfo); i++) { + if (enhinfo[i].chan == 0 || enhinfo[i].reserved != 0) + continue; /* Skip invalid entries. */ + maxpwr = 0; if (sc->txchainmask & IWN_ANT_A) maxpwr = MAX(maxpwr, enhinfo[i].chain[0]); @@ -1994,6 +2022,23 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, ieee80211_release_node(ic, ni); } +#ifndef IEEE80211_NO_HT +/* Process an incoming Compressed BlockAck. */ +void +iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, + struct iwn_rx_data *data) +{ + struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1); + struct iwn_tx_ring *txq; + + bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*ba), + BUS_DMASYNC_POSTREAD); + + txq = &sc->txq[letoh16(ba->qid)]; + /* XXX TBD */ +} +#endif + /* * Process a CALIBRATION_RESULT notification sent by the initialization * firmware on response to a CMD_CALIB_CONFIG command (5000 only.) @@ -2120,7 +2165,7 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*stat), BUS_DMASYNC_POSTREAD); - iwn_tx_done(sc, desc, stat->retrycnt, letoh32(stat->status) & 0xff); + iwn_tx_done(sc, desc, stat->ackfailcnt, letoh32(stat->status) & 0xff); } void @@ -2136,14 +2181,14 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*stat), BUS_DMASYNC_POSTREAD); - iwn_tx_done(sc, desc, stat->retrycnt, letoh16(stat->status) & 0xff); + iwn_tx_done(sc, desc, stat->ackfailcnt, letoh16(stat->status) & 0xff); } /* * Adapter-independent backend for TX_DONE firmware notifications. */ void -iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int retrycnt, +iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, uint8_t status) { struct ieee80211com *ic = &sc->sc_ic; @@ -2154,7 +2199,7 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int retrycnt, /* Update rate control statistics. */ wn->amn.amn_txcnt++; - if (retrycnt > 0) + if (ackfailcnt > 0) wn->amn.amn_retrycnt++; if (status != 1 && status != 2) @@ -2245,7 +2290,12 @@ iwn_notif_intr(struct iwn_softc *sc) /* An 802.11 frame has been received. */ iwn_rx_done(sc, desc, data); break; - +#ifndef IEEE80211_NO_HT + case IWN_RX_COMPRESSED_BA: + /* A Compressed BlockAck has been received. */ + iwn_rx_compressed_ba(sc, desc, data); + break; +#endif case IWN_TX_DONE: /* An 802.11 frame has been transmitted. */ sc->sc_hal->tx_done(sc, desc, data); @@ -2830,13 +2880,13 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, BUS_DMA_NOWAIT | BUS_DMA_WRITE); - if (error != 0 && error != EFBIG) { - printf("%s: can't map mbuf (error %d)\n", - sc->sc_dev.dv_xname, error); - m_freem(m); - return error; - } if (error != 0) { + if (error != EFBIG) { + printf("%s: can't map mbuf (error %d)\n", + sc->sc_dev.dv_xname, error); + m_freem(m); + return error; + } /* Too many DMA segments, linearize mbuf. */ MGETHDR(m1, M_DONTWAIT, MT_DATA); if (m1 == NULL) { @@ -3438,6 +3488,7 @@ iwn4965_set_txpower(struct iwn_softc *sc, int async) "EEPROM=%d)\n", tdiff, sc->temp, temp)); for (ridx = 0; ridx <= IWN_RIDX_MAX; ridx++) { + /* Convert dBm to half-dBm. */ maxchpwr = sc->maxpwr[chan] * 2; if ((ridx / 8) & 1) maxchpwr -= 6; /* MIMO 2T: -3dB */ @@ -4565,11 +4616,11 @@ iwn4965_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni, iwn_mem_write_2(sc, sc->sched_base + IWN4965_SCHED_TRANS_TBL(qid), wn->id << 4 | tid); - /* Enable chain mode for the queue. */ + /* Enable chain-building mode for the queue. */ iwn_prph_setbits(sc, IWN4965_SCHED_QCHAIN_SEL, 1 << qid); /* Set starting sequence number from the ADDBA request. */ - IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ssn); + IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | (ssn & 0xff)); iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid), ssn); /* Set scheduler window size. */ @@ -4598,7 +4649,7 @@ iwn4965_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn) IWN4965_TXQ_STATUS_CHGACT); /* Set starting sequence number from the ADDBA request. */ - IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ssn); + IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | (ssn & 0xff)); iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid), ssn); /* Disable interrupts for the queue. */ @@ -4624,14 +4675,14 @@ iwn5000_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni, iwn_mem_write_2(sc, sc->sched_base + IWN5000_SCHED_TRANS_TBL(qid), wn->id << 4 | tid); - /* Enable chain mode for the queue. */ + /* Enable chain-building mode for the queue. */ iwn_prph_setbits(sc, IWN5000_SCHED_QCHAIN_SEL, 1 << qid); /* Enable aggregation for the queue. */ iwn_prph_setbits(sc, IWN5000_SCHED_AGGR_SEL, 1 << qid); /* Set starting sequence number from the ADDBA request. */ - IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ssn); + IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | (ssn & 0xff)); iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid), ssn); /* Set scheduler window size and frame limit. */ @@ -4659,7 +4710,7 @@ iwn5000_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn) iwn_prph_clrbits(sc, IWN5000_SCHED_AGGR_SEL, 1 << qid); /* Set starting sequence number from the ADDBA request. */ - IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ssn); + IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | (ssn & 0xff)); iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid), ssn); /* Disable interrupts for the queue. */ @@ -4727,6 +4778,7 @@ iwn5000_send_wimax_coex(struct iwn_softc *sc) { struct iwn5000_wimax_coex wimax; +#ifdef notyet if (sc->hw_type == IWN_HW_REV_TYPE_6050) { /* Enable WiMAX coexistence for combo adapters. */ wimax.flags = @@ -4736,7 +4788,9 @@ iwn5000_send_wimax_coex(struct iwn_softc *sc) IWN_WIMAX_COEX_ENABLE; memcpy(wimax.events, iwn6050_wimax_events, sizeof iwn6050_wimax_events); - } else { + } else +#endif + { /* Disable WiMAX coexistence. */ wimax.flags = 0; memset(wimax.events, 0, sizeof wimax.events); diff --git a/sys/dev/pci/if_iwnreg.h b/sys/dev/pci/if_iwnreg.h index 38b0417a25f..1bfc4a70155 100644 --- a/sys/dev/pci/if_iwnreg.h +++ b/sys/dev/pci/if_iwnreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwnreg.h,v 1.33 2009/11/03 18:57:18 damien Exp $ */ +/* $OpenBSD: if_iwnreg.h,v 1.34 2009/11/08 11:54:48 damien Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -389,6 +389,7 @@ struct iwn_rx_desc { #define IWN_RX_PHY 192 #define IWN_MPDU_RX_DONE 193 #define IWN_RX_DONE 195 +#define IWN_RX_COMPRESSED_BA 197 uint8_t flags; uint8_t idx; @@ -970,9 +971,9 @@ struct iwn_ucode_info { /* Structures for IWN_TX_DONE notification. */ struct iwn4965_tx_stat { uint8_t nframes; - uint8_t killcnt; - uint8_t rtscnt; - uint8_t retrycnt; + uint8_t btkillcnt; + uint8_t rtsfailcnt; + uint8_t ackfailcnt; uint8_t rate; uint8_t rflags; uint16_t xrflags; @@ -984,9 +985,9 @@ struct iwn4965_tx_stat { struct iwn5000_tx_stat { uint8_t nframes; - uint8_t killcnt; - uint8_t rtscnt; - uint8_t retrycnt; + uint8_t btkillcnt; + uint8_t rtsfailcnt; + uint8_t ackfailcnt; uint8_t rate; uint8_t rflags; uint16_t xrflags; @@ -996,7 +997,9 @@ struct iwn5000_tx_stat { uint32_t info; uint16_t seq; uint16_t len; - uint32_t tlc; + uint8_t tlc; + uint8_t ratid; + uint8_t fc[2]; uint16_t status; uint16_t sequence; } __packed; @@ -1051,6 +1054,18 @@ struct iwn_rx_stat { #define IWN_RSSI_TO_DBM 44 +/* Structure for IWN_RX_COMPRESSED_BA notification. */ +struct iwn_compressed_ba { + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint16_t reserved; + uint8_t id; + uint8_t tid; + uint16_t seq; + uint64_t bitmap; + uint16_t qid; + uint16_t ssn; +} __packed; + /* Structure for IWN_START_SCAN notification. */ struct iwn_start_scan { uint64_t tstamp; @@ -1102,7 +1117,7 @@ struct iwn_spectrum_notif { #define IWN_MEASUREMENT_FAILED 8 } __packed; -/* Structure for IWN_{RX,BEACON}_STATISTICS notification. */ +/* Structures for IWN_{RX,BEACON}_STATISTICS notification. */ struct iwn_rx_phy_stats { uint32_t ina; uint32_t fina; @@ -1292,9 +1307,9 @@ struct iwn_eeprom_chan { } __packed; struct iwn_eeprom_enhinfo { - uint16_t reserved1; + uint16_t chan; int8_t chain[3]; /* max power in half-dBm */ - uint8_t reserved2; + uint8_t reserved; int8_t mimo2; /* max power in half-dBm */ int8_t mimo3; /* max power in half-dBm */ } __packed; diff --git a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs index 7afd0988738..af2cf6887fe 100644 --- a/sys/dev/pci/pcidevs +++ b/sys/dev/pci/pcidevs @@ -1,4 +1,4 @@ -$OpenBSD: pcidevs,v 1.1505 2009/11/04 17:46:52 damien Exp $ +$OpenBSD: pcidevs,v 1.1506 2009/11/08 11:54:48 damien Exp $ /* $NetBSD: pcidevs,v 1.30 1997/06/24 06:20:24 thorpej Exp $ */ /* @@ -2158,9 +2158,7 @@ product INTEL EESISA 0x0008 EES ISA product INTEL 21145 0x0039 21145 product INTEL WIFI_LINK_1000_1 0x0083 WiFi Link 1000 product INTEL WIFI_LINK_1000_2 0x0084 WiFi Link 1000 -product INTEL WIFI_LINK_6050_3X3_1 0x0086 WiFi Link 6050 product INTEL WIFI_LINK_6050_2X2_1 0x0087 WiFi Link 6050 -product INTEL WIFI_LINK_6050_3X3_2 0x0088 WiFi Link 6050 product INTEL WIFI_LINK_6050_2X2_2 0x0089 WiFi Link 6050 product INTEL 80303 0x0309 80303 IOP product INTEL 80312 0x030d 80312 I/O Companion |