Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/if_ndis/if_ndis.c
Show First 20 Lines • Show All 717 Lines • ▼ Show 20 Lines | fail: | ||||
DPRINTF(("attach done.\n")); | DPRINTF(("attach done.\n")); | ||||
/* We're done talking to the NIC for now; halt it. */ | /* We're done talking to the NIC for now; halt it. */ | ||||
ndis_halt_nic(sc); | ndis_halt_nic(sc); | ||||
DPRINTF(("halting done.\n")); | DPRINTF(("halting done.\n")); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | |||||
ndis_init_ratesets(struct ndis_softc *sc) | |||||
{ | |||||
#define SETRATE(rs, mode, rv) \ | |||||
do { \ | |||||
uint16_t idx; \ | |||||
\ | |||||
idx = ieee80211_convert_from_legacy_rate(rv, mode); \ | |||||
if (idx != IEEE80211_RATE_NONEXISTENT) { \ | |||||
setbit(rs->rs_bitmap, (rv)); \ | |||||
rs->rates[rs->rs_nrates].rs_index = (idx); \ | |||||
rs->rs_nrates++; \ | |||||
} \ | |||||
} while (0) | |||||
struct ieee80211com *ic = &sc->ndis_ic; | |||||
struct ieee80211_rateset *rs_11a, *rs_11b, *rs_11g; | |||||
ndis_80211_rates_ex rates; | |||||
const struct { | |||||
enum ieee80211_phymode mode; | |||||
struct ieee80211_rateset *rs; | |||||
uint16_t rates[4]; | |||||
int nrates; | |||||
} rates_to_rateset[3] = { | |||||
{ | |||||
.mode = IEEE80211_MODE_11A, | |||||
.rs = &sc->ndis_supp_rates[0], | |||||
.rates = { | |||||
IEEE80211_RATE_INDEX_OFDM24, | |||||
IEEE80211_RATE_INDEX_OFDM36, | |||||
IEEE80211_RATE_INDEX_OFDM48, | |||||
IEEE80211_RATE_INDEX_OFDM54 | |||||
}, | |||||
.nrates = 4 | |||||
}, | |||||
{ | |||||
.mode = IEEE80211_MODE_11B, | |||||
.rs = &sc->ndis_supp_rates[1], | |||||
.rates = { | |||||
IEEE80211_RATE_INDEX_CCK1, | |||||
IEEE80211_RATE_INDEX_CCK2, | |||||
IEEE80211_RATE_INDEX_CCK5, | |||||
IEEE80211_RATE_INDEX_CCK11 | |||||
}, | |||||
.nrates = 4 | |||||
}, | |||||
{ | |||||
.mode = IEEE80211_MODE_11G, | |||||
.rs = &sc->ndis_supp_rates[2], | |||||
.rates = { | |||||
IEEE80211_RATE_INDEX_OFDM24, | |||||
IEEE80211_RATE_INDEX_OFDM36, | |||||
IEEE80211_RATE_INDEX_OFDM48, | |||||
IEEE80211_RATE_INDEX_OFDM54 | |||||
}, | |||||
.nrates = 4 | |||||
}, | |||||
}; | |||||
int i, j, len, r; | |||||
rs_11a = &sc->ndis_supp_rates[0]; | |||||
rs_11b = &sc->ndis_supp_rates[1]; | |||||
rs_11g = &sc->ndis_supp_rates[2]; | |||||
len = sizeof(rates); | |||||
bzero((char *)&rates, len); | |||||
r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); | |||||
if (r != 0) | |||||
device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); | |||||
/* | |||||
* Since the supported rates only up to 8 can be supported, | |||||
* if this is not 802.11b we're just going to be faking it | |||||
* all up to heck. | |||||
*/ | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) | |||||
rs_11a->rs_nrates = 0; | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) | |||||
rs_11b->rs_nrates = 0; | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) | |||||
rs_11g->rs_nrates = 0; | |||||
for (i = 0; i < len; i++) { | |||||
switch (rates[i] & IEEE80211_RATE_VAL) { | |||||
case 2: | |||||
case 4: | |||||
case 11: | |||||
case 10: | |||||
case 22: | |||||
if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { | |||||
/* Lazy-init 802.11b. */ | |||||
setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | |||||
rs_11b->rs_nrates = 0; | |||||
} | |||||
SETRATE(rs_11b, IEEE80211_MODE_11B, rates[i]); | |||||
break; | |||||
default: | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) | |||||
SETRATE(rs_11a, IEEE80211_MODE_11A, rates[i]); | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) | |||||
SETRATE(rs_11g, IEEE80211_MODE_11G, rates[i]); | |||||
break; | |||||
} | |||||
} | |||||
/* | |||||
* If the hardware supports 802.11g, it most | |||||
* likely supports 802.11b and all of the | |||||
* 802.11b and 802.11g speeds, so maybe we can | |||||
* just cheat here. Just how in the heck do | |||||
* we detect turbo modes, though? | |||||
*/ | |||||
for (i = 0; i < nitems(rates_to_rateset); i++) { | |||||
struct ieee80211_rateset *rs; | |||||
const uint16_t *supp_rates; | |||||
int is_basic; | |||||
if (isclr(ic->ic_modecaps, rates_to_rateset[i].mode)) | |||||
continue; | |||||
rs = rates_to_rateset[i].rs; | |||||
supp_rates = rates_to_rateset[i].rates; | |||||
is_basic = (rates_to_rateset[i].mode == IEEE80211_MODE_11B); | |||||
for (j = 0; j < rates_to_rateset[i].nrates; j++) { | |||||
uint8_t rv; | |||||
rv = ieee80211_convert_to_legacy_rate(supp_rates[j]); | |||||
if (isset(rs->rs_bitmap, rv)) | |||||
continue; | |||||
setbit(rs->rs_bitmap, rv); | |||||
rs->rates[rs->rs_nrates].rs_index = supp_rates[j]; | |||||
rs->rates[rs->rs_nrates].rs_basic = is_basic; | |||||
rs->rs_nrates++; | |||||
} | |||||
} | |||||
ic->ic_sup_rates[IEEE80211_MODE_11A] = rs_11a; | |||||
ic->ic_sup_rates[IEEE80211_MODE_11B] = rs_11b; | |||||
ic->ic_sup_rates[IEEE80211_MODE_11G] = rs_11g; | |||||
#undef SETRATE | |||||
} | |||||
static int | static int | ||||
ndis_80211attach(struct ndis_softc *sc) | ndis_80211attach(struct ndis_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->ndis_ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
ndis_80211_rates_ex rates; | |||||
struct ndis_80211_nettype_list *ntl; | struct ndis_80211_nettype_list *ntl; | ||||
uint32_t arg; | uint32_t arg; | ||||
int mode, i, r, len, nonettypes = 1; | int mode, i, r, len, nonettypes = 1; | ||||
uint8_t bands[IEEE80211_MODE_BYTES] = { 0 }; | uint8_t bands[IEEE80211_MODE_BYTES] = { 0 }; | ||||
callout_init(&sc->ndis_scan_callout, 1); | callout_init(&sc->ndis_scan_callout, 1); | ||||
ic->ic_softc = sc; | ic->ic_softc = sc; | ||||
Show All 27 Lines | ndis_80211attach(struct ndis_softc *sc) | ||||
} | } | ||||
free(ntl, M_DEVBUF); | free(ntl, M_DEVBUF); | ||||
nonettypes: | nonettypes: | ||||
/* Default to 11b channels if the card did not supply any */ | /* Default to 11b channels if the card did not supply any */ | ||||
if (nonettypes) { | if (nonettypes) { | ||||
setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | ||||
setbit(bands, IEEE80211_MODE_11B); | setbit(bands, IEEE80211_MODE_11B); | ||||
} | } | ||||
len = sizeof(rates); | |||||
bzero((char *)&rates, len); | |||||
r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); | |||||
if (r != 0) | |||||
device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); | |||||
/* | |||||
* Since the supported rates only up to 8 can be supported, | |||||
* if this is not 802.11b we're just going to be faking it | |||||
* all up to heck. | |||||
*/ | |||||
#define TESTSETRATE(x, y) \ | |||||
do { \ | |||||
int i; \ | |||||
for (i = 0; i < ic->ic_sup_rates[x].rs_nrates; i++) { \ | |||||
if (ic->ic_sup_rates[x].rs_rates[i] == (y)) \ | |||||
break; \ | |||||
} \ | |||||
if (i == ic->ic_sup_rates[x].rs_nrates) { \ | |||||
ic->ic_sup_rates[x].rs_rates[i] = (y); \ | |||||
ic->ic_sup_rates[x].rs_nrates++; \ | |||||
} \ | |||||
} while (0) | |||||
#define SETRATE(x, y) \ | |||||
ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y) | |||||
#define INCRATE(x) \ | |||||
ic->ic_sup_rates[x].rs_nrates++ | |||||
ic->ic_curmode = IEEE80211_MODE_AUTO; | ic->ic_curmode = IEEE80211_MODE_AUTO; | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) | ndis_init_ratesets(sc); | ||||
ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) | |||||
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) | |||||
ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; | |||||
for (i = 0; i < len; i++) { | |||||
switch (rates[i] & IEEE80211_RATE_VAL) { | |||||
case 2: | |||||
case 4: | |||||
case 11: | |||||
case 10: | |||||
case 22: | |||||
if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { | |||||
/* Lazy-init 802.11b. */ | |||||
setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | |||||
ic->ic_sup_rates[IEEE80211_MODE_11B]. | |||||
rs_nrates = 0; | |||||
} | |||||
SETRATE(IEEE80211_MODE_11B, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11B); | |||||
break; | |||||
default: | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | |||||
SETRATE(IEEE80211_MODE_11A, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11A); | |||||
} | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | |||||
SETRATE(IEEE80211_MODE_11G, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11G); | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
/* | |||||
* If the hardware supports 802.11g, it most | |||||
* likely supports 802.11b and all of the | |||||
* 802.11b and 802.11g speeds, so maybe we can | |||||
* just cheat here. Just how in the heck do | |||||
* we detect turbo modes, though? | |||||
*/ | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { | |||||
TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); | |||||
TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); | |||||
TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); | |||||
TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); | |||||
} | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | |||||
TESTSETRATE(IEEE80211_MODE_11G, 48); | |||||
TESTSETRATE(IEEE80211_MODE_11G, 72); | |||||
TESTSETRATE(IEEE80211_MODE_11G, 96); | |||||
TESTSETRATE(IEEE80211_MODE_11G, 108); | |||||
} | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | |||||
TESTSETRATE(IEEE80211_MODE_11A, 48); | |||||
TESTSETRATE(IEEE80211_MODE_11A, 72); | |||||
TESTSETRATE(IEEE80211_MODE_11A, 96); | |||||
TESTSETRATE(IEEE80211_MODE_11A, 108); | |||||
} | |||||
#undef SETRATE | |||||
#undef INCRATE | |||||
#undef TESTSETRATE | |||||
ieee80211_init_channels(ic, NULL, bands); | ieee80211_init_channels(ic, NULL, bands); | ||||
/* | /* | ||||
* To test for WPA support, we need to see if we can | * To test for WPA support, we need to see if we can | ||||
* set AUTHENTICATION_MODE to WPA and read it back | * set AUTHENTICATION_MODE to WPA and read it back | ||||
* successfully. | * successfully. | ||||
*/ | */ | ||||
i = sizeof(arg); | i = sizeof(arg); | ||||
▲ Show 20 Lines • Show All 1,473 Lines • ▼ Show 20 Lines | ndis_set_wpa(sc, ie, ielen) | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) | ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) | ||||
{ | { | ||||
struct ieee80211vap *vap = ifp->if_softc; | struct ieee80211vap *vap = ifp->if_softc; | ||||
struct ndis_softc *sc = vap->iv_ic->ic_softc; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ndis_softc *sc = ic->ic_softc; | |||||
enum ieee80211_phymode mode; | |||||
uint32_t txrate; | uint32_t txrate; | ||||
uint16_t rate_idx; | |||||
int len; | int len; | ||||
if (!NDIS_INITIALIZED(sc)) | if (!NDIS_INITIALIZED(sc)) | ||||
return; | return; | ||||
len = sizeof(txrate); | len = sizeof(txrate); | ||||
if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0) | if (ndis_get_info(sc, OID_GEN_LINK_SPEED, &txrate, &len) == 0) { | ||||
vap->iv_bss->ni_txrate = txrate / 5000; | mode = ieee80211_chan2mode(ic->ic_curchan); | ||||
txrate /= 5000; | |||||
rate_idx = ieee80211_convert_from_legacy_rate(txrate, mode); | |||||
if (rate_idx != IEEE80211_RATE_NONEXISTENT) | |||||
vap->iv_bss->ni_txrate = rate_idx; | |||||
else { | |||||
device_printf(sc->ndis_dev, | |||||
"rate %u for mode %u was not found\n", | |||||
txrate, mode); | |||||
} | |||||
} | |||||
ieee80211_media_status(ifp, imr); | ieee80211_media_status(ifp, imr); | ||||
} | } | ||||
static void | static void | ||||
ndis_setstate_80211(struct ndis_softc *sc) | ndis_setstate_80211(struct ndis_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->ndis_ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
▲ Show 20 Lines • Show All 1,051 Lines • Show Last 20 Lines |