"Association Faild" was added to "Link Stat" messages.
; Implement wi_scan into wi.c. forces if_wi to initiate one round of access point scan. This code was written by jrb@cs.pdx.edu, modified and bug-fixed by ichiro@netbsd.org
This commit is contained in:
parent
0d1261454e
commit
e08ec84292
142
sys/dev/ic/wi.c
142
sys/dev/ic/wi.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wi.c,v 1.34 2002/01/20 07:26:14 ichiro Exp $ */
|
||||
/* $NetBSD: wi.c,v 1.35 2002/01/21 11:28:18 ichiro Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
|
@ -70,7 +70,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.34 2002/01/20 07:26:14 ichiro Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.35 2002/01/21 11:28:18 ichiro Exp $");
|
||||
|
||||
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
|
||||
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
|
||||
|
@ -125,6 +125,7 @@ static int wi_write_data __P((struct wi_softc *, int,
|
|||
static int wi_seek __P((struct wi_softc *, int, int, int));
|
||||
static int wi_alloc_nicmem __P((struct wi_softc *, int, int *));
|
||||
static void wi_inquire __P((void *));
|
||||
static void wi_wait_scan __P((void *));
|
||||
static int wi_setdef __P((struct wi_softc *, struct wi_req *));
|
||||
static int wi_getdef __P((struct wi_softc *, struct wi_req *));
|
||||
static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int));
|
||||
|
@ -160,6 +161,7 @@ wi_attach(sc)
|
|||
s = splnet();
|
||||
|
||||
callout_init(&sc->wi_inquire_ch);
|
||||
callout_init(&sc->wi_scan_sh);
|
||||
|
||||
/* Make sure interrupts are disabled. */
|
||||
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
||||
|
@ -237,6 +239,11 @@ wi_attach(sc)
|
|||
|
||||
memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
|
||||
|
||||
/* AP info was filled with 0 */
|
||||
memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps));
|
||||
sc->wi_scanning=0;
|
||||
sc->wi_naps=0;
|
||||
|
||||
/*
|
||||
* Find out if we support WEP on this card.
|
||||
*/
|
||||
|
@ -429,14 +436,43 @@ void wi_inquire(xsc)
|
|||
wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
|
||||
}
|
||||
|
||||
void wi_wait_scan(xsc)
|
||||
void *xsc;
|
||||
{
|
||||
struct wi_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
sc = xsc;
|
||||
ifp = &sc->sc_ethercom.ec_if;
|
||||
|
||||
/* If not scanning, ignore */
|
||||
if (!sc->wi_scanning)
|
||||
return;
|
||||
|
||||
/* Wait for to make INQUIRE */
|
||||
if (ifp->if_flags & IFF_OACTIVE) {
|
||||
callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* try INQUIRE */
|
||||
if (wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS) == ETIMEDOUT) {
|
||||
callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void wi_update_stats(sc)
|
||||
struct wi_softc *sc;
|
||||
{
|
||||
struct wi_ltv_gen gen;
|
||||
struct wi_scan_header ap2_header; /* Prism2 header */
|
||||
struct wi_scan_data_p2 ap2; /* Prism2 scantable*/
|
||||
struct wi_scan_data ap; /* Lucent scantable */
|
||||
u_int16_t id;
|
||||
struct ifnet *ifp;
|
||||
u_int32_t *ptr;
|
||||
int len, i;
|
||||
int len, naps, i, j;
|
||||
u_int16_t t;
|
||||
|
||||
ifp = &sc->sc_ethercom.ec_if;
|
||||
|
@ -446,6 +482,64 @@ void wi_update_stats(sc)
|
|||
wi_read_data(sc, id, 0, (char *)&gen, 4);
|
||||
|
||||
switch (gen.wi_type) {
|
||||
case WI_INFO_SCAN_RESULTS:
|
||||
if (gen.wi_len < 3)
|
||||
break;
|
||||
if (sc->sc_prism2) { /* Prism2 chip */
|
||||
naps = 2 * (gen.wi_len - 3) / sizeof(ap2);
|
||||
naps = naps > MAXAPINFO ? MAXAPINFO : naps;
|
||||
sc->wi_naps = naps;
|
||||
/* Read Header */
|
||||
for(j=0; j < sizeof(ap2_header) / 2; j++)
|
||||
((u_int16_t *)&ap2_header)[j] =
|
||||
CSR_READ_2(sc, WI_DATA1);
|
||||
/* Read Data */
|
||||
for (i=0; i < naps; i++) {
|
||||
for(j=0; j < sizeof(ap2) / 2; j++)
|
||||
((u_int16_t *)&ap2)[j] =
|
||||
CSR_READ_2(sc, WI_DATA1);
|
||||
sc->wi_aps[i].scanreason = ap2_header.wi_reason;
|
||||
memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6);
|
||||
sc->wi_aps[i].channel = ap2.wi_chid;
|
||||
sc->wi_aps[i].signal = ap2.wi_signal;
|
||||
sc->wi_aps[i].noise = ap2.wi_noise;
|
||||
sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise;
|
||||
sc->wi_aps[i].capinfo = ap2.wi_capinfo;
|
||||
sc->wi_aps[i].interval = ap2.wi_interval;
|
||||
sc->wi_aps[i].rate = ap2.wi_rate;
|
||||
if (ap2.wi_namelen > 32)
|
||||
ap2.wi_namelen = 32;
|
||||
sc->wi_aps[i].namelen = ap2.wi_namelen;
|
||||
memcpy(sc->wi_aps[i].name, ap2.wi_name,
|
||||
ap2.wi_namelen);
|
||||
}
|
||||
} else { /* Lucent chip */
|
||||
naps = 2 * gen.wi_len / sizeof(ap);
|
||||
naps = naps > MAXAPINFO ? MAXAPINFO : naps;
|
||||
sc->wi_naps = naps;
|
||||
/* Read Data*/
|
||||
for (i=0; i < naps; i++) {
|
||||
for(j=0; j < sizeof(ap) / 2; j++)
|
||||
((u_int16_t *)&ap)[j] =
|
||||
CSR_READ_2(sc, WI_DATA1);
|
||||
memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6);
|
||||
sc->wi_aps[i].channel = ap.wi_chid;
|
||||
sc->wi_aps[i].signal = ap.wi_signal;
|
||||
sc->wi_aps[i].noise = ap.wi_noise;
|
||||
sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise;
|
||||
sc->wi_aps[i].capinfo = ap.wi_capinfo;
|
||||
sc->wi_aps[i].interval = ap.wi_interval;
|
||||
if (ap.wi_namelen > 32)
|
||||
ap.wi_namelen = 32;
|
||||
sc->wi_aps[i].namelen = ap.wi_namelen;
|
||||
memcpy(sc->wi_aps[i].name, ap.wi_name,
|
||||
ap.wi_namelen);
|
||||
}
|
||||
}
|
||||
/* Done scanning */
|
||||
sc->wi_scanning = 0;
|
||||
break;
|
||||
|
||||
case WI_INFO_COUNTERS:
|
||||
/* some card versions have a larger stats structure */
|
||||
len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
|
||||
|
@ -472,7 +566,8 @@ void wi_update_stats(sc)
|
|||
"disconnected",
|
||||
"AP change",
|
||||
"AP out of range",
|
||||
"AP in range"
|
||||
"AP in range",
|
||||
"Association Faild"
|
||||
};
|
||||
|
||||
if (gen.wi_len != 2) {
|
||||
|
@ -482,7 +577,7 @@ void wi_update_stats(sc)
|
|||
break;
|
||||
}
|
||||
t = CSR_READ_2(sc, WI_DATA1);
|
||||
if ((t < 1) || (t > 5)) {
|
||||
if ((t < 1) || (t > 6)) {
|
||||
#ifdef WI_DEBUG
|
||||
printf("WI_INFO_LINK_STAT: status %d\n", t);
|
||||
#endif
|
||||
|
@ -1209,6 +1304,7 @@ wi_ioctl(ifp, command, data)
|
|||
caddr_t data;
|
||||
{
|
||||
int s, error = 0;
|
||||
int len;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
struct wi_req wreq;
|
||||
struct ifreq *ifr;
|
||||
|
@ -1281,10 +1377,24 @@ wi_ioctl(ifp, command, data)
|
|||
if (error)
|
||||
break;
|
||||
if (wreq.wi_type == WI_RID_IFACE_STATS) {
|
||||
wi_update_stats(sc);
|
||||
/* XXX native byte order */
|
||||
memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
|
||||
sizeof(sc->wi_stats));
|
||||
wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
|
||||
} else if (wreq.wi_type == WI_RID_READ_APS) {
|
||||
if (sc->wi_scanning) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
} else {
|
||||
len = sc->wi_naps * sizeof(struct wi_apinfo);
|
||||
len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
|
||||
len = len / sizeof(struct wi_apinfo);
|
||||
memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
|
||||
memcpy((char *)&wreq.wi_val + sizeof(len),
|
||||
(char *)&sc->wi_aps,
|
||||
len * sizeof(struct wi_apinfo));
|
||||
}
|
||||
} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
|
||||
/* For non-root user, return all-zeroes keys */
|
||||
if (suser(p->p_ucred, &p->p_acflag))
|
||||
|
@ -1315,6 +1425,23 @@ wi_ioctl(ifp, command, data)
|
|||
} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
|
||||
error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
|
||||
wreq.wi_len);
|
||||
} else if (wreq.wi_type == WI_RID_SCAN_APS) {
|
||||
if (wreq.wi_len != 4) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (!sc->wi_scanning) {
|
||||
if (sc->sc_prism2) {
|
||||
wreq.wi_type = WI_RID_SCAN_REQ;
|
||||
error = wi_write_record(sc,
|
||||
(struct wi_ltv_gen *)&wreq);
|
||||
}
|
||||
if (!error) {
|
||||
sc->wi_scanning = 1;
|
||||
callout_reset(&sc->wi_scan_sh, hz * 1,
|
||||
wi_wait_scan, sc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (sc->sc_enabled != 0)
|
||||
error = wi_write_record(sc,
|
||||
|
@ -1484,6 +1611,10 @@ wi_init(ifp)
|
|||
/* Enable desired port */
|
||||
wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
|
||||
|
||||
/* scanning variable is modal, therefore reinit to OFF, in case it was on. */
|
||||
sc->wi_scanning=0;
|
||||
sc->wi_naps=0;
|
||||
|
||||
if ((error = wi_alloc_nicmem(sc,
|
||||
1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
|
||||
printf("%s: tx buffer allocation failed\n",
|
||||
|
@ -1652,6 +1783,7 @@ wi_stop(ifp, disable)
|
|||
wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
|
||||
|
||||
callout_stop(&sc->wi_inquire_ch);
|
||||
callout_stop(&sc->wi_scan_sh);
|
||||
|
||||
if (disable) {
|
||||
if (sc->sc_enabled) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wi_ieee.h,v 1.8 2002/01/20 04:37:04 ichiro Exp $ */
|
||||
/* $NetBSD: wi_ieee.h,v 1.9 2002/01/21 11:28:18 ichiro Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
|
@ -87,6 +87,9 @@ struct wi_req {
|
|||
#define WI_RID_ZERO_CACHE 0x0300
|
||||
#define WI_RID_READ_CACHE 0x0400
|
||||
#endif
|
||||
#define WI_RID_MONITOR_MODE 0x0500
|
||||
#define WI_RID_SCAN_APS 0x0600
|
||||
#define WI_RID_READ_APS 0x0700
|
||||
|
||||
struct wi_80211_hdr {
|
||||
u_int16_t frame_ctl;
|
||||
|
@ -180,20 +183,6 @@ struct wi_counters {
|
|||
u_int32_t wi_rx_msg_in_bad_msg_frags;
|
||||
};
|
||||
|
||||
/*
|
||||
* These are all the LTV record types that we can read or write
|
||||
* from the WaveLAN. Not all of them are temendously useful, but I
|
||||
* list as many as I know about here for completeness.
|
||||
*/
|
||||
#define WI_SCAN_RESULTS_MAXLEN 512
|
||||
struct wi_scan_results {
|
||||
int truncated; /* incomplete data in result */
|
||||
u_int scanning; /* in hz units */
|
||||
struct timeval lastscan; /* time scan was completed */
|
||||
u_int16_t len; /* number of words */
|
||||
u_int16_t scan_results[WI_SCAN_RESULTS_MAXLEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* Network parameters, static configuration entities.
|
||||
*/
|
||||
|
@ -338,12 +327,26 @@ struct wi_ltv_keys {
|
|||
/*
|
||||
* Scan Information
|
||||
*/
|
||||
#define WI_RID_SCAN_REQ 0xFCE1
|
||||
#define WI_RID_JOIN_REQ 0xFCE2
|
||||
#define WI_RID_SCAN_REQ 0xFCE1 /* Scan request (STA only) */
|
||||
#define WI_RID_JOIN_REQ 0xFCE2 /* Join request (STA only) */
|
||||
#define WI_RID_AUTH_STATION 0xFCE3 /* Authenticates Station (AP) */
|
||||
#define WI_RID_CHANNEL_REQ 0xFCE4 /* Channel Information Request (AP) */
|
||||
#define WI_RID_SCAN_RESULTS 0xFD88 /* Scan Results Table */
|
||||
|
||||
struct wi_apinfo {
|
||||
int scanreason; /* ScanReason */
|
||||
char bssid[6]; /* BSSID (mac address) */
|
||||
int channel; /* Channel */
|
||||
int signal; /* Signal level */
|
||||
int noise; /* Average Noise Level*/
|
||||
int quality; /* Quality */
|
||||
int namelen; /* Length of SSID string */
|
||||
char name[32]; /* SSID string */
|
||||
int capinfo; /* Capability info. */
|
||||
int interval; /* BSS Beacon Interval */
|
||||
int rate; /* Data Rate */
|
||||
};
|
||||
|
||||
/*
|
||||
* Modem information
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wireg.h,v 1.16 2002/01/20 06:49:32 ichiro Exp $ */
|
||||
/* $NetBSD: wireg.h,v 1.17 2002/01/21 11:28:18 ichiro Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
|
@ -510,12 +510,58 @@ struct wi_ltv_mcast {
|
|||
*/
|
||||
#define WI_INFO_NOTIFY 0xF000 /* Handover address */
|
||||
#define WI_INFO_COUNTERS 0xF100 /* Statistics counters */
|
||||
#define WI_INFO_SCAN_RESULTS 0xF101 /* Scan results */
|
||||
#define WI_INFO_SCAN_RESULTS 0xF101 /* Scan results table (STA only) */
|
||||
#define WI_INFO_LINK_STAT 0xF200 /* Link status */
|
||||
#define WI_INFO_ASSOC_STAT 0xF201 /* Association status */
|
||||
#define WI_INFO_AUTH_REQUEST 0xF202 /* Authentication Request (AP) */
|
||||
#define WI_INFO_POWERSAVE_COUNT 0xF203 /* PowerSave User Count (AP) */
|
||||
|
||||
/*
|
||||
* Scan Results Table of Prism2 chip (STA only)
|
||||
*/
|
||||
|
||||
#define MAXAPINFO 30
|
||||
struct wi_scan_header {
|
||||
u_int16_t wi_reserve; /* future use */
|
||||
u_int16_t wi_reason; /* The reason this scan was initiated
|
||||
1: Host initiated
|
||||
2: Firmware initiated
|
||||
3: Inquiry request from host */
|
||||
};
|
||||
struct wi_scan_data_p2 {
|
||||
u_int16_t wi_chid; /* BSS Channel ID from Probe Res.(PR)*/
|
||||
u_int16_t wi_noise; /* Average Noise Level of the PR */
|
||||
u_int16_t wi_signal; /* Signal Level on the PR */
|
||||
u_int8_t wi_bssid[6]; /* MACaddress of BSS responder from PR */
|
||||
u_int16_t wi_interval; /* BSS beacon interval */
|
||||
u_int16_t wi_capinfo; /* BSS Capability Information
|
||||
IEEE Std 802.11(1997) ,see 7.3.1.4 */
|
||||
u_int16_t wi_namelen; /* Length of SSID strings */
|
||||
u_int8_t wi_name[32]; /* SSID strings */
|
||||
u_int16_t wi_suprate[5]; /* Supported Rates element from the PR
|
||||
IEEE Std 802.11(1997) ,see 7.3.2.2 */
|
||||
u_int16_t wi_rate; /* Data rate of the PR */
|
||||
#define WI_APRATE_1 0x0A /* 1 Mbps */
|
||||
#define WI_APRATE_2 0x14 /* 2 Mbps */
|
||||
#define WI_APRATE_5 0x37 /* 5.5 Mbps */
|
||||
#define WI_APRATE_11 0x6E /* 11 Mbps */
|
||||
};
|
||||
|
||||
/*
|
||||
* Scan Results of Lucent chip
|
||||
*/
|
||||
struct wi_scan_data {
|
||||
u_int16_t wi_chid; /* BSS Channel ID from PR */
|
||||
u_int16_t wi_noise; /* Average Noise Level of the PR */
|
||||
u_int16_t wi_signal; /* Signal Level on the PR */
|
||||
u_int8_t wi_bssid[6]; /* MACaddress of BSS responder from PR */
|
||||
u_int16_t wi_interval; /* BSS beacon interval */
|
||||
u_int16_t wi_capinfo; /* BSS Capability Information
|
||||
IEEE Std 802.11(1997) ,see 7.3.1.4 */
|
||||
u_int16_t wi_namelen; /* Length of SSID strings */
|
||||
u_int8_t wi_name[32]; /* SSID strings */
|
||||
};
|
||||
|
||||
/*
|
||||
* Hermes transmit/receive frame structure
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wivar.h,v 1.7 2002/01/05 20:10:53 explorer Exp $ */
|
||||
/* $NetBSD: wivar.h,v 1.8 2002/01/21 11:28:18 ichiro Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
|
@ -50,12 +50,13 @@ struct wi_softc {
|
|||
int sc_enabled;
|
||||
int sc_prism2;
|
||||
int sc_prism2_ver;
|
||||
int sc_pci; /* attach to PCI-Bus */
|
||||
int sc_pci; /* attach to PCI-Bus */
|
||||
|
||||
bus_space_tag_t sc_iot; /* bus cookie */
|
||||
bus_space_handle_t sc_ioh; /* bus i/o handle */
|
||||
|
||||
struct callout wi_inquire_ch;
|
||||
struct callout wi_scan_sh;
|
||||
|
||||
u_int8_t sc_macaddr[ETHER_ADDR_LEN];
|
||||
|
||||
|
@ -87,6 +88,10 @@ struct wi_softc {
|
|||
int wi_tx_key;
|
||||
struct wi_ltv_keys wi_keys;
|
||||
struct wi_counters wi_stats;
|
||||
|
||||
struct wi_apinfo wi_aps[MAXAPINFO];
|
||||
int wi_naps;
|
||||
int wi_scanning; /* scan mode */
|
||||
};
|
||||
|
||||
int wi_attach __P((struct wi_softc *));
|
||||
|
|
Loading…
Reference in New Issue