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