cleanup haeders.
add opt_awi.h to define AWI_DEBUG, AWI_WEP_ARC4. show the firmware version at attach. create a framework to support WEP (encryption code is not included for now). a new wiconfig compatible ioctl interface replaced the awictl interface. fix memory leak in selecting AP fix bugs in ESSID selection changes from FreeBSD-current by Warner Losh: revision 1.2 date: 2000/04/17 22:58:15; author: imp; state: Exp; lines: +16 -1 Provide mem* for compat with NetBSD to fix LINT fixes from FreeBSD-current by Guido van Rooij: revision 1.4 date: 2000/05/29 19:58:10; author: guido; state: Exp; lines: +5 -2 Fix a panic resulting from an obvious null pointer deref. Apparently some other panics still exist in this driver, but with this fix, it was at least possible to run the Nokia card at SANE 2000.
This commit is contained in:
parent
e802a7df62
commit
4da3935bae
|
@ -1,10 +1,10 @@
|
|||
# $NetBSD: Makefile,v 1.11 2000/05/07 00:29:03 wiz Exp $
|
||||
# $NetBSD: Makefile,v 1.12 2000/06/09 05:31:15 onoe Exp $
|
||||
|
||||
INCSDIR= /usr/include/dev/ic
|
||||
|
||||
INCS= ad1848reg.h ahareg.h ahavar.h aic6360reg.h aic6360var.h \
|
||||
aic77xxreg.h aic77xxvar.h aic7xxxvar.h am7930reg.h am7990reg.h \
|
||||
am7990var.h awictl.h bhareg.h bhavar.h bt431reg.h bt459reg.h \
|
||||
am7990var.h bhareg.h bhavar.h bt431reg.h bt459reg.h \
|
||||
bt463reg.h bt485reg.h bt8xx.h cacreg.h cacvar.h cd1190reg.h \
|
||||
cd1400reg.h comreg.h comvar.h cs4231reg.h cyreg.h \
|
||||
cyvar.h dc21040reg.h dp8390reg.h dp8390var.h dptreg.h dptvar.h ds.h \
|
||||
|
|
348
sys/dev/ic/awi.c
348
sys/dev/ic/awi.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: awi.c,v 1.17 2000/05/29 17:37:12 jhawk Exp $ */
|
||||
/* $NetBSD: awi.c,v 1.18 2000/06/09 05:31:15 onoe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -48,23 +48,14 @@
|
|||
* and to support adhoc mode by Atsushi Onoe <onoe@netbsd.org>
|
||||
*/
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include "opt_awi.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ns.h"
|
||||
#include "bpfilter.h"
|
||||
#include "rnd.h"
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD__ >= 3
|
||||
#include "opt_inet.h"
|
||||
#endif
|
||||
#if __FreeBSD__ >= 4
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
|
||||
#include "bpf.h"
|
||||
#define NBPFILTER NBPF
|
||||
#else
|
||||
#include "bpfilter.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -73,22 +64,14 @@
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/sockio.h>
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <sys/errno.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/select.h>
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
|
||||
#include <sys/bus.h>
|
||||
#else
|
||||
#include <sys/device.h>
|
||||
#endif
|
||||
#if NRND > 0
|
||||
#include <sys/rnd.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
|
@ -113,11 +96,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NS
|
||||
#include <netns/ns.h>
|
||||
#include <netns/ns_if.h>
|
||||
#endif
|
||||
|
||||
#if NBPFILTER > 0
|
||||
#include <net/bpf.h>
|
||||
#include <net/bpfdesc.h>
|
||||
|
@ -137,14 +115,12 @@
|
|||
#include <dev/ic/am79c930var.h>
|
||||
#include <dev/ic/awireg.h>
|
||||
#include <dev/ic/awivar.h>
|
||||
#include <dev/ic/awictl.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <dev/awi/am79c930reg.h>
|
||||
#include <dev/awi/am79c930var.h>
|
||||
#include <dev/awi/awireg.h>
|
||||
#include <dev/awi/awivar.h>
|
||||
#include <dev/awi/awictl.h>
|
||||
#endif
|
||||
|
||||
static int awi_ioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
|
||||
|
@ -154,10 +130,6 @@ static int awi_media_opt2rate __P((struct awi_softc *sc, int opt));
|
|||
static int awi_media_change __P((struct ifnet *ifp));
|
||||
static void awi_media_status __P((struct ifnet *ifp, struct ifmediareq *imr));
|
||||
#endif
|
||||
static int awi_drvget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
|
||||
static int awi_drvset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
|
||||
static int awi_init __P((struct awi_softc *sc));
|
||||
static void awi_stop __P((struct awi_softc *sc));
|
||||
static void awi_watchdog __P((struct ifnet *ifp));
|
||||
static void awi_start __P((struct ifnet *ifp));
|
||||
static void awi_txint __P((struct awi_softc *sc));
|
||||
|
@ -165,12 +137,11 @@ static struct mbuf * awi_fix_txhdr __P((struct awi_softc *sc, struct mbuf *m0));
|
|||
static struct mbuf * awi_fix_rxhdr __P((struct awi_softc *sc, struct mbuf *m0));
|
||||
static void awi_input __P((struct awi_softc *sc, struct mbuf *m, u_int32_t rxts, u_int8_t rssi));
|
||||
static void awi_rxint __P((struct awi_softc *sc));
|
||||
struct mbuf * awi_devget __P((struct awi_softc *sc, u_int32_t off, u_int16_t len));
|
||||
static struct mbuf * awi_devget __P((struct awi_softc *sc, u_int32_t off, u_int16_t len));
|
||||
static int awi_init_hw __P((struct awi_softc *sc));
|
||||
static int awi_init_mibs __P((struct awi_softc *sc));
|
||||
static int awi_init_txrx __P((struct awi_softc *sc));
|
||||
static void awi_stop_txrx __P((struct awi_softc *sc));
|
||||
static int awi_init_region __P((struct awi_softc *sc));
|
||||
static int awi_start_scan __P((struct awi_softc *sc));
|
||||
static int awi_next_scan __P((struct awi_softc *sc));
|
||||
static void awi_stop_scan __P((struct awi_softc *sc));
|
||||
|
@ -227,10 +198,6 @@ int awi_dump_len = 28;
|
|||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD__ < 4
|
||||
#define memset(p, v, n) bzero(p, n) /*XXX*/
|
||||
#endif
|
||||
|
||||
#if __FreeBSD__ >= 4
|
||||
devclass_t awi_devclass;
|
||||
#endif
|
||||
|
@ -254,17 +221,16 @@ awi_attach(sc)
|
|||
struct awi_softc *sc;
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int s;
|
||||
int error;
|
||||
#ifdef IFM_IEEE80211
|
||||
int i;
|
||||
u_int8_t *phy_rates;
|
||||
int mword;
|
||||
struct ifmediareq imr;
|
||||
#endif
|
||||
int s;
|
||||
int error;
|
||||
|
||||
s = splnet();
|
||||
|
||||
/*
|
||||
* Even if we can sleep in initialization state,
|
||||
* all other processes (e.g. ifconfig) have to wait for
|
||||
|
@ -307,10 +273,13 @@ awi_attach(sc)
|
|||
ETHER_ADDR_LEN);
|
||||
#endif
|
||||
|
||||
printf("%s: IEEE802.11 (%s %dMbps) address %s\n",
|
||||
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
|
||||
printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n",
|
||||
sc->sc_dev.dv_xname,
|
||||
sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH ? "FH" : "DS",
|
||||
sc->sc_tx_rate / 10, ether_sprintf(sc->sc_mib_addr.aMAC_Address));
|
||||
sc->sc_tx_rate / 10, sc->sc_banner);
|
||||
printf("%s: address %s\n",
|
||||
sc->sc_dev.dv_xname, ether_sprintf(sc->sc_mib_addr.aMAC_Address));
|
||||
if_attach(ifp);
|
||||
#ifdef __FreeBSD__
|
||||
ether_ifattach(ifp);
|
||||
|
@ -369,6 +338,8 @@ awi_detach(sc)
|
|||
wakeup(sc);
|
||||
(void)tsleep(sc, PWAIT, "awidet", 1);
|
||||
}
|
||||
if (sc->sc_wep_ctx != NULL)
|
||||
free(sc->sc_wep_ctx, M_DEVBUF);
|
||||
#if NBPFILTER > 0
|
||||
bpfdetach(ifp);
|
||||
#endif
|
||||
|
@ -410,27 +381,36 @@ awi_activate(self, act)
|
|||
|
||||
return error;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
void
|
||||
awi_reset(sc)
|
||||
awi_power(sc, why)
|
||||
struct awi_softc *sc;
|
||||
int why;
|
||||
{
|
||||
int s;
|
||||
int ocansleep;
|
||||
|
||||
if (!sc->sc_enabled)
|
||||
return;
|
||||
|
||||
s = splnet();
|
||||
sc->sc_invalid = 1;
|
||||
awi_stop(sc);
|
||||
if (sc->sc_disable)
|
||||
(*sc->sc_disable)(sc);
|
||||
sc->sc_enabled = 0;
|
||||
DELAY(1000);
|
||||
sc->sc_invalid = 0;
|
||||
(void)awi_init(sc);
|
||||
ocansleep = sc->sc_cansleep;
|
||||
sc->sc_cansleep = 0;
|
||||
#ifdef needtobefixed /*ONOE*/
|
||||
if (why == PWR_RESUME) {
|
||||
sc->sc_enabled = 0;
|
||||
awi_init(sc);
|
||||
(void)awi_intr(sc);
|
||||
} else {
|
||||
awi_stop(sc);
|
||||
if (sc->sc_disable)
|
||||
(*sc->sc_disable)(sc);
|
||||
}
|
||||
#endif
|
||||
sc->sc_cansleep = ocansleep;
|
||||
splx(s);
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
static int
|
||||
awi_ioctl(ifp, cmd, data)
|
||||
|
@ -486,6 +466,9 @@ awi_ioctl(ifp, cmd, data)
|
|||
ether_addmulti(ifr, &sc->sc_ec) :
|
||||
ether_delmulti(ifr, &sc->sc_ec);
|
||||
#endif
|
||||
/*
|
||||
* Do not rescan BSS. Rather, just reset multicast filter.
|
||||
*/
|
||||
if (error == ENETRESET) {
|
||||
if (sc->sc_enabled)
|
||||
error = awi_init(sc);
|
||||
|
@ -534,14 +517,8 @@ awi_ioctl(ifp, cmd, data)
|
|||
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
|
||||
break;
|
||||
#endif
|
||||
case SIOCGDRVSPEC:
|
||||
error = awi_drvget(ifp, cmd, data);
|
||||
break;
|
||||
case SIOCSDRVSPEC:
|
||||
error = awi_drvset(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
error = awi_wicfg(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
awi_unlock(sc);
|
||||
|
@ -685,187 +662,6 @@ awi_media_status(ifp, imr)
|
|||
}
|
||||
#endif /* IFM_IEEE80211 */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The following stuff is partially duplicated with SIOC[GS]IFMEDIA and
|
||||
* SIOC[GS]80211NWID, which should be integrated as well as other common
|
||||
* stuff among 802.11 wireless LAN drivers.
|
||||
*/
|
||||
|
||||
static int
|
||||
awi_drvget(ifp, cmd, data)
|
||||
struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
struct awi_softc *sc = ifp->if_softc;
|
||||
struct ifdrv *ifd = (struct ifdrv *)data;
|
||||
u_int8_t buf[AWICTL_BUFSIZE];
|
||||
u_int8_t *essid;
|
||||
int error = 0;
|
||||
|
||||
switch (ifd->ifd_cmd) {
|
||||
case AWICTL_REGION:
|
||||
if (ifd->ifd_len < 1)
|
||||
return ENOSPC;
|
||||
ifd->ifd_len = 1;
|
||||
buf[0] = sc->sc_mib_phy.aCurrent_Reg_Domain;
|
||||
break;
|
||||
case AWICTL_CHANSET:
|
||||
if (ifd->ifd_len < 3)
|
||||
return ENOSPC;
|
||||
ifd->ifd_len = 3;
|
||||
buf[0] = sc->sc_bss.chanset;
|
||||
buf[1] = sc->sc_scan_min;
|
||||
buf[2] = sc->sc_scan_max;
|
||||
break;
|
||||
case AWICTL_RAWBPF:
|
||||
if (ifd->ifd_len < 1)
|
||||
return ENOSPC;
|
||||
ifd->ifd_len = 1;
|
||||
buf[0] = sc->sc_rawbpf;
|
||||
break;
|
||||
case AWICTL_DESSID:
|
||||
case AWICTL_CESSID:
|
||||
if (ifd->ifd_cmd == AWICTL_DESSID)
|
||||
essid = sc->sc_mib_mac.aDesired_ESS_ID;
|
||||
else
|
||||
essid = sc->sc_bss.essid;
|
||||
if (ifd->ifd_len < essid[1])
|
||||
return ENOSPC;
|
||||
ifd->ifd_len = essid[1];
|
||||
if (ifd->ifd_len > 0)
|
||||
memcpy(buf, essid, ifd->ifd_len);
|
||||
break;
|
||||
case AWICTL_MODE:
|
||||
if (ifd->ifd_len < 1)
|
||||
return ENOSPC;
|
||||
ifd->ifd_len = 1;
|
||||
if (sc->sc_mib_local.Network_Mode == 0) {
|
||||
if (sc->sc_no_bssid)
|
||||
buf[0] = AWICTL_MODE_NOBSSID;
|
||||
else
|
||||
buf[0] = AWICTL_MODE_ADHOC;
|
||||
} else
|
||||
buf[0] = AWICTL_MODE_INFRA;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (error == 0 && ifd->ifd_len > 0)
|
||||
error = copyout(ifd->ifd_data, buf, ifd->ifd_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
awi_drvset(ifp, cmd, data)
|
||||
struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
struct awi_softc *sc = ifp->if_softc;
|
||||
struct ifdrv *ifd = (struct ifdrv *)data;
|
||||
u_int8_t buf[AWICTL_BUFSIZE];
|
||||
u_int8_t oregion;
|
||||
int error = 0;
|
||||
|
||||
if (ifd->ifd_len > sizeof(buf))
|
||||
return EINVAL;
|
||||
error = copyin(ifd->ifd_data, buf, ifd->ifd_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
switch (ifd->ifd_cmd) {
|
||||
case AWICTL_REGION:
|
||||
if (ifd->ifd_len != 1)
|
||||
return EINVAL;
|
||||
oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
|
||||
if (buf[0] == oregion)
|
||||
break;
|
||||
sc->sc_mib_phy.aCurrent_Reg_Domain = buf[0];
|
||||
error = awi_init_region(sc);
|
||||
if (error) {
|
||||
sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
|
||||
break;
|
||||
}
|
||||
if (sc->sc_enabled) {
|
||||
awi_stop(sc);
|
||||
error = awi_init(sc);
|
||||
}
|
||||
break;
|
||||
case AWICTL_CHANSET:
|
||||
if (ifd->ifd_len != 3)
|
||||
return EINVAL;
|
||||
/* reset scan min/max */
|
||||
awi_init_region(sc);
|
||||
if (buf[0] < sc->sc_scan_min || buf[0] > sc->sc_scan_max ||
|
||||
buf[1] < sc->sc_scan_min || buf[1] > sc->sc_scan_max ||
|
||||
buf[2] < sc->sc_scan_min || buf[2] > sc->sc_scan_max)
|
||||
return EINVAL;
|
||||
sc->sc_scan_cur = buf[0];
|
||||
sc->sc_scan_min = buf[1];
|
||||
sc->sc_scan_max = buf[2];
|
||||
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
|
||||
sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
|
||||
if (sc->sc_enabled) {
|
||||
awi_stop(sc);
|
||||
error = awi_init(sc);
|
||||
}
|
||||
break;
|
||||
case AWICTL_RAWBPF:
|
||||
if (ifd->ifd_len != 1)
|
||||
return EINVAL;
|
||||
sc->sc_rawbpf = buf[0];
|
||||
break;
|
||||
case AWICTL_DESSID:
|
||||
if (ifd->ifd_len > IEEE80211_NWID_LEN)
|
||||
return EINVAL;
|
||||
if (sc->sc_mib_mac.aDesired_ESS_ID[1] == ifd->ifd_len &&
|
||||
memcmp(&sc->sc_mib_mac.aDesired_ESS_ID[2], buf,
|
||||
ifd->ifd_len) == 0)
|
||||
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] = ifd->ifd_len;
|
||||
memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], buf, ifd->ifd_len);
|
||||
if (sc->sc_enabled) {
|
||||
awi_stop(sc);
|
||||
error = awi_init(sc);
|
||||
}
|
||||
break;
|
||||
case AWICTL_CESSID:
|
||||
error = EINVAL;
|
||||
break;
|
||||
case AWICTL_MODE:
|
||||
switch (buf[0]) {
|
||||
case AWICTL_MODE_INFRA:
|
||||
sc->sc_mib_local.Network_Mode = 1;
|
||||
sc->sc_no_bssid = 0;
|
||||
break;
|
||||
case AWICTL_MODE_ADHOC:
|
||||
sc->sc_mib_local.Network_Mode = 0;
|
||||
sc->sc_no_bssid = 0;
|
||||
break;
|
||||
case AWICTL_MODE_NOBSSID:
|
||||
sc->sc_mib_local.Network_Mode = 0;
|
||||
sc->sc_no_bssid = 1;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
if (sc->sc_enabled) {
|
||||
awi_stop(sc);
|
||||
error = awi_init(sc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
awi_intr(arg)
|
||||
void *arg;
|
||||
|
@ -917,7 +713,7 @@ awi_intr(arg)
|
|||
return handled;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
awi_init(sc)
|
||||
struct awi_softc *sc;
|
||||
{
|
||||
|
@ -1005,7 +801,7 @@ awi_init(sc)
|
|||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
awi_stop(sc)
|
||||
struct awi_softc *sc;
|
||||
{
|
||||
|
@ -1036,8 +832,10 @@ awi_stop(sc)
|
|||
break;
|
||||
m_freem(m);
|
||||
}
|
||||
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL)
|
||||
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
|
||||
TAILQ_REMOVE(&sc->sc_scan, bp, list);
|
||||
free(bp, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1111,14 +909,22 @@ awi_start(ifp)
|
|||
IF_DEQUEUE(&ifp->if_snd, m0);
|
||||
if (m0 == NULL)
|
||||
break;
|
||||
if (awi_next_txd(sc, m0->m_pkthdr.len +
|
||||
sizeof(struct ieee80211_frame), &frame, &ntxd)) {
|
||||
len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
|
||||
if (sc->sc_format_llc)
|
||||
len += sizeof(struct llc) -
|
||||
sizeof(struct ether_header);
|
||||
if (sc->sc_wep_algo != NULL)
|
||||
len += IEEE80211_WEP_IVLEN +
|
||||
IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
|
||||
if (awi_next_txd(sc, len, &frame, &ntxd)) {
|
||||
IF_PREPEND(&ifp->if_snd, m0);
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
break;
|
||||
}
|
||||
AWI_BPF_MTAP(sc, m0, AWI_BPF_NORM);
|
||||
m0 = awi_fix_txhdr(sc, m0);
|
||||
if (sc->sc_wep_algo != NULL && m0 != NULL)
|
||||
m0 = awi_wep_encrypt(sc, m0, 1);
|
||||
if (m0 == NULL) {
|
||||
ifp->if_oerrors++;
|
||||
continue;
|
||||
|
@ -1288,6 +1094,8 @@ awi_input(sc, m, rxts, rssi)
|
|||
struct ether_header *eh;
|
||||
#endif
|
||||
|
||||
/* trim CRC here for WEP can find its own CRC at the end of packet. */
|
||||
m_adj(m, -ETHER_CRC_LEN);
|
||||
AWI_BPF_MTAP(sc, m, AWI_BPF_RAW);
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
|
||||
|
@ -1295,8 +1103,17 @@ awi_input(sc, m, rxts, rssi)
|
|||
printf("%s; receive packet with wrong version: %x\n",
|
||||
sc->sc_dev.dv_xname, wh->i_fc[0]);
|
||||
m_freem(m);
|
||||
ifp->if_ierrors++;
|
||||
return;
|
||||
}
|
||||
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
|
||||
m = awi_wep_encrypt(sc, m, 0);
|
||||
if (m == NULL) {
|
||||
ifp->if_ierrors++;
|
||||
return;
|
||||
}
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
}
|
||||
#ifdef AWI_DEBUG
|
||||
if (awi_dump)
|
||||
awi_dump_pkt(sc, m, rssi);
|
||||
|
@ -1330,14 +1147,14 @@ awi_input(sc, m, rxts, rssi)
|
|||
break;
|
||||
}
|
||||
ifp->if_ipackets++;
|
||||
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
|
||||
AWI_BPF_MTAP(sc, m, AWI_BPF_NORM);
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
m->m_flags |= M_HASFCS;
|
||||
(*ifp->if_input)(ifp, m);
|
||||
#else
|
||||
eh = mtod(m, struct ether_header *);
|
||||
m_adj(m, sizeof(*eh));
|
||||
m_adj(m, -ETHER_CRC_LEN);
|
||||
ether_input(ifp, eh, m);
|
||||
#endif
|
||||
break;
|
||||
|
@ -1423,22 +1240,25 @@ awi_rxint(sc)
|
|||
sc->sc_rxdoff = rxoff;
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
static struct mbuf *
|
||||
awi_devget(sc, off, len)
|
||||
struct awi_softc *sc;
|
||||
u_int32_t off;
|
||||
u_int16_t len;
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct mbuf *top, **mp = ⊤
|
||||
struct mbuf *top, **mp;
|
||||
u_int tlen;
|
||||
|
||||
top = sc->sc_rxpend;
|
||||
mp = ⊤
|
||||
if (top != NULL) {
|
||||
sc->sc_rxpend = NULL;
|
||||
top->m_pkthdr.len += len;
|
||||
while ((m = *mp) != NULL)
|
||||
while (*mp != NULL) {
|
||||
m = *mp;
|
||||
mp = &m->m_next;
|
||||
}
|
||||
if (m->m_flags & M_EXT)
|
||||
tlen = m->m_ext.ext_size;
|
||||
else if (m->m_flags & M_PKTHDR)
|
||||
|
@ -1497,7 +1317,6 @@ awi_init_hw(sc)
|
|||
u_int8_t status;
|
||||
u_int16_t intmask;
|
||||
int i, error;
|
||||
u_int8_t banner[AWI_BANNER_LEN];
|
||||
|
||||
sc->sc_enab_intr = 0;
|
||||
awi_drvstate(sc, AWI_DRV_RESET);
|
||||
|
@ -1534,12 +1353,12 @@ awi_init_hw(sc)
|
|||
}
|
||||
|
||||
/* check banner to confirm firmware write it */
|
||||
awi_read_bytes(sc, AWI_BANNER, banner, AWI_BANNER_LEN);
|
||||
if (memcmp(banner, "PCnetMobile:", 12) != 0) {
|
||||
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
|
||||
if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
|
||||
printf("%s: failed to complete selftest (bad banner)\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
for (i = 0; i < AWI_BANNER_LEN; i++)
|
||||
printf("%s%02x", i ? ":" : "\t", banner[i]);
|
||||
printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
|
||||
printf("\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
@ -1679,7 +1498,7 @@ awi_stop_txrx(sc)
|
|||
(void)awi_cmd(sc, AWI_CMD_FLUSH_TX);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
awi_init_region(sc)
|
||||
struct awi_softc *sc;
|
||||
{
|
||||
|
@ -1707,7 +1526,6 @@ awi_init_region(sc)
|
|||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
sc->sc_scan_cur = sc->sc_scan_min;
|
||||
sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
|
||||
} else {
|
||||
switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
|
||||
|
@ -1741,6 +1559,7 @@ awi_init_region(sc)
|
|||
return EINVAL;
|
||||
}
|
||||
}
|
||||
sc->sc_ownch = sc->sc_scan_cur;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1749,19 +1568,24 @@ awi_start_scan(sc)
|
|||
struct awi_softc *sc;
|
||||
{
|
||||
int error = 0;
|
||||
struct awi_bss *bp;
|
||||
|
||||
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
|
||||
TAILQ_REMOVE(&sc->sc_scan, bp, list);
|
||||
free(bp, M_DEVBUF);
|
||||
}
|
||||
if (!sc->sc_mib_local.Network_Mode && sc->sc_no_bssid) {
|
||||
memset(&sc->sc_bss, 0, sizeof(sc->sc_bss));
|
||||
sc->sc_bss.rxtime = 0;
|
||||
memcpy(sc->sc_bss.essid, &sc->sc_mib_mac.aDesired_ESS_ID,
|
||||
sizeof(sc->sc_bss.essid));
|
||||
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
|
||||
sc->sc_bss.chanset = sc->sc_scan_set;
|
||||
sc->sc_bss.pattern = sc->sc_scan_cur;
|
||||
sc->sc_bss.chanset = sc->sc_ownch % 3 + 1;
|
||||
sc->sc_bss.pattern = sc->sc_ownch;
|
||||
sc->sc_bss.index = 1;
|
||||
sc->sc_bss.dwell_time = 19; /*XXX*/
|
||||
} else
|
||||
sc->sc_bss.chanset = sc->sc_scan_cur;
|
||||
sc->sc_bss.chanset = sc->sc_ownch;
|
||||
sc->sc_status = AWI_ST_SETSS;
|
||||
error = awi_set_ss(sc);
|
||||
} else {
|
||||
|
@ -1836,13 +1660,13 @@ awi_stop_scan(sc)
|
|||
* during my scan. So we retries to associate with
|
||||
* it unless there are any suitable AP.
|
||||
*/
|
||||
if (bp->fails < 3)
|
||||
if (bp->fails++ < 3)
|
||||
continue;
|
||||
bp->fails = 0;
|
||||
}
|
||||
if (sc->sc_mib_mac.aDesired_ESS_ID[1] != 0 &&
|
||||
memcmp(&sc->sc_mib_mac.aDesired_ESS_ID, bp->essid,
|
||||
sizeof(bp->essid) != 0))
|
||||
sizeof(bp->essid)) != 0)
|
||||
continue;
|
||||
/*
|
||||
* Since the firmware apparently scans not only the specified
|
||||
|
@ -2336,8 +2160,6 @@ awi_recv_asresp(sc, m0)
|
|||
sc->sc_status = AWI_ST_RUNNING;
|
||||
sc->sc_ifp->if_flags |= IFF_RUNNING;
|
||||
awi_drvstate(sc, AWI_DRV_INFASSOC);
|
||||
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL)
|
||||
TAILQ_REMOVE(&sc->sc_scan, bp, list);
|
||||
awi_start(sc->sc_ifp);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,450 @@
|
|||
/* $NetBSD: awi_wep.c,v 1.1 2000/06/09 05:31:16 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "opt_awi.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.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>
|
||||
#include <net/if_dl.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/am79c930reg.h>
|
||||
#include <dev/ic/am79c930var.h>
|
||||
#include <dev/ic/awireg.h>
|
||||
#include <dev/ic/awivar.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <dev/awi/am79c930reg.h>
|
||||
#include <dev/awi/am79c930var.h>
|
||||
#include <dev/awi/awireg.h>
|
||||
#include <dev/awi/awivar.h>
|
||||
#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));
|
||||
|
||||
#ifdef AWI_WEP_ARC4
|
||||
extern int awi_arc4_ctxlen __P((void));
|
||||
extern void awi_arc4_setkey __P((void *ctx, u_int8_t *key, int keylen));
|
||||
extern void awi_arc4_encrypt __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
|
||||
#endif
|
||||
#ifdef AWI_WEP_DES3
|
||||
extern int awi_des3_ctxlen __P((void));
|
||||
extern void awi_des3_setkey __P((void *ctx, u_int8_t *key, int keylen));
|
||||
extern void awi_des3_encrypt __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
|
||||
#endif
|
||||
|
||||
/* XXX: the order should be known to wiconfig/user */
|
||||
|
||||
static struct awi_wep_algo awi_wep_algo[] = {
|
||||
{ "no" }, /* dummy for no wep */
|
||||
|
||||
#ifdef AWI_WEP_ARC4
|
||||
{ "arc4", awi_arc4_ctxlen, awi_arc4_setkey,
|
||||
awi_arc4_encrypt, awi_arc4_encrypt },
|
||||
#else
|
||||
{ NULL }, /* not supported */
|
||||
#endif
|
||||
|
||||
#ifdef AWI_WEP_DES3
|
||||
{ "des3", awi_des3_ctxlen, awi_des3_setkey,
|
||||
awi_des3_encrypt, awi_des3_decrypt },
|
||||
#else
|
||||
{ NULL }, /* not supported */
|
||||
#endif
|
||||
|
||||
{ "null", awi_null_ctxlen, awi_null_setkey,
|
||||
awi_null_copy, awi_null_copy },
|
||||
/* dummy for wep without encryption */
|
||||
};
|
||||
|
||||
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;
|
||||
{
|
||||
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;
|
||||
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 {
|
||||
wh = mtod(n, struct ieee80211_frame *);
|
||||
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[3] = kid & 0x03; /* clear pad and keyid */
|
||||
noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
|
||||
} else {
|
||||
ivp = mtod(m, u_int8_t *) + moff;
|
||||
moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
|
||||
kid = ivp[IEEE80211_WEP_IVLEN] & 0x03;
|
||||
}
|
||||
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;
|
||||
noff = 0;
|
||||
for (; noff < sizeof(crcbuf); noff += len, m = m->m_next) {
|
||||
if (m->m_len < moff + len)
|
||||
len = m->m_len - moff;
|
||||
if (len == 0)
|
||||
continue;
|
||||
awa->awa_decrypt(ctx, crcbuf + noff,
|
||||
mtod(m, caddr_t) + moff, len);
|
||||
}
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,584 @@
|
|||
/* $NetBSD: awi_wicfg.c,v 1.1 2000/06/09 05:31:17 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 "opt_awi.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.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>
|
||||
#include <net/if_dl.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/am79c930reg.h>
|
||||
#include <dev/ic/am79c930var.h>
|
||||
#include <dev/ic/awireg.h>
|
||||
#include <dev/ic/awivar.h>
|
||||
|
||||
#include <dev/pcmcia/if_wi_ieee.h> /* XXX */
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <dev/awi/am79c930reg.h>
|
||||
#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:
|
||||
error = suser(curproc->p_ucred, &curproc->p_acflag);
|
||||
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_scan_cur;
|
||||
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_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_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;
|
||||
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 &&
|
||||
!sc->sc_no_bssid && sc->sc_start_bss)
|
||||
error = ENETRESET;
|
||||
break;
|
||||
case WI_RID_CURRENT_CHAN:
|
||||
error = EPERM;
|
||||
break;
|
||||
case WI_RID_COMMS_QUALITY:
|
||||
error = EPERM;
|
||||
break;
|
||||
case WI_RID_PROMISC:
|
||||
error = EPERM;
|
||||
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:
|
||||
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:
|
||||
/* 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_SYSTEM_SCALE:
|
||||
error = EINVAL; /* not supported */
|
||||
break;
|
||||
case WI_RID_PM_ENABLED:
|
||||
case WI_RID_MAX_SLEEP:
|
||||
error = EINVAL; /* not implemented */
|
||||
break;
|
||||
case WI_RID_WEP_AVAIL:
|
||||
error = EPERM;
|
||||
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(sc);
|
||||
error = awi_init(sc);
|
||||
} else
|
||||
error = 0;
|
||||
}
|
||||
return error;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/* $NetBSD: awictl.h,v 1.1 2000/03/23 06:04:24 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.
|
||||
*/
|
||||
|
||||
#ifndef _IC_AWICTL_H
|
||||
#define _IC_AWICTL_H
|
||||
|
||||
#define AWICTL_BUFSIZE 32
|
||||
|
||||
#define AWICTL_REGION 1 /* u_int8_t: region code */
|
||||
#define AWICTL_CHANSET 2 /* u_int8_t[3]: cur, min, max */
|
||||
#define AWICTL_RAWBPF 3 /* u_int8_t: pass raw 802.11 header to bpf */
|
||||
#define AWICTL_DESSID 4 /* u_int8_t[IEEE80211_NWID_LEN]: desired ESSID*/
|
||||
#define AWICTL_CESSID 5 /* u_int8_t[IEEE80211_NWID_LEN]: current ESSID*/
|
||||
#define AWICTL_MODE 6 /* u_int8_t: mode */
|
||||
#define AWICTL_MODE_INFRA 0 /* infrastructure mode */
|
||||
#define AWICTL_MODE_ADHOC 1 /* adhoc mode */
|
||||
#define AWICTL_MODE_NOBSSID 2 /* adhoc without bssid mode */
|
||||
|
||||
#ifndef SIOCSDRVSPEC
|
||||
#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv)
|
||||
#endif
|
||||
|
||||
#ifndef SIOCGDRVSPEC
|
||||
#define SIOCGDRVSPEC _IOWR('i', 122, struct ifdrv)
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
struct ifdrv {
|
||||
char ifd_name[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
unsigned long ifd_cmd;
|
||||
size_t ifd_len;
|
||||
void *ifd_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* !_IC_AWICTL_H */
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: awivar.h,v 1.8 2000/05/29 17:37:12 jhawk Exp $ */
|
||||
/* $NetBSD: awivar.h,v 1.9 2000/06/09 05:31:18 onoe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -47,6 +47,7 @@
|
|||
#define AWI_TRANS_TIMEOUT 2000
|
||||
|
||||
#define AWI_NTXBUFS 4
|
||||
#define AWI_MAX_KEYLEN 16
|
||||
|
||||
enum awi_status {
|
||||
AWI_ST_INIT,
|
||||
|
@ -76,6 +77,14 @@ struct awi_bss
|
|||
u_int8_t essid[IEEE80211_NWID_LEN + 2];
|
||||
};
|
||||
|
||||
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__
|
||||
|
@ -92,7 +101,6 @@ struct awi_softc
|
|||
struct device sc_dev;
|
||||
#endif
|
||||
struct arpcom sc_ec;
|
||||
struct callout_handle sc_tohandle;
|
||||
#endif
|
||||
struct am79c930_softc sc_chip;
|
||||
struct ifnet *sc_ifp;
|
||||
|
@ -123,6 +131,8 @@ struct awi_softc
|
|||
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;
|
||||
|
||||
int sc_rx_timer;
|
||||
u_int32_t sc_rxdoff;
|
||||
|
@ -137,6 +147,13 @@ struct awi_softc
|
|||
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 */
|
||||
struct awi_wep_algo *sc_wep_algo;
|
||||
|
||||
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;
|
||||
|
@ -186,4 +203,32 @@ void awi_reset __P((struct awi_softc *));
|
|||
#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
|
||||
|
||||
void awi_stop __P((struct awi_softc *sc));
|
||||
int awi_init __P((struct awi_softc *sc));
|
||||
int awi_init_region __P((struct awi_softc *));
|
||||
int awi_wicfg __P((struct ifnet *, u_long, caddr_t));
|
||||
|
||||
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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.pcmcia,v 1.27 2000/06/06 16:16:36 soren Exp $
|
||||
# $NetBSD: files.pcmcia,v 1.28 2000/06/09 05:31:19 onoe Exp $
|
||||
#
|
||||
# Config.new file and device description for machine-independent PCMCIA code.
|
||||
# Included by ports that need it.
|
||||
|
@ -93,8 +93,11 @@ file dev/pcmcia/if_ray.c ray
|
|||
# AMD 79c930-based 802.11 cards (including BayStack 650 FH card).
|
||||
device awi: arp, ether, ifnet
|
||||
attach awi at pcmcia with awi_pcmcia
|
||||
defopt opt_awi.h AWI_DEBUG
|
||||
file dev/pcmcia/if_awi_pcmcia.c awi_pcmcia
|
||||
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
|
||||
|
||||
# Xircom Ethernet cards
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_awi_pcmcia.c,v 1.14 2000/03/22 22:33:47 mycroft Exp $ */
|
||||
/* $NetBSD: if_awi_pcmcia.c,v 1.15 2000/06/09 05:31:19 onoe Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
|
@ -44,6 +44,7 @@
|
|||
* DS cards based on the same chipset.
|
||||
*/
|
||||
|
||||
#include "opt_awi.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ns.h"
|
||||
#include "bpfilter.h"
|
||||
|
@ -122,11 +123,6 @@ struct cfattach awi_pcmcia_ca = {
|
|||
awi_pcmcia_detach, awi_activate
|
||||
};
|
||||
|
||||
#if __NetBSD_Version__ <= 104120000
|
||||
#define PCMCIA_VENDOR_BAY 0x01eb /* Bay Networks */
|
||||
#define PCMCIA_PRODUCT_BAY_STACK_650 0x804
|
||||
#endif
|
||||
|
||||
static struct awi_pcmcia_product {
|
||||
u_int32_t app_vendor; /* vendor ID */
|
||||
u_int32_t app_product; /* product ID */
|
||||
|
@ -242,7 +238,6 @@ awi_pcmcia_find(psc, pa, cfe)
|
|||
{
|
||||
struct awi_softc *sc = &psc->sc_awi;
|
||||
int fail = 0;
|
||||
u_int8_t version[AWI_BANNER_LEN];
|
||||
|
||||
/*
|
||||
* see if we can read the firmware version sanely
|
||||
|
@ -270,9 +265,9 @@ awi_pcmcia_find(psc, pa, cfe)
|
|||
|
||||
DELAY(1000);
|
||||
|
||||
awi_read_bytes(sc, AWI_BANNER, version, AWI_BANNER_LEN);
|
||||
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
|
||||
|
||||
if (memcmp(version, "PCnetMobile:", 12) == 0)
|
||||
if (memcmp(sc->sc_banner, "PCnetMobile:", 12) == 0)
|
||||
return (0);
|
||||
|
||||
fail++;
|
||||
|
@ -433,12 +428,6 @@ awi_pcmcia_powerhook(why, arg)
|
|||
{
|
||||
struct awi_pcmcia_softc *psc = arg;
|
||||
struct awi_softc *sc = &psc->sc_awi;
|
||||
int ocansleep;
|
||||
|
||||
if (why == PWR_RESUME) {
|
||||
ocansleep = sc->sc_cansleep;
|
||||
sc->sc_cansleep = 0;
|
||||
awi_reset(sc);
|
||||
sc->sc_cansleep = ocansleep;
|
||||
}
|
||||
awi_power(sc, why);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ieee80211.h,v 1.2 2000/03/10 05:44:23 onoe Exp $ */
|
||||
/* $NetBSD: if_ieee80211.h,v 1.3 2000/06/09 05:31:20 onoe Exp $ */
|
||||
|
||||
|
||||
#ifndef _NET_IF_IEEE80211_H_
|
||||
|
@ -103,6 +103,11 @@ struct ieee80211_frame {
|
|||
#define IEEE80211_STATUS_CHALLENGE 15
|
||||
#define IEEE80211_STATUS_TIMEOUT 16
|
||||
|
||||
#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
|
||||
#define IEEE80211_WEP_IVLEN 3 /* 24bit */
|
||||
#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
|
||||
#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
|
||||
#define IEEE80211_WEP_NKID 4 /* number of key ids */
|
||||
|
||||
#define IEEE80211_NWID_LEN 32
|
||||
|
||||
|
|
Loading…
Reference in New Issue