1 /* $NetBSD: an.c,v 1.56 2009/05/12 14:25:17 cegger Exp $ */
3 * Copyright (c) 1997, 1998, 1999
4 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
33 * $FreeBSD: src/sys/dev/an/if_an.c,v 1.12 2000/11/13 23:04:12 wpaul Exp $
36 * Copyright (c) 2004, 2005 David Young. All rights reserved.
37 * Copyright (c) 2004, 2005 OJC Technologies. All rights reserved.
38 * Copyright (c) 2004, 2005 Dayton Data Center Services, LLC. All
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the author nor the names of any co-contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY David Young AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL David Young AND CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
63 * THE POSSIBILITY OF SUCH DAMAGE.
67 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
69 * Written by Bill Paul <wpaul@ctr.columbia.edu>
70 * Electrical Engineering Department
71 * Columbia University, New York City
75 * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: an.c,v 1.56 2009/05/12 14:25:17 cegger Exp $");
84 #include <sys/param.h>
85 #include <sys/callout.h>
86 #include <sys/sysctl.h>
87 #include <sys/systm.h>
88 #include <sys/sockio.h>
90 #include <sys/kernel.h>
91 #include <sys/ucred.h>
92 #include <sys/socket.h>
93 #include <sys/device.h>
96 #include <sys/endian.h>
97 #include <sys/kauth.h>
102 #include <net/if_dl.h>
103 #include <net/if_ether.h>
104 #include <net/if_llc.h>
105 #include <net/if_media.h>
106 #include <net/if_types.h>
108 #include <net80211/ieee80211_netbsd.h>
109 #include <net80211/ieee80211_var.h>
110 #include <net80211/ieee80211_radiotap.h>
114 #include <net/bpfdesc.h>
117 #include <dev/ic/anreg.h>
118 #include <dev/ic/anvar.h>
120 static int an_reset(struct an_softc
*);
121 static void an_wait(struct an_softc
*);
122 static int an_init(struct ifnet
*);
123 static void an_stop(struct ifnet
*, int);
124 static void an_start(struct ifnet
*);
125 static void an_watchdog(struct ifnet
*);
126 static int an_ioctl(struct ifnet
*, u_long
, void *);
127 static int an_media_change(struct ifnet
*);
128 static void an_media_status(struct ifnet
*, struct ifmediareq
*);
130 static int an_set_nwkey(struct an_softc
*, struct ieee80211_nwkey
*);
131 static int an_set_nwkey_wep(struct an_softc
*, struct ieee80211_nwkey
*);
132 static int an_set_nwkey_eap(struct an_softc
*, struct ieee80211_nwkey
*);
133 static int an_get_nwkey(struct an_softc
*, struct ieee80211_nwkey
*);
134 static int an_write_wepkey(struct an_softc
*, int, struct an_wepkey
*,
137 static void an_rx_intr(struct an_softc
*);
138 static void an_tx_intr(struct an_softc
*, int);
139 static void an_linkstat_intr(struct an_softc
*);
141 static int an_cmd(struct an_softc
*, int, int);
142 static int an_seek_bap(struct an_softc
*, int, int);
143 static int an_read_bap(struct an_softc
*, int, int, void *, int);
144 static int an_write_bap(struct an_softc
*, int, int, void *, int);
145 static int an_mwrite_bap(struct an_softc
*, int, int, struct mbuf
*, int);
146 static int an_read_rid(struct an_softc
*, int, void *, int *);
147 static int an_write_rid(struct an_softc
*, int, void *, int);
149 static int an_alloc_fid(struct an_softc
*, int, int *);
151 static int an_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
156 #define DPRINTF(X) if (an_debug) printf X
157 #define DPRINTF2(X) if (an_debug > 1) printf X
158 static int an_sysctl_verify(SYSCTLFN_PROTO
, int lower
, int upper
);
159 static int an_sysctl_verify_debug(SYSCTLFN_PROTO
);
166 an_attach(struct an_softc
*sc
)
168 struct ieee80211com
*ic
= &sc
->sc_ic
;
169 struct ifnet
*ifp
= &sc
->sc_if
;
171 struct an_rid_wepkey
*akey
;
172 int buflen
, kid
, rid
;
173 int chan
, chan_min
, chan_max
;
178 if (an_reset(sc
) != 0) {
179 config_deactivate(sc
->sc_dev
);
184 /* Load factory config */
185 if (an_cmd(sc
, AN_CMD_READCFG
, 0) != 0) {
187 aprint_error_dev(sc
->sc_dev
, "failed to load config data\n");
191 /* Read the current configuration */
192 buflen
= sizeof(sc
->sc_config
);
193 if (an_read_rid(sc
, AN_RID_GENCONFIG
, &sc
->sc_config
, &buflen
) != 0) {
195 aprint_error_dev(sc
->sc_dev
, "read config failed\n");
199 /* Read the card capabilities */
200 buflen
= sizeof(sc
->sc_caps
);
201 if (an_read_rid(sc
, AN_RID_CAPABILITIES
, &sc
->sc_caps
, &buflen
) != 0) {
203 aprint_error_dev(sc
->sc_dev
, "read caps failed\n");
209 static const int dumprid
[] = {
210 AN_RID_GENCONFIG
, AN_RID_CAPABILITIES
, AN_RID_SSIDLIST
,
211 AN_RID_APLIST
, AN_RID_STATUS
, AN_RID_ENCAP
214 for (rid
= 0; rid
< sizeof(dumprid
)/sizeof(dumprid
[0]); rid
++) {
215 buflen
= sizeof(sc
->sc_buf
);
216 if (an_read_rid(sc
, dumprid
[rid
], &sc
->sc_buf
, &buflen
)
219 printf("%04x (%d):\n", dumprid
[rid
], buflen
);
220 for (i
= 0; i
< (buflen
+ 1) / 2; i
++)
221 printf(" %04x", sc
->sc_buf
.sc_val
[i
]);
227 /* Read WEP settings from persistent memory */
228 akey
= &sc
->sc_buf
.sc_wepkey
;
229 buflen
= sizeof(struct an_rid_wepkey
);
230 rid
= AN_RID_WEP_VOLATILE
; /* first persistent key */
231 while (an_read_rid(sc
, rid
, akey
, &buflen
) == 0) {
232 kid
= le16toh(akey
->an_key_index
);
233 DPRINTF(("an_attach: wep rid=0x%x len=%d(%zu) index=0x%04x "
234 "mac[0]=%02x keylen=%d\n",
235 rid
, buflen
, sizeof(*akey
), kid
,
236 akey
->an_mac_addr
[0], le16toh(akey
->an_key_len
)));
238 sc
->sc_tx_perskey
= akey
->an_mac_addr
[0];
242 if (kid
>= IEEE80211_WEP_NKID
)
244 sc
->sc_perskeylen
[kid
] = le16toh(akey
->an_key_len
);
245 sc
->sc_wepkeys
[kid
].an_wep_keylen
= -1;
246 rid
= AN_RID_WEP_PERSISTENT
; /* for next key */
247 buflen
= sizeof(struct an_rid_wepkey
);
250 aprint_normal_dev(sc
->sc_dev
, "%s %s (firmware %s)\n",
251 sc
->sc_caps
.an_manufname
, sc
->sc_caps
.an_prodname
,
252 sc
->sc_caps
.an_prodvers
);
254 memcpy(ifp
->if_xname
, device_xname(sc
->sc_dev
), IFNAMSIZ
);
257 ifp
->if_flags
= IFF_BROADCAST
| IFF_NOTRAILERS
| IFF_SIMPLEX
|
258 IFF_MULTICAST
| IFF_ALLMULTI
;
259 ifp
->if_ioctl
= an_ioctl
;
260 ifp
->if_start
= an_start
;
261 ifp
->if_init
= an_init
;
262 ifp
->if_stop
= an_stop
;
263 ifp
->if_watchdog
= an_watchdog
;
264 IFQ_SET_READY(&ifp
->if_snd
);
267 ic
->ic_phytype
= IEEE80211_T_DS
;
268 ic
->ic_opmode
= IEEE80211_M_STA
;
269 ic
->ic_caps
= IEEE80211_C_WEP
| IEEE80211_C_PMGT
| IEEE80211_C_IBSS
|
271 ic
->ic_state
= IEEE80211_S_INIT
;
272 IEEE80211_ADDR_COPY(ic
->ic_myaddr
, sc
->sc_caps
.an_oemaddr
);
274 switch (le16toh(sc
->sc_caps
.an_regdomain
)) {
276 case AN_REGDOMAIN_USA
:
277 case AN_REGDOMAIN_CANADA
:
278 chan_min
= 1; chan_max
= 11; break;
279 case AN_REGDOMAIN_EUROPE
:
280 case AN_REGDOMAIN_AUSTRALIA
:
281 chan_min
= 1; chan_max
= 13; break;
282 case AN_REGDOMAIN_JAPAN
:
283 chan_min
= 14; chan_max
= 14; break;
284 case AN_REGDOMAIN_SPAIN
:
285 chan_min
= 10; chan_max
= 11; break;
286 case AN_REGDOMAIN_FRANCE
:
287 chan_min
= 10; chan_max
= 13; break;
288 case AN_REGDOMAIN_JAPANWIDE
:
289 chan_min
= 1; chan_max
= 14; break;
292 for (chan
= chan_min
; chan
<= chan_max
; chan
++) {
293 ic
->ic_channels
[chan
].ic_freq
=
294 ieee80211_ieee2mhz(chan
, IEEE80211_CHAN_2GHZ
);
295 ic
->ic_channels
[chan
].ic_flags
= IEEE80211_CHAN_B
;
297 ic
->ic_ibss_chan
= &ic
->ic_channels
[chan_min
];
299 aprint_normal("%s: 802.11 address: %s, channel: %d-%d\n",
300 ifp
->if_xname
, ether_sprintf(ic
->ic_myaddr
), chan_min
, chan_max
);
302 /* Find supported rate */
303 for (i
= 0; i
< sizeof(sc
->sc_caps
.an_rates
); i
++) {
304 if (sc
->sc_caps
.an_rates
[i
] == 0)
306 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_rates
[
307 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_nrates
++] =
308 sc
->sc_caps
.an_rates
[i
];
312 * Call MI attach routine.
315 ieee80211_ifattach(ic
);
317 sc
->sc_newstate
= ic
->ic_newstate
;
318 ic
->ic_newstate
= an_newstate
;
320 ieee80211_media_init(ic
, an_media_change
, an_media_status
);
323 * radiotap BPF device
326 bpfattach2(ifp
, DLT_IEEE802_11_RADIO
,
327 sizeof(struct ieee80211_frame
) + 64, &sc
->sc_drvbpf
);
330 memset(&sc
->sc_rxtapu
, 0, sizeof(sc
->sc_rxtapu
));
331 sc
->sc_rxtap
.ar_ihdr
.it_len
= htole16(sizeof(sc
->sc_rxtapu
));
332 sc
->sc_rxtap
.ar_ihdr
.it_present
= htole32(AN_RX_RADIOTAP_PRESENT
);
334 memset(&sc
->sc_txtapu
, 0, sizeof(sc
->sc_txtapu
));
335 sc
->sc_txtap
.at_ihdr
.it_len
= htole16(sizeof(sc
->sc_txtapu
));
336 sc
->sc_txtap
.at_ihdr
.it_present
= htole32(AN_TX_RADIOTAP_PRESENT
);
341 ieee80211_announce(ic
);
347 * Setup sysctl(3) MIB, hw.an.*
349 * TBD condition CTLFLAG_PERMANENT on being a module or not
351 SYSCTL_SETUP(sysctl_an
, "sysctl an(4) subtree setup")
354 const struct sysctlnode
*cnode
, *rnode
;
356 if ((rc
= sysctl_createv(clog
, 0, NULL
, &rnode
,
357 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "hw", NULL
,
358 NULL
, 0, NULL
, 0, CTL_HW
, CTL_EOL
)) != 0)
361 if ((rc
= sysctl_createv(clog
, 0, &rnode
, &rnode
,
362 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "an",
363 "Cisco/Aironet 802.11 controls",
364 NULL
, 0, NULL
, 0, CTL_CREATE
, CTL_EOL
)) != 0)
367 /* control debugging printfs */
368 if ((rc
= sysctl_createv(clog
, 0, &rnode
, &cnode
,
369 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
, CTLTYPE_INT
,
370 "debug", SYSCTL_DESCR("Enable Cisco/Aironet debugging output"),
371 an_sysctl_verify_debug
, 0, &an_debug
, 0,
372 CTL_CREATE
, CTL_EOL
)) != 0)
377 printf("%s: sysctl_createv failed (rc = %d)\n", __func__
, rc
);
381 an_sysctl_verify(SYSCTLFN_ARGS
, int lower
, int upper
)
384 struct sysctlnode node
;
387 t
= *(int*)rnode
->sysctl_data
;
388 node
.sysctl_data
= &t
;
389 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
390 if (error
|| newp
== NULL
)
393 if (t
< lower
|| t
> upper
)
396 *(int*)rnode
->sysctl_data
= t
;
402 an_sysctl_verify_debug(SYSCTLFN_ARGS
)
404 return an_sysctl_verify(SYSCTLFN_CALL(rnode
), 0, 2);
406 #endif /* AN_DEBUG */
409 an_detach(struct an_softc
*sc
)
411 struct ieee80211com
*ic
= &sc
->sc_ic
;
412 struct ifnet
*ifp
= &sc
->sc_if
;
415 if (!sc
->sc_attached
)
420 ieee80211_ifdetach(ic
);
427 an_activate(device_t self
, enum devact act
)
429 struct an_softc
*sc
= device_private(self
);
432 case DVACT_DEACTIVATE
:
433 if_deactivate(&sc
->sc_if
);
443 struct an_softc
*sc
= arg
;
444 struct ifnet
*ifp
= &sc
->sc_if
;
448 if (!sc
->sc_enabled
|| !device_is_active(sc
->sc_dev
) ||
449 (ifp
->if_flags
& IFF_RUNNING
) == 0)
452 if ((ifp
->if_flags
& IFF_UP
) == 0) {
453 CSR_WRITE_2(sc
, AN_INT_EN
, 0);
454 CSR_WRITE_2(sc
, AN_EVENT_ACK
, ~0);
458 /* maximum 10 loops per interrupt */
459 for (i
= 0; i
< 10; i
++) {
460 if (!sc
->sc_enabled
|| !device_is_active(sc
->sc_dev
))
462 if (CSR_READ_2(sc
, AN_SW0
) != AN_MAGIC
) {
463 DPRINTF(("an_intr: magic number changed: %x\n",
464 CSR_READ_2(sc
, AN_SW0
)));
465 config_deactivate(sc
->sc_dev
);
468 status
= CSR_READ_2(sc
, AN_EVENT_STAT
);
469 CSR_WRITE_2(sc
, AN_EVENT_ACK
, status
& ~(AN_INTRS
));
470 if ((status
& AN_INTRS
) == 0)
473 if (status
& AN_EV_RX
)
476 if (status
& (AN_EV_TX
| AN_EV_TX_EXC
))
477 an_tx_intr(sc
, status
);
479 if (status
& AN_EV_LINKSTAT
)
480 an_linkstat_intr(sc
);
482 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 &&
483 sc
->sc_ic
.ic_state
== IEEE80211_S_RUN
&&
484 !IFQ_IS_EMPTY(&ifp
->if_snd
))
492 an_init(struct ifnet
*ifp
)
494 struct an_softc
*sc
= ifp
->if_softc
;
495 struct ieee80211com
*ic
= &sc
->sc_ic
;
498 DPRINTF(("an_init: enabled %d\n", sc
->sc_enabled
));
499 if (!sc
->sc_enabled
) {
501 (*sc
->sc_enable
)(sc
);
506 if ((error
= an_reset(sc
)) != 0) {
507 printf("%s: failed to reset\n", ifp
->if_xname
);
512 CSR_WRITE_2(sc
, AN_SW0
, AN_MAGIC
);
514 /* Allocate the TX buffers */
515 for (i
= 0; i
< AN_TX_RING_CNT
; i
++) {
516 if ((error
= an_alloc_fid(sc
, AN_TX_MAX_LEN
, &fid
)) != 0) {
517 printf("%s: failed to allocate nic memory\n",
522 DPRINTF2(("an_init: txbuf %d allocated %x\n", i
, fid
));
523 sc
->sc_txd
[i
].d_fid
= fid
;
524 sc
->sc_txd
[i
].d_inuse
= 0;
526 sc
->sc_txcur
= sc
->sc_txnext
= 0;
528 IEEE80211_ADDR_COPY(sc
->sc_config
.an_macaddr
, ic
->ic_myaddr
);
529 sc
->sc_config
.an_scanmode
= htole16(AN_SCANMODE_ACTIVE
);
530 sc
->sc_config
.an_authtype
= htole16(AN_AUTHTYPE_OPEN
); /*XXX*/
531 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
532 sc
->sc_config
.an_authtype
|=
533 htole16(AN_AUTHTYPE_PRIVACY_IN_USE
);
535 sc
->sc_config
.an_authtype
|=
536 htole16(AN_AUTHTYPE_LEAP
);
538 sc
->sc_config
.an_listen_interval
= htole16(ic
->ic_lintval
);
539 sc
->sc_config
.an_beacon_period
= htole16(ic
->ic_lintval
);
540 if (ic
->ic_flags
& IEEE80211_F_PMGTON
)
541 sc
->sc_config
.an_psave_mode
= htole16(AN_PSAVE_PSP
);
543 sc
->sc_config
.an_psave_mode
= htole16(AN_PSAVE_CAM
);
544 sc
->sc_config
.an_ds_channel
=
545 htole16(ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
));
547 switch (ic
->ic_opmode
) {
548 case IEEE80211_M_STA
:
549 sc
->sc_config
.an_opmode
=
550 htole16(AN_OPMODE_INFRASTRUCTURE_STATION
);
551 sc
->sc_config
.an_rxmode
= htole16(AN_RXMODE_BC_MC_ADDR
);
553 case IEEE80211_M_IBSS
:
554 sc
->sc_config
.an_opmode
= htole16(AN_OPMODE_IBSS_ADHOC
);
555 sc
->sc_config
.an_rxmode
= htole16(AN_RXMODE_BC_MC_ADDR
);
557 case IEEE80211_M_MONITOR
:
558 sc
->sc_config
.an_opmode
=
559 htole16(AN_OPMODE_INFRASTRUCTURE_STATION
);
560 sc
->sc_config
.an_rxmode
=
561 htole16(AN_RXMODE_80211_MONITOR_ANYBSS
);
562 sc
->sc_config
.an_authtype
= htole16(AN_AUTHTYPE_NONE
);
563 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
564 sc
->sc_config
.an_authtype
|=
565 htole16(AN_AUTHTYPE_PRIVACY_IN_USE
|
566 AN_AUTHTYPE_ALLOW_UNENCRYPTED
);
569 printf("%s: bad opmode %d\n", ifp
->if_xname
, ic
->ic_opmode
);
573 sc
->sc_config
.an_rxmode
|= htole16(AN_RXMODE_NO_8023_HEADER
);
575 /* Set the ssid list */
576 memset(&sc
->sc_buf
, 0, sizeof(sc
->sc_buf
.sc_ssidlist
));
577 sc
->sc_buf
.sc_ssidlist
.an_entry
[0].an_ssid_len
=
578 htole16(ic
->ic_des_esslen
);
579 if (ic
->ic_des_esslen
)
580 memcpy(sc
->sc_buf
.sc_ssidlist
.an_entry
[0].an_ssid
,
581 ic
->ic_des_essid
, ic
->ic_des_esslen
);
582 if (an_write_rid(sc
, AN_RID_SSIDLIST
, &sc
->sc_buf
,
583 sizeof(sc
->sc_buf
.sc_ssidlist
)) != 0) {
584 printf("%s: failed to write ssid list\n", ifp
->if_xname
);
589 /* Set the AP list */
590 memset(&sc
->sc_buf
, 0, sizeof(sc
->sc_buf
.sc_aplist
));
591 (void)an_write_rid(sc
, AN_RID_APLIST
, &sc
->sc_buf
,
592 sizeof(sc
->sc_buf
.sc_aplist
));
594 /* Set the encapsulation */
595 for (i
= 0; i
< AN_ENCAP_NENTS
; i
++) {
596 sc
->sc_buf
.sc_encap
.an_entry
[i
].an_ethertype
= htole16(0);
597 sc
->sc_buf
.sc_encap
.an_entry
[i
].an_action
=
598 htole16(AN_RXENCAP_RFC1024
| AN_TXENCAP_RFC1024
);
600 (void)an_write_rid(sc
, AN_RID_ENCAP
, &sc
->sc_buf
,
601 sizeof(sc
->sc_buf
.sc_encap
));
603 /* Set the WEP Keys */
604 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
605 an_write_wepkey(sc
, AN_RID_WEP_VOLATILE
, sc
->sc_wepkeys
,
608 /* Set the configuration */
611 printf("write config:\n");
612 for (i
= 0; i
< sizeof(sc
->sc_config
) / 2; i
++)
613 printf(" %04x", ((u_int16_t
*)&sc
->sc_config
)[i
]);
617 if (an_write_rid(sc
, AN_RID_GENCONFIG
, &sc
->sc_config
,
618 sizeof(sc
->sc_config
)) != 0) {
619 printf("%s: failed to write config\n", ifp
->if_xname
);
625 if (an_cmd(sc
, AN_CMD_ENABLE
, 0)) {
626 aprint_error_dev(sc
->sc_dev
, "failed to enable MAC\n");
630 if (ifp
->if_flags
& IFF_PROMISC
)
631 an_cmd(sc
, AN_CMD_SET_MODE
, 0xffff);
633 ifp
->if_flags
|= IFF_RUNNING
;
634 ifp
->if_flags
&= ~IFF_OACTIVE
;
635 ic
->ic_state
= IEEE80211_S_INIT
;
636 if (ic
->ic_opmode
== IEEE80211_M_MONITOR
)
637 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
639 /* enable interrupts */
640 CSR_WRITE_2(sc
, AN_INT_EN
, AN_INTRS
);
645 an_stop(struct ifnet
*ifp
, int disable
)
647 struct an_softc
*sc
= ifp
->if_softc
;
653 DPRINTF(("an_stop: disable %d\n", disable
));
656 ieee80211_new_state(&sc
->sc_ic
, IEEE80211_S_INIT
, -1);
657 if (device_is_active(sc
->sc_dev
)) {
658 an_cmd(sc
, AN_CMD_FORCE_SYNCLOSS
, 0);
659 CSR_WRITE_2(sc
, AN_INT_EN
, 0);
660 an_cmd(sc
, AN_CMD_DISABLE
, 0);
662 for (i
= 0; i
< AN_TX_RING_CNT
; i
++)
663 an_cmd(sc
, AN_CMD_DEALLOC_MEM
, sc
->sc_txd
[i
].d_fid
);
668 ifp
->if_flags
&= ~(IFF_RUNNING
|IFF_OACTIVE
);
672 (*sc
->sc_disable
)(sc
);
679 an_start(struct ifnet
*ifp
)
681 struct an_softc
*sc
= (struct an_softc
*)ifp
->if_softc
;
682 struct ieee80211com
*ic
= &sc
->sc_ic
;
683 struct ieee80211_node
*ni
;
684 struct ieee80211_frame
*wh
;
685 struct an_txframe frmhdr
;
686 struct ether_header
*eh
;
691 if (!sc
->sc_enabled
|| !device_is_active(sc
->sc_dev
)) {
692 DPRINTF(("an_start: noop: enabled %d invalid %d\n",
693 sc
->sc_enabled
, !device_is_active(sc
->sc_dev
)));
697 memset(&frmhdr
, 0, sizeof(frmhdr
));
700 if (ic
->ic_state
!= IEEE80211_S_RUN
) {
701 DPRINTF(("an_start: not running %d\n", ic
->ic_state
));
704 IFQ_POLL(&ifp
->if_snd
, m
);
706 DPRINTF2(("an_start: no pending mbuf\n"));
709 if (sc
->sc_txd
[cur
].d_inuse
) {
710 DPRINTF2(("an_start: %x/%d busy\n",
711 sc
->sc_txd
[cur
].d_fid
, cur
));
712 ifp
->if_flags
|= IFF_OACTIVE
;
715 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
719 bpf_mtap(ifp
->if_bpf
, m
);
721 eh
= mtod(m
, struct ether_header
*);
722 ni
= ieee80211_find_txnode(ic
, eh
->ether_dhost
);
724 /* NB: ieee80211_find_txnode does stat+msg */
727 if ((m
= ieee80211_encap(ic
, m
, ni
)) == NULL
)
729 ieee80211_free_node(ni
);
732 bpf_mtap(ic
->ic_rawbpf
, m
);
735 wh
= mtod(m
, struct ieee80211_frame
*);
736 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
737 wh
->i_fc
[1] |= IEEE80211_FC1_WEP
;
738 m_copydata(m
, 0, sizeof(struct ieee80211_frame
),
739 (void *)&frmhdr
.an_whdr
);
741 /* insert payload length in front of llc/snap */
742 len
= htons(m
->m_pkthdr
.len
- sizeof(struct ieee80211_frame
));
743 m_adj(m
, sizeof(struct ieee80211_frame
) - sizeof(len
));
744 if (mtod(m
, u_long
) & 0x01)
745 memcpy(mtod(m
, void *), &len
, sizeof(len
));
747 *mtod(m
, u_int16_t
*) = len
;
750 * XXX Aironet firmware apparently convert the packet
751 * with longer than 1500 bytes in length into LLC/SNAP.
752 * If we have 1500 bytes in ethernet payload, it is
753 * 1508 bytes including LLC/SNAP and will be inserted
754 * additional LLC/SNAP header with 1501-1508 in its
756 * So we skip LLC/SNAP header and force firmware to
757 * convert it to LLC/SNAP again.
759 m_adj(m
, sizeof(struct llc
));
761 frmhdr
.an_tx_ctl
= htole16(AN_TXCTL_80211
);
762 frmhdr
.an_tx_payload_len
= htole16(m
->m_pkthdr
.len
);
763 frmhdr
.an_gaplen
= htole16(AN_TXGAP_802_11
);
765 if (ic
->ic_fixed_rate
!= -1)
767 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_rates
[
768 ic
->ic_fixed_rate
] & IEEE80211_RATE_VAL
;
770 frmhdr
.an_tx_rate
= 0;
772 /* XXX radiotap for tx must be completed */
775 struct an_tx_radiotap_header
*tap
= &sc
->sc_txtap
;
776 tap
->at_rate
= ic
->ic_bss
->ni_rates
.rs_rates
[ic
->ic_bss
->ni_txrate
];
777 tap
->at_chan_freq
= htole16(ic
->ic_bss
->ni_chan
->ic_freq
);
778 tap
->at_chan_flags
= htole16(ic
->ic_bss
->ni_chan
->ic_flags
);
779 /* TBD tap->wt_flags */
780 bpf_mtap2(sc
->sc_drvbpf
, tap
, tap
->at_ihdr
.it_len
, m
);
785 if ((ifp
->if_flags
& (IFF_DEBUG
|IFF_LINK2
)) ==
786 (IFF_DEBUG
|IFF_LINK2
)) {
787 ieee80211_dump_pkt((u_int8_t
*)&frmhdr
.an_whdr
,
788 sizeof(struct ieee80211_frame
), -1, 0);
789 printf(" txctl 0x%x plen %u\n",
790 le16toh(frmhdr
.an_tx_ctl
),
791 le16toh(frmhdr
.an_tx_payload_len
));
794 if (sizeof(frmhdr
) + AN_TXGAP_802_11
+ sizeof(len
) +
795 m
->m_pkthdr
.len
> AN_TX_MAX_LEN
)
798 fid
= sc
->sc_txd
[cur
].d_fid
;
799 if (an_write_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) != 0)
801 /* dummy write to avoid seek. */
802 an_write_bap(sc
, fid
, -1, &frmhdr
, AN_TXGAP_802_11
);
803 an_mwrite_bap(sc
, fid
, -1, m
, m
->m_pkthdr
.len
);
806 DPRINTF2(("an_start: send %zu byte via %x/%d\n",
807 ntohs(len
) + sizeof(struct ieee80211_frame
),
809 sc
->sc_txd
[cur
].d_inuse
= 1;
810 if (an_cmd(sc
, AN_CMD_TX
, fid
)) {
811 printf("%s: xmit failed\n", ifp
->if_xname
);
812 sc
->sc_txd
[cur
].d_inuse
= 0;
817 AN_INC(cur
, AN_TX_RING_CNT
);
827 an_reset(struct an_softc
*sc
)
830 DPRINTF(("an_reset\n"));
835 an_cmd(sc
, AN_CMD_ENABLE
, 0);
836 an_cmd(sc
, AN_CMD_FW_RESTART
, 0);
837 an_cmd(sc
, AN_CMD_NOOP2
, 0);
839 if (an_cmd(sc
, AN_CMD_FORCE_SYNCLOSS
, 0) == ETIMEDOUT
) {
840 aprint_error_dev(sc
->sc_dev
, "reset failed\n");
844 an_cmd(sc
, AN_CMD_DISABLE
, 0);
849 an_watchdog(struct ifnet
*ifp
)
851 struct an_softc
*sc
= ifp
->if_softc
;
856 if (sc
->sc_tx_timer
) {
857 if (--sc
->sc_tx_timer
== 0) {
858 printf("%s: device timeout\n", ifp
->if_xname
);
865 ieee80211_watchdog(&sc
->sc_ic
);
869 an_ioctl(struct ifnet
*ifp
, u_long command
, void *data
)
871 struct an_softc
*sc
= ifp
->if_softc
;
874 if (!device_is_active(sc
->sc_dev
))
881 if ((error
= ifioctl_common(ifp
, command
, data
)) != 0)
883 if (ifp
->if_flags
& IFF_UP
) {
884 if (sc
->sc_enabled
) {
886 * To avoid rescanning another access point,
887 * do not call an_init() here. Instead, only
888 * reflect promisc mode settings.
890 error
= an_cmd(sc
, AN_CMD_SET_MODE
,
891 (ifp
->if_flags
& IFF_PROMISC
) ? 0xffff : 0);
893 error
= an_init(ifp
);
894 } else if (sc
->sc_enabled
)
899 error
= ether_ioctl(ifp
, command
, data
);
900 if (error
== ENETRESET
) {
901 /* we don't have multicast filter. */
905 case SIOCS80211NWKEY
:
906 error
= an_set_nwkey(sc
, (struct ieee80211_nwkey
*)data
);
908 case SIOCG80211NWKEY
:
909 error
= an_get_nwkey(sc
, (struct ieee80211_nwkey
*)data
);
912 error
= ieee80211_ioctl(&sc
->sc_ic
, command
, data
);
915 if (error
== ENETRESET
) {
917 error
= an_init(ifp
);
925 /* TBD factor with ieee80211_media_change */
927 an_media_change(struct ifnet
*ifp
)
929 struct an_softc
*sc
= ifp
->if_softc
;
930 struct ieee80211com
*ic
= &sc
->sc_ic
;
931 struct ifmedia_entry
*ime
;
932 enum ieee80211_opmode newmode
;
933 int i
, rate
, error
= 0;
935 ime
= ic
->ic_media
.ifm_cur
;
936 if (IFM_SUBTYPE(ime
->ifm_media
) == IFM_AUTO
) {
939 struct ieee80211_rateset
*rs
=
940 &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
941 rate
= ieee80211_media2rate(ime
->ifm_media
);
944 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
945 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
) == rate
)
948 if (i
== rs
->rs_nrates
)
951 if (ic
->ic_fixed_rate
!= i
) {
952 ic
->ic_fixed_rate
= i
;
956 if (ime
->ifm_media
& IFM_IEEE80211_ADHOC
)
957 newmode
= IEEE80211_M_IBSS
;
958 else if (ime
->ifm_media
& IFM_IEEE80211_HOSTAP
)
959 newmode
= IEEE80211_M_HOSTAP
;
960 else if (ime
->ifm_media
& IFM_IEEE80211_MONITOR
)
961 newmode
= IEEE80211_M_MONITOR
;
963 newmode
= IEEE80211_M_STA
;
964 if (ic
->ic_opmode
!= newmode
) {
965 ic
->ic_opmode
= newmode
;
968 if (error
== ENETRESET
) {
970 error
= an_init(ifp
);
974 ifp
->if_baudrate
= ifmedia_baudrate(ic
->ic_media
.ifm_cur
->ifm_media
);
980 an_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
982 struct an_softc
*sc
= ifp
->if_softc
;
983 struct ieee80211com
*ic
= &sc
->sc_ic
;
986 if (sc
->sc_enabled
== 0) {
987 imr
->ifm_active
= IFM_IEEE80211
| IFM_NONE
;
992 imr
->ifm_status
= IFM_AVALID
;
993 imr
->ifm_active
= IFM_IEEE80211
;
994 if (ic
->ic_state
== IEEE80211_S_RUN
)
995 imr
->ifm_status
|= IFM_ACTIVE
;
996 buflen
= sizeof(sc
->sc_buf
);
997 if (ic
->ic_fixed_rate
!= -1)
998 rate
= ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_rates
[
999 ic
->ic_fixed_rate
] & IEEE80211_RATE_VAL
;
1000 else if (an_read_rid(sc
, AN_RID_STATUS
, &sc
->sc_buf
, &buflen
) != 0)
1003 rate
= le16toh(sc
->sc_buf
.sc_status
.an_current_tx_rate
);
1004 imr
->ifm_active
|= ieee80211_rate2media(ic
, rate
, IEEE80211_MODE_11B
);
1005 switch (ic
->ic_opmode
) {
1006 case IEEE80211_M_STA
:
1008 case IEEE80211_M_IBSS
:
1009 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
1011 case IEEE80211_M_HOSTAP
:
1012 imr
->ifm_active
|= IFM_IEEE80211_HOSTAP
;
1014 case IEEE80211_M_MONITOR
:
1015 imr
->ifm_active
|= IFM_IEEE80211_MONITOR
;
1023 an_set_nwkey(struct an_softc
*sc
, struct ieee80211_nwkey
*nwkey
)
1026 struct ieee80211com
*ic
= &sc
->sc_ic
;
1030 prevauth
= sc
->sc_config
.an_authtype
;
1032 switch (nwkey
->i_wepon
) {
1033 case IEEE80211_NWKEY_OPEN
:
1034 sc
->sc_config
.an_authtype
= AN_AUTHTYPE_OPEN
;
1035 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
1038 case IEEE80211_NWKEY_WEP
:
1039 case IEEE80211_NWKEY_WEP
| IEEE80211_NWKEY_PERSIST
:
1040 error
= an_set_nwkey_wep(sc
, nwkey
);
1041 if (error
== 0 || error
== ENETRESET
) {
1042 sc
->sc_config
.an_authtype
=
1043 AN_AUTHTYPE_OPEN
| AN_AUTHTYPE_PRIVACY_IN_USE
;
1044 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
1048 case IEEE80211_NWKEY_EAP
:
1049 error
= an_set_nwkey_eap(sc
, nwkey
);
1050 if (error
== 0 || error
== ENETRESET
) {
1051 sc
->sc_config
.an_authtype
= AN_AUTHTYPE_OPEN
|
1052 AN_AUTHTYPE_PRIVACY_IN_USE
| AN_AUTHTYPE_LEAP
;
1053 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
1060 if (error
== 0 && prevauth
!= sc
->sc_config
.an_authtype
)
1066 an_set_nwkey_wep(struct an_softc
*sc
, struct ieee80211_nwkey
*nwkey
)
1068 int i
, txkey
, anysetkey
, needreset
, error
;
1069 struct an_wepkey keys
[IEEE80211_WEP_NKID
];
1072 memset(keys
, 0, sizeof(keys
));
1073 anysetkey
= needreset
= 0;
1075 /* load argument and sanity check */
1076 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1077 keys
[i
].an_wep_keylen
= nwkey
->i_key
[i
].i_keylen
;
1078 if (keys
[i
].an_wep_keylen
< 0)
1080 if (keys
[i
].an_wep_keylen
!= 0 &&
1081 keys
[i
].an_wep_keylen
< IEEE80211_WEP_KEYLEN
)
1083 if (keys
[i
].an_wep_keylen
> sizeof(keys
[i
].an_wep_key
))
1085 if ((error
= copyin(nwkey
->i_key
[i
].i_keydat
,
1086 keys
[i
].an_wep_key
, keys
[i
].an_wep_keylen
)) != 0)
1090 txkey
= nwkey
->i_defkid
- 1;
1092 if (txkey
>= IEEE80211_WEP_NKID
)
1094 /* default key must have a valid value */
1095 if (keys
[txkey
].an_wep_keylen
== 0 ||
1096 (keys
[txkey
].an_wep_keylen
< 0 &&
1097 sc
->sc_perskeylen
[txkey
] == 0))
1101 DPRINTF(("an_set_nwkey_wep: %s: %sold(%d:%d,%d,%d,%d) "
1102 "pers(%d:%d,%d,%d,%d) new(%d:%d,%d,%d,%d)\n",
1103 device_xname(sc
->sc_dev
),
1104 ((nwkey
->i_wepon
& IEEE80211_NWKEY_PERSIST
) ? "persist: " : ""),
1106 sc
->sc_wepkeys
[0].an_wep_keylen
, sc
->sc_wepkeys
[1].an_wep_keylen
,
1107 sc
->sc_wepkeys
[2].an_wep_keylen
, sc
->sc_wepkeys
[3].an_wep_keylen
,
1109 sc
->sc_perskeylen
[0], sc
->sc_perskeylen
[1],
1110 sc
->sc_perskeylen
[2], sc
->sc_perskeylen
[3],
1112 keys
[0].an_wep_keylen
, keys
[1].an_wep_keylen
,
1113 keys
[2].an_wep_keylen
, keys
[3].an_wep_keylen
));
1114 if (!(nwkey
->i_wepon
& IEEE80211_NWKEY_PERSIST
)) {
1115 /* set temporary keys */
1116 sc
->sc_tx_key
= txkey
;
1117 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1118 if (keys
[i
].an_wep_keylen
< 0)
1120 memcpy(&sc
->sc_wepkeys
[i
], &keys
[i
], sizeof(keys
[i
]));
1123 /* set persist keys */
1125 /* prepare to write nvram */
1126 if (!sc
->sc_enabled
) {
1128 (*sc
->sc_enable
)(sc
);
1131 error
= an_write_wepkey(sc
,
1132 AN_RID_WEP_PERSISTENT
, keys
, txkey
);
1134 (*sc
->sc_disable
)(sc
);
1137 an_cmd(sc
, AN_CMD_DISABLE
, 0);
1138 error
= an_write_wepkey(sc
,
1139 AN_RID_WEP_PERSISTENT
, keys
, txkey
);
1140 an_cmd(sc
, AN_CMD_ENABLE
, 0);
1146 sc
->sc_tx_perskey
= txkey
;
1147 if (sc
->sc_tx_key
>= 0) {
1151 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1152 if (sc
->sc_wepkeys
[i
].an_wep_keylen
>= 0) {
1153 memset(&sc
->sc_wepkeys
[i
].an_wep_key
, 0,
1154 sizeof(sc
->sc_wepkeys
[i
].an_wep_key
));
1155 sc
->sc_wepkeys
[i
].an_wep_keylen
= -1;
1158 if (keys
[i
].an_wep_keylen
>= 0)
1159 sc
->sc_perskeylen
[i
] = keys
[i
].an_wep_keylen
;
1163 /* firmware restart to reload persistent key */
1166 if (anysetkey
|| needreset
)
1172 an_set_nwkey_eap(struct an_softc
*sc
, struct ieee80211_nwkey
*nwkey
)
1175 struct ifnet
*ifp
= &sc
->sc_if
;
1176 struct an_rid_leapkey
*key
;
1177 u_int16_t unibuf
[sizeof(key
->an_key
)];
1178 static const int leap_rid
[] = { AN_RID_LEAP_PASS
, AN_RID_LEAP_USER
};
1183 if (nwkey
->i_key
[0].i_keydat
== NULL
&&
1184 nwkey
->i_key
[1].i_keydat
== NULL
)
1186 if (!sc
->sc_enabled
)
1188 an_cmd(sc
, AN_CMD_DISABLE
, 0);
1189 key
= &sc
->sc_buf
.sc_leapkey
;
1190 for (i
= 0; i
< 2; i
++) {
1191 if (nwkey
->i_key
[i
].i_keydat
== NULL
)
1193 len
= nwkey
->i_key
[i
].i_keylen
;
1194 if (len
> sizeof(key
->an_key
))
1196 memset(key
, 0, sizeof(*key
));
1197 key
->an_key_len
= htole16(len
);
1198 if ((error
= copyin(nwkey
->i_key
[i
].i_keydat
, key
->an_key
,
1203 * Cisco seems to use PasswordHash and PasswordHashHash
1204 * in RFC-2759 (MS-CHAP-V2).
1206 memset(unibuf
, 0, sizeof(unibuf
));
1207 /* XXX: convert password to unicode */
1208 for (i
= 0; i
< len
; i
++)
1209 unibuf
[i
] = key
->an_key
[i
];
1210 /* set PasswordHash */
1212 MD4Update(&ctx
, (u_int8_t
*)unibuf
, len
* 2);
1213 MD4Final(key
->an_key
, &ctx
);
1214 /* set PasswordHashHash */
1216 MD4Update(&ctx
, key
->an_key
, 16);
1217 MD4Final(key
->an_key
+ 16, &ctx
);
1218 key
->an_key_len
= htole16(32);
1220 if ((error
= an_write_rid(sc
, leap_rid
[i
], key
,
1221 sizeof(*key
))) != 0) {
1222 printf("%s: LEAP set failed\n", ifp
->if_xname
);
1226 error
= an_cmd(sc
, AN_CMD_ENABLE
, 0);
1228 printf("%s: an_set_nwkey: failed to enable MAC\n",
1236 an_get_nwkey(struct an_softc
*sc
, struct ieee80211_nwkey
*nwkey
)
1241 if (sc
->sc_config
.an_authtype
& AN_AUTHTYPE_LEAP
)
1242 nwkey
->i_wepon
= IEEE80211_NWKEY_EAP
;
1243 else if (sc
->sc_config
.an_authtype
& AN_AUTHTYPE_PRIVACY_IN_USE
)
1244 nwkey
->i_wepon
= IEEE80211_NWKEY_WEP
;
1246 nwkey
->i_wepon
= IEEE80211_NWKEY_OPEN
;
1247 if (sc
->sc_tx_key
== -1)
1248 nwkey
->i_defkid
= sc
->sc_tx_perskey
+ 1;
1250 nwkey
->i_defkid
= sc
->sc_tx_key
+ 1;
1251 if (nwkey
->i_key
[0].i_keydat
== NULL
)
1253 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1254 if (nwkey
->i_key
[i
].i_keydat
== NULL
)
1256 /* do not show any keys to non-root user */
1257 /* XXX-elad: why is this inside a loop? */
1258 if ((error
= kauth_authorize_network(curlwp
->l_cred
,
1259 KAUTH_NETWORK_INTERFACE
,
1260 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV
, sc
->sc_ic
.ic_ifp
,
1261 KAUTH_ARG(SIOCG80211NWKEY
), NULL
)) != 0)
1263 nwkey
->i_key
[i
].i_keylen
= sc
->sc_wepkeys
[i
].an_wep_keylen
;
1264 if (nwkey
->i_key
[i
].i_keylen
< 0) {
1265 if (sc
->sc_perskeylen
[i
] == 0)
1266 nwkey
->i_key
[i
].i_keylen
= 0;
1269 if ((error
= copyout(sc
->sc_wepkeys
[i
].an_wep_key
,
1270 nwkey
->i_key
[i
].i_keydat
,
1271 sc
->sc_wepkeys
[i
].an_wep_keylen
)) != 0)
1278 an_write_wepkey(struct an_softc
*sc
, int type
, struct an_wepkey
*keys
, int kid
)
1281 struct an_rid_wepkey
*akey
;
1284 akey
= &sc
->sc_buf
.sc_wepkey
;
1285 memset(akey
, 0, sizeof(struct an_rid_wepkey
));
1286 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
1287 if (keys
[i
].an_wep_keylen
< 0 ||
1288 keys
[i
].an_wep_keylen
> sizeof(akey
->an_key
))
1290 akey
->an_key_len
= htole16(keys
[i
].an_wep_keylen
);
1291 akey
->an_key_index
= htole16(i
);
1292 akey
->an_mac_addr
[0] = 1; /* default mac */
1293 memcpy(akey
->an_key
, keys
[i
].an_wep_key
, keys
[i
].an_wep_keylen
);
1294 if ((error
= an_write_rid(sc
, type
, akey
, sizeof(*akey
))) != 0)
1298 akey
->an_key_index
= htole16(0xffff);
1299 akey
->an_mac_addr
[0] = kid
;
1300 akey
->an_key_len
= htole16(0);
1301 memset(akey
->an_key
, 0, sizeof(akey
->an_key
));
1302 error
= an_write_rid(sc
, type
, akey
, sizeof(*akey
));
1309 an_dump_pkt(const char *devname
, struct mbuf
*m
)
1312 uint8_t *pkt
= mtod(m
, uint8_t *);
1313 const char *delim
= "";
1316 printf("%s: pkt ", devname
);
1317 col
= col0
= strlen(devname
) + strlen(": pkt ");
1318 for (i
= 0; i
< m
->m_len
; i
++) {
1319 printf("%s%02x", delim
, pkt
[i
]);
1324 printf("\n%*s", col0
, "");
1333 #endif /* AN_DEBUG */
1336 * Low level functions
1340 an_rx_intr(struct an_softc
*sc
)
1342 struct ieee80211com
*ic
= &sc
->sc_ic
;
1343 struct ifnet
*ifp
= &sc
->sc_if
;
1344 struct ieee80211_frame_min
*wh
;
1345 struct ieee80211_node
*ni
;
1346 struct an_rxframe frmhdr
;
1349 int fid
, gaplen
, len
, off
;
1352 fid
= CSR_READ_2(sc
, AN_RX_FID
);
1354 /* First read in the frame header */
1355 if (an_read_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) != 0) {
1356 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1358 DPRINTF(("an_rx_intr: read fid %x failed\n", fid
));
1363 if ((ifp
->if_flags
& (IFF_DEBUG
|IFF_LINK2
)) == (IFF_DEBUG
|IFF_LINK2
)) {
1364 ieee80211_dump_pkt((u_int8_t
*)&frmhdr
.an_whdr
,
1365 sizeof(struct ieee80211_frame
), frmhdr
.an_rx_rate
,
1366 frmhdr
.an_rx_signal_strength
);
1367 printf(" time 0x%x status 0x%x plen %u chan %u"
1368 " plcp %02x %02x %02x %02x gap %u\n",
1369 le32toh(frmhdr
.an_rx_time
), le16toh(frmhdr
.an_rx_status
),
1370 le16toh(frmhdr
.an_rx_payload_len
), frmhdr
.an_rx_chan
,
1371 frmhdr
.an_plcp_hdr
[0], frmhdr
.an_plcp_hdr
[1],
1372 frmhdr
.an_plcp_hdr
[2], frmhdr
.an_plcp_hdr
[3],
1373 le16toh(frmhdr
.an_gaplen
));
1377 status
= le16toh(frmhdr
.an_rx_status
);
1378 if ((status
& AN_STAT_ERRSTAT
) != 0 &&
1379 ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1380 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1382 DPRINTF(("an_rx_intr: fid %x status %x\n", fid
, status
));
1386 /* the payload length field includes a 16-bit "mystery field" */
1387 len
= le16toh(frmhdr
.an_rx_payload_len
) - sizeof(uint16_t);
1388 off
= ALIGN(sizeof(struct ieee80211_frame
));
1390 if (off
+ len
> MCLBYTES
) {
1391 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1392 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1394 DPRINTF(("an_rx_intr: oversized packet %d\n", len
));
1400 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1402 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1404 DPRINTF(("an_rx_intr: MGET failed\n"));
1407 if (off
+ len
+ AN_GAPLEN_MAX
> MHLEN
) {
1408 MCLGET(m
, M_DONTWAIT
);
1409 if ((m
->m_flags
& M_EXT
) == 0) {
1410 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1413 DPRINTF(("an_rx_intr: MCLGET failed\n"));
1417 m
->m_data
+= off
- sizeof(struct ieee80211_frame
);
1419 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1420 gaplen
= le16toh(frmhdr
.an_gaplen
);
1421 if (gaplen
> AN_GAPLEN_MAX
) {
1422 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1425 DPRINTF(("%s: gap too long\n", __func__
));
1429 * We don't need the 16-bit mystery field (payload length?),
1430 * so read it into the region reserved for the 802.11 header.
1432 * When Cisco Aironet 350 cards w/ firmware version 5 or
1433 * greater operate with certain Cisco 350 APs,
1434 * the "gap" is filled with the SNAP header. Read
1435 * it in after the 802.11 header.
1437 gap
= m
->m_data
+ sizeof(struct ieee80211_frame
) -
1439 an_read_bap(sc
, fid
, -1, gap
, gaplen
+ sizeof(u_int16_t
));
1441 if ((ifp
->if_flags
& (IFF_DEBUG
|IFF_LINK2
)) ==
1442 (IFF_DEBUG
|IFF_LINK2
)) {
1445 for (i
= 0; i
< gaplen
+ sizeof(u_int16_t
); i
++)
1446 printf(" %02x", gap
[i
]);
1453 an_read_bap(sc
, fid
, -1,
1454 m
->m_data
+ sizeof(struct ieee80211_frame
) + gaplen
, len
);
1455 m
->m_pkthdr
.len
= m
->m_len
= sizeof(struct ieee80211_frame
) + gaplen
+
1458 memcpy(m
->m_data
, &frmhdr
.an_whdr
, sizeof(struct ieee80211_frame
));
1459 m
->m_pkthdr
.rcvif
= ifp
;
1460 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_RX
);
1463 if (sc
->sc_drvbpf
) {
1464 struct an_rx_radiotap_header
*tap
= &sc
->sc_rxtap
;
1466 tap
->ar_rate
= frmhdr
.an_rx_rate
;
1467 tap
->ar_chan_flags
= htole16(ic
->ic_bss
->ni_chan
->ic_flags
);
1468 tap
->ar_chan_freq
= htole16(ic
->ic_bss
->ni_chan
->ic_freq
);
1469 tap
->ar_antsignal
= frmhdr
.an_rx_signal_strength
;
1470 if ((le16toh(frmhdr
.an_rx_status
) & AN_STAT_BADCRC
) ||
1471 (le16toh(frmhdr
.an_rx_status
) & AN_STAT_ERRSTAT
) ||
1472 (le16toh(frmhdr
.an_rx_status
) & AN_STAT_UNDECRYPTABLE
))
1473 tap
->ar_flags
|= IEEE80211_RADIOTAP_F_BADFCS
;
1475 bpf_mtap2(sc
->sc_drvbpf
, tap
, tap
->ar_ihdr
.it_len
, m
);
1478 wh
= mtod(m
, struct ieee80211_frame_min
*);
1479 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
1481 * WEP is decrypted by hardware. Clear WEP bit
1482 * header for ieee80211_input().
1484 wh
->i_fc
[1] &= ~IEEE80211_FC1_WEP
;
1489 an_dump_pkt(device_xname(sc
->sc_dev
), m
);
1490 #endif /* AN_DEBUG */
1492 ni
= ieee80211_find_rxnode(ic
, wh
);
1493 ieee80211_input(ic
, m
, ni
, frmhdr
.an_rx_signal_strength
,
1494 le32toh(frmhdr
.an_rx_time
));
1495 ieee80211_free_node(ni
);
1499 an_tx_intr(struct an_softc
*sc
, int status
)
1501 struct ifnet
*ifp
= &sc
->sc_if
;
1504 sc
->sc_tx_timer
= 0;
1505 ifp
->if_flags
&= ~IFF_OACTIVE
;
1507 fid
= CSR_READ_2(sc
, AN_TX_CMP_FID
);
1508 CSR_WRITE_2(sc
, AN_EVENT_ACK
, status
& (AN_EV_TX
| AN_EV_TX_EXC
));
1510 if (status
& AN_EV_TX_EXC
)
1516 if (sc
->sc_txd
[cur
].d_fid
== fid
) {
1517 sc
->sc_txd
[cur
].d_inuse
= 0;
1518 DPRINTF2(("an_tx_intr: sent %x/%d\n", fid
, cur
));
1519 AN_INC(cur
, AN_TX_RING_CNT
);
1522 for (cur
= 0; cur
< AN_TX_RING_CNT
; cur
++) {
1523 if (fid
== sc
->sc_txd
[cur
].d_fid
) {
1524 sc
->sc_txd
[cur
].d_inuse
= 0;
1528 if (ifp
->if_flags
& IFF_DEBUG
)
1529 printf("%s: tx mismatch: "
1530 "expected %x(%d), actual %x(%d)\n",
1531 device_xname(sc
->sc_dev
),
1532 sc
->sc_txd
[sc
->sc_txcur
].d_fid
, sc
->sc_txcur
,
1540 an_linkstat_intr(struct an_softc
*sc
)
1542 struct ieee80211com
*ic
= &sc
->sc_ic
;
1545 status
= CSR_READ_2(sc
, AN_LINKSTAT
);
1546 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_LINKSTAT
);
1547 DPRINTF(("an_linkstat_intr: status 0x%x\n", status
));
1549 if (status
== AN_LINKSTAT_ASSOCIATED
) {
1550 if (ic
->ic_state
!= IEEE80211_S_RUN
||
1551 ic
->ic_opmode
== IEEE80211_M_IBSS
)
1552 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
1554 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1555 ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
1559 /* Must be called at proper protection level! */
1561 an_cmd(struct an_softc
*sc
, int cmd
, int val
)
1565 /* make sure that previous command completed */
1566 if (CSR_READ_2(sc
, AN_COMMAND
) & AN_CMD_BUSY
) {
1567 if (sc
->sc_if
.if_flags
& IFF_DEBUG
)
1568 printf("%s: command 0x%x busy\n", device_xname(sc
->sc_dev
),
1569 CSR_READ_2(sc
, AN_COMMAND
));
1570 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_CLR_STUCK_BUSY
);
1573 CSR_WRITE_2(sc
, AN_PARAM0
, val
);
1574 CSR_WRITE_2(sc
, AN_PARAM1
, 0);
1575 CSR_WRITE_2(sc
, AN_PARAM2
, 0);
1576 CSR_WRITE_2(sc
, AN_COMMAND
, cmd
);
1578 if (cmd
== AN_CMD_FW_RESTART
) {
1579 /* XXX: should sleep here */
1583 for (i
= 0; i
< AN_TIMEOUT
; i
++) {
1584 if (CSR_READ_2(sc
, AN_EVENT_STAT
) & AN_EV_CMD
)
1589 status
= CSR_READ_2(sc
, AN_STATUS
);
1591 /* clear stuck command busy if necessary */
1592 if (CSR_READ_2(sc
, AN_COMMAND
) & AN_CMD_BUSY
)
1593 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_CLR_STUCK_BUSY
);
1595 /* Ack the command */
1596 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_CMD
);
1598 if (i
== AN_TIMEOUT
) {
1599 if (sc
->sc_if
.if_flags
& IFF_DEBUG
)
1600 printf("%s: command 0x%x param 0x%x timeout\n",
1601 device_xname(sc
->sc_dev
), cmd
, val
);
1604 if (status
& AN_STAT_CMD_RESULT
) {
1605 if (sc
->sc_if
.if_flags
& IFF_DEBUG
)
1606 printf("%s: command 0x%x param 0x%x status 0x%x "
1607 "resp 0x%x 0x%x 0x%x\n",
1608 device_xname(sc
->sc_dev
), cmd
, val
, status
,
1609 CSR_READ_2(sc
, AN_RESP0
), CSR_READ_2(sc
, AN_RESP1
),
1610 CSR_READ_2(sc
, AN_RESP2
));
1619 * Wait for firmware come up after power enabled.
1622 an_wait(struct an_softc
*sc
)
1626 CSR_WRITE_2(sc
, AN_COMMAND
, AN_CMD_NOOP2
);
1627 for (i
= 0; i
< 3*hz
; i
++) {
1628 if (CSR_READ_2(sc
, AN_EVENT_STAT
) & AN_EV_CMD
)
1630 (void)tsleep(sc
, PWAIT
, "anatch", 1);
1632 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_CMD
);
1636 an_seek_bap(struct an_softc
*sc
, int id
, int off
)
1640 CSR_WRITE_2(sc
, AN_SEL0
, id
);
1641 CSR_WRITE_2(sc
, AN_OFF0
, off
);
1643 for (i
= 0; ; i
++) {
1644 status
= CSR_READ_2(sc
, AN_OFF0
);
1645 if ((status
& AN_OFF_BUSY
) == 0)
1647 if (i
== AN_TIMEOUT
) {
1648 printf("%s: timeout in an_seek_bap to 0x%x/0x%x\n",
1649 device_xname(sc
->sc_dev
), id
, off
);
1650 sc
->sc_bap_off
= AN_OFF_ERR
; /* invalidate */
1655 if (status
& AN_OFF_ERR
) {
1656 aprint_error_dev(sc
->sc_dev
, "failed in an_seek_bap to 0x%x/0x%x\n",
1658 sc
->sc_bap_off
= AN_OFF_ERR
; /* invalidate */
1662 sc
->sc_bap_off
= off
;
1667 an_read_bap(struct an_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
1674 off
= sc
->sc_bap_off
;
1675 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
1676 if ((error
= an_seek_bap(sc
, id
, off
)) != 0)
1680 cnt
= (buflen
+ 1) / 2;
1681 CSR_READ_MULTI_STREAM_2(sc
, AN_DATA0
, (u_int16_t
*)buf
, cnt
);
1682 sc
->sc_bap_off
+= cnt
* 2;
1687 an_write_bap(struct an_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
1694 off
= sc
->sc_bap_off
;
1695 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
1696 if ((error
= an_seek_bap(sc
, id
, off
)) != 0)
1700 cnt
= (buflen
+ 1) / 2;
1701 CSR_WRITE_MULTI_STREAM_2(sc
, AN_DATA0
, (u_int16_t
*)buf
, cnt
);
1702 sc
->sc_bap_off
+= cnt
* 2;
1707 an_mwrite_bap(struct an_softc
*sc
, int id
, int off
, struct mbuf
*m
, int totlen
)
1709 int error
, len
, cnt
;
1712 off
= sc
->sc_bap_off
;
1713 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
1714 if ((error
= an_seek_bap(sc
, id
, off
)) != 0)
1718 for (len
= 0; m
!= NULL
; m
= m
->m_next
) {
1721 len
= min(m
->m_len
, totlen
);
1723 if ((mtod(m
, u_long
) & 0x1) || (len
& 0x1)) {
1724 m_copydata(m
, 0, totlen
, (void *)&sc
->sc_buf
.sc_txbuf
);
1725 cnt
= (totlen
+ 1) / 2;
1726 CSR_WRITE_MULTI_STREAM_2(sc
, AN_DATA0
,
1727 sc
->sc_buf
.sc_val
, cnt
);
1732 CSR_WRITE_MULTI_STREAM_2(sc
, AN_DATA0
, mtod(m
, u_int16_t
*),
1737 sc
->sc_bap_off
= off
;
1742 an_alloc_fid(struct an_softc
*sc
, int len
, int *idp
)
1746 if (an_cmd(sc
, AN_CMD_ALLOC_MEM
, len
)) {
1747 aprint_error_dev(sc
->sc_dev
, "failed to allocate %d bytes on NIC\n",
1752 for (i
= 0; i
< AN_TIMEOUT
; i
++) {
1753 if (CSR_READ_2(sc
, AN_EVENT_STAT
) & AN_EV_ALLOC
)
1755 if (i
== AN_TIMEOUT
) {
1756 printf("%s: timeout in alloc\n", device_xname(sc
->sc_dev
));
1762 *idp
= CSR_READ_2(sc
, AN_ALLOC_FID
);
1763 CSR_WRITE_2(sc
, AN_EVENT_ACK
, AN_EV_ALLOC
);
1768 an_read_rid(struct an_softc
*sc
, int rid
, void *buf
, int *buflenp
)
1773 /* Tell the NIC to enter record read mode. */
1774 error
= an_cmd(sc
, AN_CMD_ACCESS
| AN_ACCESS_READ
, rid
);
1778 /* length in byte, including length itself */
1779 error
= an_read_bap(sc
, rid
, 0, &len
, sizeof(len
));
1783 len
= le16toh(len
) - 2;
1784 if (*buflenp
< len
) {
1785 aprint_error_dev(sc
->sc_dev
, "record buffer is too small, "
1786 "rid=%x, size=%d, len=%d\n",
1787 rid
, *buflenp
, len
);
1791 return an_read_bap(sc
, rid
, sizeof(len
), buf
, len
);
1795 an_write_rid(struct an_softc
*sc
, int rid
, void *buf
, int buflen
)
1800 /* length in byte, including length itself */
1801 len
= htole16(buflen
+ 2);
1803 error
= an_write_bap(sc
, rid
, 0, &len
, sizeof(len
));
1806 error
= an_write_bap(sc
, rid
, sizeof(len
), buf
, buflen
);
1810 return an_cmd(sc
, AN_CMD_ACCESS
| AN_ACCESS_WRITE
, rid
);
1814 an_newstate(struct ieee80211com
*ic
, enum ieee80211_state nstate
, int arg
)
1816 struct an_softc
*sc
= (struct an_softc
*)ic
->ic_ifp
->if_softc
;
1817 struct ieee80211_node
*ni
= ic
->ic_bss
;
1818 enum ieee80211_state ostate
;
1821 ostate
= ic
->ic_state
;
1822 DPRINTF(("an_newstate: %s -> %s\n", ieee80211_state_name
[ostate
],
1823 ieee80211_state_name
[nstate
]));
1826 case IEEE80211_S_INIT
:
1827 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
1828 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);
1830 case IEEE80211_S_SCAN
:
1831 case IEEE80211_S_AUTH
:
1832 case IEEE80211_S_ASSOC
:
1833 ic
->ic_state
= nstate
; /* NB: skip normal ieee80211 handling */
1836 case IEEE80211_S_RUN
:
1837 buflen
= sizeof(sc
->sc_buf
);
1838 an_read_rid(sc
, AN_RID_STATUS
, &sc
->sc_buf
, &buflen
);
1839 IEEE80211_ADDR_COPY(ni
->ni_bssid
,
1840 sc
->sc_buf
.sc_status
.an_cur_bssid
);
1841 IEEE80211_ADDR_COPY(ni
->ni_macaddr
, ni
->ni_bssid
);
1842 ni
->ni_chan
= &ic
->ic_channels
[
1843 le16toh(sc
->sc_buf
.sc_status
.an_cur_channel
)];
1844 ni
->ni_esslen
= le16toh(sc
->sc_buf
.sc_status
.an_ssidlen
);
1845 if (ni
->ni_esslen
> IEEE80211_NWID_LEN
)
1846 ni
->ni_esslen
= IEEE80211_NWID_LEN
; /*XXX*/
1847 memcpy(ni
->ni_essid
, sc
->sc_buf
.sc_status
.an_ssid
,
1849 ni
->ni_rates
= ic
->ic_sup_rates
[IEEE80211_MODE_11B
]; /*XXX*/
1850 if (ic
->ic_ifp
->if_flags
& IFF_DEBUG
) {
1851 printf("%s: ", device_xname(sc
->sc_dev
));
1852 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1853 printf("associated ");
1855 printf("synchronized ");
1856 printf("with %s ssid ", ether_sprintf(ni
->ni_bssid
));
1857 ieee80211_print_essid(ni
->ni_essid
, ni
->ni_esslen
);
1858 printf(" channel %u start %uMb\n",
1859 le16toh(sc
->sc_buf
.sc_status
.an_cur_channel
),
1860 le16toh(sc
->sc_buf
.sc_status
.an_current_tx_rate
)/2);
1867 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);