1/*- 2 * Copyright (c) 2007-2009 3 * Damien Bergamini <damien.bergamini@free.fr> 4 * Copyright (c) 2008 5 * Benjamin Close <benjsc@FreeBSD.org> 6 * Copyright (c) 2008 Sam Leffler, Errno Consulting 7 * 8 * Permission to use, copy, modify, and distribute this software for any --- 10 unchanged lines hidden (view full) --- 19 */ 20 21/* 22 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network 23 * adapters. 24 */ 25 26#include <sys/cdefs.h> |
27__FBSDID("$FreeBSD: head/sys/dev/iwn/if_iwn.c 252727 2013-07-04 21:16:49Z adrian $"); |
28 29#include "opt_wlan.h" 30 31#include <sys/param.h> 32#include <sys/sockio.h> 33#include <sys/sysctl.h> 34#include <sys/mbuf.h> 35#include <sys/kernel.h> --- 294 unchanged lines hidden (view full) --- 330 IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */ 331 IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */ 332 IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ 333 IWN_DEBUG_INTR = 0x00000100, /* ISR */ 334 IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */ 335 IWN_DEBUG_NODE = 0x00000400, /* node management */ 336 IWN_DEBUG_LED = 0x00000800, /* led management */ 337 IWN_DEBUG_CMD = 0x00001000, /* cmd submission */ |
338 IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */ 339 IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ |
340 IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ 341 IWN_DEBUG_ANY = 0xffffffff 342}; 343 344#define DPRINTF(sc, m, fmt, ...) do { \ 345 if (sc->sc_debug & (m)) \ 346 printf(fmt, __VA_ARGS__); \ 347} while (0) --- 1747 unchanged lines hidden (view full) --- 2095 case 2: return 10; 2096 case 4: return 20; 2097 case 11: return 55; 2098 case 22: return 110; 2099 } 2100 return 0; 2101} 2102 |
2103/* 2104 * Calculate the required PLCP value from the given rate, 2105 * to the given node. 2106 * 2107 * This will take the node configuration (eg 11n, rate table 2108 * setup, etc) into consideration. 2109 */ 2110static uint32_t 2111iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni, 2112 uint8_t rate) |
2113{ 2114#define RV(v) ((v) & IEEE80211_RATE_VAL) 2115 struct ieee80211com *ic = ni->ni_ic; |
2116 uint8_t txant1, txant2; |
2117 uint32_t plcp = 0; 2118 int ridx; |
2119 2120 /* Use the first valid TX antenna. */ 2121 txant1 = IWN_LSB(sc->txchainmask); 2122 txant2 = IWN_LSB(sc->txchainmask & ~txant1); 2123 |
2124 /* 2125 * If it's an MCS rate, let's set the plcp correctly 2126 * and set the relevant flags based on the node config. 2127 */ |
2128 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { |
2129 /* 2130 * Set the initial PLCP value to be between 0->31 for 2131 * MCS 0 -> MCS 31, then set the "I'm an MCS rate!" 2132 * flag. 2133 */ 2134 plcp = RV(rate) | IWN_RFLAG_MCS; 2135 2136 /* 2137 * XXX the following should only occur if both 2138 * the local configuration _and_ the remote node 2139 * advertise these capabilities. Thus this code 2140 * may need fixing! 2141 */ 2142 2143 /* 2144 * Set the channel width and guard interval. 2145 */ 2146 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { 2147 plcp |= IWN_RFLAG_HT40; 2148 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) |
2149 plcp |= IWN_RFLAG_SGI; |
2150 } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) { 2151 plcp |= IWN_RFLAG_SGI; |
2152 } |
2153 2154 /* 2155 * If it's a two stream rate, enable TX on both 2156 * antennas. 2157 * 2158 * XXX three stream rates? 2159 */ 2160 if (rate > 0x87) 2161 plcp |= IWN_RFLAG_ANT(txant1 | txant2); 2162 else |
2163 plcp |= IWN_RFLAG_ANT(txant1); |
2164 } else { 2165 /* 2166 * Set the initial PLCP - fine for both 2167 * OFDM and CCK rates. 2168 */ 2169 plcp = rate2plcp(rate); 2170 2171 /* Set CCK flag if it's CCK */ 2172 2173 /* XXX It would be nice to have a method 2174 * to map the ridx -> phy table entry 2175 * so we could just query that, rather than 2176 * this hack to check against IWN_RIDX_OFDM6. 2177 */ 2178 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 2179 rate & IEEE80211_RATE_VAL); 2180 if (ridx < IWN_RIDX_OFDM6 && 2181 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 2182 plcp |= IWN_RFLAG_CCK; 2183 2184 /* Set antenna configuration */ 2185 plcp |= IWN_RFLAG_ANT(txant1); |
2186 } |
2187 2188 DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n", 2189 __func__, 2190 rate, 2191 plcp); 2192 2193 return (htole32(plcp)); |
2194#undef RV 2195} 2196 |
2197static void 2198iwn_newassoc(struct ieee80211_node *ni, int isnew) 2199{ 2200 /* Doesn't do anything at the moment */ 2201} 2202 |
2203static int 2204iwn_media_change(struct ifnet *ifp) 2205{ 2206 int error; 2207 2208 error = ieee80211_media_change(ifp); 2209 /* NB: only the fixed rate can change and that doesn't need a reset */ 2210 return (error == ENETRESET ? 0 : error); --- 1237 unchanged lines hidden (view full) --- 3448 rate = tp->mcastrate; 3449 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 3450 rate = tp->ucastrate; 3451 else { 3452 /* XXX pass pktlen */ 3453 (void) ieee80211_ratectl_rate(ni, NULL, 0); 3454 rate = ni->ni_txrate; 3455 } |
3456 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 3457 rate & IEEE80211_RATE_VAL); |
3458 3459 /* Encrypt the frame if need be. */ 3460 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3461 /* Retrieve key for TX. */ 3462 k = ieee80211_crypto_encap(ni, m); 3463 if (k == NULL) { 3464 m_freem(m); 3465 return ENOBUFS; --- 89 unchanged lines hidden (view full) --- 3555 } else 3556 pad = 0; 3557 3558 tx->len = htole16(totlen); 3559 tx->tid = tid; 3560 tx->rts_ntries = 60; 3561 tx->data_ntries = 15; 3562 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); |
3563 tx->rate = iwn_rate_to_plcp(sc, ni, rate); |
3564 if (tx->id == sc->broadcast_id) { 3565 /* Group or management frame. */ 3566 tx->linkq = 0; 3567 /* XXX Alternate between antenna A and B? */ 3568 txant = IWN_LSB(sc->txchainmask); 3569 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); 3570 } else { 3571 tx->linkq = ni->ni_rates.rs_nrates - ridx - 1; --- 114 unchanged lines hidden (view full) --- 3686 ac = params->ibp_pri & 3; 3687 3688 ring = &sc->txq[ac]; 3689 desc = &ring->desc[ring->cur]; 3690 data = &ring->data[ring->cur]; 3691 3692 /* Choose a TX rate index. */ 3693 rate = params->ibp_rate0; |
3694 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 3695 rate & IEEE80211_RATE_VAL); |
3696 if (ridx == (uint8_t)-1) { 3697 /* XXX fall back to mcast/mgmt rate? */ 3698 m_freem(m); 3699 return EINVAL; 3700 } 3701 3702 totlen = m->m_pkthdr.len; 3703 --- 59 unchanged lines hidden (view full) --- 3763 } 3764 3765 tx->len = htole16(totlen); 3766 tx->tid = 0; 3767 tx->id = sc->broadcast_id; 3768 tx->rts_ntries = params->ibp_try1; 3769 tx->data_ntries = params->ibp_try0; 3770 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); |
3771 3772 /* XXX should just use iwn_rate_to_plcp() */ |
3773 tx->rate = htole32(rate2plcp(rate)); 3774 if (ridx < IWN_RIDX_OFDM6 && 3775 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 3776 tx->rate |= htole32(IWN_RFLAG_CCK); |
3777 |
3778 /* Group or management frame. */ 3779 tx->linkq = 0; 3780 txant = IWN_LSB(sc->txchainmask); 3781 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); |
3782 |
3783 /* Set physical address of "scratch area". */ 3784 tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); 3785 tx->hiaddr = IWN_HIADDR(data->scratch_paddr); 3786 3787 /* Copy 802.11 header in TX command. */ 3788 memcpy((uint8_t *)(tx + 1), wh, hdrlen); 3789 3790 /* Trim 802.11 header. */ --- 339 unchanged lines hidden (view full) --- 4130 linkq.ampdu_limit = htole16(4000); /* 4ms */ 4131 4132 /* Start at highest available bit-rate. */ 4133 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4134 txrate = ni->ni_htrates.rs_nrates - 1; 4135 else 4136 txrate = rs->rs_nrates - 1; 4137 for (i = 0; i < IWN_MAX_TX_RETRIES; i++) { |
4138 uint32_t plcp; 4139 |
4140 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4141 rate = IEEE80211_RATE_MCS | txrate; 4142 else 4143 rate = RV(rs->rs_rates[txrate]); |
4144 |
4145 /* Do rate -> PLCP config mapping */ 4146 plcp = iwn_rate_to_plcp(sc, ni, rate); 4147 linkq.retry[i] = plcp; 4148 4149 /* Special case for dual-stream rates? */ 4150 if ((le32toh(plcp) & IWN_RFLAG_MCS) && 4151 RV(le32toh(plcp)) > 7) |
4152 linkq.mimo = i + 1; 4153 4154 /* Next retry at immediate lower bit-rate. */ 4155 if (txrate > 0) 4156 txrate--; 4157 } 4158 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, 1); 4159#undef RV --- 839 unchanged lines hidden (view full) --- 4999iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async) 5000{ 5001 struct iwn_pmgt_cmd cmd; 5002 const struct iwn_pmgt *pmgt; 5003 uint32_t max, skip_dtim; 5004 uint32_t reg; 5005 int i; 5006 |
5007 DPRINTF(sc, IWN_DEBUG_PWRSAVE, 5008 "%s: dtim=%d, level=%d, async=%d\n", 5009 __func__, 5010 dtim, 5011 level, 5012 async); 5013 |
5014 /* Select which PS parameters to use. */ 5015 if (dtim <= 2) 5016 pmgt = &iwn_pmgt[0][level]; 5017 else if (dtim <= 10) 5018 pmgt = &iwn_pmgt[1][level]; 5019 else 5020 pmgt = &iwn_pmgt[2][level]; 5021 --- 2153 unchanged lines hidden --- |