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