Home | History | Annotate | Line # | Download | only in ic
wi.c revision 1.80
      1  1.80   thorpej /*	$NetBSD: wi.c,v 1.80 2002/08/11 21:54:19 thorpej Exp $	*/
      2   1.1    ichiro 
      3   1.1    ichiro /*
      4   1.1    ichiro  * Copyright (c) 1997, 1998, 1999
      5   1.1    ichiro  *	Bill Paul <wpaul (at) ctr.columbia.edu>.  All rights reserved.
      6   1.1    ichiro  *
      7   1.1    ichiro  * Redistribution and use in source and binary forms, with or without
      8   1.1    ichiro  * modification, are permitted provided that the following conditions
      9   1.1    ichiro  * are met:
     10   1.1    ichiro  * 1. Redistributions of source code must retain the above copyright
     11   1.1    ichiro  *    notice, this list of conditions and the following disclaimer.
     12   1.1    ichiro  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1    ichiro  *    notice, this list of conditions and the following disclaimer in the
     14   1.1    ichiro  *    documentation and/or other materials provided with the distribution.
     15   1.1    ichiro  * 3. All advertising materials mentioning features or use of this software
     16   1.1    ichiro  *    must display the following acknowledgement:
     17   1.1    ichiro  *	This product includes software developed by Bill Paul.
     18   1.1    ichiro  * 4. Neither the name of the author nor the names of any co-contributors
     19   1.1    ichiro  *    may be used to endorse or promote products derived from this software
     20   1.1    ichiro  *    without specific prior written permission.
     21   1.1    ichiro  *
     22   1.1    ichiro  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     23   1.1    ichiro  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1    ichiro  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1    ichiro  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
     26   1.1    ichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27   1.1    ichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28   1.1    ichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29   1.1    ichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30   1.1    ichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31   1.1    ichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     32   1.1    ichiro  * THE POSSIBILITY OF SUCH DAMAGE.
     33   1.1    ichiro  */
     34   1.1    ichiro 
     35   1.1    ichiro /*
     36   1.1    ichiro  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
     37   1.1    ichiro  *
     38   1.1    ichiro  * Original FreeBSD driver written by Bill Paul <wpaul (at) ctr.columbia.edu>
     39   1.1    ichiro  * Electrical Engineering Department
     40   1.1    ichiro  * Columbia University, New York City
     41   1.1    ichiro  */
     42   1.1    ichiro 
     43   1.1    ichiro /*
     44   1.1    ichiro  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
     45   1.1    ichiro  * from Lucent. Unlike the older cards, the new ones are programmed
     46   1.1    ichiro  * entirely via a firmware-driven controller called the Hermes.
     47   1.1    ichiro  * Unfortunately, Lucent will not release the Hermes programming manual
     48   1.1    ichiro  * without an NDA (if at all). What they do release is an API library
     49   1.1    ichiro  * called the HCF (Hardware Control Functions) which is supposed to
     50   1.1    ichiro  * do the device-specific operations of a device driver for you. The
     51   1.1    ichiro  * publically available version of the HCF library (the 'HCF Light') is
     52   1.1    ichiro  * a) extremely gross, b) lacks certain features, particularly support
     53   1.1    ichiro  * for 802.11 frames, and c) is contaminated by the GNU Public License.
     54   1.1    ichiro  *
     55   1.1    ichiro  * This driver does not use the HCF or HCF Light at all. Instead, it
     56   1.1    ichiro  * programs the Hermes controller directly, using information gleaned
     57   1.1    ichiro  * from the HCF Light code and corresponding documentation.
     58   1.1    ichiro  *
     59   1.1    ichiro  * This driver supports both the PCMCIA and ISA versions of the
     60   1.1    ichiro  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
     61   1.1    ichiro  * anything of the sort: it's actually a PCMCIA bridge adapter
     62   1.1    ichiro  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
     63   1.1    ichiro  * inserted. Consequently, you need to use the pccard support for
     64   1.1    ichiro  * both the ISA and PCMCIA adapters.
     65   1.1    ichiro  */
     66   1.1    ichiro 
     67   1.1    ichiro /*
     68   1.1    ichiro  * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
     69   1.1    ichiro  * Oslo IETF plenary meeting.
     70   1.1    ichiro  */
     71  1.29     lukem 
     72  1.29     lukem #include <sys/cdefs.h>
     73  1.80   thorpej __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.80 2002/08/11 21:54:19 thorpej Exp $");
     74   1.1    ichiro 
     75   1.1    ichiro #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
     76   1.1    ichiro #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
     77   1.1    ichiro 
     78   1.1    ichiro #include "bpfilter.h"
     79   1.1    ichiro 
     80   1.1    ichiro #include <sys/param.h>
     81   1.1    ichiro #include <sys/systm.h>
     82   1.1    ichiro #include <sys/callout.h>
     83   1.1    ichiro #include <sys/device.h>
     84   1.1    ichiro #include <sys/socket.h>
     85   1.1    ichiro #include <sys/mbuf.h>
     86   1.1    ichiro #include <sys/ioctl.h>
     87   1.1    ichiro #include <sys/kernel.h>		/* for hz */
     88   1.1    ichiro #include <sys/proc.h>
     89   1.1    ichiro 
     90   1.1    ichiro #include <net/if.h>
     91   1.1    ichiro #include <net/if_dl.h>
     92   1.1    ichiro #include <net/if_media.h>
     93   1.1    ichiro #include <net/if_ether.h>
     94   1.1    ichiro #include <net/if_ieee80211.h>
     95   1.1    ichiro 
     96   1.1    ichiro #if NBPFILTER > 0
     97   1.1    ichiro #include <net/bpf.h>
     98   1.1    ichiro #include <net/bpfdesc.h>
     99   1.1    ichiro #endif
    100   1.1    ichiro 
    101  1.18   nathanw #include <machine/bus.h>
    102   1.1    ichiro 
    103   1.1    ichiro #include <dev/ic/wi_ieee.h>
    104   1.1    ichiro #include <dev/ic/wireg.h>
    105   1.1    ichiro #include <dev/ic/wivar.h>
    106   1.1    ichiro 
    107   1.1    ichiro static void wi_reset		__P((struct wi_softc *));
    108   1.1    ichiro static int wi_ioctl		__P((struct ifnet *, u_long, caddr_t));
    109   1.1    ichiro static void wi_start		__P((struct ifnet *));
    110   1.1    ichiro static void wi_watchdog		__P((struct ifnet *));
    111   1.1    ichiro static int wi_init		__P((struct ifnet *));
    112   1.1    ichiro static void wi_stop		__P((struct ifnet *, int));
    113   1.1    ichiro static void wi_rxeof		__P((struct wi_softc *));
    114   1.1    ichiro static void wi_txeof		__P((struct wi_softc *, int));
    115   1.1    ichiro static void wi_update_stats	__P((struct wi_softc *));
    116   1.1    ichiro static void wi_setmulti		__P((struct wi_softc *));
    117   1.1    ichiro 
    118   1.1    ichiro static int wi_cmd		__P((struct wi_softc *, int, int));
    119   1.1    ichiro static int wi_read_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    120   1.1    ichiro static int wi_write_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    121   1.1    ichiro static int wi_read_data		__P((struct wi_softc *, int,
    122   1.1    ichiro 					int, caddr_t, int));
    123   1.1    ichiro static int wi_write_data	__P((struct wi_softc *, int,
    124   1.1    ichiro 					int, caddr_t, int));
    125   1.1    ichiro static int wi_seek		__P((struct wi_softc *, int, int, int));
    126   1.1    ichiro static int wi_alloc_nicmem	__P((struct wi_softc *, int, int *));
    127  1.30  explorer static void wi_inquire		__P((void *));
    128  1.35    ichiro static void wi_wait_scan	__P((void *));
    129   1.1    ichiro static int wi_setdef		__P((struct wi_softc *, struct wi_req *));
    130   1.1    ichiro static int wi_getdef		__P((struct wi_softc *, struct wi_req *));
    131   1.1    ichiro 
    132   1.1    ichiro static int wi_media_change __P((struct ifnet *));
    133   1.1    ichiro static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
    134   1.1    ichiro 
    135   1.4    ichiro static void wi_get_id		__P((struct wi_softc *));
    136   1.4    ichiro 
    137   1.1    ichiro static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int));
    138   1.1    ichiro static void wi_request_fill_ssid __P((struct wi_req *,
    139   1.1    ichiro     struct ieee80211_nwid *));
    140   1.1    ichiro static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
    141   1.1    ichiro     struct ieee80211_nwid *));
    142   1.1    ichiro static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    143   1.1    ichiro static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    144   1.1    ichiro static int wi_sync_media __P((struct wi_softc *, int, int));
    145   1.1    ichiro static int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
    146   1.1    ichiro static int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
    147   1.1    ichiro 
    148  1.64    ichiro struct wi_card_ident wi_card_ident[] = {
    149  1.74   thorpej 	/* CARD_ID			CARD_NAME		FIRM_TYPE */
    150  1.67    ichiro 	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },
    151  1.67    ichiro 	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },
    152  1.67    ichiro 	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },
    153  1.67    ichiro 	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },
    154  1.67    ichiro 	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },
    155  1.67    ichiro 	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },
    156  1.67    ichiro 	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },
    157  1.67    ichiro 	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },
    158  1.67    ichiro 	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },
    159  1.67    ichiro 	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },
    160  1.67    ichiro 	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },
    161  1.67    ichiro 	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },
    162  1.64    ichiro 	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    163  1.64    ichiro 	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    164  1.64    ichiro 	{ WI_NIC_3842_PCMCIA_ATM_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    165  1.64    ichiro 	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    166  1.64    ichiro 	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    167  1.64    ichiro 	{ WI_NIC_3842_MINI_ATM_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    168  1.64    ichiro 	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    169  1.64    ichiro 	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    170  1.64    ichiro 	{ WI_NIC_3842_PCI_ATM_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    171  1.64    ichiro 	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    172  1.64    ichiro 	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    173  1.64    ichiro 	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    174  1.64    ichiro 	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    175  1.64    ichiro 	{ 0,	NULL,	0 },
    176  1.64    ichiro };
    177  1.64    ichiro 
    178   1.1    ichiro int
    179   1.1    ichiro wi_attach(sc)
    180   1.1    ichiro 	struct wi_softc *sc;
    181   1.1    ichiro {
    182   1.1    ichiro 	struct ifnet *ifp = sc->sc_ifp;
    183  1.75   thorpej 	const char *sep = "";
    184   1.1    ichiro 	struct wi_ltv_macaddr   mac;
    185   1.1    ichiro 	struct wi_ltv_gen       gen;
    186   1.1    ichiro 	static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
    187   1.1    ichiro 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    188   1.1    ichiro 	};
    189   1.1    ichiro 	int s;
    190   1.1    ichiro 
    191   1.1    ichiro 	s = splnet();
    192   1.1    ichiro 
    193  1.30  explorer 	callout_init(&sc->wi_inquire_ch);
    194  1.35    ichiro 	callout_init(&sc->wi_scan_sh);
    195   1.1    ichiro 
    196   1.1    ichiro 	/* Make sure interrupts are disabled. */
    197   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    198   1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    199   1.1    ichiro 
    200   1.1    ichiro 	/* Reset the NIC. */
    201   1.1    ichiro 	wi_reset(sc);
    202   1.1    ichiro 
    203   1.1    ichiro 	memset(&mac, 0, sizeof(mac));
    204   1.1    ichiro 	/* Read the station address. */
    205   1.1    ichiro 	mac.wi_type = WI_RID_MAC_NODE;
    206   1.1    ichiro 	mac.wi_len = 4;
    207   1.1    ichiro 	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
    208   1.1    ichiro 	memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
    209   1.1    ichiro 
    210   1.1    ichiro 	/*
    211   1.1    ichiro 	 * Check if we got anything meaningful.
    212   1.1    ichiro 	 *
    213   1.1    ichiro 	 * Is it really enough just checking against null ethernet address?
    214   1.1    ichiro 	 * Or, check against possible vendor?  XXX.
    215   1.1    ichiro 	 */
    216  1.19   thorpej 	if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) {
    217  1.65  jdolecek 		printf("could not get mac address, attach failed\n");
    218  1.42      yamt 		splx(s);
    219  1.42      yamt 		return 1;
    220   1.1    ichiro 	}
    221   1.1    ichiro 
    222   1.1    ichiro 	printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr));
    223   1.1    ichiro 
    224   1.4    ichiro 	/* Read NIC identification */
    225   1.4    ichiro 	wi_get_id(sc);
    226   1.4    ichiro 
    227   1.1    ichiro 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
    228   1.1    ichiro 	ifp->if_softc = sc;
    229   1.1    ichiro 	ifp->if_start = wi_start;
    230   1.1    ichiro 	ifp->if_ioctl = wi_ioctl;
    231   1.1    ichiro 	ifp->if_watchdog = wi_watchdog;
    232   1.1    ichiro 	ifp->if_init = wi_init;
    233   1.1    ichiro 	ifp->if_stop = wi_stop;
    234   1.1    ichiro 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    235   1.1    ichiro #ifdef IFF_NOTRAILERS
    236   1.1    ichiro 	ifp->if_flags |= IFF_NOTRAILERS;
    237   1.1    ichiro #endif
    238   1.1    ichiro 	IFQ_SET_READY(&ifp->if_snd);
    239   1.1    ichiro 
    240   1.1    ichiro 	(void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
    241   1.1    ichiro 	    sizeof(WI_DEFAULT_NODENAME) - 1);
    242   1.1    ichiro 	(void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
    243   1.1    ichiro 	    sizeof(WI_DEFAULT_NETNAME) - 1);
    244   1.1    ichiro 	(void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
    245   1.1    ichiro 	    sizeof(WI_DEFAULT_IBSS) - 1);
    246   1.1    ichiro 
    247   1.1    ichiro 	sc->wi_portnum = WI_DEFAULT_PORT;
    248   1.1    ichiro 	sc->wi_ptype = WI_PORTTYPE_BSS;
    249   1.1    ichiro 	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
    250   1.1    ichiro 	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
    251   1.1    ichiro 	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
    252   1.1    ichiro 	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
    253   1.1    ichiro 	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
    254   1.1    ichiro 	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
    255   1.1    ichiro 	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
    256   1.4    ichiro 	sc->wi_roaming = WI_DEFAULT_ROAMING;
    257   1.4    ichiro 	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
    258   1.1    ichiro 
    259   1.1    ichiro 	/*
    260   1.1    ichiro 	 * Read the default channel from the NIC. This may vary
    261   1.1    ichiro 	 * depending on the country where the NIC was purchased, so
    262   1.1    ichiro 	 * we can't hard-code a default and expect it to work for
    263   1.1    ichiro 	 * everyone.
    264   1.1    ichiro 	 */
    265   1.1    ichiro 	gen.wi_type = WI_RID_OWN_CHNL;
    266   1.1    ichiro 	gen.wi_len = 2;
    267   1.1    ichiro 	wi_read_record(sc, &gen);
    268  1.11    tsubai 	sc->wi_channel = le16toh(gen.wi_val);
    269   1.1    ichiro 
    270  1.21   thorpej 	memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
    271   1.1    ichiro 
    272  1.35    ichiro 	/* AP info was filled with 0 */
    273  1.35    ichiro 	memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps));
    274  1.77   thorpej 	sc->wi_scanning = 0;
    275  1.77   thorpej 	sc->wi_naps = 0;
    276  1.77   thorpej 
    277  1.77   thorpej 	/*
    278  1.77   thorpej 	 * Set flags based on firmware version.
    279  1.77   thorpej 	 */
    280  1.77   thorpej 	switch (sc->sc_firmware_type) {
    281  1.77   thorpej 	case WI_LUCENT:
    282  1.77   thorpej 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
    283  1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 60000)
    284  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_MOR;
    285  1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 60006) {
    286  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    287  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    288  1.77   thorpej 		}
    289  1.77   thorpej 		sc->wi_ibss_port = htole16(1);
    290  1.77   thorpej 		break;
    291  1.77   thorpej 
    292  1.77   thorpej 	case WI_INTERSIL:
    293  1.77   thorpej 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
    294  1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 800) {
    295  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
    296  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    297  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    298  1.77   thorpej 		}
    299  1.77   thorpej 		sc->wi_ibss_port = htole16(0);
    300  1.77   thorpej 		break;
    301  1.77   thorpej 
    302  1.77   thorpej 	case WI_SYMBOL:
    303  1.77   thorpej 		sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
    304  1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 20000)
    305  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    306  1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 25000)
    307  1.77   thorpej 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    308  1.77   thorpej 		sc->wi_ibss_port = htole16(4);
    309  1.77   thorpej 		break;
    310  1.77   thorpej 	}
    311  1.35    ichiro 
    312   1.1    ichiro 	/*
    313   1.1    ichiro 	 * Find out if we support WEP on this card.
    314   1.1    ichiro 	 */
    315   1.1    ichiro 	gen.wi_type = WI_RID_WEP_AVAIL;
    316   1.1    ichiro 	gen.wi_len = 2;
    317  1.77   thorpej 	if (wi_read_record(sc, &gen) == 0 &&
    318  1.77   thorpej 	    gen.wi_val != le16toh(0))
    319  1.77   thorpej 		sc->wi_flags |= WI_FLAGS_HAS_WEP;
    320   1.1    ichiro 
    321  1.78   thorpej 	/* Find supported rates. */
    322  1.78   thorpej 	gen.wi_type = WI_RID_DATA_RATES;
    323  1.75   thorpej 	gen.wi_len = 2;
    324  1.78   thorpej 	if (wi_read_record(sc, &gen))
    325  1.75   thorpej 		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
    326  1.75   thorpej 		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
    327  1.75   thorpej 	else
    328  1.75   thorpej 		sc->wi_supprates = le16toh(gen.wi_val);
    329  1.75   thorpej 
    330   1.1    ichiro 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
    331  1.75   thorpej 	if (sc->wi_supprates != 0)
    332  1.75   thorpej 		printf("%s: supported rates: ", sc->sc_dev.dv_xname);
    333   1.1    ichiro #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
    334  1.75   thorpej #define	PRINT(n)	printf("%s%s", sep, (n)); sep = ", "
    335   1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
    336  1.56      onoe 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
    337  1.77   thorpej 	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    338  1.77   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
    339  1.77   thorpej 		    0), 0);
    340  1.77   thorpej 	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    341  1.77   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
    342  1.77   thorpej 		    IFM_IEEE80211_IBSSMASTER, 0), 0);
    343  1.79   thorpej 	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    344  1.79   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
    345  1.79   thorpej 		    IFM_IEEE80211_HOSTAP, 0), 0);
    346  1.75   thorpej 	if (sc->wi_supprates & WI_SUPPRATES_1M) {
    347  1.75   thorpej 		PRINT("1Mbps");
    348  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
    349  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    350  1.75   thorpej 		    IFM_IEEE80211_ADHOC, 0), 0);
    351  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    352  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    353  1.77   thorpej 			    IFM_IEEE80211_IBSS, 0), 0);
    354  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    355  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    356  1.77   thorpej 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    357  1.79   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    358  1.79   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    359  1.79   thorpej 			    IFM_IEEE80211_HOSTAP, 0), 0);
    360  1.75   thorpej 	}
    361  1.75   thorpej 	if (sc->wi_supprates & WI_SUPPRATES_2M) {
    362  1.75   thorpej 		PRINT("2Mbps");
    363  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
    364  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    365  1.75   thorpej 		    IFM_IEEE80211_ADHOC, 0), 0);
    366  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    367  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    368  1.77   thorpej 			    IFM_IEEE80211_IBSS, 0), 0);
    369  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    370  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    371  1.77   thorpej 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    372  1.79   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    373  1.79   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    374  1.79   thorpej 			    IFM_IEEE80211_HOSTAP, 0), 0);
    375  1.75   thorpej 	}
    376  1.75   thorpej 	if (sc->wi_supprates & WI_SUPPRATES_5M) {
    377  1.75   thorpej 		PRINT("5.5Mbps");
    378  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
    379  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    380  1.75   thorpej 		    IFM_IEEE80211_ADHOC, 0), 0);
    381  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    382  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    383  1.77   thorpej 			    IFM_IEEE80211_IBSS, 0), 0);
    384  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    385  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    386  1.77   thorpej 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    387  1.79   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    388  1.79   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    389  1.79   thorpej 			    IFM_IEEE80211_HOSTAP, 0), 0);
    390  1.75   thorpej 	}
    391  1.75   thorpej 	if (sc->wi_supprates & WI_SUPPRATES_11M) {
    392  1.75   thorpej 		PRINT("11Mbps");
    393  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
    394  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    395  1.75   thorpej 		    IFM_IEEE80211_ADHOC, 0), 0);
    396  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    397  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    398  1.77   thorpej 			    IFM_IEEE80211_IBSS, 0), 0);
    399  1.77   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    400  1.77   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    401  1.77   thorpej 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    402  1.79   thorpej 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    403  1.79   thorpej 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    404  1.79   thorpej 			    IFM_IEEE80211_HOSTAP, 0), 0);
    405  1.75   thorpej 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
    406  1.75   thorpej 	}
    407  1.75   thorpej 	if (sc->wi_supprates != 0)
    408  1.75   thorpej 		printf("\n");
    409  1.75   thorpej 	ifmedia_set(&sc->sc_media,
    410  1.75   thorpej 	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
    411   1.1    ichiro #undef ADD
    412  1.75   thorpej #undef PRINT
    413   1.1    ichiro 
    414   1.1    ichiro 	/*
    415   1.1    ichiro 	 * Call MI attach routines.
    416   1.1    ichiro 	 */
    417   1.1    ichiro 	if_attach(ifp);
    418   1.1    ichiro 	ether_ifattach(ifp, mac.wi_mac_addr);
    419   1.1    ichiro 
    420   1.1    ichiro 	ifp->if_baudrate = IF_Mbps(2);
    421   1.1    ichiro 
    422   1.1    ichiro 	/* Attach is successful. */
    423   1.1    ichiro 	sc->sc_attached = 1;
    424   1.1    ichiro 
    425   1.1    ichiro 	splx(s);
    426   1.1    ichiro 	return 0;
    427   1.1    ichiro }
    428   1.1    ichiro 
    429   1.1    ichiro static void wi_rxeof(sc)
    430   1.1    ichiro 	struct wi_softc		*sc;
    431   1.1    ichiro {
    432   1.1    ichiro 	struct ifnet		*ifp;
    433   1.1    ichiro 	struct ether_header	*eh;
    434   1.1    ichiro 	struct wi_frame		rx_frame;
    435   1.1    ichiro 	struct mbuf		*m;
    436   1.1    ichiro 	int			id;
    437   1.1    ichiro 
    438   1.1    ichiro 	ifp = sc->sc_ifp;
    439   1.1    ichiro 
    440   1.1    ichiro 	id = CSR_READ_2(sc, WI_RX_FID);
    441   1.1    ichiro 
    442   1.1    ichiro 	/* First read in the frame header */
    443   1.1    ichiro 	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
    444   1.1    ichiro 		ifp->if_ierrors++;
    445   1.1    ichiro 		return;
    446   1.1    ichiro 	}
    447   1.1    ichiro 
    448  1.25  explorer 	/*
    449  1.25  explorer 	 * Drop undecryptable or packets with receive errors here
    450  1.25  explorer 	 */
    451  1.30  explorer 	if (le16toh(rx_frame.wi_status) & WI_STAT_ERRSTAT) {
    452   1.1    ichiro 		ifp->if_ierrors++;
    453   1.1    ichiro 		return;
    454   1.1    ichiro 	}
    455   1.1    ichiro 
    456   1.1    ichiro 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    457   1.1    ichiro 	if (m == NULL) {
    458   1.1    ichiro 		ifp->if_ierrors++;
    459   1.1    ichiro 		return;
    460   1.1    ichiro 	}
    461   1.1    ichiro 	MCLGET(m, M_DONTWAIT);
    462   1.1    ichiro 	if (!(m->m_flags & M_EXT)) {
    463   1.1    ichiro 		m_freem(m);
    464   1.1    ichiro 		ifp->if_ierrors++;
    465   1.1    ichiro 		return;
    466   1.1    ichiro 	}
    467   1.1    ichiro 
    468   1.1    ichiro 	/* Align the data after the ethernet header */
    469  1.11    tsubai 	m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
    470   1.1    ichiro 	    - sizeof(struct ether_header);
    471   1.1    ichiro 
    472   1.1    ichiro 	eh = mtod(m, struct ether_header *);
    473   1.1    ichiro 	m->m_pkthdr.rcvif = ifp;
    474   1.1    ichiro 
    475  1.79   thorpej 	if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_MGMT &&
    476  1.79   thorpej 	    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
    477  1.79   thorpej 		if ((le16toh(rx_frame.wi_dat_len) + WI_802_11_OFFSET_RAW + 2) >
    478  1.79   thorpej 		    MCLBYTES) {
    479  1.79   thorpej 			printf("%s: oversized packet received in "
    480  1.79   thorpej 			    "Host-AP mode (wi_dat_len=%d, wi_status=0x%x)\n",
    481  1.79   thorpej 			    sc->sc_dev.dv_xname,
    482  1.79   thorpej 			    le16toh(rx_frame.wi_dat_len),
    483  1.79   thorpej 			    le16toh(rx_frame.wi_status));
    484  1.79   thorpej 			m_freem(m);
    485  1.79   thorpej 			ifp->if_ierrors++;
    486  1.79   thorpej 			return;
    487  1.79   thorpej 		}
    488  1.79   thorpej 
    489  1.79   thorpej 		/* Put the whole header in there. */
    490  1.79   thorpej 		memcpy(mtod(m, void *), &rx_frame, sizeof(rx_frame));
    491  1.79   thorpej 		if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
    492  1.79   thorpej 		    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
    493  1.79   thorpej 		    le16toh(rx_frame.wi_dat_len) + 2)) {
    494  1.79   thorpej 			m_freem(m);
    495  1.79   thorpej 			if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
    496  1.79   thorpej 				printf("%s: Host-AP: failed to copy header\n",
    497  1.79   thorpej 				    sc->sc_dev.dv_xname);
    498  1.79   thorpej 			ifp->if_ierrors++;
    499  1.79   thorpej 			return;
    500  1.79   thorpej 		}
    501  1.79   thorpej 
    502  1.79   thorpej 		m->m_pkthdr.len = m->m_len =
    503  1.79   thorpej 		    WI_802_11_OFFSET_RAW + le16toh(rx_frame.wi_dat_len);
    504  1.79   thorpej 
    505  1.79   thorpej 		/* XXX Consider giving packet to bhp? */
    506  1.79   thorpej 
    507  1.79   thorpej 		wihap_mgmt_input(sc, &rx_frame, m);
    508  1.79   thorpej 		return;
    509  1.79   thorpej 	}
    510  1.79   thorpej 
    511  1.73   mycroft 	if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_1042 ||
    512  1.73   mycroft 	    (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_TUNNEL ||
    513  1.73   mycroft 	    (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_WMP_MSG) {
    514  1.11    tsubai 		if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) {
    515   1.1    ichiro 			printf("%s: oversized packet received "
    516   1.1    ichiro 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    517   1.1    ichiro 			    sc->sc_dev.dv_xname,
    518  1.11    tsubai 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    519   1.1    ichiro 			m_freem(m);
    520   1.1    ichiro 			ifp->if_ierrors++;
    521   1.1    ichiro 			return;
    522   1.1    ichiro 		}
    523   1.1    ichiro 		m->m_pkthdr.len = m->m_len =
    524  1.11    tsubai 		    le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
    525   1.1    ichiro 
    526  1.20   thorpej 		memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr,
    527  1.20   thorpej 		    ETHER_ADDR_LEN);
    528  1.20   thorpej 		memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr,
    529  1.20   thorpej 		    ETHER_ADDR_LEN);
    530  1.20   thorpej 		memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type,
    531  1.20   thorpej 		    sizeof(u_int16_t));
    532   1.1    ichiro 
    533   1.1    ichiro 		if (wi_read_data(sc, id, WI_802_11_OFFSET,
    534   1.1    ichiro 		    mtod(m, caddr_t) + sizeof(struct ether_header),
    535   1.1    ichiro 		    m->m_len + 2)) {
    536   1.1    ichiro 			m_freem(m);
    537   1.1    ichiro 			ifp->if_ierrors++;
    538   1.1    ichiro 			return;
    539   1.1    ichiro 		}
    540   1.1    ichiro 	} else {
    541  1.11    tsubai 		if ((le16toh(rx_frame.wi_dat_len) +
    542   1.1    ichiro 		    sizeof(struct ether_header)) > MCLBYTES) {
    543   1.1    ichiro 			printf("%s: oversized packet received "
    544   1.1    ichiro 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    545   1.1    ichiro 			    sc->sc_dev.dv_xname,
    546  1.11    tsubai 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    547   1.1    ichiro 			m_freem(m);
    548   1.1    ichiro 			ifp->if_ierrors++;
    549   1.1    ichiro 			return;
    550   1.1    ichiro 		}
    551   1.1    ichiro 		m->m_pkthdr.len = m->m_len =
    552  1.11    tsubai 		    le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header);
    553   1.1    ichiro 
    554   1.1    ichiro 		if (wi_read_data(sc, id, WI_802_3_OFFSET,
    555   1.1    ichiro 		    mtod(m, caddr_t), m->m_len + 2)) {
    556   1.1    ichiro 			m_freem(m);
    557   1.1    ichiro 			ifp->if_ierrors++;
    558   1.1    ichiro 			return;
    559   1.1    ichiro 		}
    560   1.1    ichiro 	}
    561   1.1    ichiro 
    562   1.1    ichiro 	ifp->if_ipackets++;
    563   1.1    ichiro 
    564  1.79   thorpej 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
    565  1.79   thorpej 		/*
    566  1.79   thorpej 		 * Give Host-AP first crack at data packets.  If it
    567  1.79   thorpej 		 * decides to handle it (or drop it), it will return
    568  1.79   thorpej 		 * non-zero.  Otherwise, it is destined for this host.
    569  1.79   thorpej 		 */
    570  1.79   thorpej 		if (wihap_data_input(sc, &rx_frame, m))
    571  1.79   thorpej 			return;
    572  1.79   thorpej 	}
    573  1.79   thorpej 
    574   1.1    ichiro #if NBPFILTER > 0
    575   1.1    ichiro 	/* Handle BPF listeners. */
    576   1.1    ichiro 	if (ifp->if_bpf)
    577   1.1    ichiro 		bpf_mtap(ifp->if_bpf, m);
    578   1.1    ichiro #endif
    579   1.1    ichiro 
    580   1.1    ichiro 	/* Receive packet. */
    581   1.1    ichiro 	(*ifp->if_input)(ifp, m);
    582   1.1    ichiro }
    583   1.1    ichiro 
    584   1.1    ichiro static void wi_txeof(sc, status)
    585   1.1    ichiro 	struct wi_softc	*sc;
    586   1.1    ichiro 	int		status;
    587   1.1    ichiro {
    588   1.1    ichiro 	struct ifnet	*ifp = sc->sc_ifp;
    589   1.1    ichiro 
    590   1.1    ichiro 	ifp->if_timer = 0;
    591   1.1    ichiro 	ifp->if_flags &= ~IFF_OACTIVE;
    592   1.1    ichiro 
    593   1.1    ichiro 	if (status & WI_EV_TX_EXC)
    594   1.1    ichiro 		ifp->if_oerrors++;
    595   1.1    ichiro 	else
    596   1.1    ichiro 		ifp->if_opackets++;
    597   1.1    ichiro 
    598   1.1    ichiro 	return;
    599   1.1    ichiro }
    600   1.1    ichiro 
    601  1.30  explorer void wi_inquire(xsc)
    602   1.1    ichiro 	void			*xsc;
    603   1.1    ichiro {
    604   1.1    ichiro 	struct wi_softc		*sc;
    605   1.1    ichiro 	struct ifnet		*ifp;
    606  1.40    martin 	int			s;
    607   1.1    ichiro 
    608   1.1    ichiro 	sc = xsc;
    609   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    610   1.1    ichiro 
    611   1.1    ichiro 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
    612   1.1    ichiro 		return;
    613   1.1    ichiro 
    614  1.49       dbj 	KASSERT(sc->sc_enabled);
    615  1.49       dbj 
    616  1.30  explorer 	callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
    617   1.1    ichiro 
    618   1.1    ichiro 	/* Don't do this while we're transmitting */
    619   1.1    ichiro 	if (ifp->if_flags & IFF_OACTIVE)
    620   1.1    ichiro 		return;
    621   1.1    ichiro 
    622  1.40    martin 	s = splnet();
    623   1.1    ichiro 	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
    624  1.40    martin 	splx(s);
    625  1.25  explorer }
    626  1.25  explorer 
    627  1.35    ichiro void wi_wait_scan(xsc)
    628  1.35    ichiro 	void			*xsc;
    629  1.35    ichiro {
    630  1.35    ichiro 	struct wi_softc         *sc;
    631  1.40    martin 	struct ifnet            *ifp;
    632  1.40    martin 	int			s, result;
    633  1.35    ichiro 
    634  1.35    ichiro 	sc = xsc;
    635  1.35    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    636  1.35    ichiro 
    637  1.35    ichiro 	/* If not scanning, ignore */
    638  1.35    ichiro 	if (!sc->wi_scanning)
    639  1.35    ichiro 		return;
    640  1.35    ichiro 
    641  1.40    martin 	s = splnet();
    642  1.40    martin 
    643  1.40    martin 	/* Wait for sending complete to make INQUIRE */
    644  1.35    ichiro 	if (ifp->if_flags & IFF_OACTIVE) {
    645  1.35    ichiro 		callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
    646  1.40    martin 		splx(s);
    647  1.35    ichiro 		return;
    648  1.35    ichiro 	}
    649  1.35    ichiro 
    650  1.35    ichiro 	/* try INQUIRE */
    651  1.40    martin 	result = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS);
    652  1.40    martin 	if (result == ETIMEDOUT)
    653  1.35    ichiro 		callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
    654  1.40    martin 
    655  1.40    martin 	splx(s);
    656  1.35    ichiro }
    657  1.35    ichiro 
    658   1.1    ichiro void wi_update_stats(sc)
    659   1.1    ichiro 	struct wi_softc		*sc;
    660   1.1    ichiro {
    661   1.1    ichiro 	struct wi_ltv_gen	gen;
    662  1.35    ichiro 	struct wi_scan_header	ap2_header;	/* Prism2 header */
    663  1.35    ichiro 	struct wi_scan_data_p2	ap2;		/* Prism2 scantable*/
    664  1.35    ichiro 	struct wi_scan_data	ap;		/* Lucent scantable */
    665  1.36    ichiro 	struct wi_assoc		assoc;		/* Association Status */
    666   1.1    ichiro 	u_int16_t		id;
    667   1.1    ichiro 	struct ifnet		*ifp;
    668   1.1    ichiro 	u_int32_t		*ptr;
    669  1.35    ichiro 	int			len, naps, i, j;
    670   1.1    ichiro 	u_int16_t		t;
    671   1.1    ichiro 
    672   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    673   1.1    ichiro 
    674   1.1    ichiro 	id = CSR_READ_2(sc, WI_INFO_FID);
    675   1.1    ichiro 
    676  1.48       dbj 	if (wi_seek(sc, id, 0, WI_BAP1)) {
    677  1.48       dbj 		return;
    678  1.48       dbj 	}
    679  1.48       dbj 
    680  1.48       dbj 	gen.wi_len = CSR_READ_2(sc, WI_DATA1);
    681  1.48       dbj 	gen.wi_type = CSR_READ_2(sc, WI_DATA1);
    682   1.1    ichiro 
    683  1.31  drochner 	switch (gen.wi_type) {
    684  1.35    ichiro 	case WI_INFO_SCAN_RESULTS:
    685  1.71      onoe 	case WI_INFO_HOST_SCAN_RESULTS:
    686  1.47       dbj 		if (gen.wi_len <= 3) {
    687  1.47       dbj 			sc->wi_naps = 0;
    688  1.56      onoe 			sc->wi_scanning = 0;
    689  1.56      onoe 			break;
    690  1.56      onoe 		}
    691  1.56      onoe 		switch (sc->sc_firmware_type) {
    692  1.56      onoe 		case WI_INTERSIL:
    693  1.71      onoe 		case WI_SYMBOL:
    694  1.71      onoe 			if (sc->sc_firmware_type == WI_INTERSIL) {
    695  1.71      onoe 				naps = 2 * (gen.wi_len - 3) / sizeof(ap2);
    696  1.71      onoe 				/* Read Header */
    697  1.71      onoe 				for(j=0; j < sizeof(ap2_header) / 2; j++)
    698  1.71      onoe 					((u_int16_t *)&ap2_header)[j] =
    699  1.71      onoe 					    CSR_READ_2(sc, WI_DATA1);
    700  1.71      onoe 			} else {	/* WI_SYMBOL */
    701  1.71      onoe 				naps = 2 * (gen.wi_len - 1) / (sizeof(ap2) + 6);
    702  1.71      onoe 				ap2_header.wi_reason = 0;
    703  1.71      onoe 			}
    704  1.35    ichiro 			naps = naps > MAXAPINFO ? MAXAPINFO : naps;
    705  1.35    ichiro 			sc->wi_naps = naps;
    706  1.35    ichiro 			/* Read Data */
    707  1.35    ichiro 			for (i=0; i < naps; i++) {
    708  1.35    ichiro 				for(j=0; j < sizeof(ap2) / 2; j++)
    709  1.35    ichiro 					((u_int16_t *)&ap2)[j] =
    710  1.35    ichiro 						CSR_READ_2(sc, WI_DATA1);
    711  1.71      onoe 				if (sc->sc_firmware_type == WI_SYMBOL) {
    712  1.71      onoe 					/* 3 more words */
    713  1.71      onoe 					for (j = 0; j < 3; j++)
    714  1.71      onoe 						CSR_READ_2(sc, WI_DATA1);
    715  1.71      onoe 				}
    716  1.48       dbj 				/* unswap 8 bit data fields: */
    717  1.48       dbj 				for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
    718  1.48       dbj 					LE16TOH(((u_int16_t *)&ap.wi_bssid[0])[j]);
    719  1.48       dbj 				for(j=0;j<sizeof(ap.wi_name)/2;j++)
    720  1.48       dbj 					LE16TOH(((u_int16_t *)&ap.wi_name[0])[j]);
    721  1.35    ichiro 				sc->wi_aps[i].scanreason = ap2_header.wi_reason;
    722  1.35    ichiro 				memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6);
    723  1.35    ichiro 				sc->wi_aps[i].channel = ap2.wi_chid;
    724  1.35    ichiro 				sc->wi_aps[i].signal  = ap2.wi_signal;
    725  1.35    ichiro 				sc->wi_aps[i].noise   = ap2.wi_noise;
    726  1.35    ichiro 				sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise;
    727  1.35    ichiro 				sc->wi_aps[i].capinfo = ap2.wi_capinfo;
    728  1.35    ichiro 				sc->wi_aps[i].interval = ap2.wi_interval;
    729  1.35    ichiro 				sc->wi_aps[i].rate    = ap2.wi_rate;
    730  1.35    ichiro 				if (ap2.wi_namelen > 32)
    731  1.35    ichiro 					ap2.wi_namelen = 32;
    732  1.35    ichiro 				sc->wi_aps[i].namelen = ap2.wi_namelen;
    733  1.35    ichiro 				memcpy(sc->wi_aps[i].name, ap2.wi_name,
    734  1.35    ichiro 				       ap2.wi_namelen);
    735  1.35    ichiro 			}
    736  1.56      onoe 			break;
    737  1.56      onoe 
    738  1.56      onoe 		case WI_LUCENT:
    739  1.35    ichiro 			naps = 2 * gen.wi_len / sizeof(ap);
    740  1.35    ichiro 			naps = naps > MAXAPINFO ? MAXAPINFO : naps;
    741  1.35    ichiro 			sc->wi_naps = naps;
    742  1.35    ichiro 			/* Read Data*/
    743  1.35    ichiro 			for (i=0; i < naps; i++) {
    744  1.35    ichiro 				for(j=0; j < sizeof(ap) / 2; j++)
    745  1.35    ichiro 					((u_int16_t *)&ap)[j] =
    746  1.35    ichiro 						CSR_READ_2(sc, WI_DATA1);
    747  1.48       dbj 				/* unswap 8 bit data fields: */
    748  1.48       dbj 				for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
    749  1.48       dbj 					HTOLE16(((u_int16_t *)&ap.wi_bssid[0])[j]);
    750  1.48       dbj 				for(j=0;j<sizeof(ap.wi_name)/2;j++)
    751  1.48       dbj 					HTOLE16(((u_int16_t *)&ap.wi_name[0])[j]);
    752  1.35    ichiro 				memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6);
    753  1.35    ichiro 				sc->wi_aps[i].channel = ap.wi_chid;
    754  1.35    ichiro 				sc->wi_aps[i].signal  = ap.wi_signal;
    755  1.35    ichiro 				sc->wi_aps[i].noise   = ap.wi_noise;
    756  1.35    ichiro 				sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise;
    757  1.35    ichiro 				sc->wi_aps[i].capinfo = ap.wi_capinfo;
    758  1.35    ichiro 				sc->wi_aps[i].interval = ap.wi_interval;
    759  1.35    ichiro 				if (ap.wi_namelen > 32)
    760  1.35    ichiro 					ap.wi_namelen = 32;
    761  1.35    ichiro 				sc->wi_aps[i].namelen = ap.wi_namelen;
    762  1.35    ichiro 				memcpy(sc->wi_aps[i].name, ap.wi_name,
    763  1.35    ichiro 				       ap.wi_namelen);
    764  1.35    ichiro 			}
    765  1.56      onoe 			break;
    766  1.35    ichiro 		}
    767  1.35    ichiro 		/* Done scanning */
    768  1.35    ichiro 		sc->wi_scanning = 0;
    769  1.35    ichiro 		break;
    770  1.35    ichiro 
    771  1.31  drochner 	case WI_INFO_COUNTERS:
    772  1.31  drochner 		/* some card versions have a larger stats structure */
    773  1.31  drochner 		len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
    774  1.31  drochner 			gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
    775  1.31  drochner 		ptr = (u_int32_t *)&sc->wi_stats;
    776  1.30  explorer 
    777  1.31  drochner 		for (i = 0; i < len; i++) {
    778  1.31  drochner 			t = CSR_READ_2(sc, WI_DATA1);
    779  1.31  drochner #ifdef WI_HERMES_STATS_WAR
    780  1.31  drochner 			if (t > 0xF000)
    781  1.31  drochner 				t = ~t & 0xFFFF;
    782  1.31  drochner #endif
    783  1.31  drochner 			ptr[i] += t;
    784  1.31  drochner 		}
    785   1.1    ichiro 
    786  1.31  drochner 		ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
    787  1.31  drochner 			sc->wi_stats.wi_tx_multi_retries +
    788  1.31  drochner 			sc->wi_stats.wi_tx_retry_limit;
    789  1.31  drochner 		break;
    790  1.31  drochner 
    791  1.31  drochner 	case WI_INFO_LINK_STAT: {
    792  1.31  drochner 		static char *msg[] = {
    793  1.31  drochner 			"connected",
    794  1.31  drochner 			"disconnected",
    795  1.31  drochner 			"AP change",
    796  1.31  drochner 			"AP out of range",
    797  1.35    ichiro 			"AP in range",
    798  1.45       dbj 			"Association Failed"
    799  1.31  drochner 		};
    800  1.31  drochner 
    801  1.31  drochner 		if (gen.wi_len != 2) {
    802  1.31  drochner #ifdef WI_DEBUG
    803  1.31  drochner 			printf("WI_INFO_LINK_STAT: len=%d\n", gen.wi_len);
    804  1.31  drochner #endif
    805  1.31  drochner 			break;
    806  1.31  drochner 		}
    807  1.30  explorer 		t = CSR_READ_2(sc, WI_DATA1);
    808  1.35    ichiro 		if ((t < 1) || (t > 6)) {
    809  1.31  drochner #ifdef WI_DEBUG
    810  1.31  drochner 			printf("WI_INFO_LINK_STAT: status %d\n", t);
    811  1.31  drochner #endif
    812  1.31  drochner 			break;
    813  1.31  drochner 		}
    814  1.71      onoe 		if (sc->sc_firmware_type == WI_SYMBOL && t == 4) {
    815  1.71      onoe 			wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS);
    816  1.71      onoe 			break;
    817  1.71      onoe 		}
    818  1.38    martin 		/*
    819  1.38    martin 		 * Some cards issue streams of "connected" messages while
    820  1.38    martin 		 * trying to find a peer. Don't bother the user with this
    821  1.38    martin 		 * unless he is debugging.
    822  1.38    martin 		 */
    823  1.39    itojun 		if (ifp->if_flags & IFF_DEBUG)
    824  1.38    martin 			printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
    825  1.31  drochner 		break;
    826  1.31  drochner 		}
    827  1.31  drochner 
    828  1.36    ichiro 	case WI_INFO_ASSOC_STAT: {
    829  1.36    ichiro 		static char *msg[] = {
    830  1.36    ichiro 			"STA Associated",
    831  1.36    ichiro 			"STA Reassociated",
    832  1.36    ichiro 			"STA Disassociated",
    833  1.36    ichiro 			"Association Failure",
    834  1.45       dbj 			"Authentication Failed"
    835  1.36    ichiro 		};
    836  1.36    ichiro 		if (gen.wi_len != 10)
    837  1.36    ichiro                         break;
    838  1.36    ichiro 		for (i=0; i < gen.wi_len - 1; i++)
    839  1.36    ichiro 			((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
    840  1.48       dbj 		/* unswap 8 bit data fields: */
    841  1.48       dbj 		for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
    842  1.48       dbj 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
    843  1.48       dbj 		for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
    844  1.48       dbj 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
    845  1.36    ichiro 		switch (assoc.wi_assoc_stat) {
    846  1.36    ichiro 		case ASSOC:
    847  1.36    ichiro 		case DISASSOC:
    848  1.36    ichiro 		case ASSOCFAIL:
    849  1.36    ichiro 		case AUTHFAIL:
    850  1.46       dbj 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    851  1.36    ichiro 				sc->sc_dev.dv_xname,
    852  1.36    ichiro 				msg[assoc.wi_assoc_stat - 1],
    853  1.36    ichiro 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    854  1.36    ichiro 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    855  1.36    ichiro 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
    856  1.36    ichiro 			break;
    857  1.36    ichiro 		case REASSOC:
    858  1.46       dbj 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
    859  1.46       dbj 				"OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    860  1.36    ichiro 				sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
    861  1.36    ichiro 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    862  1.36    ichiro 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    863  1.36    ichiro 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
    864  1.36    ichiro 				assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
    865  1.36    ichiro 				assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
    866  1.36    ichiro 				assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
    867  1.36    ichiro 			break;
    868  1.36    ichiro 		}
    869  1.36    ichiro 		}
    870  1.71      onoe 
    871  1.31  drochner 	default:
    872  1.44       dbj #ifdef WI_DEBUG
    873  1.43       dbj 		printf("%s: got info type: 0x%04x len=0x%04x\n",
    874  1.43       dbj       sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
    875  1.43       dbj #endif
    876  1.31  drochner #if 0
    877  1.31  drochner 		for (i = 0; i < gen.wi_len; i++) {
    878  1.31  drochner 			t = CSR_READ_2(sc, WI_DATA1);
    879  1.31  drochner 			printf("[0x%02x] = 0x%04x\n", i, t);
    880  1.43       dbj 		}
    881   1.1    ichiro #endif
    882  1.31  drochner 		break;
    883  1.30  explorer 	}
    884   1.1    ichiro }
    885   1.1    ichiro 
    886   1.1    ichiro int wi_intr(arg)
    887   1.1    ichiro 	void *arg;
    888   1.1    ichiro {
    889   1.1    ichiro 	struct wi_softc		*sc = arg;
    890   1.1    ichiro 	struct ifnet		*ifp;
    891   1.1    ichiro 	u_int16_t		status;
    892   1.1    ichiro 
    893   1.1    ichiro 	if (sc->sc_enabled == 0 ||
    894   1.1    ichiro 	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
    895   1.1    ichiro 	    (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
    896   1.1    ichiro 		return (0);
    897   1.1    ichiro 
    898   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    899   1.1    ichiro 
    900   1.1    ichiro 	if (!(ifp->if_flags & IFF_UP)) {
    901   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    902   1.1    ichiro 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    903   1.1    ichiro 		return 1;
    904   1.1    ichiro 	}
    905   1.1    ichiro 
    906   1.1    ichiro 	/* Disable interrupts. */
    907   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    908   1.1    ichiro 
    909   1.1    ichiro 	status = CSR_READ_2(sc, WI_EVENT_STAT);
    910   1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
    911   1.1    ichiro 
    912   1.1    ichiro 	if (status & WI_EV_RX) {
    913   1.1    ichiro 		wi_rxeof(sc);
    914   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
    915   1.1    ichiro 	}
    916   1.1    ichiro 
    917   1.1    ichiro 	if (status & WI_EV_TX) {
    918   1.1    ichiro 		wi_txeof(sc, status);
    919   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
    920   1.1    ichiro 	}
    921   1.1    ichiro 
    922   1.1    ichiro 	if (status & WI_EV_ALLOC) {
    923   1.1    ichiro 		int			id;
    924   1.1    ichiro 		id = CSR_READ_2(sc, WI_ALLOC_FID);
    925   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
    926   1.1    ichiro 		if (id == sc->wi_tx_data_id)
    927   1.1    ichiro 			wi_txeof(sc, status);
    928   1.1    ichiro 	}
    929   1.1    ichiro 
    930   1.1    ichiro 	if (status & WI_EV_INFO) {
    931   1.1    ichiro 		wi_update_stats(sc);
    932   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
    933   1.1    ichiro 	}
    934   1.1    ichiro 
    935   1.1    ichiro 	if (status & WI_EV_TX_EXC) {
    936   1.1    ichiro 		wi_txeof(sc, status);
    937   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
    938   1.1    ichiro 	}
    939   1.1    ichiro 
    940   1.1    ichiro 	if (status & WI_EV_INFO_DROP) {
    941   1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
    942   1.1    ichiro 	}
    943   1.1    ichiro 
    944   1.1    ichiro 	/* Re-enable interrupts. */
    945   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    946   1.1    ichiro 
    947   1.1    ichiro 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    948   1.1    ichiro 		wi_start(ifp);
    949   1.1    ichiro 
    950   1.1    ichiro 	return 1;
    951   1.1    ichiro }
    952   1.1    ichiro 
    953  1.40    martin /* Must be called at proper protection level! */
    954  1.11    tsubai static int
    955   1.1    ichiro wi_cmd(sc, cmd, val)
    956   1.1    ichiro 	struct wi_softc		*sc;
    957   1.1    ichiro 	int			cmd;
    958   1.1    ichiro 	int			val;
    959   1.1    ichiro {
    960   1.1    ichiro 	int			i, s = 0;
    961   1.1    ichiro 
    962   1.1    ichiro 	/* wait for the busy bit to clear */
    963   1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    964   1.1    ichiro 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
    965   1.1    ichiro 			break;
    966   1.1    ichiro 	}
    967   1.1    ichiro 
    968  1.40    martin 	if (i == WI_TIMEOUT) {
    969  1.40    martin 		printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
    970  1.40    martin 			sc->sc_dev.dv_xname, cmd);
    971  1.40    martin 		return EIO;
    972  1.40    martin 	}
    973  1.40    martin 
    974   1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM0, val);
    975   1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM1, 0);
    976   1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM2, 0);
    977   1.1    ichiro 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
    978   1.1    ichiro 
    979   1.1    ichiro 	/* wait for the cmd completed bit */
    980   1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    981   1.1    ichiro 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
    982   1.1    ichiro 			break;
    983   1.2    ichiro 		DELAY(1);
    984   1.1    ichiro 	}
    985   1.1    ichiro 
    986   1.1    ichiro 	/* Ack the command */
    987   1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
    988   1.1    ichiro 
    989   1.1    ichiro 	s = CSR_READ_2(sc, WI_STATUS);
    990   1.1    ichiro 	if (s & WI_STAT_CMD_RESULT)
    991   1.1    ichiro 		return(EIO);
    992   1.1    ichiro 
    993  1.40    martin 	if (i == WI_TIMEOUT) {
    994  1.40    martin 		if (!sc->wi_scanning)
    995  1.40    martin 		    printf("%s: command timed out, cmd=0x%x\n",
    996  1.40    martin 			sc->sc_dev.dv_xname, cmd);
    997   1.1    ichiro 		return(ETIMEDOUT);
    998  1.40    martin 	}
    999   1.1    ichiro 
   1000   1.1    ichiro 	return(0);
   1001   1.1    ichiro }
   1002   1.1    ichiro 
   1003  1.11    tsubai static void
   1004   1.1    ichiro wi_reset(sc)
   1005   1.1    ichiro 	struct wi_softc		*sc;
   1006   1.1    ichiro {
   1007  1.56      onoe 
   1008  1.11    tsubai 	DELAY(100*1000); /* 100 m sec */
   1009   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_INI, 0))
   1010   1.1    ichiro 		printf("%s: init failed\n", sc->sc_dev.dv_xname);
   1011   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1012   1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
   1013   1.1    ichiro 
   1014   1.1    ichiro 	/* Calibrate timer. */
   1015   1.1    ichiro 	WI_SETVAL(WI_RID_TICK_TIME, 8);
   1016  1.26    ichiro 
   1017  1.26    ichiro 	return;
   1018  1.26    ichiro }
   1019  1.26    ichiro 
   1020   1.1    ichiro /*
   1021   1.1    ichiro  * Read an LTV record from the NIC.
   1022   1.1    ichiro  */
   1023   1.1    ichiro static int wi_read_record(sc, ltv)
   1024   1.1    ichiro 	struct wi_softc		*sc;
   1025   1.1    ichiro 	struct wi_ltv_gen	*ltv;
   1026   1.1    ichiro {
   1027   1.1    ichiro 	u_int16_t		*ptr;
   1028  1.15    toshii 	int			len, code;
   1029   1.1    ichiro 	struct wi_ltv_gen	*oltv, p2ltv;
   1030   1.1    ichiro 
   1031  1.56      onoe 	if (sc->sc_firmware_type != WI_LUCENT) {
   1032   1.1    ichiro 		oltv = ltv;
   1033   1.1    ichiro 		switch (ltv->wi_type) {
   1034   1.1    ichiro 		case WI_RID_ENCRYPTION:
   1035   1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1036   1.1    ichiro 			p2ltv.wi_len = 2;
   1037   1.1    ichiro 			ltv = &p2ltv;
   1038   1.1    ichiro 			break;
   1039   1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
   1040   1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1041   1.1    ichiro 			p2ltv.wi_len = 2;
   1042   1.1    ichiro 			ltv = &p2ltv;
   1043   1.1    ichiro 			break;
   1044  1.70      onoe 		case WI_RID_ROAMING_MODE:
   1045  1.70      onoe 			if (sc->sc_firmware_type == WI_INTERSIL)
   1046  1.70      onoe 				break;
   1047  1.70      onoe 			/* not supported */
   1048  1.70      onoe 			ltv->wi_len = 1;
   1049  1.70      onoe 			return 0;
   1050  1.70      onoe 		case WI_RID_MICROWAVE_OVEN:
   1051  1.70      onoe 			/* not supported */
   1052  1.70      onoe 			ltv->wi_len = 1;
   1053  1.70      onoe 			return 0;
   1054   1.1    ichiro 		}
   1055   1.1    ichiro 	}
   1056   1.1    ichiro 
   1057   1.1    ichiro 	/* Tell the NIC to enter record read mode. */
   1058   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
   1059   1.1    ichiro 		return(EIO);
   1060   1.1    ichiro 
   1061   1.1    ichiro 	/* Seek to the record. */
   1062   1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1063   1.1    ichiro 		return(EIO);
   1064   1.1    ichiro 
   1065   1.1    ichiro 	/*
   1066   1.1    ichiro 	 * Read the length and record type and make sure they
   1067   1.1    ichiro 	 * match what we expect (this verifies that we have enough
   1068   1.1    ichiro 	 * room to hold all of the returned data).
   1069   1.1    ichiro 	 */
   1070   1.1    ichiro 	len = CSR_READ_2(sc, WI_DATA1);
   1071   1.1    ichiro 	if (len > ltv->wi_len)
   1072   1.1    ichiro 		return(ENOSPC);
   1073   1.1    ichiro 	code = CSR_READ_2(sc, WI_DATA1);
   1074   1.1    ichiro 	if (code != ltv->wi_type)
   1075   1.1    ichiro 		return(EIO);
   1076   1.1    ichiro 
   1077   1.1    ichiro 	ltv->wi_len = len;
   1078   1.1    ichiro 	ltv->wi_type = code;
   1079   1.1    ichiro 
   1080   1.1    ichiro 	/* Now read the data. */
   1081   1.1    ichiro 	ptr = &ltv->wi_val;
   1082  1.16    toshii 	if (ltv->wi_len > 1)
   1083  1.16    toshii 		CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1084   1.1    ichiro 
   1085  1.77   thorpej 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1086  1.77   thorpej 	    sc->wi_ptype == WI_PORTTYPE_IBSS &&
   1087  1.77   thorpej 	    ltv->wi_val == sc->wi_ibss_port) {
   1088  1.77   thorpej 		/*
   1089  1.77   thorpej 		 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
   1090  1.77   thorpej 		 * Since Lucent uses port type 1 for BSS *and* IBSS we
   1091  1.77   thorpej 		 * have to rely on wi_ptype to distinguish this for us.
   1092  1.77   thorpej 		 */
   1093  1.77   thorpej 		ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
   1094  1.77   thorpej 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1095  1.11    tsubai 		int v;
   1096  1.11    tsubai 
   1097   1.1    ichiro 		switch (oltv->wi_type) {
   1098   1.1    ichiro 		case WI_RID_TX_RATE:
   1099   1.1    ichiro 		case WI_RID_CUR_TX_RATE:
   1100  1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
   1101  1.11    tsubai 			case 1: v = 1; break;
   1102  1.11    tsubai 			case 2: v = 2; break;
   1103  1.11    tsubai 			case 3:	v = 6; break;
   1104  1.11    tsubai 			case 4: v = 5; break;
   1105  1.11    tsubai 			case 7: v = 7; break;
   1106  1.11    tsubai 			case 8: v = 11; break;
   1107  1.11    tsubai 			case 15: v = 3; break;
   1108  1.11    tsubai 			default: v = 0x100 + le16toh(ltv->wi_val); break;
   1109   1.1    ichiro 			}
   1110  1.11    tsubai 			oltv->wi_val = htole16(v);
   1111   1.1    ichiro 			break;
   1112   1.1    ichiro 		case WI_RID_ENCRYPTION:
   1113   1.1    ichiro 			oltv->wi_len = 2;
   1114  1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
   1115  1.11    tsubai 				oltv->wi_val = htole16(1);
   1116   1.1    ichiro 			else
   1117  1.11    tsubai 				oltv->wi_val = htole16(0);
   1118   1.1    ichiro 			break;
   1119   1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
   1120   1.1    ichiro 			oltv->wi_len = 2;
   1121   1.1    ichiro 			oltv->wi_val = ltv->wi_val;
   1122   1.1    ichiro 			break;
   1123  1.79   thorpej 		case WI_RID_CNFAUTHMODE:
   1124   1.4    ichiro 			oltv->wi_len = 2;
   1125  1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
   1126  1.11    tsubai 				oltv->wi_val = htole16(1);
   1127  1.11    tsubai 			else if (le16toh(ltv->wi_val) & 0x02)
   1128  1.11    tsubai 				oltv->wi_val = htole16(2);
   1129   1.4    ichiro 			break;
   1130   1.1    ichiro 		}
   1131   1.1    ichiro 	}
   1132   1.1    ichiro 
   1133   1.1    ichiro 	return(0);
   1134   1.1    ichiro }
   1135   1.1    ichiro 
   1136   1.1    ichiro /*
   1137   1.1    ichiro  * Same as read, except we inject data instead of reading it.
   1138   1.1    ichiro  */
   1139   1.1    ichiro static int wi_write_record(sc, ltv)
   1140   1.1    ichiro 	struct wi_softc		*sc;
   1141   1.1    ichiro 	struct wi_ltv_gen	*ltv;
   1142   1.1    ichiro {
   1143   1.1    ichiro 	u_int16_t		*ptr;
   1144   1.1    ichiro 	int			i;
   1145   1.1    ichiro 	struct wi_ltv_gen	p2ltv;
   1146   1.1    ichiro 
   1147  1.77   thorpej 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1148  1.77   thorpej 	    ltv->wi_val == le16toh(WI_PORTTYPE_IBSS)) {
   1149  1.77   thorpej 		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
   1150  1.77   thorpej 		p2ltv.wi_type = WI_RID_PORTTYPE;
   1151  1.77   thorpej 		p2ltv.wi_len = 2;
   1152  1.77   thorpej 		p2ltv.wi_val = sc->wi_ibss_port;
   1153  1.77   thorpej 		ltv = &p2ltv;
   1154  1.77   thorpej 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1155  1.11    tsubai 		int v;
   1156  1.11    tsubai 
   1157   1.1    ichiro 		switch (ltv->wi_type) {
   1158   1.1    ichiro 		case WI_RID_TX_RATE:
   1159   1.1    ichiro 			p2ltv.wi_type = WI_RID_TX_RATE;
   1160   1.1    ichiro 			p2ltv.wi_len = 2;
   1161  1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
   1162  1.11    tsubai 			case 1: v = 1; break;
   1163  1.11    tsubai 			case 2: v = 2; break;
   1164  1.11    tsubai 			case 3:	v = 15; break;
   1165  1.11    tsubai 			case 5: v = 4; break;
   1166  1.11    tsubai 			case 6: v = 3; break;
   1167  1.11    tsubai 			case 7: v = 7; break;
   1168  1.11    tsubai 			case 11: v = 8; break;
   1169   1.1    ichiro 			default: return EINVAL;
   1170   1.1    ichiro 			}
   1171  1.11    tsubai 			p2ltv.wi_val = htole16(v);
   1172   1.1    ichiro 			ltv = &p2ltv;
   1173   1.1    ichiro 			break;
   1174   1.1    ichiro 		case WI_RID_ENCRYPTION:
   1175   1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1176   1.1    ichiro 			p2ltv.wi_len = 2;
   1177  1.79   thorpej 			if (le16toh(ltv->wi_val)) {
   1178  1.80   thorpej 				uint16_t val = PRIVACY_INVOKED;
   1179  1.80   thorpej 				/*
   1180  1.80   thorpej 				 * If using shared key WEP we must set the
   1181  1.80   thorpej 				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
   1182  1.80   thorpej 				 * need this bit even when not using shared
   1183  1.80   thorpej 				 * key.  We can't just test for
   1184  1.80   thorpej 				 * IEEE80211_AUTH_SHARED since Symbol cards
   1185  1.80   thorpej 				 * have 2 shared key modes.
   1186  1.80   thorpej 				 */
   1187  1.80   thorpej 				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
   1188  1.80   thorpej 				    sc->sc_firmware_type == WI_SYMBOL)
   1189  1.80   thorpej 					val |= EXCLUDE_UNENCRYPTED;
   1190  1.79   thorpej 				/* Tx encryption is broken in Host-AP mode. */
   1191  1.79   thorpej 				if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
   1192  1.79   thorpej 					val |= HOST_ENCRYPT;
   1193  1.79   thorpej 				p2ltv.wi_val = htole16(val);
   1194  1.79   thorpej 			} else
   1195  1.59    ichiro 				p2ltv.wi_val =
   1196  1.59    ichiro 				    htole16(HOST_ENCRYPT | HOST_DECRYPT);
   1197   1.1    ichiro 			ltv = &p2ltv;
   1198   1.1    ichiro 			break;
   1199   1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
   1200   1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1201   1.1    ichiro 			p2ltv.wi_len = 2;
   1202   1.1    ichiro 			p2ltv.wi_val = ltv->wi_val;
   1203   1.1    ichiro 			ltv = &p2ltv;
   1204   1.1    ichiro 			break;
   1205   1.1    ichiro 		case WI_RID_DEFLT_CRYPT_KEYS:
   1206   1.1    ichiro 		    {
   1207   1.1    ichiro 			int error;
   1208  1.52    ichiro 			int keylen;
   1209   1.1    ichiro 			struct wi_ltv_str	ws;
   1210   1.1    ichiro 			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
   1211  1.52    ichiro 
   1212  1.52    ichiro 			keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
   1213  1.52    ichiro 
   1214   1.1    ichiro 			for (i = 0; i < 4; i++) {
   1215  1.33    ichiro 				memset(&ws, 0, sizeof(ws));
   1216  1.52    ichiro 				ws.wi_len = (keylen > 5) ? 8 : 4;
   1217   1.1    ichiro 				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
   1218  1.52    ichiro 				memcpy(ws.wi_str,
   1219  1.52    ichiro 					&wk->wi_keys[i].wi_keydat, keylen);
   1220  1.52    ichiro 				error = wi_write_record(sc,
   1221  1.52    ichiro 					(struct wi_ltv_gen *)&ws);
   1222  1.52    ichiro 				if (error)
   1223   1.1    ichiro 					return error;
   1224   1.1    ichiro 			}
   1225   1.1    ichiro 			return 0;
   1226   1.1    ichiro 		    }
   1227  1.79   thorpej 		case WI_RID_CNFAUTHMODE:
   1228  1.79   thorpej 			p2ltv.wi_type = WI_RID_CNFAUTHMODE;
   1229   1.4    ichiro 			p2ltv.wi_len = 2;
   1230  1.11    tsubai 			if (le16toh(ltv->wi_val) == 1)
   1231  1.11    tsubai 				p2ltv.wi_val = htole16(0x01);
   1232  1.11    tsubai 			else if (le16toh(ltv->wi_val) == 2)
   1233  1.11    tsubai 				p2ltv.wi_val = htole16(0x02);
   1234   1.4    ichiro 			ltv = &p2ltv;
   1235   1.4    ichiro 			break;
   1236  1.70      onoe 
   1237  1.70      onoe 		case WI_RID_ROAMING_MODE:
   1238  1.70      onoe 			if (sc->sc_firmware_type == WI_INTERSIL)
   1239  1.70      onoe 				break;
   1240  1.70      onoe 			/* not supported */
   1241  1.70      onoe 			return 0;
   1242  1.70      onoe 
   1243  1.70      onoe 		case WI_RID_MICROWAVE_OVEN:
   1244  1.70      onoe 			/* not supported */
   1245  1.70      onoe 			return 0;
   1246   1.1    ichiro 		}
   1247   1.1    ichiro 	}
   1248   1.1    ichiro 
   1249   1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1250   1.1    ichiro 		return(EIO);
   1251   1.1    ichiro 
   1252   1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
   1253   1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
   1254   1.1    ichiro 
   1255   1.1    ichiro 	/* Write data */
   1256   1.1    ichiro 	ptr = &ltv->wi_val;
   1257  1.16    toshii 	if (ltv->wi_len > 1)
   1258  1.16    toshii 		CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1259   1.1    ichiro 
   1260   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
   1261   1.1    ichiro 		return(EIO);
   1262   1.1    ichiro 
   1263   1.1    ichiro 	return(0);
   1264   1.1    ichiro }
   1265   1.1    ichiro 
   1266   1.1    ichiro static int wi_seek(sc, id, off, chan)
   1267   1.1    ichiro 	struct wi_softc		*sc;
   1268   1.1    ichiro 	int			id, off, chan;
   1269   1.1    ichiro {
   1270   1.1    ichiro 	int			i;
   1271   1.1    ichiro 	int			selreg, offreg;
   1272   1.1    ichiro 	int 			status;
   1273   1.1    ichiro 
   1274   1.1    ichiro 	switch (chan) {
   1275   1.1    ichiro 	case WI_BAP0:
   1276   1.1    ichiro 		selreg = WI_SEL0;
   1277   1.1    ichiro 		offreg = WI_OFF0;
   1278   1.1    ichiro 		break;
   1279   1.1    ichiro 	case WI_BAP1:
   1280   1.1    ichiro 		selreg = WI_SEL1;
   1281   1.1    ichiro 		offreg = WI_OFF1;
   1282   1.1    ichiro 		break;
   1283   1.1    ichiro 	default:
   1284   1.1    ichiro 		printf("%s: invalid data path: %x\n",
   1285   1.1    ichiro 		    sc->sc_dev.dv_xname, chan);
   1286   1.1    ichiro 		return(EIO);
   1287   1.1    ichiro 	}
   1288   1.1    ichiro 
   1289   1.1    ichiro 	CSR_WRITE_2(sc, selreg, id);
   1290   1.1    ichiro 	CSR_WRITE_2(sc, offreg, off);
   1291   1.1    ichiro 
   1292   1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
   1293   1.1    ichiro 	  	status = CSR_READ_2(sc, offreg);
   1294   1.1    ichiro 		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
   1295   1.1    ichiro 			break;
   1296   1.1    ichiro 	}
   1297   1.1    ichiro 
   1298   1.1    ichiro 	if (i == WI_TIMEOUT) {
   1299   1.1    ichiro 		printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
   1300   1.1    ichiro 		       sc->sc_dev.dv_xname, id, off, status);
   1301   1.1    ichiro 		return(ETIMEDOUT);
   1302   1.1    ichiro 	}
   1303   1.1    ichiro 	return(0);
   1304   1.1    ichiro }
   1305   1.1    ichiro 
   1306   1.1    ichiro static int wi_read_data(sc, id, off, buf, len)
   1307   1.1    ichiro 	struct wi_softc		*sc;
   1308   1.1    ichiro 	int			id, off;
   1309   1.1    ichiro 	caddr_t			buf;
   1310   1.1    ichiro 	int			len;
   1311   1.1    ichiro {
   1312   1.1    ichiro 	u_int16_t		*ptr;
   1313   1.1    ichiro 
   1314   1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP1))
   1315   1.1    ichiro 		return(EIO);
   1316   1.1    ichiro 
   1317   1.1    ichiro 	ptr = (u_int16_t *)buf;
   1318  1.15    toshii 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
   1319   1.1    ichiro 
   1320   1.1    ichiro 	return(0);
   1321   1.1    ichiro }
   1322   1.1    ichiro 
   1323   1.1    ichiro /*
   1324   1.1    ichiro  * According to the comments in the HCF Light code, there is a bug in
   1325   1.1    ichiro  * the Hermes (or possibly in certain Hermes firmware revisions) where
   1326   1.1    ichiro  * the chip's internal autoincrement counter gets thrown off during
   1327   1.1    ichiro  * data writes: the autoincrement is missed, causing one data word to
   1328   1.1    ichiro  * be overwritten and subsequent words to be written to the wrong memory
   1329   1.1    ichiro  * locations. The end result is that we could end up transmitting bogus
   1330   1.1    ichiro  * frames without realizing it. The workaround for this is to write a
   1331   1.1    ichiro  * couple of extra guard words after the end of the transfer, then
   1332   1.1    ichiro  * attempt to read then back. If we fail to locate the guard words where
   1333   1.1    ichiro  * we expect them, we preform the transfer over again.
   1334   1.1    ichiro  */
   1335   1.1    ichiro static int wi_write_data(sc, id, off, buf, len)
   1336   1.1    ichiro 	struct wi_softc		*sc;
   1337   1.1    ichiro 	int			id, off;
   1338   1.1    ichiro 	caddr_t			buf;
   1339   1.1    ichiro 	int			len;
   1340   1.1    ichiro {
   1341   1.1    ichiro 	u_int16_t		*ptr;
   1342   1.1    ichiro 
   1343   1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
   1344   1.1    ichiro again:
   1345   1.1    ichiro #endif
   1346   1.1    ichiro 
   1347   1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP0))
   1348   1.1    ichiro 		return(EIO);
   1349   1.1    ichiro 
   1350   1.1    ichiro 	ptr = (u_int16_t *)buf;
   1351  1.15    toshii 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
   1352   1.1    ichiro 
   1353   1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
   1354   1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
   1355   1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
   1356   1.1    ichiro 
   1357   1.1    ichiro 	if (wi_seek(sc, id, off + len, WI_BAP0))
   1358   1.1    ichiro 		return(EIO);
   1359   1.1    ichiro 
   1360   1.1    ichiro 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
   1361   1.1    ichiro 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
   1362   1.1    ichiro 		goto again;
   1363   1.1    ichiro #endif
   1364   1.1    ichiro 
   1365   1.1    ichiro 	return(0);
   1366   1.1    ichiro }
   1367   1.1    ichiro 
   1368   1.1    ichiro /*
   1369   1.1    ichiro  * Allocate a region of memory inside the NIC and zero
   1370   1.1    ichiro  * it out.
   1371   1.1    ichiro  */
   1372   1.1    ichiro static int wi_alloc_nicmem(sc, len, id)
   1373   1.1    ichiro 	struct wi_softc		*sc;
   1374   1.1    ichiro 	int			len;
   1375   1.1    ichiro 	int			*id;
   1376   1.1    ichiro {
   1377   1.1    ichiro 	int			i;
   1378   1.1    ichiro 
   1379   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
   1380   1.1    ichiro 		printf("%s: failed to allocate %d bytes on NIC\n",
   1381   1.1    ichiro 		    sc->sc_dev.dv_xname, len);
   1382   1.1    ichiro 		return(ENOMEM);
   1383   1.1    ichiro 	}
   1384   1.1    ichiro 
   1385   1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
   1386   1.1    ichiro 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   1387   1.1    ichiro 			break;
   1388   1.1    ichiro 	}
   1389   1.1    ichiro 
   1390   1.1    ichiro 	if (i == WI_TIMEOUT) {
   1391   1.1    ichiro 		printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
   1392   1.1    ichiro 		return(ETIMEDOUT);
   1393   1.1    ichiro 	}
   1394   1.1    ichiro 
   1395  1.56      onoe 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
   1396   1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1397   1.1    ichiro 
   1398   1.1    ichiro 	if (wi_seek(sc, *id, 0, WI_BAP0)) {
   1399   1.1    ichiro 		printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
   1400   1.1    ichiro 		return(EIO);
   1401   1.1    ichiro 	}
   1402   1.1    ichiro 
   1403   1.1    ichiro 	for (i = 0; i < len / 2; i++)
   1404   1.1    ichiro 		CSR_WRITE_2(sc, WI_DATA0, 0);
   1405   1.1    ichiro 
   1406   1.1    ichiro 	return(0);
   1407   1.1    ichiro }
   1408   1.1    ichiro 
   1409   1.1    ichiro static void wi_setmulti(sc)
   1410   1.1    ichiro 	struct wi_softc		*sc;
   1411   1.1    ichiro {
   1412   1.1    ichiro 	struct ifnet		*ifp;
   1413   1.1    ichiro 	int			i = 0;
   1414   1.1    ichiro 	struct wi_ltv_mcast	mcast;
   1415   1.1    ichiro 	struct ether_multi *enm;
   1416   1.1    ichiro 	struct ether_multistep estep;
   1417   1.1    ichiro 	struct ethercom *ec = &sc->sc_ethercom;
   1418   1.1    ichiro 
   1419   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1420   1.1    ichiro 
   1421   1.1    ichiro 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1422   1.1    ichiro allmulti:
   1423   1.1    ichiro 		ifp->if_flags |= IFF_ALLMULTI;
   1424  1.21   thorpej 		memset((char *)&mcast, 0, sizeof(mcast));
   1425  1.28  christos 		mcast.wi_type = WI_RID_MCAST_LIST;
   1426   1.1    ichiro 		mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
   1427   1.1    ichiro 
   1428   1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1429   1.1    ichiro 		return;
   1430   1.1    ichiro 	}
   1431   1.1    ichiro 
   1432   1.1    ichiro 	i = 0;
   1433   1.1    ichiro 	ETHER_FIRST_MULTI(estep, ec, enm);
   1434   1.1    ichiro 	while (enm != NULL) {
   1435   1.1    ichiro 		/* Punt on ranges or too many multicast addresses. */
   1436  1.19   thorpej 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1437   1.1    ichiro 		    ETHER_ADDR_LEN) != 0 ||
   1438   1.1    ichiro 		    i >= 16)
   1439   1.1    ichiro 			goto allmulti;
   1440   1.1    ichiro 
   1441  1.20   thorpej 		memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
   1442  1.20   thorpej 		    ETHER_ADDR_LEN);
   1443   1.1    ichiro 		i++;
   1444   1.1    ichiro 		ETHER_NEXT_MULTI(estep, enm);
   1445   1.1    ichiro 	}
   1446   1.1    ichiro 
   1447   1.1    ichiro 	ifp->if_flags &= ~IFF_ALLMULTI;
   1448  1.28  christos 	mcast.wi_type = WI_RID_MCAST_LIST;
   1449   1.1    ichiro 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
   1450   1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1451   1.1    ichiro }
   1452   1.1    ichiro 
   1453   1.1    ichiro static int
   1454   1.1    ichiro wi_setdef(sc, wreq)
   1455   1.1    ichiro 	struct wi_softc		*sc;
   1456   1.1    ichiro 	struct wi_req		*wreq;
   1457   1.1    ichiro {
   1458   1.1    ichiro 	struct sockaddr_dl	*sdl;
   1459   1.1    ichiro 	struct ifnet		*ifp;
   1460   1.1    ichiro 	int error = 0;
   1461   1.1    ichiro 
   1462   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1463   1.1    ichiro 
   1464   1.1    ichiro 	switch(wreq->wi_type) {
   1465   1.1    ichiro 	case WI_RID_MAC_NODE:
   1466   1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1467  1.20   thorpej 		memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
   1468   1.1    ichiro 		    ETHER_ADDR_LEN);
   1469  1.20   thorpej 		memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
   1470   1.1    ichiro 		break;
   1471   1.1    ichiro 	case WI_RID_PORTTYPE:
   1472  1.77   thorpej 		error = wi_sync_media(sc, le16toh(wreq->wi_val[0]),
   1473  1.77   thorpej 		    sc->wi_tx_rate);
   1474   1.1    ichiro 		break;
   1475   1.1    ichiro 	case WI_RID_TX_RATE:
   1476  1.77   thorpej 		error = wi_sync_media(sc, sc->wi_ptype,
   1477  1.77   thorpej 		    le16toh(wreq->wi_val[0]));
   1478   1.1    ichiro 		break;
   1479   1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1480  1.11    tsubai 		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
   1481   1.1    ichiro 		break;
   1482   1.1    ichiro 	case WI_RID_RTS_THRESH:
   1483  1.11    tsubai 		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
   1484   1.1    ichiro 		break;
   1485   1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1486  1.11    tsubai 		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
   1487   1.1    ichiro 		break;
   1488   1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1489  1.77   thorpej 		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
   1490  1.77   thorpej 		error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
   1491   1.1    ichiro 		break;
   1492   1.1    ichiro 	case WI_RID_OWN_CHNL:
   1493  1.11    tsubai 		sc->wi_channel = le16toh(wreq->wi_val[0]);
   1494   1.1    ichiro 		break;
   1495   1.1    ichiro 	case WI_RID_NODENAME:
   1496   1.1    ichiro 		error = wi_set_ssid(&sc->wi_nodeid,
   1497  1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1498   1.1    ichiro 		break;
   1499   1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1500   1.1    ichiro 		error = wi_set_ssid(&sc->wi_netid,
   1501  1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1502   1.1    ichiro 		break;
   1503   1.1    ichiro 	case WI_RID_OWN_SSID:
   1504   1.1    ichiro 		error = wi_set_ssid(&sc->wi_ibssid,
   1505  1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1506   1.1    ichiro 		break;
   1507   1.1    ichiro 	case WI_RID_PM_ENABLED:
   1508  1.11    tsubai 		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
   1509   1.1    ichiro 		break;
   1510   1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1511  1.11    tsubai 		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
   1512   1.1    ichiro 		break;
   1513   1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1514  1.11    tsubai 		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
   1515   1.1    ichiro 		break;
   1516  1.79   thorpej 	case WI_RID_CNFAUTHMODE:
   1517  1.11    tsubai 		sc->wi_authtype = le16toh(wreq->wi_val[0]);
   1518   1.4    ichiro 		break;
   1519   1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1520  1.11    tsubai 		sc->wi_roaming = le16toh(wreq->wi_val[0]);
   1521   1.4    ichiro 		break;
   1522   1.1    ichiro 	case WI_RID_ENCRYPTION:
   1523  1.11    tsubai 		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
   1524   1.1    ichiro 		break;
   1525   1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1526  1.11    tsubai 		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
   1527   1.1    ichiro 		break;
   1528   1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1529  1.20   thorpej 		memcpy((char *)&sc->wi_keys, (char *)wreq,
   1530   1.1    ichiro 		    sizeof(struct wi_ltv_keys));
   1531   1.1    ichiro 		break;
   1532   1.1    ichiro 	default:
   1533   1.1    ichiro 		error = EINVAL;
   1534   1.1    ichiro 		break;
   1535   1.1    ichiro 	}
   1536   1.1    ichiro 
   1537   1.1    ichiro 	return (error);
   1538   1.1    ichiro }
   1539   1.1    ichiro 
   1540   1.1    ichiro static int
   1541   1.1    ichiro wi_getdef(sc, wreq)
   1542   1.1    ichiro 	struct wi_softc		*sc;
   1543   1.1    ichiro 	struct wi_req		*wreq;
   1544   1.1    ichiro {
   1545   1.1    ichiro 	struct sockaddr_dl	*sdl;
   1546   1.1    ichiro 	struct ifnet		*ifp;
   1547   1.1    ichiro 	int error = 0;
   1548   1.1    ichiro 
   1549   1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1550   1.1    ichiro 
   1551   1.1    ichiro 	wreq->wi_len = 2;			/* XXX */
   1552   1.1    ichiro 	switch (wreq->wi_type) {
   1553   1.1    ichiro 	case WI_RID_MAC_NODE:
   1554   1.1    ichiro 		wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
   1555   1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1556  1.20   thorpej 		memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
   1557  1.20   thorpej 		memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
   1558   1.1    ichiro 		break;
   1559   1.1    ichiro 	case WI_RID_PORTTYPE:
   1560  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ptype);
   1561   1.1    ichiro 		break;
   1562   1.1    ichiro 	case WI_RID_TX_RATE:
   1563  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_rate);
   1564   1.1    ichiro 		break;
   1565   1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1566  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_data_len);
   1567   1.1    ichiro 		break;
   1568   1.1    ichiro 	case WI_RID_RTS_THRESH:
   1569  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
   1570   1.1    ichiro 		break;
   1571   1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1572  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ap_density);
   1573   1.1    ichiro 		break;
   1574   1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1575  1.77   thorpej 		wreq->wi_val[0] = htole16(sc->wi_create_ibss);
   1576   1.1    ichiro 		break;
   1577   1.1    ichiro 	case WI_RID_OWN_CHNL:
   1578  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_channel);
   1579   1.1    ichiro 		break;
   1580   1.1    ichiro 	case WI_RID_NODENAME:
   1581   1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_nodeid);
   1582   1.1    ichiro 		break;
   1583   1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1584   1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_netid);
   1585   1.1    ichiro 		break;
   1586   1.1    ichiro 	case WI_RID_OWN_SSID:
   1587   1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_ibssid);
   1588   1.1    ichiro 		break;
   1589   1.1    ichiro 	case WI_RID_PM_ENABLED:
   1590  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
   1591   1.1    ichiro 		break;
   1592   1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1593  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
   1594   1.1    ichiro 		break;
   1595   1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1596  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_sleep);
   1597   1.1    ichiro 		break;
   1598  1.79   thorpej 	case WI_RID_CNFAUTHMODE:
   1599  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_authtype);
   1600   1.4    ichiro 		break;
   1601   1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1602  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_roaming);
   1603   1.4    ichiro 		break;
   1604   1.1    ichiro 	case WI_RID_WEP_AVAIL:
   1605  1.77   thorpej 		wreq->wi_val[0] = (sc->wi_flags & WI_FLAGS_HAS_WEP) ?
   1606  1.77   thorpej 		    htole16(1) : htole16(0);
   1607   1.1    ichiro 		break;
   1608   1.1    ichiro 	case WI_RID_ENCRYPTION:
   1609  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_use_wep);
   1610   1.1    ichiro 		break;
   1611   1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1612  1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_key);
   1613   1.1    ichiro 		break;
   1614   1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1615   1.1    ichiro 		wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
   1616  1.20   thorpej 		memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
   1617   1.1    ichiro 		break;
   1618   1.1    ichiro 	default:
   1619   1.1    ichiro #if 0
   1620   1.1    ichiro 		error = EIO;
   1621   1.1    ichiro #else
   1622   1.1    ichiro #ifdef WI_DEBUG
   1623   1.1    ichiro 		printf("%s: wi_getdef: unknown request %d\n",
   1624   1.1    ichiro 		    sc->sc_dev.dv_xname, wreq->wi_type);
   1625   1.1    ichiro #endif
   1626   1.1    ichiro #endif
   1627   1.1    ichiro 		break;
   1628   1.1    ichiro 	}
   1629   1.1    ichiro 
   1630   1.1    ichiro 	return (error);
   1631   1.1    ichiro }
   1632   1.1    ichiro 
   1633   1.1    ichiro static int
   1634   1.1    ichiro wi_ioctl(ifp, command, data)
   1635   1.1    ichiro 	struct ifnet		*ifp;
   1636   1.1    ichiro 	u_long			command;
   1637   1.1    ichiro 	caddr_t			data;
   1638   1.1    ichiro {
   1639  1.30  explorer 	int			s, error = 0;
   1640  1.35    ichiro 	int			len;
   1641   1.1    ichiro 	struct wi_softc		*sc = ifp->if_softc;
   1642   1.1    ichiro 	struct wi_req		wreq;
   1643   1.1    ichiro 	struct ifreq		*ifr;
   1644   1.1    ichiro 	struct proc *p = curproc;
   1645   1.1    ichiro 	struct ieee80211_nwid nwid;
   1646   1.1    ichiro 
   1647   1.1    ichiro 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1648   1.1    ichiro 		return (ENXIO);
   1649   1.1    ichiro 
   1650   1.1    ichiro 	s = splnet();
   1651   1.1    ichiro 
   1652   1.1    ichiro 	ifr = (struct ifreq *)data;
   1653   1.1    ichiro 	switch (command) {
   1654   1.1    ichiro 	case SIOCSIFADDR:
   1655   1.1    ichiro 	case SIOCGIFADDR:
   1656   1.1    ichiro 	case SIOCSIFMTU:
   1657   1.1    ichiro 		error = ether_ioctl(ifp, command, data);
   1658   1.1    ichiro 		break;
   1659   1.1    ichiro 	case SIOCSIFFLAGS:
   1660   1.3    ichiro 		if (ifp->if_flags & IFF_UP) {
   1661   1.3    ichiro 			if (ifp->if_flags & IFF_RUNNING &&
   1662   1.3    ichiro 			    ifp->if_flags & IFF_PROMISC &&
   1663   1.3    ichiro 			    !(sc->wi_if_flags & IFF_PROMISC)) {
   1664  1.79   thorpej 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1665  1.79   thorpej 					WI_SETVAL(WI_RID_PROMISC, 1);
   1666   1.3    ichiro 			} else if (ifp->if_flags & IFF_RUNNING &&
   1667   1.3    ichiro 			    !(ifp->if_flags & IFF_PROMISC) &&
   1668   1.3    ichiro 			    sc->wi_if_flags & IFF_PROMISC) {
   1669  1.79   thorpej 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1670  1.79   thorpej 					WI_SETVAL(WI_RID_PROMISC, 0);
   1671  1.79   thorpej 			} else
   1672  1.79   thorpej 				wi_init(ifp);
   1673  1.79   thorpej 		} else if (ifp->if_flags & IFF_RUNNING)
   1674  1.79   thorpej 			wi_stop(ifp, 0);
   1675   1.3    ichiro 		sc->wi_if_flags = ifp->if_flags;
   1676   1.3    ichiro 
   1677   1.1    ichiro 		if (!(ifp->if_flags & IFF_UP)) {
   1678   1.3    ichiro 			if (sc->sc_enabled) {
   1679   1.3    ichiro 				if (sc->sc_disable)
   1680   1.3    ichiro 					(*sc->sc_disable)(sc);
   1681   1.3    ichiro 				sc->sc_enabled = 0;
   1682   1.3    ichiro 				ifp->if_flags &= ~IFF_RUNNING;
   1683   1.3    ichiro 			}
   1684   1.3    ichiro 		}
   1685   1.3    ichiro 		error = 0;
   1686   1.1    ichiro 		break;
   1687   1.1    ichiro 	case SIOCADDMULTI:
   1688   1.1    ichiro 	case SIOCDELMULTI:
   1689   1.1    ichiro 		error = (command == SIOCADDMULTI) ?
   1690   1.1    ichiro 			ether_addmulti(ifr, &sc->sc_ethercom) :
   1691   1.1    ichiro 			ether_delmulti(ifr, &sc->sc_ethercom);
   1692   1.1    ichiro 		if (error == ENETRESET) {
   1693   1.1    ichiro 			if (sc->sc_enabled != 0) {
   1694   1.3    ichiro 				/*
   1695   1.3    ichiro 				 * Multicast list has changed.  Set the
   1696   1.3    ichiro 				 * hardware filter accordingly.
   1697   1.3    ichiro 				 */
   1698   1.3    ichiro 				wi_setmulti(sc);
   1699   1.1    ichiro 			}
   1700   1.1    ichiro 			error = 0;
   1701   1.1    ichiro 		}
   1702   1.1    ichiro 		break;
   1703   1.1    ichiro 	case SIOCSIFMEDIA:
   1704   1.1    ichiro 	case SIOCGIFMEDIA:
   1705   1.1    ichiro 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
   1706   1.1    ichiro 		break;
   1707   1.1    ichiro 	case SIOCGWAVELAN:
   1708   1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1709   1.1    ichiro 		if (error)
   1710   1.1    ichiro 			break;
   1711  1.30  explorer 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1712  1.20   thorpej 			memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
   1713  1.30  explorer 			    sizeof(sc->wi_stats));
   1714   1.1    ichiro 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
   1715  1.35    ichiro 		} else if (wreq.wi_type == WI_RID_READ_APS) {
   1716  1.35    ichiro 			if (sc->wi_scanning) {
   1717  1.50       dbj 				error = EINPROGRESS;
   1718  1.35    ichiro 				break;
   1719  1.35    ichiro 			} else {
   1720  1.35    ichiro 				len = sc->wi_naps * sizeof(struct wi_apinfo);
   1721  1.35    ichiro 				len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
   1722  1.35    ichiro 				len = len / sizeof(struct wi_apinfo);
   1723  1.35    ichiro 				memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
   1724  1.35    ichiro 				memcpy((char *)&wreq.wi_val + sizeof(len),
   1725  1.35    ichiro 					(char *)&sc->wi_aps,
   1726  1.35    ichiro 					len * sizeof(struct wi_apinfo));
   1727  1.35    ichiro 			}
   1728  1.30  explorer 		} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
   1729   1.1    ichiro 			/* For non-root user, return all-zeroes keys */
   1730   1.1    ichiro 			if (suser(p->p_ucred, &p->p_acflag))
   1731  1.21   thorpej 				memset((char *)&wreq, 0,
   1732  1.30  explorer 				    sizeof(struct wi_ltv_keys));
   1733   1.1    ichiro 			else
   1734  1.20   thorpej 				memcpy((char *)&wreq, (char *)&sc->wi_keys,
   1735  1.30  explorer 				    sizeof(struct wi_ltv_keys));
   1736  1.30  explorer 		} else {
   1737   1.1    ichiro 			if (sc->sc_enabled == 0)
   1738   1.1    ichiro 				error = wi_getdef(sc, &wreq);
   1739  1.60  jdolecek 			else if (wreq.wi_len > WI_MAX_DATALEN)
   1740  1.60  jdolecek 				error = EINVAL;
   1741  1.30  explorer 			else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
   1742   1.1    ichiro 				error = EINVAL;
   1743   1.1    ichiro 		}
   1744   1.1    ichiro 		if (error == 0)
   1745   1.1    ichiro 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
   1746   1.1    ichiro 		break;
   1747   1.1    ichiro 	case SIOCSWAVELAN:
   1748   1.1    ichiro 		error = suser(p->p_ucred, &p->p_acflag);
   1749   1.1    ichiro 		if (error)
   1750   1.1    ichiro 			break;
   1751   1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1752   1.1    ichiro 		if (error)
   1753   1.1    ichiro 			break;
   1754  1.30  explorer 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1755  1.49       dbj 			if (sc->sc_enabled)
   1756  1.49       dbj 				wi_inquire(sc);
   1757   1.1    ichiro 			break;
   1758  1.30  explorer 		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
   1759   1.1    ichiro 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
   1760  1.30  explorer 			    wreq.wi_len);
   1761  1.35    ichiro 		} else if (wreq.wi_type == WI_RID_SCAN_APS) {
   1762  1.35    ichiro 			if (wreq.wi_len != 4) {
   1763  1.35    ichiro 				error = EINVAL;
   1764  1.35    ichiro 				break;
   1765  1.35    ichiro 			}
   1766  1.35    ichiro 			if (!sc->wi_scanning) {
   1767  1.71      onoe 				switch (sc->sc_firmware_type) {
   1768  1.71      onoe 				case WI_LUCENT:
   1769  1.71      onoe 					break;
   1770  1.71      onoe 				case WI_INTERSIL:
   1771  1.35    ichiro 					wreq.wi_type = WI_RID_SCAN_REQ;
   1772  1.35    ichiro 					error = wi_write_record(sc,
   1773  1.35    ichiro 					    (struct wi_ltv_gen *)&wreq);
   1774  1.71      onoe 					break;
   1775  1.71      onoe 				case WI_SYMBOL:
   1776  1.71      onoe 					/*
   1777  1.71      onoe 					 * XXX only supported on 3.x ?
   1778  1.71      onoe 					 */
   1779  1.71      onoe 					wreq.wi_type = WI_RID_BCAST_SCAN_REQ;
   1780  1.71      onoe 					wreq.wi_val[0] =
   1781  1.71      onoe 					    BSCAN_BCAST | BSCAN_ONETIME;
   1782  1.71      onoe 					wreq.wi_len = 2;
   1783  1.71      onoe 					error = wi_write_record(sc,
   1784  1.71      onoe 					    (struct wi_ltv_gen *)&wreq);
   1785  1.71      onoe 					break;
   1786  1.35    ichiro 				}
   1787  1.35    ichiro 				if (!error) {
   1788  1.35    ichiro 					sc->wi_scanning = 1;
   1789  1.35    ichiro 					callout_reset(&sc->wi_scan_sh, hz * 1,
   1790  1.35    ichiro 						wi_wait_scan, sc);
   1791  1.35    ichiro 				}
   1792  1.35    ichiro 			}
   1793  1.30  explorer 		} else {
   1794  1.77   thorpej 			/*
   1795  1.77   thorpej 			 * Filter stuff out based on what the
   1796  1.77   thorpej 			 * card can do.
   1797  1.77   thorpej 			 */
   1798  1.77   thorpej 			if ((wreq.wi_type == WI_RID_ROAMING_MODE &&
   1799  1.77   thorpej 			     (sc->wi_flags & WI_FLAGS_HAS_ROAMING) == 0) ||
   1800  1.77   thorpej 			    (wreq.wi_type == WI_RID_CREATE_IBSS &&
   1801  1.77   thorpej 			     (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0) ||
   1802  1.77   thorpej 			    (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
   1803  1.77   thorpej 			     (sc->wi_flags & WI_FLAGS_HAS_MOR) == 0))
   1804  1.77   thorpej 				break;
   1805  1.77   thorpej 
   1806  1.60  jdolecek 			if (wreq.wi_len > WI_MAX_DATALEN)
   1807  1.60  jdolecek 				error = EINVAL;
   1808  1.60  jdolecek 			else if (sc->sc_enabled != 0)
   1809   1.1    ichiro 				error = wi_write_record(sc,
   1810   1.1    ichiro 				    (struct wi_ltv_gen *)&wreq);
   1811   1.1    ichiro 			if (error == 0)
   1812   1.1    ichiro 				error = wi_setdef(sc, &wreq);
   1813   1.1    ichiro 			if (error == 0 && sc->sc_enabled != 0)
   1814   1.1    ichiro 				/* Reinitialize WaveLAN. */
   1815   1.1    ichiro 				wi_init(ifp);
   1816  1.25  explorer 		}
   1817  1.25  explorer 		break;
   1818   1.1    ichiro 	case SIOCG80211NWID:
   1819   1.1    ichiro 		if (sc->sc_enabled == 0) {
   1820   1.1    ichiro 			/* Return the desired ID */
   1821   1.1    ichiro 			error = copyout(&sc->wi_netid, ifr->ifr_data,
   1822   1.1    ichiro 			    sizeof(sc->wi_netid));
   1823   1.1    ichiro 		} else {
   1824   1.1    ichiro 			wreq.wi_type = WI_RID_CURRENT_SSID;
   1825   1.1    ichiro 			wreq.wi_len = WI_MAX_DATALEN;
   1826   1.1    ichiro 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
   1827  1.11    tsubai 			    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
   1828   1.1    ichiro 				error = EINVAL;
   1829   1.1    ichiro 			else {
   1830   1.1    ichiro 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
   1831  1.11    tsubai 				    le16toh(wreq.wi_val[0]));
   1832   1.1    ichiro 				error = copyout(&nwid, ifr->ifr_data,
   1833   1.1    ichiro 				    sizeof(nwid));
   1834   1.1    ichiro 			}
   1835   1.1    ichiro 		}
   1836   1.1    ichiro 		break;
   1837   1.1    ichiro 	case SIOCS80211NWID:
   1838   1.1    ichiro 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
   1839   1.1    ichiro 		if (error != 0)
   1840   1.1    ichiro 			break;
   1841   1.1    ichiro 		if (nwid.i_len > IEEE80211_NWID_LEN) {
   1842   1.1    ichiro 			error = EINVAL;
   1843   1.1    ichiro 			break;
   1844   1.1    ichiro 		}
   1845   1.1    ichiro 		if (sc->wi_netid.i_len == nwid.i_len &&
   1846   1.1    ichiro 		    memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
   1847   1.1    ichiro 			break;
   1848   1.1    ichiro 		wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
   1849   1.1    ichiro 		if (sc->sc_enabled != 0)
   1850   1.1    ichiro 			/* Reinitialize WaveLAN. */
   1851   1.1    ichiro 			wi_init(ifp);
   1852   1.1    ichiro 		break;
   1853   1.1    ichiro 	case SIOCS80211NWKEY:
   1854   1.1    ichiro 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
   1855   1.1    ichiro 		break;
   1856   1.1    ichiro 	case SIOCG80211NWKEY:
   1857   1.1    ichiro 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
   1858   1.1    ichiro 		break;
   1859   1.1    ichiro 	case SIOCS80211POWER:
   1860   1.1    ichiro 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
   1861   1.1    ichiro 		break;
   1862   1.1    ichiro 	case SIOCG80211POWER:
   1863   1.1    ichiro 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
   1864   1.1    ichiro 		break;
   1865  1.79   thorpej 	case SIOCHOSTAP_ADD:
   1866  1.79   thorpej 	case SIOCHOSTAP_DEL:
   1867  1.79   thorpej 	case SIOCHOSTAP_GET:
   1868  1.79   thorpej 	case SIOCHOSTAP_GETALL:
   1869  1.79   thorpej 	case SIOCHOSTAP_GFLAGS:
   1870  1.79   thorpej 	case SIOCHOSTAP_SFLAGS:
   1871  1.79   thorpej 		/* Send all Host-AP specific ioctls to the Host-AP code. */
   1872  1.79   thorpej 		error = wihap_ioctl(sc, command, data);
   1873  1.79   thorpej 		break;
   1874   1.1    ichiro 
   1875   1.1    ichiro 	default:
   1876   1.1    ichiro 		error = EINVAL;
   1877   1.1    ichiro 		break;
   1878   1.1    ichiro 	}
   1879   1.1    ichiro 
   1880   1.1    ichiro 	splx(s);
   1881   1.1    ichiro 	return (error);
   1882   1.1    ichiro }
   1883   1.1    ichiro 
   1884   1.1    ichiro static int
   1885   1.1    ichiro wi_init(ifp)
   1886   1.1    ichiro 	struct ifnet *ifp;
   1887   1.1    ichiro {
   1888   1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   1889   1.1    ichiro 	struct wi_req wreq;
   1890   1.1    ichiro 	struct wi_ltv_macaddr mac;
   1891  1.56      onoe 	int error, id = 0, wasenabled;
   1892   1.1    ichiro 
   1893  1.56      onoe 	wasenabled = sc->sc_enabled;
   1894   1.1    ichiro 	if (!sc->sc_enabled) {
   1895  1.11    tsubai 		if ((error = (*sc->sc_enable)(sc)) != 0)
   1896   1.1    ichiro 			goto out;
   1897   1.1    ichiro 		sc->sc_enabled = 1;
   1898   1.1    ichiro 	}
   1899   1.1    ichiro 
   1900   1.1    ichiro 	wi_stop(ifp, 0);
   1901  1.56      onoe 	/* Symbol firmware cannot be initialized more than once */
   1902  1.56      onoe 	if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
   1903  1.56      onoe 		wi_reset(sc);
   1904   1.1    ichiro 
   1905   1.1    ichiro 	/* Program max data length. */
   1906   1.1    ichiro 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
   1907   1.1    ichiro 
   1908   1.1    ichiro 	/* Enable/disable IBSS creation. */
   1909  1.77   thorpej 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
   1910   1.1    ichiro 
   1911   1.1    ichiro 	/* Set the port type. */
   1912   1.1    ichiro 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
   1913   1.1    ichiro 
   1914   1.1    ichiro 	/* Program the RTS/CTS threshold. */
   1915   1.1    ichiro 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
   1916   1.1    ichiro 
   1917   1.1    ichiro 	/* Program the TX rate */
   1918   1.1    ichiro 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
   1919   1.1    ichiro 
   1920   1.1    ichiro 	/* Access point density */
   1921   1.1    ichiro 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
   1922   1.1    ichiro 
   1923   1.1    ichiro 	/* Power Management Enabled */
   1924   1.1    ichiro 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
   1925   1.1    ichiro 
   1926   1.1    ichiro 	/* Power Managment Max Sleep */
   1927   1.1    ichiro 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
   1928   1.1    ichiro 
   1929   1.4    ichiro 	/* Roaming type */
   1930  1.77   thorpej 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
   1931  1.77   thorpej 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
   1932   1.1    ichiro 
   1933   1.1    ichiro 	/* Specify the network name */
   1934   1.1    ichiro 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
   1935   1.1    ichiro 
   1936  1.77   thorpej 	/* Specify the IBSS name */
   1937  1.77   thorpej 	if (sc->wi_netid.i_len != 0 &&
   1938  1.79   thorpej 	    (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
   1939  1.79   thorpej 	     (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
   1940  1.77   thorpej 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
   1941  1.77   thorpej 	else
   1942  1.77   thorpej 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
   1943  1.77   thorpej 
   1944   1.1    ichiro 	/* Specify the frequency to use */
   1945   1.1    ichiro 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
   1946   1.1    ichiro 
   1947   1.1    ichiro 	/* Program the nodename. */
   1948   1.1    ichiro 	wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
   1949   1.1    ichiro 
   1950   1.1    ichiro 	/* Set our MAC address. */
   1951   1.1    ichiro 	mac.wi_len = 4;
   1952   1.1    ichiro 	mac.wi_type = WI_RID_MAC_NODE;
   1953   1.1    ichiro 	memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
   1954   1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
   1955   1.1    ichiro 
   1956  1.79   thorpej 	/*
   1957  1.79   thorpej 	 * Initialize promisc mode.
   1958  1.79   thorpej 	 *	Being in the Host-AP mode causes a great
   1959  1.79   thorpej 	 *	deal of pain if primisc mode is set.
   1960  1.79   thorpej 	 *	Therefore we avoid confusing the firmware
   1961  1.79   thorpej 	 *	and always reset promisc mode in Host-AP
   1962  1.79   thorpej 	 *	mode.  Host-AP sees all the packets anyway.
   1963  1.79   thorpej 	 */
   1964  1.79   thorpej 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP &&
   1965  1.79   thorpej 	    (ifp->if_flags & IFF_PROMISC) != 0) {
   1966   1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 1);
   1967   1.4    ichiro 	} else {
   1968   1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 0);
   1969   1.4    ichiro 	}
   1970   1.4    ichiro 
   1971   1.1    ichiro 	/* Configure WEP. */
   1972  1.77   thorpej 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
   1973   1.1    ichiro 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
   1974   1.1    ichiro 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
   1975   1.1    ichiro 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
   1976   1.1    ichiro 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   1977   1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
   1978  1.56      onoe 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
   1979   1.4    ichiro 			/*
   1980  1.14    ichiro 			 * ONLY HWB3163 EVAL-CARD Firmware version
   1981  1.54     itohy 			 * less than 0.8 variant2
   1982  1.14    ichiro 			 *
   1983   1.5    ichiro 			 *   If promiscuous mode disable, Prism2 chip
   1984   1.5    ichiro 			 *  does not work with WEP .
   1985   1.4    ichiro 			 * It is under investigation for details.
   1986   1.4    ichiro 			 * (ichiro (at) netbsd.org)
   1987   1.4    ichiro 			 */
   1988  1.56      onoe 			if (sc->sc_firmware_type == WI_INTERSIL &&
   1989  1.58    ichiro 			    sc->sc_sta_firmware_ver < 802 ) {
   1990  1.54     itohy 				/* firm ver < 0.8 variant 2 */
   1991   1.6    ichiro 				WI_SETVAL(WI_RID_PROMISC, 1);
   1992   1.6    ichiro 			}
   1993  1.79   thorpej 			WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
   1994   1.4    ichiro 		}
   1995   1.1    ichiro 	}
   1996   1.1    ichiro 
   1997   1.1    ichiro 	/* Set multicast filter. */
   1998   1.1    ichiro 	wi_setmulti(sc);
   1999   1.1    ichiro 
   2000   1.1    ichiro 	/* Enable desired port */
   2001   1.1    ichiro 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
   2002   1.1    ichiro 
   2003  1.35    ichiro 	/*  scanning variable is modal, therefore reinit to OFF, in case it was on. */
   2004  1.35    ichiro 	sc->wi_scanning=0;
   2005  1.35    ichiro 	sc->wi_naps=0;
   2006  1.35    ichiro 
   2007   1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   2008   1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2009   1.1    ichiro 		printf("%s: tx buffer allocation failed\n",
   2010   1.1    ichiro 		    sc->sc_dev.dv_xname);
   2011   1.1    ichiro 		goto out;
   2012   1.1    ichiro 	}
   2013   1.1    ichiro 	sc->wi_tx_data_id = id;
   2014   1.1    ichiro 
   2015   1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   2016   1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2017   1.1    ichiro 		printf("%s: mgmt. buffer allocation failed\n",
   2018   1.1    ichiro 		    sc->sc_dev.dv_xname);
   2019   1.1    ichiro 		goto out;
   2020   1.1    ichiro 	}
   2021   1.1    ichiro 	sc->wi_tx_mgmt_id = id;
   2022   1.1    ichiro 
   2023   1.1    ichiro 	/* Enable interrupts */
   2024   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
   2025   1.1    ichiro 
   2026  1.79   thorpej 	wihap_init(sc);
   2027  1.79   thorpej 
   2028   1.1    ichiro 	ifp->if_flags |= IFF_RUNNING;
   2029   1.1    ichiro 	ifp->if_flags &= ~IFF_OACTIVE;
   2030   1.1    ichiro 
   2031  1.30  explorer 	callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
   2032   1.1    ichiro 
   2033   1.1    ichiro  out:
   2034   1.1    ichiro 	if (error) {
   2035   1.1    ichiro 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   2036   1.1    ichiro 		ifp->if_timer = 0;
   2037   1.1    ichiro 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   2038   1.1    ichiro 	}
   2039   1.1    ichiro 	return (error);
   2040   1.1    ichiro }
   2041   1.1    ichiro 
   2042  1.80   thorpej static const u_int32_t crc32_tab[] = {
   2043  1.80   thorpej 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
   2044  1.80   thorpej 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
   2045  1.80   thorpej 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
   2046  1.80   thorpej 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
   2047  1.80   thorpej 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
   2048  1.80   thorpej 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
   2049  1.80   thorpej 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
   2050  1.80   thorpej 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
   2051  1.80   thorpej 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
   2052  1.80   thorpej 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
   2053  1.80   thorpej 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
   2054  1.80   thorpej 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
   2055  1.80   thorpej 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
   2056  1.80   thorpej 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
   2057  1.80   thorpej 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
   2058  1.80   thorpej 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
   2059  1.80   thorpej 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
   2060  1.80   thorpej 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
   2061  1.80   thorpej 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
   2062  1.80   thorpej 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
   2063  1.80   thorpej 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
   2064  1.80   thorpej 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
   2065  1.80   thorpej 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
   2066  1.80   thorpej 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
   2067  1.80   thorpej 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
   2068  1.80   thorpej 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
   2069  1.80   thorpej 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
   2070  1.80   thorpej 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
   2071  1.80   thorpej 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
   2072  1.80   thorpej 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
   2073  1.80   thorpej 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
   2074  1.80   thorpej 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
   2075  1.80   thorpej 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
   2076  1.80   thorpej 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
   2077  1.80   thorpej 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
   2078  1.80   thorpej 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
   2079  1.80   thorpej 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
   2080  1.80   thorpej 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
   2081  1.80   thorpej 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
   2082  1.80   thorpej 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
   2083  1.80   thorpej 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
   2084  1.80   thorpej 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
   2085  1.80   thorpej 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
   2086  1.80   thorpej 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
   2087  1.80   thorpej 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
   2088  1.80   thorpej 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
   2089  1.80   thorpej 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
   2090  1.80   thorpej 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
   2091  1.80   thorpej 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
   2092  1.80   thorpej 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
   2093  1.80   thorpej 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
   2094  1.80   thorpej 	0x2d02ef8dL
   2095  1.80   thorpej };
   2096  1.80   thorpej 
   2097  1.80   thorpej #define RC4STATE 256
   2098  1.80   thorpej #define RC4KEYLEN 16
   2099  1.80   thorpej #define RC4SWAP(x,y) \
   2100  1.80   thorpej     do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
   2101  1.80   thorpej 
   2102  1.11    tsubai static void
   2103  1.79   thorpej wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
   2104  1.79   thorpej {
   2105  1.80   thorpej 	u_int32_t i, crc, klen;
   2106  1.80   thorpej 	u_int8_t state[RC4STATE], key[RC4KEYLEN];
   2107  1.80   thorpej 	u_int8_t x, y, *dat;
   2108  1.79   thorpej 
   2109  1.80   thorpej 	if (!sc->wi_icv_flag) {
   2110  1.79   thorpej 		sc->wi_icv = arc4random();
   2111  1.79   thorpej 		sc->wi_icv_flag++;
   2112  1.80   thorpej 	} else
   2113  1.80   thorpej 		sc->wi_icv++;
   2114  1.80   thorpej 	/*
   2115  1.80   thorpej 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
   2116  1.80   thorpej 	 * (B, 255, N) with 3 <= B < 8
   2117  1.80   thorpej 	 */
   2118  1.80   thorpej 	if (sc->wi_icv >= 0x03ff00 &&
   2119  1.80   thorpej             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
   2120  1.80   thorpej                 sc->wi_icv += 0x000100;
   2121  1.80   thorpej 
   2122  1.80   thorpej 	/* prepend 24bit IV to tx key, byte order does not matter */
   2123  1.80   thorpej 	key[0] = sc->wi_icv >> 16;
   2124  1.80   thorpej 	key[1] = sc->wi_icv >> 8;
   2125  1.80   thorpej 	key[2] = sc->wi_icv;
   2126  1.80   thorpej 
   2127  1.80   thorpej 	klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen +
   2128  1.80   thorpej 	    IEEE80211_WEP_IVLEN;
   2129  1.80   thorpej 	klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
   2130  1.80   thorpej 	bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
   2131  1.80   thorpej 	    (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
   2132  1.80   thorpej 
   2133  1.80   thorpej 	/* rc4 keysetup */
   2134  1.80   thorpej 	x = y = 0;
   2135  1.80   thorpej 	for (i = 0; i < RC4STATE; i++)
   2136  1.80   thorpej 		state[i] = i;
   2137  1.80   thorpej 	for (i = 0; i < RC4STATE; i++) {
   2138  1.80   thorpej 		y = (key[x] + state[i] + y) % RC4STATE;
   2139  1.80   thorpej 		RC4SWAP(i, y);
   2140  1.80   thorpej 		x = (x + 1) % klen;
   2141  1.80   thorpej 	}
   2142  1.80   thorpej 
   2143  1.80   thorpej 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
   2144  1.80   thorpej 	dat = buf;
   2145  1.80   thorpej 	dat[0] = key[0];
   2146  1.80   thorpej 	dat[1] = key[1];
   2147  1.80   thorpej 	dat[2] = key[2];
   2148  1.80   thorpej 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
   2149  1.80   thorpej 	dat += 4;
   2150  1.80   thorpej 
   2151  1.80   thorpej 	/* compute rc4 over data, crc32 over data */
   2152  1.80   thorpej 	crc = ~0;
   2153  1.80   thorpej 	x = y = 0;
   2154  1.80   thorpej 	for (i = 0; i < len; i++) {
   2155  1.80   thorpej 		x = (x + 1) % RC4STATE;
   2156  1.80   thorpej 		y = (state[x] + y) % RC4STATE;
   2157  1.80   thorpej 		RC4SWAP(x, y);
   2158  1.80   thorpej 		crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
   2159  1.80   thorpej 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2160  1.80   thorpej 	}
   2161  1.80   thorpej 	crc = ~crc;
   2162  1.80   thorpej 	dat += len;
   2163  1.80   thorpej 
   2164  1.80   thorpej 	/* append little-endian crc32 and encrypt */
   2165  1.80   thorpej 	dat[0] = crc;
   2166  1.80   thorpej 	dat[1] = crc >> 8;
   2167  1.80   thorpej 	dat[2] = crc >> 16;
   2168  1.80   thorpej 	dat[3] = crc >> 24;
   2169  1.80   thorpej 	for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
   2170  1.80   thorpej 		x = (x + 1) % RC4STATE;
   2171  1.80   thorpej 		y = (state[x] + y) % RC4STATE;
   2172  1.80   thorpej 		RC4SWAP(x, y);
   2173  1.80   thorpej 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2174  1.79   thorpej 	}
   2175  1.79   thorpej }
   2176  1.79   thorpej 
   2177  1.79   thorpej static void
   2178   1.1    ichiro wi_start(ifp)
   2179   1.1    ichiro 	struct ifnet		*ifp;
   2180   1.1    ichiro {
   2181   1.1    ichiro 	struct wi_softc		*sc;
   2182   1.1    ichiro 	struct mbuf		*m0;
   2183   1.1    ichiro 	struct wi_frame		tx_frame;
   2184   1.1    ichiro 	struct ether_header	*eh;
   2185   1.1    ichiro 	int			id;
   2186   1.1    ichiro 
   2187   1.1    ichiro 	sc = ifp->if_softc;
   2188   1.1    ichiro 
   2189   1.1    ichiro 	if (ifp->if_flags & IFF_OACTIVE)
   2190   1.1    ichiro 		return;
   2191   1.1    ichiro 
   2192  1.79   thorpej  nextpkt:
   2193   1.1    ichiro 	IFQ_DEQUEUE(&ifp->if_snd, m0);
   2194   1.1    ichiro 	if (m0 == NULL)
   2195   1.1    ichiro 		return;
   2196   1.1    ichiro 
   2197  1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2198  1.79   thorpej 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
   2199   1.1    ichiro 	id = sc->wi_tx_data_id;
   2200   1.1    ichiro 	eh = mtod(m0, struct ether_header *);
   2201   1.1    ichiro 
   2202  1.79   thorpej 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2203  1.79   thorpej 		if (wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
   2204  1.79   thorpej 				   &tx_frame.wi_tx_rate) == 0 &&
   2205  1.79   thorpej 		    (ifp->if_flags & IFF_PROMISC) == 0) {
   2206  1.79   thorpej 			if (ifp->if_flags & IFF_DEBUG)
   2207  1.79   thorpej 				printf("%s: Host-AP: dropping unassoc "
   2208  1.79   thorpej 				    "dst %s\n", sc->sc_dev.dv_xname,
   2209  1.79   thorpej 				    ether_sprintf(eh->ether_dhost));
   2210  1.79   thorpej 			m_freem(m0);
   2211  1.79   thorpej 			goto nextpkt;
   2212  1.79   thorpej 		}
   2213  1.79   thorpej 	}
   2214  1.79   thorpej 
   2215   1.1    ichiro 	/*
   2216   1.1    ichiro 	 * Use RFC1042 encoding for IP and ARP datagrams,
   2217   1.1    ichiro 	 * 802.3 for anything else.
   2218   1.1    ichiro 	 */
   2219  1.73   mycroft 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
   2220  1.73   mycroft 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
   2221  1.73   mycroft 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
   2222  1.73   mycroft 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
   2223  1.20   thorpej 		memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
   2224  1.20   thorpej 		    ETHER_ADDR_LEN);
   2225  1.79   thorpej 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2226  1.79   thorpej 			tx_frame.wi_tx_ctl |= htole16(WI_ENC_TX_MGMT);/* XXX */
   2227  1.79   thorpej 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
   2228  1.79   thorpej 			if (sc->wi_use_wep)
   2229  1.79   thorpej 				tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
   2230  1.79   thorpej 			memcpy((char *)&tx_frame.wi_addr2,
   2231  1.79   thorpej 			    (char *)LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
   2232  1.79   thorpej 			memcpy((char *)&tx_frame.wi_addr3,
   2233  1.79   thorpej 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2234  1.79   thorpej 		} else
   2235  1.79   thorpej 			memcpy((char *)&tx_frame.wi_addr2,
   2236  1.79   thorpej 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2237  1.20   thorpej 		memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
   2238  1.20   thorpej 		    ETHER_ADDR_LEN);
   2239  1.20   thorpej 		memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
   2240  1.20   thorpej 		    ETHER_ADDR_LEN);
   2241   1.1    ichiro 
   2242  1.79   thorpej 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
   2243   1.1    ichiro 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
   2244   1.1    ichiro 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
   2245   1.1    ichiro 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   2246   1.1    ichiro 		tx_frame.wi_type = eh->ether_type;
   2247   1.1    ichiro 
   2248  1.79   thorpej 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2249  1.79   thorpej 			/* Do host encryption. */
   2250  1.79   thorpej 			memcpy(&sc->wi_txbuf[4], &tx_frame.wi_dat[0], 8);
   2251  1.79   thorpej 
   2252  1.79   thorpej 			m_copydata(m0, sizeof(struct ether_header),
   2253  1.79   thorpej 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2254  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf[12]);
   2255  1.79   thorpej 
   2256  1.79   thorpej 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
   2257  1.79   thorpej 			    tx_frame.wi_dat_len);
   2258  1.79   thorpej 
   2259  1.79   thorpej 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
   2260  1.79   thorpej 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
   2261  1.79   thorpej 
   2262  1.79   thorpej 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2263  1.79   thorpej 
   2264  1.79   thorpej 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2265  1.79   thorpej 			    sizeof(struct wi_frame));
   2266  1.79   thorpej 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
   2267  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf,
   2268  1.79   thorpej 			    (m0->m_pkthdr.len -
   2269  1.79   thorpej 			     sizeof(struct ether_header)) + 18);
   2270  1.79   thorpej 		} else {
   2271  1.79   thorpej 			m_copydata(m0, sizeof(struct ether_header),
   2272  1.79   thorpej 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2273  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf);
   2274  1.79   thorpej 
   2275  1.79   thorpej 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2276  1.79   thorpej 
   2277  1.79   thorpej 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2278  1.79   thorpej 			    sizeof(struct wi_frame));
   2279  1.79   thorpej 			wi_write_data(sc, id, WI_802_11_OFFSET,
   2280  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf,
   2281  1.79   thorpej 			    (m0->m_pkthdr.len -
   2282  1.79   thorpej 			     sizeof(struct ether_header)) + 2);
   2283  1.79   thorpej 		}
   2284   1.1    ichiro 	} else {
   2285  1.11    tsubai 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
   2286   1.1    ichiro 
   2287  1.79   thorpej 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2288  1.79   thorpej 			/* Do host encryption.  (XXX - not implemented) */
   2289  1.79   thorpej 			printf("%s: host encryption not implemented "
   2290  1.79   thorpej 			    "for 802.3\n", sc->sc_dev.dv_xname);
   2291  1.79   thorpej 		} else {
   2292  1.79   thorpej 			m_copydata(m0, 0, m0->m_pkthdr.len,
   2293  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf);
   2294   1.1    ichiro 
   2295  1.79   thorpej 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2296  1.79   thorpej 			    sizeof(struct wi_frame));
   2297  1.79   thorpej 			wi_write_data(sc, id, WI_802_3_OFFSET,
   2298  1.79   thorpej 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
   2299  1.79   thorpej 		}
   2300   1.1    ichiro 	}
   2301   1.1    ichiro 
   2302   1.1    ichiro #if NBPFILTER > 0
   2303   1.1    ichiro 	/*
   2304   1.1    ichiro 	 * If there's a BPF listener, bounce a copy of
   2305   1.1    ichiro 	 * this frame to him.
   2306   1.1    ichiro 	 */
   2307   1.1    ichiro 	if (ifp->if_bpf)
   2308   1.1    ichiro 		bpf_mtap(ifp->if_bpf, m0);
   2309   1.1    ichiro #endif
   2310   1.1    ichiro 
   2311   1.1    ichiro 	m_freem(m0);
   2312   1.1    ichiro 
   2313   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
   2314   1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2315   1.1    ichiro 
   2316   1.1    ichiro 	ifp->if_flags |= IFF_OACTIVE;
   2317   1.1    ichiro 
   2318   1.1    ichiro 	/*
   2319   1.1    ichiro 	 * Set a timeout in case the chip goes out to lunch.
   2320   1.1    ichiro 	 */
   2321   1.1    ichiro 	ifp->if_timer = 5;
   2322   1.1    ichiro 
   2323   1.1    ichiro 	return;
   2324   1.1    ichiro }
   2325   1.1    ichiro 
   2326  1.79   thorpej int
   2327   1.1    ichiro wi_mgmt_xmit(sc, data, len)
   2328   1.1    ichiro 	struct wi_softc		*sc;
   2329   1.1    ichiro 	caddr_t			data;
   2330   1.1    ichiro 	int			len;
   2331   1.1    ichiro {
   2332   1.1    ichiro 	struct wi_frame		tx_frame;
   2333   1.1    ichiro 	int			id;
   2334   1.1    ichiro 	struct wi_80211_hdr	*hdr;
   2335   1.1    ichiro 	caddr_t			dptr;
   2336   1.1    ichiro 
   2337   1.1    ichiro 	hdr = (struct wi_80211_hdr *)data;
   2338   1.1    ichiro 	dptr = data + sizeof(struct wi_80211_hdr);
   2339   1.1    ichiro 
   2340  1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2341   1.1    ichiro 	id = sc->wi_tx_mgmt_id;
   2342   1.1    ichiro 
   2343  1.20   thorpej 	memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
   2344   1.1    ichiro 	   sizeof(struct wi_80211_hdr));
   2345   1.1    ichiro 
   2346  1.79   thorpej 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
   2347  1.79   thorpej 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
   2348  1.79   thorpej 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
   2349  1.79   thorpej 
   2350  1.79   thorpej 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2351   1.1    ichiro 
   2352   1.1    ichiro 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
   2353   1.1    ichiro 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
   2354   1.1    ichiro 	    (len - sizeof(struct wi_80211_hdr)) + 2);
   2355   1.1    ichiro 
   2356   1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
   2357   1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2358   1.1    ichiro 		return(EIO);
   2359   1.1    ichiro 	}
   2360   1.1    ichiro 
   2361   1.1    ichiro 	return(0);
   2362   1.1    ichiro }
   2363   1.1    ichiro 
   2364   1.1    ichiro static void
   2365   1.1    ichiro wi_stop(ifp, disable)
   2366   1.1    ichiro 	struct ifnet *ifp;
   2367   1.1    ichiro {
   2368   1.1    ichiro 	struct wi_softc	*sc = ifp->if_softc;
   2369   1.1    ichiro 
   2370  1.79   thorpej 	wihap_shutdown(sc);
   2371  1.79   thorpej 
   2372   1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   2373   1.1    ichiro 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
   2374   1.1    ichiro 
   2375  1.30  explorer 	callout_stop(&sc->wi_inquire_ch);
   2376  1.35    ichiro 	callout_stop(&sc->wi_scan_sh);
   2377   1.1    ichiro 
   2378   1.1    ichiro 	if (disable) {
   2379   1.4    ichiro 		if (sc->sc_enabled) {
   2380   1.4    ichiro 			if (sc->sc_disable)
   2381   1.4    ichiro 				(*sc->sc_disable)(sc);
   2382   1.4    ichiro 			sc->sc_enabled = 0;
   2383   1.4    ichiro 		}
   2384   1.1    ichiro 	}
   2385   1.1    ichiro 
   2386   1.1    ichiro 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
   2387   1.1    ichiro 	ifp->if_timer = 0;
   2388   1.1    ichiro }
   2389   1.1    ichiro 
   2390  1.11    tsubai static void
   2391   1.1    ichiro wi_watchdog(ifp)
   2392   1.1    ichiro 	struct ifnet		*ifp;
   2393   1.1    ichiro {
   2394   1.1    ichiro 	struct wi_softc		*sc;
   2395   1.1    ichiro 
   2396   1.1    ichiro 	sc = ifp->if_softc;
   2397   1.1    ichiro 
   2398   1.1    ichiro 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
   2399   1.1    ichiro 
   2400   1.1    ichiro 	wi_init(ifp);
   2401   1.1    ichiro 
   2402   1.1    ichiro 	ifp->if_oerrors++;
   2403   1.1    ichiro 
   2404   1.1    ichiro 	return;
   2405   1.1    ichiro }
   2406   1.1    ichiro 
   2407   1.1    ichiro void
   2408   1.1    ichiro wi_shutdown(sc)
   2409   1.1    ichiro 	struct wi_softc *sc;
   2410   1.1    ichiro {
   2411  1.11    tsubai 	int s;
   2412   1.1    ichiro 
   2413  1.11    tsubai 	s = splnet();
   2414  1.11    tsubai 	if (sc->sc_enabled) {
   2415  1.11    tsubai 		if (sc->sc_disable)
   2416  1.11    tsubai 			(*sc->sc_disable)(sc);
   2417  1.11    tsubai 		sc->sc_enabled = 0;
   2418  1.11    tsubai 	}
   2419   1.1    ichiro 	splx(s);
   2420   1.1    ichiro }
   2421   1.1    ichiro 
   2422   1.1    ichiro int
   2423   1.1    ichiro wi_activate(self, act)
   2424   1.1    ichiro 	struct device *self;
   2425   1.1    ichiro 	enum devact act;
   2426   1.1    ichiro {
   2427   1.1    ichiro 	struct wi_softc *sc = (struct wi_softc *)self;
   2428   1.1    ichiro 	int rv = 0, s;
   2429   1.1    ichiro 
   2430   1.1    ichiro 	s = splnet();
   2431   1.1    ichiro 	switch (act) {
   2432   1.1    ichiro 	case DVACT_ACTIVATE:
   2433   1.1    ichiro 		rv = EOPNOTSUPP;
   2434   1.1    ichiro 		break;
   2435   1.1    ichiro 
   2436   1.1    ichiro 	case DVACT_DEACTIVATE:
   2437   1.1    ichiro 		if_deactivate(&sc->sc_ethercom.ec_if);
   2438   1.1    ichiro 		break;
   2439   1.1    ichiro 	}
   2440   1.1    ichiro 	splx(s);
   2441   1.1    ichiro 	return (rv);
   2442   1.1    ichiro }
   2443   1.1    ichiro 
   2444   1.4    ichiro static void
   2445   1.4    ichiro wi_get_id(sc)
   2446   1.4    ichiro 	struct wi_softc *sc;
   2447   1.4    ichiro {
   2448   1.4    ichiro 	struct wi_ltv_ver       ver;
   2449  1.64    ichiro 	struct wi_card_ident	*id;
   2450   1.4    ichiro 
   2451   1.6    ichiro 	/* getting chip identity */
   2452  1.11    tsubai 	memset(&ver, 0, sizeof(ver));
   2453  1.28  christos 	ver.wi_type = WI_RID_CARD_ID;
   2454  1.11    tsubai 	ver.wi_len = 5;
   2455  1.11    tsubai 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2456   1.9    ichiro 	printf("%s: using ", sc->sc_dev.dv_xname);
   2457  1.64    ichiro 
   2458  1.67    ichiro 	sc->sc_firmware_type = WI_NOTYPE;
   2459  1.64    ichiro 	for (id = wi_card_ident; id->card_name != NULL; id++) {
   2460  1.64    ichiro 		if (le16toh(ver.wi_ver[0]) == id->card_id) {
   2461  1.64    ichiro 			printf("%s", id->card_name);
   2462  1.64    ichiro 			sc->sc_firmware_type = id->firm_type;
   2463  1.64    ichiro 			break;
   2464  1.64    ichiro 		}
   2465  1.64    ichiro 	}
   2466  1.67    ichiro 	if (sc->sc_firmware_type == WI_NOTYPE) {
   2467  1.56      onoe 		if (le16toh(ver.wi_ver[0]) & 0x8000) {
   2468  1.56      onoe 			printf("Unknown PRISM2 chip");
   2469  1.56      onoe 			sc->sc_firmware_type = WI_INTERSIL;
   2470  1.56      onoe 		} else {
   2471  1.56      onoe 			printf("Unknown Lucent chip");
   2472  1.56      onoe 			sc->sc_firmware_type = WI_LUCENT;
   2473  1.56      onoe 		}
   2474   1.4    ichiro 	}
   2475   1.6    ichiro 
   2476  1.67    ichiro 	/* get primary firmware version (Only Prism chips) */
   2477  1.68    ichiro 	if (sc->sc_firmware_type != WI_LUCENT) {
   2478  1.67    ichiro 		memset(&ver, 0, sizeof(ver));
   2479  1.67    ichiro 		ver.wi_type = WI_RID_PRI_IDENTITY;
   2480  1.67    ichiro 		ver.wi_len = 5;
   2481  1.67    ichiro 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2482  1.67    ichiro 		LE16TOH(ver.wi_ver[1]);
   2483  1.67    ichiro 		LE16TOH(ver.wi_ver[2]);
   2484  1.67    ichiro 		LE16TOH(ver.wi_ver[3]);
   2485  1.67    ichiro 		sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
   2486  1.67    ichiro 		    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2487  1.67    ichiro 	}
   2488  1.58    ichiro 
   2489  1.57    ichiro 	/* get station firmware version */
   2490  1.55       dbj 	memset(&ver, 0, sizeof(ver));
   2491  1.55       dbj 	ver.wi_type = WI_RID_STA_IDENTITY;
   2492  1.55       dbj 	ver.wi_len = 5;
   2493  1.55       dbj 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2494  1.55       dbj 	LE16TOH(ver.wi_ver[1]);
   2495  1.55       dbj 	LE16TOH(ver.wi_ver[2]);
   2496  1.55       dbj 	LE16TOH(ver.wi_ver[3]);
   2497  1.58    ichiro 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
   2498  1.56      onoe 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2499  1.56      onoe 	if (sc->sc_firmware_type == WI_INTERSIL &&
   2500  1.58    ichiro 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
   2501  1.56      onoe 		struct wi_ltv_str sver;
   2502  1.56      onoe 		char *p;
   2503  1.56      onoe 
   2504  1.56      onoe 		memset(&sver, 0, sizeof(sver));
   2505  1.56      onoe 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
   2506  1.56      onoe 		sver.wi_len = 7;
   2507  1.70      onoe 		/* value should be the format like "V2.00-11" */
   2508  1.56      onoe 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
   2509  1.70      onoe 		    *(p = (char *)sver.wi_str) >= 'A' &&
   2510  1.56      onoe 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
   2511  1.56      onoe 			sc->sc_firmware_type = WI_SYMBOL;
   2512  1.58    ichiro 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
   2513  1.56      onoe 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
   2514  1.56      onoe 			    (p[6] - '0') * 10 + (p[7] - '0');
   2515  1.56      onoe 		}
   2516  1.56      onoe 	}
   2517  1.58    ichiro 
   2518  1.69  augustss 	printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
   2519  1.58    ichiro 	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
   2520  1.58    ichiro 	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
   2521  1.58    ichiro 	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
   2522  1.58    ichiro 	    printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
   2523  1.58    ichiro 		    (sc->sc_pri_firmware_ver % 10000) / 100,
   2524  1.58    ichiro 		    sc->sc_pri_firmware_ver % 100);
   2525  1.58    ichiro 	printf("Station (%u.%u.%u)\n",
   2526  1.58    ichiro 	    sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
   2527  1.58    ichiro 	    sc->sc_sta_firmware_ver % 100);
   2528   1.6    ichiro 
   2529   1.4    ichiro 	return;
   2530   1.4    ichiro }
   2531   1.4    ichiro 
   2532   1.1    ichiro int
   2533   1.1    ichiro wi_detach(sc)
   2534   1.1    ichiro 	struct wi_softc *sc;
   2535   1.1    ichiro {
   2536   1.1    ichiro 	struct ifnet *ifp = sc->sc_ifp;
   2537   1.1    ichiro 	int s;
   2538   1.1    ichiro 
   2539   1.1    ichiro 	if (!sc->sc_attached)
   2540   1.1    ichiro 		return (0);
   2541   1.1    ichiro 
   2542   1.1    ichiro 	s = splnet();
   2543  1.30  explorer 	callout_stop(&sc->wi_inquire_ch);
   2544   1.1    ichiro 
   2545   1.1    ichiro 	/* Delete all remaining media. */
   2546   1.1    ichiro 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
   2547   1.1    ichiro 
   2548   1.1    ichiro 	ether_ifdetach(ifp);
   2549   1.1    ichiro 	if_detach(ifp);
   2550   1.1    ichiro 	if (sc->sc_enabled) {
   2551   1.1    ichiro 		if (sc->sc_disable)
   2552   1.1    ichiro 			(*sc->sc_disable)(sc);
   2553   1.1    ichiro 		sc->sc_enabled = 0;
   2554   1.1    ichiro 	}
   2555   1.1    ichiro 	splx(s);
   2556   1.1    ichiro 	return (0);
   2557   1.1    ichiro }
   2558   1.1    ichiro 
   2559   1.1    ichiro void
   2560   1.1    ichiro wi_power(sc, why)
   2561   1.1    ichiro 	struct wi_softc *sc;
   2562   1.1    ichiro 	int why;
   2563   1.1    ichiro {
   2564   1.1    ichiro 	int s;
   2565   1.1    ichiro 
   2566   1.1    ichiro 	if (!sc->sc_enabled)
   2567   1.1    ichiro 		return;
   2568   1.1    ichiro 
   2569   1.1    ichiro 	s = splnet();
   2570   1.1    ichiro 	switch (why) {
   2571   1.1    ichiro 	case PWR_SUSPEND:
   2572   1.1    ichiro 	case PWR_STANDBY:
   2573   1.1    ichiro 		wi_stop(sc->sc_ifp, 0);
   2574   1.4    ichiro 		if (sc->sc_enabled) {
   2575   1.4    ichiro 			if (sc->sc_disable)
   2576   1.4    ichiro 				(*sc->sc_disable)(sc);
   2577   1.4    ichiro 		}
   2578   1.1    ichiro 		break;
   2579   1.1    ichiro 	case PWR_RESUME:
   2580   1.1    ichiro 		sc->sc_enabled = 0;
   2581   1.1    ichiro 		wi_init(sc->sc_ifp);
   2582   1.1    ichiro 		(void)wi_intr(sc);
   2583   1.1    ichiro 		break;
   2584   1.1    ichiro 	case PWR_SOFTSUSPEND:
   2585   1.1    ichiro 	case PWR_SOFTSTANDBY:
   2586   1.1    ichiro 	case PWR_SOFTRESUME:
   2587   1.1    ichiro 		break;
   2588   1.1    ichiro 	}
   2589   1.1    ichiro 	splx(s);
   2590   1.1    ichiro }
   2591   1.1    ichiro 
   2592   1.1    ichiro static int
   2593   1.1    ichiro wi_set_ssid(ws, id, len)
   2594   1.1    ichiro 	struct ieee80211_nwid *ws;
   2595   1.1    ichiro 	u_int8_t *id;
   2596   1.1    ichiro 	int len;
   2597   1.1    ichiro {
   2598   1.1    ichiro 
   2599   1.1    ichiro 	if (len > IEEE80211_NWID_LEN)
   2600   1.1    ichiro 		return (EINVAL);
   2601   1.1    ichiro 	ws->i_len = len;
   2602   1.1    ichiro 	memcpy(ws->i_nwid, id, len);
   2603   1.1    ichiro 	return (0);
   2604   1.1    ichiro }
   2605   1.1    ichiro 
   2606   1.1    ichiro static void
   2607   1.1    ichiro wi_request_fill_ssid(wreq, ws)
   2608   1.1    ichiro 	struct wi_req *wreq;
   2609   1.1    ichiro 	struct ieee80211_nwid *ws;
   2610   1.1    ichiro {
   2611  1.11    tsubai 	int len = ws->i_len;
   2612   1.1    ichiro 
   2613   1.1    ichiro 	memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
   2614  1.11    tsubai 	wreq->wi_val[0] = htole16(len);
   2615  1.11    tsubai 	wreq->wi_len = roundup(len, 2) / 2 + 2;
   2616  1.11    tsubai 	memcpy(&wreq->wi_val[1], ws->i_nwid, len);
   2617   1.1    ichiro }
   2618   1.1    ichiro 
   2619   1.1    ichiro static int
   2620   1.1    ichiro wi_write_ssid(sc, type, wreq, ws)
   2621   1.1    ichiro 	struct wi_softc *sc;
   2622   1.1    ichiro 	int type;
   2623   1.1    ichiro 	struct wi_req *wreq;
   2624   1.1    ichiro 	struct ieee80211_nwid *ws;
   2625   1.1    ichiro {
   2626   1.1    ichiro 
   2627   1.1    ichiro 	wreq->wi_type = type;
   2628   1.1    ichiro 	wi_request_fill_ssid(wreq, ws);
   2629   1.1    ichiro 	return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
   2630   1.1    ichiro }
   2631   1.1    ichiro 
   2632   1.1    ichiro static int
   2633   1.1    ichiro wi_sync_media(sc, ptype, txrate)
   2634   1.1    ichiro 	struct wi_softc *sc;
   2635   1.1    ichiro 	int ptype;
   2636   1.1    ichiro 	int txrate;
   2637   1.1    ichiro {
   2638   1.1    ichiro 	int media = sc->sc_media.ifm_cur->ifm_media;
   2639   1.1    ichiro 	int options = IFM_OPTIONS(media);
   2640   1.1    ichiro 	int subtype;
   2641   1.1    ichiro 
   2642   1.1    ichiro 	switch (txrate) {
   2643   1.1    ichiro 	case 1:
   2644   1.1    ichiro 		subtype = IFM_IEEE80211_DS1;
   2645   1.1    ichiro 		break;
   2646   1.1    ichiro 	case 2:
   2647   1.1    ichiro 		subtype = IFM_IEEE80211_DS2;
   2648   1.1    ichiro 		break;
   2649   1.1    ichiro 	case 3:
   2650   1.1    ichiro 		subtype = IFM_AUTO;
   2651   1.1    ichiro 		break;
   2652  1.34    ichiro 	case 5:
   2653  1.33    ichiro 		subtype = IFM_IEEE80211_DS5;
   2654  1.33    ichiro 		break;
   2655   1.1    ichiro 	case 11:
   2656   1.1    ichiro 		subtype = IFM_IEEE80211_DS11;
   2657   1.1    ichiro 		break;
   2658   1.1    ichiro 	default:
   2659   1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2660   1.1    ichiro 		break;
   2661   1.1    ichiro 	}
   2662  1.77   thorpej 
   2663  1.77   thorpej 	options &= ~IFM_OMASK;
   2664   1.1    ichiro 	switch (ptype) {
   2665  1.77   thorpej 	case WI_PORTTYPE_BSS:
   2666  1.77   thorpej 		/* default port type */
   2667  1.77   thorpej 		break;
   2668   1.1    ichiro 	case WI_PORTTYPE_ADHOC:
   2669   1.1    ichiro 		options |= IFM_IEEE80211_ADHOC;
   2670   1.1    ichiro 		break;
   2671  1.77   thorpej 	case WI_PORTTYPE_IBSS:
   2672  1.77   thorpej 		if (sc->wi_create_ibss)
   2673  1.77   thorpej 			options |= IFM_IEEE80211_IBSSMASTER;
   2674  1.77   thorpej 		else
   2675  1.77   thorpej 			options |= IFM_IEEE80211_IBSS;
   2676   1.1    ichiro 		break;
   2677   1.1    ichiro 	default:
   2678   1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2679   1.1    ichiro 		break;
   2680   1.1    ichiro 	}
   2681   1.1    ichiro 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
   2682   1.1    ichiro 	    IFM_INST(media));
   2683   1.1    ichiro 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
   2684   1.1    ichiro 		return (EINVAL);
   2685   1.1    ichiro 	ifmedia_set(&sc->sc_media, media);
   2686   1.1    ichiro 	sc->wi_ptype = ptype;
   2687   1.1    ichiro 	sc->wi_tx_rate = txrate;
   2688   1.1    ichiro 	return (0);
   2689   1.1    ichiro }
   2690   1.1    ichiro 
   2691   1.1    ichiro static int
   2692   1.1    ichiro wi_media_change(ifp)
   2693   1.1    ichiro 	struct ifnet *ifp;
   2694   1.1    ichiro {
   2695   1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2696   1.1    ichiro 	int otype = sc->wi_ptype;
   2697   1.1    ichiro 	int orate = sc->wi_tx_rate;
   2698  1.77   thorpej 	int ocreate_ibss = sc->wi_create_ibss;
   2699   1.1    ichiro 
   2700  1.77   thorpej 	sc->wi_create_ibss = 0;
   2701  1.77   thorpej 
   2702  1.77   thorpej 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
   2703  1.77   thorpej 	case 0:
   2704  1.77   thorpej 		sc->wi_ptype = WI_PORTTYPE_BSS;
   2705  1.77   thorpej 		break;
   2706  1.77   thorpej 	case IFM_IEEE80211_ADHOC:
   2707   1.1    ichiro 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
   2708  1.79   thorpej 		break;
   2709  1.79   thorpej 	case IFM_IEEE80211_HOSTAP:
   2710  1.79   thorpej 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
   2711  1.77   thorpej 		break;
   2712  1.77   thorpej 	case IFM_IEEE80211_IBSSMASTER:
   2713  1.77   thorpej 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
   2714  1.77   thorpej 		if ((sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0)
   2715  1.77   thorpej 			return (EINVAL);
   2716  1.77   thorpej 		sc->wi_create_ibss = 1;
   2717  1.77   thorpej 		/* FALLTHROUGH */
   2718  1.77   thorpej 	case IFM_IEEE80211_IBSS:
   2719  1.77   thorpej 		sc->wi_ptype = WI_PORTTYPE_IBSS;
   2720  1.77   thorpej 		break;
   2721  1.77   thorpej 	default:
   2722  1.77   thorpej 		/* Invalid combination. */
   2723  1.77   thorpej 		sc->wi_create_ibss = ocreate_ibss;
   2724  1.77   thorpej 		return (EINVAL);
   2725  1.77   thorpej 	}
   2726   1.1    ichiro 
   2727   1.1    ichiro 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
   2728   1.1    ichiro 	case IFM_IEEE80211_DS1:
   2729   1.1    ichiro 		sc->wi_tx_rate = 1;
   2730   1.1    ichiro 		break;
   2731   1.1    ichiro 	case IFM_IEEE80211_DS2:
   2732   1.1    ichiro 		sc->wi_tx_rate = 2;
   2733   1.1    ichiro 		break;
   2734   1.1    ichiro 	case IFM_AUTO:
   2735   1.1    ichiro 		sc->wi_tx_rate = 3;
   2736  1.33    ichiro 		break;
   2737  1.33    ichiro 	case IFM_IEEE80211_DS5:
   2738  1.34    ichiro 		sc->wi_tx_rate = 5;
   2739   1.1    ichiro 		break;
   2740   1.1    ichiro 	case IFM_IEEE80211_DS11:
   2741   1.1    ichiro 		sc->wi_tx_rate = 11;
   2742   1.1    ichiro 		break;
   2743   1.1    ichiro 	}
   2744   1.1    ichiro 
   2745   1.1    ichiro 	if (sc->sc_enabled != 0) {
   2746   1.1    ichiro 		if (otype != sc->wi_ptype ||
   2747  1.77   thorpej 		    orate != sc->wi_tx_rate ||
   2748  1.77   thorpej 		    ocreate_ibss != sc->wi_create_ibss)
   2749   1.1    ichiro 			wi_init(ifp);
   2750   1.1    ichiro 	}
   2751   1.1    ichiro 
   2752   1.1    ichiro 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
   2753   1.1    ichiro 
   2754   1.1    ichiro 	return (0);
   2755   1.1    ichiro }
   2756   1.1    ichiro 
   2757   1.1    ichiro static void
   2758   1.1    ichiro wi_media_status(ifp, imr)
   2759   1.1    ichiro 	struct ifnet *ifp;
   2760   1.1    ichiro 	struct ifmediareq *imr;
   2761   1.1    ichiro {
   2762   1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2763   1.1    ichiro 
   2764   1.1    ichiro 	if (sc->sc_enabled == 0) {
   2765   1.1    ichiro 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
   2766   1.1    ichiro 		imr->ifm_status = 0;
   2767   1.1    ichiro 		return;
   2768   1.1    ichiro 	}
   2769   1.1    ichiro 
   2770   1.1    ichiro 	imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
   2771   1.1    ichiro 	imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
   2772   1.1    ichiro }
   2773   1.1    ichiro 
   2774   1.1    ichiro static int
   2775   1.1    ichiro wi_set_nwkey(sc, nwkey)
   2776   1.1    ichiro 	struct wi_softc *sc;
   2777   1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2778   1.1    ichiro {
   2779  1.22  jdolecek 	int i, error;
   2780  1.22  jdolecek 	size_t len;
   2781   1.1    ichiro 	struct wi_req wreq;
   2782   1.1    ichiro 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
   2783   1.1    ichiro 
   2784  1.77   thorpej 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2785   1.1    ichiro 		return ENODEV;
   2786   1.1    ichiro 	if (nwkey->i_defkid <= 0 ||
   2787   1.1    ichiro 	    nwkey->i_defkid > IEEE80211_WEP_NKID)
   2788   1.1    ichiro 		return EINVAL;
   2789   1.1    ichiro 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
   2790   1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2791   1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2792   1.1    ichiro 			continue;
   2793   1.1    ichiro 		len = nwkey->i_key[i].i_keylen;
   2794   1.1    ichiro 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
   2795   1.1    ichiro 			return EINVAL;
   2796   1.1    ichiro 		error = copyin(nwkey->i_key[i].i_keydat,
   2797   1.1    ichiro 		    wk->wi_keys[i].wi_keydat, len);
   2798   1.1    ichiro 		if (error)
   2799   1.1    ichiro 			return error;
   2800  1.11    tsubai 		wk->wi_keys[i].wi_keylen = htole16(len);
   2801   1.1    ichiro 	}
   2802   1.1    ichiro 
   2803   1.1    ichiro 	wk->wi_len = (sizeof(*wk) / 2) + 1;
   2804   1.1    ichiro 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   2805   1.1    ichiro 	if (sc->sc_enabled != 0) {
   2806   1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2807   1.1    ichiro 		if (error)
   2808   1.1    ichiro 			return error;
   2809   1.1    ichiro 	}
   2810   1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2811   1.1    ichiro 	if (error)
   2812   1.1    ichiro 		return error;
   2813   1.1    ichiro 
   2814   1.1    ichiro 	wreq.wi_len = 2;
   2815   1.1    ichiro 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
   2816  1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
   2817   1.1    ichiro 	if (sc->sc_enabled != 0) {
   2818   1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2819   1.1    ichiro 		if (error)
   2820   1.1    ichiro 			return error;
   2821   1.1    ichiro 	}
   2822   1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2823   1.1    ichiro 	if (error)
   2824   1.1    ichiro 		return error;
   2825   1.1    ichiro 
   2826   1.1    ichiro 	wreq.wi_type = WI_RID_ENCRYPTION;
   2827  1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
   2828   1.1    ichiro 	if (sc->sc_enabled != 0) {
   2829   1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2830   1.1    ichiro 		if (error)
   2831   1.1    ichiro 			return error;
   2832   1.1    ichiro 	}
   2833   1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2834   1.1    ichiro 	if (error)
   2835   1.1    ichiro 		return error;
   2836   1.1    ichiro 
   2837   1.1    ichiro 	if (sc->sc_enabled != 0)
   2838   1.1    ichiro 		wi_init(&sc->sc_ethercom.ec_if);
   2839   1.1    ichiro 	return 0;
   2840   1.1    ichiro }
   2841   1.1    ichiro 
   2842   1.1    ichiro static int
   2843   1.1    ichiro wi_get_nwkey(sc, nwkey)
   2844   1.1    ichiro 	struct wi_softc *sc;
   2845   1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2846   1.1    ichiro {
   2847   1.1    ichiro 	int i, len, error;
   2848   1.1    ichiro 	struct wi_ltv_keys *wk = &sc->wi_keys;
   2849   1.1    ichiro 
   2850  1.77   thorpej 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2851   1.1    ichiro 		return ENODEV;
   2852   1.1    ichiro 	nwkey->i_wepon = sc->wi_use_wep;
   2853   1.1    ichiro 	nwkey->i_defkid = sc->wi_tx_key + 1;
   2854   1.1    ichiro 
   2855   1.1    ichiro 	/* do not show any keys to non-root user */
   2856   1.1    ichiro 	error = suser(curproc->p_ucred, &curproc->p_acflag);
   2857   1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2858   1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2859   1.1    ichiro 			continue;
   2860   1.1    ichiro 		/* error holds results of suser() for the first time */
   2861   1.1    ichiro 		if (error)
   2862   1.1    ichiro 			return error;
   2863  1.11    tsubai 		len = le16toh(wk->wi_keys[i].wi_keylen);
   2864   1.1    ichiro 		if (nwkey->i_key[i].i_keylen < len)
   2865   1.1    ichiro 			return ENOSPC;
   2866   1.1    ichiro 		nwkey->i_key[i].i_keylen = len;
   2867   1.1    ichiro 		error = copyout(wk->wi_keys[i].wi_keydat,
   2868   1.1    ichiro 		    nwkey->i_key[i].i_keydat, len);
   2869   1.1    ichiro 		if (error)
   2870   1.1    ichiro 			return error;
   2871   1.1    ichiro 	}
   2872   1.1    ichiro 	return 0;
   2873   1.1    ichiro }
   2874   1.1    ichiro 
   2875   1.1    ichiro static int
   2876   1.1    ichiro wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2877   1.1    ichiro {
   2878   1.1    ichiro 
   2879   1.1    ichiro 	sc->wi_pm_enabled = power->i_enabled;
   2880   1.1    ichiro 	sc->wi_max_sleep = power->i_maxsleep;
   2881   1.1    ichiro 
   2882   1.1    ichiro 	if (sc->sc_enabled)
   2883   1.1    ichiro 		return (wi_init(&sc->sc_ethercom.ec_if));
   2884   1.1    ichiro 
   2885   1.1    ichiro 	return (0);
   2886   1.1    ichiro }
   2887   1.1    ichiro 
   2888   1.1    ichiro static int
   2889   1.1    ichiro wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2890   1.1    ichiro {
   2891   1.1    ichiro 
   2892   1.1    ichiro 	power->i_enabled = sc->wi_pm_enabled;
   2893   1.1    ichiro 	power->i_maxsleep = sc->wi_max_sleep;
   2894   1.1    ichiro 
   2895   1.1    ichiro 	return (0);
   2896   1.1    ichiro }
   2897