Home | History | Annotate | Line # | Download | only in ic
wi.c revision 1.159.2.1
      1  1.159.2.1       jdc /*	$NetBSD: wi.c,v 1.159.2.1 2004/06/07 06:37:28 jdc Exp $	*/
      2        1.1    ichiro 
      3        1.1    ichiro /*
      4        1.1    ichiro  * Copyright (c) 1997, 1998, 1999
      5        1.1    ichiro  *	Bill Paul <wpaul (at) ctr.columbia.edu>.  All rights reserved.
      6        1.1    ichiro  *
      7        1.1    ichiro  * Redistribution and use in source and binary forms, with or without
      8        1.1    ichiro  * modification, are permitted provided that the following conditions
      9        1.1    ichiro  * are met:
     10        1.1    ichiro  * 1. Redistributions of source code must retain the above copyright
     11        1.1    ichiro  *    notice, this list of conditions and the following disclaimer.
     12        1.1    ichiro  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1    ichiro  *    notice, this list of conditions and the following disclaimer in the
     14        1.1    ichiro  *    documentation and/or other materials provided with the distribution.
     15        1.1    ichiro  * 3. All advertising materials mentioning features or use of this software
     16        1.1    ichiro  *    must display the following acknowledgement:
     17        1.1    ichiro  *	This product includes software developed by Bill Paul.
     18        1.1    ichiro  * 4. Neither the name of the author nor the names of any co-contributors
     19        1.1    ichiro  *    may be used to endorse or promote products derived from this software
     20        1.1    ichiro  *    without specific prior written permission.
     21        1.1    ichiro  *
     22        1.1    ichiro  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     23        1.1    ichiro  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24        1.1    ichiro  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25        1.1    ichiro  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
     26        1.1    ichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27        1.1    ichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28        1.1    ichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29        1.1    ichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30        1.1    ichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31        1.1    ichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     32        1.1    ichiro  * THE POSSIBILITY OF SUCH DAMAGE.
     33        1.1    ichiro  */
     34        1.1    ichiro 
     35        1.1    ichiro /*
     36        1.1    ichiro  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
     37        1.1    ichiro  *
     38        1.1    ichiro  * Original FreeBSD driver written by Bill Paul <wpaul (at) ctr.columbia.edu>
     39        1.1    ichiro  * Electrical Engineering Department
     40        1.1    ichiro  * Columbia University, New York City
     41        1.1    ichiro  */
     42        1.1    ichiro 
     43        1.1    ichiro /*
     44        1.1    ichiro  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
     45        1.1    ichiro  * from Lucent. Unlike the older cards, the new ones are programmed
     46        1.1    ichiro  * entirely via a firmware-driven controller called the Hermes.
     47        1.1    ichiro  * Unfortunately, Lucent will not release the Hermes programming manual
     48        1.1    ichiro  * without an NDA (if at all). What they do release is an API library
     49        1.1    ichiro  * called the HCF (Hardware Control Functions) which is supposed to
     50        1.1    ichiro  * do the device-specific operations of a device driver for you. The
     51        1.1    ichiro  * publically available version of the HCF library (the 'HCF Light') is
     52        1.1    ichiro  * a) extremely gross, b) lacks certain features, particularly support
     53        1.1    ichiro  * for 802.11 frames, and c) is contaminated by the GNU Public License.
     54        1.1    ichiro  *
     55        1.1    ichiro  * This driver does not use the HCF or HCF Light at all. Instead, it
     56        1.1    ichiro  * programs the Hermes controller directly, using information gleaned
     57        1.1    ichiro  * from the HCF Light code and corresponding documentation.
     58        1.1    ichiro  *
     59        1.1    ichiro  * This driver supports both the PCMCIA and ISA versions of the
     60        1.1    ichiro  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
     61        1.1    ichiro  * anything of the sort: it's actually a PCMCIA bridge adapter
     62        1.1    ichiro  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
     63        1.1    ichiro  * inserted. Consequently, you need to use the pccard support for
     64        1.1    ichiro  * both the ISA and PCMCIA adapters.
     65        1.1    ichiro  */
     66        1.1    ichiro 
     67        1.1    ichiro /*
     68        1.1    ichiro  * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
     69        1.1    ichiro  * Oslo IETF plenary meeting.
     70        1.1    ichiro  */
     71       1.29     lukem 
     72       1.29     lukem #include <sys/cdefs.h>
     73  1.159.2.1       jdc __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.159.2.1 2004/06/07 06:37:28 jdc Exp $");
     74        1.1    ichiro 
     75        1.1    ichiro #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
     76        1.1    ichiro #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
     77        1.1    ichiro 
     78        1.1    ichiro #include "bpfilter.h"
     79        1.1    ichiro 
     80        1.1    ichiro #include <sys/param.h>
     81        1.1    ichiro #include <sys/systm.h>
     82        1.1    ichiro #include <sys/callout.h>
     83        1.1    ichiro #include <sys/device.h>
     84        1.1    ichiro #include <sys/socket.h>
     85        1.1    ichiro #include <sys/mbuf.h>
     86        1.1    ichiro #include <sys/ioctl.h>
     87        1.1    ichiro #include <sys/kernel.h>		/* for hz */
     88        1.1    ichiro #include <sys/proc.h>
     89        1.1    ichiro 
     90        1.1    ichiro #include <net/if.h>
     91        1.1    ichiro #include <net/if_dl.h>
     92      1.116       kml #include <net/if_llc.h>
     93        1.1    ichiro #include <net/if_media.h>
     94        1.1    ichiro #include <net/if_ether.h>
     95      1.133    dyoung 
     96      1.133    dyoung #include <net80211/ieee80211_var.h>
     97      1.133    dyoung #include <net80211/ieee80211_compat.h>
     98      1.133    dyoung #include <net80211/ieee80211_ioctl.h>
     99      1.144    dyoung #include <net80211/ieee80211_radiotap.h>
    100      1.148    dyoung #include <net80211/ieee80211_rssadapt.h>
    101        1.1    ichiro 
    102        1.1    ichiro #if NBPFILTER > 0
    103        1.1    ichiro #include <net/bpf.h>
    104        1.1    ichiro #include <net/bpfdesc.h>
    105        1.1    ichiro #endif
    106        1.1    ichiro 
    107       1.18   nathanw #include <machine/bus.h>
    108        1.1    ichiro 
    109        1.1    ichiro #include <dev/ic/wi_ieee.h>
    110        1.1    ichiro #include <dev/ic/wireg.h>
    111        1.1    ichiro #include <dev/ic/wivar.h>
    112        1.1    ichiro 
    113       1.90      onoe static int  wi_init(struct ifnet *);
    114       1.90      onoe static void wi_stop(struct ifnet *, int);
    115       1.90      onoe static void wi_start(struct ifnet *);
    116       1.90      onoe static int  wi_reset(struct wi_softc *);
    117       1.90      onoe static void wi_watchdog(struct ifnet *);
    118       1.90      onoe static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
    119       1.90      onoe static int  wi_media_change(struct ifnet *);
    120       1.90      onoe static void wi_media_status(struct ifnet *, struct ifmediareq *);
    121       1.90      onoe 
    122      1.148    dyoung static struct ieee80211_node *wi_node_alloc(struct ieee80211com *);
    123      1.148    dyoung static void wi_node_copy(struct ieee80211com *, struct ieee80211_node *,
    124      1.148    dyoung     const struct ieee80211_node *);
    125      1.148    dyoung static void wi_node_free(struct ieee80211com *, struct ieee80211_node *);
    126      1.148    dyoung 
    127      1.148    dyoung static void wi_raise_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
    128      1.148    dyoung static void wi_lower_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
    129      1.148    dyoung static void wi_choose_rate(struct ieee80211com *, struct ieee80211_node *,
    130      1.148    dyoung     struct ieee80211_frame *, u_int);
    131      1.148    dyoung static void wi_rssadapt_updatestats_cb(void *, struct ieee80211_node *);
    132      1.148    dyoung static void wi_rssadapt_updatestats(void *);
    133      1.148    dyoung 
    134       1.90      onoe static void wi_rx_intr(struct wi_softc *);
    135      1.148    dyoung static void wi_txalloc_intr(struct wi_softc *);
    136       1.90      onoe static void wi_tx_intr(struct wi_softc *);
    137      1.121    dyoung static void wi_tx_ex_intr(struct wi_softc *);
    138       1.90      onoe static void wi_info_intr(struct wi_softc *);
    139       1.90      onoe 
    140       1.90      onoe static int  wi_get_cfg(struct ifnet *, u_long, caddr_t);
    141       1.90      onoe static int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
    142      1.135    dyoung static int  wi_cfg_txrate(struct wi_softc *);
    143      1.135    dyoung static int  wi_write_txrate(struct wi_softc *, int);
    144       1.90      onoe static int  wi_write_wep(struct wi_softc *);
    145       1.90      onoe static int  wi_write_multi(struct wi_softc *);
    146       1.90      onoe static int  wi_alloc_fid(struct wi_softc *, int, int *);
    147       1.90      onoe static void wi_read_nicid(struct wi_softc *);
    148       1.90      onoe static int  wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
    149       1.90      onoe 
    150       1.90      onoe static int  wi_cmd(struct wi_softc *, int, int, int, int);
    151       1.90      onoe static int  wi_seek_bap(struct wi_softc *, int, int);
    152       1.90      onoe static int  wi_read_bap(struct wi_softc *, int, int, void *, int);
    153       1.90      onoe static int  wi_write_bap(struct wi_softc *, int, int, void *, int);
    154      1.108    dyoung static int  wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
    155       1.90      onoe static int  wi_read_rid(struct wi_softc *, int, void *, int *);
    156       1.90      onoe static int  wi_write_rid(struct wi_softc *, int, void *, int);
    157       1.90      onoe 
    158      1.133    dyoung static int  wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
    159      1.116       kml static int  wi_set_tim(struct ieee80211com *, int, int);
    160       1.90      onoe 
    161      1.123    dyoung static int  wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
    162       1.90      onoe static void wi_scan_result(struct wi_softc *, int, int);
    163       1.90      onoe 
    164      1.119    dyoung static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
    165      1.119    dyoung 
    166       1.90      onoe static inline int
    167       1.90      onoe wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
    168       1.90      onoe {
    169       1.90      onoe 
    170       1.90      onoe 	val = htole16(val);
    171       1.90      onoe 	return wi_write_rid(sc, rid, &val, sizeof(val));
    172       1.90      onoe }
    173       1.90      onoe 
    174      1.121    dyoung static	struct timeval lasttxerror;	/* time of last tx error msg */
    175      1.126  christos static	int curtxeps = 0;		/* current tx error msgs/sec */
    176      1.121    dyoung static	int wi_txerate = 0;		/* tx error rate: max msgs/sec */
    177      1.121    dyoung 
    178       1.90      onoe #ifdef WI_DEBUG
    179      1.109    dyoung int wi_debug = 0;
    180       1.90      onoe 
    181       1.90      onoe #define	DPRINTF(X)	if (wi_debug) printf X
    182       1.90      onoe #define	DPRINTF2(X)	if (wi_debug > 1) printf X
    183      1.119    dyoung #define	IFF_DUMPPKTS(_ifp) \
    184      1.119    dyoung 	(((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
    185       1.90      onoe #else
    186       1.90      onoe #define	DPRINTF(X)
    187       1.90      onoe #define	DPRINTF2(X)
    188      1.119    dyoung #define	IFF_DUMPPKTS(_ifp)	0
    189       1.84   thorpej #endif
    190        1.1    ichiro 
    191      1.157    dyoung #define WI_INTRS	(WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO | \
    192      1.157    dyoung 			 WI_EV_TX | WI_EV_TX_EXC)
    193       1.90      onoe 
    194       1.90      onoe struct wi_card_ident
    195       1.90      onoe wi_card_ident[] = {
    196       1.74   thorpej 	/* CARD_ID			CARD_NAME		FIRM_TYPE */
    197       1.67    ichiro 	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },
    198       1.67    ichiro 	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },
    199       1.67    ichiro 	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },
    200       1.67    ichiro 	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },
    201       1.67    ichiro 	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },
    202       1.67    ichiro 	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },
    203       1.67    ichiro 	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },
    204       1.67    ichiro 	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },
    205       1.67    ichiro 	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },
    206       1.67    ichiro 	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },
    207       1.67    ichiro 	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },
    208       1.67    ichiro 	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },
    209       1.64    ichiro 	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    210       1.64    ichiro 	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    211       1.64    ichiro 	{ WI_NIC_3842_PCMCIA_ATM_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    212       1.64    ichiro 	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    213       1.64    ichiro 	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    214       1.64    ichiro 	{ WI_NIC_3842_MINI_ATM_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    215       1.64    ichiro 	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    216       1.64    ichiro 	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    217       1.64    ichiro 	{ WI_NIC_3842_PCI_ATM_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    218       1.64    ichiro 	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    219       1.64    ichiro 	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    220       1.64    ichiro 	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    221       1.64    ichiro 	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    222       1.64    ichiro 	{ 0,	NULL,	0 },
    223       1.64    ichiro };
    224       1.64    ichiro 
    225        1.1    ichiro int
    226       1.90      onoe wi_attach(struct wi_softc *sc)
    227        1.1    ichiro {
    228       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
    229       1.90      onoe 	struct ifnet *ifp = &ic->ic_if;
    230      1.142    dyoung 	int chan, nrate, buflen;
    231      1.142    dyoung 	u_int16_t val, chanavail;
    232      1.146    dyoung  	struct {
    233      1.146    dyoung  		u_int16_t nrates;
    234      1.146    dyoung  		char rates[IEEE80211_RATE_SIZE];
    235      1.146    dyoung  	} ratebuf;
    236       1.90      onoe 	static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
    237        1.1    ichiro 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    238        1.1    ichiro 	};
    239      1.125    dyoung 	int s;
    240        1.1    ichiro 
    241      1.125    dyoung 	s = splnet();
    242        1.1    ichiro 
    243        1.1    ichiro 	/* Make sure interrupts are disabled. */
    244        1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    245       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
    246        1.1    ichiro 
    247      1.127    dyoung 	sc->sc_invalid = 0;
    248      1.127    dyoung 
    249        1.1    ichiro 	/* Reset the NIC. */
    250       1.90      onoe 	if (wi_reset(sc) != 0) {
    251      1.127    dyoung 		sc->sc_invalid = 1;
    252      1.125    dyoung 		splx(s);
    253       1.90      onoe 		return 1;
    254       1.90      onoe 	}
    255        1.1    ichiro 
    256       1.90      onoe 	buflen = IEEE80211_ADDR_LEN;
    257       1.90      onoe 	if (wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen) != 0 ||
    258       1.90      onoe 	    IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
    259       1.90      onoe 		printf(" could not get mac address, attach failed\n");
    260      1.125    dyoung 		splx(s);
    261       1.42      yamt 		return 1;
    262        1.1    ichiro 	}
    263        1.1    ichiro 
    264       1.90      onoe 	printf(" 802.11 address %s\n", ether_sprintf(ic->ic_myaddr));
    265        1.1    ichiro 
    266        1.4    ichiro 	/* Read NIC identification */
    267       1.90      onoe 	wi_read_nicid(sc);
    268        1.4    ichiro 
    269        1.1    ichiro 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
    270        1.1    ichiro 	ifp->if_softc = sc;
    271        1.1    ichiro 	ifp->if_start = wi_start;
    272        1.1    ichiro 	ifp->if_ioctl = wi_ioctl;
    273        1.1    ichiro 	ifp->if_watchdog = wi_watchdog;
    274        1.1    ichiro 	ifp->if_init = wi_init;
    275        1.1    ichiro 	ifp->if_stop = wi_stop;
    276       1.90      onoe 	ifp->if_flags =
    277       1.90      onoe 	    IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS;
    278        1.1    ichiro 	IFQ_SET_READY(&ifp->if_snd);
    279        1.1    ichiro 
    280       1.90      onoe 	ic->ic_phytype = IEEE80211_T_DS;
    281       1.90      onoe 	ic->ic_opmode = IEEE80211_M_STA;
    282      1.133    dyoung 	ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO;
    283       1.90      onoe 	ic->ic_state = IEEE80211_S_INIT;
    284      1.116       kml 	ic->ic_max_aid = WI_MAX_AID;
    285       1.90      onoe 
    286       1.90      onoe 	/* Find available channel */
    287      1.142    dyoung 	buflen = sizeof(chanavail);
    288      1.142    dyoung 	if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &chanavail, &buflen) != 0)
    289      1.142    dyoung 		chanavail = htole16(0x1fff);	/* assume 1-11 */
    290      1.142    dyoung 	for (chan = 16; chan > 0; chan--) {
    291      1.142    dyoung 		if (!isset((u_int8_t*)&chanavail, chan - 1))
    292      1.142    dyoung 			continue;
    293      1.142    dyoung 		ic->ic_ibss_chan = &ic->ic_channels[chan];
    294      1.133    dyoung 		ic->ic_channels[chan].ic_freq =
    295      1.133    dyoung 		    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
    296      1.133    dyoung 		ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
    297       1.90      onoe 	}
    298       1.90      onoe 
    299      1.142    dyoung 	/* Find default IBSS channel */
    300      1.142    dyoung 	buflen = sizeof(val);
    301      1.142    dyoung 	if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
    302      1.142    dyoung 		chan = le16toh(val);
    303      1.142    dyoung 		if (isset((u_int8_t*)&chanavail, chan - 1))
    304      1.142    dyoung 			ic->ic_ibss_chan = &ic->ic_channels[chan];
    305      1.142    dyoung 	}
    306      1.142    dyoung 	if (ic->ic_ibss_chan == NULL)
    307      1.142    dyoung 		panic("%s: no available channel\n", sc->sc_dev.dv_xname);
    308      1.142    dyoung 
    309      1.131    dyoung 	if (sc->sc_firmware_type == WI_LUCENT) {
    310      1.131    dyoung 		sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
    311      1.131    dyoung 	} else {
    312      1.131    dyoung 		buflen = sizeof(val);
    313      1.131    dyoung 		if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
    314      1.131    dyoung 		    wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0)
    315      1.131    dyoung 			sc->sc_dbm_offset = le16toh(val);
    316      1.131    dyoung 		else
    317      1.131    dyoung 			sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
    318      1.102    dyoung 	}
    319       1.77   thorpej 
    320      1.159    dyoung 	sc->sc_flags |= WI_FLAGS_RSSADAPTSTA;
    321      1.159    dyoung 
    322       1.77   thorpej 	/*
    323       1.77   thorpej 	 * Set flags based on firmware version.
    324       1.77   thorpej 	 */
    325       1.77   thorpej 	switch (sc->sc_firmware_type) {
    326       1.77   thorpej 	case WI_LUCENT:
    327       1.90      onoe 		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
    328       1.90      onoe #ifdef WI_HERMES_AUTOINC_WAR
    329       1.90      onoe 		/* XXX: not confirmed, but never seen for recent firmware */
    330       1.90      onoe 		if (sc->sc_sta_firmware_ver <  40000) {
    331       1.90      onoe 			sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
    332       1.90      onoe 		}
    333       1.90      onoe #endif
    334       1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 60000)
    335       1.90      onoe 			sc->sc_flags |= WI_FLAGS_HAS_MOR;
    336      1.130        rh 		if (sc->sc_sta_firmware_ver >= 60006) {
    337      1.133    dyoung 			ic->ic_caps |= IEEE80211_C_IBSS;
    338      1.133    dyoung 			ic->ic_caps |= IEEE80211_C_MONITOR;
    339      1.130        rh 		}
    340       1.90      onoe 		sc->sc_ibss_port = 1;
    341       1.77   thorpej 		break;
    342       1.77   thorpej 
    343       1.77   thorpej 	case WI_INTERSIL:
    344      1.104    dyoung 		sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
    345       1.90      onoe 		sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
    346       1.90      onoe 		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
    347      1.105    dyoung 		if (sc->sc_sta_firmware_ver > 10101)
    348      1.105    dyoung 			sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
    349       1.77   thorpej 		if (sc->sc_sta_firmware_ver >= 800) {
    350      1.114    dyoung 			if (sc->sc_sta_firmware_ver != 10402)
    351      1.133    dyoung 				ic->ic_caps |= IEEE80211_C_HOSTAP;
    352      1.133    dyoung 			ic->ic_caps |= IEEE80211_C_IBSS;
    353      1.133    dyoung 			ic->ic_caps |= IEEE80211_C_MONITOR;
    354       1.77   thorpej 		}
    355       1.90      onoe 		sc->sc_ibss_port = 0;
    356      1.148    dyoung 		sc->sc_alt_retry = 2;
    357       1.77   thorpej 		break;
    358       1.77   thorpej 
    359       1.77   thorpej 	case WI_SYMBOL:
    360       1.90      onoe 		sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
    361      1.101   mycroft 		if (sc->sc_sta_firmware_ver >= 20000)
    362      1.133    dyoung 			ic->ic_caps |= IEEE80211_C_IBSS;
    363       1.90      onoe 		sc->sc_ibss_port = 4;
    364       1.77   thorpej 		break;
    365       1.77   thorpej 	}
    366       1.35    ichiro 
    367        1.1    ichiro 	/*
    368        1.1    ichiro 	 * Find out if we support WEP on this card.
    369        1.1    ichiro 	 */
    370       1.90      onoe 	buflen = sizeof(val);
    371       1.90      onoe 	if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
    372       1.90      onoe 	    val != htole16(0))
    373      1.133    dyoung 		ic->ic_caps |= IEEE80211_C_WEP;
    374       1.84   thorpej 
    375       1.78   thorpej 	/* Find supported rates. */
    376       1.90      onoe 	buflen = sizeof(ratebuf);
    377      1.146    dyoung 	if (wi_read_rid(sc, WI_RID_DATA_RATES, &ratebuf, &buflen) == 0) {
    378      1.146    dyoung 		nrate = le16toh(ratebuf.nrates);
    379       1.90      onoe 		if (nrate > IEEE80211_RATE_SIZE)
    380       1.90      onoe 			nrate = IEEE80211_RATE_SIZE;
    381      1.133    dyoung 		memcpy(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates,
    382      1.146    dyoung 		    &ratebuf.rates[0], nrate);
    383      1.133    dyoung 		ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = nrate;
    384       1.90      onoe 	}
    385       1.90      onoe 	buflen = sizeof(val);
    386       1.90      onoe 
    387       1.90      onoe 	sc->sc_max_datalen = 2304;
    388       1.90      onoe 	sc->sc_rts_thresh = 2347;
    389      1.102    dyoung 	sc->sc_frag_thresh = 2346;
    390       1.90      onoe 	sc->sc_system_scale = 1;
    391      1.100      onoe 	sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
    392       1.90      onoe 	sc->sc_roaming_mode = 1;
    393       1.75   thorpej 
    394      1.148    dyoung 	callout_init(&sc->sc_rssadapt_ch);
    395      1.148    dyoung 
    396        1.1    ichiro 	/*
    397        1.1    ichiro 	 * Call MI attach routines.
    398        1.1    ichiro 	 */
    399        1.1    ichiro 	if_attach(ifp);
    400       1.90      onoe 	ieee80211_ifattach(ifp);
    401       1.84   thorpej 
    402      1.133    dyoung 	sc->sc_newstate = ic->ic_newstate;
    403      1.133    dyoung 	ic->ic_newstate = wi_newstate;
    404      1.148    dyoung 	ic->ic_node_alloc = wi_node_alloc;
    405      1.148    dyoung 	ic->ic_node_free = wi_node_free;
    406      1.148    dyoung 	ic->ic_node_copy = wi_node_copy;
    407      1.133    dyoung 	ic->ic_set_tim = wi_set_tim;
    408      1.133    dyoung 
    409      1.133    dyoung 	ieee80211_media_init(ifp, wi_media_change, wi_media_status);
    410      1.132    dyoung 
    411      1.144    dyoung #if NBPFILTER > 0
    412      1.144    dyoung 	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
    413      1.144    dyoung 	    sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
    414      1.144    dyoung #endif
    415      1.144    dyoung 
    416      1.144    dyoung 	memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
    417      1.144    dyoung 	sc->sc_rxtap.wr_ihdr.it_len = sizeof(sc->sc_rxtapu);
    418      1.144    dyoung 	sc->sc_rxtap.wr_ihdr.it_present = WI_RX_RADIOTAP_PRESENT;
    419      1.144    dyoung 
    420      1.144    dyoung 	memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
    421      1.144    dyoung 	sc->sc_txtap.wt_ihdr.it_len = sizeof(sc->sc_txtapu);
    422      1.144    dyoung 	sc->sc_txtap.wt_ihdr.it_present = WI_TX_RADIOTAP_PRESENT;
    423      1.144    dyoung 
    424        1.1    ichiro 	/* Attach is successful. */
    425        1.1    ichiro 	sc->sc_attached = 1;
    426        1.1    ichiro 
    427      1.125    dyoung 	splx(s);
    428        1.1    ichiro 	return 0;
    429        1.1    ichiro }
    430        1.1    ichiro 
    431       1.90      onoe int
    432       1.90      onoe wi_detach(struct wi_softc *sc)
    433       1.84   thorpej {
    434       1.90      onoe 	struct ifnet *ifp = &sc->sc_ic.ic_if;
    435      1.125    dyoung 	int s;
    436       1.90      onoe 
    437       1.90      onoe 	if (!sc->sc_attached)
    438       1.90      onoe 		return 0;
    439       1.84   thorpej 
    440      1.125    dyoung 	s = splnet();
    441       1.84   thorpej 
    442      1.127    dyoung 	sc->sc_invalid = 1;
    443      1.127    dyoung 	wi_stop(ifp, 1);
    444      1.127    dyoung 
    445       1.90      onoe 	/* Delete all remaining media. */
    446      1.132    dyoung 	ifmedia_delete_instance(&sc->sc_ic.ic_media, IFM_INST_ANY);
    447       1.84   thorpej 
    448       1.90      onoe 	ieee80211_ifdetach(ifp);
    449       1.90      onoe 	if_detach(ifp);
    450      1.125    dyoung 	splx(s);
    451       1.90      onoe 	return 0;
    452       1.84   thorpej }
    453       1.84   thorpej 
    454      1.122    dyoung #ifdef __NetBSD__
    455       1.90      onoe int
    456       1.90      onoe wi_activate(struct device *self, enum devact act)
    457       1.84   thorpej {
    458       1.90      onoe 	struct wi_softc *sc = (struct wi_softc *)self;
    459      1.125    dyoung 	int rv = 0, s;
    460       1.90      onoe 
    461      1.125    dyoung 	s = splnet();
    462       1.90      onoe 	switch (act) {
    463       1.90      onoe 	case DVACT_ACTIVATE:
    464       1.90      onoe 		rv = EOPNOTSUPP;
    465       1.90      onoe 		break;
    466       1.84   thorpej 
    467       1.90      onoe 	case DVACT_DEACTIVATE:
    468       1.90      onoe 		if_deactivate(&sc->sc_ic.ic_if);
    469       1.90      onoe 		break;
    470       1.84   thorpej 	}
    471      1.125    dyoung 	splx(s);
    472       1.90      onoe 	return rv;
    473       1.90      onoe }
    474       1.90      onoe 
    475       1.90      onoe void
    476       1.90      onoe wi_power(struct wi_softc *sc, int why)
    477       1.90      onoe {
    478       1.90      onoe 	struct ifnet *ifp = &sc->sc_ic.ic_if;
    479      1.125    dyoung 	int s;
    480       1.84   thorpej 
    481      1.125    dyoung 	s = splnet();
    482       1.90      onoe 	switch (why) {
    483       1.90      onoe 	case PWR_SUSPEND:
    484       1.90      onoe 	case PWR_STANDBY:
    485       1.90      onoe 		wi_stop(ifp, 1);
    486       1.90      onoe 		break;
    487       1.90      onoe 	case PWR_RESUME:
    488       1.90      onoe 		if (ifp->if_flags & IFF_UP) {
    489       1.90      onoe 			wi_init(ifp);
    490       1.90      onoe 			(void)wi_intr(sc);
    491       1.90      onoe 		}
    492       1.90      onoe 		break;
    493       1.90      onoe 	case PWR_SOFTSUSPEND:
    494       1.90      onoe 	case PWR_SOFTSTANDBY:
    495       1.90      onoe 	case PWR_SOFTRESUME:
    496       1.90      onoe 		break;
    497       1.84   thorpej 	}
    498      1.125    dyoung 	splx(s);
    499       1.90      onoe }
    500      1.122    dyoung #endif /* __NetBSD__ */
    501       1.84   thorpej 
    502       1.90      onoe void
    503       1.90      onoe wi_shutdown(struct wi_softc *sc)
    504       1.90      onoe {
    505       1.90      onoe 	struct ifnet *ifp = &sc->sc_ic.ic_if;
    506       1.84   thorpej 
    507       1.90      onoe 	if (sc->sc_attached)
    508       1.90      onoe 		wi_stop(ifp, 1);
    509       1.90      onoe }
    510       1.84   thorpej 
    511       1.90      onoe int
    512       1.90      onoe wi_intr(void *arg)
    513       1.90      onoe {
    514       1.90      onoe 	int i;
    515       1.90      onoe 	struct wi_softc	*sc = arg;
    516       1.90      onoe 	struct ifnet *ifp = &sc->sc_ic.ic_if;
    517      1.128    dyoung 	u_int16_t status;
    518       1.84   thorpej 
    519       1.90      onoe 	if (sc->sc_enabled == 0 ||
    520       1.90      onoe 	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
    521       1.90      onoe 	    (ifp->if_flags & IFF_RUNNING) == 0)
    522       1.90      onoe 		return 0;
    523       1.84   thorpej 
    524       1.90      onoe 	if ((ifp->if_flags & IFF_UP) == 0) {
    525      1.111    dyoung 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    526       1.90      onoe 		CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
    527       1.90      onoe 		return 1;
    528       1.90      onoe 	}
    529       1.84   thorpej 
    530      1.128    dyoung 	/* This is superfluous on Prism, but Lucent breaks if we
    531      1.128    dyoung 	 * do not disable interrupts.
    532      1.128    dyoung 	 */
    533      1.128    dyoung 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    534      1.128    dyoung 
    535       1.90      onoe 	/* maximum 10 loops per interrupt */
    536       1.90      onoe 	for (i = 0; i < 10; i++) {
    537       1.90      onoe 		/*
    538       1.90      onoe 		 * Only believe a status bit when we enter wi_intr, or when
    539       1.90      onoe 		 * the bit was "off" the last time through the loop. This is
    540       1.90      onoe 		 * my strategy to avoid racing the hardware/firmware if I
    541       1.90      onoe 		 * can re-read the event status register more quickly than
    542       1.90      onoe 		 * it is updated.
    543       1.90      onoe 		 */
    544      1.128    dyoung 		status = CSR_READ_2(sc, WI_EVENT_STAT);
    545       1.90      onoe 		if ((status & WI_INTRS) == 0)
    546       1.90      onoe 			break;
    547       1.84   thorpej 
    548       1.90      onoe 		if (status & WI_EV_RX)
    549       1.90      onoe 			wi_rx_intr(sc);
    550       1.84   thorpej 
    551       1.90      onoe 		if (status & WI_EV_ALLOC)
    552      1.148    dyoung 			wi_txalloc_intr(sc);
    553      1.148    dyoung 
    554      1.148    dyoung 		if (status & WI_EV_TX)
    555       1.90      onoe 			wi_tx_intr(sc);
    556       1.84   thorpej 
    557      1.121    dyoung 		if (status & WI_EV_TX_EXC)
    558      1.121    dyoung 			wi_tx_ex_intr(sc);
    559      1.121    dyoung 
    560       1.90      onoe 		if (status & WI_EV_INFO)
    561       1.90      onoe 			wi_info_intr(sc);
    562       1.84   thorpej 
    563       1.98      onoe 		if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
    564       1.98      onoe 		    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
    565       1.90      onoe 		    !IFQ_IS_EMPTY(&ifp->if_snd))
    566       1.90      onoe 			wi_start(ifp);
    567       1.84   thorpej 	}
    568      1.128    dyoung 
    569      1.128    dyoung 	/* re-enable interrupts */
    570      1.128    dyoung 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    571       1.84   thorpej 
    572       1.90      onoe 	return 1;
    573       1.90      onoe }
    574       1.90      onoe 
    575      1.151    dyoung #define arraylen(a) (sizeof(a) / sizeof((a)[0]))
    576      1.151    dyoung 
    577      1.151    dyoung static void
    578      1.151    dyoung wi_rssdescs_init(struct wi_rssdesc (*rssd)[WI_NTXRSS], wi_rssdescq_t *rssdfree)
    579      1.151    dyoung {
    580      1.151    dyoung 	int i;
    581      1.151    dyoung 	SLIST_INIT(rssdfree);
    582      1.151    dyoung 	for (i = 0; i < arraylen(*rssd); i++) {
    583      1.151    dyoung 		SLIST_INSERT_HEAD(rssdfree, &(*rssd)[i], rd_next);
    584      1.151    dyoung 	}
    585      1.151    dyoung }
    586      1.151    dyoung 
    587      1.151    dyoung static void
    588      1.151    dyoung wi_rssdescs_reset(struct ieee80211com *ic, struct wi_rssdesc (*rssd)[WI_NTXRSS],
    589      1.151    dyoung     wi_rssdescq_t *rssdfree, u_int8_t (*txpending)[IEEE80211_RATE_MAXSIZE])
    590      1.151    dyoung {
    591      1.151    dyoung 	struct ieee80211_node *ni;
    592      1.151    dyoung 	int i;
    593      1.151    dyoung 	for (i = 0; i < arraylen(*rssd); i++) {
    594      1.151    dyoung 		ni = (*rssd)[i].rd_desc.id_node;
    595      1.151    dyoung 		(*rssd)[i].rd_desc.id_node = NULL;
    596      1.151    dyoung 		if (ni != NULL && (ic->ic_if.if_flags & IFF_DEBUG) != 0)
    597      1.151    dyoung 			printf("%s: cleaning outstanding rssadapt "
    598      1.151    dyoung 			    "descriptor for %s\n",
    599      1.151    dyoung 			    ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
    600      1.151    dyoung 		if (ni != NULL && ni != ic->ic_bss)
    601      1.151    dyoung 			ieee80211_free_node(ic, ni);
    602      1.151    dyoung 	}
    603      1.151    dyoung 	memset(*txpending, 0, sizeof(*txpending));
    604      1.151    dyoung 	wi_rssdescs_init(rssd, rssdfree);
    605      1.151    dyoung }
    606      1.151    dyoung 
    607       1.90      onoe static int
    608       1.90      onoe wi_init(struct ifnet *ifp)
    609       1.90      onoe {
    610       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
    611       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
    612       1.90      onoe 	struct wi_joinreq join;
    613       1.90      onoe 	int i;
    614       1.90      onoe 	int error = 0, wasenabled;
    615       1.90      onoe 
    616       1.90      onoe 	DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled));
    617       1.90      onoe 	wasenabled = sc->sc_enabled;
    618       1.90      onoe 	if (!sc->sc_enabled) {
    619       1.90      onoe 		if ((error = (*sc->sc_enable)(sc)) != 0)
    620       1.90      onoe 			goto out;
    621       1.90      onoe 		sc->sc_enabled = 1;
    622       1.90      onoe 	} else
    623       1.90      onoe 		wi_stop(ifp, 0);
    624       1.84   thorpej 
    625       1.90      onoe 	/* Symbol firmware cannot be initialized more than once */
    626      1.123    dyoung 	if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled)
    627       1.90      onoe 		if ((error = wi_reset(sc)) != 0)
    628       1.90      onoe 			goto out;
    629       1.84   thorpej 
    630       1.90      onoe 	/* common 802.11 configuration */
    631       1.97      onoe 	ic->ic_flags &= ~IEEE80211_F_IBSSON;
    632       1.98      onoe 	sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
    633       1.90      onoe 	switch (ic->ic_opmode) {
    634       1.90      onoe 	case IEEE80211_M_STA:
    635       1.90      onoe 		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
    636       1.90      onoe 		break;
    637       1.91      onoe 	case IEEE80211_M_IBSS:
    638       1.90      onoe 		wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
    639       1.97      onoe 		ic->ic_flags |= IEEE80211_F_IBSSON;
    640      1.107    dyoung 		sc->sc_syn_timer = 5;
    641      1.107    dyoung 		ifp->if_timer = 1;
    642       1.90      onoe 		break;
    643       1.91      onoe 	case IEEE80211_M_AHDEMO:
    644       1.91      onoe 		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
    645       1.91      onoe 		break;
    646       1.90      onoe 	case IEEE80211_M_HOSTAP:
    647       1.90      onoe 		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
    648       1.90      onoe 		break;
    649      1.112    dyoung 	case IEEE80211_M_MONITOR:
    650      1.130        rh 		if (sc->sc_firmware_type == WI_LUCENT)
    651      1.130        rh 			wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
    652      1.112    dyoung 		wi_cmd(sc, WI_CMD_TEST | (WI_TEST_MONITOR << 8), 0, 0, 0);
    653      1.112    dyoung 		break;
    654       1.90      onoe 	}
    655       1.84   thorpej 
    656       1.90      onoe 	/* Intersil interprets this RID as joining ESS even in IBSS mode */
    657       1.90      onoe 	if (sc->sc_firmware_type == WI_LUCENT &&
    658       1.90      onoe 	    (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
    659       1.90      onoe 		wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
    660       1.90      onoe 	else
    661       1.90      onoe 		wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
    662       1.90      onoe 	wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
    663       1.90      onoe 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
    664       1.90      onoe 	    ic->ic_des_esslen);
    665      1.133    dyoung 	wi_write_val(sc, WI_RID_OWN_CHNL,
    666      1.133    dyoung 	    ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
    667       1.90      onoe 	wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
    668       1.93      onoe 	IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    669       1.90      onoe 	wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
    670       1.90      onoe 	wi_write_val(sc, WI_RID_PM_ENABLED,
    671       1.90      onoe 	    (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
    672       1.90      onoe 
    673       1.90      onoe 	/* not yet common 802.11 configuration */
    674       1.90      onoe 	wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
    675       1.90      onoe 	wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh);
    676      1.104    dyoung 	if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
    677      1.104    dyoung 		wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh);
    678       1.90      onoe 
    679       1.90      onoe 	/* driver specific 802.11 configuration */
    680       1.90      onoe 	if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
    681       1.90      onoe 		wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
    682       1.90      onoe 	if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
    683       1.90      onoe 		wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
    684       1.90      onoe 	if (sc->sc_flags & WI_FLAGS_HAS_MOR)
    685       1.90      onoe 		wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
    686      1.135    dyoung 	wi_cfg_txrate(sc);
    687       1.90      onoe 	wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
    688       1.90      onoe 
    689       1.95      onoe 	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
    690       1.95      onoe 	    sc->sc_firmware_type == WI_INTERSIL) {
    691       1.90      onoe 		wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
    692       1.90      onoe 		wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
    693       1.90      onoe 		wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
    694       1.90      onoe 		wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
    695       1.84   thorpej 	}
    696       1.84   thorpej 
    697      1.152    dyoung 	if (sc->sc_firmware_type == WI_INTERSIL)
    698      1.148    dyoung 		wi_write_val(sc, WI_RID_ALT_RETRY_COUNT, sc->sc_alt_retry);
    699      1.148    dyoung 
    700       1.90      onoe 	/*
    701       1.90      onoe 	 * Initialize promisc mode.
    702      1.145    dyoung 	 *	Being in Host-AP mode causes a great
    703      1.145    dyoung 	 *	deal of pain if promiscuous mode is set.
    704       1.90      onoe 	 *	Therefore we avoid confusing the firmware
    705       1.90      onoe 	 *	and always reset promisc mode in Host-AP
    706       1.90      onoe 	 *	mode.  Host-AP sees all the packets anyway.
    707       1.90      onoe 	 */
    708       1.90      onoe 	if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
    709       1.90      onoe 	    (ifp->if_flags & IFF_PROMISC) != 0) {
    710       1.90      onoe 		wi_write_val(sc, WI_RID_PROMISC, 1);
    711       1.90      onoe 	} else {
    712       1.90      onoe 		wi_write_val(sc, WI_RID_PROMISC, 0);
    713       1.84   thorpej 	}
    714       1.84   thorpej 
    715       1.90      onoe 	/* Configure WEP. */
    716      1.133    dyoung 	if (ic->ic_caps & IEEE80211_C_WEP)
    717       1.90      onoe 		wi_write_wep(sc);
    718       1.84   thorpej 
    719       1.90      onoe 	/* Set multicast filter. */
    720       1.90      onoe 	wi_write_multi(sc);
    721       1.84   thorpej 
    722       1.96      onoe 	if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
    723       1.96      onoe 		sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
    724       1.96      onoe 		if (sc->sc_firmware_type == WI_SYMBOL)
    725       1.96      onoe 			sc->sc_buflen = 1585;	/* XXX */
    726       1.96      onoe 		for (i = 0; i < WI_NTXBUF; i++) {
    727       1.96      onoe 			error = wi_alloc_fid(sc, sc->sc_buflen,
    728       1.96      onoe 			    &sc->sc_txd[i].d_fid);
    729       1.96      onoe 			if (error) {
    730       1.96      onoe 				printf("%s: tx buffer allocation failed\n",
    731       1.96      onoe 				    sc->sc_dev.dv_xname);
    732       1.96      onoe 				goto out;
    733       1.96      onoe 			}
    734       1.96      onoe 			DPRINTF2(("wi_init: txbuf %d allocated %x\n", i,
    735       1.96      onoe 			    sc->sc_txd[i].d_fid));
    736       1.96      onoe 			sc->sc_txd[i].d_len = 0;
    737       1.90      onoe 		}
    738       1.84   thorpej 	}
    739       1.92      onoe 	sc->sc_txcur = sc->sc_txnext = 0;
    740       1.84   thorpej 
    741      1.151    dyoung 	wi_rssdescs_init(&sc->sc_rssd, &sc->sc_rssdfree);
    742      1.148    dyoung 
    743      1.118    dyoung 	/* Enable desired port */
    744      1.118    dyoung 	wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
    745       1.90      onoe 	ifp->if_flags |= IFF_RUNNING;
    746       1.90      onoe 	ifp->if_flags &= ~IFF_OACTIVE;
    747      1.133    dyoung 	ic->ic_state = IEEE80211_S_INIT;
    748      1.133    dyoung 
    749       1.91      onoe 	if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
    750      1.112    dyoung 	    ic->ic_opmode == IEEE80211_M_MONITOR ||
    751       1.91      onoe 	    ic->ic_opmode == IEEE80211_M_HOSTAP)
    752      1.133    dyoung 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    753       1.90      onoe 
    754       1.90      onoe 	/* Enable interrupts */
    755       1.90      onoe 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    756       1.84   thorpej 
    757       1.96      onoe 	if (!wasenabled &&
    758       1.96      onoe 	    ic->ic_opmode == IEEE80211_M_HOSTAP &&
    759       1.96      onoe 	    sc->sc_firmware_type == WI_INTERSIL) {
    760       1.90      onoe 		/* XXX: some card need to be re-enabled for hostap */
    761       1.90      onoe 		wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
    762       1.90      onoe 		wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
    763       1.90      onoe 	}
    764       1.84   thorpej 
    765       1.90      onoe 	if (ic->ic_opmode == IEEE80211_M_STA &&
    766       1.90      onoe 	    ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
    767      1.133    dyoung 	    ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
    768       1.90      onoe 		memset(&join, 0, sizeof(join));
    769       1.90      onoe 		if (ic->ic_flags & IEEE80211_F_DESBSSID)
    770       1.90      onoe 			IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
    771      1.133    dyoung 		if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
    772      1.133    dyoung 			join.wi_chan =
    773      1.133    dyoung 			    htole16(ieee80211_chan2ieee(ic, ic->ic_des_chan));
    774      1.106    dyoung 		/* Lucent firmware does not support the JOIN RID. */
    775      1.106    dyoung 		if (sc->sc_firmware_type != WI_LUCENT)
    776      1.106    dyoung 			wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
    777       1.84   thorpej 	}
    778       1.84   thorpej 
    779       1.90      onoe  out:
    780       1.90      onoe 	if (error) {
    781       1.90      onoe 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
    782       1.95      onoe 		wi_stop(ifp, 0);
    783       1.90      onoe 	}
    784       1.90      onoe 	DPRINTF(("wi_init: return %d\n", error));
    785       1.90      onoe 	return error;
    786       1.84   thorpej }
    787       1.84   thorpej 
    788       1.90      onoe static void
    789       1.90      onoe wi_stop(struct ifnet *ifp, int disable)
    790       1.84   thorpej {
    791       1.90      onoe 	struct wi_softc	*sc = ifp->if_softc;
    792      1.133    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
    793      1.151    dyoung 	int s;
    794      1.118    dyoung 
    795      1.127    dyoung 	if (!sc->sc_enabled)
    796      1.127    dyoung 		return;
    797      1.127    dyoung 
    798      1.125    dyoung 	s = splnet();
    799       1.84   thorpej 
    800       1.90      onoe 	DPRINTF(("wi_stop: disable %d\n", disable));
    801      1.127    dyoung 
    802      1.133    dyoung 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    803      1.127    dyoung 	if (!sc->sc_invalid) {
    804       1.90      onoe 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    805      1.118    dyoung 		wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
    806       1.84   thorpej 	}
    807       1.84   thorpej 
    808      1.151    dyoung 	wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
    809      1.151    dyoung 	    &sc->sc_txpending);
    810      1.148    dyoung 
    811       1.90      onoe 	sc->sc_tx_timer = 0;
    812       1.90      onoe 	sc->sc_scan_timer = 0;
    813      1.107    dyoung 	sc->sc_syn_timer = 0;
    814      1.107    dyoung 	sc->sc_false_syns = 0;
    815       1.90      onoe 	sc->sc_naps = 0;
    816       1.90      onoe 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
    817       1.90      onoe 	ifp->if_timer = 0;
    818      1.118    dyoung 
    819      1.127    dyoung 	if (disable) {
    820      1.127    dyoung 		if (sc->sc_disable)
    821      1.127    dyoung 			(*sc->sc_disable)(sc);
    822      1.127    dyoung 		sc->sc_enabled = 0;
    823      1.127    dyoung 	}
    824      1.125    dyoung 	splx(s);
    825       1.90      onoe }
    826       1.84   thorpej 
    827      1.148    dyoung /*
    828      1.148    dyoung  * Choose a data rate for a packet len bytes long that suits the packet
    829      1.153    dyoung  * type and the wireless conditions.
    830      1.148    dyoung  *
    831      1.148    dyoung  * TBD Adapt fragmentation threshold.
    832      1.148    dyoung  */
    833      1.148    dyoung static void
    834      1.148    dyoung wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
    835      1.148    dyoung     struct ieee80211_frame *wh, u_int len)
    836      1.148    dyoung {
    837      1.148    dyoung 	struct wi_softc	*sc = ic->ic_if.if_softc;
    838      1.155    dyoung 	struct wi_node *wn = (void*)ni;
    839      1.155    dyoung 	struct ieee80211_rssadapt *ra = &wn->wn_rssadapt;
    840      1.155    dyoung 	int do_not_adapt, i, rateidx, s;
    841      1.155    dyoung 
    842      1.155    dyoung 	do_not_adapt = (ic->ic_opmode != IEEE80211_M_HOSTAP) &&
    843      1.155    dyoung 	    (sc->sc_flags & WI_FLAGS_RSSADAPTSTA) == 0;
    844      1.148    dyoung 
    845      1.148    dyoung 	s = splnet();
    846      1.148    dyoung 
    847      1.155    dyoung 	rateidx = ieee80211_rssadapt_choose(ra, &ni->ni_rates, wh, len,
    848      1.155    dyoung 	    ic->ic_fixed_rate,
    849      1.155    dyoung 	    ((ic->ic_if.if_flags & IFF_DEBUG) == 0) ? NULL : ic->ic_if.if_xname,
    850      1.155    dyoung 	    do_not_adapt);
    851      1.148    dyoung 
    852      1.148    dyoung 	if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
    853      1.148    dyoung 		/* choose the slowest pending rate so that we don't
    854      1.148    dyoung 		 * accidentally send a packet on the MAC's queue
    855      1.148    dyoung 		 * too fast. TBD find out if the MAC labels Tx
    856      1.148    dyoung 		 * packets w/ rate when enqueued or dequeued.
    857      1.148    dyoung 		 */
    858      1.148    dyoung 		for (i = 0; i < rateidx && sc->sc_txpending[i] == 0; i++);
    859      1.148    dyoung 		ni->ni_txrate = i;
    860      1.148    dyoung 	} else
    861      1.148    dyoung 		ni->ni_txrate = rateidx;
    862      1.148    dyoung 	splx(s);
    863      1.148    dyoung 	return;
    864      1.148    dyoung }
    865      1.148    dyoung 
    866      1.148    dyoung static void
    867      1.148    dyoung wi_raise_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
    868      1.148    dyoung {
    869      1.148    dyoung 	struct wi_node *wn;
    870      1.148    dyoung 	if (id->id_node == NULL)
    871      1.148    dyoung 		return;
    872      1.148    dyoung 
    873      1.148    dyoung 	wn = (void*)id->id_node;
    874      1.148    dyoung 	ieee80211_rssadapt_raise_rate(ic, &wn->wn_rssadapt, id);
    875      1.148    dyoung }
    876      1.148    dyoung 
    877      1.148    dyoung static void
    878      1.148    dyoung wi_lower_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
    879      1.148    dyoung {
    880      1.148    dyoung 	struct ieee80211_node *ni;
    881      1.148    dyoung 	struct wi_node *wn;
    882      1.148    dyoung 	int s;
    883      1.148    dyoung 
    884      1.148    dyoung 	s = splnet();
    885      1.148    dyoung 
    886      1.148    dyoung 	if ((ni = id->id_node) == NULL) {
    887      1.148    dyoung 		DPRINTF(("wi_lower_rate: missing node\n"));
    888      1.148    dyoung 		goto out;
    889      1.148    dyoung 	}
    890      1.148    dyoung 
    891      1.148    dyoung 	wn = (void *)ni;
    892      1.148    dyoung 
    893      1.148    dyoung 	ieee80211_rssadapt_lower_rate(ic, ni, &wn->wn_rssadapt, id);
    894      1.148    dyoung out:
    895      1.148    dyoung 	splx(s);
    896      1.148    dyoung 	return;
    897      1.148    dyoung }
    898      1.148    dyoung 
    899       1.90      onoe static void
    900       1.90      onoe wi_start(struct ifnet *ifp)
    901       1.90      onoe {
    902       1.90      onoe 	struct wi_softc	*sc = ifp->if_softc;
    903       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
    904      1.125    dyoung 	struct ieee80211_node *ni;
    905       1.90      onoe 	struct ieee80211_frame *wh;
    906      1.148    dyoung 	struct ieee80211_rateset *rs;
    907      1.148    dyoung 	struct wi_rssdesc *rd;
    908      1.148    dyoung 	struct ieee80211_rssdesc *id;
    909      1.108    dyoung 	struct mbuf *m0;
    910       1.90      onoe 	struct wi_frame frmhdr;
    911       1.90      onoe 	int cur, fid, off;
    912      1.123    dyoung 
    913      1.127    dyoung 	if (!sc->sc_enabled || sc->sc_invalid)
    914      1.123    dyoung 		return;
    915      1.125    dyoung 	if (sc->sc_flags & WI_FLAGS_OUTRANGE)
    916       1.98      onoe 		return;
    917       1.84   thorpej 
    918       1.90      onoe 	memset(&frmhdr, 0, sizeof(frmhdr));
    919       1.90      onoe 	cur = sc->sc_txnext;
    920       1.90      onoe 	for (;;) {
    921      1.133    dyoung 		ni = ic->ic_bss;
    922      1.116       kml 		if (!IF_IS_EMPTY(&ic->ic_mgtq)) {
    923      1.148    dyoung 			if (sc->sc_txd[cur].d_len != 0 ||
    924      1.148    dyoung 			    SLIST_EMPTY(&sc->sc_rssdfree)) {
    925       1.90      onoe 				ifp->if_flags |= IFF_OACTIVE;
    926       1.90      onoe 				break;
    927       1.90      onoe 			}
    928       1.90      onoe 			IF_DEQUEUE(&ic->ic_mgtq, m0);
    929       1.90      onoe 			m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
    930       1.90      onoe 			    (caddr_t)&frmhdr.wi_ehdr);
    931       1.90      onoe 			frmhdr.wi_ehdr.ether_type = 0;
    932       1.90      onoe                         wh = mtod(m0, struct ieee80211_frame *);
    933      1.141    dyoung 			ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
    934      1.141    dyoung 			m0->m_pkthdr.rcvif = NULL;
    935      1.116       kml 		} else if (!IF_IS_EMPTY(&ic->ic_pwrsaveq)) {
    936      1.116       kml 			struct llc *llc;
    937      1.116       kml 
    938      1.116       kml 			/*
    939      1.116       kml 			 * Should these packets be processed after the
    940      1.116       kml 			 * regular packets or before?  Since they are being
    941      1.116       kml 			 * probed for, they are probably less time critical
    942      1.116       kml 			 * than other packets, but, on the other hand,
    943      1.116       kml 			 * we want the power saving nodes to go back to
    944      1.116       kml 			 * sleep as quickly as possible to save power...
    945      1.116       kml 			 */
    946      1.116       kml 
    947      1.116       kml 			if (ic->ic_state != IEEE80211_S_RUN)
    948      1.116       kml 				break;
    949      1.116       kml 
    950      1.148    dyoung 			if (sc->sc_txd[cur].d_len != 0 ||
    951      1.148    dyoung 			    SLIST_EMPTY(&sc->sc_rssdfree)) {
    952      1.116       kml 				ifp->if_flags |= IFF_OACTIVE;
    953      1.116       kml 				break;
    954      1.116       kml 			}
    955      1.116       kml 			IF_DEQUEUE(&ic->ic_pwrsaveq, m0);
    956      1.116       kml                         wh = mtod(m0, struct ieee80211_frame *);
    957      1.116       kml 			llc = (struct llc *) (wh + 1);
    958      1.116       kml 			m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
    959      1.116       kml 			    (caddr_t)&frmhdr.wi_ehdr);
    960      1.116       kml 			frmhdr.wi_ehdr.ether_type = llc->llc_snap.ether_type;
    961      1.140    dyoung 			ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
    962      1.140    dyoung 			m0->m_pkthdr.rcvif = NULL;
    963       1.90      onoe 		} else {
    964      1.133    dyoung 			if (ic->ic_state != IEEE80211_S_RUN) {
    965       1.90      onoe 				break;
    966      1.133    dyoung 			}
    967       1.90      onoe 			IFQ_POLL(&ifp->if_snd, m0);
    968      1.133    dyoung 			if (m0 == NULL) {
    969       1.90      onoe 				break;
    970      1.133    dyoung 			}
    971      1.148    dyoung 			if (sc->sc_txd[cur].d_len != 0 ||
    972      1.148    dyoung 			    SLIST_EMPTY(&sc->sc_rssdfree)) {
    973       1.90      onoe 				ifp->if_flags |= IFF_OACTIVE;
    974       1.90      onoe 				break;
    975       1.90      onoe 			}
    976       1.90      onoe 			IFQ_DEQUEUE(&ifp->if_snd, m0);
    977       1.90      onoe 			ifp->if_opackets++;
    978       1.90      onoe 			m_copydata(m0, 0, ETHER_HDR_LEN,
    979       1.90      onoe 			    (caddr_t)&frmhdr.wi_ehdr);
    980       1.90      onoe #if NBPFILTER > 0
    981       1.90      onoe 			if (ifp->if_bpf)
    982       1.90      onoe 				bpf_mtap(ifp->if_bpf, m0);
    983       1.90      onoe #endif
    984       1.84   thorpej 
    985      1.133    dyoung 			if ((m0 = ieee80211_encap(ifp, m0, &ni)) == NULL) {
    986       1.90      onoe 				ifp->if_oerrors++;
    987       1.90      onoe 				continue;
    988       1.90      onoe 			}
    989       1.90      onoe                         wh = mtod(m0, struct ieee80211_frame *);
    990      1.116       kml 			if (ic->ic_flags & IEEE80211_F_WEPON)
    991      1.116       kml 				wh->i_fc[1] |= IEEE80211_FC1_WEP;
    992       1.90      onoe 			if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
    993       1.90      onoe 			    !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
    994       1.90      onoe 			    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
    995      1.116       kml 			    IEEE80211_FC0_TYPE_DATA) {
    996      1.133    dyoung 				if (ni->ni_associd == 0) {
    997      1.116       kml 					m_freem(m0);
    998      1.116       kml 					ifp->if_oerrors++;
    999      1.133    dyoung 					goto next;
   1000      1.116       kml 				}
   1001      1.116       kml 				if (ni->ni_pwrsave & IEEE80211_PS_SLEEP) {
   1002      1.116       kml 					ieee80211_pwrsave(ic, ni, m0);
   1003      1.140    dyoung 					continue; /* don't free node. */
   1004      1.116       kml 				}
   1005       1.90      onoe 			}
   1006       1.90      onoe 		}
   1007       1.90      onoe #if NBPFILTER > 0
   1008       1.90      onoe 		if (ic->ic_rawbpf)
   1009       1.90      onoe 			bpf_mtap(ic->ic_rawbpf, m0);
   1010       1.90      onoe #endif
   1011      1.148    dyoung 		frmhdr.wi_tx_ctl =
   1012      1.148    dyoung 		    htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX|WI_TXCNTL_TX_OK);
   1013      1.152    dyoung 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
   1014      1.152    dyoung 			frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_ALTRTRY);
   1015       1.90      onoe 		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
   1016       1.90      onoe 		    (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
   1017       1.90      onoe 			if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
   1018       1.90      onoe 				ifp->if_oerrors++;
   1019      1.133    dyoung 				goto next;
   1020       1.90      onoe 			}
   1021       1.90      onoe 			frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
   1022       1.90      onoe 		}
   1023      1.148    dyoung 
   1024      1.148    dyoung 		wi_choose_rate(ic, ni, wh, m0->m_pkthdr.len);
   1025      1.148    dyoung 
   1026       1.90      onoe #if NBPFILTER > 0
   1027       1.90      onoe 		if (sc->sc_drvbpf) {
   1028       1.90      onoe 			struct mbuf mb;
   1029       1.84   thorpej 
   1030      1.144    dyoung 			struct wi_tx_radiotap_header *tap = &sc->sc_txtap;
   1031      1.144    dyoung 
   1032      1.144    dyoung 			tap->wt_rate = ni->ni_rates.rs_rates[ni->ni_txrate];
   1033      1.150    dyoung 			tap->wt_chan_freq =
   1034      1.150    dyoung 			    htole16(ic->ic_bss->ni_chan->ic_freq);
   1035      1.150    dyoung 			tap->wt_chan_flags =
   1036      1.150    dyoung 			    htole16(ic->ic_bss->ni_chan->ic_flags);
   1037      1.144    dyoung 
   1038      1.150    dyoung 			/* TBD tap->wt_flags */
   1039      1.144    dyoung 
   1040       1.90      onoe 			M_COPY_PKTHDR(&mb, m0);
   1041      1.144    dyoung 			mb.m_data = (caddr_t)tap;
   1042      1.144    dyoung 			mb.m_len = tap->wt_ihdr.it_len;
   1043       1.90      onoe 			mb.m_next = m0;
   1044       1.90      onoe 			mb.m_pkthdr.len += mb.m_len;
   1045       1.90      onoe 			bpf_mtap(sc->sc_drvbpf, &mb);
   1046       1.90      onoe 		}
   1047       1.90      onoe #endif
   1048      1.148    dyoung 		rs = &ni->ni_rates;
   1049      1.148    dyoung 		rd = SLIST_FIRST(&sc->sc_rssdfree);
   1050      1.148    dyoung 		id = &rd->rd_desc;
   1051      1.148    dyoung 		id->id_len = m0->m_pkthdr.len;
   1052      1.148    dyoung 		sc->sc_txd[cur].d_rate = id->id_rateidx = ni->ni_txrate;
   1053      1.148    dyoung 		id->id_rssi = ni->ni_rssi;
   1054      1.148    dyoung 
   1055      1.148    dyoung 		frmhdr.wi_tx_idx = rd - sc->sc_rssd;
   1056      1.148    dyoung 
   1057      1.148    dyoung 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
   1058      1.148    dyoung 			frmhdr.wi_tx_rate = 5 * (rs->rs_rates[ni->ni_txrate] &
   1059      1.148    dyoung 			    IEEE80211_RATE_VAL);
   1060      1.153    dyoung 		else if (sc->sc_flags & WI_FLAGS_RSSADAPTSTA)
   1061      1.148    dyoung 			(void)wi_write_txrate(sc, rs->rs_rates[ni->ni_txrate]);
   1062      1.148    dyoung 
   1063      1.137    dyoung 		m_copydata(m0, 0, sizeof(struct ieee80211_frame),
   1064      1.137    dyoung 		    (caddr_t)&frmhdr.wi_whdr);
   1065      1.137    dyoung 		m_adj(m0, sizeof(struct ieee80211_frame));
   1066      1.137    dyoung 		frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
   1067      1.119    dyoung 		if (IFF_DUMPPKTS(ifp))
   1068      1.119    dyoung 			wi_dump_pkt(&frmhdr, ni, -1);
   1069       1.90      onoe 		fid = sc->sc_txd[cur].d_fid;
   1070       1.90      onoe 		off = sizeof(frmhdr);
   1071      1.108    dyoung 		if (wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0 ||
   1072      1.108    dyoung 		    wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0) {
   1073      1.108    dyoung 			ifp->if_oerrors++;
   1074      1.108    dyoung 			m_freem(m0);
   1075      1.133    dyoung 			goto next;
   1076       1.90      onoe 		}
   1077       1.90      onoe 		m_freem(m0);
   1078       1.90      onoe 		sc->sc_txd[cur].d_len = off;
   1079       1.90      onoe 		if (sc->sc_txcur == cur) {
   1080       1.90      onoe 			if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
   1081       1.90      onoe 				printf("%s: xmit failed\n",
   1082       1.90      onoe 				    sc->sc_dev.dv_xname);
   1083       1.90      onoe 				sc->sc_txd[cur].d_len = 0;
   1084      1.133    dyoung 				goto next;
   1085       1.90      onoe 			}
   1086      1.148    dyoung 			sc->sc_txpending[ni->ni_txrate]++;
   1087       1.90      onoe 			sc->sc_tx_timer = 5;
   1088       1.90      onoe 			ifp->if_timer = 1;
   1089       1.90      onoe 		}
   1090       1.90      onoe 		sc->sc_txnext = cur = (cur + 1) % WI_NTXBUF;
   1091      1.148    dyoung 		SLIST_REMOVE_HEAD(&sc->sc_rssdfree, rd_next);
   1092      1.153    dyoung 		id->id_node = ni;
   1093      1.153    dyoung 		continue;
   1094      1.133    dyoung next:
   1095      1.133    dyoung 		if (ni != NULL && ni != ic->ic_bss)
   1096      1.133    dyoung 			ieee80211_free_node(ic, ni);
   1097       1.84   thorpej 	}
   1098       1.90      onoe }
   1099       1.84   thorpej 
   1100       1.84   thorpej 
   1101       1.84   thorpej static int
   1102       1.90      onoe wi_reset(struct wi_softc *sc)
   1103       1.84   thorpej {
   1104       1.90      onoe 	int i, error;
   1105       1.90      onoe 
   1106       1.90      onoe 	DPRINTF(("wi_reset\n"));
   1107      1.113    dyoung 
   1108      1.113    dyoung 	if (sc->sc_reset)
   1109      1.113    dyoung 		(*sc->sc_reset)(sc);
   1110      1.113    dyoung 
   1111       1.90      onoe 	error = 0;
   1112       1.90      onoe 	for (i = 0; i < 5; i++) {
   1113       1.90      onoe 		DELAY(20*1000);	/* XXX: way too long! */
   1114       1.90      onoe 		if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
   1115       1.90      onoe 			break;
   1116       1.90      onoe 	}
   1117       1.90      onoe 	if (error) {
   1118       1.90      onoe 		printf("%s: init failed\n", sc->sc_dev.dv_xname);
   1119       1.90      onoe 		return error;
   1120       1.84   thorpej 	}
   1121       1.90      onoe 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1122       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
   1123       1.84   thorpej 
   1124       1.90      onoe 	/* Calibrate timer. */
   1125       1.90      onoe 	wi_write_val(sc, WI_RID_TICK_TIME, 0);
   1126       1.90      onoe 	return 0;
   1127       1.90      onoe }
   1128       1.84   thorpej 
   1129       1.90      onoe static void
   1130       1.90      onoe wi_watchdog(struct ifnet *ifp)
   1131       1.90      onoe {
   1132       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
   1133      1.133    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   1134       1.84   thorpej 
   1135       1.90      onoe 	ifp->if_timer = 0;
   1136       1.90      onoe 	if (!sc->sc_enabled)
   1137       1.90      onoe 		return;
   1138       1.84   thorpej 
   1139       1.90      onoe 	if (sc->sc_tx_timer) {
   1140       1.90      onoe 		if (--sc->sc_tx_timer == 0) {
   1141       1.90      onoe 			printf("%s: device timeout\n", ifp->if_xname);
   1142       1.90      onoe 			ifp->if_oerrors++;
   1143       1.90      onoe 			wi_init(ifp);
   1144       1.90      onoe 			return;
   1145       1.90      onoe 		}
   1146       1.90      onoe 		ifp->if_timer = 1;
   1147       1.90      onoe 	}
   1148       1.84   thorpej 
   1149       1.90      onoe 	if (sc->sc_scan_timer) {
   1150       1.90      onoe 		if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
   1151       1.90      onoe 		    sc->sc_firmware_type == WI_INTERSIL) {
   1152       1.90      onoe 			DPRINTF(("wi_watchdog: inquire scan\n"));
   1153       1.90      onoe 			wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
   1154       1.90      onoe 		}
   1155       1.90      onoe 		if (sc->sc_scan_timer)
   1156       1.90      onoe 			ifp->if_timer = 1;
   1157       1.90      onoe 	}
   1158       1.84   thorpej 
   1159      1.107    dyoung 	if (sc->sc_syn_timer) {
   1160      1.107    dyoung 		if (--sc->sc_syn_timer == 0) {
   1161      1.107    dyoung 			DPRINTF2(("%s: %d false syns\n",
   1162      1.107    dyoung 			    sc->sc_dev.dv_xname, sc->sc_false_syns));
   1163      1.107    dyoung 			sc->sc_false_syns = 0;
   1164      1.133    dyoung 			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
   1165      1.107    dyoung 			sc->sc_syn_timer = 5;
   1166      1.107    dyoung 		}
   1167      1.107    dyoung 		ifp->if_timer = 1;
   1168      1.107    dyoung 	}
   1169      1.107    dyoung 
   1170       1.90      onoe 	/* TODO: rate control */
   1171       1.90      onoe 	ieee80211_watchdog(ifp);
   1172       1.84   thorpej }
   1173       1.84   thorpej 
   1174       1.90      onoe static int
   1175       1.90      onoe wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
   1176        1.1    ichiro {
   1177       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
   1178       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1179       1.90      onoe 	struct ifreq *ifr = (struct ifreq *)data;
   1180      1.125    dyoung 	int s, error = 0;
   1181        1.1    ichiro 
   1182       1.90      onoe 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1183       1.90      onoe 		return ENXIO;
   1184        1.1    ichiro 
   1185      1.125    dyoung 	s = splnet();
   1186        1.1    ichiro 
   1187       1.90      onoe 	switch (cmd) {
   1188        1.1    ichiro 	case SIOCSIFFLAGS:
   1189      1.123    dyoung 		/*
   1190      1.123    dyoung 		 * Can't do promisc and hostap at the same time.  If all that's
   1191      1.123    dyoung 		 * changing is the promisc flag, try to short-circuit a call to
   1192      1.123    dyoung 		 * wi_init() by just setting PROMISC in the hardware.
   1193      1.123    dyoung 		 */
   1194        1.3    ichiro 		if (ifp->if_flags & IFF_UP) {
   1195       1.90      onoe 			if (sc->sc_enabled) {
   1196       1.90      onoe 				if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
   1197       1.90      onoe 				    (ifp->if_flags & IFF_PROMISC) != 0)
   1198       1.90      onoe 					wi_write_val(sc, WI_RID_PROMISC, 1);
   1199       1.90      onoe 				else
   1200       1.90      onoe 					wi_write_val(sc, WI_RID_PROMISC, 0);
   1201       1.79   thorpej 			} else
   1202       1.90      onoe 				error = wi_init(ifp);
   1203       1.90      onoe 		} else if (sc->sc_enabled)
   1204       1.90      onoe 			wi_stop(ifp, 1);
   1205       1.90      onoe 		break;
   1206       1.90      onoe 	case SIOCSIFMEDIA:
   1207       1.90      onoe 	case SIOCGIFMEDIA:
   1208      1.132    dyoung 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
   1209        1.1    ichiro 		break;
   1210        1.1    ichiro 	case SIOCADDMULTI:
   1211        1.1    ichiro 	case SIOCDELMULTI:
   1212       1.90      onoe 		error = (cmd == SIOCADDMULTI) ?
   1213       1.90      onoe 		    ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
   1214       1.90      onoe 		    ether_delmulti(ifr, &sc->sc_ic.ic_ec);
   1215        1.1    ichiro 		if (error == ENETRESET) {
   1216       1.90      onoe 			if (sc->sc_enabled) {
   1217       1.90      onoe 				/* do not rescan */
   1218       1.90      onoe 				error = wi_write_multi(sc);
   1219       1.90      onoe 			} else
   1220       1.90      onoe 				error = 0;
   1221        1.1    ichiro 		}
   1222        1.1    ichiro 		break;
   1223       1.90      onoe 	case SIOCGIFGENERIC:
   1224       1.90      onoe 		error = wi_get_cfg(ifp, cmd, data);
   1225        1.1    ichiro 		break;
   1226       1.90      onoe 	case SIOCSIFGENERIC:
   1227       1.90      onoe 		error = suser(curproc->p_ucred, &curproc->p_acflag);
   1228        1.1    ichiro 		if (error)
   1229        1.1    ichiro 			break;
   1230       1.90      onoe 		error = wi_set_cfg(ifp, cmd, data);
   1231       1.90      onoe 		if (error == ENETRESET) {
   1232       1.90      onoe 			if (sc->sc_enabled)
   1233       1.90      onoe 				error = wi_init(ifp);
   1234        1.1    ichiro 			else
   1235       1.90      onoe 				error = 0;
   1236        1.1    ichiro 		}
   1237        1.1    ichiro 		break;
   1238      1.106    dyoung 	case SIOCS80211BSSID:
   1239      1.106    dyoung 		if (sc->sc_firmware_type == WI_LUCENT) {
   1240      1.106    dyoung 			error = ENODEV;
   1241      1.106    dyoung 			break;
   1242      1.106    dyoung 		}
   1243      1.106    dyoung 		/* fall through */
   1244       1.90      onoe 	default:
   1245       1.90      onoe 		error = ieee80211_ioctl(ifp, cmd, data);
   1246       1.90      onoe 		if (error == ENETRESET) {
   1247       1.49       dbj 			if (sc->sc_enabled)
   1248       1.90      onoe 				error = wi_init(ifp);
   1249       1.90      onoe 			else
   1250       1.90      onoe 				error = 0;
   1251        1.1    ichiro 		}
   1252        1.1    ichiro 		break;
   1253        1.1    ichiro 	}
   1254      1.125    dyoung 	splx(s);
   1255       1.90      onoe 	return error;
   1256        1.1    ichiro }
   1257        1.1    ichiro 
   1258        1.1    ichiro static int
   1259       1.90      onoe wi_media_change(struct ifnet *ifp)
   1260        1.1    ichiro {
   1261        1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   1262       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1263  1.159.2.1       jdc 	int error;
   1264  1.159.2.1       jdc 
   1265  1.159.2.1       jdc 	error = ieee80211_media_change(ifp);
   1266       1.90      onoe 	if (error == ENETRESET) {
   1267       1.90      onoe 		if (sc->sc_enabled)
   1268       1.90      onoe 			error = wi_init(ifp);
   1269       1.90      onoe 		else
   1270       1.90      onoe 			error = 0;
   1271       1.90      onoe 	}
   1272      1.132    dyoung 	ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media);
   1273       1.84   thorpej 
   1274       1.91      onoe 	return error;
   1275       1.90      onoe }
   1276       1.84   thorpej 
   1277       1.90      onoe static void
   1278       1.90      onoe wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
   1279       1.90      onoe {
   1280       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
   1281       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1282       1.90      onoe 	u_int16_t val;
   1283       1.90      onoe 	int rate, len;
   1284       1.84   thorpej 
   1285       1.90      onoe 	if (sc->sc_enabled == 0) {
   1286       1.90      onoe 		imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
   1287       1.90      onoe 		imr->ifm_status = 0;
   1288       1.90      onoe 		return;
   1289       1.90      onoe 	}
   1290       1.84   thorpej 
   1291       1.90      onoe 	imr->ifm_status = IFM_AVALID;
   1292       1.90      onoe 	imr->ifm_active = IFM_IEEE80211;
   1293       1.98      onoe 	if (ic->ic_state == IEEE80211_S_RUN &&
   1294       1.98      onoe 	    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
   1295       1.90      onoe 		imr->ifm_status |= IFM_ACTIVE;
   1296       1.98      onoe 	len = sizeof(val);
   1297       1.98      onoe 	if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) != 0)
   1298       1.98      onoe 		rate = 0;
   1299       1.90      onoe 	else {
   1300       1.98      onoe 		/* convert to 802.11 rate */
   1301      1.146    dyoung 		val = le16toh(val);
   1302       1.98      onoe 		rate = val * 2;
   1303       1.98      onoe 		if (sc->sc_firmware_type == WI_LUCENT) {
   1304       1.98      onoe 			if (rate == 10)
   1305       1.98      onoe 				rate = 11;	/* 5.5Mbps */
   1306       1.98      onoe 		} else {
   1307       1.98      onoe 			if (rate == 4*2)
   1308       1.98      onoe 				rate = 11;	/* 5.5Mbps */
   1309       1.98      onoe 			else if (rate == 8*2)
   1310       1.98      onoe 				rate = 22;	/* 11Mbps */
   1311       1.90      onoe 		}
   1312       1.90      onoe 	}
   1313      1.133    dyoung 	imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
   1314       1.90      onoe 	switch (ic->ic_opmode) {
   1315       1.90      onoe 	case IEEE80211_M_STA:
   1316       1.90      onoe 		break;
   1317       1.91      onoe 	case IEEE80211_M_IBSS:
   1318       1.90      onoe 		imr->ifm_active |= IFM_IEEE80211_ADHOC;
   1319       1.91      onoe 		break;
   1320       1.91      onoe 	case IEEE80211_M_AHDEMO:
   1321       1.91      onoe 		imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
   1322       1.90      onoe 		break;
   1323       1.90      onoe 	case IEEE80211_M_HOSTAP:
   1324       1.90      onoe 		imr->ifm_active |= IFM_IEEE80211_HOSTAP;
   1325       1.90      onoe 		break;
   1326      1.112    dyoung 	case IEEE80211_M_MONITOR:
   1327      1.112    dyoung 		imr->ifm_active |= IFM_IEEE80211_MONITOR;
   1328      1.112    dyoung 		break;
   1329       1.90      onoe 	}
   1330       1.90      onoe }
   1331       1.84   thorpej 
   1332      1.148    dyoung static struct ieee80211_node *
   1333      1.148    dyoung wi_node_alloc(struct ieee80211com *ic)
   1334      1.148    dyoung {
   1335      1.148    dyoung 	struct wi_node *wn =
   1336      1.148    dyoung 	    malloc(sizeof(struct wi_node), M_DEVBUF, M_NOWAIT | M_ZERO);
   1337      1.148    dyoung 	return wn ? &wn->wn_node : NULL;
   1338      1.148    dyoung }
   1339      1.148    dyoung 
   1340      1.148    dyoung static void
   1341      1.148    dyoung wi_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
   1342      1.148    dyoung {
   1343      1.148    dyoung 	struct wi_softc *sc = ic->ic_if.if_softc;
   1344      1.148    dyoung 	int i;
   1345      1.148    dyoung 
   1346      1.148    dyoung 	for (i = 0; i < WI_NTXRSS; i++) {
   1347      1.148    dyoung 		if (sc->sc_rssd[i].rd_desc.id_node == ni)
   1348      1.148    dyoung 			sc->sc_rssd[i].rd_desc.id_node = NULL;
   1349      1.148    dyoung 	}
   1350      1.148    dyoung 	free(ni, M_DEVBUF);
   1351      1.148    dyoung }
   1352      1.148    dyoung 
   1353      1.148    dyoung static void
   1354      1.148    dyoung wi_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
   1355      1.148    dyoung     const struct ieee80211_node *src)
   1356      1.148    dyoung {
   1357      1.148    dyoung 	*(struct wi_node *)dst = *(const struct wi_node *)src;
   1358      1.148    dyoung }
   1359      1.148    dyoung 
   1360       1.90      onoe static void
   1361      1.107    dyoung wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
   1362      1.107    dyoung {
   1363      1.107    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   1364      1.133    dyoung 	struct ieee80211_node *ni = ic->ic_bss;
   1365      1.107    dyoung 	struct ifnet *ifp = &ic->ic_if;
   1366      1.107    dyoung 
   1367      1.107    dyoung 	if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
   1368      1.107    dyoung 		return;
   1369      1.107    dyoung 
   1370      1.123    dyoung 	DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
   1371      1.107    dyoung 	DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
   1372      1.107    dyoung 
   1373      1.107    dyoung 	/* In promiscuous mode, the BSSID field is not a reliable
   1374      1.107    dyoung 	 * indicator of the firmware's BSSID. Damp spurious
   1375      1.107    dyoung 	 * change-of-BSSID indications.
   1376      1.107    dyoung 	 */
   1377      1.107    dyoung 	if ((ifp->if_flags & IFF_PROMISC) != 0 &&
   1378      1.107    dyoung 	    sc->sc_false_syns >= WI_MAX_FALSE_SYNS)
   1379      1.107    dyoung 		return;
   1380      1.107    dyoung 
   1381      1.133    dyoung 	ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
   1382      1.107    dyoung }
   1383      1.107    dyoung 
   1384      1.148    dyoung static __inline void
   1385      1.148    dyoung wi_rssadapt_input(struct ieee80211com *ic, struct ieee80211_node *ni,
   1386      1.148    dyoung     struct ieee80211_frame *wh, int rssi)
   1387      1.148    dyoung {
   1388      1.148    dyoung 	struct wi_node *wn;
   1389      1.148    dyoung 
   1390      1.148    dyoung 	if (ni == NULL) {
   1391      1.148    dyoung 		printf("%s: null node", __func__);
   1392      1.148    dyoung 		return;
   1393      1.148    dyoung 	}
   1394      1.148    dyoung 
   1395      1.148    dyoung 	wn = (void*)ni;
   1396      1.148    dyoung 	ieee80211_rssadapt_input(ic, ni, &wn->wn_rssadapt, rssi);
   1397      1.148    dyoung }
   1398      1.148    dyoung 
   1399      1.107    dyoung static void
   1400       1.90      onoe wi_rx_intr(struct wi_softc *sc)
   1401       1.90      onoe {
   1402       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1403       1.90      onoe 	struct ifnet *ifp = &ic->ic_if;
   1404      1.133    dyoung 	struct ieee80211_node *ni;
   1405       1.90      onoe 	struct wi_frame frmhdr;
   1406       1.90      onoe 	struct mbuf *m;
   1407       1.90      onoe 	struct ieee80211_frame *wh;
   1408       1.96      onoe 	int fid, len, off, rssi;
   1409      1.107    dyoung 	u_int8_t dir;
   1410       1.90      onoe 	u_int16_t status;
   1411       1.96      onoe 	u_int32_t rstamp;
   1412        1.1    ichiro 
   1413       1.90      onoe 	fid = CSR_READ_2(sc, WI_RX_FID);
   1414        1.1    ichiro 
   1415       1.90      onoe 	/* First read in the frame header */
   1416       1.90      onoe 	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
   1417       1.90      onoe 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1418       1.90      onoe 		ifp->if_ierrors++;
   1419       1.90      onoe 		DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
   1420       1.90      onoe 		return;
   1421        1.1    ichiro 	}
   1422      1.120    dyoung 
   1423      1.120    dyoung 	if (IFF_DUMPPKTS(ifp))
   1424      1.120    dyoung 		wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
   1425        1.1    ichiro 
   1426        1.1    ichiro 	/*
   1427       1.90      onoe 	 * Drop undecryptable or packets with receive errors here
   1428        1.1    ichiro 	 */
   1429       1.90      onoe 	status = le16toh(frmhdr.wi_status);
   1430      1.148    dyoung 	if ((status & WI_STAT_ERRSTAT) != 0 &&
   1431      1.148    dyoung 	    ic->ic_opmode != IEEE80211_M_MONITOR) {
   1432       1.90      onoe 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1433       1.90      onoe 		ifp->if_ierrors++;
   1434       1.90      onoe 		DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
   1435       1.90      onoe 		return;
   1436       1.90      onoe 	}
   1437       1.96      onoe 	rssi = frmhdr.wi_rx_signal;
   1438       1.96      onoe 	rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
   1439       1.96      onoe 	    le16toh(frmhdr.wi_rx_tstamp1);
   1440        1.1    ichiro 
   1441       1.90      onoe 	len = le16toh(frmhdr.wi_dat_len);
   1442       1.90      onoe 	off = ALIGN(sizeof(struct ieee80211_frame));
   1443        1.1    ichiro 
   1444      1.112    dyoung 	/* Sometimes the PRISM2.x returns bogusly large frames. Except
   1445      1.112    dyoung 	 * in monitor mode, just throw them away.
   1446      1.112    dyoung 	 */
   1447      1.108    dyoung 	if (off + len > MCLBYTES) {
   1448      1.112    dyoung 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
   1449      1.112    dyoung 			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1450      1.112    dyoung 			ifp->if_ierrors++;
   1451      1.112    dyoung 			DPRINTF(("wi_rx_intr: oversized packet\n"));
   1452      1.112    dyoung 			return;
   1453      1.112    dyoung 		} else
   1454      1.112    dyoung 			len = 0;
   1455      1.108    dyoung 	}
   1456      1.108    dyoung 
   1457       1.90      onoe 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1458       1.90      onoe 	if (m == NULL) {
   1459       1.90      onoe 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1460       1.90      onoe 		ifp->if_ierrors++;
   1461       1.90      onoe 		DPRINTF(("wi_rx_intr: MGET failed\n"));
   1462       1.90      onoe 		return;
   1463       1.90      onoe 	}
   1464       1.90      onoe 	if (off + len > MHLEN) {
   1465       1.90      onoe 		MCLGET(m, M_DONTWAIT);
   1466       1.90      onoe 		if ((m->m_flags & M_EXT) == 0) {
   1467       1.90      onoe 			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1468       1.90      onoe 			m_freem(m);
   1469       1.90      onoe 			ifp->if_ierrors++;
   1470       1.90      onoe 			DPRINTF(("wi_rx_intr: MCLGET failed\n"));
   1471       1.90      onoe 			return;
   1472       1.90      onoe 		}
   1473       1.90      onoe 	}
   1474        1.1    ichiro 
   1475       1.90      onoe 	m->m_data += off - sizeof(struct ieee80211_frame);
   1476       1.90      onoe 	memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
   1477       1.90      onoe 	wi_read_bap(sc, fid, sizeof(frmhdr),
   1478       1.90      onoe 	    m->m_data + sizeof(struct ieee80211_frame), len);
   1479       1.90      onoe 	m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
   1480       1.90      onoe 	m->m_pkthdr.rcvif = ifp;
   1481        1.1    ichiro 
   1482       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
   1483        1.1    ichiro 
   1484       1.90      onoe #if NBPFILTER > 0
   1485       1.90      onoe 	if (sc->sc_drvbpf) {
   1486       1.90      onoe 		struct mbuf mb;
   1487      1.144    dyoung 		struct wi_rx_radiotap_header *tap = &sc->sc_rxtap;
   1488      1.144    dyoung 
   1489      1.144    dyoung 		tap->wr_rate = frmhdr.wi_rx_rate / 5;
   1490      1.144    dyoung 		tap->wr_antsignal = WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_signal);
   1491      1.144    dyoung 		tap->wr_antnoise = WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_silence);
   1492      1.144    dyoung 
   1493      1.150    dyoung 		tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
   1494      1.150    dyoung 		tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
   1495      1.144    dyoung 		if (frmhdr.wi_status & WI_STAT_PCF)
   1496      1.144    dyoung 			tap->wr_flags |= IEEE80211_RADIOTAP_F_CFP;
   1497        1.1    ichiro 
   1498       1.90      onoe 		M_COPY_PKTHDR(&mb, m);
   1499      1.144    dyoung 		mb.m_data = (caddr_t)tap;
   1500      1.144    dyoung 		mb.m_len = tap->wr_ihdr.it_len;
   1501       1.90      onoe 		mb.m_next = m;
   1502       1.90      onoe 		mb.m_pkthdr.len += mb.m_len;
   1503       1.90      onoe 		bpf_mtap(sc->sc_drvbpf, &mb);
   1504       1.90      onoe 	}
   1505       1.84   thorpej #endif
   1506       1.90      onoe 	wh = mtod(m, struct ieee80211_frame *);
   1507       1.90      onoe 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
   1508       1.90      onoe 		/*
   1509       1.90      onoe 		 * WEP is decrypted by hardware. Clear WEP bit
   1510       1.90      onoe 		 * header for ieee80211_input().
   1511       1.90      onoe 		 */
   1512       1.90      onoe 		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
   1513        1.1    ichiro 	}
   1514      1.107    dyoung 
   1515      1.107    dyoung 	/* synchronize driver's BSSID with firmware's BSSID */
   1516      1.107    dyoung 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
   1517      1.107    dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
   1518      1.107    dyoung 		wi_sync_bssid(sc, wh->i_addr3);
   1519      1.107    dyoung 
   1520      1.143    dyoung 	ni = ieee80211_find_rxnode(ic, wh);
   1521      1.133    dyoung 
   1522      1.133    dyoung 	ieee80211_input(ifp, m, ni, rssi, rstamp);
   1523      1.133    dyoung 
   1524      1.148    dyoung 	wi_rssadapt_input(ic, ni, wh, rssi);
   1525      1.148    dyoung 
   1526      1.133    dyoung 	/*
   1527      1.133    dyoung 	 * The frame may have caused the node to be marked for
   1528      1.133    dyoung 	 * reclamation (e.g. in response to a DEAUTH message)
   1529      1.133    dyoung 	 * so use free_node here instead of unref_node.
   1530      1.133    dyoung 	 */
   1531      1.133    dyoung 	if (ni == ic->ic_bss)
   1532      1.133    dyoung 		ieee80211_unref_node(&ni);
   1533      1.133    dyoung 	else
   1534      1.133    dyoung 		ieee80211_free_node(ic, ni);
   1535      1.121    dyoung }
   1536      1.121    dyoung 
   1537      1.121    dyoung static void
   1538      1.121    dyoung wi_tx_ex_intr(struct wi_softc *sc)
   1539      1.121    dyoung {
   1540      1.121    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   1541      1.121    dyoung 	struct ifnet *ifp = &ic->ic_if;
   1542      1.148    dyoung 	struct ieee80211_node *ni;
   1543      1.148    dyoung 	struct ieee80211_rssdesc *id;
   1544      1.148    dyoung 	struct wi_rssdesc *rssd;
   1545      1.121    dyoung 	struct wi_frame frmhdr;
   1546      1.121    dyoung 	int fid;
   1547      1.148    dyoung 	u_int16_t status;
   1548      1.121    dyoung 
   1549      1.121    dyoung 	fid = CSR_READ_2(sc, WI_TX_CMP_FID);
   1550      1.121    dyoung 	/* Read in the frame header */
   1551      1.148    dyoung 	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
   1552      1.154    dyoung 		printf("%s: %s read fid %x failed\n", sc->sc_dev.dv_xname,
   1553      1.154    dyoung 		    __func__, fid);
   1554      1.154    dyoung 		wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
   1555      1.154    dyoung 		    &sc->sc_txpending);
   1556      1.154    dyoung 		goto out;
   1557      1.148    dyoung 	}
   1558      1.121    dyoung 
   1559      1.148    dyoung 	if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
   1560      1.154    dyoung 		printf("%s: %s bad idx %02x\n",
   1561      1.154    dyoung 		    sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
   1562      1.154    dyoung 		wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
   1563      1.154    dyoung 		    &sc->sc_txpending);
   1564      1.154    dyoung 		goto out;
   1565      1.148    dyoung 	}
   1566      1.148    dyoung 
   1567      1.148    dyoung 	status = le16toh(frmhdr.wi_status);
   1568      1.148    dyoung 
   1569      1.148    dyoung 	/*
   1570      1.148    dyoung 	 * Spontaneous station disconnects appear as xmit
   1571      1.148    dyoung 	 * errors.  Don't announce them and/or count them
   1572      1.148    dyoung 	 * as an output error.
   1573      1.148    dyoung 	 */
   1574      1.148    dyoung 	if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
   1575      1.148    dyoung 		printf("%s: tx failed", sc->sc_dev.dv_xname);
   1576      1.148    dyoung 		if (status & WI_TXSTAT_RET_ERR)
   1577      1.148    dyoung 			printf(", retry limit exceeded");
   1578      1.148    dyoung 		if (status & WI_TXSTAT_AGED_ERR)
   1579      1.148    dyoung 			printf(", max transmit lifetime exceeded");
   1580      1.148    dyoung 		if (status & WI_TXSTAT_DISCONNECT)
   1581      1.148    dyoung 			printf(", port disconnected");
   1582      1.148    dyoung 		if (status & WI_TXSTAT_FORM_ERR)
   1583      1.148    dyoung 			printf(", invalid format (data len %u src %s)",
   1584      1.148    dyoung 				le16toh(frmhdr.wi_dat_len),
   1585      1.148    dyoung 				ether_sprintf(frmhdr.wi_ehdr.ether_shost));
   1586      1.148    dyoung 		if (status & ~0xf)
   1587      1.148    dyoung 			printf(", status=0x%x", status);
   1588      1.148    dyoung 		printf("\n");
   1589      1.148    dyoung 	}
   1590      1.148    dyoung 	ifp->if_oerrors++;
   1591      1.148    dyoung 	rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
   1592      1.148    dyoung 	id = &rssd->rd_desc;
   1593      1.148    dyoung 	if ((status & WI_TXSTAT_RET_ERR) != 0)
   1594      1.148    dyoung 		wi_lower_rate(ic, id);
   1595      1.148    dyoung 
   1596      1.148    dyoung 	ni = id->id_node;
   1597      1.148    dyoung 	id->id_node = NULL;
   1598      1.148    dyoung 
   1599      1.154    dyoung 	if (ni == NULL) {
   1600      1.154    dyoung 		printf("%s: %s null node, rssdesc %02x\n",
   1601      1.154    dyoung 		    sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
   1602      1.154    dyoung 		goto out;
   1603      1.154    dyoung 	}
   1604      1.154    dyoung 
   1605      1.148    dyoung 	if (sc->sc_txpending[id->id_rateidx]-- == 0) {
   1606      1.154    dyoung 	        printf("%s: %s txpending[%i] wraparound", sc->sc_dev.dv_xname,
   1607      1.154    dyoung 		    __func__, id->id_rateidx);
   1608      1.148    dyoung 		sc->sc_txpending[id->id_rateidx] = 0;
   1609      1.148    dyoung 	}
   1610      1.148    dyoung 	if (ni != NULL && ni != ic->ic_bss)
   1611      1.148    dyoung 		ieee80211_free_node(ic, ni);
   1612      1.148    dyoung 	SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
   1613      1.154    dyoung out:
   1614      1.148    dyoung 	ifp->if_flags &= ~IFF_OACTIVE;
   1615      1.121    dyoung 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
   1616        1.1    ichiro }
   1617        1.1    ichiro 
   1618        1.1    ichiro static void
   1619      1.148    dyoung wi_txalloc_intr(struct wi_softc *sc)
   1620        1.1    ichiro {
   1621       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1622       1.90      onoe 	struct ifnet *ifp = &ic->ic_if;
   1623       1.90      onoe 	int fid, cur;
   1624        1.1    ichiro 
   1625       1.90      onoe 	fid = CSR_READ_2(sc, WI_ALLOC_FID);
   1626       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1627       1.79   thorpej 
   1628       1.90      onoe 	cur = sc->sc_txcur;
   1629       1.90      onoe 	if (sc->sc_txd[cur].d_fid != fid) {
   1630       1.96      onoe 		printf("%s: bad alloc %x != %x, cur %d nxt %d\n",
   1631       1.96      onoe 		    sc->sc_dev.dv_xname, fid, sc->sc_txd[cur].d_fid, cur,
   1632       1.96      onoe 		    sc->sc_txnext);
   1633       1.84   thorpej 		return;
   1634       1.90      onoe 	}
   1635       1.90      onoe 	sc->sc_tx_timer = 0;
   1636       1.90      onoe 	sc->sc_txd[cur].d_len = 0;
   1637       1.90      onoe 	sc->sc_txcur = cur = (cur + 1) % WI_NTXBUF;
   1638       1.90      onoe 	if (sc->sc_txd[cur].d_len == 0)
   1639       1.90      onoe 		ifp->if_flags &= ~IFF_OACTIVE;
   1640       1.90      onoe 	else {
   1641       1.90      onoe 		if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
   1642       1.90      onoe 		    0, 0)) {
   1643       1.90      onoe 			printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   1644       1.90      onoe 			sc->sc_txd[cur].d_len = 0;
   1645       1.90      onoe 		} else {
   1646      1.148    dyoung 			sc->sc_txpending[sc->sc_txd[cur].d_rate]++;
   1647       1.90      onoe 			sc->sc_tx_timer = 5;
   1648       1.90      onoe 			ifp->if_timer = 1;
   1649        1.4    ichiro 		}
   1650        1.1    ichiro 	}
   1651        1.1    ichiro }
   1652        1.1    ichiro 
   1653       1.11    tsubai static void
   1654      1.148    dyoung wi_tx_intr(struct wi_softc *sc)
   1655      1.148    dyoung {
   1656      1.148    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   1657      1.148    dyoung 	struct ifnet *ifp = &ic->ic_if;
   1658      1.148    dyoung 	struct ieee80211_node *ni;
   1659      1.148    dyoung 	struct ieee80211_rssdesc *id;
   1660      1.148    dyoung 	struct wi_rssdesc *rssd;
   1661      1.148    dyoung 	struct wi_frame frmhdr;
   1662      1.148    dyoung 	int fid;
   1663      1.148    dyoung 
   1664      1.148    dyoung 	fid = CSR_READ_2(sc, WI_TX_CMP_FID);
   1665      1.148    dyoung 	/* Read in the frame header */
   1666      1.148    dyoung 	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
   1667      1.154    dyoung 		printf("%s: %s read fid %x failed\n", sc->sc_dev.dv_xname,
   1668      1.154    dyoung 		    __func__, fid);
   1669      1.154    dyoung 		wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
   1670      1.154    dyoung 		    &sc->sc_txpending);
   1671      1.148    dyoung 		goto out;
   1672      1.148    dyoung 	}
   1673      1.148    dyoung 
   1674      1.148    dyoung 	if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
   1675      1.154    dyoung 		printf("%s: %s bad idx %02x\n",
   1676      1.154    dyoung 		    sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
   1677      1.154    dyoung 		wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
   1678      1.154    dyoung 		    &sc->sc_txpending);
   1679      1.148    dyoung 		goto out;
   1680      1.148    dyoung 	}
   1681      1.148    dyoung 
   1682      1.148    dyoung 	rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
   1683      1.148    dyoung 	id = &rssd->rd_desc;
   1684      1.148    dyoung 	wi_raise_rate(ic, id);
   1685      1.148    dyoung 
   1686      1.148    dyoung 	ni = id->id_node;
   1687      1.148    dyoung 	id->id_node = NULL;
   1688      1.148    dyoung 
   1689      1.154    dyoung 	if (ni == NULL) {
   1690      1.154    dyoung 		printf("%s: %s null node, rssdesc %02x\n",
   1691      1.154    dyoung 		    sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
   1692      1.154    dyoung 		goto out;
   1693      1.154    dyoung 	}
   1694      1.154    dyoung 
   1695      1.148    dyoung 	if (sc->sc_txpending[id->id_rateidx]-- == 0) {
   1696      1.154    dyoung 	        printf("%s: %s txpending[%i] wraparound", sc->sc_dev.dv_xname,
   1697      1.154    dyoung 		    __func__, id->id_rateidx);
   1698      1.148    dyoung 		sc->sc_txpending[id->id_rateidx] = 0;
   1699      1.148    dyoung 	}
   1700      1.148    dyoung 	if (ni != NULL && ni != ic->ic_bss)
   1701      1.148    dyoung 		ieee80211_free_node(ic, ni);
   1702      1.148    dyoung 	SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
   1703      1.154    dyoung out:
   1704      1.148    dyoung 	ifp->if_flags &= ~IFF_OACTIVE;
   1705      1.148    dyoung 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
   1706      1.148    dyoung }
   1707      1.148    dyoung 
   1708      1.148    dyoung static void
   1709       1.90      onoe wi_info_intr(struct wi_softc *sc)
   1710        1.1    ichiro {
   1711       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1712       1.90      onoe 	struct ifnet *ifp = &ic->ic_if;
   1713       1.90      onoe 	int i, fid, len, off;
   1714       1.90      onoe 	u_int16_t ltbuf[2];
   1715       1.90      onoe 	u_int16_t stat;
   1716       1.90      onoe 	u_int32_t *ptr;
   1717       1.90      onoe 
   1718       1.90      onoe 	fid = CSR_READ_2(sc, WI_INFO_FID);
   1719       1.90      onoe 	wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
   1720       1.90      onoe 
   1721       1.90      onoe 	switch (le16toh(ltbuf[1])) {
   1722       1.90      onoe 
   1723       1.90      onoe 	case WI_INFO_LINK_STAT:
   1724       1.90      onoe 		wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
   1725       1.90      onoe 		DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
   1726       1.90      onoe 		switch (le16toh(stat)) {
   1727       1.90      onoe 		case CONNECTED:
   1728       1.98      onoe 			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
   1729       1.99      onoe 			if (ic->ic_state == IEEE80211_S_RUN &&
   1730       1.99      onoe 			    ic->ic_opmode != IEEE80211_M_IBSS)
   1731       1.90      onoe 				break;
   1732       1.90      onoe 			/* FALLTHROUGH */
   1733       1.90      onoe 		case AP_CHANGE:
   1734      1.133    dyoung 			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
   1735       1.94      onoe 			break;
   1736       1.90      onoe 		case AP_IN_RANGE:
   1737       1.98      onoe 			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
   1738       1.90      onoe 			break;
   1739       1.90      onoe 		case AP_OUT_OF_RANGE:
   1740       1.90      onoe 			if (sc->sc_firmware_type == WI_SYMBOL &&
   1741       1.90      onoe 			    sc->sc_scan_timer > 0) {
   1742       1.90      onoe 				if (wi_cmd(sc, WI_CMD_INQUIRE,
   1743       1.90      onoe 				    WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
   1744       1.90      onoe 					sc->sc_scan_timer = 0;
   1745       1.90      onoe 				break;
   1746       1.90      onoe 			}
   1747       1.98      onoe 			if (ic->ic_opmode == IEEE80211_M_STA)
   1748       1.98      onoe 				sc->sc_flags |= WI_FLAGS_OUTRANGE;
   1749       1.98      onoe 			break;
   1750       1.90      onoe 		case DISCONNECTED:
   1751       1.90      onoe 		case ASSOC_FAILED:
   1752       1.91      onoe 			if (ic->ic_opmode == IEEE80211_M_STA)
   1753      1.133    dyoung 				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   1754       1.90      onoe 			break;
   1755       1.90      onoe 		}
   1756       1.90      onoe 		break;
   1757        1.1    ichiro 
   1758       1.90      onoe 	case WI_INFO_COUNTERS:
   1759       1.90      onoe 		/* some card versions have a larger stats structure */
   1760       1.90      onoe 		len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
   1761       1.90      onoe 		ptr = (u_int32_t *)&sc->sc_stats;
   1762       1.90      onoe 		off = sizeof(ltbuf);
   1763       1.90      onoe 		for (i = 0; i < len; i++, off += 2, ptr++) {
   1764       1.90      onoe 			wi_read_bap(sc, fid, off, &stat, sizeof(stat));
   1765      1.146    dyoung 			stat = le16toh(stat);
   1766       1.90      onoe #ifdef WI_HERMES_STATS_WAR
   1767       1.90      onoe 			if (stat & 0xf000)
   1768       1.90      onoe 				stat = ~stat;
   1769       1.90      onoe #endif
   1770       1.90      onoe 			*ptr += stat;
   1771       1.90      onoe 		}
   1772       1.90      onoe 		ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
   1773       1.90      onoe 		    sc->sc_stats.wi_tx_multi_retries +
   1774       1.90      onoe 		    sc->sc_stats.wi_tx_retry_limit;
   1775       1.90      onoe 		break;
   1776        1.1    ichiro 
   1777       1.90      onoe 	case WI_INFO_SCAN_RESULTS:
   1778       1.90      onoe 	case WI_INFO_HOST_SCAN_RESULTS:
   1779       1.90      onoe 		wi_scan_result(sc, fid, le16toh(ltbuf[0]));
   1780       1.90      onoe 		break;
   1781        1.1    ichiro 
   1782       1.90      onoe 	default:
   1783       1.90      onoe 		DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
   1784       1.90      onoe 		    le16toh(ltbuf[1]), le16toh(ltbuf[0])));
   1785       1.90      onoe 		break;
   1786       1.90      onoe 	}
   1787       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
   1788        1.1    ichiro }
   1789        1.1    ichiro 
   1790       1.90      onoe static int
   1791       1.90      onoe wi_write_multi(struct wi_softc *sc)
   1792        1.1    ichiro {
   1793       1.90      onoe 	struct ifnet *ifp = &sc->sc_ic.ic_if;
   1794      1.123    dyoung 	int n;
   1795       1.90      onoe 	struct wi_mcast mlist;
   1796       1.90      onoe 	struct ether_multi *enm;
   1797       1.90      onoe 	struct ether_multistep estep;
   1798        1.1    ichiro 
   1799      1.129    dyoung 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1800       1.90      onoe allmulti:
   1801       1.90      onoe 		ifp->if_flags |= IFF_ALLMULTI;
   1802       1.90      onoe 		memset(&mlist, 0, sizeof(mlist));
   1803       1.90      onoe 		return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
   1804       1.90      onoe 		    sizeof(mlist));
   1805       1.11    tsubai 	}
   1806       1.84   thorpej 
   1807       1.90      onoe 	n = 0;
   1808       1.90      onoe 	ETHER_FIRST_MULTI(estep, &sc->sc_ic.ic_ec, enm);
   1809       1.90      onoe 	while (enm != NULL) {
   1810       1.90      onoe 		/* Punt on ranges or too many multicast addresses. */
   1811       1.90      onoe 		if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi) ||
   1812       1.90      onoe 		    n >= sizeof(mlist) / sizeof(mlist.wi_mcast[0]))
   1813       1.90      onoe 			goto allmulti;
   1814        1.1    ichiro 
   1815       1.90      onoe 		IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], enm->enm_addrlo);
   1816       1.90      onoe 		n++;
   1817       1.90      onoe 		ETHER_NEXT_MULTI(estep, enm);
   1818        1.1    ichiro 	}
   1819       1.90      onoe 	ifp->if_flags &= ~IFF_ALLMULTI;
   1820       1.90      onoe 	return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
   1821       1.90      onoe 	    IEEE80211_ADDR_LEN * n);
   1822        1.1    ichiro }
   1823        1.1    ichiro 
   1824       1.90      onoe 
   1825        1.4    ichiro static void
   1826      1.123    dyoung wi_read_nicid(struct wi_softc *sc)
   1827        1.4    ichiro {
   1828       1.90      onoe 	struct wi_card_ident *id;
   1829       1.90      onoe 	char *p;
   1830       1.90      onoe 	int len;
   1831       1.90      onoe 	u_int16_t ver[4];
   1832        1.4    ichiro 
   1833        1.6    ichiro 	/* getting chip identity */
   1834       1.90      onoe 	memset(ver, 0, sizeof(ver));
   1835       1.90      onoe 	len = sizeof(ver);
   1836       1.90      onoe 	wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
   1837        1.9    ichiro 	printf("%s: using ", sc->sc_dev.dv_xname);
   1838       1.90      onoe DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
   1839       1.64    ichiro 
   1840       1.67    ichiro 	sc->sc_firmware_type = WI_NOTYPE;
   1841       1.64    ichiro 	for (id = wi_card_ident; id->card_name != NULL; id++) {
   1842       1.90      onoe 		if (le16toh(ver[0]) == id->card_id) {
   1843       1.64    ichiro 			printf("%s", id->card_name);
   1844       1.64    ichiro 			sc->sc_firmware_type = id->firm_type;
   1845       1.64    ichiro 			break;
   1846       1.64    ichiro 		}
   1847       1.64    ichiro 	}
   1848       1.67    ichiro 	if (sc->sc_firmware_type == WI_NOTYPE) {
   1849       1.90      onoe 		if (le16toh(ver[0]) & 0x8000) {
   1850       1.56      onoe 			printf("Unknown PRISM2 chip");
   1851       1.56      onoe 			sc->sc_firmware_type = WI_INTERSIL;
   1852       1.56      onoe 		} else {
   1853       1.56      onoe 			printf("Unknown Lucent chip");
   1854       1.56      onoe 			sc->sc_firmware_type = WI_LUCENT;
   1855       1.56      onoe 		}
   1856        1.4    ichiro 	}
   1857        1.6    ichiro 
   1858       1.67    ichiro 	/* get primary firmware version (Only Prism chips) */
   1859       1.68    ichiro 	if (sc->sc_firmware_type != WI_LUCENT) {
   1860       1.90      onoe 		memset(ver, 0, sizeof(ver));
   1861       1.90      onoe 		len = sizeof(ver);
   1862       1.90      onoe 		wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
   1863       1.90      onoe 		sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
   1864       1.90      onoe 		    le16toh(ver[3]) * 100 + le16toh(ver[1]);
   1865       1.67    ichiro 	}
   1866       1.58    ichiro 
   1867       1.57    ichiro 	/* get station firmware version */
   1868       1.90      onoe 	memset(ver, 0, sizeof(ver));
   1869       1.90      onoe 	len = sizeof(ver);
   1870       1.90      onoe 	wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
   1871       1.90      onoe 	sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
   1872       1.90      onoe 	    le16toh(ver[3]) * 100 + le16toh(ver[1]);
   1873       1.56      onoe 	if (sc->sc_firmware_type == WI_INTERSIL &&
   1874       1.90      onoe 	    (sc->sc_sta_firmware_ver == 10102 ||
   1875       1.90      onoe 	     sc->sc_sta_firmware_ver == 20102)) {
   1876       1.90      onoe 		char ident[12];
   1877       1.90      onoe 		memset(ident, 0, sizeof(ident));
   1878       1.90      onoe 		len = sizeof(ident);
   1879       1.70      onoe 		/* value should be the format like "V2.00-11" */
   1880       1.90      onoe 		if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
   1881       1.90      onoe 		    *(p = (char *)ident) >= 'A' &&
   1882       1.56      onoe 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
   1883       1.56      onoe 			sc->sc_firmware_type = WI_SYMBOL;
   1884       1.58    ichiro 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
   1885       1.56      onoe 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
   1886       1.56      onoe 			    (p[6] - '0') * 10 + (p[7] - '0');
   1887       1.56      onoe 		}
   1888       1.56      onoe 	}
   1889       1.58    ichiro 
   1890       1.69  augustss 	printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
   1891       1.58    ichiro 	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
   1892       1.58    ichiro 	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
   1893       1.58    ichiro 	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
   1894       1.90      onoe 		printf("Primary (%u.%u.%u), ",
   1895       1.90      onoe 		    sc->sc_pri_firmware_ver / 10000,
   1896       1.58    ichiro 		    (sc->sc_pri_firmware_ver % 10000) / 100,
   1897       1.58    ichiro 		    sc->sc_pri_firmware_ver % 100);
   1898       1.58    ichiro 	printf("Station (%u.%u.%u)\n",
   1899       1.90      onoe 	    sc->sc_sta_firmware_ver / 10000,
   1900       1.90      onoe 	    (sc->sc_sta_firmware_ver % 10000) / 100,
   1901       1.58    ichiro 	    sc->sc_sta_firmware_ver % 100);
   1902       1.90      onoe }
   1903        1.6    ichiro 
   1904       1.90      onoe static int
   1905       1.90      onoe wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
   1906       1.90      onoe {
   1907       1.90      onoe 	struct wi_ssid ssid;
   1908       1.90      onoe 
   1909       1.90      onoe 	if (buflen > IEEE80211_NWID_LEN)
   1910       1.90      onoe 		return ENOBUFS;
   1911       1.95      onoe 	memset(&ssid, 0, sizeof(ssid));
   1912       1.90      onoe 	ssid.wi_len = htole16(buflen);
   1913       1.90      onoe 	memcpy(ssid.wi_ssid, buf, buflen);
   1914       1.95      onoe 	return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
   1915        1.4    ichiro }
   1916        1.4    ichiro 
   1917       1.90      onoe static int
   1918       1.90      onoe wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
   1919        1.1    ichiro {
   1920       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
   1921       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   1922       1.90      onoe 	struct ifreq *ifr = (struct ifreq *)data;
   1923       1.90      onoe 	struct wi_req wreq;
   1924       1.90      onoe 	int len, n, error;
   1925       1.90      onoe 
   1926       1.90      onoe 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1927       1.90      onoe 	if (error)
   1928       1.90      onoe 		return error;
   1929       1.90      onoe 	len = (wreq.wi_len - 1) * 2;
   1930       1.90      onoe 	if (len < sizeof(u_int16_t))
   1931       1.90      onoe 		return ENOSPC;
   1932       1.90      onoe 	if (len > sizeof(wreq.wi_val))
   1933       1.90      onoe 		len = sizeof(wreq.wi_val);
   1934       1.90      onoe 
   1935       1.90      onoe 	switch (wreq.wi_type) {
   1936       1.90      onoe 
   1937       1.90      onoe 	case WI_RID_IFACE_STATS:
   1938       1.90      onoe 		memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
   1939       1.90      onoe 		if (len < sizeof(sc->sc_stats))
   1940       1.90      onoe 			error = ENOSPC;
   1941       1.90      onoe 		else
   1942       1.90      onoe 			len = sizeof(sc->sc_stats);
   1943       1.90      onoe 		break;
   1944       1.90      onoe 
   1945       1.90      onoe 	case WI_RID_ENCRYPTION:
   1946       1.90      onoe 	case WI_RID_TX_CRYPT_KEY:
   1947       1.90      onoe 	case WI_RID_DEFLT_CRYPT_KEYS:
   1948      1.103    dyoung 	case WI_RID_TX_RATE:
   1949       1.90      onoe 		return ieee80211_cfgget(ifp, cmd, data);
   1950       1.90      onoe 
   1951       1.90      onoe 	case WI_RID_MICROWAVE_OVEN:
   1952       1.90      onoe 		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
   1953       1.90      onoe 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   1954       1.90      onoe 			    &len);
   1955       1.90      onoe 			break;
   1956       1.90      onoe 		}
   1957       1.90      onoe 		wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
   1958       1.90      onoe 		len = sizeof(u_int16_t);
   1959       1.90      onoe 		break;
   1960        1.1    ichiro 
   1961      1.105    dyoung 	case WI_RID_DBM_ADJUST:
   1962      1.105    dyoung 		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
   1963      1.105    dyoung 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   1964      1.105    dyoung 			    &len);
   1965      1.105    dyoung 			break;
   1966      1.105    dyoung 		}
   1967      1.131    dyoung 		wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
   1968      1.105    dyoung 		len = sizeof(u_int16_t);
   1969      1.105    dyoung 		break;
   1970      1.105    dyoung 
   1971       1.90      onoe 	case WI_RID_ROAMING_MODE:
   1972       1.90      onoe 		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
   1973       1.90      onoe 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   1974       1.90      onoe 			    &len);
   1975       1.90      onoe 			break;
   1976       1.90      onoe 		}
   1977       1.90      onoe 		wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
   1978       1.90      onoe 		len = sizeof(u_int16_t);
   1979       1.90      onoe 		break;
   1980        1.1    ichiro 
   1981       1.90      onoe 	case WI_RID_SYSTEM_SCALE:
   1982       1.90      onoe 		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
   1983       1.90      onoe 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   1984       1.90      onoe 			    &len);
   1985       1.90      onoe 			break;
   1986       1.90      onoe 		}
   1987       1.90      onoe 		wreq.wi_val[0] = htole16(sc->sc_system_scale);
   1988       1.90      onoe 		len = sizeof(u_int16_t);
   1989       1.90      onoe 		break;
   1990        1.1    ichiro 
   1991      1.104    dyoung 	case WI_RID_FRAG_THRESH:
   1992      1.104    dyoung 		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
   1993      1.104    dyoung 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   1994      1.104    dyoung 			    &len);
   1995      1.104    dyoung 			break;
   1996      1.104    dyoung 		}
   1997      1.104    dyoung 		wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
   1998      1.104    dyoung 		len = sizeof(u_int16_t);
   1999      1.104    dyoung 		break;
   2000      1.104    dyoung 
   2001       1.90      onoe 	case WI_RID_READ_APS:
   2002       1.90      onoe 		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
   2003       1.90      onoe 			return ieee80211_cfgget(ifp, cmd, data);
   2004       1.90      onoe 		if (sc->sc_scan_timer > 0) {
   2005       1.90      onoe 			error = EINPROGRESS;
   2006       1.90      onoe 			break;
   2007       1.90      onoe 		}
   2008       1.90      onoe 		n = sc->sc_naps;
   2009       1.90      onoe 		if (len < sizeof(n)) {
   2010       1.90      onoe 			error = ENOSPC;
   2011       1.90      onoe 			break;
   2012       1.90      onoe 		}
   2013       1.90      onoe 		if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
   2014       1.90      onoe 			n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
   2015       1.90      onoe 		len = sizeof(n) + sizeof(struct wi_apinfo) * n;
   2016       1.90      onoe 		memcpy(wreq.wi_val, &n, sizeof(n));
   2017       1.90      onoe 		memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
   2018       1.90      onoe 		    sizeof(struct wi_apinfo) * n);
   2019       1.90      onoe 		break;
   2020        1.1    ichiro 
   2021       1.90      onoe 	default:
   2022       1.90      onoe 		if (sc->sc_enabled) {
   2023       1.90      onoe 			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
   2024       1.90      onoe 			    &len);
   2025       1.90      onoe 			break;
   2026       1.90      onoe 		}
   2027       1.90      onoe 		switch (wreq.wi_type) {
   2028       1.90      onoe 		case WI_RID_MAX_DATALEN:
   2029       1.90      onoe 			wreq.wi_val[0] = htole16(sc->sc_max_datalen);
   2030      1.110    dyoung 			len = sizeof(u_int16_t);
   2031      1.110    dyoung 			break;
   2032      1.110    dyoung 		case WI_RID_FRAG_THRESH:
   2033      1.110    dyoung 			wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
   2034       1.90      onoe 			len = sizeof(u_int16_t);
   2035       1.90      onoe 			break;
   2036       1.90      onoe 		case WI_RID_RTS_THRESH:
   2037       1.90      onoe 			wreq.wi_val[0] = htole16(sc->sc_rts_thresh);
   2038       1.90      onoe 			len = sizeof(u_int16_t);
   2039       1.90      onoe 			break;
   2040       1.90      onoe 		case WI_RID_CNFAUTHMODE:
   2041       1.90      onoe 			wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
   2042       1.90      onoe 			len = sizeof(u_int16_t);
   2043       1.90      onoe 			break;
   2044       1.90      onoe 		case WI_RID_NODENAME:
   2045       1.90      onoe 			if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
   2046       1.90      onoe 				error = ENOSPC;
   2047       1.90      onoe 				break;
   2048       1.90      onoe 			}
   2049       1.90      onoe 			len = sc->sc_nodelen + sizeof(u_int16_t);
   2050       1.90      onoe 			wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
   2051       1.90      onoe 			memcpy(&wreq.wi_val[1], sc->sc_nodename,
   2052       1.90      onoe 			    sc->sc_nodelen);
   2053       1.90      onoe 			break;
   2054       1.90      onoe 		default:
   2055       1.90      onoe 			return ieee80211_cfgget(ifp, cmd, data);
   2056       1.90      onoe 		}
   2057       1.90      onoe 		break;
   2058        1.1    ichiro 	}
   2059       1.90      onoe 	if (error)
   2060       1.90      onoe 		return error;
   2061       1.90      onoe 	wreq.wi_len = (len + 1) / 2 + 1;
   2062       1.90      onoe 	return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
   2063        1.1    ichiro }
   2064        1.1    ichiro 
   2065       1.90      onoe static int
   2066       1.90      onoe wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
   2067       1.90      onoe {
   2068       1.90      onoe 	struct wi_softc *sc = ifp->if_softc;
   2069       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   2070       1.90      onoe 	struct ifreq *ifr = (struct ifreq *)data;
   2071      1.133    dyoung 	struct ieee80211_rateset *rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
   2072       1.90      onoe 	struct wi_req wreq;
   2073       1.90      onoe 	struct mbuf *m;
   2074       1.90      onoe 	int i, len, error;
   2075       1.90      onoe 
   2076       1.90      onoe 	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   2077       1.90      onoe 	if (error)
   2078       1.90      onoe 		return error;
   2079       1.90      onoe 	len = (wreq.wi_len - 1) * 2;
   2080       1.90      onoe 	switch (wreq.wi_type) {
   2081      1.105    dyoung 	case WI_RID_DBM_ADJUST:
   2082      1.105    dyoung 		return ENODEV;
   2083      1.105    dyoung 
   2084       1.90      onoe 	case WI_RID_NODENAME:
   2085       1.90      onoe 		if (le16toh(wreq.wi_val[0]) * 2 > len ||
   2086       1.90      onoe 		    le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
   2087       1.90      onoe 			error = ENOSPC;
   2088       1.90      onoe 			break;
   2089       1.90      onoe 		}
   2090       1.90      onoe 		if (sc->sc_enabled) {
   2091       1.90      onoe 			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
   2092       1.90      onoe 			    len);
   2093       1.90      onoe 			if (error)
   2094       1.90      onoe 				break;
   2095       1.90      onoe 		}
   2096       1.90      onoe 		sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
   2097       1.90      onoe 		memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
   2098       1.90      onoe 		break;
   2099       1.91      onoe 
   2100       1.90      onoe 	case WI_RID_MICROWAVE_OVEN:
   2101       1.90      onoe 	case WI_RID_ROAMING_MODE:
   2102       1.90      onoe 	case WI_RID_SYSTEM_SCALE:
   2103      1.104    dyoung 	case WI_RID_FRAG_THRESH:
   2104       1.90      onoe 		if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
   2105       1.90      onoe 		    (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
   2106       1.90      onoe 			break;
   2107       1.90      onoe 		if (wreq.wi_type == WI_RID_ROAMING_MODE &&
   2108       1.90      onoe 		    (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
   2109       1.90      onoe 			break;
   2110       1.90      onoe 		if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
   2111       1.90      onoe 		    (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
   2112       1.90      onoe 			break;
   2113      1.104    dyoung 		if (wreq.wi_type == WI_RID_FRAG_THRESH &&
   2114      1.104    dyoung 		    (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
   2115      1.104    dyoung 			break;
   2116       1.90      onoe 		/* FALLTHROUGH */
   2117       1.90      onoe 	case WI_RID_RTS_THRESH:
   2118       1.90      onoe 	case WI_RID_CNFAUTHMODE:
   2119       1.90      onoe 	case WI_RID_MAX_DATALEN:
   2120       1.90      onoe 		if (sc->sc_enabled) {
   2121       1.90      onoe 			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
   2122       1.90      onoe 			    sizeof(u_int16_t));
   2123       1.90      onoe 			if (error)
   2124       1.90      onoe 				break;
   2125       1.90      onoe 		}
   2126       1.90      onoe 		switch (wreq.wi_type) {
   2127      1.102    dyoung 		case WI_RID_FRAG_THRESH:
   2128      1.102    dyoung 			sc->sc_frag_thresh = le16toh(wreq.wi_val[0]);
   2129      1.102    dyoung 			break;
   2130       1.90      onoe 		case WI_RID_RTS_THRESH:
   2131       1.90      onoe 			sc->sc_rts_thresh = le16toh(wreq.wi_val[0]);
   2132       1.90      onoe 			break;
   2133       1.90      onoe 		case WI_RID_MICROWAVE_OVEN:
   2134       1.90      onoe 			sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
   2135       1.90      onoe 			break;
   2136       1.90      onoe 		case WI_RID_ROAMING_MODE:
   2137       1.90      onoe 			sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
   2138       1.90      onoe 			break;
   2139       1.90      onoe 		case WI_RID_SYSTEM_SCALE:
   2140       1.90      onoe 			sc->sc_system_scale = le16toh(wreq.wi_val[0]);
   2141       1.90      onoe 			break;
   2142       1.90      onoe 		case WI_RID_CNFAUTHMODE:
   2143       1.90      onoe 			sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
   2144       1.90      onoe 			break;
   2145       1.90      onoe 		case WI_RID_MAX_DATALEN:
   2146       1.90      onoe 			sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
   2147       1.90      onoe 			break;
   2148       1.90      onoe 		}
   2149       1.90      onoe 		break;
   2150       1.91      onoe 
   2151       1.90      onoe 	case WI_RID_TX_RATE:
   2152       1.90      onoe 		switch (le16toh(wreq.wi_val[0])) {
   2153       1.90      onoe 		case 3:
   2154       1.90      onoe 			ic->ic_fixed_rate = -1;
   2155       1.90      onoe 			break;
   2156       1.90      onoe 		default:
   2157       1.90      onoe 			for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
   2158      1.133    dyoung 				if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
   2159       1.90      onoe 				    / 2 == le16toh(wreq.wi_val[0]))
   2160       1.90      onoe 					break;
   2161       1.90      onoe 			}
   2162       1.90      onoe 			if (i == IEEE80211_RATE_SIZE)
   2163       1.90      onoe 				return EINVAL;
   2164       1.90      onoe 			ic->ic_fixed_rate = i;
   2165        1.4    ichiro 		}
   2166       1.90      onoe 		if (sc->sc_enabled)
   2167      1.135    dyoung 			error = wi_cfg_txrate(sc);
   2168        1.1    ichiro 		break;
   2169       1.91      onoe 
   2170       1.90      onoe 	case WI_RID_SCAN_APS:
   2171       1.90      onoe 		if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
   2172      1.123    dyoung 			error = wi_scan_ap(sc, 0x3fff, 0x000f);
   2173       1.90      onoe 		break;
   2174       1.91      onoe 
   2175       1.90      onoe 	case WI_RID_MGMT_XMIT:
   2176       1.90      onoe 		if (!sc->sc_enabled) {
   2177       1.90      onoe 			error = ENETDOWN;
   2178       1.90      onoe 			break;
   2179       1.90      onoe 		}
   2180       1.90      onoe 		if (ic->ic_mgtq.ifq_len > 5) {
   2181       1.90      onoe 			error = EAGAIN;
   2182       1.90      onoe 			break;
   2183       1.90      onoe 		}
   2184       1.90      onoe 		/* XXX wi_len looks in u_int8_t, not in u_int16_t */
   2185       1.90      onoe 		m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
   2186       1.90      onoe 		if (m == NULL) {
   2187       1.90      onoe 			error = ENOMEM;
   2188       1.90      onoe 			break;
   2189       1.90      onoe 		}
   2190       1.90      onoe 		IF_ENQUEUE(&ic->ic_mgtq, m);
   2191        1.1    ichiro 		break;
   2192       1.91      onoe 
   2193       1.90      onoe 	default:
   2194       1.90      onoe 		if (sc->sc_enabled) {
   2195       1.90      onoe 			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
   2196       1.90      onoe 			    len);
   2197       1.90      onoe 			if (error)
   2198       1.90      onoe 				break;
   2199       1.90      onoe 		}
   2200       1.90      onoe 		error = ieee80211_cfgset(ifp, cmd, data);
   2201        1.1    ichiro 		break;
   2202        1.1    ichiro 	}
   2203       1.90      onoe 	return error;
   2204        1.1    ichiro }
   2205        1.1    ichiro 
   2206      1.135    dyoung /* Rate is 0 for hardware auto-select, otherwise rate is
   2207      1.135    dyoung  * 2, 4, 11, or 22 (units of 500Kbps).
   2208      1.135    dyoung  */
   2209        1.1    ichiro static int
   2210      1.135    dyoung wi_write_txrate(struct wi_softc *sc, int rate)
   2211        1.1    ichiro {
   2212      1.135    dyoung 	u_int16_t hwrate;
   2213       1.90      onoe 	int i;
   2214      1.133    dyoung 
   2215      1.135    dyoung 	rate = (rate & IEEE80211_RATE_VAL) / 2;
   2216        1.1    ichiro 
   2217       1.90      onoe 	/* rate: 0, 1, 2, 5, 11 */
   2218       1.90      onoe 	switch (sc->sc_firmware_type) {
   2219       1.90      onoe 	case WI_LUCENT:
   2220      1.135    dyoung 		switch (rate) {
   2221      1.135    dyoung 		case 0:
   2222      1.135    dyoung 			hwrate = 3;	/* auto */
   2223      1.135    dyoung 			break;
   2224      1.135    dyoung 		case 5:
   2225      1.135    dyoung 			hwrate = 4;
   2226      1.135    dyoung 			break;
   2227      1.135    dyoung 		case 11:
   2228      1.135    dyoung 			hwrate = 5;
   2229      1.135    dyoung 			break;
   2230      1.135    dyoung 		default:
   2231      1.135    dyoung 			hwrate = rate;
   2232      1.135    dyoung 			break;
   2233      1.135    dyoung 		}
   2234       1.90      onoe 		break;
   2235       1.90      onoe 	default:
   2236      1.103    dyoung 		/* Choose a bit according to this table.
   2237      1.103    dyoung 		 *
   2238      1.103    dyoung 		 * bit | data rate
   2239      1.103    dyoung 		 * ----+-------------------
   2240      1.103    dyoung 		 * 0   | 1Mbps
   2241      1.103    dyoung 		 * 1   | 2Mbps
   2242      1.103    dyoung 		 * 2   | 5.5Mbps
   2243      1.103    dyoung 		 * 3   | 11Mbps
   2244      1.103    dyoung 		 */
   2245       1.90      onoe 		for (i = 8; i > 0; i >>= 1) {
   2246       1.90      onoe 			if (rate >= i)
   2247       1.90      onoe 				break;
   2248       1.90      onoe 		}
   2249       1.90      onoe 		if (i == 0)
   2250      1.135    dyoung 			hwrate = 0xf;	/* auto */
   2251       1.90      onoe 		else
   2252      1.135    dyoung 			hwrate = i;
   2253       1.90      onoe 		break;
   2254       1.90      onoe 	}
   2255      1.135    dyoung 
   2256      1.135    dyoung 	if (sc->sc_tx_rate == hwrate)
   2257      1.135    dyoung 		return 0;
   2258      1.135    dyoung 
   2259      1.139    dyoung 	if (sc->sc_if.if_flags & IFF_DEBUG)
   2260      1.139    dyoung 		printf("%s: tx rate %d -> %d (%d)\n", __func__, sc->sc_tx_rate,
   2261      1.139    dyoung 		    hwrate, rate);
   2262      1.139    dyoung 
   2263      1.135    dyoung 	sc->sc_tx_rate = hwrate;
   2264      1.135    dyoung 
   2265      1.135    dyoung 	return wi_write_val(sc, WI_RID_TX_RATE, sc->sc_tx_rate);
   2266      1.135    dyoung }
   2267      1.135    dyoung 
   2268      1.135    dyoung static int
   2269      1.135    dyoung wi_cfg_txrate(struct wi_softc *sc)
   2270      1.135    dyoung {
   2271      1.135    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   2272      1.135    dyoung 	struct ieee80211_rateset *rs;
   2273      1.135    dyoung 	int rate;
   2274      1.135    dyoung 
   2275      1.135    dyoung 	rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
   2276      1.135    dyoung 
   2277      1.135    dyoung 	sc->sc_tx_rate = 0; /* force write to RID */
   2278      1.135    dyoung 
   2279      1.135    dyoung 	if (ic->ic_fixed_rate < 0)
   2280      1.135    dyoung 		rate = 0;	/* auto */
   2281      1.135    dyoung 	else
   2282      1.139    dyoung 		rate = rs->rs_rates[ic->ic_fixed_rate];
   2283      1.135    dyoung 
   2284      1.135    dyoung 	return wi_write_txrate(sc, rate);
   2285        1.1    ichiro }
   2286        1.1    ichiro 
   2287        1.1    ichiro static int
   2288       1.90      onoe wi_write_wep(struct wi_softc *sc)
   2289        1.1    ichiro {
   2290       1.90      onoe 	struct ieee80211com *ic = &sc->sc_ic;
   2291       1.90      onoe 	int error = 0;
   2292       1.90      onoe 	int i, keylen;
   2293       1.90      onoe 	u_int16_t val;
   2294       1.90      onoe 	struct wi_key wkey[IEEE80211_WEP_NKID];
   2295        1.1    ichiro 
   2296       1.90      onoe 	switch (sc->sc_firmware_type) {
   2297       1.90      onoe 	case WI_LUCENT:
   2298       1.90      onoe 		val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
   2299       1.90      onoe 		error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
   2300       1.90      onoe 		if (error)
   2301       1.90      onoe 			break;
   2302       1.90      onoe 		error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
   2303       1.90      onoe 		if (error)
   2304       1.90      onoe 			break;
   2305       1.90      onoe 		memset(wkey, 0, sizeof(wkey));
   2306       1.90      onoe 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2307       1.90      onoe 			keylen = ic->ic_nw_keys[i].wk_len;
   2308       1.90      onoe 			wkey[i].wi_keylen = htole16(keylen);
   2309       1.90      onoe 			memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
   2310       1.90      onoe 			    keylen);
   2311       1.90      onoe 		}
   2312       1.90      onoe 		error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
   2313       1.90      onoe 		    wkey, sizeof(wkey));
   2314        1.1    ichiro 		break;
   2315       1.77   thorpej 
   2316       1.90      onoe 	case WI_INTERSIL:
   2317       1.90      onoe 	case WI_SYMBOL:
   2318       1.90      onoe 		if (ic->ic_flags & IEEE80211_F_WEPON) {
   2319       1.90      onoe 			/*
   2320       1.90      onoe 			 * ONLY HWB3163 EVAL-CARD Firmware version
   2321       1.90      onoe 			 * less than 0.8 variant2
   2322       1.90      onoe 			 *
   2323       1.90      onoe 			 *   If promiscuous mode disable, Prism2 chip
   2324       1.90      onoe 			 *  does not work with WEP .
   2325       1.90      onoe 			 * It is under investigation for details.
   2326      1.147    keihan 			 * (ichiro (at) NetBSD.org)
   2327       1.90      onoe 			 */
   2328       1.90      onoe 			if (sc->sc_firmware_type == WI_INTERSIL &&
   2329       1.90      onoe 			    sc->sc_sta_firmware_ver < 802 ) {
   2330       1.90      onoe 				/* firm ver < 0.8 variant 2 */
   2331       1.90      onoe 				wi_write_val(sc, WI_RID_PROMISC, 1);
   2332       1.90      onoe 			}
   2333       1.90      onoe 			wi_write_val(sc, WI_RID_CNFAUTHMODE,
   2334       1.90      onoe 			    sc->sc_cnfauthmode);
   2335       1.90      onoe 			val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
   2336      1.100      onoe 			/*
   2337      1.100      onoe 			 * Encryption firmware has a bug for HostAP mode.
   2338      1.100      onoe 			 */
   2339      1.100      onoe 			if (sc->sc_firmware_type == WI_INTERSIL &&
   2340      1.100      onoe 			    ic->ic_opmode == IEEE80211_M_HOSTAP)
   2341       1.90      onoe 				val |= HOST_ENCRYPT;
   2342       1.90      onoe 		} else {
   2343      1.100      onoe 			wi_write_val(sc, WI_RID_CNFAUTHMODE,
   2344      1.100      onoe 			    IEEE80211_AUTH_OPEN);
   2345       1.90      onoe 			val = HOST_ENCRYPT | HOST_DECRYPT;
   2346       1.90      onoe 		}
   2347       1.90      onoe 		error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
   2348       1.90      onoe 		if (error)
   2349       1.90      onoe 			break;
   2350       1.90      onoe 		error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
   2351       1.90      onoe 		    ic->ic_wep_txkey);
   2352       1.90      onoe 		if (error)
   2353       1.90      onoe 			break;
   2354      1.100      onoe 		/*
   2355      1.100      onoe 		 * It seems that the firmware accept 104bit key only if
   2356      1.100      onoe 		 * all the keys have 104bit length.  We get the length of
   2357      1.100      onoe 		 * the transmit key and use it for all other keys.
   2358      1.100      onoe 		 * Perhaps we should use software WEP for such situation.
   2359      1.100      onoe 		 */
   2360      1.100      onoe 		keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
   2361      1.100      onoe 		if (keylen > IEEE80211_WEP_KEYLEN)
   2362      1.100      onoe 			keylen = 13;	/* 104bit keys */
   2363      1.100      onoe 		else
   2364      1.100      onoe 			keylen = IEEE80211_WEP_KEYLEN;
   2365       1.90      onoe 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2366       1.90      onoe 			error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
   2367       1.90      onoe 			    ic->ic_nw_keys[i].wk_key, keylen);
   2368       1.90      onoe 			if (error)
   2369       1.90      onoe 				break;
   2370       1.90      onoe 		}
   2371        1.1    ichiro 		break;
   2372        1.1    ichiro 	}
   2373       1.90      onoe 	return error;
   2374        1.1    ichiro }
   2375        1.1    ichiro 
   2376       1.90      onoe /* Must be called at proper protection level! */
   2377        1.1    ichiro static int
   2378       1.90      onoe wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
   2379        1.1    ichiro {
   2380       1.90      onoe 	int i, status;
   2381       1.90      onoe 
   2382       1.90      onoe 	/* wait for the busy bit to clear */
   2383      1.117    dyoung 	for (i = 500; i > 0; i--) {	/* 5s */
   2384       1.90      onoe 		if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
   2385       1.90      onoe 			break;
   2386      1.117    dyoung 		DELAY(10*1000);	/* 10 m sec */
   2387       1.77   thorpej 	}
   2388      1.117    dyoung 	if (i == 0) {
   2389      1.117    dyoung 		printf("%s: wi_cmd: busy bit won't clear.\n",
   2390      1.117    dyoung 		    sc->sc_dev.dv_xname);
   2391      1.117    dyoung 		return(ETIMEDOUT);
   2392      1.117    dyoung   	}
   2393       1.90      onoe 	CSR_WRITE_2(sc, WI_PARAM0, val0);
   2394       1.90      onoe 	CSR_WRITE_2(sc, WI_PARAM1, val1);
   2395       1.90      onoe 	CSR_WRITE_2(sc, WI_PARAM2, val2);
   2396       1.90      onoe 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
   2397       1.90      onoe 
   2398       1.90      onoe 	if (cmd == WI_CMD_INI) {
   2399       1.90      onoe 		/* XXX: should sleep here. */
   2400       1.90      onoe 		DELAY(100*1000);
   2401       1.90      onoe 	}
   2402       1.90      onoe 	/* wait for the cmd completed bit */
   2403       1.90      onoe 	for (i = 0; i < WI_TIMEOUT; i++) {
   2404       1.90      onoe 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
   2405       1.90      onoe 			break;
   2406      1.123    dyoung 		DELAY(WI_DELAY);
   2407        1.1    ichiro 	}
   2408        1.1    ichiro 
   2409       1.90      onoe 	status = CSR_READ_2(sc, WI_STATUS);
   2410       1.90      onoe 
   2411       1.90      onoe 	/* Ack the command */
   2412       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
   2413       1.90      onoe 
   2414       1.90      onoe 	if (i == WI_TIMEOUT) {
   2415       1.90      onoe 		printf("%s: command timed out, cmd=0x%x, arg=0x%x\n",
   2416       1.90      onoe 		    sc->sc_dev.dv_xname, cmd, val0);
   2417       1.90      onoe 		return ETIMEDOUT;
   2418        1.1    ichiro 	}
   2419        1.1    ichiro 
   2420       1.90      onoe 	if (status & WI_STAT_CMD_RESULT) {
   2421       1.90      onoe 		printf("%s: command failed, cmd=0x%x, arg=0x%x\n",
   2422       1.90      onoe 		    sc->sc_dev.dv_xname, cmd, val0);
   2423       1.90      onoe 		return EIO;
   2424       1.90      onoe 	}
   2425       1.90      onoe 	return 0;
   2426        1.1    ichiro }
   2427        1.1    ichiro 
   2428       1.90      onoe static int
   2429       1.90      onoe wi_seek_bap(struct wi_softc *sc, int id, int off)
   2430        1.1    ichiro {
   2431       1.90      onoe 	int i, status;
   2432        1.1    ichiro 
   2433       1.90      onoe 	CSR_WRITE_2(sc, WI_SEL0, id);
   2434       1.90      onoe 	CSR_WRITE_2(sc, WI_OFF0, off);
   2435        1.1    ichiro 
   2436       1.90      onoe 	for (i = 0; ; i++) {
   2437       1.90      onoe 		status = CSR_READ_2(sc, WI_OFF0);
   2438       1.90      onoe 		if ((status & WI_OFF_BUSY) == 0)
   2439       1.84   thorpej 			break;
   2440       1.90      onoe 		if (i == WI_TIMEOUT) {
   2441       1.90      onoe 			printf("%s: timeout in wi_seek to %x/%x\n",
   2442       1.90      onoe 			    sc->sc_dev.dv_xname, id, off);
   2443       1.90      onoe 			sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
   2444       1.90      onoe 			return ETIMEDOUT;
   2445       1.84   thorpej 		}
   2446       1.90      onoe 		DELAY(1);
   2447       1.84   thorpej 	}
   2448       1.90      onoe 	if (status & WI_OFF_ERR) {
   2449       1.90      onoe 		printf("%s: failed in wi_seek to %x/%x\n",
   2450       1.90      onoe 		    sc->sc_dev.dv_xname, id, off);
   2451       1.90      onoe 		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
   2452       1.90      onoe 		return EIO;
   2453       1.84   thorpej 	}
   2454       1.90      onoe 	sc->sc_bap_id = id;
   2455       1.90      onoe 	sc->sc_bap_off = off;
   2456       1.90      onoe 	return 0;
   2457        1.1    ichiro }
   2458        1.1    ichiro 
   2459        1.1    ichiro static int
   2460       1.90      onoe wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
   2461        1.1    ichiro {
   2462       1.90      onoe 	int error, cnt;
   2463        1.1    ichiro 
   2464       1.90      onoe 	if (buflen == 0)
   2465       1.90      onoe 		return 0;
   2466       1.90      onoe 	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
   2467       1.90      onoe 		if ((error = wi_seek_bap(sc, id, off)) != 0)
   2468        1.1    ichiro 			return error;
   2469        1.1    ichiro 	}
   2470       1.90      onoe 	cnt = (buflen + 1) / 2;
   2471       1.90      onoe 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
   2472       1.90      onoe 	sc->sc_bap_off += cnt * 2;
   2473       1.90      onoe 	return 0;
   2474       1.90      onoe }
   2475       1.90      onoe 
   2476       1.90      onoe static int
   2477       1.90      onoe wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
   2478       1.90      onoe {
   2479       1.90      onoe 	int error, cnt;
   2480        1.1    ichiro 
   2481       1.90      onoe 	if (buflen == 0)
   2482       1.90      onoe 		return 0;
   2483        1.1    ichiro 
   2484       1.90      onoe #ifdef WI_HERMES_AUTOINC_WAR
   2485       1.90      onoe   again:
   2486       1.90      onoe #endif
   2487       1.90      onoe 	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
   2488       1.90      onoe 		if ((error = wi_seek_bap(sc, id, off)) != 0)
   2489        1.1    ichiro 			return error;
   2490        1.1    ichiro 	}
   2491       1.90      onoe 	cnt = (buflen + 1) / 2;
   2492       1.90      onoe 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
   2493       1.90      onoe 	sc->sc_bap_off += cnt * 2;
   2494        1.1    ichiro 
   2495       1.90      onoe #ifdef WI_HERMES_AUTOINC_WAR
   2496       1.90      onoe 	/*
   2497       1.90      onoe 	 * According to the comments in the HCF Light code, there is a bug
   2498       1.90      onoe 	 * in the Hermes (or possibly in certain Hermes firmware revisions)
   2499       1.90      onoe 	 * where the chip's internal autoincrement counter gets thrown off
   2500       1.90      onoe 	 * during data writes:  the autoincrement is missed, causing one
   2501       1.90      onoe 	 * data word to be overwritten and subsequent words to be written to
   2502       1.90      onoe 	 * the wrong memory locations. The end result is that we could end
   2503       1.90      onoe 	 * up transmitting bogus frames without realizing it. The workaround
   2504       1.90      onoe 	 * for this is to write a couple of extra guard words after the end
   2505       1.90      onoe 	 * of the transfer, then attempt to read then back. If we fail to
   2506       1.90      onoe 	 * locate the guard words where we expect them, we preform the
   2507       1.90      onoe 	 * transfer over again.
   2508       1.90      onoe 	 */
   2509       1.90      onoe 	if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
   2510       1.90      onoe 		CSR_WRITE_2(sc, WI_DATA0, 0x1234);
   2511       1.90      onoe 		CSR_WRITE_2(sc, WI_DATA0, 0x5678);
   2512       1.90      onoe 		wi_seek_bap(sc, id, sc->sc_bap_off);
   2513       1.90      onoe 		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
   2514       1.90      onoe 		if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
   2515       1.90      onoe 		    CSR_READ_2(sc, WI_DATA0) != 0x5678) {
   2516       1.90      onoe 			printf("%s: detect auto increment bug, try again\n",
   2517       1.90      onoe 			    sc->sc_dev.dv_xname);
   2518       1.90      onoe 			goto again;
   2519       1.90      onoe 		}
   2520        1.1    ichiro 	}
   2521       1.90      onoe #endif
   2522      1.108    dyoung 	return 0;
   2523      1.108    dyoung }
   2524      1.108    dyoung 
   2525      1.108    dyoung static int
   2526      1.108    dyoung wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
   2527      1.108    dyoung {
   2528      1.108    dyoung 	int error, len;
   2529      1.108    dyoung 	struct mbuf *m;
   2530      1.108    dyoung 
   2531      1.108    dyoung 	for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
   2532      1.108    dyoung 		if (m->m_len == 0)
   2533      1.108    dyoung 			continue;
   2534      1.108    dyoung 
   2535      1.108    dyoung 		len = min(m->m_len, totlen);
   2536      1.108    dyoung 
   2537      1.108    dyoung 		if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
   2538      1.108    dyoung 			m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
   2539      1.108    dyoung 			return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
   2540      1.108    dyoung 			    totlen);
   2541      1.108    dyoung 		}
   2542      1.108    dyoung 
   2543      1.108    dyoung 		if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
   2544      1.108    dyoung 			return error;
   2545      1.108    dyoung 
   2546      1.108    dyoung 		off += m->m_len;
   2547      1.108    dyoung 		totlen -= len;
   2548      1.108    dyoung 	}
   2549        1.1    ichiro 	return 0;
   2550        1.1    ichiro }
   2551        1.1    ichiro 
   2552        1.1    ichiro static int
   2553       1.90      onoe wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
   2554        1.1    ichiro {
   2555       1.90      onoe 	int i;
   2556       1.90      onoe 
   2557       1.90      onoe 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
   2558       1.90      onoe 		printf("%s: failed to allocate %d bytes on NIC\n",
   2559       1.90      onoe 		    sc->sc_dev.dv_xname, len);
   2560       1.90      onoe 		return ENOMEM;
   2561       1.90      onoe 	}
   2562        1.1    ichiro 
   2563       1.90      onoe 	for (i = 0; i < WI_TIMEOUT; i++) {
   2564       1.90      onoe 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   2565       1.90      onoe 			break;
   2566       1.90      onoe 		if (i == WI_TIMEOUT) {
   2567       1.90      onoe 			printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
   2568       1.90      onoe 			return ETIMEDOUT;
   2569       1.90      onoe 		}
   2570       1.90      onoe 		DELAY(1);
   2571        1.1    ichiro 	}
   2572       1.90      onoe 	*idp = CSR_READ_2(sc, WI_ALLOC_FID);
   2573       1.90      onoe 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   2574        1.1    ichiro 	return 0;
   2575        1.1    ichiro }
   2576        1.1    ichiro 
   2577        1.1    ichiro static int
   2578       1.90      onoe wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
   2579        1.1    ichiro {
   2580       1.90      onoe 	int error, len;
   2581       1.90      onoe 	u_int16_t ltbuf[2];
   2582        1.1    ichiro 
   2583       1.90      onoe 	/* Tell the NIC to enter record read mode. */
   2584       1.90      onoe 	error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
   2585       1.90      onoe 	if (error)
   2586       1.90      onoe 		return error;
   2587        1.1    ichiro 
   2588       1.90      onoe 	error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
   2589       1.90      onoe 	if (error)
   2590       1.90      onoe 		return error;
   2591        1.1    ichiro 
   2592       1.90      onoe 	if (le16toh(ltbuf[1]) != rid) {
   2593       1.90      onoe 		printf("%s: record read mismatch, rid=%x, got=%x\n",
   2594       1.90      onoe 		    sc->sc_dev.dv_xname, rid, le16toh(ltbuf[1]));
   2595       1.90      onoe 		return EIO;
   2596       1.90      onoe 	}
   2597      1.156    dyoung 	len = max(0, le16toh(ltbuf[0]) - 1) * 2;	 /* already got rid */
   2598       1.90      onoe 	if (*buflenp < len) {
   2599       1.90      onoe 		printf("%s: record buffer is too small, "
   2600       1.90      onoe 		    "rid=%x, size=%d, len=%d\n",
   2601       1.90      onoe 		    sc->sc_dev.dv_xname, rid, *buflenp, len);
   2602       1.90      onoe 		return ENOSPC;
   2603       1.90      onoe 	}
   2604       1.90      onoe 	*buflenp = len;
   2605       1.90      onoe 	return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
   2606        1.1    ichiro }
   2607        1.1    ichiro 
   2608        1.1    ichiro static int
   2609       1.90      onoe wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
   2610        1.1    ichiro {
   2611       1.90      onoe 	int error;
   2612       1.90      onoe 	u_int16_t ltbuf[2];
   2613       1.90      onoe 
   2614       1.90      onoe 	ltbuf[0] = htole16((buflen + 1) / 2 + 1);	 /* includes rid */
   2615       1.90      onoe 	ltbuf[1] = htole16(rid);
   2616        1.1    ichiro 
   2617       1.90      onoe 	error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
   2618       1.90      onoe 	if (error)
   2619       1.90      onoe 		return error;
   2620       1.90      onoe 	error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
   2621       1.90      onoe 	if (error)
   2622       1.90      onoe 		return error;
   2623        1.1    ichiro 
   2624       1.90      onoe 	return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
   2625       1.84   thorpej }
   2626       1.84   thorpej 
   2627      1.148    dyoung static void
   2628      1.148    dyoung wi_rssadapt_updatestats_cb(void *arg, struct ieee80211_node *ni)
   2629      1.148    dyoung {
   2630      1.148    dyoung 	struct wi_node *wn = (void*)ni;
   2631      1.148    dyoung 	ieee80211_rssadapt_updatestats(&wn->wn_rssadapt);
   2632      1.148    dyoung }
   2633      1.148    dyoung 
   2634      1.148    dyoung static void
   2635      1.148    dyoung wi_rssadapt_updatestats(void *arg)
   2636      1.148    dyoung {
   2637      1.148    dyoung 	struct wi_softc *sc = arg;
   2638      1.148    dyoung 	struct ieee80211com *ic = &sc->sc_ic;
   2639      1.148    dyoung 	ieee80211_iterate_nodes(ic, wi_rssadapt_updatestats_cb, arg);
   2640      1.148    dyoung 	if (ic->ic_opmode != IEEE80211_M_MONITOR &&
   2641      1.148    dyoung 	    ic->ic_state == IEEE80211_S_RUN)
   2642      1.148    dyoung 		callout_reset(&sc->sc_rssadapt_ch, hz / 10,
   2643      1.148    dyoung 		    wi_rssadapt_updatestats, arg);
   2644      1.148    dyoung }
   2645      1.148    dyoung 
   2646       1.84   thorpej static int
   2647      1.133    dyoung wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
   2648       1.84   thorpej {
   2649      1.133    dyoung 	struct wi_softc *sc = ic->ic_softc;
   2650      1.133    dyoung 	struct ieee80211_node *ni = ic->ic_bss;
   2651      1.133    dyoung 	int buflen;
   2652       1.90      onoe 	u_int16_t val;
   2653       1.90      onoe 	struct wi_ssid ssid;
   2654      1.138   mycroft 	struct wi_macaddr bssid, old_bssid;
   2655       1.90      onoe 	enum ieee80211_state ostate;
   2656       1.90      onoe #ifdef WI_DEBUG
   2657       1.90      onoe 	static const char *stname[] =
   2658       1.90      onoe 	    { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
   2659       1.90      onoe #endif /* WI_DEBUG */
   2660       1.90      onoe 
   2661       1.90      onoe 	ostate = ic->ic_state;
   2662       1.90      onoe 	DPRINTF(("wi_newstate: %s -> %s\n", stname[ostate], stname[nstate]));
   2663       1.90      onoe 
   2664       1.90      onoe 	switch (nstate) {
   2665       1.90      onoe 	case IEEE80211_S_INIT:
   2666      1.148    dyoung 		if (ic->ic_opmode != IEEE80211_M_MONITOR)
   2667      1.148    dyoung 			callout_stop(&sc->sc_rssadapt_ch);
   2668       1.90      onoe 		ic->ic_flags &= ~IEEE80211_F_SIBSS;
   2669       1.98      onoe 		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
   2670      1.133    dyoung 		return (*sc->sc_newstate)(ic, nstate, arg);
   2671       1.90      onoe 
   2672       1.90      onoe 	case IEEE80211_S_RUN:
   2673       1.98      onoe 		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
   2674       1.90      onoe 		buflen = IEEE80211_ADDR_LEN;
   2675      1.138   mycroft 		IEEE80211_ADDR_COPY(old_bssid.wi_mac_addr, ni->ni_bssid);
   2676      1.138   mycroft 		wi_read_rid(sc, WI_RID_CURRENT_BSSID, &bssid, &buflen);
   2677      1.138   mycroft 		IEEE80211_ADDR_COPY(ni->ni_bssid, &bssid);
   2678      1.138   mycroft 		IEEE80211_ADDR_COPY(ni->ni_macaddr, &bssid);
   2679       1.90      onoe 		buflen = sizeof(val);
   2680       1.90      onoe 		wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
   2681      1.133    dyoung 		if (!isset(ic->ic_chan_avail, le16toh(val)))
   2682      1.133    dyoung 			panic("%s: invalid channel %d\n", sc->sc_dev.dv_xname,
   2683      1.133    dyoung 			    le16toh(val));
   2684      1.133    dyoung 		ni->ni_chan = &ic->ic_channels[le16toh(val)];
   2685      1.107    dyoung 
   2686      1.138   mycroft 		if (IEEE80211_ADDR_EQ(old_bssid.wi_mac_addr, ni->ni_bssid))
   2687      1.107    dyoung 			sc->sc_false_syns++;
   2688      1.107    dyoung 		else
   2689      1.107    dyoung 			sc->sc_false_syns = 0;
   2690       1.90      onoe 
   2691       1.96      onoe 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
   2692       1.96      onoe 			ni->ni_esslen = ic->ic_des_esslen;
   2693       1.96      onoe 			memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
   2694      1.133    dyoung 			ni->ni_rates = ic->ic_sup_rates[
   2695      1.133    dyoung 			    ieee80211_chan2mode(ic, ni->ni_chan)];
   2696       1.96      onoe 			ni->ni_intval = ic->ic_lintval;
   2697       1.96      onoe 			ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
   2698       1.96      onoe 			if (ic->ic_flags & IEEE80211_F_WEPON)
   2699       1.96      onoe 				ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
   2700       1.96      onoe 		} else {
   2701       1.96      onoe 			buflen = sizeof(ssid);
   2702       1.96      onoe 			wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
   2703       1.96      onoe 			ni->ni_esslen = le16toh(ssid.wi_len);
   2704       1.96      onoe 			if (ni->ni_esslen > IEEE80211_NWID_LEN)
   2705       1.96      onoe 				ni->ni_esslen = IEEE80211_NWID_LEN;	/*XXX*/
   2706       1.96      onoe 			memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
   2707      1.148    dyoung 			ni->ni_rates = ic->ic_sup_rates[
   2708      1.148    dyoung 			    ieee80211_chan2mode(ic, ni->ni_chan)]; /*XXX*/
   2709       1.96      onoe 		}
   2710      1.148    dyoung 		if (ic->ic_opmode != IEEE80211_M_MONITOR)
   2711      1.148    dyoung 			callout_reset(&sc->sc_rssadapt_ch, hz / 10,
   2712      1.148    dyoung 			    wi_rssadapt_updatestats, sc);
   2713       1.90      onoe 		break;
   2714       1.90      onoe 
   2715       1.90      onoe 	case IEEE80211_S_SCAN:
   2716       1.90      onoe 	case IEEE80211_S_AUTH:
   2717       1.90      onoe 	case IEEE80211_S_ASSOC:
   2718       1.90      onoe 		break;
   2719       1.84   thorpej 	}
   2720       1.84   thorpej 
   2721      1.136    dyoung 	ic->ic_state = nstate;
   2722       1.90      onoe 	/* skip standard ieee80211 handling */
   2723      1.133    dyoung 	return 0;
   2724      1.116       kml }
   2725      1.116       kml 
   2726      1.116       kml static int
   2727      1.116       kml wi_set_tim(struct ieee80211com *ic, int aid, int which)
   2728      1.116       kml {
   2729      1.116       kml 	struct wi_softc *sc = ic->ic_softc;
   2730      1.116       kml 
   2731      1.116       kml 	aid &= ~0xc000;
   2732      1.116       kml 	if (which)
   2733      1.116       kml 		aid |= 0x8000;
   2734      1.116       kml 
   2735      1.116       kml 	return wi_write_val(sc, WI_RID_SET_TIM, aid);
   2736       1.90      onoe }
   2737       1.90      onoe 
   2738       1.90      onoe static int
   2739      1.123    dyoung wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
   2740       1.90      onoe {
   2741       1.90      onoe 	int error = 0;
   2742       1.90      onoe 	u_int16_t val[2];
   2743       1.84   thorpej 
   2744       1.90      onoe 	if (!sc->sc_enabled)
   2745       1.90      onoe 		return ENXIO;
   2746       1.90      onoe 	switch (sc->sc_firmware_type) {
   2747       1.90      onoe 	case WI_LUCENT:
   2748       1.90      onoe 		(void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
   2749       1.90      onoe 		break;
   2750       1.90      onoe 	case WI_INTERSIL:
   2751      1.146    dyoung 		val[0] = htole16(chanmask);	/* channel */
   2752      1.146    dyoung 		val[1] = htole16(txrate);	/* tx rate */
   2753       1.90      onoe 		error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
   2754       1.90      onoe 		break;
   2755       1.90      onoe 	case WI_SYMBOL:
   2756       1.90      onoe 		/*
   2757       1.90      onoe 		 * XXX only supported on 3.x ?
   2758       1.84   thorpej 		 */
   2759       1.90      onoe 		val[0] = BSCAN_BCAST | BSCAN_ONETIME;
   2760       1.90      onoe 		error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
   2761       1.90      onoe 		    val, sizeof(val[0]));
   2762       1.84   thorpej 		break;
   2763       1.84   thorpej 	}
   2764       1.90      onoe 	if (error == 0) {
   2765       1.90      onoe 		sc->sc_scan_timer = WI_SCAN_WAIT;
   2766       1.90      onoe 		sc->sc_ic.ic_if.if_timer = 1;
   2767      1.123    dyoung 		DPRINTF(("wi_scan_ap: start scanning, "
   2768      1.123    dyoung 			"chanmask 0x%x txrate 0x%x\n", chanmask, txrate));
   2769       1.90      onoe 	}
   2770       1.84   thorpej 	return error;
   2771       1.84   thorpej }
   2772       1.84   thorpej 
   2773       1.90      onoe static void
   2774       1.90      onoe wi_scan_result(struct wi_softc *sc, int fid, int cnt)
   2775       1.84   thorpej {
   2776      1.123    dyoung #define	N(a)	(sizeof (a) / sizeof (a[0]))
   2777       1.90      onoe 	int i, naps, off, szbuf;
   2778       1.90      onoe 	struct wi_scan_header ws_hdr;	/* Prism2 header */
   2779       1.90      onoe 	struct wi_scan_data_p2 ws_dat;	/* Prism2 scantable*/
   2780       1.90      onoe 	struct wi_apinfo *ap;
   2781       1.90      onoe 
   2782       1.90      onoe 	off = sizeof(u_int16_t) * 2;
   2783       1.90      onoe 	memset(&ws_hdr, 0, sizeof(ws_hdr));
   2784       1.90      onoe 	switch (sc->sc_firmware_type) {
   2785       1.90      onoe 	case WI_INTERSIL:
   2786       1.90      onoe 		wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
   2787       1.90      onoe 		off += sizeof(ws_hdr);
   2788       1.90      onoe 		szbuf = sizeof(struct wi_scan_data_p2);
   2789       1.90      onoe 		break;
   2790       1.90      onoe 	case WI_SYMBOL:
   2791       1.90      onoe 		szbuf = sizeof(struct wi_scan_data_p2) + 6;
   2792       1.90      onoe 		break;
   2793       1.90      onoe 	case WI_LUCENT:
   2794       1.90      onoe 		szbuf = sizeof(struct wi_scan_data);
   2795       1.84   thorpej 		break;
   2796      1.123    dyoung 	default:
   2797      1.123    dyoung 		printf("%s: wi_scan_result: unknown firmware type %u\n",
   2798      1.123    dyoung 		    sc->sc_dev.dv_xname, sc->sc_firmware_type);
   2799      1.123    dyoung 		naps = 0;
   2800      1.123    dyoung 		goto done;
   2801       1.84   thorpej 	}
   2802       1.90      onoe 	naps = (cnt * 2 + 2 - off) / szbuf;
   2803      1.123    dyoung 	if (naps > N(sc->sc_aps))
   2804      1.123    dyoung 		naps = N(sc->sc_aps);
   2805       1.90      onoe 	sc->sc_naps = naps;
   2806       1.90      onoe 	/* Read Data */
   2807       1.90      onoe 	ap = sc->sc_aps;
   2808       1.90      onoe 	memset(&ws_dat, 0, sizeof(ws_dat));
   2809       1.90      onoe 	for (i = 0; i < naps; i++, ap++) {
   2810       1.90      onoe 		wi_read_bap(sc, fid, off, &ws_dat,
   2811       1.90      onoe 		    (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
   2812       1.90      onoe 		DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
   2813       1.90      onoe 		    ether_sprintf(ws_dat.wi_bssid)));
   2814       1.90      onoe 		off += szbuf;
   2815       1.90      onoe 		ap->scanreason = le16toh(ws_hdr.wi_reason);
   2816       1.90      onoe 		memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
   2817       1.90      onoe 		ap->channel = le16toh(ws_dat.wi_chid);
   2818       1.90      onoe 		ap->signal  = le16toh(ws_dat.wi_signal);
   2819       1.90      onoe 		ap->noise   = le16toh(ws_dat.wi_noise);
   2820       1.90      onoe 		ap->quality = ap->signal - ap->noise;
   2821       1.90      onoe 		ap->capinfo = le16toh(ws_dat.wi_capinfo);
   2822       1.90      onoe 		ap->interval = le16toh(ws_dat.wi_interval);
   2823       1.90      onoe 		ap->rate    = le16toh(ws_dat.wi_rate);
   2824       1.90      onoe 		ap->namelen = le16toh(ws_dat.wi_namelen);
   2825       1.90      onoe 		if (ap->namelen > sizeof(ap->name))
   2826       1.90      onoe 			ap->namelen = sizeof(ap->name);
   2827       1.90      onoe 		memcpy(ap->name, ws_dat.wi_name, ap->namelen);
   2828       1.90      onoe 	}
   2829      1.123    dyoung done:
   2830       1.90      onoe 	/* Done scanning */
   2831       1.90      onoe 	sc->sc_scan_timer = 0;
   2832       1.90      onoe 	DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
   2833      1.123    dyoung #undef N
   2834      1.119    dyoung }
   2835      1.119    dyoung 
   2836      1.119    dyoung static void
   2837      1.119    dyoung wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
   2838      1.119    dyoung {
   2839      1.119    dyoung 	ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
   2840      1.133    dyoung 	    ni	? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL
   2841      1.133    dyoung 		: -1,
   2842      1.133    dyoung 	    rssi);
   2843      1.119    dyoung 	printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
   2844      1.119    dyoung 		le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
   2845      1.119    dyoung 		le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
   2846      1.119    dyoung 	printf(" rx_signal %u rx_rate %u rx_flow %u\n",
   2847      1.119    dyoung 		wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
   2848      1.119    dyoung 	printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
   2849      1.119    dyoung 		wh->wi_tx_rtry, wh->wi_tx_rate,
   2850      1.119    dyoung 		le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
   2851      1.119    dyoung 	printf(" ehdr dst %s src %s type 0x%x\n",
   2852      1.119    dyoung 		ether_sprintf(wh->wi_ehdr.ether_dhost),
   2853      1.119    dyoung 		ether_sprintf(wh->wi_ehdr.ether_shost),
   2854      1.119    dyoung 		wh->wi_ehdr.ether_type);
   2855        1.1    ichiro }
   2856