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