2 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the NetBSD
19 * Foundation, Inc. and its contributors.
20 * 4. Neither the name of The NetBSD Foundation nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
36 * $NetBSD: awi.c,v 1.26 2000/07/21 04:48:55 onoe Exp $
37 * $FreeBSD: src/sys/dev/awi/awi.c,v 1.10.2.2 2003/01/23 21:06:42 sam Exp $
38 * $DragonFly: src/sys/dev/netif/awi/awi.c,v 1.30 2007/01/03 13:33:02 swildner Exp $
41 * Driver for AMD 802.11 firmware.
42 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
44 * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
49 * - flush tx queue on resynch.
50 * - clear oactive on "down".
51 * - rewrite copy-into-mbuf code
52 * - mgmt state machine gets stuck retransmitting assoc requests.
54 * - fix device reset so it's more likely to work
55 * - show status goo through ifmedia.
58 * - deal with more 802.11 frames.
59 * - send reassoc request
60 * - deal with reassoc response
61 * - send/deal with disassociation
62 * - deal with "full" access points (no room for me).
67 * - need ioctls for poking at the MIBs
68 * - implement ad-hoc mode (including bss creation).
69 * - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
70 * (focus on inf. mode since that will be needed for ietf)
71 * - deal with DH vs. FH versions of the card
72 * - deal with faster cards (2mb/s)
73 * - ?WEP goo (mmm, rc4) (it looks not particularly useful).
75 * - common 802.11 mibish things.
76 * - common 802.11 media layer.
80 * Driver for AMD 802.11 PCnetMobile firmware.
81 * Uses am79c930 chip driver to talk to firmware running on the am79c930.
83 * The initial version of the driver was written by
84 * Bill Sommerfeld <sommerfeld@netbsd.org>.
85 * Then the driver module completely rewritten to support cards with DS phy
86 * and to support adhoc mode by Atsushi Onoe <onoe@netbsd.org>
91 #include <sys/param.h>
92 #include <sys/systm.h>
93 #include <sys/kernel.h>
95 #include <sys/malloc.h>
97 #include <sys/socket.h>
98 #include <sys/sockio.h>
99 #include <sys/errno.h>
100 #include <sys/syslog.h>
102 #include <sys/thread2.h>
105 #include <net/ifq_var.h>
106 #include <net/if_dl.h>
107 #include <net/ethernet.h>
108 #include <net/if_media.h>
109 #include <net/if_llc.h>
110 #include <netproto/802_11/ieee80211.h>
111 #include <netproto/802_11/ieee80211_ioctl.h>
114 #include <netinet/in.h>
115 #include <netinet/in_systm.h>
116 #include <netinet/in_var.h>
117 #include <netinet/ip.h>
118 #include <netinet/if_ether.h>
122 #include <net/bpfdesc.h>
124 #include <machine/cpu.h>
126 #include <dev/netif/awi/am79c930reg.h>
127 #include <dev/netif/awi/am79c930var.h>
128 #include <dev/netif/awi/awireg.h>
129 #include <dev/netif/awi/awivar.h>
131 static int awi_ioctl (struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*);
132 static int awi_media_rate2opt (struct awi_softc
*sc
, int rate
);
133 static int awi_media_opt2rate (struct awi_softc
*sc
, int opt
);
134 static int awi_media_change (struct ifnet
*ifp
);
135 static void awi_media_status (struct ifnet
*ifp
, struct ifmediareq
*imr
);
136 static void awi_watchdog (struct ifnet
*ifp
);
137 static void awi_start (struct ifnet
*ifp
);
138 static void awi_txint (struct awi_softc
*sc
);
139 static struct mbuf
* awi_fix_txhdr (struct awi_softc
*sc
, struct mbuf
*m0
);
140 static struct mbuf
* awi_fix_rxhdr (struct awi_softc
*sc
, struct mbuf
*m0
);
141 static void awi_input (struct awi_softc
*sc
, struct mbuf
*m
, u_int32_t rxts
, u_int8_t rssi
);
142 static void awi_rxint (struct awi_softc
*sc
);
143 static struct mbuf
* awi_devget (struct awi_softc
*sc
, u_int32_t off
, u_int16_t len
);
144 static int awi_init_hw (struct awi_softc
*sc
);
145 static int awi_init_mibs (struct awi_softc
*sc
);
146 static int awi_init_txrx (struct awi_softc
*sc
);
147 static void awi_stop_txrx (struct awi_softc
*sc
);
148 static int awi_start_scan (struct awi_softc
*sc
);
149 static int awi_next_scan (struct awi_softc
*sc
);
150 static void awi_stop_scan (struct awi_softc
*sc
);
151 static void awi_recv_beacon (struct awi_softc
*sc
, struct mbuf
*m0
, u_int32_t rxts
, u_int8_t rssi
);
152 static int awi_set_ss (struct awi_softc
*sc
);
153 static void awi_try_sync (struct awi_softc
*sc
);
154 static void awi_sync_done (struct awi_softc
*sc
);
155 static void awi_send_deauth (struct awi_softc
*sc
);
156 static void awi_send_auth (struct awi_softc
*sc
, int seq
);
157 static void awi_recv_auth (struct awi_softc
*sc
, struct mbuf
*m0
);
158 static void awi_send_asreq (struct awi_softc
*sc
, int reassoc
);
159 static void awi_recv_asresp (struct awi_softc
*sc
, struct mbuf
*m0
);
160 static int awi_mib (struct awi_softc
*sc
, u_int8_t cmd
, u_int8_t mib
);
161 static int awi_cmd_scan (struct awi_softc
*sc
);
162 static int awi_cmd (struct awi_softc
*sc
, u_int8_t cmd
);
163 static void awi_cmd_done (struct awi_softc
*sc
);
164 static int awi_next_txd (struct awi_softc
*sc
, int len
, u_int32_t
*framep
, u_int32_t
*ntxdp
);
165 static int awi_intr_lock (struct awi_softc
*sc
);
166 static void awi_intr_unlock (struct awi_softc
*sc
);
167 static int awi_cmd_wait (struct awi_softc
*sc
);
168 static void awi_print_essid (u_int8_t
*essid
);
170 DECLARE_DUMMY_MODULE(if_awi
);
173 static void awi_dump_pkt (struct awi_softc
*sc
, struct mbuf
*m
, int rssi
);
176 #define AWI_DUMP_MASK(fc0) (1 << (((fc0) & IEEE80211_FC0_SUBTYPE_MASK) >> 4))
177 int awi_dump_mask
= AWI_DUMP_MASK(IEEE80211_FC0_SUBTYPE_BEACON
);
178 int awi_dump_hdr
= 0;
179 int awi_dump_len
= 28;
182 #define AWI_BPF_NORM 0
183 #define AWI_BPF_RAW 1
184 #define AWI_BPF_MTAP(sc, m, raw) do { \
185 if ((sc)->sc_rawbpf == (raw)) \
186 BPF_MTAP((sc)->sc_ifp, (m)); \
190 #define llc_snap llc_un.type_snap
193 devclass_t awi_devclass
;
196 awi_attach(struct awi_softc
*sc
)
198 struct ifnet
*ifp
= sc
->sc_ifp
;
203 struct ifmediareq imr
;
206 * Even if we can sleep in initialization state,
207 * all other processes (e.g. ifconfig) have to wait for
208 * completion of attaching interface.
210 sc
->sc_status
= AWI_ST_INIT
;
211 TAILQ_INIT(&sc
->sc_scan
);
212 error
= awi_init_hw(sc
);
217 error
= awi_init_mibs(sc
);
224 ifp
->if_start
= awi_start
;
225 ifp
->if_ioctl
= awi_ioctl
;
226 ifp
->if_watchdog
= awi_watchdog
;
227 ifp
->if_mtu
= ETHERMTU
;
228 ifp
->if_hdrlen
= sizeof(struct ieee80211_frame
) +
229 sizeof(struct ether_header
);
230 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
231 #ifdef IFF_NOTRAILERS
232 ifp
->if_flags
|= IFF_NOTRAILERS
;
234 ifq_set_maxlen(&ifp
->if_snd
, ifqmaxlen
);
235 ifq_set_ready(&ifp
->if_snd
);
236 memcpy(sc
->sc_ec
.ac_enaddr
, sc
->sc_mib_addr
.aMAC_Address
,
239 if_printf(ifp
, "IEEE802.11 %s %dMbps (firmware %s)\n",
240 sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
? "FH" : "DS",
241 sc
->sc_tx_rate
/ 10, sc
->sc_banner
);
242 ether_ifattach(ifp
, sc
->sc_mib_addr
.aMAC_Address
, NULL
);
244 lwkt_serialize_enter(ifp
->if_serializer
);
246 ifmedia_init(&sc
->sc_media
, 0, awi_media_change
, awi_media_status
);
247 phy_rates
= sc
->sc_mib_phy
.aSuprt_Data_Rates
;
248 for (i
= 0; i
< phy_rates
[1]; i
++) {
249 mword
= awi_media_rate2opt(sc
, AWI_80211_RATE(phy_rates
[2 + i
]));
252 mword
|= IFM_IEEE80211
;
253 ifmedia_add(&sc
->sc_media
, mword
, 0, NULL
);
254 ifmedia_add(&sc
->sc_media
,
255 mword
| IFM_IEEE80211_ADHOC
, 0, NULL
);
256 if (sc
->sc_mib_phy
.IEEE_PHY_Type
!= AWI_PHY_TYPE_FH
)
257 ifmedia_add(&sc
->sc_media
,
258 mword
| IFM_IEEE80211_ADHOC
| IFM_FLAG0
, 0, NULL
);
260 awi_media_status(ifp
, &imr
);
261 ifmedia_set(&sc
->sc_media
, imr
.ifm_active
);
262 /* Attach is successful. */
264 lwkt_serialize_exit(ifp
->if_serializer
);
269 awi_ioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
271 struct awi_softc
*sc
= ifp
->if_softc
;
272 struct ifreq
*ifr
= (struct ifreq
*)data
;
273 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
275 struct ieee80211_nwid nwid
;
282 ifp
->if_flags
|= IFF_UP
;
283 switch (ifa
->ifa_addr
->sa_family
) {
286 arp_ifinit((void *)ifp
, ifa
);
292 sc
->sc_format_llc
= !(ifp
->if_flags
& IFF_LINK0
);
293 if (!(ifp
->if_flags
& IFF_UP
)) {
294 if (sc
->sc_enabled
) {
297 (*sc
->sc_disable
)(sc
);
302 error
= awi_init(sc
);
307 error
= ENETRESET
; /*XXX*/
309 * Do not rescan BSS. Rather, just reset multicast filter.
311 if (error
== ENETRESET
) {
313 error
= awi_init(sc
);
319 if (ifr
->ifr_mtu
> ETHERMTU
)
322 ifp
->if_mtu
= ifr
->ifr_mtu
;
325 error
= suser_cred(cr
, NULL_CRED_OKAY
); /* EPERM if no proc */
328 error
= copyin(ifr
->ifr_data
, &nwid
, sizeof(nwid
));
331 if (nwid
.i_len
> IEEE80211_NWID_LEN
) {
335 if (sc
->sc_mib_mac
.aDesired_ESS_ID
[1] == nwid
.i_len
&&
336 memcmp(&sc
->sc_mib_mac
.aDesired_ESS_ID
[2], nwid
.i_nwid
,
339 memset(sc
->sc_mib_mac
.aDesired_ESS_ID
, 0, AWI_ESS_ID_SIZE
);
340 sc
->sc_mib_mac
.aDesired_ESS_ID
[0] = IEEE80211_ELEMID_SSID
;
341 sc
->sc_mib_mac
.aDesired_ESS_ID
[1] = nwid
.i_len
;
342 memcpy(&sc
->sc_mib_mac
.aDesired_ESS_ID
[2], nwid
.i_nwid
,
344 if (sc
->sc_enabled
) {
346 error
= awi_init(sc
);
350 if (ifp
->if_flags
& IFF_RUNNING
)
351 p
= sc
->sc_bss
.essid
;
353 p
= sc
->sc_mib_mac
.aDesired_ESS_ID
;
354 error
= copyout(p
+ 1, ifr
->ifr_data
, 1 + IEEE80211_NWID_LEN
);
356 case SIOCS80211NWKEY
:
357 error
= suser_cred(cr
, NULL_CRED_OKAY
); /* EPERM if no proc */
360 error
= awi_wep_setnwkey(sc
, (struct ieee80211_nwkey
*)data
);
362 case SIOCG80211NWKEY
:
363 error
= awi_wep_getnwkey(sc
, (struct ieee80211_nwkey
*)data
);
367 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->sc_media
, cmd
);
370 error
= awi_wicfg(ifp
, cmd
, data
);
377 awi_media_rate2opt(struct awi_softc
*sc
, int rate
)
384 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
385 mword
= IFM_IEEE80211_FH1
;
387 mword
= IFM_IEEE80211_DS1
;
390 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
391 mword
= IFM_IEEE80211_FH2
;
393 mword
= IFM_IEEE80211_DS2
;
396 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_DS
)
397 mword
= IFM_IEEE80211_DS5
;
400 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_DS
)
401 mword
= IFM_IEEE80211_DS11
;
408 awi_media_opt2rate(struct awi_softc
*sc
, int opt
)
413 switch (IFM_SUBTYPE(opt
)) {
414 case IFM_IEEE80211_FH1
:
415 case IFM_IEEE80211_FH2
:
416 if (sc
->sc_mib_phy
.IEEE_PHY_Type
!= AWI_PHY_TYPE_FH
)
419 case IFM_IEEE80211_DS1
:
420 case IFM_IEEE80211_DS2
:
421 case IFM_IEEE80211_DS5
:
422 case IFM_IEEE80211_DS11
:
423 if (sc
->sc_mib_phy
.IEEE_PHY_Type
!= AWI_PHY_TYPE_DS
)
428 switch (IFM_SUBTYPE(opt
)) {
429 case IFM_IEEE80211_FH1
:
430 case IFM_IEEE80211_DS1
:
433 case IFM_IEEE80211_FH2
:
434 case IFM_IEEE80211_DS2
:
437 case IFM_IEEE80211_DS5
:
440 case IFM_IEEE80211_DS11
:
448 * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
451 awi_media_change(struct ifnet
*ifp
)
453 struct awi_softc
*sc
= ifp
->if_softc
;
454 struct ifmedia_entry
*ime
;
459 ime
= sc
->sc_media
.ifm_cur
;
460 rate
= awi_media_opt2rate(sc
, ime
->ifm_media
);
463 if (rate
!= sc
->sc_tx_rate
) {
464 phy_rates
= sc
->sc_mib_phy
.aSuprt_Data_Rates
;
465 for (i
= 0; i
< phy_rates
[1]; i
++) {
466 if (rate
== AWI_80211_RATE(phy_rates
[2 + i
]))
469 if (i
== phy_rates
[1])
472 if (ime
->ifm_media
& IFM_IEEE80211_ADHOC
) {
473 sc
->sc_mib_local
.Network_Mode
= 0;
474 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
477 sc
->sc_no_bssid
= (ime
->ifm_media
& IFM_FLAG0
) ? 1 : 0;
479 sc
->sc_mib_local
.Network_Mode
= 1;
481 if (sc
->sc_enabled
) {
483 error
= awi_init(sc
);
489 awi_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
491 struct awi_softc
*sc
= ifp
->if_softc
;
493 imr
->ifm_status
= IFM_AVALID
;
494 if (ifp
->if_flags
& IFF_RUNNING
)
495 imr
->ifm_status
|= IFM_ACTIVE
;
496 imr
->ifm_active
= IFM_IEEE80211
;
497 imr
->ifm_active
|= awi_media_rate2opt(sc
, sc
->sc_tx_rate
);
498 if (sc
->sc_mib_local
.Network_Mode
== 0) {
499 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
501 imr
->ifm_active
|= IFM_FLAG0
;
508 struct awi_softc
*sc
= arg
;
510 int error
, handled
= 0;
512 if (!sc
->sc_enabled
|| !sc
->sc_enab_intr
|| sc
->sc_invalid
)
515 am79c930_gcr_setbits(&sc
->sc_chip
,
516 AM79C930_GCR_DISPWDN
| AM79C930_GCR_ECINT
);
517 awi_write_1(sc
, AWI_DIS_PWRDN
, 1);
520 error
= awi_intr_lock(sc
);
523 status
= awi_read_1(sc
, AWI_INTSTAT
);
524 awi_write_1(sc
, AWI_INTSTAT
, 0);
525 awi_write_1(sc
, AWI_INTSTAT
, 0);
526 status
|= awi_read_1(sc
, AWI_INTSTAT2
) << 8;
527 awi_write_1(sc
, AWI_INTSTAT2
, 0);
530 if (!sc
->sc_cmd_inprog
)
531 status
&= ~AWI_INT_CMD
; /* make sure */
535 if (status
& AWI_INT_RX
)
537 if (status
& AWI_INT_TX
)
539 if (status
& AWI_INT_CMD
)
541 if (status
& AWI_INT_SCAN_CMPLT
) {
542 if (sc
->sc_status
== AWI_ST_SCAN
&&
543 sc
->sc_mgt_timer
> 0)
547 am79c930_gcr_clearbits(&sc
->sc_chip
, AM79C930_GCR_DISPWDN
);
548 awi_write_1(sc
, AWI_DIS_PWRDN
, 0);
553 awi_init(struct awi_softc
*sc
)
555 struct ifnet
*ifp
= sc
->sc_ifp
;
558 struct ifmultiaddr
*ifma
;
560 /* reinitialize muticast filter */
562 ifp
->if_flags
|= IFF_ALLMULTI
;
563 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 0;
564 if (ifp
->if_flags
& IFF_PROMISC
) {
565 sc
->sc_mib_mac
.aPromiscuous_Enable
= 1;
568 sc
->sc_mib_mac
.aPromiscuous_Enable
= 0;
569 if (ifp
->if_amcount
!= 0)
571 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
572 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
574 if (n
== AWI_GROUP_ADDR_SIZE
)
576 memcpy(sc
->sc_mib_addr
.aGroup_Addresses
[n
],
577 LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
),
581 for (; n
< AWI_GROUP_ADDR_SIZE
; n
++)
582 memset(sc
->sc_mib_addr
.aGroup_Addresses
[n
], 0, ETHER_ADDR_LEN
);
583 ifp
->if_flags
&= ~IFF_ALLMULTI
;
584 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 1;
587 #ifdef notdef /* allow non-encrypted frame for receiving. */
588 sc
->sc_mib_mgt
.Wep_Required
= sc
->sc_wep_algo
!= NULL
? 1 : 0;
590 if (!sc
->sc_enabled
) {
593 (*sc
->sc_enable
)(sc
);
594 sc
->sc_status
= AWI_ST_INIT
;
595 error
= awi_init_hw(sc
);
599 ostatus
= sc
->sc_status
;
600 sc
->sc_status
= AWI_ST_INIT
;
601 if ((error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_LOCAL
)) != 0 ||
602 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_ADDR
)) != 0 ||
603 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MAC
)) != 0 ||
604 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MGT
)) != 0 ||
605 (error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_PHY
)) != 0) {
609 if (ifp
->if_flags
& IFF_RUNNING
)
610 sc
->sc_status
= AWI_ST_RUNNING
;
612 if (ostatus
== AWI_ST_INIT
) {
613 error
= awi_init_txrx(sc
);
617 error
= awi_start_scan(sc
);
623 awi_stop(struct awi_softc
*sc
)
625 struct ifnet
*ifp
= sc
->sc_ifp
;
628 sc
->sc_status
= AWI_ST_INIT
;
629 if (!sc
->sc_invalid
) {
631 if (sc
->sc_mib_local
.Network_Mode
&&
632 sc
->sc_status
> AWI_ST_AUTH
)
636 ifp
->if_flags
&= ~(IFF_RUNNING
|IFF_OACTIVE
);
638 sc
->sc_tx_timer
= sc
->sc_rx_timer
= sc
->sc_mgt_timer
= 0;
639 IF_DRAIN(&sc
->sc_mgtq
);
640 ifq_purge(&ifp
->if_snd
);
641 while ((bp
= TAILQ_FIRST(&sc
->sc_scan
)) != NULL
) {
642 TAILQ_REMOVE(&sc
->sc_scan
, bp
, list
);
648 awi_watchdog(struct ifnet
*ifp
)
650 struct awi_softc
*sc
= ifp
->if_softc
;
652 if (sc
->sc_invalid
) {
657 if (sc
->sc_tx_timer
&& --sc
->sc_tx_timer
== 0) {
658 if_printf(ifp
, "transmit timeout\n");
661 if (sc
->sc_rx_timer
&& --sc
->sc_rx_timer
== 0) {
662 if (ifp
->if_flags
& IFF_DEBUG
) {
663 if_printf(ifp
, "no recent beacons from %6D; rescanning\n",
664 sc
->sc_bss
.bssid
, ":");
666 ifp
->if_flags
&= ~IFF_RUNNING
;
669 if (sc
->sc_mgt_timer
&& --sc
->sc_mgt_timer
== 0) {
670 switch (sc
->sc_status
) {
684 if (sc
->sc_tx_timer
== 0 && sc
->sc_rx_timer
== 0 &&
685 sc
->sc_mgt_timer
== 0)
692 awi_start(struct ifnet
*ifp
)
694 struct awi_softc
*sc
= ifp
->if_softc
;
696 u_int32_t txd
, frame
, ntxd
;
702 IF_DEQUEUE(&sc
->sc_mgtq
, m0
);
704 if (awi_next_txd(sc
, m0
->m_pkthdr
.len
, &frame
, &ntxd
)) {
705 IF_PREPEND(&sc
->sc_mgtq
, m0
);
706 ifp
->if_flags
|= IFF_OACTIVE
;
710 if (!(ifp
->if_flags
& IFF_RUNNING
))
712 m0
= ifq_poll(&ifp
->if_snd
);
715 len
= m0
->m_pkthdr
.len
+ sizeof(struct ieee80211_frame
);
716 if (sc
->sc_format_llc
)
717 len
+= sizeof(struct llc
) -
718 sizeof(struct ether_header
);
719 if (sc
->sc_wep_algo
!= NULL
)
720 len
+= IEEE80211_WEP_IVLEN
+
721 IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_CRCLEN
;
722 if (awi_next_txd(sc
, len
, &frame
, &ntxd
)) {
723 ifp
->if_flags
|= IFF_OACTIVE
;
726 ifq_dequeue(&ifp
->if_snd
, m0
);
727 AWI_BPF_MTAP(sc
, m0
, AWI_BPF_NORM
);
728 m0
= awi_fix_txhdr(sc
, m0
);
729 if (sc
->sc_wep_algo
!= NULL
&& m0
!= NULL
)
730 m0
= awi_wep_encrypt(sc
, m0
, 1);
739 awi_dump_pkt(sc
, m0
, -1);
741 AWI_BPF_MTAP(sc
, m0
, AWI_BPF_RAW
);
743 for (m
= m0
; m
!= NULL
; m
= m
->m_next
) {
744 awi_write_bytes(sc
, frame
+ len
, mtod(m
, u_int8_t
*),
749 rate
= sc
->sc_tx_rate
; /*XXX*/
750 awi_write_1(sc
, ntxd
+ AWI_TXD_STATE
, 0);
751 awi_write_4(sc
, txd
+ AWI_TXD_START
, frame
);
752 awi_write_4(sc
, txd
+ AWI_TXD_NEXT
, ntxd
);
753 awi_write_4(sc
, txd
+ AWI_TXD_LENGTH
, len
);
754 awi_write_1(sc
, txd
+ AWI_TXD_RATE
, rate
);
755 awi_write_4(sc
, txd
+ AWI_TXD_NDA
, 0);
756 awi_write_4(sc
, txd
+ AWI_TXD_NRA
, 0);
757 awi_write_1(sc
, txd
+ AWI_TXD_STATE
, AWI_TXD_ST_OWN
);
758 sc
->sc_txnext
= ntxd
;
762 if (sc
->sc_tx_timer
== 0)
767 kprintf("awi_start: sent %d txdone %d txnext %d txbase %d txend %d\n", sent
, sc
->sc_txdone
, sc
->sc_txnext
, sc
->sc_txbase
, sc
->sc_txend
);
773 awi_txint(struct awi_softc
*sc
)
775 struct ifnet
*ifp
= sc
->sc_ifp
;
778 while (sc
->sc_txdone
!= sc
->sc_txnext
) {
779 flags
= awi_read_1(sc
, sc
->sc_txdone
+ AWI_TXD_STATE
);
780 if ((flags
& AWI_TXD_ST_OWN
) || !(flags
& AWI_TXD_ST_DONE
))
782 if (flags
& AWI_TXD_ST_ERROR
)
784 sc
->sc_txdone
= awi_read_4(sc
, sc
->sc_txdone
+ AWI_TXD_NEXT
) &
788 ifp
->if_flags
&= ~IFF_OACTIVE
;
791 kprintf("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
792 sc
->sc_txdone
, sc
->sc_txnext
, sc
->sc_txbase
, sc
->sc_txend
);
798 awi_fix_txhdr(struct awi_softc
*sc
, struct mbuf
*m0
)
800 struct ether_header eh
;
801 struct ieee80211_frame
*wh
;
804 if (m0
->m_len
< sizeof(eh
)) {
805 m0
= m_pullup(m0
, sizeof(eh
));
809 memcpy(&eh
, mtod(m0
, caddr_t
), sizeof(eh
));
810 if (sc
->sc_format_llc
) {
811 m_adj(m0
, sizeof(struct ether_header
) - sizeof(struct llc
));
812 llc
= mtod(m0
, struct llc
*);
813 llc
->llc_dsap
= llc
->llc_ssap
= LLC_SNAP_LSAP
;
814 llc
->llc_control
= LLC_UI
;
815 llc
->llc_snap
.org_code
[0] = llc
->llc_snap
.org_code
[1] =
816 llc
->llc_snap
.org_code
[2] = 0;
817 llc
->llc_snap
.ether_type
= eh
.ether_type
;
819 M_PREPEND(m0
, sizeof(struct ieee80211_frame
), MB_DONTWAIT
);
822 wh
= mtod(m0
, struct ieee80211_frame
*);
824 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_DATA
;
825 LE_WRITE_2(wh
->i_dur
, 0);
826 LE_WRITE_2(wh
->i_seq
, 0);
827 if (sc
->sc_mib_local
.Network_Mode
) {
828 wh
->i_fc
[1] = IEEE80211_FC1_DIR_TODS
;
829 memcpy(wh
->i_addr1
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
830 memcpy(wh
->i_addr2
, eh
.ether_shost
, ETHER_ADDR_LEN
);
831 memcpy(wh
->i_addr3
, eh
.ether_dhost
, ETHER_ADDR_LEN
);
833 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
834 memcpy(wh
->i_addr1
, eh
.ether_dhost
, ETHER_ADDR_LEN
);
835 memcpy(wh
->i_addr2
, eh
.ether_shost
, ETHER_ADDR_LEN
);
836 memcpy(wh
->i_addr3
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
842 awi_fix_rxhdr(struct awi_softc
*sc
, struct mbuf
*m0
)
844 struct ieee80211_frame wh
;
845 struct ether_header
*eh
;
848 if (m0
->m_len
< sizeof(wh
)) {
852 llc
= (struct llc
*)(mtod(m0
, caddr_t
) + sizeof(wh
));
853 if (llc
->llc_dsap
== LLC_SNAP_LSAP
&&
854 llc
->llc_ssap
== LLC_SNAP_LSAP
&&
855 llc
->llc_control
== LLC_UI
&&
856 llc
->llc_snap
.org_code
[0] == 0 &&
857 llc
->llc_snap
.org_code
[1] == 0 &&
858 llc
->llc_snap
.org_code
[2] == 0) {
859 memcpy(&wh
, mtod(m0
, caddr_t
), sizeof(wh
));
860 m_adj(m0
, sizeof(wh
) + sizeof(*llc
) - sizeof(*eh
));
861 eh
= mtod(m0
, struct ether_header
*);
862 switch (wh
.i_fc
[1] & IEEE80211_FC1_DIR_MASK
) {
863 case IEEE80211_FC1_DIR_NODS
:
864 memcpy(eh
->ether_dhost
, wh
.i_addr1
, ETHER_ADDR_LEN
);
865 memcpy(eh
->ether_shost
, wh
.i_addr2
, ETHER_ADDR_LEN
);
867 case IEEE80211_FC1_DIR_TODS
:
868 memcpy(eh
->ether_dhost
, wh
.i_addr3
, ETHER_ADDR_LEN
);
869 memcpy(eh
->ether_shost
, wh
.i_addr2
, ETHER_ADDR_LEN
);
871 case IEEE80211_FC1_DIR_FROMDS
:
872 memcpy(eh
->ether_dhost
, wh
.i_addr1
, ETHER_ADDR_LEN
);
873 memcpy(eh
->ether_shost
, wh
.i_addr3
, ETHER_ADDR_LEN
);
875 case IEEE80211_FC1_DIR_DSTODS
:
880 /* assuming ethernet encapsulation, just strip 802.11 header */
881 m_adj(m0
, sizeof(wh
));
883 if (ALIGN(mtod(m0
, caddr_t
) + sizeof(struct ether_header
)) !=
884 (u_int
)(mtod(m0
, caddr_t
) + sizeof(struct ether_header
))) {
885 /* XXX: we loose to estimate the type of encapsulation */
886 struct mbuf
*n
, *n0
, **np
;
893 while (m0
->m_pkthdr
.len
> off
) {
896 n
= m_getl(m0
->m_pkthdr
.len
- off
, MB_DONTWAIT
,
897 MT_DATA
, n0
== NULL
? M_PKTHDR
: 0, &msize
);
904 M_MOVE_PKTHDR(n
, m0
);
907 + sizeof(struct ether_header
))
908 - sizeof(struct ether_header
);
909 n
->m_len
-= newdata
- n
->m_data
;
912 if (n
->m_len
> m0
->m_pkthdr
.len
- off
)
913 n
->m_len
= m0
->m_pkthdr
.len
- off
;
914 m_copydata(m0
, off
, n
->m_len
, mtod(n
, caddr_t
));
926 awi_input(struct awi_softc
*sc
, struct mbuf
*m
, u_int32_t rxts
, u_int8_t rssi
)
928 struct ifnet
*ifp
= sc
->sc_ifp
;
929 struct ieee80211_frame
*wh
;
931 /* trim CRC here for WEP can find its own CRC at the end of packet. */
932 m_adj(m
, -ETHER_CRC_LEN
);
933 AWI_BPF_MTAP(sc
, m
, AWI_BPF_RAW
);
934 wh
= mtod(m
, struct ieee80211_frame
*);
935 if ((wh
->i_fc
[0] & IEEE80211_FC0_VERSION_MASK
) !=
936 IEEE80211_FC0_VERSION_0
) {
937 if_printf(ifp
, "receive packet with wrong version: %x\n",
943 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
944 m
= awi_wep_encrypt(sc
, m
, 0);
949 wh
= mtod(m
, struct ieee80211_frame
*);
953 awi_dump_pkt(sc
, m
, rssi
);
956 if ((sc
->sc_mib_local
.Network_Mode
|| !sc
->sc_no_bssid
) &&
957 sc
->sc_status
== AWI_ST_RUNNING
) {
958 if (memcmp(wh
->i_addr2
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
) == 0) {
959 sc
->sc_rx_timer
= 10;
960 sc
->sc_bss
.rssi
= rssi
;
963 switch (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
964 case IEEE80211_FC0_TYPE_DATA
:
965 if (sc
->sc_mib_local
.Network_Mode
) {
966 if ((wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) !=
967 IEEE80211_FC1_DIR_FROMDS
) {
972 if ((wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) !=
973 IEEE80211_FC1_DIR_NODS
) {
978 m
= awi_fix_rxhdr(sc
, m
);
984 ifp
->if_input(ifp
, m
);
986 case IEEE80211_FC0_TYPE_MGT
:
987 if ((wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) !=
988 IEEE80211_FC1_DIR_NODS
) {
992 switch (wh
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
) {
993 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
994 case IEEE80211_FC0_SUBTYPE_BEACON
:
995 awi_recv_beacon(sc
, m
, rxts
, rssi
);
997 case IEEE80211_FC0_SUBTYPE_AUTH
:
998 awi_recv_auth(sc
, m
);
1000 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
1001 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP
:
1002 awi_recv_asresp(sc
, m
);
1004 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
1005 if (sc
->sc_mib_local
.Network_Mode
)
1006 awi_send_auth(sc
, 1);
1008 case IEEE80211_FC0_SUBTYPE_DISASSOC
:
1009 if (sc
->sc_mib_local
.Network_Mode
)
1010 awi_send_asreq(sc
, 1);
1015 case IEEE80211_FC0_TYPE_CTL
:
1017 /* should not come here */
1024 awi_rxint(struct awi_softc
*sc
)
1026 u_int8_t state
, rate
, rssi
;
1028 u_int32_t frame
, next
, rxts
, rxoff
;
1031 rxoff
= sc
->sc_rxdoff
;
1033 state
= awi_read_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
);
1034 if (state
& AWI_RXD_ST_OWN
)
1036 if (!(state
& AWI_RXD_ST_CONSUMED
)) {
1037 if (state
& AWI_RXD_ST_RXERROR
)
1038 sc
->sc_ifp
->if_ierrors
++;
1040 len
= awi_read_2(sc
, rxoff
+ AWI_RXD_LEN
);
1041 rate
= awi_read_1(sc
, rxoff
+ AWI_RXD_RATE
);
1042 rssi
= awi_read_1(sc
, rxoff
+ AWI_RXD_RSSI
);
1043 frame
= awi_read_4(sc
, rxoff
+ AWI_RXD_START_FRAME
) & 0x7fff;
1044 rxts
= awi_read_4(sc
, rxoff
+ AWI_RXD_LOCALTIME
);
1045 m
= awi_devget(sc
, frame
, len
);
1046 if (state
& AWI_RXD_ST_LF
)
1047 awi_input(sc
, m
, rxts
, rssi
);
1051 state
|= AWI_RXD_ST_CONSUMED
;
1052 awi_write_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
, state
);
1054 next
= awi_read_4(sc
, rxoff
+ AWI_RXD_NEXT
);
1055 if (next
& AWI_RXD_NEXT_LAST
)
1057 /* make sure the next pointer is correct */
1058 if (next
!= awi_read_4(sc
, rxoff
+ AWI_RXD_NEXT
))
1060 state
|= AWI_RXD_ST_OWN
;
1061 awi_write_1(sc
, rxoff
+ AWI_RXD_HOST_DESC_STATE
, state
);
1062 rxoff
= next
& 0x7fff;
1064 sc
->sc_rxdoff
= rxoff
;
1067 static struct mbuf
*
1068 awi_devget(struct awi_softc
*sc
, u_int32_t off
, u_int16_t len
)
1071 struct mbuf
*top
, **mp
;
1075 top
= sc
->sc_rxpend
;
1078 sc
->sc_rxpend
= NULL
;
1079 top
->m_pkthdr
.len
+= len
;
1081 while (*mp
!= NULL
) {
1085 if (m
->m_flags
& M_EXT
)
1086 tlen
= m
->m_ext
.ext_size
;
1087 else if (m
->m_flags
& M_PKTHDR
)
1094 awi_read_bytes(sc
, off
, mtod(m
, u_int8_t
*) + m
->m_len
, tlen
);
1100 m
= m_getl(len
, MB_DONTWAIT
, MT_DATA
,
1101 top
== NULL
? M_PKTHDR
: 0, &msize
);
1108 int hdrlen
= sizeof(struct ieee80211_frame
) +
1109 (sc
->sc_format_llc
? sizeof(struct llc
) :
1110 sizeof(struct ether_header
));
1111 caddr_t newdata
= (caddr_t
)
1112 ALIGN(m
->m_data
+ hdrlen
) - hdrlen
;
1114 m
->m_pkthdr
.rcvif
= sc
->sc_ifp
;
1115 m
->m_pkthdr
.len
= len
;
1116 m
->m_len
-= newdata
- m
->m_data
;
1117 m
->m_data
= newdata
;
1121 awi_read_bytes(sc
, off
, mtod(m
, u_int8_t
*), m
->m_len
);
1131 * Initialize hardware and start firmware to accept commands.
1132 * Called everytime after power on firmware.
1136 awi_init_hw(struct awi_softc
*sc
)
1138 struct ifnet
*ifp
= sc
->sc_ifp
;
1143 sc
->sc_enab_intr
= 0;
1144 sc
->sc_invalid
= 0; /* XXX: really? */
1145 awi_drvstate(sc
, AWI_DRV_RESET
);
1147 /* reset firmware */
1148 am79c930_gcr_setbits(&sc
->sc_chip
, AM79C930_GCR_CORESET
);
1150 awi_write_1(sc
, AWI_SELFTEST
, 0);
1151 awi_write_1(sc
, AWI_CMD
, 0);
1152 awi_write_1(sc
, AWI_BANNER
, 0);
1153 am79c930_gcr_clearbits(&sc
->sc_chip
, AM79C930_GCR_CORESET
);
1156 /* wait for selftest completion */
1157 for (i
= 0; ; i
++) {
1158 if (i
>= AWI_SELFTEST_TIMEOUT
*hz
/1000) {
1159 if_printf(ifp
, "failed to complete selftest (timeout)\n");
1162 status
= awi_read_1(sc
, AWI_SELFTEST
);
1163 if ((status
& 0xf0) == 0xf0)
1166 tsleep(sc
, 0, "awitst", 1);
1169 if (status
!= AWI_SELFTEST_PASSED
) {
1170 if_printf(ifp
, "failed to complete selftest (code %x)\n",
1175 /* check banner to confirm firmware write it */
1176 awi_read_bytes(sc
, AWI_BANNER
, sc
->sc_banner
, AWI_BANNER_LEN
);
1177 if (memcmp(sc
->sc_banner
, "PCnetMobile:", 12) != 0) {
1178 if_printf(ifp
, "failed to complete selftest (bad banner)\n");
1179 for (i
= 0; i
< AWI_BANNER_LEN
; i
++)
1180 kprintf("%s%02x", i
? ":" : "\t", sc
->sc_banner
[i
]);
1185 /* initializing interrupt */
1186 sc
->sc_enab_intr
= 1;
1187 error
= awi_intr_lock(sc
);
1190 intmask
= AWI_INT_GROGGY
| AWI_INT_SCAN_CMPLT
|
1191 AWI_INT_TX
| AWI_INT_RX
| AWI_INT_CMD
;
1192 awi_write_1(sc
, AWI_INTMASK
, ~intmask
& 0xff);
1193 awi_write_1(sc
, AWI_INTMASK2
, 0);
1194 awi_write_1(sc
, AWI_INTSTAT
, 0);
1195 awi_write_1(sc
, AWI_INTSTAT2
, 0);
1196 awi_intr_unlock(sc
);
1197 am79c930_gcr_setbits(&sc
->sc_chip
, AM79C930_GCR_ENECINT
);
1199 /* issueing interface test command */
1200 error
= awi_cmd(sc
, AWI_CMD_NOP
);
1202 if_printf(ifp
, "failed to complete selftest");
1204 kprintf(" (no hardware)\n");
1205 else if (error
!= EWOULDBLOCK
)
1206 kprintf(" (error %d)\n", error
);
1208 kprintf(" (command timeout)\n");
1214 * Extract the factory default MIB value from firmware and assign the driver
1216 * Called once at attaching the interface.
1220 awi_init_mibs(struct awi_softc
*sc
)
1225 if ((error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_LOCAL
)) != 0 ||
1226 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_ADDR
)) != 0 ||
1227 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_MAC
)) != 0 ||
1228 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_MGT
)) != 0 ||
1229 (error
= awi_mib(sc
, AWI_CMD_GET_MIB
, AWI_MIB_PHY
)) != 0) {
1230 if_printf(sc
->sc_ifp
,
1231 "failed to get default mib value (error %d)\n",
1236 rate
= sc
->sc_mib_phy
.aSuprt_Data_Rates
;
1237 sc
->sc_tx_rate
= AWI_RATE_1MBIT
;
1238 for (i
= 0; i
< rate
[1]; i
++) {
1239 if (AWI_80211_RATE(rate
[2 + i
]) > sc
->sc_tx_rate
)
1240 sc
->sc_tx_rate
= AWI_80211_RATE(rate
[2 + i
]);
1242 awi_init_region(sc
);
1243 memset(&sc
->sc_mib_mac
.aDesired_ESS_ID
, 0, AWI_ESS_ID_SIZE
);
1244 sc
->sc_mib_mac
.aDesired_ESS_ID
[0] = IEEE80211_ELEMID_SSID
;
1245 sc
->sc_mib_local
.Fragmentation_Dis
= 1;
1246 sc
->sc_mib_local
.Accept_All_Multicast_Dis
= 1;
1247 sc
->sc_mib_local
.Power_Saving_Mode_Dis
= 1;
1249 /* allocate buffers */
1250 sc
->sc_txbase
= AWI_BUFFERS
;
1251 sc
->sc_txend
= sc
->sc_txbase
+
1252 (AWI_TXD_SIZE
+ sizeof(struct ieee80211_frame
) +
1253 sizeof(struct ether_header
) + ETHERMTU
) * AWI_NTXBUFS
;
1254 LE_WRITE_4(&sc
->sc_mib_local
.Tx_Buffer_Offset
, sc
->sc_txbase
);
1255 LE_WRITE_4(&sc
->sc_mib_local
.Tx_Buffer_Size
,
1256 sc
->sc_txend
- sc
->sc_txbase
);
1257 LE_WRITE_4(&sc
->sc_mib_local
.Rx_Buffer_Offset
, sc
->sc_txend
);
1258 LE_WRITE_4(&sc
->sc_mib_local
.Rx_Buffer_Size
,
1259 AWI_BUFFERS_END
- sc
->sc_txend
);
1260 sc
->sc_mib_local
.Network_Mode
= 1;
1261 sc
->sc_mib_local
.Acting_as_AP
= 0;
1266 * Start transmitter and receiver of firmware
1267 * Called after awi_init_hw() to start operation.
1271 awi_init_txrx(struct awi_softc
*sc
)
1275 /* start transmitter */
1276 sc
->sc_txdone
= sc
->sc_txnext
= sc
->sc_txbase
;
1277 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_START
, 0);
1278 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NEXT
, 0);
1279 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_LENGTH
, 0);
1280 awi_write_1(sc
, sc
->sc_txbase
+ AWI_TXD_RATE
, 0);
1281 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NDA
, 0);
1282 awi_write_4(sc
, sc
->sc_txbase
+ AWI_TXD_NRA
, 0);
1283 awi_write_1(sc
, sc
->sc_txbase
+ AWI_TXD_STATE
, 0);
1284 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_TX_DATA
, sc
->sc_txbase
);
1285 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_TX_MGT
, 0);
1286 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_TX_BCAST
, 0);
1287 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_TX_PS
, 0);
1288 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_TX_CF
, 0);
1289 error
= awi_cmd(sc
, AWI_CMD_INIT_TX
);
1293 /* start receiver */
1294 if (sc
->sc_rxpend
) {
1295 m_freem(sc
->sc_rxpend
);
1296 sc
->sc_rxpend
= NULL
;
1298 error
= awi_cmd(sc
, AWI_CMD_INIT_RX
);
1301 sc
->sc_rxdoff
= awi_read_4(sc
, AWI_CMD_PARAMS
+AWI_CA_IRX_DATA_DESC
);
1302 sc
->sc_rxmoff
= awi_read_4(sc
, AWI_CMD_PARAMS
+AWI_CA_IRX_PS_DESC
);
1307 awi_stop_txrx(struct awi_softc
*sc
)
1310 if (sc
->sc_cmd_inprog
)
1312 awi_cmd(sc
, AWI_CMD_KILL_RX
);
1314 sc
->sc_cmd_inprog
= AWI_CMD_FLUSH_TX
;
1315 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_FTX_DATA
, 1);
1316 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_FTX_MGT
, 0);
1317 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_FTX_BCAST
, 0);
1318 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_FTX_PS
, 0);
1319 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_FTX_CF
, 0);
1320 awi_cmd(sc
, AWI_CMD_FLUSH_TX
);
1325 awi_init_region(struct awi_softc
*sc
)
1328 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1329 switch (sc
->sc_mib_phy
.aCurrent_Reg_Domain
) {
1330 case AWI_REG_DOMAIN_US
:
1331 case AWI_REG_DOMAIN_CA
:
1332 case AWI_REG_DOMAIN_EU
:
1333 sc
->sc_scan_min
= 0;
1334 sc
->sc_scan_max
= 77;
1336 case AWI_REG_DOMAIN_ES
:
1337 sc
->sc_scan_min
= 0;
1338 sc
->sc_scan_max
= 26;
1340 case AWI_REG_DOMAIN_FR
:
1341 sc
->sc_scan_min
= 0;
1342 sc
->sc_scan_max
= 32;
1344 case AWI_REG_DOMAIN_JP
:
1345 sc
->sc_scan_min
= 6;
1346 sc
->sc_scan_max
= 17;
1351 sc
->sc_scan_set
= sc
->sc_scan_cur
% 3 + 1;
1353 switch (sc
->sc_mib_phy
.aCurrent_Reg_Domain
) {
1354 case AWI_REG_DOMAIN_US
:
1355 case AWI_REG_DOMAIN_CA
:
1356 sc
->sc_scan_min
= 1;
1357 sc
->sc_scan_max
= 11;
1358 sc
->sc_scan_cur
= 3;
1360 case AWI_REG_DOMAIN_EU
:
1361 sc
->sc_scan_min
= 1;
1362 sc
->sc_scan_max
= 13;
1363 sc
->sc_scan_cur
= 3;
1365 case AWI_REG_DOMAIN_ES
:
1366 sc
->sc_scan_min
= 10;
1367 sc
->sc_scan_max
= 11;
1368 sc
->sc_scan_cur
= 10;
1370 case AWI_REG_DOMAIN_FR
:
1371 sc
->sc_scan_min
= 10;
1372 sc
->sc_scan_max
= 13;
1373 sc
->sc_scan_cur
= 10;
1375 case AWI_REG_DOMAIN_JP
:
1376 sc
->sc_scan_min
= 14;
1377 sc
->sc_scan_max
= 14;
1378 sc
->sc_scan_cur
= 14;
1384 sc
->sc_ownch
= sc
->sc_scan_cur
;
1389 awi_start_scan(struct awi_softc
*sc
)
1394 while ((bp
= TAILQ_FIRST(&sc
->sc_scan
)) != NULL
) {
1395 TAILQ_REMOVE(&sc
->sc_scan
, bp
, list
);
1396 kfree(bp
, M_DEVBUF
);
1398 if (!sc
->sc_mib_local
.Network_Mode
&& sc
->sc_no_bssid
) {
1399 memset(&sc
->sc_bss
, 0, sizeof(sc
->sc_bss
));
1400 sc
->sc_bss
.essid
[0] = IEEE80211_ELEMID_SSID
;
1401 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1402 sc
->sc_bss
.chanset
= sc
->sc_ownch
% 3 + 1;
1403 sc
->sc_bss
.pattern
= sc
->sc_ownch
;
1404 sc
->sc_bss
.index
= 1;
1405 sc
->sc_bss
.dwell_time
= 200; /*XXX*/
1407 sc
->sc_bss
.chanset
= sc
->sc_ownch
;
1408 sc
->sc_status
= AWI_ST_SETSS
;
1409 error
= awi_set_ss(sc
);
1411 if (sc
->sc_mib_local
.Network_Mode
)
1412 awi_drvstate(sc
, AWI_DRV_INFSC
);
1414 awi_drvstate(sc
, AWI_DRV_ADHSC
);
1415 sc
->sc_start_bss
= 0;
1416 sc
->sc_active_scan
= 1;
1417 sc
->sc_mgt_timer
= AWI_ASCAN_WAIT
/ 1000;
1418 sc
->sc_ifp
->if_timer
= 1;
1419 sc
->sc_status
= AWI_ST_SCAN
;
1420 error
= awi_cmd_scan(sc
);
1426 awi_next_scan(struct awi_softc
*sc
)
1432 * The pattern parameter for FH phy should be incremented
1433 * by 3. But BayStack 650 Access Points apparently always
1434 * assign hop pattern set parameter to 1 for any pattern.
1435 * So we try all combinations of pattern/set parameters.
1436 * Since this causes no error, it may be a bug of
1437 * PCnetMobile firmware.
1440 if (sc
->sc_scan_cur
> sc
->sc_scan_max
) {
1441 sc
->sc_scan_cur
= sc
->sc_scan_min
;
1442 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
1443 sc
->sc_scan_set
= sc
->sc_scan_set
% 3 + 1;
1445 error
= awi_cmd_scan(sc
);
1446 if (error
!= EINVAL
)
1453 awi_stop_scan(struct awi_softc
*sc
)
1455 struct ifnet
*ifp
= sc
->sc_ifp
;
1456 struct awi_bss
*bp
, *sbp
;
1459 bp
= TAILQ_FIRST(&sc
->sc_scan
);
1462 if (sc
->sc_active_scan
) {
1463 if (ifp
->if_flags
& IFF_DEBUG
)
1464 if_printf(ifp
, "entering passive scan mode\n");
1465 sc
->sc_active_scan
= 0;
1467 sc
->sc_mgt_timer
= AWI_PSCAN_WAIT
/ 1000;
1473 if (ifp
->if_flags
& IFF_DEBUG
)
1474 if_printf(ifp
, "\tmacaddr ch/pat sig flag wep essid\n");
1475 for (; bp
!= NULL
; bp
= TAILQ_NEXT(bp
, list
)) {
1478 * The configuration of the access points may change
1479 * during my scan. So we retries to associate with
1480 * it unless there are any suitable AP.
1482 if (bp
->fails
++ < 3)
1488 * Since the firmware apparently scans not only the specified
1489 * channel of SCAN command but all available channel within
1490 * the region, we should filter out unnecessary responses here.
1492 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1493 if (bp
->pattern
< sc
->sc_scan_min
||
1494 bp
->pattern
> sc
->sc_scan_max
)
1497 if (bp
->chanset
< sc
->sc_scan_min
||
1498 bp
->chanset
> sc
->sc_scan_max
)
1501 if (sc
->sc_mib_local
.Network_Mode
) {
1502 if (!(bp
->capinfo
& IEEE80211_CAPINFO_ESS
) ||
1503 (bp
->capinfo
& IEEE80211_CAPINFO_IBSS
))
1506 if ((bp
->capinfo
& IEEE80211_CAPINFO_ESS
) ||
1507 !(bp
->capinfo
& IEEE80211_CAPINFO_IBSS
))
1510 if (sc
->sc_wep_algo
== NULL
) {
1511 if (bp
->capinfo
& IEEE80211_CAPINFO_PRIVACY
)
1514 if (!(bp
->capinfo
& IEEE80211_CAPINFO_PRIVACY
))
1517 if (sc
->sc_mib_mac
.aDesired_ESS_ID
[1] != 0 &&
1518 memcmp(&sc
->sc_mib_mac
.aDesired_ESS_ID
, bp
->essid
,
1519 sizeof(bp
->essid
)) != 0)
1521 if (ifp
->if_flags
& IFF_DEBUG
) {
1522 kprintf(" %c %6D", fail
? '-' : '+', bp
->esrc
, ":");
1523 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
1524 kprintf(" %2d/%d%c", bp
->pattern
, bp
->chanset
,
1525 fail
& 0x01 ? '!' : ' ');
1527 kprintf(" %4d%c", bp
->chanset
,
1528 fail
& 0x01 ? '!' : ' ');
1529 kprintf(" %+4d", bp
->rssi
);
1531 (bp
->capinfo
& IEEE80211_CAPINFO_ESS
) ? "ess" :
1532 (bp
->capinfo
& IEEE80211_CAPINFO_IBSS
) ? "ibss" :
1534 fail
& 0x02 ? '!' : ' ');
1536 (bp
->capinfo
& IEEE80211_CAPINFO_PRIVACY
) ? "wep" :
1538 fail
& 0x04 ? '!' : ' ');
1539 awi_print_essid(bp
->essid
);
1540 kprintf("%s\n", fail
& 0x08 ? "!" : "");
1543 if (sbp
== NULL
|| bp
->rssi
> sbp
->rssi
)
1554 awi_recv_beacon(struct awi_softc
*sc
, struct mbuf
*m0
, u_int32_t rxts
,
1557 struct ieee80211_frame
*wh
;
1559 u_int8_t
*frame
, *eframe
;
1560 u_int8_t
*tstamp
, *bintval
, *capinfo
, *ssid
, *rates
, *parms
;
1562 if (sc
->sc_status
!= AWI_ST_SCAN
)
1564 wh
= mtod(m0
, struct ieee80211_frame
*);
1566 frame
= (u_int8_t
*)&wh
[1];
1567 eframe
= mtod(m0
, u_int8_t
*) + m0
->m_len
;
1571 * beacon interval [2]
1572 * capability information [2]
1574 * supported rates [tlv]
1575 * parameter set [tlv]
1578 if (frame
+ 12 > eframe
) {
1581 kprintf("awi_recv_beacon: frame too short \n");
1592 ssid
= rates
= parms
= NULL
;
1593 while (frame
< eframe
) {
1595 case IEEE80211_ELEMID_SSID
:
1598 case IEEE80211_ELEMID_RATES
:
1601 case IEEE80211_ELEMID_FHPARMS
:
1602 case IEEE80211_ELEMID_DSPARMS
:
1606 frame
+= frame
[1] + 2;
1608 if (ssid
== NULL
|| rates
== NULL
|| parms
== NULL
) {
1611 kprintf("awi_recv_beacon: ssid=%p, rates=%p, parms=%p\n",
1612 ssid
, rates
, parms
);
1616 if (ssid
[1] > IEEE80211_NWID_LEN
) {
1619 kprintf("awi_recv_beacon: bad ssid len: %d from %6D\n",
1620 ssid
[1], wh
->i_addr2
, ":");
1625 for (bp
= TAILQ_FIRST(&sc
->sc_scan
); bp
!= NULL
;
1626 bp
= TAILQ_NEXT(bp
, list
)) {
1627 if (memcmp(bp
->esrc
, wh
->i_addr2
, ETHER_ADDR_LEN
) == 0 &&
1628 memcmp(bp
->bssid
, wh
->i_addr3
, ETHER_ADDR_LEN
) == 0)
1632 bp
= kmalloc(sizeof(struct awi_bss
), M_DEVBUF
, M_INTWAIT
);
1635 TAILQ_INSERT_TAIL(&sc
->sc_scan
, bp
, list
);
1636 memcpy(bp
->esrc
, wh
->i_addr2
, ETHER_ADDR_LEN
);
1637 memcpy(bp
->bssid
, wh
->i_addr3
, ETHER_ADDR_LEN
);
1638 memset(bp
->essid
, 0, sizeof(bp
->essid
));
1639 memcpy(bp
->essid
, ssid
, 2 + ssid
[1]);
1643 memcpy(bp
->timestamp
, tstamp
, sizeof(bp
->timestamp
));
1644 bp
->interval
= LE_READ_2(bintval
);
1645 bp
->capinfo
= LE_READ_2(capinfo
);
1646 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
1647 bp
->chanset
= parms
[4];
1648 bp
->pattern
= parms
[5];
1649 bp
->index
= parms
[6];
1650 bp
->dwell_time
= LE_READ_2(parms
+ 2);
1652 bp
->chanset
= parms
[2];
1657 if (sc
->sc_mgt_timer
== 0)
1662 awi_set_ss(struct awi_softc
*sc
)
1664 struct ifnet
*ifp
= sc
->sc_ifp
;
1668 sc
->sc_status
= AWI_ST_SETSS
;
1670 if (ifp
->if_flags
& IFF_DEBUG
) {
1671 if_printf(ifp
, "ch %d pat %d id %d dw %d iv %d bss %6D ssid ",
1672 bp
->chanset
, bp
->pattern
, bp
->index
, bp
->dwell_time
,
1673 bp
->interval
, bp
->bssid
, ":");
1674 awi_print_essid(bp
->essid
);
1677 memcpy(&sc
->sc_mib_mgt
.aCurrent_BSS_ID
, bp
->bssid
, ETHER_ADDR_LEN
);
1678 memcpy(&sc
->sc_mib_mgt
.aCurrent_ESS_ID
, bp
->essid
,
1680 LE_WRITE_2(&sc
->sc_mib_mgt
.aBeacon_Period
, bp
->interval
);
1681 error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MGT
);
1686 awi_try_sync(struct awi_softc
*sc
)
1690 sc
->sc_status
= AWI_ST_SYNC
;
1693 if (sc
->sc_cmd_inprog
) {
1694 if (awi_cmd_wait(sc
))
1697 sc
->sc_cmd_inprog
= AWI_CMD_SYNC
;
1698 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_SET
, bp
->chanset
);
1699 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_PATTERN
, bp
->pattern
);
1700 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_IDX
, bp
->index
);
1701 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_STARTBSS
,
1702 sc
->sc_start_bss
? 1 : 0);
1703 awi_write_2(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_DWELL
, bp
->dwell_time
);
1704 awi_write_2(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_MBZ
, 0);
1705 awi_write_bytes(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_TIMESTAMP
,
1707 awi_write_4(sc
, AWI_CMD_PARAMS
+AWI_CA_SYNC_REFTIME
, bp
->rxtime
);
1708 awi_cmd(sc
, AWI_CMD_SYNC
);
1712 awi_sync_done(struct awi_softc
*sc
)
1714 struct ifnet
*ifp
= sc
->sc_ifp
;
1716 if (sc
->sc_mib_local
.Network_Mode
) {
1717 awi_drvstate(sc
, AWI_DRV_INFSY
);
1718 awi_send_auth(sc
, 1);
1720 if (ifp
->if_flags
& IFF_DEBUG
) {
1721 if_printf(ifp
, "synced with");
1722 if (sc
->sc_no_bssid
)
1723 kprintf(" no-bssid");
1725 kprintf(" %6D ssid ", sc
->sc_bss
.bssid
, ":");
1726 awi_print_essid(sc
->sc_bss
.essid
);
1728 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
1729 kprintf(" at chanset %d pattern %d\n",
1730 sc
->sc_bss
.chanset
, sc
->sc_bss
.pattern
);
1732 kprintf(" at channel %d\n", sc
->sc_bss
.chanset
);
1734 awi_drvstate(sc
, AWI_DRV_ADHSY
);
1735 sc
->sc_status
= AWI_ST_RUNNING
;
1736 ifp
->if_flags
|= IFF_RUNNING
;
1742 awi_send_deauth(struct awi_softc
*sc
)
1744 struct ifnet
*ifp
= sc
->sc_ifp
;
1746 struct ieee80211_frame
*wh
;
1749 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
1752 if (ifp
->if_flags
& IFF_DEBUG
)
1753 if_printf(ifp
, "sending deauth to %6D\n",
1754 sc
->sc_bss
.bssid
, ":");
1756 wh
= mtod(m
, struct ieee80211_frame
*);
1757 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_MGT
|
1758 IEEE80211_FC0_SUBTYPE_AUTH
;
1759 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
1760 LE_WRITE_2(wh
->i_dur
, 0);
1761 LE_WRITE_2(wh
->i_seq
, 0);
1762 memcpy(wh
->i_addr1
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
1763 memcpy(wh
->i_addr2
, sc
->sc_mib_addr
.aMAC_Address
, ETHER_ADDR_LEN
);
1764 memcpy(wh
->i_addr3
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
1766 deauth
= (u_int8_t
*)&wh
[1];
1767 LE_WRITE_2(deauth
, IEEE80211_REASON_AUTH_LEAVE
);
1770 m
->m_pkthdr
.len
= m
->m_len
= deauth
- mtod(m
, u_int8_t
*);
1771 IF_ENQUEUE(&sc
->sc_mgtq
, m
);
1773 awi_drvstate(sc
, AWI_DRV_INFTOSS
);
1777 awi_send_auth(struct awi_softc
*sc
, int seq
)
1779 struct ifnet
*ifp
= sc
->sc_ifp
;
1781 struct ieee80211_frame
*wh
;
1784 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
1787 sc
->sc_status
= AWI_ST_AUTH
;
1788 if (ifp
->if_flags
& IFF_DEBUG
)
1789 if_printf(ifp
, "sending auth to %6D\n",
1790 sc
->sc_bss
.bssid
, ":");
1792 wh
= mtod(m
, struct ieee80211_frame
*);
1793 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_MGT
|
1794 IEEE80211_FC0_SUBTYPE_AUTH
;
1795 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
1796 LE_WRITE_2(wh
->i_dur
, 0);
1797 LE_WRITE_2(wh
->i_seq
, 0);
1798 memcpy(wh
->i_addr1
, sc
->sc_bss
.esrc
, ETHER_ADDR_LEN
);
1799 memcpy(wh
->i_addr2
, sc
->sc_mib_addr
.aMAC_Address
, ETHER_ADDR_LEN
);
1800 memcpy(wh
->i_addr3
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
1802 auth
= (u_int8_t
*)&wh
[1];
1803 /* algorithm number */
1804 LE_WRITE_2(auth
, IEEE80211_AUTH_ALG_OPEN
);
1806 /* sequence number */
1807 LE_WRITE_2(auth
, seq
);
1810 LE_WRITE_2(auth
, 0);
1813 m
->m_pkthdr
.len
= m
->m_len
= auth
- mtod(m
, u_int8_t
*);
1814 IF_ENQUEUE(&sc
->sc_mgtq
, m
);
1817 sc
->sc_mgt_timer
= AWI_TRANS_TIMEOUT
/ 1000;
1822 awi_recv_auth(struct awi_softc
*sc
, struct mbuf
*m0
)
1824 struct ifnet
*ifp
= sc
->sc_ifp
;
1825 struct ieee80211_frame
*wh
;
1826 u_int8_t
*auth
, *eframe
;
1830 wh
= mtod(m0
, struct ieee80211_frame
*);
1831 auth
= (u_int8_t
*)&wh
[1];
1832 eframe
= mtod(m0
, u_int8_t
*) + m0
->m_len
;
1833 if (ifp
->if_flags
& IFF_DEBUG
)
1834 if_printf(ifp
, "receive auth from %6D\n", wh
->i_addr2
, ":");
1836 /* algorithm number */
1837 if (LE_READ_2(auth
) != IEEE80211_AUTH_ALG_OPEN
)
1840 if (!sc
->sc_mib_local
.Network_Mode
) {
1841 if (sc
->sc_status
!= AWI_ST_RUNNING
)
1843 if (LE_READ_2(auth
) == 1)
1844 awi_send_auth(sc
, 2);
1847 if (sc
->sc_status
!= AWI_ST_AUTH
)
1849 /* sequence number */
1850 if (LE_READ_2(auth
) != 2)
1854 status
= LE_READ_2(auth
);
1856 if_printf(ifp
, "authentication failed (reason %d)\n", status
);
1857 for (bp
= TAILQ_FIRST(&sc
->sc_scan
); bp
!= NULL
;
1858 bp
= TAILQ_NEXT(bp
, list
)) {
1859 if (memcmp(bp
->esrc
, sc
->sc_bss
.esrc
, ETHER_ADDR_LEN
)
1867 sc
->sc_mgt_timer
= 0;
1868 awi_drvstate(sc
, AWI_DRV_INFAUTH
);
1869 awi_send_asreq(sc
, 0);
1873 awi_send_asreq(struct awi_softc
*sc
, int reassoc
)
1875 struct ifnet
*ifp
= sc
->sc_ifp
;
1877 struct ieee80211_frame
*wh
;
1881 MGETHDR(m
, MB_DONTWAIT
, MT_DATA
);
1884 sc
->sc_status
= AWI_ST_ASSOC
;
1885 if (ifp
->if_flags
& IFF_DEBUG
)
1886 if_printf(ifp
, "sending %sassoc req to %6D\n",
1887 reassoc
? "re" : "", sc
->sc_bss
.bssid
, ":");
1889 wh
= mtod(m
, struct ieee80211_frame
*);
1890 wh
->i_fc
[0] = IEEE80211_FC0_VERSION_0
| IEEE80211_FC0_TYPE_MGT
;
1892 wh
->i_fc
[0] |= IEEE80211_FC0_SUBTYPE_REASSOC_REQ
;
1894 wh
->i_fc
[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_REQ
;
1895 wh
->i_fc
[1] = IEEE80211_FC1_DIR_NODS
;
1896 LE_WRITE_2(wh
->i_dur
, 0);
1897 LE_WRITE_2(wh
->i_seq
, 0);
1898 memcpy(wh
->i_addr1
, sc
->sc_bss
.esrc
, ETHER_ADDR_LEN
);
1899 memcpy(wh
->i_addr2
, sc
->sc_mib_addr
.aMAC_Address
, ETHER_ADDR_LEN
);
1900 memcpy(wh
->i_addr3
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
1902 asreq
= (u_int8_t
*)&wh
[1];
1904 /* capability info */
1905 if (sc
->sc_wep_algo
== NULL
)
1906 LE_WRITE_2(asreq
, IEEE80211_CAPINFO_CF_POLLABLE
);
1909 IEEE80211_CAPINFO_CF_POLLABLE
| IEEE80211_CAPINFO_PRIVACY
);
1911 /* listen interval */
1912 lintval
= LE_READ_2(&sc
->sc_mib_mgt
.aListen_Interval
);
1913 LE_WRITE_2(asreq
, lintval
);
1916 /* current AP address */
1917 memcpy(asreq
, sc
->sc_bss
.bssid
, ETHER_ADDR_LEN
);
1918 asreq
+= ETHER_ADDR_LEN
;
1921 memcpy(asreq
, sc
->sc_bss
.essid
, 2 + sc
->sc_bss
.essid
[1]);
1922 asreq
+= 2 + asreq
[1];
1923 /* supported rates */
1924 memcpy(asreq
, &sc
->sc_mib_phy
.aSuprt_Data_Rates
, 4);
1925 asreq
+= 2 + asreq
[1];
1927 m
->m_pkthdr
.len
= m
->m_len
= asreq
- mtod(m
, u_int8_t
*);
1928 IF_ENQUEUE(&sc
->sc_mgtq
, m
);
1931 sc
->sc_mgt_timer
= AWI_TRANS_TIMEOUT
/ 1000;
1936 awi_recv_asresp(struct awi_softc
*sc
, struct mbuf
*m0
)
1938 struct ifnet
*ifp
= sc
->sc_ifp
;
1939 struct ieee80211_frame
*wh
;
1940 u_int8_t
*asresp
, *eframe
;
1942 u_int8_t rate
, *phy_rates
;
1946 wh
= mtod(m0
, struct ieee80211_frame
*);
1947 asresp
= (u_int8_t
*)&wh
[1];
1948 eframe
= mtod(m0
, u_int8_t
*) + m0
->m_len
;
1949 if (ifp
->if_flags
& IFF_DEBUG
)
1950 if_printf(ifp
, "receive assoc resp from %6D\n",
1953 if (!sc
->sc_mib_local
.Network_Mode
)
1956 if (sc
->sc_status
!= AWI_ST_ASSOC
)
1958 /* capability info */
1961 status
= LE_READ_2(asresp
);
1963 if_printf(ifp
, "association failed (reason %d)\n", status
);
1964 for (bp
= TAILQ_FIRST(&sc
->sc_scan
); bp
!= NULL
;
1965 bp
= TAILQ_NEXT(bp
, list
)) {
1966 if (memcmp(bp
->esrc
, sc
->sc_bss
.esrc
, ETHER_ADDR_LEN
)
1975 /* association id */
1977 /* supported rates */
1978 rate
= AWI_RATE_1MBIT
;
1979 for (i
= 0; i
< asresp
[1]; i
++) {
1980 if (AWI_80211_RATE(asresp
[2 + i
]) <= rate
)
1982 phy_rates
= sc
->sc_mib_phy
.aSuprt_Data_Rates
;
1983 for (j
= 0; j
< phy_rates
[1]; j
++) {
1984 if (AWI_80211_RATE(asresp
[2 + i
]) ==
1985 AWI_80211_RATE(phy_rates
[2 + j
]))
1986 rate
= AWI_80211_RATE(asresp
[2 + i
]);
1989 if (ifp
->if_flags
& IFF_DEBUG
) {
1990 if_printf(ifp
, "associated with %6D ssid ",
1991 sc
->sc_bss
.bssid
, ":");
1992 awi_print_essid(sc
->sc_bss
.essid
);
1993 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
)
1994 kprintf(" chanset %d pattern %d\n",
1995 sc
->sc_bss
.chanset
, sc
->sc_bss
.pattern
);
1997 kprintf(" channel %d\n", sc
->sc_bss
.chanset
);
1999 sc
->sc_tx_rate
= rate
;
2000 sc
->sc_mgt_timer
= 0;
2001 sc
->sc_rx_timer
= 10;
2003 sc
->sc_status
= AWI_ST_RUNNING
;
2004 ifp
->if_flags
|= IFF_RUNNING
;
2005 awi_drvstate(sc
, AWI_DRV_INFASSOC
);
2010 awi_mib(struct awi_softc
*sc
, u_int8_t cmd
, u_int8_t mib
)
2013 u_int8_t size
, *ptr
;
2017 ptr
= (u_int8_t
*)&sc
->sc_mib_local
;
2018 size
= sizeof(sc
->sc_mib_local
);
2021 ptr
= (u_int8_t
*)&sc
->sc_mib_addr
;
2022 size
= sizeof(sc
->sc_mib_addr
);
2025 ptr
= (u_int8_t
*)&sc
->sc_mib_mac
;
2026 size
= sizeof(sc
->sc_mib_mac
);
2029 ptr
= (u_int8_t
*)&sc
->sc_mib_stat
;
2030 size
= sizeof(sc
->sc_mib_stat
);
2033 ptr
= (u_int8_t
*)&sc
->sc_mib_mgt
;
2034 size
= sizeof(sc
->sc_mib_mgt
);
2037 ptr
= (u_int8_t
*)&sc
->sc_mib_phy
;
2038 size
= sizeof(sc
->sc_mib_phy
);
2043 if (sc
->sc_cmd_inprog
) {
2044 error
= awi_cmd_wait(sc
);
2046 if (error
== EWOULDBLOCK
)
2047 kprintf("awi_mib: cmd %d inprog",
2052 sc
->sc_cmd_inprog
= cmd
;
2053 if (cmd
== AWI_CMD_SET_MIB
)
2054 awi_write_bytes(sc
, AWI_CMD_PARAMS
+AWI_CA_MIB_DATA
, ptr
, size
);
2055 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_MIB_TYPE
, mib
);
2056 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_MIB_SIZE
, size
);
2057 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_MIB_INDEX
, 0);
2058 error
= awi_cmd(sc
, cmd
);
2061 if (cmd
== AWI_CMD_GET_MIB
) {
2062 awi_read_bytes(sc
, AWI_CMD_PARAMS
+AWI_CA_MIB_DATA
, ptr
, size
);
2067 kprintf("awi_mib: #%d:", mib
);
2068 for (i
= 0; i
< size
; i
++)
2069 kprintf(" %02x", ptr
[i
]);
2078 awi_cmd_scan(struct awi_softc
*sc
)
2083 if (sc
->sc_active_scan
)
2084 scan_mode
= AWI_SCAN_ACTIVE
;
2086 scan_mode
= AWI_SCAN_PASSIVE
;
2087 if (sc
->sc_mib_mgt
.aScan_Mode
!= scan_mode
) {
2088 sc
->sc_mib_mgt
.aScan_Mode
= scan_mode
;
2089 error
= awi_mib(sc
, AWI_CMD_SET_MIB
, AWI_MIB_MGT
);
2093 if (sc
->sc_cmd_inprog
) {
2094 error
= awi_cmd_wait(sc
);
2098 sc
->sc_cmd_inprog
= AWI_CMD_SCAN
;
2099 awi_write_2(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_DURATION
,
2100 sc
->sc_active_scan
? AWI_ASCAN_DURATION
: AWI_PSCAN_DURATION
);
2101 if (sc
->sc_mib_phy
.IEEE_PHY_Type
== AWI_PHY_TYPE_FH
) {
2102 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_SET
,
2104 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_PATTERN
,
2106 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_IDX
, 1);
2108 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_SET
,
2110 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_PATTERN
, 0);
2111 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_IDX
, 0);
2113 awi_write_1(sc
, AWI_CMD_PARAMS
+AWI_CA_SCAN_SUSP
, 0);
2114 return awi_cmd(sc
, AWI_CMD_SCAN
);
2118 awi_cmd(struct awi_softc
*sc
, u_int8_t cmd
)
2123 sc
->sc_cmd_inprog
= cmd
;
2124 awi_write_1(sc
, AWI_CMD_STATUS
, AWI_STAT_IDLE
);
2125 awi_write_1(sc
, AWI_CMD
, cmd
);
2126 if (sc
->sc_status
!= AWI_ST_INIT
)
2128 error
= awi_cmd_wait(sc
);
2131 status
= awi_read_1(sc
, AWI_CMD_STATUS
);
2132 awi_write_1(sc
, AWI_CMD
, 0);
2136 case AWI_STAT_BADPARM
:
2139 if_printf(sc
->sc_ifp
, "command %d failed %x\n", cmd
, status
);
2146 awi_cmd_done(struct awi_softc
*sc
)
2148 u_int8_t cmd
, status
;
2150 status
= awi_read_1(sc
, AWI_CMD_STATUS
);
2151 if (status
== AWI_STAT_IDLE
)
2152 return; /* stray interrupt */
2154 cmd
= sc
->sc_cmd_inprog
;
2155 sc
->sc_cmd_inprog
= 0;
2156 if (sc
->sc_status
== AWI_ST_INIT
) {
2160 awi_write_1(sc
, AWI_CMD
, 0);
2162 if (status
!= AWI_STAT_OK
) {
2163 if_printf(sc
->sc_ifp
, "command %d failed %x\n", cmd
, status
);
2166 switch (sc
->sc_status
) {
2168 if (cmd
== AWI_CMD_SET_MIB
)
2169 awi_cmd_scan(sc
); /* retry */
2183 awi_next_txd(struct awi_softc
*sc
, int len
, u_int32_t
*framep
, u_int32_t
*ntxdp
)
2185 u_int32_t txd
, ntxd
, frame
;
2187 txd
= sc
->sc_txnext
;
2188 frame
= txd
+ AWI_TXD_SIZE
;
2189 if (frame
+ len
> sc
->sc_txend
)
2190 frame
= sc
->sc_txbase
;
2192 if (ntxd
+ AWI_TXD_SIZE
> sc
->sc_txend
)
2193 ntxd
= sc
->sc_txbase
;
2197 * Determine if there are any room in ring buffer.
2198 * --- send wait, === new data, +++ conflict (ENOBUFS)
2199 * base........................end
2200 * done----txd=====ntxd OK
2201 * --txd=====done++++ntxd-- full
2202 * --txd=====ntxd done-- OK
2203 * ==ntxd done----txd=== OK
2204 * ==done++++ntxd----txd=== full
2205 * ++ntxd txd=====done++ full
2208 if (txd
< sc
->sc_txdone
&& ntxd
+ AWI_TXD_SIZE
> sc
->sc_txdone
)
2211 if (txd
< sc
->sc_txdone
|| ntxd
+ AWI_TXD_SIZE
> sc
->sc_txdone
)
2218 awi_intr_lock(struct awi_softc
*sc
)
2224 for (retry
= 0; retry
< 10; retry
++) {
2225 for (i
= 0; i
< AWI_LOCKOUT_TIMEOUT
*1000/5; i
++) {
2226 status
= awi_read_1(sc
, AWI_LOCKOUT_HOST
);
2233 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 1);
2234 status
= awi_read_1(sc
, AWI_LOCKOUT_HOST
);
2237 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 0);
2240 if_printf(sc
->sc_ifp
, "failed to lock interrupt\n");
2247 awi_intr_unlock(struct awi_softc
*sc
)
2250 awi_write_1(sc
, AWI_LOCKOUT_MAC
, 0);
2254 awi_cmd_wait(struct awi_softc
*sc
)
2259 while (sc
->sc_cmd_inprog
) {
2262 if (awi_read_1(sc
, AWI_CMD
) != sc
->sc_cmd_inprog
) {
2263 if_printf(sc
->sc_ifp
, "failed to access hardware\n");
2268 error
= tsleep(sc
, 0, "awicmd", AWI_CMD_TIMEOUT
*hz
/1000);
2277 awi_print_essid(u_int8_t
*essid
)
2283 if (len
> IEEE80211_NWID_LEN
)
2284 len
= IEEE80211_NWID_LEN
; /*XXX*/
2285 /* determine printable or not */
2286 for (i
= 0, p
= essid
+ 2; i
< len
; i
++, p
++) {
2287 if (*p
< ' ' || *p
> 0x7e)
2292 for (i
= 0, p
= essid
+ 2; i
< len
; i
++, p
++)
2297 for (i
= 0, p
= essid
+ 2; i
< len
; i
++, p
++)
2298 kprintf("%02x", *p
);
2304 awi_dump_pkt(struct awi_softc
*sc
, struct mbuf
*m
, int rssi
)
2306 struct ieee80211_frame
*wh
;
2309 wh
= mtod(m
, struct ieee80211_frame
*);
2311 if (awi_dump_mask
!= 0 &&
2312 ((wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
)==IEEE80211_FC1_DIR_NODS
) &&
2313 ((wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
)==IEEE80211_FC0_TYPE_MGT
)) {
2314 if ((AWI_DUMP_MASK(wh
->i_fc
[0]) & awi_dump_mask
) != 0)
2317 if (awi_dump_mask
< 0 &&
2318 (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
)==IEEE80211_FC0_TYPE_DATA
)
2325 switch (wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) {
2326 case IEEE80211_FC1_DIR_NODS
:
2327 kprintf("NODS %6D->%6D(%6D)", wh
->i_addr2
, ":",
2328 wh
->i_addr1
, ":", wh
->i_addr3
, ":");
2330 case IEEE80211_FC1_DIR_TODS
:
2331 kprintf("TODS %6D->%6D(%6D)", wh
->i_addr2
, ":",
2332 wh
->i_addr3
, ":", wh
->i_addr1
, ":");
2334 case IEEE80211_FC1_DIR_FROMDS
:
2335 kprintf("FRDS %6D->%6D(%6D)", wh
->i_addr3
, ":",
2336 wh
->i_addr1
, ":", wh
->i_addr2
, ":");
2338 case IEEE80211_FC1_DIR_DSTODS
:
2339 kprintf("DSDS %6D->%6D(%6D->%6D)", (u_int8_t
*)&wh
[1], ":",
2340 wh
->i_addr3
, ":", wh
->i_addr2
, ":", wh
->i_addr1
, ":");
2343 switch (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
2344 case IEEE80211_FC0_TYPE_DATA
:
2347 case IEEE80211_FC0_TYPE_MGT
:
2348 switch (wh
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
) {
2349 case IEEE80211_FC0_SUBTYPE_PROBE_REQ
:
2350 kprintf(" probe_req");
2352 case IEEE80211_FC0_SUBTYPE_PROBE_RESP
:
2353 kprintf(" probe_resp");
2355 case IEEE80211_FC0_SUBTYPE_BEACON
:
2358 case IEEE80211_FC0_SUBTYPE_AUTH
:
2361 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ
:
2362 kprintf(" assoc_req");
2364 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP
:
2365 kprintf(" assoc_resp");
2367 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ
:
2368 kprintf(" reassoc_req");
2370 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP
:
2371 kprintf(" reassoc_resp");
2373 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
2376 case IEEE80211_FC0_SUBTYPE_DISASSOC
:
2377 kprintf(" disassoc");
2381 wh
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
);
2387 wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
);
2390 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
)
2393 kprintf(" +%d", rssi
);
2395 if (awi_dump_len
> 0) {
2397 if (l
> awi_dump_len
+ sizeof(*wh
))
2398 l
= awi_dump_len
+ sizeof(*wh
);
2402 for (; i
< l
; i
++) {
2405 kprintf("%02x", mtod(m
, u_int8_t
*)[i
]);