Home | History | Annotate | Line # | Download | only in ic
wi.c revision 1.24.2.1
      1  1.24.2.1      fvdl /*	$NetBSD: wi.c,v 1.24.2.1 2001/10/01 12:45:44 fvdl 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.24.2.1      fvdl #define STATS_FREQUENCY   (60 * hz) /* collect stats every 60 seconds */
    105  1.24.2.1      fvdl 
    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.24.2.1      fvdl static void wi_inquire_stats	__P((void *));
    127  1.24.2.1      fvdl 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.24.2.1      fvdl 	callout_init(&sc->wi_stats_ch);
    163  1.24.2.1      fvdl 	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.24.2.1      fvdl 	memset(&sc->wi_results, 0, sizeof (sc->wi_results));
    229  1.24.2.1      fvdl 
    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.24.2.1      fvdl 	u_int16_t		msg_type;
    294  1.24.2.1      fvdl 	u_int16_t		status;
    295  1.24.2.1      fvdl 	u_int16_t		frame_ctl;
    296  1.24.2.1      fvdl 	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.24.2.1      fvdl 	status = le16toh(rx_frame.wi_status);
    309  1.24.2.1      fvdl 	frame_ctl = le16toh(rx_frame.wi_frame_ctl);
    310  1.24.2.1      fvdl 	port = (status >> 8) & 0x07;
    311  1.24.2.1      fvdl 	msg_type = status & WI_RXSTAT_MSG_TYPE;
    312  1.24.2.1      fvdl 
    313  1.24.2.1      fvdl 	/*
    314  1.24.2.1      fvdl 	 * Drop packets with CRC errors here.  We may want the others,
    315  1.24.2.1      fvdl 	 * since we may be doing interesting things with undecryptable
    316  1.24.2.1      fvdl 	 * packets, like analyzing them in userland.
    317  1.24.2.1      fvdl 	 */
    318  1.24.2.1      fvdl 	if (status & WI_STAT_BADCRC) {
    319  1.24.2.1      fvdl 		ifp->if_ierrors++;
    320  1.24.2.1      fvdl 		return;
    321  1.24.2.1      fvdl 	}
    322  1.24.2.1      fvdl 
    323  1.24.2.1      fvdl 	if (port == 7) {
    324  1.24.2.1      fvdl 		if ((le16toh(rx_frame.wi_dat_len) + 60) > MCLBYTES)
    325  1.24.2.1      fvdl 			return;
    326  1.24.2.1      fvdl 
    327  1.24.2.1      fvdl 		MGETHDR(m, M_DONTWAIT, MT_DATA);
    328  1.24.2.1      fvdl 		if (m == NULL) {
    329  1.24.2.1      fvdl 			ifp->if_ierrors++;
    330  1.24.2.1      fvdl 			return;
    331  1.24.2.1      fvdl 		}
    332  1.24.2.1      fvdl 		MCLGET(m, M_DONTWAIT);
    333  1.24.2.1      fvdl 		if (!(m->m_flags & M_EXT)) {
    334  1.24.2.1      fvdl 			m_freem(m);
    335  1.24.2.1      fvdl 			ifp->if_ierrors++;
    336  1.24.2.1      fvdl 			return;
    337  1.24.2.1      fvdl 		}
    338  1.24.2.1      fvdl 
    339  1.24.2.1      fvdl 		memcpy(mtod(m, caddr_t), &rx_frame, 60);
    340  1.24.2.1      fvdl 		m->m_pkthdr.rcvif = ifp;
    341  1.24.2.1      fvdl 
    342  1.24.2.1      fvdl 		m->m_pkthdr.len = m->m_len =
    343  1.24.2.1      fvdl 			le16toh(rx_frame.wi_dat_len) + 60;
    344  1.24.2.1      fvdl 
    345  1.24.2.1      fvdl 		if (wi_read_data(sc, id, 60, mtod(m, caddr_t) + 60,
    346  1.24.2.1      fvdl 				 m->m_len - 60)) {
    347  1.24.2.1      fvdl 			m_freem(m);
    348  1.24.2.1      fvdl 			ifp->if_ierrors++;
    349  1.24.2.1      fvdl 			return;
    350  1.24.2.1      fvdl 		}
    351  1.24.2.1      fvdl 
    352  1.24.2.1      fvdl #if NBPFILTER > 0
    353  1.24.2.1      fvdl 		if (ifp->if_bpf)
    354  1.24.2.1      fvdl 			bpf_mtap(ifp->if_bpf, m);
    355  1.24.2.1      fvdl #endif
    356  1.24.2.1      fvdl 		m_freem(m);
    357  1.24.2.1      fvdl 		return;
    358  1.24.2.1      fvdl 	}
    359  1.24.2.1      fvdl 
    360  1.24.2.1      fvdl 	/*
    361  1.24.2.1      fvdl 	 * Drop undecryptable or packets with receive errors here
    362  1.24.2.1      fvdl 	 */
    363  1.24.2.1      fvdl 	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.24.2.1      fvdl 	/*
    447  1.24.2.1      fvdl 	 * Discard packets which are not data packets
    448  1.24.2.1      fvdl 	 */
    449  1.24.2.1      fvdl 	if (WLAN_FC_GET_TYPE(frame_ctl) != WLAN_FC_TYPE_DATA) {
    450  1.24.2.1      fvdl 		m_freem(m);
    451  1.24.2.1      fvdl 		return;
    452  1.24.2.1      fvdl 	}
    453  1.24.2.1      fvdl 
    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.24.2.1      fvdl 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.24.2.1      fvdl 	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.24.2.1      fvdl }
    495       1.1    ichiro 
    496  1.24.2.1      fvdl void wi_inquire_scan(xsc)
    497  1.24.2.1      fvdl 	void			*xsc;
    498  1.24.2.1      fvdl {
    499  1.24.2.1      fvdl 	struct wi_softc		*sc;
    500  1.24.2.1      fvdl 	struct ifnet		*ifp;
    501  1.24.2.1      fvdl 
    502  1.24.2.1      fvdl 	sc = xsc;
    503  1.24.2.1      fvdl 	ifp = &sc->sc_ethercom.ec_if;
    504  1.24.2.1      fvdl 
    505  1.24.2.1      fvdl 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
    506  1.24.2.1      fvdl 		return;
    507  1.24.2.1      fvdl 
    508  1.24.2.1      fvdl 	if (sc->wi_results.scanning > 0)
    509  1.24.2.1      fvdl 		callout_reset(&sc->wi_scan_ch, sc->wi_results.scanning,
    510  1.24.2.1      fvdl 			      wi_inquire_scan, sc);
    511  1.24.2.1      fvdl 	else
    512  1.24.2.1      fvdl 		callout_stop(&sc->wi_scan_ch);
    513  1.24.2.1      fvdl 
    514  1.24.2.1      fvdl 	/* Don't do this while we're transmitting */
    515  1.24.2.1      fvdl 	if (ifp->if_flags & IFF_OACTIVE)
    516  1.24.2.1      fvdl 		return;
    517  1.24.2.1      fvdl 
    518  1.24.2.1      fvdl 	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.24.2.1      fvdl 	switch (gen.wi_type) {
    538  1.24.2.1      fvdl 	case WI_INFO_COUNTERS:
    539  1.24.2.1      fvdl 		/* some card versions have a larger stats structure */
    540  1.24.2.1      fvdl 		len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
    541  1.24.2.1      fvdl 			gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
    542  1.24.2.1      fvdl 		ptr = (u_int32_t *)&sc->wi_stats;
    543       1.1    ichiro 
    544  1.24.2.1      fvdl 		for (i = 0; i < len; i++) {
    545  1.24.2.1      fvdl 			t = CSR_READ_2(sc, WI_DATA1);
    546       1.1    ichiro #ifdef WI_HERMES_STATS_WAR
    547  1.24.2.1      fvdl 			if (t > 0xF000)
    548  1.24.2.1      fvdl 				t = ~t & 0xFFFF;
    549       1.1    ichiro #endif
    550  1.24.2.1      fvdl 			ptr[i] += t;
    551  1.24.2.1      fvdl 		}
    552       1.1    ichiro 
    553  1.24.2.1      fvdl 		ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
    554  1.24.2.1      fvdl 			sc->wi_stats.wi_tx_multi_retries +
    555  1.24.2.1      fvdl 			sc->wi_stats.wi_tx_retry_limit;
    556  1.24.2.1      fvdl 		break;
    557       1.1    ichiro 
    558  1.24.2.1      fvdl 	case WI_INFO_SCAN_RESULTS:
    559  1.24.2.1      fvdl 		microtime(&sc->wi_results.lastscan);
    560  1.24.2.1      fvdl 		for (i = 0 ; i < gen.wi_len - 1 ; i++) {
    561  1.24.2.1      fvdl 			t = CSR_READ_2(sc, WI_DATA1);
    562  1.24.2.1      fvdl 			if (i < WI_SCAN_RESULTS_MAXLEN)
    563  1.24.2.1      fvdl 				sc->wi_results.scan_results[i] = t;
    564  1.24.2.1      fvdl 		}
    565  1.24.2.1      fvdl 		if (gen.wi_len - 1 <= WI_SCAN_RESULTS_MAXLEN) {
    566  1.24.2.1      fvdl 			sc->wi_results.len = gen.wi_len - 1;
    567  1.24.2.1      fvdl 			sc->wi_results.truncated = 0;
    568  1.24.2.1      fvdl 		} else {
    569  1.24.2.1      fvdl 			sc->wi_results.len = WI_SCAN_RESULTS_MAXLEN;
    570  1.24.2.1      fvdl 			sc->wi_results.truncated = 1;
    571  1.24.2.1      fvdl 		}
    572  1.24.2.1      fvdl 		break;
    573  1.24.2.1      fvdl 
    574  1.24.2.1      fvdl 	default:
    575  1.24.2.1      fvdl #if 0
    576  1.24.2.1      fvdl 		printf("Got info type: %04x\n", gen.wi_type);
    577  1.24.2.1      fvdl #endif
    578  1.24.2.1      fvdl 		for (i = 0; i < gen.wi_len; i++) {
    579  1.24.2.1      fvdl 			t = CSR_READ_2(sc, WI_DATA1);
    580  1.24.2.1      fvdl #if 0
    581  1.24.2.1      fvdl 			printf("[0x%02x] = 0x%04x\n", i, t);
    582  1.24.2.1      fvdl #endif
    583  1.24.2.1      fvdl 		}
    584  1.24.2.1      fvdl 		break;
    585  1.24.2.1      fvdl 	}
    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.1    ichiro /*
    711       1.1    ichiro  * Read an LTV record from the NIC.
    712       1.1    ichiro  */
    713       1.1    ichiro static int wi_read_record(sc, ltv)
    714       1.1    ichiro 	struct wi_softc		*sc;
    715       1.1    ichiro 	struct wi_ltv_gen	*ltv;
    716       1.1    ichiro {
    717       1.1    ichiro 	u_int16_t		*ptr;
    718      1.15    toshii 	int			len, code;
    719       1.1    ichiro 	struct wi_ltv_gen	*oltv, p2ltv;
    720       1.1    ichiro 
    721       1.1    ichiro 	if (sc->sc_prism2) {
    722       1.1    ichiro 		oltv = ltv;
    723       1.1    ichiro 		switch (ltv->wi_type) {
    724       1.1    ichiro 		case WI_RID_ENCRYPTION:
    725       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
    726       1.1    ichiro 			p2ltv.wi_len = 2;
    727       1.1    ichiro 			ltv = &p2ltv;
    728       1.1    ichiro 			break;
    729       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    730       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
    731       1.1    ichiro 			p2ltv.wi_len = 2;
    732       1.1    ichiro 			ltv = &p2ltv;
    733       1.1    ichiro 			break;
    734       1.1    ichiro 		}
    735       1.1    ichiro 	}
    736       1.1    ichiro 
    737       1.1    ichiro 	/* Tell the NIC to enter record read mode. */
    738       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
    739       1.1    ichiro 		return(EIO);
    740       1.1    ichiro 
    741       1.1    ichiro 	/* Seek to the record. */
    742       1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
    743       1.1    ichiro 		return(EIO);
    744       1.1    ichiro 
    745       1.1    ichiro 	/*
    746       1.1    ichiro 	 * Read the length and record type and make sure they
    747       1.1    ichiro 	 * match what we expect (this verifies that we have enough
    748       1.1    ichiro 	 * room to hold all of the returned data).
    749       1.1    ichiro 	 */
    750       1.1    ichiro 	len = CSR_READ_2(sc, WI_DATA1);
    751       1.1    ichiro 	if (len > ltv->wi_len)
    752       1.1    ichiro 		return(ENOSPC);
    753       1.1    ichiro 	code = CSR_READ_2(sc, WI_DATA1);
    754       1.1    ichiro 	if (code != ltv->wi_type)
    755       1.1    ichiro 		return(EIO);
    756       1.1    ichiro 
    757       1.1    ichiro 	ltv->wi_len = len;
    758       1.1    ichiro 	ltv->wi_type = code;
    759       1.1    ichiro 
    760       1.1    ichiro 	/* Now read the data. */
    761       1.1    ichiro 	ptr = &ltv->wi_val;
    762      1.16    toshii 	if (ltv->wi_len > 1)
    763      1.16    toshii 		CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
    764       1.1    ichiro 
    765       1.1    ichiro 	if (sc->sc_prism2) {
    766      1.11    tsubai 		int v;
    767      1.11    tsubai 
    768       1.1    ichiro 		switch (oltv->wi_type) {
    769       1.1    ichiro 		case WI_RID_TX_RATE:
    770       1.1    ichiro 		case WI_RID_CUR_TX_RATE:
    771      1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
    772      1.11    tsubai 			case 1: v = 1; break;
    773      1.11    tsubai 			case 2: v = 2; break;
    774      1.11    tsubai 			case 3:	v = 6; break;
    775      1.11    tsubai 			case 4: v = 5; break;
    776      1.11    tsubai 			case 7: v = 7; break;
    777      1.11    tsubai 			case 8: v = 11; break;
    778      1.11    tsubai 			case 15: v = 3; break;
    779      1.11    tsubai 			default: v = 0x100 + le16toh(ltv->wi_val); break;
    780       1.1    ichiro 			}
    781      1.11    tsubai 			oltv->wi_val = htole16(v);
    782       1.1    ichiro 			break;
    783       1.1    ichiro 		case WI_RID_ENCRYPTION:
    784       1.1    ichiro 			oltv->wi_len = 2;
    785      1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
    786      1.11    tsubai 				oltv->wi_val = htole16(1);
    787       1.1    ichiro 			else
    788      1.11    tsubai 				oltv->wi_val = htole16(0);
    789       1.1    ichiro 			break;
    790       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    791       1.1    ichiro 			oltv->wi_len = 2;
    792       1.1    ichiro 			oltv->wi_val = ltv->wi_val;
    793       1.1    ichiro 			break;
    794       1.4    ichiro 		case WI_RID_AUTH_CNTL:
    795       1.4    ichiro 			oltv->wi_len = 2;
    796      1.11    tsubai 			if (le16toh(ltv->wi_val) & 0x01)
    797      1.11    tsubai 				oltv->wi_val = htole16(1);
    798      1.11    tsubai 			else if (le16toh(ltv->wi_val) & 0x02)
    799      1.11    tsubai 				oltv->wi_val = htole16(2);
    800       1.4    ichiro 			break;
    801       1.1    ichiro 		}
    802       1.1    ichiro 	}
    803       1.1    ichiro 
    804       1.1    ichiro 	return(0);
    805       1.1    ichiro }
    806       1.1    ichiro 
    807       1.1    ichiro /*
    808       1.1    ichiro  * Same as read, except we inject data instead of reading it.
    809       1.1    ichiro  */
    810       1.1    ichiro static int wi_write_record(sc, ltv)
    811       1.1    ichiro 	struct wi_softc		*sc;
    812       1.1    ichiro 	struct wi_ltv_gen	*ltv;
    813       1.1    ichiro {
    814       1.1    ichiro 	u_int16_t		*ptr;
    815       1.1    ichiro 	int			i;
    816       1.1    ichiro 	struct wi_ltv_gen	p2ltv;
    817       1.1    ichiro 
    818       1.1    ichiro 	if (sc->sc_prism2) {
    819      1.11    tsubai 		int v;
    820      1.11    tsubai 
    821       1.1    ichiro 		switch (ltv->wi_type) {
    822       1.1    ichiro 		case WI_RID_TX_RATE:
    823       1.1    ichiro 			p2ltv.wi_type = WI_RID_TX_RATE;
    824       1.1    ichiro 			p2ltv.wi_len = 2;
    825      1.11    tsubai 			switch (le16toh(ltv->wi_val)) {
    826      1.11    tsubai 			case 1: v = 1; break;
    827      1.11    tsubai 			case 2: v = 2; break;
    828      1.11    tsubai 			case 3:	v = 15; break;
    829      1.11    tsubai 			case 5: v = 4; break;
    830      1.11    tsubai 			case 6: v = 3; break;
    831      1.11    tsubai 			case 7: v = 7; break;
    832      1.11    tsubai 			case 11: v = 8; break;
    833       1.1    ichiro 			default: return EINVAL;
    834       1.1    ichiro 			}
    835      1.11    tsubai 			p2ltv.wi_val = htole16(v);
    836       1.1    ichiro 			ltv = &p2ltv;
    837       1.1    ichiro 			break;
    838       1.1    ichiro 		case WI_RID_ENCRYPTION:
    839       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
    840       1.1    ichiro 			p2ltv.wi_len = 2;
    841      1.11    tsubai 			if (le16toh(ltv->wi_val))
    842      1.11    tsubai 				p2ltv.wi_val = htole16(0x03);
    843       1.1    ichiro 			else
    844      1.11    tsubai 				p2ltv.wi_val = htole16(0x90);
    845       1.1    ichiro 			ltv = &p2ltv;
    846       1.1    ichiro 			break;
    847       1.1    ichiro 		case WI_RID_TX_CRYPT_KEY:
    848       1.1    ichiro 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
    849       1.1    ichiro 			p2ltv.wi_len = 2;
    850       1.1    ichiro 			p2ltv.wi_val = ltv->wi_val;
    851       1.1    ichiro 			ltv = &p2ltv;
    852       1.1    ichiro 			break;
    853       1.1    ichiro 		case WI_RID_DEFLT_CRYPT_KEYS:
    854       1.1    ichiro 		    {
    855       1.1    ichiro 			int error;
    856       1.1    ichiro 			struct wi_ltv_str	ws;
    857       1.1    ichiro 			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
    858       1.1    ichiro 			for (i = 0; i < 4; i++) {
    859       1.1    ichiro 				ws.wi_len = 4;
    860       1.1    ichiro 				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
    861       1.1    ichiro 				memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
    862       1.1    ichiro 				ws.wi_str[5] = '\0';
    863       1.1    ichiro 				error = wi_write_record(sc,
    864       1.1    ichiro 				    (struct wi_ltv_gen *)&ws);
    865       1.1    ichiro 				if (error)
    866       1.1    ichiro 					return error;
    867       1.1    ichiro 			}
    868       1.1    ichiro 			return 0;
    869       1.1    ichiro 		    }
    870       1.4    ichiro 		case WI_RID_AUTH_CNTL:
    871       1.4    ichiro 			p2ltv.wi_type = WI_RID_AUTH_CNTL;
    872       1.4    ichiro 			p2ltv.wi_len = 2;
    873      1.11    tsubai 			if (le16toh(ltv->wi_val) == 1)
    874      1.11    tsubai 				p2ltv.wi_val = htole16(0x01);
    875      1.11    tsubai 			else if (le16toh(ltv->wi_val) == 2)
    876      1.11    tsubai 				p2ltv.wi_val = htole16(0x02);
    877       1.4    ichiro 			ltv = &p2ltv;
    878       1.4    ichiro 			break;
    879       1.1    ichiro 		}
    880       1.1    ichiro 	}
    881       1.1    ichiro 
    882       1.1    ichiro 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
    883       1.1    ichiro 		return(EIO);
    884       1.1    ichiro 
    885       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
    886       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
    887       1.1    ichiro 
    888       1.1    ichiro 	/* Write data */
    889       1.1    ichiro 	ptr = &ltv->wi_val;
    890      1.16    toshii 	if (ltv->wi_len > 1)
    891      1.16    toshii 		CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
    892       1.1    ichiro 
    893       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
    894       1.1    ichiro 		return(EIO);
    895       1.1    ichiro 
    896       1.1    ichiro 	return(0);
    897       1.1    ichiro }
    898       1.1    ichiro 
    899       1.1    ichiro static int wi_seek(sc, id, off, chan)
    900       1.1    ichiro 	struct wi_softc		*sc;
    901       1.1    ichiro 	int			id, off, chan;
    902       1.1    ichiro {
    903       1.1    ichiro 	int			i;
    904       1.1    ichiro 	int			selreg, offreg;
    905       1.1    ichiro 	int 			status;
    906       1.1    ichiro 
    907       1.1    ichiro 	switch (chan) {
    908       1.1    ichiro 	case WI_BAP0:
    909       1.1    ichiro 		selreg = WI_SEL0;
    910       1.1    ichiro 		offreg = WI_OFF0;
    911       1.1    ichiro 		break;
    912       1.1    ichiro 	case WI_BAP1:
    913       1.1    ichiro 		selreg = WI_SEL1;
    914       1.1    ichiro 		offreg = WI_OFF1;
    915       1.1    ichiro 		break;
    916       1.1    ichiro 	default:
    917       1.1    ichiro 		printf("%s: invalid data path: %x\n",
    918       1.1    ichiro 		    sc->sc_dev.dv_xname, chan);
    919       1.1    ichiro 		return(EIO);
    920       1.1    ichiro 	}
    921       1.1    ichiro 
    922       1.1    ichiro 	CSR_WRITE_2(sc, selreg, id);
    923       1.1    ichiro 	CSR_WRITE_2(sc, offreg, off);
    924       1.1    ichiro 
    925       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
    926       1.1    ichiro 	  	status = CSR_READ_2(sc, offreg);
    927       1.1    ichiro 		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
    928       1.1    ichiro 			break;
    929       1.1    ichiro 	}
    930       1.1    ichiro 
    931       1.1    ichiro 	if (i == WI_TIMEOUT) {
    932       1.1    ichiro 		printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
    933       1.1    ichiro 		       sc->sc_dev.dv_xname, id, off, status);
    934       1.1    ichiro 		return(ETIMEDOUT);
    935       1.1    ichiro 	}
    936       1.1    ichiro 	return(0);
    937       1.1    ichiro }
    938       1.1    ichiro 
    939       1.1    ichiro static int wi_read_data(sc, id, off, buf, len)
    940       1.1    ichiro 	struct wi_softc		*sc;
    941       1.1    ichiro 	int			id, off;
    942       1.1    ichiro 	caddr_t			buf;
    943       1.1    ichiro 	int			len;
    944       1.1    ichiro {
    945       1.1    ichiro 	u_int16_t		*ptr;
    946       1.1    ichiro 
    947       1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP1))
    948       1.1    ichiro 		return(EIO);
    949       1.1    ichiro 
    950       1.1    ichiro 	ptr = (u_int16_t *)buf;
    951      1.15    toshii 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
    952       1.1    ichiro 
    953       1.1    ichiro 	return(0);
    954       1.1    ichiro }
    955       1.1    ichiro 
    956       1.1    ichiro /*
    957       1.1    ichiro  * According to the comments in the HCF Light code, there is a bug in
    958       1.1    ichiro  * the Hermes (or possibly in certain Hermes firmware revisions) where
    959       1.1    ichiro  * the chip's internal autoincrement counter gets thrown off during
    960       1.1    ichiro  * data writes: the autoincrement is missed, causing one data word to
    961       1.1    ichiro  * be overwritten and subsequent words to be written to the wrong memory
    962       1.1    ichiro  * locations. The end result is that we could end up transmitting bogus
    963       1.1    ichiro  * frames without realizing it. The workaround for this is to write a
    964       1.1    ichiro  * couple of extra guard words after the end of the transfer, then
    965       1.1    ichiro  * attempt to read then back. If we fail to locate the guard words where
    966       1.1    ichiro  * we expect them, we preform the transfer over again.
    967       1.1    ichiro  */
    968       1.1    ichiro static int wi_write_data(sc, id, off, buf, len)
    969       1.1    ichiro 	struct wi_softc		*sc;
    970       1.1    ichiro 	int			id, off;
    971       1.1    ichiro 	caddr_t			buf;
    972       1.1    ichiro 	int			len;
    973       1.1    ichiro {
    974       1.1    ichiro 	u_int16_t		*ptr;
    975       1.1    ichiro 
    976       1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
    977       1.1    ichiro again:
    978       1.1    ichiro #endif
    979       1.1    ichiro 
    980       1.1    ichiro 	if (wi_seek(sc, id, off, WI_BAP0))
    981       1.1    ichiro 		return(EIO);
    982       1.1    ichiro 
    983       1.1    ichiro 	ptr = (u_int16_t *)buf;
    984      1.15    toshii 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
    985       1.1    ichiro 
    986       1.1    ichiro #ifdef WI_HERMES_AUTOINC_WAR
    987       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
    988       1.1    ichiro 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
    989       1.1    ichiro 
    990       1.1    ichiro 	if (wi_seek(sc, id, off + len, WI_BAP0))
    991       1.1    ichiro 		return(EIO);
    992       1.1    ichiro 
    993       1.1    ichiro 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
    994       1.1    ichiro 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
    995       1.1    ichiro 		goto again;
    996       1.1    ichiro #endif
    997       1.1    ichiro 
    998       1.1    ichiro 	return(0);
    999       1.1    ichiro }
   1000       1.1    ichiro 
   1001       1.1    ichiro /*
   1002       1.1    ichiro  * Allocate a region of memory inside the NIC and zero
   1003       1.1    ichiro  * it out.
   1004       1.1    ichiro  */
   1005       1.1    ichiro static int wi_alloc_nicmem(sc, len, id)
   1006       1.1    ichiro 	struct wi_softc		*sc;
   1007       1.1    ichiro 	int			len;
   1008       1.1    ichiro 	int			*id;
   1009       1.1    ichiro {
   1010       1.1    ichiro 	int			i;
   1011       1.1    ichiro 
   1012       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
   1013       1.1    ichiro 		printf("%s: failed to allocate %d bytes on NIC\n",
   1014       1.1    ichiro 		    sc->sc_dev.dv_xname, len);
   1015       1.1    ichiro 		return(ENOMEM);
   1016       1.1    ichiro 	}
   1017       1.1    ichiro 
   1018       1.1    ichiro 	for (i = 0; i < WI_TIMEOUT; i++) {
   1019       1.1    ichiro 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   1020       1.1    ichiro 			break;
   1021       1.1    ichiro 	}
   1022       1.1    ichiro 
   1023       1.1    ichiro 	if (i == WI_TIMEOUT) {
   1024       1.1    ichiro 		printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
   1025       1.1    ichiro 		return(ETIMEDOUT);
   1026       1.1    ichiro 	}
   1027       1.1    ichiro 
   1028       1.1    ichiro 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1029       1.1    ichiro 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
   1030       1.1    ichiro 
   1031       1.1    ichiro 	if (wi_seek(sc, *id, 0, WI_BAP0)) {
   1032       1.1    ichiro 		printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
   1033       1.1    ichiro 		return(EIO);
   1034       1.1    ichiro 	}
   1035       1.1    ichiro 
   1036       1.1    ichiro 	for (i = 0; i < len / 2; i++)
   1037       1.1    ichiro 		CSR_WRITE_2(sc, WI_DATA0, 0);
   1038       1.1    ichiro 
   1039       1.1    ichiro 	return(0);
   1040       1.1    ichiro }
   1041       1.1    ichiro 
   1042       1.1    ichiro static void wi_setmulti(sc)
   1043       1.1    ichiro 	struct wi_softc		*sc;
   1044       1.1    ichiro {
   1045       1.1    ichiro 	struct ifnet		*ifp;
   1046       1.1    ichiro 	int			i = 0;
   1047       1.1    ichiro 	struct wi_ltv_mcast	mcast;
   1048       1.1    ichiro 	struct ether_multi *enm;
   1049       1.1    ichiro 	struct ether_multistep estep;
   1050       1.1    ichiro 	struct ethercom *ec = &sc->sc_ethercom;
   1051       1.1    ichiro 
   1052       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1053       1.1    ichiro 
   1054       1.1    ichiro 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1055       1.1    ichiro allmulti:
   1056       1.1    ichiro 		ifp->if_flags |= IFF_ALLMULTI;
   1057      1.21   thorpej 		memset((char *)&mcast, 0, sizeof(mcast));
   1058       1.1    ichiro 		mcast.wi_type = WI_RID_MCAST;
   1059       1.1    ichiro 		mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
   1060       1.1    ichiro 
   1061       1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1062       1.1    ichiro 		return;
   1063       1.1    ichiro 	}
   1064       1.1    ichiro 
   1065       1.1    ichiro 	i = 0;
   1066       1.1    ichiro 	ETHER_FIRST_MULTI(estep, ec, enm);
   1067       1.1    ichiro 	while (enm != NULL) {
   1068       1.1    ichiro 		/* Punt on ranges or too many multicast addresses. */
   1069      1.19   thorpej 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1070       1.1    ichiro 		    ETHER_ADDR_LEN) != 0 ||
   1071       1.1    ichiro 		    i >= 16)
   1072       1.1    ichiro 			goto allmulti;
   1073       1.1    ichiro 
   1074      1.20   thorpej 		memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
   1075      1.20   thorpej 		    ETHER_ADDR_LEN);
   1076       1.1    ichiro 		i++;
   1077       1.1    ichiro 		ETHER_NEXT_MULTI(estep, enm);
   1078       1.1    ichiro 	}
   1079       1.1    ichiro 
   1080       1.1    ichiro 	ifp->if_flags &= ~IFF_ALLMULTI;
   1081       1.1    ichiro 	mcast.wi_type = WI_RID_MCAST;
   1082       1.1    ichiro 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
   1083       1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1084       1.1    ichiro }
   1085       1.1    ichiro 
   1086       1.1    ichiro static int
   1087       1.1    ichiro wi_setdef(sc, wreq)
   1088       1.1    ichiro 	struct wi_softc		*sc;
   1089       1.1    ichiro 	struct wi_req		*wreq;
   1090       1.1    ichiro {
   1091       1.1    ichiro 	struct sockaddr_dl	*sdl;
   1092       1.1    ichiro 	struct ifnet		*ifp;
   1093       1.1    ichiro 	int error = 0;
   1094       1.1    ichiro 
   1095       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1096       1.1    ichiro 
   1097       1.1    ichiro 	switch(wreq->wi_type) {
   1098       1.1    ichiro 	case WI_RID_MAC_NODE:
   1099       1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1100      1.20   thorpej 		memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
   1101       1.1    ichiro 		    ETHER_ADDR_LEN);
   1102      1.20   thorpej 		memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
   1103       1.1    ichiro 		break;
   1104       1.1    ichiro 	case WI_RID_PORTTYPE:
   1105      1.11    tsubai 		error = wi_sync_media(sc, le16toh(wreq->wi_val[0]), sc->wi_tx_rate);
   1106       1.1    ichiro 		break;
   1107       1.1    ichiro 	case WI_RID_TX_RATE:
   1108      1.11    tsubai 		error = wi_sync_media(sc, sc->wi_ptype, le16toh(wreq->wi_val[0]));
   1109       1.1    ichiro 		break;
   1110       1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1111      1.11    tsubai 		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
   1112       1.1    ichiro 		break;
   1113       1.1    ichiro 	case WI_RID_RTS_THRESH:
   1114      1.11    tsubai 		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
   1115       1.1    ichiro 		break;
   1116       1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1117      1.11    tsubai 		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
   1118       1.1    ichiro 		break;
   1119       1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1120      1.11    tsubai 		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
   1121       1.1    ichiro 		break;
   1122       1.1    ichiro 	case WI_RID_OWN_CHNL:
   1123      1.11    tsubai 		sc->wi_channel = le16toh(wreq->wi_val[0]);
   1124       1.1    ichiro 		break;
   1125       1.1    ichiro 	case WI_RID_NODENAME:
   1126       1.1    ichiro 		error = wi_set_ssid(&sc->wi_nodeid,
   1127      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1128       1.1    ichiro 		break;
   1129       1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1130       1.1    ichiro 		error = wi_set_ssid(&sc->wi_netid,
   1131      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1132       1.1    ichiro 		break;
   1133       1.1    ichiro 	case WI_RID_OWN_SSID:
   1134       1.1    ichiro 		error = wi_set_ssid(&sc->wi_ibssid,
   1135      1.11    tsubai 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1136       1.1    ichiro 		break;
   1137       1.1    ichiro 	case WI_RID_PM_ENABLED:
   1138      1.11    tsubai 		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
   1139       1.1    ichiro 		break;
   1140       1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1141      1.11    tsubai 		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
   1142       1.1    ichiro 		break;
   1143       1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1144      1.11    tsubai 		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
   1145       1.1    ichiro 		break;
   1146       1.4    ichiro 	case WI_RID_AUTH_CNTL:
   1147      1.11    tsubai 		sc->wi_authtype = le16toh(wreq->wi_val[0]);
   1148       1.4    ichiro 		break;
   1149       1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1150      1.11    tsubai 		sc->wi_roaming = le16toh(wreq->wi_val[0]);
   1151       1.4    ichiro 		break;
   1152       1.1    ichiro 	case WI_RID_ENCRYPTION:
   1153      1.11    tsubai 		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
   1154       1.1    ichiro 		break;
   1155       1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1156      1.11    tsubai 		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
   1157       1.1    ichiro 		break;
   1158       1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1159      1.20   thorpej 		memcpy((char *)&sc->wi_keys, (char *)wreq,
   1160       1.1    ichiro 		    sizeof(struct wi_ltv_keys));
   1161       1.1    ichiro 		break;
   1162       1.1    ichiro 	default:
   1163       1.1    ichiro 		error = EINVAL;
   1164       1.1    ichiro 		break;
   1165       1.1    ichiro 	}
   1166       1.1    ichiro 
   1167       1.1    ichiro 	return (error);
   1168       1.1    ichiro }
   1169       1.1    ichiro 
   1170       1.1    ichiro static int
   1171       1.1    ichiro wi_getdef(sc, wreq)
   1172       1.1    ichiro 	struct wi_softc		*sc;
   1173       1.1    ichiro 	struct wi_req		*wreq;
   1174       1.1    ichiro {
   1175       1.1    ichiro 	struct sockaddr_dl	*sdl;
   1176       1.1    ichiro 	struct ifnet		*ifp;
   1177       1.1    ichiro 	int error = 0;
   1178       1.1    ichiro 
   1179       1.1    ichiro 	ifp = &sc->sc_ethercom.ec_if;
   1180       1.1    ichiro 
   1181       1.1    ichiro 	wreq->wi_len = 2;			/* XXX */
   1182       1.1    ichiro 	switch (wreq->wi_type) {
   1183       1.1    ichiro 	case WI_RID_MAC_NODE:
   1184       1.1    ichiro 		wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
   1185       1.1    ichiro 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1186      1.20   thorpej 		memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
   1187      1.20   thorpej 		memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
   1188       1.1    ichiro 		break;
   1189       1.1    ichiro 	case WI_RID_PORTTYPE:
   1190      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ptype);
   1191       1.1    ichiro 		break;
   1192       1.1    ichiro 	case WI_RID_TX_RATE:
   1193      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_rate);
   1194       1.1    ichiro 		break;
   1195       1.1    ichiro 	case WI_RID_MAX_DATALEN:
   1196      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_data_len);
   1197       1.1    ichiro 		break;
   1198       1.1    ichiro 	case WI_RID_RTS_THRESH:
   1199      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
   1200       1.1    ichiro 		break;
   1201       1.1    ichiro 	case WI_RID_SYSTEM_SCALE:
   1202      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_ap_density);
   1203       1.1    ichiro 		break;
   1204       1.1    ichiro 	case WI_RID_CREATE_IBSS:
   1205      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_create_ibss);
   1206       1.1    ichiro 		break;
   1207       1.1    ichiro 	case WI_RID_OWN_CHNL:
   1208      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_channel);
   1209       1.1    ichiro 		break;
   1210       1.1    ichiro 	case WI_RID_NODENAME:
   1211       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_nodeid);
   1212       1.1    ichiro 		break;
   1213       1.1    ichiro 	case WI_RID_DESIRED_SSID:
   1214       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_netid);
   1215       1.1    ichiro 		break;
   1216       1.1    ichiro 	case WI_RID_OWN_SSID:
   1217       1.1    ichiro 		wi_request_fill_ssid(wreq, &sc->wi_ibssid);
   1218       1.1    ichiro 		break;
   1219       1.1    ichiro 	case WI_RID_PM_ENABLED:
   1220      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
   1221       1.1    ichiro 		break;
   1222       1.1    ichiro 	case WI_RID_MICROWAVE_OVEN:
   1223      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
   1224       1.1    ichiro 		break;
   1225       1.1    ichiro 	case WI_RID_MAX_SLEEP:
   1226      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_max_sleep);
   1227       1.1    ichiro 		break;
   1228       1.4    ichiro 	case WI_RID_AUTH_CNTL:
   1229      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_authtype);
   1230       1.4    ichiro 		break;
   1231       1.4    ichiro 	case WI_RID_ROAMING_MODE:
   1232      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_roaming);
   1233       1.4    ichiro 		break;
   1234       1.1    ichiro 	case WI_RID_WEP_AVAIL:
   1235      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_has_wep);
   1236       1.1    ichiro 		break;
   1237       1.1    ichiro 	case WI_RID_ENCRYPTION:
   1238      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_use_wep);
   1239       1.1    ichiro 		break;
   1240       1.1    ichiro 	case WI_RID_TX_CRYPT_KEY:
   1241      1.11    tsubai 		wreq->wi_val[0] = htole16(sc->wi_tx_key);
   1242       1.1    ichiro 		break;
   1243       1.1    ichiro 	case WI_RID_DEFLT_CRYPT_KEYS:
   1244       1.1    ichiro 		wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
   1245      1.20   thorpej 		memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
   1246       1.1    ichiro 		break;
   1247       1.1    ichiro 	default:
   1248       1.1    ichiro #if 0
   1249       1.1    ichiro 		error = EIO;
   1250       1.1    ichiro #else
   1251       1.1    ichiro #ifdef WI_DEBUG
   1252       1.1    ichiro 		printf("%s: wi_getdef: unknown request %d\n",
   1253       1.1    ichiro 		    sc->sc_dev.dv_xname, wreq->wi_type);
   1254       1.1    ichiro #endif
   1255       1.1    ichiro #endif
   1256       1.1    ichiro 		break;
   1257       1.1    ichiro 	}
   1258       1.1    ichiro 
   1259       1.1    ichiro 	return (error);
   1260       1.1    ichiro }
   1261       1.1    ichiro 
   1262       1.1    ichiro static int
   1263       1.1    ichiro wi_ioctl(ifp, command, data)
   1264       1.1    ichiro 	struct ifnet		*ifp;
   1265       1.1    ichiro 	u_long			command;
   1266       1.1    ichiro 	caddr_t			data;
   1267       1.1    ichiro {
   1268  1.24.2.1      fvdl 	int			i, s, error = 0;
   1269       1.1    ichiro 	struct wi_softc		*sc = ifp->if_softc;
   1270       1.1    ichiro 	struct wi_req		wreq;
   1271       1.1    ichiro 	struct ifreq		*ifr;
   1272  1.24.2.1      fvdl 	struct ifdrv		*ifd;
   1273       1.1    ichiro 	struct proc *p = curproc;
   1274       1.1    ichiro 	struct ieee80211_nwid nwid;
   1275       1.1    ichiro 
   1276       1.1    ichiro 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1277       1.1    ichiro 		return (ENXIO);
   1278       1.1    ichiro 
   1279       1.1    ichiro 	s = splnet();
   1280       1.1    ichiro 
   1281       1.1    ichiro 	ifr = (struct ifreq *)data;
   1282       1.1    ichiro 	switch (command) {
   1283       1.1    ichiro 	case SIOCSIFADDR:
   1284       1.1    ichiro 	case SIOCGIFADDR:
   1285       1.1    ichiro 	case SIOCSIFMTU:
   1286       1.1    ichiro 		error = ether_ioctl(ifp, command, data);
   1287       1.1    ichiro 		break;
   1288       1.1    ichiro 	case SIOCSIFFLAGS:
   1289       1.3    ichiro 		if (ifp->if_flags & IFF_UP) {
   1290       1.3    ichiro 			if (ifp->if_flags & IFF_RUNNING &&
   1291       1.3    ichiro 			    ifp->if_flags & IFF_PROMISC &&
   1292       1.3    ichiro 			    !(sc->wi_if_flags & IFF_PROMISC)) {
   1293       1.3    ichiro 				WI_SETVAL(WI_RID_PROMISC, 1);
   1294       1.3    ichiro 			} else if (ifp->if_flags & IFF_RUNNING &&
   1295       1.3    ichiro 			    !(ifp->if_flags & IFF_PROMISC) &&
   1296       1.3    ichiro 			    sc->wi_if_flags & IFF_PROMISC) {
   1297       1.3    ichiro 				WI_SETVAL(WI_RID_PROMISC, 0);
   1298       1.3    ichiro 			}
   1299       1.3    ichiro 			wi_init(ifp);
   1300       1.3    ichiro 		} else {
   1301       1.3    ichiro 			if (ifp->if_flags & IFF_RUNNING) {
   1302       1.3    ichiro 				wi_stop(ifp, 0);
   1303       1.3    ichiro 			}
   1304       1.3    ichiro 		}
   1305       1.3    ichiro 		sc->wi_if_flags = ifp->if_flags;
   1306       1.3    ichiro 
   1307       1.1    ichiro 		if (!(ifp->if_flags & IFF_UP)) {
   1308       1.3    ichiro 			if (sc->sc_enabled) {
   1309       1.3    ichiro 				if (sc->sc_disable)
   1310       1.3    ichiro 					(*sc->sc_disable)(sc);
   1311       1.3    ichiro 				sc->sc_enabled = 0;
   1312       1.3    ichiro 				ifp->if_flags &= ~IFF_RUNNING;
   1313       1.3    ichiro 			}
   1314       1.3    ichiro 		}
   1315       1.3    ichiro 		error = 0;
   1316       1.1    ichiro 		break;
   1317       1.1    ichiro 	case SIOCADDMULTI:
   1318       1.1    ichiro 	case SIOCDELMULTI:
   1319       1.1    ichiro 		error = (command == SIOCADDMULTI) ?
   1320       1.1    ichiro 			ether_addmulti(ifr, &sc->sc_ethercom) :
   1321       1.1    ichiro 			ether_delmulti(ifr, &sc->sc_ethercom);
   1322       1.1    ichiro 		if (error == ENETRESET) {
   1323       1.1    ichiro 			if (sc->sc_enabled != 0) {
   1324       1.3    ichiro 				/*
   1325       1.3    ichiro 				 * Multicast list has changed.  Set the
   1326       1.3    ichiro 				 * hardware filter accordingly.
   1327       1.3    ichiro 				 */
   1328       1.3    ichiro 				wi_setmulti(sc);
   1329       1.1    ichiro 			}
   1330       1.1    ichiro 			error = 0;
   1331       1.1    ichiro 		}
   1332       1.1    ichiro 		break;
   1333       1.1    ichiro 	case SIOCSIFMEDIA:
   1334       1.1    ichiro 	case SIOCGIFMEDIA:
   1335       1.1    ichiro 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
   1336       1.1    ichiro 		break;
   1337       1.1    ichiro 	case SIOCGWAVELAN:
   1338       1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1339       1.1    ichiro 		if (error)
   1340       1.1    ichiro 			break;
   1341  1.24.2.1      fvdl 		switch (wreq.wi_type) {
   1342  1.24.2.1      fvdl 		case WI_RID_IFACE_STATS:
   1343      1.11    tsubai 			/* XXX native byte order */
   1344      1.20   thorpej 			memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
   1345  1.24.2.1      fvdl 			       sizeof(sc->wi_stats));
   1346       1.1    ichiro 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
   1347  1.24.2.1      fvdl 			break;
   1348  1.24.2.1      fvdl 		case WI_RID_DEFLT_CRYPT_KEYS:
   1349       1.1    ichiro 			/* For non-root user, return all-zeroes keys */
   1350       1.1    ichiro 			if (suser(p->p_ucred, &p->p_acflag))
   1351      1.21   thorpej 				memset((char *)&wreq, 0,
   1352  1.24.2.1      fvdl 				       sizeof(struct wi_ltv_keys));
   1353       1.1    ichiro 			else
   1354      1.20   thorpej 				memcpy((char *)&wreq, (char *)&sc->wi_keys,
   1355  1.24.2.1      fvdl 				       sizeof(struct wi_ltv_keys));
   1356  1.24.2.1      fvdl 			break;
   1357  1.24.2.1      fvdl 		default:
   1358       1.1    ichiro 			if (sc->sc_enabled == 0)
   1359       1.1    ichiro 				error = wi_getdef(sc, &wreq);
   1360  1.24.2.1      fvdl 			else if (wi_read_record(sc,
   1361  1.24.2.1      fvdl 						(struct wi_ltv_gen *)&wreq))
   1362       1.1    ichiro 				error = EINVAL;
   1363  1.24.2.1      fvdl 			break;
   1364       1.1    ichiro 		}
   1365       1.1    ichiro 		if (error == 0)
   1366       1.1    ichiro 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
   1367       1.1    ichiro 		break;
   1368  1.24.2.1      fvdl 
   1369       1.1    ichiro 	case SIOCSWAVELAN:
   1370       1.1    ichiro 		error = suser(p->p_ucred, &p->p_acflag);
   1371       1.1    ichiro 		if (error)
   1372       1.1    ichiro 			break;
   1373       1.1    ichiro 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1374       1.1    ichiro 		if (error)
   1375       1.1    ichiro 			break;
   1376  1.24.2.1      fvdl 		switch (wreq.wi_type) {
   1377  1.24.2.1      fvdl 		case WI_RID_IFACE_STATS:
   1378       1.1    ichiro 			error = EINVAL;
   1379       1.1    ichiro 			break;
   1380  1.24.2.1      fvdl 		case WI_RID_MGMT_XMIT:
   1381       1.1    ichiro 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
   1382  1.24.2.1      fvdl 					     wreq.wi_len);
   1383  1.24.2.1      fvdl 			break;
   1384  1.24.2.1      fvdl 
   1385  1.24.2.1      fvdl 		default:
   1386       1.1    ichiro 			if (sc->sc_enabled != 0)
   1387       1.1    ichiro 				error = wi_write_record(sc,
   1388       1.1    ichiro 				    (struct wi_ltv_gen *)&wreq);
   1389       1.1    ichiro 			if (error == 0)
   1390       1.1    ichiro 				error = wi_setdef(sc, &wreq);
   1391       1.1    ichiro 			if (error == 0 && sc->sc_enabled != 0)
   1392       1.1    ichiro 				/* Reinitialize WaveLAN. */
   1393       1.1    ichiro 				wi_init(ifp);
   1394  1.24.2.1      fvdl 			break;
   1395  1.24.2.1      fvdl 		}
   1396  1.24.2.1      fvdl 		break;
   1397  1.24.2.1      fvdl 
   1398  1.24.2.1      fvdl 	case SIOCSDRVSPEC:
   1399  1.24.2.1      fvdl 		error = suser(p->p_ucred, &p->p_acflag);
   1400  1.24.2.1      fvdl 		if (error)
   1401  1.24.2.1      fvdl 			break;
   1402  1.24.2.1      fvdl 		ifd = (struct ifdrv *)data;
   1403  1.24.2.1      fvdl 		switch (ifd->ifd_cmd) {
   1404  1.24.2.1      fvdl 		case WI_IOCTL_SET_SCAN:
   1405  1.24.2.1      fvdl 			error = copyin(ifd->ifd_data, &i, sizeof (i));
   1406  1.24.2.1      fvdl 			if (error)
   1407  1.24.2.1      fvdl 				break;
   1408  1.24.2.1      fvdl 
   1409  1.24.2.1      fvdl 			sc->wi_results.scanning = i;
   1410  1.24.2.1      fvdl 			if (sc->wi_results.scanning > 0)
   1411  1.24.2.1      fvdl 				callout_reset(&sc->wi_scan_ch,
   1412  1.24.2.1      fvdl 					      sc->wi_results.scanning,
   1413  1.24.2.1      fvdl 					      wi_inquire_scan, sc);
   1414  1.24.2.1      fvdl 			else
   1415  1.24.2.1      fvdl 				callout_stop(&sc->wi_scan_ch);
   1416  1.24.2.1      fvdl 			break;
   1417  1.24.2.1      fvdl 
   1418  1.24.2.1      fvdl 		/*
   1419  1.24.2.1      fvdl 		 * Experimental XXXMLG
   1420  1.24.2.1      fvdl 		 */
   1421  1.24.2.1      fvdl 		case WI_IOCTL_SET_TESTMODE:
   1422  1.24.2.1      fvdl 			error = copyin(ifd->ifd_data, &i, sizeof (i));
   1423  1.24.2.1      fvdl 			if (error)
   1424  1.24.2.1      fvdl 				break;
   1425  1.24.2.1      fvdl 			if (i) {
   1426  1.24.2.1      fvdl 				wi_cmd(sc, WI_CMD_TEST | WI_TEST_MONITOR << 8,
   1427  1.24.2.1      fvdl 				       0);
   1428  1.24.2.1      fvdl 				printf("wi test mode enabled\n");
   1429  1.24.2.1      fvdl 			} else {
   1430  1.24.2.1      fvdl 				wi_cmd(sc, WI_CMD_TEST | WI_TEST_STOP << 8, 0);
   1431  1.24.2.1      fvdl 				printf("wi test mode disabled\n");
   1432  1.24.2.1      fvdl 			}
   1433  1.24.2.1      fvdl 			break;
   1434  1.24.2.1      fvdl 
   1435  1.24.2.1      fvdl 		default:
   1436  1.24.2.1      fvdl 			error = EINVAL;
   1437  1.24.2.1      fvdl 			break;
   1438  1.24.2.1      fvdl 		}
   1439  1.24.2.1      fvdl 		break;
   1440  1.24.2.1      fvdl 
   1441  1.24.2.1      fvdl 	case SIOCGDRVSPEC:
   1442  1.24.2.1      fvdl 		ifd = (struct ifdrv *)data;
   1443  1.24.2.1      fvdl 		switch (ifd->ifd_cmd) {
   1444  1.24.2.1      fvdl 		case WI_IOCTL_GET_SCAN_RESULTS:
   1445  1.24.2.1      fvdl 			error = copyout(&sc->wi_results, ifd->ifd_data,
   1446  1.24.2.1      fvdl 					sizeof(struct wi_scan_results));
   1447  1.24.2.1      fvdl 			break;
   1448  1.24.2.1      fvdl 
   1449  1.24.2.1      fvdl 		default:
   1450  1.24.2.1      fvdl 			error = EINVAL;
   1451  1.24.2.1      fvdl 			break;
   1452       1.1    ichiro 		}
   1453       1.1    ichiro 		break;
   1454  1.24.2.1      fvdl 
   1455       1.1    ichiro 	case SIOCG80211NWID:
   1456       1.1    ichiro 		if (sc->sc_enabled == 0) {
   1457       1.1    ichiro 			/* Return the desired ID */
   1458       1.1    ichiro 			error = copyout(&sc->wi_netid, ifr->ifr_data,
   1459       1.1    ichiro 			    sizeof(sc->wi_netid));
   1460       1.1    ichiro 		} else {
   1461       1.1    ichiro 			wreq.wi_type = WI_RID_CURRENT_SSID;
   1462       1.1    ichiro 			wreq.wi_len = WI_MAX_DATALEN;
   1463       1.1    ichiro 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
   1464      1.11    tsubai 			    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
   1465       1.1    ichiro 				error = EINVAL;
   1466       1.1    ichiro 			else {
   1467       1.1    ichiro 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
   1468      1.11    tsubai 				    le16toh(wreq.wi_val[0]));
   1469       1.1    ichiro 				error = copyout(&nwid, ifr->ifr_data,
   1470       1.1    ichiro 				    sizeof(nwid));
   1471       1.1    ichiro 			}
   1472       1.1    ichiro 		}
   1473       1.1    ichiro 		break;
   1474       1.1    ichiro 	case SIOCS80211NWID:
   1475       1.1    ichiro 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
   1476       1.1    ichiro 		if (error != 0)
   1477       1.1    ichiro 			break;
   1478       1.1    ichiro 		if (nwid.i_len > IEEE80211_NWID_LEN) {
   1479       1.1    ichiro 			error = EINVAL;
   1480       1.1    ichiro 			break;
   1481       1.1    ichiro 		}
   1482       1.1    ichiro 		if (sc->wi_netid.i_len == nwid.i_len &&
   1483       1.1    ichiro 		    memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
   1484       1.1    ichiro 			break;
   1485       1.1    ichiro 		wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
   1486       1.1    ichiro 		if (sc->sc_enabled != 0)
   1487       1.1    ichiro 			/* Reinitialize WaveLAN. */
   1488       1.1    ichiro 			wi_init(ifp);
   1489       1.1    ichiro 		break;
   1490       1.1    ichiro 	case SIOCS80211NWKEY:
   1491       1.1    ichiro 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
   1492       1.1    ichiro 		break;
   1493       1.1    ichiro 	case SIOCG80211NWKEY:
   1494       1.1    ichiro 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
   1495       1.1    ichiro 		break;
   1496       1.1    ichiro 	case SIOCS80211POWER:
   1497       1.1    ichiro 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
   1498       1.1    ichiro 		break;
   1499       1.1    ichiro 	case SIOCG80211POWER:
   1500       1.1    ichiro 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
   1501       1.1    ichiro 		break;
   1502       1.1    ichiro 
   1503       1.1    ichiro 	default:
   1504       1.1    ichiro 		error = EINVAL;
   1505       1.1    ichiro 		break;
   1506       1.1    ichiro 	}
   1507       1.1    ichiro 
   1508       1.1    ichiro 	splx(s);
   1509       1.1    ichiro 	return (error);
   1510       1.1    ichiro }
   1511       1.1    ichiro 
   1512       1.1    ichiro static int
   1513       1.1    ichiro wi_init(ifp)
   1514       1.1    ichiro 	struct ifnet *ifp;
   1515       1.1    ichiro {
   1516       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   1517       1.1    ichiro 	struct wi_req wreq;
   1518       1.1    ichiro 	struct wi_ltv_macaddr mac;
   1519       1.1    ichiro 	int error, id = 0;
   1520       1.1    ichiro 
   1521       1.1    ichiro 	if (!sc->sc_enabled) {
   1522      1.11    tsubai 		if ((error = (*sc->sc_enable)(sc)) != 0)
   1523       1.1    ichiro 			goto out;
   1524       1.1    ichiro 		sc->sc_enabled = 1;
   1525       1.1    ichiro 	}
   1526       1.1    ichiro 
   1527       1.1    ichiro 	wi_stop(ifp, 0);
   1528       1.1    ichiro 	wi_reset(sc);
   1529       1.1    ichiro 
   1530       1.1    ichiro 	/* Program max data length. */
   1531       1.1    ichiro 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
   1532       1.1    ichiro 
   1533       1.1    ichiro 	/* Enable/disable IBSS creation. */
   1534       1.1    ichiro 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
   1535       1.1    ichiro 
   1536       1.1    ichiro 	/* Set the port type. */
   1537       1.1    ichiro 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
   1538       1.1    ichiro 
   1539       1.1    ichiro 	/* Program the RTS/CTS threshold. */
   1540       1.1    ichiro 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
   1541       1.1    ichiro 
   1542       1.1    ichiro 	/* Program the TX rate */
   1543       1.1    ichiro 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
   1544       1.1    ichiro 
   1545       1.1    ichiro 	/* Access point density */
   1546       1.1    ichiro 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
   1547       1.1    ichiro 
   1548       1.1    ichiro 	/* Power Management Enabled */
   1549       1.1    ichiro 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
   1550       1.1    ichiro 
   1551       1.1    ichiro 	/* Power Managment Max Sleep */
   1552       1.1    ichiro 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
   1553       1.1    ichiro 
   1554       1.4    ichiro 	/* Roaming type */
   1555       1.4    ichiro 	WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
   1556       1.4    ichiro 
   1557       1.1    ichiro 	/* Specify the IBSS name */
   1558       1.1    ichiro 	wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
   1559       1.1    ichiro 
   1560       1.1    ichiro 	/* Specify the network name */
   1561       1.1    ichiro 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
   1562       1.1    ichiro 
   1563       1.1    ichiro 	/* Specify the frequency to use */
   1564       1.1    ichiro 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
   1565       1.1    ichiro 
   1566       1.1    ichiro 	/* Program the nodename. */
   1567       1.1    ichiro 	wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
   1568       1.1    ichiro 
   1569       1.1    ichiro 	/* Set our MAC address. */
   1570       1.1    ichiro 	mac.wi_len = 4;
   1571       1.1    ichiro 	mac.wi_type = WI_RID_MAC_NODE;
   1572       1.1    ichiro 	memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
   1573       1.1    ichiro 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
   1574       1.1    ichiro 
   1575       1.4    ichiro 	/* Initialize promisc mode. */
   1576       1.4    ichiro 	if (ifp->if_flags & IFF_PROMISC) {
   1577       1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 1);
   1578       1.4    ichiro 	} else {
   1579       1.4    ichiro 		WI_SETVAL(WI_RID_PROMISC, 0);
   1580       1.4    ichiro 	}
   1581       1.4    ichiro 
   1582       1.1    ichiro 	/* Configure WEP. */
   1583       1.1    ichiro 	if (sc->wi_has_wep) {
   1584       1.1    ichiro 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
   1585       1.1    ichiro 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
   1586       1.1    ichiro 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
   1587       1.1    ichiro 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   1588       1.1    ichiro 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
   1589       1.4    ichiro 		if (sc->sc_prism2 && sc->wi_use_wep) {
   1590       1.4    ichiro 			/*
   1591      1.14    ichiro 			 * ONLY HWB3163 EVAL-CARD Firmware version
   1592      1.14    ichiro 			 * less than 0.8 variant3
   1593      1.14    ichiro 			 *
   1594       1.5    ichiro 			 *   If promiscuous mode disable, Prism2 chip
   1595       1.5    ichiro 			 *  does not work with WEP .
   1596       1.4    ichiro 			 * It is under investigation for details.
   1597       1.4    ichiro 			 * (ichiro (at) netbsd.org)
   1598       1.4    ichiro 			 */
   1599       1.9    ichiro 			if (sc->sc_prism2_ver < 83 ) {
   1600       1.9    ichiro 				/* firm ver < 0.8 variant 3 */
   1601       1.6    ichiro 				WI_SETVAL(WI_RID_PROMISC, 1);
   1602       1.6    ichiro 			}
   1603       1.4    ichiro 			WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
   1604       1.4    ichiro 		}
   1605       1.1    ichiro 	}
   1606       1.1    ichiro 
   1607       1.1    ichiro 	/* Set multicast filter. */
   1608       1.1    ichiro 	wi_setmulti(sc);
   1609       1.1    ichiro 
   1610       1.1    ichiro 	/* Enable desired port */
   1611       1.1    ichiro 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
   1612       1.1    ichiro 
   1613       1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   1614       1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   1615       1.1    ichiro 		printf("%s: tx buffer allocation failed\n",
   1616       1.1    ichiro 		    sc->sc_dev.dv_xname);
   1617       1.1    ichiro 		goto out;
   1618       1.1    ichiro 	}
   1619       1.1    ichiro 	sc->wi_tx_data_id = id;
   1620       1.1    ichiro 
   1621       1.1    ichiro 	if ((error = wi_alloc_nicmem(sc,
   1622       1.1    ichiro 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   1623       1.1    ichiro 		printf("%s: mgmt. buffer allocation failed\n",
   1624       1.1    ichiro 		    sc->sc_dev.dv_xname);
   1625       1.1    ichiro 		goto out;
   1626       1.1    ichiro 	}
   1627       1.1    ichiro 	sc->wi_tx_mgmt_id = id;
   1628       1.1    ichiro 
   1629       1.1    ichiro 	/* Enable interrupts */
   1630       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
   1631       1.1    ichiro 
   1632       1.1    ichiro 	ifp->if_flags |= IFF_RUNNING;
   1633       1.1    ichiro 	ifp->if_flags &= ~IFF_OACTIVE;
   1634       1.1    ichiro 
   1635  1.24.2.1      fvdl 	callout_reset(&sc->wi_stats_ch, STATS_FREQUENCY, wi_inquire_stats, sc);
   1636       1.1    ichiro 
   1637       1.1    ichiro  out:
   1638       1.1    ichiro 	if (error) {
   1639       1.1    ichiro 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1640       1.1    ichiro 		ifp->if_timer = 0;
   1641       1.1    ichiro 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   1642       1.1    ichiro 	}
   1643       1.1    ichiro 	return (error);
   1644       1.1    ichiro }
   1645       1.1    ichiro 
   1646      1.11    tsubai static void
   1647       1.1    ichiro wi_start(ifp)
   1648       1.1    ichiro 	struct ifnet		*ifp;
   1649       1.1    ichiro {
   1650       1.1    ichiro 	struct wi_softc		*sc;
   1651       1.1    ichiro 	struct mbuf		*m0;
   1652       1.1    ichiro 	struct wi_frame		tx_frame;
   1653       1.1    ichiro 	struct ether_header	*eh;
   1654       1.1    ichiro 	int			id;
   1655       1.1    ichiro 
   1656       1.1    ichiro 	sc = ifp->if_softc;
   1657       1.1    ichiro 
   1658       1.1    ichiro 	if (ifp->if_flags & IFF_OACTIVE)
   1659       1.1    ichiro 		return;
   1660       1.1    ichiro 
   1661       1.1    ichiro 	IFQ_DEQUEUE(&ifp->if_snd, m0);
   1662       1.1    ichiro 	if (m0 == NULL)
   1663       1.1    ichiro 		return;
   1664       1.1    ichiro 
   1665      1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   1666       1.1    ichiro 	id = sc->wi_tx_data_id;
   1667       1.1    ichiro 	eh = mtod(m0, struct ether_header *);
   1668       1.1    ichiro 
   1669       1.1    ichiro 	/*
   1670       1.1    ichiro 	 * Use RFC1042 encoding for IP and ARP datagrams,
   1671       1.1    ichiro 	 * 802.3 for anything else.
   1672       1.1    ichiro 	 */
   1673       1.1    ichiro 	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
   1674       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
   1675       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
   1676       1.1    ichiro 	    ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
   1677      1.20   thorpej 		memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
   1678      1.20   thorpej 		    ETHER_ADDR_LEN);
   1679      1.20   thorpej 		memcpy((char *)&tx_frame.wi_addr2, (char *)&eh->ether_shost,
   1680      1.20   thorpej 		    ETHER_ADDR_LEN);
   1681      1.20   thorpej 		memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
   1682      1.20   thorpej 		    ETHER_ADDR_LEN);
   1683      1.20   thorpej 		memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
   1684      1.20   thorpej 		    ETHER_ADDR_LEN);
   1685       1.1    ichiro 
   1686      1.11    tsubai 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   1687      1.11    tsubai 		tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
   1688       1.1    ichiro 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
   1689       1.1    ichiro 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
   1690       1.1    ichiro 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   1691       1.1    ichiro 		tx_frame.wi_type = eh->ether_type;
   1692       1.1    ichiro 
   1693       1.1    ichiro 		m_copydata(m0, sizeof(struct ether_header),
   1694       1.1    ichiro 		    m0->m_pkthdr.len - sizeof(struct ether_header),
   1695       1.1    ichiro 		    (caddr_t)&sc->wi_txbuf);
   1696       1.1    ichiro 
   1697       1.1    ichiro 		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   1698       1.1    ichiro 		    sizeof(struct wi_frame));
   1699       1.1    ichiro 		wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf,
   1700       1.1    ichiro 		    (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2);
   1701       1.1    ichiro 	} else {
   1702      1.11    tsubai 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
   1703       1.1    ichiro 
   1704       1.1    ichiro 		m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
   1705       1.1    ichiro 
   1706       1.1    ichiro 		wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   1707       1.1    ichiro 		    sizeof(struct wi_frame));
   1708       1.1    ichiro 		wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf,
   1709       1.1    ichiro 		    m0->m_pkthdr.len + 2);
   1710       1.1    ichiro 	}
   1711       1.1    ichiro 
   1712       1.1    ichiro #if NBPFILTER > 0
   1713       1.1    ichiro 	/*
   1714       1.1    ichiro 	 * If there's a BPF listener, bounce a copy of
   1715       1.1    ichiro 	 * this frame to him.
   1716       1.1    ichiro 	 */
   1717       1.1    ichiro 	if (ifp->if_bpf)
   1718       1.1    ichiro 		bpf_mtap(ifp->if_bpf, m0);
   1719       1.1    ichiro #endif
   1720       1.1    ichiro 
   1721       1.1    ichiro 	m_freem(m0);
   1722       1.1    ichiro 
   1723       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
   1724       1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   1725       1.1    ichiro 
   1726       1.1    ichiro 	ifp->if_flags |= IFF_OACTIVE;
   1727       1.1    ichiro 
   1728       1.1    ichiro 	/*
   1729       1.1    ichiro 	 * Set a timeout in case the chip goes out to lunch.
   1730       1.1    ichiro 	 */
   1731       1.1    ichiro 	ifp->if_timer = 5;
   1732       1.1    ichiro 
   1733       1.1    ichiro 	return;
   1734       1.1    ichiro }
   1735       1.1    ichiro 
   1736      1.11    tsubai static int
   1737       1.1    ichiro wi_mgmt_xmit(sc, data, len)
   1738       1.1    ichiro 	struct wi_softc		*sc;
   1739       1.1    ichiro 	caddr_t			data;
   1740       1.1    ichiro 	int			len;
   1741       1.1    ichiro {
   1742       1.1    ichiro 	struct wi_frame		tx_frame;
   1743       1.1    ichiro 	int			id;
   1744       1.1    ichiro 	struct wi_80211_hdr	*hdr;
   1745       1.1    ichiro 	caddr_t			dptr;
   1746       1.1    ichiro 
   1747       1.1    ichiro 	hdr = (struct wi_80211_hdr *)data;
   1748       1.1    ichiro 	dptr = data + sizeof(struct wi_80211_hdr);
   1749       1.1    ichiro 
   1750      1.21   thorpej 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   1751       1.1    ichiro 	id = sc->wi_tx_mgmt_id;
   1752       1.1    ichiro 
   1753      1.20   thorpej 	memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
   1754       1.1    ichiro 	   sizeof(struct wi_80211_hdr));
   1755       1.1    ichiro 
   1756      1.11    tsubai 	tx_frame.wi_dat_len = htole16(len - WI_SNAPHDR_LEN);
   1757       1.1    ichiro 	tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN);
   1758       1.1    ichiro 
   1759       1.1    ichiro 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
   1760       1.1    ichiro 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
   1761       1.1    ichiro 	    (len - sizeof(struct wi_80211_hdr)) + 2);
   1762       1.1    ichiro 
   1763       1.1    ichiro 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
   1764       1.1    ichiro 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   1765       1.1    ichiro 		return(EIO);
   1766       1.1    ichiro 	}
   1767       1.1    ichiro 
   1768       1.1    ichiro 	return(0);
   1769       1.1    ichiro }
   1770       1.1    ichiro 
   1771       1.1    ichiro static void
   1772       1.1    ichiro wi_stop(ifp, disable)
   1773       1.1    ichiro 	struct ifnet *ifp;
   1774       1.1    ichiro {
   1775       1.1    ichiro 	struct wi_softc	*sc = ifp->if_softc;
   1776       1.1    ichiro 
   1777       1.1    ichiro 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1778       1.1    ichiro 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
   1779       1.1    ichiro 
   1780  1.24.2.1      fvdl 	callout_stop(&sc->wi_stats_ch);
   1781  1.24.2.1      fvdl 	callout_stop(&sc->wi_scan_ch);
   1782       1.1    ichiro 
   1783       1.1    ichiro 	if (disable) {
   1784       1.4    ichiro 		if (sc->sc_enabled) {
   1785       1.4    ichiro 			if (sc->sc_disable)
   1786       1.4    ichiro 				(*sc->sc_disable)(sc);
   1787       1.4    ichiro 			sc->sc_enabled = 0;
   1788       1.4    ichiro 		}
   1789       1.1    ichiro 	}
   1790       1.1    ichiro 
   1791       1.1    ichiro 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
   1792       1.1    ichiro 	ifp->if_timer = 0;
   1793       1.1    ichiro }
   1794       1.1    ichiro 
   1795      1.11    tsubai static void
   1796       1.1    ichiro wi_watchdog(ifp)
   1797       1.1    ichiro 	struct ifnet		*ifp;
   1798       1.1    ichiro {
   1799       1.1    ichiro 	struct wi_softc		*sc;
   1800       1.1    ichiro 
   1801       1.1    ichiro 	sc = ifp->if_softc;
   1802       1.1    ichiro 
   1803       1.1    ichiro 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
   1804       1.1    ichiro 
   1805       1.1    ichiro 	wi_init(ifp);
   1806       1.1    ichiro 
   1807       1.1    ichiro 	ifp->if_oerrors++;
   1808       1.1    ichiro 
   1809       1.1    ichiro 	return;
   1810       1.1    ichiro }
   1811       1.1    ichiro 
   1812       1.1    ichiro void
   1813       1.1    ichiro wi_shutdown(sc)
   1814       1.1    ichiro 	struct wi_softc *sc;
   1815       1.1    ichiro {
   1816      1.11    tsubai 	int s;
   1817       1.1    ichiro 
   1818      1.11    tsubai 	s = splnet();
   1819      1.11    tsubai 	if (sc->sc_enabled) {
   1820      1.11    tsubai 		if (sc->sc_disable)
   1821      1.11    tsubai 			(*sc->sc_disable)(sc);
   1822      1.11    tsubai 		sc->sc_enabled = 0;
   1823      1.11    tsubai 	}
   1824       1.1    ichiro 	splx(s);
   1825       1.1    ichiro }
   1826       1.1    ichiro 
   1827       1.1    ichiro int
   1828       1.1    ichiro wi_activate(self, act)
   1829       1.1    ichiro 	struct device *self;
   1830       1.1    ichiro 	enum devact act;
   1831       1.1    ichiro {
   1832       1.1    ichiro 	struct wi_softc *sc = (struct wi_softc *)self;
   1833       1.1    ichiro 	int rv = 0, s;
   1834       1.1    ichiro 
   1835       1.1    ichiro 	s = splnet();
   1836       1.1    ichiro 	switch (act) {
   1837       1.1    ichiro 	case DVACT_ACTIVATE:
   1838       1.1    ichiro 		rv = EOPNOTSUPP;
   1839       1.1    ichiro 		break;
   1840       1.1    ichiro 
   1841       1.1    ichiro 	case DVACT_DEACTIVATE:
   1842       1.1    ichiro 		if_deactivate(&sc->sc_ethercom.ec_if);
   1843       1.1    ichiro 		break;
   1844       1.1    ichiro 	}
   1845       1.1    ichiro 	splx(s);
   1846       1.1    ichiro 	return (rv);
   1847       1.1    ichiro }
   1848       1.1    ichiro 
   1849       1.4    ichiro static void
   1850       1.4    ichiro wi_get_id(sc)
   1851       1.4    ichiro 	struct wi_softc *sc;
   1852       1.4    ichiro {
   1853       1.4    ichiro 	struct wi_ltv_ver       ver;
   1854       1.4    ichiro 
   1855       1.6    ichiro 	/* getting chip identity */
   1856      1.11    tsubai 	memset(&ver, 0, sizeof(ver));
   1857      1.11    tsubai 	ver.wi_type = WI_RID_CARDID;
   1858      1.11    tsubai 	ver.wi_len = 5;
   1859      1.11    tsubai 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   1860       1.9    ichiro 	printf("%s: using ", sc->sc_dev.dv_xname);
   1861      1.11    tsubai 	switch (le16toh(ver.wi_ver[0])) {
   1862      1.24       wiz 	case WI_NIC_EVB2:
   1863      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841");
   1864      1.24       wiz 		sc->sc_prism2 = 1;
   1865      1.24       wiz 		break;
   1866      1.24       wiz 	case WI_NIC_HWB3763:
   1867      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3763 rev.B");
   1868      1.24       wiz 		sc->sc_prism2 = 1;
   1869      1.24       wiz 		break;
   1870      1.24       wiz 	case WI_NIC_HWB3163:
   1871      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.A");
   1872      1.24       wiz 		sc->sc_prism2 = 1;
   1873      1.24       wiz 		break;
   1874      1.24       wiz 	case WI_NIC_HWB3163B:
   1875      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163 rev.B");
   1876      1.24       wiz 		sc->sc_prism2 = 1;
   1877      1.24       wiz 		break;
   1878      1.24       wiz 	case WI_NIC_EVB3:
   1879      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3842");
   1880      1.24       wiz 		sc->sc_prism2 = 1;
   1881      1.24       wiz 		break;
   1882      1.24       wiz 	case WI_NIC_HWB1153:
   1883      1.24       wiz 		printf("RF:PRISM1 MAC:HFA3841 CARD:HWB1153");
   1884      1.24       wiz 		sc->sc_prism2 = 1;
   1885      1.24       wiz 		break;
   1886      1.24       wiz 	case WI_NIC_P2_SST:
   1887      1.24       wiz 		printf("RF:PRISM2 MAC:HFA3841 CARD:HWB3163-SST-flash");
   1888      1.24       wiz 		sc->sc_prism2 = 1;
   1889      1.24       wiz 		break;
   1890      1.24       wiz 	case WI_NIC_PRISM2_5:
   1891      1.24       wiz 		printf("RF:PRISM2.5 MAC:ISL3873");
   1892      1.24       wiz 		sc->sc_prism2 = 1;
   1893      1.24       wiz 		break;
   1894      1.24       wiz 	default:
   1895      1.24       wiz 		printf("Lucent chip or unknown chip\n");
   1896      1.24       wiz 		sc->sc_prism2 = 0;
   1897      1.24       wiz 		break;
   1898       1.4    ichiro 	}
   1899       1.6    ichiro 
   1900       1.6    ichiro 	if (sc->sc_prism2) {
   1901       1.6    ichiro 		/* try to get prism2 firm version */
   1902       1.6    ichiro 		memset(&ver, 0, sizeof(ver));
   1903       1.6    ichiro 		ver.wi_type = WI_RID_IDENT;
   1904       1.6    ichiro 		ver.wi_len = 5;
   1905       1.6    ichiro 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   1906      1.11    tsubai 		LE16TOH(ver.wi_ver[1]);
   1907      1.11    tsubai 		LE16TOH(ver.wi_ver[2]);
   1908      1.11    tsubai 		LE16TOH(ver.wi_ver[3]);
   1909      1.23       wiz 		printf(", Firmware: %i.%i variant %i\n", ver.wi_ver[2],
   1910      1.11    tsubai 		       ver.wi_ver[3], ver.wi_ver[1]);
   1911       1.9    ichiro 		sc->sc_prism2_ver = ver.wi_ver[2] * 100 +
   1912       1.9    ichiro 				    ver.wi_ver[3] *  10 + ver.wi_ver[1];
   1913       1.6    ichiro 	}
   1914       1.6    ichiro 
   1915       1.4    ichiro 	return;
   1916       1.4    ichiro }
   1917       1.4    ichiro 
   1918       1.1    ichiro int
   1919       1.1    ichiro wi_detach(sc)
   1920       1.1    ichiro 	struct wi_softc *sc;
   1921       1.1    ichiro {
   1922       1.1    ichiro 	struct ifnet *ifp = sc->sc_ifp;
   1923       1.1    ichiro 	int s;
   1924       1.1    ichiro 
   1925       1.1    ichiro 	if (!sc->sc_attached)
   1926       1.1    ichiro 		return (0);
   1927       1.1    ichiro 
   1928       1.1    ichiro 	s = splnet();
   1929  1.24.2.1      fvdl 	callout_stop(&sc->wi_stats_ch);
   1930  1.24.2.1      fvdl 	callout_stop(&sc->wi_scan_ch);
   1931       1.1    ichiro 
   1932       1.1    ichiro 	/* Delete all remaining media. */
   1933       1.1    ichiro 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
   1934       1.1    ichiro 
   1935       1.1    ichiro 	ether_ifdetach(ifp);
   1936       1.1    ichiro 	if_detach(ifp);
   1937       1.1    ichiro 	if (sc->sc_enabled) {
   1938       1.1    ichiro 		if (sc->sc_disable)
   1939       1.1    ichiro 			(*sc->sc_disable)(sc);
   1940       1.1    ichiro 		sc->sc_enabled = 0;
   1941       1.1    ichiro 	}
   1942       1.1    ichiro 	splx(s);
   1943       1.1    ichiro 	return (0);
   1944       1.1    ichiro }
   1945       1.1    ichiro 
   1946       1.1    ichiro void
   1947       1.1    ichiro wi_power(sc, why)
   1948       1.1    ichiro 	struct wi_softc *sc;
   1949       1.1    ichiro 	int why;
   1950       1.1    ichiro {
   1951       1.1    ichiro 	int s;
   1952       1.1    ichiro 
   1953       1.1    ichiro 	if (!sc->sc_enabled)
   1954       1.1    ichiro 		return;
   1955       1.1    ichiro 
   1956       1.1    ichiro 	s = splnet();
   1957       1.1    ichiro 	switch (why) {
   1958       1.1    ichiro 	case PWR_SUSPEND:
   1959       1.1    ichiro 	case PWR_STANDBY:
   1960       1.1    ichiro 		wi_stop(sc->sc_ifp, 0);
   1961       1.4    ichiro 		if (sc->sc_enabled) {
   1962       1.4    ichiro 			if (sc->sc_disable)
   1963       1.4    ichiro 				(*sc->sc_disable)(sc);
   1964       1.4    ichiro 		}
   1965       1.1    ichiro 		break;
   1966       1.1    ichiro 	case PWR_RESUME:
   1967       1.1    ichiro 		sc->sc_enabled = 0;
   1968       1.1    ichiro 		wi_init(sc->sc_ifp);
   1969       1.1    ichiro 		(void)wi_intr(sc);
   1970       1.1    ichiro 		break;
   1971       1.1    ichiro 	case PWR_SOFTSUSPEND:
   1972       1.1    ichiro 	case PWR_SOFTSTANDBY:
   1973       1.1    ichiro 	case PWR_SOFTRESUME:
   1974       1.1    ichiro 		break;
   1975       1.1    ichiro 	}
   1976       1.1    ichiro 	splx(s);
   1977       1.1    ichiro }
   1978       1.1    ichiro 
   1979       1.1    ichiro static int
   1980       1.1    ichiro wi_set_ssid(ws, id, len)
   1981       1.1    ichiro 	struct ieee80211_nwid *ws;
   1982       1.1    ichiro 	u_int8_t *id;
   1983       1.1    ichiro 	int len;
   1984       1.1    ichiro {
   1985       1.1    ichiro 
   1986       1.1    ichiro 	if (len > IEEE80211_NWID_LEN)
   1987       1.1    ichiro 		return (EINVAL);
   1988       1.1    ichiro 	ws->i_len = len;
   1989       1.1    ichiro 	memcpy(ws->i_nwid, id, len);
   1990       1.1    ichiro 	return (0);
   1991       1.1    ichiro }
   1992       1.1    ichiro 
   1993       1.1    ichiro static void
   1994       1.1    ichiro wi_request_fill_ssid(wreq, ws)
   1995       1.1    ichiro 	struct wi_req *wreq;
   1996       1.1    ichiro 	struct ieee80211_nwid *ws;
   1997       1.1    ichiro {
   1998      1.11    tsubai 	int len = ws->i_len;
   1999       1.1    ichiro 
   2000       1.1    ichiro 	memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
   2001      1.11    tsubai 	wreq->wi_val[0] = htole16(len);
   2002      1.11    tsubai 	wreq->wi_len = roundup(len, 2) / 2 + 2;
   2003      1.11    tsubai 	memcpy(&wreq->wi_val[1], ws->i_nwid, len);
   2004       1.1    ichiro }
   2005       1.1    ichiro 
   2006       1.1    ichiro static int
   2007       1.1    ichiro wi_write_ssid(sc, type, wreq, ws)
   2008       1.1    ichiro 	struct wi_softc *sc;
   2009       1.1    ichiro 	int type;
   2010       1.1    ichiro 	struct wi_req *wreq;
   2011       1.1    ichiro 	struct ieee80211_nwid *ws;
   2012       1.1    ichiro {
   2013       1.1    ichiro 
   2014       1.1    ichiro 	wreq->wi_type = type;
   2015       1.1    ichiro 	wi_request_fill_ssid(wreq, ws);
   2016       1.1    ichiro 	return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
   2017       1.1    ichiro }
   2018       1.1    ichiro 
   2019       1.1    ichiro static int
   2020       1.1    ichiro wi_sync_media(sc, ptype, txrate)
   2021       1.1    ichiro 	struct wi_softc *sc;
   2022       1.1    ichiro 	int ptype;
   2023       1.1    ichiro 	int txrate;
   2024       1.1    ichiro {
   2025       1.1    ichiro 	int media = sc->sc_media.ifm_cur->ifm_media;
   2026       1.1    ichiro 	int options = IFM_OPTIONS(media);
   2027       1.1    ichiro 	int subtype;
   2028       1.1    ichiro 
   2029       1.1    ichiro 	switch (txrate) {
   2030       1.1    ichiro 	case 1:
   2031       1.1    ichiro 		subtype = IFM_IEEE80211_DS1;
   2032       1.1    ichiro 		break;
   2033       1.1    ichiro 	case 2:
   2034       1.1    ichiro 		subtype = IFM_IEEE80211_DS2;
   2035       1.1    ichiro 		break;
   2036       1.1    ichiro 	case 3:
   2037       1.1    ichiro 		subtype = IFM_AUTO;
   2038       1.1    ichiro 		break;
   2039       1.1    ichiro 	case 11:
   2040       1.1    ichiro 		subtype = IFM_IEEE80211_DS11;
   2041       1.1    ichiro 		break;
   2042       1.1    ichiro 	default:
   2043       1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2044       1.1    ichiro 		break;
   2045       1.1    ichiro 	}
   2046       1.1    ichiro 	switch (ptype) {
   2047       1.1    ichiro 	case WI_PORTTYPE_ADHOC:
   2048       1.1    ichiro 		options |= IFM_IEEE80211_ADHOC;
   2049       1.1    ichiro 		break;
   2050       1.1    ichiro 	case WI_PORTTYPE_BSS:
   2051       1.1    ichiro 		options &= ~IFM_IEEE80211_ADHOC;
   2052       1.1    ichiro 		break;
   2053       1.1    ichiro 	default:
   2054       1.1    ichiro 		subtype = IFM_MANUAL;		/* Unable to represent */
   2055       1.1    ichiro 		break;
   2056       1.1    ichiro 	}
   2057       1.1    ichiro 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
   2058       1.1    ichiro 	    IFM_INST(media));
   2059       1.1    ichiro 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
   2060       1.1    ichiro 		return (EINVAL);
   2061       1.1    ichiro 	ifmedia_set(&sc->sc_media, media);
   2062       1.1    ichiro 	sc->wi_ptype = ptype;
   2063       1.1    ichiro 	sc->wi_tx_rate = txrate;
   2064       1.1    ichiro 	return (0);
   2065       1.1    ichiro }
   2066       1.1    ichiro 
   2067       1.1    ichiro static int
   2068       1.1    ichiro wi_media_change(ifp)
   2069       1.1    ichiro 	struct ifnet *ifp;
   2070       1.1    ichiro {
   2071       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2072       1.1    ichiro 	int otype = sc->wi_ptype;
   2073       1.1    ichiro 	int orate = sc->wi_tx_rate;
   2074       1.1    ichiro 
   2075       1.1    ichiro 	if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
   2076       1.1    ichiro 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
   2077       1.1    ichiro 	else
   2078       1.1    ichiro 		sc->wi_ptype = WI_PORTTYPE_BSS;
   2079       1.1    ichiro 
   2080       1.1    ichiro 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
   2081       1.1    ichiro 	case IFM_IEEE80211_DS1:
   2082       1.1    ichiro 		sc->wi_tx_rate = 1;
   2083       1.1    ichiro 		break;
   2084       1.1    ichiro 	case IFM_IEEE80211_DS2:
   2085       1.1    ichiro 		sc->wi_tx_rate = 2;
   2086       1.1    ichiro 		break;
   2087       1.1    ichiro 	case IFM_AUTO:
   2088       1.1    ichiro 		sc->wi_tx_rate = 3;
   2089       1.1    ichiro 		break;
   2090       1.1    ichiro 	case IFM_IEEE80211_DS11:
   2091       1.1    ichiro 		sc->wi_tx_rate = 11;
   2092       1.1    ichiro 		break;
   2093       1.1    ichiro 	}
   2094       1.1    ichiro 
   2095       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2096       1.1    ichiro 		if (otype != sc->wi_ptype ||
   2097       1.1    ichiro 		    orate != sc->wi_tx_rate)
   2098       1.1    ichiro 			wi_init(ifp);
   2099       1.1    ichiro 	}
   2100       1.1    ichiro 
   2101       1.1    ichiro 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
   2102       1.1    ichiro 
   2103       1.1    ichiro 	return (0);
   2104       1.1    ichiro }
   2105       1.1    ichiro 
   2106       1.1    ichiro static void
   2107       1.1    ichiro wi_media_status(ifp, imr)
   2108       1.1    ichiro 	struct ifnet *ifp;
   2109       1.1    ichiro 	struct ifmediareq *imr;
   2110       1.1    ichiro {
   2111       1.1    ichiro 	struct wi_softc *sc = ifp->if_softc;
   2112       1.1    ichiro 
   2113       1.1    ichiro 	if (sc->sc_enabled == 0) {
   2114       1.1    ichiro 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
   2115       1.1    ichiro 		imr->ifm_status = 0;
   2116       1.1    ichiro 		return;
   2117       1.1    ichiro 	}
   2118       1.1    ichiro 
   2119       1.1    ichiro 	imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
   2120       1.1    ichiro 	imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
   2121       1.1    ichiro }
   2122       1.1    ichiro 
   2123       1.1    ichiro static int
   2124       1.1    ichiro wi_set_nwkey(sc, nwkey)
   2125       1.1    ichiro 	struct wi_softc *sc;
   2126       1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2127       1.1    ichiro {
   2128      1.22  jdolecek 	int i, error;
   2129      1.22  jdolecek 	size_t len;
   2130       1.1    ichiro 	struct wi_req wreq;
   2131       1.1    ichiro 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
   2132       1.1    ichiro 
   2133       1.1    ichiro 	if (!sc->wi_has_wep)
   2134       1.1    ichiro 		return ENODEV;
   2135       1.1    ichiro 	if (nwkey->i_defkid <= 0 ||
   2136       1.1    ichiro 	    nwkey->i_defkid > IEEE80211_WEP_NKID)
   2137       1.1    ichiro 		return EINVAL;
   2138       1.1    ichiro 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
   2139       1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2140       1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2141       1.1    ichiro 			continue;
   2142       1.1    ichiro 		len = nwkey->i_key[i].i_keylen;
   2143       1.1    ichiro 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
   2144       1.1    ichiro 			return EINVAL;
   2145       1.1    ichiro 		error = copyin(nwkey->i_key[i].i_keydat,
   2146       1.1    ichiro 		    wk->wi_keys[i].wi_keydat, len);
   2147       1.1    ichiro 		if (error)
   2148       1.1    ichiro 			return error;
   2149      1.11    tsubai 		wk->wi_keys[i].wi_keylen = htole16(len);
   2150       1.1    ichiro 	}
   2151       1.1    ichiro 
   2152       1.1    ichiro 	wk->wi_len = (sizeof(*wk) / 2) + 1;
   2153       1.1    ichiro 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   2154       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2155       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2156       1.1    ichiro 		if (error)
   2157       1.1    ichiro 			return error;
   2158       1.1    ichiro 	}
   2159       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2160       1.1    ichiro 	if (error)
   2161       1.1    ichiro 		return error;
   2162       1.1    ichiro 
   2163       1.1    ichiro 	wreq.wi_len = 2;
   2164       1.1    ichiro 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
   2165      1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
   2166       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2167       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2168       1.1    ichiro 		if (error)
   2169       1.1    ichiro 			return error;
   2170       1.1    ichiro 	}
   2171       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2172       1.1    ichiro 	if (error)
   2173       1.1    ichiro 		return error;
   2174       1.1    ichiro 
   2175       1.1    ichiro 	wreq.wi_type = WI_RID_ENCRYPTION;
   2176      1.11    tsubai 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
   2177       1.1    ichiro 	if (sc->sc_enabled != 0) {
   2178       1.1    ichiro 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2179       1.1    ichiro 		if (error)
   2180       1.1    ichiro 			return error;
   2181       1.1    ichiro 	}
   2182       1.1    ichiro 	error = wi_setdef(sc, &wreq);
   2183       1.1    ichiro 	if (error)
   2184       1.1    ichiro 		return error;
   2185       1.1    ichiro 
   2186       1.1    ichiro 	if (sc->sc_enabled != 0)
   2187       1.1    ichiro 		wi_init(&sc->sc_ethercom.ec_if);
   2188       1.1    ichiro 	return 0;
   2189       1.1    ichiro }
   2190       1.1    ichiro 
   2191       1.1    ichiro static int
   2192       1.1    ichiro wi_get_nwkey(sc, nwkey)
   2193       1.1    ichiro 	struct wi_softc *sc;
   2194       1.1    ichiro 	struct ieee80211_nwkey *nwkey;
   2195       1.1    ichiro {
   2196       1.1    ichiro 	int i, len, error;
   2197       1.1    ichiro 	struct wi_ltv_keys *wk = &sc->wi_keys;
   2198       1.1    ichiro 
   2199       1.1    ichiro 	if (!sc->wi_has_wep)
   2200       1.1    ichiro 		return ENODEV;
   2201       1.1    ichiro 	nwkey->i_wepon = sc->wi_use_wep;
   2202       1.1    ichiro 	nwkey->i_defkid = sc->wi_tx_key + 1;
   2203       1.1    ichiro 
   2204       1.1    ichiro 	/* do not show any keys to non-root user */
   2205       1.1    ichiro 	error = suser(curproc->p_ucred, &curproc->p_acflag);
   2206       1.1    ichiro 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2207       1.1    ichiro 		if (nwkey->i_key[i].i_keydat == NULL)
   2208       1.1    ichiro 			continue;
   2209       1.1    ichiro 		/* error holds results of suser() for the first time */
   2210       1.1    ichiro 		if (error)
   2211       1.1    ichiro 			return error;
   2212      1.11    tsubai 		len = le16toh(wk->wi_keys[i].wi_keylen);
   2213       1.1    ichiro 		if (nwkey->i_key[i].i_keylen < len)
   2214       1.1    ichiro 			return ENOSPC;
   2215       1.1    ichiro 		nwkey->i_key[i].i_keylen = len;
   2216       1.1    ichiro 		error = copyout(wk->wi_keys[i].wi_keydat,
   2217       1.1    ichiro 		    nwkey->i_key[i].i_keydat, len);
   2218       1.1    ichiro 		if (error)
   2219       1.1    ichiro 			return error;
   2220       1.1    ichiro 	}
   2221       1.1    ichiro 	return 0;
   2222       1.1    ichiro }
   2223       1.1    ichiro 
   2224       1.1    ichiro static int
   2225       1.1    ichiro wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2226       1.1    ichiro {
   2227       1.1    ichiro 
   2228       1.1    ichiro 	sc->wi_pm_enabled = power->i_enabled;
   2229       1.1    ichiro 	sc->wi_max_sleep = power->i_maxsleep;
   2230       1.1    ichiro 
   2231       1.1    ichiro 	if (sc->sc_enabled)
   2232       1.1    ichiro 		return (wi_init(&sc->sc_ethercom.ec_if));
   2233       1.1    ichiro 
   2234       1.1    ichiro 	return (0);
   2235       1.1    ichiro }
   2236       1.1    ichiro 
   2237       1.1    ichiro static int
   2238       1.1    ichiro wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2239       1.1    ichiro {
   2240       1.1    ichiro 
   2241       1.1    ichiro 	power->i_enabled = sc->wi_pm_enabled;
   2242       1.1    ichiro 	power->i_maxsleep = sc->wi_max_sleep;
   2243       1.1    ichiro 
   2244       1.1    ichiro 	return (0);
   2245       1.1    ichiro }
   2246