Bug Summary

File:dev/pci/if_iwn.c
Warning:line 2634, column 2
Value stored to 'seq' is never read

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_iwn.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/pci/if_iwn.c
1/* $OpenBSD: if_iwn.c,v 1.254 2022/01/09 05:42:52 jsg Exp $ */
2
3/*-
4 * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network
21 * adapters.
22 */
23
24#include "bpfilter.h"
25
26#include <sys/param.h>
27#include <sys/sockio.h>
28#include <sys/mbuf.h>
29#include <sys/kernel.h>
30#include <sys/rwlock.h>
31#include <sys/socket.h>
32#include <sys/systm.h>
33#include <sys/malloc.h>
34#include <sys/conf.h>
35#include <sys/device.h>
36#include <sys/task.h>
37#include <sys/endian.h>
38
39#include <machine/bus.h>
40#include <machine/intr.h>
41
42#include <dev/pci/pcireg.h>
43#include <dev/pci/pcivar.h>
44#include <dev/pci/pcidevs.h>
45
46#if NBPFILTER1 > 0
47#include <net/bpf.h>
48#endif
49#include <net/if.h>
50#include <net/if_dl.h>
51#include <net/if_media.h>
52
53#include <netinet/in.h>
54#include <netinet/if_ether.h>
55
56#include <net80211/ieee80211_var.h>
57#include <net80211/ieee80211_amrr.h>
58#include <net80211/ieee80211_ra.h>
59#include <net80211/ieee80211_radiotap.h>
60#include <net80211/ieee80211_priv.h> /* for SEQ_LT */
61#undef DPRINTF /* defined in ieee80211_priv.h */
62
63#include <dev/pci/if_iwnreg.h>
64#include <dev/pci/if_iwnvar.h>
65
66static const struct pci_matchid iwn_devices[] = {
67 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_4965_10x4229 },
68 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_4965_20x4230 },
69 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5100_10x4232 },
70 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5100_20x4237 },
71 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5150_10x423c },
72 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5150_20x423d },
73 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5300_10x4235 },
74 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5300_20x4236 },
75 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5350_10x423a },
76 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_5350_20x423b },
77 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_1000_10x0083 },
78 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_1000_20x0084 },
79 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6300_10x422b },
80 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6300_20x4238 },
81 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6200_10x422c },
82 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6200_20x4239 },
83 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6050_10x0087 },
84 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6050_20x0089 },
85 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6005_10x0082 },
86 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6005_20x0085 },
87 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6030_10x0090 },
88 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6030_20x0091 },
89 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_1030_10x008a },
90 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_1030_20x008b },
91 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_100_10x08ae },
92 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_100_20x08af },
93 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_130_10x0896 },
94 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_130_20x0897 },
95 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6235_10x088e },
96 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_6235_20x088f },
97 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_2230_10x0887 },
98 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_2230_20x0888 },
99 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_2200_10x0890 },
100 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_2200_20x0891 },
101 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_135_10x0892 },
102 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_135_20x0893 },
103 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_105_10x0894 },
104 { PCI_VENDOR_INTEL0x8086, PCI_PRODUCT_INTEL_WL_105_20x0895 },
105};
106
107int iwn_match(struct device *, void *, void *);
108void iwn_attach(struct device *, struct device *, void *);
109int iwn4965_attach(struct iwn_softc *, pci_product_id_t);
110int iwn5000_attach(struct iwn_softc *, pci_product_id_t);
111#if NBPFILTER1 > 0
112void iwn_radiotap_attach(struct iwn_softc *);
113#endif
114int iwn_detach(struct device *, int);
115int iwn_activate(struct device *, int);
116void iwn_wakeup(struct iwn_softc *);
117void iwn_init_task(void *);
118int iwn_nic_lock(struct iwn_softc *);
119int iwn_eeprom_lock(struct iwn_softc *);
120int iwn_init_otprom(struct iwn_softc *);
121int iwn_read_prom_data(struct iwn_softc *, uint32_t, void *, int);
122int iwn_dma_contig_alloc(bus_dma_tag_t, struct iwn_dma_info *,
123 void **, bus_size_t, bus_size_t);
124void iwn_dma_contig_free(struct iwn_dma_info *);
125int iwn_alloc_sched(struct iwn_softc *);
126void iwn_free_sched(struct iwn_softc *);
127int iwn_alloc_kw(struct iwn_softc *);
128void iwn_free_kw(struct iwn_softc *);
129int iwn_alloc_ict(struct iwn_softc *);
130void iwn_free_ict(struct iwn_softc *);
131int iwn_alloc_fwmem(struct iwn_softc *);
132void iwn_free_fwmem(struct iwn_softc *);
133int iwn_alloc_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
134void iwn_reset_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
135void iwn_free_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
136int iwn_alloc_tx_ring(struct iwn_softc *, struct iwn_tx_ring *,
137 int);
138void iwn_reset_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
139void iwn_free_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
140void iwn5000_ict_reset(struct iwn_softc *);
141int iwn_read_eeprom(struct iwn_softc *);
142void iwn4965_read_eeprom(struct iwn_softc *);
143void iwn4965_print_power_group(struct iwn_softc *, int);
144void iwn5000_read_eeprom(struct iwn_softc *);
145void iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);
146void iwn_read_eeprom_enhinfo(struct iwn_softc *);
147struct ieee80211_node *iwn_node_alloc(struct ieee80211com *);
148void iwn_newassoc(struct ieee80211com *, struct ieee80211_node *,
149 int);
150int iwn_media_change(struct ifnet *);
151int iwn_newstate(struct ieee80211com *, enum ieee80211_state, int);
152void iwn_iter_func(void *, struct ieee80211_node *);
153void iwn_calib_timeout(void *);
154int iwn_ccmp_decap(struct iwn_softc *, struct mbuf *,
155 struct ieee80211_node *);
156void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,
157 struct iwn_rx_data *);
158void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *,
159 struct iwn_rx_data *, struct mbuf_list *);
160void iwn_ra_choose(struct iwn_softc *, struct ieee80211_node *);
161void iwn_ampdu_rate_control(struct iwn_softc *, struct ieee80211_node *,
162 struct iwn_tx_ring *, uint16_t, uint16_t);
163void iwn_ht_single_rate_control(struct iwn_softc *,
164 struct ieee80211_node *, uint8_t, uint8_t, uint8_t, int);
165void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *,
166 struct iwn_rx_data *);
167void iwn5000_rx_calib_results(struct iwn_softc *,
168 struct iwn_rx_desc *, struct iwn_rx_data *);
169void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *,
170 struct iwn_rx_data *);
171void iwn_ampdu_txq_advance(struct iwn_softc *, struct iwn_tx_ring *,
172 int, int);
173void iwn_ampdu_tx_done(struct iwn_softc *, struct iwn_tx_ring *,
174 struct iwn_rx_desc *, uint16_t, uint8_t, uint8_t, uint8_t,
175 int, uint32_t, struct iwn_txagg_status *);
176void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
177 struct iwn_rx_data *);
178void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
179 struct iwn_rx_data *);
180void iwn_tx_done_free_txdata(struct iwn_softc *,
181 struct iwn_tx_data *);
182void iwn_clear_oactive(struct iwn_softc *, struct iwn_tx_ring *);
183void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
184 uint8_t, uint8_t, uint8_t, int, int, uint16_t);
185void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *);
186void iwn_notif_intr(struct iwn_softc *);
187void iwn_wakeup_intr(struct iwn_softc *);
188void iwn_fatal_intr(struct iwn_softc *);
189int iwn_intr(void *);
190void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t,
191 uint16_t);
192void iwn4965_reset_sched(struct iwn_softc *, int, int);
193void iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,
194 uint16_t);
195void iwn5000_reset_sched(struct iwn_softc *, int, int);
196int iwn_tx(struct iwn_softc *, struct mbuf *,
197 struct ieee80211_node *);
198int iwn_rval2ridx(int);
199void iwn_start(struct ifnet *);
200void iwn_watchdog(struct ifnet *);
201int iwn_ioctl(struct ifnet *, u_long, caddr_t);
202int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
203int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
204 int);
205int iwn5000_add_node(struct iwn_softc *, struct iwn_node_info *,
206 int);
207int iwn_set_link_quality(struct iwn_softc *,
208 struct ieee80211_node *);
209int iwn_add_broadcast_node(struct iwn_softc *, int, int);
210void iwn_updateedca(struct ieee80211com *);
211void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);
212int iwn_set_critical_temp(struct iwn_softc *);
213int iwn_set_timing(struct iwn_softc *, struct ieee80211_node *);
214void iwn4965_power_calibration(struct iwn_softc *, int);
215int iwn4965_set_txpower(struct iwn_softc *, int);
216int iwn5000_set_txpower(struct iwn_softc *, int);
217int iwn4965_get_rssi(const struct iwn_rx_stat *);
218int iwn5000_get_rssi(const struct iwn_rx_stat *);
219int iwn_get_noise(const struct iwn_rx_general_stats *);
220int iwn4965_get_temperature(struct iwn_softc *);
221int iwn5000_get_temperature(struct iwn_softc *);
222int iwn_init_sensitivity(struct iwn_softc *);
223void iwn_collect_noise(struct iwn_softc *,
224 const struct iwn_rx_general_stats *);
225int iwn4965_init_gains(struct iwn_softc *);
226int iwn5000_init_gains(struct iwn_softc *);
227int iwn4965_set_gains(struct iwn_softc *);
228int iwn5000_set_gains(struct iwn_softc *);
229void iwn_tune_sensitivity(struct iwn_softc *,
230 const struct iwn_rx_stats *);
231int iwn_send_sensitivity(struct iwn_softc *);
232int iwn_set_pslevel(struct iwn_softc *, int, int, int);
233int iwn_send_temperature_offset(struct iwn_softc *);
234int iwn_send_btcoex(struct iwn_softc *);
235int iwn_send_advanced_btcoex(struct iwn_softc *);
236int iwn5000_runtime_calib(struct iwn_softc *);
237int iwn_config(struct iwn_softc *);
238uint16_t iwn_get_active_dwell_time(struct iwn_softc *, uint16_t, uint8_t);
239uint16_t iwn_limit_dwell(struct iwn_softc *, uint16_t);
240uint16_t iwn_get_passive_dwell_time(struct iwn_softc *, uint16_t);
241int iwn_scan(struct iwn_softc *, uint16_t, int);
242void iwn_scan_abort(struct iwn_softc *);
243int iwn_bgscan(struct ieee80211com *);
244void iwn_rxon_configure_ht40(struct ieee80211com *,
245 struct ieee80211_node *);
246int iwn_rxon_ht40_enabled(struct iwn_softc *);
247int iwn_auth(struct iwn_softc *, int);
248int iwn_run(struct iwn_softc *);
249int iwn_set_key(struct ieee80211com *, struct ieee80211_node *,
250 struct ieee80211_key *);
251void iwn_delete_key(struct ieee80211com *, struct ieee80211_node *,
252 struct ieee80211_key *);
253void iwn_updatechan(struct ieee80211com *);
254void iwn_updateprot(struct ieee80211com *);
255void iwn_updateslot(struct ieee80211com *);
256void iwn_update_rxon_restore_power(struct iwn_softc *);
257void iwn5000_update_rxon(struct iwn_softc *);
258void iwn4965_update_rxon(struct iwn_softc *);
259int iwn_ampdu_rx_start(struct ieee80211com *,
260 struct ieee80211_node *, uint8_t);
261void iwn_ampdu_rx_stop(struct ieee80211com *,
262 struct ieee80211_node *, uint8_t);
263int iwn_ampdu_tx_start(struct ieee80211com *,
264 struct ieee80211_node *, uint8_t);
265void iwn_ampdu_tx_stop(struct ieee80211com *,
266 struct ieee80211_node *, uint8_t);
267void iwn4965_ampdu_tx_start(struct iwn_softc *,
268 struct ieee80211_node *, uint8_t, uint16_t);
269void iwn4965_ampdu_tx_stop(struct iwn_softc *,
270 uint8_t, uint16_t);
271void iwn5000_ampdu_tx_start(struct iwn_softc *,
272 struct ieee80211_node *, uint8_t, uint16_t);
273void iwn5000_ampdu_tx_stop(struct iwn_softc *,
274 uint8_t, uint16_t);
275int iwn5000_query_calibration(struct iwn_softc *);
276int iwn5000_send_calibration(struct iwn_softc *);
277int iwn5000_send_wimax_coex(struct iwn_softc *);
278int iwn5000_crystal_calib(struct iwn_softc *);
279int iwn6000_temp_offset_calib(struct iwn_softc *);
280int iwn2000_temp_offset_calib(struct iwn_softc *);
281int iwn4965_post_alive(struct iwn_softc *);
282int iwn5000_post_alive(struct iwn_softc *);
283int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
284 int);
285int iwn4965_load_firmware(struct iwn_softc *);
286int iwn5000_load_firmware_section(struct iwn_softc *, uint32_t,
287 const uint8_t *, int);
288int iwn5000_load_firmware(struct iwn_softc *);
289int iwn_read_firmware_leg(struct iwn_softc *,
290 struct iwn_fw_info *);
291int iwn_read_firmware_tlv(struct iwn_softc *,
292 struct iwn_fw_info *, uint16_t);
293int iwn_read_firmware(struct iwn_softc *);
294int iwn_clock_wait(struct iwn_softc *);
295int iwn_apm_init(struct iwn_softc *);
296void iwn_apm_stop_master(struct iwn_softc *);
297void iwn_apm_stop(struct iwn_softc *);
298int iwn4965_nic_config(struct iwn_softc *);
299int iwn5000_nic_config(struct iwn_softc *);
300int iwn_hw_prepare(struct iwn_softc *);
301int iwn_hw_init(struct iwn_softc *);
302void iwn_hw_stop(struct iwn_softc *);
303int iwn_init(struct ifnet *);
304void iwn_stop(struct ifnet *);
305
306#ifdef IWN_DEBUG
307#define DPRINTF(x) do { if (iwn_debug > 0) printf x; } while (0)
308#define DPRINTFN(n, x) do { if (iwn_debug >= (n)) printf x; } while (0)
309int iwn_debug = 1;
310#else
311#define DPRINTF(x)
312#define DPRINTFN(n, x)
313#endif
314
315struct cfdriver iwn_cd = {
316 NULL((void *)0), "iwn", DV_IFNET
317};
318
319struct cfattach iwn_ca = {
320 sizeof (struct iwn_softc), iwn_match, iwn_attach, iwn_detach,
321 iwn_activate
322};
323
324int
325iwn_match(struct device *parent, void *match, void *aux)
326{
327 return pci_matchbyid((struct pci_attach_args *)aux, iwn_devices,
328 nitems(iwn_devices)(sizeof((iwn_devices)) / sizeof((iwn_devices)[0])));
329}
330
331void
332iwn_attach(struct device *parent, struct device *self, void *aux)
333{
334 struct iwn_softc *sc = (struct iwn_softc *)self;
335 struct ieee80211com *ic = &sc->sc_ic;
336 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
337 struct pci_attach_args *pa = aux;
338 const char *intrstr;
339 pci_intr_handle_t ih;
340 pcireg_t memtype, reg;
341 int i, error;
342
343 sc->sc_pct = pa->pa_pc;
344 sc->sc_pcitag = pa->pa_tag;
345 sc->sc_dmat = pa->pa_dmat;
346
347 /*
348 * Get the offset of the PCI Express Capability Structure in PCI
349 * Configuration Space.
350 */
351 error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
352 PCI_CAP_PCIEXPRESS0x10, &sc->sc_cap_off, NULL((void *)0));
353 if (error == 0) {
354 printf(": PCIe capability structure not found!\n");
355 return;
356 }
357
358 /* Clear device-specific "PCI retry timeout" register (41h). */
359 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
360 if (reg & 0xff00)
361 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
362
363 /* Hardware bug workaround. */
364 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG0x04);
365 if (reg & PCI_COMMAND_INTERRUPT_DISABLE0x00000400) {
366 DPRINTF(("PCIe INTx Disable set\n"));
367 reg &= ~PCI_COMMAND_INTERRUPT_DISABLE0x00000400;
368 pci_conf_write(sc->sc_pct, sc->sc_pcitag,
369 PCI_COMMAND_STATUS_REG0x04, reg);
370 }
371
372 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, IWN_PCI_BAR00x10);
373 error = pci_mapreg_map(pa, IWN_PCI_BAR00x10, memtype, 0, &sc->sc_st,
374 &sc->sc_sh, NULL((void *)0), &sc->sc_sz, 0);
375 if (error != 0) {
376 printf(": can't map mem space\n");
377 return;
378 }
379
380 /* Install interrupt handler. */
381 if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
382 printf(": can't map interrupt\n");
383 return;
384 }
385 intrstr = pci_intr_string(sc->sc_pct, ih);
386 sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET0x7, iwn_intr, sc,
387 sc->sc_dev.dv_xname);
388 if (sc->sc_ih == NULL((void *)0)) {
389 printf(": can't establish interrupt");
390 if (intrstr != NULL((void *)0))
391 printf(" at %s", intrstr);
392 printf("\n");
393 return;
394 }
395 printf(": %s", intrstr);
396
397 /* Read hardware revision and attach. */
398 sc->hw_type = (IWN_READ(sc, IWN_HW_REV)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x028)))) >> 4) & 0x1f;
399 if (sc->hw_type == IWN_HW_REV_TYPE_49650)
400 error = iwn4965_attach(sc, PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff));
401 else
402 error = iwn5000_attach(sc, PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff));
403 if (error != 0) {
404 printf(": could not attach device\n");
405 return;
406 }
407
408 if ((error = iwn_hw_prepare(sc)) != 0) {
409 printf(": hardware not ready\n");
410 return;
411 }
412
413 /* Read MAC address, channels, etc from EEPROM. */
414 if ((error = iwn_read_eeprom(sc)) != 0) {
415 printf(": could not read EEPROM\n");
416 return;
417 }
418
419 /* Allocate DMA memory for firmware transfers. */
420 if ((error = iwn_alloc_fwmem(sc)) != 0) {
421 printf(": could not allocate memory for firmware\n");
422 return;
423 }
424
425 /* Allocate "Keep Warm" page. */
426 if ((error = iwn_alloc_kw(sc)) != 0) {
427 printf(": could not allocate keep warm page\n");
428 goto fail1;
429 }
430
431 /* Allocate ICT table for 5000 Series. */
432 if (sc->hw_type != IWN_HW_REV_TYPE_49650 &&
433 (error = iwn_alloc_ict(sc)) != 0) {
434 printf(": could not allocate ICT table\n");
435 goto fail2;
436 }
437
438 /* Allocate TX scheduler "rings". */
439 if ((error = iwn_alloc_sched(sc)) != 0) {
440 printf(": could not allocate TX scheduler rings\n");
441 goto fail3;
442 }
443
444 /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */
445 for (i = 0; i < sc->ntxqs; i++) {
446 if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
447 printf(": could not allocate TX ring %d\n", i);
448 goto fail4;
449 }
450 }
451
452 /* Allocate RX ring. */
453 if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {
454 printf(": could not allocate RX ring\n");
455 goto fail4;
456 }
457
458 /* Clear pending interrupts. */
459 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
460
461 /* Count the number of available chains. */
462 sc->ntxchains =
463 ((sc->txchainmask >> 2) & 1) +
464 ((sc->txchainmask >> 1) & 1) +
465 ((sc->txchainmask >> 0) & 1);
466 sc->nrxchains =
467 ((sc->rxchainmask >> 2) & 1) +
468 ((sc->rxchainmask >> 1) & 1) +
469 ((sc->rxchainmask >> 0) & 1);
470 printf(", MIMO %dT%dR, %.4s, address %s\n", sc->ntxchains,
471 sc->nrxchains, sc->eeprom_domain, ether_sprintf(ic->ic_myaddr));
472
473 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
474 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
475 ic->ic_state = IEEE80211_S_INIT;
476
477 /* Set device capabilities. */
478 ic->ic_caps =
479 IEEE80211_C_WEP0x00000001 | /* WEP */
480 IEEE80211_C_RSN0x00001000 | /* WPA/RSN */
481 IEEE80211_C_SCANALL0x00000400 | /* device scans all channels at once */
482 IEEE80211_C_SCANALLBAND0x00008000 | /* driver scans all bands at once */
483 IEEE80211_C_MONITOR0x00000200 | /* monitor mode supported */
484 IEEE80211_C_SHSLOT0x00000080 | /* short slot time supported */
485 IEEE80211_C_SHPREAMBLE0x00000100 | /* short preamble supported */
486 IEEE80211_C_PMGT0x00000004; /* power saving supported */
487
488 /* No optional HT features supported for now, */
489 ic->ic_htcaps = 0;
490 ic->ic_htxcaps = 0;
491 ic->ic_txbfcaps = 0;
492 ic->ic_aselcaps = 0;
493 ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4(5 << 2) | 0x3 /* 64k */);
494 if (sc->sc_flags & IWN_FLAG_HAS_11N(1 << 6)) {
495 ic->ic_caps |= (IEEE80211_C_QOS0x00000800 | IEEE80211_C_TX_AMPDU0x00010000);
496 /* Set HT capabilities. */
497 ic->ic_htcaps = IEEE80211_HTCAP_SGI200x00000020;
498 /* 6200 devices have issues with SGI40 for some reason. */
499 if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA(1 << 4)) == 0)
500 ic->ic_htcaps |= IEEE80211_HTCAP_SGI400x00000040;
501 ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_400x00000002;
502#ifdef notyet
503 ic->ic_htcaps |=
504#if IWN_RBUF_SIZE(4 * 1024) == 8192
505 IEEE80211_HTCAP_AMSDU79350x00000800 |
506#endif
507 if (sc->hw_type != IWN_HW_REV_TYPE_49650)
508 ic->ic_htcaps |= IEEE80211_HTCAP_GF0x00000010;
509 if (sc->hw_type == IWN_HW_REV_TYPE_60508)
510 ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DYN1;
511 else
512 ic->ic_htcaps |= IEEE80211_HTCAP_SMPS_DIS3;
513#endif /* notyet */
514 }
515
516 /* Set supported legacy rates. */
517 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
518 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
519 if (sc->sc_flags & IWN_FLAG_HAS_5GHZ(1 << 0)) {
520 ic->ic_sup_rates[IEEE80211_MODE_11A] =
521 ieee80211_std_rateset_11a;
522 }
523 if (sc->sc_flags & IWN_FLAG_HAS_11N(1 << 6)) {
524 /* Set supported HT rates. */
525 ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */
526#ifdef notyet
527 if (sc->nrxchains > 1)
528 ic->ic_sup_mcs[1] = 0xff; /* MCS 8-15 */
529 if (sc->nrxchains > 2)
530 ic->ic_sup_mcs[2] = 0xff; /* MCS 16-23 */
531#endif
532 }
533
534 /* IBSS channel undefined for now. */
535 ic->ic_ibss_chan = &ic->ic_channels[0];
536
537 ifp->if_softc = sc;
538 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
539 ifp->if_ioctl = iwn_ioctl;
540 ifp->if_start = iwn_start;
541 ifp->if_watchdog = iwn_watchdog;
542 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
543
544 if_attach(ifp);
545 ieee80211_ifattach(ifp);
546 ic->ic_node_alloc = iwn_node_alloc;
547 ic->ic_bgscan_start = iwn_bgscan;
548 ic->ic_newassoc = iwn_newassoc;
549 ic->ic_updateedca = iwn_updateedca;
550 ic->ic_set_key = iwn_set_key;
551 ic->ic_delete_key = iwn_delete_key;
552 ic->ic_updatechan = iwn_updatechan;
553 ic->ic_updateprot = iwn_updateprot;
554 ic->ic_updateslot = iwn_updateslot;
555 ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
556 ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
557 ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;
558 ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop;
559
560 /* Override 802.11 state transition machine. */
561 sc->sc_newstate = ic->ic_newstate;
562 ic->ic_newstate = iwn_newstate;
563 ieee80211_media_init(ifp, iwn_media_change, ieee80211_media_status);
564
565 sc->amrr.amrr_min_success_threshold = 1;
566 sc->amrr.amrr_max_success_threshold = 15;
567
568#if NBPFILTER1 > 0
569 iwn_radiotap_attach(sc);
570#endif
571 timeout_set(&sc->calib_to, iwn_calib_timeout, sc);
572 rw_init(&sc->sc_rwlock, "iwnlock")_rw_init_flags(&sc->sc_rwlock, "iwnlock", 0, ((void *)
0))
;
573 task_set(&sc->init_task, iwn_init_task, sc);
574 return;
575
576 /* Free allocated memory if something failed during attachment. */
577fail4: while (--i >= 0)
578 iwn_free_tx_ring(sc, &sc->txq[i]);
579 iwn_free_sched(sc);
580fail3: if (sc->ict != NULL((void *)0))
581 iwn_free_ict(sc);
582fail2: iwn_free_kw(sc);
583fail1: iwn_free_fwmem(sc);
584}
585
586int
587iwn4965_attach(struct iwn_softc *sc, pci_product_id_t pid)
588{
589 struct iwn_ops *ops = &sc->ops;
590
591 ops->load_firmware = iwn4965_load_firmware;
592 ops->read_eeprom = iwn4965_read_eeprom;
593 ops->post_alive = iwn4965_post_alive;
594 ops->nic_config = iwn4965_nic_config;
595 ops->reset_sched = iwn4965_reset_sched;
596 ops->update_sched = iwn4965_update_sched;
597 ops->update_rxon = iwn4965_update_rxon;
598 ops->get_temperature = iwn4965_get_temperature;
599 ops->get_rssi = iwn4965_get_rssi;
600 ops->set_txpower = iwn4965_set_txpower;
601 ops->init_gains = iwn4965_init_gains;
602 ops->set_gains = iwn4965_set_gains;
603 ops->add_node = iwn4965_add_node;
604 ops->tx_done = iwn4965_tx_done;
605 ops->ampdu_tx_start = iwn4965_ampdu_tx_start;
606 ops->ampdu_tx_stop = iwn4965_ampdu_tx_stop;
607 sc->ntxqs = IWN4965_NTXQUEUES16;
608 sc->first_agg_txq = IWN4965_FIRST_AGG_TXQUEUE7;
609 sc->ndmachnls = IWN4965_NDMACHNLS7;
610 sc->broadcast_id = IWN4965_ID_BROADCAST31;
611 sc->rxonsz = IWN4965_RXONSZ(sizeof (struct iwn_rxon) - 6);
612 sc->schedsz = IWN4965_SCHEDSZ(16 * 512 * 2);
613 sc->fw_text_maxsz = IWN4965_FW_TEXT_MAXSZ( 96 * 1024);
614 sc->fw_data_maxsz = IWN4965_FW_DATA_MAXSZ( 40 * 1024);
615 sc->fwsz = IWN4965_FWSZ(( 96 * 1024) + ( 40 * 1024));
616 sc->sched_txfact_addr = IWN4965_SCHED_TXFACT(0xa02c00 + 0x01c);
617 sc->limits = &iwn4965_sensitivity_limits;
618 sc->fwname = "iwn-4965";
619 /* Override chains masks, ROM is known to be broken. */
620 sc->txchainmask = IWN_ANT_AB((1 << 0) | (1 << 1));
621 sc->rxchainmask = IWN_ANT_ABC((1 << 0) | (1 << 1) | (1 << 2));
622
623 return 0;
624}
625
626int
627iwn5000_attach(struct iwn_softc *sc, pci_product_id_t pid)
628{
629 struct iwn_ops *ops = &sc->ops;
630
631 ops->load_firmware = iwn5000_load_firmware;
632 ops->read_eeprom = iwn5000_read_eeprom;
633 ops->post_alive = iwn5000_post_alive;
634 ops->nic_config = iwn5000_nic_config;
635 ops->reset_sched = iwn5000_reset_sched;
636 ops->update_sched = iwn5000_update_sched;
637 ops->update_rxon = iwn5000_update_rxon;
638 ops->get_temperature = iwn5000_get_temperature;
639 ops->get_rssi = iwn5000_get_rssi;
640 ops->set_txpower = iwn5000_set_txpower;
641 ops->init_gains = iwn5000_init_gains;
642 ops->set_gains = iwn5000_set_gains;
643 ops->add_node = iwn5000_add_node;
644 ops->tx_done = iwn5000_tx_done;
645 ops->ampdu_tx_start = iwn5000_ampdu_tx_start;
646 ops->ampdu_tx_stop = iwn5000_ampdu_tx_stop;
647 sc->ntxqs = IWN5000_NTXQUEUES20;
648 sc->first_agg_txq = IWN5000_FIRST_AGG_TXQUEUE10;
649 sc->ndmachnls = IWN5000_NDMACHNLS8;
650 sc->broadcast_id = IWN5000_ID_BROADCAST15;
651 sc->rxonsz = IWN5000_RXONSZ(sizeof (struct iwn_rxon));
652 sc->schedsz = IWN5000_SCHEDSZ(20 * (256 + 64) * 2);
653 sc->fw_text_maxsz = IWN5000_FW_TEXT_MAXSZ(256 * 1024);
654 sc->fw_data_maxsz = IWN5000_FW_DATA_MAXSZ( 80 * 1024);
655 sc->fwsz = IWN5000_FWSZ(256 * 1024);
656 sc->sched_txfact_addr = IWN5000_SCHED_TXFACT(0xa02c00 + 0x010);
657
658 switch (sc->hw_type) {
659 case IWN_HW_REV_TYPE_51005:
660 sc->limits = &iwn5000_sensitivity_limits;
661 sc->fwname = "iwn-5000";
662 /* Override chains masks, ROM is known to be broken. */
663 sc->txchainmask = IWN_ANT_B(1 << 1);
664 sc->rxchainmask = IWN_ANT_AB((1 << 0) | (1 << 1));
665 break;
666 case IWN_HW_REV_TYPE_51504:
667 sc->limits = &iwn5150_sensitivity_limits;
668 sc->fwname = "iwn-5150";
669 break;
670 case IWN_HW_REV_TYPE_53002:
671 case IWN_HW_REV_TYPE_53503:
672 sc->limits = &iwn5000_sensitivity_limits;
673 sc->fwname = "iwn-5000";
674 break;
675 case IWN_HW_REV_TYPE_10006:
676 sc->limits = &iwn1000_sensitivity_limits;
677 sc->fwname = "iwn-1000";
678 break;
679 case IWN_HW_REV_TYPE_60007:
680 sc->limits = &iwn6000_sensitivity_limits;
681 sc->fwname = "iwn-6000";
682 if (pid == PCI_PRODUCT_INTEL_WL_6200_10x422c ||
683 pid == PCI_PRODUCT_INTEL_WL_6200_20x4239) {
684 sc->sc_flags |= IWN_FLAG_INTERNAL_PA(1 << 4);
685 /* Override chains masks, ROM is known to be broken. */
686 sc->txchainmask = IWN_ANT_BC((1 << 1) | (1 << 2));
687 sc->rxchainmask = IWN_ANT_BC((1 << 1) | (1 << 2));
688 }
689 break;
690 case IWN_HW_REV_TYPE_60508:
691 sc->limits = &iwn6000_sensitivity_limits;
692 sc->fwname = "iwn-6050";
693 break;
694 case IWN_HW_REV_TYPE_600511:
695 sc->limits = &iwn6000_sensitivity_limits;
696 if (pid != PCI_PRODUCT_INTEL_WL_6005_10x0082 &&
697 pid != PCI_PRODUCT_INTEL_WL_6005_20x0085) {
698 sc->fwname = "iwn-6030";
699 sc->sc_flags |= IWN_FLAG_ADV_BT_COEX(1 << 8);
700 } else
701 sc->fwname = "iwn-6005";
702 break;
703 case IWN_HW_REV_TYPE_203012:
704 sc->limits = &iwn2000_sensitivity_limits;
705 sc->fwname = "iwn-2030";
706 sc->sc_flags |= IWN_FLAG_ADV_BT_COEX(1 << 8);
707 break;
708 case IWN_HW_REV_TYPE_200016:
709 sc->limits = &iwn2000_sensitivity_limits;
710 sc->fwname = "iwn-2000";
711 break;
712 case IWN_HW_REV_TYPE_13518:
713 sc->limits = &iwn2000_sensitivity_limits;
714 sc->fwname = "iwn-135";
715 sc->sc_flags |= IWN_FLAG_ADV_BT_COEX(1 << 8);
716 break;
717 case IWN_HW_REV_TYPE_10517:
718 sc->limits = &iwn2000_sensitivity_limits;
719 sc->fwname = "iwn-105";
720 break;
721 default:
722 printf(": adapter type %d not supported\n", sc->hw_type);
723 return ENOTSUP91;
724 }
725 return 0;
726}
727
728#if NBPFILTER1 > 0
729/*
730 * Attach the interface to 802.11 radiotap.
731 */
732void
733iwn_radiotap_attach(struct iwn_softc *sc)
734{
735 bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_ific_ac.ac_if, DLT_IEEE802_11_RADIO127,
736 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
737
738 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
739 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
740 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(IWN_RX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_TSFT) | (1 <<
IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE
) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL
) | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE))))
;
741
742 sc->sc_txtap_len = sizeof sc->sc_txtapu;
743 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
744 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(IWN_TX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL
))))
;
745}
746#endif
747
748int
749iwn_detach(struct device *self, int flags)
750{
751 struct iwn_softc *sc = (struct iwn_softc *)self;
752 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
753 int qid;
754
755 timeout_del(&sc->calib_to);
756 task_del(systq, &sc->init_task);
757
758 /* Uninstall interrupt handler. */
759 if (sc->sc_ih != NULL((void *)0))
760 pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
761
762 /* Free DMA resources. */
763 iwn_free_rx_ring(sc, &sc->rxq);
764 for (qid = 0; qid < sc->ntxqs; qid++)
765 iwn_free_tx_ring(sc, &sc->txq[qid]);
766 iwn_free_sched(sc);
767 iwn_free_kw(sc);
768 if (sc->ict != NULL((void *)0))
769 iwn_free_ict(sc);
770 iwn_free_fwmem(sc);
771
772 bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
773
774 ieee80211_ifdetach(ifp);
775 if_detach(ifp);
776
777 return 0;
778}
779
780int
781iwn_activate(struct device *self, int act)
782{
783 struct iwn_softc *sc = (struct iwn_softc *)self;
784 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
785
786 switch (act) {
787 case DVACT_SUSPEND3:
788 if (ifp->if_flags & IFF_RUNNING0x40)
789 iwn_stop(ifp);
790 break;
791 case DVACT_WAKEUP5:
792 iwn_wakeup(sc);
793 break;
794 }
795
796 return 0;
797}
798
799void
800iwn_wakeup(struct iwn_softc *sc)
801{
802 pcireg_t reg;
803
804 /* Clear device-specific "PCI retry timeout" register (41h). */
805 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
806 if (reg & 0xff00)
807 pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg & ~0xff00);
808 iwn_init_task(sc);
809}
810
811void
812iwn_init_task(void *arg1)
813{
814 struct iwn_softc *sc = arg1;
815 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
816 int s;
817
818 rw_enter_write(&sc->sc_rwlock);
819 s = splnet()splraise(0x7);
820
821 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == IFF_UP0x1)
822 iwn_init(ifp);
823
824 splx(s)spllower(s);
825 rw_exit_write(&sc->sc_rwlock);
826}
827
828int
829iwn_nic_lock(struct iwn_softc *sc)
830{
831 int ntries;
832
833 /* Request exclusive access to NIC. */
834 IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x024)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) | (
(1 << 3))))))
;
835
836 /* Spin until we actually get the lock. */
837 for (ntries = 0; ntries < 1000; ntries++) {
838 if ((IWN_READ(sc, IWN_GP_CNTRL)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) &
839 (IWN_GP_CNTRL_MAC_ACCESS_ENA(1 << 0) | IWN_GP_CNTRL_SLEEP(1 << 4))) ==
840 IWN_GP_CNTRL_MAC_ACCESS_ENA(1 << 0))
841 return 0;
842 DELAY(10)(*delay_func)(10);
843 }
844 return ETIMEDOUT60;
845}
846
847static __inline void
848iwn_nic_unlock(struct iwn_softc *sc)
849{
850 IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x024)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) &
~((1 << 3))))))
;
851}
852
853static __inline uint32_t
854iwn_prph_read(struct iwn_softc *sc, uint32_t addr)
855{
856 IWN_WRITE(sc, IWN_PRPH_RADDR, IWN_PRPH_DWORD | addr)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x448)), ((
((sizeof (uint32_t) - 1) << 24) | addr))))
;
857 IWN_BARRIER_READ_WRITE(sc)bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->
sc_sz, 0x01 | 0x02)
;
858 return IWN_READ(sc, IWN_PRPH_RDATA)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x450))));
859}
860
861static __inline void
862iwn_prph_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)
863{
864 IWN_WRITE(sc, IWN_PRPH_WADDR, IWN_PRPH_DWORD | addr)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x444)), ((
((sizeof (uint32_t) - 1) << 24) | addr))))
;
865 IWN_BARRIER_WRITE(sc)bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->
sc_sz, 0x02)
;
866 IWN_WRITE(sc, IWN_PRPH_WDATA, data)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x44c)), ((
data))))
;
867}
868
869static __inline void
870iwn_prph_setbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)
871{
872 iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) | mask);
873}
874
875static __inline void
876iwn_prph_clrbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)
877{
878 iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) & ~mask);
879}
880
881static __inline void
882iwn_prph_write_region_4(struct iwn_softc *sc, uint32_t addr,
883 const uint32_t *data, int count)
884{
885 for (; count > 0; count--, data++, addr += 4)
886 iwn_prph_write(sc, addr, *data);
887}
888
889static __inline uint32_t
890iwn_mem_read(struct iwn_softc *sc, uint32_t addr)
891{
892 IWN_WRITE(sc, IWN_MEM_RADDR, addr)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x40c)), ((
addr))))
;
893 IWN_BARRIER_READ_WRITE(sc)bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->
sc_sz, 0x01 | 0x02)
;
894 return IWN_READ(sc, IWN_MEM_RDATA)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x41c))));
895}
896
897static __inline void
898iwn_mem_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)
899{
900 IWN_WRITE(sc, IWN_MEM_WADDR, addr)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x410)), ((
addr))))
;
901 IWN_BARRIER_WRITE(sc)bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->
sc_sz, 0x02)
;
902 IWN_WRITE(sc, IWN_MEM_WDATA, data)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x418)), ((
data))))
;
903}
904
905static __inline void
906iwn_mem_write_2(struct iwn_softc *sc, uint32_t addr, uint16_t data)
907{
908 uint32_t tmp;
909
910 tmp = iwn_mem_read(sc, addr & ~3);
911 if (addr & 3)
912 tmp = (tmp & 0x0000ffff) | data << 16;
913 else
914 tmp = (tmp & 0xffff0000) | data;
915 iwn_mem_write(sc, addr & ~3, tmp);
916}
917
918static __inline void
919iwn_mem_read_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t *data,
920 int count)
921{
922 for (; count > 0; count--, addr += 4)
923 *data++ = iwn_mem_read(sc, addr);
924}
925
926static __inline void
927iwn_mem_set_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t val,
928 int count)
929{
930 for (; count > 0; count--, addr += 4)
931 iwn_mem_write(sc, addr, val);
932}
933
934int
935iwn_eeprom_lock(struct iwn_softc *sc)
936{
937 int i, ntries;
938
939 for (i = 0; i < 100; i++) {
940 /* Request exclusive access to EEPROM. */
941 IWN_SETBITS(sc, IWN_HW_IF_CONFIG,(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 21))))))
942 IWN_HW_IF_CONFIG_EEPROM_LOCKED)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 21))))))
;
943
944 /* Spin until we actually get the lock. */
945 for (ntries = 0; ntries < 100; ntries++) {
946 if (IWN_READ(sc, IWN_HW_IF_CONFIG)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) &
947 IWN_HW_IF_CONFIG_EEPROM_LOCKED(1 << 21))
948 return 0;
949 DELAY(10)(*delay_func)(10);
950 }
951 }
952 return ETIMEDOUT60;
953}
954
955static __inline void
956iwn_eeprom_unlock(struct iwn_softc *sc)
957{
958 IWN_CLRBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_EEPROM_LOCKED)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) &
~((1 << 21))))))
;
959}
960
961/*
962 * Initialize access by host to One Time Programmable ROM.
963 * NB: This kind of ROM can be found on 1000 or 6000 Series only.
964 */
965int
966iwn_init_otprom(struct iwn_softc *sc)
967{
968 uint16_t prev, base, next;
969 int count, error;
970
971 /* Wait for clock stabilization before accessing prph. */
972 if ((error = iwn_clock_wait(sc)) != 0)
973 return error;
974
975 if ((error = iwn_nic_lock(sc)) != 0)
976 return error;
977 iwn_prph_setbits(sc, IWN_APMG_PS0x300c, IWN_APMG_PS_RESET_REQ(1 << 26));
978 DELAY(5)(*delay_func)(5);
979 iwn_prph_clrbits(sc, IWN_APMG_PS0x300c, IWN_APMG_PS_RESET_REQ(1 << 26));
980 iwn_nic_unlock(sc);
981
982 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
983 if (sc->hw_type != IWN_HW_REV_TYPE_10006) {
984 IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT,(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x250)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x250)))) | (
(1U << 31))))))
985 IWN_RESET_LINK_PWR_MGMT_DIS)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x250)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x250)))) | (
(1U << 31))))))
;
986 }
987 IWN_CLRBITS(sc, IWN_EEPROM_GP, IWN_EEPROM_GP_IF_OWNER)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x030)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x030)))) &
~(0x00000180)))))
;
988 /* Clear ECC status. */
989 IWN_SETBITS(sc, IWN_OTP_GP,(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x034)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) | (
(1 << 20) | (1 << 21))))))
990 IWN_OTP_GP_ECC_CORR_STTS | IWN_OTP_GP_ECC_UNCORR_STTS)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x034)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) | (
(1 << 20) | (1 << 21))))))
;
991
992 /*
993 * Find the block before last block (contains the EEPROM image)
994 * for HW without OTP shadow RAM.
995 */
996 if (sc->hw_type == IWN_HW_REV_TYPE_10006) {
997 /* Switch to absolute addressing mode. */
998 IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x034)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) &
~((1 << 17))))))
;
999 base = 0;
1000 for (count = 0; count < IWN1000_OTP_NBLOCKS3; count++) {
1001 error = iwn_read_prom_data(sc, base, &next, 2);
1002 if (error != 0)
1003 return error;
1004 if (next == 0) /* End of linked-list. */
1005 break;
1006 prev = base;
1007 base = letoh16(next)((__uint16_t)(next));
1008 }
1009 if (count == 0 || count == IWN1000_OTP_NBLOCKS3)
1010 return EIO5;
1011 /* Skip "next" word. */
1012 sc->prom_base = prev + 1;
1013 }
1014 return 0;
1015}
1016
1017int
1018iwn_read_prom_data(struct iwn_softc *sc, uint32_t addr, void *data, int count)
1019{
1020 uint8_t *out = data;
1021 uint32_t val, tmp;
1022 int ntries;
1023
1024 addr += sc->prom_base;
1025 for (; count > 0; count -= 2, addr++) {
1026 IWN_WRITE(sc, IWN_EEPROM, addr << 2)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x02c)), ((
addr << 2))))
;
1027 for (ntries = 0; ntries < 10; ntries++) {
1028 val = IWN_READ(sc, IWN_EEPROM)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x02c))));
1029 if (val & IWN_EEPROM_READ_VALID(1 << 0))
1030 break;
1031 DELAY(5)(*delay_func)(5);
1032 }
1033 if (ntries == 10) {
1034 printf("%s: timeout reading ROM at 0x%x\n",
1035 sc->sc_dev.dv_xname, addr);
1036 return ETIMEDOUT60;
1037 }
1038 if (sc->sc_flags & IWN_FLAG_HAS_OTPROM(1 << 1)) {
1039 /* OTPROM, check for ECC errors. */
1040 tmp = IWN_READ(sc, IWN_OTP_GP)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034))));
1041 if (tmp & IWN_OTP_GP_ECC_UNCORR_STTS(1 << 21)) {
1042 printf("%s: OTPROM ECC error at 0x%x\n",
1043 sc->sc_dev.dv_xname, addr);
1044 return EIO5;
1045 }
1046 if (tmp & IWN_OTP_GP_ECC_CORR_STTS(1 << 20)) {
1047 /* Correctable ECC error, clear bit. */
1048 IWN_SETBITS(sc, IWN_OTP_GP,(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x034)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) | (
(1 << 20))))))
1049 IWN_OTP_GP_ECC_CORR_STTS)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x034)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) | (
(1 << 20))))))
;
1050 }
1051 }
1052 *out++ = val >> 16;
1053 if (count > 1)
1054 *out++ = val >> 24;
1055 }
1056 return 0;
1057}
1058
1059int
1060iwn_dma_contig_alloc(bus_dma_tag_t tag, struct iwn_dma_info *dma, void **kvap,
1061 bus_size_t size, bus_size_t alignment)
1062{
1063 int nsegs, error;
1064
1065 dma->tag = tag;
1066 dma->size = size;
1067
1068 error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,(*(tag)->_dmamap_create)((tag), (size), (1), (size), (0), (
0x0001), (&dma->map))
1069 &dma->map)(*(tag)->_dmamap_create)((tag), (size), (1), (size), (0), (
0x0001), (&dma->map))
;
1070 if (error != 0)
1071 goto fail;
1072
1073 error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,(*(tag)->_dmamem_alloc)((tag), (size), (alignment), (0), (
&dma->seg), (1), (&nsegs), (0x0001 | 0x1000))
1074 BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(tag)->_dmamem_alloc)((tag), (size), (alignment), (0), (
&dma->seg), (1), (&nsegs), (0x0001 | 0x1000))
;
1075 if (error != 0)
1076 goto fail;
1077
1078 error = bus_dmamem_map(tag, &dma->seg, 1, size, &dma->vaddr,(*(tag)->_dmamem_map)((tag), (&dma->seg), (1), (size
), (&dma->vaddr), (0x0001 | 0x0004))
1079 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)(*(tag)->_dmamem_map)((tag), (&dma->seg), (1), (size
), (&dma->vaddr), (0x0001 | 0x0004))
;
1080 if (error != 0)
1081 goto fail;
1082
1083 error = bus_dmamap_load_raw(tag, dma->map, &dma->seg, 1, size,(*(tag)->_dmamap_load_raw)((tag), (dma->map), (&dma
->seg), (1), (size), (0x0001))
1084 BUS_DMA_NOWAIT)(*(tag)->_dmamap_load_raw)((tag), (dma->map), (&dma
->seg), (1), (size), (0x0001))
;
1085 if (error != 0)
1086 goto fail;
1087
1088 bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE)(*(tag)->_dmamap_sync)((tag), (dma->map), (0), (size), (
0x04))
;
1089
1090 dma->paddr = dma->map->dm_segs[0].ds_addr;
1091 if (kvap != NULL((void *)0))
1092 *kvap = dma->vaddr;
1093
1094 return 0;
1095
1096fail: iwn_dma_contig_free(dma);
1097 return error;
1098}
1099
1100void
1101iwn_dma_contig_free(struct iwn_dma_info *dma)
1102{
1103 if (dma->map != NULL((void *)0)) {
1104 if (dma->vaddr != NULL((void *)0)) {
1105 bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,(*(dma->tag)->_dmamap_sync)((dma->tag), (dma->map
), (0), (dma->size), (0x02 | 0x08))
1106 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(dma->tag)->_dmamap_sync)((dma->tag), (dma->map
), (0), (dma->size), (0x02 | 0x08))
;
1107 bus_dmamap_unload(dma->tag, dma->map)(*(dma->tag)->_dmamap_unload)((dma->tag), (dma->map
))
;
1108 bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size)(*(dma->tag)->_dmamem_unmap)((dma->tag), (dma->vaddr
), (dma->size))
;
1109 bus_dmamem_free(dma->tag, &dma->seg, 1)(*(dma->tag)->_dmamem_free)((dma->tag), (&dma->
seg), (1))
;
1110 dma->vaddr = NULL((void *)0);
1111 }
1112 bus_dmamap_destroy(dma->tag, dma->map)(*(dma->tag)->_dmamap_destroy)((dma->tag), (dma->
map))
;
1113 dma->map = NULL((void *)0);
1114 }
1115}
1116
1117int
1118iwn_alloc_sched(struct iwn_softc *sc)
1119{
1120 /* TX scheduler rings must be aligned on a 1KB boundary. */
1121 return iwn_dma_contig_alloc(sc->sc_dmat, &sc->sched_dma,
1122 (void **)&sc->sched, sc->schedsz, 1024);
1123}
1124
1125void
1126iwn_free_sched(struct iwn_softc *sc)
1127{
1128 iwn_dma_contig_free(&sc->sched_dma);
1129}
1130
1131int
1132iwn_alloc_kw(struct iwn_softc *sc)
1133{
1134 /* "Keep Warm" page must be aligned on a 4KB boundary. */
1135 return iwn_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, NULL((void *)0), 4096,
1136 4096);
1137}
1138
1139void
1140iwn_free_kw(struct iwn_softc *sc)
1141{
1142 iwn_dma_contig_free(&sc->kw_dma);
1143}
1144
1145int
1146iwn_alloc_ict(struct iwn_softc *sc)
1147{
1148 /* ICT table must be aligned on a 4KB boundary. */
1149 return iwn_dma_contig_alloc(sc->sc_dmat, &sc->ict_dma,
1150 (void **)&sc->ict, IWN_ICT_SIZE4096, 4096);
1151}
1152
1153void
1154iwn_free_ict(struct iwn_softc *sc)
1155{
1156 iwn_dma_contig_free(&sc->ict_dma);
1157}
1158
1159int
1160iwn_alloc_fwmem(struct iwn_softc *sc)
1161{
1162 /* Must be aligned on a 16-byte boundary. */
1163 return iwn_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL((void *)0),
1164 sc->fwsz, 16);
1165}
1166
1167void
1168iwn_free_fwmem(struct iwn_softc *sc)
1169{
1170 iwn_dma_contig_free(&sc->fw_dma);
1171}
1172
1173int
1174iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
1175{
1176 bus_size_t size;
1177 int i, error;
1178
1179 ring->cur = 0;
1180
1181 /* Allocate RX descriptors (256-byte aligned). */
1182 size = IWN_RX_RING_COUNT(1 << 6) * sizeof (uint32_t);
1183 error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
1184 (void **)&ring->desc, size, 256);
1185 if (error != 0) {
1186 printf("%s: could not allocate RX ring DMA memory\n",
1187 sc->sc_dev.dv_xname);
1188 goto fail;
1189 }
1190
1191 /* Allocate RX status area (16-byte aligned). */
1192 error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma,
1193 (void **)&ring->stat, sizeof (struct iwn_rx_status), 16);
1194 if (error != 0) {
1195 printf("%s: could not allocate RX status DMA memory\n",
1196 sc->sc_dev.dv_xname);
1197 goto fail;
1198 }
1199
1200 /*
1201 * Allocate and map RX buffers.
1202 */
1203 for (i = 0; i < IWN_RX_RING_COUNT(1 << 6); i++) {
1204 struct iwn_rx_data *data = &ring->data[i];
1205
1206 error = bus_dmamap_create(sc->sc_dmat, IWN_RBUF_SIZE, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((4 *
1024)), (1), ((4 * 1024)), (0), (0x0001 | 0x0002), (&data
->map))
1207 IWN_RBUF_SIZE, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((4 *
1024)), (1), ((4 * 1024)), (0), (0x0001 | 0x0002), (&data
->map))
1208 &data->map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((4 *
1024)), (1), ((4 * 1024)), (0), (0x0001 | 0x0002), (&data
->map))
;
1209 if (error != 0) {
1210 printf("%s: could not create RX buf DMA map\n",
1211 sc->sc_dev.dv_xname);
1212 goto fail;
1213 }
1214
1215 data->m = MCLGETL(NULL, M_DONTWAIT, IWN_RBUF_SIZE)m_clget((((void *)0)), (0x0002), ((4 * 1024)));
1216 if (data->m == NULL((void *)0)) {
1217 printf("%s: could not allocate RX mbuf\n",
1218 sc->sc_dev.dv_xname);
1219 error = ENOBUFS55;
1220 goto fail;
1221 }
1222
1223 error = bus_dmamap_load(sc->sc_dmat, data->map,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
1224 mtod(data->m, void *), IWN_RBUF_SIZE, NULL,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
1225 BUS_DMA_NOWAIT | BUS_DMA_READ)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
;
1226 if (error != 0) {
1227 printf("%s: can't map mbuf (error %d)\n",
1228 sc->sc_dev.dv_xname, error);
1229 goto fail;
1230 }
1231
1232 /* Set physical address of RX buffer (256-byte aligned). */
1233 ring->desc[i] = htole32(data->map->dm_segs[0].ds_addr >> 8)((__uint32_t)(data->map->dm_segs[0].ds_addr >> 8)
)
;
1234 }
1235
1236 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0, size,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (0), (size), (0x04))
1237 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (0), (size), (0x04))
;
1238
1239 return 0;
1240
1241fail: iwn_free_rx_ring(sc, ring);
1242 return error;
1243}
1244
1245void
1246iwn_reset_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
1247{
1248 int ntries;
1249
1250 if (iwn_nic_lock(sc) == 0) {
1251 IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
(0))))
;
1252 for (ntries = 0; ntries < 1000; ntries++) {
1253 if (IWN_READ(sc, IWN_FH_RX_STATUS)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x1c44)))) &
1254 IWN_FH_RX_STATUS_IDLE(1 << 24))
1255 break;
1256 DELAY(10)(*delay_func)(10);
1257 }
1258 iwn_nic_unlock(sc);
1259 }
1260 ring->cur = 0;
1261 sc->last_rx_valid = 0;
1262}
1263
1264void
1265iwn_free_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
1266{
1267 int i;
1268
1269 iwn_dma_contig_free(&ring->desc_dma);
1270 iwn_dma_contig_free(&ring->stat_dma);
1271
1272 for (i = 0; i < IWN_RX_RING_COUNT(1 << 6); i++) {
1273 struct iwn_rx_data *data = &ring->data[i];
1274
1275 if (data->m != NULL((void *)0)) {
1276 bus_dmamap_sync(sc->sc_dmat, data->map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x02))
1277 data->map->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x02))
;
1278 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
1279 m_freem(data->m);
1280 }
1281 if (data->map != NULL((void *)0))
1282 bus_dmamap_destroy(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (data
->map))
;
1283 }
1284}
1285
1286int
1287iwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int qid)
1288{
1289 bus_addr_t paddr;
1290 bus_size_t size;
1291 int i, error;
1292
1293 ring->qid = qid;
1294 ring->queued = 0;
1295 ring->cur = 0;
1296
1297 /* Allocate TX descriptors (256-byte aligned). */
1298 size = IWN_TX_RING_COUNT256 * sizeof (struct iwn_tx_desc);
1299 error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
1300 (void **)&ring->desc, size, 256);
1301 if (error != 0) {
1302 printf("%s: could not allocate TX ring DMA memory\n",
1303 sc->sc_dev.dv_xname);
1304 goto fail;
1305 }
1306
1307 size = IWN_TX_RING_COUNT256 * sizeof (struct iwn_tx_cmd);
1308 error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma,
1309 (void **)&ring->cmd, size, 4);
1310 if (error != 0) {
1311 printf("%s: could not allocate TX cmd DMA memory\n",
1312 sc->sc_dev.dv_xname);
1313 goto fail;
1314 }
1315
1316 paddr = ring->cmd_dma.paddr;
1317 for (i = 0; i < IWN_TX_RING_COUNT256; i++) {
1318 struct iwn_tx_data *data = &ring->data[i];
1319
1320 data->cmd_paddr = paddr;
1321 data->scratch_paddr = paddr + 12;
1322 paddr += sizeof (struct iwn_tx_cmd);
1323
1324 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (20 - 1), ((1 << 11)), (0), (0x0001), (&data
->map))
1325 IWN_MAX_SCATTER - 1, MCLBYTES, 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (20 - 1), ((1 << 11)), (0), (0x0001), (&data
->map))
1326 &data->map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (20 - 1), ((1 << 11)), (0), (0x0001), (&data
->map))
;
1327 if (error != 0) {
1328 printf("%s: could not create TX buf DMA map\n",
1329 sc->sc_dev.dv_xname);
1330 goto fail;
1331 }
1332 }
1333 return 0;
1334
1335fail: iwn_free_tx_ring(sc, ring);
1336 return error;
1337}
1338
1339void
1340iwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
1341{
1342 int i;
1343
1344 for (i = 0; i < IWN_TX_RING_COUNT256; i++) {
1345 struct iwn_tx_data *data = &ring->data[i];
1346
1347 if (data->m != NULL((void *)0)) {
1348 bus_dmamap_sync(sc->sc_dmat, data->map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
1349 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
1350 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
1351 m_freem(data->m);
1352 data->m = NULL((void *)0);
1353 }
1354 }
1355 /* Clear TX descriptors. */
1356 memset(ring->desc, 0, ring->desc_dma.size)__builtin_memset((ring->desc), (0), (ring->desc_dma.size
))
;
1357 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (0), (ring->desc_dma.size), (0x04))
1358 ring->desc_dma.size, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (0), (ring->desc_dma.size), (0x04))
;
1359 sc->qfullmsk &= ~(1 << ring->qid);
1360 ring->queued = 0;
1361 ring->cur = 0;
1362}
1363
1364void
1365iwn_free_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
1366{
1367 int i;
1368
1369 iwn_dma_contig_free(&ring->desc_dma);
1370 iwn_dma_contig_free(&ring->cmd_dma);
1371
1372 for (i = 0; i < IWN_TX_RING_COUNT256; i++) {
1373 struct iwn_tx_data *data = &ring->data[i];
1374
1375 if (data->m != NULL((void *)0)) {
1376 bus_dmamap_sync(sc->sc_dmat, data->map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
1377 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
1378 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
1379 m_freem(data->m);
1380 }
1381 if (data->map != NULL((void *)0))
1382 bus_dmamap_destroy(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (data
->map))
;
1383 }
1384}
1385
1386void
1387iwn5000_ict_reset(struct iwn_softc *sc)
1388{
1389 /* Disable interrupts. */
1390 IWN_WRITE(sc, IWN_INT_MASK, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
0))))
;
1391
1392 /* Reset ICT table. */
1393 memset(sc->ict, 0, IWN_ICT_SIZE)__builtin_memset((sc->ict), (0), (4096));
1394 sc->ict_cur = 0;
1395
1396 /* Set physical address of ICT table (4KB aligned). */
1397 DPRINTF(("enabling ICT\n"));
1398 IWN_WRITE(sc, IWN_DRAM_INT_TBL, IWN_DRAM_INT_TBL_ENABLE |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x0a0)), ((
(1U << 31) | (1U << 27) | sc->ict_dma.paddr >>
12))))
1399 IWN_DRAM_INT_TBL_WRAP_CHECK | sc->ict_dma.paddr >> 12)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x0a0)), ((
(1U << 31) | (1U << 27) | sc->ict_dma.paddr >>
12))))
;
1400
1401 /* Enable periodic RX interrupt. */
1402 sc->int_mask |= IWN_INT_RX_PERIODIC(1U << 28);
1403 /* Switch to ICT interrupt mode in driver. */
1404 sc->sc_flags |= IWN_FLAG_USE_ICT(1 << 3);
1405
1406 /* Re-enable interrupts. */
1407 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
1408 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
1409}
1410
1411int
1412iwn_read_eeprom(struct iwn_softc *sc)
1413{
1414 struct iwn_ops *ops = &sc->ops;
1415 struct ieee80211com *ic = &sc->sc_ic;
1416 uint16_t val;
1417 int error;
1418
1419 /* Check whether adapter has an EEPROM or an OTPROM. */
1420 if (sc->hw_type >= IWN_HW_REV_TYPE_10006 &&
1421 (IWN_READ(sc, IWN_OTP_GP)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x034)))) & IWN_OTP_GP_DEV_SEL_OTP(1 << 16)))
1422 sc->sc_flags |= IWN_FLAG_HAS_OTPROM(1 << 1);
1423 DPRINTF(("%s found\n", (sc->sc_flags & IWN_FLAG_HAS_OTPROM) ?
1424 "OTPROM" : "EEPROM"));
1425
1426 /* Adapter has to be powered on for EEPROM access to work. */
1427 if ((error = iwn_apm_init(sc)) != 0) {
1428 printf("%s: could not power ON adapter\n",
1429 sc->sc_dev.dv_xname);
1430 return error;
1431 }
1432
1433 if ((IWN_READ(sc, IWN_EEPROM_GP)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x030)))) & 0x7) == 0) {
1434 printf("%s: bad ROM signature\n", sc->sc_dev.dv_xname);
1435 return EIO5;
1436 }
1437 if ((error = iwn_eeprom_lock(sc)) != 0) {
1438 printf("%s: could not lock ROM (error=%d)\n",
1439 sc->sc_dev.dv_xname, error);
1440 return error;
1441 }
1442 if (sc->sc_flags & IWN_FLAG_HAS_OTPROM(1 << 1)) {
1443 if ((error = iwn_init_otprom(sc)) != 0) {
1444 printf("%s: could not initialize OTPROM\n",
1445 sc->sc_dev.dv_xname);
1446 return error;
1447 }
1448 }
1449
1450 iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP0x045, &val, 2);
1451 DPRINTF(("SKU capabilities=0x%04x\n", letoh16(val)));
1452 /* Check if HT support is bonded out. */
1453 if (val & htole16(IWN_EEPROM_SKU_CAP_11N)((__uint16_t)((1 << 6))))
1454 sc->sc_flags |= IWN_FLAG_HAS_11N(1 << 6);
1455
1456 iwn_read_prom_data(sc, IWN_EEPROM_RFCFG0x048, &val, 2);
1457 sc->rfcfg = letoh16(val)((__uint16_t)(val));
1458 DPRINTF(("radio config=0x%04x\n", sc->rfcfg));
1459 /* Read Tx/Rx chains from ROM unless it's known to be broken. */
1460 if (sc->txchainmask == 0)
1461 sc->txchainmask = IWN_RFCFG_TXANTMSK(sc->rfcfg)(((sc->rfcfg) >> 8) & 0xf);
1462 if (sc->rxchainmask == 0)
1463 sc->rxchainmask = IWN_RFCFG_RXANTMSK(sc->rfcfg)(((sc->rfcfg) >> 12) & 0xf);
1464
1465 /* Read MAC address. */
1466 iwn_read_prom_data(sc, IWN_EEPROM_MAC0x015, ic->ic_myaddr, 6);
1467
1468 /* Read adapter-specific information from EEPROM. */
1469 ops->read_eeprom(sc);
1470
1471 iwn_apm_stop(sc); /* Power OFF adapter. */
1472
1473 iwn_eeprom_unlock(sc);
1474 return 0;
1475}
1476
1477void
1478iwn4965_read_eeprom(struct iwn_softc *sc)
1479{
1480 uint32_t addr;
1481 uint16_t val;
1482 int i;
1483
1484 /* Read regulatory domain (4 ASCII characters). */
1485 iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN0x060, sc->eeprom_domain, 4);
1486
1487 /* Read the list of authorized channels. */
1488 for (i = 0; i < 7; i++) {
1489 addr = iwn4965_regulatory_bands[i];
1490 iwn_read_eeprom_channels(sc, i, addr);
1491 }
1492
1493 /* Read maximum allowed TX power for 2GHz and 5GHz bands. */
1494 iwn_read_prom_data(sc, IWN4965_EEPROM_MAXPOW0x0e8, &val, 2);
1495 sc->maxpwr2GHz = val & 0xff;
1496 sc->maxpwr5GHz = val >> 8;
1497 /* Check that EEPROM values are within valid range. */
1498 if (sc->maxpwr5GHz < 20 || sc->maxpwr5GHz > 50)
1499 sc->maxpwr5GHz = 38;
1500 if (sc->maxpwr2GHz < 20 || sc->maxpwr2GHz > 50)
1501 sc->maxpwr2GHz = 38;
1502 DPRINTF(("maxpwr 2GHz=%d 5GHz=%d\n", sc->maxpwr2GHz, sc->maxpwr5GHz));
1503
1504 /* Read samples for each TX power group. */
1505 iwn_read_prom_data(sc, IWN4965_EEPROM_BANDS0x0ea, sc->bands,
1506 sizeof sc->bands);
1507
1508 /* Read voltage at which samples were taken. */
1509 iwn_read_prom_data(sc, IWN4965_EEPROM_VOLTAGE0x0e9, &val, 2);
1510 sc->eeprom_voltage = (int16_t)letoh16(val)((__uint16_t)(val));
1511 DPRINTF(("voltage=%d (in 0.3V)\n", sc->eeprom_voltage));
1512
1513#ifdef IWN_DEBUG
1514 /* Print samples. */
1515 if (iwn_debug > 0) {
1516 for (i = 0; i < IWN_NBANDS8; i++)
1517 iwn4965_print_power_group(sc, i);
1518 }
1519#endif
1520}
1521
1522#ifdef IWN_DEBUG
1523void
1524iwn4965_print_power_group(struct iwn_softc *sc, int i)
1525{
1526 struct iwn4965_eeprom_band *band = &sc->bands[i];
1527 struct iwn4965_eeprom_chan_samples *chans = band->chans;
1528 int j, c;
1529
1530 printf("===band %d===\n", i);
1531 printf("chan lo=%d, chan hi=%d\n", band->lo, band->hi);
1532 printf("chan1 num=%d\n", chans[0].num);
1533 for (c = 0; c < 2; c++) {
1534 for (j = 0; j < IWN_NSAMPLES3; j++) {
1535 printf("chain %d, sample %d: temp=%d gain=%d "
1536 "power=%d pa_det=%d\n", c, j,
1537 chans[0].samples[c][j].temp,
1538 chans[0].samples[c][j].gain,
1539 chans[0].samples[c][j].power,
1540 chans[0].samples[c][j].pa_det);
1541 }
1542 }
1543 printf("chan2 num=%d\n", chans[1].num);
1544 for (c = 0; c < 2; c++) {
1545 for (j = 0; j < IWN_NSAMPLES3; j++) {
1546 printf("chain %d, sample %d: temp=%d gain=%d "
1547 "power=%d pa_det=%d\n", c, j,
1548 chans[1].samples[c][j].temp,
1549 chans[1].samples[c][j].gain,
1550 chans[1].samples[c][j].power,
1551 chans[1].samples[c][j].pa_det);
1552 }
1553 }
1554}
1555#endif
1556
1557void
1558iwn5000_read_eeprom(struct iwn_softc *sc)
1559{
1560 struct iwn5000_eeprom_calib_hdr hdr;
1561 int32_t volt;
1562 uint32_t base, addr;
1563 uint16_t val;
1564 int i;
1565
1566 /* Read regulatory domain (4 ASCII characters). */
1567 iwn_read_prom_data(sc, IWN5000_EEPROM_REG0x066, &val, 2);
1568 base = letoh16(val)((__uint16_t)(val));
1569 iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN0x001,
1570 sc->eeprom_domain, 4);
1571
1572 /* Read the list of authorized channels. */
1573 for (i = 0; i < 7; i++) {
1574 addr = base + iwn5000_regulatory_bands[i];
1575 iwn_read_eeprom_channels(sc, i, addr);
1576 }
1577
1578 /* Read enhanced TX power information for 6000 Series. */
1579 if (sc->hw_type >= IWN_HW_REV_TYPE_60007)
1580 iwn_read_eeprom_enhinfo(sc);
1581
1582 iwn_read_prom_data(sc, IWN5000_EEPROM_CAL0x067, &val, 2);
1583 base = letoh16(val)((__uint16_t)(val));
1584 iwn_read_prom_data(sc, base, &hdr, sizeof hdr);
1585 DPRINTF(("calib version=%u pa type=%u voltage=%u\n",
1586 hdr.version, hdr.pa_type, letoh16(hdr.volt)));
1587 sc->calib_ver = hdr.version;
1588
1589 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
1590 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
1591 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
1592 sc->hw_type == IWN_HW_REV_TYPE_10517) {
1593 sc->eeprom_voltage = letoh16(hdr.volt)((__uint16_t)(hdr.volt));
1594 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP0x12a, &val, 2);
1595 sc->eeprom_temp = letoh16(val)((__uint16_t)(val));
1596 iwn_read_prom_data(sc, base + IWN2000_EEPROM_RAWTEMP0x12b, &val, 2);
1597 sc->eeprom_rawtemp = letoh16(val)((__uint16_t)(val));
1598 }
1599
1600 if (sc->hw_type == IWN_HW_REV_TYPE_51504) {
1601 /* Compute temperature offset. */
1602 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP0x12a, &val, 2);
1603 sc->eeprom_temp = letoh16(val)((__uint16_t)(val));
1604 iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT0x12b, &val, 2);
1605 volt = letoh16(val)((__uint16_t)(val));
1606 sc->temp_off = sc->eeprom_temp - (volt / -5);
1607 DPRINTF(("temp=%d volt=%d offset=%dK\n",
1608 sc->eeprom_temp, volt, sc->temp_off));
1609 } else {
1610 /* Read crystal calibration. */
1611 iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL0x128,
1612 &sc->eeprom_crystal, sizeof (uint32_t));
1613 DPRINTF(("crystal calibration 0x%08x\n",
1614 letoh32(sc->eeprom_crystal)));
1615 }
1616}
1617
1618void
1619iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
1620{
1621 struct ieee80211com *ic = &sc->sc_ic;
1622 const struct iwn_chan_band *band = &iwn_bands[n];
1623 struct iwn_eeprom_chan channels[IWN_MAX_CHAN_PER_BAND14];
1624 uint8_t chan;
1625 int i;
1626
1627 iwn_read_prom_data(sc, addr, channels,
1628 band->nchan * sizeof (struct iwn_eeprom_chan));
1629
1630 for (i = 0; i < band->nchan; i++) {
1631 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID(1 << 0)))
1632 continue;
1633
1634 chan = band->chan[i];
1635
1636 if (n == 0) { /* 2GHz band */
1637 ic->ic_channels[chan].ic_freq =
1638 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ0x0080);
1639 ic->ic_channels[chan].ic_flags =
1640 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
1641 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
1642
1643 } else if (n < 5) { /* 5GHz band */
1644 /*
1645 * Some adapters support channels 7, 8, 11 and 12
1646 * both in the 2GHz and 4.9GHz bands.
1647 * Because of limitations in our net80211 layer,
1648 * we don't support them in the 4.9GHz band.
1649 */
1650 if (chan <= 14)
1651 continue;
1652
1653 ic->ic_channels[chan].ic_freq =
1654 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ0x0100);
1655 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A(0x0100 | 0x0040);
1656 /* We have at least one valid 5GHz channel. */
1657 sc->sc_flags |= IWN_FLAG_HAS_5GHZ(1 << 0);
1658 } else { /* 40 MHz */
1659 sc->maxpwr40[chan] = channels[i].maxpwr;
1660 ic->ic_channels[chan].ic_flags |= IEEE80211_CHAN_40MHZ0x8000;
1661 }
1662
1663 if (n < 5) {
1664 /* Is active scan allowed on this channel? */
1665 if (!(channels[i].flags & IWN_EEPROM_CHAN_ACTIVE(1 << 3))) {
1666 ic->ic_channels[chan].ic_flags |=
1667 IEEE80211_CHAN_PASSIVE0x0200;
1668 }
1669
1670 /* Save maximum allowed TX power for this channel. */
1671 sc->maxpwr[chan] = channels[i].maxpwr;
1672
1673 if (sc->sc_flags & IWN_FLAG_HAS_11N(1 << 6))
1674 ic->ic_channels[chan].ic_flags |=
1675 IEEE80211_CHAN_HT0x2000;
1676 }
1677
1678 DPRINTF(("adding chan %d flags=0x%x maxpwr=%d maxpwr40=%d\n",
1679 chan, channels[i].flags, sc->maxpwr[chan],
1680 sc->maxpwr40[chan]));
1681 }
1682}
1683
1684void
1685iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
1686{
1687 struct iwn_eeprom_enhinfo enhinfo[35];
1688 uint16_t val, base;
1689 int8_t maxpwr;
1690 int i;
1691
1692 iwn_read_prom_data(sc, IWN5000_EEPROM_REG0x066, &val, 2);
1693 base = letoh16(val)((__uint16_t)(val));
1694 iwn_read_prom_data(sc, base + IWN6000_EEPROM_ENHINFO0x054,
1695 enhinfo, sizeof enhinfo);
1696
1697 memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr)__builtin_memset((sc->enh_maxpwr), (0), (sizeof sc->enh_maxpwr
))
;
1698 for (i = 0; i < nitems(enhinfo)(sizeof((enhinfo)) / sizeof((enhinfo)[0])); i++) {
1699 if ((enhinfo[i].flags & IWN_TXP_VALID(1 << 0)) == 0)
1700 continue; /* Skip invalid entries. */
1701
1702 maxpwr = 0;
1703 if (sc->txchainmask & IWN_ANT_A(1 << 0))
1704 maxpwr = MAX(maxpwr, enhinfo[i].chain[0])(((maxpwr)>(enhinfo[i].chain[0]))?(maxpwr):(enhinfo[i].chain
[0]))
;
1705 if (sc->txchainmask & IWN_ANT_B(1 << 1))
1706 maxpwr = MAX(maxpwr, enhinfo[i].chain[1])(((maxpwr)>(enhinfo[i].chain[1]))?(maxpwr):(enhinfo[i].chain
[1]))
;
1707 if (sc->txchainmask & IWN_ANT_C(1 << 2))
1708 maxpwr = MAX(maxpwr, enhinfo[i].chain[2])(((maxpwr)>(enhinfo[i].chain[2]))?(maxpwr):(enhinfo[i].chain
[2]))
;
1709 if (sc->ntxchains == 2)
1710 maxpwr = MAX(maxpwr, enhinfo[i].mimo2)(((maxpwr)>(enhinfo[i].mimo2))?(maxpwr):(enhinfo[i].mimo2)
)
;
1711 else if (sc->ntxchains == 3)
1712 maxpwr = MAX(maxpwr, enhinfo[i].mimo3)(((maxpwr)>(enhinfo[i].mimo3))?(maxpwr):(enhinfo[i].mimo3)
)
;
1713 maxpwr /= 2; /* Convert half-dBm to dBm. */
1714
1715 DPRINTF(("enhinfo %d, maxpwr=%d\n", i, maxpwr));
1716 sc->enh_maxpwr[i] = maxpwr;
1717 }
1718}
1719
1720struct ieee80211_node *
1721iwn_node_alloc(struct ieee80211com *ic)
1722{
1723 return malloc(sizeof (struct iwn_node), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
1724}
1725
1726void
1727iwn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
1728{
1729 struct iwn_softc *sc = ic->ic_ific_ac.ac_if.if_softc;
1730 struct iwn_node *wn = (void *)ni;
1731 uint8_t rate;
1732 int ridx, i;
1733
1734 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) == 0)
1735 ieee80211_amrr_node_init(&sc->amrr, &wn->amn);
1736
1737 /* Start at lowest available bit-rate, AMRR/MiRA will raise. */
1738 ni->ni_txrate = 0;
1739 ni->ni_txmcs = 0;
1740
1741 for (i = 0; i < ni->ni_rates.rs_nrates; i++) {
1742 rate = ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL0x7f;
1743 /* Map 802.11 rate to HW rate index. */
1744 for (ridx = 0; ridx <= IWN_RIDX_MAX32; ridx++) {
1745 if (iwn_rates[ridx].plcp != IWN_PLCP_INVALID0xff &&
1746 iwn_rates[ridx].rate == rate)
1747 break;
1748 }
1749 wn->ridx[i] = ridx;
1750 }
1751}
1752
1753int
1754iwn_media_change(struct ifnet *ifp)
1755{
1756 struct iwn_softc *sc = ifp->if_softc;
1757 struct ieee80211com *ic = &sc->sc_ic;
1758 uint8_t rate, ridx;
1759 int error;
1760
1761 error = ieee80211_media_change(ifp);
1762 if (error != ENETRESET52)
1763 return error;
1764
1765 if (ic->ic_fixed_mcs != -1)
1766 sc->fixed_ridx = iwn_mcs2ridx[ic->ic_fixed_mcs];
1767 if (ic->ic_fixed_rate != -1) {
1768 rate = ic->ic_sup_rates[ic->ic_curmode].
1769 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL0x7f;
1770 /* Map 802.11 rate to HW rate index. */
1771 for (ridx = 0; ridx <= IWN_RIDX_MAX32; ridx++)
1772 if (iwn_rates[ridx].plcp != IWN_PLCP_INVALID0xff &&
1773 iwn_rates[ridx].rate == rate)
1774 break;
1775 sc->fixed_ridx = ridx;
1776 }
1777
1778 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1779 (IFF_UP0x1 | IFF_RUNNING0x40)) {
1780 iwn_stop(ifp);
1781 error = iwn_init(ifp);
1782 }
1783 return error;
1784}
1785
1786int
1787iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1788{
1789 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1790 struct iwn_softc *sc = ifp->if_softc;
1791 struct ieee80211_node *ni = ic->ic_bss;
1792 int error;
1793
1794 if (ic->ic_state == IEEE80211_S_RUN) {
1795 if (nstate == IEEE80211_S_SCAN) {
1796 /*
1797 * During RUN->SCAN we don't call sc_newstate() so
1798 * we must stop A-MPDU Tx ourselves in this case.
1799 */
1800 ieee80211_stop_ampdu_tx(ic, ni, -1);
1801 ieee80211_ba_del(ni);
1802 }
1803 timeout_del(&sc->calib_to);
1804 sc->calib.state = IWN_CALIB_STATE_INIT0;
1805 if (sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9))
1806 iwn_scan_abort(sc);
1807 }
1808
1809 if (ic->ic_state == IEEE80211_S_SCAN) {
1810 if (nstate == IEEE80211_S_SCAN) {
1811 if (sc->sc_flags & IWN_FLAG_SCANNING(1 << 10))
1812 return 0;
1813 } else
1814 sc->sc_flags &= ~IWN_FLAG_SCANNING(1 << 10);
1815 /* Turn LED off when leaving scan state. */
1816 iwn_set_led(sc, IWN_LED_LINK2, 1, 0);
1817 }
1818
1819 if (ic->ic_state >= IEEE80211_S_ASSOC &&
1820 nstate <= IEEE80211_S_ASSOC) {
1821 /* Reset state to handle re- and disassociations. */
1822 sc->rxon.associd = 0;
1823 sc->rxon.filter &= ~htole32(IWN_FILTER_BSS)((__uint32_t)((1 << 5)));
1824 sc->calib.state = IWN_CALIB_STATE_INIT0;
1825 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
1826 if (error != 0)
1827 printf("%s: RXON command failed\n",
1828 sc->sc_dev.dv_xname);
1829 }
1830
1831 switch (nstate) {
1832 case IEEE80211_S_SCAN:
1833 /* Make the link LED blink while we're scanning. */
1834 iwn_set_led(sc, IWN_LED_LINK2, 10, 10);
1835
1836 if ((error = iwn_scan(sc, IEEE80211_CHAN_2GHZ0x0080, 0)) != 0) {
1837 printf("%s: could not initiate scan\n",
1838 sc->sc_dev.dv_xname);
1839 return error;
1840 }
1841 if (ifp->if_flags & IFF_DEBUG0x4)
1842 printf("%s: %s -> %s\n", ifp->if_xname,
1843 ieee80211_state_name[ic->ic_state],
1844 ieee80211_state_name[nstate]);
1845 if ((sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9)) == 0) {
1846 ieee80211_set_link_state(ic, LINK_STATE_DOWN2);
1847 ieee80211_node_cleanup(ic, ic->ic_bss);
1848 }
1849 ic->ic_state = nstate;
1850 return 0;
1851
1852 case IEEE80211_S_ASSOC:
1853 if (ic->ic_state != IEEE80211_S_RUN)
1854 break;
1855 /* FALLTHROUGH */
1856 case IEEE80211_S_AUTH:
1857 if ((error = iwn_auth(sc, arg)) != 0) {
1858 printf("%s: could not move to auth state\n",
1859 sc->sc_dev.dv_xname);
1860 return error;
1861 }
1862 break;
1863
1864 case IEEE80211_S_RUN:
1865 if ((error = iwn_run(sc)) != 0) {
1866 printf("%s: could not move to run state\n",
1867 sc->sc_dev.dv_xname);
1868 return error;
1869 }
1870 break;
1871
1872 case IEEE80211_S_INIT:
1873 sc->calib.state = IWN_CALIB_STATE_INIT0;
1874 break;
1875 }
1876
1877 return sc->sc_newstate(ic, nstate, arg);
1878}
1879
1880void
1881iwn_iter_func(void *arg, struct ieee80211_node *ni)
1882{
1883 struct iwn_softc *sc = arg;
1884 struct iwn_node *wn = (void *)ni;
1885
1886 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) == 0) {
1887 int old_txrate = ni->ni_txrate;
1888 ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
1889 if (old_txrate != ni->ni_txrate)
1890 iwn_set_link_quality(sc, ni);
1891 }
1892}
1893
1894void
1895iwn_calib_timeout(void *arg)
1896{
1897 struct iwn_softc *sc = arg;
1898 struct ieee80211com *ic = &sc->sc_ic;
1899 int s;
1900
1901 s = splnet()splraise(0x7);
1902 if (ic->ic_fixed_rate == -1) {
1903 if (ic->ic_opmode == IEEE80211_M_STA)
1904 iwn_iter_func(sc, ic->ic_bss);
1905 else
1906 ieee80211_iterate_nodes(ic, iwn_iter_func, sc);
1907 }
1908 /* Force automatic TX power calibration every 60 secs. */
1909 if (++sc->calib_cnt >= 120) {
1910 uint32_t flags = 0;
1911
1912 DPRINTFN(2, ("sending request for statistics\n"));
1913 (void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS156, &flags,
1914 sizeof flags, 1);
1915 sc->calib_cnt = 0;
1916 }
1917 splx(s)spllower(s);
1918
1919 /* Automatic rate control triggered every 500ms. */
1920 timeout_add_msec(&sc->calib_to, 500);
1921}
1922
1923int
1924iwn_ccmp_decap(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1925{
1926 struct ieee80211com *ic = &sc->sc_ic;
1927 struct ieee80211_key *k = &ni->ni_pairwise_key;
1928 struct ieee80211_frame *wh;
1929 uint64_t pn, *prsc;
1930 uint8_t *ivp;
1931 uint8_t tid;
1932 int hdrlen, hasqos;
1933
1934 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1935 hdrlen = ieee80211_get_hdrlen(wh);
1936 ivp = (uint8_t *)wh + hdrlen;
1937
1938 /* Check that ExtIV bit is set. */
1939 if (!(ivp[3] & IEEE80211_WEP_EXTIV0x20)) {
1940 DPRINTF(("CCMP decap ExtIV not set\n"));
1941 return 1;
1942 }
1943 hasqos = ieee80211_has_qos(wh);
1944 tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID0x000f : 0;
1945 prsc = &k->k_rsc[tid];
1946
1947 /* Extract the 48-bit PN from the CCMP header. */
1948 pn = (uint64_t)ivp[0] |
1949 (uint64_t)ivp[1] << 8 |
1950 (uint64_t)ivp[4] << 16 |
1951 (uint64_t)ivp[5] << 24 |
1952 (uint64_t)ivp[6] << 32 |
1953 (uint64_t)ivp[7] << 40;
1954 if (pn <= *prsc) {
1955 DPRINTF(("CCMP replayed\n"));
1956 ic->ic_stats.is_ccmp_replays++;
1957 return 1;
1958 }
1959 /* Last seen packet number is updated in ieee80211_inputm(). */
1960
1961 /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
1962 m_adj(m, -IEEE80211_CCMP_MICLEN8);
1963 return 0;
1964}
1965
1966/*
1967 * Process an RX_PHY firmware notification. This is usually immediately
1968 * followed by an MPDU_RX_DONE notification.
1969 */
1970void
1971iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc,
1972 struct iwn_rx_data *data)
1973{
1974 struct iwn_rx_stat *stat = (struct iwn_rx_stat *)(desc + 1);
1975
1976 DPRINTFN(2, ("received PHY stats\n"));
1977 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
1978 sizeof (*stat), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
;
1979
1980 /* Save RX statistics, they will be used on MPDU_RX_DONE. */
1981 memcpy(&sc->last_rx_stat, stat, sizeof (*stat))__builtin_memcpy((&sc->last_rx_stat), (stat), (sizeof (
*stat)))
;
1982 sc->last_rx_valid = IWN_LAST_RX_VALID0x01;
1983 /*
1984 * The firmware does not send separate RX_PHY
1985 * notifications for A-MPDU subframes.
1986 */
1987 if (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7))))
1988 sc->last_rx_valid |= IWN_LAST_RX_AMPDU0x02;
1989}
1990
1991/*
1992 * Process an RX_DONE (4965AGN only) or MPDU_RX_DONE firmware notification.
1993 * Each MPDU_RX_DONE notification must be preceded by an RX_PHY one.
1994 */
1995void
1996iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
1997 struct iwn_rx_data *data, struct mbuf_list *ml)
1998{
1999 struct iwn_ops *ops = &sc->ops;
2000 struct ieee80211com *ic = &sc->sc_ic;
2001 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2002 struct iwn_rx_ring *ring = &sc->rxq;
2003 struct ieee80211_frame *wh;
2004 struct ieee80211_rxinfo rxi;
2005 struct ieee80211_node *ni;
2006 struct ieee80211_channel *bss_chan = NULL((void *)0);
2007 uint8_t saved_bssid[IEEE80211_ADDR_LEN6] = { 0 };
2008 struct mbuf *m, *m1;
2009 struct iwn_rx_stat *stat;
2010 caddr_t head;
2011 uint32_t flags;
2012 int error, len, rssi;
2013 uint16_t chan;
2014
2015 if (desc->type == IWN_MPDU_RX_DONE193) {
2016 /* Check for prior RX_PHY notification. */
2017 if (!sc->last_rx_valid) {
2018 DPRINTF(("missing RX_PHY\n"));
2019 return;
2020 }
2021 sc->last_rx_valid &= ~IWN_LAST_RX_VALID0x01;
2022 stat = &sc->last_rx_stat;
2023 if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU0x02) &&
2024 (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7)))) == 0) {
2025 DPRINTF(("missing RX_PHY (expecting A-MPDU)\n"));
2026 return;
2027 }
2028 if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU0x02) == 0 &&
2029 (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7))))) {
2030 DPRINTF(("missing RX_PHY (unexpected A-MPDU)\n"));
2031 return;
2032 }
2033 } else
2034 stat = (struct iwn_rx_stat *)(desc + 1);
2035
2036 bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWN_RBUF_SIZE,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), ((4 * 1024)), (0x02))
2037 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), ((4 * 1024)), (0x02))
;
2038
2039 if (stat->cfg_phy_len > IWN_STAT_MAXLEN20) {
2040 printf("%s: invalid RX statistic header\n",
2041 sc->sc_dev.dv_xname);
2042 return;
2043 }
2044 if (desc->type == IWN_MPDU_RX_DONE193) {
2045 struct iwn_rx_mpdu *mpdu = (struct iwn_rx_mpdu *)(desc + 1);
2046 head = (caddr_t)(mpdu + 1);
2047 len = letoh16(mpdu->len)((__uint16_t)(mpdu->len));
2048 } else {
2049 head = (caddr_t)(stat + 1) + stat->cfg_phy_len;
2050 len = letoh16(stat->len)((__uint16_t)(stat->len));
2051 }
2052
2053 flags = letoh32(*(uint32_t *)(head + len))((__uint32_t)(*(uint32_t *)(head + len)));
2054
2055 /* Discard frames with a bad FCS early. */
2056 if ((flags & IWN_RX_NOERROR((1 << 0) | (1 << 1))) != IWN_RX_NOERROR((1 << 0) | (1 << 1))) {
2057 DPRINTFN(2, ("RX flags error %x\n", flags));
2058 ifp->if_ierrorsif_data.ifi_ierrors++;
2059 return;
2060 }
2061 /* Discard frames that are too short. */
2062 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2063 /* Allow control frames in monitor mode. */
2064 if (len < sizeof (struct ieee80211_frame_cts)) {
2065 DPRINTF(("frame too short: %d\n", len));
2066 ic->ic_stats.is_rx_tooshort++;
2067 ifp->if_ierrorsif_data.ifi_ierrors++;
2068 return;
2069 }
2070 } else if (len < sizeof (*wh)) {
2071 DPRINTF(("frame too short: %d\n", len));
2072 ic->ic_stats.is_rx_tooshort++;
2073 ifp->if_ierrorsif_data.ifi_ierrors++;
2074 return;
2075 }
2076
2077 m1 = MCLGETL(NULL, M_DONTWAIT, IWN_RBUF_SIZE)m_clget((((void *)0)), (0x0002), ((4 * 1024)));
2078 if (m1 == NULL((void *)0)) {
2079 ic->ic_stats.is_rx_nombuf++;
2080 ifp->if_ierrorsif_data.ifi_ierrors++;
2081 return;
2082 }
2083 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2084
2085 error = bus_dmamap_load(sc->sc_dmat, data->map, mtod(m1, void *),(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((m1)->m_hdr.mh_data))), ((4 * 1024)), (((
void *)0)), (0x0001 | 0x0200))
2086 IWN_RBUF_SIZE, NULL, BUS_DMA_NOWAIT | BUS_DMA_READ)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((m1)->m_hdr.mh_data))), ((4 * 1024)), (((
void *)0)), (0x0001 | 0x0200))
;
2087 if (error != 0) {
2088 m_freem(m1);
2089
2090 /* Try to reload the old mbuf. */
2091 error = bus_dmamap_load(sc->sc_dmat, data->map,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
2092 mtod(data->m, void *), IWN_RBUF_SIZE, NULL,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
2093 BUS_DMA_NOWAIT | BUS_DMA_READ)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (((void *)((data->m)->m_hdr.mh_data))), ((4 * 1024
)), (((void *)0)), (0x0001 | 0x0200))
;
2094 if (error != 0) {
2095 panic("%s: could not load old RX mbuf",
2096 sc->sc_dev.dv_xname);
2097 }
2098 /* Physical address may have changed. */
2099 ring->desc[ring->cur] =
2100 htole32(data->map->dm_segs[0].ds_addr >> 8)((__uint32_t)(data->map->dm_segs[0].ds_addr >> 8)
)
;
2101 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
2102 ring->cur * sizeof (uint32_t), sizeof (uint32_t),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
2103 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
;
2104 ifp->if_ierrorsif_data.ifi_ierrors++;
2105 return;
2106 }
2107
2108 m = data->m;
2109 data->m = m1;
2110 /* Update RX descriptor. */
2111 ring->desc[ring->cur] = htole32(data->map->dm_segs[0].ds_addr >> 8)((__uint32_t)(data->map->dm_segs[0].ds_addr >> 8)
)
;
2112 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
2113 ring->cur * sizeof (uint32_t), sizeof (uint32_t),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
2114 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
;
2115
2116 /* Finalize mbuf. */
2117 m->m_datam_hdr.mh_data = head;
2118 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = len;
2119
2120 /*
2121 * Grab a reference to the source node. Note that control frames are
2122 * shorter than struct ieee80211_frame but ieee80211_find_rxnode()
2123 * is being careful about control frames.
2124 */
2125 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2126 if (len < sizeof (*wh) &&
2127 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_CTL0x04) {
2128 ic->ic_stats.is_rx_tooshort++;
2129 ifp->if_ierrorsif_data.ifi_ierrors++;
2130 m_freem(m);
2131 return;
2132 }
2133 ni = ieee80211_find_rxnode(ic, wh);
2134
2135 rxi.rxi_flags = 0;
2136 if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_CTL0x04)
2137 && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) &&
2138 !IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
2139 (ni->ni_flags & IEEE80211_NODE_RXPROT0x0008) &&
2140 ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
2141 if ((flags & IWN_RX_CIPHER_MASK(7 << 8)) != IWN_RX_CIPHER_CCMP(2 << 8)) {
2142 ic->ic_stats.is_ccmp_dec_errs++;
2143 ifp->if_ierrorsif_data.ifi_ierrors++;
2144 m_freem(m);
2145 ieee80211_release_node(ic, ni);
2146 return;
2147 }
2148 /* Check whether decryption was successful or not. */
2149 if ((desc->type == IWN_MPDU_RX_DONE193 &&
2150 (flags & (IWN_RX_MPDU_DEC(1 << 11) | IWN_RX_MPDU_MIC_OK(1 << 6))) !=
2151 (IWN_RX_MPDU_DEC(1 << 11) | IWN_RX_MPDU_MIC_OK(1 << 6))) ||
2152 (desc->type != IWN_MPDU_RX_DONE193 &&
2153 (flags & IWN_RX_DECRYPT_MASK(3 << 11)) != IWN_RX_DECRYPT_OK(3 << 11))) {
2154 DPRINTF(("CCMP decryption failed 0x%x\n", flags));
2155 ic->ic_stats.is_ccmp_dec_errs++;
2156 ifp->if_ierrorsif_data.ifi_ierrors++;
2157 m_freem(m);
2158 ieee80211_release_node(ic, ni);
2159 return;
2160 }
2161 if (iwn_ccmp_decap(sc, m, ni) != 0) {
2162 ifp->if_ierrorsif_data.ifi_ierrors++;
2163 m_freem(m);
2164 ieee80211_release_node(ic, ni);
2165 return;
2166 }
2167 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
2168 }
2169
2170 rssi = ops->get_rssi(stat);
2171
2172 chan = stat->chan;
2173 if (chan > IEEE80211_CHAN_MAX255)
2174 chan = IEEE80211_CHAN_MAX255;
2175
2176 /* Fix current channel. */
2177 if (ni == ic->ic_bss) {
2178 /*
2179 * We may switch ic_bss's channel during scans.
2180 * Record the current channel so we can restore it later.
2181 */
2182 bss_chan = ni->ni_chan;
2183 IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr)__builtin_memcpy((&saved_bssid), (ni->ni_macaddr), (6)
)
;
2184 }
2185 ni->ni_chan = &ic->ic_channels[chan];
2186
2187#if NBPFILTER1 > 0
2188 if (sc->sc_drvbpf != NULL((void *)0)) {
2189 struct iwn_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
2190 uint16_t chan_flags;
2191
2192 tap->wr_flags = 0;
2193 if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE)((__uint16_t)((1 << 2))))
2194 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
2195 tap->wr_chan_freq = htole16(ic->ic_channels[chan].ic_freq)((__uint16_t)(ic->ic_channels[chan].ic_freq));
2196 chan_flags = ic->ic_channels[chan].ic_flags;
2197 if (ic->ic_curmode != IEEE80211_MODE_11N)
2198 chan_flags &= ~IEEE80211_CHAN_HT0x2000;
2199 tap->wr_chan_flags = htole16(chan_flags)((__uint16_t)(chan_flags));
2200 tap->wr_dbm_antsignal = (int8_t)rssi;
2201 tap->wr_dbm_antnoise = (int8_t)sc->noise;
2202 tap->wr_tsft = stat->tstamp;
2203 if (stat->rflags & IWN_RFLAG_MCS(1 << 0)) {
2204 tap->wr_rate = (0x80 | stat->rate); /* HT MCS index */
2205 } else {
2206 switch (stat->rate) {
2207 /* CCK rates. */
2208 case 10: tap->wr_rate = 2; break;
2209 case 20: tap->wr_rate = 4; break;
2210 case 55: tap->wr_rate = 11; break;
2211 case 110: tap->wr_rate = 22; break;
2212 /* OFDM rates. */
2213 case 0xd: tap->wr_rate = 12; break;
2214 case 0xf: tap->wr_rate = 18; break;
2215 case 0x5: tap->wr_rate = 24; break;
2216 case 0x7: tap->wr_rate = 36; break;
2217 case 0x9: tap->wr_rate = 48; break;
2218 case 0xb: tap->wr_rate = 72; break;
2219 case 0x1: tap->wr_rate = 96; break;
2220 case 0x3: tap->wr_rate = 108; break;
2221 /* Unknown rate: should not happen. */
2222 default: tap->wr_rate = 0;
2223 }
2224 }
2225
2226 bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len,
2227 m, BPF_DIRECTION_IN(1 << 0));
2228 }
2229#endif
2230
2231 /* Send the frame to the 802.11 layer. */
2232 rxi.rxi_rssi = rssi;
2233 rxi.rxi_tstamp = 0; /* unused */
2234 ieee80211_inputm(ifp, m, ni, &rxi, ml);
2235
2236 /*
2237 * ieee80211_inputm() might have changed our BSS.
2238 * Restore ic_bss's channel if we are still in the same BSS.
2239 */
2240 if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr)(__builtin_memcmp((saved_bssid), (ni->ni_macaddr), (6)) ==
0)
)
2241 ni->ni_chan = bss_chan;
2242
2243 /* Node is no longer needed. */
2244 ieee80211_release_node(ic, ni);
2245}
2246
2247void
2248iwn_ra_choose(struct iwn_softc *sc, struct ieee80211_node *ni)
2249{
2250 struct ieee80211com *ic = &sc->sc_ic;
2251 struct iwn_node *wn = (void *)ni;
2252 int old_txmcs = ni->ni_txmcs;
2253
2254 ieee80211_ra_choose(&wn->rn, ic, ni);
2255
2256 /* Update firmware's LQ retry table if RA has chosen a new MCS. */
2257 if (ni->ni_txmcs != old_txmcs)
2258 iwn_set_link_quality(sc, ni);
2259}
2260
2261void
2262iwn_ampdu_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,
2263 struct iwn_tx_ring *txq, uint16_t seq, uint16_t ssn)
2264{
2265 struct ieee80211com *ic = &sc->sc_ic;
2266 struct iwn_node *wn = (void *)ni;
2267 int idx, end_idx;
2268
2269 /*
2270 * Update Tx rate statistics for A-MPDUs before firmware's BA window.
2271 */
2272 idx = IWN_AGG_SSN_TO_TXQ_IDX(seq)((seq) & (256 - 1));
2273 end_idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
2274 while (idx != end_idx) {
2275 struct iwn_tx_data *txdata = &txq->data[idx];
2276 if (txdata->m != NULL((void *)0) && txdata->ampdu_nframes > 1) {
2277 /*
2278 * We can assume that this subframe has been ACKed
2279 * because ACK failures come as single frames and
2280 * before failing an A-MPDU subframe the firmware
2281 * sends it as a single frame at least once.
2282 */
2283 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,
2284 txdata->ampdu_txmcs, 1, 0);
2285
2286 /* Report this frame only once. */
2287 txdata->ampdu_nframes = 0;
2288 }
2289
2290 idx = (idx + 1) % IWN_TX_RING_COUNT256;
2291 }
2292
2293 iwn_ra_choose(sc, ni);
2294}
2295
2296void
2297iwn_ht_single_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,
2298 uint8_t rate, uint8_t rflags, uint8_t ackfailcnt, int txfail)
2299{
2300 struct ieee80211com *ic = &sc->sc_ic;
2301 struct iwn_node *wn = (void *)ni;
2302 int mcs = rate;
2303 const struct ieee80211_ht_rateset *rs =
2304 ieee80211_ra_get_ht_rateset(rate,
2305 ieee80211_node_supports_ht_chan40(ni),
2306 ieee80211_ra_use_ht_sgi(ni));
2307 unsigned int retries = 0, i;
2308
2309 /*
2310 * Ignore Tx reports which don't match our last LQ command.
2311 */
2312 if (rate != ni->ni_txmcs) {
2313 if (++wn->lq_rate_mismatch > 15) {
2314 /* Try to sync firmware with driver. */
2315 iwn_set_link_quality(sc, ni);
2316 wn->lq_rate_mismatch = 0;
2317 }
2318 return;
2319 }
2320
2321 wn->lq_rate_mismatch = 0;
2322
2323 /*
2324 * Firmware has attempted rates in this rate set in sequence.
2325 * Retries at a basic rate are counted against the minimum MCS.
2326 */
2327 for (i = 0; i < ackfailcnt; i++) {
2328 if (mcs > rs->min_mcs) {
2329 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);
2330 mcs--;
2331 } else
2332 retries++;
2333 }
2334
2335 if (txfail && ackfailcnt == 0)
2336 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);
2337 else
2338 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, retries + 1, retries);
2339
2340 iwn_ra_choose(sc, ni);
2341}
2342
2343/*
2344 * Process an incoming Compressed BlockAck.
2345 * Note that these block ack notifications are generated by firmware and do
2346 * not necessarily correspond to contents of block ack frames seen on the air.
2347 */
2348void
2349iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2350 struct iwn_rx_data *data)
2351{
2352 struct iwn_compressed_ba *cba = (struct iwn_compressed_ba *)(desc + 1);
2353 struct ieee80211com *ic = &sc->sc_ic;
2354 struct ieee80211_node *ni;
2355 struct ieee80211_tx_ba *ba;
2356 struct iwn_tx_ring *txq;
2357 uint16_t seq, ssn;
2358 int qid;
2359
2360 if (ic->ic_state != IEEE80211_S_RUN)
2361 return;
2362
2363 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), sizeof (*cba),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*cba)), (0x02))
2364 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*cba)), (0x02))
;
2365
2366 if (!IEEE80211_ADDR_EQ(ic->ic_bss->ni_macaddr, cba->macaddr)(__builtin_memcmp((ic->ic_bss->ni_macaddr), (cba->macaddr
), (6)) == 0)
)
2367 return;
2368
2369 ni = ic->ic_bss;
2370
2371 qid = le16toh(cba->qid)((__uint16_t)(cba->qid));
2372 if (qid < sc->first_agg_txq || qid >= sc->ntxqs)
2373 return;
2374
2375 txq = &sc->txq[qid];
2376
2377 /* Protect against a firmware bug where the queue/TID are off. */
2378 if (qid != sc->first_agg_txq + cba->tid)
2379 return;
2380
2381 ba = &ni->ni_tx_ba[cba->tid];
2382 if (ba->ba_state != IEEE80211_BA_AGREED2)
2383 return;
2384
2385 /*
2386 * The first bit in cba->bitmap corresponds to the sequence number
2387 * stored in the sequence control field cba->seq.
2388 * Multiple BA notifications in a row may be using this number, with
2389 * additional bits being set in cba->bitmap. It is unclear how the
2390 * firmware decides to shift this window forward.
2391 * We rely on ba->ba_winstart instead.
2392 */
2393 seq = le16toh(cba->seq)((__uint16_t)(cba->seq)) >> IEEE80211_SEQ_SEQ_SHIFT4;
2394
2395 /*
2396 * The firmware's new BA window starting sequence number
2397 * corresponds to the first hole in cba->bitmap, implying
2398 * that all frames between 'seq' and 'ssn' (non-inclusive)
2399 * have been acked.
2400 */
2401 ssn = le16toh(cba->ssn)((__uint16_t)(cba->ssn));
2402
2403 if (SEQ_LT(ssn, ba->ba_winstart)((((u_int16_t)(ssn) - (u_int16_t)(ba->ba_winstart)) & 0xfff
) > 2048)
)
2404 return;
2405
2406 /* Skip rate control if our Tx rate is fixed. */
2407 if (ic->ic_fixed_mcs == -1)
2408 iwn_ampdu_rate_control(sc, ni, txq, ba->ba_winstart, ssn);
2409
2410 /*
2411 * SSN corresponds to the first (perhaps not yet transmitted) frame
2412 * in firmware's BA window. Firmware is not going to retransmit any
2413 * frames before its BA window so mark them all as done.
2414 */
2415 ieee80211_output_ba_move_window(ic, ni, cba->tid, ssn);
2416 iwn_ampdu_txq_advance(sc, txq, qid,
2417 IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1)));
2418 iwn_clear_oactive(sc, txq);
2419}
2420
2421/*
2422 * Process a CALIBRATION_RESULT notification sent by the initialization
2423 * firmware on response to a CMD_CALIB_CONFIG command (5000 only).
2424 */
2425void
2426iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2427 struct iwn_rx_data *data)
2428{
2429 struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1);
2430 int len, idx = -1;
2431
2432 /* Runtime firmware should not send such a notification. */
2433 if (sc->sc_flags & IWN_FLAG_CALIB_DONE(1 << 2))
2434 return;
2435
2436 len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff) - 4;
2437 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc), len,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
2438 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
;
2439
2440 switch (calib->code) {
2441 case IWN5000_PHY_CALIB_DC8:
2442 if (sc->hw_type == IWN_HW_REV_TYPE_51504 ||
2443 sc->hw_type == IWN_HW_REV_TYPE_203012 ||
2444 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
2445 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
2446 sc->hw_type == IWN_HW_REV_TYPE_10517)
2447 idx = 0;
2448 break;
2449 case IWN5000_PHY_CALIB_LO9:
2450 idx = 1;
2451 break;
2452 case IWN5000_PHY_CALIB_TX_IQ11:
2453 idx = 2;
2454 break;
2455 case IWN5000_PHY_CALIB_TX_IQ_PERIODIC17:
2456 if (sc->hw_type < IWN_HW_REV_TYPE_60007 &&
2457 sc->hw_type != IWN_HW_REV_TYPE_51504)
2458 idx = 3;
2459 break;
2460 case IWN5000_PHY_CALIB_BASE_BAND16:
2461 idx = 4;
2462 break;
2463 }
2464 if (idx == -1) /* Ignore other results. */
2465 return;
2466
2467 /* Save calibration result. */
2468 if (sc->calibcmd[idx].buf != NULL((void *)0))
2469 free(sc->calibcmd[idx].buf, M_DEVBUF2, 0);
2470 sc->calibcmd[idx].buf = malloc(len, M_DEVBUF2, M_NOWAIT0x0002);
2471 if (sc->calibcmd[idx].buf == NULL((void *)0)) {
2472 DPRINTF(("not enough memory for calibration result %d\n",
2473 calib->code));
2474 return;
2475 }
2476 DPRINTF(("saving calibration result code=%d len=%d\n",
2477 calib->code, len));
2478 sc->calibcmd[idx].len = len;
2479 memcpy(sc->calibcmd[idx].buf, calib, len)__builtin_memcpy((sc->calibcmd[idx].buf), (calib), (len));
2480}
2481
2482/*
2483 * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.
2484 * The latter is sent by the firmware after each received beacon.
2485 */
2486void
2487iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2488 struct iwn_rx_data *data)
2489{
2490 struct iwn_ops *ops = &sc->ops;
2491 struct ieee80211com *ic = &sc->sc_ic;
2492 struct iwn_calib_state *calib = &sc->calib;
2493 struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
2494 int temp;
2495
2496 /* Ignore statistics received during a scan. */
2497 if (ic->ic_state != IEEE80211_S_RUN)
2498 return;
2499
2500 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stats)), (0x02))
2501 sizeof (*stats), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stats)), (0x02))
;
2502
2503 DPRINTFN(3, ("received statistics (cmd=%d)\n", desc->type));
2504 sc->calib_cnt = 0; /* Reset TX power calibration timeout. */
2505
2506 sc->rx_stats_flags = htole32(stats->flags)((__uint32_t)(stats->flags));
2507
2508 /* Test if temperature has changed. */
2509 if (stats->general.temp != sc->rawtemp) {
2510 /* Convert "raw" temperature to degC. */
2511 sc->rawtemp = stats->general.temp;
2512 temp = ops->get_temperature(sc);
2513 DPRINTFN(2, ("temperature=%dC\n", temp));
2514
2515 /* Update TX power if need be (4965AGN only). */
2516 if (sc->hw_type == IWN_HW_REV_TYPE_49650)
2517 iwn4965_power_calibration(sc, temp);
2518 }
2519
2520 if (desc->type != IWN_BEACON_STATISTICS157)
2521 return; /* Reply to a statistics request. */
2522
2523 sc->noise = iwn_get_noise(&stats->rx.general);
2524
2525 /* Test that RSSI and noise are present in stats report. */
2526 if (sc->noise == -127)
2527 return;
2528
2529 if (letoh32(stats->rx.general.flags)((__uint32_t)(stats->rx.general.flags)) != 1) {
2530 DPRINTF(("received statistics without RSSI\n"));
2531 return;
2532 }
2533
2534 /*
2535 * XXX Differential gain calibration makes the 6005 firmware
2536 * crap out, so skip it for now. This effectively disables
2537 * sensitivity tuning as well.
2538 */
2539 if (sc->hw_type == IWN_HW_REV_TYPE_600511)
2540 return;
2541
2542 if (calib->state == IWN_CALIB_STATE_ASSOC1)
2543 iwn_collect_noise(sc, &stats->rx.general);
2544 else if (calib->state == IWN_CALIB_STATE_RUN2)
2545 iwn_tune_sensitivity(sc, &stats->rx);
2546}
2547
2548void
2549iwn_ampdu_txq_advance(struct iwn_softc *sc, struct iwn_tx_ring *txq, int qid,
2550 int idx)
2551{
2552 struct iwn_ops *ops = &sc->ops;
2553
2554 DPRINTFN(3, ("%s: txq->cur=%d txq->read=%d txq->queued=%d qid=%d "
2555 "idx=%d\n", __func__, txq->cur, txq->read, txq->queued, qid, idx));
2556
2557 while (txq->read != idx) {
2558 struct iwn_tx_data *txdata = &txq->data[txq->read];
2559 if (txdata->m != NULL((void *)0)) {
2560 ops->reset_sched(sc, qid, txq->read);
2561 iwn_tx_done_free_txdata(sc, txdata);
2562 txq->queued--;
2563 }
2564 txq->read = (txq->read + 1) % IWN_TX_RING_COUNT256;
2565 }
2566}
2567
2568/*
2569 * Handle A-MPDU Tx queue status report.
2570 * Tx failures come as single frames (perhaps out of order), and before failing
2571 * an A-MPDU subframe the firmware transmits it as a single frame at least once.
2572 * Frames successfully transmitted in an A-MPDU are completed when a compressed
2573 * block ack notification is received.
2574 */
2575void
2576iwn_ampdu_tx_done(struct iwn_softc *sc, struct iwn_tx_ring *txq,
2577 struct iwn_rx_desc *desc, uint16_t status, uint8_t ackfailcnt,
2578 uint8_t rate, uint8_t rflags, int nframes, uint32_t ssn,
2579 struct iwn_txagg_status *agg_status)
2580{
2581 struct ieee80211com *ic = &sc->sc_ic;
2582 int tid = desc->qid - sc->first_agg_txq;
2583 struct iwn_tx_data *txdata = &txq->data[desc->idx];
2584 struct ieee80211_node *ni = txdata->ni;
2585 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2586 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2587 struct ieee80211_tx_ba *ba;
2588 uint16_t seq;
2589
2590 sc->sc_tx_timer = 0;
2591
2592 if (ic->ic_state != IEEE80211_S_RUN)
2593 return;
2594
2595 if (nframes > 1) {
2596 int i;
2597
2598 /*
2599 * Collect information about this A-MPDU.
2600 */
2601 for (i = 0; i < nframes; i++) {
2602 uint8_t qid = agg_status[i].qid;
2603 uint8_t idx = agg_status[i].idx;
2604 uint16_t txstatus = (le16toh(agg_status[i].status)((__uint16_t)(agg_status[i].status)) &
2605 IWN_AGG_TX_STATUS_MASK0x0fff);
2606
2607 if (txstatus != IWN_AGG_TX_STATE_TRANSMITTED0x0000)
2608 continue;
2609
2610 if (qid != desc->qid)
2611 continue;
2612
2613 txdata = &txq->data[idx];
2614 if (txdata->ni == NULL((void *)0))
2615 continue;
2616
2617 /* The Tx rate was the same for all subframes. */
2618 txdata->ampdu_txmcs = rate;
2619 txdata->ampdu_nframes = nframes;
2620 }
2621 return;
2622 }
2623
2624 if (ni == NULL((void *)0))
2625 return;
2626
2627 ba = &ni->ni_tx_ba[tid];
2628 if (ba->ba_state != IEEE80211_BA_AGREED2)
2629 return;
2630 if (SEQ_LT(ssn, ba->ba_winstart)((((u_int16_t)(ssn) - (u_int16_t)(ba->ba_winstart)) & 0xfff
) > 2048)
)
2631 return;
2632
2633 /* This was a final single-frame Tx attempt for frame SSN-1. */
2634 seq = (ssn - 1) & 0xfff;
Value stored to 'seq' is never read
2635
2636 /*
2637 * Skip rate control if our Tx rate is fixed.
2638 */
2639 if (ic->ic_fixed_mcs == -1) {
2640 if (txdata->ampdu_nframes > 1) {
2641 struct iwn_node *wn = (void *)ni;
2642 /*
2643 * This frame was once part of an A-MPDU.
2644 * Report one failed A-MPDU Tx attempt.
2645 * The firmware might have made several such
2646 * attempts but we don't keep track of this.
2647 */
2648 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,
2649 txdata->ampdu_txmcs, 1, 1);
2650 }
2651
2652 /* Report the final single-frame Tx attempt. */
2653 if (rflags & IWN_RFLAG_MCS(1 << 0))
2654 iwn_ht_single_rate_control(sc, ni, rate, rflags,
2655 ackfailcnt, txfail);
2656 }
2657
2658 if (txfail)
2659 ieee80211_tx_compressed_bar(ic, ni, tid, ssn);
2660
2661 /*
2662 * SSN corresponds to the first (perhaps not yet transmitted) frame
2663 * in firmware's BA window. Firmware is not going to retransmit any
2664 * frames before its BA window so mark them all as done.
2665 */
2666 ieee80211_output_ba_move_window(ic, ni, tid, ssn);
2667 iwn_ampdu_txq_advance(sc, txq, desc->qid, IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1)));
2668 iwn_clear_oactive(sc, txq);
2669}
2670
2671/*
2672 * Process a TX_DONE firmware notification. Unfortunately, the 4965AGN
2673 * and 5000 adapters have different incompatible TX status formats.
2674 */
2675void
2676iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2677 struct iwn_rx_data *data)
2678{
2679 struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1);
2680 struct iwn_tx_ring *ring;
2681 size_t len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff);
2682 uint16_t status = letoh32(stat->stat.status)((__uint32_t)(stat->stat.status)) & 0xff;
2683 uint32_t ssn;
2684
2685 if (desc->qid > IWN4965_NTXQUEUES16)
2686 return;
2687
2688 ring = &sc->txq[desc->qid];
2689
2690 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
2691 len, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
;
2692
2693 /* Sanity checks. */
2694 if (sizeof(*stat) > len)
2695 return;
2696 if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX63)
2697 return;
2698 if (desc->qid < sc->first_agg_txq && stat->nframes > 1)
2699 return;
2700 if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +
2701 stat->nframes * sizeof(stat->stat) > len)
2702 return;
2703
2704 if (desc->qid < sc->first_agg_txq) {
2705 /* XXX 4965 does not report byte count */
2706 struct iwn_tx_data *txdata = &ring->data[desc->idx];
2707 uint16_t framelen = txdata->totlen + IEEE80211_CRC_LEN4;
2708 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2709 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2710
2711 iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,
2712 stat->rflags, txfail, desc->qid, framelen);
2713 } else {
2714 memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn))__builtin_memcpy((&ssn), (&stat->stat.status + stat
->nframes), (sizeof(ssn)))
;
2715 ssn = le32toh(ssn)((__uint32_t)(ssn)) & 0xfff;
2716 iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,
2717 stat->rate, stat->rflags, stat->nframes, ssn,
2718 stat->stat.agg_status);
2719 }
2720}
2721
2722void
2723iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2724 struct iwn_rx_data *data)
2725{
2726 struct iwn5000_tx_stat *stat = (struct iwn5000_tx_stat *)(desc + 1);
2727 struct iwn_tx_ring *ring;
2728 size_t len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff);
2729 uint16_t status = letoh32(stat->stat.status)((__uint32_t)(stat->stat.status)) & 0xff;
2730 uint32_t ssn;
2731
2732 if (desc->qid > IWN5000_NTXQUEUES20)
2733 return;
2734
2735 ring = &sc->txq[desc->qid];
2736
2737 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
2738 sizeof (*stat), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
;
2739
2740 /* Sanity checks. */
2741 if (sizeof(*stat) > len)
2742 return;
2743 if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX63)
2744 return;
2745 if (desc->qid < sc->first_agg_txq && stat->nframes > 1)
2746 return;
2747 if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +
2748 stat->nframes * sizeof(stat->stat) > len)
2749 return;
2750
2751 /* If this was not an aggregated frame, complete it now. */
2752 if (desc->qid < sc->first_agg_txq) {
2753 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2754 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2755
2756 /* Reset TX scheduler slot. */
2757 iwn5000_reset_sched(sc, desc->qid, desc->idx);
2758
2759 iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,
2760 stat->rflags, txfail, desc->qid, letoh16(stat->len)((__uint16_t)(stat->len)));
2761 } else {
2762 memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn))__builtin_memcpy((&ssn), (&stat->stat.status + stat
->nframes), (sizeof(ssn)))
;
2763 ssn = le32toh(ssn)((__uint32_t)(ssn)) & 0xfff;
2764 iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,
2765 stat->rate, stat->rflags, stat->nframes, ssn,
2766 stat->stat.agg_status);
2767 }
2768}
2769
2770void
2771iwn_tx_done_free_txdata(struct iwn_softc *sc, struct iwn_tx_data *data)
2772{
2773 struct ieee80211com *ic = &sc->sc_ic;
2774
2775 bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
2776 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
2777 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2778 m_freem(data->m);
2779 data->m = NULL((void *)0);
2780 ieee80211_release_node(ic, data->ni);
2781 data->ni = NULL((void *)0);
2782 data->totlen = 0;
2783 data->ampdu_nframes = 0;
2784 data->ampdu_txmcs = 0;
2785}
2786
2787void
2788iwn_clear_oactive(struct iwn_softc *sc, struct iwn_tx_ring *ring)
2789{
2790 struct ieee80211com *ic = &sc->sc_ic;
2791 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2792
2793 if (ring->queued < IWN_TX_RING_LOMARK192) {
2794 sc->qfullmsk &= ~(1 << ring->qid);
2795 if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {
2796 ifq_clr_oactive(&ifp->if_snd);
2797 (*ifp->if_start)(ifp);
2798 }
2799 }
2800}
2801
2802/*
2803 * Adapter-independent backend for TX_DONE firmware notifications.
2804 * This handles Tx status for non-aggregation queues.
2805 */
2806void
2807iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2808 uint8_t ackfailcnt, uint8_t rate, uint8_t rflags, int txfail,
2809 int qid, uint16_t len)
2810{
2811 struct ieee80211com *ic = &sc->sc_ic;
2812 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2813 struct iwn_tx_ring *ring = &sc->txq[qid];
2814 struct iwn_tx_data *data = &ring->data[desc->idx];
2815 struct iwn_node *wn = (void *)data->ni;
2816
2817 if (data->ni == NULL((void *)0))
2818 return;
2819
2820 if (data->ni->ni_flags & IEEE80211_NODE_HT0x0400) {
2821 if (ic->ic_state == IEEE80211_S_RUN &&
2822 ic->ic_fixed_mcs == -1 && (rflags & IWN_RFLAG_MCS(1 << 0))) {
2823 iwn_ht_single_rate_control(sc, data->ni, rate, rflags,
2824 ackfailcnt, txfail);
2825 }
2826 } else {
2827 if (rate != data->ni->ni_txrate) {
2828 if (++wn->lq_rate_mismatch > 15) {
2829 /* Try to sync firmware with driver. */
2830 iwn_set_link_quality(sc, data->ni);
2831 wn->lq_rate_mismatch = 0;
2832 }
2833 } else {
2834 wn->lq_rate_mismatch = 0;
2835
2836 wn->amn.amn_txcnt++;
2837 if (ackfailcnt > 0)
2838 wn->amn.amn_retrycnt++;
2839 if (txfail)
2840 wn->amn.amn_retrycnt++;
2841 }
2842 }
2843 if (txfail)
2844 ifp->if_oerrorsif_data.ifi_oerrors++;
2845
2846 iwn_tx_done_free_txdata(sc, data);
2847
2848 sc->sc_tx_timer = 0;
2849 ring->queued--;
2850 iwn_clear_oactive(sc, ring);
2851}
2852
2853/*
2854 * Process a "command done" firmware notification. This is where we wakeup
2855 * processes waiting for a synchronous command completion.
2856 */
2857void
2858iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
2859{
2860 struct iwn_tx_ring *ring = &sc->txq[4];
2861 struct iwn_tx_data *data;
2862
2863 if ((desc->qid & 0xf) != 4)
2864 return; /* Not a command ack. */
2865
2866 data = &ring->data[desc->idx];
2867
2868 /* If the command was mapped in an mbuf, free it. */
2869 if (data->m != NULL((void *)0)) {
2870 bus_dmamap_sync(sc->sc_dmat, data->map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
2871 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
2872 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2873 m_freem(data->m);
2874 data->m = NULL((void *)0);
2875 }
2876 wakeup(&ring->desc[desc->idx]);
2877}
2878
2879/*
2880 * Process an INT_FH_RX or INT_SW_RX interrupt.
2881 */
2882void
2883iwn_notif_intr(struct iwn_softc *sc)
2884{
2885 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
2886 struct iwn_ops *ops = &sc->ops;
2887 struct ieee80211com *ic = &sc->sc_ic;
2888 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2889 uint16_t hw;
2890
2891 bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
rxq.stat_dma.map), (0), (sc->rxq.stat_dma.size), (0x02))
2892 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
rxq.stat_dma.map), (0), (sc->rxq.stat_dma.size), (0x02))
;
2893
2894 hw = letoh16(sc->rxq.stat->closed_count)((__uint16_t)(sc->rxq.stat->closed_count)) & 0xfff;
2895 while (sc->rxq.cur != hw) {
2896 struct iwn_rx_data *data = &sc->rxq.data[sc->rxq.cur];
2897 struct iwn_rx_desc *desc;
2898
2899 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (sizeof (*desc)), (0x02))
2900 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (sizeof (*desc)), (0x02))
;
2901 desc = mtod(data->m, struct iwn_rx_desc *)((struct iwn_rx_desc *)((data->m)->m_hdr.mh_data));
2902
2903 DPRINTFN(4, ("notification qid=%d idx=%d flags=%x type=%d\n",
2904 desc->qid & 0xf, desc->idx, desc->flags, desc->type));
2905
2906 if (!(desc->qid & 0x80)) /* Reply to a command. */
2907 iwn_cmd_done(sc, desc);
2908
2909 switch (desc->type) {
2910 case IWN_RX_PHY192:
2911 iwn_rx_phy(sc, desc, data);
2912 break;
2913
2914 case IWN_RX_DONE195: /* 4965AGN only. */
2915 case IWN_MPDU_RX_DONE193:
2916 /* An 802.11 frame has been received. */
2917 iwn_rx_done(sc, desc, data, &ml);
2918 break;
2919 case IWN_RX_COMPRESSED_BA197:
2920 /* A Compressed BlockAck has been received. */
2921 iwn_rx_compressed_ba(sc, desc, data);
2922 break;
2923 case IWN_TX_DONE28:
2924 /* An 802.11 frame has been transmitted. */
2925 ops->tx_done(sc, desc, data);
2926 break;
2927
2928 case IWN_RX_STATISTICS156:
2929 case IWN_BEACON_STATISTICS157:
2930 iwn_rx_statistics(sc, desc, data);
2931 break;
2932
2933 case IWN_BEACON_MISSED162:
2934 {
2935 struct iwn_beacon_missed *miss =
2936 (struct iwn_beacon_missed *)(desc + 1);
2937 uint32_t missed;
2938
2939 if ((ic->ic_opmode != IEEE80211_M_STA) ||
2940 (ic->ic_state != IEEE80211_S_RUN))
2941 break;
2942
2943 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*miss)), (0x02))
2944 sizeof (*miss), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*miss)), (0x02))
;
2945 missed = letoh32(miss->consecutive)((__uint32_t)(miss->consecutive));
2946
2947 /*
2948 * If more than 5 consecutive beacons are missed,
2949 * reinitialize the sensitivity state machine.
2950 */
2951 if (missed > 5)
2952 (void)iwn_init_sensitivity(sc);
2953
2954 /*
2955 * Rather than go directly to scan state, try to send a
2956 * directed probe request first. If that fails then the
2957 * state machine will drop us into scanning after timing
2958 * out waiting for a probe response.
2959 */
2960 if (missed > ic->ic_bmissthres && !ic->ic_mgt_timer) {
2961 if (ic->ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
2962 printf("%s: receiving no beacons from "
2963 "%s; checking if this AP is still "
2964 "responding to probe requests\n",
2965 sc->sc_dev.dv_xname, ether_sprintf(
2966 ic->ic_bss->ni_macaddr));
2967 IEEE80211_SEND_MGMT(ic, ic->ic_bss,((*(ic)->ic_send_mgmt)(ic, ic->ic_bss, 0x40, 0, 0))
2968 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0)((*(ic)->ic_send_mgmt)(ic, ic->ic_bss, 0x40, 0, 0));
2969 }
2970 break;
2971 }
2972 case IWN_UC_READY1:
2973 {
2974 struct iwn_ucode_info *uc =
2975 (struct iwn_ucode_info *)(desc + 1);
2976
2977 /* The microcontroller is ready. */
2978 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*uc)), (0x02))
2979 sizeof (*uc), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*uc)), (0x02))
;
2980 DPRINTF(("microcode alive notification version=%d.%d "
2981 "subtype=%x alive=%x\n", uc->major, uc->minor,
2982 uc->subtype, letoh32(uc->valid)));
2983
2984 if (letoh32(uc->valid)((__uint32_t)(uc->valid)) != 1) {
2985 printf("%s: microcontroller initialization "
2986 "failed\n", sc->sc_dev.dv_xname);
2987 break;
2988 }
2989 if (uc->subtype == IWN_UCODE_INIT9) {
2990 /* Save microcontroller report. */
2991 memcpy(&sc->ucode_info, uc, sizeof (*uc))__builtin_memcpy((&sc->ucode_info), (uc), (sizeof (*uc
)))
;
2992 }
2993 /* Save the address of the error log in SRAM. */
2994 sc->errptr = letoh32(uc->errptr)((__uint32_t)(uc->errptr));
2995 break;
2996 }
2997 case IWN_STATE_CHANGED161:
2998 {
2999 uint32_t *status = (uint32_t *)(desc + 1);
3000
3001 /* Enabled/disabled notification. */
3002 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*status)), (0x02))
3003 sizeof (*status), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*status)), (0x02))
;
3004 DPRINTF(("state changed to %x\n", letoh32(*status)));
3005
3006 if (letoh32(*status)((__uint32_t)(*status)) & 1) {
3007 /* Radio transmitter is off, power down. */
3008 iwn_stop(ifp);
3009 return; /* No further processing. */
3010 }
3011 break;
3012 }
3013 case IWN_START_SCAN130:
3014 {
3015 struct iwn_start_scan *scan =
3016 (struct iwn_start_scan *)(desc + 1);
3017
3018 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
3019 sizeof (*scan), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
;
3020 DPRINTFN(2, ("scan start: chan %d status %x\n",
3021 scan->chan, letoh32(scan->status)));
3022
3023 if (sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9))
3024 break;
3025
3026 /* Fix current channel. */
3027 ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
3028 break;
3029 }
3030 case IWN_STOP_SCAN132:
3031 {
3032 struct iwn_stop_scan *scan =
3033 (struct iwn_stop_scan *)(desc + 1);
3034
3035 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
3036 sizeof (*scan), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
;
3037 DPRINTFN(2, ("scan stop: nchan=%d status=%d chan=%d\n",
3038 scan->nchan, scan->status, scan->chan));
3039
3040 if (scan->status == 1 && scan->chan <= 14 &&
3041 (sc->sc_flags & IWN_FLAG_HAS_5GHZ(1 << 0))) {
3042 int error;
3043 /*
3044 * We just finished scanning 2GHz channels,
3045 * start scanning 5GHz ones.
3046 */
3047 error = iwn_scan(sc, IEEE80211_CHAN_5GHZ0x0100,
3048 (sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9)) ? 1 : 0);
3049 if (error == 0)
3050 break;
3051 }
3052 sc->sc_flags &= ~IWN_FLAG_SCANNING(1 << 10);
3053 sc->sc_flags &= ~IWN_FLAG_BGSCAN(1 << 9);
3054 ieee80211_end_scan(ifp);
3055 break;
3056 }
3057 case IWN5000_CALIBRATION_RESULT102:
3058 iwn5000_rx_calib_results(sc, desc, data);
3059 break;
3060
3061 case IWN5000_CALIBRATION_DONE103:
3062 sc->sc_flags |= IWN_FLAG_CALIB_DONE(1 << 2);
3063 wakeup(sc);
3064 break;
3065 }
3066
3067 sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT(1 << 6);
3068 }
3069 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
3070
3071 /* Tell the firmware what we have processed. */
3072 hw = (hw == 0) ? IWN_RX_RING_COUNT(1 << 6) - 1 : hw - 1;
3073 IWN_WRITE(sc, IWN_FH_RX_WPTR, hw & ~7)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(hw & ~7))))
;
3074}
3075
3076/*
3077 * Process an INT_WAKEUP interrupt raised when the microcontroller wakes up
3078 * from power-down sleep mode.
3079 */
3080void
3081iwn_wakeup_intr(struct iwn_softc *sc)
3082{
3083 int qid;
3084
3085 DPRINTF(("ucode wakeup from power-down sleep\n"));
3086
3087 /* Wakeup RX and TX rings. */
3088 IWN_WRITE(sc, IWN_FH_RX_WPTR, sc->rxq.cur & ~7)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(sc->rxq.cur & ~7))))
;
3089 for (qid = 0; qid < sc->ntxqs; qid++) {
3090 struct iwn_tx_ring *ring = &sc->txq[qid];
3091 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | ring->cur)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | ring->cur))))
;
3092 }
3093}
3094
3095/*
3096 * Dump the error log of the firmware when a firmware panic occurs. Although
3097 * we can't debug the firmware because it is neither open source nor free, it
3098 * can help us to identify certain classes of problems.
3099 */
3100void
3101iwn_fatal_intr(struct iwn_softc *sc)
3102{
3103 struct iwn_fw_dump dump;
3104 int i;
3105
3106 /* Check that the error log address is valid. */
3107 if (sc->errptr < IWN_FW_DATA_BASE0x00800000 ||
3108 sc->errptr + sizeof (dump) >
3109 IWN_FW_DATA_BASE0x00800000 + sc->fw_data_maxsz) {
3110 printf("%s: bad firmware error log address 0x%08x\n",
3111 sc->sc_dev.dv_xname, sc->errptr);
3112 return;
3113 }
3114 if (iwn_nic_lock(sc) != 0) {
3115 printf("%s: could not read firmware error log\n",
3116 sc->sc_dev.dv_xname);
3117 return;
3118 }
3119 /* Read firmware error log from SRAM. */
3120 iwn_mem_read_region_4(sc, sc->errptr, (uint32_t *)&dump,
3121 sizeof (dump) / sizeof (uint32_t));
3122 iwn_nic_unlock(sc);
3123
3124 if (dump.valid == 0) {
3125 printf("%s: firmware error log is empty\n",
3126 sc->sc_dev.dv_xname);
3127 return;
3128 }
3129 printf("firmware error log:\n");
3130 printf(" error type = \"%s\" (0x%08X)\n",
3131 (dump.id < nitems(iwn_fw_errmsg)(sizeof((iwn_fw_errmsg)) / sizeof((iwn_fw_errmsg)[0]))) ?
3132 iwn_fw_errmsg[dump.id] : "UNKNOWN",
3133 dump.id);
3134 printf(" program counter = 0x%08X\n", dump.pc);
3135 printf(" source line = 0x%08X\n", dump.src_line);
3136 printf(" error data = 0x%08X%08X\n",
3137 dump.error_data[0], dump.error_data[1]);
3138 printf(" branch link = 0x%08X%08X\n",
3139 dump.branch_link[0], dump.branch_link[1]);
3140 printf(" interrupt link = 0x%08X%08X\n",
3141 dump.interrupt_link[0], dump.interrupt_link[1]);
3142 printf(" time = %u\n", dump.time[0]);
3143
3144 /* Dump driver status (TX and RX rings) while we're here. */
3145 printf("driver status:\n");
3146 for (i = 0; i < sc->ntxqs; i++) {
3147 struct iwn_tx_ring *ring = &sc->txq[i];
3148 printf(" tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n",
3149 i, ring->qid, ring->cur, ring->queued);
3150 }
3151 printf(" rx ring: cur=%d\n", sc->rxq.cur);
3152 printf(" 802.11 state %d\n", sc->sc_ic.ic_state);
3153}
3154
3155int
3156iwn_intr(void *arg)
3157{
3158 struct iwn_softc *sc = arg;
3159 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
3160 uint32_t r1, r2, tmp;
3161
3162 /* Disable interrupts. */
3163 IWN_WRITE(sc, IWN_INT_MASK, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
0))))
;
3164
3165 /* Read interrupts from ICT (fast) or from registers (slow). */
3166 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)) {
3167 tmp = 0;
3168 while (sc->ict[sc->ict_cur] != 0) {
3169 tmp |= sc->ict[sc->ict_cur];
3170 sc->ict[sc->ict_cur] = 0; /* Acknowledge. */
3171 sc->ict_cur = (sc->ict_cur + 1) % IWN_ICT_COUNT(4096 / sizeof (uint32_t));
3172 }
3173 tmp = letoh32(tmp)((__uint32_t)(tmp));
3174 if (tmp == 0xffffffff) /* Shouldn't happen. */
3175 tmp = 0;
3176 else if (tmp & 0xc0000) /* Workaround a HW bug. */
3177 tmp |= 0x8000;
3178 r1 = (tmp & 0xff00) << 16 | (tmp & 0xff);
3179 r2 = 0; /* Unused. */
3180 } else {
3181 r1 = IWN_READ(sc, IWN_INT)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x008))));
3182 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
3183 return 0; /* Hardware gone! */
3184 r2 = IWN_READ(sc, IWN_FH_INT)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x010))));
3185 }
3186 if (r1 == 0 && r2 == 0) {
3187 if (ifp->if_flags & IFF_UP0x1)
3188 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
3189 return 0; /* Interrupt not for us. */
3190 }
3191
3192 /* Acknowledge interrupts. */
3193 IWN_WRITE(sc, IWN_INT, r1)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
r1))))
;
3194 if (!(sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)))
3195 IWN_WRITE(sc, IWN_FH_INT, r2)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
r2))))
;
3196
3197 if (r1 & IWN_INT_RF_TOGGLED(1U << 7)) {
3198 tmp = IWN_READ(sc, IWN_GP_CNTRL)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) & IWN_GP_CNTRL_RFKILL(1 << 27);
3199 printf("%s: RF switch: radio %s\n", sc->sc_dev.dv_xname,
3200 tmp ? "enabled" : "disabled");
3201 if (tmp)
3202 task_add(systq, &sc->init_task);
3203 }
3204 if (r1 & IWN_INT_CT_REACHED(1U << 6)) {
3205 printf("%s: critical temperature reached!\n",
3206 sc->sc_dev.dv_xname);
3207 }
3208 if (r1 & (IWN_INT_SW_ERR(1U << 25) | IWN_INT_HW_ERR(1U << 29))) {
3209 printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
3210
3211 /* Force a complete recalibration on next init. */
3212 sc->sc_flags &= ~IWN_FLAG_CALIB_DONE(1 << 2);
3213
3214 /* Dump firmware error log and stop. */
3215 if (ifp->if_flags & IFF_DEBUG0x4)
3216 iwn_fatal_intr(sc);
3217 iwn_stop(ifp);
3218 task_add(systq, &sc->init_task);
3219 return 1;
3220 }
3221 if ((r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3) | IWN_INT_RX_PERIODIC(1U << 28))) ||
3222 (r2 & IWN_FH_INT_RX((1 << ((0) + 16)) | (1 << ((1) + 16)) | (1 <<
30))
)) {
3223 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)) {
3224 if (r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3)))
3225 IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_RX)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
((1 << ((0) + 16)) | (1 << ((1) + 16)) | (1 <<
30))))))
;
3226 IWN_WRITE_1(sc, IWN_INT_PERIODIC,(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0x00))))
3227 IWN_INT_PERIODIC_DIS)(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0x00))))
;
3228 iwn_notif_intr(sc);
3229 if (r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3))) {
3230 IWN_WRITE_1(sc, IWN_INT_PERIODIC,(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0xff))))
3231 IWN_INT_PERIODIC_ENA)(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0xff))))
;
3232 }
3233 } else
3234 iwn_notif_intr(sc);
3235 }
3236
3237 if ((r1 & IWN_INT_FH_TX(1U << 27)) || (r2 & IWN_FH_INT_TX((1 << (0)) | (1 << (1))))) {
3238 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3))
3239 IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_TX)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
((1 << (0)) | (1 << (1)))))))
;
3240 wakeup(sc); /* FH DMA transfer completed. */
3241 }
3242
3243 if (r1 & IWN_INT_ALIVE(1U << 0))
3244 wakeup(sc); /* Firmware is alive. */
3245
3246 if (r1 & IWN_INT_WAKEUP(1U << 1))
3247 iwn_wakeup_intr(sc);
3248
3249 /* Re-enable interrupts. */
3250 if (ifp->if_flags & IFF_UP0x1)
3251 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
3252
3253 return 1;
3254}
3255
3256/*
3257 * Update TX scheduler ring when transmitting an 802.11 frame (4965AGN and
3258 * 5000 adapters use a slightly different format).
3259 */
3260void
3261iwn4965_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,
3262 uint16_t len)
3263{
3264 uint16_t *w = &sc->sched[qid * IWN4965_SCHED_COUNT512 + idx];
3265
3266 *w = htole16(len + 8)((__uint16_t)(len + 8));
3267 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3268 (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3269 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
;
3270 if (idx < IWN_SCHED_WINSZ64) {
3271 *(w + IWN_TX_RING_COUNT256) = *w;
3272 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3273 (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3274 sizeof (uint16_t), BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
;
3275 }
3276}
3277
3278void
3279iwn4965_reset_sched(struct iwn_softc *sc, int qid, int idx)
3280{
3281 /* TBD */
3282}
3283
3284void
3285iwn5000_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,
3286 uint16_t len)
3287{
3288 uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT(256 + 64) + idx];
3289
3290 *w = htole16(id << 12 | (len + 8))((__uint16_t)(id << 12 | (len + 8)));
3291 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3292 (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3293 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
;
3294 if (idx < IWN_SCHED_WINSZ64) {
3295 *(w + IWN_TX_RING_COUNT256) = *w;
3296 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3297 (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3298 sizeof (uint16_t), BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
;
3299 }
3300}
3301
3302void
3303iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)
3304{
3305 uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT(256 + 64) + idx];
3306
3307 *w = (*w & htole16(0xf000)((__uint16_t)(0xf000))) | htole16(1)((__uint16_t)(1));
3308 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3309 (caddr_t)w - sc->sched_dma.vaddr, sizeof (uint16_t),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3310 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)w - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
;
3311 if (idx < IWN_SCHED_WINSZ64) {
3312 *(w + IWN_TX_RING_COUNT256) = *w;
3313 bus_dmamap_sync(sc->sc_dmat, sc->sched_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3314 (caddr_t)(w + IWN_TX_RING_COUNT) - sc->sched_dma.vaddr,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
3315 sizeof (uint16_t), BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc->
sched_dma.map), ((caddr_t)(w + 256) - sc->sched_dma.vaddr)
, (sizeof (uint16_t)), (0x04))
;
3316 }
3317}
3318
3319int
3320iwn_rval2ridx(int rval)
3321{
3322 int ridx;
3323
3324 for (ridx = 0; ridx < nitems(iwn_rates)(sizeof((iwn_rates)) / sizeof((iwn_rates)[0])); ridx++) {
3325 if (rval == iwn_rates[ridx].rate)
3326 break;
3327 }
3328
3329 return ridx;
3330}
3331
3332int
3333iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
3334{
3335 struct iwn_ops *ops = &sc->ops;
3336 struct ieee80211com *ic = &sc->sc_ic;
3337 struct iwn_node *wn = (void *)ni;
3338 struct iwn_tx_ring *ring;
3339 struct iwn_tx_desc *desc;
3340 struct iwn_tx_data *data;
3341 struct iwn_tx_cmd *cmd;
3342 struct iwn_cmd_data *tx;
3343 const struct iwn_rate *rinfo;
3344 struct ieee80211_frame *wh;
3345 struct ieee80211_key *k = NULL((void *)0);
3346 enum ieee80211_edca_ac ac;
3347 int qid;
3348 uint32_t flags;
3349 uint16_t qos;
3350 u_int hdrlen;
3351 bus_dma_segment_t *seg;
3352 uint8_t *ivp, tid, ridx, txant, type, subtype;
3353 int i, totlen, hasqos, error, pad;
3354
3355 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
3356 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c;
3357 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK0xf0;
3358 if (type == IEEE80211_FC0_TYPE_CTL0x04)
3359 hdrlen = sizeof(struct ieee80211_frame_min);
3360 else
3361 hdrlen = ieee80211_get_hdrlen(wh);
3362
3363 if ((hasqos = ieee80211_has_qos(wh))) {
3364 /* Select EDCA Access Category and TX ring for this frame. */
3365 struct ieee80211_tx_ba *ba;
3366 qos = ieee80211_get_qos(wh);
3367 tid = qos & IEEE80211_QOS_TID0x000f;
3368 ac = ieee80211_up_to_ac(ic, tid);
3369 qid = ac;
3370
3371 /* If possible, put this frame on an aggregation queue. */
3372 if (sc->sc_tx_ba[tid].wn == wn) {
3373 ba = &ni->ni_tx_ba[tid];
3374 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
3375 ba->ba_state == IEEE80211_BA_AGREED2) {
3376 qid = sc->first_agg_txq + tid;
3377 if (sc->qfullmsk & (1 << qid)) {
3378 m_freem(m);
3379 return ENOBUFS55;
3380 }
3381 }
3382 }
3383 } else {
3384 qos = 0;
3385 tid = IWN_NONQOS_TID8;
3386 ac = EDCA_AC_BE;
3387 qid = ac;
3388 }
3389
3390 ring = &sc->txq[qid];
3391 desc = &ring->desc[ring->cur];
3392 data = &ring->data[ring->cur];
3393
3394 /* Choose a TX rate index. */
3395 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
3396 type != IEEE80211_FC0_TYPE_DATA0x08)
3397 ridx = iwn_rval2ridx(ieee80211_min_basic_rate(ic));
3398 else if (ic->ic_fixed_mcs != -1)
3399 ridx = sc->fixed_ridx;
3400 else if (ic->ic_fixed_rate != -1)
3401 ridx = sc->fixed_ridx;
3402 else {
3403 if (ni->ni_flags & IEEE80211_NODE_HT0x0400)
3404 ridx = iwn_mcs2ridx[ni->ni_txmcs];
3405 else
3406 ridx = wn->ridx[ni->ni_txrate];
3407 }
3408 rinfo = &iwn_rates[ridx];
3409#if NBPFILTER1 > 0
3410 if (sc->sc_drvbpf != NULL((void *)0)) {
3411 struct iwn_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
3412 uint16_t chan_flags;
3413
3414 tap->wt_flags = 0;
3415 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq)((__uint16_t)(ni->ni_chan->ic_freq));
3416 chan_flags = ni->ni_chan->ic_flags;
3417 if (ic->ic_curmode != IEEE80211_MODE_11N)
3418 chan_flags &= ~IEEE80211_CHAN_HT0x2000;
3419 tap->wt_chan_flags = htole16(chan_flags)((__uint16_t)(chan_flags));
3420 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3421 !IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
3422 type == IEEE80211_FC0_TYPE_DATA0x08) {
3423 tap->wt_rate = (0x80 | ni->ni_txmcs);
3424 } else
3425 tap->wt_rate = rinfo->rate;
3426 if ((ic->ic_flags & IEEE80211_F_WEPON0x00000100) &&
3427 (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40))
3428 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP0x04;
3429
3430 bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_txtap_len,
3431 m, BPF_DIRECTION_OUT(1 << 1));
3432 }
3433#endif
3434
3435 totlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
3436
3437 /* Encrypt the frame if need be. */
3438 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
3439 /* Retrieve key for TX. */
3440 k = ieee80211_get_txkey(ic, wh, ni);
3441 if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
3442 /* Do software encryption. */
3443 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
3444 return ENOBUFS55;
3445 /* 802.11 header may have moved. */
3446 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
3447 totlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
3448
3449 } else /* HW appends CCMP MIC. */
3450 totlen += IEEE80211_CCMP_HDRLEN8;
3451 }
3452
3453 data->totlen = totlen;
3454
3455 /* Prepare TX firmware command. */
3456 cmd = &ring->cmd[ring->cur];
3457 cmd->code = IWN_CMD_TX_DATA28;
3458 cmd->flags = 0;
3459 cmd->qid = ring->qid;
3460 cmd->idx = ring->cur;
3461
3462 tx = (struct iwn_cmd_data *)cmd->data;
3463 /* NB: No need to clear tx, all fields are reinitialized here. */
3464 tx->scratch = 0; /* clear "scratch" area */
3465
3466 flags = 0;
3467 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
3468 /* Unicast frame, check if an ACK is expected. */
3469 if (!hasqos || (qos & IEEE80211_QOS_ACK_POLICY_MASK0x0060) !=
3470 IEEE80211_QOS_ACK_POLICY_NOACK0x0020)
3471 flags |= IWN_TX_NEED_ACK(1 << 3);
3472 }
3473 if (type == IEEE80211_FC0_TYPE_CTL0x04 &&
3474 subtype == IEEE80211_FC0_SUBTYPE_BAR0x80) {
3475 struct ieee80211_frame_min *mwh;
3476 uint8_t *barfrm;
3477 uint16_t ctl;
3478 mwh = mtod(m, struct ieee80211_frame_min *)((struct ieee80211_frame_min *)((m)->m_hdr.mh_data));
3479 barfrm = (uint8_t *)&mwh[1];
3480 ctl = LE_READ_2(barfrm)((u_int16_t) ((((const u_int8_t *)(barfrm))[0]) | (((const u_int8_t
*)(barfrm))[1] << 8)))
;
3481 tid = (ctl & IEEE80211_BA_TID_INFO_MASK0xf000) >>
3482 IEEE80211_BA_TID_INFO_SHIFT12;
3483 flags |= (IWN_TX_NEED_ACK(1 << 3) | IWN_TX_IMM_BA(1 << 6));
3484 }
3485
3486 if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG0x04)
3487 flags |= IWN_TX_MORE_FRAG(1 << 14); /* Cannot happen yet. */
3488
3489 /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
3490 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
3491 /* NB: Group frames are sent using CCK in 802.11b/g/n (2GHz). */
3492 if (totlen + IEEE80211_CRC_LEN4 > ic->ic_rtsthreshold) {
3493 flags |= IWN_TX_NEED_RTS(1 << 1);
3494 } else if ((ic->ic_flags & IEEE80211_F_USEPROT0x00100000) &&
3495 ridx >= IWN_RIDX_OFDM64) {
3496 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
3497 flags |= IWN_TX_NEED_CTS(1 << 2);
3498 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
3499 flags |= IWN_TX_NEED_RTS(1 << 1);
3500 }
3501
3502 if (flags & (IWN_TX_NEED_RTS(1 << 1) | IWN_TX_NEED_CTS(1 << 2))) {
3503 if (sc->hw_type != IWN_HW_REV_TYPE_49650) {
3504 /* 5000 autoselects RTS/CTS or CTS-to-self. */
3505 flags &= ~(IWN_TX_NEED_RTS(1 << 1) | IWN_TX_NEED_CTS(1 << 2));
3506 flags |= IWN_TX_NEED_PROTECTION(1 << 0);
3507 } else
3508 flags |= IWN_TX_FULL_TXOP(1 << 7);
3509 }
3510 }
3511
3512 if (type == IEEE80211_FC0_TYPE_CTL0x04 &&
3513 subtype == IEEE80211_FC0_SUBTYPE_BAR0x80)
3514 tx->id = wn->id;
3515 else if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
3516 type != IEEE80211_FC0_TYPE_DATA0x08)
3517 tx->id = sc->broadcast_id;
3518 else
3519 tx->id = wn->id;
3520
3521 if (type == IEEE80211_FC0_TYPE_MGT0x00) {
3522#ifndef IEEE80211_STA_ONLY
3523 /* Tell HW to set timestamp in probe responses. */
3524 if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP0x50)
3525 flags |= IWN_TX_INSERT_TSTAMP(1 << 16);
3526#endif
3527 if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ0x00 ||
3528 subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ0x20)
3529 tx->timeout = htole16(3)((__uint16_t)(3));
3530 else
3531 tx->timeout = htole16(2)((__uint16_t)(2));
3532 } else
3533 tx->timeout = htole16(0)((__uint16_t)(0));
3534
3535 if (hdrlen & 3) {
3536 /* First segment length must be a multiple of 4. */
3537 flags |= IWN_TX_NEED_PADDING(1 << 20);
3538 pad = 4 - (hdrlen & 3);
3539 } else
3540 pad = 0;
3541
3542 tx->len = htole16(totlen)((__uint16_t)(totlen));
3543 tx->tid = tid;
3544 tx->rts_ntries = 60;
3545 tx->data_ntries = 15;
3546 tx->lifetime = htole32(IWN_LIFETIME_INFINITE)((__uint32_t)(0xffffffff));
3547
3548 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3549 tx->id != sc->broadcast_id)
3550 tx->plcp = rinfo->ht_plcp;
3551 else
3552 tx->plcp = rinfo->plcp;
3553
3554 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3555 tx->id != sc->broadcast_id) {
3556 tx->rflags = rinfo->ht_flags;
3557 if (iwn_rxon_ht40_enabled(sc))
3558 tx->rflags |= IWN_RFLAG_HT40(1 << 3);
3559 if (ieee80211_ra_use_ht_sgi(ni))
3560 tx->rflags |= IWN_RFLAG_SGI(1 << 5);
3561 }
3562 else
3563 tx->rflags = rinfo->flags;
3564 if (tx->id == sc->broadcast_id || ic->ic_fixed_mcs != -1 ||
3565 ic->ic_fixed_rate != -1) {
3566 /* Group or management frame, or fixed Tx rate. */
3567 tx->linkq = 0;
3568 /* XXX Alternate between antenna A and B? */
3569 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
3570 tx->rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3571 } else {
3572 tx->linkq = 0; /* initial index into firmware LQ retry table */
3573 flags |= IWN_TX_LINKQ(1 << 4); /* enable multi-rate retry */
3574 }
3575 /* Set physical address of "scratch area". */
3576 tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr))((__uint32_t)(((uint32_t)(data->scratch_paddr))));
3577 tx->hiaddr = IWN_HIADDR(data->scratch_paddr)(((data->scratch_paddr) >> 32) & 0xf);
3578
3579 /* Copy 802.11 header in TX command. */
3580 memcpy((uint8_t *)(tx + 1), wh, hdrlen)__builtin_memcpy(((uint8_t *)(tx + 1)), (wh), (hdrlen));
3581
3582 if (k != NULL((void *)0) && k->k_cipher == IEEE80211_CIPHER_CCMP) {
3583 /* Trim 802.11 header and prepend CCMP IV. */
3584 m_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN8);
3585 ivp = mtod(m, uint8_t *)((uint8_t *)((m)->m_hdr.mh_data));
3586 k->k_tsc++;
3587 ivp[0] = k->k_tsc;
3588 ivp[1] = k->k_tsc >> 8;
3589 ivp[2] = 0;
3590 ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV0x20;
3591 ivp[4] = k->k_tsc >> 16;
3592 ivp[5] = k->k_tsc >> 24;
3593 ivp[6] = k->k_tsc >> 32;
3594 ivp[7] = k->k_tsc >> 40;
3595
3596 tx->security = IWN_CIPHER_CCMP2;
3597 if (qid >= sc->first_agg_txq)
3598 flags |= IWN_TX_AMPDU_CCMP(1 << 22);
3599 memcpy(tx->key, k->k_key, k->k_len)__builtin_memcpy((tx->key), (k->k_key), (k->k_len));
3600
3601 /* TX scheduler includes CCMP MIC len w/5000 Series. */
3602 if (sc->hw_type != IWN_HW_REV_TYPE_49650)
3603 totlen += IEEE80211_CCMP_MICLEN8;
3604 } else {
3605 /* Trim 802.11 header. */
3606 m_adj(m, hdrlen);
3607 tx->security = 0;
3608 }
3609 tx->flags = htole32(flags)((__uint32_t)(flags));
3610
3611 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
3612 BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
;
3613 if (error != 0 && error != EFBIG27) {
3614 printf("%s: can't map mbuf (error %d)\n",
3615 sc->sc_dev.dv_xname, error);
3616 m_freem(m);
3617 return error;
3618 }
3619 if (error != 0) {
3620 /* Too many DMA segments, linearize mbuf. */
3621 if (m_defrag(m, M_DONTWAIT0x0002)) {
3622 m_freem(m);
3623 return ENOBUFS55;
3624 }
3625 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
3626 BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
;
3627 if (error != 0) {
3628 printf("%s: can't map mbuf (error %d)\n",
3629 sc->sc_dev.dv_xname, error);
3630 m_freem(m);
3631 return error;
3632 }
3633 }
3634
3635 data->m = m;
3636 data->ni = ni;
3637 data->ampdu_txmcs = ni->ni_txmcs; /* updated upon Tx interrupt */
3638
3639 DPRINTFN(4, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
3640 ring->qid, ring->cur, m->m_pkthdr.len, data->map->dm_nsegs));
3641
3642 /* Fill TX descriptor. */
3643 desc->nsegs = 1 + data->map->dm_nsegs;
3644 /* First DMA segment is used by the TX command. */
3645 desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr))((__uint32_t)(((uint32_t)(data->cmd_paddr))));
3646 desc->segs[0].len = htole16(IWN_HIADDR(data->cmd_paddr) |((__uint16_t)((((data->cmd_paddr) >> 32) & 0xf) |
(4 + sizeof (*tx) + hdrlen + pad) << 4))
3647 (4 + sizeof (*tx) + hdrlen + pad) << 4)((__uint16_t)((((data->cmd_paddr) >> 32) & 0xf) |
(4 + sizeof (*tx) + hdrlen + pad) << 4))
;
3648 /* Other DMA segments are for data payload. */
3649 seg = data->map->dm_segs;
3650 for (i = 1; i <= data->map->dm_nsegs; i++) {
3651 desc->segs[i].addr = htole32(IWN_LOADDR(seg->ds_addr))((__uint32_t)(((uint32_t)(seg->ds_addr))));
3652 desc->segs[i].len = htole16(IWN_HIADDR(seg->ds_addr) |((__uint16_t)((((seg->ds_addr) >> 32) & 0xf) | seg
->ds_len << 4))
3653 seg->ds_len << 4)((__uint16_t)((((seg->ds_addr) >> 32) & 0xf) | seg
->ds_len << 4))
;
3654 seg++;
3655 }
3656
3657 bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x04))
3658 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x04))
;
3659 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (sizeof
(*cmd)), (0x04))
3660 (caddr_t)cmd - ring->cmd_dma.vaddr, sizeof (*cmd),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (sizeof
(*cmd)), (0x04))
3661 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (sizeof
(*cmd)), (0x04))
;
3662 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
3663 (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
3664 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
;
3665
3666 /* Update TX scheduler. */
3667 ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen);
3668
3669 /* Kick TX ring. */
3670 ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT256;
3671 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
ring->qid << 8 | ring->cur))))
;
3672
3673 /* Mark TX ring as full if we reach a certain threshold. */
3674 if (++ring->queued > IWN_TX_RING_HIMARK224)
3675 sc->qfullmsk |= 1 << ring->qid;
3676
3677 return 0;
3678}
3679
3680void
3681iwn_start(struct ifnet *ifp)
3682{
3683 struct iwn_softc *sc = ifp->if_softc;
3684 struct ieee80211com *ic = &sc->sc_ic;
3685 struct ieee80211_node *ni;
3686 struct mbuf *m;
3687
3688 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
3689 return;
3690
3691 for (;;) {
3692 if (sc->qfullmsk != 0) {
3693 ifq_set_oactive(&ifp->if_snd);
3694 break;
3695 }
3696
3697 /* Send pending management frames first. */
3698 m = mq_dequeue(&ic->ic_mgtq);
3699 if (m != NULL((void *)0)) {
3700 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
3701 goto sendit;
3702 }
3703 if (ic->ic_state != IEEE80211_S_RUN ||
3704 (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY0x00000001))
3705 break;
3706
3707 /* Encapsulate and send data frames. */
3708 m = ifq_dequeue(&ifp->if_snd);
3709 if (m == NULL((void *)0))
3710 break;
3711#if NBPFILTER1 > 0
3712 if (ifp->if_bpf != NULL((void *)0))
3713 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
3714#endif
3715 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
3716 continue;
3717sendit:
3718#if NBPFILTER1 > 0
3719 if (ic->ic_rawbpf != NULL((void *)0))
3720 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
3721#endif
3722 if (iwn_tx(sc, m, ni) != 0) {
3723 ieee80211_release_node(ic, ni);
3724 ifp->if_oerrorsif_data.ifi_oerrors++;
3725 continue;
3726 }
3727
3728 sc->sc_tx_timer = 5;
3729 ifp->if_timer = 1;
3730 }
3731}
3732
3733void
3734iwn_watchdog(struct ifnet *ifp)
3735{
3736 struct iwn_softc *sc = ifp->if_softc;
3737
3738 ifp->if_timer = 0;
3739
3740 if (sc->sc_tx_timer > 0) {
3741 if (--sc->sc_tx_timer == 0) {
3742 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
3743 iwn_stop(ifp);
3744 ifp->if_oerrorsif_data.ifi_oerrors++;
3745 return;
3746 }
3747 ifp->if_timer = 1;
3748 }
3749
3750 ieee80211_watchdog(ifp);
3751}
3752
3753int
3754iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3755{
3756 struct iwn_softc *sc = ifp->if_softc;
3757 struct ieee80211com *ic = &sc->sc_ic;
3758 int s, error = 0;
3759
3760 error = rw_enter(&sc->sc_rwlock, RW_WRITE0x0001UL | RW_INTR0x0010UL);
3761 if (error)
3762 return error;
3763 s = splnet()splraise(0x7);
3764
3765 switch (cmd) {
3766 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
3767 ifp->if_flags |= IFF_UP0x1;
3768 /* FALLTHROUGH */
3769 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
3770 if (ifp->if_flags & IFF_UP0x1) {
3771 if (!(ifp->if_flags & IFF_RUNNING0x40))
3772 error = iwn_init(ifp);
3773 } else {
3774 if (ifp->if_flags & IFF_RUNNING0x40)
3775 iwn_stop(ifp);
3776 }
3777 break;
3778
3779 case SIOCS80211POWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_power)
& 0x1fff) << 16) | ((('i')) << 8) | ((234)))
:
3780 error = ieee80211_ioctl(ifp, cmd, data);
3781 if (error != ENETRESET52)
3782 break;
3783 if (ic->ic_state == IEEE80211_S_RUN &&
3784 sc->calib.state == IWN_CALIB_STATE_RUN2) {
3785 if (ic->ic_flags & IEEE80211_F_PMGTON0x00000400)
3786 error = iwn_set_pslevel(sc, 0, 3, 0);
3787 else /* back to CAM */
3788 error = iwn_set_pslevel(sc, 0, 0, 0);
3789 } else {
3790 /* Defer until transition to IWN_CALIB_STATE_RUN. */
3791 error = 0;
3792 }
3793 break;
3794
3795 default:
3796 error = ieee80211_ioctl(ifp, cmd, data);
3797 }
3798
3799 if (error == ENETRESET52) {
3800 error = 0;
3801 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
3802 (IFF_UP0x1 | IFF_RUNNING0x40)) {
3803 iwn_stop(ifp);
3804 error = iwn_init(ifp);
3805 }
3806 }
3807
3808 splx(s)spllower(s);
3809 rw_exit_write(&sc->sc_rwlock);
3810 return error;
3811}
3812
3813/*
3814 * Send a command to the firmware.
3815 */
3816int
3817iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
3818{
3819 struct iwn_ops *ops = &sc->ops;
3820 struct iwn_tx_ring *ring = &sc->txq[4];
3821 struct iwn_tx_desc *desc;
3822 struct iwn_tx_data *data;
3823 struct iwn_tx_cmd *cmd;
3824 struct mbuf *m;
3825 bus_addr_t paddr;
3826 int totlen, error;
3827
3828 desc = &ring->desc[ring->cur];
3829 data = &ring->data[ring->cur];
3830 totlen = 4 + size;
3831
3832 if (size > sizeof cmd->data) {
3833 /* Command is too large to fit in a descriptor. */
3834 if (totlen > MCLBYTES(1 << 11))
3835 return EINVAL22;
3836 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
3837 if (m == NULL((void *)0))
3838 return ENOMEM12;
3839 if (totlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
3840 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
3841 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
3842 m_freem(m);
3843 return ENOMEM12;
3844 }
3845 }
3846 cmd = mtod(m, struct iwn_tx_cmd *)((struct iwn_tx_cmd *)((m)->m_hdr.mh_data));
3847 error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, totlen,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (cmd), (totlen), (((void *)0)), (0x0001 | 0x0400))
3848 NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (cmd), (totlen), (((void *)0)), (0x0001 | 0x0400))
;
3849 if (error != 0) {
3850 m_freem(m);
3851 return error;
3852 }
3853 data->m = m;
3854 paddr = data->map->dm_segs[0].ds_addr;
3855 } else {
3856 cmd = &ring->cmd[ring->cur];
3857 paddr = data->cmd_paddr;
3858 }
3859
3860 cmd->code = code;
3861 cmd->flags = 0;
3862 cmd->qid = ring->qid;
3863 cmd->idx = ring->cur;
3864 memcpy(cmd->data, buf, size)__builtin_memcpy((cmd->data), (buf), (size));
3865
3866 desc->nsegs = 1;
3867 desc->segs[0].addr = htole32(IWN_LOADDR(paddr))((__uint32_t)(((uint32_t)(paddr))));
3868 desc->segs[0].len = htole16(IWN_HIADDR(paddr) | totlen << 4)((__uint16_t)((((paddr) >> 32) & 0xf) | totlen <<
4))
;
3869
3870 if (size > sizeof cmd->data) {
3871 bus_dmamap_sync(sc->sc_dmat, data->map, 0, totlen,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (totlen), (0x04))
3872 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (totlen), (0x04))
;
3873 } else {
3874 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (totlen
), (0x04))
3875 (caddr_t)cmd - ring->cmd_dma.vaddr, totlen,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (totlen
), (0x04))
3876 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (totlen
), (0x04))
;
3877 }
3878 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
3879 (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
3880 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), ((caddr_t)desc - ring->desc_dma.vaddr), (sizeof
(*desc)), (0x04))
;
3881
3882 /* Update TX scheduler. */
3883 ops->update_sched(sc, ring->qid, ring->cur, 0, 0);
3884
3885 /* Kick command ring. */
3886 ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT256;
3887 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
ring->qid << 8 | ring->cur))))
;
3888
3889 return async ? 0 : tsleep_nsec(desc, PCATCH0x100, "iwncmd", SEC_TO_NSEC(1));
3890}
3891
3892int
3893iwn4965_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)
3894{
3895 struct iwn4965_node_info hnode;
3896 caddr_t src, dst;
3897
3898 /*
3899 * We use the node structure for 5000 Series internally (it is
3900 * a superset of the one for 4965AGN). We thus copy the common
3901 * fields before sending the command.
3902 */
3903 src = (caddr_t)node;
3904 dst = (caddr_t)&hnode;
3905 memcpy(dst, src, 48)__builtin_memcpy((dst), (src), (48));
3906 /* Skip TSC, RX MIC and TX MIC fields from ``src''. */
3907 memcpy(dst + 48, src + 72, 20)__builtin_memcpy((dst + 48), (src + 72), (20));
3908 return iwn_cmd(sc, IWN_CMD_ADD_NODE24, &hnode, sizeof hnode, async);
3909}
3910
3911int
3912iwn5000_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)
3913{
3914 /* Direct mapping. */
3915 return iwn_cmd(sc, IWN_CMD_ADD_NODE24, node, sizeof (*node), async);
3916}
3917
3918int
3919iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
3920{
3921 struct ieee80211com *ic = &sc->sc_ic;
3922 struct iwn_node *wn = (void *)ni;
3923 struct iwn_cmd_link_quality linkq;
3924 const struct iwn_rate *rinfo;
3925 uint8_t txant;
3926 int i;
3927
3928 /* Use the first valid TX antenna. */
3929 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
3930
3931 memset(&linkq, 0, sizeof linkq)__builtin_memset((&linkq), (0), (sizeof linkq));
3932 linkq.id = wn->id;
3933 linkq.antmsk_1stream = txant;
3934 linkq.antmsk_2stream = IWN_ANT_AB((1 << 0) | (1 << 1));
3935 linkq.ampdu_max = IWN_AMPDU_MAX63;
3936 linkq.ampdu_threshold = 3;
3937 linkq.ampdu_limit = htole16(4000)((__uint16_t)(4000)); /* 4ms */
3938
3939 i = 0;
3940 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
3941 int txmcs;
3942 for (txmcs = ni->ni_txmcs; txmcs >= 0; txmcs--) {
3943 rinfo = &iwn_rates[iwn_mcs2ridx[txmcs]];
3944 linkq.retry[i].plcp = rinfo->ht_plcp;
3945 linkq.retry[i].rflags = rinfo->ht_flags;
3946
3947 /* XXX set correct ant mask for MIMO rates here */
3948 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3949
3950 /* First two Tx attempts may use 40MHz/SGI. */
3951 if (i < 2) {
3952 if (iwn_rxon_ht40_enabled(sc))
3953 linkq.retry[i].rflags |= IWN_RFLAG_HT40(1 << 3);
3954 if (ieee80211_ra_use_ht_sgi(ni))
3955 linkq.retry[i].rflags |= IWN_RFLAG_SGI(1 << 5);
3956 }
3957
3958 if (++i >= IWN_MAX_TX_RETRIES16)
3959 break;
3960 }
3961 } else {
3962 int txrate;
3963 for (txrate = ni->ni_txrate; txrate >= 0; txrate--) {
3964 rinfo = &iwn_rates[wn->ridx[txrate]];
3965 linkq.retry[i].plcp = rinfo->plcp;
3966 linkq.retry[i].rflags = rinfo->flags;
3967 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3968 if (++i >= IWN_MAX_TX_RETRIES16)
3969 break;
3970 }
3971 }
3972
3973 /* Fill the rest with the lowest basic rate. */
3974 rinfo = &iwn_rates[iwn_rval2ridx(ieee80211_min_basic_rate(ic))];
3975 while (i < IWN_MAX_TX_RETRIES16) {
3976 linkq.retry[i].plcp = rinfo->plcp;
3977 linkq.retry[i].rflags = rinfo->flags;
3978 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3979 i++;
3980 }
3981
3982 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY78, &linkq, sizeof linkq, 1);
3983}
3984
3985/*
3986 * Broadcast node is used to send group-addressed and management frames.
3987 */
3988int
3989iwn_add_broadcast_node(struct iwn_softc *sc, int async, int ridx)
3990{
3991 struct iwn_ops *ops = &sc->ops;
3992 struct iwn_node_info node;
3993 struct iwn_cmd_link_quality linkq;
3994 const struct iwn_rate *rinfo;
3995 uint8_t txant;
3996 int i, error;
3997
3998 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
3999 IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr)__builtin_memcpy((node.macaddr), (etherbroadcastaddr), (6));
4000 node.id = sc->broadcast_id;
4001 DPRINTF(("adding broadcast node\n"));
4002 if ((error = ops->add_node(sc, &node, async)) != 0)
4003 return error;
4004
4005 /* Use the first valid TX antenna. */
4006 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
4007
4008 memset(&linkq, 0, sizeof linkq)__builtin_memset((&linkq), (0), (sizeof linkq));
4009 linkq.id = sc->broadcast_id;
4010 linkq.antmsk_1stream = txant;
4011 linkq.antmsk_2stream = IWN_ANT_AB((1 << 0) | (1 << 1));
4012 linkq.ampdu_max = IWN_AMPDU_MAX_NO_AGG1;
4013 linkq.ampdu_threshold = 3;
4014 linkq.ampdu_limit = htole16(4000)((__uint16_t)(4000)); /* 4ms */
4015
4016 /* Use lowest mandatory bit-rate. */
4017 rinfo = &iwn_rates[ridx];
4018 linkq.retry[0].plcp = rinfo->plcp;
4019 linkq.retry[0].rflags = rinfo->flags;
4020 linkq.retry[0].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
4021 /* Use same bit-rate for all TX retries. */
4022 for (i = 1; i < IWN_MAX_TX_RETRIES16; i++) {
4023 linkq.retry[i].plcp = linkq.retry[0].plcp;
4024 linkq.retry[i].rflags = linkq.retry[0].rflags;
4025 }
4026 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY78, &linkq, sizeof linkq, async);
4027}
4028
4029void
4030iwn_updateedca(struct ieee80211com *ic)
4031{
4032#define IWN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
4033 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
4034 struct iwn_edca_params cmd;
4035 int aci;
4036
4037 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4038 cmd.flags = htole32(IWN_EDCA_UPDATE)((__uint32_t)((1 << 0)));
4039 for (aci = 0; aci < EDCA_NUM_AC4; aci++) {
4040 const struct ieee80211_edca_ac_params *ac =
4041 &ic->ic_edca_ac[aci];
4042 cmd.ac[aci].aifsn = ac->ac_aifsn;
4043 cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->ac_ecwmin))((__uint16_t)(IWN_EXP2(ac->ac_ecwmin)));
4044 cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->ac_ecwmax))((__uint16_t)(IWN_EXP2(ac->ac_ecwmax)));
4045 cmd.ac[aci].txoplimit =
4046 htole16(IEEE80211_TXOP_TO_US(ac->ac_txoplimit))((__uint16_t)(((ac->ac_txoplimit) * 32)));
4047 }
4048 (void)iwn_cmd(sc, IWN_CMD_EDCA_PARAMS19, &cmd, sizeof cmd, 1);
4049#undef IWN_EXP2
4050}
4051
4052void
4053iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)
4054{
4055 struct iwn_cmd_led led;
4056
4057 /* Clear microcode LED ownership. */
4058 IWN_CLRBITS(sc, IWN_LED, IWN_LED_BSM_CTRL)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x094)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x094)))) &
~((1 << 5))))))
;
4059
4060 led.which = which;
4061 led.unit = htole32(10000)((__uint32_t)(10000)); /* on/off in unit of 100ms */
4062 led.off = off;
4063 led.on = on;
4064 (void)iwn_cmd(sc, IWN_CMD_SET_LED72, &led, sizeof led, 1);
4065}
4066
4067/*
4068 * Set the critical temperature at which the firmware will stop the radio
4069 * and notify us.
4070 */
4071int
4072iwn_set_critical_temp(struct iwn_softc *sc)
4073{
4074 struct iwn_critical_temp crit;
4075 int32_t temp;
4076
4077 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CTEMP_STOP_RF)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 3)))))
;
4078
4079 if (sc->hw_type == IWN_HW_REV_TYPE_51504)
4080 temp = (IWN_CTOK(110)((110) + 273) - sc->temp_off) * -5;
4081 else if (sc->hw_type == IWN_HW_REV_TYPE_49650)
4082 temp = IWN_CTOK(110)((110) + 273);
4083 else
4084 temp = 110;
4085 memset(&crit, 0, sizeof crit)__builtin_memset((&crit), (0), (sizeof crit));
4086 crit.tempR = htole32(temp)((__uint32_t)(temp));
4087 DPRINTF(("setting critical temperature to %d\n", temp));
4088 return iwn_cmd(sc, IWN_CMD_SET_CRITICAL_TEMP164, &crit, sizeof crit, 0);
4089}
4090
4091int
4092iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
4093{
4094 struct iwn_cmd_timing cmd;
4095 uint64_t val, mod;
4096
4097 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4098 memcpy(&cmd.tstamp, ni->ni_tstamp, sizeof (uint64_t))__builtin_memcpy((&cmd.tstamp), (ni->ni_tstamp), (sizeof
(uint64_t)))
;
4099 cmd.bintval = htole16(ni->ni_intval)((__uint16_t)(ni->ni_intval));
4100 cmd.lintval = htole16(10)((__uint16_t)(10));
4101
4102 /* Compute remaining time until next beacon. */
4103 val = (uint64_t)ni->ni_intval * IEEE80211_DUR_TU1024;
4104 mod = letoh64(cmd.tstamp)((__uint64_t)(cmd.tstamp)) % val;
4105 cmd.binitval = htole32((uint32_t)(val - mod))((__uint32_t)((uint32_t)(val - mod)));
4106
4107 DPRINTF(("timing bintval=%u, tstamp=%llu, init=%u\n",
4108 ni->ni_intval, letoh64(cmd.tstamp), (uint32_t)(val - mod)));
4109
4110 return iwn_cmd(sc, IWN_CMD_TIMING20, &cmd, sizeof cmd, 1);
4111}
4112
4113void
4114iwn4965_power_calibration(struct iwn_softc *sc, int temp)
4115{
4116 /* Adjust TX power if need be (delta >= 3 degC). */
4117 DPRINTF(("temperature %d->%d\n", sc->temp, temp));
4118 if (abs(temp - sc->temp) >= 3) {
4119 /* Record temperature of last calibration. */
4120 sc->temp = temp;
4121 (void)iwn4965_set_txpower(sc, 1);
4122 }
4123}
4124
4125/*
4126 * Set TX power for current channel (each rate has its own power settings).
4127 * This function takes into account the regulatory information from EEPROM,
4128 * the current temperature and the current voltage.
4129 */
4130int
4131iwn4965_set_txpower(struct iwn_softc *sc, int async)
4132{
4133/* Fixed-point arithmetic division using a n-bit fractional part. */
4134#define fdivround(a, b, n) \
4135 ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
4136/* Linear interpolation. */
4137#define interpolate(x, x1, y1, x2, y2, n) \
4138 ((y1) + fdivround(((int)(x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
4139
4140 static const int tdiv[IWN_NATTEN_GROUPS5] = { 9, 8, 8, 8, 6 };
4141 struct ieee80211com *ic = &sc->sc_ic;
4142 struct iwn_ucode_info *uc = &sc->ucode_info;
4143 struct ieee80211_channel *ch;
4144 struct iwn4965_cmd_txpower cmd;
4145 struct iwn4965_eeprom_chan_samples *chans;
4146 const uint8_t *rf_gain, *dsp_gain;
4147 int32_t vdiff, tdiff;
4148 int i, c, grp, maxpwr, is_ht40 = 0;
4149 uint8_t chan, ext_chan;
4150
4151 /* Retrieve current channel from last RXON. */
4152 chan = sc->rxon.chan;
4153 DPRINTF(("setting TX power for channel %d\n", chan));
4154 ch = &ic->ic_channels[chan];
4155
4156 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4157 cmd.band = IEEE80211_IS_CHAN_5GHZ(ch)(((ch)->ic_flags & 0x0100) != 0) ? 0 : 1;
4158 cmd.chan = chan;
4159
4160 if (IEEE80211_IS_CHAN_5GHZ(ch)(((ch)->ic_flags & 0x0100) != 0)) {
4161 maxpwr = sc->maxpwr5GHz;
4162 rf_gain = iwn4965_rf_gain_5ghz;
4163 dsp_gain = iwn4965_dsp_gain_5ghz;
4164 } else {
4165 maxpwr = sc->maxpwr2GHz;
4166 rf_gain = iwn4965_rf_gain_2ghz;
4167 dsp_gain = iwn4965_dsp_gain_2ghz;
4168 }
4169
4170 /* Compute voltage compensation. */
4171 vdiff = ((int32_t)letoh32(uc->volt)((__uint32_t)(uc->volt)) - sc->eeprom_voltage) / 7;
4172 if (vdiff > 0)
4173 vdiff *= 2;
4174 if (abs(vdiff) > 2)
4175 vdiff = 0;
4176 DPRINTF(("voltage compensation=%d (UCODE=%d, EEPROM=%d)\n",
4177 vdiff, letoh32(uc->volt), sc->eeprom_voltage));
4178
4179 /* Get channel attenuation group. */
4180 if (chan <= 20) /* 1-20 */
4181 grp = 4;
4182 else if (chan <= 43) /* 34-43 */
4183 grp = 0;
4184 else if (chan <= 70) /* 44-70 */
4185 grp = 1;
4186 else if (chan <= 124) /* 71-124 */
4187 grp = 2;
4188 else /* 125-200 */
4189 grp = 3;
4190 DPRINTF(("chan %d, attenuation group=%d\n", chan, grp));
4191
4192 /* Get channel sub-band. */
4193 for (i = 0; i < IWN_NBANDS8; i++)
4194 if (sc->bands[i].lo != 0 &&
4195 sc->bands[i].lo <= chan && chan <= sc->bands[i].hi)
4196 break;
4197 if (i == IWN_NBANDS8) /* Can't happen in real-life. */
4198 return EINVAL22;
4199 chans = sc->bands[i].chans;
4200 DPRINTF(("chan %d sub-band=%d\n", chan, i));
4201
4202 if (iwn_rxon_ht40_enabled(sc)) {
4203 is_ht40 = 1;
4204 if (le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_HT40MINUS(1 << 22))
4205 ext_chan = chan - 2;
4206 else
4207 ext_chan = chan + 2;
4208 } else
4209 ext_chan = chan;
4210
4211 for (c = 0; c < 2; c++) {
4212 uint8_t power, gain, temp;
4213 int maxchpwr, pwr, ridx, idx;
4214
4215 power = interpolate(ext_chan,
4216 chans[0].num, chans[0].samples[c][1].power,
4217 chans[1].num, chans[1].samples[c][1].power, 1);
4218 gain = interpolate(ext_chan,
4219 chans[0].num, chans[0].samples[c][1].gain,
4220 chans[1].num, chans[1].samples[c][1].gain, 1);
4221 temp = interpolate(ext_chan,
4222 chans[0].num, chans[0].samples[c][1].temp,
4223 chans[1].num, chans[1].samples[c][1].temp, 1);
4224 DPRINTF(("TX chain %d: power=%d gain=%d temp=%d\n",
4225 c, power, gain, temp));
4226
4227 /* Compute temperature compensation. */
4228 tdiff = ((sc->temp - temp) * 2) / tdiv[grp];
4229 DPRINTF(("temperature compensation=%d (current=%d, "
4230 "EEPROM=%d)\n", tdiff, sc->temp, temp));
4231
4232 for (ridx = 0; ridx <= IWN_RIDX_MAX32; ridx++) {
4233 /* Convert dBm to half-dBm. */
4234 if (is_ht40)
4235 maxchpwr = sc->maxpwr40[chan] * 2;
4236 else
4237 maxchpwr = sc->maxpwr[chan] * 2;
4238#ifdef notyet
4239 if (ridx > iwn_mcs2ridx[7] && ridx < iwn_mcs2ridx[16])
4240 maxchpwr -= 6; /* MIMO 2T: -3dB */
4241#endif
4242
4243 pwr = maxpwr;
4244
4245 /* Adjust TX power based on rate. */
4246 if ((ridx % 8) == 5)
4247 pwr -= 15; /* OFDM48: -7.5dB */
4248 else if ((ridx % 8) == 6)
4249 pwr -= 17; /* OFDM54: -8.5dB */
4250 else if ((ridx % 8) == 7)
4251 pwr -= 20; /* OFDM60: -10dB */
4252 else
4253 pwr -= 10; /* Others: -5dB */
4254
4255 /* Do not exceed channel max TX power. */
4256 if (pwr > maxchpwr)
4257 pwr = maxchpwr;
4258
4259 idx = gain - (pwr - power) - tdiff - vdiff;
4260 if (ridx > iwn_mcs2ridx[7]) /* MIMO */
4261 idx += (int32_t)letoh32(uc->atten[grp][c])((__uint32_t)(uc->atten[grp][c]));
4262
4263 if (cmd.band == 0)
4264 idx += 9; /* 5GHz */
4265 if (ridx == IWN_RIDX_MAX32)
4266 idx += 5; /* CCK */
4267
4268 /* Make sure idx stays in a valid range. */
4269 if (idx < 0)
4270 idx = 0;
4271 else if (idx > IWN4965_MAX_PWR_INDEX107)
4272 idx = IWN4965_MAX_PWR_INDEX107;
4273
4274 DPRINTF(("TX chain %d, rate idx %d: power=%d\n",
4275 c, ridx, idx));
4276 cmd.power[ridx].rf_gain[c] = rf_gain[idx];
4277 cmd.power[ridx].dsp_gain[c] = dsp_gain[idx];
4278 }
4279 }
4280
4281 DPRINTF(("setting TX power for chan %d\n", chan));
4282 return iwn_cmd(sc, IWN_CMD_TXPOWER151, &cmd, sizeof cmd, async);
4283
4284#undef interpolate
4285#undef fdivround
4286}
4287
4288int
4289iwn5000_set_txpower(struct iwn_softc *sc, int async)
4290{
4291 struct iwn5000_cmd_txpower cmd;
4292
4293 /*
4294 * TX power calibration is handled automatically by the firmware
4295 * for 5000 Series.
4296 */
4297 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4298 cmd.global_limit = 2 * IWN5000_TXPOWER_MAX_DBM16; /* 16 dBm */
4299 cmd.flags = IWN5000_TXPOWER_NO_CLOSED(1 << 6);
4300 cmd.srv_limit = IWN5000_TXPOWER_AUTO0x7f;
4301 DPRINTF(("setting TX power\n"));
4302 return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM149, &cmd, sizeof cmd, async);
4303}
4304
4305/*
4306 * Retrieve the maximum RSSI (in dBm) among receivers.
4307 */
4308int
4309iwn4965_get_rssi(const struct iwn_rx_stat *stat)
4310{
4311 struct iwn4965_rx_phystat *phy = (void *)stat->phybuf;
4312 uint8_t mask, agc;
4313 int rssi;
4314
4315 mask = (letoh16(phy->antenna)((__uint16_t)(phy->antenna)) >> 4) & IWN_ANT_ABC((1 << 0) | (1 << 1) | (1 << 2));
4316 agc = (letoh16(phy->agc)((__uint16_t)(phy->agc)) >> 7) & 0x7f;
4317
4318 rssi = 0;
4319 if (mask & IWN_ANT_A(1 << 0))
4320 rssi = MAX(rssi, phy->rssi[0])(((rssi)>(phy->rssi[0]))?(rssi):(phy->rssi[0]));
4321 if (mask & IWN_ANT_B(1 << 1))
4322 rssi = MAX(rssi, phy->rssi[2])(((rssi)>(phy->rssi[2]))?(rssi):(phy->rssi[2]));
4323 if (mask & IWN_ANT_C(1 << 2))
4324 rssi = MAX(rssi, phy->rssi[4])(((rssi)>(phy->rssi[4]))?(rssi):(phy->rssi[4]));
4325
4326 return rssi - agc - IWN_RSSI_TO_DBM44;
4327}
4328
4329int
4330iwn5000_get_rssi(const struct iwn_rx_stat *stat)
4331{
4332 struct iwn5000_rx_phystat *phy = (void *)stat->phybuf;
4333 uint8_t agc;
4334 int rssi;
4335
4336 agc = (letoh32(phy->agc)((__uint32_t)(phy->agc)) >> 9) & 0x7f;
4337
4338 rssi = MAX(letoh16(phy->rssi[0]) & 0xff,(((((__uint16_t)(phy->rssi[0])) & 0xff)>(((__uint16_t
)(phy->rssi[1])) & 0xff))?(((__uint16_t)(phy->rssi[
0])) & 0xff):(((__uint16_t)(phy->rssi[1])) & 0xff)
)
4339 letoh16(phy->rssi[1]) & 0xff)(((((__uint16_t)(phy->rssi[0])) & 0xff)>(((__uint16_t
)(phy->rssi[1])) & 0xff))?(((__uint16_t)(phy->rssi[
0])) & 0xff):(((__uint16_t)(phy->rssi[1])) & 0xff)
)
;
4340 rssi = MAX(letoh16(phy->rssi[2]) & 0xff, rssi)(((((__uint16_t)(phy->rssi[2])) & 0xff)>(rssi))?(((
__uint16_t)(phy->rssi[2])) & 0xff):(rssi))
;
4341
4342 return rssi - agc - IWN_RSSI_TO_DBM44;
4343}
4344
4345/*
4346 * Retrieve the average noise (in dBm) among receivers.
4347 */
4348int
4349iwn_get_noise(const struct iwn_rx_general_stats *stats)
4350{
4351 int i, total, nbant, noise;
4352
4353 total = nbant = 0;
4354 for (i = 0; i < 3; i++) {
4355 if ((noise = letoh32(stats->noise[i])((__uint32_t)(stats->noise[i])) & 0xff) == 0)
4356 continue;
4357 total += noise;
4358 nbant++;
4359 }
4360 /* There should be at least one antenna but check anyway. */
4361 return (nbant == 0) ? -127 : (total / nbant) - 107;
4362}
4363
4364/*
4365 * Compute temperature (in degC) from last received statistics.
4366 */
4367int
4368iwn4965_get_temperature(struct iwn_softc *sc)
4369{
4370 struct iwn_ucode_info *uc = &sc->ucode_info;
4371 int32_t r1, r2, r3, r4, temp;
4372
4373 if (sc->rx_stats_flags & IWN_STATS_FLAGS_BAND_HT400x08) {
4374 r1 = letoh32(uc->temp[0].chan40MHz)((__uint32_t)(uc->temp[0].chan40MHz));
4375 r2 = letoh32(uc->temp[1].chan40MHz)((__uint32_t)(uc->temp[1].chan40MHz));
4376 r3 = letoh32(uc->temp[2].chan40MHz)((__uint32_t)(uc->temp[2].chan40MHz));
4377 } else {
4378 r1 = letoh32(uc->temp[0].chan20MHz)((__uint32_t)(uc->temp[0].chan20MHz));
4379 r2 = letoh32(uc->temp[1].chan20MHz)((__uint32_t)(uc->temp[1].chan20MHz));
4380 r3 = letoh32(uc->temp[2].chan20MHz)((__uint32_t)(uc->temp[2].chan20MHz));
4381 }
4382 r4 = letoh32(sc->rawtemp)((__uint32_t)(sc->rawtemp));
4383
4384 if (r1 == r3) /* Prevents division by 0 (should not happen). */
4385 return 0;
4386
4387 /* Sign-extend 23-bit R4 value to 32-bit. */
4388 r4 = ((r4 & 0xffffff) ^ 0x800000) - 0x800000;
4389 /* Compute temperature in Kelvin. */
4390 temp = (259 * (r4 - r2)) / (r3 - r1);
4391 temp = (temp * 97) / 100 + 8;
4392
4393 DPRINTF(("temperature %dK/%dC\n", temp, IWN_KTOC(temp)));
4394 return IWN_KTOC(temp)((temp) - 273);
4395}
4396
4397int
4398iwn5000_get_temperature(struct iwn_softc *sc)
4399{
4400 int32_t temp;
4401
4402 /*
4403 * Temperature is not used by the driver for 5000 Series because
4404 * TX power calibration is handled by firmware.
4405 */
4406 temp = letoh32(sc->rawtemp)((__uint32_t)(sc->rawtemp));
4407 if (sc->hw_type == IWN_HW_REV_TYPE_51504) {
4408 temp = (temp / -5) + sc->temp_off;
4409 temp = IWN_KTOC(temp)((temp) - 273);
4410 }
4411 return temp;
4412}
4413
4414/*
4415 * Initialize sensitivity calibration state machine.
4416 */
4417int
4418iwn_init_sensitivity(struct iwn_softc *sc)
4419{
4420 struct iwn_ops *ops = &sc->ops;
4421 struct iwn_calib_state *calib = &sc->calib;
4422 uint32_t flags;
4423 int error;
4424
4425 /* Reset calibration state machine. */
4426 memset(calib, 0, sizeof (*calib))__builtin_memset((calib), (0), (sizeof (*calib)));
4427 calib->state = IWN_CALIB_STATE_INIT0;
4428 calib->cck_state = IWN_CCK_STATE_HIFA2;
4429 /* Set initial correlation values. */
4430 calib->ofdm_x1 = sc->limits->min_ofdm_x1;
4431 calib->ofdm_mrc_x1 = sc->limits->min_ofdm_mrc_x1;
4432 calib->ofdm_x4 = sc->limits->min_ofdm_x4;
4433 calib->ofdm_mrc_x4 = sc->limits->min_ofdm_mrc_x4;
4434 calib->cck_x4 = 125;
4435 calib->cck_mrc_x4 = sc->limits->min_cck_mrc_x4;
4436 calib->energy_cck = sc->limits->energy_cck;
4437
4438 /* Write initial sensitivity. */
4439 if ((error = iwn_send_sensitivity(sc)) != 0)
4440 return error;
4441
4442 /* Write initial gains. */
4443 if ((error = ops->init_gains(sc)) != 0)
4444 return error;
4445
4446 /* Request statistics at each beacon interval. */
4447 flags = 0;
4448 DPRINTFN(2, ("sending request for statistics\n"));
4449 return iwn_cmd(sc, IWN_CMD_GET_STATISTICS156, &flags, sizeof flags, 1);
4450}
4451
4452/*
4453 * Collect noise and RSSI statistics for the first 20 beacons received
4454 * after association and use them to determine connected antennas and
4455 * to set differential gains.
4456 */
4457void
4458iwn_collect_noise(struct iwn_softc *sc,
4459 const struct iwn_rx_general_stats *stats)
4460{
4461 struct iwn_ops *ops = &sc->ops;
4462 struct iwn_calib_state *calib = &sc->calib;
4463 uint32_t val;
4464 int i;
4465
4466 /* Accumulate RSSI and noise for all 3 antennas. */
4467 for (i = 0; i < 3; i++) {
4468 calib->rssi[i] += letoh32(stats->rssi[i])((__uint32_t)(stats->rssi[i])) & 0xff;
4469 calib->noise[i] += letoh32(stats->noise[i])((__uint32_t)(stats->noise[i])) & 0xff;
4470 }
4471 /* NB: We update differential gains only once after 20 beacons. */
4472 if (++calib->nbeacons < 20)
4473 return;
4474
4475 /* Determine highest average RSSI. */
4476 val = MAX(calib->rssi[0], calib->rssi[1])(((calib->rssi[0])>(calib->rssi[1]))?(calib->rssi
[0]):(calib->rssi[1]))
;
4477 val = MAX(calib->rssi[2], val)(((calib->rssi[2])>(val))?(calib->rssi[2]):(val));
4478
4479 /* Determine which antennas are connected. */
4480 sc->chainmask = sc->rxchainmask;
4481 for (i = 0; i < 3; i++)
4482 if (val - calib->rssi[i] > 15 * 20)
4483 sc->chainmask &= ~(1 << i);
4484 DPRINTF(("RX chains mask: theoretical=0x%x, actual=0x%x\n",
4485 sc->rxchainmask, sc->chainmask));
4486
4487 /* If none of the TX antennas are connected, keep at least one. */
4488 if ((sc->chainmask & sc->txchainmask) == 0)
4489 sc->chainmask |= IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
4490
4491 (void)ops->set_gains(sc);
4492 calib->state = IWN_CALIB_STATE_RUN2;
4493
4494#ifdef notyet
4495 /* XXX Disable RX chains with no antennas connected. */
4496 sc->rxon.rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask))((__uint16_t)(IWN_RXCHAIN_SEL(sc->chainmask)));
4497 (void)iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
4498#endif
4499
4500 /* Enable power-saving mode if requested by user. */
4501 if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON0x00000400)
4502 (void)iwn_set_pslevel(sc, 0, 3, 1);
4503}
4504
4505int
4506iwn4965_init_gains(struct iwn_softc *sc)
4507{
4508 struct iwn_phy_calib_gain cmd;
4509
4510 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4511 cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN7;
4512 /* Differential gains initially set to 0 for all 3 antennas. */
4513 DPRINTF(("setting initial differential gains\n"));
4514 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4515}
4516
4517int
4518iwn5000_init_gains(struct iwn_softc *sc)
4519{
4520 struct iwn_phy_calib cmd;
4521
4522 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4523 cmd.code = sc->reset_noise_gain;
4524 cmd.ngroups = 1;
4525 cmd.isvalid = 1;
4526 DPRINTF(("setting initial differential gains\n"));
4527 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4528}
4529
4530int
4531iwn4965_set_gains(struct iwn_softc *sc)
4532{
4533 struct iwn_calib_state *calib = &sc->calib;
4534 struct iwn_phy_calib_gain cmd;
4535 int i, delta, noise;
4536
4537 /* Get minimal noise among connected antennas. */
4538 noise = INT_MAX0x7fffffff; /* NB: There's at least one antenna. */
4539 for (i = 0; i < 3; i++)
4540 if (sc->chainmask & (1 << i))
4541 noise = MIN(calib->noise[i], noise)(((calib->noise[i])<(noise))?(calib->noise[i]):(noise
))
;
4542
4543 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4544 cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN7;
4545 /* Set differential gains for connected antennas. */
4546 for (i = 0; i < 3; i++) {
4547 if (sc->chainmask & (1 << i)) {
4548 /* Compute attenuation (in unit of 1.5dB). */
4549 delta = (noise - (int32_t)calib->noise[i]) / 30;
4550 /* NB: delta <= 0 */
4551 /* Limit to [-4.5dB,0]. */
4552 cmd.gain[i] = MIN(abs(delta), 3)(((abs(delta))<(3))?(abs(delta)):(3));
4553 if (delta < 0)
4554 cmd.gain[i] |= 1 << 2; /* sign bit */
4555 }
4556 }
4557 DPRINTF(("setting differential gains Ant A/B/C: %x/%x/%x (%x)\n",
4558 cmd.gain[0], cmd.gain[1], cmd.gain[2], sc->chainmask));
4559 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4560}
4561
4562int
4563iwn5000_set_gains(struct iwn_softc *sc)
4564{
4565 struct iwn_calib_state *calib = &sc->calib;
4566 struct iwn_phy_calib_gain cmd;
4567 int i, ant, div, delta;
4568
4569 /* We collected 20 beacons and !=6050 need a 1.5 factor. */
4570 div = (sc->hw_type == IWN_HW_REV_TYPE_60508) ? 20 : 30;
4571
4572 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4573 cmd.code = sc->noise_gain;
4574 cmd.ngroups = 1;
4575 cmd.isvalid = 1;
4576 /*
4577 * Get first available RX antenna as referential.
4578 * IWN_LSB() return values start with 1, but antenna gain array
4579 * cmd.gain[] and noise array calib->noise[] start with 0.
4580 */
4581 ant = IWN_LSB(sc->rxchainmask)((((sc->rxchainmask) - 1) & (sc->rxchainmask)) ^ (sc
->rxchainmask))
- 1;
4582
4583 /* Set differential gains for other antennas. */
4584 for (i = ant + 1; i < 3; i++) {
4585 if (sc->chainmask & (1 << i)) {
4586 /* The delta is relative to antenna "ant". */
4587 delta = ((int32_t)calib->noise[ant] -
4588 (int32_t)calib->noise[i]) / div;
4589 DPRINTF(("Ant[%d] vs. Ant[%d]: delta %d\n", ant, i, delta));
4590 /* Limit to [-4.5dB,+4.5dB]. */
4591 cmd.gain[i] = MIN(abs(delta), 3)(((abs(delta))<(3))?(abs(delta)):(3));
4592 if (delta < 0)
4593 cmd.gain[i] |= 1 << 2; /* sign bit */
4594 DPRINTF(("Setting differential gains for antenna %d: %x\n",
4595 i, cmd.gain[i]));
4596 }
4597 }
4598 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4599}
4600
4601/*
4602 * Tune RF RX sensitivity based on the number of false alarms detected
4603 * during the last beacon period.
4604 */
4605void
4606iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
4607{
4608#define inc(val, inc, max) \
4609 if ((val) < (max)) { \
4610 if ((val) < (max) - (inc)) \
4611 (val) += (inc); \
4612 else \
4613 (val) = (max); \
4614 needs_update = 1; \
4615 }
4616#define dec(val, dec, min) \
4617 if ((val) > (min)) { \
4618 if ((val) > (min) + (dec)) \
4619 (val) -= (dec); \
4620 else \
4621 (val) = (min); \
4622 needs_update = 1; \
4623 }
4624
4625 const struct iwn_sensitivity_limits *limits = sc->limits;
4626 struct iwn_calib_state *calib = &sc->calib;
4627 uint32_t val, rxena, fa;
4628 uint32_t energy[3], energy_min;
4629 uint8_t noise[3], noise_ref;
4630 int i, needs_update = 0;
4631
4632 /* Check that we've been enabled long enough. */
4633 if ((rxena = letoh32(stats->general.load)((__uint32_t)(stats->general.load))) == 0)
4634 return;
4635
4636 /* Compute number of false alarms since last call for OFDM. */
4637 fa = letoh32(stats->ofdm.bad_plcp)((__uint32_t)(stats->ofdm.bad_plcp)) - calib->bad_plcp_ofdm;
4638 fa += letoh32(stats->ofdm.fa)((__uint32_t)(stats->ofdm.fa)) - calib->fa_ofdm;
4639 fa *= 200 * IEEE80211_DUR_TU1024; /* 200TU */
4640
4641 /* Save counters values for next call. */
4642 calib->bad_plcp_ofdm = letoh32(stats->ofdm.bad_plcp)((__uint32_t)(stats->ofdm.bad_plcp));
4643 calib->fa_ofdm = letoh32(stats->ofdm.fa)((__uint32_t)(stats->ofdm.fa));
4644
4645 if (fa > 50 * rxena) {
4646 /* High false alarm count, decrease sensitivity. */
4647 DPRINTFN(2, ("OFDM high false alarm count: %u\n", fa));
4648 inc(calib->ofdm_x1, 1, limits->max_ofdm_x1);
4649 inc(calib->ofdm_mrc_x1, 1, limits->max_ofdm_mrc_x1);
4650 inc(calib->ofdm_x4, 1, limits->max_ofdm_x4);
4651 inc(calib->ofdm_mrc_x4, 1, limits->max_ofdm_mrc_x4);
4652
4653 } else if (fa < 5 * rxena) {
4654 /* Low false alarm count, increase sensitivity. */
4655 DPRINTFN(2, ("OFDM low false alarm count: %u\n", fa));
4656 dec(calib->ofdm_x1, 1, limits->min_ofdm_x1);
4657 dec(calib->ofdm_mrc_x1, 1, limits->min_ofdm_mrc_x1);
4658 dec(calib->ofdm_x4, 1, limits->min_ofdm_x4);
4659 dec(calib->ofdm_mrc_x4, 1, limits->min_ofdm_mrc_x4);
4660 }
4661
4662 /* Compute maximum noise among 3 receivers. */
4663 for (i = 0; i < 3; i++)
4664 noise[i] = (letoh32(stats->general.noise[i])((__uint32_t)(stats->general.noise[i])) >> 8) & 0xff;
4665 val = MAX(noise[0], noise[1])(((noise[0])>(noise[1]))?(noise[0]):(noise[1]));
4666 val = MAX(noise[2], val)(((noise[2])>(val))?(noise[2]):(val));
4667 /* Insert it into our samples table. */
4668 calib->noise_samples[calib->cur_noise_sample] = val;
4669 calib->cur_noise_sample = (calib->cur_noise_sample + 1) % 20;
4670
4671 /* Compute maximum noise among last 20 samples. */
4672 noise_ref = calib->noise_samples[0];
4673 for (i = 1; i < 20; i++)
4674 noise_ref = MAX(noise_ref, calib->noise_samples[i])(((noise_ref)>(calib->noise_samples[i]))?(noise_ref):(calib
->noise_samples[i]))
;
4675
4676 /* Compute maximum energy among 3 receivers. */
4677 for (i = 0; i < 3; i++)
4678 energy[i] = letoh32(stats->general.energy[i])((__uint32_t)(stats->general.energy[i]));
4679 val = MIN(energy[0], energy[1])(((energy[0])<(energy[1]))?(energy[0]):(energy[1]));
4680 val = MIN(energy[2], val)(((energy[2])<(val))?(energy[2]):(val));
4681 /* Insert it into our samples table. */
4682 calib->energy_samples[calib->cur_energy_sample] = val;
4683 calib->cur_energy_sample = (calib->cur_energy_sample + 1) % 10;
4684
4685 /* Compute minimum energy among last 10 samples. */
4686 energy_min = calib->energy_samples[0];
4687 for (i = 1; i < 10; i++)
4688 energy_min = MAX(energy_min, calib->energy_samples[i])(((energy_min)>(calib->energy_samples[i]))?(energy_min)
:(calib->energy_samples[i]))
;
4689 energy_min += 6;
4690
4691 /* Compute number of false alarms since last call for CCK. */
4692 fa = letoh32(stats->cck.bad_plcp)((__uint32_t)(stats->cck.bad_plcp)) - calib->bad_plcp_cck;
4693 fa += letoh32(stats->cck.fa)((__uint32_t)(stats->cck.fa)) - calib->fa_cck;
4694 fa *= 200 * IEEE80211_DUR_TU1024; /* 200TU */
4695
4696 /* Save counters values for next call. */
4697 calib->bad_plcp_cck = letoh32(stats->cck.bad_plcp)((__uint32_t)(stats->cck.bad_plcp));
4698 calib->fa_cck = letoh32(stats->cck.fa)((__uint32_t)(stats->cck.fa));
4699
4700 if (fa > 50 * rxena) {
4701 /* High false alarm count, decrease sensitivity. */
4702 DPRINTFN(2, ("CCK high false alarm count: %u\n", fa));
4703 calib->cck_state = IWN_CCK_STATE_HIFA2;
4704 calib->low_fa = 0;
4705
4706 if (calib->cck_x4 > 160) {
4707 calib->noise_ref = noise_ref;
4708 if (calib->energy_cck > 2)
4709 dec(calib->energy_cck, 2, energy_min);
4710 }
4711 if (calib->cck_x4 < 160) {
4712 calib->cck_x4 = 161;
4713 needs_update = 1;
4714 } else
4715 inc(calib->cck_x4, 3, limits->max_cck_x4);
4716
4717 inc(calib->cck_mrc_x4, 3, limits->max_cck_mrc_x4);
4718
4719 } else if (fa < 5 * rxena) {
4720 /* Low false alarm count, increase sensitivity. */
4721 DPRINTFN(2, ("CCK low false alarm count: %u\n", fa));
4722 calib->cck_state = IWN_CCK_STATE_LOFA1;
4723 calib->low_fa++;
4724
4725 if (calib->cck_state != IWN_CCK_STATE_INIT0 &&
4726 (((int32_t)calib->noise_ref - (int32_t)noise_ref) > 2 ||
4727 calib->low_fa > 100)) {
4728 inc(calib->energy_cck, 2, limits->min_energy_cck);
4729 dec(calib->cck_x4, 3, limits->min_cck_x4);
4730 dec(calib->cck_mrc_x4, 3, limits->min_cck_mrc_x4);
4731 }
4732 } else {
4733 /* Not worth to increase or decrease sensitivity. */
4734 DPRINTFN(2, ("CCK normal false alarm count: %u\n", fa));
4735 calib->low_fa = 0;
4736 calib->noise_ref = noise_ref;
4737
4738 if (calib->cck_state == IWN_CCK_STATE_HIFA2) {
4739 /* Previous interval had many false alarms. */
4740 dec(calib->energy_cck, 8, energy_min);
4741 }
4742 calib->cck_state = IWN_CCK_STATE_INIT0;
4743 }
4744
4745 if (needs_update)
4746 (void)iwn_send_sensitivity(sc);
4747#undef dec
4748#undef inc
4749}
4750
4751int
4752iwn_send_sensitivity(struct iwn_softc *sc)
4753{
4754 struct iwn_calib_state *calib = &sc->calib;
4755 struct iwn_enhanced_sensitivity_cmd cmd;
4756 int len;
4757
4758 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4759 len = sizeof (struct iwn_sensitivity_cmd);
4760 cmd.which = IWN_SENSITIVITY_WORKTBL1;
4761 /* OFDM modulation. */
4762 cmd.corr_ofdm_x1 = htole16(calib->ofdm_x1)((__uint16_t)(calib->ofdm_x1));
4763 cmd.corr_ofdm_mrc_x1 = htole16(calib->ofdm_mrc_x1)((__uint16_t)(calib->ofdm_mrc_x1));
4764 cmd.corr_ofdm_x4 = htole16(calib->ofdm_x4)((__uint16_t)(calib->ofdm_x4));
4765 cmd.corr_ofdm_mrc_x4 = htole16(calib->ofdm_mrc_x4)((__uint16_t)(calib->ofdm_mrc_x4));
4766 cmd.energy_ofdm = htole16(sc->limits->energy_ofdm)((__uint16_t)(sc->limits->energy_ofdm));
4767 cmd.energy_ofdm_th = htole16(62)((__uint16_t)(62));
4768 /* CCK modulation. */
4769 cmd.corr_cck_x4 = htole16(calib->cck_x4)((__uint16_t)(calib->cck_x4));
4770 cmd.corr_cck_mrc_x4 = htole16(calib->cck_mrc_x4)((__uint16_t)(calib->cck_mrc_x4));
4771 cmd.energy_cck = htole16(calib->energy_cck)((__uint16_t)(calib->energy_cck));
4772 /* Barker modulation: use default values. */
4773 cmd.corr_barker = htole16(190)((__uint16_t)(190));
4774 cmd.corr_barker_mrc = htole16(390)((__uint16_t)(390));
4775 if (!(sc->sc_flags & IWN_FLAG_ENH_SENS(1 << 7)))
4776 goto send;
4777 /* Enhanced sensitivity settings. */
4778 len = sizeof (struct iwn_enhanced_sensitivity_cmd);
4779 cmd.ofdm_det_slope_mrc = htole16(668)((__uint16_t)(668));
4780 cmd.ofdm_det_icept_mrc = htole16(4)((__uint16_t)(4));
4781 cmd.ofdm_det_slope = htole16(486)((__uint16_t)(486));
4782 cmd.ofdm_det_icept = htole16(37)((__uint16_t)(37));
4783 cmd.cck_det_slope_mrc = htole16(853)((__uint16_t)(853));
4784 cmd.cck_det_icept_mrc = htole16(4)((__uint16_t)(4));
4785 cmd.cck_det_slope = htole16(476)((__uint16_t)(476));
4786 cmd.cck_det_icept = htole16(99)((__uint16_t)(99));
4787send:
4788 return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY168, &cmd, len, 1);
4789}
4790
4791/*
4792 * Set STA mode power saving level (between 0 and 5).
4793 * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.
4794 */
4795int
4796iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async)
4797{
4798 struct iwn_pmgt_cmd cmd;
4799 const struct iwn_pmgt *pmgt;
4800 uint32_t max, skip_dtim;
4801 pcireg_t reg;
4802 int i;
4803
4804 /* Select which PS parameters to use. */
4805 if (dtim <= 2)
4806 pmgt = &iwn_pmgt[0][level];
4807 else if (dtim <= 10)
4808 pmgt = &iwn_pmgt[1][level];
4809 else
4810 pmgt = &iwn_pmgt[2][level];
4811
4812 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4813 if (level != 0) /* not CAM */
4814 cmd.flags |= htole16(IWN_PS_ALLOW_SLEEP)((__uint16_t)((1 << 0)));
4815 if (level == 5)
4816 cmd.flags |= htole16(IWN_PS_FAST_PD)((__uint16_t)((1 << 4)));
4817 /* Retrieve PCIe Active State Power Management (ASPM). */
4818 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
4819 sc->sc_cap_off + PCI_PCIE_LCSR0x10);
4820 if (!(reg & PCI_PCIE_LCSR_ASPM_L0S0x00000001)) /* L0s Entry disabled. */
4821 cmd.flags |= htole16(IWN_PS_PCI_PMGT)((__uint16_t)((1 << 3)));
4822 cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024)((__uint32_t)(pmgt->rxtimeout * 1024));
4823 cmd.txtimeout = htole32(pmgt->txtimeout * 1024)((__uint32_t)(pmgt->txtimeout * 1024));
4824
4825 if (dtim == 0) {
4826 dtim = 1;
4827 skip_dtim = 0;
4828 } else
4829 skip_dtim = pmgt->skip_dtim;
4830 if (skip_dtim != 0) {
4831 cmd.flags |= htole16(IWN_PS_SLEEP_OVER_DTIM)((__uint16_t)((1 << 2)));
4832 max = pmgt->intval[4];
4833 if (max == (uint32_t)-1)
4834 max = dtim * (skip_dtim + 1);
4835 else if (max > dtim)
4836 max = (max / dtim) * dtim;
4837 } else
4838 max = dtim;
4839 for (i = 0; i < 5; i++)
4840 cmd.intval[i] = htole32(MIN(max, pmgt->intval[i]))((__uint32_t)((((max)<(pmgt->intval[i]))?(max):(pmgt->
intval[i]))))
;
4841
4842 DPRINTF(("setting power saving level to %d\n", level));
4843 return iwn_cmd(sc, IWN_CMD_SET_POWER_MODE119, &cmd, sizeof cmd, async);
4844}
4845
4846int
4847iwn_send_btcoex(struct iwn_softc *sc)
4848{
4849 struct iwn_bluetooth cmd;
4850
4851 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4852 cmd.flags = IWN_BT_COEX_CHAN_ANN(1 << 0) | IWN_BT_COEX_BT_PRIO(1 << 1);
4853 cmd.lead_time = IWN_BT_LEAD_TIME_DEF30;
4854 cmd.max_kill = IWN_BT_MAX_KILL_DEF5;
4855 DPRINTF(("configuring bluetooth coexistence\n"));
4856 return iwn_cmd(sc, IWN_CMD_BT_COEX155, &cmd, sizeof(cmd), 0);
4857}
4858
4859int
4860iwn_send_advanced_btcoex(struct iwn_softc *sc)
4861{
4862 static const uint32_t btcoex_3wire[12] = {
4863 0xaaaaaaaa, 0xaaaaaaaa, 0xaeaaaaaa, 0xaaaaaaaa,
4864 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
4865 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
4866 };
4867 struct iwn_btcoex_priotable btprio;
4868 struct iwn_btcoex_prot btprot;
4869 int error, i;
4870
4871 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
4872 sc->hw_type == IWN_HW_REV_TYPE_13518) {
4873 struct iwn2000_btcoex_config btconfig;
4874
4875 memset(&btconfig, 0, sizeof btconfig)__builtin_memset((&btconfig), (0), (sizeof btconfig));
4876 btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION1 |
4877 (IWN_BT_COEX6000_MODE_3W2 << IWN_BT_COEX6000_MODE_SHIFT3) |
4878 IWN_BT_SYNC_2_BT_DISABLE(1<<7);
4879 btconfig.max_kill = 5;
4880 btconfig.bt3_t7_timer = 1;
4881 btconfig.kill_ack = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4882 btconfig.kill_cts = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4883 btconfig.sample_time = 2;
4884 btconfig.bt3_t2_timer = 0xc;
4885 for (i = 0; i < 12; i++)
4886 btconfig.lookup_table[i] = htole32(btcoex_3wire[i])((__uint32_t)(btcoex_3wire[i]));
4887 btconfig.valid = htole16(0xff)((__uint16_t)(0xff));
4888 btconfig.prio_boost = htole32(0xf0)((__uint32_t)(0xf0));
4889 DPRINTF(("configuring advanced bluetooth coexistence\n"));
4890 error = iwn_cmd(sc, IWN_CMD_BT_COEX155, &btconfig,
4891 sizeof(btconfig), 1);
4892 if (error != 0)
4893 return (error);
4894 } else {
4895 struct iwn6000_btcoex_config btconfig;
4896
4897 memset(&btconfig, 0, sizeof btconfig)__builtin_memset((&btconfig), (0), (sizeof btconfig));
4898 btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION1 |
4899 (IWN_BT_COEX6000_MODE_3W2 << IWN_BT_COEX6000_MODE_SHIFT3) |
4900 IWN_BT_SYNC_2_BT_DISABLE(1<<7);
4901 btconfig.max_kill = 5;
4902 btconfig.bt3_t7_timer = 1;
4903 btconfig.kill_ack = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4904 btconfig.kill_cts = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4905 btconfig.sample_time = 2;
4906 btconfig.bt3_t2_timer = 0xc;
4907 for (i = 0; i < 12; i++)
4908 btconfig.lookup_table[i] = htole32(btcoex_3wire[i])((__uint32_t)(btcoex_3wire[i]));
4909 btconfig.valid = htole16(0xff)((__uint16_t)(0xff));
4910 btconfig.prio_boost = 0xf0;
4911 DPRINTF(("configuring advanced bluetooth coexistence\n"));
4912 error = iwn_cmd(sc, IWN_CMD_BT_COEX155, &btconfig,
4913 sizeof(btconfig), 1);
4914 if (error != 0)
4915 return (error);
4916 }
4917
4918 memset(&btprio, 0, sizeof btprio)__builtin_memset((&btprio), (0), (sizeof btprio));
4919 btprio.calib_init1 = 0x6;
4920 btprio.calib_init2 = 0x7;
4921 btprio.calib_periodic_low1 = 0x2;
4922 btprio.calib_periodic_low2 = 0x3;
4923 btprio.calib_periodic_high1 = 0x4;
4924 btprio.calib_periodic_high2 = 0x5;
4925 btprio.dtim = 0x6;
4926 btprio.scan52 = 0x8;
4927 btprio.scan24 = 0xa;
4928 error = iwn_cmd(sc, IWN_CMD_BT_COEX_PRIOTABLE204, &btprio, sizeof(btprio),
4929 1);
4930 if (error != 0)
4931 return (error);
4932
4933 /* Force BT state machine change */
4934 memset(&btprot, 0, sizeof btprot)__builtin_memset((&btprot), (0), (sizeof btprot));
4935 btprot.open = 1;
4936 btprot.type = 1;
4937 error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT205, &btprot, sizeof(btprot), 1);
4938 if (error != 0)
4939 return (error);
4940
4941 btprot.open = 0;
4942 return (iwn_cmd(sc, IWN_CMD_BT_COEX_PROT205, &btprot, sizeof(btprot), 1));
4943}
4944
4945int
4946iwn5000_runtime_calib(struct iwn_softc *sc)
4947{
4948 struct iwn5000_calib_config cmd;
4949
4950 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4951 cmd.ucode.once.enable = 0xffffffff;
4952 cmd.ucode.once.start = IWN5000_CALIB_DC(1 << 1);
4953 DPRINTF(("configuring runtime calibration\n"));
4954 return iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG101, &cmd, sizeof(cmd), 0);
4955}
4956
4957int
4958iwn_config(struct iwn_softc *sc)
4959{
4960 struct iwn_ops *ops = &sc->ops;
4961 struct ieee80211com *ic = &sc->sc_ic;
4962 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
4963 uint32_t txmask;
4964 uint16_t rxchain;
4965 int error, ridx;
4966
4967 /* Set radio temperature sensor offset. */
4968 if (sc->hw_type == IWN_HW_REV_TYPE_600511) {
4969 error = iwn6000_temp_offset_calib(sc);
4970 if (error != 0) {
4971 printf("%s: could not set temperature offset\n",
4972 sc->sc_dev.dv_xname);
4973 return error;
4974 }
4975 }
4976
4977 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
4978 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
4979 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
4980 sc->hw_type == IWN_HW_REV_TYPE_10517) {
4981 error = iwn2000_temp_offset_calib(sc);
4982 if (error != 0) {
4983 printf("%s: could not set temperature offset\n",
4984 sc->sc_dev.dv_xname);
4985 return error;
4986 }
4987 }
4988
4989 if (sc->hw_type == IWN_HW_REV_TYPE_60508 ||
4990 sc->hw_type == IWN_HW_REV_TYPE_600511) {
4991 /* Configure runtime DC calibration. */
4992 error = iwn5000_runtime_calib(sc);
4993 if (error != 0) {
4994 printf("%s: could not configure runtime calibration\n",
4995 sc->sc_dev.dv_xname);
4996 return error;
4997 }
4998 }
4999
5000 /* Configure valid TX chains for >=5000 Series. */
5001 if (sc->hw_type != IWN_HW_REV_TYPE_49650) {
5002 txmask = htole32(sc->txchainmask)((__uint32_t)(sc->txchainmask));
5003 DPRINTF(("configuring valid TX chains 0x%x\n", txmask));
5004 error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG152, &txmask,
5005 sizeof txmask, 0);
5006 if (error != 0) {
5007 printf("%s: could not configure valid TX chains\n",
5008 sc->sc_dev.dv_xname);
5009 return error;
5010 }
5011 }
5012
5013 /* Configure bluetooth coexistence. */
5014 if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX(1 << 8))
5015 error = iwn_send_advanced_btcoex(sc);
5016 else
5017 error = iwn_send_btcoex(sc);
5018 if (error != 0) {
5019 printf("%s: could not configure bluetooth coexistence\n",
5020 sc->sc_dev.dv_xname);
5021 return error;
5022 }
5023
5024 /* Set mode, channel, RX filter and enable RX. */
5025 memset(&sc->rxon, 0, sizeof (struct iwn_rxon))__builtin_memset((&sc->rxon), (0), (sizeof (struct iwn_rxon
)))
;
5026 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl))__builtin_memcpy((ic->ic_myaddr), (((caddr_t)((ifp->if_sadl
)->sdl_data + (ifp->if_sadl)->sdl_nlen))), (6))
;
5027 IEEE80211_ADDR_COPY(sc->rxon.myaddr, ic->ic_myaddr)__builtin_memcpy((sc->rxon.myaddr), (ic->ic_myaddr), (6
))
;
5028 IEEE80211_ADDR_COPY(sc->rxon.wlap, ic->ic_myaddr)__builtin_memcpy((sc->rxon.wlap), (ic->ic_myaddr), (6));
5029 sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
5030 sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF)((__uint32_t)((1 << 15) | (1 << 30)));
5031 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan)(((ic->ic_ibss_chan)->ic_flags & 0x0080) != 0)) {
5032 sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ)((__uint32_t)((1 << 2) | (1 << 0)));
5033 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5034 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5035 DPRINTF(("%s: 2ghz prot 0x%x\n", __func__,
5036 le32toh(sc->rxon.flags)));
5037 }
5038 switch (ic->ic_opmode) {
5039 case IEEE80211_M_STA:
5040 sc->rxon.mode = IWN_MODE_STA3;
5041 sc->rxon.filter = htole32(IWN_FILTER_MULTICAST)((__uint32_t)((1 << 2)));
5042 break;
5043 case IEEE80211_M_MONITOR:
5044 sc->rxon.mode = IWN_MODE_MONITOR6;
5045 sc->rxon.filter = htole32(IWN_FILTER_MULTICAST |((__uint32_t)((1 << 2) | (1 << 1) | (1 << 0
)))
5046 IWN_FILTER_CTL | IWN_FILTER_PROMISC)((__uint32_t)((1 << 2) | (1 << 1) | (1 << 0
)))
;
5047 break;
5048 default:
5049 /* Should not get there. */
5050 break;
5051 }
5052 sc->rxon.cck_mask = 0x0f; /* not yet negotiated */
5053 sc->rxon.ofdm_mask = 0xff; /* not yet negotiated */
5054 sc->rxon.ht_single_mask = 0xff;
5055 sc->rxon.ht_dual_mask = 0xff;
5056 sc->rxon.ht_triple_mask = 0xff;
5057 rxchain =
5058 IWN_RXCHAIN_VALID(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 1)
|
5059 IWN_RXCHAIN_MIMO_COUNT(sc->nrxchains)((sc->nrxchains) << 12) |
5060 IWN_RXCHAIN_IDLE_COUNT(sc->nrxchains)((sc->nrxchains) << 10);
5061 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5062 rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 4)
;
5063 rxchain |= IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 7)
;
5064 rxchain |= (IWN_RXCHAIN_DRIVER_FORCE(1 << 0) | IWN_RXCHAIN_MIMO_FORCE(1 << 14));
5065 }
5066 sc->rxon.rxchain = htole16(rxchain)((__uint16_t)(rxchain));
5067 DPRINTF(("setting configuration\n"));
5068 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x rxchain %x\n",
5069 __func__, sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5070 sc->rxon.ofdm_mask, sc->rxon.rxchain));
5071 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 0);
5072 if (error != 0) {
5073 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
5074 return error;
5075 }
5076
5077 ridx = (sc->sc_ic.ic_curmode == IEEE80211_MODE_11A) ?
5078 IWN_RIDX_OFDM64 : IWN_RIDX_CCK10;
5079 if ((error = iwn_add_broadcast_node(sc, 0, ridx)) != 0) {
5080 printf("%s: could not add broadcast node\n",
5081 sc->sc_dev.dv_xname);
5082 return error;
5083 }
5084
5085 /* Configuration has changed, set TX power accordingly. */
5086 if ((error = ops->set_txpower(sc, 0)) != 0) {
5087 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5088 return error;
5089 }
5090
5091 if ((error = iwn_set_critical_temp(sc)) != 0) {
5092 printf("%s: could not set critical temperature\n",
5093 sc->sc_dev.dv_xname);
5094 return error;
5095 }
5096
5097 /* Set power saving level to CAM during initialization. */
5098 if ((error = iwn_set_pslevel(sc, 0, 0, 0)) != 0) {
5099 printf("%s: could not set power saving level\n",
5100 sc->sc_dev.dv_xname);
5101 return error;
5102 }
5103 return 0;
5104}
5105
5106uint16_t
5107iwn_get_active_dwell_time(struct iwn_softc *sc,
5108 uint16_t flags, uint8_t n_probes)
5109{
5110 /* No channel? Default to 2GHz settings */
5111 if (flags & IEEE80211_CHAN_2GHZ0x0080) {
5112 return (IWN_ACTIVE_DWELL_TIME_2GHZ(30) +
5113 IWN_ACTIVE_DWELL_FACTOR_2GHZ(3) * (n_probes + 1));
5114 }
5115
5116 /* 5GHz dwell time */
5117 return (IWN_ACTIVE_DWELL_TIME_5GHZ(20) +
5118 IWN_ACTIVE_DWELL_FACTOR_5GHZ(2) * (n_probes + 1));
5119}
5120
5121/*
5122 * Limit the total dwell time to 85% of the beacon interval.
5123 *
5124 * Returns the dwell time in milliseconds.
5125 */
5126uint16_t
5127iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
5128{
5129 struct ieee80211com *ic = &sc->sc_ic;
5130 struct ieee80211_node *ni = ic->ic_bss;
5131 int bintval = 0;
5132
5133 /* bintval is in TU (1.024mS) */
5134 if (ni != NULL((void *)0))
5135 bintval = ni->ni_intval;
5136
5137 /*
5138 * If it's non-zero, we should calculate the minimum of
5139 * it and the DWELL_BASE.
5140 *
5141 * XXX Yes, the math should take into account that bintval
5142 * is 1.024mS, not 1mS..
5143 */
5144 if (ic->ic_state == IEEE80211_S_RUN && bintval > 0)
5145 return (MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100))((((100))<(((bintval * 85) / 100)))?((100)):(((bintval * 85
) / 100)))
);
5146
5147 /* No association context? Default */
5148 return dwell_time;
5149}
5150
5151uint16_t
5152iwn_get_passive_dwell_time(struct iwn_softc *sc, uint16_t flags)
5153{
5154 uint16_t passive;
5155 if (flags & IEEE80211_CHAN_2GHZ0x0080) {
5156 passive = IWN_PASSIVE_DWELL_BASE(100) + IWN_PASSIVE_DWELL_TIME_2GHZ(20);
5157 } else {
5158 passive = IWN_PASSIVE_DWELL_BASE(100) + IWN_PASSIVE_DWELL_TIME_5GHZ(10);
5159 }
5160
5161 /* Clamp to the beacon interval if we're associated */
5162 return (iwn_limit_dwell(sc, passive));
5163}
5164
5165int
5166iwn_scan(struct iwn_softc *sc, uint16_t flags, int bgscan)
5167{
5168 struct ieee80211com *ic = &sc->sc_ic;
5169 struct iwn_scan_hdr *hdr;
5170 struct iwn_cmd_data *tx;
5171 struct iwn_scan_essid *essid;
5172 struct iwn_scan_chan *chan;
5173 struct ieee80211_frame *wh;
5174 struct ieee80211_rateset *rs;
5175 struct ieee80211_channel *c;
5176 uint8_t *buf, *frm;
5177 uint16_t rxchain, dwell_active, dwell_passive;
5178 uint8_t txant;
5179 int buflen, error, is_active;
5180
5181 buf = malloc(IWN_SCAN_MAXSZ((1 << 11) - 4), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
5182 if (buf == NULL((void *)0)) {
5183 printf("%s: could not allocate buffer for scan command\n",
5184 sc->sc_dev.dv_xname);
5185 return ENOMEM12;
5186 }
5187 hdr = (struct iwn_scan_hdr *)buf;
5188 /*
5189 * Move to the next channel if no frames are received within 10ms
5190 * after sending the probe request.
5191 */
5192 hdr->quiet_time = htole16(10)((__uint16_t)(10)); /* timeout in milliseconds */
5193 hdr->quiet_threshold = htole16(1)((__uint16_t)(1)); /* min # of packets */
5194
5195 if (bgscan) {
5196 int bintval;
5197
5198 /* Set maximum off-channel time. */
5199 hdr->max_out = htole32(200 * 1024)((__uint32_t)(200 * 1024));
5200
5201 /* Configure scan pauses which service on-channel traffic. */
5202 bintval = ic->ic_bss->ni_intval ? ic->ic_bss->ni_intval : 100;
5203 hdr->pause_scan = htole32(((100 / bintval) << 22) |((__uint32_t)(((100 / bintval) << 22) | ((100 % bintval
) * 1024)))
5204 ((100 % bintval) * 1024))((__uint32_t)(((100 / bintval) << 22) | ((100 % bintval
) * 1024)))
;
5205 }
5206
5207 /* Select antennas for scanning. */
5208 rxchain =
5209 IWN_RXCHAIN_VALID(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 1)
|
5210 IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 7)
|
5211 IWN_RXCHAIN_DRIVER_FORCE(1 << 0);
5212 if ((flags & IEEE80211_CHAN_5GHZ0x0100) &&
5213 sc->hw_type == IWN_HW_REV_TYPE_49650) {
5214 /*
5215 * On 4965 ant A and C must be avoided in 5GHz because of a
5216 * HW bug which causes very weak RSSI values being reported.
5217 */
5218 rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B)((((1 << 1)) & ((1 << 0) | (1 << 1) | (
1 << 2))) << 4)
;
5219 } else /* Use all available RX antennas. */
5220 rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 4)
;
5221 hdr->rxchain = htole16(rxchain)((__uint16_t)(rxchain));
5222 hdr->filter = htole32(IWN_FILTER_MULTICAST | IWN_FILTER_BEACON)((__uint32_t)((1 << 2) | (1 << 6)));
5223
5224 tx = (struct iwn_cmd_data *)(hdr + 1);
5225 tx->flags = htole32(IWN_TX_AUTO_SEQ)((__uint32_t)((1 << 13)));
5226 tx->id = sc->broadcast_id;
5227 tx->lifetime = htole32(IWN_LIFETIME_INFINITE)((__uint32_t)(0xffffffff));
5228
5229 if (flags & IEEE80211_CHAN_5GHZ0x0100) {
5230 /* Send probe requests at 6Mbps. */
5231 tx->plcp = iwn_rates[IWN_RIDX_OFDM64].plcp;
5232 rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
5233 } else {
5234 hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO)((__uint32_t)((1 << 0) | (1 << 2)));
5235 if (bgscan && sc->hw_type == IWN_HW_REV_TYPE_49650 &&
5236 sc->rxon.chan > 14) {
5237 /*
5238 * 4965 firmware can crash when sending probe requests
5239 * with CCK rates while associated to a 5GHz AP.
5240 * Send probe requests at 6Mbps OFDM as a workaround.
5241 */
5242 tx->plcp = iwn_rates[IWN_RIDX_OFDM64].plcp;
5243 } else {
5244 /* Send probe requests at 1Mbps. */
5245 tx->plcp = iwn_rates[IWN_RIDX_CCK10].plcp;
5246 tx->rflags = IWN_RFLAG_CCK(1 << 1);
5247 }
5248 rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
5249 }
5250 /* Use the first valid TX antenna. */
5251 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
5252 tx->rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
5253
5254 /*
5255 * Only do active scanning if we're announcing a probe request
5256 * for a given SSID (or more, if we ever add it to the driver.)
5257 */
5258 is_active = 0;
5259
5260 /*
5261 * If we're scanning for a specific SSID, add it to the command.
5262 */
5263 essid = (struct iwn_scan_essid *)(tx + 1);
5264 if (ic->ic_des_esslen != 0) {
5265 essid[0].id = IEEE80211_ELEMID_SSID;
5266 essid[0].len = ic->ic_des_esslen;
5267 memcpy(essid[0].data, ic->ic_des_essid, ic->ic_des_esslen)__builtin_memcpy((essid[0].data), (ic->ic_des_essid), (ic->
ic_des_esslen))
;
5268
5269 is_active = 1;
5270 }
5271 /*
5272 * Build a probe request frame. Most of the following code is a
5273 * copy & paste of what is done in net80211.
5274 */
5275 wh = (struct ieee80211_frame *)(essid + 20);
5276 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
5277 IEEE80211_FC0_SUBTYPE_PROBE_REQ0x40;
5278 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
5279 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
5280 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr)__builtin_memcpy((wh->i_addr2), (ic->ic_myaddr), (6));
5281 IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr)__builtin_memcpy((wh->i_addr3), (etherbroadcastaddr), (6));
5282 *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
5283 *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
5284
5285 frm = (uint8_t *)(wh + 1);
5286 frm = ieee80211_add_ssid(frm, NULL((void *)0), 0);
5287 frm = ieee80211_add_rates(frm, rs);
5288 if (rs->rs_nrates > IEEE80211_RATE_SIZE8)
5289 frm = ieee80211_add_xrates(frm, rs);
5290 if (ic->ic_flags & IEEE80211_F_HTON0x02000000)
5291 frm = ieee80211_add_htcaps(frm, ic);
5292
5293 /* Set length of probe request. */
5294 tx->len = htole16(frm - (uint8_t *)wh)((__uint16_t)(frm - (uint8_t *)wh));
5295
5296 /*
5297 * If active scanning is requested but a certain channel is
5298 * marked passive, we can do active scanning if we detect
5299 * transmissions.
5300 *
5301 * There is an issue with some firmware versions that triggers
5302 * a sysassert on a "good CRC threshold" of zero (== disabled),
5303 * on a radar channel even though this means that we should NOT
5304 * send probes.
5305 *
5306 * The "good CRC threshold" is the number of frames that we
5307 * need to receive during our dwell time on a channel before
5308 * sending out probes -- setting this to a huge value will
5309 * mean we never reach it, but at the same time work around
5310 * the aforementioned issue. Thus use IWN_GOOD_CRC_TH_NEVER
5311 * here instead of IWN_GOOD_CRC_TH_DISABLED.
5312 *
5313 * This was fixed in later versions along with some other
5314 * scan changes, and the threshold behaves as a flag in those
5315 * versions.
5316 */
5317
5318 /*
5319 * If we're doing active scanning, set the crc_threshold
5320 * to a suitable value. This is different to active veruss
5321 * passive scanning depending upon the channel flags; the
5322 * firmware will obey that particular check for us.
5323 */
5324 if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN)
5325 hdr->crc_threshold = is_active ?
5326 IWN_GOOD_CRC_TH_DEFAULT((__uint16_t)(1)) : IWN_GOOD_CRC_TH_DISABLED0;
5327 else
5328 hdr->crc_threshold = is_active ?
5329 IWN_GOOD_CRC_TH_DEFAULT((__uint16_t)(1)) : IWN_GOOD_CRC_TH_NEVER((__uint16_t)(0xffff));
5330
5331 chan = (struct iwn_scan_chan *)frm;
5332 for (c = &ic->ic_channels[1];
5333 c <= &ic->ic_channels[IEEE80211_CHAN_MAX255]; c++) {
5334 if ((c->ic_flags & flags) != flags)
5335 continue;
5336
5337 chan->chan = htole16(ieee80211_chan2ieee(ic, c))((__uint16_t)(ieee80211_chan2ieee(ic, c)));
5338 DPRINTFN(2, ("adding channel %d\n", chan->chan));
5339 chan->flags = 0;
5340 if (ic->ic_des_esslen != 0)
5341 chan->flags |= htole32(IWN_CHAN_NPBREQS(1))((__uint32_t)((((1 << (1)) - 1) << 1)));
5342
5343 if (c->ic_flags & IEEE80211_CHAN_PASSIVE0x0200)
5344 chan->flags |= htole32(IWN_CHAN_PASSIVE)((__uint32_t)((0 << 0)));
5345 else
5346 chan->flags |= htole32(IWN_CHAN_ACTIVE)((__uint32_t)((1 << 0)));
5347
5348 /*
5349 * Calculate the active/passive dwell times.
5350 */
5351
5352 dwell_active = iwn_get_active_dwell_time(sc, flags, is_active);
5353 dwell_passive = iwn_get_passive_dwell_time(sc, flags);
5354
5355 /* Make sure they're valid */
5356 if (dwell_passive <= dwell_active)
5357 dwell_passive = dwell_active + 1;
5358
5359 chan->active = htole16(dwell_active)((__uint16_t)(dwell_active));
5360 chan->passive = htole16(dwell_passive)((__uint16_t)(dwell_passive));
5361
5362 chan->dsp_gain = 0x6e;
5363 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
5364 chan->rf_gain = 0x3b;
5365 } else {
5366 chan->rf_gain = 0x28;
5367 }
5368 hdr->nchan++;
5369 chan++;
5370 }
5371
5372 buflen = (uint8_t *)chan - buf;
5373 hdr->len = htole16(buflen)((__uint16_t)(buflen));
5374
5375 error = iwn_cmd(sc, IWN_CMD_SCAN128, buf, buflen, 1);
5376 if (error == 0) {
5377 /*
5378 * The current mode might have been fixed during association.
5379 * Ensure all channels get scanned.
5380 */
5381 if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media)((ic->ic_media.ifm_cur->ifm_media) & 0x000000ff00000000ULL
)
== IFM_AUTO0ULL)
5382 ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
5383
5384 sc->sc_flags |= IWN_FLAG_SCANNING(1 << 10);
5385 if (bgscan)
5386 sc->sc_flags |= IWN_FLAG_BGSCAN(1 << 9);
5387 }
5388 free(buf, M_DEVBUF2, IWN_SCAN_MAXSZ((1 << 11) - 4));
5389 return error;
5390}
5391
5392void
5393iwn_scan_abort(struct iwn_softc *sc)
5394{
5395 iwn_cmd(sc, IWN_CMD_SCAN_ABORT129, NULL((void *)0), 0, 1);
5396
5397 /* XXX Cannot wait for status response in interrupt context. */
5398 DELAY(100)(*delay_func)(100);
5399
5400 sc->sc_flags &= ~IWN_FLAG_SCANNING(1 << 10);
5401 sc->sc_flags &= ~IWN_FLAG_BGSCAN(1 << 9);
5402}
5403
5404int
5405iwn_bgscan(struct ieee80211com *ic)
5406{
5407 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5408 int error;
5409
5410 if (sc->sc_flags & IWN_FLAG_SCANNING(1 << 10))
5411 return 0;
5412
5413 error = iwn_scan(sc, IEEE80211_CHAN_2GHZ0x0080, 1);
5414 if (error)
5415 printf("%s: could not initiate background scan\n",
5416 sc->sc_dev.dv_xname);
5417 return error;
5418}
5419
5420void
5421iwn_rxon_configure_ht40(struct ieee80211com *ic, struct ieee80211_node *ni)
5422{
5423 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5424 uint8_t sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK0x03);
5425 enum ieee80211_htprot htprot = (ni->ni_htop1 &
5426 IEEE80211_HTOP1_PROT_MASK0x0003);
5427
5428 sc->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
5429 IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS)((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
;
5430
5431 if (ieee80211_node_supports_ht_chan40(ni) &&
5432 (sco == IEEE80211_HTOP0_SCO_SCA1 ||
5433 sco == IEEE80211_HTOP0_SCO_SCB3)) {
5434 if (sco == IEEE80211_HTOP0_SCO_SCB3)
5435 sc->rxon.flags |= htole32(IWN_RXON_HT_HT40MINUS)((__uint32_t)((1 << 22)));
5436 if (htprot == IEEE80211_HTPROT_20MHZ)
5437 sc->rxon.flags |= htole32(IWN_RXON_HT_CHANMODE_PURE40)((__uint32_t)((1 << 25)));
5438 else
5439 sc->rxon.flags |= htole32(((__uint32_t)((2 << 25)))
5440 IWN_RXON_HT_CHANMODE_MIXED2040)((__uint32_t)((2 << 25)));
5441 }
5442}
5443
5444int
5445iwn_rxon_ht40_enabled(struct iwn_softc *sc)
5446{
5447 return ((le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_CHANMODE_MIXED2040(2 << 25)) ||
5448 (le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_CHANMODE_PURE40(1 << 25))) ? 1 : 0;
5449}
5450
5451int
5452iwn_auth(struct iwn_softc *sc, int arg)
5453{
5454 struct iwn_ops *ops = &sc->ops;
5455 struct ieee80211com *ic = &sc->sc_ic;
5456 struct ieee80211_node *ni = ic->ic_bss;
5457 int error, ridx;
5458 int bss_switch =
5459 (!IEEE80211_ADDR_EQ(sc->bss_node_addr, etheranyaddr)(__builtin_memcmp((sc->bss_node_addr), (etheranyaddr), (6)
) == 0)
&&
5460 !IEEE80211_ADDR_EQ(sc->bss_node_addr, ni->ni_macaddr)(__builtin_memcmp((sc->bss_node_addr), (ni->ni_macaddr)
, (6)) == 0)
);
5461
5462 /* Update adapter configuration. */
5463 IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid)__builtin_memcpy((sc->rxon.bssid), (ni->ni_bssid), (6));
5464 sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
5465 sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF)((__uint32_t)((1 << 15) | (1 << 30)));
5466 if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0080) != 0)) {
5467 sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ)((__uint32_t)((1 << 2) | (1 << 0)));
5468 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5469 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5470 DPRINTF(("%s: 2ghz prot 0x%x\n", __func__,
5471 le32toh(sc->rxon.flags)));
5472 }
5473 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5474 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5475 else
5476 sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5477 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5478 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5479 else
5480 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5481 switch (ic->ic_curmode) {
5482 case IEEE80211_MODE_11A:
5483 sc->rxon.cck_mask = 0;
5484 sc->rxon.ofdm_mask = 0x15;
5485 break;
5486 case IEEE80211_MODE_11B:
5487 sc->rxon.cck_mask = 0x03;
5488 sc->rxon.ofdm_mask = 0;
5489 break;
5490 default: /* Assume 802.11b/g/n. */
5491 sc->rxon.cck_mask = 0x0f;
5492 sc->rxon.ofdm_mask = 0x15;
5493 }
5494 /* Configure 40MHz early to avoid problems on 6205 devices. */
5495 iwn_rxon_configure_ht40(ic, ni);
5496 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x\n", __func__,
5497 sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5498 sc->rxon.ofdm_mask));
5499 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
5500 if (error != 0) {
5501 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
5502 return error;
5503 }
5504
5505 /* Configuration has changed, set TX power accordingly. */
5506 if ((error = ops->set_txpower(sc, 1)) != 0) {
5507 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5508 return error;
5509 }
5510 /*
5511 * Reconfiguring RXON clears the firmware nodes table so we must
5512 * add the broadcast node again.
5513 */
5514 ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0100) != 0) ?
5515 IWN_RIDX_OFDM64 : IWN_RIDX_CCK10;
5516 if ((error = iwn_add_broadcast_node(sc, 1, ridx)) != 0) {
5517 printf("%s: could not add broadcast node\n",
5518 sc->sc_dev.dv_xname);
5519 return error;
5520 }
5521
5522 /*
5523 * Make sure the firmware gets to see a beacon before we send
5524 * the auth request. Otherwise the Tx attempt can fail due to
5525 * the firmware's built-in regulatory domain enforcement.
5526 * Delaying here for every incoming deauth frame can result in a DoS.
5527 * Don't delay if we're here because of an incoming frame (arg != -1)
5528 * or if we're already waiting for a response (ic_mgt_timer != 0).
5529 * If we are switching APs after a background scan then net80211 has
5530 * just faked the reception of a deauth frame from our old AP, so it
5531 * is safe to delay in that case.
5532 */
5533 if ((arg == -1 || bss_switch) && ic->ic_mgt_timer == 0)
5534 DELAY(ni->ni_intval * 3 * IEEE80211_DUR_TU)(*delay_func)(ni->ni_intval * 3 * 1024);
5535
5536 /* We can now clear the cached address of our previous AP. */
5537 memset(sc->bss_node_addr, 0, sizeof(sc->bss_node_addr))__builtin_memset((sc->bss_node_addr), (0), (sizeof(sc->
bss_node_addr)))
;
5538
5539 return 0;
5540}
5541
5542int
5543iwn_run(struct iwn_softc *sc)
5544{
5545 struct iwn_ops *ops = &sc->ops;
5546 struct ieee80211com *ic = &sc->sc_ic;
5547 struct ieee80211_node *ni = ic->ic_bss;
5548 struct iwn_node *wn = (void *)ni;
5549 struct iwn_node_info node;
5550 int error;
5551
5552 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5553 /* Link LED blinks while monitoring. */
5554 iwn_set_led(sc, IWN_LED_LINK2, 50, 50);
5555 return 0;
5556 }
5557 if ((error = iwn_set_timing(sc, ni)) != 0) {
5558 printf("%s: could not set timing\n", sc->sc_dev.dv_xname);
5559 return error;
5560 }
5561
5562 /* Update adapter configuration. */
5563 sc->rxon.associd = htole16(IEEE80211_AID(ni->ni_associd))((__uint16_t)(((ni->ni_associd) &~ 0xc000)));
5564 /* Short preamble and slot time are negotiated when associating. */
5565 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE | IWN_RXON_SHSLOT)((__uint32_t)((1 << 5) | (1 << 4)));
5566 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5567 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5568 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5569 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5570 sc->rxon.filter |= htole32(IWN_FILTER_BSS)((__uint32_t)((1 << 5)));
5571
5572 /* HT is negotiated when associating. */
5573 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5574 enum ieee80211_htprot htprot =
5575 (ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK0x0003);
5576 DPRINTF(("%s: htprot = %d\n", __func__, htprot));
5577 sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot))((__uint32_t)(((htprot) << 23)));
5578 } else
5579 sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3))((__uint32_t)(((3) << 23)));
5580
5581 iwn_rxon_configure_ht40(ic, ni);
5582
5583 if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0100) != 0)) {
5584 /* 11a or 11n 5GHz */
5585 sc->rxon.cck_mask = 0;
5586 sc->rxon.ofdm_mask = 0x15;
5587 } else if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5588 /* 11n 2GHz */
5589 sc->rxon.cck_mask = 0x0f;
5590 sc->rxon.ofdm_mask = 0x15;
5591 } else {
5592 if (ni->ni_rates.rs_nrates == 4) {
5593 /* 11b */
5594 sc->rxon.cck_mask = 0x03;
5595 sc->rxon.ofdm_mask = 0;
5596 } else {
5597 /* assume 11g */
5598 sc->rxon.cck_mask = 0x0f;
5599 sc->rxon.ofdm_mask = 0x15;
5600 }
5601 }
5602 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x\n", __func__,
5603 sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5604 sc->rxon.ofdm_mask));
5605 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
5606 if (error != 0) {
5607 printf("%s: could not update configuration\n",
5608 sc->sc_dev.dv_xname);
5609 return error;
5610 }
5611
5612 /* Configuration has changed, set TX power accordingly. */
5613 if ((error = ops->set_txpower(sc, 1)) != 0) {
5614 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5615 return error;
5616 }
5617
5618 /* Fake a join to initialize the TX rate. */
5619 ((struct iwn_node *)ni)->id = IWN_ID_BSS0;
5620 iwn_newassoc(ic, ni, 1);
5621
5622 /* Add BSS node. */
5623 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5624 IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr)__builtin_memcpy((node.macaddr), (ni->ni_macaddr), (6));
5625 node.id = IWN_ID_BSS0;
5626 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5627 node.htmask = (IWN_AMDPU_SIZE_FACTOR_MASK((0x3) << 19) |
5628 IWN_AMDPU_DENSITY_MASK((0x7) << 23));
5629 node.htflags = htole32(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5630 IWN_AMDPU_SIZE_FACTOR(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5631 (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_LE)) |((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5632 IWN_AMDPU_DENSITY(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5633 (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) >> 2))((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
;
5634 if (iwn_rxon_ht40_enabled(sc))
5635 node.htflags |= htole32(IWN_40MHZ_ENABLE)((__uint32_t)((1 << 21)));
5636 }
5637 DPRINTF(("adding BSS node\n"));
5638 error = ops->add_node(sc, &node, 1);
5639 if (error != 0) {
5640 printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
5641 return error;
5642 }
5643
5644 /* Cache address of AP in case it changes after a background scan. */
5645 IEEE80211_ADDR_COPY(sc->bss_node_addr, ni->ni_macaddr)__builtin_memcpy((sc->bss_node_addr), (ni->ni_macaddr),
(6))
;
5646
5647 DPRINTF(("setting link quality for node %d\n", node.id));
5648 if ((error = iwn_set_link_quality(sc, ni)) != 0) {
5649 printf("%s: could not setup link quality for node %d\n",
5650 sc->sc_dev.dv_xname, node.id);
5651 return error;
5652 }
5653
5654 if ((error = iwn_init_sensitivity(sc)) != 0) {
5655 printf("%s: could not set sensitivity\n",
5656 sc->sc_dev.dv_xname);
5657 return error;
5658 }
5659 /* Start periodic calibration timer. */
5660 sc->calib.state = IWN_CALIB_STATE_ASSOC1;
5661 sc->calib_cnt = 0;
5662 timeout_add_msec(&sc->calib_to, 500);
5663
5664 ieee80211_ra_node_init(&wn->rn);
5665
5666 /* Link LED always on while associated. */
5667 iwn_set_led(sc, IWN_LED_LINK2, 0, 1);
5668 return 0;
5669}
5670
5671/*
5672 * We support CCMP hardware encryption/decryption of unicast frames only.
5673 * HW support for TKIP really sucks. We should let TKIP die anyway.
5674 */
5675int
5676iwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
5677 struct ieee80211_key *k)
5678{
5679 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5680 struct iwn_ops *ops = &sc->ops;
5681 struct iwn_node *wn = (void *)ni;
5682 struct iwn_node_info node;
5683 uint16_t kflags;
5684
5685 if ((k->k_flags & IEEE80211_KEY_GROUP0x00000001) ||
5686 k->k_cipher != IEEE80211_CIPHER_CCMP)
5687 return ieee80211_set_key(ic, ni, k);
5688
5689 kflags = IWN_KFLAG_CCMP(1 << 1) | IWN_KFLAG_MAP(1 << 3) | IWN_KFLAG_KID(k->k_id)((k->k_id) << 8);
5690 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001)
5691 kflags |= IWN_KFLAG_GROUP(1 << 14);
5692
5693 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5694 node.id = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) ?
5695 sc->broadcast_id : wn->id;
5696 node.control = IWN_NODE_UPDATE(1 << 0);
5697 node.flags = IWN_FLAG_SET_KEY(1 << 0);
5698 node.kflags = htole16(kflags)((__uint16_t)(kflags));
5699 node.kid = k->k_id;
5700 memcpy(node.key, k->k_key, k->k_len)__builtin_memcpy((node.key), (k->k_key), (k->k_len));
5701 DPRINTF(("set key id=%d for node %d\n", k->k_id, node.id));
5702 return ops->add_node(sc, &node, 1);
5703}
5704
5705void
5706iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
5707 struct ieee80211_key *k)
5708{
5709 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5710 struct iwn_ops *ops = &sc->ops;
5711 struct iwn_node *wn = (void *)ni;
5712 struct iwn_node_info node;
5713
5714 if ((k->k_flags & IEEE80211_KEY_GROUP0x00000001) ||
5715 k->k_cipher != IEEE80211_CIPHER_CCMP) {
5716 /* See comment about other ciphers above. */
5717 ieee80211_delete_key(ic, ni, k);
5718 return;
5719 }
5720 if (ic->ic_state != IEEE80211_S_RUN)
5721 return; /* Nothing to do. */
5722 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5723 node.id = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) ?
5724 sc->broadcast_id : wn->id;
5725 node.control = IWN_NODE_UPDATE(1 << 0);
5726 node.flags = IWN_FLAG_SET_KEY(1 << 0);
5727 node.kflags = htole16(IWN_KFLAG_INVALID)((__uint16_t)((1 << 11)));
5728 node.kid = 0xff;
5729 DPRINTF(("delete keys for node %d\n", node.id));
5730 (void)ops->add_node(sc, &node, 1);
5731}
5732
5733void
5734iwn_updatechan(struct ieee80211com *ic)
5735{
5736 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5737
5738 if (ic->ic_state != IEEE80211_S_RUN)
5739 return;
5740
5741 iwn_rxon_configure_ht40(ic, ic->ic_bss);
5742 sc->ops.update_rxon(sc);
5743 iwn_set_link_quality(sc, ic->ic_bss);
5744}
5745
5746void
5747iwn_updateprot(struct ieee80211com *ic)
5748{
5749 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5750 enum ieee80211_htprot htprot;
5751
5752 if (ic->ic_state != IEEE80211_S_RUN)
5753 return;
5754
5755 /* Update ERP protection setting. */
5756 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5757 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5758 else
5759 sc->rxon.flags &= ~htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5760
5761 /* Update HT protection mode setting. */
5762 htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK0x0003) >>
5763 IEEE80211_HTOP1_PROT_SHIFT0;
5764 sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3))((__uint32_t)(((3) << 23)));
5765 sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot))((__uint32_t)(((htprot) << 23)));
5766
5767 sc->ops.update_rxon(sc);
5768}
5769
5770void
5771iwn_updateslot(struct ieee80211com *ic)
5772{
5773 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5774
5775 if (ic->ic_state != IEEE80211_S_RUN)
5776 return;
5777
5778 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5779 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5780 else
5781 sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5782
5783 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5784 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5785 else
5786 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5787
5788 sc->ops.update_rxon(sc);
5789}
5790
5791void
5792iwn_update_rxon_restore_power(struct iwn_softc *sc)
5793{
5794 struct ieee80211com *ic = &sc->sc_ic;
5795 struct iwn_ops *ops = &sc->ops;
5796 int error;
5797
5798 DELAY(100)(*delay_func)(100);
5799
5800 /* All RXONs wipe the firmware's txpower table. Restore it. */
5801 error = ops->set_txpower(sc, 1);
5802 if (error != 0)
5803 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5804
5805 DELAY(100)(*delay_func)(100);
5806
5807 /* Restore power saving level */
5808 if (ic->ic_flags & IEEE80211_F_PMGTON0x00000400)
5809 error = iwn_set_pslevel(sc, 0, 3, 1);
5810 else
5811 error = iwn_set_pslevel(sc, 0, 0, 1);
5812 if (error != 0)
5813 printf("%s: could not set PS level\n", sc->sc_dev.dv_xname);
5814}
5815
5816void
5817iwn5000_update_rxon(struct iwn_softc *sc)
5818{
5819 struct iwn_rxon_assoc rxon_assoc;
5820 int s, error;
5821
5822 /* Update RXON config. */
5823 memset(&rxon_assoc, 0, sizeof(rxon_assoc))__builtin_memset((&rxon_assoc), (0), (sizeof(rxon_assoc))
)
;
5824 rxon_assoc.flags = sc->rxon.flags;
5825 rxon_assoc.filter = sc->rxon.filter;
5826 rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;
5827 rxon_assoc.cck_mask = sc->rxon.cck_mask;
5828 rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;
5829 rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;
5830 rxon_assoc.ht_triple_mask = sc->rxon.ht_triple_mask;
5831 rxon_assoc.rxchain = sc->rxon.rxchain;
5832 rxon_assoc.acquisition = sc->rxon.acquisition;
5833
5834 s = splnet()splraise(0x7);
5835
5836 error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC17, &rxon_assoc,
5837 sizeof(rxon_assoc), 1);
5838 if (error != 0)
5839 printf("%s: RXON_ASSOC command failed\n", sc->sc_dev.dv_xnam