if_an.c revision 83130
1/*
2 * Copyright (c) 1997, 1998, 1999
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/dev/an/if_an.c 83130 2001-09-06 02:40:43Z jlemon $
33 */
34
35/*
36 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
37 *
38 * Written by Bill Paul <wpaul@ctr.columbia.edu>
39 * Electrical Engineering Department
40 * Columbia University, New York City
41 */
42
43/*
44 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form.
45 * This driver supports all three device types (PCI devices are supported
46 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be
47 * supported either using hard-coded IO port/IRQ settings or via Plug
48 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
49 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
50 *
51 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
52 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
53 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
54 * a couple of important differences though:
55 *
56 * - Lucent doesn't currently offer a PCI card, however Aironet does
57 * - Lucent ISA card looks to the host like a PCMCIA controller with
58 *   a PCMCIA WaveLAN card inserted. This means that even desktop
59 *   machines need to be configured with PCMCIA support in order to
60 *   use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
61 *   actually look like normal ISA and PCI devices to the host, so
62 *   no PCMCIA controller support is needed
63 *
64 * The latter point results in a small gotcha. The Aironet PCMCIA
65 * cards can be configured for one of two operating modes depending
66 * on how the Vpp1 and Vpp2 programming voltages are set when the
67 * card is activated. In order to put the card in proper PCMCIA
68 * operation (where the CIS table is visible and the interface is
69 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
70 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
71 * which leaves the card in ISA/PCI mode, which prevents it from
72 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c
73 * has to be patched slightly in order to enable the Vpp voltages in
74 * order to make the Aironet PCMCIA cards work.
75 *
76 * Note that some PCMCIA controller software packages for Windows NT
77 * fail to set the voltages as well.
78 *
79 * The Aironet devices can operate in both station mode and access point
80 * mode. Typically, when programmed for station mode, the card can be set
81 * to automatically perform encapsulation/decapsulation of Ethernet II
82 * and 802.3 frames within 802.11 frames so that the host doesn't have
83 * to do it itself. This driver doesn't program the card that way: the
84 * driver handles all of the encapsulation/decapsulation itself.
85 */
86
87#include "opt_inet.h"
88
89#ifdef INET
90#define ANCACHE			/* enable signal strength cache */
91#endif
92
93#include <sys/param.h>
94#include <sys/systm.h>
95#include <sys/sockio.h>
96#include <sys/mbuf.h>
97#include <sys/kernel.h>
98#include <sys/socket.h>
99#ifdef ANCACHE
100#include <sys/syslog.h>
101#include <sys/sysctl.h>
102#endif
103
104#include <sys/module.h>
105#include <sys/bus.h>
106#include <machine/bus.h>
107#include <sys/rman.h>
108#include <sys/mutex.h>
109#include <machine/resource.h>
110
111#include <net/if.h>
112#include <net/if_arp.h>
113#include <net/ethernet.h>
114#include <net/if_dl.h>
115#include <net/if_types.h>
116#include <net/if_ieee80211.h>
117#include <net/if_media.h>
118
119#ifdef INET
120#include <netinet/in.h>
121#include <netinet/in_systm.h>
122#include <netinet/in_var.h>
123#include <netinet/ip.h>
124#endif
125
126#include <net/bpf.h>
127
128#include <machine/md_var.h>
129
130#include <dev/an/if_aironet_ieee.h>
131#include <dev/an/if_anreg.h>
132
133#if !defined(lint)
134static const char rcsid[] =
135  "$FreeBSD: head/sys/dev/an/if_an.c 83130 2001-09-06 02:40:43Z jlemon $";
136#endif
137
138/* These are global because we need them in sys/pci/if_an_p.c. */
139static void an_reset		__P((struct an_softc *));
140static int an_ioctl		__P((struct ifnet *, u_long, caddr_t));
141static void an_init		__P((void *));
142static int an_init_tx_ring	__P((struct an_softc *));
143static void an_start		__P((struct ifnet *));
144static void an_watchdog		__P((struct ifnet *));
145static void an_rxeof		__P((struct an_softc *));
146static void an_txeof		__P((struct an_softc *, int));
147
148static void an_promisc		__P((struct an_softc *, int));
149static int an_cmd		__P((struct an_softc *, int, int));
150static int an_read_record	__P((struct an_softc *, struct an_ltv_gen *));
151static int an_write_record	__P((struct an_softc *, struct an_ltv_gen *));
152static int an_read_data		__P((struct an_softc *, int,
153					int, caddr_t, int));
154static int an_write_data	__P((struct an_softc *, int,
155					int, caddr_t, int));
156static int an_seek		__P((struct an_softc *, int, int, int));
157static int an_alloc_nicmem	__P((struct an_softc *, int, int *));
158static void an_stats_update	__P((void *));
159static void an_setdef		__P((struct an_softc *, struct an_req *));
160#ifdef ANCACHE
161static void an_cache_store	__P((struct an_softc *, struct ether_header *,
162					struct mbuf *, unsigned short));
163#endif
164
165static void an_dump_record	__P((struct an_softc *,struct an_ltv_gen *,
166				    char *));
167
168static int an_media_change	__P((struct ifnet *));
169static void an_media_status	__P((struct ifnet *, struct ifmediareq *));
170
171static int	an_dump = 0;
172/*
173 * We probe for an Aironet 4500/4800 card by attempting to
174 * read the default SSID list. On reset, the first entry in
175 * the SSID list will contain the name "tsunami." If we don't
176 * find this, then there's no card present.
177 */
178int an_probe(dev)
179	device_t		dev;
180{
181        struct an_softc *sc = device_get_softc(dev);
182	struct an_ltv_ssidlist	ssid;
183	int	error;
184
185	bzero((char *)&ssid, sizeof(ssid));
186
187	error = an_alloc_port(dev, 0, AN_IOSIZ);
188	if (error != 0)
189		return (0);
190
191	/* can't do autoprobing */
192	if (rman_get_start(sc->port_res) == -1)
193		return(0);
194
195	/*
196	 * We need to fake up a softc structure long enough
197	 * to be able to issue commands and call some of the
198	 * other routines.
199	 */
200	sc->an_bhandle = rman_get_bushandle(sc->port_res);
201	sc->an_btag = rman_get_bustag(sc->port_res);
202	sc->an_unit = device_get_unit(dev);
203
204	ssid.an_len = sizeof(ssid);
205	ssid.an_type = AN_RID_SSIDLIST;
206
207        /* Make sure interrupts are disabled. */
208        CSR_WRITE_2(sc, AN_INT_EN, 0);
209        CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF);
210
211	an_reset(sc);
212
213	if (an_cmd(sc, AN_CMD_READCFG, 0))
214		return(0);
215
216	if (an_read_record(sc, (struct an_ltv_gen *)&ssid))
217		return(0);
218
219	/* See if the ssid matches what we expect ... but doesn't have to */
220	if (strcmp(ssid.an_ssid1, AN_DEF_SSID))
221		return(0);
222
223	return(AN_IOSIZ);
224}
225
226/*
227 * Allocate a port resource with the given resource id.
228 */
229int
230an_alloc_port(dev, rid, size)
231	device_t dev;
232	int rid;
233	int size;
234{
235	struct an_softc *sc = device_get_softc(dev);
236	struct resource *res;
237
238	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
239				 0ul, ~0ul, size, RF_ACTIVE);
240	if (res) {
241		sc->port_rid = rid;
242		sc->port_res = res;
243		return (0);
244	} else {
245		return (ENOENT);
246	}
247}
248
249/*
250 * Allocate an irq resource with the given resource id.
251 */
252int
253an_alloc_irq(dev, rid, flags)
254	device_t dev;
255	int rid;
256	int flags;
257{
258	struct an_softc *sc = device_get_softc(dev);
259	struct resource *res;
260
261	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
262				 0ul, ~0ul, 1, (RF_ACTIVE | flags));
263	if (res) {
264		sc->irq_rid = rid;
265		sc->irq_res = res;
266		return (0);
267	} else {
268		return (ENOENT);
269	}
270}
271
272/*
273 * Release all resources
274 */
275void
276an_release_resources(dev)
277	device_t dev;
278{
279	struct an_softc *sc = device_get_softc(dev);
280
281	if (sc->port_res) {
282		bus_release_resource(dev, SYS_RES_IOPORT,
283				     sc->port_rid, sc->port_res);
284		sc->port_res = 0;
285	}
286	if (sc->irq_res) {
287		bus_release_resource(dev, SYS_RES_IRQ,
288				     sc->irq_rid, sc->irq_res);
289		sc->irq_res = 0;
290	}
291}
292
293int an_attach(sc, unit, flags)
294	struct an_softc *sc;
295	int unit;
296	int flags;
297{
298	struct ifnet		*ifp = &sc->arpcom.ac_if;
299
300	mtx_init(&sc->an_mtx, device_get_nameunit(sc->an_dev), MTX_DEF |
301	    MTX_RECURSE);
302	AN_LOCK(sc);
303
304	sc->an_gone = 0;
305	sc->an_associated = 0;
306
307	/* Reset the NIC. */
308	an_reset(sc);
309
310	/* Load factory config */
311	if (an_cmd(sc, AN_CMD_READCFG, 0)) {
312		printf("an%d: failed to load config data\n", sc->an_unit);
313		AN_UNLOCK(sc);
314		mtx_destroy(&sc->an_mtx);
315		return(EIO);
316	}
317
318	/* Read the current configuration */
319	sc->an_config.an_type = AN_RID_GENCONFIG;
320	sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
321	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
322		printf("an%d: read record failed\n", sc->an_unit);
323		AN_UNLOCK(sc);
324		mtx_destroy(&sc->an_mtx);
325		return(EIO);
326	}
327
328	/* Read the card capabilities */
329	sc->an_caps.an_type = AN_RID_CAPABILITIES;
330	sc->an_caps.an_len = sizeof(struct an_ltv_caps);
331	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
332		printf("an%d: read record failed\n", sc->an_unit);
333		AN_UNLOCK(sc);
334		mtx_destroy(&sc->an_mtx);
335		return(EIO);
336	}
337
338	/* Read ssid list */
339	sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
340	sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
341	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
342		printf("an%d: read record failed\n", sc->an_unit);
343		AN_UNLOCK(sc);
344		mtx_destroy(&sc->an_mtx);
345		return(EIO);
346	}
347
348	/* Read AP list */
349	sc->an_aplist.an_type = AN_RID_APLIST;
350	sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
351	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
352		printf("an%d: read record failed\n", sc->an_unit);
353		AN_UNLOCK(sc);
354		mtx_destroy(&sc->an_mtx);
355		return(EIO);
356	}
357
358	bcopy((char *)&sc->an_caps.an_oemaddr,
359	   (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
360
361	printf("an%d: Ethernet address: %6D\n", sc->an_unit,
362	    sc->arpcom.ac_enaddr, ":");
363
364	ifp->if_softc = sc;
365	ifp->if_unit = sc->an_unit = unit;
366	ifp->if_name = "an";
367	ifp->if_mtu = ETHERMTU;
368	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
369	ifp->if_ioctl = an_ioctl;
370	ifp->if_output = ether_output;
371	ifp->if_start = an_start;
372	ifp->if_watchdog = an_watchdog;
373	ifp->if_init = an_init;
374	ifp->if_baudrate = 10000000;
375	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
376
377	bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
378	bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename,
379	    sizeof(AN_DEFAULT_NODENAME) - 1);
380
381	bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1));
382	bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1,
383	    sizeof(AN_DEFAULT_NETNAME) - 1);
384	sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME);
385
386	sc->an_config.an_opmode =
387	    AN_OPMODE_INFRASTRUCTURE_STATION;
388
389	sc->an_tx_rate = 0;
390	bzero((char *)&sc->an_stats, sizeof(sc->an_stats));
391
392	ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status);
393#define	ADD(m, c)	ifmedia_add(&sc->an_ifmedia, (m), (c), NULL)
394	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
395	    IFM_IEEE80211_ADHOC, 0), 0);
396	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
397	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
398	    IFM_IEEE80211_ADHOC, 0), 0);
399	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
400	if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
401		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
402		    IFM_IEEE80211_ADHOC, 0), 0);
403		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
404	}
405	if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
406		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
407		    IFM_IEEE80211_ADHOC, 0), 0);
408		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
409	}
410	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
411	    IFM_IEEE80211_ADHOC, 0), 0);
412	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
413#undef	ADD
414	ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
415	    0, 0));
416
417	/*
418	 * Call MI attach routine.
419	 */
420	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
421	callout_handle_init(&sc->an_stat_ch);
422	AN_UNLOCK(sc);
423
424	return(0);
425}
426
427static void an_rxeof(sc)
428	struct an_softc		*sc;
429{
430	struct ifnet		*ifp;
431	struct ether_header	*eh;
432#ifdef ANCACHE
433	struct an_rxframe	rx_frame;
434#endif
435	struct an_rxframe_802_3	rx_frame_802_3;
436	struct mbuf		*m;
437	int			id, error = 0;
438
439	ifp = &sc->arpcom.ac_if;
440
441	id = CSR_READ_2(sc, AN_RX_FID);
442
443	MGETHDR(m, M_DONTWAIT, MT_DATA);
444	if (m == NULL) {
445		ifp->if_ierrors++;
446		return;
447	}
448	MCLGET(m, M_DONTWAIT);
449	if (!(m->m_flags & M_EXT)) {
450		m_freem(m);
451		ifp->if_ierrors++;
452		return;
453	}
454
455	m->m_pkthdr.rcvif = ifp;
456
457	eh = mtod(m, struct ether_header *);
458
459#ifdef ANCACHE
460	/* Read NIC frame header */
461	if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
462		ifp->if_ierrors++;
463		return;
464	}
465#endif
466	/* Read in the 802_3 frame header */
467	if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3,
468			 sizeof(rx_frame_802_3))) {
469		ifp->if_ierrors++;
470		return;
471	}
472
473	if (rx_frame_802_3.an_rx_802_3_status != 0) {
474		ifp->if_ierrors++;
475		return;
476	}
477
478	/* Check for insane frame length */
479	if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) {
480		ifp->if_ierrors++;
481		return;
482	}
483
484	m->m_pkthdr.len = m->m_len =
485	    rx_frame_802_3.an_rx_802_3_payload_len + 12;
486
487
488	bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,
489	    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
490	bcopy((char *)&rx_frame_802_3.an_rx_src_addr,
491	    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
492
493	/* in mbuf header type is just before payload */
494	error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),
495			     rx_frame_802_3.an_rx_802_3_payload_len);
496
497	if (error != 0) {
498		m_freem(m);
499		ifp->if_ierrors++;
500		return;
501	}
502
503	ifp->if_ipackets++;
504
505	/* Receive packet. */
506	m_adj(m, sizeof(struct ether_header));
507#ifdef ANCACHE
508	an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);
509#endif
510	ether_input(ifp, eh, m);
511}
512
513static void an_txeof(sc, status)
514	struct an_softc		*sc;
515	int			status;
516{
517	struct ifnet		*ifp;
518	int			id, i;
519
520	/* TX DONE enable lan monitor DJA
521	   an_enable_sniff();
522	 */
523
524	ifp = &sc->arpcom.ac_if;
525
526	ifp->if_timer = 0;
527	ifp->if_flags &= ~IFF_OACTIVE;
528
529	id = CSR_READ_2(sc, AN_TX_CMP_FID);
530
531	if (status & AN_EV_TX_EXC) {
532		ifp->if_oerrors++;
533	} else
534		ifp->if_opackets++;
535
536	for (i = 0; i < AN_TX_RING_CNT; i++) {
537		if (id == sc->an_rdata.an_tx_ring[i]) {
538			sc->an_rdata.an_tx_ring[i] = 0;
539			break;
540		}
541	}
542
543	AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
544
545	return;
546}
547
548/*
549 * We abuse the stats updater to check the current NIC status. This
550 * is important because we don't want to allow transmissions until
551 * the NIC has synchronized to the current cell (either as the master
552 * in an ad-hoc group, or as a station connected to an access point).
553 */
554void an_stats_update(xsc)
555	void			*xsc;
556{
557	struct an_softc		*sc;
558	struct ifnet		*ifp;
559
560	sc = xsc;
561	AN_LOCK(sc);
562	ifp = &sc->arpcom.ac_if;
563
564	sc->an_status.an_type = AN_RID_STATUS;
565	sc->an_status.an_len = sizeof(struct an_ltv_status);
566	an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
567
568	if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
569		sc->an_associated = 1;
570	else
571		sc->an_associated = 0;
572
573	/* Don't do this while we're transmitting */
574	if (ifp->if_flags & IFF_OACTIVE) {
575		sc->an_stat_ch = timeout(an_stats_update, sc, hz);
576		AN_UNLOCK(sc);
577		return;
578	}
579
580	sc->an_stats.an_len = sizeof(struct an_ltv_stats);
581	sc->an_stats.an_type = AN_RID_32BITS_CUM;
582	an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
583
584	sc->an_stat_ch = timeout(an_stats_update, sc, hz);
585	AN_UNLOCK(sc);
586
587	return;
588}
589
590void an_intr(xsc)
591	void			*xsc;
592{
593	struct an_softc		*sc;
594	struct ifnet		*ifp;
595	u_int16_t		status;
596
597	sc = (struct an_softc*)xsc;
598
599	AN_LOCK(sc);
600
601	if (sc->an_gone) {
602		AN_UNLOCK(sc);
603		return;
604	}
605
606	ifp = &sc->arpcom.ac_if;
607
608	/* Disable interrupts. */
609	CSR_WRITE_2(sc, AN_INT_EN, 0);
610
611	status = CSR_READ_2(sc, AN_EVENT_STAT);
612	CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS);
613
614	if (status & AN_EV_AWAKE) {
615		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE);
616	}
617
618	if (status & AN_EV_LINKSTAT) {
619		if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED)
620			sc->an_associated = 1;
621		else
622			sc->an_associated = 0;
623		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
624	}
625
626	if (status & AN_EV_RX) {
627		an_rxeof(sc);
628		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
629	}
630
631	if (status & AN_EV_TX) {
632		an_txeof(sc, status);
633		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX);
634	}
635
636	if (status & AN_EV_TX_EXC) {
637		an_txeof(sc, status);
638		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC);
639	}
640
641	if (status & AN_EV_ALLOC)
642		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
643
644	/* Re-enable interrupts. */
645	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
646
647	if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL))
648		an_start(ifp);
649
650	AN_UNLOCK(sc);
651
652	return;
653}
654
655static int an_cmd(sc, cmd, val)
656	struct an_softc		*sc;
657	int			cmd;
658	int			val;
659{
660	int			i, s = 0;
661
662	CSR_WRITE_2(sc, AN_PARAM0, val);
663	CSR_WRITE_2(sc, AN_PARAM1, 0);
664	CSR_WRITE_2(sc, AN_PARAM2, 0);
665	CSR_WRITE_2(sc, AN_COMMAND, cmd);
666
667	for (i = 0; i < AN_TIMEOUT; i++) {
668		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
669			break;
670		else {
671			if (CSR_READ_2(sc, AN_COMMAND) == cmd)
672				CSR_WRITE_2(sc, AN_COMMAND, cmd);
673		}
674	}
675
676	for (i = 0; i < AN_TIMEOUT; i++) {
677		CSR_READ_2(sc, AN_RESP0);
678		CSR_READ_2(sc, AN_RESP1);
679		CSR_READ_2(sc, AN_RESP2);
680		s = CSR_READ_2(sc, AN_STATUS);
681		if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE))
682			break;
683	}
684
685	/* Ack the command */
686	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
687
688	if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)
689		CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
690
691	if (i == AN_TIMEOUT)
692		return(ETIMEDOUT);
693
694	return(0);
695}
696
697/*
698 * This reset sequence may look a little strange, but this is the
699 * most reliable method I've found to really kick the NIC in the
700 * head and force it to reboot correctly.
701 */
702static void an_reset(sc)
703	struct an_softc		*sc;
704{
705	if (sc->an_gone)
706		return;
707
708	an_cmd(sc, AN_CMD_ENABLE, 0);
709	an_cmd(sc, AN_CMD_FW_RESTART, 0);
710	an_cmd(sc, AN_CMD_NOOP2, 0);
711
712	if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
713		printf("an%d: reset failed\n", sc->an_unit);
714
715	an_cmd(sc, AN_CMD_DISABLE, 0);
716
717	return;
718}
719
720/*
721 * Read an LTV record from the NIC.
722 */
723static int an_read_record(sc, ltv)
724	struct an_softc		*sc;
725	struct an_ltv_gen	*ltv;
726{
727	u_int16_t		*ptr;
728	u_int8_t		*ptr2;
729	int			i, len;
730
731	if (ltv->an_len < 4 || ltv->an_type == 0)
732		return(EINVAL);
733
734	/* Tell the NIC to enter record read mode. */
735	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {
736		printf("an%d: RID access failed\n", sc->an_unit);
737		return(EIO);
738	}
739
740	/* Seek to the record. */
741	if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {
742		printf("an%d: seek to record failed\n", sc->an_unit);
743		return(EIO);
744	}
745
746	/*
747	 * Read the length and record type and make sure they
748	 * match what we expect (this verifies that we have enough
749	 * room to hold all of the returned data).
750	 * Length includes type but not length.
751	 */
752	len = CSR_READ_2(sc, AN_DATA1);
753	if (len > (ltv->an_len - 2)) {
754		printf("an%d: record length mismatch -- expected %d, "
755		    "got %d for Rid %x\n", sc->an_unit,
756		    ltv->an_len - 2, len, ltv->an_type);
757		len = ltv->an_len - 2;
758	} else {
759		ltv->an_len = len + 2;
760	}
761
762	/* Now read the data. */
763	len -= 2;	/* skip the type */
764	ptr = &ltv->an_val;
765	for (i = len; i > 1; i -= 2)
766		*ptr++ = CSR_READ_2(sc, AN_DATA1);
767	if (i) {
768		ptr2 = (u_int8_t *)ptr;
769		*ptr2 = CSR_READ_1(sc, AN_DATA1);
770	}
771	if (an_dump)
772		an_dump_record(sc, ltv, "Read");
773
774	return(0);
775}
776
777/*
778 * Same as read, except we inject data instead of reading it.
779 */
780static int an_write_record(sc, ltv)
781	struct an_softc		*sc;
782	struct an_ltv_gen	*ltv;
783{
784	u_int16_t		*ptr;
785	u_int8_t		*ptr2;
786	int			i, len;
787
788	if (an_dump)
789		an_dump_record(sc, ltv, "Write");
790
791	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
792		return(EIO);
793
794	if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
795		return(EIO);
796
797	/*
798	 * Length includes type but not length.
799	 */
800	len = ltv->an_len - 2;
801	CSR_WRITE_2(sc, AN_DATA1, len);
802
803	len -= 2;	/* skip the type */
804	ptr = &ltv->an_val;
805	for (i = len; i > 1; i -= 2)
806		CSR_WRITE_2(sc, AN_DATA1, *ptr++);
807	if (i) {
808		ptr2 = (u_int8_t *)ptr;
809		CSR_WRITE_1(sc, AN_DATA0, *ptr2);
810	}
811
812	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
813		return(EIO);
814
815	return(0);
816}
817
818static void an_dump_record(sc, ltv, string)
819	struct an_softc		*sc;
820	struct an_ltv_gen	*ltv;
821	char			*string;
822{
823	u_int8_t		*ptr2;
824	int			len;
825	int			i;
826	int			count = 0;
827	char			buf[17], temp;
828
829	len = ltv->an_len - 4;
830	printf("an%d: RID %4x, Length %4d, Mode %s\n",
831		sc->an_unit, ltv->an_type, ltv->an_len - 4, string);
832
833	if (an_dump == 1 || (an_dump == ltv->an_type)) {
834		printf("an%d:\t", sc->an_unit);
835		bzero(buf,sizeof(buf));
836
837		ptr2 = (u_int8_t *)&ltv->an_val;
838		for (i = len; i > 0; i--) {
839			printf("%02x ", *ptr2);
840
841			temp = *ptr2++;
842			if (temp >= ' ' && temp <= '~')
843				buf[count] = temp;
844			else if (temp >= 'A' && temp <= 'Z')
845				buf[count] = temp;
846			else
847				buf[count] = '.';
848			if (++count == 16) {
849				count = 0;
850				printf("%s\n",buf);
851				printf("an%d:\t", sc->an_unit);
852				bzero(buf,sizeof(buf));
853			}
854		}
855		for (; count != 16; count++) {
856			printf("   ");
857		}
858		printf(" %s\n",buf);
859	}
860}
861
862static int an_seek(sc, id, off, chan)
863	struct an_softc		*sc;
864	int			id, off, chan;
865{
866	int			i;
867	int			selreg, offreg;
868
869	switch (chan) {
870	case AN_BAP0:
871		selreg = AN_SEL0;
872		offreg = AN_OFF0;
873		break;
874	case AN_BAP1:
875		selreg = AN_SEL1;
876		offreg = AN_OFF1;
877		break;
878	default:
879		printf("an%d: invalid data path: %x\n", sc->an_unit, chan);
880		return(EIO);
881	}
882
883	CSR_WRITE_2(sc, selreg, id);
884	CSR_WRITE_2(sc, offreg, off);
885
886	for (i = 0; i < AN_TIMEOUT; i++) {
887		if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
888			break;
889	}
890
891	if (i == AN_TIMEOUT)
892		return(ETIMEDOUT);
893
894	return(0);
895}
896
897static int an_read_data(sc, id, off, buf, len)
898	struct an_softc		*sc;
899	int			id, off;
900	caddr_t			buf;
901	int			len;
902{
903	int			i;
904	u_int16_t		*ptr;
905	u_int8_t		*ptr2;
906
907	if (off != -1) {
908		if (an_seek(sc, id, off, AN_BAP1))
909			return(EIO);
910	}
911
912	ptr = (u_int16_t *)buf;
913	for (i = len; i > 1; i -= 2)
914		*ptr++ = CSR_READ_2(sc, AN_DATA1);
915	if (i) {
916		ptr2 = (u_int8_t *)ptr;
917		*ptr2 = CSR_READ_1(sc, AN_DATA1);
918	}
919
920	return(0);
921}
922
923static int an_write_data(sc, id, off, buf, len)
924	struct an_softc		*sc;
925	int			id, off;
926	caddr_t			buf;
927	int			len;
928{
929	int			i;
930	u_int16_t		*ptr;
931	u_int8_t		*ptr2;
932
933	if (off != -1) {
934		if (an_seek(sc, id, off, AN_BAP0))
935			return(EIO);
936	}
937
938	ptr = (u_int16_t *)buf;
939	for (i = len; i > 1; i -= 2)
940		CSR_WRITE_2(sc, AN_DATA0, *ptr++);
941	if (i) {
942	        ptr2 = (u_int8_t *)ptr;
943	        CSR_WRITE_1(sc, AN_DATA0, *ptr2);
944	}
945
946	return(0);
947}
948
949/*
950 * Allocate a region of memory inside the NIC and zero
951 * it out.
952 */
953static int an_alloc_nicmem(sc, len, id)
954	struct an_softc		*sc;
955	int			len;
956	int			*id;
957{
958	int			i;
959
960	if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
961		printf("an%d: failed to allocate %d bytes on NIC\n",
962		    sc->an_unit, len);
963		return(ENOMEM);
964	}
965
966	for (i = 0; i < AN_TIMEOUT; i++) {
967		if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
968			break;
969	}
970
971	if (i == AN_TIMEOUT)
972		return(ETIMEDOUT);
973
974	CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
975	*id = CSR_READ_2(sc, AN_ALLOC_FID);
976
977	if (an_seek(sc, *id, 0, AN_BAP0))
978		return(EIO);
979
980	for (i = 0; i < len / 2; i++)
981		CSR_WRITE_2(sc, AN_DATA0, 0);
982
983	return(0);
984}
985
986static void an_setdef(sc, areq)
987	struct an_softc		*sc;
988	struct an_req		*areq;
989{
990	struct sockaddr_dl	*sdl;
991	struct ifaddr		*ifa;
992	struct ifnet		*ifp;
993	struct an_ltv_genconfig	*cfg;
994	struct an_ltv_ssidlist	*ssid;
995	struct an_ltv_aplist	*ap;
996	struct an_ltv_gen	*sp;
997
998	ifp = &sc->arpcom.ac_if;
999
1000	switch (areq->an_type) {
1001	case AN_RID_GENCONFIG:
1002		cfg = (struct an_ltv_genconfig *)areq;
1003
1004		ifa = ifaddr_byindex(ifp->if_index);
1005		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1006		bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr,
1007		    ETHER_ADDR_LEN);
1008		bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN);
1009
1010		bcopy((char *)cfg, (char *)&sc->an_config,
1011			sizeof(struct an_ltv_genconfig));
1012		break;
1013	case AN_RID_SSIDLIST:
1014		ssid = (struct an_ltv_ssidlist *)areq;
1015		bcopy((char *)ssid, (char *)&sc->an_ssidlist,
1016			sizeof(struct an_ltv_ssidlist));
1017		break;
1018	case AN_RID_APLIST:
1019		ap = (struct an_ltv_aplist *)areq;
1020		bcopy((char *)ap, (char *)&sc->an_aplist,
1021			sizeof(struct an_ltv_aplist));
1022		break;
1023	case AN_RID_TX_SPEED:
1024		sp = (struct an_ltv_gen *)areq;
1025		sc->an_tx_rate = sp->an_val;
1026		break;
1027	case AN_RID_WEP_TEMP:
1028		/* Disable the MAC. */
1029		an_cmd(sc, AN_CMD_DISABLE, 0);
1030
1031		/* Just write the Key, we don't want to save it */
1032		an_write_record(sc, (struct an_ltv_gen *)areq);
1033
1034		/* Turn the MAC back on. */
1035		an_cmd(sc, AN_CMD_ENABLE, 0);
1036
1037		break;
1038	case AN_RID_WEP_PERM:
1039
1040		/* Disable the MAC. */
1041		an_cmd(sc, AN_CMD_DISABLE, 0);
1042
1043		/* Just write the Key, the card will save it in this mode */
1044		an_write_record(sc, (struct an_ltv_gen *)areq);
1045
1046		/* Turn the MAC back on. */
1047		an_cmd(sc, AN_CMD_ENABLE, 0);
1048
1049		break;
1050	default:
1051		printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type);
1052		return;
1053		break;
1054	}
1055
1056
1057	/* Reinitialize the card. */
1058	if (ifp->if_flags)
1059		an_init(sc);
1060
1061	return;
1062}
1063
1064/*
1065 * We can't change the NIC configuration while the MAC is enabled,
1066 * so in order to turn on RX monitor mode, we have to turn the MAC
1067 * off first.
1068 */
1069static void an_promisc(sc, promisc)
1070	struct an_softc		*sc;
1071	int			promisc;
1072{
1073	an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0);
1074
1075	return;
1076}
1077
1078static int an_ioctl(ifp, command, data)
1079	struct ifnet		*ifp;
1080	u_long			command;
1081	caddr_t			data;
1082{
1083	int			error = 0;
1084	int			len;
1085	int			i;
1086	struct an_softc		*sc;
1087	struct an_req		areq;
1088	struct ifreq		*ifr;
1089	struct proc		*p = curproc;
1090	struct ieee80211req	*ireq;
1091	u_int8_t		tmpstr[IEEE80211_NWID_LEN*2];
1092	u_int8_t		*tmpptr;
1093	struct an_ltv_genconfig	*config;
1094	struct an_ltv_key	*key;
1095	struct an_ltv_status	*status;
1096	struct an_ltv_ssidlist	*ssids;
1097
1098	sc = ifp->if_softc;
1099	AN_LOCK(sc);
1100	ifr = (struct ifreq *)data;
1101	ireq = (struct ieee80211req *)data;
1102
1103	config = (struct an_ltv_genconfig *)&areq;
1104	key = (struct an_ltv_key *)&areq;
1105	status = (struct an_ltv_status *)&areq;
1106	ssids = (struct an_ltv_ssidlist *)&areq;
1107
1108	if (sc->an_gone) {
1109		error = ENODEV;
1110		goto out;
1111	}
1112
1113	switch(command) {
1114	case SIOCSIFADDR:
1115	case SIOCGIFADDR:
1116	case SIOCSIFMTU:
1117		error = ether_ioctl(ifp, command, data);
1118		break;
1119	case SIOCSIFFLAGS:
1120		if (ifp->if_flags & IFF_UP) {
1121			if (ifp->if_flags & IFF_RUNNING &&
1122			    ifp->if_flags & IFF_PROMISC &&
1123			    !(sc->an_if_flags & IFF_PROMISC)) {
1124				an_promisc(sc, 1);
1125			} else if (ifp->if_flags & IFF_RUNNING &&
1126			    !(ifp->if_flags & IFF_PROMISC) &&
1127			    sc->an_if_flags & IFF_PROMISC) {
1128				an_promisc(sc, 0);
1129			} else
1130				an_init(sc);
1131		} else {
1132			if (ifp->if_flags & IFF_RUNNING)
1133				an_stop(sc);
1134		}
1135		sc->an_if_flags = ifp->if_flags;
1136		error = 0;
1137		break;
1138	case SIOCSIFMEDIA:
1139	case SIOCGIFMEDIA:
1140		error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command);
1141		break;
1142	case SIOCADDMULTI:
1143	case SIOCDELMULTI:
1144		/* The Aironet has no multicast filter. */
1145		error = 0;
1146		break;
1147	case SIOCGAIRONET:
1148		error = copyin(ifr->ifr_data, &areq, sizeof(areq));
1149		if (error != 0)
1150			break;
1151#ifdef ANCACHE
1152		if (areq.an_type == AN_RID_ZERO_CACHE) {
1153			sc->an_sigitems = sc->an_nextitem = 0;
1154			break;
1155		} else if (areq.an_type == AN_RID_READ_CACHE) {
1156			char *pt = (char *)&areq.an_val;
1157			bcopy((char *)&sc->an_sigitems, (char *)pt,
1158			    sizeof(int));
1159			pt += sizeof(int);
1160			areq.an_len = sizeof(int) / 2;
1161			bcopy((char *)&sc->an_sigcache, (char *)pt,
1162			    sizeof(struct an_sigcache) * sc->an_sigitems);
1163			areq.an_len += ((sizeof(struct an_sigcache) *
1164			    sc->an_sigitems) / 2) + 1;
1165		} else
1166#endif
1167		if (an_read_record(sc, (struct an_ltv_gen *)&areq)) {
1168			error = EINVAL;
1169			break;
1170		}
1171		error = copyout(&areq, ifr->ifr_data, sizeof(areq));
1172		break;
1173	case SIOCSAIRONET:
1174		if ((error = suser(p)))
1175			goto out;
1176		error = copyin(ifr->ifr_data, &areq, sizeof(areq));
1177		if (error != 0)
1178			break;
1179		an_setdef(sc, &areq);
1180		break;
1181	case SIOCG80211:
1182		areq.an_len = sizeof(areq);
1183		switch(ireq->i_type) {
1184		case IEEE80211_IOC_SSID:
1185			if (ireq->i_val == -1) {
1186				areq.an_type = AN_RID_STATUS;
1187				if (an_read_record(sc,
1188				    (struct an_ltv_gen *)&areq)) {
1189					error = EINVAL;
1190					break;
1191				}
1192				len = status->an_ssidlen;
1193				tmpptr = status->an_ssid;
1194			} else if (ireq->i_val >= 0) {
1195				areq.an_type = AN_RID_SSIDLIST;
1196				if (an_read_record(sc,
1197				    (struct an_ltv_gen *)&areq)) {
1198					error = EINVAL;
1199					break;
1200				}
1201				if (ireq->i_val == 0) {
1202					len = ssids->an_ssid1_len;
1203					tmpptr = ssids->an_ssid1;
1204				} else if (ireq->i_val == 1) {
1205					len = ssids->an_ssid2_len;
1206					tmpptr = ssids->an_ssid3;
1207				} else if (ireq->i_val == 1) {
1208					len = ssids->an_ssid3_len;
1209					tmpptr = ssids->an_ssid3;
1210				} else {
1211					error = EINVAL;
1212					break;
1213				}
1214			} else {
1215				error = EINVAL;
1216				break;
1217			}
1218			if (len > IEEE80211_NWID_LEN) {
1219				error = EINVAL;
1220				break;
1221			}
1222			ireq->i_len = len;
1223			bzero(tmpstr, IEEE80211_NWID_LEN);
1224			bcopy(tmpptr, tmpstr, len);
1225			error = copyout(tmpstr, ireq->i_data,
1226			    IEEE80211_NWID_LEN);
1227			break;
1228		case IEEE80211_IOC_NUMSSIDS:
1229			ireq->i_val = 3;
1230			break;
1231		case IEEE80211_IOC_WEP:
1232			areq.an_type = AN_RID_ACTUALCFG;
1233			if (an_read_record(sc,
1234			    (struct an_ltv_gen *)&areq)) {
1235				error = EINVAL;
1236				break;
1237			}
1238			if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
1239				if (config->an_authtype &
1240				    AN_AUTHTYPE_ALLOW_UNENCRYPTED)
1241					ireq->i_val = IEEE80211_WEP_MIXED;
1242				else
1243					ireq->i_val = IEEE80211_WEP_ON;
1244
1245			} else {
1246				ireq->i_val = IEEE80211_WEP_OFF;
1247			}
1248			break;
1249		case IEEE80211_IOC_WEPKEY:
1250			/*
1251			 * XXX: I'm not entierly convinced this is
1252			 * correct, but it's what is implemented in
1253			 * ancontrol so it will have to do until we get
1254			 * access to actual Cisco code.
1255			 */
1256			if (ireq->i_val < 0 || ireq->i_val > 7) {
1257				error = EINVAL;
1258				break;
1259			}
1260			len = 0;
1261			if (ireq->i_val < 4) {
1262				areq.an_type = AN_RID_WEP_TEMP;
1263				for (i = 0; i < 5; i++) {
1264					if (an_read_record(sc,
1265					    (struct an_ltv_gen *)&areq)) {
1266						error = EINVAL;
1267						break;
1268					}
1269					if (key->kindex == 0xffff)
1270						break;
1271					if (key->kindex == ireq->i_val)
1272						len = key->klen;
1273					/* Required to get next entry */
1274					areq.an_type = AN_RID_WEP_PERM;
1275				}
1276				if (error != 0)
1277					break;
1278			}
1279			/* We aren't allowed to read the value of the
1280			 * key from the card so we just output zeros
1281			 * like we would if we could read the card, but
1282			 * denied the user access.
1283			 */
1284			bzero(tmpstr, len);
1285			ireq->i_len = len;
1286			error = copyout(tmpstr, ireq->i_data, len);
1287			break;
1288		case IEEE80211_IOC_NUMWEPKEYS:
1289			ireq->i_val = 8;
1290			break;
1291		case IEEE80211_IOC_WEPTXKEY:
1292			/*
1293			 * For some strange reason, you have to read all
1294			 * keys before you can read the txkey.
1295			 */
1296			areq.an_type = AN_RID_WEP_TEMP;
1297			for (i = 0; i < 5; i++) {
1298				if (an_read_record(sc,
1299				    (struct an_ltv_gen *)&areq)) {
1300					error = EINVAL;
1301					break;
1302				}
1303				if (key->kindex == 0xffff)
1304					break;
1305				/* Required to get next entry */
1306				areq.an_type = AN_RID_WEP_PERM;
1307			}
1308			if (error != 0)
1309				break;
1310
1311			areq.an_type = AN_RID_WEP_PERM;
1312			key->kindex = 0xffff;
1313			if (an_read_record(sc,
1314			    (struct an_ltv_gen *)&areq)) {
1315				error = EINVAL;
1316				break;
1317			}
1318			ireq->i_val = key->mac[0];
1319			break;
1320		case IEEE80211_IOC_AUTHMODE:
1321			areq.an_type = AN_RID_ACTUALCFG;
1322			if (an_read_record(sc,
1323			    (struct an_ltv_gen *)&areq)) {
1324				error = EINVAL;
1325				break;
1326			}
1327			if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
1328			    AN_AUTHTYPE_NONE) {
1329			    ireq->i_val = IEEE80211_AUTH_NONE;
1330			} else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
1331			    AN_AUTHTYPE_OPEN) {
1332			    ireq->i_val = IEEE80211_AUTH_OPEN;
1333			} else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
1334			    AN_AUTHTYPE_SHAREDKEY) {
1335			    ireq->i_val = IEEE80211_AUTH_SHARED;
1336			} else
1337				error = EINVAL;
1338			break;
1339		case IEEE80211_IOC_STATIONNAME:
1340			areq.an_type = AN_RID_ACTUALCFG;
1341			if (an_read_record(sc,
1342			    (struct an_ltv_gen *)&areq)) {
1343				error = EINVAL;
1344				break;
1345			}
1346			ireq->i_len = sizeof(config->an_nodename);
1347			tmpptr = config->an_nodename;
1348			bzero(tmpstr, IEEE80211_NWID_LEN);
1349			bcopy(tmpptr, tmpstr, ireq->i_len);
1350			error = copyout(tmpstr, ireq->i_data,
1351			    IEEE80211_NWID_LEN);
1352			break;
1353		case IEEE80211_IOC_CHANNEL:
1354			areq.an_type = AN_RID_STATUS;
1355			if (an_read_record(sc,
1356			    (struct an_ltv_gen *)&areq)) {
1357				error = EINVAL;
1358				break;
1359			}
1360			ireq->i_val = status->an_cur_channel;
1361			break;
1362		case IEEE80211_IOC_POWERSAVE:
1363			areq.an_type = AN_RID_ACTUALCFG;
1364			if (an_read_record(sc,
1365			    (struct an_ltv_gen *)&areq)) {
1366				error = EINVAL;
1367				break;
1368			}
1369			if (config->an_psave_mode == AN_PSAVE_NONE) {
1370				ireq->i_val = IEEE80211_POWERSAVE_OFF;
1371			} else if (config->an_psave_mode == AN_PSAVE_CAM) {
1372				ireq->i_val = IEEE80211_POWERSAVE_CAM;
1373			} else if (config->an_psave_mode == AN_PSAVE_PSP) {
1374				ireq->i_val = IEEE80211_POWERSAVE_PSP;
1375			} else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) {
1376				ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM;
1377			} else
1378				error = EINVAL;
1379			break;
1380		case IEEE80211_IOC_POWERSAVESLEEP:
1381			areq.an_type = AN_RID_ACTUALCFG;
1382			if (an_read_record(sc,
1383			    (struct an_ltv_gen *)&areq)) {
1384				error = EINVAL;
1385				break;
1386			}
1387			ireq->i_val = config->an_listen_interval;
1388			break;
1389		}
1390		break;
1391	case SIOCS80211:
1392		if ((error = suser(p)))
1393			goto out;
1394		areq.an_len = sizeof(areq);
1395		/*
1396		 * We need a config structure for everything but the WEP
1397		 * key management and SSIDs so we get it now so avoid
1398		 * duplicating this code every time.
1399		 */
1400		if (ireq->i_type != IEEE80211_IOC_SSID &&
1401		    ireq->i_type != IEEE80211_IOC_WEPKEY &&
1402		    ireq->i_type != IEEE80211_IOC_WEPTXKEY) {
1403			areq.an_type = AN_RID_GENCONFIG;
1404			if (an_read_record(sc,
1405			    (struct an_ltv_gen *)&areq)) {
1406				error = EINVAL;
1407				break;
1408			}
1409		}
1410		switch(ireq->i_type) {
1411		case IEEE80211_IOC_SSID:
1412			areq.an_type = AN_RID_SSIDLIST;
1413			if (an_read_record(sc,
1414			    (struct an_ltv_gen *)&areq)) {
1415				error = EINVAL;
1416				break;
1417			}
1418			if (ireq->i_len > IEEE80211_NWID_LEN) {
1419				error = EINVAL;
1420				break;
1421			}
1422			switch (ireq->i_val) {
1423			case 0:
1424				error = copyin(ireq->i_data,
1425				    ssids->an_ssid1, ireq->i_len);
1426				ssids->an_ssid1_len = ireq->i_len;
1427				break;
1428			case 1:
1429				error = copyin(ireq->i_data,
1430				    ssids->an_ssid2, ireq->i_len);
1431				ssids->an_ssid2_len = ireq->i_len;
1432				break;
1433			case 2:
1434				error = copyin(ireq->i_data,
1435				    ssids->an_ssid3, ireq->i_len);
1436				ssids->an_ssid3_len = ireq->i_len;
1437				break;
1438			default:
1439				error = EINVAL;
1440				break;
1441			}
1442			break;
1443		case IEEE80211_IOC_WEP:
1444			switch (ireq->i_val) {
1445			case IEEE80211_WEP_OFF:
1446				config->an_authtype &=
1447				    ~(AN_AUTHTYPE_PRIVACY_IN_USE |
1448				    AN_AUTHTYPE_ALLOW_UNENCRYPTED);
1449				break;
1450			case IEEE80211_WEP_ON:
1451				config->an_authtype |=
1452				    AN_AUTHTYPE_PRIVACY_IN_USE;
1453				config->an_authtype &=
1454				    ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
1455				break;
1456			case IEEE80211_WEP_MIXED:
1457				config->an_authtype |=
1458				    AN_AUTHTYPE_PRIVACY_IN_USE |
1459				    AN_AUTHTYPE_ALLOW_UNENCRYPTED;
1460				break;
1461			default:
1462				error = EINVAL;
1463				break;
1464			}
1465			break;
1466		case IEEE80211_IOC_WEPKEY:
1467			if (ireq->i_val < 0 || ireq->i_val > 7 ||
1468			    ireq->i_len > 13) {
1469				error = EINVAL;
1470				break;
1471			}
1472			error = copyin(ireq->i_data, tmpstr, 13);
1473			if (error != 0)
1474				break;
1475			bzero(&areq, sizeof(struct an_ltv_key));
1476			areq.an_len = sizeof(struct an_ltv_key);
1477			key->mac[0] = 1;	/* The others are 0. */
1478			key->kindex = ireq->i_val % 4;
1479			if (ireq->i_val < 4)
1480				areq.an_type = AN_RID_WEP_TEMP;
1481			else
1482				areq.an_type = AN_RID_WEP_PERM;
1483			key->klen = ireq->i_len;
1484			bcopy(tmpstr, key->key, key->klen);
1485			break;
1486		case IEEE80211_IOC_WEPTXKEY:
1487			if (ireq->i_val < 0 || ireq->i_val > 3) {
1488				error = EINVAL;
1489				break;
1490			}
1491			bzero(&areq, sizeof(struct an_ltv_key));
1492			areq.an_len = sizeof(struct an_ltv_key);
1493			areq.an_type = AN_RID_WEP_PERM;
1494			key->kindex = 0xffff;
1495			key->mac[0] = ireq->i_val;
1496			break;
1497		case IEEE80211_IOC_AUTHMODE:
1498			switch (ireq->i_val) {
1499			case IEEE80211_AUTH_NONE:
1500				config->an_authtype = AN_AUTHTYPE_NONE |
1501				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
1502				break;
1503			case IEEE80211_AUTH_OPEN:
1504				config->an_authtype = AN_AUTHTYPE_OPEN |
1505				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
1506				break;
1507			case IEEE80211_AUTH_SHARED:
1508				config->an_authtype = AN_AUTHTYPE_SHAREDKEY |
1509				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
1510				break;
1511			default:
1512				error = EINVAL;
1513			}
1514			break;
1515		case IEEE80211_IOC_STATIONNAME:
1516			if (ireq->i_len > 16) {
1517				error = EINVAL;
1518				break;
1519			}
1520			bzero(config->an_nodename, 16);
1521			error = copyin(ireq->i_data,
1522			    config->an_nodename, ireq->i_len);
1523			break;
1524		case IEEE80211_IOC_CHANNEL:
1525			/*
1526			 * The actual range is 1-14, but if you set it
1527			 * to 0 you get the default so we let that work
1528			 * too.
1529			 */
1530			if (ireq->i_val < 0 || ireq->i_val >14) {
1531				error = EINVAL;
1532				break;
1533			}
1534			config->an_ds_channel = ireq->i_val;
1535			break;
1536		case IEEE80211_IOC_POWERSAVE:
1537			switch (ireq->i_val) {
1538			case IEEE80211_POWERSAVE_OFF:
1539				config->an_psave_mode = AN_PSAVE_NONE;
1540				break;
1541			case IEEE80211_POWERSAVE_CAM:
1542				config->an_psave_mode = AN_PSAVE_CAM;
1543				break;
1544			case IEEE80211_POWERSAVE_PSP:
1545				config->an_psave_mode = AN_PSAVE_PSP;
1546				break;
1547			case IEEE80211_POWERSAVE_PSP_CAM:
1548				config->an_psave_mode = AN_PSAVE_PSP_CAM;
1549				break;
1550			default:
1551				error = EINVAL;
1552				break;
1553			}
1554			break;
1555		case IEEE80211_IOC_POWERSAVESLEEP:
1556			config->an_listen_interval = ireq->i_val;
1557			break;
1558		}
1559
1560		if (!error)
1561			an_setdef(sc, &areq);
1562		break;
1563	default:
1564		error = EINVAL;
1565		break;
1566	}
1567out:
1568	AN_UNLOCK(sc);
1569
1570	return(error != 0);
1571}
1572
1573static int an_init_tx_ring(sc)
1574	struct an_softc		*sc;
1575{
1576	int			i;
1577	int			id;
1578
1579	if (sc->an_gone)
1580		return (0);
1581
1582	for (i = 0; i < AN_TX_RING_CNT; i++) {
1583		if (an_alloc_nicmem(sc, 1518 +
1584		    0x44, &id))
1585			return(ENOMEM);
1586		sc->an_rdata.an_tx_fids[i] = id;
1587		sc->an_rdata.an_tx_ring[i] = 0;
1588	}
1589
1590	sc->an_rdata.an_tx_prod = 0;
1591	sc->an_rdata.an_tx_cons = 0;
1592
1593	return(0);
1594}
1595
1596static void an_init(xsc)
1597	void			*xsc;
1598{
1599	struct an_softc		*sc = xsc;
1600	struct ifnet		*ifp = &sc->arpcom.ac_if;
1601
1602	AN_LOCK(sc);
1603
1604	if (sc->an_gone) {
1605		AN_UNLOCK(sc);
1606		return;
1607	}
1608
1609	if (ifp->if_flags & IFF_RUNNING)
1610		an_stop(sc);
1611
1612	sc->an_associated = 0;
1613
1614	/* Allocate the TX buffers */
1615	if (an_init_tx_ring(sc)) {
1616		an_reset(sc);
1617		if (an_init_tx_ring(sc)) {
1618			printf("an%d: tx buffer allocation "
1619			    "failed\n", sc->an_unit);
1620			AN_UNLOCK(sc);
1621			return;
1622		}
1623	}
1624
1625	/* Set our MAC address. */
1626	bcopy((char *)&sc->arpcom.ac_enaddr,
1627	    (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN);
1628
1629	if (ifp->if_flags & IFF_BROADCAST)
1630		sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
1631	else
1632		sc->an_config.an_rxmode = AN_RXMODE_ADDR;
1633
1634	if (ifp->if_flags & IFF_MULTICAST)
1635		sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
1636
1637	/* Initialize promisc mode. */
1638	/* Kills card DJA can't TX packet in sniff mode
1639 	if (ifp->if_flags & IFF_PROMISC)
1640		sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS;
1641	*/
1642
1643	sc->an_rxmode = sc->an_config.an_rxmode;
1644
1645	/* Set the ssid list */
1646	sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
1647	sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
1648	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
1649		printf("an%d: failed to set ssid list\n", sc->an_unit);
1650		AN_UNLOCK(sc);
1651		return;
1652	}
1653
1654	/* Set the AP list */
1655	sc->an_aplist.an_type = AN_RID_APLIST;
1656	sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
1657	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
1658		printf("an%d: failed to set AP list\n", sc->an_unit);
1659		AN_UNLOCK(sc);
1660		return;
1661	}
1662
1663	/* Set the configuration in the NIC */
1664	sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
1665	sc->an_config.an_type = AN_RID_GENCONFIG;
1666	if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
1667		printf("an%d: failed to set configuration\n", sc->an_unit);
1668		AN_UNLOCK(sc);
1669		return;
1670	}
1671
1672	/* Enable the MAC */
1673	if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
1674		printf("an%d: failed to enable MAC\n", sc->an_unit);
1675		AN_UNLOCK(sc);
1676		return;
1677	}
1678
1679	if (ifp->if_flags & IFF_PROMISC)
1680		an_cmd(sc, AN_CMD_SET_MODE, 0xffff);
1681
1682	/* enable interrupts */
1683	CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
1684
1685	ifp->if_flags |= IFF_RUNNING;
1686	ifp->if_flags &= ~IFF_OACTIVE;
1687
1688	sc->an_stat_ch = timeout(an_stats_update, sc, hz);
1689	AN_UNLOCK(sc);
1690
1691	return;
1692}
1693
1694static void an_start(ifp)
1695	struct ifnet		*ifp;
1696{
1697	struct an_softc		*sc;
1698	struct mbuf		*m0 = NULL;
1699	struct an_txframe_802_3	tx_frame_802_3;
1700	struct ether_header	*eh;
1701	int			id;
1702	int			idx;
1703	unsigned char           txcontrol;
1704
1705	sc = ifp->if_softc;
1706
1707	if (sc->an_gone)
1708		return;
1709
1710	if (ifp->if_flags & IFF_OACTIVE)
1711		return;
1712
1713	if (!sc->an_associated)
1714		return;
1715
1716	idx = sc->an_rdata.an_tx_prod;
1717	bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3));
1718
1719	while(sc->an_rdata.an_tx_ring[idx] == 0) {
1720		IF_DEQUEUE(&ifp->if_snd, m0);
1721		if (m0 == NULL)
1722			break;
1723
1724		id = sc->an_rdata.an_tx_fids[idx];
1725		eh = mtod(m0, struct ether_header *);
1726
1727		bcopy((char *)&eh->ether_dhost,
1728		    (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN);
1729		bcopy((char *)&eh->ether_shost,
1730		    (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN);
1731
1732		tx_frame_802_3.an_tx_802_3_payload_len =
1733		  m0->m_pkthdr.len - 12;  /* minus src/dest mac & type */
1734
1735                m_copydata(m0, sizeof(struct ether_header) - 2 ,
1736                    tx_frame_802_3.an_tx_802_3_payload_len,
1737                    (caddr_t)&sc->an_txbuf);
1738
1739		txcontrol = AN_TXCTL_8023;
1740		/* write the txcontrol only */
1741		an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
1742			      sizeof(txcontrol));
1743
1744		/* 802_3 header */
1745		an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3,
1746			      sizeof(struct an_txframe_802_3));
1747
1748		/* in mbuf header type is just before payload */
1749		an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf,
1750			    tx_frame_802_3.an_tx_802_3_payload_len);
1751
1752		/*
1753		 * If there's a BPF listner, bounce a copy of
1754		 * this frame to him.
1755		 */
1756		if (ifp->if_bpf)
1757			bpf_mtap(ifp, m0);
1758
1759		m_freem(m0);
1760		m0 = NULL;
1761
1762		sc->an_rdata.an_tx_ring[idx] = id;
1763		if (an_cmd(sc, AN_CMD_TX, id))
1764			printf("an%d: xmit failed\n", sc->an_unit);
1765
1766		AN_INC(idx, AN_TX_RING_CNT);
1767	}
1768
1769	if (m0 != NULL)
1770		ifp->if_flags |= IFF_OACTIVE;
1771
1772	sc->an_rdata.an_tx_prod = idx;
1773
1774	/*
1775	 * Set a timeout in case the chip goes out to lunch.
1776	 */
1777	ifp->if_timer = 5;
1778
1779	return;
1780}
1781
1782void an_stop(sc)
1783	struct an_softc		*sc;
1784{
1785	struct ifnet		*ifp;
1786	int			i;
1787
1788	AN_LOCK(sc);
1789
1790	if (sc->an_gone) {
1791		AN_UNLOCK(sc);
1792		return;
1793	}
1794
1795	ifp = &sc->arpcom.ac_if;
1796
1797	an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
1798	CSR_WRITE_2(sc, AN_INT_EN, 0);
1799	an_cmd(sc, AN_CMD_DISABLE, 0);
1800
1801	for (i = 0; i < AN_TX_RING_CNT; i++)
1802		an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
1803
1804	untimeout(an_stats_update, sc, sc->an_stat_ch);
1805
1806	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1807
1808	AN_UNLOCK(sc);
1809
1810	return;
1811}
1812
1813static void an_watchdog(ifp)
1814	struct ifnet		*ifp;
1815{
1816	struct an_softc		*sc;
1817
1818	sc = ifp->if_softc;
1819	AN_LOCK(sc);
1820
1821	if (sc->an_gone) {
1822		AN_UNLOCK(sc);
1823		return;
1824	}
1825
1826	printf("an%d: device timeout\n", sc->an_unit);
1827
1828	an_reset(sc);
1829	an_init(sc);
1830
1831	ifp->if_oerrors++;
1832	AN_UNLOCK(sc);
1833
1834	return;
1835}
1836
1837void an_shutdown(dev)
1838	device_t		dev;
1839{
1840	struct an_softc		*sc;
1841
1842	sc = device_get_softc(dev);
1843	an_stop(sc);
1844
1845	return;
1846}
1847
1848#ifdef ANCACHE
1849/* Aironet signal strength cache code.
1850 * store signal/noise/quality on per MAC src basis in
1851 * a small fixed cache.  The cache wraps if > MAX slots
1852 * used.  The cache may be zeroed out to start over.
1853 * Two simple filters exist to reduce computation:
1854 * 1. ip only (literally 0x800) which may be used
1855 * to ignore some packets.  It defaults to ip only.
1856 * it could be used to focus on broadcast, non-IP 802.11 beacons.
1857 * 2. multicast/broadcast only.  This may be used to
1858 * ignore unicast packets and only cache signal strength
1859 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
1860 * beacons and not unicast traffic.
1861 *
1862 * The cache stores (MAC src(index), IP src (major clue), signal,
1863 *	quality, noise)
1864 *
1865 * No apologies for storing IP src here.  It's easy and saves much
1866 * trouble elsewhere.  The cache is assumed to be INET dependent,
1867 * although it need not be.
1868 *
1869 * Note: the Aironet only has a single byte of signal strength value
1870 * in the rx frame header, and it's not scaled to anything sensible.
1871 * This is kind of lame, but it's all we've got.
1872 */
1873
1874#ifdef documentation
1875
1876int an_sigitems;                                /* number of cached entries */
1877struct an_sigcache an_sigcache[MAXANCACHE];  /*  array of cache entries */
1878int an_nextitem;                                /*  index/# of entries */
1879
1880
1881#endif
1882
1883/* control variables for cache filtering.  Basic idea is
1884 * to reduce cost (e.g., to only Mobile-IP agent beacons
1885 * which are broadcast or multicast).  Still you might
1886 * want to measure signal strength anth unicast ping packets
1887 * on a pt. to pt. ant. setup.
1888 */
1889/* set true if you want to limit cache items to broadcast/mcast
1890 * only packets (not unicast).  Useful for mobile-ip beacons which
1891 * are broadcast/multicast at network layer.  Default is all packets
1892 * so ping/unicast anll work say anth pt. to pt. antennae setup.
1893 */
1894static int an_cache_mcastonly = 0;
1895SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
1896	&an_cache_mcastonly, 0, "");
1897
1898/* set true if you want to limit cache items to IP packets only
1899*/
1900static int an_cache_iponly = 1;
1901SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
1902	&an_cache_iponly, 0, "");
1903
1904/*
1905 * an_cache_store, per rx packet store signal
1906 * strength in MAC (src) indexed cache.
1907 */
1908static
1909void an_cache_store (sc, eh, m, rx_quality)
1910	struct an_softc *sc;
1911	struct ether_header *eh;
1912	struct mbuf *m;
1913	unsigned short rx_quality;
1914{
1915	struct ip *ip = 0;
1916	int i;
1917	static int cache_slot = 0; 	/* use this cache entry */
1918	static int wrapindex = 0;       /* next "free" cache entry */
1919	int saanp = 0;
1920
1921	/* filters:
1922	 * 1. ip only
1923	 * 2. configurable filter to throw out unicast packets,
1924	 * keep multicast only.
1925	 */
1926
1927	if ((ntohs(eh->ether_type) == 0x800)) {
1928		saanp = 1;
1929	}
1930
1931	/* filter for ip packets only
1932	*/
1933	if ( an_cache_iponly && !saanp) {
1934		return;
1935	}
1936
1937	/* filter for broadcast/multicast only
1938	 */
1939	if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
1940		return;
1941	}
1942
1943#ifdef SIGDEBUG
1944	printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
1945	    rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
1946#endif
1947
1948	/* find the ip header.  we want to store the ip_src
1949	 * address.
1950	 */
1951	if (saanp) {
1952		ip = mtod(m, struct ip *);
1953	}
1954
1955	/* do a linear search for a matching MAC address
1956	 * in the cache table
1957	 * . MAC address is 6 bytes,
1958	 * . var w_nextitem holds total number of entries already cached
1959	 */
1960	for (i = 0; i < sc->an_nextitem; i++) {
1961		if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc,  6 )) {
1962			/* Match!,
1963			 * so we already have this entry,
1964			 * update the data
1965			 */
1966			break;
1967		}
1968	}
1969
1970	/* did we find a matching mac address?
1971	 * if yes, then overwrite a previously existing cache entry
1972	 */
1973	if (i < sc->an_nextitem )   {
1974		cache_slot = i;
1975	}
1976	/* else, have a new address entry,so
1977	 * add this new entry,
1978	 * if table full, then we need to replace LRU entry
1979	 */
1980	else    {
1981
1982		/* check for space in cache table
1983		 * note: an_nextitem also holds number of entries
1984		 * added in the cache table
1985		 */
1986		if ( sc->an_nextitem < MAXANCACHE ) {
1987			cache_slot = sc->an_nextitem;
1988			sc->an_nextitem++;
1989			sc->an_sigitems = sc->an_nextitem;
1990		}
1991        	/* no space found, so simply wrap anth wrap index
1992		 * and "zap" the next entry
1993		 */
1994		else {
1995			if (wrapindex == MAXANCACHE) {
1996				wrapindex = 0;
1997			}
1998			cache_slot = wrapindex++;
1999		}
2000	}
2001
2002	/* invariant: cache_slot now points at some slot
2003	 * in cache.
2004	 */
2005	if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
2006		log(LOG_ERR, "an_cache_store, bad index: %d of "
2007		    "[0..%d], gross cache error\n",
2008		    cache_slot, MAXANCACHE);
2009		return;
2010	}
2011
2012	/*  store items in cache
2013	 *  .ip source address
2014	 *  .mac src
2015	 *  .signal, etc.
2016	 */
2017	if (saanp) {
2018		sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
2019	}
2020	bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc,  6);
2021
2022	sc->an_sigcache[cache_slot].signal = rx_quality;
2023
2024	return;
2025}
2026#endif
2027
2028static int an_media_change(ifp)
2029	struct ifnet		*ifp;
2030{
2031	struct an_softc *sc = ifp->if_softc;
2032	int otype = sc->an_config.an_opmode;
2033	int orate = sc->an_tx_rate;
2034
2035	if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
2036		sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
2037	else
2038		sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
2039
2040	switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) {
2041	case IFM_IEEE80211_DS1:
2042		sc->an_tx_rate = AN_RATE_1MBPS;
2043		break;
2044	case IFM_IEEE80211_DS2:
2045		sc->an_tx_rate = AN_RATE_2MBPS;
2046		break;
2047	case IFM_IEEE80211_DS5:
2048		sc->an_tx_rate = AN_RATE_5_5MBPS;
2049		break;
2050	case IFM_IEEE80211_DS11:
2051		sc->an_tx_rate = AN_RATE_11MBPS;
2052		break;
2053	case IFM_AUTO:
2054		sc->an_tx_rate = 0;
2055		break;
2056	}
2057
2058	if (otype != sc->an_config.an_opmode ||
2059	    orate != sc->an_tx_rate)
2060		an_init(sc);
2061
2062	return(0);
2063}
2064
2065static void an_media_status(ifp, imr)
2066	struct ifnet		*ifp;
2067	struct ifmediareq	*imr;
2068{
2069	struct an_ltv_status	status;
2070	struct an_softc		*sc = ifp->if_softc;
2071
2072	status.an_len = sizeof(status);
2073	status.an_type = AN_RID_STATUS;
2074	if (an_read_record(sc, (struct an_ltv_gen *)&status)) {
2075		/* If the status read fails, just lie. */
2076		imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
2077		imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
2078	}
2079
2080	if (sc->an_tx_rate == 0) {
2081		imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2082		if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
2083			imr->ifm_active |= IFM_IEEE80211_ADHOC;
2084		switch(status.an_current_tx_rate) {
2085		case AN_RATE_1MBPS:
2086			imr->ifm_active |= IFM_IEEE80211_DS1;
2087			break;
2088		case AN_RATE_2MBPS:
2089			imr->ifm_active |= IFM_IEEE80211_DS2;
2090			break;
2091		case AN_RATE_5_5MBPS:
2092			imr->ifm_active |= IFM_IEEE80211_DS5;
2093			break;
2094		case AN_RATE_11MBPS:
2095			imr->ifm_active |= IFM_IEEE80211_DS11;
2096			break;
2097		}
2098	} else {
2099		imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
2100	}
2101
2102	imr->ifm_status = IFM_AVALID;
2103	if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
2104		imr->ifm_status |= IFM_ACTIVE;
2105	else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
2106			imr->ifm_status |= IFM_ACTIVE;
2107}
2108