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