Bug Summary

File:dev/ic/if_wi.c
Warning:line 2649, column 3
6th function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_wi.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/ic/if_wi.c
1/* $OpenBSD: if_wi.c,v 1.176 2022/01/09 05:42:38 jsg Exp $ */
2
3/*
4 * Copyright (c) 1997, 1998, 1999
5 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * From: if_wi.c,v 1.7 1999/07/04 14:40:22 wpaul Exp $
35 */
36
37/*
38 * Lucent WaveLAN/IEEE 802.11 driver for OpenBSD.
39 *
40 * Originally written by Bill Paul <wpaul@ctr.columbia.edu>
41 * Electrical Engineering Department
42 * Columbia University, New York City
43 */
44
45/*
46 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
47 * from Lucent. Unlike the older cards, the new ones are programmed
48 * entirely via a firmware-driven controller called the Hermes.
49 * Unfortunately, Lucent will not release the Hermes programming manual
50 * without an NDA (if at all). What they do release is an API library
51 * called the HCF (Hardware Control Functions) which is supposed to
52 * do the device-specific operations of a device driver for you. The
53 * publicly available version of the HCF library (the 'HCF Light') is
54 * a) extremely gross, b) lacks certain features, particularly support
55 * for 802.11 frames, and c) is contaminated by the GNU Public License.
56 *
57 * This driver does not use the HCF or HCF Light at all. Instead, it
58 * programs the Hermes controller directly, using information gleaned
59 * from the HCF Light code and corresponding documentation.
60 */
61
62#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
63#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
64
65#include "bpfilter.h"
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/sockio.h>
70#include <sys/mbuf.h>
71#include <sys/malloc.h>
72#include <sys/kernel.h>
73#include <sys/socket.h>
74#include <sys/device.h>
75
76#include <net/if.h>
77#include <net/if_dl.h>
78#include <net/if_media.h>
79
80#include <netinet/in.h>
81#include <netinet/if_ether.h>
82
83#include <net80211/ieee80211_var.h>
84#include <net80211/ieee80211_ioctl.h>
85
86#if NBPFILTER1 > 0
87#include <net/bpf.h>
88#endif
89
90#include <machine/bus.h>
91
92#include <dev/ic/if_wireg.h>
93#include <dev/ic/if_wi_ieee.h>
94#include <dev/ic/if_wivar.h>
95
96#include <crypto/arc4.h>
97
98#define BPFATTACH(if_bpf,if,dlt,sz)
99#define STATIC
100
101#ifdef WIDEBUG
102
103u_int32_t widebug = WIDEBUG;
104
105#define WID_INTR 0x01
106#define WID_START 0x02
107#define WID_IOCTL 0x04
108#define WID_INIT 0x08
109#define WID_STOP 0x10
110#define WID_RESET 0x20
111
112#define DPRINTF(mask,args) if (widebug & (mask)) printf args;
113
114#else /* !WIDEBUG */
115#define DPRINTF(mask,args)
116#endif /* WIDEBUG */
117
118#ifdef foo
119static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
120#endif
121
122STATIC void wi_reset(struct wi_softc *);
123STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t);
124STATIC void wi_init_io(struct wi_softc *);
125STATIC void wi_start(struct ifnet *);
126STATIC void wi_watchdog(struct ifnet *);
127STATIC void wi_rxeof(struct wi_softc *);
128STATIC void wi_txeof(struct wi_softc *, int);
129STATIC void wi_update_stats(struct wi_softc *);
130STATIC void wi_setmulti(struct wi_softc *);
131
132STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int);
133STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *);
134STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *);
135STATIC int wi_read_data_io(struct wi_softc *, int,
136 int, caddr_t, int);
137STATIC int wi_write_data_io(struct wi_softc *, int,
138 int, caddr_t, int);
139STATIC int wi_seek(struct wi_softc *, int, int, int);
140
141STATIC void wi_inquire(void *);
142STATIC int wi_setdef(struct wi_softc *, struct wi_req *);
143STATIC void wi_get_id(struct wi_softc *);
144
145STATIC int wi_media_change(struct ifnet *);
146STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
147
148STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int);
149STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
150STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
151STATIC int wi_sync_media(struct wi_softc *, int, int);
152STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
153STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
154STATIC int wi_set_txpower(struct wi_softc *, struct ieee80211_txpower *);
155STATIC int wi_get_txpower(struct wi_softc *, struct ieee80211_txpower *);
156
157STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
158STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
159
160STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
161STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
162
163STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
164STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
165STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
166STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
167void wi_scan_timeout(void *);
168
169/* Autoconfig definition of driver back-end */
170struct cfdriver wi_cd = {
171 NULL((void *)0), "wi", DV_IFNET
172};
173
174const struct wi_card_ident wi_card_ident[] = {
175 WI_CARD_IDS{ 0x0001, "Lucent WaveLAN/IEEE", 1 }, { 0x0002, "Sony WaveLAN/IEEE"
, 1 }, { 0x0005, "Lucent Embedded WaveLAN/IEEE", 1 }, { 0x8000
, "PRISM2 HFA3841(EVB2)", 2 }, { 0x8001, "PRISM2 HWB3763 rev.B"
, 2 }, { 0x8002, "PRISM2 HWB3163 rev.A", 2 }, { 0x8003, "PRISM2 HWB3163 rev.B"
, 2 }, { 0x8004, "PRISM2 HFA3842(EVB3)", 2 }, { 0x8007, "PRISM1 HWB1153"
, 2 }, { 0x8008, "PRISM2 HWB3163 SST-flash", 2 }, { 0x8009, "PRISM2 HWB3163(EVB2) SST-flash"
, 2 }, { 0x800A, "PRISM2 HFA3842(EVAL)", 2 }, { 0x800B, "PRISM2.5 ISL3873"
, 2 }, { 0x800C, "PRISM2.5 ISL3873", 2 }, { 0x800D, "PRISM2.5 ISL3873"
, 2 }, { 0x800E, "PRISM2.5 ISL3873", 2 }, { 0x800f, "PRISM2.5 USB"
, 2 }, { 0x8010, "PRISM2.5 USB", 2 }, { 0x8011, "PRISM2.5 USB"
, 2 }, { 0x8012, "PRISM2.5 ISL3874A(Mini-PCI)", 2 }, { 0x8013
, "PRISM2.5 ISL3874A(Mini-PCI)", 2 }, { 0x8014, "PRISM2.5 ISL3874A(Mini-PCI)"
, 2 }, { 0x8015, "PRISM2.5 ISL3874A(Mini-PCI)", 2 }, { 0x8016
, "PRISM2.5 ISL3874A(PCI-bridge)", 2 }, { 0x8017, "PRISM2.5 ISL3874A(PCI-bridge)"
, 2 }, { 0x8019, "PRISM2.5 ISL3874A(PCI-bridge)", 2 }, { 0x8018
, "PRISM2.5 ISL3874A(PCI-bridge)", 2 }, { 0x801A, "PRISM3 ISL37300P"
, 2 }, { 0x801B, "PRISM3 ISL37300P", 2 }, { 0x801C, "PRISM3 ISL37300P"
, 2 }, { 0x801D, "PRISM3 ISL37300P", 2 }, { 0x801E, "PRISM2.5 USB"
, 2 }, { 0x801F, "PRISM2.5 USB", 2 }, { 0x8020, "PRISM2.5 USB"
, 2 }, { 0x8021, "PRISM3 ISL37300P(PCI)", 2 }, { 0x8022, "PRISM3 ISL37300P(PCI)"
, 2 }, { 0x8023, "PRISM3 ISL37300P(PCI)", 2 }, { 0x8024, "PRISM3 ISL37300P(PCI)"
, 2 }, { 0x8025, "PRISM3 (USB)", 2 }, { 0x8026, "PRISM3 (USB)"
, 2 }, { 0x8027, "PRISM3 (USB)", 2 }, { 0, ((void *)0), 0 }
176};
177
178struct wi_funcs wi_func_io = {
179 wi_cmd_io,
180 wi_read_record_io,
181 wi_write_record_io,
182 wi_alloc_nicmem_io,
183 wi_read_data_io,
184 wi_write_data_io,
185 wi_get_fid_io,
186 wi_init_io,
187
188 wi_start,
189 wi_ioctl,
190 wi_watchdog,
191 wi_inquire,
192};
193
194int
195wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
196{
197 struct ieee80211com *ic;
198 struct ifnet *ifp;
199 struct wi_ltv_macaddr mac;
200 struct wi_ltv_rates rates;
201 struct wi_ltv_gen gen;
202 int error;
203
204 ic = &sc->sc_ic;
205 ifp = &ic->ic_ific_ac.ac_if;
206
207 sc->sc_funcs = funcs;
208 sc->wi_cmd_count = 500;
209
210 wi_reset(sc);
211
212 /* Read the station address. */
213 mac.wi_type = WI_RID_MAC_NODE0xFC01;
214 mac.wi_len = 4;
215 error = wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&mac);
216 if (error) {
1
Assuming 'error' is 0
2
Taking false branch
217 printf(": unable to read station address\n");
218 return (error);
219 }
220 bcopy(&mac.wi_mac_addr, &ic->ic_myaddr, IEEE80211_ADDR_LEN6);
221
222 wi_get_id(sc);
3
Calling 'wi_get_id'
223 printf("address %s", ether_sprintf(ic->ic_myaddr));
224
225 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ16);
226 ifp->if_softc = sc;
227 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
228 ifp->if_ioctl = funcs->f_ioctl;
229 ifp->if_start = funcs->f_start;
230 ifp->if_watchdog = funcs->f_watchdog;
231
232 (void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME"WaveLAN/IEEE node",
233 sizeof(WI_DEFAULT_NODENAME"WaveLAN/IEEE node") - 1);
234 (void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME"",
235 sizeof(WI_DEFAULT_NETNAME"") - 1);
236 (void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS"IBSS",
237 sizeof(WI_DEFAULT_IBSS"IBSS") - 1);
238
239 sc->wi_portnum = WI_DEFAULT_PORT(0 << 8);
240 sc->wi_ptype = WI_PORTTYPE_BSS0x1;
241 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY1;
242 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH2347;
243 sc->wi_tx_rate = WI_DEFAULT_TX_RATE3;
244 sc->wi_max_data_len = WI_DEFAULT_DATALEN2304;
245 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS0;
246 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED0;
247 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP100;
248 sc->wi_roaming = WI_DEFAULT_ROAMING1;
249 sc->wi_authtype = WI_DEFAULT_AUTHTYPE1;
250 sc->wi_diversity = WI_DEFAULT_DIVERSITY0;
251 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP0x00;
252
253 /*
254 * Read the default channel from the NIC. This may vary
255 * depending on the country where the NIC was purchased, so
256 * we can't hard-code a default and expect it to work for
257 * everyone.
258 */
259 gen.wi_type = WI_RID_OWN_CHNL0xFC03;
260 gen.wi_len = 2;
261 if (wi_read_recordsc->sc_funcs->f_read_record(sc, &gen) == 0)
262 sc->wi_channel = letoh16(gen.wi_val)((__uint16_t)(gen.wi_val));
263 else
264 sc->wi_channel = 3;
265
266 /*
267 * Set flags based on firmware version.
268 */
269 switch (sc->sc_firmware_type) {
270 case WI_LUCENT1:
271 sc->wi_flags |= WI_FLAGS_HAS_ROAMING0x0040;
272 if (sc->sc_sta_firmware_ver >= 60000)
273 sc->wi_flags |= WI_FLAGS_HAS_MOR0x0020;
274 if (sc->sc_sta_firmware_ver >= 60006) {
275 sc->wi_flags |= WI_FLAGS_HAS_IBSS0x0008;
276 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS0x0010;
277 }
278 sc->wi_ibss_port = htole16(1)((__uint16_t)(1));
279 break;
280 case WI_INTERSIL2:
281 sc->wi_flags |= WI_FLAGS_HAS_ROAMING0x0040;
282 /* older prism firmware is slow so crank the count */
283 if (sc->sc_sta_firmware_ver < 10000)
284 sc->wi_cmd_count = 5000;
285 else
286 sc->wi_cmd_count = 2000;
287 if (sc->sc_sta_firmware_ver >= 800) {
288#ifndef SMALL_KERNEL
289 /*
290 * USB hostap is more pain than it is worth
291 * for now, things would have to be overhauled
292 */
293 if ((sc->sc_sta_firmware_ver != 10402) &&
294 (!(sc->wi_flags & WI_FLAGS_BUS_USB0x0400)))
295 sc->wi_flags |= WI_FLAGS_HAS_HOSTAP0x0100;
296#endif
297 sc->wi_flags |= WI_FLAGS_HAS_IBSS0x0008;
298 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS0x0010;
299 }
300 if (sc->sc_sta_firmware_ver >= 10603)
301 sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY0x0800;
302 sc->wi_ibss_port = htole16(0)((__uint16_t)(0));
303 break;
304 case WI_SYMBOL3:
305 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY0x0080;
306 if (sc->sc_sta_firmware_ver >= 20000)
307 sc->wi_flags |= WI_FLAGS_HAS_IBSS0x0008;
308 if (sc->sc_sta_firmware_ver >= 25000)
309 sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS0x0010;
310 sc->wi_ibss_port = htole16(4)((__uint16_t)(4));
311 break;
312 }
313
314 /*
315 * Find out if we support WEP on this card.
316 */
317 gen.wi_type = WI_RID_WEP_AVAIL0xFD4F;
318 gen.wi_len = 2;
319 if (wi_read_recordsc->sc_funcs->f_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0)((__uint16_t)(0)))
320 sc->wi_flags |= WI_FLAGS_HAS_WEP0x0004;
321 timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
322
323 bzero(&sc->wi_stats, sizeof(sc->wi_stats))__builtin_bzero((&sc->wi_stats), (sizeof(sc->wi_stats
)))
;
324
325 /* Find supported rates. */
326 rates.wi_type = WI_RID_DATA_RATES0xFDC6;
327 rates.wi_len = sizeof(rates.wi_rates);
328 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&rates) == 0) {
329 int i, nrates;
330
331 nrates = letoh16(*(u_int16_t *)rates.wi_rates)((__uint16_t)(*(u_int16_t *)rates.wi_rates));
332 if (nrates > sizeof(rates.wi_rates) - 2)
333 nrates = sizeof(rates.wi_rates) - 2;
334
335 sc->wi_supprates = 0;
336 for (i = 0; i < nrates; i++)
337 sc->wi_supprates |= rates.wi_rates[2 + i];
338 } else
339 sc->wi_supprates = WI_SUPPRATES_1M0x0001 | WI_SUPPRATES_2M0x0002 |
340 WI_SUPPRATES_5M0x0004 | WI_SUPPRATES_11M0x0008;
341
342 ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
343#define ADD(m, c) ifmedia_add(&sc->sc_media, (m), (c), NULL((void *)0))
344 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)((0x0000000000000400ULL) | (0ULL) | (0) | ((uint64_t)(0) <<
56))
, 0);
345 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0)((0x0000000000000400ULL) | (0ULL) | (0x0000000000010000ULL) |
((uint64_t)(0) << 56))
, 0);
346 if (sc->wi_flags & WI_FLAGS_HAS_IBSS0x0008)
347 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,((0x0000000000000400ULL) | (0ULL) | (0x0000000000040000ULL) |
((uint64_t)(0) << 56))
348 0)((0x0000000000000400ULL) | (0ULL) | (0x0000000000040000ULL) |
((uint64_t)(0) << 56))
, 0);
349 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)
350 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,((0x0000000000000400ULL) | (0ULL) | (0x0000000000080000ULL) |
((uint64_t)(0) << 56))
351 IFM_IEEE80211_IBSSMASTER, 0)((0x0000000000000400ULL) | (0ULL) | (0x0000000000080000ULL) |
((uint64_t)(0) << 56))
, 0);
352 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP0x0100)
353 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,((0x0000000000000400ULL) | (0ULL) | (0x0000000000020000ULL) |
((uint64_t)(0) << 56))
354 IFM_IEEE80211_HOSTAP, 0)((0x0000000000000400ULL) | (0ULL) | (0x0000000000020000ULL) |
((uint64_t)(0) << 56))
, 0);
355 if (sc->wi_supprates & WI_SUPPRATES_1M0x0001) {
356 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0)((0x0000000000000400ULL) | (8) | (0) | ((uint64_t)(0) <<
56))
, 0);
357 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,((0x0000000000000400ULL) | (8) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
358 IFM_IEEE80211_ADHOC, 0)((0x0000000000000400ULL) | (8) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
, 0);
359 if (sc->wi_flags & WI_FLAGS_HAS_IBSS0x0008)
360 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,((0x0000000000000400ULL) | (8) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
361 IFM_IEEE80211_IBSS, 0)((0x0000000000000400ULL) | (8) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
, 0);
362 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)
363 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,((0x0000000000000400ULL) | (8) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
364 IFM_IEEE80211_IBSSMASTER, 0)((0x0000000000000400ULL) | (8) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
, 0);
365 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP0x0100)
366 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,((0x0000000000000400ULL) | (8) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
367 IFM_IEEE80211_HOSTAP, 0)((0x0000000000000400ULL) | (8) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
, 0);
368 }
369 if (sc->wi_supprates & WI_SUPPRATES_2M0x0002) {
370 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0)((0x0000000000000400ULL) | (5) | (0) | ((uint64_t)(0) <<
56))
, 0);
371 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,((0x0000000000000400ULL) | (5) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
372 IFM_IEEE80211_ADHOC, 0)((0x0000000000000400ULL) | (5) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
, 0);
373 if (sc->wi_flags & WI_FLAGS_HAS_IBSS0x0008)
374 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,((0x0000000000000400ULL) | (5) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
375 IFM_IEEE80211_IBSS, 0)((0x0000000000000400ULL) | (5) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
, 0);
376 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)
377 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,((0x0000000000000400ULL) | (5) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
378 IFM_IEEE80211_IBSSMASTER, 0)((0x0000000000000400ULL) | (5) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
, 0);
379 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP0x0100)
380 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,((0x0000000000000400ULL) | (5) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
381 IFM_IEEE80211_HOSTAP, 0)((0x0000000000000400ULL) | (5) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
, 0);
382 }
383 if (sc->wi_supprates & WI_SUPPRATES_5M0x0004) {
384 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0)((0x0000000000000400ULL) | (6) | (0) | ((uint64_t)(0) <<
56))
, 0);
385 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,((0x0000000000000400ULL) | (6) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
386 IFM_IEEE80211_ADHOC, 0)((0x0000000000000400ULL) | (6) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
, 0);
387 if (sc->wi_flags & WI_FLAGS_HAS_IBSS0x0008)
388 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,((0x0000000000000400ULL) | (6) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
389 IFM_IEEE80211_IBSS, 0)((0x0000000000000400ULL) | (6) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
, 0);
390 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)
391 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,((0x0000000000000400ULL) | (6) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
392 IFM_IEEE80211_IBSSMASTER, 0)((0x0000000000000400ULL) | (6) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
, 0);
393 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP0x0100)
394 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,((0x0000000000000400ULL) | (6) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
395 IFM_IEEE80211_HOSTAP, 0)((0x0000000000000400ULL) | (6) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
, 0);
396 }
397 if (sc->wi_supprates & WI_SUPPRATES_11M0x0008) {
398 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0)((0x0000000000000400ULL) | (7) | (0) | ((uint64_t)(0) <<
56))
, 0);
399 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,((0x0000000000000400ULL) | (7) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
400 IFM_IEEE80211_ADHOC, 0)((0x0000000000000400ULL) | (7) | (0x0000000000010000ULL) | ((
uint64_t)(0) << 56))
, 0);
401 if (sc->wi_flags & WI_FLAGS_HAS_IBSS0x0008)
402 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,((0x0000000000000400ULL) | (7) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
403 IFM_IEEE80211_IBSS, 0)((0x0000000000000400ULL) | (7) | (0x0000000000040000ULL) | ((
uint64_t)(0) << 56))
, 0);
404 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)
405 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,((0x0000000000000400ULL) | (7) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
406 IFM_IEEE80211_IBSSMASTER, 0)((0x0000000000000400ULL) | (7) | (0x0000000000080000ULL) | ((
uint64_t)(0) << 56))
, 0);
407 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP0x0100)
408 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,((0x0000000000000400ULL) | (7) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
409 IFM_IEEE80211_HOSTAP, 0)((0x0000000000000400ULL) | (7) | (0x0000000000020000ULL) | ((
uint64_t)(0) << 56))
, 0);
410 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0)((0x0000000000000400ULL) | (1ULL) | (0) | ((uint64_t)(0) <<
56))
, 0);
411 }
412#undef ADD
413 ifmedia_set(&sc->sc_media,
414 IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0)((0x0000000000000400ULL) | (0ULL) | (0) | ((uint64_t)(0) <<
56))
);
415
416 /*
417 * Call MI attach routines.
418 */
419 if_attach(ifp);
420 memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,__builtin_memcpy((((struct arpcom *)ifp)->ac_enaddr), (ic->
ic_myaddr), (6))
421 ETHER_ADDR_LEN)__builtin_memcpy((((struct arpcom *)ifp)->ac_enaddr), (ic->
ic_myaddr), (6))
;
422 ether_ifattach(ifp);
423 printf("\n");
424
425 sc->wi_flags |= WI_FLAGS_ATTACHED0x0001;
426
427#if NBPFILTER1 > 0
428 BPFATTACH(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
429#endif
430
431 if_addgroup(ifp, "wlan");
432 ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY4;
433
434 wi_initsc->sc_funcs->f_init(sc);
435 wi_stop(sc);
436
437 return (0);
438}
439
440STATIC void
441wi_intr_enable(struct wi_softc *sc, int mode)
442{
443 if (!(sc->wi_flags & WI_FLAGS_BUS_USB0x0400))
444 CSR_WRITE_2(sc, WI_INT_EN, mode)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x32 * 2: 0x32)), ((mode))))
;
445}
446
447STATIC void
448wi_intr_ack(struct wi_softc *sc, int mode)
449{
450 if (!(sc->wi_flags & WI_FLAGS_BUS_USB0x0400))
451 CSR_WRITE_2(sc, WI_EVENT_ACK, mode)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((mode))))
;
452}
453
454int
455wi_intr(void *vsc)
456{
457 struct wi_softc *sc = vsc;
458 struct ifnet *ifp;
459 u_int16_t status;
460
461 DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
462
463 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
464
465 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001) || !(ifp->if_flags & IFF_UP0x1)) {
466 CSR_WRITE_2(sc, WI_INT_EN, 0)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x32 * 2: 0x32)), ((0))))
;
467 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0xffff))))
;
468 return (0);
469 }
470
471 /* Disable interrupts. */
472 CSR_WRITE_2(sc, WI_INT_EN, 0)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x32 * 2: 0x32)), ((0))))
;
473
474 status = CSR_READ_2(sc, WI_EVENT_STAT)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x30 * 2: 0x30))))
;
475 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((~(0x0001|0x0002|0x0004|0x0008|0x0080|0x2000
)))))
;
476
477 if (status & WI_EV_RX0x0001) {
478 wi_rxeof(sc);
479 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0001))))
;
480 }
481
482 if (status & WI_EV_TX0x0002) {
483 wi_txeof(sc, status);
484 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0002))))
;
485 }
486
487 if (status & WI_EV_ALLOC0x0008) {
488 int id;
489 id = CSR_READ_2(sc, WI_ALLOC_FID)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x22 * 2: 0x22))))
;
490 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0008))))
;
491 if (id == sc->wi_tx_data_id)
492 wi_txeof(sc, status);
493 }
494
495 if (status & WI_EV_INFO0x0080) {
496 wi_update_stats(sc);
497 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0080))))
;
498 }
499
500 if (status & WI_EV_TX_EXC0x0004) {
501 wi_txeof(sc, status);
502 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0004))))
;
503 }
504
505 if (status & WI_EV_INFO_DROP0x2000) {
506 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x2000))))
;
507 }
508
509 /* Re-enable interrupts. */
510 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x32 * 2: 0x32)), (((0x0001|0x0002|0x0004|0x0008|0x0080|0x2000
)))))
;
511
512 if (status == 0)
513 return (0);
514
515 if (!ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0))
516 wi_start(ifp);
517
518 return (1);
519}
520
521STATIC int
522wi_get_fid_io(struct wi_softc *sc, int fid)
523{
524 return CSR_READ_2(sc, fid)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? fid * 2: fid))))
;
525}
526
527
528void
529wi_rxeof(struct wi_softc *sc)
530{
531 struct ifnet *ifp;
532 struct ether_header *eh;
533 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
534 struct mbuf *m;
535 caddr_t olddata;
536 u_int16_t ftype;
537 int maxlen;
538 int id;
539
540 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
541
542 id = wi_get_fidsc->sc_funcs->f_get_fid(sc, WI_RX_FID0x20);
543
544 if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
545 struct wi_frame *rx_frame;
546 int datlen, hdrlen;
547
548 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
549 if (m == NULL((void *)0)) {
550 ifp->if_ierrorsif_data.ifi_ierrors++;
551 return;
552 }
553 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
554 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
555 m_freem(m);
556 ifp->if_ierrorsif_data.ifi_ierrors++;
557 return;
558 }
559
560 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, 0, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)),
561 sizeof(struct wi_frame))) {
562 m_freem(m);
563 ifp->if_ierrorsif_data.ifi_ierrors++;
564 return;
565 }
566
567 rx_frame = mtod(m, struct wi_frame *)((struct wi_frame *)((m)->m_hdr.mh_data));
568
569 if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)((__uint16_t)(0x0001))) {
570 m_freem(m);
571 ifp->if_ierrorsif_data.ifi_ierrors++;
572 return;
573 }
574
575 switch ((letoh16(rx_frame->wi_status)((__uint16_t)(rx_frame->wi_status)) & WI_STAT_MAC_PORT0x0700)
576 >> 8) {
577 case 7:
578 switch (letoh16(rx_frame->wi_frame_ctl)((__uint16_t)(rx_frame->wi_frame_ctl)) &
579 WI_FCTL_FTYPE0x000C) {
580 case WI_FTYPE_DATA0x0008:
581 hdrlen = WI_DATA_HDRLEN0x44;
582 datlen = letoh16(rx_frame->wi_dat_len)((__uint16_t)(rx_frame->wi_dat_len));
583 break;
584 case WI_FTYPE_MGMT0x0000:
585 hdrlen = WI_MGMT_HDRLEN0x3C;
586 datlen = letoh16(rx_frame->wi_dat_len)((__uint16_t)(rx_frame->wi_dat_len));
587 break;
588 case WI_FTYPE_CTL0x0004:
589 hdrlen = WI_CTL_HDRLEN0x3C;
590 datlen = 0;
591 break;
592 default:
593 printf(WI_PRT_FMT"%s" ": received packet of "
594 "unknown type on port 7\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
595 m_freem(m);
596 ifp->if_ierrorsif_data.ifi_ierrors++;
597 return;
598 }
599 break;
600 case 0:
601 hdrlen = WI_DATA_HDRLEN0x44;
602 datlen = letoh16(rx_frame->wi_dat_len)((__uint16_t)(rx_frame->wi_dat_len));
603 break;
604 default:
605 printf(WI_PRT_FMT"%s" ": received packet on invalid port "
606 "(wi_status=0x%x)\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
607 letoh16(rx_frame->wi_status)((__uint16_t)(rx_frame->wi_status)));
608 m_freem(m);
609 ifp->if_ierrorsif_data.ifi_ierrors++;
610 return;
611 }
612
613 if ((hdrlen + datlen + 2) > MCLBYTES(1 << 11)) {
614 m_freem(m);
615 ifp->if_ierrorsif_data.ifi_ierrors++;
616 return;
617 }
618
619 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, hdrlen, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + hdrlen,
620 datlen + 2)) {
621 m_freem(m);
622 ifp->if_ierrorsif_data.ifi_ierrors++;
623 return;
624 }
625
626 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = hdrlen + datlen;
627 } else {
628 struct wi_frame rx_frame;
629
630 /* First read in the frame header */
631 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, 0, (caddr_t)&rx_frame,
632 sizeof(rx_frame))) {
633 ifp->if_ierrorsif_data.ifi_ierrors++;
634 return;
635 }
636
637 /* Drop undecryptable or packets with receive errors here */
638 if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)((__uint16_t)(0x0003))) {
639 ifp->if_ierrorsif_data.ifi_ierrors++;
640 return;
641 }
642
643 /* Stash frame type in host byte order for later use */
644 ftype = letoh16(rx_frame.wi_frame_ctl)((__uint16_t)(rx_frame.wi_frame_ctl)) & WI_FCTL_FTYPE0x000C;
645
646 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
647 if (m == NULL((void *)0)) {
648 ifp->if_ierrorsif_data.ifi_ierrors++;
649 return;
650 }
651 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
652 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
653 m_freem(m);
654 ifp->if_ierrorsif_data.ifi_ierrors++;
655 return;
656 }
657
658 olddata = m->m_datam_hdr.mh_data;
659 /* Align the data after the ethernet header */
660 m->m_datam_hdr.mh_data = (caddr_t)ALIGN(m->m_data +(((unsigned long)(m->m_hdr.mh_data + sizeof(struct ether_header
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1))
661 sizeof(struct ether_header))(((unsigned long)(m->m_hdr.mh_data + sizeof(struct ether_header
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1))
- sizeof(struct ether_header);
662
663 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
664 maxlen = MCLBYTES(1 << 11) - (m->m_datam_hdr.mh_data - olddata);
665
666 if (ftype == WI_FTYPE_MGMT0x0000 &&
667 sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6) {
668
669 u_int16_t rxlen = letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len));
670
671 if ((WI_802_11_OFFSET_RAW0x3C + rxlen + 2) > maxlen) {
672 printf("%s: oversized mgmt packet received in "
673 "hostap mode (wi_dat_len=%d, "
674 "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
675 rxlen, letoh16(rx_frame.wi_status)((__uint16_t)(rx_frame.wi_status)));
676 m_freem(m);
677 ifp->if_ierrorsif_data.ifi_ierrors++;
678 return;
679 }
680
681 /* Put the whole header in there. */
682 bcopy(&rx_frame, mtod(m, void *)((void *)((m)->m_hdr.mh_data)),
683 sizeof(struct wi_frame));
684 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, WI_802_11_OFFSET_RAW0x3C,
685 mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + WI_802_11_OFFSET_RAW0x3C,
686 rxlen + 2)) {
687 m_freem(m);
688 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
689 printf("wihap: failed to copy header\n");
690 ifp->if_ierrorsif_data.ifi_ierrors++;
691 return;
692 }
693
694 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len =
695 WI_802_11_OFFSET_RAW0x3C + rxlen;
696
697 /* XXX: consider giving packet to bhp? */
698
699 wihap_mgmt_input(sc, &rx_frame, m);
700
701 return;
702 }
703
704 switch (letoh16(rx_frame.wi_status)((__uint16_t)(rx_frame.wi_status)) & WI_RXSTAT_MSG_TYPE0xE000) {
705 case WI_STAT_10420x2000:
706 case WI_STAT_TUNNEL0x4000:
707 case WI_STAT_WMP_MSG0x6000:
708 if ((letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)) + WI_SNAPHDR_LEN0x6) >
709 maxlen) {
710 printf(WI_PRT_FMT"%s" ": oversized packet received "
711 "(wi_dat_len=%d, wi_status=0x%x)\n",
712 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
713 letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)),
714 letoh16(rx_frame.wi_status)((__uint16_t)(rx_frame.wi_status)));
715 m_freem(m);
716 ifp->if_ierrorsif_data.ifi_ierrors++;
717 return;
718 }
719 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len =
720 letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)) + WI_SNAPHDR_LEN0x6;
721
722 bcopy(&rx_frame.wi_dst_addr,
723 &eh->ether_dhost, ETHER_ADDR_LEN6);
724 bcopy(&rx_frame.wi_src_addr,
725 &eh->ether_shost, ETHER_ADDR_LEN6);
726 bcopy(&rx_frame.wi_type,
727 &eh->ether_type, ETHER_TYPE_LEN2);
728
729 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, WI_802_11_OFFSET0x44,
730 mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + sizeof(struct ether_header),
731 m->m_lenm_hdr.mh_len + 2)) {
732 ifp->if_ierrorsif_data.ifi_ierrors++;
733 m_freem(m);
734 return;
735 }
736 break;
737 default:
738 if ((letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)) +
739 sizeof(struct ether_header)) > maxlen) {
740 printf(WI_PRT_FMT"%s" ": oversized packet received "
741 "(wi_dat_len=%d, wi_status=0x%x)\n",
742 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
743 letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)),
744 letoh16(rx_frame.wi_status)((__uint16_t)(rx_frame.wi_status)));
745 m_freem(m);
746 ifp->if_ierrorsif_data.ifi_ierrors++;
747 return;
748 }
749 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len =
750 letoh16(rx_frame.wi_dat_len)((__uint16_t)(rx_frame.wi_dat_len)) +
751 sizeof(struct ether_header);
752
753 if (wi_read_datasc->sc_funcs->f_read_data(sc, id, WI_802_3_OFFSET0x2E,
754 mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), m->m_lenm_hdr.mh_len + 2)) {
755 m_freem(m);
756 ifp->if_ierrorsif_data.ifi_ierrors++;
757 return;
758 }
759 break;
760 }
761
762 if (sc->wi_use_wep &&
763 rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)((__uint16_t)(0x4000))) {
764 int len;
765
766 switch (sc->wi_crypto_algorithm) {
767 case WI_CRYPTO_FIRMWARE_WEP0x00:
768 break;
769 case WI_CRYPTO_SOFTWARE_WEP0x01:
770 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len,
771 sc->wi_rxbuf);
772 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len -
773 sizeof(struct ether_header);
774 if (wi_do_hostdecrypt(sc, sc->wi_rxbuf +
775 sizeof(struct ether_header), len)) {
776 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
777 printf(WI_PRT_FMT"%s" ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
778 m_freem(m);
779 ifp->if_ierrorsif_data.ifi_ierrors++;
780 return;
781 }
782 len -= IEEE80211_WEP_IVLEN3 +
783 IEEE80211_WEP_KIDLEN1 + IEEE80211_WEP_CRCLEN4;
784 /*
785 * copy data back to mbufs:
786 * we need to ditch the IV & most LLC/SNAP stuff
787 * (except SNAP type, we're going use that to
788 * overwrite the ethertype in the ether_header)
789 */
790 m_copyback(m, sizeof(struct ether_header) -
791 WI_ETHERTYPE_LEN0x2, WI_ETHERTYPE_LEN0x2 +
792 (len - WI_SNAPHDR_LEN0x6),
793 sc->wi_rxbuf + sizeof(struct ether_header) +
794 IEEE80211_WEP_IVLEN3 +
795 IEEE80211_WEP_KIDLEN1 + WI_SNAPHDR_LEN0x6,
796 M_NOWAIT0x0002);
797 m_adj(m, -(WI_ETHERTYPE_LEN0x2 +
798 IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1 +
799 WI_SNAPHDR_LEN0x6));
800 break;
801 }
802 }
803
804 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6) {
805 /*
806 * Give host AP code first crack at data packets.
807 * If it decides to handle it (or drop it), it will
808 * return a non-zero. Otherwise, it is destined for
809 * this host.
810 */
811 if (wihap_data_input(sc, &rx_frame, m))
812 return;
813 }
814 }
815
816 /* Receive packet unless in procframe or monitor mode. */
817 if (sc->wi_procframe || sc->wi_debug.wi_monitor)
818 m_freem(m);
819 else {
820 ml_enqueue(&ml, m);
821 if_input(ifp, &ml);
822 }
823
824 return;
825}
826
827void
828wi_txeof(struct wi_softc *sc, int status)
829{
830 struct ifnet *ifp;
831
832 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
833
834 ifp->if_timer = 0;
835 ifq_clr_oactive(&ifp->if_snd);
836
837 if (status & WI_EV_TX_EXC0x0004)
838 ifp->if_oerrorsif_data.ifi_oerrors++;
839
840 return;
841}
842
843void
844wi_inquire(void *xsc)
845{
846 struct wi_softc *sc;
847 struct ifnet *ifp;
848 int s, rv;
849
850 sc = xsc;
851 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
852
853 timeout_add_sec(&sc->sc_timo, 60);
854
855 /* Don't do this while we're transmitting */
856 if (ifq_is_oactive(&ifp->if_snd))
857 return;
858
859 s = splnet()splraise(0x7);
860 rv = wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_INQUIRE0x0011, WI_INFO_COUNTERS0xF100, 0, 0);
861 splx(s)spllower(s);
862 if (rv)
863 printf(WI_PRT_FMT"%s" ": wi_cmd failed with %d\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
864 rv);
865
866 return;
867}
868
869void
870wi_update_stats(struct wi_softc *sc)
871{
872 struct wi_ltv_gen gen;
873 u_int16_t id;
874 struct ifnet *ifp;
875 u_int32_t *ptr;
876 int len, i;
877 u_int16_t t;
878
879 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
880
881 id = wi_get_fidsc->sc_funcs->f_get_fid(sc, WI_INFO_FID0x10);
882
883 wi_read_datasc->sc_funcs->f_read_data(sc, id, 0, (char *)&gen, 4);
884
885 if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)((__uint16_t)(0xF101))) {
886 sc->wi_scanbuf_len = letoh16(gen.wi_len)((__uint16_t)(gen.wi_len));
887 wi_read_datasc->sc_funcs->f_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
888 sc->wi_scanbuf_len * 2);
889 return;
890 } else if (gen.wi_type != htole16(WI_INFO_COUNTERS)((__uint16_t)(0xF100)))
891 return;
892
893 /* Some card versions have a larger stats structure */
894 len = (letoh16(gen.wi_len)((__uint16_t)(gen.wi_len)) - 1 < sizeof(sc->wi_stats) / 4) ?
895 letoh16(gen.wi_len)((__uint16_t)(gen.wi_len)) - 1 : sizeof(sc->wi_stats) / 4;
896
897 ptr = (u_int32_t *)&sc->wi_stats;
898
899 for (i = 0; i < len; i++) {
900 if (sc->wi_flags & WI_FLAGS_BUS_USB0x0400) {
901 wi_read_datasc->sc_funcs->f_read_data(sc, id, 4 + i*2, (char *)&t, 2);
902 t = letoh16(t)((__uint16_t)(t));
903 } else
904 t = CSR_READ_2(sc, WI_DATA1)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x38 * 2: 0x38))))
;
905#ifdef WI_HERMES_STATS_WAR
906 if (t > 0xF000)
907 t = ~t & 0xFFFF;
908#endif
909 ptr[i] += t;
910 }
911
912 ifp->if_collisionsif_data.ifi_collisions = sc->wi_stats.wi_tx_single_retries +
913 sc->wi_stats.wi_tx_multi_retries +
914 sc->wi_stats.wi_tx_retry_limit;
915
916 return;
917}
918
919STATIC int
920wi_cmd_io(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
921{
922 int i, s = 0;
923
924 /* Wait for the busy bit to clear. */
925 for (i = sc->wi_cmd_count; i--; DELAY(1000)(*delay_func)(1000)) {
926 if (!(CSR_READ_2(sc, WI_COMMAND)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x00 * 2: 0x00))))
& WI_CMD_BUSY0x8000))
927 break;
928 }
929 if (i < 0) {
930 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
931 printf(WI_PRT_FMT"%s" ": wi_cmd_io: busy bit won't clear\n",
932 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
933 return(ETIMEDOUT60);
934 }
935
936 CSR_WRITE_2(sc, WI_PARAM0, val0)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x02 * 2: 0x02)), ((val0))))
;
937 CSR_WRITE_2(sc, WI_PARAM1, val1)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x04 * 2: 0x04)), ((val1))))
;
938 CSR_WRITE_2(sc, WI_PARAM2, val2)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x06 * 2: 0x06)), ((val2))))
;
939 CSR_WRITE_2(sc, WI_COMMAND, cmd)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x00 * 2: 0x00)), ((cmd))))
;
940
941 for (i = WI_TIMEOUT(500000/5); i--; DELAY(WI_DELAY)(*delay_func)(5)) {
942 /*
943 * Wait for 'command complete' bit to be
944 * set in the event status register.
945 */
946 s = CSR_READ_2(sc, WI_EVENT_STAT)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x30 * 2: 0x30))))
& WI_EV_CMD0x0010;
947 if (s) {
948 /* Ack the event and read result code. */
949 s = CSR_READ_2(sc, WI_STATUS)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x08 * 2: 0x08))))
;
950 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0010))))
;
951 if (s & WI_STAT_CMD_RESULT0x7F00)
952 return(EIO5);
953 break;
954 }
955 }
956
957 if (i < 0) {
958 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
959 printf(WI_PRT_FMT"%s"
960 ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
961 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname, cmd, s);
962 return(ETIMEDOUT60);
963 }
964
965 return(0);
966}
967
968STATIC void
969wi_reset(struct wi_softc *sc)
970{
971 int error, tries = 3;
972
973 DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
974
975 /* Symbol firmware cannot be initialized more than once. */
976 if (sc->sc_firmware_type == WI_SYMBOL3) {
977 if (sc->wi_flags & WI_FLAGS_INITIALIZED0x0002)
978 return;
979 tries = 1;
980 }
981
982 for (; tries--; DELAY(WI_DELAY * 1000)(*delay_func)(5 * 1000)) {
983 if ((error = wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_INI0x0000, 0, 0, 0)) == 0)
984 break;
985 }
986 if (tries < 0) {
987 printf(WI_PRT_FMT"%s" ": init failed\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
988 return;
989 }
990 sc->wi_flags |= WI_FLAGS_INITIALIZED0x0002;
991
992 wi_intr_enable(sc, 0);
993 wi_intr_ack(sc, 0xffff);
994
995 /* Calibrate timer. */
996 WI_SETVAL(WI_RID_TICK_TIME, 8)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFCE0; g
.wi_val = ((__uint16_t)(8)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
997
998 return;
999}
1000
1001STATIC void
1002wi_cor_reset(struct wi_softc *sc)
1003{
1004 u_int8_t cor_value;
1005
1006 DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
1007
1008 /*
1009 * Do a soft reset of the card; this is required for Symbol cards.
1010 * This shouldn't hurt other cards but there have been reports
1011 * of the COR reset messing up old Lucent firmware revisions so
1012 * we avoid soft reset on Lucent cards for now.
1013 */
1014 if (sc->sc_firmware_type != WI_LUCENT1) {
1015 cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,((sc->wi_ltag)->read_1((sc->wi_lhandle), (sc->wi_cor_offset
)))
1016 sc->wi_cor_offset)((sc->wi_ltag)->read_1((sc->wi_lhandle), (sc->wi_cor_offset
)))
;
1017 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,((sc->wi_ltag)->write_1((sc->wi_lhandle), (sc->wi_cor_offset
), ((cor_value | (1 << 7)))))
1018 sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET))((sc->wi_ltag)->write_1((sc->wi_lhandle), (sc->wi_cor_offset
), ((cor_value | (1 << 7)))))
;
1019 DELAY(1000)(*delay_func)(1000);
1020 bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,((sc->wi_ltag)->write_1((sc->wi_lhandle), (sc->wi_cor_offset
), ((cor_value & ~(1 << 7)))))
1021 sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET))((sc->wi_ltag)->write_1((sc->wi_lhandle), (sc->wi_cor_offset
), ((cor_value & ~(1 << 7)))))
;
1022 DELAY(1000)(*delay_func)(1000);
1023 }
1024
1025 return;
1026}
1027
1028/*
1029 * Read an LTV record from the NIC.
1030 */
1031STATIC int
1032wi_read_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1033{
1034 u_int8_t *ptr;
1035 int len, code;
1036 struct wi_ltv_gen *oltv, p2ltv;
1037
1038 if (sc->sc_firmware_type != WI_LUCENT1) {
1039 oltv = ltv;
1040 switch (ltv->wi_type) {
1041 case WI_RID_ENCRYPTION0xFC20:
1042 p2ltv.wi_type = WI_RID_P2_ENCRYPTION0xFC28;
1043 p2ltv.wi_len = 2;
1044 ltv = &p2ltv;
1045 break;
1046 case WI_RID_TX_CRYPT_KEY0xFCB1:
1047 if (ltv->wi_val > WI_NLTV_KEYS4)
1048 return (EINVAL22);
1049 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY0xFC23;
1050 p2ltv.wi_len = 2;
1051 ltv = &p2ltv;
1052 break;
1053 }
1054 }
1055
1056 /* Tell the NIC to enter record read mode. */
1057 if (wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_ACCESS0x0021|WI_ACCESS_READ0x0000, ltv->wi_type, 0, 0))
1058 return(EIO5);
1059
1060 /* Seek to the record. */
1061 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP10x38))
1062 return(EIO5);
1063
1064 /*
1065 * Read the length and record type and make sure they
1066 * match what we expect (this verifies that we have enough
1067 * room to hold all of the returned data).
1068 */
1069 len = CSR_READ_2(sc, WI_DATA1)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x38 * 2: 0x38))))
;
1070 if (len > ltv->wi_len)
1071 return(ENOSPC28);
1072 code = CSR_READ_2(sc, WI_DATA1)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x38 * 2: 0x38))))
;
1073 if (code != ltv->wi_type)
1074 return(EIO5);
1075
1076 ltv->wi_len = len;
1077 ltv->wi_type = code;
1078
1079 /* Now read the data. */
1080 ptr = (u_int8_t *)&ltv->wi_val;
1081 if (ltv->wi_len > 1)
1082 CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2)(((sc)->wi_btag)->read_multi_2(((sc)->wi_bhandle), (
(sc->sc_pci? 0x38 * 2: 0x38)), (u_int16_t *)((ptr)), (((ltv
->wi_len-1)*2)) >> 1))
;
1083
1084 if (ltv->wi_type == WI_RID_PORTTYPE0xFC00 && sc->wi_ptype == WI_PORTTYPE_IBSS0x4
1085 && ltv->wi_val == sc->wi_ibss_port) {
1086 /*
1087 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1088 * Since Lucent uses port type 1 for BSS *and* IBSS we
1089 * have to rely on wi_ptype to distinguish this for us.
1090 */
1091 ltv->wi_val = htole16(WI_PORTTYPE_IBSS)((__uint16_t)(0x4));
1092 } else if (sc->sc_firmware_type != WI_LUCENT1) {
1093 int v;
1094
1095 switch (oltv->wi_type) {
1096 case WI_RID_TX_RATE0xFC84:
1097 case WI_RID_CUR_TX_RATE0xFD44:
1098 switch (letoh16(ltv->wi_val)((__uint16_t)(ltv->wi_val))) {
1099 case 1: v = 1; break;
1100 case 2: v = 2; break;
1101 case 3: v = 6; break;
1102 case 4: v = 5; break;
1103 case 7: v = 7; break;
1104 case 8: v = 11; break;
1105 case 15: v = 3; break;
1106 default: v = 0x100 + letoh16(ltv->wi_val)((__uint16_t)(ltv->wi_val)); break;
1107 }
1108 oltv->wi_val = htole16(v)((__uint16_t)(v));
1109 break;
1110 case WI_RID_ENCRYPTION0xFC20:
1111 oltv->wi_len = 2;
1112 if (ltv->wi_val & htole16(0x01)((__uint16_t)(0x01)))
1113 oltv->wi_val = htole16(1)((__uint16_t)(1));
1114 else
1115 oltv->wi_val = htole16(0)((__uint16_t)(0));
1116 break;
1117 case WI_RID_TX_CRYPT_KEY0xFCB1:
1118 case WI_RID_CNFAUTHMODE0xFC2A:
1119 oltv->wi_len = 2;
1120 oltv->wi_val = ltv->wi_val;
1121 break;
1122 }
1123 }
1124
1125 return(0);
1126}
1127
1128/*
1129 * Same as read, except we inject data instead of reading it.
1130 */
1131STATIC int
1132wi_write_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1133{
1134 u_int8_t *ptr;
1135 u_int16_t val = 0;
1136 int i;
1137 struct wi_ltv_gen p2ltv;
1138
1139 if (ltv->wi_type == WI_RID_PORTTYPE0xFC00 &&
1140 letoh16(ltv->wi_val)((__uint16_t)(ltv->wi_val)) == WI_PORTTYPE_IBSS0x4) {
1141 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1142 p2ltv.wi_type = WI_RID_PORTTYPE0xFC00;
1143 p2ltv.wi_len = 2;
1144 p2ltv.wi_val = sc->wi_ibss_port;
1145 ltv = &p2ltv;
1146 } else if (sc->sc_firmware_type != WI_LUCENT1) {
1147 int v;
1148
1149 switch (ltv->wi_type) {
1150 case WI_RID_TX_RATE0xFC84:
1151 p2ltv.wi_type = WI_RID_TX_RATE0xFC84;
1152 p2ltv.wi_len = 2;
1153 switch (letoh16(ltv->wi_val)((__uint16_t)(ltv->wi_val))) {
1154 case 1: v = 1; break;
1155 case 2: v = 2; break;
1156 case 3: v = 15; break;
1157 case 5: v = 4; break;
1158 case 6: v = 3; break;
1159 case 7: v = 7; break;
1160 case 11: v = 8; break;
1161 default: return EINVAL22;
1162 }
1163 p2ltv.wi_val = htole16(v)((__uint16_t)(v));
1164 ltv = &p2ltv;
1165 break;
1166 case WI_RID_ENCRYPTION0xFC20:
1167 p2ltv.wi_type = WI_RID_P2_ENCRYPTION0xFC28;
1168 p2ltv.wi_len = 2;
1169 if (ltv->wi_val & htole16(0x01)((__uint16_t)(0x01))) {
1170 val = PRIVACY_INVOKED0x01;
1171 /*
1172 * If using shared key WEP we must set the
1173 * EXCLUDE_UNENCRYPTED bit. Symbol cards
1174 * need this bit set even when not using
1175 * shared key. We can't just test for
1176 * IEEE80211_AUTH_SHARED since Symbol cards
1177 * have 2 shared key modes.
1178 */
1179 if (sc->wi_authtype != IEEE80211_AUTH_OPEN1 ||
1180 sc->sc_firmware_type == WI_SYMBOL3)
1181 val |= EXCLUDE_UNENCRYPTED0x02;
1182
1183 switch (sc->wi_crypto_algorithm) {
1184 case WI_CRYPTO_FIRMWARE_WEP0x00:
1185 /*
1186 * TX encryption is broken in
1187 * Host AP mode.
1188 */
1189 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6)
1190 val |= HOST_ENCRYPT0x10;
1191 break;
1192 case WI_CRYPTO_SOFTWARE_WEP0x01:
1193 val |= HOST_ENCRYPT0x10|HOST_DECRYPT0x80;
1194 break;
1195 }
1196 p2ltv.wi_val = htole16(val)((__uint16_t)(val));
1197 } else
1198 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT)((__uint16_t)(0x10 | 0x80));
1199 ltv = &p2ltv;
1200 break;
1201 case WI_RID_TX_CRYPT_KEY0xFCB1:
1202 if (ltv->wi_val > WI_NLTV_KEYS4)
1203 return (EINVAL22);
1204 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY0xFC23;
1205 p2ltv.wi_len = 2;
1206 p2ltv.wi_val = ltv->wi_val;
1207 ltv = &p2ltv;
1208 break;
1209 case WI_RID_DEFLT_CRYPT_KEYS0xFCB0: {
1210 int error;
1211 int keylen;
1212 struct wi_ltv_str ws;
1213 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1214
1215 keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1216 keylen = letoh16(keylen)((__uint16_t)(keylen));
1217
1218 for (i = 0; i < 4; i++) {
1219 bzero(&ws, sizeof(ws))__builtin_bzero((&ws), (sizeof(ws)));
1220 ws.wi_len = (keylen > 5) ? 8 : 4;
1221 ws.wi_type = WI_RID_P2_CRYPT_KEY00xFC24 + i;
1222 bcopy(&wk->wi_keys[i].wi_keydat,
1223 ws.wi_str, keylen);
1224 error = wi_write_recordsc->sc_funcs->f_write_record(sc,
1225 (struct wi_ltv_gen *)&ws);
1226 if (error)
1227 return (error);
1228 }
1229 }
1230 return (0);
1231 }
1232 }
1233
1234 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP10x38))
1235 return(EIO5);
1236
1237 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x38 * 2: 0x38)), ((ltv->wi_len))))
;
1238 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x38 * 2: 0x38)), ((ltv->wi_type))))
;
1239
1240 ptr = (u_int8_t *)&ltv->wi_val;
1241 if (ltv->wi_len > 1)
1242 CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2)(((sc)->wi_btag)->write_multi_2(((sc)->wi_bhandle), (
(sc->sc_pci? 0x38 * 2: 0x38)), (const u_int16_t *)((ptr)),
(((ltv->wi_len-1) *2)) >> 1))
;
1243
1244 if (wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_ACCESS0x0021|WI_ACCESS_WRITE0x0100, ltv->wi_type, 0, 0))
1245 return(EIO5);
1246
1247 return(0);
1248}
1249
1250STATIC int
1251wi_seek(struct wi_softc *sc, int id, int off, int chan)
1252{
1253 int i;
1254 int selreg, offreg;
1255
1256 switch (chan) {
1257 case WI_BAP00x36:
1258 selreg = WI_SEL00x18;
1259 offreg = WI_OFF00x1C;
1260 break;
1261 case WI_BAP10x38:
1262 selreg = WI_SEL10x1A;
1263 offreg = WI_OFF10x1E;
1264 break;
1265 default:
1266 printf(WI_PRT_FMT"%s" ": invalid data path: %x\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
1267 chan);
1268 return(EIO5);
1269 }
1270
1271 CSR_WRITE_2(sc, selreg, id)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? selreg * 2: selreg)), ((id))))
;
1272 CSR_WRITE_2(sc, offreg, off)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? offreg * 2: offreg)), ((off))))
;
1273
1274 for (i = WI_TIMEOUT(500000/5); i--; DELAY(1)(*delay_func)(1))
1275 if (!(CSR_READ_2(sc, offreg)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? offreg * 2: offreg))))
& (WI_OFF_BUSY0x8000|WI_OFF_ERR0x4000)))
1276 break;
1277
1278 if (i < 0)
1279 return(ETIMEDOUT60);
1280
1281 return(0);
1282}
1283
1284STATIC int
1285wi_read_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1286{
1287 u_int8_t *ptr;
1288
1289 if (wi_seek(sc, id, off, WI_BAP10x38))
1290 return(EIO5);
1291
1292 ptr = (u_int8_t *)buf;
1293 CSR_READ_RAW_2(sc, WI_DATA1, ptr, len)(((sc)->wi_btag)->read_multi_2(((sc)->wi_bhandle), (
(sc->sc_pci? 0x38 * 2: 0x38)), (u_int16_t *)((ptr)), ((len
)) >> 1))
;
1294
1295 return(0);
1296}
1297
1298/*
1299 * According to the comments in the HCF Light code, there is a bug in
1300 * the Hermes (or possibly in certain Hermes firmware revisions) where
1301 * the chip's internal autoincrement counter gets thrown off during
1302 * data writes: the autoincrement is missed, causing one data word to
1303 * be overwritten and subsequent words to be written to the wrong memory
1304 * locations. The end result is that we could end up transmitting bogus
1305 * frames without realizing it. The workaround for this is to write a
1306 * couple of extra guard words after the end of the transfer, then
1307 * attempt to read then back. If we fail to locate the guard words where
1308 * we expect them, we preform the transfer over again.
1309 */
1310STATIC int
1311wi_write_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1312{
1313 u_int8_t *ptr;
1314
1315#ifdef WI_HERMES_AUTOINC_WAR
1316again:
1317#endif
1318
1319 if (wi_seek(sc, id, off, WI_BAP00x36))
1320 return(EIO5);
1321
1322 ptr = (u_int8_t *)buf;
1323 CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len)(((sc)->wi_btag)->write_multi_2(((sc)->wi_bhandle), (
(sc->sc_pci? 0x36 * 2: 0x36)), (const u_int16_t *)((ptr)),
((len)) >> 1))
;
1324
1325#ifdef WI_HERMES_AUTOINC_WAR
1326 CSR_WRITE_2(sc, WI_DATA0, 0x1234)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x36 * 2: 0x36)), ((0x1234))))
;
1327 CSR_WRITE_2(sc, WI_DATA0, 0x5678)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x36 * 2: 0x36)), ((0x5678))))
;
1328
1329 if (wi_seek(sc, id, off + len, WI_BAP00x36))
1330 return(EIO5);
1331
1332 if (CSR_READ_2(sc, WI_DATA0)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x36 * 2: 0x36))))
!= 0x1234 ||
1333 CSR_READ_2(sc, WI_DATA0)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x36 * 2: 0x36))))
!= 0x5678)
1334 goto again;
1335#endif
1336
1337 return(0);
1338}
1339
1340/*
1341 * Allocate a region of memory inside the NIC and zero
1342 * it out.
1343 */
1344STATIC int
1345wi_alloc_nicmem_io(struct wi_softc *sc, int len, int *id)
1346{
1347 int i;
1348
1349 if (wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_ALLOC_MEM0x000A, len, 0, 0)) {
1350 printf(WI_PRT_FMT"%s" ": failed to allocate %d bytes on NIC\n",
1351 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname, len);
1352 return(ENOMEM12);
1353 }
1354
1355 for (i = WI_TIMEOUT(500000/5); i--; DELAY(1)(*delay_func)(1)) {
1356 if (CSR_READ_2(sc, WI_EVENT_STAT)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x30 * 2: 0x30))))
& WI_EV_ALLOC0x0008)
1357 break;
1358 }
1359
1360 if (i < 0)
1361 return(ETIMEDOUT60);
1362
1363 *id = CSR_READ_2(sc, WI_ALLOC_FID)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x22 * 2: 0x22))))
;
1364 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x34 * 2: 0x34)), ((0x0008))))
;
1365
1366 if (wi_seek(sc, *id, 0, WI_BAP00x36))
1367 return(EIO5);
1368
1369 for (i = 0; i < len / 2; i++)
1370 CSR_WRITE_2(sc, WI_DATA0, 0)((sc->wi_btag)->write_2((sc->wi_bhandle), ((sc->sc_pci
? 0x36 * 2: 0x36)), ((0))))
;
1371
1372 return(0);
1373}
1374
1375STATIC void
1376wi_setmulti(struct wi_softc *sc)
1377{
1378 struct arpcom *ac = &sc->sc_ic.ic_ac;
1379 struct ifnet *ifp;
1380 int i = 0;
1381 struct wi_ltv_mcast mcast;
1382 struct ether_multistep step;
1383 struct ether_multi *enm;
1384
1385 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1386
1387 bzero(&mcast, sizeof(mcast))__builtin_bzero((&mcast), (sizeof(mcast)));
1388
1389 mcast.wi_type = WI_RID_MCAST_LIST0xFC80;
1390 mcast.wi_len = ((ETHER_ADDR_LEN6 / 2) * 16) + 1;
1391
1392 if (ac->ac_multirangecnt > 0)
1393 ifp->if_flags |= IFF_ALLMULTI0x200;
1394
1395 if (ifp->if_flags & IFF_ALLMULTI0x200 || ifp->if_flags & IFF_PROMISC0x100) {
1396 wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&mcast);
1397 return;
1398 }
1399
1400 ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ac, enm)do { (step).e_enm = ((&(&sc->sc_ic.ic_ac)->ac_multiaddrs
)->lh_first); do { if ((((enm)) = ((step)).e_enm) != ((void
*)0)) ((step)).e_enm = ((((enm)))->enm_list.le_next); } while
( 0); } while ( 0)
;
1401 while (enm != NULL((void *)0)) {
1402 if (i >= 16) {
1403 bzero(&mcast, sizeof(mcast))__builtin_bzero((&mcast), (sizeof(mcast)));
1404 break;
1405 }
1406
1407 bcopy(enm->enm_addrlo, &mcast.wi_mcast[i], ETHER_ADDR_LEN6);
1408 i++;
1409 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
1410 }
1411
1412 mcast.wi_len = (i * 3) + 1;
1413 wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&mcast);
1414
1415 return;
1416}
1417
1418STATIC int
1419wi_setdef(struct wi_softc *sc, struct wi_req *wreq)
1420{
1421 struct ifnet *ifp;
1422 int error = 0;
1423
1424 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1425
1426 switch(wreq->wi_type) {
1427 case WI_RID_MAC_NODE0xFC01:
1428 bcopy(&wreq->wi_val, LLADDR(ifp->if_sadl)((caddr_t)((ifp->if_sadl)->sdl_data + (ifp->if_sadl)
->sdl_nlen))
, ETHER_ADDR_LEN6);
1429 bcopy(&wreq->wi_val, &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN6);
1430 break;
1431 case WI_RID_PORTTYPE0xFC00:
1432 error = wi_sync_media(sc, letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])),
1433 sc->wi_tx_rate);
1434 break;
1435 case WI_RID_TX_RATE0xFC84:
1436 error = wi_sync_media(sc, sc->wi_ptype,
1437 letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1438 break;
1439 case WI_RID_MAX_DATALEN0xFC07:
1440 sc->wi_max_data_len = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1441 break;
1442 case WI_RID_RTS_THRESH0xFC83:
1443 sc->wi_rts_thresh = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1444 break;
1445 case WI_RID_SYSTEM_SCALE0xFC06:
1446 sc->wi_ap_density = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1447 break;
1448 case WI_RID_CREATE_IBSS0xFC81:
1449 sc->wi_create_ibss = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1450 error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1451 break;
1452 case WI_RID_OWN_CHNL0xFC03:
1453 sc->wi_channel = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1454 break;
1455 case WI_RID_NODENAME0xFC0E:
1456 error = wi_set_ssid(&sc->wi_node_name,
1457 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1458 break;
1459 case WI_RID_DESIRED_SSID0xFC02:
1460 error = wi_set_ssid(&sc->wi_net_name,
1461 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1462 break;
1463 case WI_RID_OWN_SSID0xFC04:
1464 error = wi_set_ssid(&sc->wi_ibss_name,
1465 (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1466 break;
1467 case WI_RID_PM_ENABLED0xFC09:
1468 sc->wi_pm_enabled = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1469 break;
1470 case WI_RID_MICROWAVE_OVEN0xFC25:
1471 sc->wi_mor_enabled = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1472 break;
1473 case WI_RID_MAX_SLEEP0xFC0C:
1474 sc->wi_max_sleep = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1475 break;
1476 case WI_RID_CNFAUTHMODE0xFC2A:
1477 sc->wi_authtype = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1478 break;
1479 case WI_RID_ROAMING_MODE0xFC2D:
1480 sc->wi_roaming = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1481 break;
1482 case WI_RID_SYMBOL_DIVERSITY0xFC87:
1483 sc->wi_diversity = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1484 break;
1485 case WI_RID_ENH_SECURITY0xFC43:
1486 sc->wi_enh_security = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1487 break;
1488 case WI_RID_ENCRYPTION0xFC20:
1489 sc->wi_use_wep = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1490 break;
1491 case WI_RID_TX_CRYPT_KEY0xFCB1:
1492 sc->wi_tx_key = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1493 break;
1494 case WI_RID_DEFLT_CRYPT_KEYS0xFCB0:
1495 bcopy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1496 break;
1497 case WI_FRID_CRYPTO_ALG0xFCE3:
1498 switch (letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]))) {
1499 case WI_CRYPTO_FIRMWARE_WEP0x00:
1500 sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP0x00;
1501 break;
1502 case WI_CRYPTO_SOFTWARE_WEP0x01:
1503 sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP0x01;
1504 break;
1505 default:
1506 printf(WI_PRT_FMT"%s" ": unsupported crypto algorithm %d\n",
1507 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname, letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1508 error = EINVAL22;
1509 }
1510 break;
1511 default:
1512 error = EINVAL22;
1513 break;
1514 }
1515
1516 return (error);
1517}
1518
1519STATIC int
1520wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1521{
1522 int s, error = 0, i, j, len;
1523 struct wi_softc *sc = ifp->if_softc;
1524 struct ifreq *ifr = (struct ifreq *)data;
1525 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
1526 struct wi_scan_res *res;
1527 struct wi_scan_p2_hdr *p2;
1528 struct wi_req *wreq = NULL((void *)0);
1529 u_int32_t flags;
1530 struct ieee80211_nwid *nwidp = NULL((void *)0);
1531 struct ieee80211_nodereq_all *na;
1532 struct ieee80211_bssid *bssid;
1533
1534 s = splnet()splraise(0x7);
1535 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001)) {
1536 error = ENODEV19;
1537 goto fail;
1538 }
1539
1540 /*
1541 * Prevent processes from entering this function while another
1542 * process is tsleep'ing in it.
1543 */
1544 while ((sc->wi_flags & WI_FLAGS_BUSY0x2000) && error == 0)
1545 error = tsleep_nsec(&sc->wi_flags, PCATCH0x100, "wiioc", INFSLP0xffffffffffffffffULL);
1546 if (error != 0) {
1547 splx(s)spllower(s);
1548 return error;
1549 }
1550 sc->wi_flags |= WI_FLAGS_BUSY0x2000;
1551
1552
1553 DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1554 command, data));
1555
1556 switch(command) {
1557 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1558 ifp->if_flags |= IFF_UP0x1;
1559 wi_initsc->sc_funcs->f_init(sc);
1560 break;
1561 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1562 if (ifp->if_flags & IFF_UP0x1) {
1563 if (ifp->if_flags & IFF_RUNNING0x40 &&
1564 ifp->if_flags & IFF_PROMISC0x100 &&
1565 !(sc->wi_if_flags & IFF_PROMISC0x100)) {
1566 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP0x6)
1567 WI_SETVAL(WI_RID_PROMISC, 1)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC85; g
.wi_val = ((__uint16_t)(1)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
1568 } else if (ifp->if_flags & IFF_RUNNING0x40 &&
1569 !(ifp->if_flags & IFF_PROMISC0x100) &&
1570 sc->wi_if_flags & IFF_PROMISC0x100) {
1571 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP0x6)
1572 WI_SETVAL(WI_RID_PROMISC, 0)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC85; g
.wi_val = ((__uint16_t)(0)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
1573 } else
1574 wi_initsc->sc_funcs->f_init(sc);
1575 } else if (ifp->if_flags & IFF_RUNNING0x40)
1576 wi_stop(sc);
1577 sc->wi_if_flags = ifp->if_flags;
1578 error = 0;
1579 break;
1580 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
1581 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
1582 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1583 break;
1584 case SIOCGWAVELAN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((207)))
:
1585 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1586 error = copyin(ifr->ifr_dataifr_ifru.ifru_data, wreq, sizeof(*wreq));
1587 if (error)
1588 break;
1589 if (wreq->wi_len > WI_MAX_DATALEN512) {
1590 error = EINVAL22;
1591 break;
1592 }
1593 switch (wreq->wi_type) {
1594 case WI_RID_IFACE_STATS0x0100:
1595 /* XXX native byte order */
1596 bcopy(&sc->wi_stats, &wreq->wi_val,
1597 sizeof(sc->wi_stats));
1598 wreq->wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1599 break;
1600 case WI_RID_DEFLT_CRYPT_KEYS0xFCB0:
1601 /* For non-root user, return all-zeroes keys */
1602 if (suser(p))
1603 bzero(wreq, sizeof(struct wi_ltv_keys))__builtin_bzero((wreq), (sizeof(struct wi_ltv_keys)));
1604 else
1605 bcopy(&sc->wi_keys, wreq,
1606 sizeof(struct wi_ltv_keys));
1607 break;
1608 case WI_RID_PROCFRAME0x3137:
1609 wreq->wi_len = 2;
1610 wreq->wi_val[0] = htole16(sc->wi_procframe)((__uint16_t)(sc->wi_procframe));
1611 break;
1612 case WI_RID_PRISM20x3138:
1613 wreq->wi_len = 2;
1614 wreq->wi_val[0] = htole16(sc->sc_firmware_type ==((__uint16_t)(sc->sc_firmware_type == 1 ? 0 : 1))
1615 WI_LUCENT ? 0 : 1)((__uint16_t)(sc->sc_firmware_type == 1 ? 0 : 1));
1616 break;
1617 case WI_FRID_CRYPTO_ALG0xFCE3:
1618 wreq->wi_val[0] =
1619 htole16((u_int16_t)sc->wi_crypto_algorithm)((__uint16_t)((u_int16_t)sc->wi_crypto_algorithm));
1620 wreq->wi_len = 1;
1621 break;
1622 case WI_RID_SCAN_RES0xFD88:
1623 if (sc->sc_firmware_type == WI_LUCENT1) {
1624 memcpy((char *)wreq->wi_val,__builtin_memcpy(((char *)wreq->wi_val), ((char *)sc->wi_scanbuf
), (sc->wi_scanbuf_len * 2))
1625 (char *)sc->wi_scanbuf,__builtin_memcpy(((char *)wreq->wi_val), ((char *)sc->wi_scanbuf
), (sc->wi_scanbuf_len * 2))
1626 sc->wi_scanbuf_len * 2)__builtin_memcpy(((char *)wreq->wi_val), ((char *)sc->wi_scanbuf
), (sc->wi_scanbuf_len * 2))
;
1627 wreq->wi_len = sc->wi_scanbuf_len;
1628 break;
1629 }
1630 /* FALLTHROUGH */
1631 default:
1632 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1633 error = EINVAL22;
1634 }
1635 break;
1636 }
1637 error = copyout(wreq, ifr->ifr_dataifr_ifru.ifru_data, sizeof(*wreq));
1638 break;
1639 case SIOCSWAVELAN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((206)))
:
1640 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1641 break;
1642 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1643 error = copyin(ifr->ifr_dataifr_ifru.ifru_data, wreq, sizeof(*wreq));
1644 if (error)
1645 break;
1646 error = EINVAL22;
1647 if (wreq->wi_len > WI_MAX_DATALEN512)
1648 break;
1649 switch (wreq->wi_type) {
1650 case WI_RID_IFACE_STATS0x0100:
1651 break;
1652 case WI_RID_MGMT_XMIT0x0200:
1653 error = wi_mgmt_xmit(sc, (caddr_t)&wreq->wi_val,
1654 wreq->wi_len);
1655 break;
1656 case WI_RID_PROCFRAME0x3137:
1657 sc->wi_procframe = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1658 error = 0;
1659 break;
1660 case WI_RID_SCAN_REQ0xFCE1:
1661 error = 0;
1662 if (sc->sc_firmware_type == WI_LUCENT1)
1663 wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_INQUIRE0x0011,
1664 WI_INFO_SCAN_RESULTS0xF101, 0, 0);
1665 else
1666 error = wi_write_recordsc->sc_funcs->f_write_record(sc,
1667 (struct wi_ltv_gen *)wreq);
1668 break;
1669 case WI_FRID_CRYPTO_ALG0xFCE3:
1670 if (sc->sc_firmware_type != WI_LUCENT1) {
1671 error = wi_setdef(sc, wreq);
1672 if (!error && (ifp->if_flags & IFF_UP0x1))
1673 wi_initsc->sc_funcs->f_init(sc);
1674 }
1675 break;
1676 case WI_RID_SYMBOL_DIVERSITY0xFC87:
1677 case WI_RID_ROAMING_MODE0xFC2D:
1678 case WI_RID_CREATE_IBSS0xFC81:
1679 case WI_RID_MICROWAVE_OVEN0xFC25:
1680 case WI_RID_OWN_SSID0xFC04:
1681 case WI_RID_ENH_SECURITY0xFC43:
1682 /*
1683 * Check for features that may not be supported
1684 * (must be just before default case).
1685 */
1686 if ((wreq->wi_type == WI_RID_SYMBOL_DIVERSITY0xFC87 &&
1687 !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY0x0080)) ||
1688 (wreq->wi_type == WI_RID_ROAMING_MODE0xFC2D &&
1689 !(sc->wi_flags & WI_FLAGS_HAS_ROAMING0x0040)) ||
1690 (wreq->wi_type == WI_RID_CREATE_IBSS0xFC81 &&
1691 !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010)) ||
1692 (wreq->wi_type == WI_RID_MICROWAVE_OVEN0xFC25 &&
1693 !(sc->wi_flags & WI_FLAGS_HAS_MOR0x0020)) ||
1694 (wreq->wi_type == WI_RID_ENH_SECURITY0xFC43 &&
1695 !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY0x0800)) ||
1696 (wreq->wi_type == WI_RID_OWN_SSID0xFC04 &&
1697 wreq->wi_len != 0))
1698 break;
1699 /* FALLTHROUGH */
1700 default:
1701 error = wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)wreq);
1702 if (!error)
1703 error = wi_setdef(sc, wreq);
1704 if (!error && (ifp->if_flags & IFF_UP0x1))
1705 wi_initsc->sc_funcs->f_init(sc);
1706 }
1707 break;
1708 case SIOCGPRISM2DEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((138)))
:
1709 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1710 error = copyin(ifr->ifr_dataifr_ifru.ifru_data, wreq, sizeof(*wreq));
1711 if (error)
1712 break;
1713 if (!(ifp->if_flags & IFF_RUNNING0x40) ||
1714 sc->sc_firmware_type == WI_LUCENT1) {
1715 error = EIO5;
1716 break;
1717 }
1718 error = wi_get_debug(sc, wreq);
1719 if (error == 0)
1720 error = copyout(wreq, ifr->ifr_dataifr_ifru.ifru_data, sizeof(*wreq));
1721 break;
1722 case SIOCSPRISM2DEBUG((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((137)))
:
1723 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1724 break;
1725 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1726 error = copyin(ifr->ifr_dataifr_ifru.ifru_data, wreq, sizeof(*wreq));
1727 if (error)
1728 break;
1729 error = wi_set_debug(sc, wreq);
1730 break;
1731 case SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((231)))
:
1732 if ((ifp->if_flags & IFF_UP0x1) && sc->wi_net_name.i_len > 0) {
1733 /* Return the desired ID */
1734 error = copyout(&sc->wi_net_name, ifr->ifr_dataifr_ifru.ifru_data,
1735 sizeof(sc->wi_net_name));
1736 } else {
1737 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
1738 wreq->wi_type = WI_RID_CURRENT_SSID0xFD41;
1739 wreq->wi_len = WI_MAX_DATALEN512;
1740 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq) ||
1741 letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])) > IEEE80211_NWID_LEN32)
1742 error = EINVAL22;
1743 else {
1744 nwidp = malloc(sizeof *nwidp, M_DEVBUF2,
1745 M_WAITOK0x0001 | M_ZERO0x0008);
1746 wi_set_ssid(nwidp, (u_int8_t *)&wreq->wi_val[1],
1747 letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0])));
1748 error = copyout(nwidp, ifr->ifr_dataifr_ifru.ifru_data,
1749 sizeof(*nwidp));
1750 }
1751 }
1752 break;
1753 case SIOCS80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((230)))
:
1754 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1755 break;
1756 nwidp = malloc(sizeof *nwidp, M_DEVBUF2, M_WAITOK0x0001);
1757 error = copyin(ifr->ifr_dataifr_ifru.ifru_data, nwidp, sizeof(*nwidp));
1758 if (error)
1759 break;
1760 if (nwidp->i_len > IEEE80211_NWID_LEN32) {
1761 error = EINVAL22;
1762 break;
1763 }
1764 if (sc->wi_net_name.i_len == nwidp->i_len &&
1765 memcmp(sc->wi_net_name.i_nwid, nwidp->i_nwid, nwidp->i_len)__builtin_memcmp((sc->wi_net_name.i_nwid), (nwidp->i_nwid
), (nwidp->i_len))
== 0)
1766 break;
1767 wi_set_ssid(&sc->wi_net_name, nwidp->i_nwid, nwidp->i_len);
1768 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name)do { struct wi_ltv_str s; int l; l = (sc->wi_net_name.i_len
+ 1) & ~0x1; __builtin_bzero((&s), (sizeof(s))); s.wi_len
= (l / 2) + 2; s.wi_type = 0xFC02; s.wi_str[0] = ((__uint16_t
)(sc->wi_net_name.i_len)); bcopy(sc->wi_net_name.i_nwid
, &s.wi_str[1], sc->wi_net_name.i_len); sc->sc_funcs
->f_write_record(sc, (struct wi_ltv_gen *)&s); } while
(0)
;
1769 if (ifp->if_flags & IFF_UP0x1)
1770 /* Reinitialize WaveLAN. */
1771 wi_initsc->sc_funcs->f_init(sc);
1772 break;
1773 case SIOCS80211NWKEY((unsigned long)0x80000000 | ((sizeof(struct ieee80211_nwkey)
& 0x1fff) << 16) | ((('i')) << 8) | ((232)))
:
1774 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1775 break;
1776 error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1777 break;
1778 case SIOCG80211NWKEY(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_nwkey) & 0x1fff) << 16) | ((('i')
) << 8) | ((233)))
:
1779 error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1780 break;
1781 case SIOCS80211POWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_power)
& 0x1fff) << 16) | ((('i')) << 8) | ((234)))
:
1782 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1783 break;
1784 error = wi_set_pm(sc, (struct ieee80211_power *)data);
1785 break;
1786 case SIOCG80211POWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_power) & 0x1fff) << 16) | ((('i')
) << 8) | ((235)))
:
1787 error = wi_get_pm(sc, (struct ieee80211_power *)data);
1788 break;
1789 case SIOCS80211TXPOWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_txpower
) & 0x1fff) << 16) | ((('i')) << 8) | ((243))
)
:
1790 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1791 break;
1792 error = wi_set_txpower(sc, (struct ieee80211_txpower *)data);
1793 break;
1794 case SIOCG80211TXPOWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_txpower) & 0x1fff) << 16) | ((('i'
)) << 8) | ((244)))
:
1795 error = wi_get_txpower(sc, (struct ieee80211_txpower *)data);
1796 break;
1797 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
1798 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1799 break;
1800 if (((struct ieee80211chanreq *)data)->i_channel > 14) {
1801 error = EINVAL22;
1802 break;
1803 }
1804 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1805 wreq->wi_type = WI_RID_OWN_CHNL0xFC03;
1806 wreq->wi_val[0] =
1807 htole16(((struct ieee80211chanreq *)data)->i_channel)((__uint16_t)(((struct ieee80211chanreq *)data)->i_channel
))
;
1808 error = wi_setdef(sc, wreq);
1809 if (!error && (ifp->if_flags & IFF_UP0x1))
1810 wi_initsc->sc_funcs->f_init(sc);
1811 break;
1812 case SIOCG80211CHANNEL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211chanreq) & 0x1fff) << 16) | ((('i'
)) << 8) | ((239)))
:
1813 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1814 wreq->wi_type = WI_RID_CURRENT_CHAN0xFDC1;
1815 wreq->wi_len = WI_MAX_DATALEN512;
1816 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1817 error = EINVAL22;
1818 break;
1819 }
1820 ((struct ieee80211chanreq *)data)->i_channel =
1821 letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1822 break;
1823 case SIOCG80211BSSID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_bssid) & 0x1fff) << 16) | ((('i')
) << 8) | ((241)))
:
1824 bssid = (struct ieee80211_bssid *)data;
1825 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1826 wreq->wi_type = WI_RID_CURRENT_BSSID0xFD42;
1827 wreq->wi_len = WI_MAX_DATALEN512;
1828 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1829 error = EINVAL22;
1830 break;
1831 }
1832 IEEE80211_ADDR_COPY(bssid->i_bssid, wreq->wi_val)__builtin_memcpy((bssid->i_bssid), (wreq->wi_val), (6));
1833 break;
1834 case SIOCS80211SCAN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((210)))
:
1835 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1836 break;
1837 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6)
1838 break;
1839 if ((ifp->if_flags & IFF_UP0x1) == 0) {
1840 error = ENETDOWN50;
1841 break;
1842 }
1843 if (sc->sc_firmware_type == WI_LUCENT1) {
1844 wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_INQUIRE0x0011,
1845 WI_INFO_SCAN_RESULTS0xF101, 0, 0);
1846 } else {
1847 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
1848 wreq->wi_len = 3;
1849 wreq->wi_type = WI_RID_SCAN_REQ0xFCE1;
1850 wreq->wi_val[0] = 0x3FFF;
1851 wreq->wi_val[1] = 0x000F;
1852
1853 error = wi_write_recordsc->sc_funcs->f_write_record(sc,
1854 (struct wi_ltv_gen *)wreq);
1855 if (error)
1856 break;
1857 }
1858 sc->wi_scan_lock = 0;
1859 timeout_set(&sc->wi_scan_timeout, wi_scan_timeout, sc);
1860 len = WI_WAVELAN_RES_TIMEOUT((hz / 10) * 2);
1861 if (sc->wi_flags & WI_FLAGS_BUS_USB0x0400) {
1862 /* Use a longer timeout for wi@usb */
1863 len = WI_WAVELAN_RES_TIMEOUT((hz / 10) * 2) * 4;
1864 }
1865 timeout_add(&sc->wi_scan_timeout, len);
1866
1867 /* Let the userspace process wait for completion */
1868 error = tsleep_nsec(&sc->wi_scan_lock, PCATCH0x100, "wiscan",
1869 SEC_TO_NSEC(IEEE80211_SCAN_TIMEOUT30));
1870 break;
1871 case SIOCG80211ALLNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ieee80211_nodereq_all) & 0x1fff) << 16) | (
(('i')) << 8) | ((214)))
:
1872 {
1873 struct ieee80211_nodereq *nr = NULL((void *)0);
1874
1875 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1876 break;
1877 na = (struct ieee80211_nodereq_all *)data;
1878 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6) {
1879 /* List all associated stations */
1880 error = wihap_ioctl(sc, command, data);
1881 break;
1882 }
1883 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1884 wreq->wi_len = WI_MAX_DATALEN512;
1885 wreq->wi_type = WI_RID_SCAN_RES0xFD88;
1886 if (sc->sc_firmware_type == WI_LUCENT1) {
1887 bcopy(sc->wi_scanbuf, wreq->wi_val,
1888 sc->wi_scanbuf_len * 2);
1889 wreq->wi_len = sc->wi_scanbuf_len;
1890 i = 0;
1891 len = WI_WAVELAN_RES_SIZE50;
1892 } else {
1893 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1894 error = EINVAL22;
1895 break;
1896 }
1897 p2 = (struct wi_scan_p2_hdr *)wreq->wi_val;
1898 if (p2->wi_reason == 0)
1899 break;
1900 i = sizeof(*p2);
1901 len = WI_PRISM2_RES_SIZE62;
1902 }
1903
1904 for (na->na_nodes = j = 0; (i < (wreq->wi_len * 2) - len) &&
1905 (na->na_size >= j + sizeof(struct ieee80211_nodereq));
1906 i += len) {
1907
1908 if (nr == NULL((void *)0))
1909 nr = malloc(sizeof *nr, M_DEVBUF2, M_WAITOK0x0001);
1910 res = (struct wi_scan_res *)((char *)wreq->wi_val + i);
1911 if (res == NULL((void *)0))
1912 break;
1913
1914 bzero(nr, sizeof(*nr))__builtin_bzero((nr), (sizeof(*nr)));
1915 IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid)__builtin_memcpy((nr->nr_macaddr), (res->wi_bssid), (6)
)
;
1916 IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid)__builtin_memcpy((nr->nr_bssid), (res->wi_bssid), (6));
1917 nr->nr_channel = letoh16(res->wi_chan)((__uint16_t)(res->wi_chan));
1918 nr->nr_chan_flags = IEEE80211_CHAN_B(0x0080 | 0x0020);
1919 nr->nr_rssi = letoh16(res->wi_signal)((__uint16_t)(res->wi_signal));
1920 nr->nr_max_rssi = 0; /* XXX */
1921 nr->nr_nwid_len = letoh16(res->wi_ssid_len)((__uint16_t)(res->wi_ssid_len));
1922 bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
1923 nr->nr_intval = letoh16(res->wi_interval)((__uint16_t)(res->wi_interval));
1924 nr->nr_capinfo = letoh16(res->wi_capinfo)((__uint16_t)(res->wi_capinfo));
1925 nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M0x0a ? 2 :
1926 (res->wi_rate == WI_WAVELAN_RES_2M0x14 ? 4 :
1927 (res->wi_rate == WI_WAVELAN_RES_5M0x37 ? 11 :
1928 (res->wi_rate == WI_WAVELAN_RES_11M0x6e ? 22 : 0)));
1929 nr->nr_nrates = 0;
1930 while (res->wi_srates[nr->nr_nrates] != 0) {
1931 nr->nr_rates[nr->nr_nrates] =
1932 res->wi_srates[nr->nr_nrates] &
1933 WI_VAR_SRATES_MASK0x7F;
1934 nr->nr_nrates++;
1935 }
1936 nr->nr_flags = 0;
1937 if (bcmp(nr->nr_macaddr, nr->nr_bssid,
1938 IEEE80211_ADDR_LEN6) == 0)
1939 nr->nr_flags |= IEEE80211_NODEREQ_AP0x01;
1940
1941 error = copyout(nr, (caddr_t)na->na_node + j,
1942 sizeof(struct ieee80211_nodereq));
1943 if (error)
1944 break;
1945 j += sizeof(struct ieee80211_nodereq);
1946 na->na_nodes++;
1947 }
1948 if (nr)
1949 free(nr, M_DEVBUF2, 0);
1950 break;
1951 }
1952 case SIOCG80211FLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((216)))
:
1953 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP0x6)
1954 break;
1955 ifr->ifr_flagsifr_ifru.ifru_flags = 0;
1956 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY0x0800) {
1957 wreq = malloc(sizeof *wreq, M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
1958 wreq->wi_len = WI_MAX_DATALEN512;
1959 wreq->wi_type = WI_RID_ENH_SECURITY0xFC43;
1960 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1961 error = EINVAL22;
1962 break;
1963 }
1964 sc->wi_enh_security = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
1965 if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES0x03)
1966 ifr->ifr_flagsifr_ifru.ifru_flags |= IEEE80211_F_HIDENWID0x00000001;
1967 }
1968 break;
1969 case SIOCS80211FLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((217)))
:
1970 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
1971 break;
1972 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP0x6) {
1973 error = EINVAL22;
1974 break;
1975 }
1976 flags = (u_int32_t)ifr->ifr_flagsifr_ifru.ifru_flags;
1977 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY0x0800) {
1978 sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID0x00000001) ?
1979 WI_HIDESSID_IGNPROBES0x03 : 0;
1980 WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC43; g
.wi_val = ((__uint16_t)(sc->wi_enh_security)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
1981 }
1982 break;
1983 case SIOCHOSTAP_ADD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((201)))
:
1984 case SIOCHOSTAP_DEL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((202)))
:
1985 case SIOCHOSTAP_GET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((200)))
:
1986 case SIOCHOSTAP_GETALL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((203)))
:
1987 case SIOCHOSTAP_GFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((204)))
:
1988 case SIOCHOSTAP_SFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((205)))
:
1989 /* Send all Host AP specific ioctl's to Host AP code. */
1990 error = wihap_ioctl(sc, command, data);
1991 break;
1992 default:
1993 error = ether_ioctl(ifp, &sc->sc_ic.ic_ac, command, data);
1994 }
1995
1996 if (error == ENETRESET52) {
1997 if (ifp->if_flags & IFF_RUNNING0x40)
1998 wi_setmulti(sc);
1999 error = 0;
2000 }
2001
2002 if (wreq)
2003 free(wreq, M_DEVBUF2, 0);
2004 if (nwidp)
2005 free(nwidp, M_DEVBUF2, 0);
2006
2007fail:
2008 sc->wi_flags &= ~WI_FLAGS_BUSY0x2000;
2009 wakeup(&sc->wi_flags);
2010 splx(s)spllower(s);
2011 return(error);
2012}
2013
2014void
2015wi_scan_timeout(void *arg)
2016{
2017 struct wi_softc *sc = (struct wi_softc *)arg;
2018 struct wi_req wreq;
2019
2020 if (sc->wi_scan_lock++ < WI_WAVELAN_RES_TRIES100 &&
2021 sc->sc_firmware_type != WI_LUCENT1 &&
2022 (sc->wi_flags & WI_FLAGS_BUS_USB0x0400) == 0) {
2023 /*
2024 * The Prism2/2.5/3 chipsets will set an extra field in the
2025 * scan result if the scan request has been completed by the
2026 * firmware. This allows to poll for completion and to
2027 * wait for some more time if the scan is still in progress.
2028 *
2029 * XXX This doesn't work with wi@usb because it isn't safe
2030 * to call wi_read_record_usb() while being in the timeout
2031 * handler.
2032 */
2033 wreq.wi_len = WI_MAX_DATALEN512;
2034 wreq.wi_type = WI_RID_SCAN_RES0xFD88;
2035
2036 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2037 ((struct wi_scan_p2_hdr *)wreq.wi_val)->wi_reason == 0) {
2038 /* Wait some more time for scan completion */
2039 timeout_add(&sc->wi_scan_timeout, WI_WAVELAN_RES_TIMEOUT((hz / 10) * 2));
2040 return;
2041 }
2042 }
2043
2044 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
2045 printf(WI_PRT_FMT"%s" ": wi_scan_timeout: %d tries\n",
2046 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname, sc->wi_scan_lock);
2047
2048 /* Wakeup the userland */
2049 wakeup(&sc->wi_scan_lock);
2050 sc->wi_scan_lock = 0;
2051}
2052
2053STATIC void
2054wi_init_io(struct wi_softc *sc)
2055{
2056 struct ifnet *ifp = &sc->sc_ic.ic_ac.ac_if;
2057 int s;
2058 struct wi_ltv_macaddr mac;
2059 int id = 0;
2060
2061 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001))
2062 return;
2063
2064 DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
2065
2066 s = splnet()splraise(0x7);
2067
2068 if (ifp->if_flags & IFF_RUNNING0x40)
2069 wi_stop(sc);
2070
2071 wi_reset(sc);
2072
2073 /* Program max data length. */
2074 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC07; g
.wi_val = ((__uint16_t)(sc->wi_max_data_len)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2075
2076 /* Set the port type. */
2077 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC00; g
.wi_val = ((__uint16_t)(sc->wi_ptype)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2078
2079 /* Enable/disable IBSS creation. */
2080 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC81; g
.wi_val = ((__uint16_t)(sc->wi_create_ibss)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2081
2082 /* Program the RTS/CTS threshold. */
2083 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC83; g
.wi_val = ((__uint16_t)(sc->wi_rts_thresh)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2084
2085 /* Program the TX rate */
2086 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC84; g
.wi_val = ((__uint16_t)(sc->wi_tx_rate)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2087
2088 /* Access point density */
2089 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC06; g
.wi_val = ((__uint16_t)(sc->wi_ap_density)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2090
2091 /* Power Management Enabled */
2092 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC09; g
.wi_val = ((__uint16_t)(sc->wi_pm_enabled)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2093
2094 /* Power Management Max Sleep */
2095 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC0C; g
.wi_val = ((__uint16_t)(sc->wi_max_sleep)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2096
2097 /* Set Enhanced Security if supported. */
2098 if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY0x0800)
2099 WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC43; g
.wi_val = ((__uint16_t)(sc->wi_enh_security)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2100
2101 /* Set Roaming Mode unless this is a Symbol card. */
2102 if (sc->wi_flags & WI_FLAGS_HAS_ROAMING0x0040)
2103 WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC2D; g
.wi_val = ((__uint16_t)(sc->wi_roaming)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2104
2105 /* Set Antenna Diversity if this is a Symbol card. */
2106 if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY0x0080)
2107 WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC87; g
.wi_val = ((__uint16_t)(sc->wi_diversity)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2108
2109 /* Specify the network name */
2110 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name)do { struct wi_ltv_str s; int l; l = (sc->wi_net_name.i_len
+ 1) & ~0x1; __builtin_bzero((&s), (sizeof(s))); s.wi_len
= (l / 2) + 2; s.wi_type = 0xFC02; s.wi_str[0] = ((__uint16_t
)(sc->wi_net_name.i_len)); bcopy(sc->wi_net_name.i_nwid
, &s.wi_str[1], sc->wi_net_name.i_len); sc->sc_funcs
->f_write_record(sc, (struct wi_ltv_gen *)&s); } while
(0)
;
2111
2112 /* Specify the IBSS name */
2113 if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6 ||
2114 (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS0x4)))
2115 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name)do { struct wi_ltv_str s; int l; l = (sc->wi_net_name.i_len
+ 1) & ~0x1; __builtin_bzero((&s), (sizeof(s))); s.wi_len
= (l / 2) + 2; s.wi_type = 0xFC04; s.wi_str[0] = ((__uint16_t
)(sc->wi_net_name.i_len)); bcopy(sc->wi_net_name.i_nwid
, &s.wi_str[1], sc->wi_net_name.i_len); sc->sc_funcs
->f_write_record(sc, (struct wi_ltv_gen *)&s); } while
(0)
;
2116 else
2117 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name)do { struct wi_ltv_str s; int l; l = (sc->wi_ibss_name.i_len
+ 1) & ~0x1; __builtin_bzero((&s), (sizeof(s))); s.wi_len
= (l / 2) + 2; s.wi_type = 0xFC04; s.wi_str[0] = ((__uint16_t
)(sc->wi_ibss_name.i_len)); bcopy(sc->wi_ibss_name.i_nwid
, &s.wi_str[1], sc->wi_ibss_name.i_len); sc->sc_funcs
->f_write_record(sc, (struct wi_ltv_gen *)&s); } while
(0)
;
2118
2119 /* Specify the frequency to use */
2120 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC03; g
.wi_val = ((__uint16_t)(sc->wi_channel)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2121
2122 /* Program the nodename. */
2123 WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name)do { struct wi_ltv_str s; int l; l = (sc->wi_node_name.i_len
+ 1) & ~0x1; __builtin_bzero((&s), (sizeof(s))); s.wi_len
= (l / 2) + 2; s.wi_type = 0xFC0E; s.wi_str[0] = ((__uint16_t
)(sc->wi_node_name.i_len)); bcopy(sc->wi_node_name.i_nwid
, &s.wi_str[1], sc->wi_node_name.i_len); sc->sc_funcs
->f_write_record(sc, (struct wi_ltv_gen *)&s); } while
(0)
;
2124
2125 /* Set our MAC address. */
2126 mac.wi_len = 4;
2127 mac.wi_type = WI_RID_MAC_NODE0xFC01;
2128 bcopy(LLADDR(ifp->if_sadl)((caddr_t)((ifp->if_sadl)->sdl_data + (ifp->if_sadl)
->sdl_nlen))
, &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN6);
2129 bcopy(&sc->sc_ic.ic_myaddr, &mac.wi_mac_addr, ETHER_ADDR_LEN6);
2130 wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&mac);
2131
2132 /*
2133 * Initialize promisc mode.
2134 * Being in the Host-AP mode causes
2135 * great deal of pain if promisc mode is set.
2136 * Therefore we avoid confusing the firmware
2137 * and always reset promisc mode in Host-AP regime,
2138 * it shows us all the packets anyway.
2139 */
2140 if (sc->wi_ptype != WI_PORTTYPE_HOSTAP0x6 && ifp->if_flags & IFF_PROMISC0x100)
2141 WI_SETVAL(WI_RID_PROMISC, 1)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC85; g
.wi_val = ((__uint16_t)(1)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
2142 else
2143 WI_SETVAL(WI_RID_PROMISC, 0)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC85; g
.wi_val = ((__uint16_t)(0)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
2144
2145 /* Configure WEP. */
2146 if (sc->wi_flags & WI_FLAGS_HAS_WEP0x0004) {
2147 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC20; g
.wi_val = ((__uint16_t)(sc->wi_use_wep)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2148 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFCB1; g
.wi_val = ((__uint16_t)(sc->wi_tx_key)); sc->sc_funcs->
f_write_record(sc, &g); } while (0)
;
2149 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
2150 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS0xFCB0;
2151 wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
2152 if (sc->sc_firmware_type != WI_LUCENT1 && sc->wi_use_wep) {
2153 /*
2154 * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
2155 *
2156 * If promiscuous mode is disabled, the Prism2 chip
2157 * does not work with WEP .
2158 * I'm currently investigating the details of this.
2159 * (ichiro@netbsd.org)
2160 */
2161 if (sc->sc_firmware_type == WI_INTERSIL2 &&
2162 sc->sc_sta_firmware_ver < 802 ) {
2163 /* firm ver < 0.8.2 */
2164 WI_SETVAL(WI_RID_PROMISC, 1)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC85; g
.wi_val = ((__uint16_t)(1)); sc->sc_funcs->f_write_record
(sc, &g); } while (0)
;
2165 }
2166 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype)do { struct wi_ltv_gen g; g.wi_len = 2; g.wi_type = 0xFC2A; g
.wi_val = ((__uint16_t)(sc->wi_authtype)); sc->sc_funcs
->f_write_record(sc, &g); } while (0)
;
2167 }
2168 }
2169
2170 /* Set multicast filter. */
2171 wi_setmulti(sc);
2172
2173 /* Enable desired port */
2174 wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_ENABLE0x0001 | sc->wi_portnum, 0, 0, 0);
2175
2176 if (wi_alloc_nicmemsc->sc_funcs->f_alloc_nicmem(sc, ETHER_MAX_LEN1518 + sizeof(struct wi_frame) + 8, &id))
2177 printf(WI_PRT_FMT"%s" ": tx buffer allocation failed\n",
2178 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2179 sc->wi_tx_data_id = id;
2180
2181 if (wi_alloc_nicmemsc->sc_funcs->f_alloc_nicmem(sc, ETHER_MAX_LEN1518 + sizeof(struct wi_frame) + 8, &id))
2182 printf(WI_PRT_FMT"%s" ": mgmt. buffer allocation failed\n",
2183 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2184 sc->wi_tx_mgmt_id = id;
2185
2186 /* Set txpower */
2187 if (sc->wi_flags & WI_FLAGS_TXPOWER0x1000)
2188 wi_set_txpower(sc, NULL((void *)0));
2189
2190 /* enable interrupts */
2191 wi_intr_enable(sc, WI_INTRS(0x0001|0x0002|0x0004|0x0008|0x0080|0x2000));
2192
2193 wihap_init(sc);
2194
2195 splx(s)spllower(s);
2196
2197 ifp->if_flags |= IFF_RUNNING0x40;
2198 ifq_clr_oactive(&ifp->if_snd);
2199
2200 timeout_add_sec(&sc->sc_timo, 60);
2201
2202 return;
2203}
2204
2205STATIC void
2206wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2207{
2208 u_int32_t crc, klen;
2209 u_int8_t key[RC4KEYLEN16];
2210 u_int8_t *dat;
2211 struct rc4_ctx ctx;
2212
2213 if (!sc->wi_icv_flag) {
2214 sc->wi_icv = arc4random();
2215 sc->wi_icv_flag++;
2216 } else
2217 sc->wi_icv++;
2218 /*
2219 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2220 * (B, 255, N) with 3 <= B < 8
2221 */
2222 if (sc->wi_icv >= 0x03ff00 &&
2223 (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2224 sc->wi_icv += 0x000100;
2225
2226 /* prepend 24bit IV to tx key, byte order does not matter */
2227 bzero(key, sizeof(key))__builtin_bzero((key), (sizeof(key)));
2228 key[0] = sc->wi_icv >> 16;
2229 key[1] = sc->wi_icv >> 8;
2230 key[2] = sc->wi_icv;
2231
2232 klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen)((__uint16_t)(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen
))
;
2233 bcopy(&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2234 key + IEEE80211_WEP_IVLEN3, klen);
2235 klen = (klen > IEEE80211_WEP_KEYLEN5) ? RC4KEYLEN16 : RC4KEYLEN16 / 2;
2236
2237 /* rc4 keysetup */
2238 rc4_keysetup(&ctx, key, klen);
2239
2240 /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2241 dat = buf;
2242 dat[0] = key[0];
2243 dat[1] = key[1];
2244 dat[2] = key[2];
2245 dat[3] = sc->wi_tx_key << 6; /* pad and keyid */
2246 dat += 4;
2247
2248 /* compute crc32 over data and encrypt */
2249 crc = ~ether_crc32_le(dat, len);
2250 rc4_crypt(&ctx, dat, dat, len);
2251 dat += len;
2252
2253 /* append little-endian crc32 and encrypt */
2254 dat[0] = crc;
2255 dat[1] = crc >> 8;
2256 dat[2] = crc >> 16;
2257 dat[3] = crc >> 24;
2258 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN4);
2259}
2260
2261STATIC int
2262wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2263{
2264 u_int32_t crc, klen, kid;
2265 u_int8_t key[RC4KEYLEN16];
2266 u_int8_t *dat;
2267 struct rc4_ctx ctx;
2268
2269 if (len < IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1 +
2270 IEEE80211_WEP_CRCLEN4)
2271 return -1;
2272 len -= (IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1 +
2273 IEEE80211_WEP_CRCLEN4);
2274
2275 dat = buf;
2276
2277 bzero(key, sizeof(key))__builtin_bzero((key), (sizeof(key)));
2278 key[0] = dat[0];
2279 key[1] = dat[1];
2280 key[2] = dat[2];
2281 kid = (dat[3] >> 6) % 4;
2282 dat += 4;
2283
2284 klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen)((__uint16_t)(sc->wi_keys.wi_keys[kid].wi_keylen));
2285 bcopy(&sc->wi_keys.wi_keys[kid].wi_keydat,
2286 key + IEEE80211_WEP_IVLEN3, klen);
2287 klen = (klen > IEEE80211_WEP_KEYLEN5) ? RC4KEYLEN16 : RC4KEYLEN16 / 2;
2288
2289 /* rc4 keysetup */
2290 rc4_keysetup(&ctx, key, klen);
2291
2292 /* decrypt and compute crc32 over data */
2293 rc4_crypt(&ctx, dat, dat, len);
2294 crc = ~ether_crc32_le(dat, len);
2295 dat += len;
2296
2297 /* decrypt little-endian crc32 and verify */
2298 rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN4);
2299
2300 if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2301 (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2302 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
2303 printf(WI_PRT_FMT"%s" ": wi_do_hostdecrypt: iv mismatch: "
2304 "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
2305 dat[3], dat[2], dat[1], dat[0], crc);
2306 return -1;
2307 }
2308
2309 return 0;
2310}
2311
2312void
2313wi_start(struct ifnet *ifp)
2314{
2315 struct wi_softc *sc;
2316 struct mbuf *m0;
2317 struct wi_frame tx_frame;
2318 struct ether_header *eh;
2319 int id, hostencrypt = 0;
2320
2321 sc = ifp->if_softc;
2322
2323 DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2324
2325 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001))
2326 return;
2327
2328 if (ifq_is_oactive(&ifp->if_snd))
2329 return;
2330
2331nextpkt:
2332 m0 = ifq_dequeue(&ifp->if_snd);
2333 if (m0 == NULL((void *)0))
2334 return;
2335
2336 bzero(&tx_frame, sizeof(tx_frame))__builtin_bzero((&tx_frame), (sizeof(tx_frame)));
2337 tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA)((__uint16_t)(0x0008 | 0x0000));
2338 id = sc->wi_tx_data_id;
2339 eh = mtod(m0, struct ether_header *)((struct ether_header *)((m0)->m_hdr.mh_data));
2340
2341 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6) {
2342 if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2343 &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC0x100)) {
2344 if (ifp->if_flags & IFF_DEBUG0x4)
2345 printf(WI_PRT_FMT"%s"
2346 ": wi_start: dropping unassoc dst %s\n",
2347 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
2348 ether_sprintf(eh->ether_dhost));
2349 m_freem(m0);
2350 goto nextpkt;
2351 }
2352 }
2353
2354 /*
2355 * Use RFC1042 encoding for IP and ARP datagrams,
2356 * 802.3 for anything else.
2357 */
2358 if (eh->ether_type == htons(ETHERTYPE_IP)(__uint16_t)(__builtin_constant_p(0x0800) ? (__uint16_t)(((__uint16_t
)(0x0800) & 0xffU) << 8 | ((__uint16_t)(0x0800) &
0xff00U) >> 8) : __swap16md(0x0800))
||
2359 eh->ether_type == htons(ETHERTYPE_ARP)(__uint16_t)(__builtin_constant_p(0x0806) ? (__uint16_t)(((__uint16_t
)(0x0806) & 0xffU) << 8 | ((__uint16_t)(0x0806) &
0xff00U) >> 8) : __swap16md(0x0806))
||
2360 eh->ether_type == htons(ETHERTYPE_REVARP)(__uint16_t)(__builtin_constant_p(0x8035) ? (__uint16_t)(((__uint16_t
)(0x8035) & 0xffU) << 8 | ((__uint16_t)(0x8035) &
0xff00U) >> 8) : __swap16md(0x8035))
||
2361 eh->ether_type == htons(ETHERTYPE_IPV6)(__uint16_t)(__builtin_constant_p(0x86DD) ? (__uint16_t)(((__uint16_t
)(0x86DD) & 0xffU) << 8 | ((__uint16_t)(0x86DD) &
0xff00U) >> 8) : __swap16md(0x86DD))
) {
2362 bcopy(&eh->ether_dhost,
2363 &tx_frame.wi_addr1, ETHER_ADDR_LEN6);
2364 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6) {
2365 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT)((__uint16_t)(0x08)); /* XXX */
2366 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS)((__uint16_t)(0x0200));
2367 bcopy(&sc->sc_ic.ic_myaddr,
2368 &tx_frame.wi_addr2, ETHER_ADDR_LEN6);
2369 bcopy(&eh->ether_shost,
2370 &tx_frame.wi_addr3, ETHER_ADDR_LEN6);
2371 if (sc->wi_use_wep)
2372 hostencrypt = 1;
2373 } else if (sc->wi_ptype == WI_PORTTYPE_BSS0x1 && sc->wi_use_wep &&
2374 sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP0x00) {
2375 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT)((__uint16_t)(0x08)); /* XXX */
2376 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS)((__uint16_t)(0x0100));
2377 bcopy(&sc->sc_ic.ic_myaddr,
2378 &tx_frame.wi_addr2, ETHER_ADDR_LEN6);
2379 bcopy(&eh->ether_dhost,
2380 &tx_frame.wi_addr3, ETHER_ADDR_LEN6);
2381 hostencrypt = 1;
2382 } else
2383 bcopy(&eh->ether_shost,
2384 &tx_frame.wi_addr2, ETHER_ADDR_LEN6);
2385 bcopy(&eh->ether_dhost, &tx_frame.wi_dst_addr, ETHER_ADDR_LEN6);
2386 bcopy(&eh->ether_shost, &tx_frame.wi_src_addr, ETHER_ADDR_LEN6);
2387
2388 tx_frame.wi_dat_len = m0->m_pkthdrM_dat.MH.MH_pkthdr.len - WI_SNAPHDR_LEN0x6;
2389 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0)(__uint16_t)(__builtin_constant_p((0xaa | (0xaa << 8)))
? (__uint16_t)(((__uint16_t)((0xaa | (0xaa << 8))) &
0xffU) << 8 | ((__uint16_t)((0xaa | (0xaa << 8))
) & 0xff00U) >> 8) : __swap16md((0xaa | (0xaa <<
8))))
;
2390 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1)(__uint16_t)(__builtin_constant_p((0x00 | (0x03 << 8)))
? (__uint16_t)(((__uint16_t)((0x00 | (0x03 << 8))) &
0xffU) << 8 | ((__uint16_t)((0x00 | (0x03 << 8))
) & 0xff00U) >> 8) : __swap16md((0x00 | (0x03 <<
8))))
;
2391 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN)(__uint16_t)(__builtin_constant_p(m0->M_dat.MH.MH_pkthdr.len
- 0x6) ? (__uint16_t)(((__uint16_t)(m0->M_dat.MH.MH_pkthdr
.len - 0x6) & 0xffU) << 8 | ((__uint16_t)(m0->M_dat
.MH.MH_pkthdr.len - 0x6) & 0xff00U) >> 8) : __swap16md
(m0->M_dat.MH.MH_pkthdr.len - 0x6))
;
2392 tx_frame.wi_type = eh->ether_type;
2393
2394 if (hostencrypt) {
2395
2396 /* Do host encryption. */
2397 tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP)((__uint16_t)(0x4000));
2398 bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 6);
2399 bcopy(&tx_frame.wi_type, &sc->wi_txbuf[10], 2);
2400
2401 m_copydata(m0, sizeof(struct ether_header),
2402 m0->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(struct ether_header),
2403 &sc->wi_txbuf[12]);
2404
2405 wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2406 tx_frame.wi_dat_len);
2407
2408 tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN3 +
2409 IEEE80211_WEP_KIDLEN1 + IEEE80211_WEP_CRCLEN4;
2410
2411 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len)((__uint16_t)(tx_frame.wi_dat_len));
2412 wi_write_datasc->sc_funcs->f_write_data(sc, id, 0, (caddr_t)&tx_frame,
2413 sizeof(struct wi_frame));
2414 wi_write_datasc->sc_funcs->f_write_data(sc, id, WI_802_11_OFFSET_RAW0x3C,
2415 (caddr_t)&sc->wi_txbuf,
2416 (m0->m_pkthdrM_dat.MH.MH_pkthdr.len -
2417 sizeof(struct ether_header)) + 18);
2418 } else {
2419 m_copydata(m0, sizeof(struct ether_header),
2420 m0->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(struct ether_header),
2421 &sc->wi_txbuf);
2422
2423 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len)((__uint16_t)(tx_frame.wi_dat_len));
2424 wi_write_datasc->sc_funcs->f_write_data(sc, id, 0, (caddr_t)&tx_frame,
2425 sizeof(struct wi_frame));
2426 wi_write_datasc->sc_funcs->f_write_data(sc, id, WI_802_11_OFFSET0x44,
2427 (caddr_t)&sc->wi_txbuf,
2428 (m0->m_pkthdrM_dat.MH.MH_pkthdr.len -
2429 sizeof(struct ether_header)) + 2);
2430 }
2431 } else {
2432 tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len)((__uint16_t)(m0->M_dat.MH.MH_pkthdr.len));
2433
2434 if (sc->wi_ptype == WI_PORTTYPE_HOSTAP0x6 && sc->wi_use_wep) {
2435
2436 /* Do host encryption. (XXX - not implemented) */
2437 printf(WI_PRT_FMT"%s"
2438 ": host encrypt not implemented for 802.3\n",
2439 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2440 } else {
2441 m_copydata(m0, 0, m0->m_pkthdrM_dat.MH.MH_pkthdr.len, &sc->wi_txbuf);
2442
2443 wi_write_datasc->sc_funcs->f_write_data(sc, id, 0, (caddr_t)&tx_frame,
2444 sizeof(struct wi_frame));
2445 wi_write_datasc->sc_funcs->f_write_data(sc, id, WI_802_3_OFFSET0x2E,
2446 (caddr_t)&sc->wi_txbuf, m0->m_pkthdrM_dat.MH.MH_pkthdr.len + 2);
2447 }
2448 }
2449
2450#if NBPFILTER1 > 0
2451 /*
2452 * If there's a BPF listener, bounce a copy of
2453 * this frame to him.
2454 */
2455 if (ifp->if_bpf)
2456 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT(1 << 1));
2457#endif
2458
2459 m_freem(m0);
2460
2461 ifq_set_oactive(&ifp->if_snd);
2462
2463 /*
2464 * Set a timeout in case the chip goes out to lunch.
2465 */
2466 ifp->if_timer = 5;
2467
2468 if (wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_TX0x000B|WI_RECLAIM0x0100, id, 0, 0))
2469 printf(WI_PRT_FMT"%s" ": wi_start: xmit failed\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2470
2471 return;
2472}
2473
2474STATIC int
2475wi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len)
2476{
2477 struct wi_frame tx_frame;
2478 int id;
2479 struct wi_80211_hdr *hdr;
2480 caddr_t dptr;
2481
2482 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001))
2483 return(ENODEV19);
2484
2485 hdr = (struct wi_80211_hdr *)data;
2486 dptr = data + sizeof(struct wi_80211_hdr);
2487
2488 bzero(&tx_frame, sizeof(tx_frame))__builtin_bzero((&tx_frame), (sizeof(tx_frame)));
2489 id = sc->wi_tx_mgmt_id;
2490
2491 bcopy(hdr, &tx_frame.wi_frame_ctl, sizeof(struct wi_80211_hdr));
2492
2493 tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT)((__uint16_t)(0x08));
2494 tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2495 tx_frame.wi_len = htole16(tx_frame.wi_dat_len)((__uint16_t)(tx_frame.wi_dat_len));
2496
2497 tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len)((__uint16_t)(tx_frame.wi_dat_len));
2498 wi_write_datasc->sc_funcs->f_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2499 wi_write_datasc->sc_funcs->f_write_data(sc, id, WI_802_11_OFFSET_RAW0x3C, dptr,
2500 (len - sizeof(struct wi_80211_hdr)) + 2);
2501
2502 if (wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_TX0x000B|WI_RECLAIM0x0100, id, 0, 0)) {
2503 printf(WI_PRT_FMT"%s" ": wi_mgmt_xmit: xmit failed\n",
2504 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2505 /*
2506 * Hostile stations or corrupt frames may crash the card
2507 * and cause the kernel to get stuck printing complaints.
2508 * Reset the card and hope the problem goes away.
2509 */
2510 wi_reset(sc);
2511 return(EIO5);
2512 }
2513
2514 return(0);
2515}
2516
2517void
2518wi_stop(struct wi_softc *sc)
2519{
2520 struct ifnet *ifp;
2521
2522 wihap_shutdown(sc);
2523
2524 if (!(sc->wi_flags & WI_FLAGS_ATTACHED0x0001))
2525 return;
2526
2527 DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2528
2529 timeout_del(&sc->sc_timo);
2530
2531 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2532
2533 wi_intr_enable(sc, 0);
2534 wi_cmdsc->sc_funcs->f_cmd(sc, WI_CMD_DISABLE0x0002|sc->wi_portnum, 0, 0, 0);
2535
2536 ifp->if_flags &= ~IFF_RUNNING0x40;
2537 ifq_clr_oactive(&ifp->if_snd);
2538 ifp->if_timer = 0;
2539
2540 return;
2541}
2542
2543
2544void
2545wi_watchdog(struct ifnet *ifp)
2546{
2547 struct wi_softc *sc;
2548
2549 sc = ifp->if_softc;
2550
2551 printf(WI_PRT_FMT"%s" ": device timeout\n", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname);
2552
2553 wi_cor_reset(sc);
2554 wi_initsc->sc_funcs->f_init(sc);
2555
2556 ifp->if_oerrorsif_data.ifi_oerrors++;
2557
2558 return;
2559}
2560
2561void
2562wi_detach(struct wi_softc *sc)
2563{
2564 struct ifnet *ifp;
2565 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2566
2567 if (ifp->if_flags & IFF_RUNNING0x40)
2568 wi_stop(sc);
2569
2570 if (sc->wi_flags & WI_FLAGS_ATTACHED0x0001) {
2571 sc->wi_flags &= ~WI_FLAGS_ATTACHED0x0001;
2572 }
2573}
2574
2575STATIC void
2576wi_get_id(struct wi_softc *sc)
2577{
2578 struct wi_ltv_ver ver;
2579 const struct wi_card_ident *id;
2580 u_int16_t pri_fw_ver[3];
2581 const char *card_name;
2582 u_int16_t card_id;
2583
2584 /* get chip identity */
2585 bzero(&ver, sizeof(ver))__builtin_bzero((&ver), (sizeof(ver)));
2586 ver.wi_type = WI_RID_CARD_ID0xFD0B;
2587 ver.wi_len = 5;
2588 wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&ver);
2589 card_id = letoh16(ver.wi_ver[0])((__uint16_t)(ver.wi_ver[0]));
2590 for (id = wi_card_ident; id->firm_type != WI_NOTYPE0; id++) {
4
Assuming field 'firm_type' is not equal to WI_NOTYPE
5
Loop condition is true. Entering loop body
2591 if (card_id == id->card_id)
6
Assuming 'card_id' is equal to field 'card_id'
7
Taking true branch
2592 break;
8
Execution continues on line 2594
2593 }
2594 if (id->firm_type
8.1
Field 'firm_type' is not equal to WI_NOTYPE
!= WI_NOTYPE0) {
9
Taking true branch
2595 sc->sc_firmware_type = id->firm_type;
2596 card_name = id->card_name;
2597 } else if (ver.wi_ver[0] & htole16(0x8000)((__uint16_t)(0x8000))) {
2598 sc->sc_firmware_type = WI_INTERSIL2;
2599 card_name = "Unknown PRISM2 chip";
2600 } else {
2601 sc->sc_firmware_type = WI_LUCENT1;
2602 }
2603
2604 /* get primary firmware version (XXX - how to do Lucent?) */
2605 if (sc->sc_firmware_type != WI_LUCENT1) {
10
Assuming field 'sc_firmware_type' is equal to WI_LUCENT
11
Taking false branch
2606 bzero(&ver, sizeof(ver))__builtin_bzero((&ver), (sizeof(ver)));
2607 ver.wi_type = WI_RID_PRI_IDENTITY0xFD02;
2608 ver.wi_len = 5;
2609 wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&ver);
2610 pri_fw_ver[0] = letoh16(ver.wi_ver[2])((__uint16_t)(ver.wi_ver[2]));
2611 pri_fw_ver[1] = letoh16(ver.wi_ver[3])((__uint16_t)(ver.wi_ver[3]));
2612 pri_fw_ver[2] = letoh16(ver.wi_ver[1])((__uint16_t)(ver.wi_ver[1]));
2613 }
2614
2615 /* get station firmware version */
2616 bzero(&ver, sizeof(ver))__builtin_bzero((&ver), (sizeof(ver)));
2617 ver.wi_type = WI_RID_STA_IDENTITY0xFD20;
2618 ver.wi_len = 5;
2619 wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&ver);
2620 ver.wi_ver[1] = letoh16(ver.wi_ver[1])((__uint16_t)(ver.wi_ver[1]));
2621 ver.wi_ver[2] = letoh16(ver.wi_ver[2])((__uint16_t)(ver.wi_ver[2]));
2622 ver.wi_ver[3] = letoh16(ver.wi_ver[3])((__uint16_t)(ver.wi_ver[3]));
2623 sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2624 ver.wi_ver[3] * 100 + ver.wi_ver[1];
2625
2626 if (sc->sc_firmware_type == WI_INTERSIL2 &&
12
Assuming field 'sc_firmware_type' is not equal to WI_INTERSIL
2627 (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2628 struct wi_ltv_str sver;
2629 char *p;
2630
2631 bzero(&sver, sizeof(sver))__builtin_bzero((&sver), (sizeof(sver)));
2632 sver.wi_type = WI_RID_SYMBOL_IDENTITY0xFD24;
2633 sver.wi_len = 7;
2634 /* value should be something like "V2.00-11" */
2635 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2636 *(p = (char *)sver.wi_str) >= 'A' &&
2637 p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2638 sc->sc_firmware_type = WI_SYMBOL3;
2639 sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2640 (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2641 (p[6] - '0') * 10 + (p[7] - '0');
2642 }
2643 }
2644
2645 if (sc->sc_firmware_type == WI_LUCENT1) {
13
Assuming field 'sc_firmware_type' is not equal to WI_LUCENT
14
Taking false branch
2646 printf("%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
2647 ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2648 } else {
2649 printf("%s: %s%s (0x%04x), Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
17
6th function call argument is an uninitialized value
2650 WI_PRT_ARG(sc)(sc)->sc_dev.dv_xname,
2651 sc->sc_firmware_type == WI_SYMBOL3 ? "Symbol " : "",
15
Assuming field 'sc_firmware_type' is not equal to WI_SYMBOL
16
'?' condition is false
2652 card_name, card_id, pri_fw_ver[0], pri_fw_ver[1],
2653 pri_fw_ver[2], sc->sc_sta_firmware_ver / 10000,
2654 (sc->sc_sta_firmware_ver % 10000) / 100,
2655 sc->sc_sta_firmware_ver % 100);
2656 }
2657}
2658
2659STATIC int
2660wi_sync_media(struct wi_softc *sc, int ptype, int txrate)
2661{
2662 uint64_t media = sc->sc_media.ifm_cur->ifm_media;
2663 uint64_t options = IFM_OPTIONS(media)((media) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL));
2664 uint64_t subtype;
2665
2666 switch (txrate) {
2667 case 1:
2668 subtype = IFM_IEEE80211_DS18;
2669 break;
2670 case 2:
2671 subtype = IFM_IEEE80211_DS25;
2672 break;
2673 case 3:
2674 subtype = IFM_AUTO0ULL;
2675 break;
2676 case 5:
2677 subtype = IFM_IEEE80211_DS56;
2678 break;
2679 case 11:
2680 subtype = IFM_IEEE80211_DS117;
2681 break;
2682 default:
2683 subtype = IFM_MANUAL1ULL; /* Unable to represent */
2684 break;
2685 }
2686
2687 options &= ~IFM_OMASK0x00000000ffff0000ULL;
2688 switch (ptype) {
2689 case WI_PORTTYPE_BSS0x1:
2690 /* default port type */
2691 break;
2692 case WI_PORTTYPE_ADHOC0x3:
2693 options |= IFM_IEEE80211_ADHOC0x0000000000010000ULL;
2694 break;
2695 case WI_PORTTYPE_HOSTAP0x6:
2696 options |= IFM_IEEE80211_HOSTAP0x0000000000020000ULL;
2697 break;
2698 case WI_PORTTYPE_IBSS0x4:
2699 if (sc->wi_create_ibss)
2700 options |= IFM_IEEE80211_IBSSMASTER0x0000000000080000ULL;
2701 else
2702 options |= IFM_IEEE80211_IBSS0x0000000000040000ULL;
2703 break;
2704 default:
2705 subtype = IFM_MANUAL1ULL; /* Unable to represent */
2706 break;
2707 }
2708 media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,((((media) & 0x000000000000ff00ULL)) | (subtype) | (options
) | ((uint64_t)((((media) & 0xff00000000000000ULL) >>
56)) << 56))
2709 IFM_INST(media))((((media) & 0x000000000000ff00ULL)) | (subtype) | (options
) | ((uint64_t)((((media) & 0xff00000000000000ULL) >>
56)) << 56))
;
2710 if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL((void *)0))
2711 return (EINVAL22);
2712 ifmedia_set(&sc->sc_media, media);
2713 sc->wi_ptype = ptype;
2714 sc->wi_tx_rate = txrate;
2715 return (0);
2716}
2717
2718STATIC int
2719wi_media_change(struct ifnet *ifp)
2720{
2721 struct wi_softc *sc = ifp->if_softc;
2722 int otype = sc->wi_ptype;
2723 int orate = sc->wi_tx_rate;
2724 int ocreate_ibss = sc->wi_create_ibss;
2725
2726 if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP0x0000000000020000ULL) &&
2727 sc->sc_firmware_type != WI_INTERSIL2)
2728 return (EINVAL22);
2729
2730 sc->wi_create_ibss = 0;
2731
2732 switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK0x00000000ffff0000ULL) {
2733 case 0:
2734 sc->wi_ptype = WI_PORTTYPE_BSS0x1;
2735 break;
2736 case IFM_IEEE80211_ADHOC0x0000000000010000ULL:
2737 sc->wi_ptype = WI_PORTTYPE_ADHOC0x3;
2738 break;
2739 case IFM_IEEE80211_HOSTAP0x0000000000020000ULL:
2740 sc->wi_ptype = WI_PORTTYPE_HOSTAP0x6;
2741 break;
2742 case IFM_IEEE80211_IBSSMASTER0x0000000000080000ULL:
2743 case IFM_IEEE80211_IBSSMASTER0x0000000000080000ULL|IFM_IEEE80211_IBSS0x0000000000040000ULL:
2744 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS0x0010))
2745 return (EINVAL22);
2746 sc->wi_create_ibss = 1;
2747 /* FALLTHROUGH */
2748 case IFM_IEEE80211_IBSS0x0000000000040000ULL:
2749 sc->wi_ptype = WI_PORTTYPE_IBSS0x4;
2750 break;
2751 default:
2752 /* Invalid combination. */
2753 return (EINVAL22);
2754 }
2755
2756 switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)((sc->sc_media.ifm_cur->ifm_media) & 0x00000000000000ffULL
)
) {
2757 case IFM_IEEE80211_DS18:
2758 sc->wi_tx_rate = 1;
2759 break;
2760 case IFM_IEEE80211_DS25:
2761 sc->wi_tx_rate = 2;
2762 break;
2763 case IFM_AUTO0ULL:
2764 sc->wi_tx_rate = 3;
2765 break;
2766 case IFM_IEEE80211_DS56:
2767 sc->wi_tx_rate = 5;
2768 break;
2769 case IFM_IEEE80211_DS117:
2770 sc->wi_tx_rate = 11;
2771 break;
2772 }
2773
2774 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1) {
2775 if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2776 ocreate_ibss != sc->wi_create_ibss)
2777 wi_initsc->sc_funcs->f_init(sc);
2778 }
2779
2780 ifp->if_baudrateif_data.ifi_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2781
2782 return (0);
2783}
2784
2785STATIC void
2786wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2787{
2788 struct wi_softc *sc = ifp->if_softc;
2789 struct wi_req wreq;
2790
2791 if (!(sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1)) {
2792 imr->ifm_active = IFM_IEEE802110x0000000000000400ULL|IFM_NONE2ULL;
2793 imr->ifm_status = 0;
2794 return;
2795 }
2796
2797 if (sc->wi_tx_rate == 3) {
2798 imr->ifm_active = IFM_IEEE802110x0000000000000400ULL|IFM_AUTO0ULL;
2799
2800 wreq.wi_type = WI_RID_CUR_TX_RATE0xFD44;
2801 wreq.wi_len = WI_MAX_DATALEN512;
2802 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2803 switch (letoh16(wreq.wi_val[0])((__uint16_t)(wreq.wi_val[0]))) {
2804 case 1:
2805 imr->ifm_active |= IFM_IEEE80211_DS18;
2806 break;
2807 case 2:
2808 imr->ifm_active |= IFM_IEEE80211_DS25;
2809 break;
2810 case 6:
2811 imr->ifm_active |= IFM_IEEE80211_DS56;
2812 break;
2813 case 11:
2814 imr->ifm_active |= IFM_IEEE80211_DS117;
2815 break;
2816 }
2817 }
2818 } else {
2819 imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2820 }
2821
2822 imr->ifm_status = IFM_AVALID0x0000000000000001ULL;
2823 switch (sc->wi_ptype) {
2824 case WI_PORTTYPE_ADHOC0x3:
2825 case WI_PORTTYPE_IBSS0x4:
2826 /*
2827 * XXX: It would be nice if we could give some actually
2828 * useful status like whether we joined another IBSS or
2829 * created one ourselves.
2830 */
2831 /* FALLTHROUGH */
2832 case WI_PORTTYPE_HOSTAP0x6:
2833 imr->ifm_status |= IFM_ACTIVE0x0000000000000002ULL;
2834 break;
2835 default:
2836 wreq.wi_type = WI_RID_COMMQUAL0xFD43;
2837 wreq.wi_len = WI_MAX_DATALEN512;
2838 if (wi_read_recordsc->sc_funcs->f_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2839 letoh16(wreq.wi_val[0])((__uint16_t)(wreq.wi_val[0])) != 0)
2840 imr->ifm_status |= IFM_ACTIVE0x0000000000000002ULL;
2841 }
2842}
2843
2844STATIC int
2845wi_set_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2846{
2847 int i, len, error;
2848 struct wi_req wreq;
2849 struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2850
2851 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP0x0004))
2852 return ENODEV19;
2853 if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID4)
2854 return EINVAL22;
2855 memcpy(wk, &sc->wi_keys, sizeof(*wk))__builtin_memcpy((wk), (&sc->wi_keys), (sizeof(*wk)));
2856 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
2857 if (nwkey->i_key[i].i_keydat == NULL((void *)0))
2858 continue;
2859 len = nwkey->i_key[i].i_keylen;
2860 if (len > sizeof(wk->wi_keys[i].wi_keydat))
2861 return EINVAL22;
2862 error = copyin(nwkey->i_key[i].i_keydat,
2863 wk->wi_keys[i].wi_keydat, len);
2864 if (error)
2865 return error;
2866 wk->wi_keys[i].wi_keylen = htole16(len)((__uint16_t)(len));
2867 }
2868
2869 wk->wi_len = (sizeof(*wk) / 2) + 1;
2870 wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS0xFCB0;
2871 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1) {
2872 error = wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&wreq);
2873 if (error)
2874 return error;
2875 }
2876 if ((error = wi_setdef(sc, &wreq)))
2877 return (error);
2878
2879 wreq.wi_len = 2;
2880 wreq.wi_type = WI_RID_TX_CRYPT_KEY0xFCB1;
2881 wreq.wi_val[0] = htole16(nwkey->i_defkid - 1)((__uint16_t)(nwkey->i_defkid - 1));
2882 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1) {
2883 error = wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&wreq);
2884 if (error)
2885 return error;
2886 }
2887 if ((error = wi_setdef(sc, &wreq)))
2888 return (error);
2889
2890 wreq.wi_type = WI_RID_ENCRYPTION0xFC20;
2891 wreq.wi_val[0] = htole16(nwkey->i_wepon)((__uint16_t)(nwkey->i_wepon));
2892 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1) {
2893 error = wi_write_recordsc->sc_funcs->f_write_record(sc, (struct wi_ltv_gen *)&wreq);
2894 if (error)
2895 return error;
2896 }
2897 if ((error = wi_setdef(sc, &wreq)))
2898 return (error);
2899
2900 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1)
2901 wi_initsc->sc_funcs->f_init(sc);
2902 return 0;
2903}
2904
2905STATIC int
2906wi_get_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2907{
2908 int i;
2909
2910 if (!(sc->wi_flags & WI_FLAGS_HAS_WEP0x0004))
2911 return ENODEV19;
2912 nwkey->i_wepon = sc->wi_use_wep;
2913 nwkey->i_defkid = sc->wi_tx_key + 1;
2914
2915 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
2916 if (nwkey->i_key[i].i_keydat == NULL((void *)0))
2917 continue;
2918 /* do not show any keys to userland */
2919 return EPERM1;
2920 }
2921 return 0;
2922}
2923
2924STATIC int
2925wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2926{
2927
2928 sc->wi_pm_enabled = power->i_enabled;
2929 sc->wi_max_sleep = power->i_maxsleep;
2930
2931 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_UP0x1)
2932 wi_initsc->sc_funcs->f_init(sc);
2933
2934 return (0);
2935}
2936
2937STATIC int
2938wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2939{
2940
2941 power->i_enabled = sc->wi_pm_enabled;
2942 power->i_maxsleep = sc->wi_max_sleep;
2943
2944 return (0);
2945}
2946
2947STATIC int
2948wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
2949{
2950 u_int16_t cmd;
2951 u_int16_t power;
2952 int8_t tmp;
2953 int error;
2954 int alc;
2955
2956 if (txpower == NULL((void *)0)) {
2957 if (!(sc->wi_flags & WI_FLAGS_TXPOWER0x1000))
2958 return (EINVAL22);
2959 alc = 0; /* disable ALC */
2960 } else {
2961 if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO1) {
2962 alc = 1; /* enable ALC */
2963 sc->wi_flags &= ~WI_FLAGS_TXPOWER0x1000;
2964 } else {
2965 alc = 0; /* disable ALC */
2966 sc->wi_flags |= WI_FLAGS_TXPOWER0x1000;
2967 sc->wi_txpower = txpower->i_val;
2968 }
2969 }
2970
2971 /* Set ALC */
2972 cmd = WI_CMD_DEBUG0x0038 | (WI_DEBUG_CONFBITS0x15 << 8);
2973 if ((error = wi_cmdsc->sc_funcs->f_cmd(sc, cmd, alc, 0x8, 0)) != 0)
2974 return (error);
2975
2976 /* No need to set the TX power value if ALC is enabled */
2977 if (alc)
2978 return (0);
2979
2980 /* Convert dBM to internal TX power value */
2981 if (sc->wi_txpower > 20)
2982 power = 128;
2983 else if (sc->wi_txpower < -43)
2984 power = 127;
2985 else {
2986 tmp = sc->wi_txpower;
2987 tmp = -12 - tmp;
2988 tmp <<= 2;
2989
2990 power = (u_int16_t)tmp;
2991 }
2992
2993 /* Set manual TX power */
2994 cmd = WI_CMD_WRITE_MIF0x0031;
2995 if ((error = wi_cmdsc->sc_funcs->f_cmd(sc, cmd,
2996 WI_HFA384X_CR_MANUAL_TX_POWER0x3e, power, 0)) != 0)
2997 return (error);
2998
2999 if (sc->sc_ic.ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
3000 printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power,
3001 sc->wi_txpower);
3002
3003 return (0);
3004}
3005
3006STATIC int
3007wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
3008{
3009 u_int16_t cmd;
3010 u_int16_t power;
3011 int8_t tmp;
3012 int error;
3013
3014 if (sc->wi_flags & WI_FLAGS_BUS_USB0x0400)
3015 return (EOPNOTSUPP45);
3016
3017 /* Get manual TX power */
3018 cmd = WI_CMD_READ_MIF0x0030;
3019 if ((error = wi_cmdsc->sc_funcs->f_cmd(sc, cmd,
3020 WI_HFA384X_CR_MANUAL_TX_POWER0x3e, 0, 0)) != 0)
3021 return (error);
3022
3023 power = CSR_READ_2(sc, WI_RESP0)((sc->wi_btag)->read_2((sc->wi_bhandle), ((sc->sc_pci
? 0x0A * 2: 0x0A))))
;
3024
3025 /* Convert internal TX power value to dBM */
3026 if (power > 255)
3027 txpower->i_val = 255;
3028 else {
3029 tmp = power;
3030 tmp >>= 2;
3031 txpower->i_val = (u_int16_t)(-12 - tmp);
3032 }
3033
3034 if (sc->wi_flags & WI_FLAGS_TXPOWER0x1000)
3035 txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED0;
3036 else
3037 txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO1;
3038
3039 return (0);
3040}
3041
3042STATIC int
3043wi_set_ssid(struct ieee80211_nwid *ws, u_int8_t *id, int len)
3044{
3045
3046 if (len > IEEE80211_NWID_LEN32)
3047 return (EINVAL22);
3048 ws->i_len = len;
3049 memcpy(ws->i_nwid, id, len)__builtin_memcpy((ws->i_nwid), (id), (len));
3050 return (0);
3051}
3052
3053STATIC int
3054wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
3055{
3056 int error = 0;
3057
3058 wreq->wi_len = 1;
3059
3060 switch (wreq->wi_type) {
3061 case WI_DEBUG_SLEEP0x02:
3062 wreq->wi_len++;
3063 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep)((__uint16_t)(sc->wi_debug.wi_sleep));
3064 break;
3065 case WI_DEBUG_DELAYSUPP0x09:
3066 wreq->wi_len++;
3067 wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp)((__uint16_t)(sc->wi_debug.wi_delaysupp));
3068 break;
3069 case WI_DEBUG_TXSUPP0x0A:
3070 wreq->wi_len++;
3071 wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp)((__uint16_t)(sc->wi_debug.wi_txsupp));
3072 break;
3073 case WI_DEBUG_MONITOR0x0B:
3074 wreq->wi_len++;
3075 wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor)((__uint16_t)(sc->wi_debug.wi_monitor));
3076 break;
3077 case WI_DEBUG_LEDTEST0x0C:
3078 wreq->wi_len += 3;
3079 wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest)((__uint16_t)(sc->wi_debug.wi_ledtest));
3080 wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0)((__uint16_t)(sc->wi_debug.wi_ledtest_param0));
3081 wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1)((__uint16_t)(sc->wi_debug.wi_ledtest_param1));
3082 break;
3083 case WI_DEBUG_CONTTX0x0E:
3084 wreq->wi_len += 2;
3085 wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx)((__uint16_t)(sc->wi_debug.wi_conttx));
3086 wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0)((__uint16_t)(sc->wi_debug.wi_conttx_param0));
3087 break;
3088 case WI_DEBUG_CONTRX0x10:
3089 wreq->wi_len++;
3090 wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx)((__uint16_t)(sc->wi_debug.wi_contrx));
3091 break;
3092 case WI_DEBUG_SIGSTATE0x11:
3093 wreq->wi_len += 2;
3094 wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate)((__uint16_t)(sc->wi_debug.wi_sigstate));
3095 wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0)((__uint16_t)(sc->wi_debug.wi_sigstate_param0));
3096 break;
3097 case WI_DEBUG_CONFBITS0x15:
3098 wreq->wi_len += 2;
3099 wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits)((__uint16_t)(sc->wi_debug.wi_confbits));
3100 wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0)((__uint16_t)(sc->wi_debug.wi_confbits_param0));
3101 break;
3102 default:
3103 error = EIO5;
3104 break;
3105 }
3106
3107 return (error);
3108}
3109
3110STATIC int
3111wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3112{
3113 int error = 0;
3114 u_int16_t cmd, param0 = 0, param1 = 0;
3115
3116 switch (wreq->wi_type) {
3117 case WI_DEBUG_RESET0x00:
3118 case WI_DEBUG_INIT0x01:
3119 case WI_DEBUG_CALENABLE0x13:
3120 break;
3121 case WI_DEBUG_SLEEP0x02:
3122 sc->wi_debug.wi_sleep = 1;
3123 break;
3124 case WI_DEBUG_WAKE0x03:
3125 sc->wi_debug.wi_sleep = 0;
3126 break;
3127 case WI_DEBUG_CHAN0x08:
3128 param0 = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
3129 break;
3130 case WI_DEBUG_DELAYSUPP0x09:
3131 sc->wi_debug.wi_delaysupp = 1;
3132 break;
3133 case WI_DEBUG_TXSUPP0x0A:
3134 sc->wi_debug.wi_txsupp = 1;
3135 break;
3136 case WI_DEBUG_MONITOR0x0B:
3137 sc->wi_debug.wi_monitor = 1;
3138 break;
3139 case WI_DEBUG_LEDTEST0x0C:
3140 param0 = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
3141 param1 = letoh16(wreq->wi_val[1])((__uint16_t)(wreq->wi_val[1]));
3142 sc->wi_debug.wi_ledtest = 1;
3143 sc->wi_debug.wi_ledtest_param0 = param0;
3144 sc->wi_debug.wi_ledtest_param1 = param1;
3145 break;
3146 case WI_DEBUG_CONTTX0x0E:
3147 param0 = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
3148 sc->wi_debug.wi_conttx = 1;
3149 sc->wi_debug.wi_conttx_param0 = param0;
3150 break;
3151 case WI_DEBUG_STOPTEST0x0F:
3152 sc->wi_debug.wi_delaysupp = 0;
3153 sc->wi_debug.wi_txsupp = 0;
3154 sc->wi_debug.wi_monitor = 0;
3155 sc->wi_debug.wi_ledtest = 0;
3156 sc->wi_debug.wi_ledtest_param0 = 0;
3157 sc->wi_debug.wi_ledtest_param1 = 0;
3158 sc->wi_debug.wi_conttx = 0;
3159 sc->wi_debug.wi_conttx_param0 = 0;
3160 sc->wi_debug.wi_contrx = 0;
3161 sc->wi_debug.wi_sigstate = 0;
3162 sc->wi_debug.wi_sigstate_param0 = 0;
3163 break;
3164 case WI_DEBUG_CONTRX0x10:
3165 sc->wi_debug.wi_contrx = 1;
3166 break;
3167 case WI_DEBUG_SIGSTATE0x11:
3168 param0 = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
3169 sc->wi_debug.wi_sigstate = 1;
3170 sc->wi_debug.wi_sigstate_param0 = param0;
3171 break;
3172 case WI_DEBUG_CONFBITS0x15:
3173 param0 = letoh16(wreq->wi_val[0])((__uint16_t)(wreq->wi_val[0]));
3174 param1 = letoh16(wreq->wi_val[1])((__uint16_t)(wreq->wi_val[1]));
3175 sc->wi_debug.wi_confbits = param0;
3176 sc->wi_debug.wi_confbits_param0 = param1;
3177 break;
3178 default:
3179 error = EIO5;
3180 break;
3181 }
3182
3183 if (error)
3184 return (error);
3185
3186 cmd = WI_CMD_DEBUG0x0038 | (wreq->wi_type << 8);
3187 error = wi_cmdsc->sc_funcs->f_cmd(sc, cmd, param0, param1, 0);
3188
3189 return (error);
3190}