wi.c revision 1.27.2.1       1  1.27.2.1   thorpej /*	$NetBSD: wi.c,v 1.27.2.1 2001/11/12 21:18:09 thorpej Exp $	*/
      2       1.1    ichiro 
      3       1.1    ichiro /*
      4       1.1    ichiro  * Copyright (c) 1997, 1998, 1999
      5       1.1    ichiro  *	Bill Paul <wpaul (at) ctr.columbia.edu>.  All rights reserved.
      6       1.1    ichiro  *
      7       1.1    ichiro  * Redistribution and use in source and binary forms, with or without
      8       1.1    ichiro  * modification, are permitted provided that the following conditions
      9       1.1    ichiro  * are met:
     10       1.1    ichiro  * 1. Redistributions of source code must retain the above copyright
     11       1.1    ichiro  *    notice, this list of conditions and the following disclaimer.
     12       1.1    ichiro  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1    ichiro  *    notice, this list of conditions and the following disclaimer in the
     14       1.1    ichiro  *    documentation and/or other materials provided with the distribution.
     15       1.1    ichiro  * 3. All advertising materials mentioning features or use of this software
     16       1.1    ichiro  *    must display the following acknowledgement:
     17       1.1    ichiro  *	This product includes software developed by Bill Paul.
     18       1.1    ichiro  * 4. Neither the name of the author nor the names of any co-contributors
     19       1.1    ichiro  *    may be used to endorse or promote products derived from this software
     20       1.1    ichiro  *    without specific prior written permission.
     21       1.1    ichiro  *
     22       1.1    ichiro  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     23       1.1    ichiro  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24       1.1    ichiro  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25       1.1    ichiro  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
     26       1.1    ichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27       1.1    ichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28       1.1    ichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29       1.1    ichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30       1.1    ichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31       1.1    ichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     32       1.1    ichiro  * THE POSSIBILITY OF SUCH DAMAGE.
     33       1.1    ichiro  */
     34       1.1    ichiro 
     35       1.1    ichiro /*
     36       1.1    ichiro  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
     37       1.1    ichiro  *
     38       1.1    ichiro  * Original FreeBSD driver written by Bill Paul <wpaul (at) ctr.columbia.edu>
     39       1.1    ichiro  * Electrical Engineering Department
     40       1.1    ichiro  * Columbia University, New York City
     41       1.1    ichiro  */
     42       1.1    ichiro 
     43       1.1    ichiro /*
     44       1.1    ichiro  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
     45       1.1    ichiro  * from Lucent. Unlike the older cards, the new ones are programmed
     46       1.1    ichiro  * entirely via a firmware-driven controller called the Hermes.
     47       1.1    ichiro  * Unfortunately, Lucent will not release the Hermes programming manual
     48       1.1    ichiro  * without an NDA (if at all). What they do release is an API library
     49       1.1    ichiro  * called the HCF (Hardware Control Functions) which is supposed to
     50       1.1    ichiro  * do the device-specific operations of a device driver for you. The
     51       1.1    ichiro  * publically available version of the HCF library (the 'HCF Light') is
     52       1.1    ichiro  * a) extremely gross, b) lacks certain features, particularly support
     53       1.1    ichiro  * for 802.11 frames, and c) is contaminated by the GNU Public License.
     54       1.1    ichiro  *
     55       1.1    ichiro  * This driver does not use the HCF or HCF Light at all. Instead, it
     56       1.1    ichiro  * programs the Hermes controller directly, using information gleaned
     57       1.1    ichiro  * from the HCF Light code and corresponding documentation.
     58       1.1    ichiro  *
     59       1.1    ichiro  * This driver supports both the PCMCIA and ISA versions of the
     60       1.1    ichiro  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
     61       1.1    ichiro  * anything of the sort: it's actually a PCMCIA bridge adapter
     62       1.1    ichiro  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
     63       1.1    ichiro  * inserted. Consequently, you need to use the pccard support for
     64       1.1    ichiro  * both the ISA and PCMCIA adapters.
     65       1.1    ichiro  */
     66       1.1    ichiro 
     67       1.1    ichiro /*
     68       1.1    ichiro  * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
     69       1.1    ichiro  * Oslo IETF plenary meeting.
     70       1.1    ichiro  */
     71       1.1    ichiro 
     72       1.1    ichiro #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
     73       1.1    ichiro #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
     74       1.1    ichiro 
     75       1.1    ichiro #include "bpfilter.h"
     76       1.1    ichiro 
     77       1.1    ichiro #include <sys/param.h>
     78       1.1    ichiro #include <sys/systm.h>
     79       1.1    ichiro #include <sys/callout.h>
     80       1.1    ichiro #include <sys/device.h>
     81       1.1    ichiro #include <sys/socket.h>
     82       1.1    ichiro #include <sys/mbuf.h>
     83       1.1    ichiro #include <sys/ioctl.h>
     84       1.1    ichiro #include <sys/kernel.h>		/* for hz */
     85       1.1    ichiro #include <sys/proc.h>
     86       1.1    ichiro 
     87       1.1    ichiro #include <net/if.h>
     88       1.1    ichiro #include <net/if_dl.h>
     89       1.1    ichiro #include <net/if_media.h>
     90       1.1    ichiro #include <net/if_ether.h>
     91       1.1    ichiro #include <net/if_ieee80211.h>
     92       1.1    ichiro 
     93       1.1    ichiro #if NBPFILTER > 0
     94       1.1    ichiro #include <net/bpf.h>
     95       1.1    ichiro #include <net/bpfdesc.h>
     96       1.1    ichiro #endif
     97       1.1    ichiro 
     98      1.18   nathanw #include <machine/bus.h>
     99       1.1    ichiro 
    100       1.1    ichiro #include <dev/ic/wi_ieee.h>
    101       1.1    ichiro #include <dev/ic/wireg.h>
    102       1.1    ichiro #include <dev/ic/wivar.h>
    103       1.1    ichiro 
    104      1.25  explorer #define STATS_FREQUENCY   (60 * hz) /* collect stats every 60 seconds */
    105      1.25  explorer 
    106       1.1    ichiro static void wi_reset		__P((struct wi_softc *));
    107       1.1    ichiro static int wi_ioctl		__P((struct ifnet *, u_long, caddr_t));
    108       1.1    ichiro static void wi_start		__P((struct ifnet *));
    109       1.1    ichiro static void wi_watchdog		__P((struct ifnet *));
    110       1.1    ichiro static int wi_init		__P((struct ifnet *));
    111       1.1    ichiro static void wi_stop		__P((struct ifnet *, int));
    112       1.1    ichiro static void wi_rxeof		__P((struct wi_softc *));
    113       1.1    ichiro static void wi_txeof		__P((struct wi_softc *, int));
    114       1.1    ichiro static void wi_update_stats	__P((struct wi_softc *));
    115       1.1    ichiro static void wi_setmulti		__P((struct wi_softc *));
    116       1.1    ichiro 
    117       1.1    ichiro static int wi_cmd		__P((struct wi_softc *, int, int));
    118       1.1    ichiro static int wi_read_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    119       1.1    ichiro static int wi_write_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    120       1.1    ichiro static int wi_read_data		__P((struct wi_softc *, int,
    121       1.1    ichiro 					int, caddr_t, int));
    122       1.1    ichiro static int wi_write_data	__P((struct wi_softc *, int,
    123       1.1    ichiro 					int, caddr_t, int));
    124       1.1    ichiro static int wi_seek		__P((struct wi_softc *, int, int, int));
    125       1.1    ichiro static int wi_alloc_nicmem	__P((struct wi_softc *, int, int *));
    126      1.25  explorer static void wi_inquire_stats	__P((void *));
    127      1.25  explorer static void wi_inquire_scan	__P((void *));
    128       1.1    ichiro static int wi_setdef		__P((struct wi_softc *, struct wi_req *));
    129       1.1    ichiro static int wi_getdef		__P((struct wi_softc *, struct wi_req *));
    130       1.1    ichiro static int wi_mgmt_xmit		__P((struct wi_softc *, caddr_t, int));
    131       1.1    ichiro 
    132       1.1    ichiro static int wi_media_change __P((struct ifnet *));
    133       1.1    ichiro static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
    134       1.1    ichiro 
    135       1.4    ichiro static void wi_get_id		__P((struct wi_softc *));
    136       1.4    ichiro 
    137       1.1    ichiro static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int));
    138       1.1    ichiro static void wi_request_fill_ssid __P((struct wi_req *,
    139       1.1    ichiro     struct ieee80211_nwid *));
    140       1.1    ichiro static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
    141       1.1    ichiro     struct ieee80211_nwid *));
    142       1.1    ichiro static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    143       1.1    ichiro static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    144       1.1    ichiro static int wi_sync_media __P((struct wi_softc *, int, int));
    145       1.1    ichiro static int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
    146       1.1    ichiro static int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
    147       1.1    ichiro 
    148       1.1    ichiro int
    149       1.1    ichiro wi_attach(sc)
    150       1.1    ichiro 	struct wi_softc *sc;
    151       1.1    ichiro {
    152       1.1    ichiro 	struct ifnet *ifp = sc->sc_ifp;
    153       1.1    ichiro 	struct wi_ltv_macaddr   mac;
    154       1.1    ichiro 	struct wi_ltv_gen       gen;
    155       1.1    ichiro 	static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
    156       1.1    ichiro 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    157       1.1    ichiro 	};
    158       1.1    ichiro 	int s;
    159       1.1    ichiro 
    160       1.1    ichiro 	s = splnet();
    161       1.1    ichiro 
    162      1.25  explorer 	callout_init(&sc->wi_stats_ch);
    163      1.25  explorer 	callout_init(&sc->wi_scan_ch);
    164       1.1    ichiro 
    165       1.1    ichiro 	/* Make sure interrupts are disabled. */
    166       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    167       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    168       1.1    ichiro 
    169       1.1    ichiro 	/* Reset the NIC. */
    170       1.1    ichiro 	wi_reset(sc);
    171       1.1    ichiro 
    172       1.1    ichiro 	memset(&mac, 0, sizeof(mac));
    173       1.1    ichiro 	/* Read the station address. */
    174       1.1    ichiro 	mac.wi_type = WI_RID_MAC_NODE;
    175       1.1    ichiro 	mac.wi_len = 4;
    176       1.1    ichiro 	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
    177       1.1    ichiro 	memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
    178       1.1    ichiro 
    179       1.1    ichiro 	/*
    180       1.1    ichiro 	 * Check if we got anything meaningful.
    181       1.1    ichiro 	 *
    182       1.1    ichiro 	 * Is it really enough just checking against null ethernet address?
    183       1.1    ichiro 	 * Or, check against possible vendor?  XXX.
    184       1.1    ichiro 	 */
    185      1.19   thorpej 	if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) {
    186       1.1    ichiro 		printf("%s: could not get mac address, attach failed\n",
    187       1.1    ichiro 		    sc->sc_dev.dv_xname);
    188       1.1    ichiro 			return 1;
    189       1.1    ichiro 	}
    190       1.1    ichiro 
    191       1.1    ichiro 	printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr));
    192       1.1    ichiro 
    193       1.4    ichiro 	/* Read NIC identification */
    194       1.4    ichiro 	wi_get_id(sc);
    195       1.4    ichiro 
    196       1.1    ichiro 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
    197       1.1    ichiro 	ifp->if_softc = sc;
    198       1.1    ichiro 	ifp->if_start = wi_start;
    199       1.1    ichiro 	ifp->if_ioctl = wi_ioctl;
    200       1.1    ichiro 	ifp->if_watchdog = wi_watchdog;
    201       1.1    ichiro 	ifp->if_init = wi_init;
    202       1.1    ichiro 	ifp->if_stop = wi_stop;
    203       1.1    ichiro 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    204       1.1    ichiro #ifdef IFF_NOTRAILERS
    205       1.1    ichiro 	ifp->if_flags |= IFF_NOTRAILERS;
    206       1.1    ichiro #endif
    207       1.1    ichiro 	IFQ_SET_READY(&ifp->if_snd);
    208       1.1    ichiro 
    209       1.1    ichiro 	(void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
    210       1.1    ichiro 	    sizeof(WI_DEFAULT_NODENAME) - 1);
    211       1.1    ichiro 	(void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
    212       1.1    ichiro 	    sizeof(WI_DEFAULT_NETNAME) - 1);
    213       1.1    ichiro 	(void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
    214       1.1    ichiro 	    sizeof(WI_DEFAULT_IBSS) - 1);
    215       1.1    ichiro 
    216       1.1    ichiro 	sc->wi_portnum = WI_DEFAULT_PORT;
    217       1.1    ichiro 	sc->wi_ptype = WI_PORTTYPE_BSS;
    218       1.1    ichiro 	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
    219       1.1    ichiro 	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
    220       1.1    ichiro 	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
    221       1.1    ichiro 	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
    222       1.1    ichiro 	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
    223       1.1    ichiro 	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
    224       1.1    ichiro 	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
    225       1.4    ichiro 	sc->wi_roaming = WI_DEFAULT_ROAMING;
    226       1.4    ichiro 	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
    227       1.1    ichiro 
    228      1.25  explorer 	memset(&sc->wi_results, 0, sizeof (sc->wi_results));
    229      1.25  explorer 
    230       1.1    ichiro 	/*
    231       1.1    ichiro 	 * Read the default channel from the NIC. This may vary
    232       1.1    ichiro 	 * depending on the country where the NIC was purchased, so
    233       1.1    ichiro 	 * we can't hard-code a default and expect it to work for
    234       1.1    ichiro 	 * everyone.
    235       1.1    ichiro 	 */
    236       1.1    ichiro 	gen.wi_type = WI_RID_OWN_CHNL;
    237       1.1    ichiro 	gen.wi_len = 2;
    238       1.1    ichiro 	wi_read_record(sc, &gen);
    239      1.11    tsubai 	sc->wi_channel = le16toh(gen.wi_val);
    240       1.1    ichiro 
    241      1.21   thorpej 	memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
    242       1.1    ichiro 
    243       1.1    ichiro 	/*
    244       1.1    ichiro 	 * Find out if we support WEP on this card.
    245       1.1    ichiro 	 */
    246       1.1    ichiro 	gen.wi_type = WI_RID_WEP_AVAIL;
    247       1.1    ichiro 	gen.wi_len = 2;
    248       1.1    ichiro 	wi_read_record(sc, &gen);
    249      1.11    tsubai 	sc->wi_has_wep = le16toh(gen.wi_val);
    250       1.1    ichiro 
    251       1.1    ichiro 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
    252       1.1    ichiro #define	IFM_AUTOADHOC \
    253       1.1    ichiro 	IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0)
    254       1.1    ichiro #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
    255       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
    256       1.1    ichiro 	ADD(IFM_AUTOADHOC, 0);
    257       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
    258       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    259       1.1    ichiro 	    IFM_IEEE80211_ADHOC, 0), 0);
    260       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
    261       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    262       1.1    ichiro 	    IFM_IEEE80211_ADHOC, 0), 0);
    263       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
    264       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    265       1.1    ichiro 	    IFM_IEEE80211_ADHOC, 0), 0);
    266       1.1    ichiro 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
    267       1.1    ichiro #undef ADD
    268       1.1    ichiro 	ifmedia_set(&sc->sc_media, IFM_AUTOADHOC);
    269       1.1    ichiro 
    270       1.1    ichiro 	/*
    271       1.1    ichiro 	 * Call MI attach routines.
    272       1.1    ichiro 	 */
    273       1.1    ichiro 	if_attach(ifp);
    274       1.1    ichiro 	ether_ifattach(ifp, mac.wi_mac_addr);
    275       1.1    ichiro 
    276       1.1    ichiro 	ifp->if_baudrate = IF_Mbps(2);
    277       1.1    ichiro 
    278       1.1    ichiro 	/* Attach is successful. */
    279       1.1    ichiro 	sc->sc_attached = 1;
    280       1.1    ichiro 
    281       1.1    ichiro 	splx(s);
    282       1.1    ichiro 	return 0;
    283       1.1    ichiro }
    284       1.1    ichiro 
    285       1.1    ichiro static void wi_rxeof(sc)
    286       1.1    ichiro 	struct wi_softc		*sc;
    287       1.1    ichiro {
    288       1.1    ichiro 	struct ifnet		*ifp;
    289       1.1    ichiro 	struct ether_header	*eh;
    290       1.1    ichiro 	struct wi_frame		rx_frame;
    291       1.1    ichiro 	struct mbuf		*m;
    292       1.1    ichiro 	int			id;
    293      1.25  explorer 	u_int16_t		msg_type;
    294      1.25  explorer 	u_int16_t		status;
    295      1.25  explorer 	u_int16_t		frame_ctl;
    296      1.25  explorer 	u_int16_t		port;
    297       1.1    ichiro 
    298       1.1    ichiro 	ifp = sc->sc_ifp;
    299       1.1    ichiro 
    300       1.1    ichiro 	id = CSR_READ_2(sc, WI_RX_FID);
    301       1.1    ichiro 
    302       1.1    ichiro 	/* First read in the frame header */
    303       1.1    ichiro 	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
    304       1.1    ichiro 		ifp->if_ierrors++;
    305       1.1    ichiro 		return;
    306       1.1    ichiro 	}
    307       1.1    ichiro 
    308      1.25  explorer 	status = le16toh(rx_frame.wi_status);
    309      1.25  explorer 	frame_ctl = le16toh(rx_frame.wi_frame_ctl);
    310      1.25  explorer 	port = (status >> 8) & 0x07;
    311      1.25  explorer 	msg_type = status & WI_RXSTAT_MSG_TYPE;
    312      1.25  explorer 
    313      1.25  explorer 	/*
    314      1.25  explorer 	 * Drop packets with CRC errors here.  We may want the others,
    315      1.25  explorer 	 * since we may be doing interesting things with undecryptable
    316      1.25  explorer 	 * packets, like analyzing them in userland.
    317      1.25  explorer 	 */
    318      1.25  explorer 	if (status & WI_STAT_BADCRC) {
    319      1.25  explorer 		ifp->if_ierrors++;
    320      1.25  explorer 		return;
    321      1.25  explorer 	}
    322      1.25  explorer 
    323      1.25  explorer 	if (port == 7) {
    324      1.25  explorer 		if ((le16toh(rx_frame.wi_dat_len) + 60) > MCLBYTES)
    325      1.25  explorer 			return;
    326      1.25  explorer 
    327      1.25  explorer 		MGETHDR(m, M_DONTWAIT, MT_DATA);
    328      1.25  explorer 		if (m == NULL) {
    329      1.25  explorer 			ifp->if_ierrors++;
    330      1.25  explorer 			return;
    331      1.25  explorer 		}
    332      1.25  explorer 		MCLGET(m, M_DONTWAIT);
    333      1.25  explorer 		if (!(m->m_flags & M_EXT)) {
    334      1.25  explorer 			m_freem(m);
    335      1.25  explorer 			ifp->if_ierrors++;
    336      1.25  explorer 			return;
    337      1.25  explorer 		}
    338      1.25  explorer 
    339      1.25  explorer 		memcpy(mtod(m, caddr_t), &rx_frame, 60);
    340      1.25  explorer 		m->m_pkthdr.rcvif = ifp;
    341      1.25  explorer 
    342      1.25  explorer 		m->m_pkthdr.len = m->m_len =
    343      1.25  explorer 			le16toh(rx_frame.wi_dat_len) + 60;
    344      1.25  explorer 
    345      1.25  explorer 		if (wi_read_data(sc, id, 60, mtod(m, caddr_t) + 60,
    346      1.25  explorer 				 m->m_len - 60)) {
    347      1.25  explorer 			m_freem(m);
    348      1.25  explorer 			ifp->if_ierrors++;
    349      1.25  explorer 			return;
    350      1.25  explorer 		}
    351      1.25  explorer 
    352      1.25  explorer #if NBPFILTER > 0
    353      1.25  explorer 		if (ifp->if_bpf)
    354      1.25  explorer 			bpf_mtap(ifp->if_bpf, m);
    355      1.25  explorer #endif
    356      1.25  explorer 		m_freem(m);
    357      1.25  explorer 		return;
    358      1.25  explorer 	}
    359      1.25  explorer 
    360      1.25  explorer 	/*
    361      1.25  explorer 	 * Drop undecryptable or packets with receive errors here
    362      1.25  explorer 	 */
    363      1.25  explorer 	if (status & WI_STAT_ERRSTAT) {
    364       1.1    ichiro 		ifp->if_ierrors++;
    365       1.1    ichiro 		return;
    366       1.1    ichiro 	}
    367       1.1    ichiro 
    368       1.1    ichiro 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    369       1.1    ichiro 	if (m == NULL) {
    370       1.1    ichiro 		ifp->if_ierrors++;
    371       1.1    ichiro 		return;
    372       1.1    ichiro 	}
    373       1.1    ichiro 	MCLGET(m, M_DONTWAIT);
    374       1.1    ichiro 	if (!(m->m_flags & M_EXT)) {
    375       1.1    ichiro 		m_freem(m);
    376       1.1    ichiro 		ifp->if_ierrors++;
    377       1.1    ichiro 		return;
    378       1.1    ichiro 	}
    379       1.1    ichiro 
    380       1.1    ichiro 	/* Align the data after the ethernet header */
    381      1.11    tsubai 	m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
    382       1.1    ichiro 	    - sizeof(struct ether_header);
    383       1.1    ichiro 
    384       1.1    ichiro 	eh = mtod(m, struct ether_header *);
    385       1.1    ichiro 	m->m_pkthdr.rcvif = ifp;
    386       1.1    ichiro 
    387      1.11    tsubai 	if (le16toh(rx_frame.wi_status) == WI_STAT_1042 ||
    388      1.11    tsubai 	    le16toh(rx_frame.wi_status) == WI_STAT_TUNNEL ||
    389      1.11    tsubai 	    le16toh(rx_frame.wi_status) == WI_STAT_WMP_MSG) {
    390      1.11    tsubai 		if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) {
    391       1.1    ichiro 			printf("%s: oversized packet received "
    392       1.1    ichiro 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    393       1.1    ichiro 			    sc->sc_dev.dv_xname,
    394      1.11    tsubai 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    395       1.1    ichiro 			m_freem(m);
    396       1.1    ichiro 			ifp->if_ierrors++;
    397       1.1    ichiro 			return;
    398       1.1    ichiro 		}
    399       1.1    ichiro 		m->m_pkthdr.len = m->m_len =
    400      1.11    tsubai 		    le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
    401       1.1    ichiro 
    402      1.20   thorpej 		memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr,
    403      1.20   thorpej 		    ETHER_ADDR_LEN);
    404      1.20   thorpej 		memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr,
    405      1.20   thorpej 		    ETHER_ADDR_LEN);
    406      1.20   thorpej 		memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type,
    407      1.20   thorpej 		    sizeof(u_int16_t));
    408       1.1    ichiro 
    409       1.1    ichiro 		if (wi_read_data(sc, id, WI_802_11_OFFSET,
    410       1.1    ichiro 		    mtod(m, caddr_t) + sizeof(struct ether_header),
    411       1.1    ichiro 		    m->m_len + 2)) {
    412       1.1    ichiro 			m_freem(m);
    413       1.1    ichiro 			ifp->if_ierrors++;
    414       1.1    ichiro 			return;
    415       1.1    ichiro 		}
    416       1.1    ichiro 	} else {
    417      1.11    tsubai 		if ((le16toh(rx_frame.wi_dat_len) +
    418       1.1    ichiro 		    sizeof(struct ether_header)) > MCLBYTES) {
    419       1.1    ichiro 			printf("%s: oversized packet received "
    420       1.1    ichiro 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    421       1.1    ichiro 			    sc->sc_dev.dv_xname,
    422      1.11    tsubai 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    423       1.1    ichiro 			m_freem(m);
    424       1.1    ichiro 			ifp->if_ierrors++;
    425       1.1    ichiro 			return;
    426       1.1    ichiro 		}
    427       1.1    ichiro 		m->m_pkthdr.len = m->m_len =
    428      1.11    tsubai 		    le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header);
    429       1.1    ichiro 
    430       1.1    ichiro 		if (wi_read_data(sc, id, WI_802_3_OFFSET,
    431       1.1    ichiro 		    mtod(m, caddr_t), m->m_len + 2)) {
    432       1.1    ichiro 			m_freem(m);
    433       1.1    ichiro 			ifp->if_ierrors++;
    434       1.1    ichiro 			return;
    435       1.1    ichiro 		}
    436       1.1    ichiro 	}
    437       1.1    ichiro 
    438       1.1    ichiro 	ifp->if_ipackets++;
    439       1.1    ichiro 
    440       1.1    ichiro #if NBPFILTER > 0
    441       1.1    ichiro 	/* Handle BPF listeners. */
    442       1.1    ichiro 	if (ifp->if_bpf)
    443       1.1    ichiro 		bpf_mtap(ifp->if_bpf, m);
    444       1.1    ichiro #endif
    445       1.1    ichiro 
    446      1.25  explorer 	/*
    447      1.25  explorer 	 * Discard packets which are not data packets
    448      1.25  explorer 	 */
    449      1.25  explorer 	if (WLAN_FC_GET_TYPE(frame_ctl) != WLAN_FC_TYPE_DATA) {
    450      1.25  explorer 		m_freem(m);
    451      1.25  explorer 		return;
    452      1.25  explorer 	}
    453      1.25  explorer 
    454       1.1    ichiro 	/* Receive packet. */
    455       1.1    ichiro 	(*ifp->if_input)(ifp, m);
    456       1.1    ichiro }
    457       1.1    ichiro 
    458       1.1    ichiro static void wi_txeof(sc, status)
    459       1.1    ichiro 	struct wi_softc	*sc;
    460       1.1    ichiro 	int		status;
    461       1.1    ichiro {
    462       1.1    ichiro 	struct ifnet	*ifp = sc->sc_ifp;
    463       1.1    ichiro 
    464       1.1    ichiro 	ifp->if_timer = 0;
    465       1.1    ichiro 	ifp->if_flags &= ~IFF_OACTIVE;
    466       1.1    ichiro 
    467       1.1    ichiro 	if (status & WI_EV_TX_EXC)
    468       1.1    ichiro 		ifp->if_oerrors++;
    469       1.1    ichiro 	else
    470       1.1    ichiro 		ifp->if_opackets++;
    471       1.1    ichiro 
    472       1.1    ichiro 	return;
    473       1.1    ichiro }
    474       1.1    ichiro 
    475      1.25  explorer void wi_inquire_stats(xsc)
    476       1.1    ichiro 	void			*xsc;
    477       1.1    ichiro {
    478       1.1    ichiro 	struct wi_softc		*sc;
    479       1.1    ichiro 	struct ifnet		*ifp;
    480       1.1    ichiro 
    481       1.1    ichiro 	sc = xsc;
    482       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    483       1.1    ichiro 
    484       1.1    ichiro 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
    485       1.1    ichiro 		return;
    486       1.1    ichiro 
    487      1.25  explorer 	callout_reset(&sc->wi_stats_ch, STATS_FREQUENCY, wi_inquire_stats, sc);
    488       1.1    ichiro 
    489       1.1    ichiro 	/* Don't do this while we're transmitting */
    490       1.1    ichiro 	if (ifp->if_flags & IFF_OACTIVE)
    491       1.1    ichiro 		return;
    492       1.1    ichiro 
    493       1.1    ichiro 	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
    494      1.25  explorer }
    495      1.25  explorer 
    496      1.25  explorer void wi_inquire_scan(xsc)
    497      1.25  explorer 	void			*xsc;
    498      1.25  explorer {
    499      1.25  explorer 	struct wi_softc		*sc;
    500      1.25  explorer 	struct ifnet		*ifp;
    501      1.25  explorer 
    502      1.25  explorer 	sc = xsc;
    503      1.25  explorer 	ifp = &sc->sc_ethercom.ec_if;
    504      1.25  explorer 
    505      1.25  explorer 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
    506      1.25  explorer 		return;
    507      1.25  explorer 
    508      1.25  explorer 	if (sc->wi_results.scanning > 0)
    509      1.25  explorer 		callout_reset(&sc->wi_scan_ch, sc->wi_results.scanning,
    510      1.25  explorer 			      wi_inquire_scan, sc);
    511      1.25  explorer 	else
    512      1.25  explorer 		callout_stop(&sc->wi_scan_ch);
    513       1.1    ichiro 
    514      1.25  explorer 	/* Don't do this while we're transmitting */
    515      1.25  explorer 	if (ifp->if_flags & IFF_OACTIVE)
    516      1.25  explorer 		return;
    517      1.25  explorer 
    518      1.25  explorer 	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS);
    519       1.1    ichiro }
    520       1.1    ichiro 
    521       1.1    ichiro void wi_update_stats(sc)
    522       1.1    ichiro 	struct wi_softc		*sc;
    523       1.1    ichiro {
    524       1.1    ichiro 	struct wi_ltv_gen	gen;
    525       1.1    ichiro 	u_int16_t		id;
    526       1.1    ichiro 	struct ifnet		*ifp;
    527       1.1    ichiro 	u_int32_t		*ptr;
    528       1.1    ichiro 	int			len, i;
    529       1.1    ichiro 	u_int16_t		t;
    530       1.1    ichiro 
    531       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    532       1.1    ichiro 
    533       1.1    ichiro 	id = CSR_READ_2(sc, WI_INFO_FID);
    534       1.1    ichiro 
    535       1.1    ichiro 	wi_read_data(sc, id, 0, (char *)&gen, 4);
    536       1.1    ichiro 
    537      1.25  explorer 	switch (gen.wi_type) {
    538      1.25  explorer 	case WI_INFO_COUNTERS:
    539      1.25  explorer 		/* some card versions have a larger stats structure */
    540      1.25  explorer 		len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
    541      1.25  explorer 			gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
    542      1.25  explorer 		ptr = (u_int32_t *)&sc->wi_stats;
    543       1.1    ichiro 
    544      1.25  explorer 		for (i = 0; i < len; i++) {
    545      1.25  explorer 			t = CSR_READ_2(sc, WI_DATA1);
    546       1.1    ichiro #ifdef WI_HERMES_STATS_WAR
    547      1.25  explorer 			if (t > 0xF000)
    548      1.25  explorer 				t = ~t & 0xFFFF;
    549       1.1    ichiro #endif
    550      1.25  explorer 			ptr[i] += t;
    551      1.25  explorer 		}
    552      1.25  explorer 
    553      1.25  explorer 		ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
    554      1.25  explorer 			sc->wi_stats.wi_tx_multi_retries +
    555      1.25  explorer 			sc->wi_stats.wi_tx_retry_limit;
    556      1.25  explorer 		break;
    557       1.1    ichiro 
    558      1.25  explorer 	case WI_INFO_SCAN_RESULTS:
    559      1.25  explorer 		microtime(&sc->wi_results.lastscan);
    560      1.25  explorer 		for (i = 0 ; i < gen.wi_len - 1 ; i++) {
    561      1.25  explorer 			t = CSR_READ_2(sc, WI_DATA1);
    562      1.25  explorer 			if (i < WI_SCAN_RESULTS_MAXLEN)
    563      1.25  explorer 				sc->wi_results.scan_results[i] = t;
    564      1.25  explorer 		}
    565      1.25  explorer 		if (gen.wi_len - 1 <= WI_SCAN_RESULTS_MAXLEN) {
    566      1.25  explorer 			sc->wi_results.len = gen.wi_len - 1;
    567      1.25  explorer 			sc->wi_results.truncated = 0;
    568      1.25  explorer 		} else {
    569      1.25  explorer 			sc->wi_results.len = WI_SCAN_RESULTS_MAXLEN;
    570      1.25  explorer 			sc->wi_results.truncated = 1;
    571      1.25  explorer 		}
    572      1.25  explorer 		break;
    573       1.1    ichiro 
    574      1.25  explorer 	default:
    575      1.25  explorer #if 0
    576      1.25  explorer 		printf("Got info type: %04x\n", gen.wi_type);
    577      1.25  explorer #endif
    578      1.25  explorer 		for (i = 0; i < gen.wi_len; i++) {
    579      1.25  explorer 			t = CSR_READ_2(sc, WI_DATA1);
    580      1.25  explorer #if 0
    581      1.25  explorer 			printf("[0x%02x] = 0x%04x\n", i, t);
    582      1.25  explorer #endif
    583      1.25  explorer 		}
    584      1.25  explorer 		break;
    585      1.25  explorer 	}
    586       1.1    ichiro }
    587       1.1    ichiro 
    588       1.1    ichiro int wi_intr(arg)
    589       1.1    ichiro 	void *arg;
    590       1.1    ichiro {
    591       1.1    ichiro 	struct wi_softc		*sc = arg;
    592       1.1    ichiro 	struct ifnet		*ifp;
    593       1.1    ichiro 	u_int16_t		status;
    594       1.1    ichiro 
    595       1.1    ichiro 	if (sc->sc_enabled == 0 ||
    596       1.1    ichiro 	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
    597       1.1    ichiro 	    (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
    598       1.1    ichiro 		return (0);
    599       1.1    ichiro 
    600       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
    601       1.1    ichiro 
    602       1.1    ichiro 	if (!(ifp->if_flags & IFF_UP)) {
    603       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    604       1.1    ichiro 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    605       1.1    ichiro 		return 1;
    606       1.1    ichiro 	}
    607       1.1    ichiro 
    608       1.1    ichiro 	/* Disable interrupts. */
    609       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    610       1.1    ichiro 
    611       1.1    ichiro 	status = CSR_READ_2(sc, WI_EVENT_STAT);
    612       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
    613       1.1    ichiro 
    614       1.1    ichiro 	if (status & WI_EV_RX) {
    615       1.1    ichiro 		wi_rxeof(sc);
    616       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
    617       1.1    ichiro 	}
    618       1.1    ichiro 
    619       1.1    ichiro 	if (status & WI_EV_TX) {
    620       1.1    ichiro 		wi_txeof(sc, status);
    621       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
    622       1.1    ichiro 	}
    623       1.1    ichiro 
    624       1.1    ichiro 	if (status & WI_EV_ALLOC) {
    625       1.1    ichiro 		int			id;
    626       1.1    ichiro 		id = CSR_READ_2(sc, WI_ALLOC_FID);
    627       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
    628       1.1    ichiro 		if (id == sc->wi_tx_data_id)
    629       1.1    ichiro 			wi_txeof(sc, status);
    630       1.1    ichiro 	}
    631       1.1    ichiro 
    632       1.1    ichiro 	if (status & WI_EV_INFO) {
    633       1.1    ichiro 		wi_update_stats(sc);
    634       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
    635       1.1    ichiro 	}
    636       1.1    ichiro 
    637       1.1    ichiro 	if (status & WI_EV_TX_EXC) {
    638       1.1    ichiro 		wi_txeof(sc, status);
    639       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
    640       1.1    ichiro 	}
    641       1.1    ichiro 
    642       1.1    ichiro 	if (status & WI_EV_INFO_DROP) {
    643       1.1    ichiro 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
    644       1.1    ichiro 	}
    645       1.1    ichiro 
    646       1.1    ichiro 	/* Re-enable interrupts. */
    647       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    648       1.1    ichiro 
    649       1.1    ichiro 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    650       1.1    ichiro 		wi_start(ifp);
    651       1.1    ichiro 
    652       1.1    ichiro 	return 1;
    653       1.1    ichiro }
    654       1.1    ichiro 
    655      1.11    tsubai static int
    656       1.1    ichiro wi_cmd(sc, cmd, val)
    657       1.1    ichiro 	struct wi_softc		*sc;
    658       1.1    ichiro 	int			cmd;
    659       1.1    ichiro 	int			val;
    660       1.1    ichiro {
    661       1.1    ichiro 	int			i, s = 0;
    662       1.1    ichiro 
    663       1.1    ichiro 	/* wait for the busy bit to clear */
    664       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    665       1.1    ichiro 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
    666       1.1    ichiro 			break;
    667       1.1    ichiro 	}
    668       1.1    ichiro 
    669       1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM0, val);
    670       1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM1, 0);
    671       1.1    ichiro 	CSR_WRITE_2(sc, WI_PARAM2, 0);
    672       1.1    ichiro 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
    673       1.1    ichiro 
    674       1.1    ichiro 	/* wait for the cmd completed bit */
    675       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    676       1.1    ichiro 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
    677       1.1    ichiro 			break;
    678       1.2    ichiro 		DELAY(1);
    679       1.1    ichiro 	}
    680       1.1    ichiro 
    681       1.1    ichiro 	/* Ack the command */
    682       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
    683       1.1    ichiro 
    684       1.1    ichiro 	s = CSR_READ_2(sc, WI_STATUS);
    685       1.1    ichiro 	if (s & WI_STAT_CMD_RESULT)
    686       1.1    ichiro 		return(EIO);
    687       1.1    ichiro 
    688       1.1    ichiro 	if (i == WI_TIMEOUT)
    689       1.1    ichiro 		return(ETIMEDOUT);
    690       1.1    ichiro 
    691       1.1    ichiro 	return(0);
    692       1.1    ichiro }
    693       1.1    ichiro 
    694      1.11    tsubai static void
    695       1.1    ichiro wi_reset(sc)
    696       1.1    ichiro 	struct wi_softc		*sc;
    697       1.1    ichiro {
    698      1.11    tsubai 	DELAY(100*1000); /* 100 m sec */
    699       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_INI, 0))
    700       1.1    ichiro 		printf("%s: init failed\n", sc->sc_dev.dv_xname);
    701       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    702       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    703       1.1    ichiro 
    704       1.1    ichiro 	/* Calibrate timer. */
    705       1.1    ichiro 	WI_SETVAL(WI_RID_TICK_TIME, 8);
    706       1.1    ichiro 
    707       1.1    ichiro 	return;
    708       1.1    ichiro }
    709       1.1    ichiro 
    710      1.26    ichiro void
    711      1.26    ichiro wi_pci_reset(sc)
    712      1.26    ichiro 	struct wi_softc		*sc;
    713      1.26    ichiro {
    714      1.27    ichiro 	bus_space_write_2(sc->sc_iot, sc->sc_ioh,
    715      1.27    ichiro 			  WI_PCI_COR, WI_PCI_SOFT_RESET);
    716      1.26    ichiro 	DELAY(100*1000); /* 100 m sec */
    717      1.26    ichiro 
    718      1.26    ichiro 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WI_PCI_COR, 0x0);
    719      1.26    ichiro 	DELAY(100*1000); /* 100 m sec */
    720      1.26    ichiro 
    721      1.26    ichiro 	return;
    722      1.26    ichiro }
    723      1.26    ichiro 
    724       1.1    ichiro /*
    725       1.1    ichiro  * Read an LTV record from the NIC.
    726       1.1    ichiro  */
    727       1.1    ichiro static int wi_read_record(sc, ltv)
    728       1.1    ichiro 	struct wi_softc		*sc;
    729       1.1    ichiro 	struct wi_ltv_gen	*ltv;
    730       1.1    ichiro {
    731       1.1    ichiro 	u_int16_t		*ptr;
    732      1.15    toshii 	int			len, code;
    733       1.1    ichiro 	struct wi_ltv_gen	*oltv, p2ltv;
    734       1.1    ichiro 
    735       1.1    ichiro 	if (sc->sc_prism2) {
    736       1.1    ichiro 		oltv = ltv;
    737       1.1    ichiro 		switch (ltv->wi_type) {
    738       1.1    ichiro 		case WI_RID_ENCRYPTION:
    739       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
    740       1.1    ichiro 			p2ltv.wi_len = 2;
    741       1.1    ichiro 			ltv = &p2ltv;
    742       1.1    ichiro 			break;
    743       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    744       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
    745       1.1    ichiro 			p2ltv.wi_len = 2;
    746       1.1    ichiro 			ltv = &p2ltv;
    747       1.1    ichiro 			break;
    748       1.1    ichiro 		}
    749       1.1    ichiro 	}
    750       1.1    ichiro 
    751       1.1    ichiro 	/* Tell the NIC to enter record read mode. */
    752       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
    753       1.1    ichiro 		return(EIO);
    754       1.1    ichiro 
    755       1.1    ichiro 	/* Seek to the record. */
    756       1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
    757       1.1    ichiro 		return(EIO);
    758       1.1    ichiro 
    759       1.1    ichiro 	/*
    760       1.1    ichiro 	 * Read the length and record type and make sure they
    761       1.1    ichiro 	 * match what we expect (this verifies that we have enough
    762       1.1    ichiro 	 * room to hold all of the returned data).
    763       1.1    ichiro 	 */
    764       1.1    ichiro 	len = CSR_READ_2(sc, WI_DATA1);
    765       1.1    ichiro 	if (len > ltv->wi_len)
    766       1.1    ichiro 		return(ENOSPC);
    767       1.1    ichiro 	code = CSR_READ_2(sc, WI_DATA1);
    768       1.1    ichiro 	if (code != ltv->wi_type)
    769       1.1    ichiro 		return(EIO);
    770       1.1    ichiro 
    771       1.1    ichiro 	ltv->wi_len = len;
    772       1.1    ichiro 	ltv->wi_type = code;
    773       1.1    ichiro 
    774       1.1    ichiro 	/* Now read the data. */
    775       1.1    ichiro 	ptr = <v->wi_val;
    776      1.16    toshii 	if (ltv->wi_len > 1)
    777      1.16    toshii 		CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
    778       1.1    ichiro 
    779       1.1    ichiro 	if (sc->sc_prism2) {
    780      1.11    tsubai 		int v;
    781      1.11    tsubai 
    782       1.1    ichiro 		switch (oltv->wi_type) {
    783       1.1    ichiro 		case WI_RID_TX_RATE:
    784       1.1    ichiro 		case WI_RID_CUR_TX_RATE:
    785      1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
    786      1.11    tsubai 			case 1: v = 1; break;
    787      1.11    tsubai 			case 2: v = 2; break;
    788      1.11    tsubai 			case 3:	v = 6; break;
    789      1.11    tsubai 			case 4: v = 5; break;
    790      1.11    tsubai 			case 7: v = 7; break;
    791      1.11    tsubai 			case 8: v = 11; break;
    792      1.11    tsubai 			case 15: v = 3; break;
    793      1.11    tsubai 			default: v = 0x100 + le16toh(ltv->wi_val); break;
    794       1.1    ichiro 			}
    795      1.11    tsubai 			oltv->wi_val = htole16(v);
    796       1.1    ichiro 			break;
    797       1.1    ichiro 		case WI_RID_ENCRYPTION:
    798       1.1    ichiro 			oltv->wi_len = 2;
    799      1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
    800      1.11    tsubai 				oltv->wi_val = htole16(1);
    801       1.1    ichiro 			else
    802      1.11    tsubai 				oltv->wi_val = htole16(0);
    803       1.1    ichiro 			break;
    804       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    805       1.1    ichiro 			oltv->wi_len = 2;
    806       1.1    ichiro 			oltv->wi_val = ltv->wi_val;
    807       1.1    ichiro 			break;
    808       1.4    ichiro 		case WI_RID_AUTH_CNTL:
    809       1.4    ichiro 			oltv->wi_len = 2;
    810      1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
    811      1.11    tsubai 				oltv->wi_val = htole16(1);
    812      1.11    tsubai 			else if (le16toh(ltv->wi_val) & 0x02)
    813      1.11    tsubai 				oltv->wi_val = htole16(2);
    814       1.4    ichiro 			break;
    815       1.1    ichiro 		}
    816       1.1    ichiro 	}
    817       1.1    ichiro 
    818       1.1    ichiro 	return(0);
    819       1.1    ichiro }
    820       1.1    ichiro 
    821       1.1    ichiro /*
    822       1.1    ichiro  * Same as read, except we inject data instead of reading it.
    823       1.1    ichiro  */
    824       1.1    ichiro static int wi_write_record(sc, ltv)
    825       1.1    ichiro 	struct wi_softc		*sc;
    826       1.1    ichiro 	struct wi_ltv_gen	*ltv;
    827       1.1    ichiro {
    828       1.1    ichiro 	u_int16_t		*ptr;
    829       1.1    ichiro 	int			i;
    830       1.1    ichiro 	struct wi_ltv_gen	p2ltv;
    831       1.1    ichiro 
    832       1.1    ichiro 	if (sc->sc_prism2) {
    833      1.11    tsubai 		int v;
    834      1.11    tsubai 
    835       1.1    ichiro 		switch (ltv->wi_type) {
    836       1.1    ichiro 		case WI_RID_TX_RATE:
    837       1.1    ichiro 			p2ltv.wi_type = WI_RID_TX_RATE;
    838       1.1    ichiro 			p2ltv.wi_len = 2;
    839      1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
    840      1.11    tsubai 			case 1: v = 1; break;
    841      1.11    tsubai 			case 2: v = 2; break;
    842      1.11    tsubai 			case 3:	v = 15; break;
    843      1.11    tsubai 			case 5: v = 4; break;
    844      1.11    tsubai 			case 6: v = 3; break;
    845      1.11    tsubai 			case 7: v = 7; break;
    846      1.11    tsubai 			case 11: v = 8; break;
    847       1.1    ichiro 			default: return EINVAL;
    848       1.1    ichiro 			}
    849      1.11    tsubai 			p2ltv.wi_val = htole16(v);
    850       1.1    ichiro 			ltv = &p2ltv;
    851       1.1    ichiro 			break;
    852       1.1    ichiro 		case WI_RID_ENCRYPTION:
    853       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
    854       1.1    ichiro 			p2ltv.wi_len = 2;
    855      1.11    tsubai 			if (le16toh(ltv->wi_val))
    856      1.11    tsubai 				p2ltv.wi_val = htole16(0x03);
    857       1.1    ichiro 			else
    858      1.11    tsubai 				p2ltv.wi_val = htole16(0x90);
    859       1.1    ichiro 			ltv = &p2ltv;
    860       1.1    ichiro 			break;
    861       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    862       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
    863       1.1    ichiro 			p2ltv.wi_len = 2;
    864       1.1    ichiro 			p2ltv.wi_val = ltv->wi_val;
    865       1.1    ichiro 			ltv = &p2ltv;
    866       1.1    ichiro 			break;
    867       1.1    ichiro 		case WI_RID_DEFLT_CRYPT_KEYS:
    868       1.1    ichiro 		    {
    869       1.1    ichiro 			int error;
    870       1.1    ichiro 			struct wi_ltv_str	ws;
    871       1.1    ichiro 			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
    872       1.1    ichiro 			for (i = 0; i < 4; i++) {
    873       1.1    ichiro 				ws.wi_len = 4;
    874       1.1    ichiro 				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
    875       1.1    ichiro 				memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
    876       1.1    ichiro 				ws.wi_str[5] = '\0';
    877       1.1    ichiro 				error = wi_write_record(sc,
    878       1.1    ichiro 				    (struct wi_ltv_gen *)&ws);
    879       1.1    ichiro 				if (error)
    880       1.1    ichiro 					return error;
    881       1.1    ichiro 			}
    882       1.1    ichiro 			return 0;
    883       1.1    ichiro 		    }
    884       1.4    ichiro 		case WI_RID_AUTH_CNTL:
    885       1.4    ichiro 			p2ltv.wi_type = WI_RID_AUTH_CNTL;
    886       1.4    ichiro 			p2ltv.wi_len = 2;
    887      1.11    tsubai 			if (le16toh(ltv->wi_val) == 1)
    888      1.11    tsubai 				p2ltv.wi_val = htole16(0x01);
    889      1.11    tsubai 			else if (le16toh(ltv->wi_val) == 2)
    890      1.11    tsubai 				p2ltv.wi_val = htole16(0x02);
    891       1.4    ichiro 			ltv = &p2ltv;
    892       1.4    ichiro 			break;
    893       1.1    ichiro 		}
    894       1.1    ichiro 	}
    895       1.1    ichiro 
    896       1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
    897       1.1    ichiro 		return(EIO);
    898       1.1    ichiro 
    899       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
    900       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
    901       1.1    ichiro 
    902       1.1    ichiro 	/* Write data */
    903       1.1    ichiro 	ptr = <v->wi_val;
    904      1.16    toshii 	if (ltv->wi_len > 1)
    905      1.16    toshii 		CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
    906       1.1    ichiro 
    907       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
    908       1.1    ichiro 		return(EIO);
    909       1.1    ichiro 
    910       1.1    ichiro 	return(0);
    911       1.1    ichiro }
    912       1.1    ichiro 
    913       1.1    ichiro static int wi_seek(sc, id, off, chan)
    914       1.1    ichiro 	struct wi_softc		*sc;
    915       1.1    ichiro 	int			id, off, chan;
    916       1.1    ichiro {
    917       1.1    ichiro 	int			i;
    918       1.1    ichiro 	int			selreg, offreg;
    919       1.1    ichiro 	int 			status;
    920       1.1    ichiro 
    921       1.1    ichiro 	switch (chan) {
    922       1.1    ichiro 	case WI_BAP0:
    923       1.1    ichiro 		selreg = WI_SEL0;
    924       1.1    ichiro 		offreg = WI_OFF0;
    925       1.1    ichiro 		break;
    926       1.1    ichiro 	case WI_BAP1:
    927       1.1    ichiro 		selreg = WI_SEL1;
    928       1.1    ichiro 		offreg = WI_OFF1;
    929       1.1    ichiro 		break;
    930       1.1    ichiro 	default:
    931       1.1    ichiro 		printf("%s: invalid data path: %x\n",
    932       1.1    ichiro 		    sc->sc_dev.dv_xname, chan);
    933       1.1    ichiro 		return(EIO);
    934       1.1    ichiro 	}
    935       1.1    ichiro 
    936       1.1    ichiro 	CSR_WRITE_2(sc, selreg, id);
    937       1.1    ichiro 	CSR_WRITE_2(sc, offreg, off);
    938       1.1    ichiro 
    939       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    940       1.1    ichiro 	  	status = CSR_READ_2(sc, offreg);
    941       1.1    ichiro 		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
    942       1.1    ichiro 			break;
    943       1.1    ichiro 	}
    944       1.1    ichiro 
    945       1.1    ichiro 	if (i == WI_TIMEOUT) {
    946       1.1    ichiro 		printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
    947       1.1    ichiro 		       sc->sc_dev.dv_xname, id, off, status);
    948       1.1    ichiro 		return(ETIMEDOUT);
    949       1.1    ichiro 	}
    950       1.1    ichiro 	return(0);
    951       1.1    ichiro }
    952       1.1    ichiro 
    953       1.1    ichiro static int wi_read_data(sc, id, off, buf, len)
    954       1.1    ichiro 	struct wi_softc		*sc;
    955       1.1    ichiro 	int			id, off;
    956       1.1    ichiro 	caddr_t			buf;
    957       1.1    ichiro 	int			len;
    958       1.1    ichiro {
    959       1.1    ichiro 	u_int16_t		*ptr;
    960       1.1    ichiro 
    961       1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP1))
    962       1.1    ichiro 		return(EIO);
    963       1.1    ichiro 
    964       1.1    ichiro 	ptr = (u_int16_t *)buf;
    965      1.15    toshii 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
    966       1.1    ichiro 
    967       1.1    ichiro 	return(0);
    968       1.1    ichiro }
    969       1.1    ichiro 
    970       1.1    ichiro /*
    971       1.1    ichiro  * According to the comments in the HCF Light code, there is a bug in
    972       1.1    ichiro  * the Hermes (or possibly in certain Hermes firmware revisions) where
    973       1.1    ichiro  * the chip's internal autoincrement counter gets thrown off during
    974       1.1    ichiro  * data writes: the autoincrement is missed, causing one data word to
    975       1.1    ichiro  * be overwritten and subsequent words to be written to the wrong memory
    976       1.1    ichiro  * locations. The end result is that we could end up transmitting bogus
    977       1.1    ichiro  * frames without realizing it. The workaround for this is to write a
    978       1.1    ichiro  * couple of extra guard words after the end of the transfer, then
    979       1.1    ichiro  * attempt to read then back. If we fail to locate the guard words where
    980       1.1    ichiro  * we expect them, we preform the transfer over again.
    981       1.1    ichiro  */
    982       1.1    ichiro static int wi_write_data(sc, id, off, buf, len)
    983       1.1    ichiro 	struct wi_softc		*sc;
    984       1.1    ichiro 	int			id, off;
    985       1.1    ichiro 	caddr_t			buf;
    986       1.1    ichiro 	int			len;
    987       1.1    ichiro {
    988       1.1    ichiro 	u_int16_t		*ptr;
    989       1.1    ichiro 
    990       1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
    991       1.1    ichiro again:
    992       1.1    ichiro #endif
    993       1.1    ichiro 
    994       1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP0))
    995       1.1    ichiro 		return(EIO);
    996       1.1    ichiro 
    997       1.1    ichiro 	ptr = (u_int16_t *)buf;
    998      1.15    toshii 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
    999       1.1    ichiro 
   1000       1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
   1001       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
   1002       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
   1003       1.1    ichiro 
   1004       1.1    ichiro 	if (wi_seek(sc, id, off + len, WI_BAP0))
   1005       1.1    ichiro 		return(EIO);
   1006       1.1    ichiro 
   1007       1.1    ichiro 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
   1008       1.1    ichiro 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
   1009       1.1    ichiro 		goto again;
   1010       1.1    ichiro #endif
   1011       1.1    ichiro 
   1012       1.1    ichiro 	return(0);
   1013       1.1    ichiro }
   1014       1.1    ichiro 
   1015       1.1    ichiro /*
   1016       1.1    ichiro  * Allocate a region of memory inside the NIC and zero
   1017       1.1    ichiro  * it out.
   1018       1.1    ichiro  */
   1019       1.1    ichiro static int wi_alloc_nicmem(sc, len, id)
   1020       1.1    ichiro 	struct wi_softc		*sc;
   1021       1.1    ichiro 	int			len;
   1022       1.1    ichiro 	int			*id;
   1023       1.1    ichiro {
   1024       1.1    ichiro 	int			i;
   1025       1.1    ichiro 
   1026       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
   1027       1.1    ichiro 		printf("%s: failed to allocate %d bytes on NIC\n",
   1028       1.1    ichiro 		    sc->sc_dev.dv_xname, len);
   1029       1.1    ichiro 		return(ENOMEM);
   1030       1.1    ichiro 	}
   1031       1.1    ichiro 
   1032       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
   1033       1.1    ichiro 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   1034       1.1    ichiro 			break;
   1035       1.1    ichiro 	}
   1036       1.1    ichiro 
   1037       1.1    ichiro 	if (i == WI_TIMEOUT) {
   1038       1.1    ichiro 		printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
   1039       1.1    ichiro 		return(ETIMEDOUT);
   1040       1.1    ichiro 	}
   1041       1.1    ichiro 
   1042       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1043       1.1    ichiro 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
   1044       1.1    ichiro 
   1045       1.1    ichiro 	if (wi_seek(sc, *id, 0, WI_BAP0)) {
   1046       1.1    ichiro 		printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
   1047       1.1    ichiro 		return(EIO);
   1048       1.1    ichiro 	}
   1049       1.1    ichiro 
   1050       1.1    ichiro 	for (i = 0; i < len / 2; i++)
   1051       1.1    ichiro 		CSR_WRITE_2(sc, WI_DATA0, 0);
   1052       1.1    ichiro 
   1053       1.1    ichiro 	return(0);
   1054       1.1    ichiro }
   1055       1.1    ichiro 
   1056       1.1    ichiro static void wi_setmulti(sc)
   1057       1.1    ichiro 	struct wi_softc		*sc;
   1058       1.1    ichiro {
   1059       1.1    ichiro 	struct ifnet		*ifp;
   1060       1.1    ichiro 	int			i = 0;
   1061       1.1    ichiro 	struct wi_ltv_mcast	mcast;
   1062       1.1    ichiro 	struct ether_multi *enm;
   1063       1.1    ichiro 	struct ether_multistep estep;
   1064       1.1    ichiro 	struct ethercom *ec = &sc->sc_ethercom;
   1065       1.1    ichiro 
   1066       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1067       1.1    ichiro 
   1068       1.1    ichiro 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1069       1.1    ichiro allmulti:
   1070       1.1    ichiro 		ifp->if_flags |= IFF_ALLMULTI;
   1071      1.21   thorpej 		memset((char *)&mcast, 0, sizeof(mcast));
   1072  1.27.2.1   thorpej 		mcast.wi_type = WI_RID_MCAST_LIST;
   1073       1.1    ichiro 		mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
   1074       1.1    ichiro 
   1075       1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1076       1.1    ichiro 		return;
   1077       1.1    ichiro 	}
   1078       1.1    ichiro 
   1079       1.1    ichiro 	i = 0;
   1080       1.1    ichiro 	ETHER_FIRST_MULTI(estep, ec, enm);
   1081       1.1    ichiro 	while (enm != NULL) {
   1082       1.1    ichiro 		/* Punt on ranges or too many multicast addresses. */
   1083      1.19   thorpej 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1084       1.1    ichiro 		    ETHER_ADDR_LEN) != 0 ||
   1085       1.1    ichiro 		    i >= 16)
   1086       1.1    ichiro 			goto allmulti;
   1087       1.1    ichiro 
   1088      1.20   thorpej 		memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
   1089      1.20   thorpej 		    ETHER_ADDR_LEN);
   1090       1.1    ichiro 		i++;
   1091       1.1    ichiro 		ETHER_NEXT_MULTI(estep, enm);
   1092       1.1    ichiro 	}
   1093       1.1    ichiro 
   1094       1.1    ichiro 	ifp->if_flags &= ~IFF_ALLMULTI;
   1095  1.27.2.1   thorpej 	mcast.wi_type = WI_RID_MCAST_LIST;
   1096       1.1    ichiro 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
   1097       1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1098       1.1    ichiro }
   1099       1.1    ichiro 
   1100       1.1    ichiro static int
   1101       1.1    ichiro wi_setdef(sc, wreq)
   1102       1.1    ichiro 	struct wi_softc		*sc;
   1103       1.1    ichiro 	struct wi_req		*wreq;
   1104       1.1    ichiro {
   1105       1.1    ichiro 	struct sockaddr_dl	*sdl;
   1106       1.1    ichiro 	struct ifnet		*ifp;
   1107       1.1    ichiro 	int error = 0;
   1108       1.1    ichiro 
   1109       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1110       1.1    ichiro 
   1111       1.1    ichiro 	switch(wreq->wi_type) {
   1112       1.1    ichiro 	case WI_RID_MAC_NODE:
   1113       1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1114      1.20   thorpej 		memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
   1115       1.1    ichiro 		    ETHER_ADDR_LEN);
   1116      1.20   thorpej 		memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
   1117       1.1    ichiro 		break;
   1118       1.1    ichiro 	case WI_RID_PORTTYPE:
   1119      1.11    tsubai 		error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate);
   1120       1.1    ichiro 		break;
   1121       1.1    ichiro 	case WI_RID_TX_RATE:
   1122      1.11    tsubai 		error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0]));
   1123       1.1    ichiro 		break;
   1124       1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1125      1.11    tsubai 		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
   1126       1.1    ichiro 		break;
   1127       1.1    ichiro 	case WI_RID_RTS_THRESH:
   1128      1.11    tsubai 		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
   1129       1.1    ichiro 		break;
   1130       1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1131      1.11    tsubai 		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
   1132       1.1    ichiro 		break;
   1133       1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1134      1.11    tsubai 		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
   1135       1.1    ichiro 		break;
   1136       1.1    ichiro 	case WI_RID_OWN_CHNL:
   1137      1.11    tsubai 		sc->wi_channel = le16toh(wreq->wi_val[0]);
   1138       1.1    ichiro 		break;
   1139       1.1    ichiro 	case WI_RID_NODENAME:
   1140       1.1    ichiro 		error = wi_set_ssid(&sc->wi_nodeid,
   1141      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1142       1.1    ichiro 		break;
   1143       1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1144       1.1    ichiro 		error = wi_set_ssid(&sc->wi_netid,
   1145      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1146       1.1    ichiro 		break;
   1147       1.1    ichiro 	case WI_RID_OWN_SSID:
   1148       1.1    ichiro 		error = wi_set_ssid(&sc->wi_ibssid,
   1149      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1150       1.1    ichiro 		break;
   1151       1.1    ichiro 	case WI_RID_PM_ENABLED:
   1152      1.11    tsubai 		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
   1153       1.1    ichiro 		break;
   1154       1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1155      1.11    tsubai 		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
   1156       1.1    ichiro 		break;
   1157       1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1158      1.11    tsubai 		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
   1159       1.1    ichiro 		break;
   1160       1.4    ichiro 	case WI_RID_AUTH_CNTL:
   1161      1.11    tsubai 		sc->wi_authtype = le16toh(wreq->wi_val[0]);
   1162       1.4    ichiro 		break;
   1163       1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1164      1.11    tsubai 		sc->wi_roaming = le16toh(wreq->wi_val[0]);
   1165       1.4    ichiro 		break;
   1166       1.1    ichiro 	case WI_RID_ENCRYPTION:
   1167      1.11    tsubai 		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
   1168       1.1    ichiro 		break;
   1169       1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1170      1.11    tsubai 		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
   1171       1.1    ichiro 		break;
   1172       1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1173      1.20   thorpej 		memcpy((char *)&sc->wi_keys, (char *)wreq,
   1174       1.1    ichiro 		    sizeof(struct wi_ltv_keys));
   1175       1.1    ichiro 		break;
   1176       1.1    ichiro 	default:
   1177       1.1    ichiro 		error = EINVAL;
   1178       1.1    ichiro 		break;
   1179       1.1    ichiro 	}
   1180       1.1    ichiro 
   1181       1.1    ichiro 	return (error);
   1182       1.1    ichiro }
   1183       1.1    ichiro 
   1184       1.1    ichiro static int
   1185       1.1    ichiro wi_getdef(sc, wreq)
   1186       1.1    ichiro 	struct wi_softc		*sc;
   1187       1.1    ichiro 	struct wi_req		*wreq;
   1188       1.1    ichiro {
   1189       1.1    ichiro 	struct sockaddr_dl	*sdl;
   1190       1.1    ichiro 	struct ifnet		*ifp;
   1191       1.1    ichiro 	int error = 0;
   1192       1.1    ichiro 
   1193       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1194       1.1    ichiro 
   1195       1.1    ichiro 	wreq->wi_len = 2;			/* XXX */
   1196       1.1    ichiro 	switch (wreq->wi_type) {
   1197       1.1    ichiro 	case WI_RID_MAC_NODE:
   1198       1.1    ichiro 		wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
   1199       1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1200      1.20   thorpej 		memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
   1201      1.20   thorpej 		memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
   1202       1.1    ichiro 		break;
   1203       1.1    ichiro 	case WI_RID_PORTTYPE:
   1204      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ptype);
   1205       1.1    ichiro 		break;
   1206       1.1    ichiro 	case WI_RID_TX_RATE:
   1207      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_rate);
   1208       1.1    ichiro 		break;
   1209       1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1210      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_data_len);
   1211       1.1    ichiro 		break;
   1212       1.1    ichiro 	case WI_RID_RTS_THRESH:
   1213      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
   1214       1.1    ichiro 		break;
   1215       1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1216      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ap_density);
   1217       1.1    ichiro 		break;
   1218       1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1219      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_create_ibss);
   1220       1.1    ichiro 		break;
   1221       1.1    ichiro 	case WI_RID_OWN_CHNL:
   1222      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_channel);
   1223       1.1    ichiro 		break;
   1224       1.1    ichiro 	case WI_RID_NODENAME:
   1225       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_nodeid);
   1226       1.1    ichiro 		break;
   1227       1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1228       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_netid);
   1229       1.1    ichiro 		break;
   1230       1.1    ichiro 	case WI_RID_OWN_SSID:
   1231       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_ibssid);
   1232       1.1    ichiro 		break;
   1233       1.1    ichiro 	case WI_RID_PM_ENABLED:
   1234      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
   1235       1.1    ichiro 		break;
   1236       1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1237      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
   1238       1.1    ichiro 		break;
   1239       1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1240      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_sleep);
   1241       1.1    ichiro 		break;
   1242       1.4    ichiro 	case WI_RID_AUTH_CNTL:
   1243      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_authtype);
   1244       1.4    ichiro 		break;
   1245       1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1246      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_roaming);
   1247       1.4    ichiro 		break;
   1248       1.1    ichiro 	case WI_RID_WEP_AVAIL:
   1249      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_has_wep);
   1250       1.1    ichiro 		break;
   1251       1.1    ichiro 	case WI_RID_ENCRYPTION:
   1252      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_use_wep);
   1253       1.1    ichiro 		break;
   1254       1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1255      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_key);
   1256       1.1    ichiro 		break;
   1257       1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1258       1.1    ichiro 		wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
   1259      1.20   thorpej 		memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
   1260       1.1    ichiro 		break;
   1261       1.1    ichiro 	default:
   1262       1.1    ichiro #if 0
   1263       1.1    ichiro 		error = EIO;
   1264       1.1    ichiro #else
   1265       1.1    ichiro #ifdef WI_DEBUG
   1266       1.1    ichiro 		printf("%s: wi_getdef: unknown request %d\n",
   1267       1.1    ichiro 		    sc->sc_dev.dv_xname, wreq->wi_type);
   1268       1.1    ichiro #endif
   1269       1.1    ichiro #endif
   1270       1.1    ichiro 		break;
   1271       1.1    ichiro 	}
   1272       1.1    ichiro 
   1273       1.1    ichiro 	return (error);
   1274       1.1    ichiro }
   1275       1.1    ichiro 
   1276       1.1    ichiro static int
   1277       1.1    ichiro wi_ioctl(ifp, command, data)
   1278       1.1    ichiro 	struct ifnet		*ifp;
   1279       1.1    ichiro 	u_long			command;
   1280       1.1    ichiro 	caddr_t			data;
   1281       1.1    ichiro {
   1282      1.25  explorer 	int			i, s, error = 0;
   1283       1.1    ichiro 	struct wi_softc		*sc = ifp->if_softc;
   1284       1.1    ichiro 	struct wi_req		wreq;
   1285       1.1    ichiro 	struct ifreq		*ifr;
   1286      1.25  explorer 	struct ifdrv		*ifd;
   1287       1.1    ichiro 	struct proc *p = curproc;
   1288       1.1    ichiro 	struct ieee80211_nwid nwid;
   1289       1.1    ichiro 
   1290       1.1    ichiro 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1291       1.1    ichiro 		return (ENXIO);
   1292       1.1    ichiro 
   1293       1.1    ichiro 	s = splnet();
   1294       1.1    ichiro 
   1295       1.1    ichiro 	ifr = (struct ifreq *)data;
   1296       1.1    ichiro 	switch (command) {
   1297       1.1    ichiro 	case SIOCSIFADDR:
   1298       1.1    ichiro 	case SIOCGIFADDR:
   1299       1.1    ichiro 	case SIOCSIFMTU:
   1300       1.1    ichiro 		error = ether_ioctl(ifp, command, data);
   1301       1.1    ichiro 		break;
   1302       1.1    ichiro 	case SIOCSIFFLAGS:
   1303       1.3    ichiro 		if (ifp->if_flags & IFF_UP) {
   1304       1.3    ichiro 			if (ifp->if_flags & IFF_RUNNING &&
   1305       1.3    ichiro 			    ifp->if_flags & IFF_PROMISC &&
   1306       1.3    ichiro 			    !(sc->wi_if_flags & IFF_PROMISC)) {
   1307       1.3    ichiro 				WI_SETVAL(WI_RID_PROMISC, 1);
   1308       1.3    ichiro 			} else if (ifp->if_flags & IFF_RUNNING &&
   1309       1.3    ichiro 			    !(ifp->if_flags & IFF_PROMISC) &&
   1310       1.3    ichiro 			    sc->wi_if_flags & IFF_PROMISC) {
   1311       1.3    ichiro 				WI_SETVAL(WI_RID_PROMISC, 0);
   1312       1.3    ichiro 			}
   1313       1.3    ichiro 			wi_init(ifp);
   1314       1.3    ichiro 		} else {
   1315       1.3    ichiro 			if (ifp->if_flags & IFF_RUNNING) {
   1316       1.3    ichiro 				wi_stop(ifp, 0);
   1317       1.3    ichiro 			}
   1318       1.3    ichiro 		}
   1319       1.3    ichiro 		sc->wi_if_flags = ifp->if_flags;
   1320       1.3    ichiro 
   1321       1.1    ichiro 		if (!(ifp->if_flags & IFF_UP)) {
   1322       1.3    ichiro 			if (sc->sc_enabled) {
   1323       1.3    ichiro 				if (sc->sc_disable)
   1324       1.3    ichiro 					(*sc->sc_disable)(sc);
   1325       1.3    ichiro 				sc->sc_enabled = 0;
   1326       1.3    ichiro 				ifp->if_flags &= ~IFF_RUNNING;
   1327       1.3    ichiro 			}
   1328       1.3    ichiro 		}
   1329       1.3    ichiro 		error = 0;
   1330       1.1    ichiro 		break;
   1331       1.1    ichiro 	case SIOCADDMULTI:
   1332       1.1    ichiro 	case SIOCDELMULTI:
   1333       1.1    ichiro 		error = (command == SIOCADDMULTI) ?
   1334       1.1    ichiro 			ether_addmulti(ifr, &sc->sc_ethercom) :
   1335       1.1    ichiro 			ether_delmulti(ifr, &sc->sc_ethercom);
   1336       1.1    ichiro 		if (error == ENETRESET) {
   1337       1.1    ichiro 			if (sc->sc_enabled != 0) {
   1338       1.3    ichiro 				/*
   1339       1.3    ichiro 				 * Multicast list has changed.  Set the
   1340       1.3    ichiro 				 * hardware filter accordingly.
   1341       1.3    ichiro 				 */
   1342       1.3    ichiro 				wi_setmulti(sc);
   1343       1.1    ichiro 			}
   1344       1.1    ichiro 			error = 0;
   1345       1.1    ichiro 		}
   1346       1.1    ichiro 		break;
   1347       1.1    ichiro 	case SIOCSIFMEDIA:
   1348       1.1    ichiro 	case SIOCGIFMEDIA:
   1349       1.1    ichiro 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
   1350       1.1    ichiro 		break;
   1351       1.1    ichiro 	case SIOCGWAVELAN:
   1352       1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1353       1.1    ichiro 		if (error)
   1354       1.1    ichiro 			break;
   1355      1.25  explorer 		switch (wreq.wi_type) {
   1356      1.25  explorer 		case WI_RID_IFACE_STATS:
   1357      1.11    tsubai 			/* XXX native byte order */
   1358      1.20   thorpej 			memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
   1359      1.25  explorer 			       sizeof(sc->wi_stats));
   1360       1.1    ichiro 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
   1361      1.25  explorer 			break;
   1362      1.25  explorer 		case WI_RID_DEFLT_CRYPT_KEYS:
   1363       1.1    ichiro 			/* For non-root user, return all-zeroes keys */
   1364       1.1    ichiro 			if (suser(p->p_ucred, &p->p_acflag))
   1365      1.21   thorpej 				memset((char *)&wreq, 0,
   1366      1.25  explorer 				       sizeof(struct wi_ltv_keys));
   1367       1.1    ichiro 			else
   1368      1.20   thorpej 				memcpy((char *)&wreq, (char *)&sc->wi_keys,
   1369      1.25  explorer 				       sizeof(struct wi_ltv_keys));
   1370      1.25  explorer 			break;
   1371      1.25  explorer 		default:
   1372       1.1    ichiro 			if (sc->sc_enabled == 0)
   1373       1.1    ichiro 				error = wi_getdef(sc, &wreq);
   1374      1.25  explorer 			else if (wi_read_record(sc,
   1375      1.25  explorer 						(struct wi_ltv_gen *)&wreq))
   1376       1.1    ichiro 				error = EINVAL;
   1377      1.25  explorer 			break;
   1378       1.1    ichiro 		}
   1379       1.1    ichiro 		if (error == 0)
   1380       1.1    ichiro 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
   1381       1.1    ichiro 		break;
   1382      1.25  explorer 
   1383       1.1    ichiro 	case SIOCSWAVELAN:
   1384       1.1    ichiro 		error = suser(p->p_ucred, &p->p_acflag);
   1385       1.1    ichiro 		if (error)
   1386       1.1    ichiro 			break;
   1387       1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1388       1.1    ichiro 		if (error)
   1389       1.1    ichiro 			break;
   1390      1.25  explorer 		switch (wreq.wi_type) {
   1391      1.25  explorer 		case WI_RID_IFACE_STATS:
   1392       1.1    ichiro 			error = EINVAL;
   1393       1.1    ichiro 			break;
   1394      1.25  explorer 		case WI_RID_MGMT_XMIT:
   1395       1.1    ichiro 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
   1396      1.25  explorer 					     wreq.wi_len);
   1397      1.25  explorer 			break;
   1398      1.25  explorer 
   1399      1.25  explorer 		default:
   1400       1.1    ichiro 			if (sc->sc_enabled != 0)
   1401       1.1    ichiro 				error = wi_write_record(sc,
   1402       1.1    ichiro 				    (struct wi_ltv_gen *)&wreq);
   1403       1.1    ichiro 			if (error == 0)
   1404       1.1    ichiro 				error = wi_setdef(sc, &wreq);
   1405       1.1    ichiro 			if (error == 0 && sc->sc_enabled != 0)
   1406       1.1    ichiro 				/* Reinitialize WaveLAN. */
   1407       1.1    ichiro 				wi_init(ifp);
   1408      1.25  explorer 			break;
   1409      1.25  explorer 		}
   1410      1.25  explorer 		break;
   1411      1.25  explorer 
   1412      1.25  explorer 	case SIOCSDRVSPEC:
   1413      1.25  explorer 		error = suser(p->p_ucred, &p->p_acflag);
   1414      1.25  explorer 		if (error)
   1415      1.25  explorer 			break;
   1416      1.25  explorer 		ifd = (struct ifdrv *)data;
   1417      1.25  explorer 		switch (ifd->ifd_cmd) {
   1418      1.25  explorer 		case WI_IOCTL_SET_SCAN:
   1419      1.25  explorer 			error = copyin(ifd->ifd_data, &i, sizeof (i));
   1420      1.25  explorer 			if (error)
   1421      1.25  explorer 				break;
   1422      1.25  explorer 
   1423      1.25  explorer 			sc->wi_results.scanning = i;
   1424      1.25  explorer 			if (sc->wi_results.scanning > 0)
   1425      1.25  explorer 				callout_reset(&sc->wi_scan_ch,
   1426      1.25  explorer 					      sc->wi_results.scanning,
   1427      1.25  explorer 					      wi_inquire_scan, sc);
   1428      1.25  explorer 			else
   1429      1.25  explorer 				callout_stop(&sc->wi_scan_ch);
   1430      1.25  explorer 			break;
   1431      1.25  explorer 
   1432      1.25  explorer 		/*
   1433      1.25  explorer 		 * Experimental XXXMLG
   1434      1.25  explorer 		 */
   1435      1.25  explorer 		case WI_IOCTL_SET_TESTMODE:
   1436      1.25  explorer 			error = copyin(ifd->ifd_data, &i, sizeof (i));
   1437      1.25  explorer 			if (error)
   1438      1.25  explorer 				break;
   1439      1.25  explorer 			if (i) {
   1440      1.25  explorer 				wi_cmd(sc, WI_CMD_TEST | WI_TEST_MONITOR << 8,
   1441      1.25  explorer 				       0);
   1442      1.25  explorer 				printf("wi test mode enabled\n");
   1443      1.25  explorer 			} else {
   1444      1.25  explorer 				wi_cmd(sc, WI_CMD_TEST | WI_TEST_STOP << 8, 0);
   1445      1.25  explorer 				printf("wi test mode disabled\n");
   1446      1.25  explorer 			}
   1447      1.25  explorer 			break;
   1448      1.25  explorer 
   1449      1.25  explorer 		default:
   1450      1.25  explorer 			error = EINVAL;
   1451      1.25  explorer 			break;
   1452      1.25  explorer 		}
   1453      1.25  explorer 		break;
   1454      1.25  explorer 
   1455      1.25  explorer 	case SIOCGDRVSPEC:
   1456      1.25  explorer 		ifd = (struct ifdrv *)data;
   1457      1.25  explorer 		switch (ifd->ifd_cmd) {
   1458      1.25  explorer 		case WI_IOCTL_GET_SCAN_RESULTS:
   1459      1.25  explorer 			error = copyout(&sc->wi_results, ifd->ifd_data,
   1460      1.25  explorer 					sizeof(struct wi_scan_results));
   1461      1.25  explorer 			break;
   1462      1.25  explorer 
   1463      1.25  explorer 		default:
   1464      1.25  explorer 			error = EINVAL;
   1465      1.25  explorer 			break;
   1466       1.1    ichiro 		}
   1467       1.1    ichiro 		break;
   1468      1.25  explorer 
   1469       1.1    ichiro 	case SIOCG80211NWID:
   1470       1.1    ichiro 		if (sc->sc_enabled == 0) {
   1471       1.1    ichiro 			/* Return the desired ID */
   1472       1.1    ichiro 			error = copyout(&sc->wi_netid, ifr->ifr_data,
   1473       1.1    ichiro 			    sizeof(sc->wi_netid));
   1474       1.1    ichiro 		} else {
   1475       1.1    ichiro 			wreq.wi_type = WI_RID_CURRENT_SSID;
   1476       1.1    ichiro 			wreq.wi_len = WI_MAX_DATALEN;
   1477       1.1    ichiro 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
   1478      1.11    tsubai 			    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
   1479       1.1    ichiro 				error = EINVAL;
   1480       1.1    ichiro 			else {
   1481       1.1    ichiro 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
   1482      1.11    tsubai 				    le16toh(wreq.wi_val[0]));
   1483       1.1    ichiro 				error = copyout(&nwid, ifr->ifr_data,
   1484       1.1    ichiro 				    sizeof(nwid));
   1485       1.1    ichiro 			}
   1486       1.1    ichiro 		}
   1487       1.1    ichiro 		break;
   1488       1.1    ichiro 	case SIOCS80211NWID:
   1489       1.1    ichiro 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
   1490       1.1    ichiro 		if (error != 0)
   1491       1.1    ichiro 			break;
   1492       1.1    ichiro 		if (nwid.i_len > IEEE80211_NWID_LEN) {
   1493       1.1    ichiro 			error = EINVAL;
   1494       1.1    ichiro 			break;
   1495       1.1    ichiro 		}
   1496       1.1    ichiro 		if (sc->wi_netid.i_len == nwid.i_len &&
   1497       1.1    ichiro 		    memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
   1498       1.1    ichiro 			break;
   1499       1.1    ichiro 		wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
   1500       1.1    ichiro 		if (sc->sc_enabled != 0)
   1501       1.1    ichiro 			/* Reinitialize WaveLAN. */
   1502       1.1    ichiro 			wi_init(ifp);
   1503       1.1    ichiro 		break;
   1504       1.1    ichiro 	case SIOCS80211NWKEY:
   1505       1.1    ichiro 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
   1506       1.1    ichiro 		break;
   1507       1.1    ichiro 	case SIOCG80211NWKEY:
   1508       1.1    ichiro 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
   1509       1.1    ichiro 		break;
   1510       1.1    ichiro 	case SIOCS80211POWER:
   1511       1.1    ichiro 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
   1512       1.1    ichiro 		break;
   1513       1.1    ichiro 	case SIOCG80211POWER:
   1514       1.1    ichiro 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
   1515       1.1    ichiro 		break;
   1516       1.1    ichiro 
   1517       1.1    ichiro 	default:
   1518       1.1    ichiro 		error = EINVAL;
   1519       1.1    ichiro 		break;
   1520       1.1    ichiro 	}
   1521       1.1    ichiro 
   1522       1.1    ichiro 	splx(s);
   1523       1.1    ichiro 	return (error);
   1524       1.1    ichiro }
   1525       1.1    ichiro 
   1526       1.1    ichiro static int
   1527       1.1    ichiro wi_init(ifp)
   1528       1.1    ichiro 	struct ifnet *ifp;
   1529       1.1    ichiro {
   1530       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   1531       1.1    ichiro 	struct wi_req wreq;
   1532       1.1    ichiro 	struct wi_ltv_macaddr mac;
   1533       1.1    ichiro 	int error, id = 0;
   1534       1.1    ichiro 
   1535       1.1    ichiro 	if (!sc->sc_enabled) {
   1536      1.11    tsubai 		if ((error = (*sc->sc_enable)(sc)) != 0)
   1537       1.1    ichiro 			goto out;
   1538       1.1    ichiro 		sc->sc_enabled = 1;
   1539       1.1    ichiro 	}
   1540       1.1    ichiro 
   1541       1.1    ichiro 	wi_stop(ifp, 0);
   1542       1.1    ichiro 	wi_reset(sc);
   1543       1.1    ichiro 
   1544       1.1    ichiro 	/* Program max data length. */
   1545       1.1    ichiro 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
   1546       1.1    ichiro 
   1547       1.1    ichiro 	/* Enable/disable IBSS creation. */
   1548       1.1    ichiro 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
   1549       1.1    ichiro 
   1550       1.1    ichiro 	/* Set the port type. */
   1551       1.1    ichiro 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
   1552       1.1    ichiro 
   1553       1.1    ichiro 	/* Program the RTS/CTS threshold. */
   1554       1.1    ichiro 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
   1555       1.1    ichiro 
   1556       1.1    ichiro 	/* Program the TX rate */
   1557       1.1    ichiro 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
   1558       1.1    ichiro 
   1559       1.1    ichiro 	/* Access point density */
   1560       1.1    ichiro 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
   1561       1.1    ichiro 
   1562       1.1    ichiro 	/* Power Management Enabled */
   1563       1.1    ichiro 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
   1564       1.1    ichiro 
   1565       1.1    ichiro 	/* Power Managment Max Sleep */
   1566       1.1    ichiro 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
   1567       1.1    ichiro 
   1568       1.4    ichiro 	/* Roaming type */
   1569       1.4    ichiro 	WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
   1570       1.4    ichiro 
   1571       1.1    ichiro 	/* Specify the IBSS name */
   1572       1.1    ichiro 	wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
   1573       1.1    ichiro 
   1574       1.1    ichiro 	/* Specify the network name */
   1575       1.1    ichiro 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
   1576       1.1    ichiro 
   1577       1.1    ichiro 	/* Specify the frequency to use */
   1578       1.1    ichiro 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
   1579       1.1    ichiro 
   1580       1.1    ichiro 	/* Program the nodename. */
   1581       1.1    ichiro 	wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
   1582       1.1    ichiro 
   1583       1.1    ichiro 	/* Set our MAC address. */
   1584       1.1    ichiro 	mac.wi_len = 4;
   1585       1.1    ichiro 	mac.wi_type = WI_RID_MAC_NODE;
   1586       1.1    ichiro 	memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
   1587       1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
   1588       1.1    ichiro 
   1589       1.4    ichiro 	/* Initialize promisc mode. */
   1590       1.4    ichiro 	if (ifp->if_flags & IFF_PROMISC) {
   1591       1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 1);
   1592       1.4    ichiro 	} else {
   1593       1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 0);
   1594       1.4    ichiro 	}
   1595       1.4    ichiro 
   1596       1.1    ichiro 	/* Configure WEP. */
   1597       1.1    ichiro 	if (sc->wi_has_wep) {
   1598       1.1    ichiro 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
   1599       1.1    ichiro 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
   1600       1.1    ichiro 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
   1601       1.1    ichiro 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   1602       1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
   1603       1.4    ichiro 		if (sc->sc_prism2 && sc->wi_use_wep) {
   1604       1.4    ichiro 			/*
   1605      1.14    ichiro 			 * ONLY HWB3163 EVAL-CARD Firmware version
   1606      1.14    ichiro 			 * less than 0.8 variant3
   1607      1.14    ichiro 			 *
   1608       1.5    ichiro 			 *   If promiscuous mode disable, Prism2 chip
   1609       1.5    ichiro 			 *  does not work with WEP .
   1610       1.4    ichiro 			 * It is under investigation for details.
   1611       1.4    ichiro 			 * (ichiro (at) netbsd.org)
   1612       1.4    ichiro 			 */
   1613       1.9    ichiro 			if (sc->sc_prism2_ver < 83 ) {
   1614       1.9    ichiro 				/* firm ver < 0.8 variant 3 */
   1615       1.6    ichiro 				WI_SETVAL(WI_RID_PROMISC, 1);
   1616       1.6    ichiro 			}
   1617       1.4    ichiro 			WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
   1618       1.4    ichiro 		}
   1619       1.1    ichiro 	}
   1620       1.1    ichiro 
   1621       1.1    ichiro 	/* Set multicast filter. */
   1622       1.1    ichiro 	wi_setmulti(sc);
   1623       1.1    ichiro 
   1624       1.1    ichiro 	/* Enable desired port */
   1625       1.1    ichiro 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
   1626       1.1    ichiro 
   1627       1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   1628       1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   1629       1.1    ichiro 		printf("%s: tx buffer allocation failed\n",
   1630       1.1    ichiro 		    sc->sc_dev.dv_xname);
   1631       1.1    ichiro 		goto out;
   1632       1.1    ichiro 	}
   1633       1.1    ichiro 	sc->wi_tx_data_id = id;
   1634       1.1    ichiro 
   1635       1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   1636       1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   1637       1.1    ichiro 		printf("%s: mgmt. buffer allocation failed\n",
   1638       1.1    ichiro 		    sc->sc_dev.dv_xname);
   1639       1.1    ichiro 		goto out;
   1640       1.1    ichiro 	}
   1641       1.1    ichiro 	sc->wi_tx_mgmt_id = id;
   1642       1.1    ichiro 
   1643       1.1    ichiro 	/* Enable interrupts */
   1644       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
   1645       1.1    ichiro 
   1646       1.1    ichiro 	ifp->if_flags |= IFF_RUNNING;
   1647       1.1    ichiro 	ifp->if_flags &= ~IFF_OACTIVE;
   1648       1.1    ichiro 
   1649      1.25  explorer 	callout_reset(&sc->wi_stats_ch, STATS_FREQUENCY, wi_inquire_stats, sc);
   1650       1.1    ichiro 
   1651       1.1    ichiro  out:
   1652       1.1    ichiro 	if (error) {
   1653       1.1    ichiro 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1654       1.1    ichiro 		ifp->if_timer = 0;
   1655       1.1    ichiro 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   1656       1.1    ichiro 	}
   1657       1.1    ichiro 	return (error);
   1658       1.1    ichiro }
   1659       1.1    ichiro 
   1660      1.11    tsubai static void
   1661       1.1    ichiro wi_start(ifp)
   1662       1.1    ichiro 	struct ifnet		*ifp;
   1663       1.1    ichiro {
   1664       1.1    ichiro 	struct wi_softc		*sc;
   1665       1.1    ichiro 	struct mbuf		*m0;
   1666       1.1    ichiro 	struct wi_frame		tx_frame;
   1667       1.1    ichiro 	struct ether_header	*eh;
   1668       1.1    ichiro 	int			id;
   1669       1.1    ichiro 
   1670       1.1    ichiro 	sc = ifp->if_softc;
   1671       1.1    ichiro 
   1672       1.1    ichiro 	if (ifp->if_flags & IFF_OACTIVE)
   1673       1.1    ichiro 		return;
   1674       1.1    ichiro 
   1675       1.1    ichiro 	IFQ_DEQUEUE(&ifp->if_snd, m0);
   1676       1.1    ichiro 	if (m0 == NULL)
   1677       1.1    ichiro 		return;
   1678       1.1    ichiro 
   1679      1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   1680       1.1    ichiro 	id = sc->wi_tx_data_id;
   1681       1.1    ichiro 	eh = mtod(m0, struct ether_header *);
   1682       1.1    ichiro 
   1683       1.1    ichiro 	/*
   1684       1.1    ichiro 	 * Use RFC1042 encoding for IP and ARP datagrams,
   1685       1.1    ichiro 	 * 802.3 for anything else.
   1686       1.1    ichiro 	 */
   1687       1.1    ichiro 	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
   1688       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
   1689       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
   1690       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
   1691      1.20   thorpej 		memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
   1692      1.20   thorpej 		    ETHER_ADDR_LEN);
   1693      1.20   thorpej 		memcpy((char *)&tx_frame.wi_addr2, (char *)&eh->ether_shost,
   1694      1.20   thorpej 		    ETHER_ADDR_LEN);
   1695      1.20   thorpej 		memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
   1696      1.20   thorpej 		    ETHER_ADDR_LEN);
   1697      1.20   thorpej 		memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
   1698      1.20   thorpej 		    ETHER_ADDR_LEN);
   1699       1.1    ichiro 
   1700      1.11    tsubai 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   1701      1.11    tsubai 		tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
   1702       1.1    ichiro 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
   1703       1.1    ichiro 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
   1704       1.1    ichiro 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   1705       1.1    ichiro 		tx_frame.wi_type = eh->ether_type;
   1706       1.1    ichiro 
   1707       1.1    ichiro 		m_copydata(m0, sizeof(struct ether_header),
   1708       1.1    ichiro 		    m0->m_pkthdr.len - sizeof(struct ether_header),
   1709       1.1    ichiro 		    (caddr_t)&sc->wi_txbuf);
   1710       1.1    ichiro 
   1711       1.1    ichiro 		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   1712       1.1    ichiro 		    sizeof(struct wi_frame));
   1713       1.1    ichiro 		wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
   1714       1.1    ichiro 		    (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
   1715       1.1    ichiro 	} else {
   1716      1.11    tsubai 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
   1717       1.1    ichiro 
   1718       1.1    ichiro 		m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
   1719       1.1    ichiro 
   1720       1.1    ichiro 		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   1721       1.1    ichiro 		    sizeof(struct wi_frame));
   1722       1.1    ichiro 		wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
   1723       1.1    ichiro 		    m0->m_pkthdr.len + 2);
   1724       1.1    ichiro 	}
   1725       1.1    ichiro 
   1726       1.1    ichiro #if NBPFILTER > 0
   1727       1.1    ichiro 	/*
   1728       1.1    ichiro 	 * If there's a BPF listener, bounce a copy of
   1729       1.1    ichiro 	 * this frame to him.
   1730       1.1    ichiro 	 */
   1731       1.1    ichiro 	if (ifp->if_bpf)
   1732       1.1    ichiro 		bpf_mtap(ifp->if_bpf, m0);
   1733       1.1    ichiro #endif
   1734       1.1    ichiro 
   1735       1.1    ichiro 	m_freem(m0);
   1736       1.1    ichiro 
   1737       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
   1738       1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   1739       1.1    ichiro 
   1740       1.1    ichiro 	ifp->if_flags |= IFF_OACTIVE;
   1741       1.1    ichiro 
   1742       1.1    ichiro 	/*
   1743       1.1    ichiro 	 * Set a timeout in case the chip goes out to lunch.
   1744       1.1    ichiro 	 */
   1745       1.1    ichiro 	ifp->if_timer = 5;
   1746       1.1    ichiro 
   1747       1.1    ichiro 	return;
   1748       1.1    ichiro }
   1749       1.1    ichiro 
   1750      1.11    tsubai static int
   1751       1.1    ichiro wi_mgmt_xmit(sc, data, len)
   1752       1.1    ichiro 	struct wi_softc		*sc;
   1753       1.1    ichiro 	caddr_t			data;
   1754       1.1    ichiro 	int			len;
   1755       1.1    ichiro {
   1756       1.1    ichiro 	struct wi_frame		tx_frame;
   1757       1.1    ichiro 	int			id;
   1758       1.1    ichiro 	struct wi_80211_hdr	*hdr;
   1759       1.1    ichiro 	caddr_t			dptr;
   1760       1.1    ichiro 
   1761       1.1    ichiro 	hdr = (struct wi_80211_hdr *)data;
   1762       1.1    ichiro 	dptr = data + sizeof(struct wi_80211_hdr);
   1763       1.1    ichiro 
   1764      1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   1765       1.1    ichiro 	id = sc->wi_tx_mgmt_id;
   1766       1.1    ichiro 
   1767      1.20   thorpej 	memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
   1768       1.1    ichiro 	   sizeof(struct wi_80211_hdr));
   1769       1.1    ichiro 
   1770      1.11    tsubai 	tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
   1771       1.1    ichiro 	tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
   1772       1.1    ichiro 
   1773       1.1    ichiro 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
   1774       1.1    ichiro 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
   1775       1.1    ichiro 	    (len - sizeof(struct wi_80211_hdr)) + 2);
   1776       1.1    ichiro 
   1777       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
   1778       1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   1779       1.1    ichiro 		return(EIO);
   1780       1.1    ichiro 	}
   1781       1.1    ichiro 
   1782       1.1    ichiro 	return(0);
   1783       1.1    ichiro }
   1784       1.1    ichiro 
   1785       1.1    ichiro static void
   1786       1.1    ichiro wi_stop(ifp, disable)
   1787       1.1    ichiro 	struct ifnet *ifp;
   1788       1.1    ichiro {
   1789       1.1    ichiro 	struct wi_softc	*sc = ifp->if_softc;
   1790       1.1    ichiro 
   1791       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1792       1.1    ichiro 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
   1793       1.1    ichiro 
   1794      1.25  explorer 	callout_stop(&sc->wi_stats_ch);
   1795      1.25  explorer 	callout_stop(&sc->wi_scan_ch);
   1796       1.1    ichiro 
   1797       1.1    ichiro 	if (disable) {
   1798       1.4    ichiro 		if (sc->sc_enabled) {
   1799       1.4    ichiro 			if (sc->sc_disable)
   1800       1.4    ichiro 				(*sc->sc_disable)(sc);
   1801       1.4    ichiro 			sc->sc_enabled = 0;
   1802       1.4    ichiro 		}
   1803       1.1    ichiro 	}
   1804       1.1    ichiro 
   1805       1.1    ichiro 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
   1806       1.1    ichiro 	ifp->if_timer = 0;
   1807       1.1    ichiro }
   1808       1.1    ichiro 
   1809      1.11    tsubai static void
   1810       1.1    ichiro wi_watchdog(ifp)
   1811       1.1    ichiro 	struct ifnet		*ifp;
   1812       1.1    ichiro {
   1813       1.1    ichiro 	struct wi_softc		*sc;
   1814       1.1    ichiro 
   1815       1.1    ichiro 	sc = ifp->if_softc;
   1816       1.1    ichiro 
   1817       1.1    ichiro 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
   1818       1.1    ichiro 
   1819       1.1    ichiro 	wi_init(ifp);
   1820       1.1    ichiro 
   1821       1.1    ichiro 	ifp->if_oerrors++;
   1822       1.1    ichiro 
   1823       1.1    ichiro 	return;
   1824       1.1    ichiro }
   1825       1.1    ichiro 
   1826       1.1    ichiro void
   1827       1.1    ichiro wi_shutdown(sc)
   1828       1.1    ichiro 	struct wi_softc *sc;
   1829       1.1    ichiro {
   1830      1.11    tsubai 	int s;
   1831       1.1    ichiro 
   1832      1.11    tsubai 	s = splnet();
   1833      1.11    tsubai 	if (sc->sc_enabled) {
   1834      1.11    tsubai 		if (sc->sc_disable)
   1835      1.11    tsubai 			(*sc->sc_disable)(sc);
   1836      1.11    tsubai 		sc->sc_enabled = 0;
   1837      1.11    tsubai 	}
   1838       1.1    ichiro 	splx(s);
   1839       1.1    ichiro }
   1840       1.1    ichiro 
   1841       1.1    ichiro int
   1842       1.1    ichiro wi_activate(self, act)
   1843       1.1    ichiro 	struct device *self;
   1844       1.1    ichiro 	enum devact act;
   1845       1.1    ichiro {
   1846       1.1    ichiro 	struct wi_softc *sc = (struct wi_softc *)self;
   1847       1.1    ichiro 	int rv = 0, s;
   1848       1.1    ichiro 
   1849       1.1    ichiro 	s = splnet();
   1850       1.1    ichiro 	switch (act) {
   1851       1.1    ichiro 	case DVACT_ACTIVATE:
   1852       1.1    ichiro 		rv = EOPNOTSUPP;
   1853       1.1    ichiro 		break;
   1854       1.1    ichiro 
   1855       1.1    ichiro 	case DVACT_DEACTIVATE:
   1856       1.1    ichiro 		if_deactivate(&sc->sc_ethercom.ec_if);
   1857       1.1    ichiro 		break;
   1858       1.1    ichiro 	}
   1859       1.1    ichiro 	splx(s);
   1860       1.1    ichiro 	return (rv);
   1861       1.1    ichiro }
   1862       1.1    ichiro 
   1863       1.4    ichiro static void
   1864       1.4    ichiro wi_get_id(sc)
   1865       1.4    ichiro 	struct wi_softc *sc;
   1866       1.4    ichiro {
   1867       1.4    ichiro 	struct wi_ltv_ver       ver;
   1868       1.4    ichiro 
   1869       1.6    ichiro 	/* getting chip identity */
   1870      1.11    tsubai 	memset(&ver, 0, sizeof(ver));
   1871  1.27.2.1   thorpej 	ver.wi_type = WI_RID_CARD_ID;
   1872      1.11    tsubai 	ver.wi_len = 5;
   1873      1.11    tsubai 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   1874       1.9    ichiro 	printf("%s: using ", sc->sc_dev.dv_xname);
   1875      1.11    tsubai 	switch (le16toh(ver.wi_ver[0])) {
   1876      1.24       wiz 	case WI_NIC_EVB2:
   1877      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841");
   1878      1.24       wiz 		sc->sc_prism2 = 1;
   1879      1.24       wiz 		break;
   1880      1.24       wiz 	case WI_NIC_HWB3763:
   1881      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3763 rev.B");
   1882      1.24       wiz 		sc->sc_prism2 = 1;
   1883      1.24       wiz 		break;
   1884      1.24       wiz 	case WI_NIC_HWB3163:
   1885      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A");
   1886      1.24       wiz 		sc->sc_prism2 = 1;
   1887      1.24       wiz 		break;
   1888      1.24       wiz 	case WI_NIC_HWB3163B:
   1889      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.B");
   1890      1.24       wiz 		sc->sc_prism2 = 1;
   1891      1.24       wiz 		break;
   1892      1.24       wiz 	case WI_NIC_EVB3:
   1893      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3842");
   1894      1.24       wiz 		sc->sc_prism2 = 1;
   1895      1.24       wiz 		break;
   1896      1.24       wiz 	case WI_NIC_HWB1153:
   1897      1.24       wiz 		printf("RF:PRISM1 MAC:HFA3841 CARD:HWB1153");
   1898      1.24       wiz 		sc->sc_prism2 = 1;
   1899      1.24       wiz 		break;
   1900      1.24       wiz 	case WI_NIC_P2_SST:
   1901      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash");
   1902      1.24       wiz 		sc->sc_prism2 = 1;
   1903      1.24       wiz 		break;
   1904      1.24       wiz 	case WI_NIC_PRISM2_5:
   1905      1.24       wiz 		printf("RF:PRISM2.5 MAC:ISL3873");
   1906      1.26    ichiro 		sc->sc_prism2 = 1;
   1907      1.26    ichiro 		break;
   1908      1.26    ichiro 	case WI_NIC_3874A:
   1909      1.26    ichiro 		printf("RF:PRISM2.5 MAC:ISL3874A(PCI)");
   1910      1.24       wiz 		sc->sc_prism2 = 1;
   1911      1.24       wiz 		break;
   1912      1.24       wiz 	default:
   1913      1.24       wiz 		printf("Lucent chip or unknown chip\n");
   1914      1.24       wiz 		sc->sc_prism2 = 0;
   1915      1.24       wiz 		break;
   1916       1.4    ichiro 	}
   1917       1.6    ichiro 
   1918       1.6    ichiro 	if (sc->sc_prism2) {
   1919       1.6    ichiro 		/* try to get prism2 firm version */
   1920       1.6    ichiro 		memset(&ver, 0, sizeof(ver));
   1921  1.27.2.1   thorpej 		ver.wi_type = WI_RID_STA_IDENTITY;
   1922       1.6    ichiro 		ver.wi_len = 5;
   1923       1.6    ichiro 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   1924      1.11    tsubai 		LE16TOH(ver.wi_ver[1]);
   1925      1.11    tsubai 		LE16TOH(ver.wi_ver[2]);
   1926      1.11    tsubai 		LE16TOH(ver.wi_ver[3]);
   1927      1.23       wiz 		printf(", Firmware: %i.%i variant %i\n", ver.wi_ver[2],
   1928      1.11    tsubai 		       ver.wi_ver[3], ver.wi_ver[1]);
   1929       1.9    ichiro 		sc->sc_prism2_ver = ver.wi_ver[2] * 100 +
   1930       1.9    ichiro 				    ver.wi_ver[3] *  10 + ver.wi_ver[1];
   1931       1.6    ichiro 	}
   1932       1.6    ichiro 
   1933       1.4    ichiro 	return;
   1934       1.4    ichiro }
   1935       1.4    ichiro 
   1936       1.1    ichiro int
   1937       1.1    ichiro wi_detach(sc)
   1938       1.1    ichiro 	struct wi_softc *sc;
   1939       1.1    ichiro {
   1940       1.1    ichiro 	struct ifnet *ifp = sc->sc_ifp;
   1941       1.1    ichiro 	int s;
   1942       1.1    ichiro 
   1943       1.1    ichiro 	if (!sc->sc_attached)
   1944       1.1    ichiro 		return (0);
   1945       1.1    ichiro 
   1946       1.1    ichiro 	s = splnet();
   1947      1.25  explorer 	callout_stop(&sc->wi_stats_ch);
   1948      1.25  explorer 	callout_stop(&sc->wi_scan_ch);
   1949       1.1    ichiro 
   1950       1.1    ichiro 	/* Delete all remaining media. */
   1951       1.1    ichiro 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
   1952       1.1    ichiro 
   1953       1.1    ichiro 	ether_ifdetach(ifp);
   1954       1.1    ichiro 	if_detach(ifp);
   1955       1.1    ichiro 	if (sc->sc_enabled) {
   1956       1.1    ichiro 		if (sc->sc_disable)
   1957       1.1    ichiro 			(*sc->sc_disable)(sc);
   1958       1.1    ichiro 		sc->sc_enabled = 0;
   1959       1.1    ichiro 	}
   1960       1.1    ichiro 	splx(s);
   1961       1.1    ichiro 	return (0);
   1962       1.1    ichiro }
   1963       1.1    ichiro 
   1964       1.1    ichiro void
   1965       1.1    ichiro wi_power(sc, why)
   1966       1.1    ichiro 	struct wi_softc *sc;
   1967       1.1    ichiro 	int why;
   1968       1.1    ichiro {
   1969       1.1    ichiro 	int s;
   1970       1.1    ichiro 
   1971       1.1    ichiro 	if (!sc->sc_enabled)
   1972       1.1    ichiro 		return;
   1973       1.1    ichiro 
   1974       1.1    ichiro 	s = splnet();
   1975       1.1    ichiro 	switch (why) {
   1976       1.1    ichiro 	case PWR_SUSPEND:
   1977       1.1    ichiro 	case PWR_STANDBY:
   1978       1.1    ichiro 		wi_stop(sc->sc_ifp, 0);
   1979       1.4    ichiro 		if (sc->sc_enabled) {
   1980       1.4    ichiro 			if (sc->sc_disable)
   1981       1.4    ichiro 				(*sc->sc_disable)(sc);
   1982       1.4    ichiro 		}
   1983       1.1    ichiro 		break;
   1984       1.1    ichiro 	case PWR_RESUME:
   1985       1.1    ichiro 		sc->sc_enabled = 0;
   1986       1.1    ichiro 		wi_init(sc->sc_ifp);
   1987       1.1    ichiro 		(void)wi_intr(sc);
   1988       1.1    ichiro 		break;
   1989       1.1    ichiro 	case PWR_SOFTSUSPEND:
   1990       1.1    ichiro 	case PWR_SOFTSTANDBY:
   1991       1.1    ichiro 	case PWR_SOFTRESUME:
   1992       1.1    ichiro 		break;
   1993       1.1    ichiro 	}
   1994       1.1    ichiro 	splx(s);
   1995       1.1    ichiro }
   1996       1.1    ichiro 
   1997       1.1    ichiro static int
   1998       1.1    ichiro wi_set_ssid(ws, id, len)
   1999       1.1    ichiro 	struct ieee80211_nwid *ws;
   2000       1.1    ichiro 	u_int8_t *id;
   2001       1.1    ichiro 	int len;
   2002       1.1    ichiro {
   2003       1.1    ichiro 
   2004       1.1    ichiro 	if (len > IEEE80211_NWID_LEN)
   2005       1.1    ichiro 		return (EINVAL);
   2006       1.1    ichiro 	ws->i_len = len;
   2007       1.1    ichiro 	memcpy(ws->i_nwid, id, len);
   2008       1.1    ichiro 	return (0);
   2009       1.1    ichiro }
   2010       1.1    ichiro 
   2011       1.1    ichiro static void
   2012       1.1    ichiro wi_request_fill_ssid(wreq, ws)
   2013       1.1    ichiro 	struct wi_req *wreq;
   2014       1.1    ichiro 	struct ieee80211_nwid *ws;
   2015       1.1    ichiro {
   2016      1.11    tsubai 	int len = ws->i_len;
   2017       1.1    ichiro 
   2018       1.1    ichiro 	memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
   2019      1.11    tsubai 	wreq->wi_val[0] = htole16(len);
   2020      1.11    tsubai 	wreq->wi_len = roundup(len, 2) / 2 + 2;
   2021      1.11    tsubai 	memcpy(&wreq->wi_val[1], ws->i_nwid, len);
   2022       1.1    ichiro }
   2023       1.1    ichiro 
   2024       1.1    ichiro static int
   2025       1.1    ichiro wi_write_ssid(sc, type, wreq, ws)
   2026       1.1    ichiro 	struct wi_softc *sc;
   2027       1.1    ichiro 	int type;
   2028       1.1    ichiro 	struct wi_req *wreq;
   2029       1.1    ichiro 	struct ieee80211_nwid *ws;
   2030       1.1    ichiro {
   2031       1.1    ichiro 
   2032       1.1    ichiro 	wreq->wi_type = type;
   2033       1.1    ichiro 	wi_request_fill_ssid(wreq, ws);
   2034       1.1    ichiro 	return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
   2035       1.1    ichiro }
   2036       1.1    ichiro 
   2037       1.1    ichiro static int
   2038       1.1    ichiro wi_sync_media(sc, ptype, txrate)
   2039       1.1    ichiro 	struct wi_softc *sc;
   2040       1.1    ichiro 	int ptype;
   2041       1.1    ichiro 	int txrate;
   2042       1.1    ichiro {
   2043       1.1    ichiro 	int media = sc->sc_media.ifm_cur->ifm_media;
   2044       1.1    ichiro 	int options = IFM_OPTIONS(media);
   2045       1.1    ichiro 	int subtype;
   2046       1.1    ichiro 
   2047       1.1    ichiro 	switch (txrate) {
   2048       1.1    ichiro 	case 1:
   2049       1.1    ichiro 		subtype = IFM_IEEE80211_DS1;
   2050       1.1    ichiro 		break;
   2051       1.1    ichiro 	case 2:
   2052       1.1    ichiro 		subtype = IFM_IEEE80211_DS2;
   2053       1.1    ichiro 		break;
   2054       1.1    ichiro 	case 3:
   2055       1.1    ichiro 		subtype = IFM_AUTO;
   2056       1.1    ichiro 		break;
   2057       1.1    ichiro 	case 11:
   2058       1.1    ichiro 		subtype = IFM_IEEE80211_DS11;
   2059       1.1    ichiro 		break;
   2060       1.1    ichiro 	default:
   2061       1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2062       1.1    ichiro 		break;
   2063       1.1    ichiro 	}
   2064       1.1    ichiro 	switch (ptype) {
   2065       1.1    ichiro 	case WI_PORTTYPE_ADHOC:
   2066       1.1    ichiro 		options |= IFM_IEEE80211_ADHOC;
   2067       1.1    ichiro 		break;
   2068       1.1    ichiro 	case WI_PORTTYPE_BSS:
   2069       1.1    ichiro 		options &= ~IFM_IEEE80211_ADHOC;
   2070       1.1    ichiro 		break;
   2071       1.1    ichiro 	default:
   2072       1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2073       1.1    ichiro 		break;
   2074       1.1    ichiro 	}
   2075       1.1    ichiro 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
   2076       1.1    ichiro 	    IFM_INST(media));
   2077       1.1    ichiro 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
   2078       1.1    ichiro 		return (EINVAL);
   2079       1.1    ichiro 	ifmedia_set(&sc->sc_media, media);
   2080       1.1    ichiro 	sc->wi_ptype = ptype;
   2081       1.1    ichiro 	sc->wi_tx_rate = txrate;
   2082       1.1    ichiro 	return (0);
   2083       1.1    ichiro }
   2084       1.1    ichiro 
   2085       1.1    ichiro static int
   2086       1.1    ichiro wi_media_change(ifp)
   2087       1.1    ichiro 	struct ifnet *ifp;
   2088       1.1    ichiro {
   2089       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2090       1.1    ichiro 	int otype = sc->wi_ptype;
   2091       1.1    ichiro 	int orate = sc->wi_tx_rate;
   2092       1.1    ichiro 
   2093       1.1    ichiro 	if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
   2094       1.1    ichiro 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
   2095       1.1    ichiro 	else
   2096       1.1    ichiro 		sc->wi_ptype = WI_PORTTYPE_BSS;
   2097       1.1    ichiro 
   2098       1.1    ichiro 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
   2099       1.1    ichiro 	case IFM_IEEE80211_DS1:
   2100       1.1    ichiro 		sc->wi_tx_rate = 1;
   2101       1.1    ichiro 		break;
   2102       1.1    ichiro 	case IFM_IEEE80211_DS2:
   2103       1.1    ichiro 		sc->wi_tx_rate = 2;
   2104       1.1    ichiro 		break;
   2105       1.1    ichiro 	case IFM_AUTO:
   2106       1.1    ichiro 		sc->wi_tx_rate = 3;
   2107       1.1    ichiro 		break;
   2108       1.1    ichiro 	case IFM_IEEE80211_DS11:
   2109       1.1    ichiro 		sc->wi_tx_rate = 11;
   2110       1.1    ichiro 		break;
   2111       1.1    ichiro 	}
   2112       1.1    ichiro 
   2113       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2114       1.1    ichiro 		if (otype != sc->wi_ptype ||
   2115       1.1    ichiro 		    orate != sc->wi_tx_rate)
   2116       1.1    ichiro 			wi_init(ifp);
   2117       1.1    ichiro 	}
   2118       1.1    ichiro 
   2119       1.1    ichiro 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
   2120       1.1    ichiro 
   2121       1.1    ichiro 	return (0);
   2122       1.1    ichiro }
   2123       1.1    ichiro 
   2124       1.1    ichiro static void
   2125       1.1    ichiro wi_media_status(ifp, imr)
   2126       1.1    ichiro 	struct ifnet *ifp;
   2127       1.1    ichiro 	struct ifmediareq *imr;
   2128       1.1    ichiro {
   2129       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2130       1.1    ichiro 
   2131       1.1    ichiro 	if (sc->sc_enabled == 0) {
   2132       1.1    ichiro 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
   2133       1.1    ichiro 		imr->ifm_status = 0;
   2134       1.1    ichiro 		return;
   2135       1.1    ichiro 	}
   2136       1.1    ichiro 
   2137       1.1    ichiro 	imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
   2138       1.1    ichiro 	imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
   2139       1.1    ichiro }
   2140       1.1    ichiro 
   2141       1.1    ichiro static int
   2142       1.1    ichiro wi_set_nwkey(sc, nwkey)
   2143       1.1    ichiro 	struct wi_softc *sc;
   2144       1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2145       1.1    ichiro {
   2146      1.22  jdolecek 	int i, error;
   2147      1.22  jdolecek 	size_t len;
   2148       1.1    ichiro 	struct wi_req wreq;
   2149       1.1    ichiro 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
   2150       1.1    ichiro 
   2151       1.1    ichiro 	if (!sc->wi_has_wep)
   2152       1.1    ichiro 		return ENODEV;
   2153       1.1    ichiro 	if (nwkey->i_defkid <= 0 ||
   2154       1.1    ichiro 	    nwkey->i_defkid > IEEE80211_WEP_NKID)
   2155       1.1    ichiro 		return EINVAL;
   2156       1.1    ichiro 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
   2157       1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2158       1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2159       1.1    ichiro 			continue;
   2160       1.1    ichiro 		len = nwkey->i_key[i].i_keylen;
   2161       1.1    ichiro 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
   2162       1.1    ichiro 			return EINVAL;
   2163       1.1    ichiro 		error = copyin(nwkey->i_key[i].i_keydat,
   2164       1.1    ichiro 		    wk->wi_keys[i].wi_keydat, len);
   2165       1.1    ichiro 		if (error)
   2166       1.1    ichiro 			return error;
   2167      1.11    tsubai 		wk->wi_keys[i].wi_keylen = htole16(len);
   2168       1.1    ichiro 	}
   2169       1.1    ichiro 
   2170       1.1    ichiro 	wk->wi_len = (sizeof(*wk) / 2) + 1;
   2171       1.1    ichiro 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   2172       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2173       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2174       1.1    ichiro 		if (error)
   2175       1.1    ichiro 			return error;
   2176       1.1    ichiro 	}
   2177       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2178       1.1    ichiro 	if (error)
   2179       1.1    ichiro 		return error;
   2180       1.1    ichiro 
   2181       1.1    ichiro 	wreq.wi_len = 2;
   2182       1.1    ichiro 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
   2183      1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
   2184       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2185       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2186       1.1    ichiro 		if (error)
   2187       1.1    ichiro 			return error;
   2188       1.1    ichiro 	}
   2189       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2190       1.1    ichiro 	if (error)
   2191       1.1    ichiro 		return error;
   2192       1.1    ichiro 
   2193       1.1    ichiro 	wreq.wi_type = WI_RID_ENCRYPTION;
   2194      1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
   2195       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2196       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2197       1.1    ichiro 		if (error)
   2198       1.1    ichiro 			return error;
   2199       1.1    ichiro 	}
   2200       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2201       1.1    ichiro 	if (error)
   2202       1.1    ichiro 		return error;
   2203       1.1    ichiro 
   2204       1.1    ichiro 	if (sc->sc_enabled != 0)
   2205       1.1    ichiro 		wi_init(&sc->sc_ethercom.ec_if);
   2206       1.1    ichiro 	return 0;
   2207       1.1    ichiro }
   2208       1.1    ichiro 
   2209       1.1    ichiro static int
   2210       1.1    ichiro wi_get_nwkey(sc, nwkey)
   2211       1.1    ichiro 	struct wi_softc *sc;
   2212       1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2213       1.1    ichiro {
   2214       1.1    ichiro 	int i, len, error;
   2215       1.1    ichiro 	struct wi_ltv_keys *wk = &sc->wi_keys;
   2216       1.1    ichiro 
   2217       1.1    ichiro 	if (!sc->wi_has_wep)
   2218       1.1    ichiro 		return ENODEV;
   2219       1.1    ichiro 	nwkey->i_wepon = sc->wi_use_wep;
   2220       1.1    ichiro 	nwkey->i_defkid = sc->wi_tx_key + 1;
   2221       1.1    ichiro 
   2222       1.1    ichiro 	/* do not show any keys to non-root user */
   2223       1.1    ichiro 	error = suser(curproc->p_ucred, &curproc->p_acflag);
   2224       1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2225       1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2226       1.1    ichiro 			continue;
   2227       1.1    ichiro 		/* error holds results of suser() for the first time */
   2228       1.1    ichiro 		if (error)
   2229       1.1    ichiro 			return error;
   2230      1.11    tsubai 		len = le16toh(wk->wi_keys[i].wi_keylen);
   2231       1.1    ichiro 		if (nwkey->i_key[i].i_keylen < len)
   2232       1.1    ichiro 			return ENOSPC;
   2233       1.1    ichiro 		nwkey->i_key[i].i_keylen = len;
   2234       1.1    ichiro 		error = copyout(wk->wi_keys[i].wi_keydat,
   2235       1.1    ichiro 		    nwkey->i_key[i].i_keydat, len);
   2236       1.1    ichiro 		if (error)
   2237       1.1    ichiro 			return error;
   2238       1.1    ichiro 	}
   2239       1.1    ichiro 	return 0;
   2240       1.1    ichiro }
   2241       1.1    ichiro 
   2242       1.1    ichiro static int
   2243       1.1    ichiro wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2244       1.1    ichiro {
   2245       1.1    ichiro 
   2246       1.1    ichiro 	sc->wi_pm_enabled = power->i_enabled;
   2247       1.1    ichiro 	sc->wi_max_sleep = power->i_maxsleep;
   2248       1.1    ichiro 
   2249       1.1    ichiro 	if (sc->sc_enabled)
   2250       1.1    ichiro 		return (wi_init(&sc->sc_ethercom.ec_if));
   2251       1.1    ichiro 
   2252       1.1    ichiro 	return (0);
   2253       1.1    ichiro }
   2254       1.1    ichiro 
   2255       1.1    ichiro static int
   2256       1.1    ichiro wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2257       1.1    ichiro {
   2258       1.1    ichiro 
   2259       1.1    ichiro 	power->i_enabled = sc->wi_pm_enabled;
   2260       1.1    ichiro 	power->i_maxsleep = sc->wi_max_sleep;
   2261       1.1    ichiro 
   2262       1.1    ichiro 	return (0);
   2263       1.1    ichiro }
   2264