From owner-p4-projects Thu Mar 6 17:40:53 2003 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3B59237B405; Thu, 6 Mar 2003 17:40:26 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D93EF37B401 for ; Thu, 6 Mar 2003 17:40:25 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 46DE943FA3 for ; Thu, 6 Mar 2003 17:40:21 -0800 (PST) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h271eL0U086530 for ; Thu, 6 Mar 2003 17:40:21 -0800 (PST) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h271eL89086523 for perforce@freebsd.org; Thu, 6 Mar 2003 17:40:21 -0800 (PST) Date: Thu, 6 Mar 2003 17:40:21 -0800 (PST) Message-Id: <200303070140.h271eL89086523@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler Subject: PERFORCE change 26457 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://perforce.freebsd.org/chv.cgi?CH=26457 Change 26457 by sam@sam_ebb on 2003/03/06 17:39:39 first steps toward integrating a/b/g support: o introduce ieee80211channel instead of using IEEE channel #'s o redo scanning so active scan is done to completion instead of based on a timer (with a/b/g there can be too many channels to scan in 2 seconds) o move capability bits in ic_flags to a new if_caps field and rename values to separate them from flags o add new capabilities for txpower management and software tx retry (more to come) o add rts threshold, tx power controls, fragmentation threshold, and other stuff; mostly for use by drivers o fix contruction of ssid and rate elements in outbound frames o move most media handling to 802.11 code o add new routines for converting between IEEE channel numbers and frequency/flag settings (or ieee80211channel structures) o split ioctl support into separate files to ease portability Affected files ... .. //depot/projects/wlan/sys/dev/wi/if_wi.c#5 edit .. //depot/projects/wlan/sys/dev/wi/if_wivar.h#2 edit .. //depot/projects/wlan/sys/net/if_ieee80211.h#2 edit .. //depot/projects/wlan/sys/net/if_ieee80211ioctl.c#1 add .. //depot/projects/wlan/sys/net/if_ieee80211ioctl.h#1 add .. //depot/projects/wlan/sys/net/if_ieee80211subr.c#3 edit Differences ... ==== //depot/projects/wlan/sys/dev/wi/if_wi.c#5 (text+ko) ==== @@ -120,7 +120,6 @@ static int wi_reset(struct wi_softc *); static void wi_watchdog(struct ifnet *); static int wi_ioctl(struct ifnet *, u_long, caddr_t); -static int wi_media_change(struct ifnet *); static void wi_media_status(struct ifnet *, struct ifmediareq *); static void wi_rx_intr(struct wi_softc *); @@ -241,8 +240,7 @@ struct wi_softc *sc = device_get_softc(dev); struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - int i, nrate, mword, buflen; - u_int8_t r; + int i, nrate, buflen; u_int16_t val; u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE]; static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { @@ -311,35 +309,43 @@ ic->ic_phytype = IEEE80211_T_DS; ic->ic_opmode = IEEE80211_M_STA; - ic->ic_flags = IEEE80211_F_HASPMGT | IEEE80211_F_HASAHDEMO; + ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO; ic->ic_state = IEEE80211_S_INIT; ic->ic_newstate = wi_newstate; - /* Find available channels */ + /* + * Query the card for available channels and setup the + * channel table. We assume these are all 11b channels. + */ buflen = sizeof(val); if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) val = htole16(0x1fff); /* assume 1-11 */ - for (i = 0; i < 16; i++) { - if (isset((u_int8_t*)&val, i)) - setbit(ic->ic_chan_avail, i + 1); + KASSERT(val != 0, ("wi_attach: no available channels listed!")); + + val <<= 1; /* shift for base 1 indices */ + for (i = 1; i < 16; i++) { + if (isset((u_int8_t*)&val, i)) { + ic->ic_channels[i].ic_freq = + ieee80211_ieee2ghz(i, IEEE80211_CHAN_B); + ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B; + } } - KASSERT(ic->ic_chan_avail != 0, - ("wi_attach: no available channels listed!")); /* * Read the default channel from the NIC. This may vary * depending on the country where the NIC was purchased, so * we can't hard-code a default and expect it to work for * everyone. + * + * If no channel is specified, let the 802.11 code select. */ buflen = sizeof(val); - if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) - ic->ic_ibss_chan = le16toh(val); - else { - /* use lowest available channel */ - for (i = 0; i < 16 && !isset(ic->ic_chan_avail, i); i++) - ; - ic->ic_ibss_chan = i; + if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) { + val = le16toh(val); + KASSERT(val < IEEE80211_CHAN_MAX && + ic->ic_channels[val].ic_flags != 0, + ("wi_attach: invalid own channel %u!", val)); + ic->ic_ibss_chan = &ic->ic_channels[val]; } /* @@ -357,7 +363,7 @@ if (sc->sc_sta_firmware_ver >= 60000) sc->sc_flags |= WI_FLAGS_HAS_MOR; if (sc->sc_sta_firmware_ver >= 60006) - ic->ic_flags |= IEEE80211_F_HASIBSS; + ic->ic_caps |= IEEE80211_C_IBSS; sc->sc_ibss_port = htole16(1); break; @@ -368,21 +374,21 @@ if (sc->sc_sta_firmware_ver > 10101) sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST; if (sc->sc_sta_firmware_ver >= 800) - ic->ic_flags |= IEEE80211_F_HASIBSS; + ic->ic_caps |= IEEE80211_C_IBSS; /* * version 0.8.3 and newer are the only ones that are known * to currently work. Earlier versions can be made to work, * at least according to the Linux driver. */ if (sc->sc_sta_firmware_ver >= 803) - ic->ic_flags |= IEEE80211_F_HASHOSTAP; + ic->ic_caps |= IEEE80211_C_HOSTAP; sc->sc_ibss_port = htole16(0); break; case WI_SYMBOL: sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY; if (sc->sc_sta_firmware_ver >= 25000) - ic->ic_flags |= IEEE80211_F_HASIBSS; + ic->ic_caps |= IEEE80211_C_IBSS; sc->sc_ibss_port = htole16(4); break; } @@ -393,7 +399,7 @@ buflen = sizeof(val); if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 && val != htole16(0)) - ic->ic_flags |= IEEE80211_F_HASWEP; + ic->ic_caps |= IEEE80211_C_WEP; /* Find supported rates. */ buflen = sizeof(ratebuf); @@ -415,8 +421,6 @@ sc->sc_dbm_adjust = 100; /* default */ sc->sc_max_datalen = 2304; - sc->sc_rts_thresh = 2347; - sc->sc_frag_thresh = 2346; sc->sc_system_scale = 1; sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN; sc->sc_roaming_mode = 1; @@ -432,39 +436,14 @@ bcopy(WI_DEFAULT_NETNAME, sc->sc_net_name, sizeof(WI_DEFAULT_NETNAME) - 1); - ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status); - if_printf(ifp, "supported rates: "); -#define ADD(s, o) ifmedia_add(&sc->sc_media, \ - IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL) - ADD(IFM_AUTO, 0); - if (ic->ic_flags & IEEE80211_F_HASHOSTAP) - ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP); - if (ic->ic_flags & IEEE80211_F_HASIBSS) - ADD(IFM_AUTO, IFM_IEEE80211_ADHOC); - ADD(IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0); - for (i = 0; i < nrate; i++) { - r = ic->ic_sup_rates[i]; - mword = ieee80211_rate2media(r, IEEE80211_T_DS); - if (mword == 0) - continue; - printf("%s%d%sMbps", (i != 0 ? " " : ""), - (r & IEEE80211_RATE_VAL) / 2, ((r & 0x1) != 0 ? ".5" : "")); - ADD(mword, 0); - if (ic->ic_flags & IEEE80211_F_HASHOSTAP) - ADD(mword, IFM_IEEE80211_HOSTAP); - if (ic->ic_flags & IEEE80211_F_HASIBSS) - ADD(mword, IFM_IEEE80211_ADHOC); - ADD(mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); - } - printf("\n"); - ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); -#undef ADD - /* * Call MI attach routine. */ ieee80211_ifattach(ifp); + /* NB: override default setting */ + ic->ic_media.ifm_status = wi_media_status; + return (0); } @@ -482,9 +461,6 @@ wi_stop(ifp, 0); - /* Delete all remaining media. */ - ifmedia_removeall(&sc->sc_media); - ieee80211_ifdetach(ifp); bus_teardown_intr(dev, sc->irq, sc->wi_intrhand); wi_free(dev); @@ -667,7 +643,8 @@ wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval); wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid, ic->ic_des_esslen); - wi_write_val(sc, WI_RID_OWN_CHNL, ic->ic_ibss_chan); + wi_write_val(sc, WI_RID_OWN_CHNL, + ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen); ifa = ifaddr_byindex(ifp->if_index); @@ -680,9 +657,9 @@ /* not yet common 802.11 configuration */ wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen); - wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh); + wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold); if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) - wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh); + wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold); /* driver specific 802.11 configuration */ if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) @@ -718,7 +695,7 @@ } /* Configure WEP. */ - if (ic->ic_flags & IEEE80211_F_HASWEP) + if (ic->ic_caps & IEEE80211_C_WEP) wi_write_wep(sc); /* Set multicast filter. */ @@ -764,12 +741,13 @@ if (ic->ic_opmode == IEEE80211_M_STA && ((ic->ic_flags & IEEE80211_F_DESBSSID) || - ic->ic_des_chan != IEEE80211_CHAN_ANY)) { + ic->ic_des_chan != (struct ieee80211channel *)IEEE80211_CHAN_ANY)) { memset(&join, 0, sizeof(join)); if (ic->ic_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid); - if (ic->ic_des_chan != IEEE80211_CHAN_ANY) - join.wi_chan = htole16(ic->ic_des_chan); + if (ic->ic_des_chan != (struct ieee80211channel *)IEEE80211_CHAN_ANY) + join.wi_chan = htole16( + ieee80211_chan2ieee(ic, ic->ic_des_chan)); /* Lucent firmware does not support the JOIN RID. */ if (sc->sc_firmware_type != WI_LUCENT) wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join)); @@ -841,8 +819,6 @@ WI_UNLOCK(sc); return; } - KASSERT((ifp->if_flags & IFF_OACTIVE) == 0, - ("wi_start: if_flags %x\n", ifp->if_flags)); memset(&frmhdr, 0, sizeof(frmhdr)); cur = sc->sc_txnext; @@ -1079,10 +1055,6 @@ sc->sc_if_flags = ifp->if_flags; error = 0; break; - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); - break; case SIOCADDMULTI: case SIOCDELMULTI: error = wi_write_multi(sc); @@ -1175,58 +1147,6 @@ return (error); } -static int -wi_media_change(struct ifnet *ifp) -{ - struct wi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifmedia_entry *ime; - enum ieee80211_opmode newmode; - int i, rate, error = 0; - - ime = sc->sc_media.ifm_cur; - if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { - i = -1; - } else { - rate = ieee80211_media2rate(ime->ifm_media, IEEE80211_T_DS); - if (rate == 0) - return EINVAL; - for (i = 0; i < IEEE80211_RATE_SIZE; i++) { - if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate) - break; - } - if (i == IEEE80211_RATE_SIZE) - return EINVAL; - } - if (ic->ic_fixed_rate != i) { - ic->ic_fixed_rate = i; - error = ENETRESET; - } - - if ((ime->ifm_media & IFM_IEEE80211_ADHOC) && - (ime->ifm_media & IFM_FLAG0)) - newmode = IEEE80211_M_AHDEMO; - else if (ime->ifm_media & IFM_IEEE80211_ADHOC) - newmode = IEEE80211_M_IBSS; - else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) - newmode = IEEE80211_M_HOSTAP; - else - newmode = IEEE80211_M_STA; - if (ic->ic_opmode != newmode) { - ic->ic_opmode = newmode; - error = ENETRESET; - } - if (error == ENETRESET) { - if (sc->sc_enabled) - wi_init(ifp->if_softc); /* XXX error code lost */ - error = 0; - } -#if 0 - ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media); -#endif - return error; -} - static void wi_media_status(struct ifnet *ifp, struct ifmediareq *imr) { @@ -1262,7 +1182,7 @@ rate = 22; /* 11Mbps */ } } - imr->ifm_active |= ieee80211_rate2media(rate, IEEE80211_T_DS); + imr->ifm_active |= ieee80211_rate2media(rate, ic->ic_phytype); switch (ic->ic_opmode) { case IEEE80211_M_STA: break; @@ -1769,7 +1689,7 @@ &len); break; } - wreq.wi_val[0] = htole16(sc->sc_frag_thresh); + wreq.wi_val[0] = htole16(ic->ic_fragthreshold); len = sizeof(u_int16_t); break; @@ -1877,7 +1797,7 @@ len = sizeof(u_int16_t); break; case WI_RID_RTS_THRESH: - wreq.wi_val[0] = htole16(sc->sc_rts_thresh); + wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); len = sizeof(u_int16_t); break; case WI_RID_CNFAUTHMODE: @@ -1967,10 +1887,10 @@ } switch (wreq.wi_type) { case WI_RID_FRAG_THRESH: - sc->sc_frag_thresh = le16toh(wreq.wi_val[0]); + ic->ic_fragthreshold = le16toh(wreq.wi_val[0]); break; case WI_RID_RTS_THRESH: - sc->sc_rts_thresh = le16toh(wreq.wi_val[0]); + ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]); break; case WI_RID_MICROWAVE_OVEN: sc->sc_microwave_oven = le16toh(wreq.wi_val[0]); @@ -2504,7 +2424,8 @@ IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid); buflen = sizeof(val); wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen); - ni->ni_chan = le16toh(val); + /* XXX validate channel */ + ni->ni_chan = &ic->ic_channels[le16toh(val)]; if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid)) sc->sc_false_syns++; ==== //depot/projects/wlan/sys/dev/wi/if_wivar.h#2 (text+ko) ==== @@ -94,7 +94,6 @@ void * wi_intrhand; int wi_io_addr; - struct ifmedia sc_media; struct bpf_if *sc_drvbpf; int sc_flags; int sc_if_flags; @@ -106,8 +105,6 @@ u_int16_t sc_dbm_adjust; u_int16_t sc_max_datalen; - u_int16_t sc_frag_thresh; - u_int16_t sc_rts_thresh; u_int16_t sc_system_scale; u_int16_t sc_cnfauthmode; u_int16_t sc_roaming_mode; ==== //depot/projects/wlan/sys/net/if_ieee80211.h#2 (text+ko) ==== @@ -37,11 +37,8 @@ #ifndef _NET_IF_IEEE80211_H_ #define _NET_IF_IEEE80211_H_ -#include -#include +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ -#define IEEE80211_ADDR_LEN ETHER_ADDR_LEN - /* * generic definitions for IEEE 802.11 frames */ @@ -281,125 +278,16 @@ #define IEEE80211_MAX_LEN (2300 + IEEE80211_CRC_LEN + \ (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN)) -/* - * ioctls - */ - -/* nwid is pointed at by ifr.ifr_data */ -struct ieee80211_nwid { - u_int8_t i_len; - u_int8_t i_nwid[IEEE80211_NWID_LEN]; -}; - -#define SIOCS80211NWID _IOWR('i', 230, struct ifreq) -#define SIOCG80211NWID _IOWR('i', 231, struct ifreq) - -/* the first member must be matched with struct ifreq */ -struct ieee80211_nwkey { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - int i_wepon; /* wep enabled flag */ - int i_defkid; /* default encrypt key id */ - struct { - int i_keylen; - u_int8_t *i_keydat; - } i_key[IEEE80211_WEP_NKID]; -}; -#define SIOCS80211NWKEY _IOW('i', 232, struct ieee80211_nwkey) -#define SIOCG80211NWKEY _IOWR('i', 233, struct ieee80211_nwkey) -/* i_wepon */ -#define IEEE80211_NWKEY_OPEN 0 /* No privacy */ -#define IEEE80211_NWKEY_WEP 1 /* WEP enabled */ -#define IEEE80211_NWKEY_EAP 2 /* EAP enabled */ -#define IEEE80211_NWKEY_PERSIST 0x100 /* designate persist keyset */ - -/* power management parameters */ -struct ieee80211_power { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - int i_enabled; /* 1 == on, 0 == off */ - int i_maxsleep; /* max sleep in ms */ -}; -#ifdef __NetBSD__ -#define SIOCS80211POWER _IOW('i', 234, struct ieee80211_power) -#define SIOCG80211POWER _IOWR('i', 235, struct ieee80211_power) -#else -#define SIOCS80211POWER _IOW('i', 242, struct ieee80211_power) -#define SIOCG80211POWER _IOWR('i', 243, struct ieee80211_power) -#endif - -struct ieee80211_auth { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - int i_authtype; -}; +#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */ #define IEEE80211_AUTH_NONE 0 #define IEEE80211_AUTH_OPEN 1 #define IEEE80211_AUTH_SHARED 2 -#define SIOCS80211AUTH _IOW('i', 236, struct ieee80211_auth) -#define SIOCG80211AUTH _IOWR('i', 237, struct ieee80211_auth) - -struct ieee80211_channel { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - u_int16_t i_channel; -}; +#include -#define IEEE80211_CHAN_ANY 0xffff - -#define SIOCS80211CHANNEL _IOW('i', 238, struct ieee80211_channel) -#define SIOCG80211CHANNEL _IOWR('i', 239, struct ieee80211_channel) - -struct ieee80211_bssid { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - u_int8_t i_bssid[IEEE80211_ADDR_LEN]; -}; - -#define SIOCS80211BSSID _IOW('i', 240, struct ieee80211_bssid) -#define SIOCG80211BSSID _IOWR('i', 241, struct ieee80211_bssid) - -/* - * FreeBSD-style ioctls. - */ -/* the first member must be matched with struct ifreq */ -struct ieee80211req { - char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - u_int16_t i_type; /* req type */ - int16_t i_val; /* Index or simple value */ - int16_t i_len; /* Index or simple value */ - void *i_data; /* Extra data */ -}; -#ifdef __FreeBSD__ -#define SIOCS80211 _IOW('i', 234, struct ieee80211req) -#define SIOCG80211 _IOWR('i', 235, struct ieee80211req) -#else -#define SIOCS80211 _IOW('i', 242, struct ieee80211req) -#define SIOCG80211 _IOWR('i', 243, struct ieee80211req) -#endif - -#define IEEE80211_IOC_SSID 1 -#define IEEE80211_IOC_NUMSSIDS 2 -#define IEEE80211_IOC_WEP 3 -#define IEEE80211_WEP_NOSUP -1 -#define IEEE80211_WEP_OFF 0 -#define IEEE80211_WEP_ON 1 -#define IEEE80211_WEP_MIXED 2 -#define IEEE80211_IOC_WEPKEY 4 -#define IEEE80211_IOC_NUMWEPKEYS 5 -#define IEEE80211_IOC_WEPTXKEY 6 -#define IEEE80211_IOC_AUTHMODE 7 -#define IEEE80211_IOC_STATIONNAME 8 -#define IEEE80211_IOC_CHANNEL 9 -#define IEEE80211_IOC_POWERSAVE 10 -#define IEEE80211_POWERSAVE_NOSUP -1 -#define IEEE80211_POWERSAVE_OFF 0 -#define IEEE80211_POWERSAVE_CAM 1 -#define IEEE80211_POWERSAVE_PSP 2 -#define IEEE80211_POWERSAVE_PSP_CAM 3 -#define IEEE80211_POWERSAVE_ON IEEE80211_POWERSAVE_CAM -#define IEEE80211_IOC_POWERSAVESLEEP 11 - #ifdef _KERNEL -#define IEEE80211_ASCAN_WAIT 2 /* active scan wait */ #define IEEE80211_PSCAN_WAIT 5 /* passive scan wait */ #define IEEE80211_TRANS_WAIT 5 /* transition wait */ #define IEEE80211_INACT_WAIT 5 /* inactivity timer interval */ @@ -409,7 +297,7 @@ * Structure for IEEE 802.11 drivers. */ -#define IEEE80211_CHAN_MAX 255 +#define IEEE80211_CHAN_MAX 64 #define IEEE80211_RATE_SIZE 12 #define IEEE80211_KEYBUF_SIZE 16 #define IEEE80211_NODE_HASHSIZE 32 @@ -440,6 +328,41 @@ }; /* + * Channels are specified by frequency and attributes. + */ +/* XXX should be ieee80211_channel but NetBSD took that for an ioctl param */ +struct ieee80211channel { + u_int16_t ic_freq; /* setting in Mhz */ + u_int16_t ic_flags; /* see below */ +}; + +#define IEEE80211_CHAN_PASSIVE 0x0001 /* Only passive scan allowed on channel */ +/* bits 4-7 are for private use by drivers */ +#define IEEE80211_CHAN_PRIV3 0x0010 +#define IEEE80211_CHAN_PRIV2 0x0020 +#define IEEE80211_CHAN_PRIV1 0x0040 +#define IEEE80211_CHAN_PRIV0 0x0080 +/* channel attributes */ +#define IEEE80211_CHAN_TURBO 0x0100 /* Turbo channel */ +#define IEEE80211_CHAN_CCK 0x0200 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x0400 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x0800 /* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_5GHZ 0x1000 /* 5 GHz spectrum channel */ +/* bits 13-15 are reserved for future use and should not be used */ + +/* + * Useful combinations of channel characteristics. + */ +#define IEEE80211_CHAN_A \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_B \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) +#define IEEE80211_CHAN_PUREG \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_T \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) + +/* * Node specific information. */ struct ieee80211_node { @@ -462,7 +385,7 @@ u_int8_t ni_essid[IEEE80211_NWID_LEN]; int ni_nrate; u_int8_t ni_rates[IEEE80211_RATE_SIZE]; - u_int8_t ni_chan; + struct ieee80211channel *ni_chan; u_int16_t ni_fhdwell; /* FH only */ u_int8_t ni_fhindex; /* FH only */ @@ -510,29 +433,39 @@ int (*ic_chancheck)(void *, u_char *); u_int8_t ic_myaddr[IEEE80211_ADDR_LEN]; u_int8_t ic_sup_rates[IEEE80211_RATE_SIZE]; + struct ieee80211channel ic_channels[IEEE80211_CHAN_MAX+1]; u_char ic_chan_avail[roundup(IEEE80211_CHAN_MAX,NBBY)]; u_char ic_chan_active[roundup(IEEE80211_CHAN_MAX, NBBY)]; + u_char ic_chan_scan[roundup(IEEE80211_CHAN_MAX,NBBY)]; struct ifqueue ic_mgtq; - int ic_flags; + u_int32_t ic_flags; /* state flags */ + u_int32_t ic_caps; /* capabilities */ enum ieee80211_phytype ic_phytype; - enum ieee80211_opmode ic_opmode; - enum ieee80211_state ic_state; + enum ieee80211_opmode ic_opmode; /* operation mode */ + enum ieee80211_state ic_state; /* 802.11 state */ + struct ifmedia ic_media; /* interface media config */ struct bpf_if *ic_rawbpf; /* packet filter structure */ struct ieee80211_node ic_bss; /* information for this node */ int ic_node_privlen;/* size for ni_private */ void (*ic_node_free)(struct ieee80211com *, struct ieee80211_node *); /* callback */ - u_int8_t ic_ibss_chan; + struct ieee80211channel *ic_ibss_chan; int ic_fixed_rate; /* index to ic_sup_rates[] */ + u_int16_t ic_rtsthreshold; + u_int16_t ic_fragthreshold; TAILQ_HEAD(, ieee80211_node) ic_node; /* information of all nodes */ LIST_HEAD(, ieee80211_node) ic_hash[IEEE80211_NODE_HASHSIZE]; u_int16_t ic_lintval; /* listen interval */ + u_int16_t ic_holdover; /* PM hold over duration */ + u_int16_t ic_txmin; /* min tx retry count */ + u_int16_t ic_txmax; /* max tx retry count */ + u_int16_t ic_txlifetime; /* tx lifetime */ + u_int16_t ic_txpower; /* tx power setting (dbM) */ int ic_mgt_timer; /* mgmt timeout */ - int ic_scan_timer; /* scant wait */ int ic_inact_timer; /* inactivity timer wait */ int ic_des_esslen; u_int8_t ic_des_essid[IEEE80211_NWID_LEN]; - int ic_des_chan; /* desired channel */ + struct ieee80211channel *ic_des_chan; /* desired channel */ u_int8_t ic_des_bssid[IEEE80211_ADDR_LEN]; struct ieee80211_wepkey ic_nw_keys[IEEE80211_WEP_NKID]; int ic_wep_txkey; /* default tx key index */ @@ -560,7 +493,8 @@ #define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0) #define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN) -#define IEEE80211_IS_MULTICAST(a) ETHER_IS_MULTICAST(a) +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) /* ic_flags */ #define IEEE80211_F_ASCAN 0x00000001 /* STATUS: active scan */ @@ -570,11 +504,21 @@ #define IEEE80211_F_PMGTON 0x00000400 /* CONF: Power mgmt enable */ #define IEEE80211_F_DESBSSID 0x00000800 /* CONF: des_bssid is set */ #define IEEE80211_F_SCANAP 0x00001000 /* CONF: Scanning AP */ -#define IEEE80211_F_HASWEP 0x00010000 /* CAPABILITY: WEP available */ -#define IEEE80211_F_HASIBSS 0x00020000 /* CAPABILITY: IBSS available */ -#define IEEE80211_F_HASPMGT 0x00040000 /* CAPABILITY: Power mgmt */ -#define IEEE80211_F_HASHOSTAP 0x00080000 /* CAPABILITY: HOSTAP avail */ -#define IEEE80211_F_HASAHDEMO 0x00100000 /* CAPABILITY: Old Adhoc Demo */ +#define IEEE80211_F_ROAMING 0x00002000 /* CONF: roaming enabled */ +#define IEEE80211_F_SWRETRY 0x00004000 /* CONF: sw tx retry enabled */ +#define IEEE80211_F_TXPMGT 0x00018000 /* STATUS: tx power */ +#define IEEE80211_F_TXPOW_OFF 0x00000000 /* TX Power: radio disabled */ +#define IEEE80211_F_TXPOW_FIXED 0x00008000 /* TX Power: fixed rate */ +#define IEEE80211_F_TXPOW_AUTO 0x00010000 /* TX Power: undefined */ + +/* ic_capabilities */ +#define IEEE80211_C_WEP 0x00000001 /* CAPABILITY: WEP available */ +#define IEEE80211_C_IBSS 0x00000002 /* CAPABILITY: IBSS available */ +#define IEEE80211_C_PMGT 0x00000004 /* CAPABILITY: Power mgmt */ +#define IEEE80211_C_HOSTAP 0x00000008 /* CAPABILITY: HOSTAP avail */ +#define IEEE80211_C_AHDEMO 0x00000010 /* CAPABILITY: Old Adhoc Demo */ +#define IEEE80211_C_SWRETRY 0x00000020 /* CAPABILITY: sw tx retry */ +#define IEEE80211_C_TXPMGT 0x00000040 /* CAPABILITY: tx power mgmt */ /* flags for ieee80211_fix_rate() */ #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */ @@ -589,7 +533,10 @@ struct mbuf *, int); struct mbuf *ieee80211_encap(struct ifnet *, struct mbuf *); struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *); +void ieee80211_media_status(struct ifnet *, struct ifmediareq *); int ieee80211_ioctl(struct ifnet *, u_long, caddr_t); +int ieee80211_cfgget(struct ifnet *, u_long, caddr_t); +int ieee80211_cfgset(struct ifnet *, u_long, caddr_t); void ieee80211_print_essid(u_int8_t *, int); void ieee80211_dump_pkt(u_int8_t *, int, int, int); void ieee80211_watchdog(struct ifnet *); @@ -605,9 +552,9 @@ struct mbuf *ieee80211_wep_crypt(struct ifnet *, struct mbuf *, int); int ieee80211_rate2media(int, enum ieee80211_phytype); int ieee80211_media2rate(int, enum ieee80211_phytype); - -int ieee80211_cfgget(struct ifnet *, u_long, caddr_t); -int ieee80211_cfgset(struct ifnet *, u_long, caddr_t); +u_int ieee80211_ghz2ieee(u_int, u_int); +u_int ieee80211_chan2ieee(struct ieee80211com *, struct ieee80211channel *); +u_int ieee80211_ieee2ghz(u_int, u_int); #endif /* _KERNEL */ ==== //depot/projects/wlan/sys/net/if_ieee80211subr.c#3 (text+ko) ==== @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -80,8 +81,6 @@ #include #endif -#include - #define IEEE80211_DEBUG #ifdef IEEE80211_DEBUG int ieee80211_debug = 0; @@ -137,6 +136,8 @@ static void ieee80211_recv_deauth(struct ieee80211com *, struct mbuf *, int, u_int32_t); +static int ieee80211_media_change(struct ifnet *); + static void ieee80211_crc_init(void); static u_int32_t ieee80211_crc_update(u_int32_t, u_int8_t *, int); @@ -151,7 +152,8 @@ ieee80211_ifattach(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; - int i, rate; + struct ifmediareq imr; + int i, rate, mword; /* XXX need unit */ mtx_init(&ic->ic_mtx, ifp->if_name, "802.11 link layer", MTX_DEF); @@ -161,22 +163,93 @@ bpfattach2(ifp, DLT_IEEE802_11, sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf); #endif + + /* + * Setup crypto support. + */ ieee80211_crc_init(); ic->ic_iv = arc4random(); + + /* + * Fill in 802.11 available channel set, mark + * all available channels as active, and pick + * a default channel if not already specified. + */ + memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); + for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { + struct ieee80211channel *c = &ic->ic_channels[i]; + if (c->ic_flags) { + /* + * Verify driver passed us valid data. + */ + if (i != ieee80211_chan2ieee(ic, c)) { + if_printf(ifp, "bad channel ignored; " + "freq %u flags %x number %u\n", + c->ic_freq, c->ic_flags, i); + continue; + } + setbit(ic->ic_chan_avail, i); + } + } memcpy(ic->ic_chan_active, ic->ic_chan_avail, sizeof(ic->ic_chan_active)); - if (isclr(ic->ic_chan_active, ic->ic_ibss_chan)) { + if (ic->ic_ibss_chan == NULL) { + /* + * Pick the first active channel for default. + * XXX probably not right. + */ for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { if (isset(ic->ic_chan_active, i)) { - ic->ic_ibss_chan = i; + ic->ic_ibss_chan = &ic->ic_channels[i]; break; } } } - ic->ic_des_chan = IEEE80211_CHAN_ANY; - ic->ic_fixed_rate = -1; + + /* + * Fill in media characteristics. + */ +#define ADD(_ic, _s, _o) \ + ifmedia_add(&(_ic)->ic_media, \ + IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL) + ifmedia_init(&ic->ic_media, 0, + ieee80211_media_change, ieee80211_media_status); + ADD(ic, IFM_AUTO, 0); + if (ic->ic_caps & IEEE80211_C_IBSS) + ADD(ic, IFM_AUTO, IFM_IEEE80211_ADHOC); + if (ic->ic_caps & IEEE80211_C_HOSTAP) + ADD(ic, IFM_AUTO, IFM_IEEE80211_HOSTAP); + if (ic->ic_caps & IEEE80211_C_AHDEMO) + ADD(ic, IFM_AUTO, IFM_IEEE80211_ADHOC | IFM_FLAG0); + if_printf(ifp, "supported rates: "); + for (i = 0; i < IEEE80211_RATE_SIZE; i++) { + rate = ic->ic_sup_rates[i]; + mword = ieee80211_rate2media(rate, ic->ic_phytype); + if (mword == 0) + continue; + printf("%s%d%sMbps", (i != 0 ? " " : ""), + (rate & IEEE80211_RATE_VAL) / 2, + ((rate & 0x1) != 0 ? ".5" : "")); + ADD(ic, mword, 0); + if (ic->ic_caps & IEEE80211_C_IBSS) + ADD(ic, mword, IFM_IEEE80211_ADHOC); + if (ic->ic_caps & IEEE80211_C_HOSTAP) + ADD(ic, mword, IFM_IEEE80211_HOSTAP); + if (ic->ic_caps & IEEE80211_C_AHDEMO) + ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); + } + printf("\n"); + ieee80211_media_status(ifp, &imr); + ifmedia_set(&ic->ic_media, imr.ifm_active); +#undef ADD + + ic->ic_rtsthreshold = 2347; /* XXX not used yet */ + ic->ic_fragthreshold = 2346; /* XXX not used yet */ + ic->ic_des_chan = /* any channel is ok */ + (struct ieee80211channel *) IEEE80211_CHAN_ANY; + ic->ic_fixed_rate = -1; /* no fixed rate */ if (ic->ic_lintval == 0) - ic->ic_lintval = 100; /* default sleep */ + ic->ic_lintval = 100; /* default sleep */ TAILQ_INIT(&ic->ic_node); mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_name, "mgmt send q", MTX_DEF); @@ -189,7 +262,7 @@ ifp->if_baudrate = IF_Mbps(rate); ifp->if_hdrlen = sizeof(struct ieee80211_frame); - /* initialize management frame handler */ + /* initialize management frame handlers */ ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_PROBE_RESP >> IEEE80211_FC0_SUBTYPE_SHIFT] = ieee80211_recv_beacon; ic->ic_recv_mgmt[IEEE80211_FC0_SUBTYPE_BEACON @@ -244,6 +317,7 @@ ic->ic_wep_ctx = NULL; } ieee80211_free_allnodes(ic); + ifmedia_removeall(&ic->ic_media); #if NBPFILTER > 0 bpfdetach(ifp); #endif @@ -252,6 +326,208 @@ mtx_destroy(&ic->ic_mtx); } +/* + * Convert GHz frequency to IEEE channel number. + */ +u_int +ieee80211_ghz2ieee(u_int freq, u_int flags) +{ + if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ + if (freq == 2484) + return 14; + if (freq < 2484) + return (freq - 2407) / 5; + else + return 15 + ((freq - 2512) / 20); + } else if (IEEE80211_CHAN_5GHZ) {/* 5Ghz band */ + return (freq - 5000) / 5; + } else { /* either, guess */ + if (freq == 2484) + return 14; + if (freq < 2484) + return (freq - 2407) / 5; + if (freq < 5000) + return 15 + ((freq - 2512) / 20); + return (freq - 5000) / 5; + } +} + +/* + * Convert channel to IEEE channel number. + */ +u_int +ieee80211_chan2ieee(struct ieee80211com *ic, struct ieee80211channel *c) +{ + if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX]) + return c - ic->ic_channels; + else if (c == (struct ieee80211channel *)IEEE80211_CHAN_ANY) + return IEEE80211_CHAN_ANY; + else { + if_printf(&ic->ic_if, "invalid channel %p\n", c); + return 0; /* XXX */ + } +} + +/* + * Convert IEEE channel number to GHz frequency. + */ +u_int +ieee80211_ieee2ghz(u_int chan, u_int flags) +{ + if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ + if (chan == 14) + return 2484; + if (chan < 14) + return 2407 + chan*5; + else + return 2512 + ((chan-15)*20); + } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */ + return 5000 + (chan*5); + } else { /* either, guess */ + if (chan == 14) + return 2484; + if (chan < 14) /* 0-13 */ + return 2407 + chan*5; + if (chan < 27) /* 15-26 */ + return 2512 + ((chan-15)*20); + return 5000 + (chan*5); + } +} + +static int +ieee80211_media_change(struct ifnet *ifp) +{ + struct ieee80211com *ic = (void *)ifp; + struct ifmedia_entry *ime; + enum ieee80211_opmode newmode; + int i, rate, error = 0; + + ime = ic->ic_media.ifm_cur; + if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { + /* phytype is not right */ + rate = ieee80211_media2rate(ime->ifm_media, ic->ic_phytype); + if (rate == 0) + return EINVAL; + for (i = 0; i < IEEE80211_RATE_SIZE; i++) + if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate) + break; + if (i == IEEE80211_RATE_SIZE) + return EINVAL; + } else { + i = -1; + } + if (ic->ic_fixed_rate != i) { + ic->ic_fixed_rate = i; + error = ENETRESET; + } + if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) == + (IFM_IEEE80211_ADHOC|IFM_FLAG0)) + newmode = IEEE80211_M_AHDEMO; + else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) + newmode = IEEE80211_M_HOSTAP; + else if (ime->ifm_media & IFM_IEEE80211_ADHOC) + newmode = IEEE80211_M_IBSS; + else + newmode = IEEE80211_M_STA; + if (ic->ic_opmode != newmode) { + ic->ic_opmode = newmode; + switch (newmode) { + case IEEE80211_M_AHDEMO: + case IEEE80211_M_HOSTAP: + case IEEE80211_M_STA: + ic->ic_flags &= ~IEEE80211_F_IBSSON; + break; + case IEEE80211_M_IBSS: + ic->ic_flags |= IEEE80211_F_IBSSON; + break; + } + error = ENETRESET; + } + if (error == ENETRESET) { + (*ifp->if_init)(ifp); /* lose error */ + error = 0; >>> TRUNCATED FOR MAIL (1000 lines) <<< To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message