an.c revision 1.29
1/*	$NetBSD: an.c,v 1.29 2004/01/28 15:07:52 onoe Exp $	*/
2/*
3 * Copyright (c) 1997, 1998, 1999
4 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Bill Paul.
17 * 4. Neither the name of the author nor the names of any co-contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $FreeBSD: src/sys/dev/an/if_an.c,v 1.12 2000/11/13 23:04:12 wpaul Exp $
34 */
35
36/*
37 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
38 *
39 * Written by Bill Paul <wpaul@ctr.columbia.edu>
40 * Electrical Engineering Department
41 * Columbia University, New York City
42 */
43
44/*
45 * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego
46 * IETF meeting.
47 */
48
49#include <sys/cdefs.h>
50__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.29 2004/01/28 15:07:52 onoe Exp $");
51
52#include "bpfilter.h"
53
54#include <sys/param.h>
55#include <sys/callout.h>
56#include <sys/systm.h>
57#include <sys/sockio.h>
58#include <sys/mbuf.h>
59#include <sys/kernel.h>
60#include <sys/ucred.h>
61#include <sys/socket.h>
62#include <sys/device.h>
63#include <sys/proc.h>
64#include <sys/md4.h>
65#include <sys/endian.h>
66
67#include <machine/bus.h>
68
69#include <net/if.h>
70#include <net/if_dl.h>
71#include <net/if_ether.h>
72#include <net/if_llc.h>
73#include <net/if_media.h>
74#include <net/if_types.h>
75
76#include <net80211/ieee80211_var.h>
77#include <net80211/ieee80211_compat.h>
78
79#if NBPFILTER > 0
80#include <net/bpf.h>
81#endif
82
83#include <dev/ic/anreg.h>
84#include <dev/ic/anvar.h>
85
86static int an_reset(struct an_softc *);
87static void an_wait(struct an_softc *);
88static int an_init(struct ifnet *);
89static void an_stop(struct ifnet *, int);
90static void an_start(struct ifnet *);
91static void an_watchdog(struct ifnet *);
92static int an_ioctl(struct ifnet *, u_long, caddr_t);
93static int an_media_change(struct ifnet *);
94static void an_media_status(struct ifnet *, struct ifmediareq *);
95
96static int an_set_nwkey(struct an_softc *, struct ieee80211_nwkey *);
97static int an_set_nwkey_wep(struct an_softc *, struct ieee80211_nwkey *);
98static int an_set_nwkey_eap(struct an_softc *, struct ieee80211_nwkey *);
99static int an_get_nwkey(struct an_softc *, struct ieee80211_nwkey *);
100static int an_write_wepkey(struct an_softc *, int, struct an_wepkey *, int);
101
102static void an_rx_intr(struct an_softc *);
103static void an_tx_intr(struct an_softc *, int);
104static void an_linkstat_intr(struct an_softc *);
105
106static int an_cmd(struct an_softc *, int, int);
107static int an_seek_bap(struct an_softc *, int, int);
108static int an_read_bap(struct an_softc *, int, int, void *, int);
109static int an_write_bap(struct an_softc *, int, int, void *, int);
110static int an_mwrite_bap(struct an_softc *, int, int, struct mbuf *, int);
111static int an_read_rid(struct an_softc *, int, void *, int *);
112static int an_write_rid(struct an_softc *, int, void *, int);
113
114static int an_alloc_fid(struct an_softc *, int, int *);
115
116static int an_newstate(struct ieee80211com *, enum ieee80211_state, int);
117
118#ifdef AN_DEBUG
119int an_debug = 0;
120
121#define	DPRINTF(X)	if (an_debug) printf X
122#define	DPRINTF2(X)	if (an_debug > 1) printf X
123#else
124#define	DPRINTF(X)
125#define	DPRINTF2(X)
126#endif
127
128int
129an_attach(struct an_softc *sc)
130{
131	struct ieee80211com *ic = &sc->sc_ic;
132	struct ifnet *ifp = &ic->ic_if;
133	int i, s;
134	struct an_rid_wepkey *akey;
135	int buflen, kid, rid;
136	int chan, chan_min, chan_max;
137
138	s = splnet();
139	sc->sc_invalid = 0;
140
141	an_wait(sc);
142	if (an_reset(sc) != 0) {
143		sc->sc_invalid = 1;
144		splx(s);
145		return 1;
146	}
147
148	/* Load factory config */
149	if (an_cmd(sc, AN_CMD_READCFG, 0) != 0) {
150		splx(s);
151		aprint_error("%s: failed to load config data\n",
152		    sc->sc_dev.dv_xname);
153		return 1;
154	}
155
156	/* Read the current configuration */
157	buflen = sizeof(sc->sc_config);
158	if (an_read_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, &buflen) != 0) {
159		splx(s);
160		aprint_error("%s: read config failed\n", sc->sc_dev.dv_xname);
161		return 1;
162	}
163
164	/* Read the card capabilities */
165	buflen = sizeof(sc->sc_caps);
166	if (an_read_rid(sc, AN_RID_CAPABILITIES, &sc->sc_caps, &buflen) != 0) {
167		splx(s);
168		aprint_error("%s: read caps failed\n", sc->sc_dev.dv_xname);
169		return 1;
170	}
171
172#ifdef AN_DEBUG
173	if (an_debug) {
174		static const int dumprid[] = {
175		    AN_RID_GENCONFIG, AN_RID_CAPABILITIES, AN_RID_SSIDLIST,
176		    AN_RID_APLIST, AN_RID_STATUS, AN_RID_ENCAP
177		};
178
179		for (rid = 0; rid < sizeof(dumprid)/sizeof(dumprid[0]); rid++) {
180			buflen = sizeof(sc->sc_buf);
181			if (an_read_rid(sc, dumprid[rid], &sc->sc_buf, &buflen)
182			    != 0)
183				continue;
184			printf("%04x (%d):\n", dumprid[rid], buflen);
185			for (i = 0; i < (buflen + 1) / 2; i++)
186				printf(" %04x", sc->sc_buf.sc_val[i]);
187			printf("\n");
188		}
189	}
190#endif
191
192	/* Read WEP settings from persistent memory */
193	akey = &sc->sc_buf.sc_wepkey;
194	buflen = sizeof(struct an_rid_wepkey);
195	rid = AN_RID_WEP_VOLATILE;	/* first persistent key */
196	while (an_read_rid(sc, rid, akey, &buflen) == 0) {
197		kid = le16toh(akey->an_key_index);
198		DPRINTF(("an_attach: wep rid=0x%x len=%d(%d) index=0x%04x "
199		    "mac[0]=%02x keylen=%d\n",
200		    rid, buflen, sizeof(*akey), kid,
201		    akey->an_mac_addr[0], le16toh(akey->an_key_len)));
202		if (kid == 0xffff) {
203			sc->sc_tx_perskey = akey->an_mac_addr[0];
204			sc->sc_tx_key = -1;
205			break;
206		}
207		if (kid >= IEEE80211_WEP_NKID)
208			break;
209		sc->sc_perskeylen[kid] = le16toh(akey->an_key_len);
210		sc->sc_wepkeys[kid].an_wep_keylen = -1;
211		rid = AN_RID_WEP_PERSISTENT;	/* for next key */
212		buflen = sizeof(struct an_rid_wepkey);
213	}
214
215	aprint_normal("%s: %s %s (firmware %s)\n", sc->sc_dev.dv_xname,
216	    sc->sc_caps.an_manufname, sc->sc_caps.an_prodname,
217	    sc->sc_caps.an_prodvers);
218
219	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
220
221	ifp->if_softc = sc;
222	ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX |
223	    IFF_MULTICAST | IFF_ALLMULTI;
224	ifp->if_ioctl = an_ioctl;
225	ifp->if_start = an_start;
226	ifp->if_init = an_init;
227	ifp->if_stop = an_stop;
228	ifp->if_watchdog = an_watchdog;
229	IFQ_SET_READY(&ifp->if_snd);
230
231	ic->ic_phytype = IEEE80211_T_DS;
232	ic->ic_opmode = IEEE80211_M_STA;
233	ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_PMGT | IEEE80211_C_IBSS |
234	    IEEE80211_C_MONITOR;
235	ic->ic_state = IEEE80211_S_INIT;
236	IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_caps.an_oemaddr);
237
238	switch (le16toh(sc->sc_caps.an_regdomain)) {
239	default:
240	case AN_REGDOMAIN_USA:
241	case AN_REGDOMAIN_CANADA:
242		chan_min = 1; chan_max = 11; break;
243	case AN_REGDOMAIN_EUROPE:
244	case AN_REGDOMAIN_AUSTRALIA:
245		chan_min = 1; chan_max = 13; break;
246	case AN_REGDOMAIN_JAPAN:
247		chan_min = 14; chan_max = 14; break;
248	case AN_REGDOMAIN_SPAIN:
249		chan_min = 10; chan_max = 11; break;
250	case AN_REGDOMAIN_FRANCE:
251		chan_min = 10; chan_max = 13; break;
252	case AN_REGDOMAIN_JAPANWIDE:
253		chan_min = 1; chan_max = 14; break;
254	}
255
256	for (chan = chan_min; chan <= chan_max; chan++) {
257		ic->ic_channels[chan].ic_freq =
258		    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
259		ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
260	}
261	ic->ic_ibss_chan = &ic->ic_channels[chan_min];
262
263	aprint_normal("%s: 802.11 address: %s, channel: %d-%d\n",
264	    ifp->if_xname, ether_sprintf(ic->ic_myaddr), chan_min, chan_max);
265
266	/* Find supported rate */
267	for (i = 0; i < sizeof(sc->sc_caps.an_rates); i++) {
268		if (sc->sc_caps.an_rates[i] == 0)
269			continue;
270		ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
271		    ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates++] =
272		    sc->sc_caps.an_rates[i];
273	}
274
275	/*
276	 * Call MI attach routine.
277	 */
278	if_attach(ifp);
279	ieee80211_ifattach(ifp);
280
281	sc->sc_newstate = ic->ic_newstate;
282	ic->ic_newstate = an_newstate;
283
284	ieee80211_media_init(ifp, an_media_change, an_media_status);
285	sc->sc_attached = 1;
286	splx(s);
287
288	return 0;
289}
290
291int
292an_detach(struct an_softc *sc)
293{
294	struct ifnet *ifp = &sc->sc_ic.ic_if;
295	int s;
296
297	if (!sc->sc_attached)
298		return 0;
299
300	s = splnet();
301	sc->sc_invalid = 1;
302	an_stop(ifp, 1);
303	ifmedia_delete_instance(&sc->sc_ic.ic_media, IFM_INST_ANY);
304	ieee80211_ifdetach(ifp);
305	if_detach(ifp);
306	splx(s);
307	return 0;
308}
309
310int
311an_activate(struct device *self, enum devact act)
312{
313	struct an_softc *sc = (struct an_softc *)self;
314	int s, error = 0;
315
316	s = splnet();
317	switch (act) {
318	case DVACT_ACTIVATE:
319		error = EOPNOTSUPP;
320		break;
321
322	case DVACT_DEACTIVATE:
323		sc->sc_invalid = 1;
324		if_deactivate(&sc->sc_ic.ic_if);
325		break;
326	}
327	splx(s);
328
329	return error;
330}
331
332void
333an_power(int why, void *arg)
334{
335	int s;
336	struct an_softc *sc = arg;
337	struct ifnet *ifp = &sc->sc_ic.ic_if;
338
339	s = splnet();
340	switch (why) {
341	case PWR_SUSPEND:
342	case PWR_STANDBY:
343		an_stop(ifp, 1);
344		break;
345	case PWR_RESUME:
346		if (ifp->if_flags & IFF_UP) {
347			an_init(ifp);
348			(void)an_intr(sc);
349		}
350		break;
351	case PWR_SOFTSUSPEND:
352	case PWR_SOFTSTANDBY:
353	case PWR_SOFTRESUME:
354		break;
355	}
356	splx(s);
357}
358
359void
360an_shutdown(struct an_softc *sc)
361{
362
363	if (sc->sc_attached)
364		an_stop(&sc->sc_ic.ic_if, 1);
365}
366
367int
368an_intr(void *arg)
369{
370	struct an_softc *sc = arg;
371	struct ifnet *ifp = &sc->sc_ic.ic_if;
372	int i;
373	u_int16_t status;
374
375	if (!sc->sc_enabled || sc->sc_invalid ||
376	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
377	    (ifp->if_flags & IFF_RUNNING) == 0)
378		return 0;
379
380	if ((ifp->if_flags & IFF_UP) == 0) {
381		CSR_WRITE_2(sc, AN_INT_EN, 0);
382		CSR_WRITE_2(sc, AN_EVENT_ACK, ~0);
383		return 1;
384	}
385
386	/* maximum 10 loops per interrupt */
387	for (i = 0; i < 10; i++) {
388		if (!sc->sc_enabled || sc->sc_invalid)
389			return 1;
390		if (CSR_READ_2(sc, AN_SW0) != AN_MAGIC) {
391			DPRINTF(("an_intr: magic number changed: %x\n",
392			    CSR_READ_2(sc, AN_SW0)));
393			sc->sc_invalid = 1;
394			return 1;
395		}
396		status = CSR_READ_2(sc, AN_EVENT_STAT);
397		CSR_WRITE_2(sc, AN_EVENT_ACK, status & ~(AN_INTRS));
398		if ((status & AN_INTRS) == 0)
399			break;
400
401		if (status & AN_EV_RX)
402			an_rx_intr(sc);
403
404		if (status & (AN_EV_TX | AN_EV_TX_EXC))
405			an_tx_intr(sc, status);
406
407		if (status & AN_EV_LINKSTAT)
408			an_linkstat_intr(sc);
409
410		if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
411		    sc->sc_ic.ic_state == IEEE80211_S_RUN &&
412		    !IFQ_IS_EMPTY(&ifp->if_snd))
413			an_start(ifp);
414	}
415
416	return 1;
417}
418
419static int
420an_init(struct ifnet *ifp)
421{
422	struct an_softc *sc = ifp->if_softc;
423	struct ieee80211com *ic = &sc->sc_ic;
424	int i, error, fid;
425
426	DPRINTF(("an_init: enabled %d\n", sc->sc_enabled));
427	if (!sc->sc_enabled) {
428		if (sc->sc_enable)
429			(*sc->sc_enable)(sc);
430		an_wait(sc);
431		sc->sc_enabled = 1;
432	} else {
433		an_stop(ifp, 0);
434		if ((error = an_reset(sc)) != 0) {
435			printf("%s: failed to reset\n", ifp->if_xname);
436			an_stop(ifp, 1);
437			return error;
438		}
439	}
440	CSR_WRITE_2(sc, AN_SW0, AN_MAGIC);
441
442	/* Allocate the TX buffers */
443	for (i = 0; i < AN_TX_RING_CNT; i++) {
444		if ((error = an_alloc_fid(sc, AN_TX_MAX_LEN, &fid)) != 0) {
445			printf("%s: failed to allocate nic memory\n",
446			    ifp->if_xname);
447			an_stop(ifp, 1);
448			return error;
449		}
450		DPRINTF2(("an_init: txbuf %d allocated %x\n", i, fid));
451		sc->sc_txd[i].d_fid = fid;
452		sc->sc_txd[i].d_inuse = 0;
453	}
454	sc->sc_txcur = sc->sc_txnext = 0;
455
456	IEEE80211_ADDR_COPY(sc->sc_config.an_macaddr, ic->ic_myaddr);
457	sc->sc_config.an_scanmode = htole16(AN_SCANMODE_ACTIVE);
458	sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_OPEN);	/*XXX*/
459	if (ic->ic_flags & IEEE80211_F_WEPON) {
460		sc->sc_config.an_authtype |=
461		    htole16(AN_AUTHTYPE_PRIVACY_IN_USE);
462		if (sc->sc_use_leap)
463			sc->sc_config.an_authtype |=
464			    htole16(AN_AUTHTYPE_LEAP);
465	}
466	sc->sc_config.an_listen_interval = htole16(ic->ic_lintval);
467	sc->sc_config.an_beacon_period = htole16(ic->ic_lintval);
468	if (ic->ic_flags & IEEE80211_F_PMGTON)
469		sc->sc_config.an_psave_mode = htole16(AN_PSAVE_PSP);
470	else
471		sc->sc_config.an_psave_mode = htole16(AN_PSAVE_CAM);
472	sc->sc_config.an_ds_channel =
473	    htole16(ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
474
475	switch (ic->ic_opmode) {
476	case IEEE80211_M_STA:
477		sc->sc_config.an_opmode =
478		    htole16(AN_OPMODE_INFRASTRUCTURE_STATION);
479		sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR);
480		break;
481	case IEEE80211_M_IBSS:
482		sc->sc_config.an_opmode = htole16(AN_OPMODE_IBSS_ADHOC);
483		sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR);
484		break;
485	case IEEE80211_M_MONITOR:
486		sc->sc_config.an_opmode =
487		    htole16(AN_OPMODE_INFRASTRUCTURE_STATION);
488		sc->sc_config.an_rxmode =
489		    htole16(AN_RXMODE_80211_MONITOR_ANYBSS);
490		sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_NONE);
491		if (ic->ic_flags & IEEE80211_F_WEPON)
492			sc->sc_config.an_authtype |=
493			    htole16(AN_AUTHTYPE_PRIVACY_IN_USE |
494		            AN_AUTHTYPE_ALLOW_UNENCRYPTED);
495		break;
496	default:
497		printf("%s: bad opmode %d\n", ifp->if_xname, ic->ic_opmode);
498		an_stop(ifp, 1);
499		return EIO;
500	}
501	sc->sc_config.an_rxmode |= htole16(AN_RXMODE_NO_8023_HEADER);
502
503	/* Set the ssid list */
504	memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_ssidlist));
505	sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid_len =
506	    htole16(ic->ic_des_esslen);
507	if (ic->ic_des_esslen)
508		memcpy(sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid,
509		    ic->ic_des_essid, ic->ic_des_esslen);
510	if (an_write_rid(sc, AN_RID_SSIDLIST, &sc->sc_buf,
511	    sizeof(sc->sc_buf.sc_ssidlist)) != 0) {
512		printf("%s: failed to write ssid list\n", ifp->if_xname);
513		an_stop(ifp, 1);
514		return error;
515	}
516
517	/* Set the AP list */
518	memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_aplist));
519	(void)an_write_rid(sc, AN_RID_APLIST, &sc->sc_buf,
520	    sizeof(sc->sc_buf.sc_aplist));
521
522	/* Set the encapsulation */
523	for (i = 0; i < AN_ENCAP_NENTS; i++) {
524		sc->sc_buf.sc_encap.an_entry[i].an_ethertype = htole16(0);
525		sc->sc_buf.sc_encap.an_entry[i].an_action =
526		    htole16(AN_RXENCAP_RFC1024 | AN_TXENCAP_RFC1024);
527	}
528	(void)an_write_rid(sc, AN_RID_ENCAP, &sc->sc_buf,
529	    sizeof(sc->sc_buf.sc_encap));
530
531	/* Set the WEP Keys */
532	if (ic->ic_flags & IEEE80211_F_WEPON)
533		an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->sc_wepkeys,
534		    sc->sc_tx_key);
535
536	/* Set the configuration */
537#ifdef AN_DEBUG
538	if (an_debug) {
539		printf("write config:\n");
540		for (i = 0; i < sizeof(sc->sc_config) / 2; i++)
541			printf(" %04x", ((u_int16_t *)&sc->sc_config)[i]);
542		printf("\n");
543	}
544#endif
545	if (an_write_rid(sc, AN_RID_GENCONFIG, &sc->sc_config,
546	    sizeof(sc->sc_config)) != 0) {
547		printf("%s: failed to write config\n", ifp->if_xname);
548		an_stop(ifp, 1);
549		return error;
550	}
551
552	/* Enable the MAC */
553	if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
554		printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname);
555		an_stop(ifp, 1);
556		return ENXIO;
557	}
558	if (ifp->if_flags & IFF_PROMISC)
559		an_cmd(sc, AN_CMD_SET_MODE, 0xffff);
560
561	ifp->if_flags |= IFF_RUNNING;
562	ifp->if_flags &= ~IFF_OACTIVE;
563	ic->ic_state = IEEE80211_S_INIT;
564	if (ic->ic_opmode == IEEE80211_M_MONITOR)
565		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
566
567	/* enable interrupts */
568	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
569	return 0;
570}
571
572void
573an_stop(struct ifnet *ifp, int disable)
574{
575	struct an_softc *sc = ifp->if_softc;
576	int i, s;
577
578	if (!sc->sc_enabled)
579		return;
580
581	DPRINTF(("an_stop: disable %d\n", disable));
582
583	s = splnet();
584	ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
585	if (!sc->sc_invalid) {
586		an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
587		CSR_WRITE_2(sc, AN_INT_EN, 0);
588		an_cmd(sc, AN_CMD_DISABLE, 0);
589
590		for (i = 0; i < AN_TX_RING_CNT; i++)
591			an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->sc_txd[i].d_fid);
592	}
593
594	sc->sc_tx_timer = 0;
595	ifp->if_timer = 0;
596	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
597
598	if (disable) {
599		if (sc->sc_disable)
600			(*sc->sc_disable)(sc);
601		sc->sc_enabled = 0;
602	}
603	splx(s);
604}
605
606static void
607an_start(struct ifnet *ifp)
608{
609	struct an_softc *sc = (struct an_softc *)ifp->if_softc;
610	struct ieee80211com *ic = &sc->sc_ic;
611	struct ieee80211_node *ni;
612	struct ieee80211_frame *wh;
613	struct an_txframe frmhdr;
614	struct mbuf *m;
615	u_int16_t len;
616	int cur, fid;
617
618	if (!sc->sc_enabled || sc->sc_invalid) {
619		DPRINTF(("an_start: noop: enabled %d invalid %d\n",
620		    sc->sc_enabled, sc->sc_invalid));
621		return;
622	}
623
624	memset(&frmhdr, 0, sizeof(frmhdr));
625	cur = sc->sc_txnext;
626	for (;;) {
627		if (ic->ic_state != IEEE80211_S_RUN) {
628			DPRINTF(("an_start: not running %d\n", ic->ic_state));
629			break;
630		}
631		IFQ_POLL(&ifp->if_snd, m);
632		if (m == NULL) {
633			DPRINTF2(("an_start: no pending mbuf\n"));
634			break;
635		}
636		if (sc->sc_txd[cur].d_inuse) {
637			DPRINTF2(("an_start: %x/%d busy\n",
638			    sc->sc_txd[cur].d_fid, cur));
639			ifp->if_flags |= IFF_OACTIVE;
640			break;
641		}
642		IFQ_DEQUEUE(&ifp->if_snd, m);
643		ifp->if_opackets++;
644#if NBPFILTER > 0
645		if (ifp->if_bpf)
646			bpf_mtap(ifp->if_bpf, m);
647#endif
648		if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) {
649			ifp->if_oerrors++;
650			continue;
651		}
652#if NBPFILTER > 0
653		if (ic->ic_rawbpf)
654			bpf_mtap(ic->ic_rawbpf, m);
655#endif
656
657		wh = mtod(m, struct ieee80211_frame *);
658		if (ic->ic_flags & IEEE80211_F_WEPON)
659			wh->i_fc[1] |= IEEE80211_FC1_WEP;
660		m_copydata(m, 0, sizeof(struct ieee80211_frame),
661		    (caddr_t)&frmhdr.an_whdr);
662
663		/* insert payload length in front of llc/snap */
664		len = htons(m->m_pkthdr.len - sizeof(struct ieee80211_frame));
665		m_adj(m, sizeof(struct ieee80211_frame) - sizeof(len));
666		if (mtod(m, u_long) & 0x01)
667			memcpy(mtod(m, caddr_t), &len, sizeof(len));
668		else
669			*mtod(m, u_int16_t *) = len;
670
671		/*
672		 * XXX Aironet firmware apparently convert the packet
673		 * with longer than 1500 bytes in length into LLC/SNAP.
674		 * If we have 1500 bytes in ethernet payload, it is
675		 * 1508 bytes including LLC/SNAP and will be inserted
676		 * additional LLC/SNAP header with 1501-1508 in its
677		 * ethertype !!
678		 * So we skip LLC/SNAP header and force firmware to
679		 * convert it to LLC/SNAP again.
680		 */
681		m_adj(m, sizeof(struct llc));
682
683		frmhdr.an_tx_ctl = htole16(AN_TXCTL_80211);
684		frmhdr.an_tx_payload_len = htole16(m->m_pkthdr.len);
685		frmhdr.an_gaplen = htole16(AN_TXGAP_802_11);
686
687		if (ic->ic_fixed_rate != -1)
688			frmhdr.an_tx_rate =
689			    ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
690			    ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
691		else
692			frmhdr.an_tx_rate = 0;
693
694#ifdef AN_DEBUG
695		if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) ==
696		    (IFF_DEBUG|IFF_LINK2)) {
697			ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr,
698			    sizeof(struct ieee80211_frame), -1, 0);
699			printf(" txctl 0x%x plen %u\n",
700			    le16toh(frmhdr.an_tx_ctl),
701			    le16toh(frmhdr.an_tx_payload_len));
702		}
703#endif
704		if (sizeof(frmhdr) + AN_TXGAP_802_11 + sizeof(len) +
705		    m->m_pkthdr.len > AN_TX_MAX_LEN) {
706			ifp->if_oerrors++;
707			m_freem(m);
708			continue;
709		}
710
711		fid = sc->sc_txd[cur].d_fid;
712		if (an_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
713			ifp->if_oerrors++;
714			m_freem(m);
715			continue;
716		}
717		/* dummy write to avoid seek. */
718		an_write_bap(sc, fid, -1, &frmhdr, AN_TXGAP_802_11);
719		an_mwrite_bap(sc, fid, -1, m, m->m_pkthdr.len);
720		m_freem(m);
721
722		DPRINTF2(("an_start: send %d byte via %x/%d\n",
723		    ntohs(len) + sizeof(struct ieee80211_frame),
724		    fid, cur));
725		sc->sc_txd[cur].d_inuse = 1;
726		if (an_cmd(sc, AN_CMD_TX, fid)) {
727			printf("%s: xmit failed\n", ifp->if_xname);
728			sc->sc_txd[cur].d_inuse = 0;
729			continue;
730		}
731		sc->sc_tx_timer = 5;
732		ifp->if_timer = 1;
733		AN_INC(cur, AN_TX_RING_CNT);
734		sc->sc_txnext = cur;
735	}
736}
737
738static int
739an_reset(struct an_softc *sc)
740{
741
742	DPRINTF(("an_reset\n"));
743
744	if (!sc->sc_enabled)
745		return ENXIO;
746
747	an_cmd(sc, AN_CMD_ENABLE, 0);
748	an_cmd(sc, AN_CMD_FW_RESTART, 0);
749	an_cmd(sc, AN_CMD_NOOP2, 0);
750
751	if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) {
752		printf("%s: reset failed\n", sc->sc_dev.dv_xname);
753		return ETIMEDOUT;
754	}
755
756	an_cmd(sc, AN_CMD_DISABLE, 0);
757	return 0;
758}
759
760static void
761an_watchdog(struct ifnet *ifp)
762{
763	struct an_softc *sc = ifp->if_softc;
764
765	if (!sc->sc_enabled)
766		return;
767
768	if (sc->sc_tx_timer) {
769		if (--sc->sc_tx_timer == 0) {
770			printf("%s: device timeout\n", ifp->if_xname);
771			ifp->if_oerrors++;
772			an_init(ifp);
773			return;
774		}
775		ifp->if_timer = 1;
776	}
777	ieee80211_watchdog(ifp);
778}
779
780static int
781an_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
782{
783	struct an_softc *sc = ifp->if_softc;
784	int s, error = 0;
785
786	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
787		return ENXIO;
788
789	s = splnet();
790
791	switch (command) {
792	case SIOCSIFFLAGS:
793		if (ifp->if_flags & IFF_UP) {
794			if (sc->sc_enabled) {
795				/*
796				 * To avoid rescanning another access point,
797				 * do not call an_init() here.  Instead, only
798				 * reflect promisc mode settings.
799				 */
800				error = an_cmd(sc, AN_CMD_SET_MODE,
801				    (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0);
802			} else
803				error = an_init(ifp);
804		} else if (sc->sc_enabled)
805			an_stop(ifp, 1);
806		break;
807	case SIOCADDMULTI:
808	case SIOCDELMULTI:
809		error = ether_ioctl(ifp, command, data);
810		if (error == ENETRESET) {
811			/* we don't have multicast filter. */
812			error = 0;
813		}
814		break;
815	case SIOCS80211NWKEY:
816		error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data);
817			break;
818	case SIOCG80211NWKEY:
819		error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data);
820		break;
821	default:
822		error = ieee80211_ioctl(ifp, command, data);
823		break;
824	}
825	if (error == ENETRESET) {
826		if (sc->sc_enabled)
827			error = an_init(ifp);
828		else
829			error = 0;
830	}
831	splx(s);
832	return error;
833}
834
835/* TBD factor with ieee80211_media_change */
836static int
837an_media_change(struct ifnet *ifp)
838{
839	struct an_softc *sc = ifp->if_softc;
840	struct ieee80211com *ic = &sc->sc_ic;
841	struct ifmedia_entry *ime;
842	enum ieee80211_opmode newmode;
843	int i, rate, error = 0;
844
845	ime = ic->ic_media.ifm_cur;
846	if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
847		i = -1;
848	} else {
849		struct ieee80211_rateset *rs =
850		    &ic->ic_sup_rates[IEEE80211_MODE_11B];
851		rate = ieee80211_media2rate(ime->ifm_media);
852		if (rate == 0)
853			return EINVAL;
854		for (i = 0; i < rs->rs_nrates; i++) {
855			if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
856				break;
857		}
858		if (i == rs->rs_nrates)
859			return EINVAL;
860	}
861	if (ic->ic_fixed_rate != i) {
862		ic->ic_fixed_rate = i;
863		error = ENETRESET;
864	}
865
866	if (ime->ifm_media & IFM_IEEE80211_ADHOC)
867		newmode = IEEE80211_M_IBSS;
868	else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
869		newmode = IEEE80211_M_HOSTAP;
870	else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
871		newmode = IEEE80211_M_MONITOR;
872	else
873		newmode = IEEE80211_M_STA;
874	if (ic->ic_opmode != newmode) {
875		ic->ic_opmode = newmode;
876		error = ENETRESET;
877	}
878	if (error == ENETRESET) {
879		if (sc->sc_enabled)
880			error = an_init(ifp);
881		else
882			error = 0;
883	}
884	ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media);
885
886	return error;
887}
888
889static void
890an_media_status(struct ifnet *ifp, struct ifmediareq *imr)
891{
892	struct an_softc *sc = ifp->if_softc;
893	struct ieee80211com *ic = &sc->sc_ic;
894	int rate, buflen;
895
896	if (sc->sc_enabled == 0) {
897		imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
898		imr->ifm_status = 0;
899		return;
900	}
901
902	imr->ifm_status = IFM_AVALID;
903	imr->ifm_active = IFM_IEEE80211;
904	if (ic->ic_state == IEEE80211_S_RUN)
905		imr->ifm_status |= IFM_ACTIVE;
906	buflen = sizeof(sc->sc_buf);
907	if (ic->ic_fixed_rate != -1)
908		rate = ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
909		    ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
910	else if (an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen) != 0)
911		rate = 0;
912	else
913		rate = le16toh(sc->sc_buf.sc_status.an_current_tx_rate);
914	imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
915	switch (ic->ic_opmode) {
916	case IEEE80211_M_STA:
917		break;
918	case IEEE80211_M_IBSS:
919		imr->ifm_active |= IFM_IEEE80211_ADHOC;
920		break;
921	case IEEE80211_M_HOSTAP:
922		imr->ifm_active |= IFM_IEEE80211_HOSTAP;
923		break;
924	case IEEE80211_M_MONITOR:
925		imr->ifm_active |= IFM_IEEE80211_MONITOR;
926		break;
927	default:
928		break;
929	}
930}
931
932static int
933an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
934{
935	int error;
936	struct ieee80211com *ic = &sc->sc_ic;
937	u_int16_t prevauth;
938
939	error = 0;
940	prevauth = sc->sc_config.an_authtype;
941
942	switch (nwkey->i_wepon) {
943	case IEEE80211_NWKEY_OPEN:
944		sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN;
945		ic->ic_flags &= ~IEEE80211_F_WEPON;
946		break;
947
948	case IEEE80211_NWKEY_WEP:
949	case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST:
950		error = an_set_nwkey_wep(sc, nwkey);
951		if (error == 0 || error == ENETRESET) {
952			sc->sc_config.an_authtype =
953			    AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE;
954			ic->ic_flags |= IEEE80211_F_WEPON;
955		}
956		break;
957
958	case IEEE80211_NWKEY_EAP:
959		error = an_set_nwkey_eap(sc, nwkey);
960		if (error == 0 || error == ENETRESET) {
961			sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN |
962			    AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP;
963			ic->ic_flags |= IEEE80211_F_WEPON;
964		}
965		break;
966	default:
967		error = EINVAL;
968		break;
969	}
970	if (error == 0 && prevauth != sc->sc_config.an_authtype)
971		error = ENETRESET;
972	return error;
973}
974
975static int
976an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
977{
978	int i, txkey, anysetkey, needreset, error;
979	struct an_wepkey keys[IEEE80211_WEP_NKID];
980
981	error = 0;
982	memset(keys, 0, sizeof(keys));
983	anysetkey = needreset = 0;
984
985	/* load argument and sanity check */
986	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
987		keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen;
988		if (keys[i].an_wep_keylen < 0)
989			continue;
990		if (keys[i].an_wep_keylen != 0 &&
991		    keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN)
992			return EINVAL;
993		if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key))
994			return EINVAL;
995		if ((error = copyin(nwkey->i_key[i].i_keydat,
996		    keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0)
997			return error;
998		anysetkey++;
999	}
1000	txkey = nwkey->i_defkid - 1;
1001	if (txkey >= 0) {
1002		if (txkey >= IEEE80211_WEP_NKID)
1003			return EINVAL;
1004		/* default key must have a valid value */
1005		if (keys[txkey].an_wep_keylen == 0 ||
1006		    (keys[txkey].an_wep_keylen < 0 &&
1007		    sc->sc_perskeylen[txkey] == 0))
1008			return EINVAL;
1009		anysetkey++;
1010	}
1011	DPRINTF(("an_set_nwkey_wep: %s: %sold(%d:%d,%d,%d,%d) "
1012	    "pers(%d:%d,%d,%d,%d) new(%d:%d,%d,%d,%d)\n",
1013	    sc->sc_dev.dv_xname,
1014	    ((nwkey->i_wepon & IEEE80211_NWKEY_PERSIST) ? "persist: " : ""),
1015	    sc->sc_tx_key,
1016	    sc->sc_wepkeys[0].an_wep_keylen, sc->sc_wepkeys[1].an_wep_keylen,
1017	    sc->sc_wepkeys[2].an_wep_keylen, sc->sc_wepkeys[3].an_wep_keylen,
1018	    sc->sc_tx_perskey,
1019	    sc->sc_perskeylen[0], sc->sc_perskeylen[1],
1020	    sc->sc_perskeylen[2], sc->sc_perskeylen[3],
1021	    txkey,
1022	    keys[0].an_wep_keylen, keys[1].an_wep_keylen,
1023	    keys[2].an_wep_keylen, keys[3].an_wep_keylen));
1024	if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) {
1025		/* set temporary keys */
1026		sc->sc_tx_key = txkey;
1027		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1028			if (keys[i].an_wep_keylen < 0)
1029				continue;
1030			memcpy(&sc->sc_wepkeys[i], &keys[i], sizeof(keys[i]));
1031		}
1032	} else {
1033		/* set persist keys */
1034		if (anysetkey) {
1035			/* prepare to write nvram */
1036			if (!sc->sc_enabled) {
1037				if (sc->sc_enable)
1038					(*sc->sc_enable)(sc);
1039				an_wait(sc);
1040				sc->sc_enabled = 1;
1041				error = an_write_wepkey(sc,
1042				    AN_RID_WEP_PERSISTENT, keys, txkey);
1043				if (sc->sc_disable)
1044					(*sc->sc_disable)(sc);
1045				sc->sc_enabled = 0;
1046			} else {
1047				an_cmd(sc, AN_CMD_DISABLE, 0);
1048				error = an_write_wepkey(sc,
1049				    AN_RID_WEP_PERSISTENT, keys, txkey);
1050				an_cmd(sc, AN_CMD_ENABLE, 0);
1051			}
1052			if (error)
1053				return error;
1054		}
1055		if (txkey >= 0)
1056			sc->sc_tx_perskey = txkey;
1057		if (sc->sc_tx_key >= 0) {
1058			sc->sc_tx_key = -1;
1059			needreset++;
1060		}
1061		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1062			if (sc->sc_wepkeys[i].an_wep_keylen >= 0) {
1063				memset(&sc->sc_wepkeys[i].an_wep_key, 0,
1064				    sizeof(sc->sc_wepkeys[i].an_wep_key));
1065				sc->sc_wepkeys[i].an_wep_keylen = -1;
1066				needreset++;
1067			}
1068			if (keys[i].an_wep_keylen >= 0)
1069				sc->sc_perskeylen[i] = keys[i].an_wep_keylen;
1070		}
1071	}
1072	if (needreset) {
1073		/* firmware restart to reload persistent key */
1074		an_reset(sc);
1075	}
1076	if (anysetkey || needreset)
1077		error = ENETRESET;
1078	return error;
1079}
1080
1081static int
1082an_set_nwkey_eap(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
1083{
1084	int i, error, len;
1085	struct ifnet *ifp = &sc->sc_ic.ic_if;
1086	struct an_rid_leapkey *key;
1087	u_int16_t unibuf[sizeof(key->an_key)];
1088	static const int leap_rid[] = { AN_RID_LEAP_PASS, AN_RID_LEAP_USER };
1089	MD4_CTX ctx;
1090
1091	error = 0;
1092
1093	if (nwkey->i_key[0].i_keydat == NULL &&
1094	    nwkey->i_key[1].i_keydat == NULL)
1095		return 0;
1096	if (!sc->sc_enabled)
1097		return ENXIO;
1098	an_cmd(sc, AN_CMD_DISABLE, 0);
1099	key = &sc->sc_buf.sc_leapkey;
1100	for (i = 0; i < 2; i++) {
1101		if (nwkey->i_key[i].i_keydat == NULL)
1102			continue;
1103		len = nwkey->i_key[i].i_keylen;
1104		if (len > sizeof(key->an_key))
1105			return EINVAL;
1106		memset(key, 0, sizeof(*key));
1107		key->an_key_len = htole16(len);
1108		if ((error = copyin(nwkey->i_key[i].i_keydat, key->an_key,
1109		    len)) != 0)
1110			return error;
1111		if (i == 1) {
1112			/*
1113			 * Cisco seems to use PasswordHash and PasswordHashHash
1114			 * in RFC-2759 (MS-CHAP-V2).
1115			 */
1116			memset(unibuf, 0, sizeof(unibuf));
1117			/* XXX: convert password to unicode */
1118			for (i = 0; i < len; i++)
1119				unibuf[i] = key->an_key[i];
1120			/* set PasswordHash */
1121			MD4Init(&ctx);
1122			MD4Update(&ctx, (u_int8_t *)unibuf, len * 2);
1123			MD4Final(key->an_key, &ctx);
1124			/* set PasswordHashHash */
1125			MD4Init(&ctx);
1126			MD4Update(&ctx, key->an_key, 16);
1127			MD4Final(key->an_key + 16, &ctx);
1128			key->an_key_len = htole16(32);
1129		}
1130		if ((error = an_write_rid(sc, leap_rid[i], key,
1131		    sizeof(*key))) != 0) {
1132			printf("%s: LEAP set failed\n", ifp->if_xname);
1133			return error;
1134		}
1135	}
1136	error = an_cmd(sc, AN_CMD_ENABLE, 0);
1137	if (error)
1138		printf("%s: an_set_nwkey: failed to enable MAC\n",
1139		    ifp->if_xname);
1140	else
1141		error = ENETRESET;
1142	return error;
1143}
1144
1145static int
1146an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
1147{
1148	int i, error;
1149
1150	error = 0;
1151	if (sc->sc_config.an_authtype & AN_AUTHTYPE_LEAP)
1152		nwkey->i_wepon = IEEE80211_NWKEY_EAP;
1153	else if (sc->sc_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
1154		nwkey->i_wepon = IEEE80211_NWKEY_WEP;
1155	else
1156		nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
1157	if (sc->sc_tx_key == -1)
1158		nwkey->i_defkid = sc->sc_tx_perskey + 1;
1159	else
1160		nwkey->i_defkid = sc->sc_tx_key + 1;
1161	if (nwkey->i_key[0].i_keydat == NULL)
1162		return 0;
1163	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1164		if (nwkey->i_key[i].i_keydat == NULL)
1165			continue;
1166		/* do not show any keys to non-root user */
1167		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
1168			break;
1169		nwkey->i_key[i].i_keylen = sc->sc_wepkeys[i].an_wep_keylen;
1170		if (nwkey->i_key[i].i_keylen < 0) {
1171			if (sc->sc_perskeylen[i] == 0)
1172				nwkey->i_key[i].i_keylen = 0;
1173			continue;
1174		}
1175		if ((error = copyout(sc->sc_wepkeys[i].an_wep_key,
1176		    nwkey->i_key[i].i_keydat,
1177		    sc->sc_wepkeys[i].an_wep_keylen)) != 0)
1178			break;
1179	}
1180	return error;
1181}
1182
1183static int
1184an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid)
1185{
1186	int i, error;
1187	struct an_rid_wepkey *akey;
1188
1189	error = 0;
1190	akey = &sc->sc_buf.sc_wepkey;
1191	memset(akey, 0, sizeof(struct an_rid_wepkey));
1192	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1193		if (keys[i].an_wep_keylen < 0 ||
1194		    keys[i].an_wep_keylen > sizeof(akey->an_key))
1195			continue;
1196		akey->an_key_len = htole16(keys[i].an_wep_keylen);
1197		akey->an_key_index = htole16(i);
1198		akey->an_mac_addr[0] = 1;	/* default mac */
1199		memcpy(akey->an_key, keys[i].an_wep_key, keys[i].an_wep_keylen);
1200		if ((error = an_write_rid(sc, type, akey, sizeof(*akey))) != 0)
1201			return error;
1202	}
1203	if (kid >= 0) {
1204		akey->an_key_index = htole16(0xffff);
1205		akey->an_mac_addr[0] = kid;
1206		akey->an_key_len = htole16(0);
1207		memset(akey->an_key, 0, sizeof(akey->an_key));
1208		error = an_write_rid(sc, type, akey, sizeof(*akey));
1209	}
1210	return error;
1211}
1212
1213
1214/*
1215 * Low level functions
1216 */
1217
1218static void
1219an_rx_intr(struct an_softc *sc)
1220{
1221	struct ieee80211com *ic = &sc->sc_ic;
1222	struct ifnet *ifp = &ic->ic_if;
1223	struct ieee80211_frame *wh;
1224	struct ieee80211_node *ni;
1225	struct an_rxframe frmhdr;
1226	struct mbuf *m;
1227	u_int16_t status;
1228	int fid, off, len;
1229
1230	fid = CSR_READ_2(sc, AN_RX_FID);
1231
1232	/* First read in the frame header */
1233	if (an_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
1234		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1235		ifp->if_ierrors++;
1236		DPRINTF(("an_rx_intr: read fid %x failed\n", fid));
1237		return;
1238	}
1239
1240#ifdef AN_DEBUG
1241	if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) {
1242		ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr,
1243		    sizeof(struct ieee80211_frame), frmhdr.an_rx_rate,
1244		    frmhdr.an_rx_signal_strength);
1245		printf(" time 0x%x status 0x%x plen %u chan %u"
1246		    " plcp %02x %02x %02x %02x gap %u\n",
1247		    le32toh(frmhdr.an_rx_time), le16toh(frmhdr.an_rx_status),
1248		    le16toh(frmhdr.an_rx_payload_len), frmhdr.an_rx_chan,
1249		    frmhdr.an_plcp_hdr[0], frmhdr.an_plcp_hdr[1],
1250		    frmhdr.an_plcp_hdr[2], frmhdr.an_plcp_hdr[3],
1251		    le16toh(frmhdr.an_gaplen));
1252	}
1253#endif
1254
1255	status = le16toh(frmhdr.an_rx_status);
1256	if ((status & AN_STAT_ERRSTAT) != 0 &&
1257	    ic->ic_opmode != IEEE80211_M_MONITOR) {
1258		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1259		ifp->if_ierrors++;
1260		DPRINTF(("an_rx_intr: fid %x status %x\n", fid, status));
1261		return;
1262	}
1263
1264	len = le16toh(frmhdr.an_rx_payload_len);
1265	off = ALIGN(sizeof(struct ieee80211_frame));
1266
1267	if (off + len > MCLBYTES) {
1268		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1269			CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1270			ifp->if_ierrors++;
1271			DPRINTF(("an_rx_intr: oversized packet %d\n", len));
1272			return;
1273		}
1274		len = 0;
1275	}
1276
1277	MGETHDR(m, M_DONTWAIT, MT_DATA);
1278	if (m == NULL) {
1279		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1280		ifp->if_ierrors++;
1281		DPRINTF(("an_rx_intr: MGET failed\n"));
1282		return;
1283	}
1284	if (off + len > MHLEN) {
1285		MCLGET(m, M_DONTWAIT);
1286		if ((m->m_flags & M_EXT) == 0) {
1287			CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1288			m_freem(m);
1289			ifp->if_ierrors++;
1290			DPRINTF(("an_rx_intr: MCLGET failed\n"));
1291			return;
1292		}
1293	}
1294	m->m_data += off - sizeof(struct ieee80211_frame);
1295
1296	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1297		/*
1298		 * The gap and the payload length should be skipped.
1299		 * Make dummy read to avoid seek.
1300		 */
1301		an_read_bap(sc, fid, -1, m->m_data,
1302		    le16toh(frmhdr.an_gaplen) + sizeof(u_int16_t));
1303#ifdef AN_DEBUG
1304		if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) ==
1305		    (IFF_DEBUG|IFF_LINK2)) {
1306			int i;
1307			printf(" gap&len");
1308			for (i = 0;
1309			    i < le16toh(frmhdr.an_gaplen) + sizeof(u_int16_t);
1310			    i++)
1311				printf(" %02x", mtod(m, u_int8_t *)[i]);
1312			printf("\n");
1313		}
1314#endif
1315	}
1316	memcpy(m->m_data, &frmhdr.an_whdr, sizeof(struct ieee80211_frame));
1317	an_read_bap(sc, fid, -1, m->m_data + sizeof(struct ieee80211_frame),
1318	    len);
1319	m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
1320	m->m_pkthdr.rcvif = ifp;
1321	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1322
1323	wh = mtod(m, struct ieee80211_frame *);
1324	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1325		/*
1326		 * WEP is decrypted by hardware. Clear WEP bit
1327		 * header for ieee80211_input().
1328		 */
1329		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1330	}
1331
1332	ni = ieee80211_find_rxnode(ic, wh);
1333	ieee80211_input(ifp, m, ni, frmhdr.an_rx_signal_strength,
1334	    le32toh(frmhdr.an_rx_time));
1335}
1336
1337static void
1338an_tx_intr(struct an_softc *sc, int status)
1339{
1340	struct ifnet *ifp = &sc->sc_ic.ic_if;
1341	int cur, fid;
1342
1343	sc->sc_tx_timer = 0;
1344	ifp->if_flags &= ~IFF_OACTIVE;
1345
1346	fid = CSR_READ_2(sc, AN_TX_CMP_FID);
1347	CSR_WRITE_2(sc, AN_EVENT_ACK, status & (AN_EV_TX | AN_EV_TX_EXC));
1348
1349	if (status & AN_EV_TX_EXC)
1350		ifp->if_oerrors++;
1351	else
1352		ifp->if_opackets++;
1353
1354	cur = sc->sc_txcur;
1355	if (sc->sc_txd[cur].d_fid == fid) {
1356		sc->sc_txd[cur].d_inuse = 0;
1357		DPRINTF2(("an_tx_intr: sent %x/%d\n", fid, cur));
1358		AN_INC(cur, AN_TX_RING_CNT);
1359		sc->sc_txcur = cur;
1360	} else {
1361		for (cur = 0; cur < AN_TX_RING_CNT; cur++) {
1362			if (fid == sc->sc_txd[cur].d_fid) {
1363				sc->sc_txd[cur].d_inuse = 0;
1364				break;
1365			}
1366		}
1367		if (ifp->if_flags & IFF_DEBUG)
1368			printf("%s: tx mismatch: "
1369			    "expected %x(%d), actual %x(%d)\n",
1370			    sc->sc_dev.dv_xname,
1371			    sc->sc_txd[sc->sc_txcur].d_fid, sc->sc_txcur,
1372			    fid, cur);
1373	}
1374
1375	return;
1376}
1377
1378static void
1379an_linkstat_intr(struct an_softc *sc)
1380{
1381	struct ieee80211com *ic = &sc->sc_ic;
1382	u_int16_t status;
1383
1384	status = CSR_READ_2(sc, AN_LINKSTAT);
1385	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
1386	DPRINTF(("an_linkstat_intr: status 0x%x\n", status));
1387
1388	if (status == AN_LINKSTAT_ASSOCIATED) {
1389		if (ic->ic_state != IEEE80211_S_RUN ||
1390		    ic->ic_opmode == IEEE80211_M_IBSS)
1391			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1392	} else {
1393		if (ic->ic_opmode == IEEE80211_M_STA)
1394			ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1395	}
1396}
1397
1398/* Must be called at proper protection level! */
1399static int
1400an_cmd(struct an_softc *sc, int cmd, int val)
1401{
1402	int i, status;
1403
1404	/* make sure that previous command completed */
1405	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
1406		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
1407			printf("%s: command 0x%x busy\n", sc->sc_dev.dv_xname,
1408			    CSR_READ_2(sc, AN_COMMAND));
1409		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
1410	}
1411
1412	CSR_WRITE_2(sc, AN_PARAM0, val);
1413	CSR_WRITE_2(sc, AN_PARAM1, 0);
1414	CSR_WRITE_2(sc, AN_PARAM2, 0);
1415	CSR_WRITE_2(sc, AN_COMMAND, cmd);
1416
1417	if (cmd == AN_CMD_FW_RESTART) {
1418		/* XXX: should sleep here */
1419		DELAY(100*1000);
1420	}
1421
1422	for (i = 0; i < AN_TIMEOUT; i++) {
1423		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
1424			break;
1425		DELAY(10);
1426	}
1427
1428	status = CSR_READ_2(sc, AN_STATUS);
1429
1430	/* clear stuck command busy if necessary */
1431	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)
1432		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
1433
1434	/* Ack the command */
1435	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
1436
1437	if (i == AN_TIMEOUT) {
1438		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
1439			printf("%s: command 0x%x param 0x%x timeout\n",
1440			    sc->sc_dev.dv_xname, cmd, val);
1441		return ETIMEDOUT;
1442	}
1443	if (status & AN_STAT_CMD_RESULT) {
1444		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
1445			printf("%s: command 0x%x param 0x%x status 0x%x "
1446			    "resp 0x%x 0x%x 0x%x\n",
1447			    sc->sc_dev.dv_xname, cmd, val, status,
1448			    CSR_READ_2(sc, AN_RESP0), CSR_READ_2(sc, AN_RESP1),
1449			    CSR_READ_2(sc, AN_RESP2));
1450		return EIO;
1451	}
1452
1453	return 0;
1454}
1455
1456
1457/*
1458 * Wait for firmware come up after power enabled.
1459 */
1460static void
1461an_wait(struct an_softc *sc)
1462{
1463	int i;
1464
1465	CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2);
1466	for (i = 0; i < 3*hz; i++) {
1467		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
1468			break;
1469		(void)tsleep(sc, PWAIT, "anatch", 1);
1470	}
1471	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
1472}
1473
1474static int
1475an_seek_bap(struct an_softc *sc, int id, int off)
1476{
1477	int i, status;
1478
1479	CSR_WRITE_2(sc, AN_SEL0, id);
1480	CSR_WRITE_2(sc, AN_OFF0, off);
1481
1482	for (i = 0; ; i++) {
1483		status = CSR_READ_2(sc, AN_OFF0);
1484		if ((status & AN_OFF_BUSY) == 0)
1485			break;
1486		if (i == AN_TIMEOUT) {
1487			printf("%s: timeout in an_seek_bap to 0x%x/0x%x\n",
1488			    sc->sc_dev.dv_xname, id, off);
1489			sc->sc_bap_off = AN_OFF_ERR;	/* invalidate */
1490			return ETIMEDOUT;
1491		}
1492		DELAY(10);
1493	}
1494	if (status & AN_OFF_ERR) {
1495		printf("%s: failed in an_seek_bap to 0x%x/0x%x\n",
1496		    sc->sc_dev.dv_xname, id, off);
1497		sc->sc_bap_off = AN_OFF_ERR;	/* invalidate */
1498		return EIO;
1499	}
1500	sc->sc_bap_id = id;
1501	sc->sc_bap_off = off;
1502	return 0;
1503}
1504
1505static int
1506an_read_bap(struct an_softc *sc, int id, int off, void *buf, int buflen)
1507{
1508	int error, cnt;
1509
1510	if (buflen == 0)
1511		return 0;
1512	if (off == -1)
1513		off = sc->sc_bap_off;
1514	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
1515		if ((error = an_seek_bap(sc, id, off)) != 0)
1516			return EIO;
1517	}
1518
1519	cnt = (buflen + 1) / 2;
1520	CSR_READ_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt);
1521	sc->sc_bap_off += cnt * 2;
1522	return 0;
1523}
1524
1525static int
1526an_write_bap(struct an_softc *sc, int id, int off, void *buf, int buflen)
1527{
1528	int error, cnt;
1529
1530	if (buflen == 0)
1531		return 0;
1532	if (off == -1)
1533		off = sc->sc_bap_off;
1534	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
1535		if ((error = an_seek_bap(sc, id, off)) != 0)
1536			return EIO;
1537	}
1538
1539	cnt = (buflen + 1) / 2;
1540	CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt);
1541	sc->sc_bap_off += cnt * 2;
1542	return 0;
1543}
1544
1545static int
1546an_mwrite_bap(struct an_softc *sc, int id, int off, struct mbuf *m, int totlen)
1547{
1548	int error, len, cnt;
1549
1550	if (off == -1)
1551		off = sc->sc_bap_off;
1552	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
1553		if ((error = an_seek_bap(sc, id, off)) != 0)
1554			return EIO;
1555	}
1556
1557	for (len = 0; m != NULL; m = m->m_next) {
1558		if (m->m_len == 0)
1559			continue;
1560		len = min(m->m_len, totlen);
1561
1562		if ((mtod(m, u_long) & 0x1) || (len & 0x1)) {
1563			m_copydata(m, 0, totlen, (caddr_t)&sc->sc_buf.sc_txbuf);
1564			cnt = (totlen + 1) / 2;
1565			CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0,
1566			    sc->sc_buf.sc_val, cnt);
1567			off += cnt * 2;
1568			break;
1569		}
1570		cnt = len / 2;
1571		CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, mtod(m, u_int16_t *),
1572		    cnt);
1573		off += len;
1574		totlen -= len;
1575	}
1576	sc->sc_bap_off = off;
1577	return 0;
1578}
1579
1580static int
1581an_alloc_fid(struct an_softc *sc, int len, int *idp)
1582{
1583	int i;
1584
1585	if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
1586		printf("%s: failed to allocate %d bytes on NIC\n",
1587		    sc->sc_dev.dv_xname, len);
1588		return ENOMEM;
1589	}
1590
1591	for (i = 0; i < AN_TIMEOUT; i++) {
1592		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
1593			break;
1594		if (i == AN_TIMEOUT) {
1595			printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
1596			return ETIMEDOUT;
1597		}
1598		DELAY(10);
1599	}
1600
1601	*idp = CSR_READ_2(sc, AN_ALLOC_FID);
1602	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
1603	return 0;
1604}
1605
1606static int
1607an_read_rid(struct an_softc *sc, int rid, void *buf, int *buflenp)
1608{
1609	int error;
1610	u_int16_t len;
1611
1612	/* Tell the NIC to enter record read mode. */
1613	error = an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_READ, rid);
1614	if (error)
1615		return error;
1616
1617	/* length in byte, including length itself */
1618	error = an_read_bap(sc, rid, 0, &len, sizeof(len));
1619	if (error)
1620		return error;
1621
1622	len = le16toh(len) - 2;
1623	if (*buflenp < len) {
1624		printf("%s: record buffer is too small, "
1625		    "rid=%x, size=%d, len=%d\n",
1626		    sc->sc_dev.dv_xname, rid, *buflenp, len);
1627		return ENOSPC;
1628	}
1629	*buflenp = len;
1630	return an_read_bap(sc, rid, sizeof(len), buf, len);
1631}
1632
1633static int
1634an_write_rid(struct an_softc *sc, int rid, void *buf, int buflen)
1635{
1636	int error;
1637	u_int16_t len;
1638
1639	/* length in byte, including length itself */
1640	len = htole16(buflen + 2);
1641
1642	error = an_write_bap(sc, rid, 0, &len, sizeof(len));
1643	if (error)
1644		return error;
1645	error = an_write_bap(sc, rid, sizeof(len), buf, buflen);
1646	if (error)
1647		return error;
1648
1649	return an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_WRITE, rid);
1650}
1651
1652static int
1653an_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1654{
1655	struct an_softc *sc = ic->ic_softc;
1656	struct ieee80211_node *ni = ic->ic_bss;
1657	enum ieee80211_state ostate;
1658	int buflen;
1659
1660	ostate = ic->ic_state;
1661	DPRINTF(("an_newstate: %s -> %s\n", ieee80211_state_name[ostate],
1662	    ieee80211_state_name[nstate]));
1663
1664	switch (nstate) {
1665	case IEEE80211_S_INIT:
1666		ic->ic_flags &= ~IEEE80211_F_IBSSON;
1667		return (*sc->sc_newstate)(ic, nstate, arg);
1668
1669	case IEEE80211_S_RUN:
1670		buflen = sizeof(sc->sc_buf);
1671		an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen);
1672		IEEE80211_ADDR_COPY(ni->ni_bssid,
1673		    sc->sc_buf.sc_status.an_cur_bssid);
1674		IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
1675		ni->ni_chan = &ic->ic_channels[
1676		    le16toh(sc->sc_buf.sc_status.an_cur_channel)];
1677		ni->ni_esslen = le16toh(sc->sc_buf.sc_status.an_ssidlen);
1678		if (ni->ni_esslen > IEEE80211_NWID_LEN)
1679			ni->ni_esslen = IEEE80211_NWID_LEN;	/*XXX*/
1680		memcpy(ni->ni_essid, sc->sc_buf.sc_status.an_ssid,
1681		    ni->ni_esslen);
1682		ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];	/*XXX*/
1683		if (ic->ic_if.if_flags & IFF_DEBUG) {
1684			printf("%s: ", sc->sc_dev.dv_xname);
1685			if (ic->ic_opmode == IEEE80211_M_STA)
1686				printf("associated ");
1687			else
1688				printf("synchronized ");
1689			printf("with %s ssid ", ether_sprintf(ni->ni_bssid));
1690			ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
1691			printf(" channel %u start %uMb\n",
1692			    le16toh(sc->sc_buf.sc_status.an_cur_channel),
1693			    le16toh(sc->sc_buf.sc_status.an_current_tx_rate)/2);
1694		}
1695		break;
1696
1697	default:
1698		break;
1699	}
1700	ic->ic_state = nstate;
1701	/* skip standard ieee80211 handling */
1702	return 0;
1703}
1704