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