an.c revision 1.24
1/*	$NetBSD: an.c,v 1.24 2003/01/31 00:26:27 thorpej 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 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form.
46 * This driver supports all three device types (PCI devices are supported
47 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be
48 * supported either using hard-coded IO port/IRQ settings or via Plug
49 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
50 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
51 *
52 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
53 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
54 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
55 * a couple of important differences though:
56 *
57 * - Lucent doesn't currently offer a PCI card, however Aironet does
58 * - Lucent ISA card looks to the host like a PCMCIA controller with
59 *   a PCMCIA WaveLAN card inserted. This means that even desktop
60 *   machines need to be configured with PCMCIA support in order to
61 *   use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
62 *   actually look like normal ISA and PCI devices to the host, so
63 *   no PCMCIA controller support is needed
64 *
65 * The latter point results in a small gotcha. The Aironet PCMCIA
66 * cards can be configured for one of two operating modes depending
67 * on how the Vpp1 and Vpp2 programming voltages are set when the
68 * card is activated. In order to put the card in proper PCMCIA
69 * operation (where the CIS table is visible and the interface is
70 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
71 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
72 * which leaves the card in ISA/PCI mode, which prevents it from
73 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c
74 * has to be patched slightly in order to enable the Vpp voltages in
75 * order to make the Aironet PCMCIA cards work.
76 *
77 * Note that some PCMCIA controller software packages for Windows NT
78 * fail to set the voltages as well.
79 *
80 * The Aironet devices can operate in both station mode and access point
81 * mode. Typically, when programmed for station mode, the card can be set
82 * to automatically perform encapsulation/decapsulation of Ethernet II
83 * and 802.3 frames within 802.11 frames so that the host doesn't have
84 * to do it itself. This driver doesn't program the card that way: the
85 * driver handles all of the encapsulation/decapsulation itself.
86 */
87
88/*
89 * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego
90 * IETF meeting.
91 */
92
93#include <sys/cdefs.h>
94__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.24 2003/01/31 00:26:27 thorpej Exp $");
95
96#include "opt_inet.h"
97#include "bpfilter.h"
98
99#ifdef INET
100/*
101 * It is designed for IPv4 only.
102 * no one use it and disabled for now. -- onoe
103 */
104#undef ANCACHE			/* enable signal strength cache */
105#endif
106
107#include <sys/param.h>
108#include <sys/callout.h>
109#include <sys/systm.h>
110#include <sys/sockio.h>
111#include <sys/mbuf.h>
112#include <sys/kernel.h>
113#include <sys/ucred.h>
114#include <sys/socket.h>
115#include <sys/device.h>
116#include <sys/proc.h>
117#include <sys/md4.h>
118#ifdef ANCACHE
119#include <sys/syslog.h>
120#include <sys/sysctl.h>
121#endif
122
123#include <machine/bus.h>
124
125#include <net/if.h>
126#include <net/if_arp.h>
127#include <net/if_dl.h>
128#include <net/if_ether.h>
129#include <net/if_ieee80211.h>
130#include <net/if_types.h>
131#include <net/if_media.h>
132
133#ifdef INET
134#include <netinet/in.h>
135#include <netinet/in_systm.h>
136#include <netinet/in_var.h>
137#include <netinet/ip.h>
138#endif
139
140#if NBPFILTER > 0
141#include <net/bpf.h>
142#endif
143
144#include <dev/ic/anreg.h>
145#include <dev/ic/anvar.h>
146
147/* These are global because we need them in sys/pci/if_an_p.c. */
148static void an_reset		__P((struct an_softc *));
149static void an_wait		__P((struct an_softc *));
150static int an_ioctl		__P((struct ifnet *, u_long, caddr_t));
151static int an_set_nwkey		__P((struct an_softc *,
152					struct ieee80211_nwkey *));
153static int an_set_nwkey_wep	__P((struct an_softc *,
154					struct ieee80211_nwkey *));
155static int an_set_nwkey_eap	__P((struct an_softc *,
156					struct ieee80211_nwkey *));
157static int an_get_nwkey		__P((struct an_softc *,
158					struct ieee80211_nwkey *));
159static int an_write_wepkey	__P((struct an_softc *sc, int type,
160					struct an_wepkey *keys, int kid));
161static int an_init		__P((struct ifnet *));
162static void an_stop		__P((struct ifnet *, int));
163static int an_init_tx_ring	__P((struct an_softc *));
164static void an_start		__P((struct ifnet *));
165static void an_watchdog		__P((struct ifnet *));
166static void an_rxeof		__P((struct an_softc *));
167static void an_txeof		__P((struct an_softc *, int));
168
169static int an_cmd		__P((struct an_softc *, int, int));
170static int an_read_record	__P((struct an_softc *, struct an_ltv_gen *));
171static int an_write_record	__P((struct an_softc *, struct an_ltv_gen *));
172static int an_read_data		__P((struct an_softc *, int,
173					int, caddr_t, int));
174static int an_write_data	__P((struct an_softc *, int,
175					int, caddr_t, int));
176static int an_seek		__P((struct an_softc *, int, int, int));
177static int an_alloc_nicmem	__P((struct an_softc *, int, int *));
178static void an_stats_update	__P((void *));
179static int an_setdef		__P((struct an_softc *, struct an_req *));
180#ifdef ANCACHE
181static void an_cache_store	__P((struct an_softc *, struct ether_header *,
182					struct mbuf *, unsigned short));
183#endif
184#ifdef IFM_IEEE80211
185static int an_media_change __P((struct ifnet *ifp));
186static void an_media_status __P((struct ifnet *ifp, struct ifmediareq *imr));
187#endif
188
189int
190an_attach(struct an_softc *sc)
191{
192	struct ifnet *ifp = &sc->arpcom.ec_if;
193	int i, s;
194	struct an_ltv_wepkey *akey;
195#ifdef IFM_IEEE80211
196	int mtype;
197	struct ifmediareq imr;
198#endif
199
200	s = splnet();
201	sc->an_associated = 0;
202	an_wait(sc);
203
204	/* Load factory config */
205	if (an_cmd(sc, AN_CMD_READCFG, 0)) {
206		splx(s);
207		aprint_error("%s: failed to load config data\n",
208		    sc->an_dev.dv_xname);
209		return(EIO);
210	}
211
212	/* Read the current configuration */
213	sc->an_config.an_type = AN_RID_GENCONFIG;
214	sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
215	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
216		splx(s);
217		aprint_error("%s: read record failed\n", sc->an_dev.dv_xname);
218		return(EIO);
219	}
220
221	/* Read the card capabilities */
222	sc->an_caps.an_type = AN_RID_CAPABILITIES;
223	sc->an_caps.an_len = sizeof(struct an_ltv_caps);
224	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
225		splx(s);
226		aprint_error("%s: read record failed\n", sc->an_dev.dv_xname);
227		return(EIO);
228	}
229
230	/* Read ssid list */
231	sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
232	sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
233	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
234		splx(s);
235		aprint_error("%s: read record failed\n", sc->an_dev.dv_xname);
236		return(EIO);
237	}
238
239	/* Read AP list */
240	sc->an_aplist.an_type = AN_RID_APLIST;
241	sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
242	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
243		splx(s);
244		aprint_error("%s: read record failed\n", sc->an_dev.dv_xname);
245		return(EIO);
246	}
247
248	/* Read WEP settings from persistent memory */
249	akey = (struct an_ltv_wepkey *)&sc->an_reqbuf;
250	akey->an_type = AN_RID_WEP_VOLATILE;
251	akey->an_len = sizeof(struct an_ltv_wepkey);
252	while (an_read_record(sc, (struct an_ltv_gen *)akey) == 0) {
253		if (akey->an_key_index == 0xffff) {
254			sc->an_tx_perskey = akey->an_mac_addr[0];
255			sc->an_tx_key = -1;
256			break;
257		}
258		if (akey->an_key_index >= IEEE80211_WEP_NKID)
259			break;
260		sc->an_perskeylen[akey->an_key_index] = akey->an_key_len;
261		sc->an_wepkeys[akey->an_key_index].an_wep_keylen = -1;
262		akey->an_type = AN_RID_WEP_PERSISTENT;	/* for next key */
263		akey->an_len = sizeof(*akey);
264	}
265	/* XXX not sure if persistent key settings should be printed here */
266
267	aprint_normal("%s: 802.11 address: %s\n", sc->an_dev.dv_xname,
268	    ether_sprintf(sc->an_caps.an_oemaddr));
269
270	ifp->if_softc = sc;
271	ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX |
272	    IFF_MULTICAST | IFF_ALLMULTI;
273	ifp->if_ioctl = an_ioctl;
274	ifp->if_start = an_start;
275	ifp->if_init = an_init;
276	ifp->if_stop = an_stop;
277	ifp->if_watchdog = an_watchdog;
278	IFQ_SET_READY(&ifp->if_snd);
279
280	memcpy(ifp->if_xname, sc->an_dev.dv_xname, IFNAMSIZ);
281
282	memset(sc->an_config.an_nodename, 0, sizeof(sc->an_config.an_nodename));
283	memcpy(sc->an_config.an_nodename, AN_DEFAULT_NODENAME,
284	    sizeof(AN_DEFAULT_NODENAME) - 1);
285
286	memset(sc->an_ssidlist.an_ssid1, 0, sizeof(sc->an_ssidlist.an_ssid1));
287	memcpy(sc->an_ssidlist.an_ssid1, AN_DEFAULT_NETNAME,
288	    sizeof(AN_DEFAULT_NETNAME) - 1);
289	sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME);
290
291	sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
292
293	sc->an_tx_rate = 0;
294#if 0
295	memset(&sc->an_stats, 0, sizeof(sc->an_stats));
296#endif
297
298	/*
299	 * Call MI attach routine.
300	 */
301	if_attach(ifp);
302	ether_ifattach(ifp, sc->an_caps.an_oemaddr);
303
304#ifdef IFM_IEEE80211
305	ifmedia_init(&sc->sc_media, 0, an_media_change, an_media_status);
306	ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
307	    0, 0), 0, NULL);
308	ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
309	    IFM_IEEE80211_ADHOC, 0), 0, NULL);
310	for (i = 0; i < sizeof(sc->an_caps.an_rates); i++) {
311		switch (sc->an_caps.an_rates[i]) {
312		case AN_RATE_1MBPS:
313			mtype = IFM_IEEE80211_DS1;
314			break;
315		case AN_RATE_2MBPS:
316			mtype = IFM_IEEE80211_DS2;
317			break;
318		case AN_RATE_5_5MBPS:
319			mtype = IFM_IEEE80211_DS5;
320			break;
321		case AN_RATE_11MBPS:
322			mtype = IFM_IEEE80211_DS11;
323			break;
324		default:
325			continue;
326		}
327		ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, mtype,
328		    0, 0), 0, NULL);
329		ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, mtype,
330		    IFM_IEEE80211_ADHOC, 0), 0, NULL);
331	}
332	an_media_status(ifp, &imr);
333	ifmedia_set(&sc->sc_media, imr.ifm_active);
334#endif
335	callout_init(&sc->an_stat_ch);
336	splx(s);
337
338	return(0);
339}
340
341int
342an_detach(struct an_softc *sc)
343{
344	struct ifnet *ifp = &sc->arpcom.ec_if;
345	int s;
346
347	s = splnet();
348	an_stop(ifp, 1);
349	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
350	ether_ifdetach(ifp);
351	if_detach(ifp);
352	splx(s);
353	return 0;
354}
355
356int
357an_activate(struct device *self, enum devact act)
358{
359	struct an_softc *sc = (struct an_softc *)self;
360	int s, error = 0;
361
362	s = splnet();
363	switch (act) {
364	case DVACT_ACTIVATE:
365		error = EOPNOTSUPP;
366		break;
367
368	case DVACT_DEACTIVATE:
369		if_deactivate(&sc->arpcom.ec_if);
370		break;
371	}
372	splx(s);
373
374	return error;
375}
376
377void
378an_power(int why, void *arg)
379{
380	int s;
381	struct an_softc *sc = arg;
382	struct ifnet *ifp = &sc->arpcom.ec_if;
383
384	s = splnet();
385	switch (why) {
386	case PWR_SUSPEND:
387	case PWR_STANDBY:
388		an_stop(ifp, 1);
389		break;
390	case PWR_RESUME:
391		if (ifp->if_flags & IFF_UP)
392			an_init(ifp);
393		break;
394	case PWR_SOFTSUSPEND:
395	case PWR_SOFTSTANDBY:
396	case PWR_SOFTRESUME:
397		break;
398	}
399	splx(s);
400}
401
402void
403an_shutdown(void *arg)
404{
405	struct an_softc *sc = arg;
406
407	an_stop(&sc->arpcom.ec_if, 1);
408	return;
409}
410
411static int
412an_setdef(struct an_softc *sc, struct an_req *areq)
413{
414	int error;
415	struct ifnet *ifp = &sc->arpcom.ec_if;
416	struct an_ltv_genconfig	*cfg;
417	struct an_ltv_gen *sp;
418
419	error = 0;
420
421	switch (areq->an_type) {
422	case AN_RID_GENCONFIG:
423		cfg = (struct an_ltv_genconfig *)areq;
424		memcpy(sc->an_caps.an_oemaddr, cfg->an_macaddr, ETHER_ADDR_LEN);
425		memcpy(LLADDR(ifp->if_sadl), cfg->an_macaddr, ETHER_ADDR_LEN);
426		memcpy(&sc->an_config, areq, sizeof(struct an_ltv_genconfig));
427		error = ENETRESET;
428		break;
429	case AN_RID_SSIDLIST:
430		memcpy(&sc->an_ssidlist, areq, sizeof(struct an_ltv_ssidlist));
431		error = ENETRESET;
432		break;
433	case AN_RID_APLIST:
434		memcpy(&sc->an_aplist, areq, sizeof(struct an_ltv_aplist));
435		error = ENETRESET;
436		break;
437	case AN_RID_TX_SPEED:
438		sp = (struct an_ltv_gen *)areq;
439		sc->an_tx_rate = sp->an_val;
440		break;
441	case AN_RID_WEP_VOLATILE:
442	case AN_RID_WEP_PERSISTENT:
443	case AN_RID_LEAP_USER:
444	case AN_RID_LEAP_PASS:
445		if (!sc->sc_enabled) {
446			error = ENXIO;
447			break;
448		}
449		an_cmd(sc, AN_CMD_DISABLE, 0);
450		an_write_record(sc, (struct an_ltv_gen *)areq);
451		if (an_cmd(sc, AN_CMD_ENABLE, 0))
452			error = EIO;
453		break;
454	default:
455		if (ifp->if_flags & IFF_DEBUG)
456			printf("%s: unknown RID: %x\n", sc->an_dev.dv_xname,
457			    areq->an_type);
458		error = EINVAL;
459		break;
460	}
461	return error;
462}
463
464static int
465an_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
466{
467	int s;
468	int error = 0;
469	struct an_softc *sc;
470	struct an_req *areq;
471	struct ifreq *ifr;
472	struct ieee80211_nwid nwid;
473	struct ieee80211_power *power;
474
475	sc = ifp->if_softc;
476	ifr = (struct ifreq *)data;
477	s = splnet();
478
479	switch (command) {
480	case SIOCSIFFLAGS:
481		if (ifp->if_flags & IFF_UP) {
482			if (sc->sc_enabled) {
483				/*
484				 * To avoid rescanning another access point,
485				 * do not call an_init() here.  Instead, only
486				 * reflect promisc mode settings.
487				 */
488				error = an_cmd(sc, AN_CMD_SET_MODE,
489				    (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0);
490			} else
491				error = an_init(ifp);
492		} else if (sc->sc_enabled)
493			an_stop(ifp, 1);
494		break;
495	case SIOCGAIRONET:
496		areq = &sc->an_reqbuf;
497		error = copyin(ifr->ifr_data, areq, sizeof(struct an_req));
498		if (error)
499			break;
500		switch (areq->an_type) {
501#ifdef ANCACHE
502		case AN_RID_ZERO_CACHE:
503			/* XXX suser()? -- should belong to SIOCSAIRONET */
504			sc->an_sigitems = sc->an_nextitem = 0;
505			goto out;
506		case AN_RID_READ_CACHE:
507			caddr_t pt = (char *)&areq->an_val;
508			memcpy(pt, &sc->an_sigitems, sizeof(int));
509			pt += sizeof(int);
510			areq->an_len = sizeof(int) / 2;
511			memcpy(pt, &sc->an_sigcache,
512			    sizeof(struct an_sigcache) * sc->an_sigitems);
513			areq->an_len += ((sizeof(struct an_sigcache) *
514			    sc->an_sigitems) / 2) + 1;
515			break;
516#endif
517		default:
518			if (an_read_record(sc, (struct an_ltv_gen *)areq)) {
519				error = EINVAL;
520				break;
521			}
522			break;
523		}
524		error = copyout(areq, ifr->ifr_data, sizeof(struct an_req));
525		break;
526	case SIOCSAIRONET:
527		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)))
528			break;
529		areq = &sc->an_reqbuf;
530		error = copyin(ifr->ifr_data, areq, sizeof(struct an_req));
531		if (error)
532			break;
533		error = an_setdef(sc, areq);
534		break;
535	case SIOCS80211NWID:
536		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
537		if (error)
538			break;
539		if (nwid.i_len > IEEE80211_NWID_LEN) {
540			error = EINVAL;
541			break;
542		}
543		if (sc->an_ssidlist.an_ssid1_len == nwid.i_len &&
544		    memcmp(sc->an_ssidlist.an_ssid1, nwid.i_nwid, nwid.i_len)
545		    == 0)
546			break;
547		memset(sc->an_ssidlist.an_ssid1, 0, IEEE80211_NWID_LEN);
548		sc->an_ssidlist.an_ssid1_len = nwid.i_len;
549		memcpy(sc->an_ssidlist.an_ssid1, nwid.i_nwid, nwid.i_len);
550		error = ENETRESET;
551		break;
552	case SIOCG80211NWID:
553		memset(&nwid, 0, sizeof(nwid));
554		if (sc->sc_enabled && sc->an_associated) {
555			nwid.i_len = sc->an_status.an_ssidlen;
556			memcpy(nwid.i_nwid, sc->an_status.an_ssid, nwid.i_len);
557		} else {
558			nwid.i_len = sc->an_ssidlist.an_ssid1_len;
559			memcpy(nwid.i_nwid, sc->an_ssidlist.an_ssid1,
560			    nwid.i_len);
561		}
562		error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
563		break;
564	case SIOCS80211NWKEY:
565		error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data);
566		break;
567	case SIOCG80211NWKEY:
568		error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data);
569		break;
570	case SIOCS80211POWER:
571		power = (struct ieee80211_power *)data;
572		sc->an_config.an_psave_mode = power->i_enabled ?
573		    AN_PSAVE_PSP : AN_PSAVE_NONE;
574		sc->an_config.an_listen_interval = power->i_maxsleep;
575		error = ENETRESET;
576		break;
577	case SIOCG80211POWER:
578		power = (struct ieee80211_power *)data;
579		power->i_enabled =
580		    sc->an_config.an_psave_mode != AN_PSAVE_NONE ? 1 : 0;
581		power->i_maxsleep = sc->an_config.an_listen_interval;
582		break;
583#ifdef IFM_IEEE80211
584	case SIOCSIFMEDIA:
585	case SIOCGIFMEDIA:
586		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
587		break;
588#endif
589	case SIOCADDMULTI:
590	case SIOCDELMULTI:
591		error = ether_ioctl(ifp, command, data);
592		if (error == ENETRESET) {
593			/* we don't have multicast filter. */
594			error = 0;
595		}
596		break;
597	default:
598		error = ether_ioctl(ifp, command, data);
599		break;
600	}
601	if (error == ENETRESET) {
602		if (sc->sc_enabled)
603			error = an_init(ifp);
604		else
605			error = 0;
606	}
607#ifdef ANCACHE
608out:
609#endif
610	splx(s);
611	return error;
612}
613
614static int
615an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
616{
617	int error;
618	u_int16_t prevauth;
619
620	error = 0;
621	prevauth = sc->an_config.an_authtype;
622
623	switch (nwkey->i_wepon) {
624	case IEEE80211_NWKEY_OPEN:
625		sc->an_config.an_authtype = AN_AUTHTYPE_OPEN;
626		break;
627
628	case IEEE80211_NWKEY_WEP:
629	case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST:
630		error = an_set_nwkey_wep(sc, nwkey);
631		if (error == 0 || error == ENETRESET)
632			sc->an_config.an_authtype =
633			    AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE;
634		break;
635
636	case IEEE80211_NWKEY_EAP:
637		error = an_set_nwkey_eap(sc, nwkey);
638		if (error == 0 || error == ENETRESET)
639			sc->an_config.an_authtype = AN_AUTHTYPE_OPEN |
640			    AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP;
641		break;
642	default:
643		error = EINVAL;
644		break;
645	}
646	if (error == 0 && prevauth != sc->an_config.an_authtype)
647		error = ENETRESET;
648	return error;
649}
650
651static int
652an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
653{
654	int i, txkey, anysetkey, needreset, error;
655	struct an_wepkey keys[IEEE80211_WEP_NKID];
656
657	error = 0;
658	memset(keys, 0, sizeof(keys));
659	anysetkey = needreset = 0;
660
661	/* load argument and sanity check */
662	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
663		keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen;
664		if (keys[i].an_wep_keylen < 0)
665			continue;
666		if (keys[i].an_wep_keylen != 0 &&
667		    keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN)
668			return EINVAL;
669		if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key))
670			return EINVAL;
671		if ((error = copyin(nwkey->i_key[i].i_keydat,
672		    keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0)
673			return error;
674		anysetkey++;
675	}
676	txkey = nwkey->i_defkid - 1;
677	if (txkey >= 0) {
678		if (txkey >= IEEE80211_WEP_NKID)
679			return EINVAL;
680		/* default key must have a valid value */
681		if (keys[txkey].an_wep_keylen == 0 ||
682		    (keys[txkey].an_wep_keylen < 0 &&
683		    sc->an_perskeylen[txkey] == 0))
684			return EINVAL;
685		anysetkey++;
686	}
687	if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) {
688		/* set temporary keys */
689		sc->an_tx_key = txkey;
690		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
691			if (keys[i].an_wep_keylen < 0)
692				continue;
693			memcpy(&sc->an_wepkeys[i], &keys[i], sizeof(keys[i]));
694		}
695	} else {
696		/* set persist keys */
697		if (anysetkey) {
698			/* prepare to write nvram */
699			if (!sc->sc_enabled) {
700				if (sc->sc_enable)
701					(*sc->sc_enable)(sc);
702				an_wait(sc);
703				sc->sc_enabled = 1;
704				error = an_write_wepkey(sc,
705				    AN_RID_WEP_PERSISTENT, keys, txkey);
706				if (sc->sc_disable)
707					(*sc->sc_disable)(sc);
708				sc->sc_enabled = 0;
709			} else {
710				an_cmd(sc, AN_CMD_DISABLE, 0);
711				error = an_write_wepkey(sc,
712				    AN_RID_WEP_PERSISTENT, keys, txkey);
713				an_cmd(sc, AN_CMD_ENABLE, 0);
714			}
715			if (error)
716				return error;
717		}
718		if (txkey >= 0)
719			sc->an_tx_perskey = txkey;
720		if (sc->an_tx_key >= 0) {
721			sc->an_tx_key = -1;
722			needreset++;
723		}
724		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
725			if (sc->an_wepkeys[i].an_wep_keylen >= 0) {
726				memset(&sc->an_wepkeys[i].an_wep_key, 0,
727				    sizeof(sc->an_wepkeys[i].an_wep_key));
728				sc->an_wepkeys[i].an_wep_keylen = -1;
729				needreset++;
730			}
731			if (keys[i].an_wep_keylen >= 0)
732				sc->an_perskeylen[i] = keys[i].an_wep_keylen;
733		}
734	}
735	if (needreset) {
736		/* firmware restart to reload persistent key */
737		an_reset(sc);
738	}
739	if (anysetkey || needreset)
740		error = ENETRESET;
741	return error;
742}
743
744static int
745an_set_nwkey_eap(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
746{
747	int i, error;
748	struct an_ltv_leapkey *key;
749	u_int16_t unibuf[sizeof(key->an_key)];
750	MD4_CTX ctx;
751
752	error = 0;
753
754	if (nwkey->i_key[0].i_keydat == NULL &&
755	    nwkey->i_key[1].i_keydat == NULL)
756		return 0;
757	if (!sc->sc_enabled)
758		return ENXIO;
759	an_cmd(sc, AN_CMD_DISABLE, 0);
760	key = (struct an_ltv_leapkey *)&sc->an_reqbuf;
761	if (nwkey->i_key[0].i_keydat != NULL) {
762		memset(key, 0, sizeof(*key));
763		key->an_type = AN_RID_LEAP_USER;
764		key->an_len = sizeof(*key);
765		key->an_key_len = nwkey->i_key[0].i_keylen;
766		if (key->an_key_len > sizeof(key->an_key))
767			return EINVAL;
768		if ((error = copyin(nwkey->i_key[0].i_keydat, key->an_key,
769		    key->an_key_len)) != 0)
770			return error;
771		an_write_record(sc, (struct an_ltv_gen *)key);
772	}
773	if (nwkey->i_key[1].i_keydat != NULL) {
774		memset(key, 0, sizeof(*key));
775		key->an_type = AN_RID_LEAP_PASS;
776		key->an_len = sizeof(*key);
777		key->an_key_len = nwkey->i_key[1].i_keylen;
778		if (key->an_key_len > sizeof(key->an_key))
779			return EINVAL;
780		if ((error = copyin(nwkey->i_key[1].i_keydat, key->an_key,
781		    key->an_key_len)) != 0)
782			return error;
783		/*
784		 * Cisco seems to use PasswordHash and PasswordHashHash
785		 * in RFC-2759 (MS-CHAP-V2).
786		 */
787		memset(unibuf, 0, sizeof(unibuf));
788		/* XXX: convert password to unicode */
789		for (i = 0; i < key->an_key_len; i++)
790			unibuf[i] = key->an_key[i];
791		/* set PasswordHash */
792		MD4Init(&ctx);
793		MD4Update(&ctx, (u_int8_t *)unibuf, key->an_key_len * 2);
794		MD4Final(key->an_key, &ctx);
795		/* set PasswordHashHash */
796		MD4Init(&ctx);
797		MD4Update(&ctx, key->an_key, 16);
798		MD4Final(key->an_key + 16, &ctx);
799		key->an_key_len = 32;
800		an_write_record(sc, (struct an_ltv_gen *)key);
801	}
802	error = an_cmd(sc, AN_CMD_ENABLE, 0);
803	if (error)
804		printf("%s: an_set_nwkey: failed to enable MAC\n",
805		    sc->an_dev.dv_xname);
806	else
807		error = ENETRESET;
808	return error;
809}
810
811static int
812an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
813{
814	int i, error;
815
816	error = 0;
817	if (sc->an_config.an_authtype & AN_AUTHTYPE_LEAP)
818		nwkey->i_wepon = IEEE80211_NWKEY_EAP;
819	else if (sc->an_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
820		nwkey->i_wepon = IEEE80211_NWKEY_WEP;
821	else
822		nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
823	if (sc->an_tx_key == -1)
824		nwkey->i_defkid = sc->an_tx_perskey + 1;
825	else
826		nwkey->i_defkid = sc->an_tx_key + 1;
827	if (nwkey->i_key[0].i_keydat == NULL)
828		return 0;
829	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
830		if (nwkey->i_key[i].i_keydat == NULL)
831			continue;
832		/* do not show any keys to non-root user */
833		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
834			break;
835		nwkey->i_key[i].i_keylen = sc->an_wepkeys[i].an_wep_keylen;
836		if (nwkey->i_key[i].i_keylen < 0) {
837			if (sc->an_perskeylen[i] == 0)
838				nwkey->i_key[i].i_keylen = 0;
839			continue;
840		}
841		if ((error = copyout(sc->an_wepkeys[i].an_wep_key,
842		    nwkey->i_key[i].i_keydat,
843		    sc->an_wepkeys[i].an_wep_keylen)) != 0)
844			break;
845	}
846	return error;
847}
848
849static int
850an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid)
851{
852	int i, error;
853	struct an_ltv_wepkey	*akey;
854
855	error = 0;
856	akey = (struct an_ltv_wepkey *)&sc->an_reqbuf;
857	memset(akey, 0, sizeof(struct an_ltv_wepkey));
858	akey->an_type = type;
859	akey->an_len = sizeof(struct an_ltv_wepkey);
860	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
861		if (keys[i].an_wep_keylen < 0 ||
862		    keys[i].an_wep_keylen > sizeof(akey->an_key))
863			continue;
864		akey->an_key_len = keys[i].an_wep_keylen;
865		akey->an_key_index = i;
866		akey->an_mac_addr[0] = 1;	/* default mac */
867		memcpy(akey->an_key, keys[i].an_wep_key, akey->an_key_len);
868		error = an_write_record(sc, (struct an_ltv_gen *)akey);
869		if (error)
870			return error;
871	}
872	if (kid >= 0) {
873		akey->an_key_index = 0xffff;
874		akey->an_mac_addr[0] = kid;
875		akey->an_key_len = 0;
876		memset(akey->an_key, 0, sizeof(akey->an_key));
877		error = an_write_record(sc, (struct an_ltv_gen *)akey);
878	}
879	return error;
880}
881
882#ifdef IFM_IEEE80211
883static int
884an_media_change(struct ifnet *ifp)
885{
886	struct an_softc *sc = ifp->if_softc;
887	struct ifmedia_entry *ime;
888	int error;
889
890	error = 0;
891	ime = sc->sc_media.ifm_cur;
892	switch (IFM_SUBTYPE(ime->ifm_media)) {
893	case IFM_AUTO:
894		sc->an_tx_rate = 0;
895		break;
896	case IFM_IEEE80211_DS1:
897		sc->an_tx_rate = AN_RATE_1MBPS;
898		break;
899	case IFM_IEEE80211_DS2:
900		sc->an_tx_rate = AN_RATE_2MBPS;
901		break;
902	case IFM_IEEE80211_DS5:
903		sc->an_tx_rate = AN_RATE_5_5MBPS;
904		break;
905	case IFM_IEEE80211_DS11:
906		sc->an_tx_rate = AN_RATE_11MBPS;
907		break;
908	}
909	if (ime->ifm_media & IFM_IEEE80211_ADHOC)
910		sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
911	else
912		sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
913	/*
914	 * XXX: how to set txrate for the firmware?
915	 * There is a struct defined as an_txframe, which is used nowhere.
916	 * Perhaps we need to change the transmit mode from 802.3 to native.
917	 */
918
919	/* we cannot return ENETRESET here */
920	if (sc->sc_enabled)
921		error = an_init(ifp);
922	return error;
923}
924
925static void
926an_media_status(ifp, imr)
927	struct ifnet *ifp;
928	struct ifmediareq *imr;
929{
930	struct an_softc *sc = ifp->if_softc;
931
932	imr->ifm_status = IFM_AVALID;
933	imr->ifm_active = IFM_IEEE80211;
934	if (sc->sc_enabled && sc->an_associated) {
935		imr->ifm_status |= IFM_ACTIVE;
936		switch (sc->an_status.an_current_tx_rate) {
937		case 0:
938			imr->ifm_active |= IFM_AUTO;
939			break;
940		case AN_RATE_1MBPS:
941			imr->ifm_active |= IFM_IEEE80211_DS1;
942			break;
943		case AN_RATE_2MBPS:
944			imr->ifm_active |= IFM_IEEE80211_DS2;
945			break;
946		case AN_RATE_5_5MBPS:
947			imr->ifm_active |= IFM_IEEE80211_DS5;
948			break;
949		case AN_RATE_11MBPS:
950			imr->ifm_active |= IFM_IEEE80211_DS11;
951			break;
952		}
953	}
954	if ((sc->an_config.an_opmode & 0x0f) == AN_OPMODE_IBSS_ADHOC)
955		imr->ifm_active |= IFM_IEEE80211_ADHOC;
956}
957#endif /* IFM_IEEE80211 */
958
959static int
960an_init_tx_ring(struct an_softc *sc)
961{
962	int i, id;
963
964	for (i = 0; i < AN_TX_RING_CNT; i++) {
965		if (an_alloc_nicmem(sc,
966		    ETHER_MAX_LEN + ETHER_TYPE_LEN + AN_802_11_OFFSET, &id))
967			return ENOMEM;
968		sc->an_rdata.an_tx_fids[i] = id;
969		sc->an_rdata.an_tx_ring[i] = 0;
970	}
971
972	sc->an_rdata.an_tx_prod = 0;
973	sc->an_rdata.an_tx_cons = 0;
974	return 0;
975}
976
977static int
978an_init(struct ifnet *ifp)
979{
980	struct an_softc *sc = (struct an_softc *)ifp->if_softc;
981
982	if (sc->sc_enabled) {
983		an_stop(ifp, 0);
984	} else {
985		if (sc->sc_enable)
986			(*sc->sc_enable)(sc);
987		sc->sc_enabled = 1;
988		an_wait(sc);
989	}
990
991	sc->an_associated = 0;
992
993	/* Allocate the TX buffers */
994	if (an_init_tx_ring(sc)) {
995		an_reset(sc);
996		if (an_init_tx_ring(sc)) {
997			printf("%s: tx buffer allocation failed\n",
998			    sc->an_dev.dv_xname);
999			an_stop(ifp, 1);
1000			return ENOMEM;
1001		}
1002	}
1003
1004	/* Set our MAC address. */
1005	memcpy(sc->an_config.an_macaddr, sc->an_caps.an_oemaddr,
1006	    ETHER_ADDR_LEN);
1007
1008	if (ifp->if_flags & IFF_MULTICAST)
1009		sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
1010	else if (ifp->if_flags & IFF_BROADCAST)
1011		sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
1012	else
1013		sc->an_config.an_rxmode = AN_RXMODE_ADDR;
1014
1015	/* Set the ssid list */
1016	sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
1017	sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
1018	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
1019		printf("%s: failed to set ssid list\n", sc->an_dev.dv_xname);
1020		an_stop(ifp, 1);
1021		return ENXIO;
1022	}
1023
1024	/* Set the AP list */
1025	sc->an_aplist.an_type = AN_RID_APLIST;
1026	sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
1027	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
1028		printf("%s: failed to set AP list\n", sc->an_dev.dv_xname);
1029		an_stop(ifp, 1);
1030		return ENXIO;
1031	}
1032
1033	/* Set the configuration in the NIC */
1034	sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
1035	sc->an_config.an_type = AN_RID_GENCONFIG;
1036	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
1037		printf("%s: failed to set configuration\n", sc->an_dev.dv_xname);
1038		an_stop(ifp, 1);
1039		return ENXIO;
1040	}
1041
1042	/* Set the WEP Keys */
1043	if ((sc->an_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) != 0)
1044		an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->an_wepkeys,
1045		    sc->an_tx_key);
1046
1047	/* Enable the MAC */
1048	if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
1049		printf("%s: failed to enable MAC\n", sc->an_dev.dv_xname);
1050		an_stop(ifp, 1);
1051		return ENXIO;
1052	}
1053
1054	an_cmd(sc, AN_CMD_SET_MODE, (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0);
1055
1056	/* enable interrupts */
1057	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
1058
1059	ifp->if_flags |= IFF_RUNNING;
1060	ifp->if_flags &= ~IFF_OACTIVE;
1061
1062	callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc);
1063	return 0;
1064}
1065
1066static void
1067an_start(struct ifnet *ifp)
1068{
1069	struct an_softc *sc = (struct an_softc *)ifp->if_softc;
1070	struct mbuf *m0 = NULL, *m;
1071	struct an_txframe_802_3 tx_frame_802_3;
1072	struct ether_header *eh;
1073	int id, idx;
1074	u_int16_t txctl;
1075
1076	if (!sc->sc_enabled)
1077		return;
1078
1079	if (ifp->if_flags & IFF_OACTIVE)
1080		return;
1081
1082	if (!sc->an_associated)
1083		return;
1084
1085	idx = sc->an_rdata.an_tx_prod;
1086	memset(&tx_frame_802_3, 0, sizeof(tx_frame_802_3));
1087
1088	for (;;) {
1089		IFQ_POLL(&ifp->if_snd, m0);
1090		if (m0 == NULL)
1091			break;
1092		if (sc->an_rdata.an_tx_ring[idx] != 0)
1093			break;
1094		id = sc->an_rdata.an_tx_fids[idx];
1095		IFQ_DEQUEUE(&ifp->if_snd, m0);
1096#if NBPFILTER > 0
1097		/*
1098		 * If there's a BPF listner, bounce a copy of
1099		 * this frame to him.
1100		 */
1101		if (ifp->if_bpf)
1102			bpf_mtap(ifp->if_bpf, m0);
1103#endif
1104
1105		txctl = AN_TXCTL_8023;
1106		/* write the txctl only */
1107		an_write_data(sc, id, 0x08, (caddr_t)&txctl, sizeof(txctl));
1108
1109		eh = mtod(m0, struct ether_header *);
1110		memcpy(tx_frame_802_3.an_tx_dst_addr, eh->ether_dhost,
1111		    ETHER_ADDR_LEN);
1112		memcpy(tx_frame_802_3.an_tx_src_addr, eh->ether_shost,
1113		    ETHER_ADDR_LEN);
1114		tx_frame_802_3.an_tx_802_3_payload_len =
1115		    m0->m_pkthdr.len - ETHER_ADDR_LEN * 2;
1116		m_adj(m0, ETHER_ADDR_LEN * 2);
1117
1118		/* 802_3 header */
1119		an_write_data(sc, id, AN_802_3_OFFSET,
1120		    (caddr_t)&tx_frame_802_3, sizeof(struct an_txframe_802_3));
1121		for (m = m0; m != NULL; m = m->m_next)
1122			an_write_data(sc, id, -1, mtod(m, caddr_t), m->m_len);
1123		m_freem(m0);
1124		m0 = NULL;
1125
1126		sc->an_rdata.an_tx_ring[idx] = id;
1127		if (an_cmd(sc, AN_CMD_TX, id))
1128			printf("%s: xmit failed\n", sc->an_dev.dv_xname);
1129
1130		AN_INC(idx, AN_TX_RING_CNT);
1131	}
1132
1133	if (m0 != NULL)
1134		ifp->if_flags |= IFF_OACTIVE;
1135
1136	sc->an_rdata.an_tx_prod = idx;
1137
1138	/*
1139	 * Set a timeout in case the chip goes out to lunch.
1140	 */
1141	ifp->if_timer = 5;
1142}
1143
1144void
1145an_stop(struct ifnet *ifp, int disable)
1146{
1147	struct an_softc *sc = (struct an_softc *)ifp->if_softc;
1148	int i;
1149
1150	callout_stop(&sc->an_stat_ch);
1151
1152	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1153	ifp->if_timer = 0;
1154
1155	if (!sc->sc_enabled)
1156		return;
1157
1158	an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
1159	CSR_WRITE_2(sc, AN_INT_EN, 0);
1160	an_cmd(sc, AN_CMD_DISABLE, 0);
1161
1162	for (i = 0; i < AN_TX_RING_CNT; i++)
1163		an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
1164
1165	if (disable) {
1166		if (sc->sc_disable)
1167			(*sc->sc_disable)(sc);
1168		sc->sc_enabled = 0;
1169	}
1170}
1171
1172static void
1173an_watchdog(struct ifnet *ifp)
1174{
1175	struct an_softc *sc;
1176
1177	sc = ifp->if_softc;
1178	if (!sc->sc_enabled)
1179		return;
1180
1181	printf("%s: device timeout\n", sc->an_dev.dv_xname);
1182
1183	an_reset(sc);
1184	an_init(ifp);
1185
1186	ifp->if_oerrors++;
1187	return;
1188}
1189
1190/*
1191 * Low level functions
1192 */
1193
1194static void
1195an_rxeof(struct an_softc *sc)
1196{
1197	struct ifnet *ifp = &sc->arpcom.ec_if;
1198	struct ether_header *eh;
1199#ifdef ANCACHE
1200	struct an_rxframe rx_frame;
1201#endif
1202	struct an_rxframe_802_3	rx_frame_802_3;
1203	struct mbuf *m;
1204	int id, error = 0;
1205
1206
1207	id = CSR_READ_2(sc, AN_RX_FID);
1208
1209	MGETHDR(m, M_DONTWAIT, MT_DATA);
1210	if (m == NULL) {
1211		ifp->if_ierrors++;
1212		return;
1213	}
1214	MCLGET(m, M_DONTWAIT);
1215	if (!(m->m_flags & M_EXT)) {
1216		m_freem(m);
1217		ifp->if_ierrors++;
1218		return;
1219	}
1220
1221	m->m_pkthdr.rcvif = ifp;
1222
1223	/* Align the data after the ethernet header */
1224	m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header)) -
1225	    sizeof(struct ether_header);
1226
1227	eh = mtod(m, struct ether_header *);
1228
1229#ifdef ANCACHE
1230	/* Read NIC frame header */
1231	if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
1232		ifp->if_ierrors++;
1233		return;
1234	}
1235#endif
1236	/* Read in the 802_3 frame header */
1237	if (an_read_data(sc, id, AN_802_3_OFFSET, (caddr_t)&rx_frame_802_3,
1238	    sizeof(rx_frame_802_3))) {
1239		ifp->if_ierrors++;
1240		return;
1241	}
1242
1243	if (rx_frame_802_3.an_rx_802_3_status != 0) {
1244		ifp->if_ierrors++;
1245		return;
1246	}
1247
1248	/* Check for insane frame length */
1249	if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) {
1250		ifp->if_ierrors++;
1251		return;
1252	}
1253
1254	m->m_pkthdr.len = m->m_len =
1255	    rx_frame_802_3.an_rx_802_3_payload_len + ETHER_ADDR_LEN * 2;
1256
1257	memcpy(&eh->ether_dhost, &rx_frame_802_3.an_rx_dst_addr,
1258	    ETHER_ADDR_LEN);
1259	memcpy(&eh->ether_shost, &rx_frame_802_3.an_rx_src_addr,
1260	    ETHER_ADDR_LEN);
1261
1262	/* in mbuf header type is just before payload */
1263	error = an_read_data(sc, id, -1, (caddr_t)&(eh->ether_type),
1264	     rx_frame_802_3.an_rx_802_3_payload_len);
1265
1266	if (error) {
1267		m_freem(m);
1268		ifp->if_ierrors++;
1269		return;
1270	}
1271
1272	ifp->if_ipackets++;
1273
1274	/* Receive packet. */
1275#ifdef ANCACHE
1276	an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);
1277#endif
1278#if NBPFILTER > 0
1279	if (ifp->if_bpf)
1280		bpf_mtap(ifp->if_bpf, m);
1281#endif
1282	(*ifp->if_input)(ifp, m);
1283}
1284
1285static void
1286an_txeof(struct an_softc *sc, int status)
1287{
1288	struct ifnet *ifp = &sc->arpcom.ec_if;
1289	int i, id;
1290
1291	ifp->if_timer = 0;
1292	ifp->if_flags &= ~IFF_OACTIVE;
1293
1294	id = CSR_READ_2(sc, AN_TX_CMP_FID);
1295
1296	if (status & AN_EV_TX_EXC)
1297		ifp->if_oerrors++;
1298	else
1299		ifp->if_opackets++;
1300
1301	/* fix from Doug Ambrisko -wsr */
1302	for (i = 0; i < AN_TX_RING_CNT; i++) {
1303		if (id == sc->an_rdata.an_tx_ring[i]) {
1304			sc->an_rdata.an_tx_ring[i] = 0;
1305			break;
1306		}
1307	}
1308	if (i != sc->an_rdata.an_tx_cons) {
1309		if (ifp->if_flags & IFF_DEBUG)
1310			printf("%s: id mismatch: id %x, "
1311			    "expected %x(%d), actual %x(%d)\n",
1312			    sc->an_dev.dv_xname, id,
1313			    sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons],
1314			    sc->an_rdata.an_tx_cons, id, i);
1315	}
1316
1317	AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
1318
1319	return;
1320}
1321
1322/*
1323 * We abuse the stats updater to check the current NIC status. This
1324 * is important because we don't want to allow transmissions until
1325 * the NIC has synchronized to the current cell (either as the master
1326 * in an ad-hoc group, or as a station connected to an access point).
1327 */
1328void
1329an_stats_update(void *xsc)
1330{
1331	struct an_softc *sc = xsc;
1332
1333	if (sc->sc_enabled) {
1334		sc->an_status.an_type = AN_RID_STATUS;
1335		sc->an_status.an_len = sizeof(struct an_ltv_status);
1336		if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_status)
1337		    == 0) {
1338			if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
1339				sc->an_associated = 1;
1340			else
1341				sc->an_associated = 0;
1342#if 0
1343			/* Don't do this while we're transmitting */
1344			if (sc->arpcom.ec_if.if_flags & IFF_OACTIVE) {
1345				sc->an_stats.an_len =
1346				    sizeof(struct an_ltv_stats);
1347				sc->an_stats.an_type = AN_RID_32BITS_CUM;
1348				an_read_record(sc,
1349				    (struct an_ltv_gen *)&sc->an_stats.an_len);
1350			}
1351#endif
1352		}
1353	}
1354	callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc);
1355}
1356
1357int
1358an_intr(void *arg)
1359{
1360	struct an_softc *sc = arg;
1361	struct ifnet *ifp = &sc->arpcom.ec_if;
1362	u_int16_t status;
1363
1364	if (!sc->sc_enabled)
1365		return 0;
1366
1367	if (!(ifp->if_flags & IFF_UP)) {
1368		CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF);
1369		CSR_WRITE_2(sc, AN_INT_EN, 0);
1370		return 0;
1371	}
1372
1373	/* Disable interrupts. */
1374	CSR_WRITE_2(sc, AN_INT_EN, 0);
1375
1376	while ((status = (CSR_READ_2(sc, AN_EVENT_STAT) & AN_INTRS)) != 0) {
1377		if (status & AN_EV_RX) {
1378			an_rxeof(sc);
1379			CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
1380			status &= ~AN_EV_RX;
1381		}
1382		if (status & (AN_EV_TX | AN_EV_TX_EXC)) {
1383			an_txeof(sc, status);
1384			CSR_WRITE_2(sc, AN_EVENT_ACK,
1385			    status & (AN_EV_TX | AN_EV_TX_EXC));
1386			status &= ~(AN_EV_TX | AN_EV_TX_EXC);
1387		}
1388		if (status & AN_EV_LINKSTAT) {
1389			if (CSR_READ_2(sc, AN_LINKSTAT) ==
1390			    AN_LINKSTAT_ASSOCIATED)
1391				sc->an_associated = 1;
1392			else
1393				sc->an_associated = 0;
1394			CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
1395			status &= ~AN_EV_LINKSTAT;
1396		}
1397#if 0
1398		if (status & AN_EV_CMD) {
1399			wakeup(sc);
1400			CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
1401			status &= ~AN_EV_CMD;
1402		}
1403#endif
1404		if (status)
1405			CSR_WRITE_2(sc, AN_EVENT_ACK, status);
1406	}
1407
1408	/* Re-enable interrupts. */
1409	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
1410
1411	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1412		an_start(ifp);
1413
1414	return 1;
1415}
1416
1417static int
1418an_cmd(struct an_softc *sc, int cmd, int val)
1419{
1420	int i, stat;
1421
1422	/* make sure that previous command completed */
1423	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
1424		if (sc->arpcom.ec_if.if_flags & IFF_DEBUG)
1425			printf("%s: command 0x%x busy\n", sc->an_dev.dv_xname,
1426			    CSR_READ_2(sc, AN_COMMAND));
1427		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
1428	}
1429
1430	CSR_WRITE_2(sc, AN_PARAM0, val);
1431	CSR_WRITE_2(sc, AN_PARAM1, 0);
1432	CSR_WRITE_2(sc, AN_PARAM2, 0);
1433	CSR_WRITE_2(sc, AN_COMMAND, cmd);
1434
1435	for (i = 0; i < AN_TIMEOUT; i++) {
1436		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
1437			break;
1438		/* make sure the command is accepted */
1439		if (CSR_READ_2(sc, AN_COMMAND) == cmd)
1440			CSR_WRITE_2(sc, AN_COMMAND, cmd);
1441		DELAY(10);
1442	}
1443
1444	stat = CSR_READ_2(sc, AN_STATUS);
1445
1446	/* clear stuck command busy if necessary */
1447	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)
1448		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
1449
1450	/* Ack the command */
1451	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
1452
1453	if (i == AN_TIMEOUT) {
1454		if (sc->arpcom.ec_if.if_flags & IFF_DEBUG)
1455			printf("%s: command 0x%x param 0x%x timeout\n",
1456			    sc->an_dev.dv_xname, cmd, val);
1457		return ETIMEDOUT;
1458	}
1459	if (stat & AN_STAT_CMD_RESULT) {
1460		if (sc->arpcom.ec_if.if_flags & IFF_DEBUG)
1461			printf("%s: command 0x%x param 0x%x stat 0x%x\n",
1462			    sc->an_dev.dv_xname, cmd, val, stat);
1463		return EIO;
1464	}
1465
1466	return 0;
1467}
1468
1469/*
1470 * This reset sequence may look a little strange, but this is the
1471 * most reliable method I've found to really kick the NIC in the
1472 * head and force it to reboot correctly.
1473 */
1474static void
1475an_reset(struct an_softc *sc)
1476{
1477
1478	if (!sc->sc_enabled)
1479		return;
1480
1481	an_cmd(sc, AN_CMD_ENABLE, 0);
1482	an_cmd(sc, AN_CMD_FW_RESTART, 0);
1483	an_cmd(sc, AN_CMD_NOOP2, 0);
1484
1485	if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
1486		printf("%s: reset failed\n", sc->an_dev.dv_xname);
1487
1488	an_cmd(sc, AN_CMD_DISABLE, 0);
1489}
1490
1491/*
1492 * Wait for firmware come up after power enabled.
1493 */
1494static void
1495an_wait(struct an_softc *sc)
1496{
1497	int i;
1498
1499	CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2);
1500	for (i = 0; i < 3*hz; i++) {
1501		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
1502			break;
1503		(void)tsleep(sc, PWAIT, "anatch", 1);
1504	}
1505	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
1506}
1507
1508/*
1509 * Read an LTV record from the NIC.
1510 */
1511static int
1512an_read_record(struct an_softc *sc, struct an_ltv_gen *ltv)
1513{
1514	u_int16_t *ptr;
1515	int i, len;
1516
1517	if (ltv->an_len == 0 || ltv->an_type == 0)
1518		return EINVAL;
1519
1520	/* Tell the NIC to enter record read mode. */
1521	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
1522		return EIO;
1523
1524	/* Seek to the record. */
1525	if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
1526		return EIO;
1527
1528	/*
1529	 * Read the length and record type and make sure they
1530	 * match what we expect (this verifies that we have enough
1531	 * room to hold all of the returned data).
1532	 */
1533	len = CSR_READ_2(sc, AN_DATA1);
1534	if (len > ltv->an_len) {
1535		if (sc->arpcom.ec_if.if_flags & IFF_DEBUG)
1536			printf("%s: RID 0x%04x record length mismatch"
1537			    "-- expected %d, got %d\n", sc->an_dev.dv_xname,
1538			    ltv->an_type, ltv->an_len, len);
1539		return ENOSPC;
1540	}
1541
1542	ltv->an_len = len;
1543
1544	/* Now read the data. */
1545	ptr = &ltv->an_val;
1546	for (i = 0; i < (ltv->an_len - 2) >> 1; i++)
1547		ptr[i] = CSR_READ_2(sc, AN_DATA1);
1548
1549	return 0;
1550}
1551
1552/*
1553 * Same as read, except we inject data instead of reading it.
1554 */
1555static int
1556an_write_record(struct an_softc *sc, struct an_ltv_gen *ltv)
1557{
1558	u_int16_t *ptr;
1559	int i;
1560
1561	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
1562		return EIO;
1563
1564	if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
1565		return EIO;
1566
1567	CSR_WRITE_2(sc, AN_DATA1, ltv->an_len-2);
1568
1569	ptr = &ltv->an_val;
1570	for (i = 0; i < (ltv->an_len - 4) >> 1; i++)
1571		CSR_WRITE_2(sc, AN_DATA1, ptr[i]);
1572
1573	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
1574		return EIO;
1575
1576	return 0;
1577}
1578
1579static int
1580an_seek(struct an_softc *sc, int id, int off, int chan)
1581{
1582	int i, selreg, offreg;
1583
1584	switch (chan) {
1585	case AN_BAP0:
1586		selreg = AN_SEL0;
1587		offreg = AN_OFF0;
1588		break;
1589	case AN_BAP1:
1590		selreg = AN_SEL1;
1591		offreg = AN_OFF1;
1592		break;
1593	default:
1594		panic("%s: invalid chan: %x", sc->an_dev.dv_xname, chan);
1595	}
1596
1597	CSR_WRITE_2(sc, selreg, id);
1598	CSR_WRITE_2(sc, offreg, off);
1599
1600	for (i = 0; i < AN_TIMEOUT; i++) {
1601		if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
1602			break;
1603		DELAY(10);
1604	}
1605	if (i == AN_TIMEOUT) {
1606		if (sc->arpcom.ec_if.if_flags & IFF_DEBUG)
1607			printf("%s: seek(0x%x, 0x%x, 0x%x) timeout\n",
1608			    sc->an_dev.dv_xname, id, off, chan);
1609		return ETIMEDOUT;
1610	}
1611
1612	return 0;
1613}
1614
1615static int
1616an_read_data(struct an_softc *sc, int id, int off, caddr_t buf, int len)
1617{
1618	int i;
1619	u_int16_t *ptr;
1620	u_int8_t *ptr2;
1621
1622	if (off != -1) {
1623		if (an_seek(sc, id, off, AN_BAP1))
1624			return EIO;
1625	}
1626
1627	ptr = (u_int16_t *)buf;
1628	for (i = 0; i < len / 2; i++)
1629		ptr[i] = CSR_READ_2(sc, AN_DATA1);
1630	i *= 2;
1631	if (i < len){
1632	        ptr2 = (u_int8_t *)buf;
1633	        ptr2[i] = CSR_READ_1(sc, AN_DATA1);
1634	}
1635
1636	return 0;
1637}
1638
1639static int
1640an_write_data(struct an_softc *sc, int id, int off, caddr_t buf, int len)
1641{
1642	int i;
1643	u_int16_t *ptr;
1644	u_int8_t *ptr2;
1645
1646	if (off != -1) {
1647		if (an_seek(sc, id, off, AN_BAP0))
1648			return EIO;
1649	}
1650
1651	ptr = (u_int16_t *)buf;
1652	for (i = 0; i < (len / 2); i++)
1653		CSR_WRITE_2(sc, AN_DATA0, ptr[i]);
1654	i *= 2;
1655	if (i < len){
1656	        ptr2 = (u_int8_t *)buf;
1657	        CSR_WRITE_1(sc, AN_DATA0, ptr2[i]);
1658	}
1659
1660	return 0;
1661}
1662
1663/*
1664 * Allocate a region of memory inside the NIC and zero
1665 * it out.
1666 */
1667static int
1668an_alloc_nicmem(struct an_softc *sc, int len, int *id)
1669{
1670	int			i;
1671
1672	if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
1673		printf("%s: failed to allocate %d bytes on NIC\n",
1674		    sc->an_dev.dv_xname, len);
1675		return ENOMEM;
1676	}
1677
1678	for (i = 0; i < AN_TIMEOUT; i++) {
1679		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
1680			break;
1681		DELAY(10);
1682	}
1683
1684	if (i == AN_TIMEOUT)
1685		return(ETIMEDOUT);
1686
1687	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
1688	*id = CSR_READ_2(sc, AN_ALLOC_FID);
1689
1690	if (an_seek(sc, *id, 0, AN_BAP0))
1691		return EIO;
1692
1693	for (i = 0; i < len / 2; i++)
1694		CSR_WRITE_2(sc, AN_DATA0, 0);
1695
1696	return 0;
1697}
1698
1699#ifdef ANCACHE
1700/* Aironet signal strength cache code.
1701 * store signal/noise/quality on per MAC src basis in
1702 * a small fixed cache.  The cache wraps if > MAX slots
1703 * used.  The cache may be zeroed out to start over.
1704 * Two simple filters exist to reduce computation:
1705 * 1. ip only (literally 0x800) which may be used
1706 * to ignore some packets.  It defaults to ip only.
1707 * it could be used to focus on broadcast, non-IP 802.11 beacons.
1708 * 2. multicast/broadcast only.  This may be used to
1709 * ignore unicast packets and only cache signal strength
1710 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
1711 * beacons and not unicast traffic.
1712 *
1713 * The cache stores (MAC src(index), IP src (major clue), signal,
1714 *	quality, noise)
1715 *
1716 * No apologies for storing IP src here.  It's easy and saves much
1717 * trouble elsewhere.  The cache is assumed to be INET dependent,
1718 * although it need not be.
1719 *
1720 * Note: the Aironet only has a single byte of signal strength value
1721 * in the rx frame header, and it's not scaled to anything sensible.
1722 * This is kind of lame, but it's all we've got.
1723 */
1724
1725#ifdef documentation
1726
1727int an_sigitems;                                /* number of cached entries */
1728struct an_sigcache an_sigcache[MAXANCACHE];  /*  array of cache entries */
1729int an_nextitem;                                /*  index/# of entries */
1730
1731
1732#endif
1733
1734/* control variables for cache filtering.  Basic idea is
1735 * to reduce cost (e.g., to only Mobile-IP agent beacons
1736 * which are broadcast or multicast).  Still you might
1737 * want to measure signal strength anth unicast ping packets
1738 * on a pt. to pt. ant. setup.
1739 */
1740/* set true if you want to limit cache items to broadcast/mcast
1741 * only packets (not unicast).  Useful for mobile-ip beacons which
1742 * are broadcast/multicast at network layer.  Default is all packets
1743 * so ping/unicast anll work say anth pt. to pt. antennae setup.
1744 */
1745static int an_cache_mcastonly = 0;
1746#if 0
1747SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
1748	&an_cache_mcastonly, 0, "");
1749#endif
1750
1751/* set true if you want to limit cache items to IP packets only
1752*/
1753static int an_cache_iponly = 1;
1754#if 0
1755SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
1756	&an_cache_iponly, 0, "");
1757#endif
1758
1759/*
1760 * an_cache_store, per rx packet store signal
1761 * strength in MAC (src) indexed cache.
1762 */
1763static
1764void an_cache_store (sc, eh, m, rx_quality)
1765	struct an_softc *sc;
1766	struct ether_header *eh;
1767	struct mbuf *m;
1768	unsigned short rx_quality;
1769{
1770	struct ip *ip = 0;
1771	int i;
1772	static int cache_slot = 0; 	/* use this cache entry */
1773	static int wrapindex = 0;       /* next "free" cache entry */
1774	int saanp=0;
1775
1776	/* filters:
1777	 * 1. ip only
1778	 * 2. configurable filter to throw out unicast packets,
1779	 * keep multicast only.
1780	 */
1781
1782	if ((ntohs(eh->ether_type) == 0x800)) {
1783		saanp = 1;
1784	}
1785
1786	/* filter for ip packets only
1787	*/
1788	if (an_cache_iponly && !saanp) {
1789		return;
1790	}
1791
1792	/* filter for broadcast/multicast only
1793	 */
1794	if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
1795		return;
1796	}
1797
1798#ifdef SIGDEBUG
1799	printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
1800	    rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
1801#endif
1802
1803	/* find the ip header.  we want to store the ip_src
1804	 * address.
1805	 */
1806	if (saanp) {
1807		ip = (struct ip *)(mtod(m, caddr_t) + 14);
1808	}
1809
1810	/* do a linear search for a matching MAC address
1811	 * in the cache table
1812	 * . MAC address is 6 bytes,
1813	 * . var w_nextitem holds total number of entries already cached
1814	 */
1815	for(i = 0; i < sc->an_nextitem; i++) {
1816		if (!memcmp(eh->ether_shost , sc->an_sigcache[i].macsrc,  6 )) {
1817			/* Match!,
1818			 * so we already have this entry,
1819			 * update the data
1820			 */
1821			break;
1822		}
1823	}
1824
1825	/* did we find a matching mac address?
1826	 * if yes, then overwrite a previously existing cache entry
1827	 */
1828	if (i < sc->an_nextitem )   {
1829		cache_slot = i;
1830	}
1831	/* else, have a new address entry,so
1832	 * add this new entry,
1833	 * if table full, then we need to replace LRU entry
1834	 */
1835	else    {
1836
1837		/* check for space in cache table
1838		 * note: an_nextitem also holds number of entries
1839		 * added in the cache table
1840		 */
1841		if (sc->an_nextitem < MAXANCACHE ) {
1842			cache_slot = sc->an_nextitem;
1843			sc->an_nextitem++;
1844			sc->an_sigitems = sc->an_nextitem;
1845		}
1846        	/* no space found, so simply wrap anth wrap index
1847		 * and "zap" the next entry
1848		 */
1849		else {
1850			if (wrapindex == MAXANCACHE) {
1851				wrapindex = 0;
1852			}
1853			cache_slot = wrapindex++;
1854		}
1855	}
1856
1857	/* invariant: cache_slot now points at some slot
1858	 * in cache.
1859	 */
1860	if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
1861		log(LOG_ERR, "an_cache_store, bad index: %d of "
1862		    "[0..%d], gross cache error\n",
1863		    cache_slot, MAXANCACHE);
1864		return;
1865	}
1866
1867	/*  store items in cache
1868	 *  .ip source address
1869	 *  .mac src
1870	 *  .signal, etc.
1871	 */
1872	if (saanp) {
1873		sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
1874	}
1875	memcpy(sc->an_sigcache[cache_slot].macsrc, eh->ether_shost, 6);
1876
1877	sc->an_sigcache[cache_slot].signal = rx_quality;
1878
1879	return;
1880}
1881#endif
1882