1 /* $NetBSD: wi.c,v 1.230 2009/05/12 14:25:18 cegger Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1997, 1998, 1999
34 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by Bill Paul.
47 * 4. Neither the name of the author nor the names of any co-contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
61 * THE POSSIBILITY OF SUCH DAMAGE.
65 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
67 * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
68 * Electrical Engineering Department
69 * Columbia University, New York City
73 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
74 * from Lucent. Unlike the older cards, the new ones are programmed
75 * entirely via a firmware-driven controller called the Hermes.
76 * Unfortunately, Lucent will not release the Hermes programming manual
77 * without an NDA (if at all). What they do release is an API library
78 * called the HCF (Hardware Control Functions) which is supposed to
79 * do the device-specific operations of a device driver for you. The
80 * publically available version of the HCF library (the 'HCF Light') is
81 * a) extremely gross, b) lacks certain features, particularly support
82 * for 802.11 frames, and c) is contaminated by the GNU Public License.
84 * This driver does not use the HCF or HCF Light at all. Instead, it
85 * programs the Hermes controller directly, using information gleaned
86 * from the HCF Light code and corresponding documentation.
88 * This driver supports both the PCMCIA and ISA versions of the
89 * WaveLAN/IEEE cards. Note however that the ISA card isn't really
90 * anything of the sort: it's actually a PCMCIA bridge adapter
91 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
92 * inserted. Consequently, you need to use the pccard support for
93 * both the ISA and PCMCIA adapters.
97 * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
98 * Oslo IETF plenary meeting.
101 #include <sys/cdefs.h>
102 __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.230 2009/05/12 14:25:18 cegger Exp $");
104 #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
105 #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
108 #define STATIC static
110 #include "bpfilter.h"
112 #include <sys/param.h>
113 #include <sys/sysctl.h>
114 #include <sys/systm.h>
115 #include <sys/callout.h>
116 #include <sys/device.h>
117 #include <sys/socket.h>
118 #include <sys/mbuf.h>
119 #include <sys/ioctl.h>
120 #include <sys/kernel.h> /* for hz */
121 #include <sys/proc.h>
122 #include <sys/kauth.h>
125 #include <net/if_dl.h>
126 #include <net/if_llc.h>
127 #include <net/if_media.h>
128 #include <net/if_ether.h>
129 #include <net/route.h>
131 #include <net80211/ieee80211_netbsd.h>
132 #include <net80211/ieee80211_var.h>
133 #include <net80211/ieee80211_ioctl.h>
134 #include <net80211/ieee80211_radiotap.h>
135 #include <net80211/ieee80211_rssadapt.h>
139 #include <net/bpfdesc.h>
144 #include <dev/ic/wi_ieee.h>
145 #include <dev/ic/wireg.h>
146 #include <dev/ic/wivar.h>
148 STATIC
int wi_init(struct ifnet
*);
149 STATIC
void wi_stop(struct ifnet
*, int);
150 STATIC
void wi_start(struct ifnet
*);
151 STATIC
int wi_reset(struct wi_softc
*);
152 STATIC
void wi_watchdog(struct ifnet
*);
153 STATIC
int wi_ioctl(struct ifnet
*, u_long
, void *);
154 STATIC
int wi_media_change(struct ifnet
*);
155 STATIC
void wi_media_status(struct ifnet
*, struct ifmediareq
*);
157 STATIC
struct ieee80211_node
*wi_node_alloc(struct ieee80211_node_table
*);
158 STATIC
void wi_node_free(struct ieee80211_node
*);
160 STATIC
void wi_raise_rate(struct ieee80211com
*, struct ieee80211_rssdesc
*);
161 STATIC
void wi_lower_rate(struct ieee80211com
*, struct ieee80211_rssdesc
*);
162 STATIC
int wi_choose_rate(struct ieee80211com
*, struct ieee80211_node
*,
163 struct ieee80211_frame
*, u_int
);
164 STATIC
void wi_rssadapt_updatestats_cb(void *, struct ieee80211_node
*);
165 STATIC
void wi_rssadapt_updatestats(void *);
166 STATIC
void wi_rssdescs_init(struct wi_rssdesc (*)[], wi_rssdescq_t
*);
167 STATIC
void wi_rssdescs_reset(struct ieee80211com
*, struct wi_rssdesc (*)[],
168 wi_rssdescq_t
*, u_int8_t (*)[]);
169 STATIC
void wi_sync_bssid(struct wi_softc
*, u_int8_t new_bssid
[]);
171 STATIC
void wi_rx_intr(struct wi_softc
*);
172 STATIC
void wi_txalloc_intr(struct wi_softc
*);
173 STATIC
void wi_cmd_intr(struct wi_softc
*);
174 STATIC
void wi_tx_intr(struct wi_softc
*);
175 STATIC
void wi_tx_ex_intr(struct wi_softc
*);
176 STATIC
void wi_info_intr(struct wi_softc
*);
178 STATIC
int wi_key_delete(struct ieee80211com
*, const struct ieee80211_key
*);
179 STATIC
int wi_key_set(struct ieee80211com
*, const struct ieee80211_key
*,
180 const u_int8_t
[IEEE80211_ADDR_LEN
]);
181 STATIC
void wi_key_update_begin(struct ieee80211com
*);
182 STATIC
void wi_key_update_end(struct ieee80211com
*);
184 STATIC
void wi_push_packet(struct wi_softc
*);
185 STATIC
int wi_get_cfg(struct ifnet
*, u_long
, void *);
186 STATIC
int wi_set_cfg(struct ifnet
*, u_long
, void *);
187 STATIC
int wi_cfg_txrate(struct wi_softc
*);
188 STATIC
int wi_write_txrate(struct wi_softc
*, int);
189 STATIC
int wi_write_wep(struct wi_softc
*);
190 STATIC
int wi_write_multi(struct wi_softc
*);
191 STATIC
int wi_alloc_fid(struct wi_softc
*, int, int *);
192 STATIC
void wi_read_nicid(struct wi_softc
*);
193 STATIC
int wi_write_ssid(struct wi_softc
*, int, u_int8_t
*, int);
195 STATIC
int wi_cmd(struct wi_softc
*, int, int, int, int);
196 STATIC
int wi_cmd_start(struct wi_softc
*, int, int, int, int);
197 STATIC
int wi_cmd_wait(struct wi_softc
*, int, int);
198 STATIC
int wi_seek_bap(struct wi_softc
*, int, int);
199 STATIC
int wi_read_bap(struct wi_softc
*, int, int, void *, int);
200 STATIC
int wi_write_bap(struct wi_softc
*, int, int, void *, int);
201 STATIC
int wi_mwrite_bap(struct wi_softc
*, int, int, struct mbuf
*, int);
202 STATIC
int wi_read_rid(struct wi_softc
*, int, void *, int *);
203 STATIC
int wi_write_rid(struct wi_softc
*, int, void *, int);
205 STATIC
int wi_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
206 STATIC
void wi_set_tim(struct ieee80211_node
*, int);
208 STATIC
int wi_scan_ap(struct wi_softc
*, u_int16_t
, u_int16_t
);
209 STATIC
void wi_scan_result(struct wi_softc
*, int, int);
211 STATIC
void wi_dump_pkt(struct wi_frame
*, struct ieee80211_node
*, int rssi
);
212 STATIC
void wi_mend_flags(struct wi_softc
*, enum ieee80211_state
);
215 wi_write_val(struct wi_softc
*sc
, int rid
, u_int16_t val
)
219 return wi_write_rid(sc
, rid
, &val
, sizeof(val
));
222 static struct timeval lasttxerror
; /* time of last tx error msg */
223 static int curtxeps
= 0; /* current tx error msgs/sec */
224 static int wi_txerate
= 0; /* tx error rate: max msgs/sec */
227 #define WI_DEBUG_MAX 2
230 #define DPRINTF(X) if (wi_debug) printf X
231 #define DPRINTF2(X) if (wi_debug > 1) printf X
232 #define IFF_DUMPPKTS(_ifp) \
233 (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
234 static int wi_sysctl_verify_debug(SYSCTLFN_PROTO
);
238 #define IFF_DUMPPKTS(_ifp) 0
241 #define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO | \
242 WI_EV_TX | WI_EV_TX_EXC | WI_EV_CMD)
246 /* CARD_ID CARD_NAME FIRM_TYPE */
247 { WI_NIC_LUCENT_ID
, WI_NIC_LUCENT_STR
, WI_LUCENT
},
248 { WI_NIC_SONY_ID
, WI_NIC_SONY_STR
, WI_LUCENT
},
249 { WI_NIC_LUCENT_EMB_ID
, WI_NIC_LUCENT_EMB_STR
, WI_LUCENT
},
250 { WI_NIC_EVB2_ID
, WI_NIC_EVB2_STR
, WI_INTERSIL
},
251 { WI_NIC_HWB3763_ID
, WI_NIC_HWB3763_STR
, WI_INTERSIL
},
252 { WI_NIC_HWB3163_ID
, WI_NIC_HWB3163_STR
, WI_INTERSIL
},
253 { WI_NIC_HWB3163B_ID
, WI_NIC_HWB3163B_STR
, WI_INTERSIL
},
254 { WI_NIC_EVB3_ID
, WI_NIC_EVB3_STR
, WI_INTERSIL
},
255 { WI_NIC_HWB1153_ID
, WI_NIC_HWB1153_STR
, WI_INTERSIL
},
256 { WI_NIC_P2_SST_ID
, WI_NIC_P2_SST_STR
, WI_INTERSIL
},
257 { WI_NIC_EVB2_SST_ID
, WI_NIC_EVB2_SST_STR
, WI_INTERSIL
},
258 { WI_NIC_3842_EVA_ID
, WI_NIC_3842_EVA_STR
, WI_INTERSIL
},
259 { WI_NIC_3842_PCMCIA_AMD_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
260 { WI_NIC_3842_PCMCIA_SST_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
261 { WI_NIC_3842_PCMCIA_ATM_ID
, WI_NIC_3842_PCMCIA_STR
, WI_INTERSIL
},
262 { WI_NIC_3842_MINI_AMD_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
263 { WI_NIC_3842_MINI_SST_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
264 { WI_NIC_3842_MINI_ATM_ID
, WI_NIC_3842_MINI_STR
, WI_INTERSIL
},
265 { WI_NIC_3842_PCI_AMD_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
266 { WI_NIC_3842_PCI_SST_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
267 { WI_NIC_3842_PCI_ATM_ID
, WI_NIC_3842_PCI_STR
, WI_INTERSIL
},
268 { WI_NIC_P3_PCMCIA_AMD_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
269 { WI_NIC_P3_PCMCIA_SST_ID
, WI_NIC_P3_PCMCIA_STR
, WI_INTERSIL
},
270 { WI_NIC_P3_MINI_AMD_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
271 { WI_NIC_P3_MINI_SST_ID
, WI_NIC_P3_MINI_STR
, WI_INTERSIL
},
277 * Setup sysctl(3) MIB, hw.wi.*
279 * TBD condition CTLFLAG_PERMANENT on being a module or not
281 SYSCTL_SETUP(sysctl_wi
, "sysctl wi(4) subtree setup")
284 const struct sysctlnode
*rnode
;
286 const struct sysctlnode
*cnode
;
287 #endif /* WI_DEBUG */
289 if ((rc
= sysctl_createv(clog
, 0, NULL
, &rnode
,
290 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "hw", NULL
,
291 NULL
, 0, NULL
, 0, CTL_HW
, CTL_EOL
)) != 0)
294 if ((rc
= sysctl_createv(clog
, 0, &rnode
, &rnode
,
295 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "wi",
296 "Lucent/Prism/Symbol 802.11 controls",
297 NULL
, 0, NULL
, 0, CTL_CREATE
, CTL_EOL
)) != 0)
301 /* control debugging printfs */
302 if ((rc
= sysctl_createv(clog
, 0, &rnode
, &cnode
,
303 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
, CTLTYPE_INT
,
304 "debug", SYSCTL_DESCR("Enable debugging output"),
305 wi_sysctl_verify_debug
, 0, &wi_debug
, 0, CTL_CREATE
, CTL_EOL
)) != 0)
307 #endif /* WI_DEBUG */
310 printf("%s: sysctl_createv failed (rc = %d)\n", __func__
, rc
);
316 wi_sysctl_verify(SYSCTLFN_ARGS
, int lower
, int upper
)
319 struct sysctlnode node
;
322 t
= *(int*)rnode
->sysctl_data
;
323 node
.sysctl_data
= &t
;
324 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
325 if (error
|| newp
== NULL
)
328 if (t
< lower
|| t
> upper
)
331 *(int*)rnode
->sysctl_data
= t
;
337 wi_sysctl_verify_debug(SYSCTLFN_ARGS
)
339 return wi_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode
)),
342 #endif /* WI_DEBUG */
345 wi_read_xrid(struct wi_softc
*sc
, int rid
, void *buf
, int ebuflen
)
350 if ((rc
= wi_read_rid(sc
, rid
, buf
, &buflen
)) != 0)
353 if (buflen
< ebuflen
) {
355 printf("%s: rid=%#04x read %d, expected %d\n", __func__
,
356 rid
, buflen
, ebuflen
);
364 wi_attach(struct wi_softc
*sc
, const u_int8_t
*macaddr
)
366 struct ieee80211com
*ic
= &sc
->sc_ic
;
367 struct ifnet
*ifp
= &sc
->sc_if
;
368 int chan
, nrate
, buflen
;
369 u_int16_t val
, chanavail
;
372 char rates
[IEEE80211_RATE_SIZE
];
374 static const u_int8_t empty_macaddr
[IEEE80211_ADDR_LEN
] = {
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
381 /* Make sure interrupts are disabled. */
382 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
383 CSR_WRITE_2(sc
, WI_EVENT_ACK
, ~0);
388 if (wi_reset(sc
) != 0) {
394 if (wi_read_xrid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
,
395 IEEE80211_ADDR_LEN
) != 0 ||
396 IEEE80211_ADDR_EQ(ic
->ic_myaddr
, empty_macaddr
)) {
398 memcpy(ic
->ic_myaddr
, macaddr
, IEEE80211_ADDR_LEN
);
400 printf(" could not get mac address, attach failed\n");
406 printf(" 802.11 address %s\n", ether_sprintf(ic
->ic_myaddr
));
408 /* Read NIC identification */
411 memcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
413 ifp
->if_start
= wi_start
;
414 ifp
->if_ioctl
= wi_ioctl
;
415 ifp
->if_watchdog
= wi_watchdog
;
416 ifp
->if_init
= wi_init
;
417 ifp
->if_stop
= wi_stop
;
419 IFF_SIMPLEX
| IFF_BROADCAST
| IFF_MULTICAST
| IFF_NOTRAILERS
;
420 IFQ_SET_READY(&ifp
->if_snd
);
423 ic
->ic_phytype
= IEEE80211_T_DS
;
424 ic
->ic_opmode
= IEEE80211_M_STA
;
425 ic
->ic_caps
= IEEE80211_C_AHDEMO
;
426 ic
->ic_state
= IEEE80211_S_INIT
;
427 ic
->ic_max_aid
= WI_MAX_AID
;
429 /* Find available channel */
430 if (wi_read_xrid(sc
, WI_RID_CHANNEL_LIST
, &chanavail
,
431 sizeof(chanavail
)) != 0) {
432 aprint_normal_dev(&sc
->sc_dev
, "using default channel list\n");
433 chanavail
= htole16(0x1fff); /* assume 1-13 */
435 for (chan
= 16; chan
> 0; chan
--) {
436 if (!isset((u_int8_t
*)&chanavail
, chan
- 1))
438 ic
->ic_ibss_chan
= &ic
->ic_channels
[chan
];
439 ic
->ic_channels
[chan
].ic_freq
=
440 ieee80211_ieee2mhz(chan
, IEEE80211_CHAN_2GHZ
);
441 ic
->ic_channels
[chan
].ic_flags
= IEEE80211_CHAN_B
;
444 /* Find default IBSS channel */
445 if (wi_read_xrid(sc
, WI_RID_OWN_CHNL
, &val
, sizeof(val
)) == 0) {
447 if (isset((u_int8_t
*)&chanavail
, chan
- 1))
448 ic
->ic_ibss_chan
= &ic
->ic_channels
[chan
];
450 if (ic
->ic_ibss_chan
== NULL
) {
451 aprint_error_dev(&sc
->sc_dev
, "no available channel\n");
455 if (sc
->sc_firmware_type
== WI_LUCENT
) {
456 sc
->sc_dbm_offset
= WI_LUCENT_DBM_OFFSET
;
458 if ((sc
->sc_flags
& WI_FLAGS_HAS_DBMADJUST
) &&
459 wi_read_xrid(sc
, WI_RID_DBM_ADJUST
, &val
, sizeof(val
)) == 0)
460 sc
->sc_dbm_offset
= le16toh(val
);
462 sc
->sc_dbm_offset
= WI_PRISM_DBM_OFFSET
;
465 sc
->sc_flags
|= WI_FLAGS_RSSADAPTSTA
;
468 * Set flags based on firmware version.
470 switch (sc
->sc_firmware_type
) {
472 sc
->sc_flags
|= WI_FLAGS_HAS_SYSSCALE
;
473 #ifdef WI_HERMES_AUTOINC_WAR
474 /* XXX: not confirmed, but never seen for recent firmware */
475 if (sc
->sc_sta_firmware_ver
< 40000) {
476 sc
->sc_flags
|= WI_FLAGS_BUG_AUTOINC
;
479 if (sc
->sc_sta_firmware_ver
>= 60000)
480 sc
->sc_flags
|= WI_FLAGS_HAS_MOR
;
481 if (sc
->sc_sta_firmware_ver
>= 60006) {
482 ic
->ic_caps
|= IEEE80211_C_IBSS
;
483 ic
->ic_caps
|= IEEE80211_C_MONITOR
;
485 ic
->ic_caps
|= IEEE80211_C_PMGT
;
486 sc
->sc_ibss_port
= 1;
490 sc
->sc_flags
|= WI_FLAGS_HAS_FRAGTHR
;
491 sc
->sc_flags
|= WI_FLAGS_HAS_ROAMING
;
492 sc
->sc_flags
|= WI_FLAGS_HAS_SYSSCALE
;
493 if (sc
->sc_sta_firmware_ver
> 10101)
494 sc
->sc_flags
|= WI_FLAGS_HAS_DBMADJUST
;
495 if (sc
->sc_sta_firmware_ver
>= 800) {
496 if (sc
->sc_sta_firmware_ver
!= 10402)
497 ic
->ic_caps
|= IEEE80211_C_HOSTAP
;
498 ic
->ic_caps
|= IEEE80211_C_IBSS
;
499 ic
->ic_caps
|= IEEE80211_C_MONITOR
;
501 ic
->ic_caps
|= IEEE80211_C_PMGT
;
502 sc
->sc_ibss_port
= 0;
503 sc
->sc_alt_retry
= 2;
507 sc
->sc_flags
|= WI_FLAGS_HAS_DIVERSITY
;
508 if (sc
->sc_sta_firmware_ver
>= 20000)
509 ic
->ic_caps
|= IEEE80211_C_IBSS
;
510 sc
->sc_ibss_port
= 4;
515 * Find out if we support WEP on this card.
517 if (wi_read_xrid(sc
, WI_RID_WEP_AVAIL
, &val
, sizeof(val
)) == 0 &&
519 ic
->ic_caps
|= IEEE80211_C_WEP
;
521 /* Find supported rates. */
522 buflen
= sizeof(ratebuf
);
523 if (wi_read_rid(sc
, WI_RID_DATA_RATES
, &ratebuf
, &buflen
) == 0 &&
525 nrate
= le16toh(ratebuf
.nrates
);
526 if (nrate
> IEEE80211_RATE_SIZE
)
527 nrate
= IEEE80211_RATE_SIZE
;
528 memcpy(ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_rates
,
529 &ratebuf
.rates
[0], nrate
);
530 ic
->ic_sup_rates
[IEEE80211_MODE_11B
].rs_nrates
= nrate
;
532 aprint_error_dev(&sc
->sc_dev
, "no supported rate list\n");
536 sc
->sc_max_datalen
= 2304;
537 sc
->sc_rts_thresh
= 2347;
538 sc
->sc_frag_thresh
= 2346;
539 sc
->sc_system_scale
= 1;
540 sc
->sc_cnfauthmode
= IEEE80211_AUTH_OPEN
;
541 sc
->sc_roaming_mode
= 1;
543 callout_init(&sc
->sc_rssadapt_ch
, 0);
546 * Call MI attach routines.
549 ieee80211_ifattach(ic
);
551 sc
->sc_newstate
= ic
->ic_newstate
;
552 sc
->sc_set_tim
= ic
->ic_set_tim
;
553 ic
->ic_newstate
= wi_newstate
;
554 ic
->ic_node_alloc
= wi_node_alloc
;
555 ic
->ic_node_free
= wi_node_free
;
556 ic
->ic_set_tim
= wi_set_tim
;
558 ic
->ic_crypto
.cs_key_delete
= wi_key_delete
;
559 ic
->ic_crypto
.cs_key_set
= wi_key_set
;
560 ic
->ic_crypto
.cs_key_update_begin
= wi_key_update_begin
;
561 ic
->ic_crypto
.cs_key_update_end
= wi_key_update_end
;
563 ieee80211_media_init(ic
, wi_media_change
, wi_media_status
);
566 bpfattach2(ifp
, DLT_IEEE802_11_RADIO
,
567 sizeof(struct ieee80211_frame
) + 64, &sc
->sc_drvbpf
);
570 memset(&sc
->sc_rxtapu
, 0, sizeof(sc
->sc_rxtapu
));
571 sc
->sc_rxtap
.wr_ihdr
.it_len
= htole16(sizeof(sc
->sc_rxtapu
));
572 sc
->sc_rxtap
.wr_ihdr
.it_present
= htole32(WI_RX_RADIOTAP_PRESENT
);
574 memset(&sc
->sc_txtapu
, 0, sizeof(sc
->sc_txtapu
));
575 sc
->sc_txtap
.wt_ihdr
.it_len
= htole16(sizeof(sc
->sc_txtapu
));
576 sc
->sc_txtap
.wt_ihdr
.it_present
= htole32(WI_TX_RADIOTAP_PRESENT
);
578 /* Attach is successful. */
582 ieee80211_announce(ic
);
587 wi_detach(struct wi_softc
*sc
)
589 struct ifnet
*ifp
= &sc
->sc_if
;
592 if (!sc
->sc_attached
)
600 ieee80211_ifdetach(&sc
->sc_ic
);
607 wi_activate(device_t self
, enum devact act
)
609 struct wi_softc
*sc
= device_private(self
);
612 case DVACT_DEACTIVATE
:
613 if_deactivate(&sc
->sc_if
);
624 struct wi_softc
*sc
= arg
;
625 struct ifnet
*ifp
= &sc
->sc_if
;
628 if (sc
->sc_enabled
== 0 ||
629 !device_is_active(&sc
->sc_dev
) ||
630 (ifp
->if_flags
& IFF_RUNNING
) == 0)
633 if ((ifp
->if_flags
& IFF_UP
) == 0) {
634 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
635 CSR_WRITE_2(sc
, WI_EVENT_ACK
, ~0);
639 /* This is superfluous on Prism, but Lucent breaks if we
640 * do not disable interrupts.
642 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
644 /* maximum 10 loops per interrupt */
645 for (i
= 0; i
< 10; i
++) {
646 status
= CSR_READ_2(sc
, WI_EVENT_STAT
);
649 printf("%s: iter %d status %#04x\n", __func__
, i
,
652 #endif /* WI_DEBUG */
653 if ((status
& WI_INTRS
) == 0)
656 sc
->sc_status
= status
;
658 if (status
& WI_EV_RX
)
661 if (status
& WI_EV_ALLOC
)
664 if (status
& WI_EV_TX
)
667 if (status
& WI_EV_TX_EXC
)
670 if (status
& WI_EV_INFO
)
673 CSR_WRITE_2(sc
, WI_EVENT_ACK
, sc
->sc_status
);
675 if (sc
->sc_status
& WI_EV_CMD
)
678 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0 &&
679 (sc
->sc_flags
& WI_FLAGS_OUTRANGE
) == 0 &&
680 !IFQ_IS_EMPTY(&ifp
->if_snd
))
686 /* re-enable interrupts */
687 CSR_WRITE_2(sc
, WI_INT_EN
, WI_INTRS
);
694 #define arraylen(a) (sizeof(a) / sizeof((a)[0]))
697 wi_rssdescs_init(struct wi_rssdesc (*rssd
)[WI_NTXRSS
], wi_rssdescq_t
*rssdfree
)
700 SLIST_INIT(rssdfree
);
701 for (i
= 0; i
< arraylen(*rssd
); i
++) {
702 SLIST_INSERT_HEAD(rssdfree
, &(*rssd
)[i
], rd_next
);
707 wi_rssdescs_reset(struct ieee80211com
*ic
, struct wi_rssdesc (*rssd
)[WI_NTXRSS
],
708 wi_rssdescq_t
*rssdfree
, u_int8_t (*txpending
)[IEEE80211_RATE_MAXSIZE
])
710 struct ieee80211_node
*ni
;
712 for (i
= 0; i
< arraylen(*rssd
); i
++) {
713 ni
= (*rssd
)[i
].rd_desc
.id_node
;
714 (*rssd
)[i
].rd_desc
.id_node
= NULL
;
715 if (ni
!= NULL
&& (ic
->ic_ifp
->if_flags
& IFF_DEBUG
) != 0)
716 printf("%s: cleaning outstanding rssadapt "
717 "descriptor for %s\n",
718 ic
->ic_ifp
->if_xname
, ether_sprintf(ni
->ni_macaddr
));
720 ieee80211_free_node(ni
);
722 memset(*txpending
, 0, sizeof(*txpending
));
723 wi_rssdescs_init(rssd
, rssdfree
);
727 wi_init(struct ifnet
*ifp
)
729 struct wi_softc
*sc
= ifp
->if_softc
;
730 struct ieee80211com
*ic
= &sc
->sc_ic
;
731 struct wi_joinreq join
;
733 int error
= 0, wasenabled
;
735 DPRINTF(("wi_init: enabled %d\n", sc
->sc_enabled
));
736 wasenabled
= sc
->sc_enabled
;
737 if (!sc
->sc_enabled
) {
738 if ((error
= (*sc
->sc_enable
)(sc
)) != 0)
744 /* Symbol firmware cannot be initialized more than once */
745 if (sc
->sc_firmware_type
!= WI_SYMBOL
|| !wasenabled
)
746 if ((error
= wi_reset(sc
)) != 0)
749 /* common 802.11 configuration */
750 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
751 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
752 switch (ic
->ic_opmode
) {
753 case IEEE80211_M_STA
:
754 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_BSS
);
756 case IEEE80211_M_IBSS
:
757 wi_write_val(sc
, WI_RID_PORTTYPE
, sc
->sc_ibss_port
);
758 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
760 case IEEE80211_M_AHDEMO
:
761 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_ADHOC
);
763 case IEEE80211_M_HOSTAP
:
764 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_HOSTAP
);
766 case IEEE80211_M_MONITOR
:
767 if (sc
->sc_firmware_type
== WI_LUCENT
)
768 wi_write_val(sc
, WI_RID_PORTTYPE
, WI_PORTTYPE_ADHOC
);
769 wi_cmd(sc
, WI_CMD_TEST
| (WI_TEST_MONITOR
<< 8), 0, 0, 0);
773 /* Intersil interprets this RID as joining ESS even in IBSS mode */
774 if (sc
->sc_firmware_type
== WI_LUCENT
&&
775 (ic
->ic_flags
& IEEE80211_F_IBSSON
) && ic
->ic_des_esslen
> 0)
776 wi_write_val(sc
, WI_RID_CREATE_IBSS
, 1);
778 wi_write_val(sc
, WI_RID_CREATE_IBSS
, 0);
779 wi_write_val(sc
, WI_RID_MAX_SLEEP
, ic
->ic_lintval
);
780 wi_write_ssid(sc
, WI_RID_DESIRED_SSID
, ic
->ic_des_essid
,
782 wi_write_val(sc
, WI_RID_OWN_CHNL
,
783 ieee80211_chan2ieee(ic
, ic
->ic_ibss_chan
));
784 wi_write_ssid(sc
, WI_RID_OWN_SSID
, ic
->ic_des_essid
, ic
->ic_des_esslen
);
785 IEEE80211_ADDR_COPY(ic
->ic_myaddr
, CLLADDR(ifp
->if_sadl
));
786 wi_write_rid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
, IEEE80211_ADDR_LEN
);
787 if (ic
->ic_caps
& IEEE80211_C_PMGT
)
788 wi_write_val(sc
, WI_RID_PM_ENABLED
,
789 (ic
->ic_flags
& IEEE80211_F_PMGTON
) ? 1 : 0);
791 /* not yet common 802.11 configuration */
792 wi_write_val(sc
, WI_RID_MAX_DATALEN
, sc
->sc_max_datalen
);
793 wi_write_val(sc
, WI_RID_RTS_THRESH
, sc
->sc_rts_thresh
);
794 if (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
)
795 wi_write_val(sc
, WI_RID_FRAG_THRESH
, sc
->sc_frag_thresh
);
797 /* driver specific 802.11 configuration */
798 if (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
)
799 wi_write_val(sc
, WI_RID_SYSTEM_SCALE
, sc
->sc_system_scale
);
800 if (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
)
801 wi_write_val(sc
, WI_RID_ROAMING_MODE
, sc
->sc_roaming_mode
);
802 if (sc
->sc_flags
& WI_FLAGS_HAS_MOR
)
803 wi_write_val(sc
, WI_RID_MICROWAVE_OVEN
, sc
->sc_microwave_oven
);
805 wi_write_ssid(sc
, WI_RID_NODENAME
, sc
->sc_nodename
, sc
->sc_nodelen
);
807 #ifndef IEEE80211_NO_HOSTAP
808 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
809 sc
->sc_firmware_type
== WI_INTERSIL
) {
810 wi_write_val(sc
, WI_RID_OWN_BEACON_INT
, ic
->ic_lintval
);
811 wi_write_val(sc
, WI_RID_DTIM_PERIOD
, 1);
813 #endif /* !IEEE80211_NO_HOSTAP */
815 if (sc
->sc_firmware_type
== WI_INTERSIL
) {
816 struct ieee80211_rateset
*rs
=
817 &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
818 u_int16_t basic
= 0, supported
= 0, rate
;
820 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
821 switch (rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
) {
838 if (rs
->rs_rates
[i
] & IEEE80211_RATE_BASIC
)
842 wi_write_val(sc
, WI_RID_BASIC_RATE
, basic
);
843 wi_write_val(sc
, WI_RID_SUPPORT_RATE
, supported
);
844 wi_write_val(sc
, WI_RID_ALT_RETRY_COUNT
, sc
->sc_alt_retry
);
848 * Initialize promisc mode.
849 * Being in Host-AP mode causes a great
850 * deal of pain if promiscuous mode is set.
851 * Therefore we avoid confusing the firmware
852 * and always reset promisc mode in Host-AP
853 * mode. Host-AP sees all the packets anyway.
855 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
856 (ifp
->if_flags
& IFF_PROMISC
) != 0) {
857 wi_write_val(sc
, WI_RID_PROMISC
, 1);
859 wi_write_val(sc
, WI_RID_PROMISC
, 0);
863 if (ic
->ic_caps
& IEEE80211_C_WEP
) {
864 sc
->sc_cnfauthmode
= ic
->ic_bss
->ni_authmode
;
868 /* Set multicast filter. */
872 sc
->sc_txalloced
= 0;
876 sc
->sc_txstarted
= 0;
878 if (sc
->sc_firmware_type
!= WI_SYMBOL
|| !wasenabled
) {
879 sc
->sc_buflen
= IEEE80211_MAX_LEN
+ sizeof(struct wi_frame
);
880 if (sc
->sc_firmware_type
== WI_SYMBOL
)
881 sc
->sc_buflen
= 1585; /* XXX */
882 for (i
= 0; i
< WI_NTXBUF
; i
++) {
883 error
= wi_alloc_fid(sc
, sc
->sc_buflen
,
884 &sc
->sc_txd
[i
].d_fid
);
886 aprint_error_dev(&sc
->sc_dev
, "tx buffer allocation failed\n");
889 DPRINTF2(("wi_init: txbuf %d allocated %x\n", i
,
890 sc
->sc_txd
[i
].d_fid
));
895 wi_rssdescs_init(&sc
->sc_rssd
, &sc
->sc_rssdfree
);
897 /* Enable desired port */
898 wi_cmd(sc
, WI_CMD_ENABLE
| sc
->sc_portnum
, 0, 0, 0);
899 ifp
->if_flags
|= IFF_RUNNING
;
900 ifp
->if_flags
&= ~IFF_OACTIVE
;
901 ic
->ic_state
= IEEE80211_S_INIT
;
903 if (ic
->ic_opmode
== IEEE80211_M_AHDEMO
||
904 ic
->ic_opmode
== IEEE80211_M_IBSS
||
905 ic
->ic_opmode
== IEEE80211_M_MONITOR
||
906 ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
907 ieee80211_create_ibss(ic
, ic
->ic_ibss_chan
);
909 /* Enable interrupts */
910 CSR_WRITE_2(sc
, WI_INT_EN
, WI_INTRS
);
912 #ifndef IEEE80211_NO_HOSTAP
914 ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
915 sc
->sc_firmware_type
== WI_INTERSIL
) {
916 /* XXX: some card need to be re-enabled for hostap */
917 wi_cmd(sc
, WI_CMD_DISABLE
| WI_PORT0
, 0, 0, 0);
918 wi_cmd(sc
, WI_CMD_ENABLE
| WI_PORT0
, 0, 0, 0);
920 #endif /* !IEEE80211_NO_HOSTAP */
922 if (ic
->ic_opmode
== IEEE80211_M_STA
&&
923 ((ic
->ic_flags
& IEEE80211_F_DESBSSID
) ||
924 ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)) {
925 memset(&join
, 0, sizeof(join
));
926 if (ic
->ic_flags
& IEEE80211_F_DESBSSID
)
927 IEEE80211_ADDR_COPY(&join
.wi_bssid
, ic
->ic_des_bssid
);
928 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
)
930 htole16(ieee80211_chan2ieee(ic
, ic
->ic_des_chan
));
931 /* Lucent firmware does not support the JOIN RID. */
932 if (sc
->sc_firmware_type
!= WI_LUCENT
)
933 wi_write_rid(sc
, WI_RID_JOIN_REQ
, &join
, sizeof(join
));
938 printf("%s: interface not running\n", device_xname(&sc
->sc_dev
));
941 DPRINTF(("wi_init: return %d\n", error
));
946 wi_txcmd_wait(struct wi_softc
*sc
)
948 KASSERT(sc
->sc_txcmds
== 1);
949 if (sc
->sc_status
& WI_EV_CMD
) {
950 sc
->sc_status
&= ~WI_EV_CMD
;
951 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_CMD
);
953 (void)wi_cmd_wait(sc
, WI_CMD_TX
| WI_RECLAIM
, 0);
957 wi_stop(struct ifnet
*ifp
, int disable
)
959 struct wi_softc
*sc
= ifp
->if_softc
;
960 struct ieee80211com
*ic
= &sc
->sc_ic
;
968 DPRINTF(("wi_stop: disable %d\n", disable
));
970 ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
972 /* wait for tx command completion (deassoc, deauth) */
973 while (sc
->sc_txcmds
> 0) {
978 /* TBD wait for deassoc, deauth tx completion? */
980 if (!sc
->sc_invalid
) {
981 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
982 wi_cmd(sc
, WI_CMD_DISABLE
| sc
->sc_portnum
, 0, 0, 0);
985 wi_rssdescs_reset(ic
, &sc
->sc_rssd
, &sc
->sc_rssdfree
,
989 sc
->sc_scan_timer
= 0;
990 sc
->sc_false_syns
= 0;
992 ifp
->if_flags
&= ~(IFF_OACTIVE
| IFF_RUNNING
);
997 (*sc
->sc_disable
)(sc
);
1004 * Choose a data rate for a packet len bytes long that suits the packet
1005 * type and the wireless conditions.
1007 * TBD Adapt fragmentation threshold.
1010 wi_choose_rate(struct ieee80211com
*ic
, struct ieee80211_node
*ni
,
1011 struct ieee80211_frame
*wh
, u_int len
)
1013 struct wi_softc
*sc
= ic
->ic_ifp
->if_softc
;
1014 struct wi_node
*wn
= (void*)ni
;
1015 struct ieee80211_rssadapt
*ra
= &wn
->wn_rssadapt
;
1016 int do_not_adapt
, i
, rateidx
, s
;
1018 do_not_adapt
= (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
) &&
1019 (sc
->sc_flags
& WI_FLAGS_RSSADAPTSTA
) == 0;
1023 rateidx
= ieee80211_rssadapt_choose(ra
, &ni
->ni_rates
, wh
, len
,
1025 ((ic
->ic_ifp
->if_flags
& IFF_DEBUG
) == 0) ? NULL
: ic
->ic_ifp
->if_xname
,
1028 ni
->ni_txrate
= rateidx
;
1030 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
) {
1031 /* choose the slowest pending rate so that we don't
1032 * accidentally send a packet on the MAC's queue
1033 * too fast. TBD find out if the MAC labels Tx
1034 * packets w/ rate when enqueued or dequeued.
1036 for (i
= 0; i
< rateidx
&& sc
->sc_txpending
[i
] == 0; i
++);
1045 wi_raise_rate(struct ieee80211com
*ic
, struct ieee80211_rssdesc
*id
)
1048 if (id
->id_node
== NULL
)
1051 wn
= (void*)id
->id_node
;
1052 ieee80211_rssadapt_raise_rate(ic
, &wn
->wn_rssadapt
, id
);
1056 wi_lower_rate(struct ieee80211com
*ic
, struct ieee80211_rssdesc
*id
)
1058 struct ieee80211_node
*ni
;
1064 if ((ni
= id
->id_node
) == NULL
) {
1065 DPRINTF(("wi_lower_rate: missing node\n"));
1071 ieee80211_rssadapt_lower_rate(ic
, ni
, &wn
->wn_rssadapt
, id
);
1078 wi_start(struct ifnet
*ifp
)
1080 struct wi_softc
*sc
= ifp
->if_softc
;
1081 struct ieee80211com
*ic
= &sc
->sc_ic
;
1082 struct ether_header
*eh
;
1083 struct ieee80211_node
*ni
;
1084 struct ieee80211_frame
*wh
;
1085 struct ieee80211_rateset
*rs
;
1086 struct wi_rssdesc
*rd
;
1087 struct ieee80211_rssdesc
*id
;
1089 struct wi_frame frmhdr
;
1090 int cur
, fid
, off
, rateidx
;
1092 if (!sc
->sc_enabled
|| sc
->sc_invalid
)
1094 if (sc
->sc_flags
& WI_FLAGS_OUTRANGE
)
1097 memset(&frmhdr
, 0, sizeof(frmhdr
));
1098 cur
= sc
->sc_txqueue
;
1101 if (sc
->sc_txalloced
== 0 || SLIST_EMPTY(&sc
->sc_rssdfree
)) {
1102 ifp
->if_flags
|= IFF_OACTIVE
;
1105 if (!IF_IS_EMPTY(&ic
->ic_mgtq
)) {
1106 IF_DEQUEUE(&ic
->ic_mgtq
, m0
);
1107 m_copydata(m0
, 4, ETHER_ADDR_LEN
* 2,
1108 (void *)&frmhdr
.wi_ehdr
);
1109 frmhdr
.wi_ehdr
.ether_type
= 0;
1110 wh
= mtod(m0
, struct ieee80211_frame
*);
1111 ni
= (struct ieee80211_node
*)m0
->m_pkthdr
.rcvif
;
1112 m0
->m_pkthdr
.rcvif
= NULL
;
1113 } else if (ic
->ic_state
== IEEE80211_S_RUN
) {
1114 IFQ_POLL(&ifp
->if_snd
, m0
);
1117 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
1119 m_copydata(m0
, 0, ETHER_HDR_LEN
,
1120 (void *)&frmhdr
.wi_ehdr
);
1123 bpf_mtap(ifp
->if_bpf
, m0
);
1126 eh
= mtod(m0
, struct ether_header
*);
1127 ni
= ieee80211_find_txnode(ic
, eh
->ether_dhost
);
1132 if ((ni
->ni_flags
& IEEE80211_NODE_PWR_MGT
) &&
1133 (m0
->m_flags
& M_PWR_SAV
) == 0) {
1134 ieee80211_pwrsave(ic
, ni
, m0
);
1137 if ((m0
= ieee80211_encap(ic
, m0
, ni
)) == NULL
) {
1138 ieee80211_free_node(ni
);
1142 wh
= mtod(m0
, struct ieee80211_frame
*);
1147 bpf_mtap(ic
->ic_rawbpf
, m0
);
1150 htole16(WI_ENC_TX_802_11
|WI_TXCNTL_TX_EX
|WI_TXCNTL_TX_OK
);
1151 #ifndef IEEE80211_NO_HOSTAP
1152 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
1153 frmhdr
.wi_tx_ctl
|= htole16(WI_TXCNTL_ALTRTRY
);
1154 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
1155 (wh
->i_fc
[1] & IEEE80211_FC1_WEP
)) {
1156 if (ieee80211_crypto_encap(ic
, ni
, m0
) == NULL
) {
1161 frmhdr
.wi_tx_ctl
|= htole16(WI_TXCNTL_NOCRYPT
);
1163 #endif /* !IEEE80211_NO_HOSTAP */
1165 rateidx
= wi_choose_rate(ic
, ni
, wh
, m0
->m_pkthdr
.len
);
1169 if (sc
->sc_drvbpf
) {
1170 struct wi_tx_radiotap_header
*tap
= &sc
->sc_txtap
;
1172 tap
->wt_rate
= rs
->rs_rates
[rateidx
];
1174 htole16(ic
->ic_bss
->ni_chan
->ic_freq
);
1175 tap
->wt_chan_flags
=
1176 htole16(ic
->ic_bss
->ni_chan
->ic_flags
);
1177 /* TBD tap->wt_flags */
1179 bpf_mtap2(sc
->sc_drvbpf
, tap
, tap
->wt_ihdr
.it_len
, m0
);
1183 rd
= SLIST_FIRST(&sc
->sc_rssdfree
);
1185 id
->id_len
= m0
->m_pkthdr
.len
;
1186 id
->id_rateidx
= ni
->ni_txrate
;
1187 id
->id_rssi
= ni
->ni_rssi
;
1189 frmhdr
.wi_tx_idx
= rd
- sc
->sc_rssd
;
1191 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
1192 frmhdr
.wi_tx_rate
= 5 * (rs
->rs_rates
[rateidx
] &
1193 IEEE80211_RATE_VAL
);
1194 else if (sc
->sc_flags
& WI_FLAGS_RSSADAPTSTA
)
1195 (void)wi_write_txrate(sc
, rs
->rs_rates
[rateidx
]);
1197 m_copydata(m0
, 0, sizeof(struct ieee80211_frame
),
1198 (void *)&frmhdr
.wi_whdr
);
1199 m_adj(m0
, sizeof(struct ieee80211_frame
));
1200 frmhdr
.wi_dat_len
= htole16(m0
->m_pkthdr
.len
);
1201 if (IFF_DUMPPKTS(ifp
))
1202 wi_dump_pkt(&frmhdr
, ni
, -1);
1203 fid
= sc
->sc_txd
[cur
].d_fid
;
1204 off
= sizeof(frmhdr
);
1205 if (wi_write_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) != 0 ||
1206 wi_mwrite_bap(sc
, fid
, off
, m0
, m0
->m_pkthdr
.len
) != 0) {
1207 aprint_error_dev(&sc
->sc_dev
, "%s write fid %x failed\n",
1214 sc
->sc_txpending
[ni
->ni_txrate
]++;
1216 if (sc
->sc_txqueued
++ == 0) {
1218 if (cur
!= sc
->sc_txstart
)
1219 printf("%s: ring is desynchronized\n",
1220 device_xname(&sc
->sc_dev
));
1224 #ifdef WI_RING_DEBUG
1225 printf("%s: queue %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
1226 device_xname(&sc
->sc_dev
), fid
,
1227 sc
->sc_txalloc
, sc
->sc_txqueue
, sc
->sc_txstart
,
1228 sc
->sc_txalloced
, sc
->sc_txqueued
, sc
->sc_txstarted
);
1231 sc
->sc_txqueue
= cur
= (cur
+ 1) % WI_NTXBUF
;
1232 SLIST_REMOVE_HEAD(&sc
->sc_rssdfree
, rd_next
);
1237 ieee80211_free_node(ni
);
1243 wi_reset(struct wi_softc
*sc
)
1247 DPRINTF(("wi_reset\n"));
1250 (*sc
->sc_reset
)(sc
);
1253 for (i
= 0; i
< 5; i
++) {
1256 DELAY(20*1000); /* XXX: way too long! */
1257 if ((error
= wi_cmd(sc
, WI_CMD_INI
, 0, 0, 0)) == 0)
1261 aprint_error_dev(&sc
->sc_dev
, "init failed\n");
1264 CSR_WRITE_2(sc
, WI_INT_EN
, 0);
1265 CSR_WRITE_2(sc
, WI_EVENT_ACK
, ~0);
1267 /* Calibrate timer. */
1268 wi_write_val(sc
, WI_RID_TICK_TIME
, 0);
1273 wi_watchdog(struct ifnet
*ifp
)
1275 struct wi_softc
*sc
= ifp
->if_softc
;
1278 if (!sc
->sc_enabled
)
1281 if (sc
->sc_tx_timer
) {
1282 if (--sc
->sc_tx_timer
== 0) {
1283 printf("%s: device timeout\n", ifp
->if_xname
);
1291 if (sc
->sc_scan_timer
) {
1292 if (--sc
->sc_scan_timer
<= WI_SCAN_WAIT
- WI_SCAN_INQWAIT
&&
1293 sc
->sc_firmware_type
== WI_INTERSIL
) {
1294 DPRINTF(("wi_watchdog: inquire scan\n"));
1295 wi_cmd(sc
, WI_CMD_INQUIRE
, WI_INFO_SCAN_RESULTS
, 0, 0);
1297 if (sc
->sc_scan_timer
)
1301 /* TODO: rate control */
1302 ieee80211_watchdog(&sc
->sc_ic
);
1306 wi_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
1308 struct wi_softc
*sc
= ifp
->if_softc
;
1309 struct ieee80211com
*ic
= &sc
->sc_ic
;
1310 struct ifreq
*ifr
= (struct ifreq
*)data
;
1313 if (!device_is_active(&sc
->sc_dev
))
1320 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
1323 * Can't do promisc and hostap at the same time. If all that's
1324 * changing is the promisc flag, try to short-circuit a call to
1325 * wi_init() by just setting PROMISC in the hardware.
1327 if (ifp
->if_flags
& IFF_UP
) {
1328 if (sc
->sc_enabled
) {
1329 if (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
1330 (ifp
->if_flags
& IFF_PROMISC
) != 0)
1331 wi_write_val(sc
, WI_RID_PROMISC
, 1);
1333 wi_write_val(sc
, WI_RID_PROMISC
, 0);
1335 error
= wi_init(ifp
);
1336 } else if (sc
->sc_enabled
)
1341 error
= ifmedia_ioctl(ifp
, ifr
, &ic
->ic_media
, cmd
);
1345 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
1346 if (ifp
->if_flags
& IFF_RUNNING
) {
1348 error
= wi_write_multi(sc
);
1353 case SIOCGIFGENERIC
:
1354 error
= wi_get_cfg(ifp
, cmd
, data
);
1356 case SIOCSIFGENERIC
:
1357 error
= kauth_authorize_network(curlwp
->l_cred
,
1358 KAUTH_NETWORK_INTERFACE
,
1359 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, KAUTH_ARG(cmd
),
1363 error
= wi_set_cfg(ifp
, cmd
, data
);
1364 if (error
== ENETRESET
) {
1365 if (ifp
->if_flags
& IFF_RUNNING
)
1366 error
= wi_init(ifp
);
1371 case SIOCS80211BSSID
:
1372 if (sc
->sc_firmware_type
== WI_LUCENT
) {
1378 ic
->ic_flags
|= sc
->sc_ic_flags
;
1379 error
= ieee80211_ioctl(&sc
->sc_ic
, cmd
, data
);
1380 sc
->sc_ic_flags
= ic
->ic_flags
& IEEE80211_F_DROPUNENC
;
1381 if (error
== ENETRESET
) {
1383 error
= wi_init(ifp
);
1389 wi_mend_flags(sc
, ic
->ic_state
);
1395 wi_media_change(struct ifnet
*ifp
)
1397 struct wi_softc
*sc
= ifp
->if_softc
;
1398 struct ieee80211com
*ic
= &sc
->sc_ic
;
1401 error
= ieee80211_media_change(ifp
);
1402 if (error
== ENETRESET
) {
1404 error
= wi_init(ifp
);
1408 ifp
->if_baudrate
= ifmedia_baudrate(ic
->ic_media
.ifm_cur
->ifm_media
);
1414 wi_media_status(struct ifnet
*ifp
, struct ifmediareq
*imr
)
1416 struct wi_softc
*sc
= ifp
->if_softc
;
1417 struct ieee80211com
*ic
= &sc
->sc_ic
;
1421 if (sc
->sc_enabled
== 0) {
1422 imr
->ifm_active
= IFM_IEEE80211
| IFM_NONE
;
1423 imr
->ifm_status
= 0;
1427 imr
->ifm_status
= IFM_AVALID
;
1428 imr
->ifm_active
= IFM_IEEE80211
;
1429 if (ic
->ic_state
== IEEE80211_S_RUN
&&
1430 (sc
->sc_flags
& WI_FLAGS_OUTRANGE
) == 0)
1431 imr
->ifm_status
|= IFM_ACTIVE
;
1432 if (wi_read_xrid(sc
, WI_RID_CUR_TX_RATE
, &val
, sizeof(val
)) == 0) {
1433 /* convert to 802.11 rate */
1436 if (sc
->sc_firmware_type
== WI_LUCENT
) {
1438 rate
= 11; /* 5.5Mbps */
1441 rate
= 11; /* 5.5Mbps */
1442 else if (rate
== 8*2)
1443 rate
= 22; /* 11Mbps */
1447 imr
->ifm_active
|= ieee80211_rate2media(ic
, rate
, IEEE80211_MODE_11B
);
1448 switch (ic
->ic_opmode
) {
1449 case IEEE80211_M_STA
:
1451 case IEEE80211_M_IBSS
:
1452 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
;
1454 case IEEE80211_M_AHDEMO
:
1455 imr
->ifm_active
|= IFM_IEEE80211_ADHOC
| IFM_FLAG0
;
1457 case IEEE80211_M_HOSTAP
:
1458 imr
->ifm_active
|= IFM_IEEE80211_HOSTAP
;
1460 case IEEE80211_M_MONITOR
:
1461 imr
->ifm_active
|= IFM_IEEE80211_MONITOR
;
1466 STATIC
struct ieee80211_node
*
1467 wi_node_alloc(struct ieee80211_node_table
*nt
)
1469 struct wi_node
*wn
=
1470 malloc(sizeof(struct wi_node
), M_DEVBUF
, M_NOWAIT
| M_ZERO
);
1471 return wn
? &wn
->wn_node
: NULL
;
1475 wi_node_free(struct ieee80211_node
*ni
)
1477 struct wi_softc
*sc
= ni
->ni_ic
->ic_ifp
->if_softc
;
1480 for (i
= 0; i
< WI_NTXRSS
; i
++) {
1481 if (sc
->sc_rssd
[i
].rd_desc
.id_node
== ni
)
1482 sc
->sc_rssd
[i
].rd_desc
.id_node
= NULL
;
1488 wi_sync_bssid(struct wi_softc
*sc
, u_int8_t new_bssid
[IEEE80211_ADDR_LEN
])
1490 struct ieee80211com
*ic
= &sc
->sc_ic
;
1491 struct ieee80211_node
*ni
= ic
->ic_bss
;
1492 struct ifnet
*ifp
= &sc
->sc_if
;
1494 if (IEEE80211_ADDR_EQ(new_bssid
, ni
->ni_bssid
))
1497 DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni
->ni_bssid
)));
1498 DPRINTF(("%s ?\n", ether_sprintf(new_bssid
)));
1500 /* In promiscuous mode, the BSSID field is not a reliable
1501 * indicator of the firmware's BSSID. Damp spurious
1502 * change-of-BSSID indications.
1504 if ((ifp
->if_flags
& IFF_PROMISC
) != 0 &&
1505 !ppsratecheck(&sc
->sc_last_syn
, &sc
->sc_false_syns
,
1509 sc
->sc_false_syns
= MAX(0, sc
->sc_false_syns
- 1);
1511 * XXX hack; we should create a new node with the new bssid
1512 * and replace the existing ic_bss with it but since we don't
1513 * process management frames to collect state we cheat by
1514 * reusing the existing node as we know wi_newstate will be
1515 * called and it will overwrite the node state.
1517 ieee80211_sta_join(ic
, ieee80211_ref_node(ni
));
1521 wi_rssadapt_input(struct ieee80211com
*ic
, struct ieee80211_node
*ni
,
1522 struct ieee80211_frame
*wh
, int rssi
)
1527 printf("%s: null node", __func__
);
1532 ieee80211_rssadapt_input(ic
, ni
, &wn
->wn_rssadapt
, rssi
);
1536 wi_rx_intr(struct wi_softc
*sc
)
1538 struct ieee80211com
*ic
= &sc
->sc_ic
;
1539 struct ifnet
*ifp
= &sc
->sc_if
;
1540 struct ieee80211_node
*ni
;
1541 struct wi_frame frmhdr
;
1543 struct ieee80211_frame
*wh
;
1544 int fid
, len
, off
, rssi
;
1549 fid
= CSR_READ_2(sc
, WI_RX_FID
);
1551 /* First read in the frame header */
1552 if (wi_read_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
))) {
1553 aprint_error_dev(&sc
->sc_dev
, "%s read fid %x failed\n",
1559 if (IFF_DUMPPKTS(ifp
))
1560 wi_dump_pkt(&frmhdr
, NULL
, frmhdr
.wi_rx_signal
);
1563 * Drop undecryptable or packets with receive errors here
1565 status
= le16toh(frmhdr
.wi_status
);
1566 if ((status
& WI_STAT_ERRSTAT
) != 0 &&
1567 ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1569 DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid
, status
));
1572 rssi
= frmhdr
.wi_rx_signal
;
1573 rstamp
= (le16toh(frmhdr
.wi_rx_tstamp0
) << 16) |
1574 le16toh(frmhdr
.wi_rx_tstamp1
);
1576 len
= le16toh(frmhdr
.wi_dat_len
);
1577 off
= ALIGN(sizeof(struct ieee80211_frame
));
1579 /* Sometimes the PRISM2.x returns bogusly large frames. Except
1580 * in monitor mode, just throw them away.
1582 if (off
+ len
> MCLBYTES
) {
1583 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
) {
1585 DPRINTF(("wi_rx_intr: oversized packet\n"));
1591 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1594 DPRINTF(("wi_rx_intr: MGET failed\n"));
1597 if (off
+ len
> MHLEN
) {
1598 MCLGET(m
, M_DONTWAIT
);
1599 if ((m
->m_flags
& M_EXT
) == 0) {
1602 DPRINTF(("wi_rx_intr: MCLGET failed\n"));
1607 m
->m_data
+= off
- sizeof(struct ieee80211_frame
);
1608 memcpy(m
->m_data
, &frmhdr
.wi_whdr
, sizeof(struct ieee80211_frame
));
1609 wi_read_bap(sc
, fid
, sizeof(frmhdr
),
1610 m
->m_data
+ sizeof(struct ieee80211_frame
), len
);
1611 m
->m_pkthdr
.len
= m
->m_len
= sizeof(struct ieee80211_frame
) + len
;
1612 m
->m_pkthdr
.rcvif
= ifp
;
1614 wh
= mtod(m
, struct ieee80211_frame
*);
1615 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
1617 * WEP is decrypted by hardware. Clear WEP bit
1618 * header for ieee80211_input().
1620 wh
->i_fc
[1] &= ~IEEE80211_FC1_WEP
;
1623 if (sc
->sc_drvbpf
) {
1624 struct wi_rx_radiotap_header
*tap
= &sc
->sc_rxtap
;
1626 tap
->wr_rate
= frmhdr
.wi_rx_rate
/ 5;
1627 tap
->wr_antsignal
= frmhdr
.wi_rx_signal
;
1628 tap
->wr_antnoise
= frmhdr
.wi_rx_silence
;
1629 tap
->wr_chan_freq
= htole16(ic
->ic_bss
->ni_chan
->ic_freq
);
1630 tap
->wr_chan_flags
= htole16(ic
->ic_bss
->ni_chan
->ic_flags
);
1631 if (frmhdr
.wi_status
& WI_STAT_PCF
)
1632 tap
->wr_flags
|= IEEE80211_RADIOTAP_F_CFP
;
1634 /* XXX IEEE80211_RADIOTAP_F_WEP */
1635 bpf_mtap2(sc
->sc_drvbpf
, tap
, tap
->wr_ihdr
.it_len
, m
);
1639 /* synchronize driver's BSSID with firmware's BSSID */
1640 dir
= wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
;
1641 if (ic
->ic_opmode
== IEEE80211_M_IBSS
&& dir
== IEEE80211_FC1_DIR_NODS
)
1642 wi_sync_bssid(sc
, wh
->i_addr3
);
1644 ni
= ieee80211_find_rxnode(ic
, mtod(m
, struct ieee80211_frame_min
*));
1646 ieee80211_input(ic
, m
, ni
, rssi
, rstamp
);
1648 wi_rssadapt_input(ic
, ni
, wh
, rssi
);
1651 * The frame may have caused the node to be marked for
1652 * reclamation (e.g. in response to a DEAUTH message)
1653 * so use release_node here instead of unref_node.
1655 ieee80211_free_node(ni
);
1659 wi_tx_ex_intr(struct wi_softc
*sc
)
1661 struct ieee80211com
*ic
= &sc
->sc_ic
;
1662 struct ifnet
*ifp
= &sc
->sc_if
;
1663 struct ieee80211_node
*ni
;
1664 struct ieee80211_rssdesc
*id
;
1665 struct wi_rssdesc
*rssd
;
1666 struct wi_frame frmhdr
;
1670 fid
= CSR_READ_2(sc
, WI_TX_CMP_FID
);
1671 /* Read in the frame header */
1672 if (wi_read_bap(sc
, fid
, 0, &frmhdr
, sizeof(frmhdr
)) != 0) {
1673 aprint_error_dev(&sc
->sc_dev
, "%s read fid %x failed\n",
1675 wi_rssdescs_reset(ic
, &sc
->sc_rssd
, &sc
->sc_rssdfree
,
1680 if (frmhdr
.wi_tx_idx
>= WI_NTXRSS
) {
1681 printf("%s: %s bad idx %02x\n",
1682 device_xname(&sc
->sc_dev
), __func__
, frmhdr
.wi_tx_idx
);
1683 wi_rssdescs_reset(ic
, &sc
->sc_rssd
, &sc
->sc_rssdfree
,
1688 status
= le16toh(frmhdr
.wi_status
);
1691 * Spontaneous station disconnects appear as xmit
1692 * errors. Don't announce them and/or count them
1693 * as an output error.
1695 if (ppsratecheck(&lasttxerror
, &curtxeps
, wi_txerate
)) {
1696 aprint_error_dev(&sc
->sc_dev
, "tx failed");
1697 if (status
& WI_TXSTAT_RET_ERR
)
1698 printf(", retry limit exceeded");
1699 if (status
& WI_TXSTAT_AGED_ERR
)
1700 printf(", max transmit lifetime exceeded");
1701 if (status
& WI_TXSTAT_DISCONNECT
)
1702 printf(", port disconnected");
1703 if (status
& WI_TXSTAT_FORM_ERR
)
1704 printf(", invalid format (data len %u src %s)",
1705 le16toh(frmhdr
.wi_dat_len
),
1706 ether_sprintf(frmhdr
.wi_ehdr
.ether_shost
));
1708 printf(", status=0x%x", status
);
1712 rssd
= &sc
->sc_rssd
[frmhdr
.wi_tx_idx
];
1713 id
= &rssd
->rd_desc
;
1714 if ((status
& WI_TXSTAT_RET_ERR
) != 0)
1715 wi_lower_rate(ic
, id
);
1721 aprint_error_dev(&sc
->sc_dev
, "%s null node, rssdesc %02x\n",
1722 __func__
, frmhdr
.wi_tx_idx
);
1726 if (sc
->sc_txpending
[id
->id_rateidx
]-- == 0) {
1727 aprint_error_dev(&sc
->sc_dev
, "%s txpending[%i] wraparound",
1728 __func__
, id
->id_rateidx
);
1729 sc
->sc_txpending
[id
->id_rateidx
] = 0;
1732 ieee80211_free_node(ni
);
1733 SLIST_INSERT_HEAD(&sc
->sc_rssdfree
, rssd
, rd_next
);
1735 ifp
->if_flags
&= ~IFF_OACTIVE
;
1739 wi_txalloc_intr(struct wi_softc
*sc
)
1743 fid
= CSR_READ_2(sc
, WI_ALLOC_FID
);
1745 cur
= sc
->sc_txalloc
;
1747 if (sc
->sc_txstarted
== 0) {
1748 printf("%s: spurious alloc %x != %x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
1749 device_xname(&sc
->sc_dev
), fid
, sc
->sc_txd
[cur
].d_fid
, cur
,
1750 sc
->sc_txqueue
, sc
->sc_txstart
, sc
->sc_txalloced
, sc
->sc_txqueued
, sc
->sc_txstarted
);
1756 sc
->sc_txd
[cur
].d_fid
= fid
;
1757 sc
->sc_txalloc
= (cur
+ 1) % WI_NTXBUF
;
1758 #ifdef WI_RING_DEBUG
1759 printf("%s: alloc %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
1760 device_xname(&sc
->sc_dev
), fid
,
1761 sc
->sc_txalloc
, sc
->sc_txqueue
, sc
->sc_txstart
,
1762 sc
->sc_txalloced
, sc
->sc_txqueued
, sc
->sc_txstarted
);
1767 wi_cmd_intr(struct wi_softc
*sc
)
1769 struct ifnet
*ifp
= &sc
->sc_if
;
1775 printf("%s: %d txcmds outstanding\n", __func__
, sc
->sc_txcmds
);
1777 KASSERT(sc
->sc_txcmds
> 0);
1781 if (--sc
->sc_txqueued
== 0) {
1782 sc
->sc_tx_timer
= 0;
1783 ifp
->if_flags
&= ~IFF_OACTIVE
;
1784 #ifdef WI_RING_DEBUG
1785 printf("%s: cmd , alloc %d queue %d start %d alloced %d queued %d started %d\n",
1786 device_xname(&sc
->sc_dev
),
1787 sc
->sc_txalloc
, sc
->sc_txqueue
, sc
->sc_txstart
,
1788 sc
->sc_txalloced
, sc
->sc_txqueued
, sc
->sc_txstarted
);
1795 wi_push_packet(struct wi_softc
*sc
)
1797 struct ifnet
*ifp
= &sc
->sc_if
;
1800 cur
= sc
->sc_txstart
;
1801 fid
= sc
->sc_txd
[cur
].d_fid
;
1803 KASSERT(sc
->sc_txcmds
== 0);
1805 if (wi_cmd_start(sc
, WI_CMD_TX
| WI_RECLAIM
, fid
, 0, 0)) {
1806 aprint_error_dev(&sc
->sc_dev
, "xmit failed\n");
1807 /* XXX ring might have a hole */
1810 if (sc
->sc_txcmds
++ > 0)
1811 printf("%s: %d tx cmds pending!!!\n", __func__
, sc
->sc_txcmds
);
1815 if (sc
->sc_txstarted
> WI_NTXBUF
)
1816 aprint_error_dev(&sc
->sc_dev
, "too many buffers started\n");
1818 sc
->sc_txstart
= (cur
+ 1) % WI_NTXBUF
;
1819 sc
->sc_tx_timer
= 5;
1821 #ifdef WI_RING_DEBUG
1822 printf("%s: push %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
1823 device_xname(&sc
->sc_dev
), fid
,
1824 sc
->sc_txalloc
, sc
->sc_txqueue
, sc
->sc_txstart
,
1825 sc
->sc_txalloced
, sc
->sc_txqueued
, sc
->sc_txstarted
);
1830 wi_tx_intr(struct wi_softc
*sc
)
1832 struct ieee80211com
*ic
= &sc
->sc_ic
;
1833 struct ifnet
*ifp
= &sc
->sc_if
;
1834 struct ieee80211_node
*ni
;
1835 struct ieee80211_rssdesc
*id
;
1836 struct wi_rssdesc
*rssd
;
1837 struct wi_frame frmhdr
;
1840 fid
= CSR_READ_2(sc
, WI_TX_CMP_FID
);
1841 /* Read in the frame header */
1842 if (wi_read_bap(sc
, fid
, offsetof(struct wi_frame
, wi_tx_swsup2
),
1843 &frmhdr
.wi_tx_swsup2
, 2) != 0) {
1844 aprint_error_dev(&sc
->sc_dev
, "%s read fid %x failed\n",
1846 wi_rssdescs_reset(ic
, &sc
->sc_rssd
, &sc
->sc_rssdfree
,
1851 if (frmhdr
.wi_tx_idx
>= WI_NTXRSS
) {
1852 aprint_error_dev(&sc
->sc_dev
, "%s bad idx %02x\n",
1853 __func__
, frmhdr
.wi_tx_idx
);
1854 wi_rssdescs_reset(ic
, &sc
->sc_rssd
, &sc
->sc_rssdfree
,
1859 rssd
= &sc
->sc_rssd
[frmhdr
.wi_tx_idx
];
1860 id
= &rssd
->rd_desc
;
1861 wi_raise_rate(ic
, id
);
1867 aprint_error_dev(&sc
->sc_dev
, "%s null node, rssdesc %02x\n",
1868 __func__
, frmhdr
.wi_tx_idx
);
1872 if (sc
->sc_txpending
[id
->id_rateidx
]-- == 0) {
1873 aprint_error_dev(&sc
->sc_dev
, "%s txpending[%i] wraparound",
1874 __func__
, id
->id_rateidx
);
1875 sc
->sc_txpending
[id
->id_rateidx
] = 0;
1878 ieee80211_free_node(ni
);
1879 SLIST_INSERT_HEAD(&sc
->sc_rssdfree
, rssd
, rd_next
);
1881 ifp
->if_flags
&= ~IFF_OACTIVE
;
1885 wi_info_intr(struct wi_softc
*sc
)
1887 struct ieee80211com
*ic
= &sc
->sc_ic
;
1888 struct ifnet
*ifp
= &sc
->sc_if
;
1889 int i
, fid
, len
, off
;
1894 fid
= CSR_READ_2(sc
, WI_INFO_FID
);
1895 wi_read_bap(sc
, fid
, 0, ltbuf
, sizeof(ltbuf
));
1897 switch (le16toh(ltbuf
[1])) {
1899 case WI_INFO_LINK_STAT
:
1900 wi_read_bap(sc
, fid
, sizeof(ltbuf
), &stat
, sizeof(stat
));
1901 DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat
)));
1902 switch (le16toh(stat
)) {
1904 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
1905 if (ic
->ic_state
== IEEE80211_S_RUN
&&
1906 ic
->ic_opmode
!= IEEE80211_M_IBSS
)
1910 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
1913 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
1915 case AP_OUT_OF_RANGE
:
1916 if (sc
->sc_firmware_type
== WI_SYMBOL
&&
1917 sc
->sc_scan_timer
> 0) {
1918 if (wi_cmd(sc
, WI_CMD_INQUIRE
,
1919 WI_INFO_HOST_SCAN_RESULTS
, 0, 0) != 0)
1920 sc
->sc_scan_timer
= 0;
1923 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1924 sc
->sc_flags
|= WI_FLAGS_OUTRANGE
;
1928 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1929 ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
1934 case WI_INFO_COUNTERS
:
1935 /* some card versions have a larger stats structure */
1936 len
= min(le16toh(ltbuf
[0]) - 1, sizeof(sc
->sc_stats
) / 4);
1937 ptr
= (u_int32_t
*)&sc
->sc_stats
;
1938 off
= sizeof(ltbuf
);
1939 for (i
= 0; i
< len
; i
++, off
+= 2, ptr
++) {
1940 wi_read_bap(sc
, fid
, off
, &stat
, sizeof(stat
));
1941 stat
= le16toh(stat
);
1942 #ifdef WI_HERMES_STATS_WAR
1948 ifp
->if_collisions
= sc
->sc_stats
.wi_tx_single_retries
+
1949 sc
->sc_stats
.wi_tx_multi_retries
+
1950 sc
->sc_stats
.wi_tx_retry_limit
;
1953 case WI_INFO_SCAN_RESULTS
:
1954 case WI_INFO_HOST_SCAN_RESULTS
:
1955 wi_scan_result(sc
, fid
, le16toh(ltbuf
[0]));
1959 DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid
,
1960 le16toh(ltbuf
[1]), le16toh(ltbuf
[0])));
1966 wi_write_multi(struct wi_softc
*sc
)
1968 struct ifnet
*ifp
= &sc
->sc_if
;
1970 struct wi_mcast mlist
;
1971 struct ether_multi
*enm
;
1972 struct ether_multistep estep
;
1974 if ((ifp
->if_flags
& IFF_PROMISC
) != 0) {
1976 ifp
->if_flags
|= IFF_ALLMULTI
;
1977 memset(&mlist
, 0, sizeof(mlist
));
1978 return wi_write_rid(sc
, WI_RID_MCAST_LIST
, &mlist
,
1983 ETHER_FIRST_MULTI(estep
, &sc
->sc_ec
, enm
);
1984 while (enm
!= NULL
) {
1985 /* Punt on ranges or too many multicast addresses. */
1986 if (!IEEE80211_ADDR_EQ(enm
->enm_addrlo
, enm
->enm_addrhi
) ||
1987 n
>= sizeof(mlist
) / sizeof(mlist
.wi_mcast
[0]))
1990 IEEE80211_ADDR_COPY(&mlist
.wi_mcast
[n
], enm
->enm_addrlo
);
1992 ETHER_NEXT_MULTI(estep
, enm
);
1994 ifp
->if_flags
&= ~IFF_ALLMULTI
;
1995 return wi_write_rid(sc
, WI_RID_MCAST_LIST
, &mlist
,
1996 IEEE80211_ADDR_LEN
* n
);
2001 wi_read_nicid(struct wi_softc
*sc
)
2003 struct wi_card_ident
*id
;
2008 /* getting chip identity */
2009 memset(ver
, 0, sizeof(ver
));
2011 wi_read_rid(sc
, WI_RID_CARD_ID
, ver
, &len
);
2012 printf("%s: using ", device_xname(&sc
->sc_dev
));
2013 DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver
[0]), le16toh(ver
[1]), le16toh(ver
[2]), le16toh(ver
[3])));
2015 sc
->sc_firmware_type
= WI_NOTYPE
;
2016 for (id
= wi_card_ident
; id
->card_name
!= NULL
; id
++) {
2017 if (le16toh(ver
[0]) == id
->card_id
) {
2018 printf("%s", id
->card_name
);
2019 sc
->sc_firmware_type
= id
->firm_type
;
2023 if (sc
->sc_firmware_type
== WI_NOTYPE
) {
2024 if (le16toh(ver
[0]) & 0x8000) {
2025 printf("Unknown PRISM2 chip");
2026 sc
->sc_firmware_type
= WI_INTERSIL
;
2028 printf("Unknown Lucent chip");
2029 sc
->sc_firmware_type
= WI_LUCENT
;
2033 /* get primary firmware version (Only Prism chips) */
2034 if (sc
->sc_firmware_type
!= WI_LUCENT
) {
2035 memset(ver
, 0, sizeof(ver
));
2037 wi_read_rid(sc
, WI_RID_PRI_IDENTITY
, ver
, &len
);
2038 sc
->sc_pri_firmware_ver
= le16toh(ver
[2]) * 10000 +
2039 le16toh(ver
[3]) * 100 + le16toh(ver
[1]);
2042 /* get station firmware version */
2043 memset(ver
, 0, sizeof(ver
));
2045 wi_read_rid(sc
, WI_RID_STA_IDENTITY
, ver
, &len
);
2046 sc
->sc_sta_firmware_ver
= le16toh(ver
[2]) * 10000 +
2047 le16toh(ver
[3]) * 100 + le16toh(ver
[1]);
2048 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
2049 (sc
->sc_sta_firmware_ver
== 10102 ||
2050 sc
->sc_sta_firmware_ver
== 20102)) {
2052 memset(ident
, 0, sizeof(ident
));
2053 len
= sizeof(ident
);
2054 /* value should be the format like "V2.00-11" */
2055 if (wi_read_rid(sc
, WI_RID_SYMBOL_IDENTITY
, ident
, &len
) == 0 &&
2056 *(p
= (char *)ident
) >= 'A' &&
2057 p
[2] == '.' && p
[5] == '-' && p
[8] == '\0') {
2058 sc
->sc_firmware_type
= WI_SYMBOL
;
2059 sc
->sc_sta_firmware_ver
= (p
[1] - '0') * 10000 +
2060 (p
[3] - '0') * 1000 + (p
[4] - '0') * 100 +
2061 (p
[6] - '0') * 10 + (p
[7] - '0');
2065 printf("\n%s: %s Firmware: ", device_xname(&sc
->sc_dev
),
2066 sc
->sc_firmware_type
== WI_LUCENT
? "Lucent" :
2067 (sc
->sc_firmware_type
== WI_SYMBOL
? "Symbol" : "Intersil"));
2068 if (sc
->sc_firmware_type
!= WI_LUCENT
) /* XXX */
2069 printf("Primary (%u.%u.%u), ",
2070 sc
->sc_pri_firmware_ver
/ 10000,
2071 (sc
->sc_pri_firmware_ver
% 10000) / 100,
2072 sc
->sc_pri_firmware_ver
% 100);
2073 printf("Station (%u.%u.%u)\n",
2074 sc
->sc_sta_firmware_ver
/ 10000,
2075 (sc
->sc_sta_firmware_ver
% 10000) / 100,
2076 sc
->sc_sta_firmware_ver
% 100);
2080 wi_write_ssid(struct wi_softc
*sc
, int rid
, u_int8_t
*buf
, int buflen
)
2082 struct wi_ssid ssid
;
2084 if (buflen
> IEEE80211_NWID_LEN
)
2086 memset(&ssid
, 0, sizeof(ssid
));
2087 ssid
.wi_len
= htole16(buflen
);
2088 memcpy(ssid
.wi_ssid
, buf
, buflen
);
2089 return wi_write_rid(sc
, rid
, &ssid
, sizeof(ssid
));
2093 wi_get_cfg(struct ifnet
*ifp
, u_long cmd
, void *data
)
2095 struct wi_softc
*sc
= ifp
->if_softc
;
2096 struct ieee80211com
*ic
= &sc
->sc_ic
;
2097 struct ifreq
*ifr
= (struct ifreq
*)data
;
2101 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
2104 len
= (wreq
.wi_len
- 1) * 2;
2105 if (len
< sizeof(u_int16_t
))
2107 if (len
> sizeof(wreq
.wi_val
))
2108 len
= sizeof(wreq
.wi_val
);
2110 switch (wreq
.wi_type
) {
2112 case WI_RID_IFACE_STATS
:
2113 memcpy(wreq
.wi_val
, &sc
->sc_stats
, sizeof(sc
->sc_stats
));
2114 if (len
< sizeof(sc
->sc_stats
))
2117 len
= sizeof(sc
->sc_stats
);
2120 case WI_RID_ENCRYPTION
:
2121 case WI_RID_TX_CRYPT_KEY
:
2122 case WI_RID_DEFLT_CRYPT_KEYS
:
2123 case WI_RID_TX_RATE
:
2124 return ieee80211_cfgget(ic
, cmd
, data
);
2126 case WI_RID_MICROWAVE_OVEN
:
2127 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_MOR
)) {
2128 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2132 wreq
.wi_val
[0] = htole16(sc
->sc_microwave_oven
);
2133 len
= sizeof(u_int16_t
);
2136 case WI_RID_DBM_ADJUST
:
2137 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_DBMADJUST
)) {
2138 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2142 wreq
.wi_val
[0] = htole16(sc
->sc_dbm_offset
);
2143 len
= sizeof(u_int16_t
);
2146 case WI_RID_ROAMING_MODE
:
2147 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
)) {
2148 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2152 wreq
.wi_val
[0] = htole16(sc
->sc_roaming_mode
);
2153 len
= sizeof(u_int16_t
);
2156 case WI_RID_SYSTEM_SCALE
:
2157 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
)) {
2158 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2162 wreq
.wi_val
[0] = htole16(sc
->sc_system_scale
);
2163 len
= sizeof(u_int16_t
);
2166 case WI_RID_FRAG_THRESH
:
2167 if (sc
->sc_enabled
&& (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
)) {
2168 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2172 wreq
.wi_val
[0] = htole16(sc
->sc_frag_thresh
);
2173 len
= sizeof(u_int16_t
);
2176 case WI_RID_READ_APS
:
2177 #ifndef IEEE80211_NO_HOSTAP
2178 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
2179 return ieee80211_cfgget(ic
, cmd
, data
);
2180 #endif /* !IEEE80211_NO_HOSTAP */
2181 if (sc
->sc_scan_timer
> 0) {
2182 error
= EINPROGRESS
;
2186 if (len
< sizeof(n
)) {
2190 if (len
< sizeof(n
) + sizeof(struct wi_apinfo
) * n
)
2191 n
= (len
- sizeof(n
)) / sizeof(struct wi_apinfo
);
2192 len
= sizeof(n
) + sizeof(struct wi_apinfo
) * n
;
2193 memcpy(wreq
.wi_val
, &n
, sizeof(n
));
2194 memcpy((char *)wreq
.wi_val
+ sizeof(n
), sc
->sc_aps
,
2195 sizeof(struct wi_apinfo
) * n
);
2199 if (sc
->sc_enabled
) {
2200 error
= wi_read_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2204 switch (wreq
.wi_type
) {
2205 case WI_RID_MAX_DATALEN
:
2206 wreq
.wi_val
[0] = htole16(sc
->sc_max_datalen
);
2207 len
= sizeof(u_int16_t
);
2209 case WI_RID_FRAG_THRESH
:
2210 wreq
.wi_val
[0] = htole16(sc
->sc_frag_thresh
);
2211 len
= sizeof(u_int16_t
);
2213 case WI_RID_RTS_THRESH
:
2214 wreq
.wi_val
[0] = htole16(sc
->sc_rts_thresh
);
2215 len
= sizeof(u_int16_t
);
2217 case WI_RID_CNFAUTHMODE
:
2218 wreq
.wi_val
[0] = htole16(sc
->sc_cnfauthmode
);
2219 len
= sizeof(u_int16_t
);
2221 case WI_RID_NODENAME
:
2222 if (len
< sc
->sc_nodelen
+ sizeof(u_int16_t
)) {
2226 len
= sc
->sc_nodelen
+ sizeof(u_int16_t
);
2227 wreq
.wi_val
[0] = htole16((sc
->sc_nodelen
+ 1) / 2);
2228 memcpy(&wreq
.wi_val
[1], sc
->sc_nodename
,
2232 return ieee80211_cfgget(ic
, cmd
, data
);
2238 wreq
.wi_len
= (len
+ 1) / 2 + 1;
2239 return copyout(&wreq
, ifr
->ifr_data
, (wreq
.wi_len
+ 1) * 2);
2243 wi_set_cfg(struct ifnet
*ifp
, u_long cmd
, void *data
)
2245 struct wi_softc
*sc
= ifp
->if_softc
;
2246 struct ieee80211com
*ic
= &sc
->sc_ic
;
2247 struct ifreq
*ifr
= (struct ifreq
*)data
;
2248 struct ieee80211_rateset
*rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
2253 error
= copyin(ifr
->ifr_data
, &wreq
, sizeof(wreq
));
2256 len
= (wreq
.wi_len
- 1) * 2;
2257 switch (wreq
.wi_type
) {
2258 case WI_RID_MAC_NODE
:
2259 /* XXX convert to SIOCALIFADDR, AF_LINK, IFLR_ACTIVE */
2260 (void)memcpy(ic
->ic_myaddr
, wreq
.wi_val
, ETHER_ADDR_LEN
);
2261 if_set_sadl(ifp
, ic
->ic_myaddr
, ETHER_ADDR_LEN
, false);
2262 wi_write_rid(sc
, WI_RID_MAC_NODE
, ic
->ic_myaddr
,
2263 IEEE80211_ADDR_LEN
);
2266 case WI_RID_DBM_ADJUST
:
2269 case WI_RID_NODENAME
:
2270 if (le16toh(wreq
.wi_val
[0]) * 2 > len
||
2271 le16toh(wreq
.wi_val
[0]) > sizeof(sc
->sc_nodename
)) {
2275 if (sc
->sc_enabled
) {
2276 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2281 sc
->sc_nodelen
= le16toh(wreq
.wi_val
[0]) * 2;
2282 memcpy(sc
->sc_nodename
, &wreq
.wi_val
[1], sc
->sc_nodelen
);
2285 case WI_RID_MICROWAVE_OVEN
:
2286 case WI_RID_ROAMING_MODE
:
2287 case WI_RID_SYSTEM_SCALE
:
2288 case WI_RID_FRAG_THRESH
:
2289 if (wreq
.wi_type
== WI_RID_MICROWAVE_OVEN
&&
2290 (sc
->sc_flags
& WI_FLAGS_HAS_MOR
) == 0)
2292 if (wreq
.wi_type
== WI_RID_ROAMING_MODE
&&
2293 (sc
->sc_flags
& WI_FLAGS_HAS_ROAMING
) == 0)
2295 if (wreq
.wi_type
== WI_RID_SYSTEM_SCALE
&&
2296 (sc
->sc_flags
& WI_FLAGS_HAS_SYSSCALE
) == 0)
2298 if (wreq
.wi_type
== WI_RID_FRAG_THRESH
&&
2299 (sc
->sc_flags
& WI_FLAGS_HAS_FRAGTHR
) == 0)
2302 case WI_RID_RTS_THRESH
:
2303 case WI_RID_CNFAUTHMODE
:
2304 case WI_RID_MAX_DATALEN
:
2305 if (sc
->sc_enabled
) {
2306 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2311 switch (wreq
.wi_type
) {
2312 case WI_RID_FRAG_THRESH
:
2313 sc
->sc_frag_thresh
= le16toh(wreq
.wi_val
[0]);
2315 case WI_RID_RTS_THRESH
:
2316 sc
->sc_rts_thresh
= le16toh(wreq
.wi_val
[0]);
2318 case WI_RID_MICROWAVE_OVEN
:
2319 sc
->sc_microwave_oven
= le16toh(wreq
.wi_val
[0]);
2321 case WI_RID_ROAMING_MODE
:
2322 sc
->sc_roaming_mode
= le16toh(wreq
.wi_val
[0]);
2324 case WI_RID_SYSTEM_SCALE
:
2325 sc
->sc_system_scale
= le16toh(wreq
.wi_val
[0]);
2327 case WI_RID_CNFAUTHMODE
:
2328 sc
->sc_cnfauthmode
= le16toh(wreq
.wi_val
[0]);
2330 case WI_RID_MAX_DATALEN
:
2331 sc
->sc_max_datalen
= le16toh(wreq
.wi_val
[0]);
2336 case WI_RID_TX_RATE
:
2337 switch (le16toh(wreq
.wi_val
[0])) {
2339 ic
->ic_fixed_rate
= -1;
2342 for (i
= 0; i
< IEEE80211_RATE_SIZE
; i
++) {
2343 if ((rs
->rs_rates
[i
] & IEEE80211_RATE_VAL
)
2344 / 2 == le16toh(wreq
.wi_val
[0]))
2347 if (i
== IEEE80211_RATE_SIZE
)
2349 ic
->ic_fixed_rate
= i
;
2352 error
= wi_cfg_txrate(sc
);
2355 case WI_RID_SCAN_APS
:
2356 if (sc
->sc_enabled
&& ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
2357 error
= wi_scan_ap(sc
, 0x3fff, 0x000f);
2360 case WI_RID_MGMT_XMIT
:
2361 if (!sc
->sc_enabled
) {
2365 if (ic
->ic_mgtq
.ifq_len
> 5) {
2369 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
2370 m
= m_devget((char *)&wreq
.wi_val
, wreq
.wi_len
, 0, ifp
, NULL
);
2375 IF_ENQUEUE(&ic
->ic_mgtq
, m
);
2379 if (sc
->sc_enabled
) {
2380 error
= wi_write_rid(sc
, wreq
.wi_type
, wreq
.wi_val
,
2385 error
= ieee80211_cfgset(ic
, cmd
, data
);
2391 /* Rate is 0 for hardware auto-select, otherwise rate is
2392 * 2, 4, 11, or 22 (units of 500Kbps).
2395 wi_write_txrate(struct wi_softc
*sc
, int rate
)
2399 /* rate: 0, 2, 4, 11, 22 */
2400 switch (sc
->sc_firmware_type
) {
2402 switch (rate
& IEEE80211_RATE_VAL
) {
2410 hwrate
= 3; /* auto */
2421 switch (rate
& IEEE80211_RATE_VAL
) {
2435 hwrate
= 15; /* auto */
2441 if (sc
->sc_tx_rate
== hwrate
)
2444 if (sc
->sc_if
.if_flags
& IFF_DEBUG
)
2445 printf("%s: tx rate %d -> %d (%d)\n", __func__
, sc
->sc_tx_rate
,
2448 sc
->sc_tx_rate
= hwrate
;
2450 return wi_write_val(sc
, WI_RID_TX_RATE
, sc
->sc_tx_rate
);
2454 wi_cfg_txrate(struct wi_softc
*sc
)
2456 struct ieee80211com
*ic
= &sc
->sc_ic
;
2457 struct ieee80211_rateset
*rs
;
2460 rs
= &ic
->ic_sup_rates
[IEEE80211_MODE_11B
];
2462 sc
->sc_tx_rate
= 0; /* force write to RID */
2464 if (ic
->ic_fixed_rate
< 0)
2465 rate
= 0; /* auto */
2467 rate
= rs
->rs_rates
[ic
->ic_fixed_rate
];
2469 return wi_write_txrate(sc
, rate
);
2473 wi_key_delete(struct ieee80211com
*ic
, const struct ieee80211_key
*k
)
2475 struct wi_softc
*sc
= ic
->ic_ifp
->if_softc
;
2476 u_int keyix
= k
->wk_keyix
;
2478 DPRINTF(("%s: delete key %u\n", __func__
, keyix
));
2480 if (keyix
>= IEEE80211_WEP_NKID
)
2482 if (k
->wk_keylen
!= 0)
2483 sc
->sc_flags
&= ~WI_FLAGS_WEP_VALID
;
2489 wi_key_set(struct ieee80211com
*ic
, const struct ieee80211_key
*k
,
2490 const u_int8_t mac
[IEEE80211_ADDR_LEN
])
2492 struct wi_softc
*sc
= ic
->ic_ifp
->if_softc
;
2494 DPRINTF(("%s: set key %u\n", __func__
, k
->wk_keyix
));
2496 if (k
->wk_keyix
>= IEEE80211_WEP_NKID
)
2499 sc
->sc_flags
&= ~WI_FLAGS_WEP_VALID
;
2505 wi_key_update_begin(struct ieee80211com
*ic
)
2507 DPRINTF(("%s:\n", __func__
));
2511 wi_key_update_end(struct ieee80211com
*ic
)
2513 struct ifnet
*ifp
= ic
->ic_ifp
;
2514 struct wi_softc
*sc
= ifp
->if_softc
;
2516 DPRINTF(("%s:\n", __func__
));
2518 if ((sc
->sc_flags
& WI_FLAGS_WEP_VALID
) != 0)
2520 if ((ic
->ic_caps
& IEEE80211_C_WEP
) != 0 && sc
->sc_enabled
&&
2522 (void)wi_write_wep(sc
);
2526 wi_write_wep(struct wi_softc
*sc
)
2528 struct ifnet
*ifp
= &sc
->sc_if
;
2529 struct ieee80211com
*ic
= &sc
->sc_ic
;
2533 struct wi_key wkey
[IEEE80211_WEP_NKID
];
2535 if ((ifp
->if_flags
& IFF_RUNNING
) != 0)
2536 wi_cmd(sc
, WI_CMD_DISABLE
| sc
->sc_portnum
, 0, 0, 0);
2538 switch (sc
->sc_firmware_type
) {
2540 val
= (ic
->ic_flags
& IEEE80211_F_PRIVACY
) ? 1 : 0;
2541 error
= wi_write_val(sc
, WI_RID_ENCRYPTION
, val
);
2544 error
= wi_write_val(sc
, WI_RID_TX_CRYPT_KEY
, ic
->ic_def_txkey
);
2547 memset(wkey
, 0, sizeof(wkey
));
2548 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2549 keylen
= ic
->ic_nw_keys
[i
].wk_keylen
;
2550 wkey
[i
].wi_keylen
= htole16(keylen
);
2551 memcpy(wkey
[i
].wi_keydat
, ic
->ic_nw_keys
[i
].wk_key
,
2554 error
= wi_write_rid(sc
, WI_RID_DEFLT_CRYPT_KEYS
,
2555 wkey
, sizeof(wkey
));
2560 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
2562 * ONLY HWB3163 EVAL-CARD Firmware version
2563 * less than 0.8 variant2
2565 * If promiscuous mode disable, Prism2 chip
2566 * does not work with WEP .
2567 * It is under investigation for details.
2568 * (ichiro@NetBSD.org)
2570 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
2571 sc
->sc_sta_firmware_ver
< 802 ) {
2572 /* firm ver < 0.8 variant 2 */
2573 wi_write_val(sc
, WI_RID_PROMISC
, 1);
2575 wi_write_val(sc
, WI_RID_CNFAUTHMODE
,
2576 sc
->sc_cnfauthmode
);
2577 val
= PRIVACY_INVOKED
;
2578 if ((sc
->sc_ic_flags
& IEEE80211_F_DROPUNENC
) != 0)
2579 val
|= EXCLUDE_UNENCRYPTED
;
2580 #ifndef IEEE80211_NO_HOSTAP
2582 * Encryption firmware has a bug for HostAP mode.
2584 if (sc
->sc_firmware_type
== WI_INTERSIL
&&
2585 ic
->ic_opmode
== IEEE80211_M_HOSTAP
)
2586 val
|= HOST_ENCRYPT
;
2587 #endif /* !IEEE80211_NO_HOSTAP */
2589 wi_write_val(sc
, WI_RID_CNFAUTHMODE
,
2590 IEEE80211_AUTH_OPEN
);
2591 val
= HOST_ENCRYPT
| HOST_DECRYPT
;
2593 error
= wi_write_val(sc
, WI_RID_P2_ENCRYPTION
, val
);
2596 error
= wi_write_val(sc
, WI_RID_P2_TX_CRYPT_KEY
,
2601 * It seems that the firmware accept 104bit key only if
2602 * all the keys have 104bit length. We get the length of
2603 * the transmit key and use it for all other keys.
2604 * Perhaps we should use software WEP for such situation.
2606 if (ic
->ic_def_txkey
== IEEE80211_KEYIX_NONE
||
2607 IEEE80211_KEY_UNDEFINED(ic
->ic_nw_keys
[ic
->ic_def_txkey
]))
2608 keylen
= 13; /* No keys => 104bit ok */
2610 keylen
= ic
->ic_nw_keys
[ic
->ic_def_txkey
].wk_keylen
;
2612 if (keylen
> IEEE80211_WEP_KEYLEN
)
2613 keylen
= 13; /* 104bit keys */
2615 keylen
= IEEE80211_WEP_KEYLEN
;
2616 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
2617 error
= wi_write_rid(sc
, WI_RID_P2_CRYPT_KEY0
+ i
,
2618 ic
->ic_nw_keys
[i
].wk_key
, keylen
);
2624 if ((ifp
->if_flags
& IFF_RUNNING
) != 0)
2625 wi_cmd(sc
, WI_CMD_ENABLE
| sc
->sc_portnum
, 0, 0, 0);
2627 sc
->sc_flags
|= WI_FLAGS_WEP_VALID
;
2631 /* Must be called at proper protection level! */
2633 wi_cmd_start(struct wi_softc
*sc
, int cmd
, int val0
, int val1
, int val2
)
2636 static int hist1
[11];
2637 static int hist1count
;
2641 /* wait for the busy bit to clear */
2642 for (i
= 500; i
> 0; i
--) { /* 5s */
2643 if ((CSR_READ_2(sc
, WI_COMMAND
) & WI_CMD_BUSY
) == 0)
2647 DELAY(1000); /* 1 m sec */
2650 aprint_error_dev(&sc
->sc_dev
, "wi_cmd: busy bit won't clear.\n");
2658 if (++hist1count
== 1000) {
2660 printf("%s: hist1: %d %d %d %d %d %d %d %d %d %d %d\n",
2661 device_xname(&sc
->sc_dev
),
2662 hist1
[0], hist1
[1], hist1
[2], hist1
[3], hist1
[4],
2663 hist1
[5], hist1
[6], hist1
[7], hist1
[8], hist1
[9],
2667 CSR_WRITE_2(sc
, WI_PARAM0
, val0
);
2668 CSR_WRITE_2(sc
, WI_PARAM1
, val1
);
2669 CSR_WRITE_2(sc
, WI_PARAM2
, val2
);
2670 CSR_WRITE_2(sc
, WI_COMMAND
, cmd
);
2676 wi_cmd(struct wi_softc
*sc
, int cmd
, int val0
, int val1
, int val2
)
2682 printf("%s: [enter] %d txcmds outstanding\n", __func__
,
2686 if (sc
->sc_txcmds
> 0)
2689 if ((rc
= wi_cmd_start(sc
, cmd
, val0
, val1
, val2
)) != 0)
2692 if (cmd
== WI_CMD_INI
) {
2693 /* XXX: should sleep here. */
2698 rc
= wi_cmd_wait(sc
, cmd
, val0
);
2702 printf("%s: [ ] %d txcmds outstanding\n", __func__
,
2706 if (sc
->sc_txcmds
> 0)
2711 printf("%s: [leave] %d txcmds outstanding\n", __func__
,
2719 wi_cmd_wait(struct wi_softc
*sc
, int cmd
, int val0
)
2722 static int hist2
[11];
2723 static int hist2count
;
2728 printf("%s: cmd=%#x, arg=%#x\n", __func__
, cmd
, val0
);
2729 #endif /* WI_DEBUG */
2731 /* wait for the cmd completed bit */
2732 for (i
= 0; i
< WI_TIMEOUT
; i
++) {
2733 if (CSR_READ_2(sc
, WI_EVENT_STAT
) & WI_EV_CMD
)
2745 if (++hist2count
== 1000) {
2747 printf("%s: hist2: %d %d %d %d %d %d %d %d %d %d %d\n",
2748 device_xname(&sc
->sc_dev
),
2749 hist2
[0], hist2
[1], hist2
[2], hist2
[3], hist2
[4],
2750 hist2
[5], hist2
[6], hist2
[7], hist2
[8], hist2
[9],
2755 status
= CSR_READ_2(sc
, WI_STATUS
);
2757 if (i
== WI_TIMEOUT
) {
2758 aprint_error_dev(&sc
->sc_dev
, "command timed out, cmd=0x%x, arg=0x%x\n",
2763 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_CMD
);
2765 if (status
& WI_STAT_CMD_RESULT
) {
2766 aprint_error_dev(&sc
->sc_dev
, "command failed, cmd=0x%x, arg=0x%x\n",
2774 wi_seek_bap(struct wi_softc
*sc
, int id
, int off
)
2777 static int hist4
[11];
2778 static int hist4count
;
2782 CSR_WRITE_2(sc
, WI_SEL0
, id
);
2783 CSR_WRITE_2(sc
, WI_OFF0
, off
);
2785 for (i
= 0; ; i
++) {
2786 status
= CSR_READ_2(sc
, WI_OFF0
);
2787 if ((status
& WI_OFF_BUSY
) == 0)
2789 if (i
== WI_TIMEOUT
) {
2790 aprint_error_dev(&sc
->sc_dev
, "timeout in wi_seek to %x/%x\n",
2792 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2804 if (++hist4count
== 2500) {
2806 printf("%s: hist4: %d %d %d %d %d %d %d %d %d %d %d\n",
2807 device_xname(&sc
->sc_dev
),
2808 hist4
[0], hist4
[1], hist4
[2], hist4
[3], hist4
[4],
2809 hist4
[5], hist4
[6], hist4
[7], hist4
[8], hist4
[9],
2813 if (status
& WI_OFF_ERR
) {
2814 printf("%s: failed in wi_seek to %x/%x\n",
2815 device_xname(&sc
->sc_dev
), id
, off
);
2816 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2820 sc
->sc_bap_off
= off
;
2825 wi_read_bap(struct wi_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
2831 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
2832 if ((error
= wi_seek_bap(sc
, id
, off
)) != 0)
2835 cnt
= (buflen
+ 1) / 2;
2836 CSR_READ_MULTI_STREAM_2(sc
, WI_DATA0
, (u_int16_t
*)buf
, cnt
);
2837 sc
->sc_bap_off
+= cnt
* 2;
2842 wi_write_bap(struct wi_softc
*sc
, int id
, int off
, void *buf
, int buflen
)
2849 #ifdef WI_HERMES_AUTOINC_WAR
2852 if (id
!= sc
->sc_bap_id
|| off
!= sc
->sc_bap_off
) {
2853 if ((error
= wi_seek_bap(sc
, id
, off
)) != 0)
2856 cnt
= (buflen
+ 1) / 2;
2857 CSR_WRITE_MULTI_STREAM_2(sc
, WI_DATA0
, (u_int16_t
*)buf
, cnt
);
2858 sc
->sc_bap_off
+= cnt
* 2;
2860 #ifdef WI_HERMES_AUTOINC_WAR
2862 * According to the comments in the HCF Light code, there is a bug
2863 * in the Hermes (or possibly in certain Hermes firmware revisions)
2864 * where the chip's internal autoincrement counter gets thrown off
2865 * during data writes: the autoincrement is missed, causing one
2866 * data word to be overwritten and subsequent words to be written to
2867 * the wrong memory locations. The end result is that we could end
2868 * up transmitting bogus frames without realizing it. The workaround
2869 * for this is to write a couple of extra guard words after the end
2870 * of the transfer, then attempt to read then back. If we fail to
2871 * locate the guard words where we expect them, we preform the
2872 * transfer over again.
2874 if ((sc
->sc_flags
& WI_FLAGS_BUG_AUTOINC
) && (id
& 0xf000) == 0) {
2875 CSR_WRITE_2(sc
, WI_DATA0
, 0x1234);
2876 CSR_WRITE_2(sc
, WI_DATA0
, 0x5678);
2877 wi_seek_bap(sc
, id
, sc
->sc_bap_off
);
2878 sc
->sc_bap_off
= WI_OFF_ERR
; /* invalidate */
2879 if (CSR_READ_2(sc
, WI_DATA0
) != 0x1234 ||
2880 CSR_READ_2(sc
, WI_DATA0
) != 0x5678) {
2881 aprint_error_dev(&sc
->sc_dev
, "detect auto increment bug, try again\n");
2890 wi_mwrite_bap(struct wi_softc
*sc
, int id
, int off
, struct mbuf
*m0
, int totlen
)
2895 for (m
= m0
; m
!= NULL
&& totlen
> 0; m
= m
->m_next
) {
2899 len
= min(m
->m_len
, totlen
);
2901 if (((u_long
)m
->m_data
) % 2 != 0 || len
% 2 != 0) {
2902 m_copydata(m
, 0, totlen
, (void *)&sc
->sc_txbuf
);
2903 return wi_write_bap(sc
, id
, off
, (void *)&sc
->sc_txbuf
,
2907 if ((error
= wi_write_bap(sc
, id
, off
, m
->m_data
, len
)) != 0)
2917 wi_alloc_fid(struct wi_softc
*sc
, int len
, int *idp
)
2921 if (wi_cmd(sc
, WI_CMD_ALLOC_MEM
, len
, 0, 0)) {
2922 aprint_error_dev(&sc
->sc_dev
, "failed to allocate %d bytes on NIC\n", len
);
2926 for (i
= 0; i
< WI_TIMEOUT
; i
++) {
2927 if (CSR_READ_2(sc
, WI_EVENT_STAT
) & WI_EV_ALLOC
)
2931 if (i
== WI_TIMEOUT
) {
2932 aprint_error_dev(&sc
->sc_dev
, "timeout in alloc\n");
2935 *idp
= CSR_READ_2(sc
, WI_ALLOC_FID
);
2936 CSR_WRITE_2(sc
, WI_EVENT_ACK
, WI_EV_ALLOC
);
2941 wi_read_rid(struct wi_softc
*sc
, int rid
, void *buf
, int *buflenp
)
2946 /* Tell the NIC to enter record read mode. */
2947 error
= wi_cmd(sc
, WI_CMD_ACCESS
| WI_ACCESS_READ
, rid
, 0, 0);
2951 error
= wi_read_bap(sc
, rid
, 0, ltbuf
, sizeof(ltbuf
));
2955 if (le16toh(ltbuf
[0]) == 0)
2957 if (le16toh(ltbuf
[1]) != rid
) {
2958 aprint_error_dev(&sc
->sc_dev
, "record read mismatch, rid=%x, got=%x\n",
2959 rid
, le16toh(ltbuf
[1]));
2962 len
= (le16toh(ltbuf
[0]) - 1) * 2; /* already got rid */
2963 if (*buflenp
< len
) {
2964 aprint_error_dev(&sc
->sc_dev
, "record buffer is too small, "
2965 "rid=%x, size=%d, len=%d\n",
2966 rid
, *buflenp
, len
);
2970 return wi_read_bap(sc
, rid
, sizeof(ltbuf
), buf
, len
);
2974 wi_write_rid(struct wi_softc
*sc
, int rid
, void *buf
, int buflen
)
2979 ltbuf
[0] = htole16((buflen
+ 1) / 2 + 1); /* includes rid */
2980 ltbuf
[1] = htole16(rid
);
2982 error
= wi_write_bap(sc
, rid
, 0, ltbuf
, sizeof(ltbuf
));
2985 error
= wi_write_bap(sc
, rid
, sizeof(ltbuf
), buf
, buflen
);
2989 return wi_cmd(sc
, WI_CMD_ACCESS
| WI_ACCESS_WRITE
, rid
, 0, 0);
2993 wi_rssadapt_updatestats_cb(void *arg
, struct ieee80211_node
*ni
)
2995 struct wi_node
*wn
= (void*)ni
;
2996 ieee80211_rssadapt_updatestats(&wn
->wn_rssadapt
);
3000 wi_rssadapt_updatestats(void *arg
)
3002 struct wi_softc
*sc
= arg
;
3003 struct ieee80211com
*ic
= &sc
->sc_ic
;
3004 ieee80211_iterate_nodes(&ic
->ic_sta
, wi_rssadapt_updatestats_cb
, arg
);
3005 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
&&
3006 ic
->ic_state
== IEEE80211_S_RUN
)
3007 callout_reset(&sc
->sc_rssadapt_ch
, hz
/ 10,
3008 wi_rssadapt_updatestats
, arg
);
3012 * In HOSTAP mode, restore IEEE80211_F_DROPUNENC when operating
3013 * with WEP enabled so that the AP drops unencoded frames at the
3016 * In all other modes, clear IEEE80211_F_DROPUNENC when operating
3017 * with WEP enabled so we don't drop unencoded frames at the 802.11
3018 * layer. This is necessary because we must strip the WEP bit from
3019 * the 802.11 header before passing frames to ieee80211_input
3020 * because the card has already stripped the WEP crypto header from
3024 wi_mend_flags(struct wi_softc
*sc
, enum ieee80211_state nstate
)
3026 struct ieee80211com
*ic
= &sc
->sc_ic
;
3028 if (nstate
== IEEE80211_S_RUN
&&
3029 (ic
->ic_flags
& IEEE80211_F_PRIVACY
) != 0 &&
3030 ic
->ic_opmode
!= IEEE80211_M_HOSTAP
)
3031 ic
->ic_flags
&= ~IEEE80211_F_DROPUNENC
;
3033 ic
->ic_flags
|= sc
->sc_ic_flags
;
3035 DPRINTF(("%s: state %d, "
3036 "ic->ic_flags & IEEE80211_F_DROPUNENC = %#" PRIx32
", "
3037 "sc->sc_ic_flags & IEEE80211_F_DROPUNENC = %#" PRIx32
"\n",
3039 ic
->ic_flags
& IEEE80211_F_DROPUNENC
,
3040 sc
->sc_ic_flags
& IEEE80211_F_DROPUNENC
));
3044 wi_newstate(struct ieee80211com
*ic
, enum ieee80211_state nstate
, int arg
)
3046 struct ifnet
*ifp
= ic
->ic_ifp
;
3047 struct wi_softc
*sc
= ifp
->if_softc
;
3048 struct ieee80211_node
*ni
= ic
->ic_bss
;
3050 struct wi_ssid ssid
;
3051 struct wi_macaddr bssid
, old_bssid
;
3052 enum ieee80211_state ostate
;
3054 static const char *stname
[] =
3055 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
3056 #endif /* WI_DEBUG */
3058 ostate
= ic
->ic_state
;
3059 DPRINTF(("wi_newstate: %s -> %s\n", stname
[ostate
], stname
[nstate
]));
3062 case IEEE80211_S_INIT
:
3063 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
)
3064 callout_stop(&sc
->sc_rssadapt_ch
);
3065 ic
->ic_flags
&= ~IEEE80211_F_SIBSS
;
3066 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
3069 case IEEE80211_S_SCAN
:
3070 case IEEE80211_S_AUTH
:
3071 case IEEE80211_S_ASSOC
:
3072 ic
->ic_state
= nstate
; /* NB: skip normal ieee80211 handling */
3073 wi_mend_flags(sc
, nstate
);
3076 case IEEE80211_S_RUN
:
3077 sc
->sc_flags
&= ~WI_FLAGS_OUTRANGE
;
3078 IEEE80211_ADDR_COPY(old_bssid
.wi_mac_addr
, ni
->ni_bssid
);
3079 wi_read_xrid(sc
, WI_RID_CURRENT_BSSID
, &bssid
,
3080 IEEE80211_ADDR_LEN
);
3081 IEEE80211_ADDR_COPY(ni
->ni_bssid
, &bssid
);
3082 IEEE80211_ADDR_COPY(ni
->ni_macaddr
, &bssid
);
3083 wi_read_xrid(sc
, WI_RID_CURRENT_CHAN
, &val
, sizeof(val
));
3084 if (!isset(ic
->ic_chan_avail
, le16toh(val
)))
3085 panic("%s: invalid channel %d\n", device_xname(&sc
->sc_dev
),
3087 ni
->ni_chan
= &ic
->ic_channels
[le16toh(val
)];
3089 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
3090 #ifndef IEEE80211_NO_HOSTAP
3091 ni
->ni_esslen
= ic
->ic_des_esslen
;
3092 memcpy(ni
->ni_essid
, ic
->ic_des_essid
, ni
->ni_esslen
);
3093 ni
->ni_rates
= ic
->ic_sup_rates
[
3094 ieee80211_chan2mode(ic
, ni
->ni_chan
)];
3095 ni
->ni_intval
= ic
->ic_lintval
;
3096 ni
->ni_capinfo
= IEEE80211_CAPINFO_ESS
;
3097 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
)
3098 ni
->ni_capinfo
|= IEEE80211_CAPINFO_PRIVACY
;
3099 #endif /* !IEEE80211_NO_HOSTAP */
3101 wi_read_xrid(sc
, WI_RID_CURRENT_SSID
, &ssid
,
3103 ni
->ni_esslen
= le16toh(ssid
.wi_len
);
3104 if (ni
->ni_esslen
> IEEE80211_NWID_LEN
)
3105 ni
->ni_esslen
= IEEE80211_NWID_LEN
; /*XXX*/
3106 memcpy(ni
->ni_essid
, ssid
.wi_ssid
, ni
->ni_esslen
);
3107 ni
->ni_rates
= ic
->ic_sup_rates
[
3108 ieee80211_chan2mode(ic
, ni
->ni_chan
)]; /*XXX*/
3110 if (ic
->ic_opmode
!= IEEE80211_M_MONITOR
)
3111 callout_reset(&sc
->sc_rssadapt_ch
, hz
/ 10,
3112 wi_rssadapt_updatestats
, sc
);
3113 /* Trigger routing socket messages. XXX Copied from
3114 * ieee80211_newstate.
3116 if (ic
->ic_opmode
== IEEE80211_M_STA
)
3117 ieee80211_notify_node_join(ic
, ic
->ic_bss
,
3118 arg
== IEEE80211_FC0_SUBTYPE_ASSOC_RESP
);
3121 wi_mend_flags(sc
, nstate
);
3122 return (*sc
->sc_newstate
)(ic
, nstate
, arg
);
3126 wi_set_tim(struct ieee80211_node
*ni
, int set
)
3128 struct ieee80211com
*ic
= ni
->ni_ic
;
3129 struct wi_softc
*sc
= ic
->ic_ifp
->if_softc
;
3131 (*sc
->sc_set_tim
)(ni
, set
);
3133 if ((ic
->ic_flags
& IEEE80211_F_TIMUPDATE
) == 0)
3136 ic
->ic_flags
&= ~IEEE80211_F_TIMUPDATE
;
3138 (void)wi_write_val(sc
, WI_RID_SET_TIM
,
3139 IEEE80211_AID(ni
->ni_associd
) | (set
? 0x8000 : 0));
3143 wi_scan_ap(struct wi_softc
*sc
, u_int16_t chanmask
, u_int16_t txrate
)
3148 if (!sc
->sc_enabled
)
3150 switch (sc
->sc_firmware_type
) {
3152 (void)wi_cmd(sc
, WI_CMD_INQUIRE
, WI_INFO_SCAN_RESULTS
, 0, 0);
3155 val
[0] = htole16(chanmask
); /* channel */
3156 val
[1] = htole16(txrate
); /* tx rate */
3157 error
= wi_write_rid(sc
, WI_RID_SCAN_REQ
, val
, sizeof(val
));
3161 * XXX only supported on 3.x ?
3163 val
[0] = htole16(BSCAN_BCAST
| BSCAN_ONETIME
);
3164 error
= wi_write_rid(sc
, WI_RID_BCAST_SCAN_REQ
,
3165 val
, sizeof(val
[0]));
3169 sc
->sc_scan_timer
= WI_SCAN_WAIT
;
3170 sc
->sc_if
.if_timer
= 1;
3171 DPRINTF(("wi_scan_ap: start scanning, "
3172 "chanmask 0x%x txrate 0x%x\n", chanmask
, txrate
));
3178 wi_scan_result(struct wi_softc
*sc
, int fid
, int cnt
)
3180 #define N(a) (sizeof (a) / sizeof (a[0]))
3181 int i
, naps
, off
, szbuf
;
3182 struct wi_scan_header ws_hdr
; /* Prism2 header */
3183 struct wi_scan_data_p2 ws_dat
; /* Prism2 scantable*/
3184 struct wi_apinfo
*ap
;
3186 off
= sizeof(u_int16_t
) * 2;
3187 memset(&ws_hdr
, 0, sizeof(ws_hdr
));
3188 switch (sc
->sc_firmware_type
) {
3190 wi_read_bap(sc
, fid
, off
, &ws_hdr
, sizeof(ws_hdr
));
3191 off
+= sizeof(ws_hdr
);
3192 szbuf
= sizeof(struct wi_scan_data_p2
);
3195 szbuf
= sizeof(struct wi_scan_data_p2
) + 6;
3198 szbuf
= sizeof(struct wi_scan_data
);
3201 aprint_error_dev(&sc
->sc_dev
, "wi_scan_result: unknown firmware type %u\n",
3202 sc
->sc_firmware_type
);
3206 naps
= (cnt
* 2 + 2 - off
) / szbuf
;
3207 if (naps
> N(sc
->sc_aps
))
3208 naps
= N(sc
->sc_aps
);
3212 memset(&ws_dat
, 0, sizeof(ws_dat
));
3213 for (i
= 0; i
< naps
; i
++, ap
++) {
3214 wi_read_bap(sc
, fid
, off
, &ws_dat
,
3215 (sizeof(ws_dat
) < szbuf
? sizeof(ws_dat
) : szbuf
));
3216 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i
, off
,
3217 ether_sprintf(ws_dat
.wi_bssid
)));
3219 ap
->scanreason
= le16toh(ws_hdr
.wi_reason
);
3220 memcpy(ap
->bssid
, ws_dat
.wi_bssid
, sizeof(ap
->bssid
));
3221 ap
->channel
= le16toh(ws_dat
.wi_chid
);
3222 ap
->signal
= le16toh(ws_dat
.wi_signal
);
3223 ap
->noise
= le16toh(ws_dat
.wi_noise
);
3224 ap
->quality
= ap
->signal
- ap
->noise
;
3225 ap
->capinfo
= le16toh(ws_dat
.wi_capinfo
);
3226 ap
->interval
= le16toh(ws_dat
.wi_interval
);
3227 ap
->rate
= le16toh(ws_dat
.wi_rate
);
3228 ap
->namelen
= le16toh(ws_dat
.wi_namelen
);
3229 if (ap
->namelen
> sizeof(ap
->name
))
3230 ap
->namelen
= sizeof(ap
->name
);
3231 memcpy(ap
->name
, ws_dat
.wi_name
, ap
->namelen
);
3235 sc
->sc_scan_timer
= 0;
3236 DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps
));
3241 wi_dump_pkt(struct wi_frame
*wh
, struct ieee80211_node
*ni
, int rssi
)
3243 ieee80211_dump_pkt((u_int8_t
*) &wh
->wi_whdr
, sizeof(wh
->wi_whdr
),
3244 ni
? ni
->ni_rates
.rs_rates
[ni
->ni_txrate
] & IEEE80211_RATE_VAL
3247 printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
3248 le16toh(wh
->wi_status
), le16toh(wh
->wi_rx_tstamp1
),
3249 le16toh(wh
->wi_rx_tstamp0
), wh
->wi_rx_silence
);
3250 printf(" rx_signal %u rx_rate %u rx_flow %u\n",
3251 wh
->wi_rx_signal
, wh
->wi_rx_rate
, wh
->wi_rx_flow
);
3252 printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
3253 wh
->wi_tx_rtry
, wh
->wi_tx_rate
,
3254 le16toh(wh
->wi_tx_ctl
), le16toh(wh
->wi_dat_len
));
3255 printf(" ehdr dst %s src %s type 0x%x\n",
3256 ether_sprintf(wh
->wi_ehdr
.ether_dhost
),
3257 ether_sprintf(wh
->wi_ehdr
.ether_shost
),
3258 wh
->wi_ehdr
.ether_type
);