aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/wi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/wi')
-rw-r--r--sys/dev/wi/if_wi.c370
-rw-r--r--sys/dev/wi/if_wivar.h10
2 files changed, 280 insertions, 100 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index ebe35d260add..aeb8a4e4c0e2 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -118,7 +118,7 @@ static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
struct mbuf *m0);
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static int wi_reset(struct wi_softc *);
+static int wi_reset(struct ifnet *);
static void wi_watchdog(void *);
static int wi_ioctl(struct ifnet *, u_long, caddr_t);
static int wi_media_change(struct ifnet *);
@@ -164,6 +164,14 @@ static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
const void *, int);
static int wi_symbol_set_hcr(struct wi_softc *, int);
+static void wi_scan_start(struct ieee80211com *);
+static void wi_scan_end(struct ieee80211com *);
+static void wi_set_channel(struct ieee80211com *);
+static void wi_update_slot(struct ifnet *);
+static struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
+static int wi_ioctl_get(struct ifnet *ifp, u_long command, caddr_t data);
+static int wi_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data);
+
static __inline int
wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
{
@@ -253,6 +261,7 @@ wi_attach(device_t dev)
int error;
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
+ ifp->if_softc = sc;
if (ifp == NULL) {
device_printf(dev, "can not if_alloc\n");
wi_free(dev);
@@ -279,7 +288,7 @@ wi_attach(device_t dev)
sc->sc_firmware_type = WI_NOTYPE;
sc->wi_cmd_count = 500;
/* Reset the NIC. */
- if (wi_reset(sc) != 0)
+ if (wi_reset(ifp) != 0)
return ENXIO; /* XXX */
/*
@@ -308,7 +317,6 @@ wi_attach(device_t dev)
/* Read NIC identification */
wi_read_nicid(sc);
- ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = wi_ioctl;
@@ -338,11 +346,14 @@ wi_attach(device_t dev)
val <<= 1; /* shift for base 1 indices */
for (i = 1; i < 16; i++) {
+ struct ieee80211_channel *c;
+
if (!isset((u_int8_t*)&val, i))
continue;
- ic->ic_channels[i].ic_freq =
- ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
- ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
+ c = &ic->ic_channels[ic->ic_nchans++];
+ c->ic_freq = ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
+ c->ic_flags = IEEE80211_CHAN_B;
+ c->ic_ieee = i;
}
/*
@@ -356,14 +367,14 @@ wi_attach(device_t dev)
buflen = sizeof(val);
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];
+ ic->ic_bsschan = ieee80211_find_channel(ic,
+ ieee80211_ieee2mhz(val, IEEE80211_CHAN_B),
+ IEEE80211_MODE_AUTO);
+ /* XXX check return value */
} else {
device_printf(dev,
"WI_RID_OWN_CHNL failed, using first channel!\n");
- ic->ic_ibss_chan = &ic->ic_channels[0];
+ ic->ic_bsschan = &ic->ic_channels[0];
}
/*
@@ -469,7 +480,7 @@ wi_attach(device_t dev)
sc->sc_system_scale = 1;
sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
sc->sc_roaming_mode = 1;
-
+ sc->wi_channel = IEEE80211_CHAN_ANYC;
sc->sc_portnum = WI_DEFAULT_PORT;
sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
@@ -491,6 +502,14 @@ wi_attach(device_t dev)
ic->ic_crypto.cs_key_alloc = wi_key_alloc;
ic->ic_newstate = wi_newstate;
ic->ic_raw_xmit = wi_raw_xmit;
+
+ ic->ic_scan_start = wi_scan_start;
+ ic->ic_scan_end = wi_scan_end;
+ ic->ic_set_channel = wi_set_channel;
+ ic->ic_node_alloc = wi_node_alloc;
+ ic->ic_updateslot = wi_update_slot;
+ ic->ic_reset = wi_reset;
+
ieee80211_media_init(ic, wi_media_change, wi_media_status);
#if NBPFILTER > 0
@@ -650,19 +669,20 @@ wi_init(void *arg)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct wi_joinreq join;
+ struct ieee80211_channel *chan;
int i;
int error = 0, wasenabled;
- WI_LOCK(sc);
- if (sc->wi_gone) {
- WI_UNLOCK(sc);
+
+ if (sc->wi_gone)
return;
- }
if ((wasenabled = sc->sc_enabled))
wi_stop(ifp, 1);
- wi_reset(sc);
+
+ WI_LOCK(sc);
+ wi_reset(ifp);
/* common 802.11 configuration */
ic->ic_flags &= ~IEEE80211_F_IBSSON;
@@ -684,9 +704,9 @@ wi_init(void *arg)
* HostAP mode the controller will lock up otherwise.
*/
if (sc->sc_firmware_type == WI_INTERSIL &&
- ic->ic_des_esslen == 0) {
- ic->ic_des_essid[0] = ' ';
- ic->ic_des_esslen = 1;
+ ic->ic_des_ssid[0].len == 0) {
+ ic->ic_des_ssid[0].ssid[0] = ' ';
+ ic->ic_des_ssid[0].len = 1;
}
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
break;
@@ -703,20 +723,24 @@ wi_init(void *arg)
wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
break;
+ case IEEE80211_M_WDS:
+ /* XXXX */
+ break;
}
/* Intersil interprets this RID as joining ESS even in IBSS mode */
if (sc->sc_firmware_type == WI_LUCENT &&
- (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
+ (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_ssid[0].len > 0)
wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
else
wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
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_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_ssid[0].ssid,
+ ic->ic_des_ssid[0].len);
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);
+ ieee80211_chan2ieee(ic, ic->ic_bsschan));
+ wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_ssid[0].ssid,
+ ic->ic_des_ssid[0].len);
IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
@@ -803,9 +827,11 @@ wi_init(void *arg)
if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
ic->ic_opmode == IEEE80211_M_IBSS ||
ic->ic_opmode == IEEE80211_M_MONITOR ||
- ic->ic_opmode == IEEE80211_M_HOSTAP)
- ieee80211_create_ibss(ic, ic->ic_ibss_chan);
-
+ ic->ic_opmode == IEEE80211_M_HOSTAP) {
+ chan = (sc->wi_channel == IEEE80211_CHAN_ANYC) ?
+ ic->ic_curchan : sc->wi_channel;
+ ieee80211_create_ibss(ic, chan);
+ }
/* Enable interrupts */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
@@ -851,11 +877,10 @@ wi_stop(struct ifnet *ifp, int disable)
struct wi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
- WI_LOCK(sc);
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
DELAY(100000);
-
- ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ WI_LOCK(sc);
if (sc->sc_enabled && !sc->wi_gone) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
@@ -973,8 +998,7 @@ wi_start_locked(struct ifnet *ifp)
k = ieee80211_crypto_encap(ic, ni, m0);
if (k == NULL) {
- if (ni != NULL)
- ieee80211_free_node(ni);
+ ieee80211_free_node(ni);
m_freem(m0);
continue;
}
@@ -994,8 +1018,7 @@ wi_start_locked(struct ifnet *ifp)
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
if (IFF_DUMPPKTS(ifp))
wi_dump_pkt(&frmhdr, NULL, -1);
- if (ni != NULL)
- ieee80211_free_node(ni);
+ ieee80211_free_node(ni);
if (wi_start_tx(ifp, &frmhdr, m0))
continue;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
@@ -1131,9 +1154,9 @@ out:
}
static int
-wi_reset(struct wi_softc *sc)
+wi_reset(struct ifnet *ifp)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct wi_softc *sc = ifp->if_softc;
#define WI_INIT_TRIES 3
int i;
int error = 0;
@@ -1196,7 +1219,6 @@ wi_watchdog(void *arg)
}
/* TODO: rate control */
- ieee80211_watchdog(&sc->sc_ic);
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
}
@@ -1207,8 +1229,6 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct wi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
struct ifreq *ifr = (struct ifreq *)data;
- struct ieee80211req *ireq;
- u_int8_t nodename[IEEE80211_NWID_LEN];
int error = 0;
struct thread *td = curthread;
struct wi_req wreq;
@@ -1289,47 +1309,102 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
WI_UNLOCK(sc);
break;
case SIOCG80211:
- ireq = (struct ieee80211req *) data;
- if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
- ireq->i_len = sc->sc_nodelen + 1;
- error = copyout(sc->sc_nodename, ireq->i_data,
- ireq->i_len);
+ error = wi_ioctl_get(ifp, cmd, data);
+ break;
+ case SIOCS80211:
+ error = priv_check(td, PRIV_NET80211_MANAGE);
+ if (error)
+ break;
+ error = wi_ioctl_set(ifp, cmd, data);
+
+
break;
+ default:
+ error = ieee80211_ioctl(ic, cmd, data);
+ WI_LOCK(sc);
+ if (error == ENETRESET) {
+ if (sc->sc_enabled)
+ wi_init(sc); /* XXX no error return */
+ error = 0;
}
- goto ioctl_common;
- case SIOCS80211:
- ireq = (struct ieee80211req *) data;
- if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
- error = priv_check(td, PRIV_NET80211_MANAGE);
- if (error)
- break;
- if (ireq->i_val != 0 ||
- ireq->i_len > IEEE80211_NWID_LEN) {
- error = EINVAL;
- break;
- }
- memset(nodename, 0, IEEE80211_NWID_LEN);
- error = copyin(ireq->i_data, nodename, ireq->i_len);
- if (error)
- break;
- WI_LOCK(sc);
- if (sc->sc_enabled) {
- error = wi_write_ssid(sc, WI_RID_NODENAME,
- nodename, ireq->i_len);
- }
- if (error == 0) {
- memcpy(sc->sc_nodename, nodename,
- IEEE80211_NWID_LEN);
- sc->sc_nodelen = ireq->i_len;
- }
- WI_UNLOCK(sc);
+ WI_UNLOCK(sc);
+ break;
+ }
+ return (error);
+}
+
+static int
+wi_ioctl_get(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ int error;
+ struct wi_softc *sc;
+ struct ieee80211req *ireq;
+ struct ieee80211com *ic;
+
+
+ sc = ifp->if_softc;
+ ic = &sc->sc_ic;
+ ireq = (struct ieee80211req *) data;
+
+ switch (ireq->i_type) {
+ case IEEE80211_IOC_STATIONNAME:
+ ireq->i_len = sc->sc_nodelen + 1;
+ error = copyout(sc->sc_nodename, ireq->i_data,
+ ireq->i_len);
+ break;
+ default:
+ error = ieee80211_ioctl(ic, cmd, data);
+ WI_LOCK(sc);
+ if (error == ENETRESET) {
+ if (sc->sc_enabled)
+ wi_init(sc); /* XXX no error return */
+ error = 0;
+ }
+ WI_UNLOCK(sc);
+
+ break;
+ }
+
+ return (error);
+}
+
+static int
+wi_ioctl_set(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ int error;
+ struct wi_softc *sc;
+ struct ieee80211req *ireq;
+ u_int8_t nodename[IEEE80211_NWID_LEN];
+
+ sc = ifp->if_softc;
+ ireq = (struct ieee80211req *) data;
+ switch (ireq->i_type) {
+ case IEEE80211_IOC_STATIONNAME:
+ if (ireq->i_val != 0 ||
+ ireq->i_len > IEEE80211_NWID_LEN) {
+ error = EINVAL;
break;
}
- goto ioctl_common;
+ memset(nodename, 0, IEEE80211_NWID_LEN);
+ error = copyin(ireq->i_data, nodename, ireq->i_len);
+ if (error)
+ break;
+ WI_LOCK(sc);
+ if (sc->sc_enabled) {
+ error = wi_write_ssid(sc, WI_RID_NODENAME,
+ nodename, ireq->i_len);
+ }
+ if (error == 0) {
+ memcpy(sc->sc_nodename, nodename,
+ IEEE80211_NWID_LEN);
+ sc->sc_nodelen = ireq->i_len;
+ }
+ WI_UNLOCK(sc);
+
+ break;
default:
- ioctl_common:
+ error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
WI_LOCK(sc);
- error = ieee80211_ioctl(ic, cmd, data);
if (error == ENETRESET) {
if (sc->sc_enabled)
wi_init(sc); /* XXX no error return */
@@ -1338,9 +1413,21 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
WI_UNLOCK(sc);
break;
}
+
return (error);
}
+static struct ieee80211_node *
+wi_node_alloc(struct ieee80211_node_table *nt)
+{
+ struct wi_node *rn;
+
+ rn = malloc(sizeof (struct wi_node), M_80211_NODE,
+ M_NOWAIT | M_ZERO);
+
+ return (rn != NULL) ? &rn->ni : NULL;
+}
+
static int
wi_media_change(struct ifnet *ifp)
{
@@ -1413,6 +1500,9 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
case IEEE80211_M_MONITOR:
imr->ifm_active |= IFM_IEEE80211_MONITOR;
break;
+ case IEEE80211_M_WDS:
+ /* XXXX */
+ break;
}
}
@@ -1439,6 +1529,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
return;
sc->sc_false_syns = MAX(0, sc->sc_false_syns - 1);
+#if 0
/*
* XXX hack; we should create a new node with the new bssid
* and replace the existing ic_bss with it but since we don't
@@ -1447,6 +1538,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
* called and it will overwrite the node state.
*/
ieee80211_sta_join(ic, ieee80211_ref_node(ni));
+#endif
}
static void
@@ -1666,7 +1758,7 @@ wi_rx_intr(struct wi_softc *sc)
/*
* Send frame up for processing.
*/
- ieee80211_input(ic, m, ni, rssi, rstamp);
+ ieee80211_input(ic, m, ni, rssi, -95/*XXXXwi_rx_silence?*/, rstamp);
/*
* The frame may have caused the node to be marked for
* reclamation (e.g. in response to a DEAUTH message)
@@ -1826,8 +1918,9 @@ wi_info_intr(struct wi_softc *sc)
case WI_INFO_SCAN_RESULTS:
case WI_INFO_HOST_SCAN_RESULTS:
wi_scan_result(sc, fid, le16toh(ltbuf[0]));
+ ieee80211_notify_scan_done(ic);
break;
-
+
default:
DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
le16toh(ltbuf[1]), le16toh(ltbuf[0])));
@@ -1992,7 +2085,7 @@ wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
case WI_RID_TX_CRYPT_KEY:
case WI_RID_DEFLT_CRYPT_KEYS:
case WI_RID_TX_RATE:
- return ieee80211_cfgget(ic, cmd, data);
+ return ieee80211_ioctl(ic, cmd, data);
case WI_RID_MICROWAVE_OVEN:
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
@@ -2046,7 +2139,7 @@ wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
case WI_RID_READ_APS:
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
- return ieee80211_cfgget(ic, cmd, data);
+ return ieee80211_ioctl(ic, cmd, data);
if (sc->sc_scan_timer > 0) {
error = EINPROGRESS;
break;
@@ -2083,11 +2176,11 @@ wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case WI_RID_READ_CACHE:
- return ieee80211_cfgget(ic, cmd, data);
+ return ieee80211_ioctl(ic, cmd, data);
case WI_RID_SCAN_RES: /* compatibility interface */
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
- return ieee80211_cfgget(ic, cmd, data);
+ return ieee80211_ioctl(ic, cmd, data);
if (sc->sc_scan_timer > 0) {
error = EINPROGRESS;
break;
@@ -2169,7 +2262,7 @@ wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->sc_nodelen);
break;
default:
- return ieee80211_cfgget(ic, cmd, data);
+ return ieee80211_ioctl(ic, cmd, data);
}
break;
}
@@ -2289,7 +2382,7 @@ wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
WI_UNLOCK(sc);
return EINVAL;
}
- ic->ic_fixed_rate = i;
+ ic->ic_fixed_rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
}
if (sc->sc_enabled)
error = wi_write_txrate(sc);
@@ -2347,9 +2440,10 @@ wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
WI_LOCK(sc);
- memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
- ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
- memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
+ memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
+ ic->ic_des_ssid[0].len = le16toh(wreq.wi_val[0]) * 2;
+ memcpy(ic->ic_des_ssid[0].ssid, &wreq.wi_val[1],
+ ic->ic_des_ssid[0].len);
if (sc->sc_enabled)
wi_init(sc); /* XXX no error return */
WI_UNLOCK(sc);
@@ -2361,8 +2455,8 @@ wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
len);
if (error == 0) {
- /* XXX ieee80211_cfgset does a copyin */
- error = ieee80211_cfgset(ic, cmd, data);
+ /* XXX ieee80211_ioctl does a copyin */
+ error = ieee80211_ioctl(ic, cmd, data);
if (error == ENETRESET) {
if (sc->sc_enabled)
wi_init(sc);
@@ -2385,8 +2479,7 @@ wi_write_txrate(struct wi_softc *sc)
if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
rate = 0; /* auto */
else
- rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] &
- IEEE80211_RATE_VAL) / 2;
+ rate = ic->ic_fixed_rate / 2;
/* rate: 0, 1, 2, 5, 11 */
@@ -2868,8 +2961,7 @@ wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
/* XXX validate channel */
ni->ni_chan = &ic->ic_channels[le16toh(val)];
- ic->ic_curchan = ni->ni_chan;
- ic->ic_ibss_chan = ni->ni_chan;
+ ic->ic_curchan = ic->ic_bsschan = ni->ni_chan;
#if NBPFILTER > 0
sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
htole16(ni->ni_chan->ic_freq);
@@ -2944,6 +3036,16 @@ wi_scan_result(struct wi_softc *sc, int fid, int cnt)
struct wi_scan_header ws_hdr; /* Prism2 header */
struct wi_scan_data_p2 ws_dat; /* Prism2 scantable*/
struct wi_apinfo *ap;
+ struct ieee80211_scanparams sp;
+ struct ieee80211_frame wh;
+ static long rstamp;
+ struct ieee80211com *ic;
+ uint8_t ssid[2+IEEE80211_NWID_LEN];
+
+ printf("wi_scan_result\n");
+ ic = &sc->sc_ic;
+ rstamp++;
+ memset(&sp, 0, sizeof(sp));
off = sizeof(u_int16_t) * 2;
memset(&ws_hdr, 0, sizeof(ws_hdr));
@@ -2973,25 +3075,45 @@ wi_scan_result(struct wi_softc *sc, int fid, int cnt)
/* Read Data */
ap = sc->sc_aps;
memset(&ws_dat, 0, sizeof(ws_dat));
+
for (i = 0; i < naps; i++, ap++) {
+ uint8_t rates[2];
+ uint16_t *bssid;
wi_read_bap(sc, fid, off, &ws_dat,
(sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
ether_sprintf(ws_dat.wi_bssid)));
+
off += szbuf;
- ap->scanreason = le16toh(ws_hdr.wi_reason);
+ ap->scanreason = le16toh(ws_hdr.wi_reason);
memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
- ap->channel = le16toh(ws_dat.wi_chid);
+
+ bssid = (uint16_t *)&ap->bssid;
+ if (bssid[0] == 0 && bssid[1] == 0 && bssid[2] == 0)
+ break;
+
+ memcpy(wh.i_addr2, ws_dat.wi_bssid, sizeof(ap->bssid));
+ memcpy(wh.i_addr3, ws_dat.wi_bssid, sizeof(ap->bssid));
+ sp.chan = ap->channel = le16toh(ws_dat.wi_chid);
ap->signal = le16toh(ws_dat.wi_signal);
ap->noise = le16toh(ws_dat.wi_noise);
ap->quality = ap->signal - ap->noise;
- ap->capinfo = le16toh(ws_dat.wi_capinfo);
- ap->interval = le16toh(ws_dat.wi_interval);
- ap->rate = le16toh(ws_dat.wi_rate);
+ sp.capinfo = ap->capinfo = le16toh(ws_dat.wi_capinfo);
+ sp.bintval = ap->interval = le16toh(ws_dat.wi_interval);
+ ap->rate = le16toh(ws_dat.wi_rate);
+ rates[1] = 1;
+ rates[2] = (uint8_t)ap->rate;
ap->namelen = le16toh(ws_dat.wi_namelen);
if (ap->namelen > sizeof(ap->name))
ap->namelen = sizeof(ap->name);
memcpy(ap->name, ws_dat.wi_name, ap->namelen);
+ sp.ssid = (uint8_t *)&ssid[0];
+ memcpy(sp.ssid + 2, ap->name, ap->namelen);
+ sp.ssid[1] = ap->namelen;
+ sp.rates = &rates[0];
+ sp.tstamp = (uint8_t *)&rstamp;
+ printf("calling add_scan \n");
+ ieee80211_add_scan(ic, &sp, &wh, 0, ap->signal, ap->noise, rstamp);
}
done:
/* Done scanning */
@@ -3003,8 +3125,11 @@ done:
static void
wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
{
- ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
- ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi);
+ if (ni != NULL)
+ ieee80211_dump_pkt(ni->ni_ic,
+ (u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
+ ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL,
+ rssi);
printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
@@ -3364,3 +3489,50 @@ wi_symbol_set_hcr(struct wi_softc *sc, int mode)
tsleep(sc, PWAIT, "wiinit", 1);
return 0;
}
+
+/*
+ * This function can be called by ieee80211_set_shortslottime(). Refer to
+ * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
+ */
+static void
+wi_update_slot(struct ifnet *ifp)
+{
+ DPRINTF(("wi update slot unimplemented\n"));
+}
+
+static void
+wi_set_channel(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
+
+ WI_LOCK(sc);
+ if (!(sc->sc_flags & WI_FLAGS_SCANNING)) {
+ sc->wi_channel = ic->ic_curchan;
+ }
+ WI_UNLOCK(sc);
+}
+
+static void
+wi_scan_start(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
+
+ WI_LOCK(sc);
+ sc->sc_flags |= WI_FLAGS_SCANNING;
+ wi_scan_ap(sc, 0x3fff, 0x000f);
+ WI_UNLOCK(sc);
+
+}
+
+static void
+wi_scan_end(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct wi_softc *sc = ifp->if_softc;
+
+ WI_LOCK(sc);
+ sc->sc_flags &= ~WI_FLAGS_SCANNING;
+ WI_UNLOCK(sc);
+}
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index f7159afa8e87..88238a346534 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -100,6 +100,7 @@ struct wi_softc {
bus_space_handle_t wi_bmemhandle;
bus_space_tag_t wi_bmemtag;
void * wi_intrhand;
+ struct ieee80211_channel *wi_channel;
int wi_io_addr;
int wi_cmd_count;
@@ -108,7 +109,7 @@ struct wi_softc {
int sc_if_flags;
int sc_bap_id;
int sc_bap_off;
-
+
u_int16_t sc_procframe;
u_int16_t sc_portnum;
@@ -201,6 +202,13 @@ struct wi_softc {
#define WI_FLAGS_BUG_AUTOINC 0x0100
#define WI_FLAGS_HAS_FRAGTHR 0x0200
#define WI_FLAGS_HAS_DBMADJUST 0x0400
+#define WI_FLAGS_SCANNING 0x0800
+
+
+/* driver-specific node state */
+struct wi_node {
+ struct ieee80211_node ni; /* base class */
+};
struct wi_card_ident {
u_int16_t card_id;