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