From edfbc82ba6a3916e672798ad24460aca32dc0a38 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sat, 1 Apr 2006 10:06:39 +0000 Subject: [PATCH] Remove owi(4) (old wi) driver and adjust related bits. It's been replaced by the more generic wi(4) driver since Sep 5, 2004. --- etc/Makefile | 3 +- share/man/man9/ieee80211_ioctl.9 | 7 +- sys/conf/files | 6 +- sys/dev/netif/owi/Makefile | 7 - sys/dev/netif/owi/if_owi.c | 2961 ----------------------------- sys/dev/netif/owi/if_owi_pccard.c | 203 -- sys/dev/netif/owi/if_owi_pci.c | 232 --- sys/dev/netif/owi/if_wireg.h | 630 ------ sys/dev/netif/owi/if_wivar.h | 177 -- sys/dev/netif/owi/owi_hostap.c | 1284 ------------- sys/dev/netif/owi/wi_hostap.h | 137 -- 11 files changed, 5 insertions(+), 5642 deletions(-) delete mode 100644 sys/dev/netif/owi/Makefile delete mode 100644 sys/dev/netif/owi/if_owi.c delete mode 100644 sys/dev/netif/owi/if_owi_pccard.c delete mode 100644 sys/dev/netif/owi/if_owi_pci.c delete mode 100644 sys/dev/netif/owi/if_wireg.h delete mode 100644 sys/dev/netif/owi/if_wivar.h delete mode 100644 sys/dev/netif/owi/owi_hostap.c delete mode 100644 sys/dev/netif/owi/wi_hostap.h diff --git a/etc/Makefile b/etc/Makefile index ea9406db94..61cefcc4cb 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -1,6 +1,6 @@ # from: @(#)Makefile 5.11 (Berkeley) 5/21/91 # $FreeBSD: src/etc/Makefile,v 1.219.2.38 2003/03/04 09:49:00 ru Exp $ -# $DragonFly: src/etc/Makefile,v 1.105 2006/02/25 19:14:53 swildner Exp $ +# $DragonFly: src/etc/Makefile,v 1.106 2006/04/01 10:06:39 swildner Exp $ .if !defined(NO_SENDMAIL) SUBDIR= sendmail @@ -394,6 +394,7 @@ upgrade_etc: preupgrade .for splman in 0 bio clock high imp net softclock softtty statclock tty vm x csh -c "rm -f ${DESTDIR}/usr/share/man/{man,cat}9/spl${splman}.9.gz" .endfor + rm -f ${DESTDIR}/modules/if_owi.ko ldconfig -R .if !defined(BINARY_UPGRADE) # binary upgrade just copies these nodes .if !defined(NO_MAKEDEV) diff --git a/share/man/man9/ieee80211_ioctl.9 b/share/man/man9/ieee80211_ioctl.9 index eb466437ba..72816ea04c 100644 --- a/share/man/man9/ieee80211_ioctl.9 +++ b/share/man/man9/ieee80211_ioctl.9 @@ -25,7 +25,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $DragonFly: src/share/man/man9/ieee80211_ioctl.9,v 1.2 2005/08/05 22:35:10 swildner Exp $ +.\" $DragonFly: src/share/man/man9/ieee80211_ioctl.9,v 1.3 2006/04/01 10:06:39 swildner Exp $ .\" $Id: ieee80211_ioctl.9,v 1.2 2004/07/07 12:59:39 ru Exp $ .\" .Dd March 2, 2004 @@ -58,9 +58,7 @@ and .Fn ieee80211_cfgset functions implement a legacy interface for getting and setting 802.11 interface attributes respectively. -The interface is compatible with the RIDs implemented by the legacy -.Xr owi 4 -driver and used by the +The interface is used by the .Xr wicontrol 8 utility. .Pp @@ -82,7 +80,6 @@ in the driver's private soft state structure, so driver writers may prefer to use this as the catch-all in a switch statement to avoid code duplication. .\" .Sh SEE ALSO -.Xr owi 4 , .Xr ifconfig 8 , .Xr wicontrol 8 , .Xr ieee80211 9 , diff --git a/sys/conf/files b/sys/conf/files index 25d9d5e523..e1905d1f76 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.116 2006/04/01 02:55:36 sephe Exp $ +# $DragonFly: src/sys/conf/files,v 1.117 2006/04/01 10:06:39 swildner Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -386,10 +386,6 @@ dev/netif/vx/if_vx_pci.c optional vx pci dev/netif/wi/if_wi.c optional wi dev/netif/wi/if_wi_pccard.c optional wi pccard dev/netif/wi/if_wi_pci.c optional wi pci -dev/netif/owi/if_owi.c optional owi -dev/netif/owi/if_owi_pccard.c optional owi pccard -dev/netif/owi/if_owi_pci.c optional owi pci -dev/netif/owi/owi_hostap.c optional owi dev/netif/xe/if_xe.c optional xe dev/netif/xe/if_xe_pccard.c optional xe pccard vfs/gnu/ext2fs/ext2_alloc.c optional ext2fs diff --git a/sys/dev/netif/owi/Makefile b/sys/dev/netif/owi/Makefile deleted file mode 100644 index 5ae529efac..0000000000 --- a/sys/dev/netif/owi/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $DragonFly: src/sys/dev/netif/owi/Attic/Makefile,v 1.1 2004/09/05 13:34:56 joerg Exp $ - -KMOD= if_owi -SRCS= if_owi.c if_owi_pccard.c if_owi_pci.c owi_hostap.c \ - card_if.h device_if.h bus_if.h pci_if.h - -.include diff --git a/sys/dev/netif/owi/if_owi.c b/sys/dev/netif/owi/if_owi.c deleted file mode 100644 index 98e46c098f..0000000000 --- a/sys/dev/netif/owi/if_owi.c +++ /dev/null @@ -1,2961 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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 Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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. - * - * $FreeBSD: src/sys/dev/wi/if_wi.c,v 1.103.2.2 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/if_owi.c,v 1.15 2005/12/31 14:08:00 sephe Exp $ - */ - -/* - * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The WaveLAN/IEEE adapter is the second generation of the WaveLAN - * from Lucent. Unlike the older cards, the new ones are programmed - * entirely via a firmware-driven controller called the Hermes. - * Unfortunately, Lucent will not release the Hermes programming manual - * without an NDA (if at all). What they do release is an API library - * called the HCF (Hardware Control Functions) which is supposed to - * do the device-specific operations of a device driver for you. The - * publically available version of the HCF library (the 'HCF Light') is - * a) extremely gross, b) lacks certain features, particularly support - * for 802.11 frames, and c) is contaminated by the GNU Public License. - * - * This driver does not use the HCF or HCF Light at all. Instead, it - * programs the Hermes controller directly, using information gleaned - * from the HCF Light code and corresponding documentation. - * - * This driver supports the ISA, PCMCIA and PCI versions of the Lucent - * WaveLan cards (based on the Hermes chipset), as well as the newer - * Prism 2 chipsets with firmware from Intersil and Symbol. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "wi_hostap.h" -#include "if_wivar.h" -#include "if_wireg.h" - -#define WI_CMD_DEBUG 0x0038 /* prism2 debug */ - -static void wi_intr(void *); -static void wi_reset(struct wi_softc *); -static int wi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void wi_init(void *); -static void wi_start(struct ifnet *); -static void wi_stop(struct wi_softc *); -static void wi_watchdog(struct ifnet *); -static void wi_rxeof(struct wi_softc *); -static void wi_txeof(struct wi_softc *, int); -static void wi_update_stats(struct wi_softc *); -static void wi_setmulti(struct wi_softc *); - -static int wi_cmd(struct wi_softc *, int, int, int, int); -static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *); -static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *); -static int wi_read_data(struct wi_softc *, int, int, caddr_t, int); -static int wi_write_data(struct wi_softc *, int, int, caddr_t, int); -static int wi_seek(struct wi_softc *, int, int, int); -static int wi_alloc_nicmem(struct wi_softc *, int, int *); -static void wi_inquire(void *); -static void wi_setdef(struct wi_softc *, struct wi_req *); - -#ifdef WICACHE -static -void wi_cache_store(struct wi_softc *, struct mbuf *, unsigned short); -#endif - -static int wi_get_cur_ssid(struct wi_softc *, char *, int *); -static void wi_get_id(struct wi_softc *); -static int wi_media_change(struct ifnet *); -static void wi_media_status(struct ifnet *, struct ifmediareq *); - -static int wi_get_debug(struct wi_softc *, struct wi_req *); -static int wi_set_debug(struct wi_softc *, struct wi_req *); - -DECLARE_DUMMY_MODULE(if_wi); - -devclass_t owi_devclass; - -static struct wi_card_ident wi_card_ident[] = { - /* CARD_ID CARD_NAME FIRM_TYPE */ - { WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT }, - { WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT }, - { WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT }, - { WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL }, - { WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL }, - { WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL }, - { WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL }, - { WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL }, - { WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL }, - { WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL }, - { WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL }, - { WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL }, - { WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, - { WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, - { WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL }, - { WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, - { WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, - { WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL }, - { WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, - { WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, - { WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL }, - { WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, - { WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL }, - { WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, - { WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL }, - { 0, NULL, 0 }, -}; - -int -owi_generic_detach(device_t dev) -{ - struct wi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->arpcom.ac_if; - - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->wi_gone) { - device_printf(dev, "already unloaded\n"); - lwkt_serialize_exit(ifp->if_serializer); - return(ENODEV); - } - wi_stop(sc); - bus_teardown_intr(dev, sc->irq, sc->wi_intrhand); - sc->wi_gone = 1; - - lwkt_serialize_exit(ifp->if_serializer); - - /* Delete all remaining media. */ - ifmedia_removeall(&sc->ifmedia); - ether_ifdetach(ifp); - owi_free(dev); - - return(0); -} - -int -owi_generic_attach(device_t dev) -{ - struct wi_softc *sc; - struct wi_ltv_macaddr mac; - struct wi_ltv_gen gen; - struct ifnet *ifp; - int error; - - /* XXX maybe we need the splimp stuff here XXX */ - sc = device_get_softc(dev); - ifp = &sc->arpcom.ac_if; - callout_init(&sc->wi_stat_timer); - -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); -#endif - - /* Reset the NIC. */ - wi_reset(sc); - - /* - * Read the station address. - * And do it twice. I've seen PRISM-based cards that return - * an error when trying to read it the first time, which causes - * the probe to fail. - */ - mac.wi_type = WI_RID_MAC_NODE; - mac.wi_len = 4; - wi_read_record(sc, (struct wi_ltv_gen *)&mac); - if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) { - device_printf(dev, "mac read failed %d\n", error); - owi_free(dev); - return (error); - } - bcopy((char *)&mac.wi_mac_addr, - (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - - wi_get_id(sc); - - ifp->if_softc = sc; - if_initname(ifp, "wi", sc->wi_unit); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = wi_ioctl; - ifp->if_start = wi_start; - ifp->if_watchdog = wi_watchdog; - ifp->if_init = wi_init; - ifp->if_baudrate = 10000000; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); - ifq_set_ready(&ifp->if_snd); - - bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); - bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name, - sizeof(WI_DEFAULT_NODENAME) - 1); - - bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); - bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name, - sizeof(WI_DEFAULT_NETNAME) - 1); - - bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); - bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name, - sizeof(WI_DEFAULT_IBSS) - 1); - - sc->wi_portnum = WI_DEFAULT_PORT; - sc->wi_ptype = WI_PORTTYPE_BSS; - sc->wi_ap_density = WI_DEFAULT_AP_DENSITY; - sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH; - sc->wi_tx_rate = WI_DEFAULT_TX_RATE; - sc->wi_max_data_len = WI_DEFAULT_DATALEN; - sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS; - sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED; - sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP; - sc->wi_roaming = WI_DEFAULT_ROAMING; - sc->wi_authtype = WI_DEFAULT_AUTHTYPE; - sc->wi_authmode = IEEE80211_AUTH_OPEN; - - /* - * Read the default channel from the NIC. This may vary - * depending on the country where the NIC was purchased, so - * we can't hard-code a default and expect it to work for - * everyone. - */ - gen.wi_type = WI_RID_OWN_CHNL; - gen.wi_len = 2; - wi_read_record(sc, &gen); - sc->wi_channel = gen.wi_val; - - /* - * Set flags based on firmware version. - */ - switch (sc->sc_firmware_type) { - case WI_LUCENT: - sc->wi_flags |= WI_FLAGS_HAS_ROAMING; - if (sc->sc_sta_firmware_ver >= 60000) - sc->wi_flags |= WI_FLAGS_HAS_MOR; - if (sc->sc_sta_firmware_ver >= 60006) { - sc->wi_flags |= WI_FLAGS_HAS_IBSS; - sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; - } - sc->wi_ibss_port = htole16(1); - break; - case WI_INTERSIL: - sc->wi_flags |= WI_FLAGS_HAS_ROAMING; - if (sc->sc_sta_firmware_ver >= 800) { - sc->wi_flags |= WI_FLAGS_HAS_IBSS; - sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; - } - /* - * version 0.8.3 and newer are the only ones that are known - * to currently work. Earlier versions can be made to work, - * at least according to the Linux driver. - */ - if (sc->sc_sta_firmware_ver >= 803) - sc->wi_flags |= WI_FLAGS_HAS_HOSTAP; - sc->wi_ibss_port = htole16(0); - break; - case WI_SYMBOL: - sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY; - if (sc->sc_sta_firmware_ver >= 20000) - sc->wi_flags |= WI_FLAGS_HAS_IBSS; - /* Older Symbol firmware does not support IBSS creation. */ - if (sc->sc_sta_firmware_ver >= 25000) - sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS; - sc->wi_ibss_port = htole16(4); - break; - } - - /* - * Find out if we support WEP on this card. - */ - gen.wi_type = WI_RID_WEP_AVAIL; - gen.wi_len = 2; - wi_read_record(sc, &gen); - sc->wi_has_wep = gen.wi_val; - - if (bootverbose) - device_printf(sc->dev, "wi_has_wep = %d\n", sc->wi_has_wep); - - /* - * Find supported rates. - */ - gen.wi_type = WI_RID_DATA_RATES; - gen.wi_len = 2; - if (wi_read_record(sc, &gen)) - sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M | - WI_SUPPRATES_5M | WI_SUPPRATES_11M; - else - sc->wi_supprates = gen.wi_val; - - bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats)); - - wi_init(sc); - wi_stop(sc); - - ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status); -#define ADD(m, c) ifmedia_add(&sc->ifmedia, (m), (c), NULL) - if (sc->wi_supprates & WI_SUPPRATES_1M) { - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, - IFM_IEEE80211_ADHOC, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, - IFM_IEEE80211_IBSS, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, - IFM_IEEE80211_IBSSMASTER, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, - IFM_IEEE80211_HOSTAP, 0), 0); - } - if (sc->wi_supprates & WI_SUPPRATES_2M) { - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, - IFM_IEEE80211_ADHOC, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, - IFM_IEEE80211_IBSS, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, - IFM_IEEE80211_IBSSMASTER, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, - IFM_IEEE80211_HOSTAP, 0), 0); - } - if (sc->wi_supprates & WI_SUPPRATES_5M) { - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, - IFM_IEEE80211_ADHOC, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, - IFM_IEEE80211_IBSS, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, - IFM_IEEE80211_IBSSMASTER, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, - IFM_IEEE80211_HOSTAP, 0), 0); - } - if (sc->wi_supprates & WI_SUPPRATES_11M) { - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, - IFM_IEEE80211_ADHOC, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, - IFM_IEEE80211_IBSS, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, - IFM_IEEE80211_IBSSMASTER, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, - IFM_IEEE80211_HOSTAP, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0); - } - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS, - 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, - IFM_IEEE80211_IBSSMASTER, 0), 0); - if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP) - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, - IFM_IEEE80211_HOSTAP, 0), 0); - ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); -#undef ADD - ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)); - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, sc->arpcom.ac_enaddr, NULL); - - error = bus_setup_intr(dev, sc->irq, INTR_NETSAFE, - wi_intr, sc, &sc->wi_intrhand, - ifp->if_serializer); - if (error) { - ether_ifdetach(ifp); - device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); - owi_free(dev); - return (error); - } - - return(0); -} - -static void -wi_get_id(struct wi_softc *sc) -{ - struct wi_ltv_ver ver; - struct wi_card_ident *id; - - /* getting chip identity */ - memset(&ver, 0, sizeof(ver)); - ver.wi_type = WI_RID_CARD_ID; - ver.wi_len = 5; - wi_read_record(sc, (struct wi_ltv_gen *)&ver); - device_printf(sc->dev, "using "); - sc->sc_firmware_type = WI_NOTYPE; - for (id = wi_card_ident; id->card_name != NULL; id++) { - if (le16toh(ver.wi_ver[0]) == id->card_id) { - printf("%s", id->card_name); - sc->sc_firmware_type = id->firm_type; - break; - } - } - if (sc->sc_firmware_type == WI_NOTYPE) { - if (le16toh(ver.wi_ver[0]) & 0x8000) { - printf("Unknown PRISM2 chip"); - sc->sc_firmware_type = WI_INTERSIL; - } else { - printf("Unknown Lucent chip"); - sc->sc_firmware_type = WI_LUCENT; - } - } - - if (sc->sc_firmware_type != WI_LUCENT) { - /* get primary firmware version */ - memset(&ver, 0, sizeof(ver)); - ver.wi_type = WI_RID_PRI_IDENTITY; - ver.wi_len = 5; - wi_read_record(sc, (struct wi_ltv_gen *)&ver); - ver.wi_ver[1] = le16toh(ver.wi_ver[1]); - ver.wi_ver[2] = le16toh(ver.wi_ver[2]); - ver.wi_ver[3] = le16toh(ver.wi_ver[3]); - sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 + - ver.wi_ver[3] * 100 + ver.wi_ver[1]; - } - - /* get station firmware version */ - memset(&ver, 0, sizeof(ver)); - ver.wi_type = WI_RID_STA_IDENTITY; - ver.wi_len = 5; - wi_read_record(sc, (struct wi_ltv_gen *)&ver); - ver.wi_ver[1] = le16toh(ver.wi_ver[1]); - ver.wi_ver[2] = le16toh(ver.wi_ver[2]); - ver.wi_ver[3] = le16toh(ver.wi_ver[3]); - sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 + - ver.wi_ver[3] * 100 + ver.wi_ver[1]; - if (sc->sc_firmware_type == WI_INTERSIL && - (sc->sc_sta_firmware_ver == 10102 || - sc->sc_sta_firmware_ver == 20102)) { - struct wi_ltv_str sver; - char *p; - - memset(&sver, 0, sizeof(sver)); - sver.wi_type = WI_RID_SYMBOL_IDENTITY; - sver.wi_len = 7; - /* value should be the format like "V2.00-11" */ - if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 && - *(p = (char *)sver.wi_str) >= 'A' && - p[2] == '.' && p[5] == '-' && p[8] == '\0') { - sc->sc_firmware_type = WI_SYMBOL; - sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 + - (p[3] - '0') * 1000 + (p[4] - '0') * 100 + - (p[6] - '0') * 10 + (p[7] - '0'); - } - } - printf("\n"); - device_printf(sc->dev, "%s Firmware: ", - sc->sc_firmware_type == WI_LUCENT ? "Lucent" : - (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil")); - - /* - * The primary firmware is only valid on Prism based chipsets - * (INTERSIL or SYMBOL). - */ - if (sc->sc_firmware_type != WI_LUCENT) - printf("Primary %u.%02u.%02u, ", sc->sc_pri_firmware_ver / 10000, - (sc->sc_pri_firmware_ver % 10000) / 100, - sc->sc_pri_firmware_ver % 100); - printf("Station %u.%02u.%02u\n", - sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100, - sc->sc_sta_firmware_ver % 100); - return; -} - -static void -wi_rxeof(struct wi_softc *sc) -{ - struct ifnet *ifp; - struct ether_header *eh; - struct mbuf *m; - int id; - - ifp = &sc->arpcom.ac_if; - - id = CSR_READ_2(sc, WI_RX_FID); - - /* - * if we have the procframe flag set, disregard all this and just - * read the data from the device. - */ - if (sc->wi_procframe || sc->wi_debug.wi_monitor) { - struct wi_frame *rx_frame; - int datlen, hdrlen; - - /* first allocate mbuf for packet storage */ - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) { - ifp->if_ierrors++; - return; - } - MCLGET(m, MB_DONTWAIT); - if (!(m->m_flags & M_EXT)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - - m->m_pkthdr.rcvif = ifp; - - /* now read wi_frame first so we know how much data to read */ - if (wi_read_data(sc, id, 0, mtod(m, caddr_t), - sizeof(struct wi_frame))) { - m_freem(m); - ifp->if_ierrors++; - return; - } - - rx_frame = mtod(m, struct wi_frame *); - - switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) { - case 7: - switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) { - case WI_FTYPE_DATA: - hdrlen = WI_DATA_HDRLEN; - datlen = rx_frame->wi_dat_len + WI_FCS_LEN; - break; - case WI_FTYPE_MGMT: - hdrlen = WI_MGMT_HDRLEN; - datlen = rx_frame->wi_dat_len + WI_FCS_LEN; - break; - case WI_FTYPE_CTL: - /* - * prism2 cards don't pass control packets - * down properly or consistently, so we'll only - * pass down the header. - */ - hdrlen = WI_CTL_HDRLEN; - datlen = 0; - break; - default: - device_printf(sc->dev, "received packet of " - "unknown type on port 7\n"); - m_freem(m); - ifp->if_ierrors++; - return; - } - break; - case 0: - hdrlen = WI_DATA_HDRLEN; - datlen = rx_frame->wi_dat_len + WI_FCS_LEN; - break; - default: - device_printf(sc->dev, "received packet on invalid " - "port (wi_status=0x%x)\n", rx_frame->wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - - if ((hdrlen + datlen + 2) > MCLBYTES) { - device_printf(sc->dev, "oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - datlen, rx_frame->wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - - if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen, - datlen + 2)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - - m->m_pkthdr.len = m->m_len = hdrlen + datlen; - - ifp->if_ipackets++; - - /* Handle BPF listeners. */ - BPF_MTAP(ifp, m); - - m_freem(m); - } else { - struct wi_frame rx_frame; - - /* First read in the frame header */ - if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, - sizeof(rx_frame))) { - ifp->if_ierrors++; - return; - } - - if (rx_frame.wi_status & WI_STAT_ERRSTAT) { - ifp->if_ierrors++; - return; - } - - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) { - ifp->if_ierrors++; - return; - } - MCLGET(m, MB_DONTWAIT); - if (!(m->m_flags & M_EXT)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - - eh = mtod(m, struct ether_header *); - m->m_pkthdr.rcvif = ifp; - - if (rx_frame.wi_status == WI_STAT_MGMT && - sc->wi_ptype == WI_PORTTYPE_AP) { - if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 2) > - MCLBYTES) { - device_printf(sc->dev, "oversized mgmt packet " - "received in hostap mode " - "(wi_dat_len=%d, wi_status=0x%x)\n", - rx_frame.wi_dat_len, rx_frame.wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - - /* Put the whole header in there. */ - bcopy(&rx_frame, mtod(m, void *), - sizeof(struct wi_frame)); - if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, - mtod(m, caddr_t) + WI_802_11_OFFSET_RAW, - rx_frame.wi_dat_len + 2)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.len = m->m_len = - WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len; - /* XXX: consider giving packet to bhp? */ - owihap_mgmt_input(sc, &rx_frame, m); - return; - } - - if (rx_frame.wi_status == WI_STAT_1042 || - rx_frame.wi_status == WI_STAT_TUNNEL || - rx_frame.wi_status == WI_STAT_WMP_MSG) { - if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) { - device_printf(sc->dev, - "oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - rx_frame.wi_dat_len, rx_frame.wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.len = m->m_len = - rx_frame.wi_dat_len + WI_SNAPHDR_LEN; - -#if 0 - bcopy((char *)&rx_frame.wi_addr1, - (char *)&eh->ether_dhost, ETHER_ADDR_LEN); - if (sc->wi_ptype == WI_PORTTYPE_ADHOC) { - bcopy((char *)&rx_frame.wi_addr2, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); - } else { - bcopy((char *)&rx_frame.wi_addr3, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); - } -#else - bcopy((char *)&rx_frame.wi_dst_addr, - (char *)&eh->ether_dhost, ETHER_ADDR_LEN); - bcopy((char *)&rx_frame.wi_src_addr, - (char *)&eh->ether_shost, ETHER_ADDR_LEN); -#endif - - bcopy((char *)&rx_frame.wi_type, - (char *)&eh->ether_type, ETHER_TYPE_LEN); - - if (wi_read_data(sc, id, WI_802_11_OFFSET, - mtod(m, caddr_t) + sizeof(struct ether_header), - m->m_len + 2)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - } else { - if((rx_frame.wi_dat_len + - sizeof(struct ether_header)) > MCLBYTES) { - device_printf(sc->dev, - "oversized packet received " - "(wi_dat_len=%d, wi_status=0x%x)\n", - rx_frame.wi_dat_len, rx_frame.wi_status); - m_freem(m); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.len = m->m_len = - rx_frame.wi_dat_len + sizeof(struct ether_header); - - if (wi_read_data(sc, id, WI_802_3_OFFSET, - mtod(m, caddr_t), m->m_len + 2)) { - m_freem(m); - ifp->if_ierrors++; - return; - } - } - - ifp->if_ipackets++; - - if (sc->wi_ptype == WI_PORTTYPE_AP) { - /* - * Give host AP code first crack at data - * packets. If it decides to handle it (or - * drop it), it will return a non-zero. - * Otherwise, it is destined for this host. - */ - if (owihap_data_input(sc, &rx_frame, m)) - return; - } - /* Receive packet. */ -#ifdef WICACHE - wi_cache_store(sc, m, rx_frame.wi_q_info); -#endif - ifp->if_input(ifp, m); - } -} - -static void -wi_txeof(struct wi_softc *sc, int status) -{ - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - - if (status & WI_EV_TX_EXC) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - return; -} - -static void -wi_inquire(void *xsc) -{ - struct wi_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - - lwkt_serialize_enter(ifp->if_serializer); - - callout_reset(&sc->wi_stat_timer, hz* 60, wi_inquire, sc); - - /* Don't do this while we're transmitting */ - if ((ifp->if_flags & IFF_OACTIVE) == 0) { - wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0); - } - - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -wi_update_stats(struct wi_softc *sc) -{ - struct wi_ltv_gen gen; - u_int16_t id; - struct ifnet *ifp; - u_int32_t *ptr; - int len, i; - u_int16_t t; - - ifp = &sc->arpcom.ac_if; - - id = CSR_READ_2(sc, WI_INFO_FID); - - wi_read_data(sc, id, 0, (char *)&gen, 4); - - /* - * if we just got our scan results, copy it over into the scan buffer - * so we can return it to anyone that asks for it. (add a little - * compatibility with the prism2 scanning mechanism) - */ - if (gen.wi_type == WI_INFO_SCAN_RESULTS) - { - sc->wi_scanbuf_len = gen.wi_len; - wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf, - sc->wi_scanbuf_len * 2); - - return; - } - else if (gen.wi_type != WI_INFO_COUNTERS) - return; - - len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ? - gen.wi_len - 1 : sizeof(sc->wi_stats) / 4; - ptr = (u_int32_t *)&sc->wi_stats; - - for (i = 0; i < len - 1; i++) { - t = CSR_READ_2(sc, WI_DATA1); -#ifdef WI_HERMES_STATS_WAR - if (t > 0xF000) - t = ~t & 0xFFFF; -#endif - ptr[i] += t; - } - - ifp->if_collisions = sc->wi_stats.wi_tx_single_retries + - sc->wi_stats.wi_tx_multi_retries + - sc->wi_stats.wi_tx_retry_limit; - - return; -} - -static void -wi_intr(void *xsc) -{ - struct wi_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - u_int16_t status; - - if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) { - CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); - CSR_WRITE_2(sc, WI_INT_EN, 0); - return; - } - - /* Disable interrupts. */ - CSR_WRITE_2(sc, WI_INT_EN, 0); - - status = CSR_READ_2(sc, WI_EVENT_STAT); - CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS); - - if (status & WI_EV_RX) { - wi_rxeof(sc); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - } - - if (status & WI_EV_TX) { - wi_txeof(sc, status); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX); - } - - if (status & WI_EV_ALLOC) { - int id; - - id = CSR_READ_2(sc, WI_ALLOC_FID); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); - if (id == sc->wi_tx_data_id) - wi_txeof(sc, status); - } - - if (status & WI_EV_INFO) { - wi_update_stats(sc); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); - } - - if (status & WI_EV_TX_EXC) { - wi_txeof(sc, status); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); - } - - if (status & WI_EV_INFO_DROP) { - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP); - } - - /* Re-enable interrupts. */ - CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); - - if (!ifq_is_empty(&ifp->if_snd)) { - wi_start(ifp); - } -} - -static int -wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2) -{ - int i, s = 0; - static volatile int count = 0; - - if (count > 1) - panic("Hey partner, hold on there!"); - count++; - - /* wait for the busy bit to clear */ - for (i = 500; i > 0; i--) { /* 5s */ - if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) { - break; - } - DELAY(10*1000); /* 10 m sec */ - } - if (i == 0) { - device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" ); - count--; - return(ETIMEDOUT); - } - - CSR_WRITE_2(sc, WI_PARAM0, val0); - CSR_WRITE_2(sc, WI_PARAM1, val1); - CSR_WRITE_2(sc, WI_PARAM2, val2); - CSR_WRITE_2(sc, WI_COMMAND, cmd); - - for (i = 0; i < WI_TIMEOUT; i++) { - /* - * Wait for 'command complete' bit to be - * set in the event status register. - */ - s = CSR_READ_2(sc, WI_EVENT_STAT); - if (s & WI_EV_CMD) { - /* Ack the event and read result code. */ - s = CSR_READ_2(sc, WI_STATUS); - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); -#ifdef foo - if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK)) - return(EIO); -#endif - if (s & WI_STAT_CMD_RESULT) { - count--; - return(EIO); - } - break; - } - DELAY(WI_DELAY); - } - - count--; - if (i == WI_TIMEOUT) { - device_printf(sc->dev, - "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s); - return(ETIMEDOUT); - } - return(0); -} - -static void -wi_reset(struct wi_softc *sc) -{ -#define WI_INIT_TRIES 3 - int i; - int tries; - - /* Symbol firmware cannot be initialized more than once */ - if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_enabled) - return; - if (sc->sc_firmware_type == WI_SYMBOL) - tries = 1; - else - tries = WI_INIT_TRIES; - - for (i = 0; i < tries; i++) { - if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0) - break; - DELAY(WI_DELAY * 1000); - } - sc->sc_enabled = 1; - - if (i == tries) { - device_printf(sc->dev, "init failed\n"); - return; - } - - CSR_WRITE_2(sc, WI_INT_EN, 0); - CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); - - /* Calibrate timer. */ - WI_SETVAL(WI_RID_TICK_TIME, 8); - - return; -} - -/* - * Read an LTV record from the NIC. - */ -static int -wi_read_record(struct wi_softc *sc, struct wi_ltv_gen *ltv) -{ - u_int16_t *ptr; - int i, len, code; - struct wi_ltv_gen *oltv, p2ltv; - - oltv = ltv; - if (sc->sc_firmware_type != WI_LUCENT) { - switch (ltv->wi_type) { - case WI_RID_ENCRYPTION: - p2ltv.wi_type = WI_RID_P2_ENCRYPTION; - p2ltv.wi_len = 2; - ltv = &p2ltv; - break; - case WI_RID_TX_CRYPT_KEY: - p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; - p2ltv.wi_len = 2; - ltv = &p2ltv; - break; - case WI_RID_ROAMING_MODE: - if (sc->sc_firmware_type == WI_INTERSIL) - break; - /* not supported */ - ltv->wi_len = 1; - return 0; - case WI_RID_MICROWAVE_OVEN: - /* not supported */ - ltv->wi_len = 1; - return 0; - } - } - - /* Tell the NIC to enter record read mode. */ - if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0)) - return(EIO); - - /* Seek to the record. */ - if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) - return(EIO); - - /* - * Read the length and record type and make sure they - * match what we expect (this verifies that we have enough - * room to hold all of the returned data). - */ - len = CSR_READ_2(sc, WI_DATA1); - if (len > ltv->wi_len) - return(ENOSPC); - code = CSR_READ_2(sc, WI_DATA1); - if (code != ltv->wi_type) - return(EIO); - - ltv->wi_len = len; - ltv->wi_type = code; - - /* Now read the data. */ - ptr = <v->wi_val; - for (i = 0; i < ltv->wi_len - 1; i++) - ptr[i] = CSR_READ_2(sc, WI_DATA1); - - if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS - && ltv->wi_val == sc->wi_ibss_port) { - /* - * Convert vendor IBSS port type to WI_PORTTYPE_IBSS. - * Since Lucent uses port type 1 for BSS *and* IBSS we - * have to rely on wi_ptype to distinguish this for us. - */ - ltv->wi_val = htole16(WI_PORTTYPE_IBSS); - } else if (sc->sc_firmware_type != WI_LUCENT) { - switch (oltv->wi_type) { - case WI_RID_TX_RATE: - case WI_RID_CUR_TX_RATE: - switch (ltv->wi_val) { - case 1: oltv->wi_val = 1; break; - case 2: oltv->wi_val = 2; break; - case 3: oltv->wi_val = 6; break; - case 4: oltv->wi_val = 5; break; - case 7: oltv->wi_val = 7; break; - case 8: oltv->wi_val = 11; break; - case 15: oltv->wi_val = 3; break; - default: oltv->wi_val = 0x100 + ltv->wi_val; break; - } - break; - case WI_RID_ENCRYPTION: - oltv->wi_len = 2; - if (ltv->wi_val & 0x01) - oltv->wi_val = 1; - else - oltv->wi_val = 0; - break; - case WI_RID_TX_CRYPT_KEY: - oltv->wi_len = 2; - oltv->wi_val = ltv->wi_val; - break; - case WI_RID_CNFAUTHMODE: - oltv->wi_len = 2; - if (le16toh(ltv->wi_val) & 0x01) - oltv->wi_val = htole16(1); - else if (le16toh(ltv->wi_val) & 0x02) - oltv->wi_val = htole16(2); - break; - } - } - - return(0); -} - -/* - * Same as read, except we inject data instead of reading it. - */ -static int -wi_write_record(struct wi_softc *sc, struct wi_ltv_gen *ltv) -{ - u_int16_t *ptr; - int i; - struct wi_ltv_gen p2ltv; - - if (ltv->wi_type == WI_RID_PORTTYPE && - le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) { - /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */ - p2ltv.wi_type = WI_RID_PORTTYPE; - p2ltv.wi_len = 2; - p2ltv.wi_val = sc->wi_ibss_port; - ltv = &p2ltv; - } else if (sc->sc_firmware_type != WI_LUCENT) { - switch (ltv->wi_type) { - case WI_RID_TX_RATE: - p2ltv.wi_type = WI_RID_TX_RATE; - p2ltv.wi_len = 2; - switch (ltv->wi_val) { - case 1: p2ltv.wi_val = 1; break; - case 2: p2ltv.wi_val = 2; break; - case 3: p2ltv.wi_val = 15; break; - case 5: p2ltv.wi_val = 4; break; - case 6: p2ltv.wi_val = 3; break; - case 7: p2ltv.wi_val = 7; break; - case 11: p2ltv.wi_val = 8; break; - default: return EINVAL; - } - ltv = &p2ltv; - break; - case WI_RID_ENCRYPTION: - p2ltv.wi_type = WI_RID_P2_ENCRYPTION; - p2ltv.wi_len = 2; - if (le16toh(ltv->wi_val)) { - p2ltv.wi_val =htole16(PRIVACY_INVOKED | - EXCLUDE_UNENCRYPTED); - if (sc->wi_ptype == WI_PORTTYPE_AP) - /* - * Disable tx encryption... - * it's broken. - */ - p2ltv.wi_val |= htole16(HOST_ENCRYPT); - } else - p2ltv.wi_val = - htole16(HOST_ENCRYPT | HOST_DECRYPT); - ltv = &p2ltv; - break; - case WI_RID_TX_CRYPT_KEY: - p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; - p2ltv.wi_len = 2; - p2ltv.wi_val = ltv->wi_val; - ltv = &p2ltv; - break; - case WI_RID_DEFLT_CRYPT_KEYS: - { - int error; - int keylen; - struct wi_ltv_str ws; - struct wi_ltv_keys *wk = - (struct wi_ltv_keys *)ltv; - - keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen; - - for (i = 0; i < 4; i++) { - bzero(&ws, sizeof(ws)); - ws.wi_len = (keylen > 5) ? 8 : 4; - ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i; - memcpy(ws.wi_str, - &wk->wi_keys[i].wi_keydat, keylen); - error = wi_write_record(sc, - (struct wi_ltv_gen *)&ws); - if (error) - return error; - } - return 0; - } - case WI_RID_CNFAUTHMODE: - p2ltv.wi_type = WI_RID_CNFAUTHMODE; - p2ltv.wi_len = 2; - if (le16toh(ltv->wi_val) == 1) - p2ltv.wi_val = htole16(0x01); - else if (le16toh(ltv->wi_val) == 2) - p2ltv.wi_val = htole16(0x02); - ltv = &p2ltv; - break; - case WI_RID_ROAMING_MODE: - if (sc->sc_firmware_type == WI_INTERSIL) - break; - /* not supported */ - return 0; - case WI_RID_MICROWAVE_OVEN: - /* not supported */ - return 0; - } - } else { - /* LUCENT */ - switch (ltv->wi_type) { - case WI_RID_TX_RATE: - switch (ltv->wi_val) { - case 1: ltv->wi_val = 1; break; /* 1Mb/s fixed */ - case 2: ltv->wi_val = 2; break; /* 2Mb/s fixed */ - case 3: ltv->wi_val = 3; break; /* 11Mb/s auto */ - case 5: ltv->wi_val = 4; break; /* 5.5Mb/s fixed */ - case 6: ltv->wi_val = 6; break; /* 2Mb/s auto */ - case 7: ltv->wi_val = 7; break; /* 5.5Mb/s auto */ - case 11: ltv->wi_val = 5; break; /* 11Mb/s fixed */ - default: return EINVAL; - } - } - } - - if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) - return(EIO); - - CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len); - CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type); - - ptr = <v->wi_val; - for (i = 0; i < ltv->wi_len - 1; i++) - CSR_WRITE_2(sc, WI_DATA1, ptr[i]); - - if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0)) - return(EIO); - - return(0); -} - -static int -wi_seek(struct wi_softc *sc, int id, int off, int chan) -{ - int i; - int selreg, offreg; - int status; - - switch (chan) { - case WI_BAP0: - selreg = WI_SEL0; - offreg = WI_OFF0; - break; - case WI_BAP1: - selreg = WI_SEL1; - offreg = WI_OFF1; - break; - default: - device_printf(sc->dev, "invalid data path: %x\n", chan); - return(EIO); - } - - CSR_WRITE_2(sc, selreg, id); - CSR_WRITE_2(sc, offreg, off); - - for (i = 0; i < WI_TIMEOUT; i++) { - status = CSR_READ_2(sc, offreg); - if (!(status & (WI_OFF_BUSY|WI_OFF_ERR))) - break; - DELAY(WI_DELAY); - } - - if (i == WI_TIMEOUT) { - device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n", - id, off, status); - return(ETIMEDOUT); - } - - return(0); -} - -static int -wi_read_data(struct wi_softc *sc, int id, int off, caddr_t buf, int len) -{ - int i; - u_int16_t *ptr; - - if (wi_seek(sc, id, off, WI_BAP1)) - return(EIO); - - ptr = (u_int16_t *)buf; - for (i = 0; i < len / 2; i++) - ptr[i] = CSR_READ_2(sc, WI_DATA1); - - return(0); -} - -/* - * According to the comments in the HCF Light code, there is a bug in - * the Hermes (or possibly in certain Hermes firmware revisions) where - * the chip's internal autoincrement counter gets thrown off during - * data writes: the autoincrement is missed, causing one data word to - * be overwritten and subsequent words to be written to the wrong memory - * locations. The end result is that we could end up transmitting bogus - * frames without realizing it. The workaround for this is to write a - * couple of extra guard words after the end of the transfer, then - * attempt to read then back. If we fail to locate the guard words where - * we expect them, we preform the transfer over again. - */ -static int -wi_write_data(struct wi_softc *sc, int id, int off, caddr_t buf, int len) -{ - int i; - u_int16_t *ptr; -#ifdef WI_HERMES_AUTOINC_WAR - int retries; - - retries = 512; -again: -#endif - - if (wi_seek(sc, id, off, WI_BAP0)) - return(EIO); - - ptr = (u_int16_t *)buf; - for (i = 0; i < (len / 2); i++) - CSR_WRITE_2(sc, WI_DATA0, ptr[i]); - -#ifdef WI_HERMES_AUTOINC_WAR - CSR_WRITE_2(sc, WI_DATA0, 0x1234); - CSR_WRITE_2(sc, WI_DATA0, 0x5678); - - if (wi_seek(sc, id, off + len, WI_BAP0)) - return(EIO); - - if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || - CSR_READ_2(sc, WI_DATA0) != 0x5678) { - if (--retries >= 0) - goto again; - device_printf(sc->dev, "wi_write_data device timeout\n"); - return (EIO); - } -#endif - - return(0); -} - -/* - * Allocate a region of memory inside the NIC and zero - * it out. - */ -static int -wi_alloc_nicmem(struct wi_softc *sc, int len, int *id) -{ - int i; - - if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) { - device_printf(sc->dev, - "failed to allocate %d bytes on NIC\n", len); - return(ENOMEM); - } - - for (i = 0; i < WI_TIMEOUT; i++) { - if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) - break; - DELAY(WI_DELAY); - } - - if (i == WI_TIMEOUT) { - device_printf(sc->dev, "time out allocating memory on card\n"); - return(ETIMEDOUT); - } - - CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); - *id = CSR_READ_2(sc, WI_ALLOC_FID); - - if (wi_seek(sc, *id, 0, WI_BAP0)) { - device_printf(sc->dev, "seek failed while allocating memory on card\n"); - return(EIO); - } - - for (i = 0; i < len / 2; i++) - CSR_WRITE_2(sc, WI_DATA0, 0); - - return(0); -} - -static void -wi_setmulti(struct wi_softc *sc) -{ - struct ifnet *ifp; - int i = 0; - struct ifmultiaddr *ifma; - struct wi_ltv_mcast mcast; - - ifp = &sc->arpcom.ac_if; - - bzero((char *)&mcast, sizeof(mcast)); - - mcast.wi_type = WI_RID_MCAST_LIST; - mcast.wi_len = (3 * 16) + 1; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - wi_write_record(sc, (struct wi_ltv_gen *)&mcast); - return; - } - -#if defined(__DragonFly__) || __FreeBSD_version < 500000 - LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { -#else - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { -#endif - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - if (i < 16) { - bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN); - i++; - } else { - bzero((char *)&mcast, sizeof(mcast)); - break; - } - } - - mcast.wi_len = (i * 3) + 1; - wi_write_record(sc, (struct wi_ltv_gen *)&mcast); - - return; -} - -static void -wi_setdef(struct wi_softc *sc, struct wi_req *wreq) -{ - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - switch(wreq->wi_type) { - case WI_RID_MAC_NODE: - bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr, - ETHER_ADDR_LEN); - bcopy((char *)&wreq->wi_val, IF_LLADDR(ifp), ETHER_ADDR_LEN); - break; - case WI_RID_PORTTYPE: - sc->wi_ptype = le16toh(wreq->wi_val[0]); - break; - case WI_RID_TX_RATE: - sc->wi_tx_rate = le16toh(wreq->wi_val[0]); - break; - case WI_RID_MAX_DATALEN: - sc->wi_max_data_len = le16toh(wreq->wi_val[0]); - break; - case WI_RID_RTS_THRESH: - sc->wi_rts_thresh = le16toh(wreq->wi_val[0]); - break; - case WI_RID_SYSTEM_SCALE: - sc->wi_ap_density = le16toh(wreq->wi_val[0]); - break; - case WI_RID_CREATE_IBSS: - sc->wi_create_ibss = le16toh(wreq->wi_val[0]); - break; - case WI_RID_OWN_CHNL: - sc->wi_channel = le16toh(wreq->wi_val[0]); - break; - case WI_RID_NODENAME: - bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); - bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30); - break; - case WI_RID_DESIRED_SSID: - bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); - bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30); - break; - case WI_RID_OWN_SSID: - bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); - bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30); - break; - case WI_RID_PM_ENABLED: - sc->wi_pm_enabled = le16toh(wreq->wi_val[0]); - break; - case WI_RID_MICROWAVE_OVEN: - sc->wi_mor_enabled = le16toh(wreq->wi_val[0]); - break; - case WI_RID_MAX_SLEEP: - sc->wi_max_sleep = le16toh(wreq->wi_val[0]); - break; - case WI_RID_CNFAUTHMODE: - sc->wi_authtype = le16toh(wreq->wi_val[0]); - break; - case WI_RID_ROAMING_MODE: - sc->wi_roaming = le16toh(wreq->wi_val[0]); - break; - case WI_RID_ENCRYPTION: - sc->wi_use_wep = le16toh(wreq->wi_val[0]); - break; - case WI_RID_TX_CRYPT_KEY: - sc->wi_tx_key = le16toh(wreq->wi_val[0]); - break; - case WI_RID_DEFLT_CRYPT_KEYS: - bcopy((char *)wreq, (char *)&sc->wi_keys, - sizeof(struct wi_ltv_keys)); - break; - default: - break; - } - - /* Reinitialize WaveLAN. */ - wi_init(sc); - - return; -} - -static int -wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) -{ - int error = 0; - int len; - u_int8_t tmpkey[14]; - char tmpssid[IEEE80211_NWID_LEN]; - struct wi_softc *sc = ifp->if_softc; - struct wi_req wreq; - struct ifreq *ifr; - struct ieee80211req *ireq; - - ifr = (struct ifreq *)data; - ireq = (struct ieee80211req *)data; - - if (sc->wi_gone) { - error = ENODEV; - goto out; - } - - switch(command) { - case SIOCSIFFLAGS: - /* - * Can't do promisc and hostap at the same time. If all that's - * changing is the promisc flag, try to short-circuit a call to - * wi_init() by just setting PROMISC in the hardware. - */ - if (ifp->if_flags & IFF_UP) { - if (sc->wi_ptype != WI_PORTTYPE_AP && - ifp->if_flags & IFF_RUNNING) { - if (ifp->if_flags & IFF_PROMISC && - !(sc->wi_if_flags & IFF_PROMISC)) { - WI_SETVAL(WI_RID_PROMISC, 1); - } else if (!(ifp->if_flags & IFF_PROMISC) && - sc->wi_if_flags & IFF_PROMISC) { - WI_SETVAL(WI_RID_PROMISC, 0); - } else { - wi_init(sc); - } - } else { - wi_init(sc); - } - } else { - if (ifp->if_flags & IFF_RUNNING) { - wi_stop(sc); - } - } - sc->wi_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - wi_setmulti(sc); - error = 0; - break; - case SIOCGWAVELAN: - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - break; - if (wreq.wi_len > WI_MAX_DATALEN) { - error = EINVAL; - break; - } - /* Don't show WEP keys to non-root users. */ - if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && - suser_cred(cr, NULL_CRED_OKAY)) - break; - if (wreq.wi_type == WI_RID_IFACE_STATS) { - bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val, - sizeof(sc->wi_stats)); - wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1; - } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) { - bcopy((char *)&sc->wi_keys, (char *)&wreq, - sizeof(struct wi_ltv_keys)); - } -#ifdef WICACHE - else if (wreq.wi_type == WI_RID_ZERO_CACHE) { - sc->wi_sigitems = sc->wi_nextitem = 0; - } else if (wreq.wi_type == WI_RID_READ_CACHE) { - char *pt = (char *)&wreq.wi_val; - bcopy((char *)&sc->wi_sigitems, - (char *)pt, sizeof(int)); - pt += (sizeof (int)); - wreq.wi_len = sizeof(int) / 2; - bcopy((char *)&sc->wi_sigcache, (char *)pt, - sizeof(struct wi_sigcache) * sc->wi_sigitems); - wreq.wi_len += ((sizeof(struct wi_sigcache) * - sc->wi_sigitems) / 2) + 1; - } -#endif - else if (wreq.wi_type == WI_RID_PROCFRAME) { - wreq.wi_len = 2; - wreq.wi_val[0] = sc->wi_procframe; - } else if (wreq.wi_type == WI_RID_PRISM2) { - wreq.wi_len = 2; - wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT; - } else if (wreq.wi_type == WI_RID_SCAN_RES && - sc->sc_firmware_type == WI_LUCENT) { - memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf, - sc->wi_scanbuf_len * 2); - wreq.wi_len = sc->wi_scanbuf_len; - } else { - if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { - error = EINVAL; - break; - } - } - error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); - break; - case SIOCSWAVELAN: - if ((error = suser_cred(cr, NULL_CRED_OKAY))) - goto out; - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - break; - if (wreq.wi_len > WI_MAX_DATALEN) { - error = EINVAL; - break; - } - if (wreq.wi_type == WI_RID_IFACE_STATS) { - error = EINVAL; - break; - } else if (wreq.wi_type == WI_RID_MGMT_XMIT) { - error = owi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, - wreq.wi_len); - } else if (wreq.wi_type == WI_RID_PROCFRAME) { - sc->wi_procframe = wreq.wi_val[0]; - /* - * if we're getting a scan request from a wavelan card - * (non-prism2), send out a cmd_inquire to the card to scan - * results for the scan will be received through the info - * interrupt handler. otherwise the scan request can be - * directly handled by a prism2 card's rid interface. - */ - } else if (wreq.wi_type == WI_RID_SCAN_REQ && - sc->sc_firmware_type == WI_LUCENT) { - wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0); - } else { - error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); - if (!error) - wi_setdef(sc, &wreq); - } - break; - case SIOCGPRISM2DEBUG: - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - break; - if (!(ifp->if_flags & IFF_RUNNING) || - sc->sc_firmware_type == WI_LUCENT) { - error = EIO; - break; - } - error = wi_get_debug(sc, &wreq); - if (error == 0) - error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); - break; - case SIOCSPRISM2DEBUG: - if ((error = suser_cred(cr, NULL_CRED_OKAY))) - goto out; - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - break; - error = wi_set_debug(sc, &wreq); - break; - case SIOCG80211: - switch(ireq->i_type) { - case IEEE80211_IOC_SSID: - if(ireq->i_val == -1) { - bzero(tmpssid, IEEE80211_NWID_LEN); - error = wi_get_cur_ssid(sc, tmpssid, &len); - if (error != 0) - break; - error = copyout(tmpssid, ireq->i_data, - IEEE80211_NWID_LEN); - ireq->i_len = len; - } else if (ireq->i_val == 0) { - error = copyout(sc->wi_net_name, - ireq->i_data, - IEEE80211_NWID_LEN); - ireq->i_len = IEEE80211_NWID_LEN; - } else - error = EINVAL; - break; - case IEEE80211_IOC_NUMSSIDS: - ireq->i_val = 1; - break; - case IEEE80211_IOC_WEP: - if(!sc->wi_has_wep) { - ireq->i_val = IEEE80211_WEP_NOSUP; - } else { - if(sc->wi_use_wep) { - ireq->i_val = - IEEE80211_WEP_MIXED; - } else { - ireq->i_val = - IEEE80211_WEP_OFF; - } - } - break; - case IEEE80211_IOC_WEPKEY: - if(!sc->wi_has_wep || - ireq->i_val < 0 || ireq->i_val > 3) { - error = EINVAL; - break; - } - len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen; - if (suser_cred(cr, NULL_CRED_OKAY)) - bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, - tmpkey, len); - else - bzero(tmpkey, len); - - ireq->i_len = len; - error = copyout(tmpkey, ireq->i_data, len); - - break; - case IEEE80211_IOC_NUMWEPKEYS: - if(!sc->wi_has_wep) - error = EINVAL; - else - ireq->i_val = 4; - break; - case IEEE80211_IOC_WEPTXKEY: - if(!sc->wi_has_wep) - error = EINVAL; - else - ireq->i_val = sc->wi_tx_key; - break; - case IEEE80211_IOC_AUTHMODE: - ireq->i_val = sc->wi_authmode; - break; - case IEEE80211_IOC_STATIONNAME: - error = copyout(sc->wi_node_name, - ireq->i_data, IEEE80211_NWID_LEN); - ireq->i_len = IEEE80211_NWID_LEN; - break; - case IEEE80211_IOC_CHANNEL: - wreq.wi_type = WI_RID_CURRENT_CHAN; - wreq.wi_len = WI_MAX_DATALEN; - if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) - error = EINVAL; - else { - ireq->i_val = wreq.wi_val[0]; - } - break; - case IEEE80211_IOC_POWERSAVE: - if(sc->wi_pm_enabled) - ireq->i_val = IEEE80211_POWERSAVE_ON; - else - ireq->i_val = IEEE80211_POWERSAVE_OFF; - break; - case IEEE80211_IOC_POWERSAVESLEEP: - ireq->i_val = sc->wi_max_sleep; - break; - default: - error = EINVAL; - } - break; - case SIOCS80211: - if ((error = suser_cred(cr, NULL_CRED_OKAY))) - goto out; - switch(ireq->i_type) { - case IEEE80211_IOC_SSID: - if (ireq->i_val != 0 || - ireq->i_len > IEEE80211_NWID_LEN) { - error = EINVAL; - break; - } - /* We set both of them */ - bzero(sc->wi_net_name, IEEE80211_NWID_LEN); - error = copyin(ireq->i_data, - sc->wi_net_name, ireq->i_len); - bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN); - break; - case IEEE80211_IOC_WEP: - /* - * These cards only support one mode so - * we just turn wep on what ever is - * passed in if it's not OFF. - */ - if (ireq->i_val == IEEE80211_WEP_OFF) { - sc->wi_use_wep = 0; - } else { - sc->wi_use_wep = 1; - } - break; - case IEEE80211_IOC_WEPKEY: - if (ireq->i_val < 0 || ireq->i_val > 3 || - ireq->i_len > 13) { - error = EINVAL; - break; - } - bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13); - error = copyin(ireq->i_data, - sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, - ireq->i_len); - if(error) - break; - sc->wi_keys.wi_keys[ireq->i_val].wi_keylen = - ireq->i_len; - break; - case IEEE80211_IOC_WEPTXKEY: - if (ireq->i_val < 0 || ireq->i_val > 3) { - error = EINVAL; - break; - } - sc->wi_tx_key = ireq->i_val; - break; - case IEEE80211_IOC_AUTHMODE: - sc->wi_authmode = ireq->i_val; - break; - case IEEE80211_IOC_STATIONNAME: - if (ireq->i_len > 32) { - error = EINVAL; - break; - } - bzero(sc->wi_node_name, 32); - error = copyin(ireq->i_data, - sc->wi_node_name, ireq->i_len); - break; - case IEEE80211_IOC_CHANNEL: - /* - * The actual range is 1-14, but if you - * set it to 0 you get the default. So - * we let that work too. - */ - if (ireq->i_val < 0 || ireq->i_val > 14) { - error = EINVAL; - break; - } - sc->wi_channel = ireq->i_val; - break; - case IEEE80211_IOC_POWERSAVE: - switch (ireq->i_val) { - case IEEE80211_POWERSAVE_OFF: - sc->wi_pm_enabled = 0; - break; - case IEEE80211_POWERSAVE_ON: - sc->wi_pm_enabled = 1; - break; - default: - error = EINVAL; - break; - } - break; - case IEEE80211_IOC_POWERSAVESLEEP: - if (ireq->i_val < 0) { - error = EINVAL; - break; - } - sc->wi_max_sleep = ireq->i_val; - break; - default: - error = EINVAL; - break; - } - - /* Reinitialize WaveLAN. */ - wi_init(sc); - - break; - case SIOCHOSTAP_ADD: - case SIOCHOSTAP_DEL: - case SIOCHOSTAP_GET: - case SIOCHOSTAP_GETALL: - case SIOCHOSTAP_GFLAGS: - case SIOCHOSTAP_SFLAGS: - /* Send all Host AP specific ioctl's to Host AP code. */ - error = owihap_ioctl(sc, command, data); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } -out: - return(error); -} - -static void -wi_init(void *xsc) -{ - struct wi_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct wi_ltv_macaddr mac; - int id = 0; - - if (sc->wi_gone) - return; - - if (ifp->if_flags & IFF_RUNNING) - wi_stop(sc); - - wi_reset(sc); - - /* Program max data length. */ - WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len); - - /* Set the port type. */ - WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype); - - /* Enable/disable IBSS creation. */ - WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss); - - /* Program the RTS/CTS threshold. */ - WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh); - - /* Program the TX rate */ - WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate); - - /* Access point density */ - WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density); - - /* Power Management Enabled */ - WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled); - - /* Power Managment Max Sleep */ - WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep); - - /* Roaming type */ - WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming); - - /* Specify the IBSS name */ - WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name); - - /* Specify the network name */ - WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name); - - /* Specify the frequency to use */ - WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel); - - /* Program the nodename. */ - WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name); - - /* Specify the authentication mode. */ - WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authmode); - - /* Set our MAC address. */ - mac.wi_len = 4; - mac.wi_type = WI_RID_MAC_NODE; - bcopy((char *)&sc->arpcom.ac_enaddr, - (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN); - wi_write_record(sc, (struct wi_ltv_gen *)&mac); - - /* - * Initialize promisc mode. - * Being in the Host-AP mode causes - * great deal of pain if promisc mode is set. - * Therefore we avoid confusing the firmware - * and always reset promisc mode in Host-AP regime, - * it shows us all the packets anyway. - */ - if (sc->wi_ptype != WI_PORTTYPE_AP && ifp->if_flags & IFF_PROMISC) - WI_SETVAL(WI_RID_PROMISC, 1); - else - WI_SETVAL(WI_RID_PROMISC, 0); - - /* Configure WEP. */ - if (sc->wi_has_wep) { - WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep); - WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key); - sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1; - sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS; - wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys); - if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) { - /* - * ONLY HWB3163 EVAL-CARD Firmware version - * less than 0.8 variant2 - * - * If promiscuous mode disable, Prism2 chip - * does not work with WEP. - * It is under investigation for details. - * (ichiro@netbsd.org) - * - * And make sure that we don't need to do it - * in hostap mode, since it interferes with - * the above hostap workaround. - */ - if (sc->wi_ptype != WI_PORTTYPE_AP && - sc->sc_firmware_type == WI_INTERSIL && - sc->sc_sta_firmware_ver < 802 ) { - /* firm ver < 0.8 variant 2 */ - WI_SETVAL(WI_RID_PROMISC, 1); - } - WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype); - } - } - - /* Set multicast filter. */ - wi_setmulti(sc); - - /* Enable desired port */ - wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0); - - if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id)) - device_printf(sc->dev, "tx buffer allocation failed\n"); - sc->wi_tx_data_id = id; - - if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id)) - device_printf(sc->dev, "mgmt. buffer allocation failed\n"); - sc->wi_tx_mgmt_id = id; - - /* enable interrupts */ - CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); - - owihap_init(sc); - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - callout_reset(&sc->wi_stat_timer, hz * 60, wi_inquire, sc); -} - -#define RC4STATE 256 -#define RC4KEYLEN 16 -#define RC4SWAP(x,y) \ - do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0) - -static void -wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len) -{ - u_int32_t i, crc, klen; - u_int8_t state[RC4STATE], key[RC4KEYLEN]; - u_int8_t x, y, *dat; - - if (!sc->wi_icv_flag) { - sc->wi_icv = arc4random(); - sc->wi_icv_flag++; - } else - sc->wi_icv++; - /* - * Skip 'bad' IVs from Fluhrer/Mantin/Shamir: - * (B, 255, N) with 3 <= B < 8 - */ - if (sc->wi_icv >= 0x03ff00 && - (sc->wi_icv & 0xf8ff00) == 0x00ff00) - sc->wi_icv += 0x000100; - - /* prepend 24bit IV to tx key, byte order does not matter */ - key[0] = sc->wi_icv >> 16; - key[1] = sc->wi_icv >> 8; - key[2] = sc->wi_icv; - - klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen + - IEEE80211_WEP_IVLEN; - klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2; - bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat, - (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN); - - /* rc4 keysetup */ - x = y = 0; - for (i = 0; i < RC4STATE; i++) - state[i] = i; - for (i = 0; i < RC4STATE; i++) { - y = (key[x] + state[i] + y) % RC4STATE; - RC4SWAP(i, y); - x = (x + 1) % klen; - } - - /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */ - dat = buf; - dat[0] = key[0]; - dat[1] = key[1]; - dat[2] = key[2]; - dat[3] = sc->wi_tx_key << 6; /* pad and keyid */ - dat += 4; - - /* compute rc4 over data, crc32 over data */ - crc = ~0; - x = y = 0; - for (i = 0; i < len; i++) { - x = (x + 1) % RC4STATE; - y = (state[x] + y) % RC4STATE; - RC4SWAP(x, y); - crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8); - dat[i] ^= state[(state[x] + state[y]) % RC4STATE]; - } - crc = ~crc; - dat += len; - - /* append little-endian crc32 and encrypt */ - dat[0] = crc; - dat[1] = crc >> 8; - dat[2] = crc >> 16; - dat[3] = crc >> 24; - for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) { - x = (x + 1) % RC4STATE; - y = (state[x] + y) % RC4STATE; - RC4SWAP(x, y); - dat[i] ^= state[(state[x] + state[y]) % RC4STATE]; - } -} - -static void -wi_start(struct ifnet *ifp) -{ - struct wi_softc *sc = ifp->if_softc; - struct mbuf *m0; - struct wi_frame tx_frame; - struct ether_header *eh; - int id; - - if (sc->wi_gone) - return; - - if (ifp->if_flags & IFF_OACTIVE) - return; - -nextpkt: - m0 = ifq_dequeue(&ifp->if_snd, NULL); - if (m0 == NULL) - return; - - bzero((char *)&tx_frame, sizeof(tx_frame)); - tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA); - id = sc->wi_tx_data_id; - eh = mtod(m0, struct ether_header *); - - if (sc->wi_ptype == WI_PORTTYPE_AP) { - if (!owihap_check_tx(&sc->wi_hostap_info, - eh->ether_dhost, &tx_frame.wi_tx_rate)) { - if (ifp->if_flags & IFF_DEBUG) - printf("wi_start: dropping unassoc " - "dst %6D\n", eh->ether_dhost, ":"); - m_freem(m0); - goto nextpkt; - } - } - /* - * Use RFC1042 encoding for IP and ARP datagrams, - * 802.3 for anything else. - */ - if (ntohs(eh->ether_type) > ETHER_MAX_LEN) { - bcopy((char *)&eh->ether_dhost, - (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN); - if (sc->wi_ptype == WI_PORTTYPE_AP) { - tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT; /* XXX */ - tx_frame.wi_frame_ctl |= WI_FCTL_FROMDS; - if (sc->wi_use_wep) - tx_frame.wi_frame_ctl |= WI_FCTL_WEP; - bcopy((char *)&sc->arpcom.ac_enaddr, - (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN); - bcopy((char *)&eh->ether_shost, - (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN); - } - else - bcopy((char *)&eh->ether_shost, - (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN); - bcopy((char *)&eh->ether_dhost, - (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN); - bcopy((char *)&eh->ether_shost, - (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN); - - tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN; - tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0); - tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1); - tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN); - tx_frame.wi_type = eh->ether_type; - - if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) { - /* Do host encryption. */ - bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8); - m_copydata(m0, sizeof(struct ether_header), - m0->m_pkthdr.len - sizeof(struct ether_header), - (caddr_t)&sc->wi_txbuf[12]); - wi_do_hostencrypt(sc, &sc->wi_txbuf[0], - tx_frame.wi_dat_len); - tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN + - IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; - wi_write_data(sc, id, 0, (caddr_t)&tx_frame, - sizeof(struct wi_frame)); - wi_write_data(sc, id, WI_802_11_OFFSET_RAW, - (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len - - sizeof(struct ether_header)) + 18); - } else { - m_copydata(m0, sizeof(struct ether_header), - m0->m_pkthdr.len - sizeof(struct ether_header), - (caddr_t)&sc->wi_txbuf); - wi_write_data(sc, id, 0, (caddr_t)&tx_frame, - sizeof(struct wi_frame)); - wi_write_data(sc, id, WI_802_11_OFFSET, - (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len - - sizeof(struct ether_header)) + 2); - } - } else { - tx_frame.wi_dat_len = m0->m_pkthdr.len; - - if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) { - /* Do host encryption. */ - printf( "XXX: host encrypt not implemented for 802.3\n" ); - } else { - eh->ether_type = htons(m0->m_pkthdr.len - - WI_SNAPHDR_LEN); - m_copydata(m0, 0, m0->m_pkthdr.len, - (caddr_t)&sc->wi_txbuf); - - wi_write_data(sc, id, 0, (caddr_t)&tx_frame, - sizeof(struct wi_frame)); - wi_write_data(sc, id, WI_802_3_OFFSET, - (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2); - } - } - - /* - * If there's a BPF listner, bounce a copy of - * this frame to him. Also, don't send this to the bpf sniffer - * if we're in procframe or monitor sniffing mode. - */ - if (!(sc->wi_procframe || sc->wi_debug.wi_monitor)) - BPF_MTAP(ifp, m0); - - m_freem(m0); - - if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) - device_printf(sc->dev, "xmit failed\n"); - - ifp->if_flags |= IFF_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; -} - -int -owi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len) -{ - struct wi_frame tx_frame; - int id; - struct wi_80211_hdr *hdr; - caddr_t dptr; - - if (sc->wi_gone) - return(ENODEV); - - hdr = (struct wi_80211_hdr *)data; - dptr = data + sizeof(struct wi_80211_hdr); - - bzero((char *)&tx_frame, sizeof(tx_frame)); - id = sc->wi_tx_mgmt_id; - - bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl, - sizeof(struct wi_80211_hdr)); - - tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT; - tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr); - tx_frame.wi_len = htons(tx_frame.wi_dat_len); - - wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame)); - wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr, - len - sizeof(struct wi_80211_hdr) + 2); - - if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) { - device_printf(sc->dev, "xmit failed\n"); - return(EIO); - } - - return(0); -} - -static void -wi_stop(struct wi_softc *sc) -{ - struct ifnet *ifp; - - if (sc->wi_gone) - return; - - owihap_shutdown(sc); - - ifp = &sc->arpcom.ac_if; - - /* - * If the card is gone and the memory port isn't mapped, we will - * (hopefully) get 0xffff back from the status read, which is not - * a valid status value. - */ - if (CSR_READ_2(sc, WI_STATUS) != 0xffff) { - CSR_WRITE_2(sc, WI_INT_EN, 0); - wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0); - } - - callout_stop(&sc->wi_stat_timer); - - ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); -} - -static void -wi_watchdog(struct ifnet *ifp) -{ - struct wi_softc *sc; - - sc = ifp->if_softc; - - device_printf(sc->dev, "watchdog timeout\n"); - - wi_init(sc); - - ifp->if_oerrors++; - - return; -} - -int -owi_alloc(device_t dev, int rid) -{ - struct wi_softc *sc = device_get_softc(dev); - - if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { - sc->iobase_rid = rid; - sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->iobase_rid, 0, ~0, (1 << 6), - rman_make_alignment_flags(1 << 6) | RF_ACTIVE); - if (!sc->iobase) { - device_printf(dev, "No I/O space?!\n"); - return (ENXIO); - } - - sc->wi_io_addr = rman_get_start(sc->iobase); - sc->wi_btag = rman_get_bustag(sc->iobase); - sc->wi_bhandle = rman_get_bushandle(sc->iobase); - } else { - sc->mem_rid = rid; - sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->mem_rid, RF_ACTIVE); - - if (!sc->mem) { - device_printf(dev, "No Mem space on prism2.5?\n"); - return (ENXIO); - } - - sc->wi_btag = rman_get_bustag(sc->mem); - sc->wi_bhandle = rman_get_bushandle(sc->mem); - } - - - sc->irq_rid = 0; - sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, - RF_ACTIVE | - ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE)); - - if (!sc->irq) { - owi_free(dev); - device_printf(dev, "No irq?!\n"); - return (ENXIO); - } - - sc->dev = dev; - sc->wi_unit = device_get_unit(dev); - - return (0); -} - -void -owi_free(device_t dev) -{ - struct wi_softc *sc = device_get_softc(dev); - - if (sc->iobase != NULL) { - bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase); - sc->iobase = NULL; - } - if (sc->irq != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); - sc->irq = NULL; - } - if (sc->mem != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem); - sc->mem = NULL; - } - - return; -} - -void -owi_shutdown(device_t dev) -{ - struct wi_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - ifp = &sc->arpcom.ac_if; - lwkt_serialize_enter(ifp->if_serializer); - wi_stop(sc); - lwkt_serialize_exit(ifp->if_serializer); -} - -#ifdef WICACHE -/* wavelan signal strength cache code. - * store signal/noise/quality on per MAC src basis in - * a small fixed cache. The cache wraps if > MAX slots - * used. The cache may be zeroed out to start over. - * Two simple filters exist to reduce computation: - * 1. ip only (literally 0x800) which may be used - * to ignore some packets. It defaults to ip only. - * it could be used to focus on broadcast, non-IP 802.11 beacons. - * 2. multicast/broadcast only. This may be used to - * ignore unicast packets and only cache signal strength - * for multicast/broadcast packets (beacons); e.g., Mobile-IP - * beacons and not unicast traffic. - * - * The cache stores (MAC src(index), IP src (major clue), signal, - * quality, noise) - * - * No apologies for storing IP src here. It's easy and saves much - * trouble elsewhere. The cache is assumed to be INET dependent, - * although it need not be. - */ - -#ifdef documentation - -int owi_sigitems; /* number of cached entries */ -struct wi_sigcache owi_sigcache[MAXWICACHE]; /* array of cache entries */ -int owi_nextitem; /* index/# of entries */ - - -#endif - -/* control variables for cache filtering. Basic idea is - * to reduce cost (e.g., to only Mobile-IP agent beacons - * which are broadcast or multicast). Still you might - * want to measure signal strength with unicast ping packets - * on a pt. to pt. ant. setup. - */ -/* set true if you want to limit cache items to broadcast/mcast - * only packets (not unicast). Useful for mobile-ip beacons which - * are broadcast/multicast at network layer. Default is all packets - * so ping/unicast will work say with pt. to pt. antennae setup. - */ -static int wi_cache_mcastonly = 0; -SYSCTL_INT(_machdep, OID_AUTO, owi_cache_mcastonly, CTLFLAG_RW, - &wi_cache_mcastonly, 0, ""); - -/* set true if you want to limit cache items to IP packets only -*/ -static int wi_cache_iponly = 1; -SYSCTL_INT(_machdep, OID_AUTO, owi_cache_iponly, CTLFLAG_RW, - &wi_cache_iponly, 0, ""); - -/* - * Original comments: - * ----------------- - * wi_cache_store, per rx packet store signal - * strength in MAC (src) indexed cache. - * - * follows linux driver in how signal strength is computed. - * In ad hoc mode, we use the rx_quality field. - * signal and noise are trimmed to fit in the range from 47..138. - * rx_quality field MSB is signal strength. - * rx_quality field LSB is noise. - * "quality" is (signal - noise) as is log value. - * note: quality CAN be negative. - * - * In BSS mode, we use the RID for communication quality. - * TBD: BSS mode is currently untested. - * - * Bill's comments: - * --------------- - * Actually, we use the rx_quality field all the time for both "ad-hoc" - * and BSS modes. Why? Because reading an RID is really, really expensive: - * there's a bunch of PIO operations that have to be done to read a record - * from the NIC, and reading the comms quality RID each time a packet is - * received can really hurt performance. We don't have to do this anyway: - * the comms quality field only reflects the values in the rx_quality field - * anyway. The comms quality RID is only meaningful in infrastructure mode, - * but the values it contains are updated based on the rx_quality from - * frames received from the access point. - * - * Also, according to Lucent, the signal strength and noise level values - * can be converted to dBms by subtracting 149, so I've modified the code - * to do that instead of the scaling it did originally. - */ -static void -wi_cache_store(struct wi_softc *sc, struct mbuf *m, unsigned short rx_quality) -{ - struct ether_header *eh = mtod(m, struct ether_header *); - struct ip *ip = NULL; - int i; - static int cache_slot = 0; /* use this cache entry */ - static int wrapindex = 0; /* next "free" cache entry */ - int sig, noise; - - /* - * filters: - * 1. ip only - * 2. configurable filter to throw out unicast packets, - * keep multicast only. - */ - - if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) - ip = (struct ip *)(mtod(m, uint8_t *) + ETHER_HDR_LEN); - else if (wi_cache_iponly) - return; - - /* - * filter for broadcast/multicast only - */ - if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { - return; - } - -#ifdef SIGDEBUG - printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit, - rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); -#endif - - - /* - * do a linear search for a matching MAC address - * in the cache table - * . MAC address is 6 bytes, - * . var w_nextitem holds total number of entries already cached - */ - for(i = 0; i < sc->wi_nextitem; i++) { - if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc, 6 )) { - /* - * Match!, - * so we already have this entry, - * update the data - */ - break; - } - } - - /* - * did we find a matching mac address? - * if yes, then overwrite a previously existing cache entry - */ - if (i < sc->wi_nextitem ) { - cache_slot = i; - } - /* - * else, have a new address entry,so - * add this new entry, - * if table full, then we need to replace LRU entry - */ - else { - - /* - * check for space in cache table - * note: wi_nextitem also holds number of entries - * added in the cache table - */ - if ( sc->wi_nextitem < MAXWICACHE ) { - cache_slot = sc->wi_nextitem; - sc->wi_nextitem++; - sc->wi_sigitems = sc->wi_nextitem; - } - /* no space found, so simply wrap with wrap index - * and "zap" the next entry - */ - else { - if (wrapindex == MAXWICACHE) { - wrapindex = 0; - } - cache_slot = wrapindex++; - } - } - - /* - * invariant: cache_slot now points at some slot - * in cache. - */ - if (cache_slot < 0 || cache_slot >= MAXWICACHE) { - log(LOG_ERR, "wi_cache_store, bad index: %d of " - "[0..%d], gross cache error\n", - cache_slot, MAXWICACHE); - return; - } - - /* - * store items in cache - * .ip source address - * .mac src - * .signal, etc. - */ - if (ip != NULL) - sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; - bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc, 6); - - sig = (rx_quality >> 8) & 0xFF; - noise = rx_quality & 0xFF; - sc->wi_sigcache[cache_slot].signal = sig - 149; - sc->wi_sigcache[cache_slot].noise = noise - 149; - sc->wi_sigcache[cache_slot].quality = sig - noise; - - return; -} -#endif - -static int -wi_get_cur_ssid(struct wi_softc *sc, char *ssid, int *len) -{ - int error = 0; - struct wi_req wreq; - - wreq.wi_len = WI_MAX_DATALEN; - switch (sc->wi_ptype) { - case WI_PORTTYPE_AP: - *len = IEEE80211_NWID_LEN; - bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN); - break; - case WI_PORTTYPE_ADHOC: - wreq.wi_type = WI_RID_CURRENT_SSID; - error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); - if (error != 0) - break; - if (wreq.wi_val[0] > IEEE80211_NWID_LEN) { - error = EINVAL; - break; - } - *len = wreq.wi_val[0]; - bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN); - break; - case WI_PORTTYPE_BSS: - wreq.wi_type = WI_RID_COMMQUAL; - error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); - if (error != 0) - break; - if (wreq.wi_val[0] != 0) /* associated */ { - wreq.wi_type = WI_RID_CURRENT_SSID; - wreq.wi_len = WI_MAX_DATALEN; - error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq); - if (error != 0) - break; - if (wreq.wi_val[0] > IEEE80211_NWID_LEN) { - error = EINVAL; - break; - } - *len = wreq.wi_val[0]; - bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN); - } else { - *len = IEEE80211_NWID_LEN; - bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN); - } - break; - default: - error = EINVAL; - break; - } - - return error; -} - -static int -wi_media_change(struct ifnet *ifp) -{ - struct wi_softc *sc = ifp->if_softc; - int otype = sc->wi_ptype; - int orate = sc->wi_tx_rate; - int ocreate_ibss = sc->wi_create_ibss; - - if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) && - sc->sc_firmware_type != WI_INTERSIL) - return (EINVAL); - - sc->wi_create_ibss = 0; - - switch (sc->ifmedia.ifm_cur->ifm_media & IFM_OMASK) { - case 0: - sc->wi_ptype = WI_PORTTYPE_BSS; - break; - case IFM_IEEE80211_ADHOC: - sc->wi_ptype = WI_PORTTYPE_ADHOC; - break; - case IFM_IEEE80211_HOSTAP: - sc->wi_ptype = WI_PORTTYPE_AP; - break; - case IFM_IEEE80211_IBSSMASTER: - case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS: - if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) - return (EINVAL); - sc->wi_create_ibss = 1; - /* FALLTHROUGH */ - case IFM_IEEE80211_IBSS: - sc->wi_ptype = WI_PORTTYPE_IBSS; - break; - default: - /* Invalid combination. */ - return (EINVAL); - } - - switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { - case IFM_IEEE80211_DS1: - sc->wi_tx_rate = 1; - break; - case IFM_IEEE80211_DS2: - sc->wi_tx_rate = 2; - break; - case IFM_IEEE80211_DS5: - sc->wi_tx_rate = 5; - break; - case IFM_IEEE80211_DS11: - sc->wi_tx_rate = 11; - break; - case IFM_AUTO: - sc->wi_tx_rate = 3; - break; - } - - if (ocreate_ibss != sc->wi_create_ibss || otype != sc->wi_ptype || - orate != sc->wi_tx_rate) - wi_init(sc); - - return(0); -} - -static void -wi_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct wi_req wreq; - struct wi_softc *sc = ifp->if_softc; - - if (sc->wi_tx_rate == 3) { - imr->ifm_active = IFM_IEEE80211|IFM_AUTO; - if (sc->wi_ptype == WI_PORTTYPE_ADHOC) - imr->ifm_active |= IFM_IEEE80211_ADHOC; - else if (sc->wi_ptype == WI_PORTTYPE_AP) - imr->ifm_active |= IFM_IEEE80211_HOSTAP; - else if (sc->wi_ptype == WI_PORTTYPE_IBSS) { - if (sc->wi_create_ibss) - imr->ifm_active |= IFM_IEEE80211_IBSSMASTER; - else - imr->ifm_active |= IFM_IEEE80211_IBSS; - } - wreq.wi_type = WI_RID_CUR_TX_RATE; - wreq.wi_len = WI_MAX_DATALEN; - if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) { - switch(wreq.wi_val[0]) { - case 1: - imr->ifm_active |= IFM_IEEE80211_DS1; - break; - case 2: - imr->ifm_active |= IFM_IEEE80211_DS2; - break; - case 6: - imr->ifm_active |= IFM_IEEE80211_DS5; - break; - case 11: - imr->ifm_active |= IFM_IEEE80211_DS11; - break; - } - } - } else { - imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; - } - - imr->ifm_status = IFM_AVALID; - if (sc->wi_ptype == WI_PORTTYPE_ADHOC || - sc->wi_ptype == WI_PORTTYPE_IBSS) - /* - * XXX: It would be nice if we could give some actually - * useful status like whether we joined another IBSS or - * created one ourselves. - */ - imr->ifm_status |= IFM_ACTIVE; - else if (sc->wi_ptype == WI_PORTTYPE_AP) - imr->ifm_status |= IFM_ACTIVE; - else { - wreq.wi_type = WI_RID_COMMQUAL; - wreq.wi_len = WI_MAX_DATALEN; - if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 && - wreq.wi_val[0] != 0) - imr->ifm_status |= IFM_ACTIVE; - } -} - -static int -wi_get_debug(struct wi_softc *sc, struct wi_req *wreq) -{ - int error = 0; - - wreq->wi_len = 1; - - switch (wreq->wi_type) { - case WI_DEBUG_SLEEP: - wreq->wi_len++; - wreq->wi_val[0] = sc->wi_debug.wi_sleep; - break; - case WI_DEBUG_DELAYSUPP: - wreq->wi_len++; - wreq->wi_val[0] = sc->wi_debug.wi_delaysupp; - break; - case WI_DEBUG_TXSUPP: - wreq->wi_len++; - wreq->wi_val[0] = sc->wi_debug.wi_txsupp; - break; - case WI_DEBUG_MONITOR: - wreq->wi_len++; - wreq->wi_val[0] = sc->wi_debug.wi_monitor; - break; - case WI_DEBUG_LEDTEST: - wreq->wi_len += 3; - wreq->wi_val[0] = sc->wi_debug.wi_ledtest; - wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0; - wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1; - break; - case WI_DEBUG_CONTTX: - wreq->wi_len += 2; - wreq->wi_val[0] = sc->wi_debug.wi_conttx; - wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0; - break; - case WI_DEBUG_CONTRX: - wreq->wi_len++; - wreq->wi_val[0] = sc->wi_debug.wi_contrx; - break; - case WI_DEBUG_SIGSTATE: - wreq->wi_len += 2; - wreq->wi_val[0] = sc->wi_debug.wi_sigstate; - wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0; - break; - case WI_DEBUG_CONFBITS: - wreq->wi_len += 2; - wreq->wi_val[0] = sc->wi_debug.wi_confbits; - wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0; - break; - default: - error = EIO; - break; - } - - return (error); -} - -static int -wi_set_debug(struct wi_softc *sc, struct wi_req *wreq) -{ - int error = 0; - u_int16_t cmd, param0 = 0, param1 = 0; - - switch (wreq->wi_type) { - case WI_DEBUG_RESET: - case WI_DEBUG_INIT: - case WI_DEBUG_CALENABLE: - break; - case WI_DEBUG_SLEEP: - sc->wi_debug.wi_sleep = 1; - break; - case WI_DEBUG_WAKE: - sc->wi_debug.wi_sleep = 0; - break; - case WI_DEBUG_CHAN: - param0 = wreq->wi_val[0]; - break; - case WI_DEBUG_DELAYSUPP: - sc->wi_debug.wi_delaysupp = 1; - break; - case WI_DEBUG_TXSUPP: - sc->wi_debug.wi_txsupp = 1; - break; - case WI_DEBUG_MONITOR: - sc->wi_debug.wi_monitor = 1; - break; - case WI_DEBUG_LEDTEST: - param0 = wreq->wi_val[0]; - param1 = wreq->wi_val[1]; - sc->wi_debug.wi_ledtest = 1; - sc->wi_debug.wi_ledtest_param0 = param0; - sc->wi_debug.wi_ledtest_param1 = param1; - break; - case WI_DEBUG_CONTTX: - param0 = wreq->wi_val[0]; - sc->wi_debug.wi_conttx = 1; - sc->wi_debug.wi_conttx_param0 = param0; - break; - case WI_DEBUG_STOPTEST: - sc->wi_debug.wi_delaysupp = 0; - sc->wi_debug.wi_txsupp = 0; - sc->wi_debug.wi_monitor = 0; - sc->wi_debug.wi_ledtest = 0; - sc->wi_debug.wi_ledtest_param0 = 0; - sc->wi_debug.wi_ledtest_param1 = 0; - sc->wi_debug.wi_conttx = 0; - sc->wi_debug.wi_conttx_param0 = 0; - sc->wi_debug.wi_contrx = 0; - sc->wi_debug.wi_sigstate = 0; - sc->wi_debug.wi_sigstate_param0 = 0; - break; - case WI_DEBUG_CONTRX: - sc->wi_debug.wi_contrx = 1; - break; - case WI_DEBUG_SIGSTATE: - param0 = wreq->wi_val[0]; - sc->wi_debug.wi_sigstate = 1; - sc->wi_debug.wi_sigstate_param0 = param0; - break; - case WI_DEBUG_CONFBITS: - param0 = wreq->wi_val[0]; - param1 = wreq->wi_val[1]; - sc->wi_debug.wi_confbits = param0; - sc->wi_debug.wi_confbits_param0 = param1; - break; - default: - error = EIO; - break; - } - - if (error) - return (error); - - cmd = WI_CMD_DEBUG | (wreq->wi_type << 8); - error = wi_cmd(sc, cmd, param0, param1, 0); - - return (error); -} diff --git a/sys/dev/netif/owi/if_owi_pccard.c b/sys/dev/netif/owi/if_owi_pccard.c deleted file mode 100644 index f42b18c23c..0000000000 --- a/sys/dev/netif/owi/if_owi_pccard.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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 Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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. - * - * $FreeBSD: src/sys/dev/wi/if_wi_pccard.c,v 1.8.2.2 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/if_owi_pccard.c,v 1.2 2005/12/11 01:54:09 swildner Exp $ - */ - -/* - * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "wi_hostap.h" -#include "if_wivar.h" -#include "if_wireg.h" - -#include "card_if.h" - -static int wi_pccard_probe(device_t); -static int wi_pccard_attach(device_t); - -static int wi_pccard_match(device_t); - -static device_method_t wi_pccard_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pccard_compat_probe), - DEVMETHOD(device_attach, pccard_compat_attach), - DEVMETHOD(device_detach, owi_generic_detach), - DEVMETHOD(device_shutdown, owi_shutdown), - - /* Card interface */ - DEVMETHOD(card_compat_match, wi_pccard_match), - DEVMETHOD(card_compat_probe, wi_pccard_probe), - DEVMETHOD(card_compat_attach, wi_pccard_attach), - - { 0, 0 } -}; - -static driver_t wi_pccard_driver = { - "owi", - wi_pccard_methods, - sizeof(struct wi_softc) -}; - -DRIVER_MODULE(if_owi, pccard, wi_pccard_driver, owi_devclass, 0, 0); - -static const struct pccard_product wi_pccard_products[] = { - PCMCIA_CARD(3COM, 3CRWE737A, 0), - PCMCIA_CARD(3COM, 3CRWE777A, 0), - PCMCIA_CARD(ACTIONTEC, PRISM, 0), - PCMCIA_CARD(ADDTRON, AWP100, 0), - PCMCIA_CARD(AIRVAST, WN_100, 0), - PCMCIA_CARD(ALLIEDTELESIS, WR211PCM, 0), - PCMCIA_CARD(ARTEM, ONAIR, 0), - PCMCIA_CARD(ASUS, WL100, 0), - PCMCIA_CARD(BAY, EMOBILITY_11B, 0), - PCMCIA_CARD(BROMAX, IWN, 0), - PCMCIA_CARD(BROMAX, IWN3, 0), - PCMCIA_CARD(BROMAX, WCF11, 0), - PCMCIA_CARD(BUFFALO, WLI_CF_S11G, 0), - PCMCIA_CARD(BUFFALO, WLI_PCM_S11, 0), - PCMCIA_CARD(COMPAQ, NC5004, 0), - PCMCIA_CARD(CONTEC, FX_DS110_PCC, 0), - PCMCIA_CARD(COREGA, WIRELESS_LAN_PCC_11, 0), - PCMCIA_CARD(COREGA, WIRELESS_LAN_PCCA_11, 0), - PCMCIA_CARD(COREGA, WIRELESS_LAN_PCCB_11, 0), - PCMCIA_CARD(COREGA, WIRELESS_LAN_PCCL_11, 0), - PCMCIA_CARD(DLINK, DWL650H, 0), - PCMCIA_CARD(ELSA, XI300_IEEE, 0), - PCMCIA_CARD(ELSA, XI325_IEEE, 0), - PCMCIA_CARD(ELSA, XI800_IEEE, 0), - PCMCIA_CARD(EMTAC, WLAN, 0), - PCMCIA_CARD(ERICSSON, WIRELESSLAN, 0), - PCMCIA_CARD(GEMTEK, WLAN, 0), - PCMCIA_CARD(HWN, AIRWAY80211, 0), - PCMCIA_CARD(INTEL, PRO_WLAN_2011, 0), - PCMCIA_CARD(INTERSIL, MA401RA, 0), - PCMCIA_CARD(INTERSIL2, PRISM2, 0), - PCMCIA_CARD(IODATA2, WCF12, 0), - PCMCIA_CARD(IODATA2, WNB11PCM, 0), - PCMCIA_CARD(FUJITSU, WL110, 0), - PCMCIA_CARD(LUCENT, WAVELAN_IEEE, 0), - PCMCIA_CARD(MICROSOFT, MN_520, 0), - PCMCIA_CARD(NOKIA, C020_WLAN, 0), - PCMCIA_CARD(NOKIA, C110_WLAN, 0), - PCMCIA_CARD(PLANEX_2, GWNS11H, 0), - PCMCIA_CARD(PROXIM, HARMONY, 0), - PCMCIA_CARD(PROXIM, RANGELANDS_8430, 0), - PCMCIA_CARD(SAMSUNG, SWL_2000N, 0), - PCMCIA_CARD(SIEMENS, SS1021, 0), - PCMCIA_CARD(SIMPLETECH, SPECTRUM24_ALT, 0), - PCMCIA_CARD(SOCKET, LP_WLAN_CF, 0), - PCMCIA_CARD(SYMBOL, LA4100, 0), - PCMCIA_CARD(TDK, LAK_CD011WL, 0), - { NULL } -}; - -static int -wi_pccard_match(device_t dev) -{ - const struct pccard_product *pp; - - if ((pp = pccard_product_lookup(dev, wi_pccard_products, - sizeof(wi_pccard_products[0]), NULL)) != NULL) { - device_set_desc(dev, pp->pp_name); - return 0; - } - return ENXIO; -} - -static int -wi_pccard_probe(device_t dev) -{ - struct wi_softc *sc; - int error; - - sc = device_get_softc(dev); - sc->wi_gone = 0; - sc->wi_bus_type = WI_BUS_PCCARD; - - error = owi_alloc(dev, 0); - if (error) - return (error); - - owi_free(dev); - - /* Make sure interrupts are disabled. */ - CSR_WRITE_2(sc, WI_INT_EN, 0); - CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); - - return (0); -} - -static int -wi_pccard_attach(device_t dev) -{ - struct wi_softc *sc; - int error; - - sc = device_get_softc(dev); - - error = owi_alloc(dev, 0); - if (error) { - device_printf(dev, "wi_alloc() failed! (%d)\n", error); - return (error); - } - return (owi_generic_attach(dev)); -} diff --git a/sys/dev/netif/owi/if_owi_pci.c b/sys/dev/netif/owi/if_owi_pci.c deleted file mode 100644 index 65c5b348b9..0000000000 --- a/sys/dev/netif/owi/if_owi_pci.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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 Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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. - * - * $FreeBSD: src/sys/dev/wi/if_wi_pci.c,v 1.8.2.3 2002/06/16 18:07:18 nsayer Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/if_owi_pci.c,v 1.3 2005/12/11 01:54:09 swildner Exp $ - */ - -/* - * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wi_hostap.h" -#include "if_wivar.h" -#include "if_wireg.h" - -static int wi_pci_probe(device_t); -static int wi_pci_attach(device_t); - -static device_method_t wi_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, wi_pci_probe), - DEVMETHOD(device_attach, wi_pci_attach), - DEVMETHOD(device_detach, owi_generic_detach), - DEVMETHOD(device_shutdown, owi_shutdown), - - { 0, 0 } -}; - -static driver_t wi_pci_driver = { - "owi", - wi_pci_methods, - sizeof(struct wi_softc) -}; - -static struct { - unsigned int vendor,device; - int bus_type; - char *desc; -} pci_ids[] = { - /* Sorted by description */ - {0x10b7, 0x7770, WI_BUS_PCI_PLX, "3Com Airconnect"}, - {0x16ab, 0x1101, WI_BUS_PCI_PLX, "GLPRISM2 WaveLAN"}, - {0x1260, 0x3873, WI_BUS_PCI_NATIVE, "Intersil Prism2.5"}, - {0x16ab, 0x1102, WI_BUS_PCI_PLX, "Linksys WDT11"}, - {0x1385, 0x4100, WI_BUS_PCI_PLX, "Netgear MA301"}, - {0x1638, 0x1100, WI_BUS_PCI_PLX, "PRISM2STA WaveLAN"}, - {0x111a, 0x1023, WI_BUS_PCI_PLX, "Siemens SpeedStream"}, - {0x16ec, 0x3685, WI_BUS_PCI_PLX, "US Robotics 2415"}, - {0, 0, 0, NULL} -}; - -DRIVER_MODULE(if_owi, pci, wi_pci_driver, owi_devclass, 0, 0); - -static int -wi_pci_probe(device_t dev) -{ - struct wi_softc *sc; - int i; - - sc = device_get_softc(dev); - for(i=0; pci_ids[i].vendor != 0; i++) { - if ((pci_get_vendor(dev) == pci_ids[i].vendor) && - (pci_get_device(dev) == pci_ids[i].device)) { - sc->wi_bus_type = pci_ids[i].bus_type; - device_set_desc(dev, pci_ids[i].desc); - return (0); - } - } - return(ENXIO); -} - -static int -wi_pci_attach(device_t dev) -{ - struct wi_softc *sc; - u_int32_t command, wanted; - u_int16_t reg; - int error; - int timeout; - - sc = device_get_softc(dev); - - command = pci_read_config(dev, PCIR_COMMAND, 4); - wanted = PCIM_CMD_PORTEN|PCIM_CMD_MEMEN; - command |= wanted; - pci_write_config(dev, PCIR_COMMAND, command, 4); - command = pci_read_config(dev, PCIR_COMMAND, 4); - if ((command & wanted) != wanted) { - device_printf(dev, "wi_pci_attach() failed to enable pci!\n"); - return (ENXIO); - } - - if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { - error = owi_alloc(dev, WI_PCI_IORES); - if (error) - return (error); - - /* Make sure interrupts are disabled. */ - CSR_WRITE_2(sc, WI_INT_EN, 0); - CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); - - /* We have to do a magic PLX poke to enable interrupts */ - sc->local_rid = WI_PCI_LOCALRES; - sc->local = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &sc->local_rid, RF_ACTIVE); - sc->wi_localtag = rman_get_bustag(sc->local); - sc->wi_localhandle = rman_get_bushandle(sc->local); - command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle, - WI_LOCAL_INTCSR); - command |= WI_LOCAL_INTEN; - bus_space_write_4(sc->wi_localtag, sc->wi_localhandle, - WI_LOCAL_INTCSR, command); - bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid, - sc->local); - sc->local = NULL; - - sc->mem_rid = WI_PCI_MEMRES; - sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->mem_rid, RF_ACTIVE); - if (sc->mem == NULL) { - device_printf(dev, "couldn't allocate memory\n"); - owi_free(dev); - return (ENXIO); - } - sc->wi_bmemtag = rman_get_bustag(sc->mem); - sc->wi_bmemhandle = rman_get_bushandle(sc->mem); - - /* - * From Linux driver: - * Write COR to enable PC card - * This is a subset of the protocol that the pccard bus code - * would do. - */ - CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); - reg = CSM_READ_1(sc, WI_COR_OFFSET); - if (reg != WI_COR_VALUE) { - device_printf(dev, "CSM_READ_1(WI_COR_OFFSET) " - "wanted %d, got %d\n", WI_COR_VALUE, reg); - owi_free(dev); - return (ENXIO); - } - } else { - error = owi_alloc(dev, WI_PCI_LMEMRES); - if (error) - return (error); - - CSR_WRITE_2(sc, WI_HFA384X_PCICOR_OFF, 0x0080); - DELAY(250000); - - CSR_WRITE_2(sc, WI_HFA384X_PCICOR_OFF, 0x0000); - DELAY(500000); - - timeout=2000000; - while ((--timeout > 0) && - (CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) - DELAY(10); - - if (timeout == 0) { - device_printf(dev, "couldn't reset prism2.5 core.\n"); - owi_free(dev); - return(ENXIO); - } - } - - CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC); - reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF); - if (reg != WI_PRISM2STA_MAGIC) { - device_printf(dev, - "CSR_READ_2(WI_HFA384X_SWSUPPORT0_OFF) " - "wanted %d, got %d\n", WI_PRISM2STA_MAGIC, reg); - owi_free(dev); - return (ENXIO); - } - - return (owi_generic_attach(dev)); -} diff --git a/sys/dev/netif/owi/if_wireg.h b/sys/dev/netif/owi/if_wireg.h deleted file mode 100644 index debd70d28f..0000000000 --- a/sys/dev/netif/owi/if_wireg.h +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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 Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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. - * - * $FreeBSD: src/sys/dev/wi/if_wireg.h,v 1.31.2.2 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/if_wireg.h,v 1.1 2004/09/05 13:34:56 joerg Exp $ - */ - -#define WI_DELAY 5 -#define WI_TIMEOUT (500000/WI_DELAY) /* 500 ms */ - -#define WI_PORT0 0 -#define WI_PORT1 1 -#define WI_PORT2 2 -#define WI_PORT3 3 -#define WI_PORT4 4 -#define WI_PORT5 5 - -#define WI_PCI_LMEMRES 0x10 /* PCI Memory (native PCI implementations) */ -#define WI_PCI_LOCALRES 0x14 /* The PLX chip's local registers */ -#define WI_PCI_MEMRES 0x18 /* The PCCard's attribute memory */ -#define WI_PCI_IORES 0x1C /* The PCCard's I/O space */ - -#define WI_LOCAL_INTCSR 0x4c -#define WI_LOCAL_INTEN 0x40 -#define WI_HFA384X_SWSUPPORT0_OFF 0x28 -#define WI_PRISM2STA_MAGIC 0x4A2D -#define WI_HFA384X_PCICOR_OFF 0x26 - -/* Default port: 0 (only 0 exists on stations) */ -#define WI_DEFAULT_PORT (WI_PORT0 << 8) - -/* Default TX rate: 2Mbps, auto fallback */ -#define WI_DEFAULT_TX_RATE 3 - -/* Default network name: ANY */ -/* - * [sommerfeld 1999/07/15] Changed from "ANY" to ""; according to Bill Fenner, - * ANY is used in MS driver user interfaces, while "" is used over the - * wire.. - */ -#define WI_DEFAULT_NETNAME "" - -#define WI_DEFAULT_AP_DENSITY 1 - -#define WI_DEFAULT_RTS_THRESH 2347 - -#define WI_DEFAULT_DATALEN 2304 - -#define WI_DEFAULT_CREATE_IBSS 0 - -#define WI_DEFAULT_PM_ENABLED 0 - -#define WI_DEFAULT_MAX_SLEEP 100 - -#define WI_DEFAULT_ROAMING 1 - -#define WI_DEFAULT_AUTHTYPE 1 - -#ifdef __NetBSD__ -#define OS_STRING_NAME "NetBSD" -#endif -#ifdef __DragonFly__ -#define OS_STRING_NAME "DragonFly" -#endif -#ifdef __OpenBSD__ -#define OS_STRING_NAME "OpenBSD" -#endif - -#define WI_DEFAULT_NODENAME OS_STRING_NAME " WaveLAN/IEEE node" - -#define WI_DEFAULT_IBSS OS_STRING_NAME " IBSS" - -#define WI_DEFAULT_CHAN 3 - -#define WI_BUS_PCCARD 0 /* pccard device */ -#define WI_BUS_PCI_PLX 1 /* PCI card w/ PLX PCI/PCMICA bridge */ -#define WI_BUS_PCI_NATIVE 2 /* native PCI device (Prism 2.5) */ - -/* - * register space access macros - */ -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) -#define CSR_WRITE_2(sc, reg, val) \ - bus_space_write_2((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) -#define CSR_WRITE_1(sc, reg, val) \ - bus_space_write_1((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg), val) - -#define CSR_READ_4(sc, reg) \ - bus_space_read_4((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) -#define CSR_READ_2(sc, reg) \ - bus_space_read_2((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) -#define CSR_READ_1(sc, reg) \ - bus_space_read_1((sc)->wi_btag, (sc)->wi_bhandle, \ - (sc)->wi_bus_type == WI_BUS_PCI_NATIVE ? (reg)*2 : (reg)) - -#define CSM_WRITE_1(sc, off, val) \ - bus_space_write_1((sc)->wi_bmemtag, (sc)->wi_bmemhandle, off, val) - -#define CSM_READ_1(sc, off) \ - bus_space_read_1((sc)->wi_bmemtag, (sc)->wi_bmemhandle, off) - -/* - * The WaveLAN/IEEE cards contain an 802.11 MAC controller which Lucent - * calls 'Hermes.' In typical fashion, getting documentation about this - * controller is about as easy as squeezing blood from a stone. Here - * is more or less what I know: - * - * - The Hermes controller is firmware driven, and the host interacts - * with the Hermes via a firmware interface, which can change. - * - * - The Hermes is described in a document called: "Hermes Firmware - * WaveLAN/IEEE Station Functions," document #010245, which of course - * Lucent will not release without an NDA. - * - * - Lucent has created a library called HCF (Hardware Control Functions) - * though which it wants developers to interact with the card. The HCF - * is needlessly complex, ill conceived and badly documented. Actually, - * the comments in the HCP code itself aren't bad, but the publically - * available manual that comes with it is awful, probably due largely to - * the fact that it has been emasculated in order to hide information - * that Lucent wants to keep proprietary. The purpose of the HCF seems - * to be to insulate the driver programmer from the Hermes itself so that - * Lucent has an excuse not to release programming in for it. - * - * - Lucent only makes available documentation and code for 'HCF Light' - * which is a stripped down version of HCF with certain features not - * implemented, most notably support for 802.11 frames. - * - * - The HCF code which I have seen blows goats. Whoever decided to - * use a 132 column format should be shot. - * - * Rather than actually use the Lucent HCF library, I have stripped all - * the useful information from it and used it to create a driver in the - * usual BSD form. Note: I don't want to hear anybody whining about the - * fact that the Lucent code is GPLed and mine isn't. I did not actually - * put any of Lucent's code in this driver: I only used it as a reference - * to obtain information about the underlying hardware. The Hermes - * programming interface is not GPLed, so bite me. - */ - -/* - * Size of Hermes & Prism2 I/O space. - */ -#define WI_IOSIZ 0x40 - -/* - * Hermes & Prism2 register definitions - */ - -/* Hermes command/status registers. */ -#define WI_COMMAND 0x00 -#define WI_PARAM0 0x02 -#define WI_PARAM1 0x04 -#define WI_PARAM2 0x06 -#define WI_STATUS 0x08 -#define WI_RESP0 0x0A -#define WI_RESP1 0x0C -#define WI_RESP2 0x0E - -/* Command register values. */ -#define WI_CMD_BUSY 0x8000 /* busy bit */ -#define WI_CMD_INI 0x0000 /* initialize */ -#define WI_CMD_ENABLE 0x0001 /* enable */ -#define WI_CMD_DISABLE 0x0002 /* disable */ -#define WI_CMD_DIAG 0x0003 -#define WI_CMD_ALLOC_MEM 0x000A /* allocate NIC memory */ -#define WI_CMD_TX 0x000B /* transmit */ -#define WI_CMD_NOTIFY 0x0010 -#define WI_CMD_INQUIRE 0x0011 -#define WI_CMD_ACCESS 0x0021 -#define WI_CMD_PROGRAM 0x0022 - -#define WI_CMD_CODE_MASK 0x003F - -/* - * Reclaim qualifier bit, applicable to the - * TX and INQUIRE commands. - */ -#define WI_RECLAIM 0x0100 /* reclaim NIC memory */ - -/* - * ACCESS command qualifier bits. - */ -#define WI_ACCESS_READ 0x0000 -#define WI_ACCESS_WRITE 0x0100 - -/* - * PROGRAM command qualifier bits. - */ -#define WI_PROGRAM_DISABLE 0x0000 -#define WI_PROGRAM_ENABLE_RAM 0x0100 -#define WI_PROGRAM_ENABLE_NVRAM 0x0200 -#define WI_PROGRAM_NVRAM 0x0300 - -/* Status register values */ -#define WI_STAT_CMD_CODE 0x003F -#define WI_STAT_DIAG_ERR 0x0100 -#define WI_STAT_INQ_ERR 0x0500 -#define WI_STAT_CMD_RESULT 0x7F00 - -/* memory handle management registers */ -#define WI_INFO_FID 0x10 -#define WI_RX_FID 0x20 -#define WI_ALLOC_FID 0x22 -#define WI_TX_CMP_FID 0x24 - -/* - * Buffer Access Path (BAP) registers. - * These are I/O channels. I believe you can use each one for - * any desired purpose independently of the other. In general - * though, we use BAP1 for reading and writing LTV records and - * reading received data frames, and BAP0 for writing transmit - * frames. This is a convention though, not a rule. - */ -#define WI_SEL0 0x18 -#define WI_SEL1 0x1A -#define WI_OFF0 0x1C -#define WI_OFF1 0x1E -#define WI_DATA0 0x36 -#define WI_DATA1 0x38 -#define WI_BAP0 WI_DATA0 -#define WI_BAP1 WI_DATA1 - -#define WI_OFF_BUSY 0x8000 -#define WI_OFF_ERR 0x4000 -#define WI_OFF_DATAOFF 0x0FFF - -/* Event registers */ -#define WI_EVENT_STAT 0x30 /* Event status */ -#define WI_INT_EN 0x32 /* Interrupt enable/disable */ -#define WI_EVENT_ACK 0x34 /* Ack event */ - -/* Events */ -#define WI_EV_TICK 0x8000 /* aux timer tick */ -#define WI_EV_RES 0x4000 /* controller h/w error (time out) */ -#define WI_EV_INFO_DROP 0x2000 /* no RAM to build unsolicited frame */ -#define WI_EV_NO_CARD 0x0800 /* card removed (hunh?) */ -#define WI_EV_DUIF_RX 0x0400 /* wavelan management packet received */ -#define WI_EV_INFO 0x0080 /* async info frame */ -#define WI_EV_CMD 0x0010 /* command completed */ -#define WI_EV_ALLOC 0x0008 /* async alloc/reclaim completed */ -#define WI_EV_TX_EXC 0x0004 /* async xmit completed with failure */ -#define WI_EV_TX 0x0002 /* async xmit completed succesfully */ -#define WI_EV_RX 0x0001 /* async rx completed */ - -#define WI_INTRS \ - (WI_EV_RX|WI_EV_TX|WI_EV_TX_EXC|WI_EV_ALLOC|WI_EV_INFO|WI_EV_INFO_DROP) - -/* Host software registers */ -#define WI_SW0 0x28 -#define WI_SW1 0x2A -#define WI_SW2 0x2C -#define WI_SW3 0x2E /* does not appear in Prism2 */ - -#define WI_CNTL 0x14 - -#define WI_CNTL_AUX_ENA 0xC000 -#define WI_CNTL_AUX_ENA_STAT 0xC000 -#define WI_CNTL_AUX_DIS_STAT 0x0000 -#define WI_CNTL_AUX_ENA_CNTL 0x8000 -#define WI_CNTL_AUX_DIS_CNTL 0x4000 - -#define WI_AUX_PAGE 0x3A -#define WI_AUX_OFFSET 0x3C -#define WI_AUX_DATA 0x3E - -#define WI_COR_OFFSET 0x3e0 -#define WI_COR_VALUE 0x41 - -/* - * One form of communication with the Hermes is with what Lucent calls - * LTV records, where LTV stands for Length, Type and Value. The length - * and type are 16 bits and are in native byte order. The value is in - * multiples of 16 bits and is in little endian byte order. - */ -struct wi_ltv_gen { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_val; -}; - -struct wi_ltv_str { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_str[17]; -}; - -#define WI_SETVAL(recno, val) \ - do { \ - struct wi_ltv_gen g; \ - \ - g.wi_len = 2; \ - g.wi_type = recno; \ - g.wi_val = htole16(val); \ - wi_write_record(sc, &g); \ - } while (0) - -#define WI_SETSTR(recno, str) \ - do { \ - struct wi_ltv_str s; \ - int l; \ - \ - l = (strlen(str) + 1) & ~0x1; \ - bzero((char *)&s, sizeof(s)); \ - s.wi_len = (l / 2) + 2; \ - s.wi_type = recno; \ - s.wi_str[0] = htole16(strlen(str)); \ - bcopy(str, (char *)&s.wi_str[1], strlen(str)); \ - wi_write_record(sc, (struct wi_ltv_gen *)&s); \ - } while (0) - -/* - * Download buffer location and length (0xFD01). - */ -struct wi_ltv_dnld_buf { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_buf_pg; /* page addr of intermediate dl buf*/ - u_int16_t wi_buf_off; /* offset of idb */ - u_int16_t wi_buf_len; /* len of idb */ -}; - -/* - * Mem sizes (0xFD02). - */ -struct wi_ltv_memsz { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_mem_ram; - u_int16_t wi_mem_nvram; -}; - -/* - * NIC Identification (0xFD0B, 0xFD20) - */ -struct wi_ltv_ver { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_ver[4]; -}; - -/* define card ident */ -#define WI_NIC_LUCENT_ID 0x0001 -#define WI_NIC_LUCENT_STR "Lucent Technologies, WaveLAN/IEEE" - -#define WI_NIC_SONY_ID 0x0002 -#define WI_NIC_SONY_STR "Sony WaveLAN/IEEE" - -#define WI_NIC_LUCENT_EMB_ID 0x0005 -#define WI_NIC_LUCENT_EMB_STR "Lucent Embedded WaveLAN/IEEE" - -#define WI_NIC_EVB2_ID 0x8000 -#define WI_NIC_EVB2_STR "RF:PRISM2 MAC:HFA3841" - -#define WI_NIC_HWB3763_ID 0x8001 -#define WI_NIC_HWB3763_STR "RF:PRISM2 MAC:HFA3841 CARD:HWB3763 rev.B" - -#define WI_NIC_HWB3163_ID 0x8002 -#define WI_NIC_HWB3163_STR "RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A" - -#define WI_NIC_HWB3163B_ID 0x8003 -#define WI_NIC_HWB3163B_STR "RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.B" - -#define WI_NIC_EVB3_ID 0x8004 -#define WI_NIC_EVB3_STR "RF:PRISM2 MAC:HFA3842 CARD:HFA3842 EVAL" - -#define WI_NIC_HWB1153_ID 0x8007 -#define WI_NIC_HWB1153_STR "RF:PRISM1 MAC:HFA3841 CARD:HWB1153" - -#define WI_NIC_P2_SST_ID 0x8008 /* Prism2 with SST flush */ -#define WI_NIC_P2_SST_STR "RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash" - -#define WI_NIC_EVB2_SST_ID 0x8009 -#define WI_NIC_EVB2_SST_STR "RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash" - -#define WI_NIC_3842_EVA_ID 0x800A /* 3842 Evaluation Board */ -#define WI_NIC_3842_EVA_STR "RF:PRISM2 MAC:HFA3842 CARD:HFA3842 EVAL" - -#define WI_NIC_3842_PCMCIA_AMD_ID 0x800B /* Prism2.5 PCMCIA */ -#define WI_NIC_3842_PCMCIA_SST_ID 0x800C -#define WI_NIC_3842_PCMCIA_ATM_ID 0x800D -#define WI_NIC_3842_PCMCIA_STR "RF:PRISM2.5 MAC:ISL3873" - -#define WI_NIC_3842_MINI_AMD_ID 0x8012 /* Prism2.5 Mini-PCI */ -#define WI_NIC_3842_MINI_SST_ID 0x8013 -#define WI_NIC_3842_MINI_ATM_ID 0x8014 -#define WI_NIC_3842_MINI_STR "RF:PRISM2.5 MAC:ISL3874A(Mini-PCI)" - -#define WI_NIC_3842_PCI_AMD_ID 0x8016 /* Prism2.5 PCI-bridge */ -#define WI_NIC_3842_PCI_SST_ID 0x8017 -#define WI_NIC_3842_PCI_ATM_ID 0x8018 -#define WI_NIC_3842_PCI_STR "RF:PRISM2.5 MAC:ISL3874A(PCI-bridge)" - -#define WI_NIC_P3_PCMCIA_AMD_ID 0x801A /* Prism3 PCMCIA */ -#define WI_NIC_P3_PCMCIA_SST_ID 0x801B -#define WI_NIC_P3_PCMCIA_STR "RF:PRISM3(PCMCIA)" - -#define WI_NIC_P3_MINI_AMD_ID 0x8021 /* Prism3 Mini-PCI */ -#define WI_NIC_P3_MINI_SST_ID 0x8022 -#define WI_NIC_P3_MINI_STR "RF:PRISM3(Mini-PCI)" - -/* - * List of intended regulatory domains (0xFD11). - */ -struct wi_ltv_domains { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_domains[6]; -}; - -/* - * CIS struct (0xFD13). - */ -struct wi_ltv_cis { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_cis[240]; -}; - -/* - * Communications quality (0xFD43). - */ -struct wi_ltv_commqual { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_coms_qual; - u_int16_t wi_sig_lvl; - u_int16_t wi_noise_lvl; -}; - -/* - * Actual system scale thresholds (0xFC06, 0xFD46). - */ -struct wi_ltv_scalethresh { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_energy_detect; - u_int16_t wi_carrier_detect; - u_int16_t wi_defer; - u_int16_t wi_cell_search; - u_int16_t wi_out_of_range; - u_int16_t wi_delta_snr; -}; - -/* - * PCF info struct (0xFD87). - */ -struct wi_ltv_pcf { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_energy_detect; - u_int16_t wi_carrier_detect; - u_int16_t wi_defer; - u_int16_t wi_cell_search; - u_int16_t wi_range; -}; - -/* - * Connection control characteristics. (0xFC00) - * 0 == IBSS (802.11 compliant mode) (Only PRISM2) - * 1 == Basic Service Set (BSS) - * 2 == Wireless Distribudion System (WDS) - * 3 == Pseudo IBSS - * (Only PRISM2; not 802.11 compliant mode, testing use only) - * 6 == HOST AP (Only PRISM2) - */ -#define WI_PORTTYPE_BSS 0x1 -#define WI_PORTTYPE_WDS 0x2 -#define WI_PORTTYPE_ADHOC 0x3 -#define WI_PORTTYPE_IBSS 0x4 -#define WI_PORTTYPE_AP 0x6 - -/* - * Mac addresses. (0xFC01, 0xFC08) - */ -struct wi_ltv_macaddr { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_mac_addr[3]; -}; - -/* - * Station set identification (SSID). (0xFC02, 0xFC04) - */ -struct wi_ltv_ssid { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_id[17]; -}; - -/* - * Set our station name. (0xFC0E) - */ -struct wi_ltv_nodename { - u_int16_t wi_len; - u_int16_t wi_type; - u_int16_t wi_nodename[17]; -}; - -/* - * Multicast addresses to be put in filter. We're - * allowed up to 16 addresses in the filter. (0xFC80) - */ -struct wi_ltv_mcast { - u_int16_t wi_len; - u_int16_t wi_type; - struct ether_addr wi_mcast[16]; -}; - -/* - * supported rates. (0xFCB4) - */ -#define WI_SUPPRATES_1M 0x0001 -#define WI_SUPPRATES_2M 0x0002 -#define WI_SUPPRATES_5M 0x0004 -#define WI_SUPPRATES_11M 0x0008 -#define WI_RATES_BITS "\20\0011M\0022M\0035.5M\00411M" - -/* - * Information frame types. - */ -#define WI_INFO_NOTIFY 0xF000 /* Handover address */ -#define WI_INFO_COUNTERS 0xF100 /* Statistics counters */ -#define WI_INFO_SCAN_RESULTS 0xF101 /* Scan results */ -#define WI_INFO_LINK_STAT 0xF200 /* Link status */ -#define WI_INFO_ASSOC_STAT 0xF201 /* Association status */ - -/* - * Hermes transmit/receive frame structure - */ -struct wi_frame { - u_int16_t wi_status; /* 0x00 */ - u_int16_t wi_rsvd0; /* 0x02 */ - u_int16_t wi_rsvd1; /* 0x04 */ - u_int16_t wi_q_info; /* 0x06 */ - u_int16_t wi_rsvd2; /* 0x08 */ - u_int8_t wi_tx_rtry; /* 0x0A */ - u_int8_t wi_tx_rate; /* 0x0B */ - u_int16_t wi_tx_ctl; /* 0x0C */ - u_int16_t wi_frame_ctl; /* 0x0E */ - u_int16_t wi_id; /* 0x10 */ - u_int8_t wi_addr1[6]; /* 0x12 */ - u_int8_t wi_addr2[6]; /* 0x18 */ - u_int8_t wi_addr3[6]; /* 0x1E */ - u_int16_t wi_seq_ctl; /* 0x24 */ - u_int8_t wi_addr4[6]; /* 0x26 */ - u_int16_t wi_dat_len; /* 0x2C */ - u_int8_t wi_dst_addr[6]; /* 0x2E */ - u_int8_t wi_src_addr[6]; /* 0x34 */ - u_int16_t wi_len; /* 0x3A */ - u_int16_t wi_dat[3]; /* 0x3C */ /* SNAP header */ - u_int16_t wi_type; /* 0x42 */ -}; - -#define WI_802_3_OFFSET 0x2E -#define WI_802_11_OFFSET 0x44 -#define WI_802_11_OFFSET_RAW 0x3C -#define WI_802_11_OFFSET_HDR 0x0E - -#define WI_STAT_BADCRC 0x0001 -#define WI_STAT_UNDECRYPTABLE 0x0002 -#define WI_STAT_ERRSTAT 0x0003 -#define WI_STAT_MAC_PORT 0x0700 -#define WI_STAT_1042 0x2000 /* RFC1042 encoded */ -#define WI_STAT_TUNNEL 0x4000 /* Bridge-tunnel encoded */ -#define WI_STAT_WMP_MSG 0x6000 /* WaveLAN-II management protocol */ -#define WI_STAT_MGMT 0x8000 /* 802.11b management frames */ -#define WI_RXSTAT_MSG_TYPE 0xE000 - -#define WI_ENC_TX_802_3 0x00 -#define WI_ENC_TX_802_11 0x11 -#define WI_ENC_TX_MGMT 0x08 -#define WI_ENC_TX_E_II 0x0E - -#define WI_ENC_TX_1042 0x00 -#define WI_ENC_TX_TUNNEL 0xF8 - -#define WI_TXCNTL_MACPORT 0x00FF -#define WI_TXCNTL_STRUCTTYPE 0xFF00 -#define WI_TXCNTL_TX_EX 0x0004 -#define WI_TXCNTL_TX_OK 0x0002 -#define WI_TXCNTL_NOCRYPT 0x0080 - -/* - * SNAP (sub-network access protocol) constants for transmission - * of IP datagrams over IEEE 802 networks, taken from RFC1042. - * We need these for the LLC/SNAP header fields in the TX/RX frame - * structure. - */ -#define WI_SNAP_K1 0xaa /* assigned global SAP for SNAP */ -#define WI_SNAP_K2 0x00 -#define WI_SNAP_CONTROL 0x03 /* unnumbered information format */ -#define WI_SNAP_WORD0 (WI_SNAP_K1 | (WI_SNAP_K1 << 8)) -#define WI_SNAP_WORD1 (WI_SNAP_K2 | (WI_SNAP_CONTROL << 8)) -#define WI_SNAPHDR_LEN 0x6 -#define WI_FCS_LEN 0x4 diff --git a/sys/dev/netif/owi/if_wivar.h b/sys/dev/netif/owi/if_wivar.h deleted file mode 100644 index 50aca2c017..0000000000 --- a/sys/dev/netif/owi/if_wivar.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2002 - * M Warner Losh . All rights reserved. - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . 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 Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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. - * - * $FreeBSD: src/sys/dev/wi/if_wivar.h,v 1.8.2.3 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/if_wivar.h,v 1.4 2005/06/13 19:05:19 joerg Exp $ - */ - -#define WICACHE /* turn on signal strength cache code */ -#define MAXWICACHE 10 - -/* - * Encryption controls. We can enable or disable encryption as - * well as specify up to 4 encryption keys. We can also specify - * which of the four keys will be used for transmit encryption. - */ -#define WI_RID_ENCRYPTION 0xFC20 -#define WI_RID_AUTHTYPE 0xFC21 -#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0 -#define WI_RID_TX_CRYPT_KEY 0xFCB1 -#define WI_RID_WEP_AVAIL 0xFD4F -#define WI_RID_P2_TX_CRYPT_KEY 0xFC23 -#define WI_RID_P2_CRYPT_KEY0 0xFC24 -#define WI_RID_P2_CRYPT_KEY1 0xFC25 -#define WI_RID_MICROWAVE_OVEN 0xFC25 -#define WI_RID_P2_CRYPT_KEY2 0xFC26 -#define WI_RID_P2_CRYPT_KEY3 0xFC27 -#define WI_RID_P2_ENCRYPTION 0xFC28 -#define WI_RID_ROAMING_MODE 0xFC2D -#define WI_RID_CUR_TX_RATE 0xFD44 /* current TX rate */ - -struct wi_softc { - struct arpcom arpcom; - struct ifmedia ifmedia; - device_t dev; - int wi_unit; - struct resource * local; - int local_rid; - struct resource * iobase; - int iobase_rid; - struct resource * irq; - int irq_rid; - struct resource * mem; - int mem_rid; - bus_space_handle_t wi_localhandle; - bus_space_tag_t wi_localtag; - bus_space_handle_t wi_bhandle; - bus_space_tag_t wi_btag; - bus_space_handle_t wi_bmemhandle; - bus_space_tag_t wi_bmemtag; - void * wi_intrhand; - int sc_firmware_type; -#define WI_NOTYPE 0 -#define WI_LUCENT 1 -#define WI_INTERSIL 2 -#define WI_SYMBOL 3 - int sc_pri_firmware_ver; /* Primary firmware */ - int sc_sta_firmware_ver; /* Station firmware */ - int sc_enabled; - int wi_io_addr; - int wi_tx_data_id; - int wi_tx_mgmt_id; - int wi_gone; - int wi_flags; -#define WI_FLAGS_ATTACHED 0x01 -#define WI_FLAGS_INITIALIZED 0x02 -#define WI_FLAGS_HAS_WEP 0x04 -#define WI_FLAGS_HAS_IBSS 0x08 -#define WI_FLAGS_HAS_CREATE_IBSS 0x10 -#define WI_FLAGS_HAS_MOR 0x20 -#define WI_FLAGS_HAS_ROAMING 0x30 -#define WI_FLAGS_HAS_DIVERSITY 0x40 -#define WI_FLAGS_HAS_HOSTAP 0x80 - int wi_if_flags; - u_int16_t wi_procframe; - u_int16_t wi_ptype; - u_int16_t wi_portnum; - u_int16_t wi_max_data_len; - u_int16_t wi_rts_thresh; - u_int16_t wi_ap_density; - u_int16_t wi_tx_rate; - u_int16_t wi_create_ibss; - u_int16_t wi_channel; - u_int16_t wi_pm_enabled; - u_int16_t wi_mor_enabled; - u_int16_t wi_max_sleep; - u_int16_t wi_supprates; - u_int16_t wi_authtype; - u_int16_t wi_roaming; - char wi_node_name[32]; - char wi_net_name[32]; - char wi_ibss_name[32]; - u_int8_t wi_txbuf[1596]; - u_int8_t wi_scanbuf[1596]; - int wi_scanbuf_len; - struct wi_counters wi_stats; - int wi_has_wep; - int wi_use_wep; - int wi_authmode; - int wi_tx_key; - struct wi_ltv_keys wi_keys; -#ifdef WICACHE - int wi_sigitems; - struct wi_sigcache wi_sigcache[MAXWICACHE]; - int wi_nextitem; -#endif - struct wihap_info wi_hostap_info; - u_int32_t wi_icv; - int wi_icv_flag; - int wi_ibss_port; - struct callout wi_stat_timer; -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - struct mtx wi_mtx; -#endif - int wi_nic_type; - int wi_bus_type; /* Bus attachment type */ - struct { - u_int16_t wi_sleep; - u_int16_t wi_delaysupp; - u_int16_t wi_txsupp; - u_int16_t wi_monitor; - u_int16_t wi_ledtest; - u_int16_t wi_ledtest_param0; - u_int16_t wi_ledtest_param1; - u_int16_t wi_conttx; - u_int16_t wi_conttx_param0; - u_int16_t wi_contrx; - u_int16_t wi_sigstate; - u_int16_t wi_sigstate_param0; - u_int16_t wi_confbits; - u_int16_t wi_confbits_param0; - } wi_debug; - -}; - -struct wi_card_ident { - u_int16_t card_id; - char *card_name; - u_int8_t firm_type; -}; - -int owi_generic_attach(device_t); -int owi_generic_detach(device_t); -void owi_shutdown(device_t); -int owi_alloc(device_t, int); -void owi_free(device_t); -extern devclass_t owi_devclass; -int owi_mgmt_xmit(struct wi_softc *, caddr_t, int); diff --git a/sys/dev/netif/owi/owi_hostap.c b/sys/dev/netif/owi/owi_hostap.c deleted file mode 100644 index c2582d5cd3..0000000000 --- a/sys/dev/netif/owi/owi_hostap.c +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * Copyright (c) 2002 - * Thomas Skibo . 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 Thomas Skibo. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Thomas Skibo 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 Thomas Skibo OR HIS DRINKING PALS - * 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. - * - * $FreeBSD: src/sys/dev/wi/wi_hostap.c,v 1.7.2.4 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/owi_hostap.c,v 1.5 2005/06/18 19:05:02 corecode Exp $ - */ - -/* This is experimental Host AP software for Prism 2 802.11b interfaces. - * - * Much of this is based upon the "Linux Host AP driver Host AP driver - * for Intersil Prism2" by Jouni Malinen or . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "wi_hostap.h" -#include "if_wivar.h" -#include "if_wireg.h" - -static MALLOC_DEFINE(M_HAP_STA, "hostap_sta", "if_wi host AP mode station entry"); - -static void wihap_sta_timeout(void *v); -static struct wihap_sta_info *wihap_sta_alloc(struct wi_softc *sc, - u_int8_t *addr); -static void wihap_sta_delete(struct wihap_sta_info *sta); -static struct wihap_sta_info *wihap_sta_find(struct wihap_info *whi, - u_int8_t *addr); -static int wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]); -static void wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len); -static void wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[], - u_int16_t reason); -static void wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len); -static void wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len); -static void wihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[], - u_int16_t reason); -static void wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len); - -/* - * Spl use in this driver. - * - * splnet is used everywhere here to block timeouts when we need to do - * so. - */ - -/* - * take_hword() - * - * Used for parsing management frames. The pkt pointer and length - * variables are updated after the value is removed. - */ -static __inline u_int16_t -take_hword(caddr_t *ppkt, int *plen) -{ - u_int16_t s = le16toh(* (u_int16_t *) *ppkt); - *ppkt += sizeof(u_int16_t); - *plen -= sizeof(u_int16_t); - return s; -} - -/* take_tlv() - * - * Parse out TLV element from a packet, check for underflow of packet - * or overflow of buffer, update pkt/len. - */ -static int -take_tlv(caddr_t *ppkt, int *plen, int id_expect, void *dst, int maxlen) -{ - u_int8_t id, len; - - if (*plen < 2) - return -1; - - id = ((u_int8_t *)*ppkt)[0]; - len = ((u_int8_t *)*ppkt)[1]; - - if (id != id_expect || *plen < len+2 || maxlen < len) - return -1; - - bcopy(*ppkt + 2, dst, len); - *plen -= 2 + len; - *ppkt += 2 + len; - - return (len); -} - -/* put_hword() - * Put half-word element into management frames. - */ -static __inline void -put_hword(caddr_t *ppkt, u_int16_t s) -{ - * (u_int16_t *) *ppkt = htole16(s); - *ppkt += sizeof(u_int16_t); -} - -/* put_tlv() - * Put TLV elements into management frames. - */ -static void -put_tlv(caddr_t *ppkt, u_int8_t id, void *src, u_int8_t len) -{ - (*ppkt)[0] = id; - (*ppkt)[1] = len; - bcopy(src, (*ppkt) + 2, len); - *ppkt += 2 + len; -} - -static int -put_rates(caddr_t *ppkt, u_int16_t rates) -{ - u_int8_t ratebuf[8]; - int len = 0; - - if (rates & WI_SUPPRATES_1M) - ratebuf[len++] = 0x82; - if (rates & WI_SUPPRATES_2M) - ratebuf[len++] = 0x84; - if (rates & WI_SUPPRATES_5M) - ratebuf[len++] = 0x8b; - if (rates & WI_SUPPRATES_11M) - ratebuf[len++] = 0x96; - - put_tlv(ppkt, IEEE80211_ELEMID_RATES, ratebuf, len); - return len; -} - -/* wihap_init() - * - * Initialize host AP data structures. Called even if port type is - * not AP. - */ -void -owihap_init(struct wi_softc *sc) -{ - int i; - struct wihap_info *whi = &sc->wi_hostap_info; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_init: sc=0x%x whi=0x%x\n", (int)sc, (int)whi); - - bzero(whi, sizeof(struct wihap_info)); - - if (sc->wi_ptype != WI_PORTTYPE_AP) - return; - - whi->apflags = WIHAPFL_ACTIVE; - - LIST_INIT(&whi->sta_list); - for (i = 0; i < WI_STA_HASH_SIZE; i++) - LIST_INIT(&whi->sta_hash[i]); - - whi->inactivity_time = WIHAP_DFLT_INACTIVITY_TIME; -} - -/* wihap_sta_disassoc() - * - * Send a disassociation frame to a specified station. - */ -static void -wihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[], u_int16_t reason) -{ - struct wi_80211_hdr *resp_hdr; - caddr_t pkt; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("Sending disassoc to sta %6D\n", sta_addr, ":"); - - /* Send disassoc packet. */ - resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; - bzero(resp_hdr, sizeof(struct wi_80211_hdr)); - resp_hdr->frame_ctl = WI_FTYPE_MGMT | WI_STYPE_MGMT_DISAS; - pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr); - - bcopy(sta_addr, resp_hdr->addr1, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN); - - put_hword(&pkt, reason); - - owi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr)); -} - -/* wihap_sta_deauth() - * - * Send a deauthentication message to a specified station. - */ -static void -wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[], u_int16_t reason) -{ - struct wi_80211_hdr *resp_hdr; - caddr_t pkt; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("Sending deauth to sta %6D\n", sta_addr, ":"); - - /* Send deauth packet. */ - resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; - bzero(resp_hdr, sizeof(struct wi_80211_hdr)); - resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_DEAUTH); - pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr); - - bcopy(sta_addr, resp_hdr->addr1, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN); - - put_hword(&pkt, reason); - - owi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr)); -} - -/* wihap_shutdown() - * - * Disassociate all stations and free up data structures. - */ -void -owihap_shutdown(struct wi_softc *sc) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta, *next; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_shutdown: sc=0x%x whi=0x%x\n", - (int)sc, (int)whi); - - if (!(whi->apflags & WIHAPFL_ACTIVE)) - return; - - /* XXX: I read somewhere you can deauth all the stations with - * a single broadcast. Maybe try that someday. - */ - - crit_enter(); - - sta = LIST_FIRST(&whi->sta_list); - while (sta) { - callout_stop(&sta->tmo); - if (!sc->wi_gone) { - /* Disassociate station. */ - if (sta->flags & WI_SIFLAGS_ASSOC) - wihap_sta_disassoc(sc, sta->addr, - IEEE80211_REASON_ASSOC_LEAVE); - /* Deauth station. */ - if (sta->flags & WI_SIFLAGS_AUTHEN) - wihap_sta_deauth(sc, sta->addr, - IEEE80211_REASON_AUTH_LEAVE); - } - - /* Delete the structure. */ - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_shutdown: FREE(sta=0x%x)\n", (int)sta); - next = LIST_NEXT(sta, list); - FREE(sta, M_HAP_STA); - sta = next; - } - - whi->apflags = 0; - - crit_exit(); -} - -/* sta_hash_func() - * Hash function for finding stations from ethernet address. - */ -static __inline int -sta_hash_func(u_int8_t addr[]) -{ - return ((addr[3] + addr[4] + addr[5]) % WI_STA_HASH_SIZE); -} - -/* addr_cmp(): Maybe this is a faster way to compare addresses? */ -static __inline int -addr_cmp(u_int8_t a[], u_int8_t b[]) -{ - return (*(u_int16_t *)(a + 4) == *(u_int16_t *)(b + 4) && - *(u_int32_t *)(a ) == *(u_int32_t *)(b)); -} - -static void -wihap_sta_timeout(void *v) -{ - struct wihap_sta_info *sta = v; - struct wi_softc *sc = sta->sc; - struct wihap_info *whi = &sc->wi_hostap_info; - - crit_enter(); - - if (sta->flags & WI_SIFLAGS_ASSOC) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - device_printf(sc->dev, "inactivity disassoc: %6D\n", - sta->addr, ":"); - - /* Disassoc station. */ - wihap_sta_disassoc(sc, sta->addr, - IEEE80211_REASON_ASSOC_EXPIRE); - sta->flags &= ~WI_SIFLAGS_ASSOC; - - callout_reset(&sta->tmo, hz * whi->inactivity_time, - wihap_sta_timeout, sta); - - } else if (sta->flags & WI_SIFLAGS_AUTHEN) { - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - device_printf(sc->dev, "inactivity disassoc: %6D\n", - sta->addr, ":"); - - /* Deauthenticate station. */ - wihap_sta_deauth(sc, sta->addr, IEEE80211_REASON_AUTH_EXPIRE); - sta->flags &= ~WI_SIFLAGS_AUTHEN; - - /* Delete the station if it's not permanent. */ - if (!(sta->flags & WI_SIFLAGS_PERM)) - wihap_sta_delete(sta); - } - - crit_exit(); -} - -/* wihap_sta_delete() - * Delete a single station and free up its data structure. - */ -static void -wihap_sta_delete(struct wihap_sta_info *sta) -{ - struct wi_softc *sc = sta->sc; - struct wihap_info *whi = &sc->wi_hostap_info; - int i = sta->asid - 0xc001; - - callout_stop(&sta->tmo); - - whi->asid_inuse_mask[i >> 4] &= ~(1UL << (i & 0xf)); - - LIST_REMOVE(sta, list); - LIST_REMOVE(sta, hash); - if (sta->challenge) - FREE(sta->challenge, M_TEMP); - FREE(sta, M_HAP_STA); - whi->n_stations--; -} - -/* wihap_sta_alloc() - * - * Create a new station data structure and put it in the list - * and hash table. - */ -static struct wihap_sta_info * -wihap_sta_alloc(struct wi_softc *sc, u_int8_t *addr) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - int i, hash = sta_hash_func(addr); - - /* Allocate structure. */ - MALLOC(sta, struct wihap_sta_info *, sizeof(struct wihap_sta_info), - M_HAP_STA, M_INTWAIT); - if (sta == NULL) - return(NULL); - - bzero(sta, sizeof(struct wihap_sta_info)); - callout_init(&sta->tmo); - - /* Allocate an ASID. */ - i=hash<<4; - while (whi->asid_inuse_mask[i >> 4] & (1UL << (i & 0xf))) - i = (i == (WI_STA_HASH_SIZE << 4) - 1) ? 0 : (i + 1); - whi->asid_inuse_mask[i >> 4] |= (1UL << (i & 0xf)); - sta->asid = 0xc001 + i; - - /* Insert in list and hash list. */ - LIST_INSERT_HEAD(&whi->sta_list, sta, list); - LIST_INSERT_HEAD(&whi->sta_hash[hash], sta, hash); - - sta->sc = sc; - whi->n_stations++; - bcopy(addr, &sta->addr, ETHER_ADDR_LEN); - - return(sta); -} - -/* wihap_sta_find() - * - * Find station structure given address. - */ -static struct wihap_sta_info * -wihap_sta_find(struct wihap_info *whi, u_int8_t *addr) -{ - int i; - struct wihap_sta_info *sta; - - i = sta_hash_func(addr); - LIST_FOREACH(sta, &whi->sta_hash[i], hash) - if (addr_cmp(addr,sta->addr)) - return sta; - - return (NULL); -} - -static int -wihap_check_rates(struct wihap_sta_info *sta, u_int8_t rates[], int rates_len) -{ - struct wi_softc *sc = sta->sc; - int i; - - sta->rates = 0; - sta->tx_max_rate = 0; - for (i=0; irates |= WI_SUPPRATES_1M; - break; - case 0x04: - sta->rates |= WI_SUPPRATES_2M; - if (sta->tx_max_rate<1) - sta->tx_max_rate = 1; - break; - case 0x0b: - sta->rates |= WI_SUPPRATES_5M; - if (sta->tx_max_rate<2) - sta->tx_max_rate = 2; - break; - case 0x16: - sta->rates |= WI_SUPPRATES_11M; - sta->tx_max_rate = 3; - break; - } - - sta->rates &= sc->wi_supprates; - sta->tx_curr_rate = sta->tx_max_rate; - - return (sta->rates == 0 ? -1 : 0); -} - - -/* wihap_auth_req() - * - * Handle incoming authentication request. Only handle OPEN - * requests. - */ -static void -wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - - u_int16_t algo; - u_int16_t seq; - u_int16_t status; - int i, challenge_len; - u_int32_t challenge[32]; - - struct wi_80211_hdr *resp_hdr; - - if (len < 6) - return; - - /* Break open packet. */ - algo = take_hword(&pkt, &len); - seq = take_hword(&pkt, &len); - status = take_hword(&pkt, &len); - challenge_len = 0; - if (len > 0 && (challenge_len = take_tlv(&pkt, &len, - IEEE80211_ELEMID_CHALLENGE, challenge, sizeof(challenge))) < 0) - return; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_auth_req: station %6D algo=0x%x seq=0x%x\n", - rxfrm->wi_addr2, ":", algo, seq); - - /* Find or create station info. */ - sta = wihap_sta_find(whi, rxfrm->wi_addr2); - if (sta == NULL) { - - /* Are we allowing new stations? - */ - if (whi->apflags & WIHAPFL_MAC_FILT) { - status = IEEE80211_STATUS_OTHER; /* XXX */ - goto fail; - } - - /* Check for too many stations. - */ - if (whi->n_stations >= WIHAP_MAX_STATIONS) { - status = IEEE80211_STATUS_TOO_MANY_STATIONS; - goto fail; - } - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_auth_req: new station\n"); - - /* Create new station. */ - sta = wihap_sta_alloc(sc, rxfrm->wi_addr2); - if (sta == NULL) { - /* Out of memory! */ - status = IEEE80211_STATUS_TOO_MANY_STATIONS; - goto fail; - } - } - - /* Note: it's okay to leave the station info structure around - * if the authen fails. It'll be timed out eventually. - */ - switch (algo) { - case IEEE80211_AUTH_ALG_OPEN: - if (sc->wi_authmode != IEEE80211_AUTH_OPEN) { - seq = 2; - status = IEEE80211_STATUS_ALG; - goto fail; - } - if (seq != 1) { - seq = 2; - status = IEEE80211_STATUS_SEQUENCE; - goto fail; - } - challenge_len = 0; - seq = 2; - sta->flags |= WI_SIFLAGS_AUTHEN; - break; - case IEEE80211_AUTH_ALG_SHARED: - if (sc->wi_authmode != IEEE80211_AUTH_SHARED) { - seq = 2; - status = IEEE80211_STATUS_ALG; - goto fail; - } - switch (seq) { - case 1: - /* Create a challenge frame. */ - if (!sta->challenge) { - MALLOC(sta->challenge, u_int32_t *, 128, - M_TEMP, M_INTWAIT); - if (!sta->challenge) - return; - } - for (i = 0; i < 32; i++) - challenge[i] = sta->challenge[i] = - arc4random(); - challenge_len = 128; - seq = 2; - break; - case 3: - if (challenge_len != 128 || !sta->challenge || - !(le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_WEP)) { - status = IEEE80211_STATUS_CHALLENGE; - goto fail; - } - challenge_len = 0; - seq = 4; - - /* Check the challenge text. (Was decrypted by - * the adapter.) - */ - for (i=0; i<32; i++) - if (sta->challenge[i] != challenge[i]) { - status = IEEE80211_STATUS_CHALLENGE; - FREE(sta->challenge, M_TEMP); - sta->challenge = NULL; - goto fail; - } - - sta->flags |= WI_SIFLAGS_AUTHEN; - FREE(sta->challenge, M_TEMP); - sta->challenge = NULL; - break; - default: - seq = 2; - status = IEEE80211_STATUS_SEQUENCE; - goto fail; - } /* switch (seq) */ - break; - default: - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_auth_req: algorithm unsupported: 0x%x\n", - algo); - status = IEEE80211_STATUS_ALG; - goto fail; - } /* switch (algo) */ - - status = IEEE80211_STATUS_SUCCESS; - -fail: - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_auth_req: returns status=0x%x\n", status); - - /* Send response. */ - resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; - bzero(resp_hdr, sizeof(struct wi_80211_hdr)); - resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_AUTH); - bcopy(rxfrm->wi_addr2, resp_hdr->addr1, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN); - pkt = &sc->wi_txbuf[sizeof(struct wi_80211_hdr)]; - put_hword(&pkt, algo); - put_hword(&pkt, seq); - put_hword(&pkt, status); - if (challenge_len > 0) - put_tlv(&pkt, IEEE80211_ELEMID_CHALLENGE, - challenge, challenge_len); - owi_mgmt_xmit(sc, sc->wi_txbuf, (char *) pkt - (char *) sc->wi_txbuf); -} - -/* wihap_assoc_req() - * - * Handle incoming association and reassociation requests. - */ -static void -wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - struct wi_80211_hdr *resp_hdr; - u_int16_t capinfo; - u_int16_t lstintvl; - u_int8_t rates[8]; - int ssid_len, rates_len; - char ssid[33]; - u_int16_t status; - u_int16_t asid = 0; - - if (len < 8) - return; - - /* Pull out request parameters. */ - capinfo = take_hword(&pkt, &len); - lstintvl = take_hword(&pkt, &len); - - if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_STYPE)) == - htole16(WI_STYPE_MGMT_REASREQ)) { - if (len < 6) - return; - /* Eat the MAC address of the current AP */ - take_hword(&pkt, &len); - take_hword(&pkt, &len); - take_hword(&pkt, &len); - } - - if ((ssid_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_SSID, - ssid, sizeof(ssid) - 1))<0) - return; - ssid[ssid_len] = '\0'; - if ((rates_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_RATES, - rates, sizeof(rates)))<0) - return; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: from station %6D\n", - rxfrm->wi_addr2, ":"); - - /* If SSID doesn't match, simply drop. */ - if (strcmp(sc->wi_net_name, ssid) != 0) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: bad ssid: '%s' != '%s'\n", - ssid, sc->wi_net_name); - return; - } - - /* Is this station authenticated yet? */ - sta = wihap_sta_find(whi, rxfrm->wi_addr2); - if (sta == NULL || !(sta->flags & WI_SIFLAGS_AUTHEN)) { - wihap_sta_deauth(sc, rxfrm->wi_addr2, - IEEE80211_REASON_NOT_AUTHED); - return; - } - - /* Check supported rates against ours. */ - if (wihap_check_rates(sta, rates, rates_len) < 0) { - status = IEEE80211_STATUS_RATES; - goto fail; - } - - /* Check capinfo. - * Check for ESS, not IBSS. - * Check WEP/PRIVACY flags match. - * Refuse stations requesting to be put on CF-polling list. - */ - sta->capinfo = capinfo; - status = IEEE80211_STATUS_CAPINFO; - if ((capinfo & (IEEE80211_CAPINFO_ESS | IEEE80211_CAPINFO_IBSS)) != - IEEE80211_CAPINFO_ESS) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: capinfo mismatch: " - "client using IBSS mode\n"); - goto fail; - - } - if ((sc->wi_use_wep && !(capinfo & IEEE80211_CAPINFO_PRIVACY)) || - (!sc->wi_use_wep && (capinfo & IEEE80211_CAPINFO_PRIVACY))) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: capinfo mismatch: client " - "%susing WEP\n", sc->wi_use_wep ? "not " : ""); - goto fail; - } - if ((capinfo & (IEEE80211_CAPINFO_CF_POLLABLE | - IEEE80211_CAPINFO_CF_POLLREQ)) == IEEE80211_CAPINFO_CF_POLLABLE) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: capinfo mismatch: " - "client requested CF polling\n"); - goto fail; - } - - /* Use ASID is allocated by whi_sta_alloc(). */ - asid = sta->asid; - - if (sta->flags & WI_SIFLAGS_ASSOC) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: already assoc'ed?\n"); - } - - sta->flags |= WI_SIFLAGS_ASSOC; - sta->inactivity_timer = whi->inactivity_time; - status = IEEE80211_STATUS_SUCCESS; - -fail: - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_assoc_req: returns status=0x%x\n", status); - - /* Send response. */ - resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; - bzero(resp_hdr, sizeof(struct wi_80211_hdr)); - resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_ASRESP); - pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr); - - bcopy(rxfrm->wi_addr2, resp_hdr->addr1, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN); - bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN); - - put_hword(&pkt, capinfo); - put_hword(&pkt, status); - put_hword(&pkt, asid); - rates_len = put_rates(&pkt, sc->wi_supprates); - - owi_mgmt_xmit(sc, sc->wi_txbuf, - 8 + rates_len + sizeof(struct wi_80211_hdr)); -} - -/* wihap_deauth_req() - * - * Handle deauthentication requests. Delete the station. - */ -static void -wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - u_int16_t reason; - - if (len<2) - return; - - reason = take_hword(&pkt, &len); - - sta = wihap_sta_find(whi, rxfrm->wi_addr2); - if (sta == NULL) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_deauth_req: unknown station: %6D\n", - rxfrm->wi_addr2, ":"); - } - else - wihap_sta_delete(sta); -} - -/* wihap_disassoc_req() - * - * Handle disassociation requests. Just reset the assoc flag. - * We'll free up the station resources when we get a deauth - * request or when it times out. - */ -static void -wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, - caddr_t pkt, int len) -{ - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - u_int16_t reason; - - if (len < 2) - return; - - reason = take_hword(&pkt, &len); - - sta = wihap_sta_find(whi, rxfrm->wi_addr2); - if (sta == NULL) { - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - printf("wihap_disassoc_req: unknown station: %6D\n", - rxfrm->wi_addr2, ":"); - } - else if (!(sta->flags & WI_SIFLAGS_AUTHEN)) { - /* - * If station is not authenticated, send deauthentication - * frame. - */ - wihap_sta_deauth(sc, rxfrm->wi_addr2, - IEEE80211_REASON_NOT_AUTHED); - return; - } - else - sta->flags &= ~WI_SIFLAGS_ASSOC; -} - -/* wihap_debug_frame_type() - * - * Print out frame type. Used in early debugging. - */ -static __inline void -wihap_debug_frame_type(struct wi_frame *rxfrm) -{ - printf("wihap_mgmt_input: len=%d ", le16toh(rxfrm->wi_dat_len)); - - if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) == - htole16(WI_FTYPE_MGMT)) { - - printf("MGMT: "); - - switch (le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) { - case WI_STYPE_MGMT_ASREQ: - printf("assoc req: \n"); - break; - case WI_STYPE_MGMT_ASRESP: - printf("assoc resp: \n"); - break; - case WI_STYPE_MGMT_REASREQ: - printf("reassoc req: \n"); - break; - case WI_STYPE_MGMT_REASRESP: - printf("reassoc resp: \n"); - break; - case WI_STYPE_MGMT_PROBEREQ: - printf("probe req: \n"); - break; - case WI_STYPE_MGMT_PROBERESP: - printf("probe resp: \n"); - break; - case WI_STYPE_MGMT_BEACON: - printf("beacon: \n"); - break; - case WI_STYPE_MGMT_ATIM: - printf("ann traf ind \n"); - break; - case WI_STYPE_MGMT_DISAS: - printf("disassociation: \n"); - break; - case WI_STYPE_MGMT_AUTH: - printf("auth: \n"); - break; - case WI_STYPE_MGMT_DEAUTH: - printf("deauth: \n"); - break; - default: - printf("unknown (stype=0x%x)\n", - le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE); - } - - } - else { - printf("ftype=0x%x (ctl=0x%x)\n", - le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_FTYPE, - le16toh(rxfrm->wi_frame_ctl)); - } -} - -/* wihap_mgmt_input: - * - * Called for each management frame received in host ap mode. - * wihap_mgmt_input() is expected to free the mbuf. - */ -void -owihap_mgmt_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m) -{ - caddr_t pkt; - int len; - - if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) - wihap_debug_frame_type(rxfrm); - - pkt = mtod(m, caddr_t) + WI_802_11_OFFSET_RAW; - len = m->m_len - WI_802_11_OFFSET_RAW; - - if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) == - htole16(WI_FTYPE_MGMT)) { - - /* any of the following will mess w/ the station list */ - crit_enter(); - - switch (le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) { - case WI_STYPE_MGMT_ASREQ: - wihap_assoc_req(sc, rxfrm, pkt, len); - break; - case WI_STYPE_MGMT_ASRESP: - break; - case WI_STYPE_MGMT_REASREQ: - wihap_assoc_req(sc, rxfrm, pkt, len); - break; - case WI_STYPE_MGMT_REASRESP: - break; - case WI_STYPE_MGMT_PROBEREQ: - break; - case WI_STYPE_MGMT_PROBERESP: - break; - case WI_STYPE_MGMT_BEACON: - break; - case WI_STYPE_MGMT_ATIM: - break; - case WI_STYPE_MGMT_DISAS: - wihap_disassoc_req(sc, rxfrm, pkt, len); - break; - case WI_STYPE_MGMT_AUTH: - wihap_auth_req(sc, rxfrm, pkt, len); - break; - case WI_STYPE_MGMT_DEAUTH: - wihap_deauth_req(sc, rxfrm, pkt, len); - break; - } - - crit_exit(); - } - - m_freem(m); -} - -/* wihap_sta_is_assoc() - * - * Determine if a station is assoc'ed. Update its activity - * counter as a side-effect. - */ -static int -wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]) -{ - struct wihap_sta_info *sta; - int retval = 0; - - crit_enter(); - - sta = wihap_sta_find(whi, addr); - if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) { - /* Keep it active. */ - callout_reset(&sta->tmo, hz * whi->inactivity_time, - wihap_sta_timeout, sta); - retval = 1; - } - - crit_exit(); - - return (retval); -} - -/* wihap_check_tx() - * - * Determine if a station is assoc'ed, get its tx rate, and update - * its activity. - */ -int -owihap_check_tx(struct wihap_info *whi, u_int8_t addr[], u_int8_t *txrate) -{ - struct wihap_sta_info *sta; - static u_int8_t txratetable[] = { 10, 20, 55, 110 }; - - if (addr[0] & 0x01) { - *txrate = 0; /* XXX: multicast rate? */ - return(1); - } - - crit_enter(); - - sta = wihap_sta_find(whi, addr); - if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) { - /* Keep it active. */ - callout_reset(&sta->tmo, hz * whi->inactivity_time, - wihap_sta_timeout, sta); - *txrate = txratetable[ sta->tx_curr_rate ]; - crit_exit(); - return(1); - } - - crit_exit(); - - return(0); -} - -/* - * wihap_data_input() - * - * Handle all data input on interface when in Host AP mode. - * Some packets are destined for this machine, others are - * repeated to other stations. - * - * If wihap_data_input() returns a non-zero, it has processed - * the packet and will free the mbuf. - */ -int -owihap_data_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - int mcast; - - /* TODS flag must be set. */ - if (!(rxfrm->wi_frame_ctl & htole16(WI_FCTL_TODS))) { - if (ifp->if_flags & IFF_DEBUG) - printf("wihap_data_input: no TODS src=%6D\n", - rxfrm->wi_addr2, ":"); - m_freem(m); - return(1); - } - - /* Check BSSID. (Is this necessary?) */ - if (!addr_cmp(rxfrm->wi_addr1, sc->arpcom.ac_enaddr)) { - if (ifp->if_flags & IFF_DEBUG) - printf("wihap_data_input: incorrect bss: %6D\n", - rxfrm->wi_addr1, ":"); - m_freem(m); - return (1); - } - - crit_enter(); - - /* Find source station. */ - sta = wihap_sta_find(whi, rxfrm->wi_addr2); - - /* Source station must be associated. */ - if (sta == NULL || !(sta->flags & WI_SIFLAGS_ASSOC)) { - if (ifp->if_flags & IFF_DEBUG) - printf("wihap_data_input: dropping unassoc src %6D\n", - rxfrm->wi_addr2, ":"); - wihap_sta_disassoc(sc, rxfrm->wi_addr2, - IEEE80211_REASON_ASSOC_LEAVE); - crit_exit(); - m_freem(m); - return(1); - } - - callout_reset(&sta->tmo, hz * whi->inactivity_time, - wihap_sta_timeout, sta); - sta->sig_info = le16toh(rxfrm->wi_q_info); - - crit_exit(); - - /* Repeat this packet to BSS? */ - mcast = (rxfrm->wi_addr3[0] & 0x01) != 0; - if (mcast || wihap_sta_is_assoc(whi, rxfrm->wi_addr3)) { - - /* If it's multicast, make a copy. - */ - if (mcast) { - m = m_copym(m, 0, M_COPYALL, MB_DONTWAIT); - if (m == NULL) - return(0); - m->m_flags |= M_MCAST; /* XXX */ - } - - /* Queue up for repeating. - */ - ifq_handoff(ifp, m, NULL); - return (!mcast); - } - - return(0); -} - -/* wihap_ioctl() - * - * Handle Host AP specific ioctls. Called from wi_ioctl(). - */ -int -owihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data) -{ - struct ifreq *ifr = (struct ifreq *) data; - struct wihap_info *whi = &sc->wi_hostap_info; - struct wihap_sta_info *sta; - struct hostap_getall reqall; - struct hostap_sta reqsta; - struct hostap_sta stabuf; - int error = 0, n, flag; - struct thread *td = curthread; - - if (!(sc->arpcom.ac_if.if_flags & IFF_RUNNING)) - return ENODEV; - - switch (command) { - case SIOCHOSTAP_DEL: - if ((error = suser(td))) - break; - if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) - break; - - crit_enter(); - - sta = wihap_sta_find(whi, reqsta.addr); - if (sta == NULL) - error = ENOENT; - else { - /* Disassociate station. */ - if (sta->flags & WI_SIFLAGS_ASSOC) - wihap_sta_disassoc(sc, sta->addr, - IEEE80211_REASON_ASSOC_LEAVE); - /* Deauth station. */ - if (sta->flags & WI_SIFLAGS_AUTHEN) - wihap_sta_deauth(sc, sta->addr, - IEEE80211_REASON_AUTH_LEAVE); - - wihap_sta_delete(sta); - } - - crit_exit(); - - break; - - case SIOCHOSTAP_GET: - if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) - break; - - crit_enter(); - - sta = wihap_sta_find(whi, reqsta.addr); - if (sta == NULL) { - error = ENOENT; - - crit_exit(); - } else { - reqsta.flags = sta->flags; - reqsta.asid = sta->asid; - reqsta.capinfo = sta->capinfo; - reqsta.sig_info = sta->sig_info; - reqsta.rates = sta->rates; - - crit_exit(); - - error = copyout(&reqsta, ifr->ifr_data, - sizeof(reqsta)); - } - break; - - case SIOCHOSTAP_ADD: - if ((error = suser(td))) - break; - if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) - break; - - crit_enter(); - - sta = wihap_sta_find(whi, reqsta.addr); - if (sta != NULL) { - error = EEXIST; - crit_exit(); - break; - } - if (whi->n_stations >= WIHAP_MAX_STATIONS) { - error = ENOSPC; - crit_exit(); - break; - } - sta = wihap_sta_alloc(sc, reqsta.addr); - sta->flags = reqsta.flags; - callout_reset(&sta->tmo, hz * whi->inactivity_time, - wihap_sta_timeout, sta); - crit_exit(); - break; - - case SIOCHOSTAP_SFLAGS: - if ((error = suser(td))) - break; - if ((error = copyin(ifr->ifr_data, &flag, sizeof(int)))) - break; - - crit_enter(); - whi->apflags = (whi->apflags & WIHAPFL_CANTCHANGE) | - (flag & ~WIHAPFL_CANTCHANGE); - crit_exit(); - break; - - case SIOCHOSTAP_GFLAGS: - flag = (int) whi->apflags; - error = copyout(&flag, ifr->ifr_data, sizeof(int)); - break; - - case SIOCHOSTAP_GETALL: - if ((error = copyin(ifr->ifr_data, &reqall, sizeof(reqall)))) - break; - - reqall.nstations = whi->n_stations; - n = 0; - crit_enter(); - sta = LIST_FIRST(&whi->sta_list); - while (sta && reqall.size >= n+sizeof(struct hostap_sta)) { - - bcopy(sta->addr, stabuf.addr, ETHER_ADDR_LEN); - stabuf.asid = sta->asid; - stabuf.flags = sta->flags; - stabuf.capinfo = sta->capinfo; - stabuf.sig_info = sta->sig_info; - stabuf.rates = sta->rates; - - error = copyout(&stabuf, (caddr_t) reqall.addr + n, - sizeof(struct hostap_sta)); - if (error) - break; - - sta = LIST_NEXT(sta, list); - n += sizeof(struct hostap_sta); - } - crit_exit(); - - if (!error) - error = copyout(&reqall, ifr->ifr_data, - sizeof(reqall)); - break; - default: - printf("wihap_ioctl: i shouldn't get other ioctls!\n"); - error = EINVAL; - } - - return(error); -} diff --git a/sys/dev/netif/owi/wi_hostap.h b/sys/dev/netif/owi/wi_hostap.h deleted file mode 100644 index 94ac35ea7c..0000000000 --- a/sys/dev/netif/owi/wi_hostap.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2002 - * Thomas Skibo . 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 Thomas Skibo. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Thomas Skibo 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 Thomas Skibo OR HIS DRINKING PALS - * 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. - * - * $FreeBSD: src/sys/dev/wi/wi_hostap.h,v 1.3.2.3 2002/08/02 07:11:34 imp Exp $ - * $DragonFly: src/sys/dev/netif/owi/Attic/wi_hostap.h,v 1.2 2004/09/15 00:21:09 joerg Exp $ - */ - -#ifndef __WI_HOSTAP_H__ -#define __WI_HOSTAP_H__ - -#define WIHAP_MAX_STATIONS 1800 - -struct hostap_sta { - u_int8_t addr[6]; - u_int16_t asid; - u_int16_t flags; - u_int16_t sig_info; /* 15:8 signal, 7:0 noise */ - u_int16_t capinfo; - u_int8_t rates; -}; - -#define HOSTAP_FLAGS_AUTHEN 0x0001 -#define HOSTAP_FLAGS_ASSOC 0x0002 -#define HOSTAP_FLAGS_PERM 0x0004 -#define HOSTAP_FLAGS_BITS "\20\01ASSOC\02AUTH\03PERM" - -#define SIOCHOSTAP_GET _IOWR('i', 210, struct ifreq) -#define SIOCHOSTAP_ADD _IOWR('i', 211, struct ifreq) -#define SIOCHOSTAP_DEL _IOWR('i', 212, struct ifreq) -#define SIOCHOSTAP_GETALL _IOWR('i', 213, struct ifreq) -#define SIOCHOSTAP_GFLAGS _IOWR('i', 214, struct ifreq) -#define SIOCHOSTAP_SFLAGS _IOWR('i', 215, struct ifreq) - -/* Flags for SIOCHOSTAP_GFLAGS/SFLAGS */ -#define WIHAPFL_ACTIVE 0x0001 -#define WIHAPFL_MAC_FILT 0x0002 - -/* Flags set inernally only: */ -#define WIHAPFL_CANTCHANGE (WIHAPFL_ACTIVE) - -struct hostap_getall { - int nstations; - struct hostap_sta *addr; - int size; -}; - - - -#ifdef _KERNEL -struct wihap_sta_info { - LIST_ENTRY(wihap_sta_info) list; - LIST_ENTRY(wihap_sta_info) hash; - - struct wi_softc *sc; - u_int8_t addr[6]; - u_short flags; - int inactivity_timer; - - u_int16_t asid; - u_int16_t capinfo; - u_int16_t sig_info; /* 15:8 signal, 7:0 noise */ - u_int8_t rates; - u_int8_t tx_curr_rate; - u_int8_t tx_max_rate; - u_int32_t *challenge; - struct callout tmo; -}; - -#define WI_SIFLAGS_ASSOC HOSTAP_FLAGS_ASSOC -#define WI_SIFLAGS_AUTHEN HOSTAP_FLAGS_AUTHEN -#define WI_SIFLAGS_PERM HOSTAP_FLAGS_PERM - -#define WI_STA_HASH_SIZE 113 - -#if WI_STA_HASH_SIZE*16 >= 2007 /* will generate ASID's too large. */ -#error "WI_STA_HASH_SIZE too big" -#endif -#if WI_STA_HASH_SIZE*16 < WIHAP_MAX_STATIONS -#error "WI_STA_HASH_SIZE too small" -#endif - -struct wihap_info { - LIST_HEAD(sta_list, wihap_sta_info) sta_list; - LIST_HEAD(sta_hash, wihap_sta_info) sta_hash[WI_STA_HASH_SIZE]; - - u_int16_t apflags; - - int n_stations; - u_int16_t asid_inuse_mask[WI_STA_HASH_SIZE]; - - int inactivity_time; -}; - -#define WIHAP_INTERVAL 5 -#define WIHAP_DFLT_INACTIVITY_TIME 120 /* 2 minutes */ - -struct wi_softc; -struct wi_frame; - -void owihap_timer(void *); -void owihap_mgmt_input(struct wi_softc *, struct wi_frame *, struct mbuf *); -int owihap_data_input(struct wi_softc *, struct wi_frame *, struct mbuf *); -int owihap_check_tx(struct wihap_info *, u_int8_t [], u_int8_t *); -void owihap_init(struct wi_softc *); -void owihap_shutdown(struct wi_softc *); -int owihap_ioctl(struct wi_softc *, u_long, caddr_t); - -#endif /* _KERNEL */ -#endif /* __WI_HOSTAP_H__ */ -- 2.41.0