Move IEEE 802.11 MAC management functions from awi driver to

if_ieee80211subr.c, which can be shared between any IEEE 802.11
drivers.
However, most of current working IEEE 802.11b wireless LAN cards
have rich firmware and we cannot have a control to management frames
for such cards.

IBSS creation is now supported for the awi driver.
This commit is contained in:
onoe 2001-09-18 09:09:57 +00:00
parent 22966108bb
commit 6a617566bc
9 changed files with 3698 additions and 3462 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.462 2001/09/16 07:33:31 manu Exp $
# $NetBSD: files,v 1.463 2001/09/18 09:09:57 onoe Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -328,8 +328,6 @@ file dev/ic/an.c an
# AMD 79c930-based 802.11 cards
device awi: arp, wlan, ifnet
file dev/ic/awi.c awi
file dev/ic/awi_wep.c awi
file dev/ic/awi_wicfg.c awi
file dev/ic/am79c930.c awi
# Lucent & Intersil WaveLan IEEE (802.11)
@ -984,6 +982,7 @@ file net/if_gif.c gif needs-flag
file net/if_gre.c gre needs-count
file net/if_hippisubr.c hippi needs-flag
file net/if_ieee1394subr.c ieee1394
file net/if_ieee80211subr.c wlan
file net/if_loop.c loop needs-count
file net/if_media.c
file net/if_ppp.c ppp needs-count

File diff suppressed because it is too large Load Diff

View File

@ -1,521 +0,0 @@
/* $NetBSD: awi_wep.c,v 1.9 2001/07/26 19:40:59 jdolecek Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Atsushi Onoe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* WEP support framework for the awi driver.
*
* No actual encryption capability is provided here, but any can be added
* to awi_wep_algo table below.
*
* Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
* which is a proprietary encryption algorithm available under license
* from RSA Data Security Inc. Using another algorithm, includes null
* encryption provided here, the awi driver cannot be able to communicate
* with other stations.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include <sys/bus.h>
#else
#include <sys/device.h>
#endif
#include <net/if.h>
#ifdef __FreeBSD__
#include <net/ethernet.h>
#include <net/if_arp.h>
#else
#include <net/if_ether.h>
#endif
#include <net/if_media.h>
#include <net/if_ieee80211.h>
#include <machine/cpu.h>
#include <machine/bus.h>
#ifdef __FreeBSD__
#include <machine/clock.h>
#endif
#ifdef __NetBSD__
#include <dev/ic/am79c930var.h>
#include <dev/ic/awireg.h>
#include <dev/ic/awivar.h>
#include <crypto/arc4/arc4.h>
#endif
#ifdef __FreeBSD__
#include <dev/awi/am79c930var.h>
#include <dev/awi/awireg.h>
#include <dev/awi/awivar.h>
#include <crypto/rc4/rc4.h>
static __inline int
arc4_ctxlen(void)
{
return sizeof(struct rc4_state);
}
static __inline void
arc4_setkey(void *ctx, u_int8_t *key, int keylen)
{
rc4_init(ctx, key, keylen);
}
static __inline void
arc4_encrypt(void *ctx, u_int8_t *dst, u_int8_t *src, int len)
{
rc4_crypt(ctx, dst, src, len);
}
#endif
static void awi_crc_init __P((void));
static u_int32_t awi_crc_update __P((u_int32_t crc, u_int8_t *buf, int len));
static int awi_null_ctxlen __P((void));
static void awi_null_setkey __P((void *ctx, u_int8_t *key, int keylen));
static void awi_null_copy __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
/* XXX: the order should be known to wiconfig/user */
static const struct awi_wep_algo awi_wep_algo[] = {
/* 0: no wep */
{ "no" }, /* dummy for no wep */
/* 1: normal wep (arc4) */
{ "arc4", arc4_ctxlen, arc4_setkey,
arc4_encrypt, arc4_encrypt },
/* 2: debug wep (null) */
{ "null", awi_null_ctxlen, awi_null_setkey,
awi_null_copy, awi_null_copy },
/* dummy for wep without encryption */
};
int
awi_wep_setnwkey(sc, nwkey)
struct awi_softc *sc;
struct ieee80211_nwkey *nwkey;
{
int i, error;
size_t len;
u_int8_t keybuf[AWI_MAX_KEYLEN];
if (nwkey->i_defkid <= 0 ||
nwkey->i_defkid > IEEE80211_WEP_NKID)
return EINVAL;
error = 0;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
if (nwkey->i_key[i].i_keydat == NULL)
continue;
len = nwkey->i_key[i].i_keylen;
if (len > sizeof(keybuf)) {
error = EINVAL;
break;
}
error = copyin(nwkey->i_key[i].i_keydat, keybuf, len);
if (error)
break;
error = awi_wep_setkey(sc, i, keybuf, len);
if (error)
break;
}
if (error == 0) {
sc->sc_wep_defkid = nwkey->i_defkid - 1;
error = awi_wep_setalgo(sc, nwkey->i_wepon);
}
return error;
}
int
awi_wep_getnwkey(sc, nwkey)
struct awi_softc *sc;
struct ieee80211_nwkey *nwkey;
{
int i, len, error, suerr;
u_int8_t keybuf[AWI_MAX_KEYLEN];
nwkey->i_wepon = awi_wep_getalgo(sc);
nwkey->i_defkid = sc->sc_wep_defkid + 1;
/* do not show any keys to non-root user */
#ifdef __FreeBSD__
suerr = suser(curproc);
#else
suerr = suser(curproc->p_ucred, &curproc->p_acflag);
#endif
error = 0;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
if (nwkey->i_key[i].i_keydat == NULL)
continue;
if (suerr) {
error = suerr;
break;
}
len = sizeof(keybuf);
error = awi_wep_getkey(sc, i, keybuf, &len);
if (error)
break;
if (nwkey->i_key[i].i_keylen < len) {
error = ENOSPC;
break;
}
nwkey->i_key[i].i_keylen = len;
error = copyout(keybuf, nwkey->i_key[i].i_keydat, len);
if (error)
break;
}
return error;
}
int
awi_wep_getalgo(sc)
struct awi_softc *sc;
{
if (sc->sc_wep_algo == NULL)
return 0;
return sc->sc_wep_algo - awi_wep_algo;
}
int
awi_wep_setalgo(sc, algo)
struct awi_softc *sc;
int algo;
{
const struct awi_wep_algo *awa;
int ctxlen;
awi_crc_init(); /* XXX: not belongs here */
if (algo < 0 || algo > sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
return EINVAL;
awa = &awi_wep_algo[algo];
if (awa->awa_name == NULL)
return EINVAL;
if (awa->awa_ctxlen == NULL) {
awa = NULL;
ctxlen = 0;
} else
ctxlen = awa->awa_ctxlen();
if (sc->sc_wep_ctx != NULL) {
free(sc->sc_wep_ctx, M_DEVBUF);
sc->sc_wep_ctx = NULL;
}
if (ctxlen) {
sc->sc_wep_ctx = malloc(ctxlen, M_DEVBUF, M_NOWAIT);
if (sc->sc_wep_ctx == NULL)
return ENOMEM;
}
sc->sc_wep_algo = awa;
return 0;
}
int
awi_wep_setkey(sc, kid, key, keylen)
struct awi_softc *sc;
int kid;
unsigned char *key;
int keylen;
{
if (kid < 0 || kid >= IEEE80211_WEP_NKID)
return EINVAL;
if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
return EINVAL;
sc->sc_wep_keylen[kid] = keylen;
if (keylen > 0)
memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
return 0;
}
int
awi_wep_getkey(sc, kid, key, keylen)
struct awi_softc *sc;
int kid;
unsigned char *key;
int *keylen;
{
if (kid < 0 || kid >= IEEE80211_WEP_NKID)
return EINVAL;
if (*keylen < sc->sc_wep_keylen[kid])
return ENOSPC;
*keylen = sc->sc_wep_keylen[kid];
if (*keylen > 0)
memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
return 0;
}
struct mbuf *
awi_wep_encrypt(sc, m0, txflag)
struct awi_softc *sc;
struct mbuf *m0;
int txflag;
{
struct mbuf *m, *n, *n0;
struct ieee80211_frame *wh;
const struct awi_wep_algo *awa;
int left, len, moff, noff, keylen, kid;
u_int32_t iv, crc;
u_int8_t *key, *ivp;
void *ctx;
u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
n0 = NULL;
awa = sc->sc_wep_algo;
if (awa == NULL)
goto fail;
ctx = sc->sc_wep_ctx;
m = m0;
left = m->m_pkthdr.len;
MGET(n, M_DONTWAIT, m->m_type);
n0 = n;
if (n == NULL)
goto fail;
M_COPY_PKTHDR(n, m);
len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
if (txflag) {
n->m_pkthdr.len += len;
} else {
n->m_pkthdr.len -= len;
left -= len;
}
n->m_len = MHLEN;
if (n->m_pkthdr.len >= MINCLSIZE) {
MCLGET(n, M_DONTWAIT);
if (n->m_flags & M_EXT)
n->m_len = n->m_ext.ext_size;
}
len = sizeof(struct ieee80211_frame);
memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
left -= len;
moff = len;
noff = len;
if (txflag) {
kid = sc->sc_wep_defkid;
wh = mtod(n, struct ieee80211_frame *);
wh->i_fc[1] |= IEEE80211_FC1_WEP;
iv = random();
/*
* store IV, byte order is not the matter since it's random.
* assuming IEEE80211_WEP_IVLEN is 3
*/
ivp = mtod(n, u_int8_t *) + noff;
ivp[0] = (iv >> 16) & 0xff;
ivp[1] = (iv >> 8) & 0xff;
ivp[2] = iv & 0xff;
ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */
noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
} else {
ivp = mtod(m, u_int8_t *) + moff;
kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
}
key = sc->sc_wep_key[kid];
keylen = sc->sc_wep_keylen[kid];
/* assuming IEEE80211_WEP_IVLEN is 3 */
key[0] = ivp[0];
key[1] = ivp[1];
key[2] = ivp[2];
awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
/* encrypt with calculating CRC */
crc = ~0;
while (left > 0) {
len = m->m_len - moff;
if (len == 0) {
m = m->m_next;
moff = 0;
continue;
}
if (len > n->m_len - noff) {
len = n->m_len - noff;
if (len == 0) {
MGET(n->m_next, M_DONTWAIT, n->m_type);
if (n->m_next == NULL)
goto fail;
n = n->m_next;
n->m_len = MLEN;
if (left >= MINCLSIZE) {
MCLGET(n, M_DONTWAIT);
if (n->m_flags & M_EXT)
n->m_len = n->m_ext.ext_size;
}
noff = 0;
continue;
}
}
if (len > left)
len = left;
if (txflag) {
awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
mtod(m, caddr_t) + moff, len);
crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
} else {
awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
mtod(m, caddr_t) + moff, len);
crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
}
left -= len;
moff += len;
noff += len;
}
crc = ~crc;
if (txflag) {
LE_WRITE_4(crcbuf, crc);
if (n->m_len >= noff + sizeof(crcbuf))
n->m_len = noff + sizeof(crcbuf);
else {
n->m_len = noff;
MGET(n->m_next, M_DONTWAIT, n->m_type);
if (n->m_next == NULL)
goto fail;
n = n->m_next;
n->m_len = sizeof(crcbuf);
noff = 0;
}
awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
sizeof(crcbuf));
} else {
n->m_len = noff;
for (noff = 0; noff < sizeof(crcbuf); noff += len) {
len = sizeof(crcbuf) - noff;
if (len > m->m_len - moff)
len = m->m_len - moff;
if (len > 0)
awa->awa_decrypt(ctx, crcbuf + noff,
mtod(m, caddr_t) + moff, len);
m = m->m_next;
moff = 0;
}
if (crc != LE_READ_4(crcbuf))
goto fail;
}
m_freem(m0);
return n0;
fail:
m_freem(m0);
m_freem(n0);
return NULL;
}
/*
* CRC 32 -- routine from RFC 2083
*/
/* Table of CRCs of all 8-bit messages */
static u_int32_t awi_crc_table[256];
static int awi_crc_table_computed = 0;
/* Make the table for a fast CRC. */
static void
awi_crc_init()
{
u_int32_t c;
int n, k;
if (awi_crc_table_computed)
return;
for (n = 0; n < 256; n++) {
c = (u_int32_t)n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = 0xedb88320UL ^ (c >> 1);
else
c = c >> 1;
}
awi_crc_table[n] = c;
}
awi_crc_table_computed = 1;
}
/*
* Update a running CRC with the bytes buf[0..len-1]--the CRC
* should be initialized to all 1's, and the transmitted value
* is the 1's complement of the final running CRC
*/
static u_int32_t
awi_crc_update(crc, buf, len)
u_int32_t crc;
u_int8_t *buf;
int len;
{
u_int8_t *endbuf;
for (endbuf = buf + len; buf < endbuf; buf++)
crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
return crc;
}
/*
* Null -- do nothing but copy.
*/
static int
awi_null_ctxlen()
{
return 0;
}
static void
awi_null_setkey(ctx, key, keylen)
void *ctx;
u_char *key;
int keylen;
{
}
static void
awi_null_copy(ctx, dst, src, len)
void *ctx;
u_char *dst;
u_char *src;
int len;
{
memcpy(dst, src, len);
}

View File

@ -1,657 +0,0 @@
/* $NetBSD: awi_wicfg.c,v 1.7 2001/06/28 10:40:04 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Atsushi Onoe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* WaveLAN compatible configuration support routines for the awi driver.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/sockio.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include <sys/bus.h>
#else
#include <sys/device.h>
#endif
#include <net/if.h>
#ifdef __FreeBSD__
#include <net/ethernet.h>
#include <net/if_arp.h>
#else
#include <net/if_ether.h>
#endif
#include <net/if_media.h>
#include <net/if_ieee80211.h>
#include <machine/cpu.h>
#include <machine/bus.h>
#ifdef __FreeBSD__
#include <machine/clock.h>
#endif
#ifdef __NetBSD__
#include <dev/ic/am79c930var.h>
#include <dev/ic/awireg.h>
#include <dev/ic/awivar.h>
#include <dev/ic/wi_ieee.h> /* XXX */
#endif
#ifdef __FreeBSD__
#include <dev/awi/am79c930var.h>
#undef _KERNEL /* XXX */
#include <i386/include/if_wavelan_ieee.h> /* XXX */
#define _KERNEL /* XXX */
#include <dev/awi/awireg.h>
#include <dev/awi/awivar.h>
#endif
static int awi_cfgget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
static int awi_cfgset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
int
awi_wicfg(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int error;
switch (cmd) {
case SIOCGWAVELAN:
error = awi_cfgget(ifp, cmd, data);
break;
case SIOCSWAVELAN:
#ifdef __FreeBSD__
error = suser(curproc);
#else
error = suser(curproc->p_ucred, &curproc->p_acflag);
#endif
if (error)
break;
error = awi_cfgset(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
}
static int
awi_cfgget(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int i, error, keylen;
char *p;
struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct wi_ltv_keys *keys;
struct wi_key *k;
struct wi_req wreq;
#ifdef WICACHE
struct wi_sigcache wsc;
struct awi_bss *bp;
#endif /* WICACHE */
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
if (error)
return error;
switch (wreq.wi_type) {
case WI_RID_SERIALNO:
memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
break;
case WI_RID_NODENAME:
strcpy((char *)&wreq.wi_val[1], hostname);
wreq.wi_val[0] = strlen(hostname);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_OWN_SSID:
p = sc->sc_ownssid;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_CURRENT_SSID:
if (ifp->if_flags & IFF_RUNNING) {
p = sc->sc_bss.essid;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
} else {
wreq.wi_val[0] = 0;
wreq.wi_val[1] = '\0';
}
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_DESIRED_SSID:
p = sc->sc_mib_mac.aDesired_ESS_ID;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_CURRENT_BSSID:
if (ifp->if_flags & IFF_RUNNING)
memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
else
memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
wreq.wi_len = ETHER_ADDR_LEN / 2;
break;
case WI_RID_CHANNEL_LIST:
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
wreq.wi_val[0] = sc->sc_scan_min;
wreq.wi_val[1] = sc->sc_scan_max;
wreq.wi_len = 2;
} else {
wreq.wi_val[0] = 0;
for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
wreq.wi_val[0] |= 1 << (i - 1);
wreq.wi_len = 1;
}
break;
case WI_RID_OWN_CHNL:
wreq.wi_val[0] = sc->sc_ownch;
wreq.wi_len = 1;
break;
case WI_RID_CURRENT_CHAN:
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
wreq.wi_val[0] = sc->sc_bss.pattern;
else
wreq.wi_val[0] = sc->sc_bss.chanset;
wreq.wi_len = 1;
break;
case WI_RID_COMMS_QUALITY:
wreq.wi_val[0] = 0; /* quality */
wreq.wi_val[1] = sc->sc_bss.rssi; /* signal */
wreq.wi_val[2] = 0; /* noise */
wreq.wi_len = 3;
break;
case WI_RID_PROMISC:
wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
wreq.wi_len = 1;
break;
case WI_RID_PORTTYPE:
if (sc->sc_mib_local.Network_Mode)
wreq.wi_val[0] = 1;
else if (!sc->sc_no_bssid)
wreq.wi_val[0] = 2;
else
wreq.wi_val[0] = 3;
wreq.wi_len = 1;
break;
case WI_RID_MAC_NODE:
memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
ETHER_ADDR_LEN);
wreq.wi_len = ETHER_ADDR_LEN / 2;
break;
case WI_RID_TX_RATE:
case WI_RID_CUR_TX_RATE:
wreq.wi_val[0] = sc->sc_tx_rate / 10;
wreq.wi_len = 1;
break;
case WI_RID_RTS_THRESH:
wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
wreq.wi_len = 1;
break;
case WI_RID_CREATE_IBSS:
wreq.wi_val[0] = sc->sc_start_bss;
wreq.wi_len = 1;
break;
case WI_RID_MICROWAVE_OVEN:
wreq.wi_val[0] = 0; /* no ... not supported */
wreq.wi_len = 1;
break;
case WI_RID_ROAMING_MODE:
wreq.wi_val[0] = 1; /* enabled ... not supported */
wreq.wi_len = 1;
break;
case WI_RID_SYSTEM_SCALE:
wreq.wi_val[0] = 1; /* low density ... not supported */
wreq.wi_len = 1;
break;
case WI_RID_PM_ENABLED:
wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
wreq.wi_len = 1;
break;
case WI_RID_MAX_SLEEP:
wreq.wi_val[0] = 0; /* not implemented */
wreq.wi_len = 1;
break;
case WI_RID_WEP_AVAIL:
wreq.wi_val[0] = 1;
wreq.wi_len = 1;
break;
case WI_RID_AUTH_CNTL:
wreq.wi_val[0] = 1; /* open system authentication only */
wreq.wi_len = 1;
break;
case WI_RID_ENCRYPTION:
wreq.wi_val[0] = awi_wep_getalgo(sc);
wreq.wi_len = 1;
break;
case WI_RID_TX_CRYPT_KEY:
wreq.wi_val[0] = sc->sc_wep_defkid;
wreq.wi_len = 1;
break;
case WI_RID_DEFLT_CRYPT_KEYS:
keys = (struct wi_ltv_keys *)&wreq;
/* do not show keys to non-root user */
#ifdef __FreeBSD__
error = suser(curproc);
#else
error = suser(curproc->p_ucred, &curproc->p_acflag);
#endif
if (error) {
memset(keys, 0, sizeof(*keys));
error = 0;
break;
}
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
k = &keys->wi_keys[i];
keylen = sizeof(k->wi_keydat);
error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
if (error)
break;
k->wi_keylen = keylen;
}
wreq.wi_len = sizeof(*keys) / 2;
break;
case WI_RID_MAX_DATALEN:
wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
wreq.wi_len = 1;
break;
case WI_RID_IFACE_STATS:
/* not implemented yet */
wreq.wi_len = 0;
break;
#ifdef WICACHE
case WI_RID_READ_CACHE:
for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
bp != NULL && i < MAXWICACHE;
bp = TAILQ_NEXT(bp, list), i++) {
memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
/*XXX*/
memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
wsc.signal = bp->rssi;
wsc.noise = 0;
wsc.quality = 0;
memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
&wsc, sizeof(wsc));
}
wreq.wi_len = sizeof(wsc) * i / 2;
break;
#endif /* WICACHE */
default:
error = EINVAL;
break;
}
if (error == 0) {
wreq.wi_len++;
error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
}
return error;
}
static int
awi_cfgset(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int i, error, rate, oregion;
u_int8_t *phy_rates;
struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct wi_ltv_keys *keys;
struct wi_key *k;
struct wi_req wreq;
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
if (error)
return error;
if (wreq.wi_len-- < 1)
return EINVAL;
switch (wreq.wi_type) {
case WI_RID_SERIALNO:
case WI_RID_NODENAME:
error = EPERM;
break;
case WI_RID_OWN_SSID:
if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
sc->sc_ownssid[1] = wreq.wi_val[0];
memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
if (!sc->sc_mib_local.Network_Mode &&
!sc->sc_no_bssid && sc->sc_start_bss)
error = ENETRESET;
break;
case WI_RID_CURRENT_SSID:
error = EPERM;
break;
case WI_RID_DESIRED_SSID:
if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
wreq.wi_val[0]);
if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
error = ENETRESET;
break;
case WI_RID_CURRENT_BSSID:
error = EPERM;
break;
case WI_RID_CHANNEL_LIST:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
if (wreq.wi_val[0] == oregion)
break;
sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
error = awi_init_region(sc);
if (error) {
sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
break;
}
error = ENETRESET;
break;
case WI_RID_OWN_CHNL:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] < sc->sc_scan_min ||
wreq.wi_val[0] > sc->sc_scan_max) {
error = EINVAL;
break;
}
sc->sc_ownch = wreq.wi_val[0];
if (!sc->sc_mib_local.Network_Mode)
error = ENETRESET;
break;
case WI_RID_CURRENT_CHAN:
error = EPERM;
break;
case WI_RID_COMMS_QUALITY:
error = EPERM;
break;
case WI_RID_PROMISC:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (ifp->if_flags & IFF_PROMISC) {
if (wreq.wi_val[0] == 0) {
ifp->if_flags &= ~IFF_PROMISC;
error = ENETRESET;
}
} else {
if (wreq.wi_val[0] != 0) {
ifp->if_flags |= IFF_PROMISC;
error = ENETRESET;
}
}
break;
case WI_RID_PORTTYPE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
switch (wreq.wi_val[0]) {
case 1:
sc->sc_mib_local.Network_Mode = 1;
sc->sc_no_bssid = 0;
error = ENETRESET;
break;
case 2:
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 0;
error = ENETRESET;
break;
case 3:
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
error = EINVAL;
break;
}
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 1;
error = ENETRESET;
break;
default:
error = EINVAL;
break;
}
break;
case WI_RID_MAC_NODE:
/* XXX: should be implemented? */
error = EPERM;
break;
case WI_RID_TX_RATE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
switch (wreq.wi_val[0]) {
case 1:
case 2:
case 5:
case 11:
rate = wreq.wi_val[0] * 10;
if (rate == 50)
rate += 5; /*XXX*/
break;
case 3:
case 6:
case 7:
/* auto rate */
phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
rate = AWI_RATE_1MBIT;
for (i = 0; i < phy_rates[1]; i++) {
if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
rate = AWI_80211_RATE(phy_rates[2 + i]);
}
break;
default:
rate = 0;
error = EINVAL;
break;
}
if (error)
break;
for (i = 0; i < phy_rates[1]; i++) {
if (rate == AWI_80211_RATE(phy_rates[2 + i]))
break;
}
if (i == phy_rates[1]) {
error = EINVAL;
break;
}
sc->sc_tx_rate = rate;
break;
case WI_RID_CUR_TX_RATE:
error = EPERM;
break;
case WI_RID_RTS_THRESH:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
error = ENETRESET;
break;
case WI_RID_CREATE_IBSS:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
error = ENETRESET;
break;
case WI_RID_MICROWAVE_OVEN:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] != 0)
error = EINVAL; /* not supported */
break;
case WI_RID_ROAMING_MODE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] != 1)
error = EINVAL; /* not supported */
break;
case WI_RID_SYSTEM_SCALE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] != 1)
error = EINVAL; /* not supported */
break;
case WI_RID_PM_ENABLED:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] != 0)
error = EINVAL; /* not implemented */
break;
case WI_RID_MAX_SLEEP:
error = EINVAL; /* not implemented */
break;
case WI_RID_WEP_AVAIL:
error = EPERM;
break;
case WI_RID_AUTH_CNTL:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] != 1)
error = EINVAL; /* not implmented */
break;
case WI_RID_ENCRYPTION:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
error = awi_wep_setalgo(sc, wreq.wi_val[0]);
if (error)
break;
error = ENETRESET;
break;
case WI_RID_TX_CRYPT_KEY:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
error = EINVAL;
break;
}
sc->sc_wep_defkid = wreq.wi_val[1];
break;
case WI_RID_DEFLT_CRYPT_KEYS:
if (wreq.wi_len != sizeof(*keys) / 2) {
error = EINVAL;
break;
}
keys = (struct wi_ltv_keys *)&wreq;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
k = &keys->wi_keys[i];
error = awi_wep_setkey(sc, i, k->wi_keydat,
k->wi_keylen);
if (error)
break;
}
break;
case WI_RID_MAX_DATALEN:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
error = EINVAL;
break;
}
LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
break;
case WI_RID_IFACE_STATS:
error = EPERM;
break;
default:
error = EINVAL;
break;
}
if (error == ENETRESET) {
if (sc->sc_enabled) {
awi_stop(ifp, 0);
error = awi_init(ifp);
} else
error = 0;
}
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: awireg.h,v 1.4 2001/06/12 15:17:21 wiz Exp $ */
/* $NetBSD: awireg.h,v 1.5 2001/09/18 09:09:59 onoe Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -36,6 +36,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_AWIREG_H
#define _DEV_IC_AWIREG_H
/*
* The firmware typically loaded onto Am79C930-based 802.11 interfaces
* uses a 32k or larger shared memory buffer to communicate with the
@ -91,70 +94,65 @@
#define AWI_CMD_SET_MIB 0x2
#define AWI_CMD_GET_MIB 0x9
#define AWI_CA_MIB_TYPE 0x0
#define AWI_CA_MIB_SIZE 0x1
#define AWI_CA_MIB_INDEX 0x2
#define AWI_CA_MIB_DATA 0x4
#define AWI_MIB_LOCAL 0x0
#define AWI_MIB_ADDR 0x2
#define AWI_MIB_MAC 0x3
#define AWI_MIB_STAT 0x4
#define AWI_MIB_MGT 0x5
#define AWI_MIB_DRVR 0x6
#define AWI_MIB_PHY 0x7
#define AWI_CA_MIB_TYPE (AWI_CMD_PARAMS + 0x0)
#define AWI_CA_MIB_SIZE (AWI_CMD_PARAMS + 0x1)
#define AWI_CA_MIB_INDEX (AWI_CMD_PARAMS + 0x2)
#define AWI_CA_MIB_DATA (AWI_CMD_PARAMS + 0x4)
#define AWI_MIB_LOCAL 0
#define AWI_MIB_ADDR 2
#define AWI_MIB_MAC 3
#define AWI_MIB_STAT 4
#define AWI_MIB_MGT 5
#define AWI_MIB_DRVR 6
#define AWI_MIB_PHY 7
#define AWI_CMD_INIT_TX 0x3
#define AWI_CA_TX_LEN 0x14
#define AWI_CA_TX_DATA 0x0
#define AWI_CA_TX_MGT 0x4
#define AWI_CA_TX_BCAST 0x8
#define AWI_CA_TX_PS 0xc
#define AWI_CA_TX_CF 0x10
#define AWI_CA_TX_LEN 20
#define AWI_CA_TX_DATA (AWI_CMD_PARAMS + 0x0)
#define AWI_CA_TX_MGT (AWI_CMD_PARAMS + 0x4)
#define AWI_CA_TX_BCAST (AWI_CMD_PARAMS + 0x8)
#define AWI_CA_TX_PS (AWI_CMD_PARAMS + 0xc)
#define AWI_CA_TX_CF (AWI_CMD_PARAMS + 0x10)
#define AWI_CMD_FLUSH_TX 0x4
#define AWI_CA_FTX_LEN 0x5
#define AWI_CA_FTX_DATA 0x0
#define AWI_CA_FTX_MGT 0x1
#define AWI_CA_FTX_BCAST 0x2
#define AWI_CA_FTX_PS 0x3
#define AWI_CA_FTX_CF 0x4
#define AWI_CA_FTX_LEN 5
#define AWI_CA_FTX_DATA (AWI_CMD_PARAMS + 0x0)
#define AWI_CA_FTX_MGT (AWI_CMD_PARAMS + 0x1)
#define AWI_CA_FTX_BCAST (AWI_CMD_PARAMS + 0x2)
#define AWI_CA_FTX_PS (AWI_CMD_PARAMS + 0x3)
#define AWI_CA_FTX_CF (AWI_CMD_PARAMS + 0x4)
#define AWI_CMD_INIT_RX 0x5
#define AWI_CA_IRX_LEN 0x8
#define AWI_CA_IRX_DATA_DESC 0x0 /* return */
#define AWI_CA_IRX_PS_DESC 0x4 /* return */
#define AWI_CA_IRX_DATA_DESC (AWI_CMD_PARAMS + 0x0) /* return */
#define AWI_CA_IRX_PS_DESC (AWI_CMD_PARAMS + 0x4) /* return */
#define AWI_CMD_KILL_RX 0x6
#define AWI_CMD_SLEEP 0x7
#define AWI_CA_SLEEP_LEN 0x8
#define AWI_CA_WAKEUP 0x0 /* uint64 */
#define AWI_CA_SLEEP_LEN 8
#define AWI_CA_WAKEUP (AWI_CMD_PARAMS + 0x0) /* uint64 */
#define AWI_CMD_WAKE 0x8
#define AWI_CMD_SCAN 0xa
#define AWI_CA_SCAN_LEN 0x6
#define AWI_CA_SCAN_DURATION 0x0
#define AWI_CA_SCAN_SET 0x2
#define AWI_CA_SCAN_PATTERN 0x3
#define AWI_CA_SCAN_IDX 0x4
#define AWI_CA_SCAN_SUSP 0x5
#define AWI_CA_SCAN_LEN 6
#define AWI_CA_SCAN_DURATION (AWI_CMD_PARAMS + 0x0)
#define AWI_CA_SCAN_SET (AWI_CMD_PARAMS + 0x2)
#define AWI_CA_SCAN_PATTERN (AWI_CMD_PARAMS + 0x3)
#define AWI_CA_SCAN_IDX (AWI_CMD_PARAMS + 0x4)
#define AWI_CA_SCAN_SUSP (AWI_CMD_PARAMS + 0x5)
#define AWI_CMD_SYNC 0xb
#define AWI_CA_SYNC_LEN 0x14
#define AWI_CA_SYNC_SET 0x0
#define AWI_CA_SYNC_PATTERN 0x1
#define AWI_CA_SYNC_IDX 0x2
#define AWI_CA_SYNC_STARTBSS 0x3
#define AWI_CA_SYNC_DWELL 0x4
#define AWI_CA_SYNC_MBZ 0x6
#define AWI_CA_SYNC_TIMESTAMP 0x8
#define AWI_CA_SYNC_REFTIME 0x10
#define AWI_CA_SYNC_LEN 20
#define AWI_CA_SYNC_SET (AWI_CMD_PARAMS + 0x0)
#define AWI_CA_SYNC_PATTERN (AWI_CMD_PARAMS + 0x1)
#define AWI_CA_SYNC_IDX (AWI_CMD_PARAMS + 0x2)
#define AWI_CA_SYNC_STARTBSS (AWI_CMD_PARAMS + 0x3)
#define AWI_CA_SYNC_DWELL (AWI_CMD_PARAMS + 0x4)
#define AWI_CA_SYNC_MBZ (AWI_CMD_PARAMS + 0x6)
#define AWI_CA_SYNC_TIMESTAMP (AWI_CMD_PARAMS + 0x8)
#define AWI_CA_SYNC_REFTIME (AWI_CMD_PARAMS + 0x10)
#define AWI_CMD_RESUME 0xc
@ -356,7 +354,7 @@ struct awi_mib_local {
u_int8_t Rx_Buffer_Size[4];
u_int8_t Acting_as_AP;
u_int8_t Fill_CFP;
};
} __attribute__((__packed__));;
struct awi_mib_mac {
u_int8_t _Reserved1[2];
@ -378,7 +376,7 @@ struct awi_mib_mac {
u_int8_t aMax_Receive_MSDU_Lifetime[4];
u_int8_t aStation_Basic_Rate[2];
u_int8_t aDesired_ESS_ID[AWI_ESS_ID_SIZE];
};
} __attribute__((__packed__));
struct awi_mib_stat {
u_int8_t aTransmitted_MPDU_Count[4];
@ -400,7 +398,7 @@ struct awi_mib_stat {
u_int8_t aFCS_Error_Count[4];
u_int8_t aError_Count[4];
u_int8_t aWEP_Undecryptable_Count[4];
};
} __attribute__((__packed__));
struct awi_mib_mgt {
u_int8_t aPower_Mgt_Mode;
@ -424,7 +422,7 @@ struct awi_mib_mgt {
u_int8_t aStation_ID[2];
u_int8_t aCurrent_BSS_ID[ETHER_ADDR_LEN];
u_int8_t aCurrent_ESS_ID[AWI_ESS_ID_SIZE];
};
} __attribute__((__packed__));
#define AWI_GROUP_ADDR_SIZE 4
struct awi_mib_addr {
@ -432,7 +430,7 @@ struct awi_mib_addr {
u_int8_t aGroup_Addresses[AWI_GROUP_ADDR_SIZE][ETHER_ADDR_LEN];
u_int8_t aTransmit_Enable_Status;
u_int8_t _Reserved1;
};
} __attribute__((__packed__));
#define AWI_PWR_LEVEL_SIZE 4
struct awi_mib_phy {
@ -456,4 +454,6 @@ struct awi_mib_phy {
#define AWI_PHY_TYPE_DS 2
#define AWI_PHY_TYPE_IR 3
u_int8_t RCR_33A_Bits[8];
};
} __attribute__((__packed__));
#endif /* _DEV_IC_AWIREG_H */

View File

@ -1,7 +1,7 @@
/* $NetBSD: awivar.h,v 1.14 2001/06/28 10:40:04 onoe Exp $ */
/* $NetBSD: awivar.h,v 1.15 2001/09/18 09:09:59 onoe Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -36,6 +36,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_AWIVAR_H
#define _DEV_IC_AWIVAR_H
/* timer values in msec */
#define AWI_SELFTEST_TIMEOUT 5000
#define AWI_CMD_TIMEOUT 2000
@ -44,96 +47,56 @@
#define AWI_ASCAN_WAIT 3000
#define AWI_PSCAN_DURATION 200
#define AWI_PSCAN_WAIT 5000
#define AWI_TRANS_TIMEOUT 2000
#define AWI_TRANS_TIMEOUT 5000
#define AWI_NTXBUFS 4
#define AWI_MAX_KEYLEN 16
enum awi_status {
AWI_ST_INIT,
AWI_ST_SCAN,
AWI_ST_SETSS,
AWI_ST_SYNC,
AWI_ST_AUTH,
AWI_ST_ASSOC,
AWI_ST_RUNNING
enum awi_sub_state {
AWI_ST_NONE,
AWI_ST_SCAN_INIT,
AWI_ST_SCAN_SETMIB,
AWI_ST_SCAN_SCCMD,
AWI_ST_SUB_INIT,
AWI_ST_SUB_SETSS,
AWI_ST_SUB_SYNC
};
struct awi_bss
{
TAILQ_ENTRY(awi_bss) list;
u_int8_t esrc[ETHER_ADDR_LEN];
u_int8_t chanset; /* channel set to use */
u_int8_t pattern; /* hop pattern to use */
u_int8_t index; /* index to use */
u_int8_t rssi; /* strength of this beacon */
u_int16_t dwell_time; /* dwell time */
u_int8_t timestamp[8]; /* timestamp of this bss */
u_int8_t bssid[ETHER_ADDR_LEN];
u_int16_t capinfo;
u_int32_t rxtime; /* unit's local time */
u_int16_t interval; /* beacon interval */
u_int8_t txrate;
u_int8_t fails;
u_int8_t essid[IEEE80211_NWID_LEN + 2];
#define AWI_WAIT 0 /* must wait for completion */
#define AWI_NOWAIT 1 /* do not wait */
struct awi_chanset {
u_int8_t cs_type;
u_int8_t cs_region;
u_int8_t cs_min;
u_int8_t cs_max;
u_int8_t cs_def;
};
struct awi_wep_algo {
char *awa_name;
int (*awa_ctxlen) __P((void));
void (*awa_setkey) __P((void *, u_char *, int));
void (*awa_encrypt) __P((void *, u_char *, u_char *, int));
void (*awa_decrypt) __P((void *, u_char *, u_char *, int));
};
struct awi_softc
{
#ifdef __NetBSD__
struct device sc_dev;
struct ethercom sc_ec;
void *sc_ih; /* interrupt handler */
#endif
#ifdef __FreeBSD__
#if __FreeBSD__ >= 4
struct {
char dv_xname[64]; /*XXX*/
} sc_dev;
#else
struct awi_softc {
struct device sc_dev;
#endif
struct arpcom sc_ec;
#endif
struct am79c930_softc sc_chip;
struct ifnet *sc_ifp;
int (*sc_enable) __P((struct awi_softc *));
void (*sc_disable) __P((struct awi_softc *));
struct ifmedia sc_media;
enum awi_status sc_status;
unsigned int sc_enabled:1,
struct ieee80211com sc_ic;
u_char sc_banner[AWI_BANNER_LEN];
int (*sc_enable)(struct awi_softc *);
void (*sc_disable)(struct awi_softc *);
void (*sc_power)(struct awi_softc *, int);
void *sc_sdhook; /* shutdown hook */
void *sc_powerhook; /* power management hook */
unsigned int sc_attached:1,
sc_enabled:1,
sc_busy:1,
sc_cansleep:1,
sc_invalid:1,
sc_enab_intr:1,
sc_format_llc:1,
sc_start_bss:1,
sc_rawbpf:1,
sc_no_bssid:1,
sc_active_scan:1,
sc_attached:1; /* attach has succeeded */
u_int8_t sc_cmd_inprog;
sc_adhoc_ap:1,
sc_fhset_one:1,
sc_invalid:1;
struct ifmedia sc_media;
enum ieee80211_state sc_nstate;
enum awi_sub_state sc_substate;
int sc_sleep_cnt;
int sc_mgt_timer;
TAILQ_HEAD(, awi_bss) sc_scan;
u_int8_t sc_scan_cur;
u_int8_t sc_scan_min;
u_int8_t sc_scan_max;
u_int8_t sc_scan_set;
struct awi_bss sc_bss;
u_int8_t sc_ownssid[IEEE80211_NWID_LEN + 2];
u_int8_t sc_ownch;
u_int8_t sc_cmd_inprog;
u_int8_t sc_cur_chan;
int sc_rx_timer;
u_int32_t sc_rxdoff;
@ -141,20 +104,11 @@ struct awi_softc
struct mbuf *sc_rxpend;
int sc_tx_timer;
u_int8_t sc_tx_rate;
struct ifqueue sc_mgtq;
u_int32_t sc_txbase;
u_int32_t sc_txend;
u_int32_t sc_txnext;
u_int32_t sc_txdone;
int sc_wep_keylen[IEEE80211_WEP_NKID]; /* keylen */
u_int8_t sc_wep_key[IEEE80211_WEP_NKID][AWI_MAX_KEYLEN];
int sc_wep_defkid;
void *sc_wep_ctx; /* work area */
const struct awi_wep_algo *sc_wep_algo;
u_char sc_banner[AWI_BANNER_LEN];
struct awi_mib_local sc_mib_local;
struct awi_mib_addr sc_mib_addr;
struct awi_mib_mac sc_mib_mac;
@ -166,7 +120,8 @@ struct awi_softc
#define awi_read_1(sc, off) ((sc)->sc_chip.sc_ops->read_1)(&sc->sc_chip, off)
#define awi_read_2(sc, off) ((sc)->sc_chip.sc_ops->read_2)(&sc->sc_chip, off)
#define awi_read_4(sc, off) ((sc)->sc_chip.sc_ops->read_4)(&sc->sc_chip, off)
#define awi_read_bytes(sc, off, ptr, len) ((sc)->sc_chip.sc_ops->read_bytes)(&sc->sc_chip, off, ptr, len)
#define awi_read_bytes(sc, off, ptr, len) \
((sc)->sc_chip.sc_ops->read_bytes)(&sc->sc_chip, off, ptr, len)
#define awi_write_1(sc, off, val) \
((sc)->sc_chip.sc_ops->write_1)(&sc->sc_chip, off, val)
@ -181,57 +136,11 @@ struct awi_softc
awi_write_1(sc, AWI_DRIVERSTATE, \
((state) | AWI_DRV_AUTORXLED|AWI_DRV_AUTOTXLED))
/* unalligned little endian access */
#define LE_READ_2(p) \
(((u_int8_t *)(p))[0] | (((u_int8_t *)(p))[1] << 8))
#define LE_READ_4(p) \
(((u_int8_t *)(p))[0] | (((u_int8_t *)(p))[1] << 8) | \
(((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))
#define LE_WRITE_2(p, v) \
((((u_int8_t *)(p))[0] = ((u_int32_t)(v) & 0xff)), \
(((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)))
#define LE_WRITE_4(p, v) \
((((u_int8_t *)(p))[0] = ((u_int32_t)(v) & 0xff)), \
(((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)), \
(((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)), \
(((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff)))
int awi_attach(struct awi_softc *);
int awi_detach(struct awi_softc *);
int awi_activate(struct device *, enum devact);
void awi_power(int, void *);
void awi_shutdown(void *);
int awi_intr(void *);
#define AWI_80211_RATE(rate) (((rate) & 0x7f) * 5)
int awi_attach __P((struct awi_softc *));
int awi_intr __P((void *));
void awi_reset __P((struct awi_softc *));
int awi_init __P((struct ifnet *));
void awi_stop __P((struct ifnet *, int));
#ifdef __NetBSD__
int awi_activate __P((struct device *, enum devact));
int awi_detach __P((struct awi_softc *));
void awi_power __P((struct awi_softc *, int));
#endif
int awi_init_region __P((struct awi_softc *));
int awi_wicfg __P((struct ifnet *, u_long, caddr_t));
int awi_wep_setnwkey __P((struct awi_softc *, struct ieee80211_nwkey *));
int awi_wep_getnwkey __P((struct awi_softc *, struct ieee80211_nwkey *));
int awi_wep_getalgo __P((struct awi_softc *));
int awi_wep_setalgo __P((struct awi_softc *, int));
int awi_wep_setkey __P((struct awi_softc *, int, unsigned char *, int));
int awi_wep_getkey __P((struct awi_softc *, int, unsigned char *, int *));
struct mbuf *awi_wep_encrypt __P((struct awi_softc *, struct mbuf *, int));
#ifdef __FreeBSD__
/* Provide mem* for compat with NetBSD to fix LINT */
static __inline int
memcmp(const void *b1, const void *b2, size_t len)
{
return (bcmp(b1, b2, len));
}
static __inline void *
memset(void *b, int c, size_t len)
{
bzero(b, len);
return (b);
}
#endif
#endif /* _DEV_IC_AWIVAR_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_awi_pcmcia.c,v 1.19 2001/07/01 16:35:37 thorpej Exp $ */
/* $NetBSD: if_awi_pcmcia.c,v 1.20 2001/09/18 09:10:00 onoe Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -73,12 +73,11 @@
#include <dev/pcmcia/pcmciavar.h>
#include <dev/pcmcia/pcmciadevs.h>
static int awi_pcmcia_match __P((struct device *, struct cfdata *, void *));
static void awi_pcmcia_attach __P((struct device *, struct device *, void *));
static int awi_pcmcia_detach __P((struct device *, int));
static int awi_pcmcia_enable __P((struct awi_softc *));
static void awi_pcmcia_disable __P((struct awi_softc *));
static void awi_pcmcia_powerhook __P((int, void *));
static int awi_pcmcia_match(struct device *, struct cfdata *, void *);
static void awi_pcmcia_attach(struct device *, struct device *, void *);
static int awi_pcmcia_detach(struct device *, int);
static int awi_pcmcia_enable(struct awi_softc *);
static void awi_pcmcia_disable(struct awi_softc *);
struct awi_pcmcia_softc {
struct awi_softc sc_awi; /* real "awi" softc */
@ -89,7 +88,7 @@ struct awi_pcmcia_softc {
int sc_io_window; /* our i/o window */
int sc_mem_window; /* our memory window */
struct pcmcia_function *sc_pf; /* our PCMCIA function */
void *sc_powerhook; /* power hook descriptor */
void *sc_ih; /* interrupt handler */
};
static int awi_pcmcia_find __P((struct awi_pcmcia_softc *,
@ -169,15 +168,15 @@ awi_pcmcia_enable(sc)
struct pcmcia_function *pf = psc->sc_pf;
/* establish the interrupt. */
sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, awi_intr, sc);
if (sc->sc_ih == NULL) {
psc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, awi_intr, sc);
if (psc->sc_ih == NULL) {
printf("%s: couldn't establish interrupt\n",
sc->sc_dev.dv_xname);
return (1);
}
if (pcmcia_function_enable(pf)) {
pcmcia_intr_disestablish(pf, sc->sc_ih);
pcmcia_intr_disestablish(pf, psc->sc_ih);
return (1);
}
DELAY(1000);
@ -193,7 +192,7 @@ awi_pcmcia_disable(sc)
struct pcmcia_function *pf = psc->sc_pf;
pcmcia_function_disable(pf);
pcmcia_intr_disestablish(pf, sc->sc_ih);
pcmcia_intr_disestablish(pf, psc->sc_ih);
}
static int
@ -325,13 +324,12 @@ awi_pcmcia_attach(parent, self, aux)
sc->sc_disable = awi_pcmcia_disable;
/* establish the interrupt. */
sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, awi_intr, sc);
if (sc->sc_ih == NULL) {
psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, awi_intr, sc);
if (psc->sc_ih == NULL) {
printf("%s: couldn't establish interrupt\n",
sc->sc_dev.dv_xname);
goto no_interrupt;
}
sc->sc_ifp = &sc->sc_ec.ec_if;
sc->sc_cansleep = 1;
if (awi_attach(sc) != 0) {
@ -339,7 +337,6 @@ awi_pcmcia_attach(parent, self, aux)
sc->sc_dev.dv_xname);
goto attach_failed;
}
psc->sc_powerhook = powerhook_establish(awi_pcmcia_powerhook, psc);
sc->sc_enabled = 0;
/* disable device and disestablish the interrupt */
@ -347,7 +344,7 @@ awi_pcmcia_attach(parent, self, aux)
return;
attach_failed:
pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
no_interrupt:
/* Unmap our memory window and space */
@ -380,9 +377,6 @@ awi_pcmcia_detach(self, flags)
/* Nothing to detach. */
return (0);
if (psc->sc_powerhook != NULL)
powerhook_disestablish(psc->sc_powerhook);
error = awi_detach(&psc->sc_awi);
if (error != 0)
return (error);
@ -400,14 +394,3 @@ awi_pcmcia_detach(self, flags)
pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
return (0);
}
static void
awi_pcmcia_powerhook(why, arg)
int why;
void *arg;
{
struct awi_pcmcia_softc *psc = arg;
struct awi_softc *sc = &psc->sc_awi;
awi_power(sc, why);
}

View File

@ -1,32 +1,68 @@
/* $NetBSD: if_ieee80211.h,v 1.10 2001/09/11 12:25:18 onoe Exp $ */
/* $NetBSD: if_ieee80211.h,v 1.11 2001/09/18 09:10:00 onoe Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NET_IF_IEEE80211_H_
#define _NET_IF_IEEE80211_H_
#include <net/if_ether.h>
#define IEEE80211_ADDR_LEN ETHER_ADDR_LEN
/*
* generic definitions for IEEE 802.11 frames
*/
struct ieee80211_frame {
u_int8_t i_fc[2];
u_int8_t i_dur[2];
u_int8_t i_addr1[ETHER_ADDR_LEN];
u_int8_t i_addr2[ETHER_ADDR_LEN];
u_int8_t i_addr3[ETHER_ADDR_LEN];
u_int8_t i_addr1[IEEE80211_ADDR_LEN];
u_int8_t i_addr2[IEEE80211_ADDR_LEN];
u_int8_t i_addr3[IEEE80211_ADDR_LEN];
u_int8_t i_seq[2];
/* possibly followed by addr4[ETHER_ADDR_LEN]; */
/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
/* see below */
};
} __attribute__((__packed__));
struct ieee80211_frame_addr4 {
u_int8_t i_fc[2];
u_int8_t i_dur[2];
u_int8_t i_addr1[ETHER_ADDR_LEN];
u_int8_t i_addr2[ETHER_ADDR_LEN];
u_int8_t i_addr3[ETHER_ADDR_LEN];
u_int8_t i_addr1[IEEE80211_ADDR_LEN];
u_int8_t i_addr2[IEEE80211_ADDR_LEN];
u_int8_t i_addr3[IEEE80211_ADDR_LEN];
u_int8_t i_seq[2];
u_int8_t i_addr4[ETHER_ADDR_LEN];
};
u_int8_t i_addr4[IEEE80211_ADDR_LEN];
} __attribute__((__packed__));
#define IEEE80211_FC0_VERSION_MASK 0x03
#define IEEE80211_FC0_VERSION_0 0x00
@ -91,6 +127,9 @@ struct ieee80211_frame_addr4 {
#define IEEE80211_ELEMID_IBSSPARMS 6
#define IEEE80211_ELEMID_CHALLENGE 16
#define IEEE80211_RATE_BASIC 0x80
#define IEEE80211_RATE_VAL 0x7f
#define IEEE80211_AUTH_ALG_OPEN 0x0000
#define IEEE80211_AUTH_ALG_SHARED 0x0001
@ -136,6 +175,16 @@ struct ieee80211_frame_addr4 {
#define IEEE80211_NWID_LEN 32
#define IEEE80211_CRC_LEN 4
#define IEEE80211_MTU 1500
#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;
@ -172,4 +221,120 @@ struct ieee80211_power {
#define SIOCS80211POWER _IOW('i', 234, struct ieee80211_power)
#define SIOCG80211POWER _IOWR('i', 235, struct ieee80211_power)
#endif /* !_NET_IF_IEEE80211_H_ */
#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 */
/*
* Structure for IEEE 802.11 drivers.
*/
#define IEEE80211_CHAN_MAX 255
#define IEEE80211_RATE_SIZE 12
#define IEEE80211_KEYBUF_SIZE 16
enum ieee80211_state {
IEEE80211_S_INIT, /* default state */
IEEE80211_S_SCAN, /* scanning */
IEEE80211_S_AUTH, /* try to authenticate */
IEEE80211_S_ASSOC, /* try to assoc */
IEEE80211_S_RUN /* associated */
};
struct ieee80211_bss {
TAILQ_ENTRY(ieee80211_bss) bs_list;
u_int8_t bs_macaddr[IEEE80211_ADDR_LEN];
u_int8_t bs_bssid[IEEE80211_ADDR_LEN];
u_int8_t bs_esslen;
u_int8_t bs_essid[IEEE80211_NWID_LEN];
u_int8_t bs_tstamp[8];
u_int16_t bs_intval;
u_int16_t bs_capinfo;
u_int16_t bs_dwell;
u_int16_t bs_associd;
u_int32_t bs_timoff;
u_int8_t bs_chan;
u_int8_t bs_rssi;
u_int8_t bs_rates[IEEE80211_RATE_SIZE];
u_int16_t bs_txseq;
u_int16_t bs_rxseq;
int bs_nrate;
int bs_fails;
int bs_txrate;
};
struct ieee80211_wepkey {
int wk_len;
u_int8_t wk_key[IEEE80211_KEYBUF_SIZE];
};
struct ieee80211com {
struct ethercom ic_ec;
int (*ic_newstate)(void *, enum ieee80211_state);
int (*ic_chancheck)(void *, u_char *);
u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
u_int8_t ic_sup_rates[IEEE80211_RATE_SIZE];
u_char ic_chan_avail[(IEEE80211_CHAN_MAX+1)/NBBY];
u_char ic_chan_active[(IEEE80211_CHAN_MAX+1)/NBBY];
struct ifqueue ic_mgtq;
int ic_flags;
enum ieee80211_state ic_state;
struct ieee80211_bss ic_bss;
u_int8_t ic_ibss_chan;
int ic_fixed_rate;
TAILQ_HEAD(, ieee80211_bss) ic_scan;
u_int16_t ic_lintval; /* listen interval */
int ic_mgt_timer; /* mgmt timeout */
int ic_scan_timer; /* scant wait */
int ic_des_esslen;
u_int8_t ic_des_essid[IEEE80211_NWID_LEN];
struct ieee80211_wepkey ic_nw_keys[IEEE80211_WEP_NKID];
int ic_wep_txkey;
void *ic_wep_ctx;
};
#define ic_if ic_ec.ec_if
#define ic_softc ic_ec.ec_if.if_softc
/* ic_flags */
#define IEEE80211_F_ASCAN 0x00000001 /* STATUS: active scan */
#define IEEE80211_F_SIBSS 0x00000002 /* STATUS: start IBSS */
#define IEEE80211_F_WEPON 0x00000100 /* CONF: WEP enabled */
#define IEEE80211_F_IBSSON 0x00000200 /* CONF: IBSS creation enable */
#define IEEE80211_F_PMGTON 0x00000400 /* CONF: Power mgmt enable */
#define IEEE80211_F_ADHOC 0x00000800 /* CONF: adhoc mode */
#define IEEE80211_F_HASWEP 0x00010000 /* CAPABILITY: WEP available */
#define IEEE80211_F_HASIBSS 0x00020000 /* CAPABILITY: IBSS available */
#define IEEE80211_F_HASPMGT 0x00040000 /* CAPABILITY: Power mgmt */
/* flags for ieee80211_fix_rate */
#define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */
#define IEEE80211_F_DOFRATE 0x00000002 /* use fixed rate */
#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
#define IEEE80211_F_DODEL 0x00000008 /* delete ignore rate */
void ieee80211_ifattach(struct ifnet *);
void ieee80211_ifdetach(struct ifnet *);
void ieee80211_input(struct ifnet *, struct mbuf *, int, u_int);
int ieee80211_mgmt_output(struct ifnet *, struct mbuf *, int);
struct mbuf *ieee80211_encap(struct ifnet *, struct mbuf *);
struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *);
int ieee80211_ioctl(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 *);
void ieee80211_next_scan(struct ifnet *);
void ieee80211_end_scan(struct ifnet *);
void ieee80211_free_scan(struct ifnet *);
int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_bss *, int);
int ieee80211_new_state(struct ifnet *, enum ieee80211_state, int);
struct mbuf *ieee80211_wep_crypt(struct ifnet *, struct mbuf *, int);
int ieee80211_cfgget(struct ifnet *, u_long, caddr_t);
int ieee80211_cfgset(struct ifnet *, u_long, caddr_t);
#endif /* _KERNEL */
#endif /* _NET_IF_IEEE80211_H_ */

2192
sys/net/if_ieee80211subr.c Normal file

File diff suppressed because it is too large Load Diff